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