Android 自动休眠唤醒

时间:2021-02-12 23:49:21

这几天研究的内容:
**一、自动休眠唤醒的实现.
二、binder机制.(广播既然能实现进程间通信,两者区别?)
三、自定义控件的使用和原理.(benwenbutantao….)
四、动画效果的实现原理.**

一、自动休眠唤醒的实现.
分析:
标准Linux睡眠唤醒机制简介:
在标准Linux中,休眠主要分三个主要的步骤:(1)冻结用户态进程和内核态任务;(2)调用注册的设备的suspend的回调函数,其调用顺序是按照驱动加载时的注册顺序。(3)休眠核心设备和使CPU进入休眠态冻结进程是内核把进程列表中所有的进程的状态都设置为停止,并且保存下所有进程的上下文。 当这些进程被解冻的时候,它们是不知道自己被冻结过的,只是简单的继续执行。
那么是如何让Linux进入休眠的呢?其实很简单,因为Android和kernel已经做了很多复杂的工作,所以用户只需可以通过读写sys文件/sys /power/state 就可以实现控制系统进入休眠。
比如: #echo mem > /sys/power/state /////// 使系统进行睡眠

    #echo  on   > /sys/power/state////////////使系统从睡眠中唤醒过来

当然还有其它的状态操作,在下面的内容中将有介绍。

Android睡眠唤醒机制简介:

Android在Linux内核原有的睡眠唤醒模块上基础上,主要增加了下面三个机制:

Wake _Lock 唤醒锁机制;

Early _Suspend 预挂起机制;

Late _Resume 迟唤醒机制;

其基本原理如下:
当启动一个应用程序的时候,它都可以申请一个wake_lock唤醒锁,每当申请成功之后都会在内核中注册一下(通知系统内核,现在已经有锁被申请),当应用程序在某种情况下释放wake_lock的时候,会注销之前所申请的wake_lock。特别要注意的是:只要是系统中有一个wake_lock的时候,系统此时都不能进行睡眠。但此时各个模块可以进行early_suspend。当系统中所有的wake_lock都被释放之后,系统就会进入真正的kernel的睡眠状态。在系统启动的时候会创建一个主唤醒锁main_wake_lock,该锁是内核初始化并持有的一个WAKE_LOCK_SUSPEND属性的非限时唤醒锁。因此,系统正常工作时,将始终因为该锁被内核持有而无法进入睡眠状态。也就是说在不添加新锁的情况下,只需将main_wake_lock 解锁,系统即可进入睡眠状态。
Android 自动休眠唤醒
源代码的实现为:
PowerManager.java goToSleep( )
PowerManagerService.java goToSleep()
PowerManagerService.java goToSleepWithReason()
PowerManagerService.java setPowerState()
PowerManagerService.java SetScreenStateLocked ()
Power.java setScreenState()
android_os_Power.cpp setScreenState()
power.c set_screen_state( )
main.c state_store( )
项目中的逻辑为:
1.发出广播,由助手来实现自动开关机。

// 保存信息
SharedPrefrenceUtil.saveData(activity,
SplashActivity.CONNECTER_INFO, ConnecterInfo.getInstance());

Intent intent = new Intent();
intent.setAction("R2KTIMEMACHINESENDER");
String time = ConnecterInfo.getInstance().getTime();
if (isSleepInable) {
if (time != null && time.length() != 0 && time.contains("#")) {
String times[] = time.split("#");
intent.putExtra("timeOnHour", Integer.parseInt(times[0].split(":")[0]));
intent.putExtra("timeOnMin", Integer.parseInt(times[0].split(":")[1]));
intent.putExtra("timeOffHour", Integer.parseInt(times[1].split(":")[0]));
intent.putExtra("timeOffMin", Integer.parseInt(times[1].split(":")[1]));
}
}
activity.sendBroadcast(intent);

2.助手收到广播后启动service并保存时间信息。

/*
<receiver android:name="com.example.zreceive.r2ktimemachine.TimeMachineBroReceiver"
>
<intent-filter >
<action android:name="R2KTIMEMACHINESENDER"/>
</intent-filter>
</receiver>
*/

