Integrating simpleperf to app launch tests

1. This change is backward compatible. The old test command should still be
valid and should just run fine.
2. To test the path, use the original "am instriment" command and add -e
dispatcher com.android.performanceLaunch.DispatchActivity".

Bug: 28964480

Change-Id: Ib63581ee57c56f31264b12c8e7a5a21c2d621020
diff --git a/tests/perf/PerformanceAppTest/AndroidManifest.xml b/tests/perf/PerformanceAppTest/AndroidManifest.xml
index 5f90671..f526ec7 100644
--- a/tests/perf/PerformanceAppTest/AndroidManifest.xml
+++ b/tests/perf/PerformanceAppTest/AndroidManifest.xml
@@ -15,6 +15,7 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.performanceapp.tests"
+    android:sharedUserId="com.android.performanceapp.tests"
     android:versionCode="1"
     android:versionName="1.0" >
 
@@ -34,4 +35,4 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/tests/perf/PerformanceAppTest/src/com/android/performanceapp/tests/AppLaunchTests.java b/tests/perf/PerformanceAppTest/src/com/android/performanceapp/tests/AppLaunchTests.java
index c897ddc..91d913b 100644
--- a/tests/perf/PerformanceAppTest/src/com/android/performanceapp/tests/AppLaunchTests.java
+++ b/tests/perf/PerformanceAppTest/src/com/android/performanceapp/tests/AppLaunchTests.java
@@ -50,6 +50,10 @@
 
     private static final String TAG = "AppLaunchInstrumentation";
     private static final String TARGETPACKAGE = "targetpackage";
+    private static final String SIMPLEPERF_BIN = "simpleperf_bin";
+    private static final String SIMPLEPERF_EVT = "simpleperf_event";
+    private static final String SIMPLEPERF_DATA = "simpleperf_data";
+    private static final String DISPATCHER = "dispatcher";
     private static final String ACTIVITYLIST = "activitylist";
     private static final String LAUNCHCOUNT = "launchcount";
     private static final String RECORDTRACE = "recordtrace";
@@ -61,6 +65,10 @@
     private Context mContext;
     private Bundle mResult;
     private String mTargetPackageName;
+    private String mSimpleperfBin;
+    private String mSimpleperfEvt;
+    private String mSimpleperfDir;
+    private String mDispatcher;
     private int mLaunchCount;
     private String mCustomActivityList;
     private PackageInfo mPackageInfo;
@@ -79,6 +87,13 @@
         assertNotNull("Unable to get the args", args);
         mTargetPackageName = args.getString(TARGETPACKAGE);
         assertNotNull("Target package name not set", mTargetPackageName);
