FrameworkPerfActivity.java revision 6b57b7e4d568bfa6273f87ef4c9af2fdc0ca1a06
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.frameworkperf; 18 19import android.app.Activity; 20import android.content.ComponentName; 21import android.content.Intent; 22import android.content.ServiceConnection; 23import android.os.Bundle; 24import android.os.Handler; 25import android.os.IBinder; 26import android.os.Message; 27import android.os.Messenger; 28import android.os.PowerManager; 29import android.os.RemoteException; 30import android.util.Log; 31import android.view.View; 32import android.view.WindowManager; 33import android.widget.AdapterView; 34import android.widget.ArrayAdapter; 35import android.widget.Button; 36import android.widget.CheckBox; 37import android.widget.Spinner; 38import android.widget.TextView; 39 40import java.util.ArrayList; 41 42/** 43 * So you thought sync used up your battery life. 44 */ 45public class FrameworkPerfActivity extends Activity 46 implements AdapterView.OnItemSelectedListener { 47 static final String TAG = "Perf"; 48 49 Spinner mFgSpinner; 50 Spinner mBgSpinner; 51 TextView mTestTime; 52 Button mStartButton; 53 Button mStopButton; 54 CheckBox mLocalCheckBox; 55 TextView mLog; 56 PowerManager.WakeLock mPartialWakeLock; 57 58 long mMaxRunTime = 5000; 59 boolean mStarted; 60 61 final String[] mAvailOpLabels; 62 final String[] mAvailOpDescriptions; 63 64 int mFgTestIndex = -1; 65 int mBgTestIndex = -1; 66 TestService.Op mFgTest; 67 TestService.Op mBgTest; 68 int mCurOpIndex = 0; 69 TestConnection mCurConnection; 70 71 final ArrayList<RunResult> mResults = new ArrayList<RunResult>(); 72 73 class TestConnection implements ServiceConnection { 74 Messenger mService; 75 76 @Override public void onServiceConnected(ComponentName name, IBinder service) { 77 mService = new Messenger(service); 78 dispatchCurOp(this); 79 } 80 81 @Override public void onServiceDisconnected(ComponentName name) { 82 } 83 } 84 85 static final int MSG_CONTINUE = 1000; 86 87 final Handler mHandler = new Handler() { 88 @Override public void handleMessage(Message msg) { 89 switch (msg.what) { 90 case TestService.RES_TEST_FINISHED: { 91 Bundle bundle = (Bundle)msg.obj; 92 bundle.setClassLoader(getClassLoader()); 93 RunResult res = (RunResult)bundle.getParcelable("res"); 94 completeCurOp(res); 95 } break; 96 case TestService.RES_TERMINATED: { 97 // Give a little time for things to settle down. 98 sendMessageDelayed(obtainMessage(MSG_CONTINUE), 500); 99 } break; 100 case MSG_CONTINUE: { 101 startCurOp(); 102 } break; 103 } 104 } 105 }; 106 107 final Messenger mMessenger = new Messenger(mHandler); 108 109 public FrameworkPerfActivity() { 110 mAvailOpLabels = new String[TestService.mAvailOps.length]; 111 mAvailOpDescriptions = new String[TestService.mAvailOps.length]; 112 for (int i=0; i<TestService.mAvailOps.length; i++) { 113 TestService.Op op = TestService.mAvailOps[i]; 114 if (op == null) { 115 mAvailOpLabels[i] = "All"; 116 mAvailOpDescriptions[i] = "All tests"; 117 } else { 118 mAvailOpLabels[i] = op.getName(); 119 if (mAvailOpLabels[i] == null) { 120 mAvailOpLabels[i] = "Nothing"; 121 } 122 mAvailOpDescriptions[i] = op.getLongName(); 123 } 124 } 125 } 126 127 @Override 128 public void onCreate(Bundle savedInstanceState) { 129 super.onCreate(savedInstanceState); 130 131 // Set the layout for this activity. You can find it 132 // in res/layout/hello_activity.xml 133 setContentView(R.layout.main); 134 135 mFgSpinner = (Spinner) findViewById(R.id.fgspinner); 136 ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 137 android.R.layout.simple_spinner_item, mAvailOpLabels); 138 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 139 mFgSpinner.setAdapter(adapter); 140 mFgSpinner.setOnItemSelectedListener(this); 141 mBgSpinner = (Spinner) findViewById(R.id.bgspinner); 142 adapter = new ArrayAdapter<String>(this, 143 android.R.layout.simple_spinner_item, mAvailOpLabels); 144 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 145 mBgSpinner.setAdapter(adapter); 146 mBgSpinner.setOnItemSelectedListener(this); 147 148 mTestTime = (TextView)findViewById(R.id.testtime); 149 150 mStartButton = (Button)findViewById(R.id.start); 151 mStartButton.setOnClickListener(new View.OnClickListener() { 152 @Override public void onClick(View v) { 153 startRunning(); 154 } 155 }); 156 mStopButton = (Button)findViewById(R.id.stop); 157 mStopButton.setOnClickListener(new View.OnClickListener() { 158 @Override public void onClick(View v) { 159 stopRunning(); 160 } 161 }); 162 mStopButton.setEnabled(false); 163 mLocalCheckBox = (CheckBox)findViewById(R.id.local); 164 165 mLog = (TextView)findViewById(R.id.log); 166 167 PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE); 168 mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Scheduler"); 169 mPartialWakeLock.setReferenceCounted(false); 170 } 171 172 @Override 173 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 174 if (parent == mFgSpinner || parent == mBgSpinner) { 175 TestService.Op op = TestService.mAvailOps[position]; 176 if (parent == mFgSpinner) { 177 mFgTestIndex = position; 178 mFgTest = op; 179 ((TextView)findViewById(R.id.fgtext)).setText(mAvailOpDescriptions[position]); 180 } else { 181 mBgTestIndex = position; 182 mBgTest = op; 183 ((TextView)findViewById(R.id.bgtext)).setText(mAvailOpDescriptions[position]); 184 } 185 } 186 } 187 188 @Override 189 public void onNothingSelected(AdapterView<?> parent) { 190 } 191 192 @Override 193 public void onResume() { 194 super.onResume(); 195 } 196 197 @Override 198 public void onDestroy() { 199 super.onDestroy(); 200 stopRunning(); 201 if (mPartialWakeLock.isHeld()) { 202 mPartialWakeLock.release(); 203 } 204 } 205 206 void dispatchCurOp(TestConnection conn) { 207 if (mCurConnection != conn) { 208 Log.w(TAG, "Dispatching on invalid connection: " + conn); 209 return; 210 } 211 TestArgs args = new TestArgs(); 212 args.maxTime = mMaxRunTime; 213 if (mFgTestIndex == 0 && mBgTestIndex == 0) { 214 args.combOp = mCurOpIndex; 215 } else if (mFgTestIndex != 0 && mBgTestIndex != 0) { 216 args.fgOp = mFgTestIndex; 217 args.bgOp = mBgTestIndex; 218 } else { 219 // Skip null test. 220 if (mCurOpIndex == 0) { 221 mCurOpIndex = 1; 222 } 223 if (mFgTestIndex != 0) { 224 args.fgOp = mFgTestIndex; 225 args.bgOp = mCurOpIndex; 226 } else { 227 args.fgOp = mCurOpIndex; 228 args.bgOp = mFgTestIndex; 229 } 230 } 231 Bundle bundle = new Bundle(); 232 bundle.putParcelable("args", args); 233 Message msg = Message.obtain(null, TestService.CMD_START_TEST, bundle); 234 msg.replyTo = mMessenger; 235 try { 236 conn.mService.send(msg); 237 } catch (RemoteException e) { 238 Log.i(TAG, "Failure communicating with service", e); 239 } 240 } 241 242 void completeCurOp(RunResult result) { 243 log(String.format("%s: fg=%d*%gms/op (%dms) / bg=%d*%gms/op (%dms)", 244 result.name, result.fgOps, result.getFgMsPerOp(), result.fgTime, 245 result.bgOps, result.getBgMsPerOp(), result.bgTime)); 246 mResults.add(result); 247 if (!mStarted) { 248 log("Stop"); 249 stopRunning(); 250 return; 251 } 252 if (mFgTest != null && mBgTest != null) { 253 log("Finished"); 254 stopRunning(); 255 return; 256 } 257 if (mFgTest == null && mBgTest == null) { 258 mCurOpIndex+=2; 259 if (mCurOpIndex >= TestService.mOpPairs.length) { 260 log("Finished"); 261 stopRunning(); 262 return; 263 } 264 } else { 265 mCurOpIndex++; 266 if (mCurOpIndex >= TestService.mAvailOps.length) { 267 log("Finished"); 268 stopRunning(); 269 return; 270 } 271 } 272 startCurOp(); 273 } 274 275 void disconnect() { 276 if (mCurConnection != null) { 277 unbindService(mCurConnection); 278 if (mCurConnection.mService != null) { 279 Message msg = Message.obtain(null, TestService.CMD_TERMINATE); 280 msg.replyTo = mMessenger; 281 try { 282 mCurConnection.mService.send(msg); 283 } catch (RemoteException e) { 284 Log.i(TAG, "Failure communicating with service", e); 285 } 286 } 287 mCurConnection = null; 288 } 289 } 290 291 void startCurOp() { 292 if (mCurConnection != null) { 293 disconnect(); 294 } 295 if (mStarted) { 296 mHandler.removeMessages(TestService.RES_TEST_FINISHED); 297 mHandler.removeMessages(TestService.RES_TERMINATED); 298 mHandler.removeMessages(MSG_CONTINUE); 299 mCurConnection = new TestConnection(); 300 Intent intent; 301 if (mLocalCheckBox.isChecked()) { 302 intent = new Intent(this, LocalTestService.class); 303 } else { 304 intent = new Intent(this, TestService.class); 305 } 306 bindService(intent, mCurConnection, BIND_AUTO_CREATE|BIND_IMPORTANT); 307 } 308 } 309 310 void startRunning() { 311 if (!mStarted) { 312 log("Start"); 313 mStarted = true; 314 mStartButton.setEnabled(false); 315 mStopButton.setEnabled(true); 316 mLocalCheckBox.setEnabled(false); 317 mTestTime.setEnabled(false); 318 mFgSpinner.setEnabled(false); 319 mBgSpinner.setEnabled(false); 320 updateWakeLock(); 321 startService(new Intent(this, SchedulerService.class)); 322 mCurOpIndex = 0; 323 mMaxRunTime = Integer.parseInt(mTestTime.getText().toString()); 324 mResults.clear(); 325 startCurOp(); 326 } 327 } 328 329 void stopRunning() { 330 if (mStarted) { 331 disconnect(); 332 mStarted = false; 333 mStartButton.setEnabled(true); 334 mStopButton.setEnabled(false); 335 mLocalCheckBox.setEnabled(true); 336 mTestTime.setEnabled(true); 337 mFgSpinner.setEnabled(true); 338 mBgSpinner.setEnabled(true); 339 updateWakeLock(); 340 stopService(new Intent(this, SchedulerService.class)); 341 for (int i=0; i<mResults.size(); i++) { 342 RunResult result = mResults.get(i); 343 float fgMsPerOp = result.getFgMsPerOp(); 344 float bgMsPerOp = result.getBgMsPerOp(); 345 String fgMsPerOpStr = fgMsPerOp != 0 ? Float.toString(fgMsPerOp) : ""; 346 String bgMsPerOpStr = bgMsPerOp != 0 ? Float.toString(bgMsPerOp) : ""; 347 Log.i("PerfRes", "\t" + result.name + "\t" + result.fgOps 348 + "\t" + result.getFgMsPerOp() + "\t" + result.fgTime 349 + "\t" + result.fgLongName + "\t" + result.bgOps 350 + "\t" + result.getBgMsPerOp() + "\t" + result.bgTime 351 + "\t" + result.bgLongName); 352 } 353 } 354 } 355 356 void updateWakeLock() { 357 if (mStarted) { 358 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 359 if (!mPartialWakeLock.isHeld()) { 360 mPartialWakeLock.acquire(); 361 } 362 } else { 363 getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 364 if (mPartialWakeLock.isHeld()) { 365 mPartialWakeLock.release(); 366 } 367 } 368 } 369 370 void log(String s) { 371 mLog.setText(mLog.getText() + "\n" + s); 372 Log.i(TAG, s); 373 } 374} 375