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是系統用戶

 

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

  

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM