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 java.io.File;
20import java.io.FileNotFoundException;
21import java.io.FileOutputStream;
22import java.io.IOException;
23import java.io.RandomAccessFile;
24
25import org.xmlpull.v1.XmlPullParser;
26import org.xmlpull.v1.XmlPullParserException;
27
28import android.app.Service;
29import android.content.Context;
30import android.content.Intent;
31import android.content.pm.PackageManager;
32import android.content.res.TypedArray;
33import android.content.res.XmlResourceParser;
34import android.graphics.Bitmap;
35import android.graphics.BitmapFactory;
36import android.graphics.Paint;
37import android.os.Bundle;
38import android.os.FileUtils;
39import android.os.Handler;
40import android.os.IBinder;
41import android.os.Looper;
42import android.os.Message;
43import android.os.Messenger;
44import android.os.Process;
45import android.os.RemoteException;
46import android.os.SystemClock;
47import android.util.AttributeSet;
48import android.util.DisplayMetrics;
49import android.util.Log;
50import android.util.Xml;
51import android.view.LayoutInflater;
52
53public class TestService extends Service {
54    static final String TAG = "Perf";
55
56    final static Op[] mOpPairs = new Op[] {
57            new MethodCallOp(), new NoOp(),
58            new MethodCallOp(), new CpuOp(),
59            new MethodCallOp(), new SchedulerOp(),
60            new MethodCallOp(), new GcOp(),
61            new MethodCallOp(), new CreateFileOp(),
62            new MethodCallOp(), new CreateWriteFileOp(),
63            new MethodCallOp(), new CreateWriteSyncFileOp(),
64            new MethodCallOp(), new WriteFileOp(),
65            new MethodCallOp(), new ReadFileOp(),
66            new SchedulerOp(), new SchedulerOp(),
67            new GcOp(), new NoOp(),
68            new ObjectGcOp(), new NoOp(),
69            new FinalizingGcOp(), new NoOp(),
70            new PaintGcOp(), new NoOp(),
71            new IpcOp(), new NoOp(),
72            new IpcOp(), new CpuOp(),
73            new IpcOp(), new SchedulerOp(),
74            new IpcOp(), new GcOp(),
75            new IpcOp(), new CreateFileOp(),
76            new IpcOp(), new CreateWriteFileOp(),
77            new IpcOp(), new CreateWriteSyncFileOp(),
78            new IpcOp(), new WriteFileOp(),
79            new IpcOp(), new ReadFileOp(),
80            new CreateFileOp(), new NoOp(),
81            new CreateWriteFileOp(), new NoOp(),
82            new CreateWriteSyncFileOp(), new NoOp(),
83            new WriteFileOp(), new NoOp(),
84            new ReadFileOp(), new NoOp(),
85            new WriteFileOp(), new CreateWriteFileOp(),
86            new ReadFileOp(), new CreateWriteFileOp(),
87            new WriteFileOp(), new CreateWriteSyncFileOp(),
88            new ReadFileOp(), new CreateWriteSyncFileOp(),
89            new WriteFileOp(), new WriteFileOp(),
90            new WriteFileOp(), new ReadFileOp(),
91            new ReadFileOp(), new WriteFileOp(),
92            new ReadFileOp(), new ReadFileOp(),
93            new OpenXmlResOp(), new NoOp(),
94            new ReadXmlAttrsOp(), new NoOp(),
95            new ParseXmlResOp(), new NoOp(),
96            new ParseLargeXmlResOp(), new NoOp(),
97            new LayoutInflaterOp(), new NoOp(),
98            new LayoutInflaterLargeOp(), new NoOp(),
99            new LayoutInflaterViewOp(), new NoOp(),
100            new LayoutInflaterButtonOp(), new NoOp(),
101            new LayoutInflaterImageButtonOp(), new NoOp(),
102            new CreateBitmapOp(), new NoOp(),
103            new CreateRecycleBitmapOp(), new NoOp(),
104            new LoadSmallBitmapOp(), new NoOp(),
105            new LoadRecycleSmallBitmapOp(), new NoOp(),
106            new LoadLargeBitmapOp(), new NoOp(),
107            new LoadRecycleLargeBitmapOp(), new NoOp(),
108            new LoadSmallScaledBitmapOp(), new NoOp(),
109            new LoadLargeScaledBitmapOp(), new NoOp(),
110    };
111
112    final static Op[] mAvailOps = new Op[] {
113            null,
114            new NoOp(),
115            new CpuOp(),
116            new SchedulerOp(),
117            new MethodCallOp(),
118            new GcOp(),
119            new ObjectGcOp(),
120            new FinalizingGcOp(),
121            new PaintGcOp(),
122            new IpcOp(),
123            new CreateFileOp(),
124            new CreateWriteFileOp(),
125            new CreateWriteSyncFileOp(),
126            new WriteFileOp(),
127            new ReadFileOp(),
128            new OpenXmlResOp(),
129            new ReadXmlAttrsOp(),
130            new ParseXmlResOp(),
131            new ParseLargeXmlResOp(),
132            new LayoutInflaterOp(),
133            new LayoutInflaterLargeOp(),
134            new LayoutInflaterViewOp(),
135            new LayoutInflaterButtonOp(),
136            new LayoutInflaterImageButtonOp(),
137            new CreateBitmapOp(),
138            new CreateRecycleBitmapOp(),
139            new LoadSmallBitmapOp(),
140            new LoadRecycleSmallBitmapOp(),
141            new LoadLargeBitmapOp(),
142            new LoadRecycleLargeBitmapOp(),
143            new LoadSmallScaledBitmapOp(),
144            new LoadLargeScaledBitmapOp(),
145    };
146
147    static final int CMD_START_TEST = 1;
148    static final int CMD_TERMINATE = 2;
149
150    static final int MSG_REALLY_START = 1000;
151    static final int MSG_REALLY_TERMINATE = 1001;
152
153    static final int RES_TEST_FINISHED = 1;
154    static final int RES_TERMINATED = 2;
155
156    final Handler mHandler = new Handler() {
157        @Override public void handleMessage(Message msg) {
158            switch (msg.what) {
159                case CMD_START_TEST: {
160                    // Give a little time for things to settle down.
161                    Message newMsg = Message.obtain(null, MSG_REALLY_START);
162                    newMsg.obj = msg.obj;
163                    newMsg.replyTo = msg.replyTo;
164                    sendMessageDelayed(newMsg, 500);
165                } break;
166                case MSG_REALLY_START: {
167                    Bundle bundle = (Bundle)msg.obj;
168                    bundle.setClassLoader(getClassLoader());
169                    final TestArgs args = (TestArgs)bundle.getParcelable("args");
170                    final Messenger replyTo = msg.replyTo;
171                    mRunner.run(this, args, new Runnable() {
172                        @Override public void run() {
173                            if (replyTo != null) {
174                                Message msg = Message.obtain(null, RES_TEST_FINISHED);
175                                Bundle bundle = new Bundle();
176                                bundle.putParcelable("res", new RunResult(mRunner));
177                                msg.obj = bundle;
178                                try {
179                                    replyTo.send(msg);
180                                } catch (RemoteException e) {
181                                }
182                            }
183                        }
184                    });
185                } break;
186                case CMD_TERMINATE: {
187                    // Give a little time for things to settle down.
188                    Message newMsg = Message.obtain(null, MSG_REALLY_TERMINATE);
189                    newMsg.obj = msg.obj;
190                    newMsg.replyTo = msg.replyTo;
191                    sendMessageDelayed(newMsg, 50);
192                } break;
193                case MSG_REALLY_TERMINATE: {
194                    if (msg.replyTo != null) {
195                        Message reply = Message.obtain(null, RES_TERMINATED);
196                        try {
197                            msg.replyTo.send(reply);
198                        } catch (RemoteException e) {
199                        }
200                    }
201                    terminate();
202                } break;
203            }
204        }
205    };
206
207    final TestRunner mRunner = new TestRunner();
208
209    @Override
210    public IBinder onBind(Intent intent) {
211        return (new Messenger(mHandler)).getBinder();
212    }
213
214    void terminate() {
215        Runtime.getRuntime().exit(0);
216    }
217
218    enum BackgroundMode {
219        NOTHING,
220        CPU,
221        SCHEDULER
222    };
223
224    public class TestRunner {
225        Handler mHandler;
226        long mMaxRunTime;
227        long mMaxOps;
228        Op mForegroundOp;
229        Op mBackgroundOp;
230        Runnable mDoneCallback;
231
232        RunnerThread mBackgroundThread;
233        RunnerThread mForegroundThread;
234        long mStartTime;
235
236        boolean mBackgroundRunning;
237        boolean mForegroundRunning;
238
239        long mBackgroundEndTime;
240        long mBackgroundOps;
241        long mForegroundEndTime;
242        long mForegroundOps;
243
244        public TestRunner() {
245        }
246
247        public String getForegroundName() {
248            return mForegroundOp.getName();
249        }
250
251        public String getBackgroundName() {
252            return mBackgroundOp.getName();
253        }
254
255        public String getName() {
256            String fgName = mForegroundOp.getName();
257            String bgName = mBackgroundOp.getName();
258            StringBuilder res = new StringBuilder();
259            if (fgName != null) {
260                res.append(fgName);
261                res.append("Fg");
262            }
263            if (bgName != null) {
264                res.append(bgName);
265                res.append("Bg");
266            }
267            return res.toString();
268        }
269
270        public String getForegroundLongName() {
271            return mForegroundOp.getLongName();
272        }
273
274        public String getBackgroundLongName() {
275            return mBackgroundOp.getLongName();
276        }
277
278        public void run(Handler handler, TestArgs args, Runnable doneCallback) {
279            mHandler = handler;
280            mMaxRunTime = args.maxTime;
281            mMaxOps = args.maxOps;
282            if (args.combOp >= 0) {
283                mForegroundOp = mOpPairs[args.combOp];
284                mBackgroundOp = mOpPairs[args.combOp+1];
285            } else {
286                mForegroundOp = mAvailOps[args.fgOp];
287                mBackgroundOp = mAvailOps[args.bgOp];
288            }
289            mDoneCallback = doneCallback;
290            mBackgroundThread = new RunnerThread("background", new Runnable() {
291                @Override public void run() {
292                    boolean running;
293                    int ops = 0;
294                    do {
295                        running = mBackgroundOp.onRun();
296                        ops++;
297                    } while (evalRepeat(running, true) && running);
298                    mBackgroundEndTime = SystemClock.uptimeMillis();
299                    mBackgroundOps = ops * mBackgroundOp.getOpsPerRun();
300                    threadFinished(false);
301                }
302            }, Process.THREAD_PRIORITY_BACKGROUND);
303            mForegroundThread = new RunnerThread("background", new Runnable() {
304                @Override public void run() {
305                    boolean running;
306                    int ops = 0;
307                    do {
308                        running = mForegroundOp.onRun();
309                        ops++;
310                    } while (evalRepeat(true, running) && running);
311                    mForegroundEndTime = SystemClock.uptimeMillis();
312                    mForegroundOps = ops * mForegroundOp.getOpsPerRun();
313                    threadFinished(true);
314                }
315            }, Process.THREAD_PRIORITY_FOREGROUND);
316
317            mForegroundOp.onInit(TestService.this, true);
318            mBackgroundOp.onInit(TestService.this, false);
319
320            synchronized (this) {
321                mStartTime = SystemClock.uptimeMillis();
322                mBackgroundRunning = true;
323                mForegroundRunning = true;
324            }
325
326            mBackgroundThread.start();
327            mForegroundThread.start();
328        }
329
330        public long getForegroundTime() {
331            return mForegroundEndTime-mStartTime;
332        }
333
334        public long getForegroundOps() {
335            return mForegroundOps;
336        }
337
338        public long getBackgroundTime() {
339            return mBackgroundEndTime-mStartTime;
340        }
341
342        public long getBackgroundOps() {
343            return mBackgroundOps;
344        }
345
346        private boolean evalRepeat(boolean bgRunning, boolean fgRunning) {
347            synchronized (this) {
348                if (!bgRunning) {
349                    mBackgroundRunning = false;
350                }
351                if (!fgRunning) {
352                    mForegroundRunning = false;
353                }
354                if (!mBackgroundRunning && !mForegroundRunning) {
355                    return false;
356                }
357                if (mMaxOps > 0) {
358                    // iteration-limited case
359                    if (mForegroundOps >= mMaxOps) {
360                        return false;
361                    }
362                    mForegroundOps++;
363                } else {
364                    // time-limited case
365                    long now = SystemClock.uptimeMillis();
366                    if (now > (mStartTime+mMaxRunTime)) {
367                        return false;
368                    }
369                }
370                return true;
371            }
372        }
373
374        private void threadFinished(boolean foreground) {
375            synchronized (this) {
376                if (foreground) {
377                    mForegroundRunning = false;
378                } else {
379                    mBackgroundRunning = false;
380                }
381                if (!mBackgroundRunning && !mForegroundRunning) {
382                    mHandler.post(new Runnable() {
383                        @Override public void run() {
384                            mForegroundOp.onTerm(TestService.this);
385                            mBackgroundOp.onTerm(TestService.this);
386                            if (mDoneCallback != null) {
387                                mDoneCallback.run();
388                            }
389                        }
390                    });
391                }
392            }
393        }
394    }
395
396    class RunnerThread extends Thread {
397        private final Runnable mOp;
398        private final int mPriority;
399
400        RunnerThread(String name, Runnable op, int priority) {
401            super(name);
402            mOp = op;
403            mPriority = priority;
404        }
405
406        public void run() {
407            Process.setThreadPriority(mPriority);
408            mOp.run();
409        }
410    }
411
412    static public abstract class Op {
413        final String mName;
414        final String mLongName;
415
416        public Op(String name, String longName) {
417            mName = name;
418            mLongName = longName;
419        }
420
421        public String getName() {
422            return mName;
423        }
424
425        public String getLongName() {
426            return mLongName;
427        }
428
429        void onInit(Context context, boolean foreground) {
430        }
431
432        abstract boolean onRun();
433
434        void onTerm(Context context) {
435        }
436
437        int getOpsPerRun() {
438            return 1;
439        }
440    }
441
442    static class NoOp extends Op {
443        NoOp() {
444            super(null, "Nothing");
445        }
446
447        boolean onRun() {
448            return false;
449        }
450
451        int getOpsPerRun() {
452            return 0;
453        }
454    }
455
456    static class CpuOp extends Op {
457        CpuOp() {
458            super("CPU", "Consume CPU");
459        }
460
461        boolean onRun() {
462            return true;
463        }
464    }
465
466    static class SchedulerOp extends Op {
467        SchedulerOp() {
468            super("Sched", "Change scheduler group");
469        }
470
471        boolean onRun() {
472            Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
473            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
474            return true;
475        }
476    }
477
478    static class GcOp extends Op {
479        GcOp() {
480            super("Gc", "Run garbage collector");
481        }
482
483        boolean onRun() {
484            byte[] stuff = new byte[1024*1024];
485            return true;
486        }
487    }
488
489    static class ObjectGcOp extends Op {
490        ObjectGcOp() {
491            super("ObjectGc", "Run garbage collector with simple objects");
492        }
493
494        boolean onRun() {
495            Object obj = new Object();
496            return true;
497        }
498    }
499
500    static class FinalizingGcOp extends Op {
501        class Finalizable {
502            Finalizable() {}
503            @Override
504            protected void finalize() throws Throwable {
505                super.finalize();
506            }
507        }
508
509        FinalizingGcOp() {
510            super("FinalizingGc", "Run garbage collector with finalizable objects");
511        }
512
513        boolean onRun() {
514            Finalizable obj = new Finalizable();
515            return true;
516        }
517    }
518
519    static class PaintGcOp extends Op {
520        PaintGcOp() {
521            super("PaintGc", "Run garbage collector with Paint objects");
522        }
523
524        boolean onRun() {
525            Paint p = new Paint();
526            return true;
527        }
528    }
529
530    static class MethodCallOp extends Op {
531        MethodCallOp() {
532            super("MethodCall", "Method call");
533        }
534
535        boolean onRun() {
536            final int N = getOpsPerRun();
537            for (int i=0; i<N; i++) {
538                someFunc(i);
539            }
540            return true;
541        }
542
543        int someFunc(int foo) {
544            return 0;
545        }
546
547        int getOpsPerRun() {
548            return 500;
549        }
550    }
551
552    static class IpcOp extends Op {
553        PackageManager mPm;
554        String mProcessName;
555
556        IpcOp() {
557            super("Ipc", "IPC to system process");
558        }
559
560        void onInit(Context context, boolean foreground) {
561            mPm = context.getPackageManager();
562            mProcessName = context.getApplicationInfo().processName;
563        }
564
565        boolean onRun() {
566            final int N = getOpsPerRun();
567            for (int i=0; i<N; i++) {
568                mPm.queryContentProviders(mProcessName, Process.myUid(), 0);
569            }
570            return true;
571        }
572
573        int getOpsPerRun() {
574            return 100;
575        }
576    }
577
578    static class OpenXmlResOp extends Op {
579        Context mContext;
580
581        OpenXmlResOp() {
582            super("OpenXmlRes", "Open (and close) an XML resource");
583        }
584
585        void onInit(Context context, boolean foreground) {
586            mContext = context;
587        }
588
589        boolean onRun() {
590            XmlResourceParser parser = mContext.getResources().getLayout(R.xml.simple);
591            parser.close();
592            return true;
593        }
594    }
595
596    static class ReadXmlAttrsOp extends Op {
597        Context mContext;
598        XmlResourceParser mParser;
599        AttributeSet mAttrs;
600
601        ReadXmlAttrsOp() {
602            super("ReadXmlAttrs", "Read attributes from an XML tag");
603        }
604
605        void onInit(Context context, boolean foreground) {
606            mContext = context;
607            mParser = mContext.getResources().getLayout(R.xml.simple);
608            mAttrs = Xml.asAttributeSet(mParser);
609
610            int eventType;
611            try {
612                // Find the first <item> tag.
613                eventType = mParser.getEventType();
614                String tagName;
615                do {
616                    if (eventType == XmlPullParser.START_TAG) {
617                        tagName = mParser.getName();
618                        if (tagName.equals("item")) {
619                            break;
620                        }
621                    }
622                    eventType = mParser.next();
623                } while (eventType != XmlPullParser.END_DOCUMENT);
624            } catch (XmlPullParserException e) {
625                throw new RuntimeException("I died", e);
626            } catch (IOException e) {
627                throw new RuntimeException("I died", e);
628            }
629        }
630
631        void onTerm(Context context) {
632            mParser.close();
633        }
634
635        boolean onRun() {
636            TypedArray a = mContext.obtainStyledAttributes(mAttrs,
637                    com.android.internal.R.styleable.MenuItem);
638            a.recycle();
639            return true;
640        }
641    }
642
643    static class ParseXmlResOp extends Op {
644        Context mContext;
645
646        ParseXmlResOp() {
647            super("ParseXmlRes", "Parse compiled XML resource");
648        }
649
650        void onInit(Context context, boolean foreground) {
651            mContext = context;
652        }
653
654        boolean onRun() {
655            SimpleInflater inf = new SimpleInflater(mContext);
656            inf.inflate(R.xml.simple);
657            return true;
658        }
659    }
660
661    static class ParseLargeXmlResOp extends Op {
662        Context mContext;
663
664        ParseLargeXmlResOp() {
665            super("ParseLargeXmlRes", "Parse large XML resource");
666        }
667
668        void onInit(Context context, boolean foreground) {
669            mContext = context;
670        }
671
672        boolean onRun() {
673            SimpleInflater inf = new SimpleInflater(mContext);
674            inf.inflate(R.xml.simple_large);
675            return true;
676        }
677    }
678
679    static class LayoutInflaterOp extends Op {
680        Context mContext;
681
682        LayoutInflaterOp() {
683            super("LayoutInflater", "Inflate layout resource");
684        }
685
686        void onInit(Context context, boolean foreground) {
687            mContext = context;
688        }
689
690        boolean onRun() {
691            if (Looper.myLooper() == null) {
692                Looper.prepare();
693            }
694            LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
695                    Context.LAYOUT_INFLATER_SERVICE);
696            inf.inflate(R.layout.small_layout, null);
697            return true;
698        }
699    }
700
701    static class LayoutInflaterLargeOp extends Op {
702        Context mContext;
703
704        LayoutInflaterLargeOp() {
705            super("LayoutInflaterLarge", "Inflate large 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.large_layout, null);
719            return true;
720        }
721    }
722
723    static class LayoutInflaterViewOp extends Op {
724        Context mContext;
725
726        LayoutInflaterViewOp() {
727            super("LayoutInflaterView", "Inflate layout with 50 View objects");
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.view_layout, null);
741            return true;
742        }
743    }
744
745    static class LayoutInflaterButtonOp extends Op {
746        Context mContext;
747
748        LayoutInflaterButtonOp() {
749            super("LayoutInflaterButton", "Inflate layout with 50 Button objects");
750        }
751
752        void onInit(Context context, boolean foreground) {
753            mContext = context;
754        }
755
756        boolean onRun() {
757            if (Looper.myLooper() == null) {
758                Looper.prepare();
759            }
760            LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
761                    Context.LAYOUT_INFLATER_SERVICE);
762            inf.inflate(R.layout.button_layout, null);
763            return true;
764        }
765    }
766
767    static class LayoutInflaterImageButtonOp extends Op {
768        Context mContext;
769
770        LayoutInflaterImageButtonOp() {
771            super("LayoutInflaterImageButton", "Inflate layout with 50 ImageButton objects");
772        }
773
774        void onInit(Context context, boolean foreground) {
775            mContext = context;
776        }
777
778        boolean onRun() {
779            if (Looper.myLooper() == null) {
780                Looper.prepare();
781            }
782            LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
783                    Context.LAYOUT_INFLATER_SERVICE);
784            inf.inflate(R.layout.image_button_layout, null);
785            return true;
786        }
787    }
788
789    static class CreateBitmapOp extends Op {
790        Context mContext;
791
792        CreateBitmapOp() {
793            super("CreateBitmap", "Create a Bitmap");
794        }
795
796        void onInit(Context context, boolean foreground) {
797            mContext = context;
798        }
799
800        boolean onRun() {
801            BitmapFactory.Options opts = new BitmapFactory.Options();
802            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
803            Bitmap bm = Bitmap.createBitmap(16, 16, Bitmap.Config.ARGB_8888);
804            return true;
805        }
806    }
807
808    static class CreateRecycleBitmapOp extends Op {
809        Context mContext;
810
811        CreateRecycleBitmapOp() {
812            super("CreateRecycleBitmap", "Create and recycle a Bitmap");
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 = Bitmap.createBitmap(16, 16, Bitmap.Config.ARGB_8888);
823            bm.recycle();
824            return true;
825        }
826    }
827
828    static class LoadSmallBitmapOp extends Op {
829        Context mContext;
830
831        LoadSmallBitmapOp() {
832            super("LoadSmallBitmap", "Load small raw bitmap");
833        }
834
835        void onInit(Context context, boolean foreground) {
836            mContext = context;
837        }
838
839        boolean onRun() {
840            BitmapFactory.Options opts = new BitmapFactory.Options();
841            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
842            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
843                    R.drawable.stat_sample, opts);
844            return true;
845        }
846    }
847
848    static class LoadRecycleSmallBitmapOp extends Op {
849        Context mContext;
850
851        LoadRecycleSmallBitmapOp() {
852            super("LoadRecycleSmallBitmap", "Load and recycle small raw bitmap");
853        }
854
855        void onInit(Context context, boolean foreground) {
856            mContext = context;
857        }
858
859        boolean onRun() {
860            BitmapFactory.Options opts = new BitmapFactory.Options();
861            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
862            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
863                    R.drawable.stat_sample, opts);
864            bm.recycle();
865            return true;
866        }
867    }
868
869    static class LoadLargeBitmapOp extends Op {
870        Context mContext;
871
872        LoadLargeBitmapOp() {
873            super("LoadLargeBitmap", "Load large raw bitmap");
874        }
875
876        void onInit(Context context, boolean foreground) {
877            mContext = context;
878        }
879
880        boolean onRun() {
881            BitmapFactory.Options opts = new BitmapFactory.Options();
882            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
883            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
884                    R.drawable.wallpaper_goldengate, opts);
885            return true;
886        }
887    }
888
889    static class LoadRecycleLargeBitmapOp extends Op {
890        Context mContext;
891
892        LoadRecycleLargeBitmapOp() {
893            super("LoadRecycleLargeBitmap", "Load and recycle large raw bitmap");
894        }
895
896        void onInit(Context context, boolean foreground) {
897            mContext = context;
898        }
899
900        boolean onRun() {
901            BitmapFactory.Options opts = new BitmapFactory.Options();
902            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
903            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
904                    R.drawable.wallpaper_goldengate, opts);
905            bm.recycle();
906            return true;
907        }
908    }
909
910    static class LoadSmallScaledBitmapOp extends Op {
911        Context mContext;
912
913        LoadSmallScaledBitmapOp() {
914            super("LoadSmallScaledBitmap", "Load small raw bitmap that is scaled for density");
915        }
916
917        void onInit(Context context, boolean foreground) {
918            mContext = context;
919        }
920
921        boolean onRun() {
922            BitmapFactory.Options opts = new BitmapFactory.Options();
923            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
924            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
925                    R.drawable.stat_sample_scale, opts);
926            return true;
927        }
928    }
929
930    static class LoadLargeScaledBitmapOp extends Op {
931        Context mContext;
932
933        LoadLargeScaledBitmapOp() {
934            super("LoadLargeScaledBitmap", "Load large raw bitmap that is scaled for density");
935        }
936
937        void onInit(Context context, boolean foreground) {
938            mContext = context;
939        }
940
941        boolean onRun() {
942            BitmapFactory.Options opts = new BitmapFactory.Options();
943            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
944            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
945                    R.drawable.wallpaper_goldengate_scale, opts);
946            return true;
947        }
948    }
949
950    static class CreateFileOp extends Op {
951        File mFile;
952
953        CreateFileOp() {
954            super("CreateFile", "Create and delete a file");
955        }
956
957        void onInit(Context context, boolean foreground) {
958            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
959            mFile.delete();
960        }
961
962        boolean onRun() {
963            try {
964                mFile.createNewFile();
965            } catch (IOException e) {
966                Log.w(TAG, "Failure creating " + mFile, e);
967            }
968            mFile.delete();
969            return true;
970        }
971    }
972
973    static class CreateWriteFileOp extends Op {
974        File mFile;
975
976        CreateWriteFileOp() {
977            super("CreateWriteFile", "Create, write, and delete a file");
978        }
979
980        void onInit(Context context, boolean foreground) {
981            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
982            mFile.delete();
983        }
984
985        boolean onRun() {
986            try {
987                FileOutputStream fos = new FileOutputStream(mFile);
988                fos.write(1);
989                fos.close();
990            } catch (IOException e) {
991                Log.w(TAG, "Failure creating " + mFile, e);
992            }
993            mFile.delete();
994            return true;
995        }
996    }
997
998    static class CreateWriteSyncFileOp extends Op {
999        File mFile;
1000
1001        CreateWriteSyncFileOp() {
1002            super("CreateWriteSyncFile", "Create, write, sync, and delete a file");
1003        }
1004
1005        void onInit(Context context, boolean foreground) {
1006            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
1007            mFile.delete();
1008        }
1009
1010        boolean onRun() {
1011            try {
1012                FileOutputStream fos = new FileOutputStream(mFile);
1013                fos.write(1);
1014                fos.flush();
1015                FileUtils.sync(fos);
1016                fos.close();
1017            } catch (IOException e) {
1018                Log.w(TAG, "Failure creating " + mFile, e);
1019            }
1020            mFile.delete();
1021            return true;
1022        }
1023    }
1024
1025    static class WriteFileOp extends Op {
1026        File mFile;
1027        RandomAccessFile mRAF;
1028        byte[] mBuffer;
1029
1030        WriteFileOp() {
1031            super("WriteFile", "Truncate and write a 64k file");
1032        }
1033
1034        void onInit(Context context, boolean foreground) {
1035            mBuffer = new byte[1024*64];
1036            for (int i=0; i<mBuffer.length; i++) {
1037                mBuffer[i] = (byte)i;
1038            }
1039            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
1040            mFile.delete();
1041            try {
1042                mRAF = new RandomAccessFile(mFile, "rw");
1043            } catch (FileNotFoundException e) {
1044                Log.w(TAG, "Failure creating " + mFile, e);
1045            }
1046        }
1047
1048        boolean onRun() {
1049            try {
1050                mRAF.seek(0);
1051                mRAF.setLength(0);
1052                mRAF.write(mBuffer);
1053            } catch (IOException e) {
1054                Log.w(TAG, "Failure writing " + mFile, e);
1055            }
1056            return true;
1057        }
1058
1059        void onTerm(Context context) {
1060            try {
1061                mRAF.close();
1062            } catch (IOException e) {
1063                Log.w(TAG, "Failure closing " + mFile, e);
1064            }
1065            mFile.delete();
1066        }
1067    }
1068
1069    static class ReadFileOp extends Op {
1070        File mFile;
1071        RandomAccessFile mRAF;
1072        byte[] mBuffer;
1073
1074        ReadFileOp() {
1075            super("ReadFile", "Seek and read a 64k file");
1076        }
1077
1078        void onInit(Context context, boolean foreground) {
1079            mBuffer = new byte[1024*64];
1080            for (int i=0; i<mBuffer.length; i++) {
1081                mBuffer[i] = (byte)i;
1082            }
1083            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
1084            mFile.delete();
1085            try {
1086                mRAF = new RandomAccessFile(mFile, "rw");
1087                mRAF.seek(0);
1088                mRAF.setLength(0);
1089                mRAF.write(mBuffer);
1090            } catch (IOException e) {
1091                Log.w(TAG, "Failure creating " + mFile, e);
1092            }
1093        }
1094
1095        boolean onRun() {
1096            try {
1097                mRAF.seek(0);
1098                mRAF.read(mBuffer);
1099            } catch (IOException e) {
1100                Log.w(TAG, "Failure reading " + mFile, e);
1101            }
1102            return true;
1103        }
1104
1105        void onTerm(Context context) {
1106            try {
1107                mRAF.close();
1108            } catch (IOException e) {
1109                Log.w(TAG, "Failure closing " + mFile, e);
1110            }
1111            mFile.delete();
1112        }
1113    }
1114}
1115