刚在做手机自动化测试的过程中,发现手机深度睡眠后会出现以下问题
先来了解一下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 时钟信号才被唤醒。