shell based UI Automator source move

frameworks/testing/uiautomator -> frameworks/base/cmds/uiautomator
  (samples, utils sub folders exlcuded)
frameworks/testing/uiautomator/utils -> frameworks/base/tests/utils

no source files changed, only one line makefile update (for
UI Automator API check)

Bug: 18708851
Change-Id: I396bd386d3d55a52df18af183685daf80caa9f73
diff --git a/tests/utils/Android.mk b/tests/utils/Android.mk
new file mode 100644
index 0000000..c141484
--- /dev/null
+++ b/tests/utils/Android.mk
@@ -0,0 +1,17 @@
+#
+# 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.
+#
+
+include $(call all-subdir-makefiles)
diff --git a/tests/utils/DummyIME/Android.mk b/tests/utils/DummyIME/Android.mk
new file mode 100644
index 0000000..c8d9f87
--- /dev/null
+++ b/tests/utils/DummyIME/Android.mk
@@ -0,0 +1,26 @@
+#
+# 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_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := DummyIME
+
+include $(BUILD_PACKAGE)
diff --git a/tests/utils/DummyIME/AndroidManifest.xml b/tests/utils/DummyIME/AndroidManifest.xml
new file mode 100644
index 0000000..fd17a52
--- /dev/null
+++ b/tests/utils/DummyIME/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<!--
+/*
+ * Copyright 2006, 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.testing.dummyime">
+    <application android:label="Dummy IME">
+        <service android:name="DummyIme"
+                android:permission="android.permission.BIND_INPUT_METHOD">
+            <intent-filter>
+                <action android:name="android.view.InputMethod" />
+            </intent-filter>
+            <meta-data android:name="android.view.im" android:resource="@xml/method" />
+        </service>
+        <activity android:name=".ImePreferences" android:label="Dummy IME Settings">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/utils/DummyIME/res/xml/method.xml b/tests/utils/DummyIME/res/xml/method.xml
new file mode 100644
index 0000000..43a330e
--- /dev/null
+++ b/tests/utils/DummyIME/res/xml/method.xml
@@ -0,0 +1,29 @@
+<?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.
+ */
+-->
+
+<!-- The attributes in this XML file provide configuration information -->
+<!-- for the Search Manager. -->
+
+<input-method xmlns:android="http://schemas.android.com/apk/res/android"
+        android:settingsActivity="com.android.testing.dummyime.ImePreferences">
+    <subtype
+        android:label="Generic"
+        android:imeSubtypeLocale="en_US"
+        android:imeSubtypeMode="keyboard" />
+</input-method>
\ No newline at end of file
diff --git a/tests/utils/DummyIME/src/com/android/testing/dummyime/DummyIme.java b/tests/utils/DummyIME/src/com/android/testing/dummyime/DummyIme.java
new file mode 100644
index 0000000..7b7a39a
--- /dev/null
+++ b/tests/utils/DummyIME/src/com/android/testing/dummyime/DummyIme.java
@@ -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.
+ */
+
+package com.android.testing.dummyime;
+
+import android.inputmethodservice.InputMethodService;
+
+/**
+ * Dummy IME implementation that basically does nothing
+ */
+public class DummyIme extends InputMethodService {
+
+    @Override
+    public boolean onEvaluateFullscreenMode() {
+        return false;
+    }
+
+    @Override
+    public boolean onEvaluateInputViewShown() {
+        return false;
+    }
+}
diff --git a/tests/utils/DummyIME/src/com/android/testing/dummyime/ImePreferences.java b/tests/utils/DummyIME/src/com/android/testing/dummyime/ImePreferences.java
new file mode 100644
index 0000000..41036ab
--- /dev/null
+++ b/tests/utils/DummyIME/src/com/android/testing/dummyime/ImePreferences.java
@@ -0,0 +1,26 @@
+/*
+ * 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.testing.dummyime;
+
+import android.preference.PreferenceActivity;
+
+/**
+ * Dummy IME preference activity
+ */
+public class ImePreferences extends PreferenceActivity {
+
+}
diff --git a/tests/utils/SleepUtils/AlarmService/Android.mk b/tests/utils/SleepUtils/AlarmService/Android.mk
new file mode 100644
index 0000000..9022f03
--- /dev/null
+++ b/tests/utils/SleepUtils/AlarmService/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2013 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_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES += \
+    src/com/android/testing/alarmservice/Alarm.aidl
+LOCAL_PACKAGE_NAME := SleepUtilsAlarmService
+LOCAL_SDK_VERSION := 7
+include $(BUILD_PACKAGE)
diff --git a/tests/utils/SleepUtils/AlarmService/AndroidManifest.xml b/tests/utils/SleepUtils/AlarmService/AndroidManifest.xml
new file mode 100644
index 0000000..1b6de39
--- /dev/null
+++ b/tests/utils/SleepUtils/AlarmService/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.testing.alarmservice" >
+
+    <uses-sdk android:minSdkVersion="7" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+
+    <application android:label="Sleep Utils Alarm Service">
+        <service android:name=".AlarmService"
+            android:label="Sleep Utils Alarm Service"
+            android:exported="true"
+            android:enabled="true">
+            <intent-filter>
+                <action android:name="com.android.testing.ALARM_SERVICE" />
+            </intent-filter>
+        </service>
+        <receiver android:name=".WakeUpCall">
+            <intent-filter>
+                <action android:name="com.android.testing.alarmservice.WAKEUP" />
+            </intent-filter>
+        </receiver>
+    </application>
+</manifest>
diff --git a/tests/utils/SleepUtils/AlarmService/src/com/android/testing/alarmservice/Alarm.aidl b/tests/utils/SleepUtils/AlarmService/src/com/android/testing/alarmservice/Alarm.aidl
new file mode 100644
index 0000000..62a8c48
--- /dev/null
+++ b/tests/utils/SleepUtils/AlarmService/src/com/android/testing/alarmservice/Alarm.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2013 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.testing.alarmservice;
+
+interface Alarm {
+    int prepare();
+    int setAlarmAndWait(long timeoutMills);
+    int done();
+}
\ No newline at end of file
diff --git a/tests/utils/SleepUtils/AlarmService/src/com/android/testing/alarmservice/AlarmImpl.java b/tests/utils/SleepUtils/AlarmService/src/com/android/testing/alarmservice/AlarmImpl.java
new file mode 100644
index 0000000..122d55d
--- /dev/null
+++ b/tests/utils/SleepUtils/AlarmService/src/com/android/testing/alarmservice/AlarmImpl.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 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.testing.alarmservice;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Log;
+
+import com.android.testing.alarmservice.Alarm.Stub;
+
+public class AlarmImpl extends Stub {
+
+    private static final String LOG_TAG = AlarmImpl.class.getSimpleName();
+
+    private Context mContext;
+
+    public AlarmImpl(Context context) {
+        super();
+        mContext = context;
+    }
+
+    @Override
+    public int prepare() throws RemoteException {
+        WakeUpController.getController().getWakeLock().acquire();
+        Log.d(LOG_TAG, "AlarmService prepared, wake lock acquired");
+        return 0;
+    }
+
+    @Override
+    public int setAlarmAndWait(long timeoutMills) throws RemoteException {
+        // calculate when device should be waken up
+        long atTime = SystemClock.elapsedRealtime() + timeoutMills;
+        AlarmManager am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+        Intent wakupIntent = new Intent(WakeUpCall.WAKEUP_CALL);
+        PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, wakupIntent, 0);
+        // set alarm, which will be delivered in form of the wakeupIntent
+        am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, atTime, pi);
+        Log.d(LOG_TAG, String.format("Alarm set: %d, giving up wake lock", atTime));
+        Object lock = WakeUpController.getController().getWakeSync();
+        // release wakelock and wait for the lock to be poked from the broadcast receiver
+        WakeUpController.getController().getWakeLock().release();
+        // does not really matter if device enters suspend before we start waiting on lock
+        synchronized (lock) {
+            try {
+                lock.wait();
+            } catch (InterruptedException e) {
+            }
+        }
+        Log.d(LOG_TAG, String.format("Alarm triggered, done waiting"));
+        return 0;
+    }
+
+    @Override
+    public int done() throws RemoteException {
+        WakeUpController.getController().getWakeLock().release();
+        return 0;
+    }
+
+}
diff --git a/tests/utils/SleepUtils/AlarmService/src/com/android/testing/alarmservice/AlarmService.java b/tests/utils/SleepUtils/AlarmService/src/com/android/testing/alarmservice/AlarmService.java
new file mode 100644
index 0000000..576a1cf
--- /dev/null
+++ b/tests/utils/SleepUtils/AlarmService/src/com/android/testing/alarmservice/AlarmService.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 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.testing.alarmservice;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class AlarmService extends Service {
+
+    private AlarmImpl mAlarmImpl = null;
+    static Context sContext;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        sContext = this;
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return getAlarmImpl();
+    }
+
+    private AlarmImpl getAlarmImpl() {
+        if (mAlarmImpl == null) {
+            mAlarmImpl = new AlarmImpl(this);
+        }
+        return mAlarmImpl;
+    }
+
+    @Override
+    public void onDestroy() {
+        sContext = null;
+        super.onDestroy();
+    }
+}
diff --git a/tests/utils/SleepUtils/AlarmService/src/com/android/testing/alarmservice/WakeUpCall.java b/tests/utils/SleepUtils/AlarmService/src/com/android/testing/alarmservice/WakeUpCall.java
new file mode 100644
index 0000000..f4bb4db
--- /dev/null
+++ b/tests/utils/SleepUtils/AlarmService/src/com/android/testing/alarmservice/WakeUpCall.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 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.testing.alarmservice;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * The receiver for the alarm we set
+ *
+ */
+public class WakeUpCall extends BroadcastReceiver {
+
+    public static final String WAKEUP_CALL = "com.android.testing.alarmservice.WAKEUP";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        // we acquire wakelock without release because user is supposed to manually release it
+        WakeUpController.getController().getWakeLock().acquire();
+        Object lock = WakeUpController.getController().getWakeSync();
+        synchronized (lock) {
+            // poke the lock so the service side can be woken from waiting on the lock
+            lock.notifyAll();
+        }
+    }
+
+}
diff --git a/tests/utils/SleepUtils/AlarmService/src/com/android/testing/alarmservice/WakeUpController.java b/tests/utils/SleepUtils/AlarmService/src/com/android/testing/alarmservice/WakeUpController.java
new file mode 100644
index 0000000..478371f
--- /dev/null
+++ b/tests/utils/SleepUtils/AlarmService/src/com/android/testing/alarmservice/WakeUpController.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2013 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.testing.alarmservice;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import android.util.Log;
+
+/**
+ * A singleton used for controlling and sharing of states/wakelocks
+ *
+ */
+public class WakeUpController {
+
+    private static final String LOG_TAG = WakeUpController.class.getName();
+    private static WakeUpController mController = null;
+    private WakeLock mWakeLock = null;
+    private Object mWakeSync = new Object();
+
+    private WakeUpController() {
+        Log.i(LOG_TAG, "Created instance: 0x" + Integer.toHexString(this.hashCode()));
+    }
+
+    public static synchronized WakeUpController getController() {
+        if (mController == null) {
+            mController = new WakeUpController();
+        }
+        return mController;
+    }
+
+    public WakeLock getWakeLock() {
+        if (mWakeLock == null) {
+            PowerManager pm =
+                    (PowerManager) AlarmService.sContext.getSystemService(Context.POWER_SERVICE);
+            mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "testing-alarmservice");
+            Log.i(LOG_TAG, "Create wakelock: 0x" + Integer.toHexString(mWakeLock.hashCode()));
+        }
+        return mWakeLock;
+    }
+
+    public Object getWakeSync() {
+        return mWakeSync;
+    }
+}
diff --git a/tests/utils/SleepUtils/Android.mk b/tests/utils/SleepUtils/Android.mk
new file mode 100644
index 0000000..0e65e22
--- /dev/null
+++ b/tests/utils/SleepUtils/Android.mk
@@ -0,0 +1,2 @@
+LOCAL_PATH:= $(call my-dir)
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/tests/utils/SleepUtils/README b/tests/utils/SleepUtils/README
new file mode 100644
index 0000000..bfe07da
--- /dev/null
+++ b/tests/utils/SleepUtils/README
@@ -0,0 +1,23 @@
+This folder contains utils to properly perform timed suspend and wakeup.
+
+AlarmService - a service that client can bind to and perform:
+1) holding wakelock (singleton to this service)
+2) setting alarm for a specified period and releasing the wakelock; service
+   call will block until alarm has been triggered and the wakelock is held
+3) releasing the wakelock
+
+SleepHelper - a self instrumentation meant as a convenient way to trigger
+the service functions from command line. Corresponding to service function
+above, supported operations are:
+1) holding wakelock
+am instrument -w -e command prepare \
+  com.android.testing.sleephelper/.SetAlarm
+
+2) setting alarm and wait til triggered
+am instrument -w -e command set_wait \
+  -e param <time in ms> com.android.testing.sleephelper/.SetAlarm
+Note: for the function to work properly, "-w" parameter is required
+
+3) releasing wakelock
+am instrument -w -e command done \
+  com.android.testing.sleephelper/.SetAlarm
diff --git a/tests/utils/SleepUtils/SleepHelper/Android.mk b/tests/utils/SleepUtils/SleepHelper/Android.mk
new file mode 100644
index 0000000..f8267fd
--- /dev/null
+++ b/tests/utils/SleepUtils/SleepHelper/Android.mk
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2013 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_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES += \
+    ../AlarmService/src/com/android/testing/alarmservice/Alarm.aidl
+LOCAL_SDK_VERSION := 7
+LOCAL_PACKAGE_NAME := SleepUtilsSleepHelper
+
+include $(BUILD_PACKAGE)
diff --git a/tests/utils/SleepUtils/SleepHelper/AndroidManifest.xml b/tests/utils/SleepUtils/SleepHelper/AndroidManifest.xml
new file mode 100644
index 0000000..0f1d491
--- /dev/null
+++ b/tests/utils/SleepUtils/SleepHelper/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.testing.sleephelper">
+
+    <uses-sdk android:minSdkVersion="7" />
+    <instrumentation android:label="Sleep Helper"
+                     android:name="com.android.testing.sleephelper.SetAlarm"
+                     android:targetPackage="com.android.testing.sleephelper" />
+
+    <application android:label="Sleep Utils Sleep Helper">
+        <uses-library android:name="android.test.runner" />
+    </application>
+</manifest>
diff --git a/tests/utils/SleepUtils/SleepHelper/src/com/android/testing/sleephelper/SetAlarm.java b/tests/utils/SleepUtils/SleepHelper/src/com/android/testing/sleephelper/SetAlarm.java
new file mode 100644
index 0000000..b558741
--- /dev/null
+++ b/tests/utils/SleepUtils/SleepHelper/src/com/android/testing/sleephelper/SetAlarm.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2013 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.testing.sleephelper;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.Debug;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.testing.alarmservice.Alarm;
+
+public class SetAlarm extends Instrumentation {
+
+    private static final String COMMAND = "command";
+    private static final String PARAM = "param";
+    private static final String CMD_PREPARE = "prepare";
+    private static final String CMD_SET = "set_wait";
+    private static final String CMD_DONE = "done";
+    private static final String SERVICE_ACTION = "com.android.testing.ALARM_SERVICE";
+    private static final String SERVICE_PKG = "com.android.testing.alarmservice";
+    private static final String LOG_TAG = SetAlarm.class.getSimpleName();
+
+    private Alarm mAlarmService = null;
+    private Bundle mArgs = null;
+    private String mCommand = null;
+    private Intent mServceIntent = new Intent(SERVICE_ACTION).setPackage(SERVICE_PKG);
+
+    private ServiceConnection mConn = new ServiceConnection() {
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            Log.d(LOG_TAG, "Service disconnected.");
+            mAlarmService = null;
+            errorFinish("service disconnected");
+        }
+
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            Log.d(LOG_TAG, "Service connected.");
+            mAlarmService = Alarm.Stub.asInterface(service);
+            handleCommands();
+        }
+    };
+
+
+    private void handleCommands() {
+        if (CMD_PREPARE.equals(mCommand)) {
+            callPrepare();
+        } else if (CMD_SET.equals(mCommand)) {
+            String paramString = mArgs.getString(PARAM);
+            if (paramString == null) {
+                errorFinish("argument expected for alarm time");
+            }
+            long timeout = -1;
+            try {
+                timeout = Long.parseLong(paramString);
+            } catch (NumberFormatException nfe) {
+                errorFinish("a number argument is expected");
+            }
+            callSetAndWait(timeout);
+        } else if (CMD_DONE.equals(mCommand)) {
+            callDone();
+        } else {
+            errorFinish("Unrecognized command: " + mCommand);
+        }
+        finish(Activity.RESULT_OK, new Bundle());
+    }
+
+    @Override
+    public void onCreate(Bundle arguments) {
+        super.onCreate(arguments);
+        mCommand = arguments.getString(COMMAND);
+        if ("true".equals(arguments.getString("debug"))) {
+            Debug.waitForDebugger();
+        }
+        if (mCommand == null) {
+            errorFinish("No command specified");
+        }
+        mArgs = arguments;
+        connectToAlarmService();
+    }
+
+    private void errorFinish(String msg) {
+        Bundle ret = new Bundle();
+        ret.putString("error", msg);
+        finish(Activity.RESULT_CANCELED, ret);
+    }
+
+    private void connectToAlarmService() {
+        // start the service with an intent, this ensures the service keeps running after unbind
+        ComponentName cn = getContext().startService(mServceIntent);
+        if (cn == null) {
+            errorFinish("failed to start service");
+        }
+        if (!getContext().bindService(mServceIntent, mConn, Context.BIND_AUTO_CREATE)) {
+            errorFinish("failed to bind service");
+        }
+    }
+
+    private void callPrepare() {
+        try {
+            mAlarmService.prepare();
+        } catch (RemoteException e) {
+            errorFinish("RemoteExeption in prepare()");
+        } finally {
+            getContext().unbindService(mConn);
+        }
+    }
+
+    private void callDone() {
+        try {
+            mAlarmService.done();
+        } catch (RemoteException e) {
+            errorFinish("RemoteExeption in prepare()");
+        } finally {
+            getContext().unbindService(mConn);
+        }
+        // explicitly stop the service (started in prepare()) so that the service is now free
+        // to be reclaimed
+        getContext().stopService(mServceIntent);
+    }
+
+    private void callSetAndWait(long timeoutMills) {
+        try {
+            mAlarmService.setAlarmAndWait(timeoutMills);
+        } catch (RemoteException e) {
+            errorFinish("RemoteExeption in setAlarmAndWait()");
+        } finally {
+            getContext().unbindService(mConn);
+        }
+    }
+}
diff --git a/tests/utils/SleepUtils/WakeLoopService/Android.mk b/tests/utils/SleepUtils/WakeLoopService/Android.mk
new file mode 100644
index 0000000..a8a944b
--- /dev/null
+++ b/tests/utils/SleepUtils/WakeLoopService/Android.mk
@@ -0,0 +1,24 @@
+#
+# Copyright (C) 2014 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_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_PACKAGE_NAME := WakeupLoopService
+LOCAL_SDK_VERSION := 7
+include $(BUILD_PACKAGE)
diff --git a/tests/utils/SleepUtils/WakeLoopService/AndroidManifest.xml b/tests/utils/SleepUtils/WakeLoopService/AndroidManifest.xml
new file mode 100644
index 0000000..a7028c4
--- /dev/null
+++ b/tests/utils/SleepUtils/WakeLoopService/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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="android.test.wakeuploop" >
+
+    <uses-sdk android:minSdkVersion="7" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+    <application android:label="Auto Wakeup Loop">
+        <service android:name=".WakeLoopService"
+            android:label="Wakup Loop Service"
+            android:exported="true"
+            android:enabled="true">
+            <intent-filter>
+                <action android:name="android.test.wakeuploop.WAKEUP_SERVICE" />
+            </intent-filter>
+        </service>
+        <receiver android:name=".WakeUpCall">
+            <intent-filter>
+                <action android:name="android.test.wakeuploop.WAKEUP" />
+            </intent-filter>
+        </receiver>
+    </application>
+</manifest>
diff --git a/tests/utils/SleepUtils/WakeLoopService/src/android/test/wakeuploop/FileUtil.java b/tests/utils/SleepUtils/WakeLoopService/src/android/test/wakeuploop/FileUtil.java
new file mode 100644
index 0000000..c8b075b
--- /dev/null
+++ b/tests/utils/SleepUtils/WakeLoopService/src/android/test/wakeuploop/FileUtil.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2014 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 android.test.wakeuploop;
+
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class FileUtil {
+
+    private static FileUtil sInst = null;
+    private static DateFormat sDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+
+    private FileUtil() {};
+
+    public static FileUtil get() {
+        if (sInst == null) {
+            sInst = new FileUtil();
+        }
+        return sInst;
+    }
+
+    public void writeDateToFile(File file) {
+        try {
+            FileOutputStream fos = new FileOutputStream(file);
+            fos.write(sDateFormat.format(new Date()).getBytes());
+            fos.write('\n');
+            fos.flush();
+            fos.close();
+        } catch (IOException ioe) {
+            Log.e("FileUtil", "exception writing date to file", ioe);
+        }
+    }
+}
diff --git a/tests/utils/SleepUtils/WakeLoopService/src/android/test/wakeuploop/WakeLoopService.java b/tests/utils/SleepUtils/WakeLoopService/src/android/test/wakeuploop/WakeLoopService.java
new file mode 100644
index 0000000..4f557b8
--- /dev/null
+++ b/tests/utils/SleepUtils/WakeLoopService/src/android/test/wakeuploop/WakeLoopService.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2014 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 android.test.wakeuploop;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.SystemClock;
+import android.util.Log;
+
+import java.io.File;
+
+public class WakeLoopService extends Service {
+
+    private static final String LOG_TAG = WakeLoopService.class.getSimpleName();
+    static final String WAKEUP_INTERNAL = "WAKEUP_INTERVAL";
+    static final String MAX_LOOP = "MAX_LOOP";
+    static final String STOP_CALLBACK = "STOP_CALLBACK";
+    static final String THIS_LOOP = "THIS_LOOP";
+    static final int MSG_STOP_SERVICE = 0xd1ed1e;
+
+    private final Handler mHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            if (msg.what == MSG_STOP_SERVICE) {
+                stopSelf();
+            } else {
+                super.handleMessage(msg);
+            }
+        };
+    };
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        // no binding, just start via intent
+        return null;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        // get wakeup interval from intent
+        long wakeupInterval = intent.getLongExtra(WAKEUP_INTERNAL, 0);
+        long maxLoop = intent.getLongExtra(MAX_LOOP, 0);
+
+        if (wakeupInterval == 0) {
+            // stop and error
+            Log.e(LOG_TAG, "No wakeup interval specified, not starting the service");
+            stopSelf();
+            return START_NOT_STICKY;
+        }
+        FileUtil.get().writeDateToFile(new File(Environment.getExternalStorageDirectory(),
+                "wakeup-loop-start.txt"));
+        Log.d(LOG_TAG, String.format("WakeLoop: STARTED interval = %d, total loop = %d",
+                wakeupInterval, maxLoop));
+        // calculate when device should be waken up
+        long atTime = SystemClock.elapsedRealtime() + wakeupInterval;
+        AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
+        Intent wakupIntent = new Intent(WakeUpCall.WAKEUP_CALL)
+            .putExtra(WAKEUP_INTERNAL, wakeupInterval)
+            .putExtra(MAX_LOOP, maxLoop)
+            .putExtra(THIS_LOOP, 0L)
+            .putExtra(STOP_CALLBACK, new Messenger(mHandler));
+        PendingIntent pi = PendingIntent.getBroadcast(this, 0, wakupIntent,
+                PendingIntent.FLAG_UPDATE_CURRENT);
+        // set alarm, which will be delivered in form of the wakeupIntent
+        am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, atTime, pi);
+        return START_NOT_STICKY;
+    }
+
+    @Override
+    public void onDestroy() {
+        Log.d(LOG_TAG, "WakeLoop: STOPPED");
+        // cancel alarms first
+        Intent intent = new Intent(WakeUpCall.WAKEUP_CALL)
+            .putExtra(WakeUpCall.CANCEL, "true");
+        sendBroadcast(intent);
+    }
+}
diff --git a/tests/utils/SleepUtils/WakeLoopService/src/android/test/wakeuploop/WakeUpCall.java b/tests/utils/SleepUtils/WakeLoopService/src/android/test/wakeuploop/WakeUpCall.java
new file mode 100644
index 0000000..8347bbf0
--- /dev/null
+++ b/tests/utils/SleepUtils/WakeLoopService/src/android/test/wakeuploop/WakeUpCall.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 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 android.test.wakeuploop;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Environment;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Log;
+
+import java.io.File;
+
+/**
+ * The receiver for the alarm we set
+ *
+ */
+public class WakeUpCall extends BroadcastReceiver {
+    private static final String LOG_TAG = WakeUpCall.class.getSimpleName();
+    static final String WAKEUP_CALL = "android.test.wakeuploop.WAKEUP";
+    static final String CANCEL = "CANCEL";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        boolean cancel = intent.hasExtra(CANCEL);
+        if (!cancel) {
+            long maxLoop = intent.getLongExtra(WakeLoopService.MAX_LOOP, 0);
+            long wakeupInterval = intent.getLongExtra(WakeLoopService.WAKEUP_INTERNAL, 0);
+            long thisLoop = intent.getLongExtra(WakeLoopService.THIS_LOOP, -1);
+            Log.d(LOG_TAG, String.format("incoming: interval = %d, max loop = %d, this loop = %d",
+                    wakeupInterval, maxLoop, thisLoop));
+            if (thisLoop == -1) {
+                Log.e(LOG_TAG, "no valid loop count received, trying to stop service");
+                stopService(intent);
+                return;
+            }
+            if (wakeupInterval == 0) {
+                Log.e(LOG_TAG, "no valid wakeup interval received, trying to stop service");
+                stopService(intent);
+                return;
+            }
+            thisLoop++;
+            Log.d(LOG_TAG, String.format("WakeLoop - iteration %d of %d", thisLoop, maxLoop));
+            if (thisLoop == maxLoop) {
+                // when maxLoop is 0, we loop forever, so not checking that case
+                // here
+                Log.d(LOG_TAG, "reached max loop count, stopping service");
+                stopService(intent);
+                return;
+            }
+            screenOn(context);
+            FileUtil.get().writeDateToFile(
+                    new File(Environment.getExternalStorageDirectory(), "wakeup-loop.txt"));
+            // calculate when device should be waken up
+            long atTime = SystemClock.elapsedRealtime() + wakeupInterval;
+            intent.putExtra(WakeLoopService.THIS_LOOP, thisLoop);
+            PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent,
+                    PendingIntent.FLAG_UPDATE_CURRENT);
+            // set alarm, which will be delivered in form of the wakeupIntent
+            am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, atTime, pi);
+        } else {
+            // cancel alarms
+            Log.d(LOG_TAG, "cancelling future alarms on request");
+            am.cancel(PendingIntent.getBroadcast(context, 0, intent, 0));
+        }
+    }
+
+    private void stopService(Intent i) {
+        Messenger msgr = i.getParcelableExtra(WakeLoopService.STOP_CALLBACK);
+        if (msgr == null) {
+            Log.e(LOG_TAG, "no stop service callback found, cannot stop");
+        } else {
+            Message msg = new Message();
+            msg.what = WakeLoopService.MSG_STOP_SERVICE;
+            try {
+                msgr.send(msg);
+            } catch (RemoteException e) {
+                Log.e(LOG_TAG, "ignored remoted exception while attempting to stop service", e);
+            }
+        }
+    }
+
+    private void screenOn(Context context) {
+        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        @SuppressWarnings("deprecation")
+        WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK |
+                PowerManager.ACQUIRE_CAUSES_WAKEUP, LOG_TAG);
+        wl.acquire(500);
+    }
+}