Merge "Updating the parsing to reflect media recorder stress test refactor."
diff --git a/Android.mk b/Android.mk
index d17703f..cb142aa 100644
--- a/Android.mk
+++ b/Android.mk
@@ -71,7 +71,7 @@
 tradefed_dist_host_exes := tradefed.sh
 tradefed_dist_host_exe_files := $(foreach m, $(tradefed_dist_host_exes), $(BUILD_OUT_EXECUTABLES)/$(m))
 
-tradefed_dist_test_apks := TradeFedUiTestApp TradeFedTestApp DismissKeyguardUtil
+tradefed_dist_test_apks := TradeFedUiTestApp TradeFedTestApp DeviceSetupUtil
 tradefed_dist_test_apk_files := $(foreach m, $(tradefed_dist_test_apks), $(TARGET_OUT_DATA_APPS)/$(m).apk)
 
 tradefed_dist_files := \
diff --git a/prod-tests/src/com/android/framework/tests/PackageManagerOTATestUtils.java b/prod-tests/src/com/android/framework/tests/PackageManagerOTATestUtils.java
index 293f3d2..32e7380 100644
--- a/prod-tests/src/com/android/framework/tests/PackageManagerOTATestUtils.java
+++ b/prod-tests/src/com/android/framework/tests/PackageManagerOTATestUtils.java
@@ -239,12 +239,15 @@
     }
 
     /**
-     * Helper method to start system shell.
+     * Helper method to start system shell. It also reset the flag dev.bootcomplete to 0 to ensure
+     * that the package manager had a chance to finish.
      *
      * @throws DeviceNotAvailableException
      */
     public void startSystem() throws DeviceNotAvailableException {
+        mDevice.executeShellCommand("setprop dev.bootcomplete 0");
         mDevice.executeShellCommand("start");
+        mDevice.waitForDeviceAvailable();
     }
 
     /**
diff --git a/prod-tests/src/com/android/framework/tests/PackageManagerOTATests.java b/prod-tests/src/com/android/framework/tests/PackageManagerOTATests.java
index 1f8e07d..08e3142 100644
--- a/prod-tests/src/com/android/framework/tests/PackageManagerOTATests.java
+++ b/prod-tests/src/com/android/framework/tests/PackageManagerOTATests.java
@@ -295,7 +295,7 @@
         assertTrue("ACCESS_CACHE_FILESYSTEM permission should be granted",
                 mUtils.packageHasPermission(PACKAGE_NAME, CACHE_PERMISSION));
 
-        // The "=d" command forces a downgrade.
+        // The "-d" command forces a downgrade.
         mUtils.installFile(getTestAppFilePath(VERSION_1_APK), true, "-d");
         mPackageXml = mUtils.pullPackagesXML();
         assertFalse("After system app upgrade, the path should be the upgraded app on /data",
diff --git a/prod-tests/src/com/android/media/tests/CameraZoomTest.java b/prod-tests/src/com/android/media/tests/CameraSettingsTest.java
similarity index 87%
rename from prod-tests/src/com/android/media/tests/CameraZoomTest.java
rename to prod-tests/src/com/android/media/tests/CameraSettingsTest.java
index 5a480b8..5dacc94 100644
--- a/prod-tests/src/com/android/media/tests/CameraZoomTest.java
+++ b/prod-tests/src/com/android/media/tests/CameraSettingsTest.java
@@ -19,6 +19,7 @@
 import com.android.ddmlib.IDevice;
 import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.tradefed.config.Option;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
@@ -46,9 +47,10 @@
  * Camera zoom stress test that increments the camera's zoom level across the
  * entire range [min, max], taking a picture at each level.
  */
