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

     

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

      

     

     

      

  • 相关阅读:
    反向映射和写时复制
    内存分析的好blog
    minicom使用
    tee的妙用
    网络带宽
    mem analyse
    linux 应用层常用API/命令
    ubuntu 库依赖问题
    Python基础学习笔记(一:hello world)
    第7章 取消与关闭
  • 原文地址:https://www.cnblogs.com/crushgirl/p/15630106.html
Copyright © 2020-2023  润新知