Automated Historical Performance Analysis with kmemtracer

Preview:

DESCRIPTION

Material presented at the 12th Korea Android Conference, Oct. 2013.

Citation preview

Automated Historical

Performance Analysis

with kmemtracer

LG전자 이경민

2 12th Kandroid Conference - www.kandroid.org

Why Automated Historical Performance Testing?

kmemtracer: What and How?

Enhancement I : Automating UI Interaction

Enhancement II: Adding More Performance Metrics

Contents

3 12th Kandroid Conference - www.kandroid.org

If you can’t measure it, you can’t manage it.

Peter F. Drucker (1909~2005)

4 12th Kandroid Conference - www.kandroid.org

If you can’t measure it, you can’t manage it.

Peter F. Drucker (1909~2005)

If you can’t automate the measurement of it,

it is difficult to improve it.

5 12th Kandroid Conference - www.kandroid.org

http://developer.android.com/about/dashboards/index.html

Platform Versions

Diversity or Fragmentation

6 12th Kandroid Conference - www.kandroid.org

http://developer.android.com/about/dashboards/index.html

Platform Versions

Screen Sizes and Densities

Diversity or Fragmentation

7 12th Kandroid Conference - www.kandroid.org

http://www.mactrast.com/2012/05/visualized-the-truth-about-android-fragmentation/

8 12th Kandroid Conference - www.kandroid.org

Why Historical Analysis?

Source: Memory and Performance at the 11th Korea Android Conference

Historical Performance Analysis

9 12th Kandroid Conference - www.kandroid.org

Why Historical Analysis?

Source: Memory and Performance at the 11th Korea Android Conference

Historical Performance Analysis

10 12th Kandroid Conference - www.kandroid.org

Why Historical Analysis?

Source: Memory and Performance at the 11th Korea Android Conference

Activity Navigation & Lifecycle

Historical Performance Analysis

11 12th Kandroid Conference - www.kandroid.org

How to Track Activity Navigation & Lifecycle?

12 12th Kandroid Conference - www.kandroid.org

How to Track Activity Navigation & Lifecycle?

Override onCreate, onStart, … of your Activity classes

13 12th Kandroid Conference - www.kandroid.org

How to Track Activity Navigation & Lifecycle?

Modify android.app.Activity

in the framework

14 12th Kandroid Conference - www.kandroid.org

How to Track Activity Navigation & Lifecycle?

Is there a way that does not require the modification of

an application or framework?

15 12th Kandroid Conference - www.kandroid.org

How to Track Activity Navigation & Lifecycle?

Is there a way that does not require the modification of

an application or framework?

Instrumentation

16 12th Kandroid Conference - www.kandroid.org

17 12th Kandroid Conference - www.kandroid.org