-public class CameraZoomTest implements IDeviceTest, IRemoteTest {
+public class CameraSettingsTest implements IDeviceTest, IRemoteTest {
 
-    private static final String ZOOM_STANZA = "Camera zoom stress:";
+    private static final String ZOOM_STANZA = "testStressCameraZoom:";
+    private static final String SCENE_MODES_STANZA = "testStressCameraSceneModes:";
     private static final Pattern EXPECTED_LOOP_COUNT_PATTERN =
             Pattern.compile("(Total number of loops:)(\\s*)(\\d+)");
     private static final Pattern ACTUAL_LOOP_COUNT_PATTERN =
@@ -56,13 +58,16 @@
 
     private static final String TEST_CLASS_NAME =
             "com.android.mediaframeworktest.stress.CameraStressTest";
-    private static final String TEST_METHOD_NAME = "testStressCameraZoom";
     private static final String TEST_PACKAGE_NAME = "com.android.mediaframeworktest";
     private static final String TEST_RUNNER_NAME =
             "com.android.mediaframeworktest.CameraStressTestRunner";
     private static final String TEST_RU = "CameraApplicationStress";
 
     private final String mOutputPath = "cameraStressOutput.txt";
+
+    @Option(name="testMethodName", description="Used to specify a specific test method to run")
+    private String mTestMethodName = null;
+
     ITestDevice mTestDevice = null;
 
     /**
@@ -75,7 +80,10 @@
         IRemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(TEST_PACKAGE_NAME,
                 TEST_RUNNER_NAME, mTestDevice.getIDevice());
         runner.setClassName(TEST_CLASS_NAME);
-        runner.setMethodName(TEST_CLASS_NAME, TEST_METHOD_NAME);
+
+        if (mTestMethodName != null) {
+            runner.setMethodName(TEST_CLASS_NAME, mTestMethodName);
+        }
 
         BugreportCollector bugListener = new BugreportCollector(listener, mTestDevice);
         bugListener.addPredicate(BugreportCollector.AFTER_FAILED_TESTCASES);
@@ -163,29 +171,34 @@
 
         while (listIterator.hasNext()) {
             line = listIterator.next();
+            CLog.d(String.format("Parsing line: \"%s\"", line));
 
             if (ZOOM_STANZA.equals(line)) {
                 key = "CameraZoom";
+            } else if (SCENE_MODES_STANZA.equals(line)) {
+                key = "CameraSceneMode";
             }
 
             Matcher expectedMatcher = EXPECTED_LOOP_COUNT_PATTERN.matcher(line);
             if (expectedMatcher.matches()) {
                 expectedCount = new Integer(expectedMatcher.group(3));
+                CLog.d(String.format("Found expected count for key \"%s\": %s",
+                        key, expectedCount));
             }
 
             Matcher actualMatcher = ACTUAL_LOOP_COUNT_PATTERN.matcher(line);
             if (actualMatcher.matches()) {
                 actualCount = new Integer(actualMatcher.group(3));
+                CLog.d(String.format("Found actual count for key \"%s\": %s", key, actualCount));
             }
 
             if ((key != null) && (expectedCount != null) && (actualCount != null)) {
-                metrics.put(key, String.format("%d",
-                        coalesceLoopCounts(expectedCount, actualCount)));
-
-                key = null;
-                expectedCount = null;
-                actualCount = null;
+                metrics.put(key, String.format("%d", actualCount));
             }
+
+            key = null;
+            expectedCount = null;
+            actualCount = null;
         }
 
         return metrics;
@@ -208,18 +221,4 @@
         listener.testRunStarted(runName, 0);
         listener.testRunEnded(0, metrics);
     }
-
-    /**
-     * Given an actual and an expected iteration count, determine a single
-     * metric to report.
-     */
-    private int coalesceLoopCounts(Integer actual, Integer expected) {
-        if (expected == null || expected <= 0) {
-            return -1;
-        } else if (actual == null) {
-            return 0;
-        } else {
-            return actual;
-        }
-    }
 }
diff --git a/src/com/android/tradefed/build/DeviceBuildDescriptor.java b/src/com/android/tradefed/build/DeviceBuildDescriptor.java
index fffc021..dd4ffb9 100644
--- a/src/com/android/tradefed/build/DeviceBuildDescriptor.java
+++ b/src/com/android/tradefed/build/DeviceBuildDescriptor.java
@@ -56,8 +56,8 @@
     }
 
     /**
-     * Gets the device build alias. Maps to the {@link ITestDevice#DISPLAYED_BUILD_ID_PROP}
-     * property on device. Typically follows format IMM76.
+     * Gets the device build alias. Maps to the ro.build.id property on device. Typically follows
+     * format IMM76.
      */
     public String getDeviceBuildAlias() {
         return mBuild.getBuildAttributes().get(DEVICE_BUILD_ALIAS);
@@ -86,8 +86,7 @@
     public static void injectDeviceAttributes(ITestDevice device, IBuildInfo b)
             throws DeviceNotAvailableException {
         b.addBuildAttribute(DEVICE_BUILD_ID, device.getBuildId());
-        b.addBuildAttribute(DEVICE_BUILD_ALIAS, device.getProperty(
-                ITestDevice.DISPLAYED_BUILD_ID_PROP));
+        b.addBuildAttribute(DEVICE_BUILD_ALIAS, device.getProperty("ro.build.id"));
         b.addBuildAttribute(DEVICE_PRODUCT, device.getProperty("ro.product.name"));
         b.addBuildAttribute(DEVICE_BUILD_TYPE, device.getProperty("ro.build.type"));
     }
diff --git a/src/com/android/tradefed/device/DeviceManager.java b/src/com/android/tradefed/device/DeviceManager.java
index d8b08f8..34a2320 100644
--- a/src/com/android/tradefed/device/DeviceManager.java
+++ b/src/com/android/tradefed/device/DeviceManager.java
@@ -932,7 +932,7 @@
                     deviceState,
                     getDisplay(selector.getDeviceProductType(device)),
                     getDisplay(selector.getDeviceProductVariant(device)),
-                    getDisplay(device.getProperty(ITestDevice.DISPLAYED_BUILD_ID_PROP)),
+                    getDisplay(device.getProperty("ro.build.id")),
                     getDisplay(selector.getBatteryLevel(device)))
             );
         }
