Android 休眠(二)真.永久不休眠

Platform: RK3288
OS: Android 7.1.2
Kernel: 4.4.143 

 

adb shell settings get system screen_off_timeout

 一.SettingsProvider def_screen_off_timeout

1.1.frameworks\base\packages\SettingsProvider\res\values\defaults.xml 

欸为什么是0x7fffffff  换算 十进制 是2147483647  

ro.rk.screenoff_time 也是2147483647

整形最大取值就是 2147483647 换算成天数也就是24.85

1
2
3
4
<resources>
    <bool name="def_dim_screen">true</bool>
    <integer name="def_screen_off_timeout">0x7fffffff</integer>
    <integer name="def_sleep_timeout">-1</integer>

1.2.frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\DatabaseHelper.java

1
2
3
//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)));

1.3.frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java

a.观察 数据库 变化

1
2
3
4
5
6
7
8
9
10
11
12
    class SettingsObserver extends ContentObserver {
        SettingsObserver(Handler handler) {
            super(handler);
        }
 
        void observe() {
            // Observe all users' changes
……………………………………………………………………………………
            resolver.registerContentObserver(Settings.System.getUriFor(
                    Settings.System.SCREEN_OFF_TIMEOUT), false, this,
                    UserHandle.USER_ALL);   
    

b.updateSettings  mLockScreenTimeout

1
2
3
4
5
6
7
8
    public void updateSettings() {
        ContentResolver resolver = 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);

c.postDelayed 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void updateLockScreenTimeout() {
    synchronized (mScreenLockTimeout) {
        boolean enable = (mAllowLockscreenWhenOn && mAwake &&
                mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
        if (mLockScreenTimerActive != enable) {
            if (enable) {
                if (localLOGV) Log.v(TAG, "setting lockscreen timer");
                mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
            } else {
                if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
                mHandler.removeCallbacks(mScreenLockTimeout);
            }
            mLockScreenTimerActive = enable;
        }
    }
}

1.4.frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java

mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver,
Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT,
UserHandle.USER_CURRENT);

获取休眠时间

1
2
3
4
5
6
7
8
9
10
11
12
13
private int getScreenOffTimeoutLocked(int sleepTimeout) {
    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);
} 

//根据nextTimeOut延迟发送信息,信息被处理后,将重新调用updatePowerStateLocked,于是再次进入到该方法
//通过不断进入该方法,不断评估是否根据用户动作亮、熄屏等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private void updateUserActivitySummaryLocked(long now, int dirty) {
    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) {
  
            //获取进入休眠状态的时间sleepTimeout
            //getSleepTimeoutLocked中会判断休眠时间和屏幕熄灭时间的关系
            //如果休眠时间sleepTimeout小于屏幕熄灭时间screenOfftime, 
            //则休眠时间被调整为屏幕熄灭时间,因为屏幕亮屏状态下,终端不能进入休眠
            final int sleepTimeout = getSleepTimeoutLocked();
  
            //获取屏幕熄灭的时间
            final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
  
            //获取屏幕变暗的时间
            final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
……………………………………………………
                if (mUserActivitySummary != 0 && nextTimeout >= 0) {
                    Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
                    msg.setAsynchronous(true);
                    mHandler.sendMessageAtTime(msg, nextTimeout);
                }
            } else {
                mUserActivitySummary = 0;
            }

 

 二.永久休眠 方案一  WakeLock

 2.1.WakeLock 唤醒锁

a.权限

1
<uses-permission android:name="android.permission.WAKE_LOCK" />  

c.WakeLock 常见的锁

WakeLock 分类如下:
PARTIAL_WAKE_LOCK: 保持CPU 运转 灭屏 关闭键盘背光的情况下
PROXIMITY_SCREEN_OFF_WAKE_LOCK: 基于距离感应器熄灭屏幕。最典型的运用场景是我们贴近耳朵打电话时,屏幕会自动熄灭
SCREEN_DIM_WAKE_LOCK:保持CPU 运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯
SCREEN_BRIGHT_WAKE_LOCK:保持CPU 运转,允许保持屏幕高亮显示,允许关闭键盘灯
FULL_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度
SCREEN_DIM_WAKE_LOCK/SCREEN_BRIGHT_WAKE_LOCK/FULL_WAKE_LOCK:这三种WakeLock都已经过时了 它们的目的是为了保持屏幕长亮 Android官方建议用getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);方式替换 因为比起申请WakeLock 这种方式更简单 还不需要特别申请android.permission.WAKE_LOCK权限
DOZE_WAKE_LOCK/DRAW_WAKE_LOCK:隐藏的分类,系统级别才会用到

