Home | History | Annotate | Download | only in frameworkperf
      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
    226     public IBinder onBind(Intent intent) {
    227         return (new Messenger(mHandler)).getBinder();
    228     }
    229 
    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 
    260         public TestRunner() {
    261         }
    262 
    263         public String getForegroundName() {
    264             return mForegroundOp.getName();
    265         }
    266 
    267         public String getBackgroundName() {
    268             return mBackgroundOp.getName();
    269         }
    270 
    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 
    286         public String getForegroundLongName() {
    287             return mForegroundOp.getLongName();
    288         }
    289 
    290         public String getBackgroundLongName() {
    291             return mBackgroundOp.getLongName();
    292         }
    293 
    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 
    346         public long getForegroundTime() {
    347             return mForegroundEndTime-mStartTime;
    348         }
    349 
    350         public long getForegroundOps() {
    351             return mForegroundOps;
    352         }
    353 
    354         public long getBackgroundTime() {
    355             return mBackgroundEndTime-mStartTime;
    356         }
    357 
    358         public long getBackgroundOps() {
    359             return mBackgroundOps;
    360         }
    361 
    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 
    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 
    416         RunnerThread(String name, Runnable op, int priority) {
    417             super(name);
    418             mOp = op;
    419             mPriority = priority;
    420         }
    421 
    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 
    432         public Op(String name, String longName) {
    433             mName = name;
    434             mLongName = longName;
    435         }
    436 
    437         public String getName() {
    438             return mName;
    439         }
    440 
    441         public String getLongName() {
    442             return mLongName;
    443         }
    444 
    445         void onInit(Context context, boolean foreground) {
    446         }
    447 
    448         abstract boolean onRun();
    449 
    450         void onTerm(Context context) {
    451         }
    452 
    453         int getOpsPerRun() {
    454             return 1;
    455         }
    456     }
    457 
    458     static class NoOp extends Op {
    459         NoOp() {
    460             super(null, "Nothing");
    461         }
    462 
    463         boolean onRun() {
    464             return false;
    465         }
    466 
    467         int getOpsPerRun() {
    468             return 0;
    469         }
    470     }
    471 
    472     static class CpuOp extends Op {
    473         CpuOp() {
    474             super("CPU", "Consume CPU");
    475         }
    476 
    477         boolean onRun() {
    478             return true;
    479         }
    480     }
    481 
    482     static class SchedulerOp extends Op {
    483         SchedulerOp() {
    484             super("Sched", "Change scheduler group");
    485         }
    486 
    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 {
    495         GcOp() {
    496             super("Gc", "Run garbage collector");
    497         }
    498 
    499         boolean onRun() {
    500             byte[] stuff = new byte[1024*1024];
    501             return true;
    502         }
    503     }
    504 
    505     static class ObjectGcOp extends Op {
    506         ObjectGcOp() {
    507             super("ObjectGc", "Run garbage collector with simple objects");
    508         }
    509 
    510         boolean onRun() {
    511             Object obj = new Object();
    512             return true;
    513         }
    514     }
    515 
    516     static class FinalizingGcOp extends Op {
    517         class Finalizable {
    518             Finalizable() {}
    519             @Override
    520             protected void finalize() throws Throwable {
    521                 super.finalize();
    522             }
    523         }
    524 
    525         FinalizingGcOp() {
    526             super("FinalizingGc", "Run garbage collector with finalizable objects");
    527         }
    528 
    529         boolean onRun() {
    530             Finalizable obj = new Finalizable();
    531             return true;
    532         }
    533     }
    534 
    535     static class PaintGcOp extends Op {
    536         PaintGcOp() {
    537             super("PaintGc", "Run garbage collector with Paint objects");
    538         }
    539 
    540         boolean onRun() {
    541             Paint p = new Paint();
    542             return true;
    543         }
    544     }
    545 
    546     static class MethodCallOp extends Op {
    547         MethodCallOp() {
    548             super("MethodCall", "Method call");
    549         }
    550 
    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 
    559         int someFunc(int foo) {
    560             return 0;
    561         }
    562 
    563         int getOpsPerRun() {
    564             return 500;
    565         }
    566     }
    567 
    568     static class IpcOp extends Op {
    569         PackageManager mPm;
    570         String mProcessName;
    571 
    572         IpcOp() {
    573             super("Ipc", "IPC to system process");
    574         }
    575 
    576         void onInit(Context context, boolean foreground) {
    577             mPm = context.getPackageManager();
    578             mProcessName = context.getApplicationInfo().processName;
    579         }
    580 
    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 
    589         int getOpsPerRun() {
    590             return 100;
    591         }
    592     }
    593 
    594     static class OpenXmlResOp extends Op {
    595         Context mContext;
    596 
    597         OpenXmlResOp() {
    598             super("OpenXmlRes", "Open (and close) an XML resource");
    599         }
    600 
    601         void onInit(Context context, boolean foreground) {
    602             mContext = context;
    603         }
    604 
    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 
    617         ReadXmlAttrsOp() {
    618             super("ReadXmlAttrs", "Read attributes from an XML tag");
    619         }
    620 
    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 
    647         void onTerm(Context context) {
    648             mParser.close();
    649         }
    650 
    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 
    662         ParseXmlResOp() {
    663             super("ParseXmlRes", "Parse compiled XML resource");
    664         }
    665 
    666         void onInit(Context context, boolean foreground) {
    667             mContext = context;
    668         }
    669 
    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 
    680         ParseLargeXmlResOp() {
    681             super("ParseLargeXmlRes", "Parse large XML resource");
    682         }
    683 
    684         void onInit(Context context, boolean foreground) {
    685             mContext = context;
    686         }
    687 
    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 
    698         LayoutInflaterOp() {
    699             super("LayoutInflater", "Inflate layout resource");
    700         }
    701 
    702         void onInit(Context context, boolean foreground) {
    703             mContext = context;
    704         }
    705 
    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 
    720         LayoutInflaterLargeOp() {
    721             super("LayoutInflaterLarge", "Inflate large layout resource");
    722         }
    723 
    724         void onInit(Context context, boolean foreground) {
    725             mContext = context;
    726         }
    727 
    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 
    742         LayoutInflaterViewOp() {
    743             super("LayoutInflaterView", "Inflate layout with 50 View objects");
    744         }
    745 
    746         void onInit(Context context, boolean foreground) {
    747             mContext = context;
    748         }
    749 
    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 
    764         LayoutInflaterButtonOp() {
    765             super("LayoutInflaterButton", "Inflate layout with 50 Button objects");
    766         }
    767 
    768         void onInit(Context context, boolean foreground) {
    769             mContext = context;
    770         }
    771 
    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 
    786         LayoutInflaterImageButtonOp() {
    787             super("LayoutInflaterImageButton", "Inflate layout with 50 ImageButton objects");
    788         }
    789 
    790         void onInit(Context context, boolean foreground) {
    791             mContext = context;
    792         }
    793 
    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 
    808         CreateBitmapOp() {
    809             super("CreateBitmap", "Create a Bitmap");
    810         }
    811 
    812         void onInit(Context context, boolean foreground) {
    813             mContext = context;
    814         }
    815 
    816         boolean onRun() {
    817             BitmapFactory.Options opts = new BitmapFactory.Options();
    818             opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
    819             Bitmap bm = Bitmap.createBitmap(16, 16, Bitmap.Config.ARGB_8888);
    820             return true;
    821         }
    822     }
    823 
    824     static class CreateRecycleBitmapOp extends Op {
    825         Context mContext;
    826 
    827         CreateRecycleBitmapOp() {
    828             super("CreateRecycleBitmap", "Create and recycle a Bitmap");
    829         }
    830 
    831         void onInit(Context context, boolean foreground) {
    832             mContext = context;
    833         }
    834 
    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 
    847         LoadSmallBitmapOp() {
    848             super("LoadSmallBitmap", "Load small raw bitmap");
    849         }
    850 
    851         void onInit(Context context, boolean foreground) {
    852             mContext = context;
    853         }
    854 
    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 
    867         LoadRecycleSmallBitmapOp() {
    868             super("LoadRecycleSmallBitmap", "Load and recycle small raw bitmap");
    869         }
    870 
    871         void onInit(Context context, boolean foreground) {
    872             mContext = context;
    873         }
    874 
    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 
    888         LoadLargeBitmapOp() {
    889             super("LoadLargeBitmap", "Load large raw bitmap");
    890         }
    891 
    892         void onInit(Context context, boolean foreground) {
    893             mContext = context;
    894         }
    895 
    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 
    908         LoadRecycleLargeBitmapOp() {
    909             super("LoadRecycleLargeBitmap", "Load and recycle large raw bitmap");
    910         }
    911 
    912         void onInit(Context context, boolean foreground) {
    913             mContext = context;
    914         }
    915 
    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 
    929         LoadSmallScaledBitmapOp() {
    930             super("LoadSmallScaledBitmap", "Load small raw bitmap that is scaled for density");
    931         }
    932 
    933         void onInit(Context context, boolean foreground) {
    934             mContext = context;
    935         }
    936 
    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 
    949         LoadLargeScaledBitmapOp() {
    950             super("LoadLargeScaledBitmap", "Load large raw bitmap that is scaled for density");
    951         }
    952 
    953         void onInit(Context context, boolean foreground) {
    954             mContext = context;
    955         }
    956 
    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 
    969         CreateFileOp() {
    970             super("CreateFile", "Create and delete a file");
    971         }
    972 
    973         void onInit(Context context, boolean foreground) {
    974             mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
    975             mFile.delete();
    976         }
    977 
    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 
    992         CreateWriteFileOp() {
    993             super("CreateWriteFile", "Create, write, and delete a file");
    994         }
    995 
    996         void onInit(Context context, boolean foreground) {
    997             mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
    998             mFile.delete();
    999         }
   1000 
   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 
   1017         CreateWriteSyncFileOp() {
   1018             super("CreateWriteSyncFile", "Create, write, sync, and delete a file");
   1019         }
   1020 
   1021         void onInit(Context context, boolean foreground) {
   1022             mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
   1023             mFile.delete();
   1024         }
   1025 
   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 
   1046         WriteFileOp() {
   1047             super("WriteFile", "Truncate and write a 64k file");
   1048         }
   1049 
   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 
   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 
   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 
   1090         ReadFileOp() {
   1091             super("ReadFile", "Seek and read a 64k file");
   1092         }
   1093 
   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 
   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 
   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 
   1136         GenericMapOp(String name, String longName, int size) {
   1137             super(name, longName);
   1138             mSize = size;
   1139         }
   1140 
   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 
   1156         int getOpsPerRun() {
   1157             return mSize;
   1158         }
   1159     }
   1160 
   1161     static class GrowTinyHashMapOp extends GenericMapOp {
   1162         GrowTinyHashMapOp() {
   1163             super("GrowTinyHashMap", "Add 5 items to a HashMap", 5);
   1164         }
   1165 
   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 {
   1176         GrowTinyArrayMapOp() {
   1177             super("GrowTinyArrayMap", "Add 5 items to a ArrayMap", 5);
   1178         }
   1179 
   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 {
   1190         GrowSmallHashMapOp() {
   1191             super("GrowSmallHashMap", "Add 100 items to a HashMap", 100);
   1192         }
   1193 
   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 {
   1204         GrowSmallArrayMapOp() {
   1205             super("GrowSmallArrayMap", "Add 100 items to a ArrayMap", 100);
   1206         }
   1207 
   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 {
   1218         GrowLargeHashMapOp() {
   1219             super("GrowLargeHashMap", "Add 10000 items to a HashMap", 10000);
   1220         }
   1221 
   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 {
   1232         GrowLargeArrayMapOp() {
   1233             super("GrowLargeArrayMap", "Add 10000 items to a ArrayMap", 10000);
   1234         }
   1235 
   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 {
   1246         LookupTinyHashMapOp() {
   1247             super("LookupTinyHashMap", "Lookup items in 5 entry HashMap", 5);
   1248         }
   1249     }
   1250 
   1251     static class LookupTinyArrayMapOp extends LookupSmallArrayMapOp {
   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 
   1260         LookupSmallHashMapOp() {
   1261             super("LookupSmallHashMap", "Lookup items in 100 entry HashMap", 100);
   1262         }
   1263 
   1264         LookupSmallHashMapOp(String name, String longname, int size) {
   1265             super(name, longname, size);
   1266         }
   1267 
   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 
   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 
   1287         LookupSmallArrayMapOp() {
   1288             super("LookupSmallArrayMap", "Lookup items in 100 entry ArrayMap", 100);
   1289         }
   1290 
   1291         LookupSmallArrayMapOp(String name, String longname, int size) {
   1292             super(name, longname, size);
   1293         }
   1294 
   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 
   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 {
   1312         LookupLargeHashMapOp() {
   1313             super("LookupLargeHashMap", "Lookup items in 10000 entry HashMap", 10000);
   1314         }
   1315     }
   1316 
   1317     static class LookupLargeArrayMapOp extends LookupSmallArrayMapOp {
   1318         LookupLargeArrayMapOp() {
   1319             super("LookupLargeArrayMap", "Lookup items in 10000 entry ArrayMap", 10000);
   1320         }
   1321     }
   1322 }
   1323