add taskswitching / install time measurement

- taskswitching: two apps started sequentially
    completion of switching notified after onResume is finished.
- install: measure time including adb download time to install replicaisland

Change-Id: Id44567ec62ffacba60d625c699c20854ad2d8e78
diff --git a/suite/pts/PtsBuild.mk b/suite/pts/PtsBuild.mk
index 3c4df8b..7455c9a 100644
--- a/suite/pts/PtsBuild.mk
+++ b/suite/pts/PtsBuild.mk
@@ -24,11 +24,17 @@
     PtsDeviceUi \
     PtsDeviceDram
 
+
 PTS_SUPPORT_PACKAGES := \
-	TestDeviceSetup
+    TestDeviceSetup \
+    PtsDeviceTaskswitchingAppA \
+    PtsDeviceTaskswitchingAppB \
+    PtsDeviceTaskswitchingControl \
+    com.replica.replicaisland
 
 PTS_HOST_CASES := \
-    PtsHostBootup
+    PtsHostBootup \
+    PtsHostUi
 
 PTS_HOST_LIBS := \
     $(HOST_OUT_JAVA_LIBRARIES)/ptscommonutilhost.jar
diff --git a/suite/pts/hostTests/bootup/Android.mk b/suite/pts/hostTests/bootup/Android.mk
index b0226c3..4d779a0 100644
--- a/suite/pts/hostTests/bootup/Android.mk
+++ b/suite/pts/hostTests/bootup/Android.mk
@@ -28,4 +28,3 @@
 
 include $(BUILD_PTS_HOST_JAVA_LIBRARY)
 
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/suite/pts/hostTests/bootup/src/com/android/pts/bootup/BootupTimeTest.java b/suite/pts/hostTests/bootup/src/com/android/pts/bootup/BootupTimeTest.java
index 709588b..e78289b 100644
--- a/suite/pts/hostTests/bootup/src/com/android/pts/bootup/BootupTimeTest.java
+++ b/suite/pts/hostTests/bootup/src/com/android/pts/bootup/BootupTimeTest.java
@@ -26,10 +26,15 @@
 import com.android.tradefed.device.TestDeviceOptions;
 import com.android.tradefed.testtype.DeviceTestCase;
 