Android instrumentation is a set of control methods or "hooks" in the Android system. These hooks control an Android component independently of its normal lifecycle. They also control how Android loads applications. (http://developer.android.com/tools/testing/testing_android.html)

18 12th Kandroid Conference - www.kandroid.org

Why Automated Historical Performance Testing?

kmemtracer: What and How?

Enhancement I : Automating UI Interaction

Enhancement II: Adding More Performance Metrics

Contents

19 12th Kandroid Conference - www.kandroid.org

Historical Analysis w/ kmemtracer

Test Package

Application Package

android.test. Instrumentation

TestRunner

Control

20 12th Kandroid Conference - www.kandroid.org

Historical Analysis w/ kmemtracer

https://github.com/snailee/kmemtracer-libs

Test Package

Application Package

android.test. Instrumentation

TestRunner

org.kandroid. memtracer.Memory

Instrumentation

Control Track

Trace Package

21 12th Kandroid Conference - www.kandroid.org

android.app.Instrumentation

void callActivityOnCreate(Activity, Bundle)

void callActivityOnDestroy(Activity)

void callActivityOnNewIntent(Activity, Intent)

void callActivityOnPause(Activity)

void callActivityOnPostCreate(Activity, Bundle)

void callActivityOnRestart(Activity)

void callActivityOnRestoreInstanceState(Activity, Bundle)

void callActivityOnResume(Activity)

void callActivityOnSaveInstanceState(Activity, Bundle)

void callActivityOnStart(Activity)

void callActivityOnStop(Activity)

void callActivityOnUserLeaving(Activity)

void callApplicationOnCreate(Application)

22 12th Kandroid Conference - www.kandroid.org

android.app.Instrumentation

void callActivityOnCreate(Activity, Bundle)

void callActivityOnDestroy(Activity)

void callActivityOnNewIntent(Activity, Intent)

void callActivityOnPause(Activity)

void callActivityOnPostCreate(Activity, Bundle)

void callActivityOnRestart(Activity)

void callActivityOnRestoreInstanceState(Activity, Bundle)

void callActivityOnResume(Activity)

void callActivityOnSaveInstanceState(Activity, Bundle)

void callActivityOnStart(Activity)

void callActivityOnStop(Activity)

void callActivityOnUserLeaving(Activity)

void callApplicationOnCreate(Application)

Call for Control

23 12th Kandroid Conference - www.kandroid.org

android.app.Instrumentation

void callActivityOnCreate(Activity, Bundle)

void callActivityOnDestroy(Activity)

void callActivityOnNewIntent(Activity, Intent)

void callActivityOnPause(Activity)

void callActivityOnPostCreate(Activity, Bundle)

void callActivityOnRestart(Activity)

void callActivityOnRestoreInstanceState(Activity, Bundle)

void callActivityOnResume(Activity)

void callActivityOnSaveInstanceState(Activity, Bundle)

void callActivityOnStart(Activity)

void callActivityOnStop(Activity)

void callActivityOnUserLeaving(Activity)

void callApplicationOnCreate(Application)

Call for Control

Override for Track

24 12th Kandroid Conference - www.kandroid.org

org.kandroid.memtracer.MemoryInstrumentation

public class MemoryInstrumentation extends Instrumentation { private static final String ARGUMENT_INSTRUMENT_CLASS = "class"; private MemoryTracer mMemoryTracer; private String mMainActivityName; ... @Override public void onCreate(Bundle arguments) { mMainActivityName = arguments.getString(ARGUMENT_INSTRUMENT_CLASS); mMemoryTracer = createMemoryTracer(); mMemoryTracer.startTracing(getTargetContext().getPackageName()); start(); } @Override public void callActivityOnCreate(Activity activity, Bundle icicle) { String tag = activity.getLocalClassName()+"-OnCreate"; Bundle snapshot = mMemoryTracer.addSnapshot(tag); super.callActivityOnCreate(activity, icicle); } }

25 12th Kandroid Conference - www.kandroid.org

Tracing Performance Snapshots in kmemtracer

public class MemoryInstrumentation extends Instrumentation { ... ... }

26 12th Kandroid Conference - www.kandroid.org

Tracing Performance Snapshots in kmemtracer

public class MemoryInstrumentation extends Instrumentation { ... private MemoryTracer mMemoryTracer; ... @Override public void onCreate(Bundle arguments) { ... mMemoryTracer = createMemoryTracer(); ... } ... ... }

Create an instance of MemoryTracer

27 12th Kandroid Conference - www.kandroid.org

Tracing Performance Snapshots in kmemtracer

public class MemoryInstrumentation extends Instrumentation { ... private MemoryTracer mMemoryTracer; ... @Override public void onCreate(Bundle arguments) { ... mMemoryTracer = createMemoryTracer(); ... } ... @Override public void callActivityOnCreate(Activity activity, Bundle icicle) { String tag = activity.getLocalClassName()+"-OnCreate"; Bundle snapshot = mMemoryTracer.addSnapshot(tag); ... } ... }

Create an instance of MemoryTracer

Add performance snapshot

28 12th Kandroid Conference - www.kandroid.org

MemoryTracer.addSnapshot

public Bundle addSnapshot(String label) { ...

29 12th Kandroid Conference - www.kandroid.org

MemoryTracer.addSnapshot

public Bundle addSnapshot(String label) { ... long nativeMax = Debug.getNativeHeapSize() / 1024; long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; long nativeFree = Debug.getNativeHeapFreeSize() / 1024; Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); Debug.getMemoryInfo(memInfo); ...

Get usage data

30 12th Kandroid Conference - www.kandroid.org

MemoryTracer.addSnapshot

public Bundle addSnapshot(String label) { ... long nativeMax = Debug.getNativeHeapSize() / 1024; long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; long nativeFree = Debug.getNativeHeapFreeSize() / 1024; Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); Debug.getMemoryInfo(memInfo); ... Bundle snapshot = new Bundle(); snapshot.putString(METRIC_KEY_LABEL, label); ... snapshot.putLong(METRIC_KEY_NATIVE_SIZE, nativeMax); snapshot.putLong(METRIC_KEY_NATIVE_ALLOCATED, nativeAllocated); snapshot.putLong(METRIC_KEY_NATIVE_FREE, nativeFree); ...

Get usage data

Save data to a bundle

31 12th Kandroid Conference - www.kandroid.org

MemoryTracer.addSnapshot

public Bundle addSnapshot(String label) { ... long nativeMax = Debug.getNativeHeapSize() / 1024; long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; long nativeFree = Debug.getNativeHeapFreeSize() / 1024; Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); Debug.getMemoryInfo(memInfo); ... Bundle snapshot = new Bundle(); snapshot.putString(METRIC_KEY_LABEL, label); ... snapshot.putLong(METRIC_KEY_NATIVE_SIZE, nativeMax); snapshot.putLong(METRIC_KEY_NATIVE_ALLOCATED, nativeAllocated); snapshot.putLong(METRIC_KEY_NATIVE_FREE, nativeFree); ... if (mResultsWriter != null) { mResultsWriter.writeTraceSnapshot(snapshot); } return snapshot; }

Get usage data

Write date using ResultsWriter

Save data to a bundle

32 12th Kandroid Conference - www.kandroid.org

MemoryTracerCsvWriter$writeTraceSnapshot

public class MemoryTraceCsvWriter implements MemoryTracer.ResultsWriter { ...

33 12th Kandroid Conference - www.kandroid.org

MemoryTracerCsvWriter$writeTraceSnapshot

public class MemoryTraceCsvWriter implements MemoryTracer.ResultsWriter { ... public MemoryTraceCsvWriter(String[] metricKeys) { mMetricKeys = metricKeys; } ...

Create an instance with metrics to print

34 12th Kandroid Conference - www.kandroid.org

MemoryTracerCsvWriter$writeTraceSnapshot

public class MemoryTraceCsvWriter implements MemoryTracer.ResultsWriter { ... public MemoryTraceCsvWriter(String[] metricKeys) { mMetricKeys = metricKeys; } ... private void openTraceFile(String filename) { ... mTraceOut = new PrintStream(new FileOutputStream(traceFile)); ... } ...

Create an instance with metrics to print

Open a trace file in the sdcard at init

35 12th Kandroid Conference - www.kandroid.org

MemoryTracerCsvWriter$writeTraceSnapshot

public class MemoryTraceCsvWriter implements MemoryTracer.ResultsWriter { ... public MemoryTraceCsvWriter(String[] metricKeys) { mMetricKeys = metricKeys; } ... private void openTraceFile(String filename) { ... mTraceOut = new PrintStream(new FileOutputStream(traceFile)); ... } ... @Override public void writeTraceSnapshot(Bundle snapshot) { PrintStream out = mTraceOut; for (String key : mMetricKeys) { out.print(snapshot.get(key)); out.print(','); } out.println(); out.flush(); } ... }

Create an instance with metrics to print

Write snapshot to a line of the file

Open a trace file in the sdcard at init

36 12th Kandroid Conference - www.kandroid.org

How to Use kmemtracer?

37 12th Kandroid Conference - www.kandroid.org

How to Use kmemtracer?

1. Create an Android Test Project for the trace package.

38 12th Kandroid Conference - www.kandroid.org

How to Use kmemtracer?

1. Create an Android Test Project for the trace package.

2. Add ‘kmemtracer-libs.jar’ in the ‘libs’ directory.

39 12th Kandroid Conference - www.kandroid.org

How to Use kmemtracer?

1. Create an Android Test Project for the trace package.

2. Add ‘kmemtracer-libs.jar’ in the ‘libs’ directory.

3. Edit the <instrumentation> element in the Manifest file.

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.apis.test" android:versionCode="1" android:versionName="1.0"> <instrumentation android:name="org.kandroid.memtracer.MemoryInstrumentation" android:targetPackage="com.example.android.apis" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:label="@string/app_name" android:icon="@drawable/ic_launcher“> <uses-library android:theme="android.text.runner“> </application> </manifest>

40 12th Kandroid Conference - www.kandroid.org

How to Use kmemtracer?

4. Install the trace package as well as the application package.

$ adb install –r ApiDemos.apk $ adb install –r ApiDemosTest.apk

41 12th Kandroid Conference - www.kandroid.org

How to Use kmemtracer?

4. Install the trace package as well as the application package.

5. Start the instrumentation with ‘am instrument’ in the shell.

$ adb install –r ApiDemos.apk $ adb install –r ApiDemosTest.apk

$ adb shell am instrument -e class \ > com.example.android.apis.ApiDemos \ > com.example.android.apis.tests/\ > org.kandroid.memtracer.MemoryInstrumentation

42 12th Kandroid Conference - www.kandroid.org

How to Use kmemtracer?

4. Install the trace package as well as the application package.

5. Start the instrumentation with ‘am instrument’ in the shell.

6. Do interact with the application.

$ adb install –r ApiDemos.apk $ adb install –r ApiDemosTest.apk

$ adb shell am instrument -e class \ > com.example.android.apis.ApiDemos \ > com.example.android.apis.tests/\ > org.kandroid.memtracer.MemoryInstrumentation

43 12th Kandroid Conference - www.kandroid.org

How to Use kmemtracer?

4. Install the trace package as well as the application package.

5. Start the instrumentation with ‘am instrument’ in the shell.

6. Do interact with the application.

7. Pull the trace file ‘kmemtrace.csv’ from /sdcard/kmemtracer.

$ adb install –r ApiDemos.apk $ adb install –r ApiDemosTest.apk

$ adb shell am instrument -e class \ > com.example.android.apis.ApiDemos \ > com.example.android.apis.tests/\ > org.kandroid.memtracer.MemoryInstrumentation

$ adb pull /sdcard/kmemtracer/kmemtrace.csv .

44 12th Kandroid Conference - www.kandroid.org

How to Use kmemtracer?

8. Open the trace file with Excel and create charts.

45 12th Kandroid Conference - www.kandroid.org

Why Automated Historical Performance Testing?

kmemtracer: What and How?

Enhancement I : Automating UI Interaction

Enhancement II: Adding More Performance Metrics

Contents

46 12th Kandroid Conference - www.kandroid.org

Automate Controlling UI

Test Package

Application Package

android.test. Instrumentation

TestRunner

org.kandroid. memtracer.Memory

Instrumentation

Control Track

Trace Package

47 12th Kandroid Conference - www.kandroid.org

Automate Controlling UI

Test Package

Application Package

android.test. Instrumentation

TestRunner

org.kandroid. memtracer.Memory

Instrumentation

Control Track

Trace Package

48 12th Kandroid Conference - www.kandroid.org

Automate Controlling UI

Test Package

Application Package

android.test. Instrumentation

TestRunner

org.kandroid. memtracer.Memory

Instrumentation

Control Track

Trace Package

49 12th Kandroid Conference - www.kandroid.org

Three Alternatives

50 12th Kandroid Conference - www.kandroid.org

Three Alternatives

Instrumentation

API Level 1 ~ Single activity Framework APIs White-box

http://developer.android.com/tools/testing/testing_android.html

51 12th Kandroid Conference - www.kandroid.org

Three Alternatives

Instrumentation Robotium

API Level 1 ~ Single activity Framework APIs White-box

2010/01 ~ Multiple activities High-level APIs White-box & black-box

http://developer.android.com/tools/testing/testing_android.html https://code.google.com/p/robotium/

52 12th Kandroid Conference - www.kandroid.org

Three Alternatives

Instrumentation Robotium uiautomator

API Level 1 ~ Single activity Framework APIs White-box

2010/01 ~ Multiple activities High-level APIs White-box & black-box

API Level 17 ~ Multiple processes Simple APIs Black-box

http://developer.android.com/tools/testing/testing_android.html https://code.google.com/p/robotium/ http://developer.android.com/tools/testing/testing_ui.html

53 12th Kandroid Conference - www.kandroid.org

Case Study: ApiDemos

https://github.com/snailee/deview-2013-samples

54 12th Kandroid Conference - www.kandroid.org

Click

Case Study: ApiDemos

https://github.com/snailee/deview-2013-samples

55 12th Kandroid Conference - www.kandroid.org

Click

Case Study: ApiDemos

https://github.com/snailee/deview-2013-samples

56 12th Kandroid Conference - www.kandroid.org

Click

Case Study: ApiDemos

Scroll down

https://github.com/snailee/deview-2013-samples

57 12th Kandroid Conference - www.kandroid.org

Click

Case Study: ApiDemos

Scroll down

https://github.com/snailee/deview-2013-samples

58 12th Kandroid Conference - www.kandroid.org

Click

Case Study: ApiDemos

Scroll down

Click

https://github.com/snailee/deview-2013-samples

59 12th Kandroid Conference - www.kandroid.org

Click

Case Study: ApiDemos

Scroll down

Click

https://github.com/snailee/deview-2013-samples

60 12th Kandroid Conference - www.kandroid.org

Click

Case Study: ApiDemos

Scroll down

Click Click

https://github.com/snailee/deview-2013-samples

61 12th Kandroid Conference - www.kandroid.org

Click

Case Study: ApiDemos

Scroll down

Click Click

https://github.com/snailee/deview-2013-samples

62 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

63 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

1. Create an Android Test Project for the test package.

$ android create test-project --main ../ApiDemos \ > –-name ApiDemosInstrumentTest --path ApiDemosInstrumentTest

64 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

1. Create an Android Test Project for the test package.

2. Add a test class inheriting ActivityInstrumentationTestCase2.

$ android create test-project --main ../ApiDemos \ > –-name ApiDemosInstrumentTest --path ApiDemosInstrumentTest

public class ApiDemosInstrumentTest extends ActivityInstrumentationTestCase2<ApiDemos> { ... public ApiDemosInstrumentTest() { super(ApiDemos.class); }

65 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

1. Create an Android Test Project for the test package.

2. Add a test class inheriting ActivityInstrumentationTestCase2.

3. Add a test method and launch the activity.

$ android create test-project --main ../ApiDemos \ > –-name ApiDemosInstrumentTest --path ApiDemosInstrumentTest

public class ApiDemosInstrumentTest extends ActivityInstrumentationTestCase2<ApiDemos> { ... public ApiDemosInstrumentTest() { super(ApiDemos.class); }

public void testNavigate() { final ApiDemos apiDemos = getActivity(); ... }

66 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

public void testNavigate() { ...

4. Find and act on a control.

67 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

public void testNavigate() { ... final ListView demoList = apiDemos.getListView(); final View graphicsDemo = getChildViewByText(demoList, "Graphics"); assertNotNull("Graphics demo should exist", graphicsDemo);

Find a view to control

4. Find and act on a control.

68 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

public void testNavigate() { ... final ListView demoList = apiDemos.getListView(); final View graphicsDemo = getChildViewByText(demoList, "Graphics"); assertNotNull("Graphics demo should exist", graphicsDemo); apiDemos.runOnUiThread(new Runnable() { public void run() { int pos = demoList.getPositionForView(graphicsDemo); demoList.smoothScrollToPosition(pos); demoList.setSelection(pos); demoList.performItemClick(graphicsDemo, pos, graphicsDemo.getId()); } }); ...

Find a view to control

Act on the view

4. Find and act on a control.

69 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

public void testNavigate() { ... final ListView demoList = apiDemos.getListView(); final View graphicsDemo = getChildViewByText(demoList, "Graphics"); assertNotNull("Graphics demo should exist", graphicsDemo); apiDemos.runOnUiThread(new Runnable() { public void run() { int pos = demoList.getPositionForView(graphicsDemo); demoList.smoothScrollToPosition(pos); demoList.setSelection(pos); demoList.performItemClick(graphicsDemo, pos, graphicsDemo.getId()); } }); ...

Find a view to control

Act on the view

4. Find and act on a control.

70 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

private View getChildViewByText(ListView listView, String text) {

4. Find and act on a control: getChildViewByText.

71 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

private View getChildViewByText(ListView listView, String text) { View view = null; int count = listView.getCount(); Log.e(TAG, “no. children = " + count); for (int i = 0; i < count; i++) { TextView textView = (TextView) listView.getChildAt(i);

Iterate through child views

4. Find and act on a control: getChildViewByText.

72 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

private View getChildViewByText(ListView listView, String text) { View view = null; int count = listView.getCount(); Log.e(TAG, “no. children = " + count); for (int i = 0; i < count; i++) { TextView textView = (TextView) listView.getChildAt(i); Log.e(TAG, i + "-th text view is " + textView); if (textView != null && textView.getText().equals(text)) { view = textView; break; } } return view; }

Iterate through child views

Compare texts

4. Find and act on a control: getChildViewByText.

73 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

private View getChildViewByText(ListView listView, String text) { View view = null; int count = listView.getCount(); Log.e(TAG, “no. children = " + count); for (int i = 0; i < count; i++) { TextView textView = (TextView) listView.getChildAt(i); Log.e(TAG, i + "-th text view is " + textView); if (textView != null && textView.getText().equals(text)) { view = textView; break; } } return view; }

Iterate through child views

Compare texts

4. Find and act on a control: getChildViewByText.

com.example.android.apis.instrument.test.ApiDemosInstrumentTest: INSTRUMENTATION_RESULT: shortMsg=junit.framework.AssertionFailedError INSTRUMENTATION_RESULT: longMsg= junit.framework.AssertionFailedError: OpenGL ES demo should exist INSTRUMENTATION_CODE: 0

74 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

private View getChildViewByText(final ListView listView, String text) { ... for (int i = 0; i < count; i++) { TextView textView = (TextView) listView.getChildAt(i); if (textView != null && textView.getText().equals(text)) { view = textView; break; } if (textView == null) { final int lastPos = listView.getLastVisiblePosition(); getInstrumentation().runOnMainSync(new Runnable() { public void run() { listView.smoothScrollToPosition(lastPos + 5, lastPos); } }); getInstrumentation().waitForIdleSync(); i = listView.getFirstVisiblePosition(); } } return view; }

4. Find and act on a control: Revised getChildViewByText.

75 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

private View getChildViewByText(final ListView listView, String text) { ... for (int i = 0; i < count; i++) { TextView textView = (TextView) listView.getChildAt(i); if (textView != null && textView.getText().equals(text)) { view = textView; break; } if (textView == null) { final int lastPos = listView.getLastVisiblePosition(); getInstrumentation().runOnMainSync(new Runnable() { public void run() { listView.smoothScrollToPosition(lastPos + 5, lastPos); } }); getInstrumentation().waitForIdleSync(); i = listView.getFirstVisiblePosition(); } } return view; }

Scroll down

4. Find and act on a control: Revised getChildViewByText.

76 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

private int getPositionForChildViewByText(ListView listView, String text) { ListAdapter listAdapter = listView.getAdapter(); int count = listAdapter.getCount(); Log.e(TAG, "children: " + count); for (int i = 0; i < count; i++) { String itemText = (String) ((Map)listAdapter.getItem(i)).get("title"); Log.e(TAG, i + "-th text item " + itemText); if (itemText != null && itemText.equals(text)) { return i; } } return -1; }

4. Find and act on a control: getPositionForChildViewByText.

... final ListView graphicsDemoList = graphicsDemoActivity.getListView(); int pos = getPositionForChildViewByText(graphicsDemoList, "OpenGL ES"); assertTrue("Cannot find OpenGL ES", pos != -1); ...

77 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

private int getPositionForChildViewByText(ListView listView, String text) { ListAdapter listAdapter = listView.getAdapter(); int count = listAdapter.getCount(); Log.e(TAG, "children: " + count); for (int i = 0; i < count; i++) { String itemText = (String) ((Map)listAdapter.getItem(i)).get("title"); Log.e(TAG, i + "-th text item " + itemText); if (itemText != null && itemText.equals(text)) { return i; } } return -1; }

4. Find and act on a control: getPositionForChildViewByText.

... final ListView graphicsDemoList = graphicsDemoActivity.getListView(); int pos = getPositionForChildViewByText(graphicsDemoList, "OpenGL ES"); assertTrue("Cannot find OpenGL ES", pos != -1); ...

78 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

5. Monitor a new Activity to launch.

public void testNavigate() { ... Instrumentation.ActivityMonitor graphicsDemoActivityMonitor = getInstrumentation().addMonitor( ApiDemos.class.getName(), null, false); final ApiDemos graphicsDemoActivity = (ApiDemos) graphicsDemoActivityMonitor.waitForActivity(); assertNotNull("Graphics Demo (ApiDemos) activity should not be null", graphicsDemoActivity); ...

79 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

5. Monitor a new Activity to launch.

6. Iterate step 4 & 5.

public void testNavigate() { ... Instrumentation.ActivityMonitor graphicsDemoActivityMonitor = getInstrumentation().addMonitor( ApiDemos.class.getName(), null, false); final ApiDemos graphicsDemoActivity = (ApiDemos) graphicsDemoActivityMonitor.waitForActivity(); assertNotNull("Graphics Demo (ApiDemos) activity should not be null", graphicsDemoActivity); ...

80 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

7. Build and Install the test package.

$ cd ApiDemosInstrumentTest $ ant debug $ adb install –r bin/ApiDemosInstrumentTest-debug.apk

81 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

7. Build and Install the test package.

8. Run the test and see the result.

$ adb shell am instrument -w \ > com.example.android.apis.instrument.test/\ > android.test.InstrumentationTestRunner

$ cd ApiDemosInstrumentTest $ ant debug $ adb install –r bin/ApiDemosInstrumentTest-debug.apk

82 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Instrumentation

7. Build and Install the test package.

8. Run the test and see the result.

$ adb shell am instrument -w \ > com.example.android.apis.instrument.test/\ > android.test.InstrumentationTestRunner

$ cd ApiDemosInstrumentTest $ ant debug $ adb install –r bin/ApiDemosInstrumentTest-debug.apk

$ ant test

83 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Robotium

84 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Robotium

1. Create an Android Test Project for the test package.

$ android create test-project --main ../ApiDemos \ > –-name ApiDemosRobotiumTest --path ApiDemosRobotiumTest

85 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Robotium

1. Create an Android Test Project for the test package.

2. Add ‘robotium-solo-<ver>.jar’ in the ‘libs’ directory.

$ android create test-project --main ../ApiDemos \ > –-name ApiDemosRobotiumTest --path ApiDemosRobotiumTest

86 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Robotium

1. Create an Android Test Project for the test package.

2. Add ‘robotium-solo-<ver>.jar’ in the ‘libs’ directory.

3. Add a test class inheriting ActivityInstrumentationTestCase2.

$ android create test-project --main ../ApiDemos \ > –-name ApiDemosRobotiumTest --path ApiDemosRobotiumTest

public class ApiDemosRobotiumTest extends ActivityInstrumentationTestCase2<ApiDemos> { ... public ApiDemosRobotiumTest() { super(ApiDemos.class); } ...

87 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Robotium

4. Create an instance of Solo in the setUp method and

close open activities in the tearDown method.

... private Solo solo; ... @Override public void setUp() throws Exception { solo = new Solo(getInstrumentation(), getActivity()); } @Override public void tearDown() throws Exception { solo.finishOpenedActivities(); } ...

88 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Robotium

4. Find and act on a control.

public void testNavigate() { solo.assertCurrentActivity("Should be on ApiDemos", ApiDemos.class); solo.clickOnText("^Graphics$", 1, true); solo.assertCurrentActivity("Should be on a new ApiDemos", ApiDemos.class, true); solo.clickOnText("^OpenGL ES$", 1, true); solo.assertCurrentActivity("Should be on a new ApiDemos", ApiDemos.class, true); solo.clickOnText("^Kube$", 1, true); solo.assertCurrentActivity("Should be on a Kube", Kube.class, true); solo.sleep(3000); }

89 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Robotium

6. Build and Install the test package.

$ cd ApiDemosRobotiumTest $ ant debug $ adb install –r bin/ApiDemosRobotiumTest-debug.apk

90 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Robotium

6. Build and Install the test package.

7. Run the test and see the result.

$ adb shell am instrument -w \ > com.example.android.apis.robotium.test/\ > android.test.InstrumentationTestRunner

$ cd ApiDemosRobotiumTest $ ant debug $ adb install –r bin/ApiDemosRobotiumTest-debug.apk

91 12th Kandroid Conference - www.kandroid.org

Controlling UI Using Robotium

6. Build and Install the test package.

7. Run the test and see the result.

$ adb shell am instrument -w \ > com.example.android.apis.robotium.test/\ > android.test.InstrumentationTestRunner

$ cd ApiDemosRobotiumTest $ ant debug $ adb install –r bin/ApiDemosRobotiumTest-debug.apk

$ ant test

92 12th Kandroid Conference - www.kandroid.org

Controlling UI Using uiautomator

1. Create an Java Project for the test jar.

93 12th Kandroid Conference - www.kandroid.org

Controlling UI Using uiautomator

1. Create an Java Project for the test jar.

2. Add ‘android.jar’ and ‘uiautomator.jar’ in the build path.

94 12th Kandroid Conference - www.kandroid.org

Controlling UI Using uiautomator

1. Create an Java Project for the test jar.

2. Add ‘android.jar’ and ‘uiautomator.jar’ in the build path.

3. Add a test class inheriting UiAutomatorTestCase.

public class ApiDemosUiAutoTest extends UiAutomatorTestCase { ... }

95 12th Kandroid Conference - www.kandroid.org

Controlling UI Using uiautomator

4. Launch ApiDemos.

public void testNavigate() throws UiObjectNotFoundException {

96 12th Kandroid Conference - www.kandroid.org

Controlling UI Using uiautomator

4. Launch ApiDemos.

public void testNavigate() throws UiObjectNotFoundException { getUiDevice().pressHome();

Press home button

97 12th Kandroid Conference - www.kandroid.org

Controlling UI Using uiautomator

4. Launch ApiDemos.

public void testNavigate() throws UiObjectNotFoundException { getUiDevice().pressHome(); UiObject allAppsButton = new UiObject( new UiSelector().description("Apps")); allAppsButton.clickAndWaitForNewWindow();

Click ‘All Apps’ button

Press home button

98 12th Kandroid Conference - www.kandroid.org

Controlling UI Using uiautomator

4. Launch ApiDemos.

public void testNavigate() throws UiObjectNotFoundException { getUiDevice().pressHome(); UiObject allAppsButton = new UiObject( new UiSelector().description("Apps")); allAppsButton.clickAndWaitForNewWindow(); UiObject appsTab = new UiObject(new UiSelector().text("Apps")); appsTab.click();

Click ‘All Apps’ button

Press home button

Click ‘Apps’ tab

99 12th Kandroid Conference - www.kandroid.org

Controlling UI Using uiautomator

4. Launch ApiDemos.

public void testNavigate() throws UiObjectNotFoundException { getUiDevice().pressHome(); UiObject allAppsButton = new UiObject( new UiSelector().description("Apps")); allAppsButton.clickAndWaitForNewWindow(); UiObject appsTab = new UiObject(new UiSelector().text("Apps")); appsTab.click(); UiScrollable appList = new UiScrollable( new UiSelector().scrollable(true)); appList.setAsHorizontalList(); UiObject apiDemos = appList.getChildByText( new UiSelector().className(TextView.class.getName()), "API Demos"); apiDemos.clickAndWaitForNewWindow();

Click ‘All Apps’ button

Press home button

Click ‘Apps’ tab

Click ‘ApiDemos’ icon

100 12th Kandroid Conference - www.kandroid.org

Controlling UI Using uiautomator

4. Launch ApiDemos.

public void testNavigate() throws UiObjectNotFoundException { getUiDevice().pressHome(); UiObject allAppsButton = new UiObject( new UiSelector().description("Apps")); allAppsButton.clickAndWaitForNewWindow(); UiObject appsTab = new UiObject(new UiSelector().text("Apps")); appsTab.click(); UiScrollable appList = new UiScrollable( new UiSelector().scrollable(true)); appList.setAsHorizontalList(); UiObject apiDemos = appList.getChildByText( new UiSelector().className(TextView.class.getName()), "API Demos"); apiDemos.clickAndWaitForNewWindow(); UiObject apiDemosPackage = new UiObject( new UiSelector().packageName("com.example.android.apis")); assertTrue("Should be on ApiDemos", apiDemosPackage.exists()); ...

Click ‘All Apps’ button

Press home button

Click ‘Apps’ tab

Click ‘ApiDemos’ icon

Validate the launch of ‘ApiDemos’

101 12th Kandroid Conference - www.kandroid.org

Controlling UI Using uiautomator

5. Find and act on a control.

... UiScrollable demoList = new UiScrollable( new UiSelector().className("android.widget.ListView")); UiObject graphicsDemo = demoList.getChildByText( new UiSelector().className(TextView.class.getName()), “Graphics"); graphicsDemo.clickAndWaitForNewWindow(); UiObject alphaBitmapDemo = new UiObject( new UiSelector().text(“AlphaBitmap")); assertTrue(“AlphaBitmap should be visible", alpahBitmapDemo.exists()); ...

102 12th Kandroid Conference - www.kandroid.org

Controlling UI Using uiautomator

5. Find and act on a control.

6. Iterate step 5.

... UiScrollable demoList = new UiScrollable( new UiSelector().className("android.widget.ListView")); UiObject graphicsDemo = demoList.getChildByText( new UiSelector().className(TextView.class.getName()), “Graphics"); graphicsDemo.clickAndWaitForNewWindow(); UiObject alphaBitmapDemo = new UiObject( new UiSelector().text(“AlphaBitmap")); assertTrue(“AlphaBitmap should be visible", alpahBitmapDemo.exists()); ...

103 12th Kandroid Conference - www.kandroid.org

Controlling UI Using uiautomator

7. Compile your test case into a JAR file.

$ android create uitest-project --name ApiDemosUiAutoTest \ > --target 1 --path ApiDemosUiAutoTest $ cd ApiDemosUiAutoTest $ ant build

104 12th Kandroid Conference - www.kandroid.org

Controlling UI Using uiautomator

7. Compile your test case into a JAR file.

8. Install the jar on your test device.

$ android create uitest-project --name ApiDemosUiAutoTest \ > --target 1 --path ApiDemosUiAutoTest $ cd ApiDemosUiAutoTest $ ant build

$ adb push bin/ApiDemosUiAutoTest.jar /data/local/tmp/

105 12th Kandroid Conference - www.kandroid.org

Controlling UI Using uiautomator

7. Compile your test case into a JAR file.

8. Install the jar on your test device.

9. Run the test and view the test result.

$ android create uitest-project --name ApiDemosUiAutoTest \ > --target 1 --path ApiDemosUiAutoTest $ cd ApiDemosUiAutoTest $ ant build

$ adb push bin/ApiDemosUiAutoTest.jar /data/local/tmp/

$ adb shell uiautomator runtest ApiDemosUiAutoTest.jar \ > –c com.example.android.apis.uiauto.test.ApiDemosUiAutoTest

106 12th Kandroid Conference - www.kandroid.org

Controlling UI Using uiautomator

7. Compile your test case into a JAR file.

8. Install the jar on your test device.

9. Run the test and view the test result.

$ android create uitest-project --name ApiDemosUiAutoTest \ > --target 1 --path ApiDemosUiAutoTest $ cd ApiDemosUiAutoTest $ ant build

$ adb push bin/ApiDemosUiAutoTest.jar /data/local/tmp/

$ adb shell uiautomator runtest ApiDemosUiAutoTest.jar \ > –c com.example.android.apis.uiauto.test.ApiDemosUiAutoTest

$ ant test

107 12th Kandroid Conference - www.kandroid.org

Controlling UI Using uiautomator

7. Compile your test case into a JAR file.

8. Install the jar on your test device.

9. Run the test and view the test result.

$ android create uitest-project --name ApiDemosUiAutoTest \ > --target 1 --path ApiDemosUiAutoTest $ cd ApiDemosUiAutoTest $ ant build

$ adb push bin/ApiDemosUiAutoTest.jar /data/local/tmp/

$ adb shell uiautomator runtest ApiDemosUiAutoTest.jar \ > –c com.example.android.apis.uiauto.test.ApiDemosUiAutoTest

$ ant test

108 12th Kandroid Conference - www.kandroid.org

Doing both Controlling and Tracking

109 12th Kandroid Conference - www.kandroid.org

Doing both Controlling and Tracking

1. Modify org.kandroid.memtracer.MemoryInstrumentation.

public class MemoryInstrumentation extends InstrumentationTestRunner { ... @Override public void onCreate(Bundle arguments) { ... start(); super.onCreate(arguments); } @Override public void onStart() { String mainActivityName = getMainActivityName(); if (mainActivityName != null && mainActivityName.length() > 0) { launchMainActivity(getTargetContext().getPackageName(), getMainActivityName()); } else { super.onStart(); } } ...

110 12th Kandroid Conference - www.kandroid.org

Doing both Controlling and Tracking

1. Modify org.kandroid.memtracer.MemoryInstrumentation.

public class MemoryInstrumentation extends InstrumentationTestRunner { ... @Override public void onCreate(Bundle arguments) { ... start(); super.onCreate(arguments); } @Override public void onStart() { String mainActivityName = getMainActivityName(); if (mainActivityName != null && mainActivityName.length() > 0) { launchMainActivity(getTargetContext().getPackageName(), getMainActivityName()); } else { super.onStart(); } } ...

111 12th Kandroid Conference - www.kandroid.org

Doing both Controlling and Tracking

1. Modify org.kandroid.memtracer.MemoryInstrumentation.

public class MemoryInstrumentation extends InstrumentationTestRunner { ... @Override public void onCreate(Bundle arguments) { ... start(); super.onCreate(arguments); } @Override public void onStart() { String mainActivityName = getMainActivityName(); if (mainActivityName != null && mainActivityName.length() > 0) { launchMainActivity(getTargetContext().getPackageName(), getMainActivityName()); } else { super.onStart(); } } ...

112 12th Kandroid Conference - www.kandroid.org

Doing both Controlling and Tracking

1. Modify org.kandroid.memtracer.MemoryInstrumentation.

public class MemoryInstrumentation extends InstrumentationTestRunner { ... @Override public void onCreate(Bundle arguments) { ... start(); super.onCreate(arguments); } @Override public void onStart() { String mainActivityName = getMainActivityName(); if (mainActivityName != null && mainActivityName.length() > 0) { launchMainActivity(getTargetContext().getPackageName(), getMainActivityName()); } else { super.onStart(); } } ...

113 12th Kandroid Conference - www.kandroid.org

Doing both Controlling and Tracking

2. Add ‘kmemtracer-libs.jar’ in the ‘libs’ directory.

114 12th Kandroid Conference - www.kandroid.org

Doing both Controlling and Tracking

2. Add ‘kmemtracer-libs.jar’ in the ‘libs’ directory.

3. Edit the <instrumentation> element in the manifest file.

115 12th Kandroid Conference - www.kandroid.org

Doing both Controlling and Tracking

2. Add ‘kmemtracer-libs.jar’ in the ‘libs’ directory.

3. Edit the <instrumentation> element in the manifest file.

4. Build and Install the test package.

$ cd ApiDemosInstrumentTest $ ant debug $ adb install –r bin/ApiDemosInstrumentTest-debug.apk

116 12th Kandroid Conference - www.kandroid.org

Doing both Controlling and Tracking

2. Add ‘kmemtracer-libs.jar’ in the ‘libs’ directory.

3. Edit the <instrumentation> element in the manifest file.

4. Build and Install the test package.

5. Run the test and see the result.

$ adb shell am instrument -w \ > com.example.android.apis.instrument.test/\ > org.kandroid.memtracer.MemoryInstrumentation

$ cd ApiDemosInstrumentTest $ ant debug $ adb install –r bin/ApiDemosInstrumentTest-debug.apk

117 12th Kandroid Conference - www.kandroid.org

Doing both Controlling and Tracking

2. Add ‘kmemtracer-libs.jar’ in the ‘libs’ directory.

3. Edit the <instrumentation> element in the manifest file.

4. Build and Install the test package.

5. Run the test and see the result.

6. Pull the trace file ‘kmemtrace.csv’ from /sdcard/kmemtracer.

$ adb shell am instrument -w \ > com.example.android.apis.instrument.test/\ > org.kandroid.memtracer.MemoryInstrumentation

$ cd ApiDemosInstrumentTest $ ant debug $ adb install –r bin/ApiDemosInstrumentTest-debug.apk

$ adb pull /sdcard/kmemtracer/kmemtrace.csv .

118 12th Kandroid Conference - www.kandroid.org

Instrument Robotium uiautomator

Compatibility O O X

Multi-activities O O

Multi-processes X X O

Ease of APIs X O

Black box X O

Comparison

119 12th Kandroid Conference - www.kandroid.org

Why Automated Historical Performance Testing?

kmemtracer: What and How?

Enhancement I : Automating UI Interaction

Enhancement II: Adding More Performance Metrics

Contents

120 12th Kandroid Conference - www.kandroid.org

What to Measure?

Rendering (or GUI) Performance Frame Rate (FPS), Frame Time , Jankiness, Input Latency, …

Resource Consumption Memory, CPU, I/O (Disk, Network), Battery, …

Network Performance Response time, Throughput, … …

121 12th Kandroid Conference - www.kandroid.org

What to Measure?

Rendering (or GUI) Performance Frame Rate (FPS), Frame Time , Jankiness, Input Latency, …

Resource Consumption Memory, CPU, I/O (Disk, Network), Battery, …

Network Performance Response time, Throughput, … …

122 12th Kandroid Conference - www.kandroid.org

How to Measure Resource Consumption?

123 12th Kandroid Conference - www.kandroid.org

How to Measure Resource Consumption?

API cmds

124 12th Kandroid Conference - www.kandroid.org

How to Measure Resource Consumption?

API cmds

Public Internal

125 12th Kandroid Conference - www.kandroid.org

How to Measure Resource Consumption?

API cmds

Public Internal Android Linux

126 12th Kandroid Conference - www.kandroid.org

How to Measure Resource Consumption?

API cmds

Public Internal Android Linux

Easy Flexible

127 12th Kandroid Conference - www.kandroid.org

Measuring Memory Usage

128 12th Kandroid Conference - www.kandroid.org

Measuring Memory Usage

Public

android.app.ActivityManager.MemoryInfo android.os.Debug android.os.Debug.MemoryInfo

129 12th Kandroid Conference - www.kandroid.org

Measuring Memory Usage

Public Internal

android.app.ActivityManager.MemoryInfo android.os.Debug android.os.Debug.MemoryInfo

dalvik.system.VMDebug

130 12th Kandroid Conference - www.kandroid.org

Measuring Memory Usage

Public Internal Android

android.app.ActivityManager.MemoryInfo android.os.Debug android.os.Debug.MemoryInfo

adb shell dumpsys meminfo [pid|pname] adb shell dumpsys gfxinfo [pid|pname] adb shell procrank

dalvik.system.VMDebug

131 12th Kandroid Conference - www.kandroid.org

Measuring Memory Usage

Public Internal Android Linux

android.app.ActivityManager.MemoryInfo android.os.Debug android.os.Debug.MemoryInfo

adb shell dumpsys meminfo [pid|pname] adb shell dumpsys gfxinfo [pid|pname] adb shell procrank

adb shell cat /proc/meminfo adb shell cat /proc/<pid>/[s]maps adb shell cat /proc/vmstat adb shell top adb shell ps

dalvik.system.VMDebug

132 12th Kandroid Conference - www.kandroid.org

$ adb shell dumpsys meminfo com.example.android.apis Applications Memory Usage (kB): Uptime: 93065 Realtime: 93065 ** MEMINFO in pid 1259 [com.example.android.apis] ** native dalvik other total size: 3548 5831 N/A 9379 allocated: 3475 3335 N/A 6810 free: 48 2496 N/A 2544 (Pss): 699 382 4889 5970 (shared dirty): 1500 1876 8356 11732 (priv dirty): 628 40 2472 3140 ...

GB (API Level 10)

Measuring Memory Usage: dumpsys meminfo

133 12th Kandroid Conference - www.kandroid.org

$ adb shell dumpsys meminfo com.example.android.apis Applications Memory Usage (kB): Uptime: 93065 Realtime: 93065 ** MEMINFO in pid 1259 [com.example.android.apis] ** native dalvik other total size: 3548 5831 N/A 9379 allocated: 3475 3335 N/A 6810 free: 48 2496 N/A 2544 (Pss): 699 382 4889 5970 (shared dirty): 1500 1876 8356 11732 (priv dirty): 628 40 2472 3140 ...

GB (API Level 10)

Measuring Memory Usage: dumpsys meminfo

134 12th Kandroid Conference - www.kandroid.org

$ adb shell dumpsys meminfo com.example.android.apis ... ** MEMINFO in pid 1875 [com.example.android.apis] ** Shared Private Heap Heap Heap Pss Dirty Dirty Size Alloc Free ------ ------ ------ ------ ------ ------ Native 1377 1256 1300 12084 7332 567 Dalvik 5274 5476 4952 6260 5712 548 Stack 76 12 76 Cursor 0 0 0 Ashmem 0 0 0 Other dev 4 20 0 .so mmap 1526 4836 592 .jar mmap 0 0 0 .apk mmap 267 0 0 .ttf mmap 5 0 0 .dex mmap 1085 0 0 Other mmap 18 8 4 Unknown 824 0 824 TOTAL 10456 11608 7748 18344 13044 1115 ...

JB (API Level 18)

Measuring Memory Usage: dumpsys meminfo

135 12th Kandroid Conference - www.kandroid.org

$ adb shell dumpsys meminfo com.example.android.apis ... ** MEMINFO in pid 1875 [com.example.android.apis] ** Shared Private Heap Heap Heap Pss Dirty Dirty Size Alloc Free ------ ------ ------ ------ ------ ------ Native 1377 1256 1300 12084 7332 567 Dalvik 5274 5476 4952 6260 5712 548 Stack 76 12 76 Cursor 0 0 0 Ashmem 0 0 0 Other dev 4 20 0 .so mmap 1526 4836 592 .jar mmap 0 0 0 .apk mmap 267 0 0 .ttf mmap 5 0 0 .dex mmap 1085 0 0 Other mmap 18 8 4 Unknown 824 0 824 TOTAL 10456 11608 7748 18344 13044 1115 ...

JB (API Level 18)

Measuring Memory Usage: dumpsys meminfo

136 12th Kandroid Conference - www.kandroid.org

https://android.googlesource.com/platform/frameworks/base.git/+/0e3328fbdd3845b0e2bec364e951498eaee6b079

137 12th Kandroid Conference - www.kandroid.org

How ‘dumpsys meminfo’ works?

adb shell dumpsys meminfo [-a] [-oom] [-process]

138 12th Kandroid Conference - www.kandroid.org

How ‘dumpsys meminfo’ works?

com.android.server.am. ActivityManagerService

adb shell dumpsys meminfo [-a] [-oom] [-process]

139 12th Kandroid Conference - www.kandroid.org

How ‘dumpsys meminfo’ works?

com.android.server.am. ActivityManagerService

android.os Debug

android.app.ActivityThread. ApplicationThread

adb shell dumpsys meminfo [-a] [-oom] [-process]

android.app.ActivityThread. ApplicationThread

android.app.ActivityThread. ApplicationThread

140 12th Kandroid Conference - www.kandroid.org

How ‘dumpsys meminfo’ works?

com.android.server.am. ActivityManagerService

android.os Debug

android.app.ActivityThread. ApplicationThread

adb shell dumpsys meminfo [-a] [-oom] [-process]

android.app.ActivityThread. ApplicationThread

android.app.ActivityThread. ApplicationThread

141 12th Kandroid Conference - www.kandroid.org

How ‘dumpsys meminfo’ works?

com.android.server.am. ActivityManagerService

android.os Debug

android.app.ActivityThread. ApplicationThread

/proc/<pid>/smaps

adb shell dumpsys meminfo [-a] [-oom] [-process]

mallinfo()

getNativeHeap*() getMemoryInfo()

android.app.ActivityThread. ApplicationThread

android.app.ActivityThread. ApplicationThread

142 12th Kandroid Conference - www.kandroid.org

android.app.ActivityThread.ApplicationThread.dumpMemInfo()

long nativeMax = Debug.getNativeHeapSize() / 1024; long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; long nativeFree = Debug.getNativeHeapFreeSize() / 1024; Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); Debug.getMemoryInfo(memInfo); Runtime runtime = Runtime.getRuntime(); long dalvikMax = runtime.totalMemory() / 1024; long dalvikFree = runtime.freeMemory() / 1024; long dalvikAllocated = dalvikMax - dalvikFree;

How ‘dumpsys meminfo’ works?

143 12th Kandroid Conference - www.kandroid.org

android.app.ActivityThread.ApplicationThread.dumpMemInfo()

long nativeMax = Debug.getNativeHeapSize() / 1024; long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; long nativeFree = Debug.getNativeHeapFreeSize() / 1024; Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); Debug.getMemoryInfo(memInfo); Runtime runtime = Runtime.getRuntime(); long dalvikMax = runtime.totalMemory() / 1024; long dalvikFree = runtime.freeMemory() / 1024; long dalvikAllocated = dalvikMax - dalvikFree;

struct mallinfo info = mallinfo(); (jlong) info.usmblks; // Debug.getNativeHeapSize() (jlong) info.uordblks; // Debug.getNativeHeapAllocatedSize() (jlong) info.fordblks; // Debug.getNativeHeapFreeSize()

android.os.Debug.getNativeHeap*()

How ‘dumpsys meminfo’ works?

144 12th Kandroid Conference - www.kandroid.org

struct mallinfo { MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ MALLINFO_FIELD_TYPE smblks; /* always 0 */ MALLINFO_FIELD_TYPE hblks; /* always 0 */ MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ MALLINFO_FIELD_TYPE fordblks; /* total free space */ MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ };

bionic\libc\upstream-dlmalloc\malloc.c

① Total allocated = uordblks ② Total free = fordblks ③ Footprint = uordblks + fordblks ④ Max footprint = usmblks

2

1

3

4

How ‘dumpsys meminfo’ works?

145 12th Kandroid Conference - www.kandroid.org

Measuring CPU Usage

146 12th Kandroid Conference - www.kandroid.org

Measuring CPU Usage

Public

android.os.Process android.os.Debug.InstructionCount

147 12th Kandroid Conference - www.kandroid.org

Measuring CPU Usage

Public Internal

android.os.Process android.os.Debug.InstructionCount

com.android.internal.os.ProcessStats

148 12th Kandroid Conference - www.kandroid.org

Measuring CPU Usage

Public Internal Android

android.os.Process android.os.Debug.InstructionCount

adb shell dumpsys cpuinfo

com.android.internal.os.ProcessStats

149 12th Kandroid Conference - www.kandroid.org

Measuring CPU Usage

Public Internal Android Linux

android.os.Process android.os.Debug.InstructionCount

adb shell dumpsys cpuinfo

adb shell cat /proc/stat adb shell cat /proc/<pid>/stat adb shell top

com.android.internal.os.ProcessStats

150 12th Kandroid Conference - www.kandroid.org

Measuring CPU Usage: dumpsys cpuinfo

$ adb shell dumpsys cpuinfo Load: 0.0 / 0.01 / 0.05 CPU usage from 27006ms to 5405ms ago: 1.1% 1421/com.android.launcher: 0.3% user + 0.8% kernel / faults: 2187 minor 2.4% 1225/system_server: 0.4% user + 1.9% kernel / faults: 2030 minor 0.1% 949/surfaceflinger: 0% user + 0.1% kernel / faults: 3 minor 0% 952/mediaserver: 0% user + 0% kernel / faults: 8 minor 0% 959/adbd: 0% user + 0% kernel / faults: 11 minor 0% 1295/com.android.systemui: 0% user + 0% kernel / faults: 5 minor +0% 1901/com.example.android.apis: 0% user + 0% kernel 56% TOTAL: 10% user + 45% kernel + 0.7% softirq

151 12th Kandroid Conference - www.kandroid.org

How ‘dumpsys cpuinfo’ works?

adb shell dumpsys cpuinfo

152 12th Kandroid Conference - www.kandroid.org

How ‘dumpsys cpuinfo’ works?

adb shell dumpsys cpuinfo

com.android.server.am. ActivityManagerService

153 12th Kandroid Conference - www.kandroid.org

com.android.internal.os ProcessStats

How ‘dumpsys cpuinfo’ works?

adb shell dumpsys cpuinfo

com.android.server.am. ActivityManagerService

154 12th Kandroid Conference - www.kandroid.org

com.android.internal.os ProcessStats

com.android.internal.os ProcessStats.Stats

com.android.internal.os ProcessStats.Stats

com.android.internal.os ProcessStats.Stats

How ‘dumpsys cpuinfo’ works?

adb shell dumpsys cpuinfo

com.android.server.am. ActivityManagerService

155 12th Kandroid Conference - www.kandroid.org

com.android.internal.os ProcessStats

com.android.internal.os ProcessStats.Stats

android.os Process

com.android.internal.os ProcessStats.Stats

com.android.internal.os ProcessStats.Stats

android_util_Process.cpp

How ‘dumpsys cpuinfo’ works?

adb shell dumpsys cpuinfo

/proc/stat /proc/loadavg /proc/<pid>/stat /proc/<ppid>/task/<pid>/stat

com.android.server.am. ActivityManagerService

156 12th Kandroid Conference - www.kandroid.org

How ‘dumpsys cpuinfo’ works?

procfs (or the proc filesystem) is a special filesystem in UNIX-

like operating systems that presents information about processes

and other system information in a hierarchical file-like structure,

providing a more convenient and standardized method for

dynamically accessing process data held in the kernel than

traditional tracing methods or direct access to kernel memory.

http://en.wikipedia.org/wiki/Procfs

157 12th Kandroid Conference - www.kandroid.org

http://manpages.courier-mta.org/htmlman5/proc.5.html

How ‘dumpsys cpuinfo’ works?

procfs (or the proc filesystem) is a special filesystem in UNIX-

like operating systems that presents information about processes

and other system information in a hierarchical file-like structure,

providing a more convenient and standardized method for

dynamically accessing process data held in the kernel than

traditional tracing methods or direct access to kernel memory.

http://en.wikipedia.org/wiki/Procfs

158 12th Kandroid Conference - www.kandroid.org

Measuring I/O Usage

159 12th Kandroid Conference - www.kandroid.org

Measuring I/O Usage

Public

android.net.TrafficStats

160 12th Kandroid Conference - www.kandroid.org

Measuring I/O Usage

Public Internal

android.net.TrafficStats

android.net.NetworkStats android.net.NetworkStatsHistory com.android.internal.net.NetworkStatsFactory

161 12th Kandroid Conference - www.kandroid.org

Measuring I/O Usage

Public Internal Android

android.net.TrafficStats

adb shell dumpsys netstats adb shell dumpsys diskstats

android.net.NetworkStats android.net.NetworkStatsHistory com.android.internal.net.NetworkStatsFactory

162 12th Kandroid Conference - www.kandroid.org

Measuring I/O Usage

Public Internal Android Linux

android.net.TrafficStats

adb shell dumpsys netstats adb shell dumpsys diskstats

/proc/net/*

android.net.NetworkStats android.net.NetworkStatsHistory com.android.internal.net.NetworkStatsFactory

163 12th Kandroid Conference - www.kandroid.org

Measuring Network IO Usage: dumpsys netstats

$ adb shell dumpsys netstats Active interfaces: iface=eth0 ident=[[type=MOBILE, subType=COMBINED, subscriberId=310260000000000]] Dev stats: Pending bytes: 43783 History since boot: ident=[[type=MOBILE_HIPRI, subType=COMBINED, subscriberId=310260000000000], [type=MOBILE, subType=COMBINED, subscriberId=310260000000000]] uid=-1 set=ALL tag=0x0 NetworkStatsHistory: bucketDuration=3600000 bucketStart=1382443200000 activeTime=4813 rxBytes=17410 rxPackets=203 txBytes=25579 txPackets=173 operations=0 ... Xt stats: Pending bytes: 37557 History since boot: ident=[[type=MOBILE_HIPRI, subType=COMBINED, subscriberId=310260000000000], [type=MOBILE, subType=COMBINED, subscriberId=310260000000000]] uid=-1 set=ALL tag=0x0 ... UID stats: ... UID tag stats: ...

164 12th Kandroid Conference - www.kandroid.org

adb shell dumpsys netstats [--full] [--uid] [--tag]

How ‘dumpsys netstats’ works?

165 12th Kandroid Conference - www.kandroid.org

com.android.server.net. NetworkStatsService

adb shell dumpsys netstats [--full] [--uid] [--tag]

How ‘dumpsys netstats’ works?

166 12th Kandroid Conference - www.kandroid.org

com.android.server.net. NetworkStatsService

com.android.server.net NetworkStatsRecorder

adb shell dumpsys netstats [--full] [--uid] [--tag]

How ‘dumpsys netstats’ works?

com.android.server.net NetworkStatsRecorder

com.android.server.net NetworkStatsRecorder

com.android.server.net NetworkStatsRecorder

167 12th Kandroid Conference - www.kandroid.org

com.android.server.net. NetworkStatsService

android.net NetworkStatsHistory

com.android.server.net NetworkStatsCollection

com.android.server.net NetworkStatsRecorder

adb shell dumpsys netstats [--full] [--uid] [--tag]

How ‘dumpsys netstats’ works?

com.android.server.net NetworkStatsRecorder

com.android.server.net NetworkStatsRecorder

com.android.server.net NetworkStatsRecorder

android.net NetworkStatsHistory

android.net NetworkStatsHistory

168 12th Kandroid Conference - www.kandroid.org

com.android.internal.net NetworkStatsFactory

com.android.server.net. NetworkStatsService

android.net NetworkStats

android.net NetworkStatsHistory

com.android.server.net NetworkStatsCollection

com.android.server.net NetworkStatsRecorder

adb shell dumpsys netstats [--full] [--uid] [--tag]

How ‘dumpsys netstats’ works?

com.android.server.net NetworkStatsRecorder

com.android.server.net NetworkStatsRecorder

com.android.server.net NetworkStatsRecorder

android.net NetworkStatsHistory

android.net NetworkStatsHistory

/proc/net/xt_qtaguid/iface_stat_all /proc/net/xt_qtaguid/iface_stat_fmt /proc/net/xt_qtaguid/stats

com.android.server NetworkManagementService

169 12th Kandroid Conference - www.kandroid.org

@Override public Config getDevConfig() { return new Config(getSecureLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS), getSecureLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS), getSecureLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS)); } @Override public Config getXtConfig() { return getDevConfig(); } @Override public Config getUidConfig() { return new Config(getSecureLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS), getSecureLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS), getSecureLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS)); } @Override public Config getUidTagConfig() { return new Config(getSecureLong(NETSTATS_UID_TAG_BUCKET_DURATION, 2 * HOUR_IN_MILLIS), getSecureLong(NETSTATS_UID_TAG_ROTATE_AGE, 5 * DAY_IN_MILLIS), getSecureLong(NETSTATS_UID_TAG_DELETE_AGE, 15 * DAY_IN_MILLIS)); }

How ‘dumpsys netstats’ works?

com.android.server.net.NetworkStatsService.DefaultNetworkStatsSettings

170 12th Kandroid Conference - www.kandroid.org

$ adb shell cat /proc/net/xt_qtaguid/iface_stat_all eth0 1 0 0 0 0 220609 3228 2891157 2995

$ adb shell cat /proc/net/xt_qtaguid/iface_stat_fmt ifname total_skb_rx_bytes total_skb_rx_packets total_skb_tx_bytes total_skb_tx_packets eth0 163781 3231 2846738 2994

Dev: IP + Non IP layer traffic

Xt: Only IP layer traffic

$ adb shell cat /proc/net/xt_qtaguid/stats idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets 2 eth0 0x0 0 0 163335 3226 2846228 2988 161473 3222 1862 4 0 0 2845850 2982 266 4 112 2 3 eth0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 eth0 0x0 1000 0 819 11 965 12 667 9 152 2 0 0 813 10 152 2 0 0 5 eth0 0x0 1000 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Uid: UID level details

How ‘dumpsys netstats’ works?

171 12th Kandroid Conference - www.kandroid.org

Measuring Battery Usage

172 12th Kandroid Conference - www.kandroid.org

Measuring Battery Usage

Public

android.os.BatteryManager

173 12th Kandroid Conference - www.kandroid.org

Measuring Battery Usage

Public Internal

android.os.BatteryManager

android.os.BatteryStats com.android.internal.os.BatteryStatsImpl com.android.internal.os.PowerProfile com.android.server.os.BatteryStatsService

174 12th Kandroid Conference - www.kandroid.org

Measuring Battery Usage

Public Internal Android

android.os.BatteryManager

adb shell dumpsys battery adb shell dumpsys batteryinfo

android.os.BatteryStats com.android.internal.os.BatteryStatsImpl com.android.internal.os.PowerProfile com.android.server.os.BatteryStatsService

175 12th Kandroid Conference - www.kandroid.org

Measuring Battery Usage

Public Internal Android Linux

android.os.BatteryManager

adb shell dumpsys battery adb shell dumpsys batteryinfo

None (?)

android.os.BatteryStats com.android.internal.os.BatteryStatsImpl com.android.internal.os.PowerProfile com.android.server.os.BatteryStatsService

176 12th Kandroid Conference - www.kandroid.org

$ adb shell dumpsys batteryinfo Battery History: -1d00h43m02s057ms START -1d00h40m00s730ms 050 20080002 status=charging health=good plug=ac temp=0 volt=0 +plugged +sensor brightness=medium -1d00h39m57s332ms 050 60080002 +wake_lock -1d00h39m57s202ms 050 60080302 phone_state=off ... Per-PID Stats: PID 1227 wake time: +3s445ms PID 1227 wake time: +199ms ... Statistics since last charge: System starts: 29, currently on battery: false Time on battery: 0ms (0.0%) realtime, 0ms (0.0%) uptime Total run time: 1d 2h 1m 3s 606ms realtime, 1d 2h 1m 3s 603ms uptime, ... #1000: User activity: 26 other, 27 button, 93 touch Sensor 0: (not used) Apk com.android.keychain: (nothing executed) ... Statistics since last unplugged: Time on battery: 0ms (0.0%) realtime, 0ms (0.0%) uptime ...

Measuring Battery Usage: dumpsys batteryinfo

177 12th Kandroid Conference - www.kandroid.org

adb shell dumpsys batteryinfo

How ‘dumpsys batteryinfo’ works?

178 12th Kandroid Conference - www.kandroid.org

com.android.server.am. BatteryStatsService

adb shell dumpsys batteryinfo

How ‘dumpsys batteryinfo’ works?

179 12th Kandroid Conference - www.kandroid.org

com.android.internal.os BatteryStatsImpl

com.android.server.am. BatteryStatsService

adb shell dumpsys batteryinfo

How ‘dumpsys batteryinfo’ works?

180 12th Kandroid Conference - www.kandroid.org

com.android.internal.os BatteryStatsImpl

android.os BatteryStats

com.android.server.am. BatteryStatsService

adb shell dumpsys batteryinfo

How ‘dumpsys batteryinfo’ works?

181 12th Kandroid Conference - www.kandroid.org

com.android.internal.os BatteryStatsImpl

android.os BatteryStats

com.android.server.am. BatteryStatsService

adb shell dumpsys batteryinfo

How ‘dumpsys batteryinfo’ works?

noteBluetoothOff() noteBluetoothOn() noteFullWifiLockAcquired(int) noteFullWifiLockAcquiredFromSource(WorkSource) noteFullWifiLockReleased(int) noteFullWifiLockReleasedFromSource(WorkSource) noteInputEvent() noteNetworkInterfaceType(String, int) notePhoneDataConnectionState(int, boolean) notePhoneOff() notePhoneOn() notePhoneSignalStrength(SignalStrength) notePhoneState(int) noteScreenBrightness(int) noteScreenOff() noteScreenOn() ... noteWifiScanStarted(int) noteWifiScanStartedFromSource(WorkSource) noteWifiScanStopped(int) noteWifiScanStoppedFromSource(WorkSource) noteWifiStopped(WorkSource)

182 12th Kandroid Conference - www.kandroid.org

If you can’t automate the measurement of it,

it is difficult to improve it.

183 12th Kandroid Conference - www.kandroid.org

If you can’t automate the measurement of it,

it is difficult to improve it.

If you can’t understand the measurement results,

it is impossible to improve it.

Recommended