FrameworkPerfActivity.java revision 2c84cfc001fb92a71811bf7384b7f865ff31ff9d
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.frameworkperf;
18
19import android.app.Activity;
20import android.content.Context;
21import android.content.Intent;
22import android.content.pm.PackageManager;
23import android.graphics.Bitmap;
24import android.graphics.BitmapFactory;
25import android.os.Bundle;
26import android.os.FileUtils;
27import android.os.Handler;
28import android.os.Looper;
29import android.os.PowerManager;
30import android.os.Process;
31import android.os.SystemClock;
32import android.util.DisplayMetrics;
33import android.util.Log;
34import android.view.LayoutInflater;
35import android.view.View;
36import android.view.WindowManager;
37import android.widget.AdapterView;
38import android.widget.ArrayAdapter;
39import android.widget.Spinner;
40import android.widget.TextView;
41
42import java.io.File;
43import java.io.FileNotFoundException;
44import java.io.FileOutputStream;
45import java.io.IOException;
46import java.io.RandomAccessFile;
47import java.util.ArrayList;
48
49/**
50 * So you thought sync used up your battery life.
51 */
52public class FrameworkPerfActivity extends Activity
53        implements AdapterView.OnItemSelectedListener {
54    static final String TAG = "Perf";
55
56    final Handler mHandler = new Handler();
57
58    Spinner mFgSpinner;
59    Spinner mBgSpinner;
60    TextView mLog;
61    PowerManager.WakeLock mPartialWakeLock;
62
63    long mMaxRunTime = 5000;
64    boolean mStarted;
65
66    final TestRunner mRunner = new TestRunner();
67
68    final Op[] mOpPairs = new Op[] {
69            new MethodCallOp(), new NoOp(),
70            new MethodCallOp(), new CpuOp(),
71            new MethodCallOp(), new SchedulerOp(),
72            new MethodCallOp(), new GcOp(),
73            new MethodCallOp(), new CreateFileOp(),
74            new MethodCallOp(), new CreateWriteFileOp(),
75            new MethodCallOp(), new CreateWriteSyncFileOp(),
76            new MethodCallOp(), new WriteFileOp(),
77            new MethodCallOp(), new ReadFileOp(),
78            new SchedulerOp(), new SchedulerOp(),
79            new GcOp(), new NoOp(),
80            new IpcOp(), new NoOp(),
81            new IpcOp(), new CpuOp(),
82            new IpcOp(), new SchedulerOp(),
83            new IpcOp(), new GcOp(),
84            new IpcOp(), new CreateFileOp(),
85            new IpcOp(), new CreateWriteFileOp(),
86            new IpcOp(), new CreateWriteSyncFileOp(),
87            new IpcOp(), new WriteFileOp(),
88            new IpcOp(), new ReadFileOp(),
89            new CreateFileOp(), new NoOp(),
90            new CreateWriteFileOp(), new NoOp(),
91            new CreateWriteSyncFileOp(), new NoOp(),
92            new WriteFileOp(), new NoOp(),
93            new ReadFileOp(), new NoOp(),
94            new WriteFileOp(), new CreateWriteFileOp(),
95            new ReadFileOp(), new CreateWriteFileOp(),
96            new WriteFileOp(), new CreateWriteSyncFileOp(),
97            new ReadFileOp(), new CreateWriteSyncFileOp(),
98            new WriteFileOp(), new WriteFileOp(),
99            new WriteFileOp(), new ReadFileOp(),
100            new ReadFileOp(), new WriteFileOp(),
101            new ReadFileOp(), new ReadFileOp(),
102            new ParseXmlResOp(), new NoOp(),
103            new ParseLargeXmlResOp(), new NoOp(),
104            new LayoutInflaterOp(), new NoOp(),
105            new LayoutInflaterLargeOp(), new NoOp(),
106            new LoadSmallBitmapOp(), new NoOp(),
107            new LoadLargeBitmapOp(), new NoOp(),
108            new LoadSmallScaledBitmapOp(), new NoOp(),
109            new LoadLargeScaledBitmapOp(), new NoOp(),
110    };
111
112    final Op[] mAvailOps = new Op[] {
113            new NoOp(),
114            new CpuOp(),
115            new SchedulerOp(),
116            new MethodCallOp(),
117            new IpcOp(),
118            new CreateFileOp(),
119            new CreateWriteFileOp(),
120            new CreateWriteSyncFileOp(),
121            new WriteFileOp(),
122            new ReadFileOp(),
123            new ParseXmlResOp(),
124            new ParseLargeXmlResOp(),
125            new LoadSmallBitmapOp(),
126            new LoadLargeBitmapOp(),
127            new LoadSmallScaledBitmapOp(),
128            new LoadLargeScaledBitmapOp(),
129    };
130
131    final String[] mAvailOpLabels;
132    final String[] mAvailOpDescriptions;
133
134    Op mFgTest;
135    Op mBgTest;
136    int mCurOpIndex = 0;
137
138    class RunResult {
139        final String name;
140        final String fgLongName;
141        final String bgLongName;
142        final long fgTime;
143        final long fgOps;
144        final long bgTime;
145        final long bgOps;
146
147        RunResult(TestRunner op) {
148            name = op.getName();
149            fgLongName = op.getForegroundLongName();
150            bgLongName = op.getBackgroundLongName();
151            fgTime = op.getForegroundTime();
152            fgOps = op.getForegroundOps();
153            bgTime = op.getBackgroundTime();
154            bgOps = op.getBackgroundOps();
155        }
156
157        float getFgMsPerOp() {
158            return fgOps != 0 ? (fgTime / (float)fgOps) : 0;
159        }
160
161        float getBgMsPerOp() {
162            return bgOps != 0 ? (bgTime / (float)bgOps) : 0;
163        }
164    }
165
166    final ArrayList<RunResult> mResults = new ArrayList<RunResult>();
167
168    public FrameworkPerfActivity() {
169        mAvailOpLabels = new String[mAvailOps.length];
170        mAvailOpDescriptions = new String[mAvailOps.length];
171        for (int i=0; i<mAvailOps.length; i++) {
172            Op op = mAvailOps[i];
173            if (op.getClass() == NoOp.class) {
174                mAvailOpLabels[i] = "All";
175                mAvailOpDescriptions[i] = "All tests";
176            } else {
177                mAvailOpLabels[i] = op.getName();
178                mAvailOpDescriptions[i] = op.getLongName();
179            }
180        }
181    }
182
183    @Override
184    public void onCreate(Bundle savedInstanceState) {
185        super.onCreate(savedInstanceState);
186
187        // Set the layout for this activity.  You can find it
188        // in res/layout/hello_activity.xml
189        setContentView(R.layout.main);
190
191        mFgSpinner = (Spinner) findViewById(R.id.fgspinner);
192        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
193                android.R.layout.simple_spinner_item, mAvailOpLabels);
194        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
195        mFgSpinner.setAdapter(adapter);
196        mFgSpinner.setOnItemSelectedListener(this);
197        mBgSpinner = (Spinner) findViewById(R.id.bgspinner);
198        adapter = new ArrayAdapter<String>(this,
199                android.R.layout.simple_spinner_item, mAvailOpLabels);
200        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
201        mBgSpinner.setAdapter(adapter);
202        mBgSpinner.setOnItemSelectedListener(this);
203
204        findViewById(R.id.start).setOnClickListener(new View.OnClickListener() {
205            @Override public void onClick(View v) {
206                startRunning();
207            }
208        });
209        findViewById(R.id.stop).setOnClickListener(new View.OnClickListener() {
210            @Override public void onClick(View v) {
211                stopRunning();
212            }
213        });
214        mLog = (TextView)findViewById(R.id.log);
215
216        PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE);
217        mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Scheduler");
218        mPartialWakeLock.setReferenceCounted(false);
219    }
220
221    @Override
222    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
223        if (parent == mFgSpinner || parent == mBgSpinner) {
224            Spinner spinner = (Spinner)parent;
225            Op op = mAvailOps[position];
226            if (op.getClass() == NoOp.class) {
227                op = null;
228            }
229            if (parent == mFgSpinner) {
230                mFgTest = op;
231                ((TextView)findViewById(R.id.fgtext)).setText(mAvailOpDescriptions[position]);
232            } else {
233                mBgTest = op;
234                ((TextView)findViewById(R.id.bgtext)).setText(mAvailOpDescriptions[position]);
235            }
236        }
237    }
238
239    @Override
240    public void onNothingSelected(AdapterView<?> parent) {
241        // TODO Auto-generated method stub
242
243    }
244
245    @Override
246    public void onResume() {
247        super.onResume();
248    }
249
250    @Override
251    public void onDestroy() {
252        super.onDestroy();
253        stopRunning();
254        if (mPartialWakeLock.isHeld()) {
255            mPartialWakeLock.release();
256        }
257    }
258
259    void startCurOp() {
260        Op fgOp, bgOp;
261        if (mFgTest == null && mBgTest == null) {
262            fgOp = mOpPairs[mCurOpIndex];
263            bgOp = mOpPairs[mCurOpIndex+1];
264        } else if (mFgTest != null && mBgTest != null) {
265            fgOp = mFgTest;
266            bgOp = mBgTest;
267        } else if (mFgTest != null) {
268            fgOp = mFgTest;
269            bgOp = mAvailOps[mCurOpIndex];
270        } else {
271            fgOp = mAvailOps[mCurOpIndex];
272            bgOp = mBgTest;
273        }
274        mRunner.run(mHandler, fgOp, bgOp, new Runnable() {
275            @Override public void run() {
276                RunResult result = new RunResult(mRunner);
277                log(String.format("%s: fg=%d*%gms/op (%dms) / bg=%d*%gms/op (%dms)",
278                        result.name, result.fgOps, result.getFgMsPerOp(), result.fgTime,
279                        result.bgOps, result.getBgMsPerOp(), result.bgTime));
280                mResults.add(result);
281                if (!mStarted) {
282                    log("Stop");
283                    stopRunning();
284                    return;
285                }
286                if (mFgTest != null && mBgTest != null) {
287                    log("Finished");
288                    stopRunning();
289                    return;
290                }
291                if (mFgTest == null && mBgTest == null) {
292                    mCurOpIndex+=2;
293                    if (mCurOpIndex >= mOpPairs.length) {
294                        log("Finished");
295                        stopRunning();
296                        return;
297                    }
298                }
299                mCurOpIndex++;
300                if (mCurOpIndex >= mAvailOps.length) {
301                    log("Finished");
302                    stopRunning();
303                    return;
304                }
305                startCurOp();
306            }
307        });
308    }
309
310    void startRunning() {
311        if (!mStarted) {
312            log("Start");
313            mStarted = true;
314            updateWakeLock();
315            startService(new Intent(this, SchedulerService.class));
316            mCurOpIndex = 0;
317            mResults.clear();
318            startCurOp();
319        }
320    }
321
322    void stopRunning() {
323        if (mStarted) {
324            mStarted = false;
325            updateWakeLock();
326            stopService(new Intent(this, SchedulerService.class));
327            for (int i=0; i<mResults.size(); i++) {
328                RunResult result = mResults.get(i);
329                float fgMsPerOp = result.getFgMsPerOp();
330                float bgMsPerOp = result.getBgMsPerOp();
331                String fgMsPerOpStr = fgMsPerOp != 0 ? Float.toString(fgMsPerOp) : "";
332                String bgMsPerOpStr = bgMsPerOp != 0 ? Float.toString(bgMsPerOp) : "";
333                Log.i(TAG, "\t" + result.name + "\t" + result.fgOps
334                        + "\t" + result.getFgMsPerOp() + "\t" + result.fgTime
335                        + "\t" + result.fgLongName + "\t" + result.bgOps
336                        + "\t" + result.getBgMsPerOp() + "\t" + result.bgTime
337                        + "\t" + result.bgLongName);
338            }
339        }
340    }
341
342    void updateWakeLock() {
343        if (mStarted) {
344            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
345            if (!mPartialWakeLock.isHeld()) {
346                mPartialWakeLock.acquire();
347            }
348        } else {
349            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
350            if (mPartialWakeLock.isHeld()) {
351                mPartialWakeLock.release();
352            }
353        }
354    }
355
356    void log(String s) {
357        mLog.setText(mLog.getText() + "\n" + s);
358        Log.i(TAG, s);
359    }
360
361    enum BackgroundMode {
362        NOTHING,
363        CPU,
364        SCHEDULER
365    };
366
367    public class TestRunner {
368        Handler mHandler;
369        Op mForegroundOp;
370        Op mBackgroundOp;
371        Runnable mDoneCallback;
372
373        RunnerThread mBackgroundThread;
374        RunnerThread mForegroundThread;
375        long mStartTime;
376
377        boolean mBackgroundRunning;
378        boolean mForegroundRunning;
379
380        long mBackgroundEndTime;
381        long mBackgroundOps;
382        long mForegroundEndTime;
383        long mForegroundOps;
384
385        public TestRunner() {
386        }
387
388        public String getForegroundName() {
389            return mForegroundOp.getName();
390        }
391
392        public String getBackgroundName() {
393            return mBackgroundOp.getName();
394        }
395
396        public String getName() {
397            String fgName = mForegroundOp.getName();
398            String bgName = mBackgroundOp.getName();
399            StringBuilder res = new StringBuilder();
400            if (fgName != null) {
401                res.append(fgName);
402                res.append("Fg");
403            }
404            if (bgName != null) {
405                res.append(bgName);
406                res.append("Bg");
407            }
408            return res.toString();
409        }
410
411        public String getForegroundLongName() {
412            return mForegroundOp.getLongName();
413        }
414
415        public String getBackgroundLongName() {
416            return mBackgroundOp.getLongName();
417        }
418
419        public void run(Handler handler, Op foreground, Op background, Runnable doneCallback) {
420            mHandler = handler;
421            mForegroundOp = foreground;
422            mBackgroundOp = background;
423            mDoneCallback = doneCallback;
424            mBackgroundThread = new RunnerThread("background", new Runnable() {
425                @Override public void run() {
426                    boolean running;
427                    int ops = 0;
428                    do {
429                        running = mBackgroundOp.onRun();
430                        ops++;
431                    } while (evalRepeat(running, true) && running);
432                    mBackgroundEndTime = SystemClock.uptimeMillis();
433                    mBackgroundOps = ops * mBackgroundOp.getOpsPerRun();
434                    threadFinished(false);
435                }
436            }, Process.THREAD_PRIORITY_BACKGROUND);
437            mForegroundThread = new RunnerThread("background", new Runnable() {
438                @Override public void run() {
439                    boolean running;
440                    int ops = 0;
441                    do {
442                        running = mForegroundOp.onRun();
443                        ops++;
444                    } while (evalRepeat(true, running) && running);
445                    mForegroundEndTime = SystemClock.uptimeMillis();
446                    mForegroundOps = ops * mForegroundOp.getOpsPerRun();
447                    threadFinished(true);
448                }
449            }, Process.THREAD_PRIORITY_FOREGROUND);
450
451            mForegroundOp.onInit(FrameworkPerfActivity.this, true);
452            mBackgroundOp.onInit(FrameworkPerfActivity.this, false);
453
454            synchronized (this) {
455                mStartTime = SystemClock.uptimeMillis();
456                mBackgroundRunning = true;
457                mForegroundRunning = true;
458            }
459
460            mBackgroundThread.start();
461            mForegroundThread.start();
462        }
463
464        public long getForegroundTime() {
465            return mForegroundEndTime-mStartTime;
466        }
467
468        public long getForegroundOps() {
469            return mForegroundOps;
470        }
471
472        public long getBackgroundTime() {
473            return mBackgroundEndTime-mStartTime;
474        }
475
476        public long getBackgroundOps() {
477            return mBackgroundOps;
478        }
479
480        private boolean evalRepeat(boolean bgRunning, boolean fgRunning) {
481            synchronized (this) {
482                if (!bgRunning) {
483                    mBackgroundRunning = false;
484                }
485                if (!fgRunning) {
486                    mForegroundRunning = false;
487                }
488                if (!mBackgroundRunning && !mForegroundRunning) {
489                    return false;
490                }
491                long now = SystemClock.uptimeMillis();
492                if (now > (mStartTime+mMaxRunTime)) {
493                    return false;
494                }
495                return true;
496            }
497        }
498
499        private void threadFinished(boolean foreground) {
500            synchronized (this) {
501                if (foreground) {
502                    mForegroundRunning = false;
503                } else {
504                    mBackgroundRunning = false;
505                }
506                if (!mBackgroundRunning && !mForegroundRunning) {
507                    mHandler.post(new Runnable() {
508                        @Override public void run() {
509                            mForegroundOp.onTerm(FrameworkPerfActivity.this);
510                            mBackgroundOp.onTerm(FrameworkPerfActivity.this);
511                            if (mDoneCallback != null) {
512                                mDoneCallback.run();
513                            }
514                        }
515                    });
516                }
517            }
518        }
519    }
520
521    class RunnerThread extends Thread {
522        private final Runnable mOp;
523        private final int mPriority;
524
525        RunnerThread(String name, Runnable op, int priority) {
526            super(name);
527            mOp = op;
528            mPriority = priority;
529        }
530
531        public void run() {
532            Process.setThreadPriority(mPriority);
533            mOp.run();
534        }
535    }
536
537    static public abstract class Op {
538        final String mName;
539        final String mLongName;
540
541        public Op(String name, String longName) {
542            mName = name;
543            mLongName = longName;
544        }
545
546        public String getName() {
547            return mName;
548        }
549
550        public String getLongName() {
551            return mLongName;
552        }
553
554        void onInit(Context context, boolean foreground) {
555        }
556
557        abstract boolean onRun();
558
559        void onTerm(Context context) {
560        }
561
562        int getOpsPerRun() {
563            return 1;
564        }
565    }
566
567    static class NoOp extends Op {
568        NoOp() {
569            super(null, "Nothing");
570        }
571
572        boolean onRun() {
573            return false;
574        }
575
576        int getOpsPerRun() {
577            return 0;
578        }
579    }
580
581    static class CpuOp extends Op {
582        CpuOp() {
583            super("CPU", "Consume CPU");
584        }
585
586        boolean onRun() {
587            return true;
588        }
589    }
590
591    static class SchedulerOp extends Op {
592        SchedulerOp() {
593            super("Sched", "Change scheduler group");
594        }
595
596        boolean onRun() {
597            Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
598            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
599            return true;
600        }
601    }
602
603    static class GcOp extends Op {
604        GcOp() {
605            super("Gc", "Run garbage collector");
606        }
607
608        boolean onRun() {
609            byte[] stuff = new byte[1024*1024];
610            return true;
611        }
612    }
613
614    static class MethodCallOp extends Op {
615        MethodCallOp() {
616            super("MethodCall", "Method call");
617        }
618
619        boolean onRun() {
620            final int N = getOpsPerRun();
621            for (int i=0; i<N; i++) {
622                someFunc(i);
623            }
624            return true;
625        }
626
627        int someFunc(int foo) {
628            return 0;
629        }
630
631        int getOpsPerRun() {
632            return 500;
633        }
634    }
635
636    static class IpcOp extends Op {
637        PackageManager mPm;
638        String mProcessName;
639
640        IpcOp() {
641            super("Ipc", "IPC to system process");
642        }
643
644        void onInit(Context context, boolean foreground) {
645            mPm = context.getPackageManager();
646            mProcessName = context.getApplicationInfo().processName;
647        }
648
649        boolean onRun() {
650            final int N = getOpsPerRun();
651            for (int i=0; i<N; i++) {
652                mPm.queryContentProviders(mProcessName, Process.myUid(), 0);
653            }
654            return true;
655        }
656
657        int getOpsPerRun() {
658            return 100;
659        }
660    }
661
662    static class ParseXmlResOp extends Op {
663        Context mContext;
664
665        ParseXmlResOp() {
666            super("ParseXmlRes", "Parse compiled XML resource");
667        }
668
669        void onInit(Context context, boolean foreground) {
670            mContext = context;
671        }
672
673        boolean onRun() {
674            SimpleInflater inf = new SimpleInflater(mContext);
675            inf.inflate(R.xml.simple);
676            return true;
677        }
678    }
679
680    static class ParseLargeXmlResOp extends Op {
681        Context mContext;
682
683        ParseLargeXmlResOp() {
684            super("ParseLargeXmlRes", "Parse large XML resource");
685        }
686
687        void onInit(Context context, boolean foreground) {
688            mContext = context;
689        }
690
691        boolean onRun() {
692            SimpleInflater inf = new SimpleInflater(mContext);
693            inf.inflate(R.xml.simple_large);
694            return true;
695        }
696    }
697
698    static class LayoutInflaterOp extends Op {
699        Context mContext;
700
701        LayoutInflaterOp() {
702            super("LayoutInflaterOp", "Inflate layout resource");
703        }
704
705        void onInit(Context context, boolean foreground) {
706            mContext = context;
707        }
708
709        boolean onRun() {
710            if (Looper.myLooper() == null) {
711                Looper.prepare();
712            }
713            LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
714                    Context.LAYOUT_INFLATER_SERVICE);
715            inf.inflate(R.layout.small_layout, null);
716            return true;
717        }
718    }
719
720    static class LayoutInflaterLargeOp extends Op {
721        Context mContext;
722
723        LayoutInflaterLargeOp() {
724            super("LayoutInflaterLargeOp", "Inflate large layout resource");
725        }
726
727        void onInit(Context context, boolean foreground) {
728            mContext = context;
729        }
730
731        boolean onRun() {
732            if (Looper.myLooper() == null) {
733                Looper.prepare();
734            }
735            LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
736                    Context.LAYOUT_INFLATER_SERVICE);
737            inf.inflate(R.layout.large_layout, null);
738            return true;
739        }
740    }
741
742    static class LoadSmallBitmapOp extends Op {
743        Context mContext;
744
745        LoadSmallBitmapOp() {
746            super("LoadSmallBitmap", "Load small raw bitmap");
747        }
748
749        void onInit(Context context, boolean foreground) {
750            mContext = context;
751        }
752
753        boolean onRun() {
754            BitmapFactory.Options opts = new BitmapFactory.Options();
755            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
756            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
757                    R.drawable.stat_sample, opts);
758            bm.recycle();
759            return true;
760        }
761    }
762
763    static class LoadLargeBitmapOp extends Op {
764        Context mContext;
765
766        LoadLargeBitmapOp() {
767            super("LoadLargeBitmap", "Load large raw bitmap");
768        }
769
770        void onInit(Context context, boolean foreground) {
771            mContext = context;
772        }
773
774        boolean onRun() {
775            BitmapFactory.Options opts = new BitmapFactory.Options();
776            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
777            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
778                    R.drawable.wallpaper_goldengate, opts);
779            bm.recycle();
780            return true;
781        }
782    }
783
784    static class LoadSmallScaledBitmapOp extends Op {
785        Context mContext;
786
787        LoadSmallScaledBitmapOp() {
788            super("LoadSmallScaledBitmap", "Load small raw bitmap that is scaled for density");
789        }
790
791        void onInit(Context context, boolean foreground) {
792            mContext = context;
793        }
794
795        boolean onRun() {
796            BitmapFactory.Options opts = new BitmapFactory.Options();
797            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
798            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
799                    R.drawable.stat_sample_scale, opts);
800            bm.recycle();
801            return true;
802        }
803    }
804
805    static class LoadLargeScaledBitmapOp extends Op {
806        Context mContext;
807
808        LoadLargeScaledBitmapOp() {
809            super("LoadLargeScaledBitmap", "Load large raw bitmap that is scaled for density");
810        }
811
812        void onInit(Context context, boolean foreground) {
813            mContext = context;
814        }
815
816        boolean onRun() {
817            BitmapFactory.Options opts = new BitmapFactory.Options();
818            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
819            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
820                    R.drawable.wallpaper_goldengate_scale, opts);
821            bm.recycle();
822            return true;
823        }
824    }
825
826    static class CreateFileOp extends Op {
827        File mFile;
828
829        CreateFileOp() {
830            super("CreateFile", "Create and delete a file");
831        }
832
833        void onInit(Context context, boolean foreground) {
834            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
835            mFile.delete();
836        }
837
838        boolean onRun() {
839            try {
840                mFile.createNewFile();
841            } catch (IOException e) {
842                Log.w(TAG, "Failure creating " + mFile, e);
843            }
844            mFile.delete();
845            return true;
846        }
847    }
848
849    static class CreateWriteFileOp extends Op {
850        File mFile;
851
852        CreateWriteFileOp() {
853            super("CreateWriteFile", "Create, write, and delete a file");
854        }
855
856        void onInit(Context context, boolean foreground) {
857            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
858            mFile.delete();
859        }
860
861        boolean onRun() {
862            try {
863                FileOutputStream fos = new FileOutputStream(mFile);
864                fos.write(1);
865                fos.close();
866            } catch (IOException e) {
867                Log.w(TAG, "Failure creating " + mFile, e);
868            }
869            mFile.delete();
870            return true;
871        }
872    }
873
874    static class CreateWriteSyncFileOp extends Op {
875        File mFile;
876
877        CreateWriteSyncFileOp() {
878            super("CreateWriteSyncFile", "Create, write, sync, and delete a file");
879        }
880
881        void onInit(Context context, boolean foreground) {
882            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
883            mFile.delete();
884        }
885
886        boolean onRun() {
887            try {
888                FileOutputStream fos = new FileOutputStream(mFile);
889                fos.write(1);
890                fos.flush();
891                FileUtils.sync(fos);
892                fos.close();
893            } catch (IOException e) {
894                Log.w(TAG, "Failure creating " + mFile, e);
895            }
896            mFile.delete();
897            return true;
898        }
899    }
900
901    static class WriteFileOp extends Op {
902        File mFile;
903        RandomAccessFile mRAF;
904        byte[] mBuffer;
905
906        WriteFileOp() {
907            super("WriteFile", "Truncate and write a 64k file");
908        }
909
910        void onInit(Context context, boolean foreground) {
911            mBuffer = new byte[1024*64];
912            for (int i=0; i<mBuffer.length; i++) {
913                mBuffer[i] = (byte)i;
914            }
915            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
916            mFile.delete();
917            try {
918                mRAF = new RandomAccessFile(mFile, "rw");
919            } catch (FileNotFoundException e) {
920                Log.w(TAG, "Failure creating " + mFile, e);
921            }
922        }
923
924        boolean onRun() {
925            try {
926                mRAF.seek(0);
927                mRAF.setLength(0);
928                mRAF.write(mBuffer);
929            } catch (IOException e) {
930                Log.w(TAG, "Failure writing " + mFile, e);
931            }
932            return true;
933        }
934
935        void onTerm(Context context) {
936            try {
937                mRAF.close();
938            } catch (IOException e) {
939                Log.w(TAG, "Failure closing " + mFile, e);
940            }
941            mFile.delete();
942        }
943    }
944
945    static class ReadFileOp extends Op {
946        File mFile;
947        RandomAccessFile mRAF;
948        byte[] mBuffer;
949
950        ReadFileOp() {
951            super("ReadFile", "Seek and read a 64k file");
952        }
953
954        void onInit(Context context, boolean foreground) {
955            mBuffer = new byte[1024*64];
956            for (int i=0; i<mBuffer.length; i++) {
957                mBuffer[i] = (byte)i;
958            }
959            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
960            mFile.delete();
961            try {
962                mRAF = new RandomAccessFile(mFile, "rw");
963                mRAF.seek(0);
964                mRAF.setLength(0);
965                mRAF.write(mBuffer);
966            } catch (IOException e) {
967                Log.w(TAG, "Failure creating " + mFile, e);
968            }
969        }
970
971        boolean onRun() {
972            try {
973                mRAF.seek(0);
974                mRAF.read(mBuffer);
975            } catch (IOException e) {
976                Log.w(TAG, "Failure reading " + mFile, e);
977            }
978            return true;
979        }
980
981        void onTerm(Context context) {
982            try {
983                mRAF.close();
984            } catch (IOException e) {
985                Log.w(TAG, "Failure closing " + mFile, e);
986            }
987            mFile.delete();
988        }
989    }
990}
991