diff --git a/src/com/android/tradefed/device/ITestDevice.java b/src/com/android/tradefed/device/ITestDevice.java
index 0748f4d..0f40802 100644
--- a/src/com/android/tradefed/device/ITestDevice.java
+++ b/src/com/android/tradefed/device/ITestDevice.java
@@ -52,13 +52,6 @@
     }
 
     /**
-     * The property name of the device's 'displayed' build ID. This is typically a more
-     * user-friendly presentation than {@link ITestDevice#getBuildId()} which for Nexus devices is
-     * typically an integer.
-     */
-    public static final String DISPLAYED_BUILD_ID_PROP = "ro.build.display.id";
-
-    /**
      * A simple struct class to store information about a single mountpoint
      */
     public static class MountPointInfo {
diff --git a/src/com/android/tradefed/targetprep/AppSetup.java b/src/com/android/tradefed/targetprep/AppSetup.java
index 75c32fb..160b16d 100644
--- a/src/com/android/tradefed/targetprep/AppSetup.java
+++ b/src/com/android/tradefed/targetprep/AppSetup.java
@@ -33,7 +33,7 @@
 @OptionClass(alias="app-setup")
 public class AppSetup implements ITargetPreparer, ITargetCleaner {
 
-    @Option(name = "reboot", description = "reboot device during setup.")
+    @Option(name="reboot", description="reboot device after running tests.")
     private boolean mReboot = true;
 
     @Option(name = "install", description = "install all apks in build.")
@@ -58,11 +58,6 @@
         IAppBuildInfo appBuild = (IAppBuildInfo)buildInfo;
         CLog.i("Performing setup on %s", device.getSerialNumber());
 
-        if (mReboot) {
-            // reboot device to get a clean state
-            device.reboot();
-        }
-
         if (mInstall) {
             for (VersionedFile apkFile : appBuild.getAppPackageFiles()) {
                 String result = device.installPackage(apkFile.getFile(), true);
@@ -81,6 +76,10 @@
     @Override
     public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e)
             throws DeviceNotAvailableException {
+        // reboot device before uninstalling apps, in case device is wedged
+        if (mReboot) {
+            device.reboot();
+        }
         if (mUninstall) {
             Set<String> pkgs = device.getInstalledNonSystemPackageNames();
             for (String pkg : pkgs) {
diff --git a/src/com/android/tradefed/targetprep/TestSystemAppInstallSetup.java b/src/com/android/tradefed/targetprep/TestSystemAppInstallSetup.java
new file mode 100644
index 0000000..3acfd93
--- /dev/null
+++ b/src/com/android/tradefed/targetprep/TestSystemAppInstallSetup.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tradefed.targetprep;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.build.IDeviceBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.Option.Importance;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.device.ITestDevice.RecoveryMode;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.util.FileUtil;
+
+/**
+ * A {@link ITargetPreparer} that installs one or more apps from a
+ * {@link IDeviceBuildInfo#getTestsDir()} folder onto the /system partition on
+ * device.
+ * <p/>
+ * Requires adb root
+ */
+@OptionClass(alias = "tests-system-app")
+public class TestSystemAppInstallSetup implements ITargetPreparer {
+
+    @Option(name = "system-file-name", description =
+        "the name of a test zip file to install on device system partition. Can be repeated.",
+        importance = Importance.IF_UNSET)
+    private Collection<String> mTestFileNames = new ArrayList<String>();
+
+    /**
+     * Adds a file to the list of apks to install
+     *
+     * @param fileName
+     */
+    public void addTestFileName(String fileName) {
+        mTestFileNames.add(fileName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+            DeviceNotAvailableException {
+        if (!(buildInfo instanceof IDeviceBuildInfo)) {
+            throw new IllegalArgumentException(String.format("Provided buildInfo is not a %s",
+                    IDeviceBuildInfo.class.getCanonicalName()));
+        }
+        if (mTestFileNames.size() == 0) {
+            CLog.i("No test apps to install, skipping");
+            return;
+        }
+        File testsDir = ((IDeviceBuildInfo)buildInfo).getTestsDir();
+        if (testsDir == null || !testsDir.exists()) {
+            throw new TargetSetupError(
+                    "Provided buildInfo does not contain a valid tests directory");
+        }
+        device.enableAdbRoot();
+        device.setRecoveryMode(RecoveryMode.ONLINE);
+        device.executeAdbCommand("remount");
+        device.executeShellCommand("stop");
+
+        for (String testAppName : mTestFileNames) {
+            File testAppFile = FileUtil.getFileForPath(testsDir, "DATA", "app", testAppName);
+            if (!testAppFile.exists()) {
+                throw new TargetSetupError(
+                    String.format("Could not find test app %s directory in extracted tests.zip",
+                            testAppFile));
+            }
+            device.pushFile(testAppFile,  String.format("/system/app/%s", testAppName));
+        }
+        device.setRecoveryMode(RecoveryMode.AVAILABLE);
+        device.executeShellCommand("start");
+        device.waitForDeviceAvailable();
+    }
+}
diff --git a/tests/src/com/android/tradefed/device/TestDeviceStressTest.java b/tests/src/com/android/tradefed/device/TestDeviceStressTest.java
index fabb239..e233ebc 100644
--- a/tests/src/com/android/tradefed/device/TestDeviceStressTest.java
+++ b/tests/src/com/android/tradefed/device/TestDeviceStressTest.java
@@ -38,6 +38,10 @@
     @Option(name = "iterations", description = "number of iterations to test")
     private int mIterations = 50;
 
+    @Option(name = "stop-on-failure", description =
+            "stops the rest of the iteration on a failure")
+    private boolean mStopOnFailure = true;
+
     private static final String LOG_TAG = "TestDeviceStressTest";
     private static final int TEST_FILE_COUNT= 200;
     private TestDevice mTestDevice;
@@ -84,11 +88,19 @@
     }
 
     public void testManyDisableKeyguard() throws DeviceNotAvailableException {
+        int passed = 0;
+        boolean iterationPassed;
         for (int i=0; i < mIterations; i++) {
             Log.i(LOG_TAG, String.format("testDisableKeyguard attempt %d", i));
             mTestDevice.reboot();
-            assertTrue(runUITests());
+            iterationPassed = runUITests();
+            if (mStopOnFailure){
+                assertTrue(iterationPassed);
+            } else {
+                passed += iterationPassed? 1 : 0;
+            }
         }
+        assertEquals(mIterations, passed);
     }
 
     /**
diff --git a/tests/src/com/android/tradefed/targetprep/DeviceSetupTest.java b/tests/src/com/android/tradefed/targetprep/DeviceSetupTest.java
index 823d511..3fdb381 100644
--- a/tests/src/com/android/tradefed/targetprep/DeviceSetupTest.java
+++ b/tests/src/com/android/tradefed/targetprep/DeviceSetupTest.java
@@ -90,8 +90,7 @@
         // expect a bunch of shell commands - no need to verify which ones
         EasyMock.expect(mMockDevice.executeShellCommand((String)EasyMock.anyObject())).
                 andReturn("").anyTimes();
-        EasyMock.expect(mMockDevice.getProperty(ITestDevice.DISPLAYED_BUILD_ID_PROP)).andReturn(
-                "IMM76K");
+        EasyMock.expect(mMockDevice.getProperty("ro.build.id")).andReturn("IMM76K");
     }
 
     /**
diff --git a/tradefed.sh b/tradefed.sh
index 938c5c9..a7cfd05 100755
--- a/tradefed.sh
+++ b/tradefed.sh
@@ -79,5 +79,5 @@
 
 
 # Note: must leave ${RDBG_FLAG} unquoted so that it goes away when unset
-java ${RDBG_FLAG} \
+java ${RDBG_FLAG} -XX:+HeapDumpOnOutOfMemoryError \
   -cp "${ddmlib_path}:${tf_path}" com.android.tradefed.command.Console "$@"
diff --git a/util-apps/DismissKeyguardUtil/Android.mk b/util-apps/DeviceSetupUtil/Android.mk
similarity index 94%
rename from util-apps/DismissKeyguardUtil/Android.mk
rename to util-apps/DeviceSetupUtil/Android.mk
index fff2c7c..79b6a4c 100644
--- a/util-apps/DismissKeyguardUtil/Android.mk
+++ b/util-apps/DeviceSetupUtil/Android.mk
@@ -20,7 +20,7 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_SDK_VERSION := 8
-LOCAL_PACKAGE_NAME := DismissKeyguardUtil
+LOCAL_PACKAGE_NAME := DeviceSetupUtil
 
 include $(BUILD_PACKAGE)
 
diff --git a/util-apps/DismissKeyguardUtil/AndroidManifest.xml b/util-apps/DeviceSetupUtil/AndroidManifest.xml
similarity index 68%
rename from util-apps/DismissKeyguardUtil/AndroidManifest.xml
rename to util-apps/DeviceSetupUtil/AndroidManifest.xml
index 4620642..69123f6 100644
--- a/util-apps/DismissKeyguardUtil/AndroidManifest.xml
+++ b/util-apps/DeviceSetupUtil/AndroidManifest.xml
@@ -19,15 +19,21 @@
     package="com.android.tradefed.utils" >
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
 
     <application>
-        <receiver android:name="com.android.tradefed.utils.DismissKeyguardIntentReceiver" >
+        <receiver android:name="com.android.tradefed.utils.DeviceSetupIntentReceiver" >
             <intent-filter>
-                <action android:name="com.android.tradefed.utils.DISMISS_KEYGUARD" />
+                <action android:name="com.android.tradefed.utils.DEVICE_SETUP" />
+                <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
+                <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
+                <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
+                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
             </intent-filter>
         </receiver>
 
-        <service android:name="com.android.tradefed.utils.DismissKeyguardService" />
+        <service android:name="com.android.tradefed.utils.DeviceSetupService" />
 
         <activity
             android:name="com.android.tradefed.utils.MainActivity"
diff --git a/util-apps/DismissKeyguardUtil/res/layout/activity_main.xml b/util-apps/DeviceSetupUtil/res/layout/activity_main.xml
similarity index 100%
rename from util-apps/DismissKeyguardUtil/res/layout/activity_main.xml
rename to util-apps/DeviceSetupUtil/res/layout/activity_main.xml
diff --git a/util-apps/DismissKeyguardUtil/res/values/strings.xml b/util-apps/DeviceSetupUtil/res/values/strings.xml
similarity index 100%
rename from util-apps/DismissKeyguardUtil/res/values/strings.xml
rename to util-apps/DeviceSetupUtil/res/values/strings.xml
diff --git a/util-apps/DeviceSetupUtil/src/com/android/tradefed/utils/DeviceSetupIntentReceiver.java b/util-apps/DeviceSetupUtil/src/com/android/tradefed/utils/DeviceSetupIntentReceiver.java
new file mode 100644
index 0000000..7ba84a6
--- /dev/null
+++ b/util-apps/DeviceSetupUtil/src/com/android/tradefed/utils/DeviceSetupIntentReceiver.java
@@ -0,0 +1,57 @@
+/*
+ * 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.tradefed.utils;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+/**
+ * A BroadcastReceiver that starts a service to dismiss the keyguard.
+ *
+ * adb shell am broadcast -a com.android.tradefed.actor.DEVICE_SETUP
+ */
+public class DeviceSetupIntentReceiver extends BroadcastReceiver {
+
+    public static final String
+            DEVICE_SETUP_INTENT = "com.android.tradefed.utils.DEVICE_SETUP";
+    public static final String TAG = "DeviceSetupUtil";
+    private final Intent intent = new Intent();
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (DEVICE_SETUP_INTENT.equals(intent.getAction())) {
+            Log.v(TAG, "Starting Service");
+            intent.setClass(context, DeviceSetupService.class);
+            context.startService(intent);
+        } else if (Intent.ACTION_POWER_DISCONNECTED.equals(intent.getAction())) {
+            // when power is disconnected assume the usb is disconnect,
+            // stop the service from holding the wake lock
+            Log.v(TAG, "Stopping Service");
+            intent.setClass(context, DeviceSetupService.class);
+            context.stopService(intent);
+        } else if (Intent.ACTION_POWER_CONNECTED.equals(intent.getAction())) {
+            // when power is connected assume the usb is connected,
+            // restart the service to acquire the wake lock
+            Log.v(TAG, "Re-starting Service");
+            intent.setClass(context, DeviceSetupService.class);
+            context.startService(intent);
+        }
+        Log.v(TAG, "Recevied: " + intent.getAction());
+    }
+}
diff --git a/util-apps/DeviceSetupUtil/src/com/android/tradefed/utils/DeviceSetupService.java b/util-apps/DeviceSetupUtil/src/com/android/tradefed/utils/DeviceSetupService.java
new file mode 100644
index 0000000..14e72bd
--- /dev/null
+++ b/util-apps/DeviceSetupUtil/src/com/android/tradefed/utils/DeviceSetupService.java
@@ -0,0 +1,77 @@
+/*
+ * 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.tradefed.utils;
+
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.app.KeyguardManager.KeyguardLock;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.util.Log;
+
+/**
+ * A service that sets up the device for testing by dismissing the keyguard
+ * and keep the screen on.
+ */
+public class DeviceSetupService extends Service {
+    PowerManager.WakeLock wl;
+
+    private static final int SCREEN_OFF_TIMEOUT = -1; //never timeout
+
+    @Override
+    public void onCreate() {
+        Log.v(DeviceSetupIntentReceiver.TAG, "Setup service started.");
+        // dismiss keyguard
+        KeyguardManager keyguardManager = (KeyguardManager) getSystemService(
+                Activity.KEYGUARD_SERVICE);
+        KeyguardLock lock = keyguardManager.newKeyguardLock(KEYGUARD_SERVICE);
+        lock.disableKeyguard();
+
+        // change screen off timeout
+        Settings.System.putInt(
+                getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, SCREEN_OFF_TIMEOUT);
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        // keep screen on
+        Log.v(DeviceSetupIntentReceiver.TAG, "Acquiring wake lock.");
+        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+        wl = pm.newWakeLock(
+                PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
+                DeviceSetupIntentReceiver.TAG);
+        wl.acquire();
+        return START_STICKY;
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public void onDestroy() {
+        if (wl != null){
+            wl.release();
+        }
+        Log.v(DeviceSetupIntentReceiver.TAG, "Setup service stopped.");
+    }
+}
diff --git a/util-apps/DismissKeyguardUtil/src/com/android/tradefed/utils/MainActivity.java b/util-apps/DeviceSetupUtil/src/com/android/tradefed/utils/MainActivity.java
similarity index 100%
rename from util-apps/DismissKeyguardUtil/src/com/android/tradefed/utils/MainActivity.java
rename to util-apps/DeviceSetupUtil/src/com/android/tradefed/utils/MainActivity.java
diff --git a/util-apps/DismissKeyguardUtil/src/com/android/tradefed/utils/DismissKeyguardIntentReceiver.java b/util-apps/DismissKeyguardUtil/src/com/android/tradefed/utils/DismissKeyguardIntentReceiver.java
deleted file mode 100644
index 58cf9f4..0000000
--- a/util-apps/DismissKeyguardUtil/src/com/android/tradefed/utils/DismissKeyguardIntentReceiver.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.tradefed.utils;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-/**
- * A BroadcastReceiver that starts a service to dismiss the keyguard.
- *
- * adb shell am broadcast -a com.android.tradefed.actor.DISMISS_KEYGUARD
- */
-public class DismissKeyguardIntentReceiver extends BroadcastReceiver {
-
-    public static final String
-            DISMISS_KEYGUARD_INTENT = "com.android.tradefed.utils.DISMISS_KEYGUARD";
-    public static final String TAG = "DismissKeyguardUtil";
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        if (DISMISS_KEYGUARD_INTENT.equals(intent.getAction())) {
-            Log.v(TAG, "Starting Service");
-            Intent pushIntent = new Intent(context, DismissKeyguardService.class);
-            context.startService(pushIntent);
-        }
-    }
-}
diff --git a/util-apps/DismissKeyguardUtil/src/com/android/tradefed/utils/DismissKeyguardService.java b/util-apps/DismissKeyguardUtil/src/com/android/tradefed/utils/DismissKeyguardService.java
deleted file mode 100644
index 852b1e5..0000000
--- a/util-apps/DismissKeyguardUtil/src/com/android/tradefed/utils/DismissKeyguardService.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.tradefed.utils;
-
-import android.app.Activity;
-import android.app.KeyguardManager;
-import android.app.KeyguardManager.KeyguardLock;
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-import android.util.Log;
-
-/**
- * A service that dismisses the keyguard.
- */
-public class DismissKeyguardService extends Service {
-
-    @Override
-    public void onCreate() {
-        KeyguardManager keyguardManager = (KeyguardManager) getSystemService(
-                Activity.KEYGUARD_SERVICE);
-        KeyguardLock lock = keyguardManager.newKeyguardLock(KEYGUARD_SERVICE);
-        lock.disableKeyguard();
-        Log.v(DismissKeyguardIntentReceiver.TAG, "Keyguard disabled");
-        this.stopSelf();
-    }
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        return null;
-    }
-}