解析自动休眠---实现自动关机
从Application上往下跟,解析自动休眠的实现策略
Application层
Settings----Display----Sleep
这里是超时设置的地方。
文件目录:packages/apps/Settings/src/com/android/settings/DisplaySettings.java
这里比较简单:
onCreate()
{
…
mScreenTimeoutPreference = (ListPreference)findPreference(KEY_SCREEN_TIMEOUT);
final long currentTimeout =Settings.System.getLong(resolver, SCREEN_OFF_TIMEOUT,
FALLBACK_SCREEN_TIMEOUT_VALUE);
mScreenTimeoutPreference.setValue(String.valueOf(currentTimeout));
mScreenTimeoutPreference.setOnPreferenceChangeListener(this);
disableUnusableTimeouts(mScreenTimeoutPreference);
updateTimeoutPreferenceDescription(currentTimeout);
…
}
……….
@Override
publicboolean onPreferenceChange(Preference preference, Object objValue) {
finalString key = preference.getKey();
if(KEY_SCREEN_TIMEOUT.equals(key)) {
try {
int value = Integer.parseInt((String) objValue);
Settings.System.putInt(getContentResolver(), SCREEN_OFF_TIMEOUT, value);
updateTimeoutPreferenceDescription(value);
}catch (NumberFormatException e) {
Log.e(TAG, "could not persist screen timeout setting", e);
}
}
}
Settings里头,只是将当前的数值保存在数据库里头,这意味着默认值可以在SettingsProvider中被设置,这是比较正统的做法。同时,也意味着会有一个Observer。
---------------------------------------------------------------------------------------------------------------------------
Framework层
有以下几处用到了这个SCREEN_OFF_TIMEOUT
1. frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
2. frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
3. frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
4. frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
这几处要一个一个查。具体是什么作用
从简单的开始查,基本上可以肯定DatabaseHelper.java只是初始化,读取默认参数。去看看。
一、DatabaseHelper.java
private voidloadSystemSettings(SQLiteDatabase db) {
SQLiteStatement stmt = null;
try {
……...
//add for factory as ro.rk.screenoff_time
loadSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
SystemProperties.getInt("ro.rk.screenoff_time",mContext.getResources().getInteger(R.integer.def_screen_off_timeout)));
………..
}
这里读取ro.rk.screenoff_time读取数据,默认数值保存在def_screen_off_timeout中。只是初始化数值。
SCREEN_OFF_TIMEOUT这个关键字还出现upgradeScreenTimeoutFromNever中,但这里只是数据库更新时的操作,没有更多的意义。
二、PhoneWindowManager.java第二个文件是这个。
特地说明下这个类:PhoneWindowManager.java继承自WindowManagePolicy.java
WindowManagePolicy.java是做什么的呢?这里头有一大堆lw li t
--------接口类,提供了WindowManager的所有UI定制行为。在WindowManager启动的时候被实例化,允许定制window层级,制定window类型,key事件派发,布局。
WindowManagePolicy.java提供了与系统窗口管理的深层交互。在这个interface中的一些方法会被许多被多重限制的context调用。这里怎么理解呢?多重限制。可以理解成这是些被很多lock限制的context。这些函数会用一些 后缀 来判别被调用时持有了哪些lock。如果没有后缀。那就意味着函数可能是被window manager 主线程或 其他调用windowmanager的线程。
后缀:Ti--------Thread input; Tq----------Thread Queue; Lw---------------lock mainwindowmanager; Li-----------------Lock input thread
同时,在PhoneWindowManager中,新增后缀Lp--------Lock phone window manager
这里的限制======锁=====locks
还有一点:老规矩frameworks/base/services/java/com/android/server/WindowManagerService.java是核心,有很多调用都从这里来,PhoneWindowManager.java侧重与提供app调用的接口。
接着讲PhoneWindowManager.java。进入正题。
class SettingsObserver extendsContentObserver {
SettingsObserver(Handler handler) {
super(handler);
}
void observe() {
………….
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_OFF_TIMEOUT), false, this,
UserHandle.USER_ALL);
………..
updateSettings();
}
@Overridepublic void onChange(boolean selfChange) {
updateSettings();
updateRotation(false);
}
}
另一处是在updateSettings中。
public void updateSettings() {
ContentResolverresolver = mContext.getContentResolver();
boolean updateRotation = false;
synchronized (mLock) {
……………..
//use screen off timeout setting as the timeout for the lockscreen
mLockScreenTimeout = Settings.System.getIntForUser(resolver,
Settings.System.SCREEN_OFF_TIMEOUT,0, UserHandle.USER_CURRENT);
……………..
}
………….
}
结合起来看,就是PhoneWindowManager监听了SCREEN_OFF_TIMEOUT。同时,在数据库改变时,讲最新的值保存在mLockScreenTimeout中。----------注意这是保存了超时时间的变量
-------------------------------------------------------------------------------------------------------
那么,mLockScreenTimeout在什么时候调用呢?
两个地方
private void updateLockScreenTimeout() {
synchronized (mScreenLockTimeout) {
boolean enable = (mAllowLockscreenWhenOn && mAwake &&
mKeyguardDelegate != null&& mKeyguardDelegate.isSecure());
if (mLockScreenTimerActive != enable) {
if (enable) {
if (localLOGV) Log.v(TAG,"setting lockscreen timer");
mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
} else {
if (localLOGV) Log.v(TAG,"clearing lockscreen timer");
mHandler.removeCallbacks(mScreenLockTimeout);
}
mLockScreenTimerActive =enable;
}
}
}
看函数体,这是根据一些变量,判断是否要添加mScreenLockTimeout的Handler。mLockScreenTimerActive保存住当前是否开启了自动锁屏功能。
updateLockScreenTimeout在三个地方被调用:
1. finishPostLayoutPolicyLw----WindowManagerService.java
2. goingToSleep--------Notifier.java
3. wakingUp---------Notifier.java
小结,ScreenTimeout只在睡眠唤醒UI刷新时会检查判断。which is quite often.
如果读者有兴趣可以继续跟这几个函数的具体调用。针对这个研究目标已经足够。
另一个地方:
public void userActivity() {
………
synchronized (mScreenLockTimeout) {
if (mLockScreenTimerActive) {
// reset the timer
mHandler.removeCallbacks(mScreenLockTimeout);
mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
}
}
……….
}
在userActivity的时候不断的更新。
userActivity又是如何调用的呢?
在事件派发机制中,有个InputDispatcher.cpp,kernel收到events之后,通过这个类的pokeUserActivity,传递到com_android_server_input_InputManagerService.cpp中,再通过com_android_server_input_InputManagerService.cpp的调用android_server_PowerManagerService_userActivity,最终userActivityFromNative真正传到PowerManagerService。再调到PhoneWindowManager.java的userActivity。
三、KeyguardViewMediator.java第三个文件是这个。
private void doKeyguardLaterLocked() {
// if thescreen turned off because of timeout or the user hit the power button
// and wedon't need to lock immediately, set an alarm
// toenable it a little bit later (i.e, give the user a chance
// toturn the screen back on within a certain window without
// havingto unlock the screen)
finalContentResolver cr = mContext.getContentResolver();
// FromDisplaySettings
longdisplayTimeout = Settings.System.getInt(cr, SCREEN_OFF_TIMEOUT,
KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT);
// FromSecuritySettings
finallong lockAfterTimeout = Settings.Secure.getInt(cr,
Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
KEYGUARD_LOCK_AFTER_DELAY_DEFAULT);
// FromDevicePolicyAdmin
finallong policyTimeout = mLockPatternUtils.getDevicePolicyManager()
.getMaximumTimeToLock(null, mLockPatternUtils.getCurrentUser());
longtimeout;
if(policyTimeout > 0) {
//policy in effect. Make sure we don't go beyond policy limit.
displayTimeout = Math.max(displayTimeout, 0); // ignore negative values
timeout = Math.min(policyTimeout - displayTimeout, lockAfterTimeout);
} else {
timeout = lockAfterTimeout;
}
if(timeout <= 0) {
//Lock now
mSuppressNextLockSound = true;
doKeyguardLocked(null);
} else {
//Lock in the future
longwhen = SystemClock.elapsedRealtime() + timeout;
Intent intent = new Intent(DELAYED_KEYGUARD_ACTION);
intent.putExtra("seq", mDelayedShowingSequence);
PendingIntent sender = PendingIntent.getBroadcast(mContext,
0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, sender);
if(DEBUG) Log.d(TAG, "setting alarm to turn off keyguard, seq = "
+mDelayedShowingSequence);
}
}
这里看起来比较方便。获取了SCREEN_OFF_TIMEOUT的最新值,保存在displayTimeout。并根据这个值计算要待机的时间。
四、PowerManagerService.java最烦就是这个。
可以查到
public voidsystemReady(IAppOpsService appOps) {
synchronized (mLock) {
……
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_OFF_TIMEOUT),
…….
}
}
PowerManagerService.java添加了对SCREEN_OFF_TIMEOUT的监听。
private void updateSettingsLocked() {
……..
mScreenOffTimeoutSetting =Settings.System.getIntForUser(resolver,
Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT,
UserHandle.USER_CURRENT);
……..
}
将数据库中的值保存在mScreenOffTimeoutSetting中。
private int getScreenOffTimeoutLocked(intsleepTimeout) {
int timeout = mScreenOffTimeoutSetting;
if(isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
timeout = Math.min(timeout,mMaximumScreenOffTimeoutFromDeviceAdmin);
}
if (mUserActivityTimeoutOverrideFromWindowManager>= 0) {
timeout = (int)Math.min(timeout,mUserActivityTimeoutOverrideFromWindowManager);
}
if (sleepTimeout >= 0) {
timeout = Math.min(timeout,sleepTimeout);
}
return Math.max(timeout,mMinimumScreenOffTimeoutConfig);
}
继续看,可以发现mScreenOffTimeoutSetting,经过处理,会通过getScreenOffTimeoutLocked函数被其他函数 使用。
private voidupdateUserActivitySummaryLocked(long now, int dirty) {
// Update the status of the user activitytimeout timer.
if ((dirty & (DIRTY_WAKE_LOCKS |DIRTY_USER_ACTIVITY
| DIRTY_WAKEFULNESS |DIRTY_SETTINGS)) != 0) {
mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
long nextTimeout = 0;
if (mWakefulness == WAKEFULNESS_AWAKE
|| mWakefulness ==WAKEFULNESS_DREAMING
|| mWakefulness ==WAKEFULNESS_DOZING) {
final int sleepTimeout =getSleepTimeoutLocked();
final int screenOffTimeout =getScreenOffTimeoutLocked(sleepTimeout);
final int screenDimDuration =getScreenDimDurationLocked(screenOffTimeout);
mUserActivitySummary = 0;
if (mLastUserActivityTime >=mLastWakeTime) {
nextTimeout =mLastUserActivityTime
+ screenOffTimeout- screenDimDuration;
if (now < nextTimeout) {
mUserActivitySummary =USER_ACTIVITY_SCREEN_BRIGHT;
} else {
nextTimeout =mLastUserActivityTime + screenOffTimeout;
if (now <nextTimeout) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
}
}
}
if (mUserActivitySummary == 0
&&mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
nextTimeout =mLastUserActivityTimeNoChangeLights + screenOffTimeout;
if (now < nextTimeout) {
if(mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
} else if (mDisplayPowerRequest.policy== DisplayPowerRequest.POLICY_DIM) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
}
}
}
if (mUserActivitySummary == 0){
if (sleepTimeout >= 0) {
final longanyUserActivity = Math.max(mLastUserActivityTime,
mLastUserActivityTimeNoChangeLights);
if (anyUserActivity>= mLastWakeTime) {
nextTimeout =anyUserActivity + sleepTimeout;
if (now <nextTimeout) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
}
}
} else {
mUserActivitySummary =USER_ACTIVITY_SCREEN_DREAM;
nextTimeout = -1;
}
}
if (mUserActivitySummary != 0&& nextTimeout >= 0) {
Message msg =mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextTimeout);
}
} else {
mUserActivitySummary = 0;
}
…………..
}
}
MSG_USER_ACTIVITY_TIMEOUT 又会触发handleUserActivityTimeout。又一次去updatePowerStateLocked。updateUserActivitySummaryLocked又在updatePowerStateLocked被调用,这就是一个不断更新的环路。
不管这里的函数应该如何调用。从这里可以看出一点。
这里的SCREEN_OFF_TIMEOUT被用作控制屏幕是dim或者bright。或者asleep后就被ignored。
总结
至此,可以明白了。自动关机该如何实现?在PhoneWindowManager中,添加超时即可。其他的系统会帮你做。具体的实现涉及哪些文件呢?
1. 在system.prop中添加switcher
2. frameworks/base/core/java/android/provider/Settings.java中加KEY:POWER_OFF_TIMEOUT
3. frameworks/base/core/res/res/values/config.xml加与system.prop中配套的default_config值
4. frameworks/base/core/res/res/values/symbols.xml别忘了这个
5. frameworks/base/packages/SettingsProvider支持起来
6. frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java中加AlarmManager去设置一个timer
7. packages/apps/Settings/添加支持。
解析自动休眠---实现自动关机相关推荐
- 设置计算机在睡眠状态下能共享,使用wifi共享精灵的过程中电脑会自动休眠锁屏的解决方法...
我在使用wifi共享精灵的过程中经常是这样做:电脑一直开着,然后自己躺在床上用手机看小说.看韩剧.但几十分钟之后,电脑会因为长期没人操作而自动休眠,从而导致wifi连接不上,要是每次重启软件又太费事, ...
- 怎么让电脑不自动休眠_【平安惠阳提醒您】电脑应设置自动休眠 避免产生火灾隐患...
不少市民平时在家时,都十分注意防范安全隐患.消防部门有关专家提示,对于上班族每天工作的办公室来说,同样存在不少容易被忽视的不安全因素,上班族的安全意识一定不能放松,尤其是要防范电气火灾隐患. 办公室电 ...
- win10休眠设置_电脑总是“打瞌睡”?教你如何简单关闭自动休眠
电脑休眠指的是将当前处于运行状态的数据保存在硬盘中,整机完全停止供电.通常电脑的自动休眠是有一个电源计划的,电脑如果在设定的时间内没有使用,那么就会进入自动休眠状态. 然而许多人长时间不操作电脑,只是 ...
- 如何关闭移动硬盘的自动休眠功能
移动硬盘一般都有自动休眠功能,即连接电脑长时间不用后会自动休眠.该功能的初衷是好的,可以保护移动硬盘,延迟使用寿命.但对于使用者来讲,有时却是很烦恼的.因为当移动硬盘休眠后,想幻醒是需要时间的.具体时 ...
- 处理win10系统自动休眠bug
最近有win10系统用户遇到一个很棘手的问题,明明已经禁止了睡眠,设置从不关闭显示器,从不进入睡眠,只要不动鼠标,还是会在2分钟或3分钟自动进入睡眠状态,很是麻烦.如果遇到win10系统自动休眠bug ...
- 解决硬盘自动休眠问题
我的笔记本型号是 机械革命x6 ,cpu i5-4210M ,显卡 GTX 860M ,硬盘 128SSD+1T机械硬盘 15年刚入手的时候发现了一个问题,打联盟的时候,时间长不打字突然打字发点什么电 ...
- 远程计算机一键休眠,nuc8i5远程登录-windows10频繁自动休眠解决方案
nuc8i5远程登录-windows10频繁自动休眠解决方案 2021-05-08 16:49:11 0点赞 0收藏 0评论 nuc8i5远程登录-windows10频繁自动休眠解决方案 远程开机后, ...
- VBS+迷你QQ,实现机器远程休眠和电驴的自动休眠
VBS+迷你QQ,实现机器远程休眠和电驴的自动休眠 首先到http://www.xdowns.com/soft/40/125/2006/Soft_28470.html下载迷你QQ,解压后运行MiniQ ...
- 计算机休眠移动硬盘不休眠,关闭硬盘盒自动休眠软件
关闭硬盘盒自动休眠软件是防止硬盘盒子自动休眠,配合VL71主控芯片使用,提供详细教程分享,让你的硬盘盒子不会自动休眠了,提升电脑的性能! 软件介绍 大部分硬盘盒为了降低硬盘损耗,会在3-5分钟无操作的 ...
最新文章
- 深度学习的算法实践和演进
- 物流系统高可用架构案例
- vivado如何实现增量编译,加快布局布线
- 第一行代码学习笔记第六章——详解持久化技术
- leetcode(2)495——提莫攻击(C++),运算符优先级(+=,?,+,-)
- 假笨说-谨防JDK8重复类定义造成的内存泄漏
- 探索 .NET Core 依赖注入的 IServiceCollection
- nssl1469-W【dp】
- [css] 怎么才能让图文不可复制?
- table隔行变色与table单元格根据条件更改字体颜色
- 使用SDL2中SDL_CreateWindow()函数时报错跳进wincore.cpp(wntdll.pbd not load)
- 交换机中对于tagged帧和untagged帧的处理
- php 极光推送别名数组,PHP使用极光推送-Go语言中文社区
- 【Windows】Win10强制删除文件夹
- centos6.5安装谷歌浏览器+谷歌浏览器flash插件安装+谷歌浏览器pdf阅读器安装
- Protecting Against DNN Model Stealing Attacks 论文阅读心得
- 杭州云栖大会“弹性计算用户实践专场”等你来
- 动态规划 自然数拆分
- JAVA:Java Swing 练习题
- linux startx无效_startx启动失败的几个解决方法
热门文章
- pg2.OperationalError: could not connect to server: Connection timed out (0x0000274C/10060)
- easyexcel导出excel文件合并相同单元格数据
- 大动作|阿里云扩招5000人!云计算、AI抢夺全球人才
- eve-ng ubuntu 20.04 设置iptables
- xcode 配置wechat_Xcode 真机调试微信支付 提示 mainfest.json配置APPID和订单的appid 不一致...
- 安装java环境----血泪版
- 图片按指定比例缩放并压缩至指定大小,解决保存图片文件体积过大bug。
- time.h时间函数
- Linux 常用基本命令 ps top kill
- CodeForces 858C Did you mean... 、 CodeForces 858D Polycarp's phone book!黑科技