剛在做手機自動化測試的過程中,發現手機深度睡眠後會出現以下問題
先來了解一下Windows下的睡眠功能:
電腦在 睡眠狀態時,將切斷除內存外其他硬件配件的電源,工作狀態的數據將保存在內存中,這樣在重新喚醒電腦時,就可以快速恢復睡眠前的工作狀態。
Linux系統下的睡眠功能:
Linux操作系統的睡眠有兩種方式:mem和standby ,這兩種方式都是suspend to RAM,簡稱STR,只是standby耗電更多一些,返回到正常工作方式時間更短一些而已。
實現的方法也是將系統狀態的數據保存到內存,喚醒時再從內存讀數據。
Android下的睡眠:
Android並不是真正的系統,用的是Linux核心,也就是基於Linux核心,更類似於應用平臺。所以,如果是依據Windows和Linux操作系統下的睡眠理論來說,Android本身並不具有睡眠的功能,也就不存在“深度睡眠”這種說法。再根據Android平臺架構體系,如果Linux核心進入睡眠了,那麼Android這個平臺的一切功能都將喪失。
那麼當關閉手機屏幕,長期未使用手機時,Android平臺又是處於什麼樣的狀態呢?
來做一個簡單的實驗,打開Eclipse,並將手機連到電腦上,觀察DDMS和LogCat:
1、並關閉屏幕,起初,從LogCat中可以觀察到手機上的一切進程還是照樣運行,手機上的網絡也還是通的。
2、過一段時間後,這個時間不確定性,每個手機所反映出來的結果會不一樣,從LogCat中可以觀察到手機上的網絡會被斷開,部份應用可能會被註銷,但筆者運行的一個服務還是照樣在運行;
3、再過一段時間後,這個時間較長,半個小時以上,發現電腦已經檢測不到手機的信息,從DDMS裏面反映出來連接上的是未知設置。
4、當重新開啓屏幕後,再次連上手機時,發現筆者用於測試的那個進程照樣還在運行,並未結束掉。
由於測試環境有限,只能在有限的幾部不同型號的手機進行測試,當手機長期未使用的時間,手機的不常用的硬件可能會斷電,比如網絡、USB接口、攝像頭、藍牙、GPS等...,或者說是這些相應的系統服務被關閉。但手機並未進入“睡眠”狀態,頂多可以假設爲是“休眠”狀態。
以下是個人愚見:
1. 首先啓動一個service 在service 從啓動一個線程(while(true)類型),在線程中 mgr.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), 20 * 1000, pi); 看出這個時鐘會每隔20 秒鐘喚醒一次手機,而這個線程也會被喚醒, pttRunobject.wait(1000 * downtime_1);, 看到了嗎(重點在這,這個wait 只記錄手機被喚醒的時間,在手機深度睡眠之後,線程等待的時間是不走的)意思是wait 只計算手機被持鎖的時間,如果不持有鎖, 手機會立馬又睡下去 。
public class MyThread implements Runnable {
int uptime_1 = 3;
int downtime_1 = 3;
int printtime_1 = 5;
public MyThread(int downtime, int uptime, int printtime) {
uptime_1 = uptime;
downtime_1 = downtime;
AutoTestLogUtils.logPtt("MyThread oncreate.........");
}
public void run() {
AutoTestUtil.scheduleAlarms(mContext, downtime_1, uptime_1);
while (pttRunflag) {
synchronized (pttRunobject) {
AutoTestUtil.sendKeyDownCode(KeyEvent.KEYCODE_PTT);
try {
pttRunobject.wait(1000 * uptime_1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
AutoTestLogUtils.logPtt("ptt down end and up start");
AutoTestUtil.sendKeyUpCode(KeyEvent.KEYCODE_PTT);
try {
pttRunobject.wait(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
AutoTestLogUtils.logPtt("ptt up end and end key start");
AutoTestUtil.sendKeyDownAndUpCode(KeyEvent.KEYCODE_ENDCALL);
// 喚醒時間空白時間,
AutoTestUtil.scheduleAlarms(mContext, downtime_1, uptime_1);
try {
pttRunobject.wait(1000 * downtime_1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
AutoTestLogUtils.logPtt("ptt end key end anddown key start");
}
}
}
}
public static void scheduleAlarms(Context ctxt,int downTime,int upTIme) {
AlarmManager mgr = (AlarmManager) ctxt
.getSystemService(Context.ALARM_SERVICE);
Intent intent2 = new Intent(ctxt, BootReceiver.class);
intent2.putExtra(AutoTestUtil.PTT_DOWN_TIME,
Integer.valueOf(downTime));
intent2.putExtra(AutoTestUtil.PTT_UP_TIME,
Integer.valueOf(upTIme));
intent2.setAction(AutoTestUtil.WAKE_UP_DEVICES_ACTION);
PendingIntent pi = PendingIntent.getBroadcast(ctxt, 0, intent2, 0);
mgr.cancel(pi);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 60);
mgr.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), 20 * 1000, pi);
}
在onReceive 中
pManager = ((PowerManager) context.getSystemService(context.POWER_SERVICE));
WakeLock mWakeLock = pManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
| PowerManager.ON_AFTER_RELEASE, TAG);
mWakeLock.acquire(30*1000);
mWakeLock.release();
總結:類似推測手機深睡眠後,上層的ap 應該是死的,只有接到了底層art 時鐘信號才被喚醒。