从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/添加支持。

解析自动休眠---实现自动关机相关推荐

  1. 设置计算机在睡眠状态下能共享,使用wifi共享精灵的过程中电脑会自动休眠锁屏的解决方法...

    我在使用wifi共享精灵的过程中经常是这样做:电脑一直开着,然后自己躺在床上用手机看小说.看韩剧.但几十分钟之后,电脑会因为长期没人操作而自动休眠,从而导致wifi连接不上,要是每次重启软件又太费事, ...

  2. 怎么让电脑不自动休眠_【平安惠阳提醒您】电脑应设置自动休眠 避免产生火灾隐患...

    不少市民平时在家时,都十分注意防范安全隐患.消防部门有关专家提示,对于上班族每天工作的办公室来说,同样存在不少容易被忽视的不安全因素,上班族的安全意识一定不能放松,尤其是要防范电气火灾隐患. 办公室电 ...

  3. win10休眠设置_电脑总是“打瞌睡”?教你如何简单关闭自动休眠

    电脑休眠指的是将当前处于运行状态的数据保存在硬盘中,整机完全停止供电.通常电脑的自动休眠是有一个电源计划的,电脑如果在设定的时间内没有使用,那么就会进入自动休眠状态. 然而许多人长时间不操作电脑,只是 ...

  4. 如何关闭移动硬盘的自动休眠功能

    移动硬盘一般都有自动休眠功能,即连接电脑长时间不用后会自动休眠.该功能的初衷是好的,可以保护移动硬盘,延迟使用寿命.但对于使用者来讲,有时却是很烦恼的.因为当移动硬盘休眠后,想幻醒是需要时间的.具体时 ...

  5. 处理win10系统自动休眠bug

    最近有win10系统用户遇到一个很棘手的问题,明明已经禁止了睡眠,设置从不关闭显示器,从不进入睡眠,只要不动鼠标,还是会在2分钟或3分钟自动进入睡眠状态,很是麻烦.如果遇到win10系统自动休眠bug ...

  6. 解决硬盘自动休眠问题

    我的笔记本型号是 机械革命x6 ,cpu i5-4210M ,显卡 GTX 860M ,硬盘 128SSD+1T机械硬盘 15年刚入手的时候发现了一个问题,打联盟的时候,时间长不打字突然打字发点什么电 ...

  7. 远程计算机一键休眠,nuc8i5远程登录-windows10频繁自动休眠解决方案

    nuc8i5远程登录-windows10频繁自动休眠解决方案 2021-05-08 16:49:11 0点赞 0收藏 0评论 nuc8i5远程登录-windows10频繁自动休眠解决方案 远程开机后, ...

  8. VBS+迷你QQ,实现机器远程休眠和电驴的自动休眠

    VBS+迷你QQ,实现机器远程休眠和电驴的自动休眠 首先到http://www.xdowns.com/soft/40/125/2006/Soft_28470.html下载迷你QQ,解压后运行MiniQ ...

  9. 计算机休眠移动硬盘不休眠,关闭硬盘盒自动休眠软件

    关闭硬盘盒自动休眠软件是防止硬盘盒子自动休眠,配合VL71主控芯片使用,提供详细教程分享,让你的硬盘盒子不会自动休眠了,提升电脑的性能! 软件介绍 大部分硬盘盒为了降低硬盘损耗,会在3-5分钟无操作的 ...

最新文章

  1. 深度学习的算法实践和演进
  2. 物流系统高可用架构案例
  3. vivado如何实现增量编译,加快布局布线
  4. 第一行代码学习笔记第六章——详解持久化技术
  5. leetcode(2)495——提莫攻击(C++),运算符优先级(+=,?,+,-)
  6. 假笨说-谨防JDK8重复类定义造成的内存泄漏
  7. 探索 .NET Core 依赖注入的 IServiceCollection
  8. nssl1469-W【dp】
  9. [css] 怎么才能让图文不可复制?
  10. table隔行变色与table单元格根据条件更改字体颜色
  11. 使用SDL2中SDL_CreateWindow()函数时报错跳进wincore.cpp(wntdll.pbd not load)
  12. 交换机中对于tagged帧和untagged帧的处理
  13. php 极光推送别名数组,PHP使用极光推送-Go语言中文社区
  14. 【Windows】Win10强制删除文件夹
  15. centos6.5安装谷歌浏览器+谷歌浏览器flash插件安装+谷歌浏览器pdf阅读器安装
  16. Protecting Against DNN Model Stealing Attacks 论文阅读心得
  17. 杭州云栖大会“弹性计算用户实践专场”等你来
  18. 动态规划 自然数拆分
  19. JAVA:Java Swing 练习题
  20. linux startx无效_startx启动失败的几个解决方法

热门文章

  1. pg2.OperationalError: could not connect to server: Connection timed out (0x0000274C/10060)
  2. easyexcel导出excel文件合并相同单元格数据
  3. 大动作|阿里云扩招5000人!云计算、AI抢夺全球人才
  4. eve-ng ubuntu 20.04 设置iptables
  5. xcode 配置wechat_Xcode 真机调试微信支付 提示 mainfest.json配置APPID和订单的appid 不一致...
  6. 安装java环境----血泪版
  7. 图片按指定比例缩放并压缩至指定大小,解决保存图片文件体积过大bug。
  8. time.h时间函数
  9. Linux 常用基本命令 ps top kill
  10. CodeForces 858C Did you mean... 、 CodeForces 858D Polycarp's phone book!黑科技