關於android 深度睡眠的認識

剛在做手機自動化測試的過程中,發現手機深度睡眠後會出現以下問題

先來了解一下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 時鐘信號才被喚醒。







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章