WakeLock的flag如下:
ACQUIRE_CAUSES_WAKEUP:点亮屏幕 比如应用接收到通知后,屏幕亮起。
ON_AFTER_RELEASE:释放WakeLock后 屏幕不马上熄灭 保持屏幕亮起一段时间
UNIMPORTANT_FOR_LOGGING:隐藏的flag 系统级别才会用到

b.wakeLock.acquire();  wakeLock.release();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package com.gatsby.wakelockservice;
 
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;
 
public class WakeLockService extends Service {
 
    private WakeLock wakeLock = null;
 
    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }
 
    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        acquireWakeLock();
    }
 
    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        Log.d("gatsby","WakeLockService onDestroy");
        releaseWakeLock();
    }
 
    // 获取电源锁
    private void acquireWakeLock() {
        if (null == wakeLock) {
            PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
            wakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE,
                    "gatsby-wakelockService-TAG");
            if (null != wakeLock) {
                wakeLock.acquire();
            }
        }
    }
 
    // 释放设备电源锁
    private void releaseWakeLock() {
        if (null != wakeLock) {
            wakeLock.release();
            wakeLock = null;
        }
    }
 
}

d.研究一下 源码 先欢迎 四年级学生森下下士  我们的老大哥  小草凡 Android 功耗分析之wakelock

先跟着老大哥 走了一遍源码   

1
2
3
4
5
6
7
8
frameworks/base/core/java/android/os/PowerManager.java
acquire--->acquireLocked---->PowerManagerService.acquireWakeLock
 
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
acquireWakeLock--->acquireWakeLockInternal---->updatePowerStateLocked---->updateSuspendBlockerLocked---->mWakeLockSuspendBlocker.acquire---->PowerManagerService$SuspendBlockerImpl.acquire---->nativeAcquireSuspendBlocker
 
frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp
nativeAcquireSuspendBlocker---->acquire_wake_lock

hardware\libhardware_legacy\power\power.c 

1
2
3
4
5
6
7
8
9
12-06 12:10:48.884   457   855 I power   : release_wake_lock id='PowerManagerService.WakeLocks'
12-06 12:10:59.157   457   457 I power   : acquire_wake_lock lock=1 id='PowerManagerService.WakeLocks'
12-06 12:10:59.193   457   923 I power   : release_wake_lock id='PowerManagerService.WakeLocks'
12-06 12:10:59.852   457   568 I power   : acquire_wake_lock lock=1 id='PowerManagerService.Broadcasts'
12-06 12:10:59.854   457   568 I power   : release_wake_lock id='PowerManagerService.Display'
12-06 12:11:00.347   457   457 I power   : release_wake_lock id='PowerManagerService.Broadcasts'
12-06 12:11:04.196   457   587 I power   : acquire_wake_lock lock=1 id='PowerManagerService.WakeLocks'
12-06 12:11:04.341   457   457 I power   : release_wake_lock id='PowerManagerService.WakeLocks'
12-06 12:11:04.854   457   598 I power   : acquire_wake_lock lock=1 id='KeyEvents'

 /sys/power/wake_lock写入节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
acquire_wake_lock(int lock, const char* id)
{
    initialize_fds();
 
//    ALOGI("acquire_wake_lock lock=%d id='%s'\n", lock, id);
 
    if (g_error) return g_error;
 
    int fd;
    size_t len;
    ssize_t ret;
 
    if (lock != PARTIAL_WAKE_LOCK) {
        return -EINVAL;
    }
 
    fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];
 
    ret = write(fd, id, strlen(id));
    if (ret < 0) {
        return -errno;
    }
 
    return ret;
}
 
int
release_wake_lock(const char* id)
{
    initialize_fds();
 
//    ALOGI("release_wake_lock id='%s'\n", id);
 
    if (g_error) return g_error;
 
    ssize_t len = write(g_fds[RELEASE_WAKE_LOCK], id, strlen(id));
    if (len < 0) {
        return -errno;
    }
    return len;
}

龙套三人组:听不见!重来!/根本听不见!再说一遍!/听不见!重来/这么小声还想开军舰! 到了power这里还不算完  

到 android 休眠唤醒机制分析(一) — wake_lock

1
2
3
static struct wake_lock xh_charge_display_lock;// 申请锁
wake_lock_init(&xh_charge_display_lock, WAKE_LOCK_SUSPEND, "xh_charge_display_lock");// WAKE_LOCK_SUSPEND 阻止进入深度休眠模式
wake_lock(&xh_charge_display_lock);//保管锁

2.2.patch

 测试 方法

1
2
am startservice -n  com.android.settings/com.android.settings.WakeLockService
am stopservice -n   com.android.settings/com.android.settings.WakeLockService

 查看锁   dumpsys power|grep -i wake

通过adb命令查看WakeLock锁的个数: dumpsys power    uid=1000是系统用户

 

三.永久不休眠 方案二  死循环休眠  

  

 

 

  

posted @   CrushGirl  阅读(4170)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示