diff options
author | Guang Zhu <guangzhu@google.com> | 2014-12-11 15:12:30 -0800 |
---|---|---|
committer | Guang Zhu <guangzhu@google.com> | 2014-12-12 17:31:38 -0800 |
commit | 18b892c723e812a7e111f102d2b0c0782b116bb6 (patch) | |
tree | ab7f42c778169da272b503d308c2cc712effef2b /tests/utils | |
parent | 1f28a6a571a9b4ff78d85e2b62a30d77ce986d7b (diff) | |
download | frameworks_base-18b892c723e812a7e111f102d2b0c0782b116bb6.zip frameworks_base-18b892c723e812a7e111f102d2b0c0782b116bb6.tar.gz frameworks_base-18b892c723e812a7e111f102d2b0c0782b116bb6.tar.bz2 |
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
Diffstat (limited to 'tests/utils')
23 files changed, 1024 insertions, 0 deletions
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..8347bbf --- /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); + } +} |