-
+/**
+ *  Measure reboot-time using adb shell reboot
+ */
 public class BootupTimeTest extends DeviceTestCase {
 
     private ReportLog mReport = null;
+    // add some delay before each reboot
+    final static long SLEEP_BEFORE_REBOOT_TIME = 2 * 60 * 1000L;
+    final static int REBOOT_TIMEOUT_MS = 10 * 60 * 1000;
 
     @Override
     protected void setUp() throws Exception {
@@ -40,8 +45,8 @@
 
     @Override
     protected void tearDown() throws Exception {
-        mReport.throwReportToHost();
         super.tearDown();
+        mReport.throwReportToHost();
     }
 
     @TimeoutReq(minutes = 30)
@@ -53,8 +58,7 @@
                 if (i == 0) {
                     return;
                 }
-                final long SLEEP_TIME = 2 * 60 * 1000L;
-                Thread.sleep(SLEEP_TIME);
+                Thread.sleep(SLEEP_BEFORE_REBOOT_TIME);
             }
             @Override
             public void run(int i) throws Exception {
@@ -67,13 +71,12 @@
     }
 
     private void rebootDevice() throws DeviceNotAvailableException {
-        final int TIMEOUT_MS = 10 * 60 * 1000;
         TestDeviceOptions options = getDevice().getOptions();
         // store default value and increase time-out for reboot
         int rebootTimeout = options.getRebootTimeout();
         long onlineTimeout = options.getOnlineTimeout();
-        options.setRebootTimeout(TIMEOUT_MS);
-        options.setOnlineTimeout(TIMEOUT_MS);
+        options.setRebootTimeout(REBOOT_TIMEOUT_MS);
+        options.setOnlineTimeout(REBOOT_TIMEOUT_MS);
         getDevice().setOptions(options);
         getDevice().reboot();
         // restore default values
diff --git a/suite/pts/hostTests/uihost/Android.mk b/suite/pts/hostTests/uihost/Android.mk
new file mode 100644
index 0000000..77673a2
--- /dev/null
+++ b/suite/pts/hostTests/uihost/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := PtsHostUi
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt ddmlib-prebuilt junit ptscommonutilhost
+
+LOCAL_PTS_TEST_PACKAGE := com.android.pts.uihost
+
+include $(BUILD_PTS_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/suite/pts/hostTests/uihost/appA/Android.mk b/suite/pts/hostTests/uihost/appA/Android.mk
new file mode 100644
index 0000000..7dce44c
--- /dev/null
+++ b/suite/pts/hostTests/uihost/appA/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := ptsutil ctsutil ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := PtsDeviceTaskswitchingAppA
+
+LOCAL_SDK_VERSION := 16
+
+include $(BUILD_PTS_PACKAGE)
+
+
diff --git a/suite/pts/hostTests/uihost/appA/AndroidManifest.xml b/suite/pts/hostTests/uihost/appA/AndroidManifest.xml
new file mode 100644
index 0000000..1115ee6
--- /dev/null
+++ b/suite/pts/hostTests/uihost/appA/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.pts.taskswitching.appa">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
+    <application>
+        <activity
+                android:name=".AppAActivity"
+                android:screenOrientation="portrait"
+                android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/suite/pts/hostTests/uihost/appA/src/com/android/pts/taskswitching/appa/AppAActivity.java b/suite/pts/hostTests/uihost/appA/src/com/android/pts/taskswitching/appa/AppAActivity.java
new file mode 100644
index 0000000..bb0c158
--- /dev/null
+++ b/suite/pts/hostTests/uihost/appA/src/com/android/pts/taskswitching/appa/AppAActivity.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 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.pts.taskswitching.appa;
+
+
+import android.app.ListActivity;
+import android.content.Intent;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.WindowManager;
+import android.widget.AbsListView;
+import android.widget.AbsListView.OnScrollListener;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+/**
+ * Simple activity to notify completion via broadcast after onResume.
+ * This is for measuring taskswitching time between two apps.
+ */
+public class AppAActivity extends ListActivity {
+    static final String TAG = "AppAActivity";
+    private static final int NUMBER_ELEMENTS = 1000;
+    private static final String TASKSWITCHING_INTENT = "com.android.pts.taskswitching.appa";
+    private Handler mHandler;
+
+    private String[] mItems = new String[NUMBER_ELEMENTS];
+
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+        for (int i = 0; i < NUMBER_ELEMENTS; i++) {
+            mItems[i] = "A" + Integer.toString(i);
+        }
+        setListAdapter(new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, mItems));
+        ListView view = getListView();
+        mHandler = new Handler();
+    }
+
+    public void onResume() {
+        super.onResume();
+        mHandler.post(new Runnable() {
+
+            @Override
+            public void run() {
+                Intent intent = new Intent(TASKSWITCHING_INTENT);
+                sendBroadcast(intent);
+            }
+        });
+    }
+}
diff --git a/suite/pts/hostTests/uihost/appB/Android.mk b/suite/pts/hostTests/uihost/appB/Android.mk
new file mode 100644
index 0000000..caa1090
--- /dev/null
+++ b/suite/pts/hostTests/uihost/appB/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := ptsutil ctsutil ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := PtsDeviceTaskswitchingAppB
+
+LOCAL_SDK_VERSION := 16
+
+include $(BUILD_PTS_PACKAGE)
+
+
diff --git a/suite/pts/hostTests/uihost/appB/AndroidManifest.xml b/suite/pts/hostTests/uihost/appB/AndroidManifest.xml
new file mode 100644
index 0000000..d0ec4d7
--- /dev/null
+++ b/suite/pts/hostTests/uihost/appB/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.pts.taskswitching.appb">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
+    <application>
+        <activity
+                android:name=".AppBActivity"
+                android:screenOrientation="portrait"
+                android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/suite/pts/hostTests/uihost/appB/src/com/android/pts/taskswitching/appb/AppBActivity.java b/suite/pts/hostTests/uihost/appB/src/com/android/pts/taskswitching/appb/AppBActivity.java
new file mode 100644
index 0000000..22ebdac
--- /dev/null
+++ b/suite/pts/hostTests/uihost/appB/src/com/android/pts/taskswitching/appb/AppBActivity.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 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.pts.taskswitching.appb;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.WindowManager;
+import android.widget.AbsListView;
+import android.widget.AbsListView.OnScrollListener;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+/**
+ * Simple activity to notify completion via broadcast after onResume.
+ * This is for measuring taskswitching time between two apps.
+ */
+public class AppBActivity extends ListActivity {
+    static final String TAG = "AppBActivity";
+    private static final int NUMBER_ELEMENTS = 1000;
+    private static final String TASKSWITCHING_INTENT = "com.android.pts.taskswitching.appb";
+    private Handler mHandler;
+
+    private String[] mItems = new String[NUMBER_ELEMENTS];
+
+    public void onCreate(Bundle icicle)
+    {
+        super.onCreate(icicle);
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+        for (int i = 0; i < NUMBER_ELEMENTS; i++) {
+            mItems[i] = "B" + Integer.toString(i);
+        }
+        setListAdapter(new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, mItems));
+        ListView view = getListView();
+        mHandler = new Handler();
+    }
+
+    public void onResume()
+    {
+        super.onResume();
+        mHandler.post(new Runnable() {
+
+            @Override
+            public void run() {
+                Intent intent = new Intent(TASKSWITCHING_INTENT);
+                sendBroadcast(intent);
+            }
+        });
+    }
+}
diff --git a/suite/pts/hostTests/uihost/control/Android.mk b/suite/pts/hostTests/uihost/control/Android.mk
new file mode 100644
index 0000000..86ceb7c
--- /dev/null
+++ b/suite/pts/hostTests/uihost/control/Android.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := ptsutil ctsutil ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := PtsDeviceTaskswitchingControl
+
+LOCAL_SDK_VERSION := 16
+
+include $(BUILD_PTS_PACKAGE)
diff --git a/suite/pts/hostTests/uihost/control/AndroidManifest.xml b/suite/pts/hostTests/uihost/control/AndroidManifest.xml
new file mode 100644
index 0000000..a7ab928
--- /dev/null
+++ b/suite/pts/hostTests/uihost/control/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.pts.taskswitching.control">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+    <instrumentation
+        android:targetPackage="com.android.pts.taskswitching.control"
+        android:name="android.test.InstrumentationCtsTestRunner" />
+</manifest>
diff --git a/suite/pts/hostTests/uihost/control/src/com/android/pts/taskswitching/control/TaskswitchingDeviceTest.java b/suite/pts/hostTests/uihost/control/src/com/android/pts/taskswitching/control/TaskswitchingDeviceTest.java
new file mode 100644
index 0000000..fc5bc04
--- /dev/null
+++ b/suite/pts/hostTests/uihost/control/src/com/android/pts/taskswitching/control/TaskswitchingDeviceTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2012 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.pts.taskswitching.control;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+import com.android.pts.util.MeasureRun;
+import com.android.pts.util.MeasureTime;
+import com.android.pts.util.PtsAndroidTestCase;
+import com.android.pts.util.Stat;
+
+
+/**
+ * Device test which actually launches two apps sequentially and
+ * measure time for switching.
+ * Completion of launch is notified via broadcast.
+ */
+public class TaskswitchingDeviceTest extends PtsAndroidTestCase {
+    private static final String PKG_A = "com.android.pts.taskswitching.appa";
+    private static final String PKG_B = "com.android.pts.taskswitching.appb";
+    private static final String ACTIVITY_A = "AppAActivity";
+    private static final String ACTIVITY_B = "AppBActivity";
+    private static final long TASK_SWITCHING_WAIT_TIME = 5;
+    private final AppBroadcastReceiver mReceiverA = new AppBroadcastReceiver();
+    private final AppBroadcastReceiver mReceiverB = new AppBroadcastReceiver();
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        startActivity(PKG_A, ACTIVITY_A);
+        startActivity(PKG_B, ACTIVITY_B);
+        IntentFilter filterA = new IntentFilter();
+        filterA.addAction(PKG_A);
+        IntentFilter filterB = new IntentFilter();
+        filterB.addAction(PKG_B);
+        getContext().registerReceiver(mReceiverA, filterA);
+        getContext().registerReceiver(mReceiverB, filterB);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        getContext().unregisterReceiver(mReceiverA);
+        getContext().unregisterReceiver(mReceiverB);
+        super.tearDown();
+    }
+
+    public void testMeasureTaskSwitching() throws Exception {
+        final int NUMBER_REPEAT = 10;
+        final int SWITCHING_PER_ONE_TRY = 10;
+
+        double[] results = MeasureTime.measure(NUMBER_REPEAT, new MeasureRun() {
+
+            @Override
+            public void run(int i) throws Exception {
+                for (int j = 0; j < SWITCHING_PER_ONE_TRY; j++) {
+                    startActivity(PKG_A, ACTIVITY_A);
+                    assertTrue(mReceiverA.waitForBroadcast(TASK_SWITCHING_WAIT_TIME));
+                    startActivity(PKG_B, ACTIVITY_B);
+                    assertTrue(mReceiverB.waitForBroadcast(TASK_SWITCHING_WAIT_TIME));
+                }
+            }
+        });
+        getReportLog().printArray("ms", results, false);
+        Stat.StatResult stat = Stat.getStat(results);
+        getReportLog().printSummary("Time ms", stat.mAverage, stat.mStddev);
+    }
+
+    private void startActivity(String packageName, String activityName) {
+        Context context = getContext();
+        Intent intent = new Intent();
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.addCategory(Intent.CATEGORY_LAUNCHER);
+        intent.setComponent(new ComponentName(packageName, packageName + "." + activityName));
+        context.startActivity(intent);
+    }
+
+    class AppBroadcastReceiver extends BroadcastReceiver {
+        private final Semaphore mSemaphore = new Semaphore(0);
+
+        public boolean waitForBroadcast(long timeoutInSec) throws InterruptedException {
+            return mSemaphore.tryAcquire(timeoutInSec, TimeUnit.SECONDS);
+        }
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            mSemaphore.release();
+        }
+    }
+}
diff --git a/suite/pts/hostTests/uihost/src/com/android/pts/uihost/InstallTimeTest.java b/suite/pts/hostTests/uihost/src/com/android/pts/uihost/InstallTimeTest.java
new file mode 100644
index 0000000..4bfcde1
--- /dev/null
+++ b/suite/pts/hostTests/uihost/src/com/android/pts/uihost/InstallTimeTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2012 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.pts.uihost;
+
+import android.cts.util.TimeoutReq;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.pts.util.MeasureRun;
+import com.android.pts.util.MeasureTime;
+import com.android.pts.util.PtsException;
+import com.android.pts.util.ReportLog;
+import com.android.pts.util.Stat;
+import com.android.pts.util.Stat.StatResult;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.device.TestDeviceOptions;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.File;
+import java.util.Map;
+
+/**
+ * Test to measure installation time of a APK.
+ */
+public class InstallTimeTest extends DeviceTestCase implements IBuildReceiver {
+    private static final String TAG = "InstallTimeTest";
+    private final static String CTS_RUNNER = "android.test.InstrumentationCtsTestRunner";
+    private CtsBuildHelper mBuild;
+    private ITestDevice mDevice;
+    private ReportLog mReport = null;
+
+    static final String PACKAGE = "com.replica.replicaisland";
+    static final String APK = "com.replica.replicaisland.apk";
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mReport = new ReportLog();
+        mDevice = getDevice();
+    }
+
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        mDevice.uninstallPackage(PACKAGE);
+        mReport.throwReportToHost();
+    }
+
+    public void testInstallTime() throws Exception {
+        final int NUMBER_REPEAT = 10;
+        final CtsBuildHelper build = mBuild;
+        final ITestDevice device = mDevice;
+        double[] result = MeasureTime.measure(NUMBER_REPEAT, new MeasureRun() {
+            @Override
+            public void prepare(int i) throws Exception {
+                device.uninstallPackage(PACKAGE);
+            }
+            @Override
+            public void run(int i) throws Exception {
+                File app = build.getTestApp(APK);
+                device.installPackage(app, false);
+            }
+        });
+        mReport.printArray("time in ms", result, false);
+        StatResult stat = Stat.getStat(result);
+        mReport.printSummary("time in ms", stat.mAverage, stat.mStddev);
+    }
+
+}
diff --git a/suite/pts/hostTests/uihost/src/com/android/pts/uihost/TaskSwitchingTest.java b/suite/pts/hostTests/uihost/src/com/android/pts/uihost/TaskSwitchingTest.java
new file mode 100644
index 0000000..49d14a3
--- /dev/null
+++ b/suite/pts/hostTests/uihost/src/com/android/pts/uihost/TaskSwitchingTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2012 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.pts.uihost;
+
+import android.cts.util.TimeoutReq;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.pts.util.MeasureRun;
+import com.android.pts.util.MeasureTime;
+import com.android.pts.util.PtsException;
+import com.android.pts.util.Stat;
+import com.android.pts.util.Stat.StatResult;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.device.TestDeviceOptions;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.File;
+import java.util.Map;
+
+/**
+ * Measure time to taskswitching between two Apps: A & B
+ * Actual test is done in device, but this host side code installs all necessary APKs
+ * and starts device test which is in PtsDeviceTaskswitchingControl.
+ */
+public class TaskSwitchingTest extends DeviceTestCase implements IBuildReceiver {
+    private static final String TAG = "TaskSwitchingTest";
+    private final static String CTS_RUNNER = "android.test.InstrumentationCtsTestRunner";
+    private CtsBuildHelper mBuild;
+    private ITestDevice mDevice;
+
+    static final String[] PACKAGES = {
+        "com.android.pts.taskswitching.control",
+        "com.android.pts.taskswitching.appa",
+        "com.android.pts.taskswitching.appb"
+    };
+    static final String[] APKS = {
+        "PtsDeviceTaskswitchingControl.apk",
+        "PtsDeviceTaskswitchingAppA.apk",
+        "PtsDeviceTaskswitchingAppB.apk"
+    };
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mDevice = getDevice();
+        for (int i = 0; i < PACKAGES.length; i++) {
+            mDevice.uninstallPackage(PACKAGES[i]);
+            File app = mBuild.getTestApp(APKS[i]);
+            mDevice.installPackage(app, false);
+        }
+    }
+
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        for (int i = 0; i < PACKAGES.length; i++) {
+            mDevice.uninstallPackage(PACKAGES[i]);
+        }
+    }
+
+    @TimeoutReq(minutes = 30)
+    public void testTaskswitching() throws Exception {
+        RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(PACKAGES[0], CTS_RUNNER,
+                mDevice.getIDevice());
+        CollectingTestListener listener = new CollectingTestListener();
+        mDevice.runInstrumentationTests(testRunner, listener);
+        TestRunResult result = listener.getCurrentRunResults();
+        if (result.isRunFailure()) {
+            fail(result.getRunFailureMessage());
+        }
+        Map<TestIdentifier, TestResult> details = result.getTestResults();
+        final String expectedException = "com.android.pts.util.PtsException";
+        for (Map.Entry<TestIdentifier, TestResult> entry : details.entrySet()) {
+            TestResult res = entry.getValue();
+            String stackTrace = res.getStackTrace();
+            if (stackTrace != null) {
+                if (stackTrace.startsWith(expectedException)) {
+                    String[] lines = stackTrace.split("[\r\n]+");
+                    String msg = lines[0].substring(expectedException.length() + 1).trim();
+                    throw new PtsException(msg);
+                }
+            }
+        }
+        fail("no performance data");
+    }
+
+}