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