public class TimeMachineBroReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub

SharedPreferences sp = context.getSharedPreferences("TimeMachine",
context.MODE_PRIVATE);
Editor editor = sp.edit();
Boolean isSleepInable = intent.getBooleanExtra("isSleepInable", false);
int timeOnHour = intent.getIntExtra("timeOnHour", -1);
int timeOnMin = intent.getIntExtra("timeOnMin", -1);
int timeOffHour = intent.getIntExtra("timeOffHour", -1);
int timeOffMin = intent.getIntExtra("timeOffMin", -1);
editor.putInt("timeOnHour", timeOnHour);
editor.putInt("timeOnMin", timeOnMin);
editor.putInt("timeOffHour", timeOffHour);
editor.putInt("timeOffMin", timeOffMin);
editor.commit();
}
}
//MainActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initlayout();

/*
* 启动自动开关机服务
*/

Intent iJettyServiceIntent = new Intent(this, SleepTimerService.class);
this.startService(iJettyServiceIntent);
}

3.service执行自动开关机操作.

public class SleepTimerService extends Service {
private WakeLock mWakeLock ;

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
acquireWakeLock();
new Thread(new LockScreenRunbale()).start();
return super.onStartCommand(intent, flags, startId);
}

@Override
public IBinder onBind(Intent intent) {
return null;
}

private class LockScreenRunbale implements Runnable {

@Override
public void run() {
while (true) {
try {
Thread.sleep(1000 * 50);
} catch (InterruptedException e) {
e.printStackTrace();
}
int onTimeHour = 0;
int onTimeMin = 0;

int offTimeHour = 0;
int offTimeMin = 0;

SharedPreferences sp = getSharedPreferences("TimeMachine", MODE_PRIVATE);
onTimeHour = sp.getInt("timeOnHour", -1);
onTimeMin = sp.getInt("timeOnMin", -1);
offTimeHour = sp.getInt("timeOffHour", -1);
offTimeMin = sp.getInt("timeOffMin", -1);

if (onTimeHour == offTimeHour && onTimeMin == offTimeMin) {
return;
}
if (isOnTime(onTimeHour, onTimeMin) || isOffTime(offTimeHour, offTimeMin)) {
// 触发POWER事件
execShell("input keyevent 26");
}
}
}

};

public void execShell(String cmd) {
try {
// 权限设置
Process p = Runtime.getRuntime().exec("sh");
// 获取输出流
OutputStream outputStream = p.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(
outputStream);
// 将命令写入
dataOutputStream.writeBytes(cmd);
// 提交命令
dataOutputStream.flush();
// 关闭流操作
dataOutputStream.close();
outputStream.close();
} catch (Throwable t) {
t.printStackTrace();
}
}


/**
* 保持电源锁,防止系统进入休眠后关机
*/

private void acquireWakeLock() {
if (null == mWakeLock) {
PowerManager pm = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE,"");
if (null != mWakeLock) {
mWakeLock.acquire();
}
}
}

//释放设备电源锁,目前未使用
private void releaseWakeLock() {
if (null != mWakeLock) {
mWakeLock.release();
mWakeLock = null;
}
}

/**
* 判断是否已经到关机时间
* @param offTimeHour
* @param offTimeMinute
* @return
*/

private boolean isOffTime(int offTimeHour, int offTimeMinute) {
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
if (!pm.isScreenOn()) {
return false;
}
Calendar c = Calendar.getInstance();//可以对每个时间域单独修改

int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);

if (hour == offTimeHour && minute == offTimeMinute) {
return true;
}
return false;
}

/**
* 判断是否已经到开机时间
* @param onTimeHour
* @param onTimeMinute
* @return
*/

private boolean isOnTime(int onTimeHour, int onTimeMinute) {
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
if (pm.isScreenOn()) {
return false;
}
Calendar c = Calendar.getInstance();//可以对每个时间域单独修改

int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);

if (hour == onTimeHour && minute == onTimeMinute) {
return true;
}
return false;
}
}