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

<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

	    //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.观察 数据库 变化

    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

    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 

    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);

获取休眠时间

    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,于是再次进入到该方法
//通过不断进入该方法,不断评估是否根据用户动作亮、熄屏等

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.权限

<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();

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

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

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 

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写入节点

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

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

diff --git a/packages/apps/Settings/AndroidManifest.xml b/packages/apps/Settings/AndroidManifest.xml
index 52841dd..5764d40 100755
--- a/packages/apps/Settings/AndroidManifest.xml
+++ b/packages/apps/Settings/AndroidManifest.xml
@@ -86,6 +86,7 @@
     <uses-permission android:name="android.permission.PEERS_MAC_ADDRESS"/>
     <uses-permission android:name="android.permission.MANAGE_NOTIFICATIONS"/>
     <uses-permission android:name="android.permission.DELETE_PACKAGES"/>
+	<uses-permission android:name="android.permission.WAKE_LOCK" />
 
     <application android:label="@string/settings_label"
             android:icon="@mipmap/ic_launcher_settings"
@@ -3272,6 +3273,9 @@
             android:enabled="@bool/config_has_help" />
 <activity
     android:name="com.android.settings.display.ScreenScaleActivity"/>
+	
+        <service android:name=".WakeLockService" >
+        </service>	
         <!-- This is the longest AndroidManifest.xml ever. -->
     </application>
 </manifest>
diff --git a/packages/apps/Settings/src/com/android/settings/DisplaySettings.java b/packages/apps/Settings/src/com/android/settings/DisplaySettings.java
index 2b52b39..f084af8 100755
--- a/packages/apps/Settings/src/com/android/settings/DisplaySettings.java
+++ b/packages/apps/Settings/src/com/android/settings/DisplaySettings.java
@@ -110,7 +110,8 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
     private String mProduct;
 	private ListPreference	mDensityListPreference;
 	DisplayMetrics dm;
-	private String density_olddegree;	
+	private String density_olddegree;
+	private Intent wakelock_intent;	
 
     @Override
     protected int getMetricsCategory() {
@@ -469,12 +470,19 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
     @Override
     public boolean onPreferenceChange(Preference preference, Object objValue) {
         final String key = preference.getKey();
-        if (KEY_SCREEN_TIMEOUT.equals(key)) {
+		final Context context = preference.getContext();
+        if (KEY_SCREEN_TIMEOUT.equals(key)) {			
+			wakelock_intent = new Intent(context,WakeLockService.class);			
             try {
                 int value = Integer.parseInt((String) objValue);
                 if (value == 0) {
                     value = Integer.MAX_VALUE;
-                }
+					context.startService(wakelock_intent);
+					SystemProperties.set("persist.sys.wakeLock","1");
+                }else {
+					context.stopService(wakelock_intent);
+					SystemProperties.set("persist.sys.wakeLock","0");
+				}
                 Settings.System.putInt(getContentResolver(), SCREEN_OFF_TIMEOUT, value);
                 updateTimeoutPreferenceDescription(value);
             } catch (NumberFormatException e) {
diff --git a/packages/apps/Settings/src/com/android/settings/HdmiReceiver.java b/packages/apps/Settings/src/com/android/settings/HdmiReceiver.java
index aff17a5..604997c 100755
--- a/packages/apps/Settings/src/com/android/settings/HdmiReceiver.java
+++ b/packages/apps/Settings/src/com/android/settings/HdmiReceiver.java
@@ -33,6 +33,11 @@ import android.widget.Toast;
 import android.os.DisplayOutputManager;
 import com.android.settings.R;
 
+import android.provider.Settings;
+import android.os.Bundle;
+import android.content.Intent;
+import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+
 public class HdmiReceiver extends BroadcastReceiver {
    private final String HDMI_ACTION = "android.intent.action.HDMI_PLUG";
    private final String BOOT_ACTION="android.intent.action.BOOT_COMPLETED";
@@ -47,6 +52,8 @@ public class HdmiReceiver extends BroadcastReceiver {
    private SharedPreferences preferences;
    private File DualModeFile = new File("/sys/class/graphics/fb0/dual_mode");
    private DisplayOutputManager mDisplayManagement = null;
+   private Intent wakelock_intent;
+   
    @Override
    public void onReceive(Context context, Intent intent) {
        mcontext = context;
@@ -125,6 +132,18 @@ public class HdmiReceiver extends BroadcastReceiver {
                   SystemProperties.set("sys.abc_switch", "1");
            //InitDualModeTask initDualModeTask=new InitDualModeTask();
            //initDualModeTask.execute();
+	   	   try {
+		       long screen_off_timeout = Settings.System.getLong(context.getContentResolver(), SCREEN_OFF_TIMEOUT,30000);
+			   boolean enable_wakeLock = (SystemProperties.getInt("persist.sys.wakeLock", 0) == 1); 
+			   Log.d("gatsby","HdmiReceiver HdmiReceiver enable_wakeLock ->"+enable_wakeLock);
+			   wakelock_intent = new Intent(context,WakeLockService.class);	
+			   if((screen_off_timeout == Integer.MAX_VALUE) && enable_wakeLock){
+			      Log.d("gatsby","HdmiReceiver HdmiReceiver");
+			   	  context.startService(wakelock_intent);			
+			   }
+		  }catch (NumberFormatException e) {
+                Log.e("gatsby", "could not persist screen timeout setting", e);
+          }	   
        }
 
    }
diff --git a/packages/apps/Settings/src/com/android/settings/WakeLockService.java b/packages/apps/Settings/src/com/android/settings/WakeLockService.java
new file mode 100755
index 0000000..8c021cd
--- /dev/null
+++ b/packages/apps/Settings/src/com/android/settings/WakeLockService.java
@@ -0,0 +1,52 @@
+package com.android.settings;
+
+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) {
+		return null;
+	}
+
+	@Override
+	public void onCreate() {
+		super.onCreate();
+		Log.d("gatsby","WakeLockService onCreate");
+		acquireWakeLock();
+	}
+
+	@Override
+	public void onDestroy() {
+		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;
+		}
+	}
+
+}

 测试 方法

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是系统用户

 

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

  

 

 

  

原文地址:https://www.cnblogs.com/crushgirl/p/15630106.html