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