Merge "New framework performance tests." into ics-mr1
This commit is contained in:
committed by
Android (Google) Code Review
commit
114ac293b8
12
tests/FrameworkPerf/Android.mk
Normal file
12
tests/FrameworkPerf/Android.mk
Normal file
@@ -0,0 +1,12 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
LOCAL_SRC_FILES := $(call all-subdir-java-files)
|
||||
|
||||
LOCAL_PACKAGE_NAME := FrameworkPerf
|
||||
|
||||
LOCAL_AAPT_FLAGS = -c 120dpi,240dpi,160dpi,161dpi,320dpi,nodpi
|
||||
|
||||
include $(BUILD_PACKAGE)
|
||||
17
tests/FrameworkPerf/AndroidManifest.xml
Normal file
17
tests/FrameworkPerf/AndroidManifest.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.frameworkperf">
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-sdk android:minSdkVersion="5" />
|
||||
|
||||
<application>
|
||||
<activity android:name="FrameworkPerfActivity" android:label="Framework Perf">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<service android:name="SchedulerService">
|
||||
</service>
|
||||
</application>
|
||||
</manifest>
|
||||
BIN
tests/FrameworkPerf/res/drawable-161dpi/stat_sample_scale.png
Executable file
BIN
tests/FrameworkPerf/res/drawable-161dpi/stat_sample_scale.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 364 B |
Binary file not shown.
|
After Width: | Height: | Size: 420 KiB |
BIN
tests/FrameworkPerf/res/drawable-hdpi/stat_happy.png
Executable file
BIN
tests/FrameworkPerf/res/drawable-hdpi/stat_happy.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 634 B |
BIN
tests/FrameworkPerf/res/drawable-mdpi/stat_happy.png
Normal file
BIN
tests/FrameworkPerf/res/drawable-mdpi/stat_happy.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
tests/FrameworkPerf/res/drawable-nodpi/stat_sample.png
Executable file
BIN
tests/FrameworkPerf/res/drawable-nodpi/stat_sample.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 364 B |
BIN
tests/FrameworkPerf/res/drawable-nodpi/wallpaper_goldengate.jpg
Normal file
BIN
tests/FrameworkPerf/res/drawable-nodpi/wallpaper_goldengate.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 420 KiB |
54
tests/FrameworkPerf/res/layout/main.xml
Normal file
54
tests/FrameworkPerf/res/layout/main.xml
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2009 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<Button android:id="@+id/start"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/start"
|
||||
/>
|
||||
<Button android:id="@+id/stop"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/stop"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<ScrollView android:id="@+id/scroll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0px"
|
||||
android:layout_weight="1"
|
||||
>
|
||||
<TextView android:id="@+id/log"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="25dp"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#ffffffff"
|
||||
/>
|
||||
</ScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
64
tests/FrameworkPerf/res/values/attrs.xml
Normal file
64
tests/FrameworkPerf/res/values/attrs.xml
Normal file
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2011 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<!-- Base attributes that are available to all Item objects. -->
|
||||
<declare-styleable name="MenuItem">
|
||||
|
||||
<!-- The ID of the item. -->
|
||||
<attr name="android:id" />
|
||||
|
||||
<!-- The category applied to the item.
|
||||
(This will be or'ed with the orderInCategory attribute.) -->
|
||||
<attr name="android:menuCategory" />
|
||||
|
||||
<!-- The order within the category applied to the item.
|
||||
(This will be or'ed with the category attribute.) -->
|
||||
<attr name="android:orderInCategory" />
|
||||
|
||||
<!-- The title associated with the item. -->
|
||||
<attr name="android:title" />
|
||||
|
||||
<!-- The condensed title associated with the item. This is used in situations where the
|
||||
normal title may be too long to be displayed. -->
|
||||
<attr name="android:titleCondensed" />
|
||||
|
||||
<!-- The icon associated with this item. This icon will not always be shown, so
|
||||
the title should be sufficient in describing this item. -->
|
||||
<attr name="android:icon" />
|
||||
|
||||
<!-- The alphabetic shortcut key. This is the shortcut when using a keyboard
|
||||
with alphabetic keys. -->
|
||||
<attr name="android:alphabeticShortcut" />
|
||||
|
||||
<!-- The numeric shortcut key. This is the shortcut when using a numeric (e.g., 12-key)
|
||||
keyboard. -->
|
||||
<attr name="android:numericShortcut" />
|
||||
|
||||
<!-- Whether the item is capable of displaying a check mark. -->
|
||||
<attr name="android:checkable" />
|
||||
|
||||
<!-- Whether the item is checked. Note that you must first have enabled checking with
|
||||
the checkable attribute or else the check mark will not appear. -->
|
||||
<attr name="android:checked" />
|
||||
|
||||
<!-- Whether the item is shown/visible. -->
|
||||
<attr name="android:visible" />
|
||||
|
||||
<!-- Whether the item is enabled. -->
|
||||
<attr name="android:enabled" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
25
tests/FrameworkPerf/res/values/strings.xml
Normal file
25
tests/FrameworkPerf/res/values/strings.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2011 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<string name="start">Start</string>
|
||||
<string name="stop">Stop</string>
|
||||
<string name="data_usage_menu_roaming">Data roaming</string>
|
||||
<string name="data_usage_menu_restrict_background">Restrict background data</string>
|
||||
<string name="data_usage_menu_split_4g">Separate 4G usage</string>
|
||||
<string name="data_usage_menu_show_wifi">Show Wi-Fi usage</string>
|
||||
<string name="data_usage_menu_show_ethernet">Show Ethernet usage</string>
|
||||
</resources>
|
||||
38
tests/FrameworkPerf/res/xml/simple.xml
Normal file
38
tests/FrameworkPerf/res/xml/simple.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2011 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/data_usage_menu_roaming"
|
||||
android:title="@string/data_usage_menu_roaming"
|
||||
android:checkable="true" />
|
||||
<item
|
||||
android:id="@+id/data_usage_menu_restrict_background"
|
||||
android:title="@string/data_usage_menu_restrict_background"
|
||||
android:checkable="true" />
|
||||
<item
|
||||
android:id="@+id/data_usage_menu_split_4g"
|
||||
android:title="@string/data_usage_menu_split_4g"
|
||||
android:checkable="true" />
|
||||
<item
|
||||
android:id="@+id/data_usage_menu_show_wifi"
|
||||
android:title="@string/data_usage_menu_show_wifi"
|
||||
android:checkable="true" />
|
||||
<item
|
||||
android:id="@+id/data_usage_menu_show_ethernet"
|
||||
android:title="@string/data_usage_menu_show_ethernet"
|
||||
android:checkable="true" />
|
||||
</menu>
|
||||
@@ -0,0 +1,694 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.frameworkperf;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.PowerManager;
|
||||
import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* So you thought sync used up your battery life.
|
||||
*/
|
||||
public class FrameworkPerfActivity extends Activity {
|
||||
final Handler mHandler = new Handler();
|
||||
|
||||
TextView mLog;
|
||||
PowerManager.WakeLock mPartialWakeLock;
|
||||
|
||||
long mMaxRunTime = 5000;
|
||||
boolean mStarted;
|
||||
|
||||
final TestRunner mRunner = new TestRunner();
|
||||
|
||||
final Op[] mOpPairs = new Op[] {
|
||||
new MethodCallOp(), new NoOp(),
|
||||
new MethodCallOp(), new CpuOp(),
|
||||
new MethodCallOp(), new SchedulerOp(),
|
||||
new MethodCallOp(), new GcOp(),
|
||||
new SchedulerOp(), new SchedulerOp(),
|
||||
new GcOp(), new NoOp(),
|
||||
new IpcOp(), new NoOp(),
|
||||
new IpcOp(), new CpuOp(),
|
||||
new IpcOp(), new SchedulerOp(),
|
||||
new IpcOp(), new GcOp(),
|
||||
new ParseXmlResOp(), new NoOp(),
|
||||
new ParseLargeXmlResOp(), new NoOp(),
|
||||
new LayoutInflaterOp(), new NoOp(),
|
||||
new LayoutInflaterLargeOp(), new NoOp(),
|
||||
new LoadSmallBitmapOp(), new NoOp(),
|
||||
new LoadLargeBitmapOp(), new NoOp(),
|
||||
new LoadSmallScaledBitmapOp(), new NoOp(),
|
||||
new LoadLargeScaledBitmapOp(), new NoOp(),
|
||||
};
|
||||
|
||||
final Op[] mAvailOps = new Op[] {
|
||||
new NoOp(),
|
||||
new CpuOp(),
|
||||
new SchedulerOp(),
|
||||
new MethodCallOp(),
|
||||
new IpcOp(),
|
||||
new ParseXmlResOp(),
|
||||
new ParseLargeXmlResOp(),
|
||||
new LoadSmallBitmapOp(),
|
||||
new LoadLargeBitmapOp(),
|
||||
new LoadSmallScaledBitmapOp(),
|
||||
new LoadLargeScaledBitmapOp(),
|
||||
};
|
||||
|
||||
int mCurOpIndex = 0;
|
||||
|
||||
class RunResult {
|
||||
final String name;
|
||||
final String fgLongName;
|
||||
final String bgLongName;
|
||||
final long fgTime;
|
||||
final long fgOps;
|
||||
final long bgTime;
|
||||
final long bgOps;
|
||||
|
||||
RunResult(TestRunner op) {
|
||||
name = op.getName();
|
||||
fgLongName = op.getForegroundLongName();
|
||||
bgLongName = op.getBackgroundLongName();
|
||||
fgTime = op.getForegroundTime();
|
||||
fgOps = op.getForegroundOps();
|
||||
bgTime = op.getBackgroundTime();
|
||||
bgOps = op.getBackgroundOps();
|
||||
}
|
||||
|
||||
float getFgMsPerOp() {
|
||||
return fgOps != 0 ? (fgTime / (float)fgOps) : 0;
|
||||
}
|
||||
|
||||
float getBgMsPerOp() {
|
||||
return bgOps != 0 ? (bgTime / (float)bgOps) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
final ArrayList<RunResult> mResults = new ArrayList<RunResult>();
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Set the layout for this activity. You can find it
|
||||
// in res/layout/hello_activity.xml
|
||||
setContentView(R.layout.main);
|
||||
|
||||
findViewById(R.id.start).setOnClickListener(new View.OnClickListener() {
|
||||
@Override public void onClick(View v) {
|
||||
startRunning();
|
||||
}
|
||||
});
|
||||
findViewById(R.id.stop).setOnClickListener(new View.OnClickListener() {
|
||||
@Override public void onClick(View v) {
|
||||
stopRunning();
|
||||
}
|
||||
});
|
||||
mLog = (TextView)findViewById(R.id.log);
|
||||
|
||||
PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE);
|
||||
mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Scheduler");
|
||||
mPartialWakeLock.setReferenceCounted(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
stopRunning();
|
||||
if (mPartialWakeLock.isHeld()) {
|
||||
mPartialWakeLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
void startCurOp() {
|
||||
mRunner.run(mHandler, mOpPairs[mCurOpIndex], mOpPairs[mCurOpIndex+1], new Runnable() {
|
||||
@Override public void run() {
|
||||
RunResult result = new RunResult(mRunner);
|
||||
log(String.format("%s: fg=%d*%gms/op (%dms) / bg=%d*%gms/op (%dms)",
|
||||
result.name, result.fgOps, result.getFgMsPerOp(), result.fgTime,
|
||||
result.bgOps, result.getBgMsPerOp(), result.bgTime));
|
||||
mResults.add(result);
|
||||
if (!mStarted) {
|
||||
log("Stop");
|
||||
stopRunning();
|
||||
return;
|
||||
}
|
||||
mCurOpIndex+=2;
|
||||
if (mCurOpIndex >= mOpPairs.length) {
|
||||
log("Finished");
|
||||
stopRunning();
|
||||
return;
|
||||
}
|
||||
startCurOp();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void startRunning() {
|
||||
if (!mStarted) {
|
||||
log("Start");
|
||||
mStarted = true;
|
||||
updateWakeLock();
|
||||
startService(new Intent(this, SchedulerService.class));
|
||||
mCurOpIndex = 0;
|
||||
mResults.clear();
|
||||
startCurOp();
|
||||
}
|
||||
}
|
||||
|
||||
void stopRunning() {
|
||||
if (mStarted) {
|
||||
mStarted = false;
|
||||
updateWakeLock();
|
||||
stopService(new Intent(this, SchedulerService.class));
|
||||
for (int i=0; i<mResults.size(); i++) {
|
||||
RunResult result = mResults.get(i);
|
||||
float fgMsPerOp = result.getFgMsPerOp();
|
||||
float bgMsPerOp = result.getBgMsPerOp();
|
||||
String fgMsPerOpStr = fgMsPerOp != 0 ? Float.toString(fgMsPerOp) : "";
|
||||
String bgMsPerOpStr = bgMsPerOp != 0 ? Float.toString(bgMsPerOp) : "";
|
||||
Log.i("Perf", "\t" + result.name + "\t" + result.fgOps
|
||||
+ "\t" + result.getFgMsPerOp() + "\t" + result.fgTime
|
||||
+ "\t" + result.fgLongName + "\t" + result.bgOps
|
||||
+ "\t" + result.getBgMsPerOp() + "\t" + result.bgTime
|
||||
+ "\t" + result.bgLongName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateWakeLock() {
|
||||
if (mStarted) {
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
if (!mPartialWakeLock.isHeld()) {
|
||||
mPartialWakeLock.acquire();
|
||||
}
|
||||
} else {
|
||||
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
if (mPartialWakeLock.isHeld()) {
|
||||
mPartialWakeLock.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void log(String s) {
|
||||
mLog.setText(mLog.getText() + "\n" + s);
|
||||
Log.i("Perf", s);
|
||||
}
|
||||
|
||||
enum BackgroundMode {
|
||||
NOTHING,
|
||||
CPU,
|
||||
SCHEDULER
|
||||
};
|
||||
|
||||
public class TestRunner {
|
||||
Handler mHandler;
|
||||
Op mForegroundOp;
|
||||
Op mBackgroundOp;
|
||||
Runnable mDoneCallback;
|
||||
|
||||
RunnerThread mBackgroundThread;
|
||||
RunnerThread mForegroundThread;
|
||||
long mStartTime;
|
||||
|
||||
boolean mBackgroundRunning;
|
||||
boolean mForegroundRunning;
|
||||
|
||||
long mBackgroundEndTime;
|
||||
long mBackgroundOps;
|
||||
long mForegroundEndTime;
|
||||
long mForegroundOps;
|
||||
|
||||
public TestRunner() {
|
||||
}
|
||||
|
||||
public String getForegroundName() {
|
||||
return mForegroundOp.getName();
|
||||
}
|
||||
|
||||
public String getBackgroundName() {
|
||||
return mBackgroundOp.getName();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
String fgName = mForegroundOp.getName();
|
||||
String bgName = mBackgroundOp.getName();
|
||||
StringBuilder res = new StringBuilder();
|
||||
if (fgName != null) {
|
||||
res.append(fgName);
|
||||
res.append("Fg");
|
||||
}
|
||||
if (bgName != null) {
|
||||
res.append(bgName);
|
||||
res.append("Bg");
|
||||
}
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
public String getForegroundLongName() {
|
||||
return mForegroundOp.getLongName();
|
||||
}
|
||||
|
||||
public String getBackgroundLongName() {
|
||||
return mBackgroundOp.getLongName();
|
||||
}
|
||||
|
||||
public void run(Handler handler, Op foreground, Op background, Runnable doneCallback) {
|
||||
mHandler = handler;
|
||||
mForegroundOp = foreground;
|
||||
mBackgroundOp = background;
|
||||
mDoneCallback = doneCallback;
|
||||
mBackgroundThread = new RunnerThread("background", new Runnable() {
|
||||
@Override public void run() {
|
||||
boolean running;
|
||||
int ops = 0;
|
||||
do {
|
||||
running = mBackgroundOp.onRun();
|
||||
ops++;
|
||||
} while (evalRepeat(running, true) && running);
|
||||
mBackgroundEndTime = SystemClock.uptimeMillis();
|
||||
mBackgroundOps = ops * mBackgroundOp.getOpsPerRun();
|
||||
threadFinished(false);
|
||||
}
|
||||
}, Process.THREAD_PRIORITY_BACKGROUND);
|
||||
mForegroundThread = new RunnerThread("background", new Runnable() {
|
||||
@Override public void run() {
|
||||
boolean running;
|
||||
int ops = 0;
|
||||
do {
|
||||
running = mForegroundOp.onRun();
|
||||
ops++;
|
||||
} while (evalRepeat(true, running) && running);
|
||||
mForegroundEndTime = SystemClock.uptimeMillis();
|
||||
mForegroundOps = ops * mForegroundOp.getOpsPerRun();
|
||||
threadFinished(true);
|
||||
}
|
||||
}, Process.THREAD_PRIORITY_FOREGROUND);
|
||||
|
||||
mForegroundOp.onInit(FrameworkPerfActivity.this);
|
||||
mBackgroundOp.onInit(FrameworkPerfActivity.this);
|
||||
|
||||
synchronized (this) {
|
||||
mStartTime = SystemClock.uptimeMillis();
|
||||
mBackgroundRunning = true;
|
||||
mForegroundRunning = true;
|
||||
}
|
||||
|
||||
mBackgroundThread.start();
|
||||
mForegroundThread.start();
|
||||
}
|
||||
|
||||
public long getForegroundTime() {
|
||||
return mForegroundEndTime-mStartTime;
|
||||
}
|
||||
|
||||
public long getForegroundOps() {
|
||||
return mForegroundOps;
|
||||
}
|
||||
|
||||
public long getBackgroundTime() {
|
||||
return mBackgroundEndTime-mStartTime;
|
||||
}
|
||||
|
||||
public long getBackgroundOps() {
|
||||
return mBackgroundOps;
|
||||
}
|
||||
|
||||
private boolean evalRepeat(boolean bgRunning, boolean fgRunning) {
|
||||
synchronized (this) {
|
||||
if (!bgRunning) {
|
||||
mBackgroundRunning = false;
|
||||
}
|
||||
if (!fgRunning) {
|
||||
mForegroundRunning = false;
|
||||
}
|
||||
if (!mBackgroundRunning && !mForegroundRunning) {
|
||||
return false;
|
||||
}
|
||||
long now = SystemClock.uptimeMillis();
|
||||
if (now > (mStartTime+mMaxRunTime)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void threadFinished(boolean foreground) {
|
||||
synchronized (this) {
|
||||
if (foreground) {
|
||||
mForegroundRunning = false;
|
||||
} else {
|
||||
mBackgroundRunning = false;
|
||||
}
|
||||
if (!mBackgroundRunning && !mForegroundRunning) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override public void run() {
|
||||
if (mDoneCallback != null) {
|
||||
mDoneCallback.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RunnerThread extends Thread {
|
||||
private final Runnable mOp;
|
||||
private final int mPriority;
|
||||
|
||||
RunnerThread(String name, Runnable op, int priority) {
|
||||
super(name);
|
||||
mOp = op;
|
||||
mPriority = priority;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
Process.setThreadPriority(mPriority);
|
||||
mOp.run();
|
||||
}
|
||||
}
|
||||
|
||||
static public abstract class Op {
|
||||
final String mName;
|
||||
final String mLongName;
|
||||
|
||||
public Op(String name, String longName) {
|
||||
mName = name;
|
||||
mLongName = longName;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
public String getLongName() {
|
||||
return mLongName;
|
||||
}
|
||||
|
||||
void onInit(Context context) {
|
||||
}
|
||||
|
||||
abstract boolean onRun();
|
||||
|
||||
int getOpsPerRun() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static class NoOp extends Op {
|
||||
NoOp() {
|
||||
super(null, "Nothing");
|
||||
}
|
||||
|
||||
boolean onRun() {
|
||||
return false;
|
||||
}
|
||||
|
||||
int getOpsPerRun() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static class CpuOp extends Op {
|
||||
CpuOp() {
|
||||
super("CPU", "Consume CPU");
|
||||
}
|
||||
|
||||
boolean onRun() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class SchedulerOp extends Op {
|
||||
SchedulerOp() {
|
||||
super("Sched", "Change scheduler group");
|
||||
}
|
||||
|
||||
boolean onRun() {
|
||||
Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
|
||||
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class GcOp extends Op {
|
||||
GcOp() {
|
||||
super("Gc", "Run garbage collector");
|
||||
}
|
||||
|
||||
boolean onRun() {
|
||||
byte[] stuff = new byte[1024*1024];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class MethodCallOp extends Op {
|
||||
MethodCallOp() {
|
||||
super("MethodCall", "Method call");
|
||||
}
|
||||
|
||||
boolean onRun() {
|
||||
final int N = getOpsPerRun();
|
||||
for (int i=0; i<N; i++) {
|
||||
someFunc(i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int someFunc(int foo) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getOpsPerRun() {
|
||||
return 500;
|
||||
}
|
||||
}
|
||||
|
||||
static class IpcOp extends Op {
|
||||
PackageManager mPm;
|
||||
String mProcessName;
|
||||
|
||||
IpcOp() {
|
||||
super("Ipc", "IPC to system process");
|
||||
}
|
||||
|
||||
void onInit(Context context) {
|
||||
mPm = context.getPackageManager();
|
||||
mProcessName = context.getApplicationInfo().processName;
|
||||
}
|
||||
|
||||
boolean onRun() {
|
||||
final int N = getOpsPerRun();
|
||||
for (int i=0; i<N; i++) {
|
||||
mPm.queryContentProviders(mProcessName, Process.myUid(), 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int getOpsPerRun() {
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
|
||||
static class ParseXmlResOp extends Op {
|
||||
Context mContext;
|
||||
|
||||
ParseXmlResOp() {
|
||||
super("ParseXmlRes", "Parse compiled XML resource");
|
||||
}
|
||||
|
||||
void onInit(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
boolean onRun() {
|
||||
SimpleInflater inf = new SimpleInflater(mContext);
|
||||
inf.inflate(R.xml.simple);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class ParseLargeXmlResOp extends Op {
|
||||
Context mContext;
|
||||
|
||||
ParseLargeXmlResOp() {
|
||||
super("ParseLargeXmlRes", "Parse large XML resource");
|
||||
}
|
||||
|
||||
void onInit(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
boolean onRun() {
|
||||
SimpleInflater inf = new SimpleInflater(mContext);
|
||||
inf.inflate(R.xml.simple_large);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class LayoutInflaterOp extends Op {
|
||||
Context mContext;
|
||||
|
||||
LayoutInflaterOp() {
|
||||
super("LayoutInflaterOp", "Inflate layout resource");
|
||||
}
|
||||
|
||||
void onInit(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
boolean onRun() {
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare();
|
||||
}
|
||||
LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
|
||||
Context.LAYOUT_INFLATER_SERVICE);
|
||||
inf.inflate(R.layout.small_layout, null);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class LayoutInflaterLargeOp extends Op {
|
||||
Context mContext;
|
||||
|
||||
LayoutInflaterLargeOp() {
|
||||
super("LayoutInflaterLargeOp", "Inflate large layout resource");
|
||||
}
|
||||
|
||||
void onInit(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
boolean onRun() {
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare();
|
||||
}
|
||||
LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
|
||||
Context.LAYOUT_INFLATER_SERVICE);
|
||||
inf.inflate(R.layout.large_layout, null);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class LoadSmallBitmapOp extends Op {
|
||||
Context mContext;
|
||||
|
||||
LoadSmallBitmapOp() {
|
||||
super("LoadSmallBitmap", "Load small raw bitmap");
|
||||
}
|
||||
|
||||
void onInit(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
boolean onRun() {
|
||||
BitmapFactory.Options opts = new BitmapFactory.Options();
|
||||
opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
|
||||
Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
|
||||
R.drawable.stat_sample, opts);
|
||||
bm.recycle();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class LoadLargeBitmapOp extends Op {
|
||||
Context mContext;
|
||||
|
||||
LoadLargeBitmapOp() {
|
||||
super("LoadLargeBitmap", "Load large raw bitmap");
|
||||
}
|
||||
|
||||
void onInit(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
boolean onRun() {
|
||||
BitmapFactory.Options opts = new BitmapFactory.Options();
|
||||
opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
|
||||
Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
|
||||
R.drawable.wallpaper_goldengate, opts);
|
||||
bm.recycle();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class LoadSmallScaledBitmapOp extends Op {
|
||||
Context mContext;
|
||||
|
||||
LoadSmallScaledBitmapOp() {
|
||||
super("LoadSmallScaledBitmap", "Load small raw bitmap that is scaled for density");
|
||||
}
|
||||
|
||||
void onInit(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
boolean onRun() {
|
||||
BitmapFactory.Options opts = new BitmapFactory.Options();
|
||||
opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
|
||||
Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
|
||||
R.drawable.stat_sample_scale, opts);
|
||||
bm.recycle();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class LoadLargeScaledBitmapOp extends Op {
|
||||
Context mContext;
|
||||
|
||||
LoadLargeScaledBitmapOp() {
|
||||
super("LoadLargeScaledBitmap", "Load large raw bitmap that is scaled for density");
|
||||
}
|
||||
|
||||
void onInit(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
boolean onRun() {
|
||||
BitmapFactory.Options opts = new BitmapFactory.Options();
|
||||
opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
|
||||
Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
|
||||
R.drawable.wallpaper_goldengate_scale, opts);
|
||||
bm.recycle();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.frameworkperf;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
|
||||
public class SchedulerService extends Service {
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
Notification status = new Notification(R.drawable.stat_happy, null,
|
||||
System.currentTimeMillis());
|
||||
status.flags |= Notification.FLAG_ONGOING_EVENT;
|
||||
status.setLatestEventInfo(this, "Scheduler Test running",
|
||||
"Scheduler Test running", PendingIntent.getActivity(this, 0,
|
||||
new Intent(this, FrameworkPerfActivity.class)
|
||||
.setAction(Intent.ACTION_MAIN)
|
||||
.addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0));
|
||||
startForeground(1, status);
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.frameworkperf;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Xml;
|
||||
import android.view.InflateException;
|
||||
|
||||
public class SimpleInflater {
|
||||
/** Menu tag name in XML. */
|
||||
private static final String XML_MENU = "menu";
|
||||
|
||||
/** Group tag name in XML. */
|
||||
private static final String XML_GROUP = "group";
|
||||
|
||||
/** Item tag name in XML. */
|
||||
private static final String XML_ITEM = "item";
|
||||
|
||||
private Context mContext;
|
||||
|
||||
public SimpleInflater(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public void inflate(int menuRes) {
|
||||
XmlResourceParser parser = null;
|
||||
try {
|
||||
parser = mContext.getResources().getLayout(menuRes);
|
||||
AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||
|
||||
parseMenu(parser, attrs);
|
||||
} catch (XmlPullParserException e) {
|
||||
throw new InflateException("Error inflating menu XML", e);
|
||||
} catch (IOException e) {
|
||||
throw new InflateException("Error inflating menu XML", e);
|
||||
} finally {
|
||||
if (parser != null) parser.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void parseMenu(XmlPullParser parser, AttributeSet attrs)
|
||||
throws XmlPullParserException, IOException {
|
||||
int eventType = parser.getEventType();
|
||||
String tagName;
|
||||
boolean lookingForEndOfUnknownTag = false;
|
||||
String unknownTagName = null;
|
||||
|
||||
// This loop will skip to the menu start tag
|
||||
do {
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
tagName = parser.getName();
|
||||
if (tagName.equals(XML_MENU)) {
|
||||
// Go to next tag
|
||||
eventType = parser.next();
|
||||
break;
|
||||
}
|
||||
|
||||
throw new RuntimeException("Expecting menu, got " + tagName);
|
||||
}
|
||||
eventType = parser.next();
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
boolean reachedEndOfMenu = false;
|
||||
while (!reachedEndOfMenu) {
|
||||
switch (eventType) {
|
||||
case XmlPullParser.START_TAG:
|
||||
if (lookingForEndOfUnknownTag) {
|
||||
break;
|
||||
}
|
||||
|
||||
tagName = parser.getName();
|
||||
if (tagName.equals(XML_ITEM)) {
|
||||
readItem(attrs);
|
||||
} else if (tagName.equals(XML_MENU)) {
|
||||
parseMenu(parser, attrs);
|
||||
} else {
|
||||
lookingForEndOfUnknownTag = true;
|
||||
unknownTagName = tagName;
|
||||
}
|
||||
break;
|
||||
|
||||
case XmlPullParser.END_TAG:
|
||||
tagName = parser.getName();
|
||||
if (lookingForEndOfUnknownTag && tagName.equals(unknownTagName)) {
|
||||
lookingForEndOfUnknownTag = false;
|
||||
unknownTagName = null;
|
||||
} else if (tagName.equals(XML_ITEM)) {
|
||||
} else if (tagName.equals(XML_MENU)) {
|
||||
reachedEndOfMenu = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case XmlPullParser.END_DOCUMENT:
|
||||
throw new RuntimeException("Unexpected end of document");
|
||||
}
|
||||
|
||||
eventType = parser.next();
|
||||
}
|
||||
}
|
||||
|
||||
public void readItem(AttributeSet attrs) {
|
||||
TypedArray a = mContext.obtainStyledAttributes(attrs,
|
||||
com.android.internal.R.styleable.MenuItem);
|
||||
|
||||
// Inherit attributes from the group as default value
|
||||
int itemId = a.getResourceId(R.styleable.MenuItem_android_id, 0);
|
||||
final int category = a.getInt(R.styleable.MenuItem_android_menuCategory, 0);
|
||||
final int order = a.getInt(R.styleable.MenuItem_android_orderInCategory, 0);
|
||||
CharSequence itemTitle = a.getText(R.styleable.MenuItem_android_title);
|
||||
CharSequence itemTitleCondensed = a.getText(R.styleable.MenuItem_android_titleCondensed);
|
||||
int itemIconResId = a.getResourceId(R.styleable.MenuItem_android_icon, 0);
|
||||
String itemAlphabeticShortcut = a.getString(R.styleable.MenuItem_android_alphabeticShortcut);
|
||||
String itemNumericShortcut = a.getString(R.styleable.MenuItem_android_numericShortcut);
|
||||
int itemCheckable = 0;
|
||||
if (a.hasValue(R.styleable.MenuItem_android_checkable)) {
|
||||
// Item has attribute checkable, use it
|
||||
itemCheckable = a.getBoolean(R.styleable.MenuItem_android_checkable, false) ? 1 : 0;
|
||||
}
|
||||
boolean itemChecked = a.getBoolean(R.styleable.MenuItem_android_checked, false);
|
||||
boolean itemVisible = a.getBoolean(R.styleable.MenuItem_android_visible, false);
|
||||
boolean itemEnabled = a.getBoolean(R.styleable.MenuItem_android_enabled, false);
|
||||
|
||||
a.recycle();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user