+        mSimpleperfEvt = args.getString(SIMPLEPERF_EVT);
+        mDispatcher = args.getString(DISPATCHER);
+        if (mDispatcher != null && !mDispatcher.isEmpty()) {
+            mSimpleperfBin = args.getString(SIMPLEPERF_BIN);
+            mSimpleperfEvt = args.getString(SIMPLEPERF_EVT);
+            mSimpleperfDir = args.getString(SIMPLEPERF_DATA);
+        }
         mCustomActivityList = args.getString(ACTIVITYLIST);
         if (mCustomActivityList == null || mCustomActivityList.isEmpty()) {
             // Get full list of activities from the target package
@@ -104,15 +119,28 @@
         assertNotNull("Unable to get the root of the external storage", root);
         File logsDir = new File(root, "atrace_logs");
         assertTrue("Unable to create the directory to store atrace logs", logsDir.mkdir());
+        if (mDispatcher != null && !mDispatcher.isEmpty()) {
+            if (mSimpleperfDir == null)
+                mSimpleperfDir = "/sdcard/perf_simpleperf/";
+            File simpleperfDir = new File(mSimpleperfDir);
+            assertTrue("Unable to create the directory to store simpleperf data", simpleperfDir.mkdir());
+        }
         for (int count = 0; count < mLaunchCount; count++) {
             for (String activityName : mActivityList) {
                 ComponentName cn = new ComponentName(mTargetPackageName,
-                        activityName);
+                        mDispatcher != null ? mDispatcher : activityName);
                 Intent intent = new Intent(Intent.ACTION_MAIN);
                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                 intent.setComponent(cn);
 
+                if (mDispatcher != null) {
+                    intent.putExtra("ACTIVITY_NAME", activityName);
+                    intent.putExtra("SIMPLEPERF_DIR", mSimpleperfDir);
+                    intent.putExtra("SIMPLEPERF_EVT", mSimpleperfEvt);
+                    intent.putExtra("SIMPLEPERF_BIN", mSimpleperfBin);
+                }
+
                 // Start the atrace
                 if (mRecordTrace) {
                     assertNotNull(
@@ -127,6 +155,16 @@
                 mContext.startActivity(intent);
                 Thread.sleep(5 * 1000);
 
+                // Make sure we stops simpleperf
+                if (mDispatcher != null) {
+                    try {
+                        Runtime.getRuntime().exec("pkill -l SIGINT simpleperf").waitFor();
+                    } catch (Exception e) {
+                        Log.v(TAG, "simpleperf throw exception");
+                        e.printStackTrace();
+                    }
+                }
+
                 // Dump atrace info and write it to file
                 if (mRecordTrace) {
                     int processId = getProcessId(mTargetPackageName);
diff --git a/tests/perf/PerformanceLaunch/Android.mk b/tests/perf/PerformanceLaunch/Android.mk
index 98e5037..15d8289 100644
--- a/tests/perf/PerformanceLaunch/Android.mk
+++ b/tests/perf/PerformanceLaunch/Android.mk
@@ -16,6 +16,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := PerformanceLaunch
+LOCAL_CERTIFICATE := platform
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_MODULE_TAGS := tests
 
diff --git a/tests/perf/PerformanceLaunch/AndroidManifest.xml b/tests/perf/PerformanceLaunch/AndroidManifest.xml
index 48461a2..5902da0 100644
--- a/tests/perf/PerformanceLaunch/AndroidManifest.xml
+++ b/tests/perf/PerformanceLaunch/AndroidManifest.xml
@@ -15,9 +15,12 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.performanceLaunch"
+    android:sharedUserId="com.android.performanceapp.tests"
     android:versionCode="1"
     android:versionName="1.0" >
 
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
     <uses-sdk
         android:minSdkVersion="22"
         android:targetSdkVersion="22" />
@@ -28,7 +31,7 @@
         android:label="@string/app_name"
         android:theme="@style/AppTheme" >
         <activity
-            android:name=".EmptyActivity"
+            android:name=".DispatchActivity"
             android:label="@string/app_name"
             android:autoRemoveFromRecents="true"
             android:exported="true"
@@ -39,6 +42,12 @@
             </intent-filter>
         </activity>
         <activity
+            android:name=".EmptyActivity"
+            android:label="@string/app_name"
+            android:autoRemoveFromRecents="true"
+            android:exported="true"
+            android:screenOrientation="nosensor" />
+        <activity
             android:name=".SimpleActivity"
             android:label="@string/app_name"
             android:autoRemoveFromRecents="true"
diff --git a/tests/perf/PerformanceLaunch/src/com/android/performanceLaunch/DispatchActivity.java b/tests/perf/PerformanceLaunch/src/com/android/performanceLaunch/DispatchActivity.java
new file mode 100644
index 0000000..47b1c21
--- /dev/null
+++ b/tests/perf/PerformanceLaunch/src/com/android/performanceLaunch/DispatchActivity.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2016 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.performanceLaunch;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Process;
+import android.util.Log;
+import java.io.File;
+import java.io.InputStream;
+import java.io.IOException;
+import java.lang.ProcessBuilder;
+
+public class DispatchActivity extends Activity {
+
+    private static final String TAG = "DispatchActivity";
+    private Context mContext;
+    private Bundle mExtras;
+    private Intent mIntent;
+    private String mActivityName;
+    private String mSimpleperfBin;
+    private String mSimpleperfEvt;
+    private String mSimpleperfDir;
+    private String mPackageName;
+    private int mPid;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mExtras = getIntent().getExtras();
+        if (mExtras != null) {
+            mActivityName = mExtras.getString("ACTIVITY_NAME");
+            mSimpleperfBin = mExtras.getString("SIMPLEPERF_BIN");
+            mSimpleperfEvt = mExtras.getString("SIMPLEPERF_EVT");
+            mSimpleperfDir = mExtras.getString("SIMPLEPERF_DIR");
+            if (mSimpleperfBin == null || mSimpleperfBin.isEmpty()) {
+                mSimpleperfEvt = "/system/xbin/simpleperf";
+            }
+            if (mSimpleperfEvt == null || mSimpleperfEvt.isEmpty()) {
+                mSimpleperfEvt = "cpu-cycles,instructions:k,instructions:u";
+            }
+            if (mSimpleperfDir == null || mSimpleperfDir.isEmpty()) {
+                mSimpleperfDir = "/sdcard/perf_simpleperf";
+            }
+            mPackageName = getApplicationContext().getPackageName();
+            mContext = getApplicationContext();
+
+            ComponentName cn = new ComponentName(mPackageName, mActivityName);
+            mIntent = new Intent(Intent.ACTION_MAIN);
+            mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            mIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+            mIntent.setComponent(cn);
+        }
+
+        try {
+            mPid = android.os.Process.myPid();
+            ProcessBuilder simpleperf =
+                    new ProcessBuilder(mSimpleperfBin, "stat", "--group",
+                            mSimpleperfEvt, "-p", String.valueOf(mPid));
+
+            simpleperf.redirectOutput(new File(String.format("%s/%s.%s",
+                    mSimpleperfDir, "perf.data", String.valueOf(mPid))));
+            simpleperf.start();
+
+        } catch (Exception e) {
+            Log.v(TAG, "simpleperf throw exception");
+            e.printStackTrace();
+        }
+
+        startActivity(mIntent);
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        try {
+            Runtime.getRuntime().exec("pkill -l SIGINT simpleperf").waitFor();
+        } catch (Exception e) {
+            Log.v(TAG, "Failed to stop simpleperf");
+            e.printStackTrace();
+        }
+    }
+}