我的编程空间,编程开发者的网络收藏夹
学习永远不晚

初识Android PowerManagerService省电模式

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

初识Android PowerManagerService省电模式

前言

最近遇到一些关于省电模式、电量消耗、Doze模式,等等相关问题。于是,我决定对它们进行彻底分析,那就先从省电模式开启。

功能介绍

可以在 Settings->Battery->Battery Saver 界面进行省电模式的操作,如下图:

界面中有三个开关,它们的意思如下:

  • Use Battery Saver : 打开/关闭省电模式。
  • Set a Schedule : 设置一个电量百分比阈值,当电量低于这个阈值的时候,就会触发省电模式。设置阈值的界面如下图

  • Turn off when charging : 这个开关的意思不能按表面意思理解,它真正的意思是,省电模式被打开的情况下,拔掉充电器或者重启,如果电量百分比大于90%,那么不会再次开启省电模式。

由于省电模式的功能涉及的代码比较多,本文只分析省电模式环境的初始化,涉及的文件路径如下

  • frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
  • frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
  • frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
  • frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java

环境

省电模式属于 PowerManagerService 的一部分功能,下面列出与省电模式环境相关的代码:

PowerManagerService(Context context, Injector injector) {
    super(context);
    // ...

    // Class to decide whether to turn on battery saver mode for specific services.
    mBatterySaverPolicy =
            mInjector.createBatterySaverPolicy(mLock, mContext, mBatterySavingStats);

    // Responsible for battery saver mode transition logic.
    mBatterySaverController = mInjector.createBatterySaverController(mLock, mContext,
            mBatterySaverPolicy, mBatterySavingStats);

    //  Decides when to enable / disable battery saver.
    mBatterySaverStateMachine = mInjector.createBatterySaverStateMachine(mLock, mContext,
            mBatterySaverController);
   
    // ...
}

与省电模式相关的类有三个,BatterySaverPolicyBatterySaverControllerBatterySaverStateMachine

介绍下三个类的作用:

  • BatterySaverPolicy : 省电模式的策略。
  • BatterySaverController : 控制省电模式的打开/关闭,并根据省电模式策略,控制某些功能,例如控制 CPU 频率。
  • BatterySaverStateMachine : 一个状态机,管理着省电模式相关的状态,并通过 BatterySaverController 控制省电模式的开启/关闭。

这里创建三个类对象的方式,就是调用构造函数,下面大致看下这几个构造函数

public BatterySaverPolicy(Object lock, Context context, BatterySavingStats batterySavingStats) {
    super(BackgroundThread.getHandler());
    mLock = lock;
    mHandler = BackgroundThread.getHandler();
    mContext = context;
    mContentResolver = context.getContentResolver();
    mBatterySavingStats = batterySavingStats;
}
public BatterySaverController(Object lock, Context context, Looper looper,
        BatterySaverPolicy policy, BatterySavingStats batterySavingStats) {
    mLock = lock;
    mContext = context;
    mHandler = new MyHandler(looper);
    mBatterySaverPolicy = policy;
    // 注意,监听了 policy change
    mBatterySaverPolicy.addListener(this);
    
    // FileUpdater 负责向底层文件节点写值,例如向CPU频率的节点写值,控制CPU频率
    mFileUpdater = new FileUpdater(context);
    
    mBatterySavingStats = batterySavingStats;

    // 刷新获取省电模式的缓存
    PowerManager.invalidatePowerSaveModeCaches();
}
public BatterySaverStateMachine(Object lock,
        Context context, BatterySaverController batterySaverController) {
    mLock = lock;
    mContext = context;
    mBatterySaverController = batterySaverController;
    mState = STATE_OFF;
    // Whether or not battery saver should be "sticky" when manually enabled.
    // false
    // 注意了,值为 false,表明这个 battery saver sticky 功能是打开的
    mBatterySaverStickyBehaviourDisabled = mContext.getResources().getBoolean(
            com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled);
            
    //  Config flag to track default disable threshold for Dynamic power savings enabled battery saver.
    // 80
    mDynamicPowerSavingsDefaultDisableThreshold = mContext.getResources().getInteger(
            com.android.internal.R.integer.config_dynamicPowerSavingsDefaultDisableThreshold);
}

BatterySaverController 的构造函数,只需要注意一点,那就是它监听了省电模式策略的改变,因为这个策略会影响省电模式。

BatterySaverStateMachine 的构造函数,需要注意 mBatterySaverStickyBehaviourDisabled,它表示是否支持 battery saver sticky 功能。注意了,它的值 false,但是表示支持这个功能,而不是不支持。mDynamicPowerSavingsDefaultDisableThreshold 是与动态省电模式相关,读者可自行分析。

继续看 PowerManagerService 对省电模式环境的初始化代码

public void systemReady(IAppOpsService appOps) {
    synchronized (mLock) {
        // ...
        mBatterySaverController.systemReady();
        mBatterySaverPolicy.systemReady();
        
        // ...
    }   
}

首先看看 BatterySaverController#systemRead()

public void systemReady() {
    // 监听这些东西,来控制 battery saver
    final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    filter.addAction(Intent.ACTION_BATTERY_CHANGED);
    filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
    filter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
    mContext.registerReceiver(mReceiver, filter);

    // 如果 Runtime 重启,那么读取 /data/system/battery-saver/default-values.xml 保存的数据,否则删除这个文件。
    mFileUpdater.systemReady(LocalServices.getService(ActivityManagerInternal.class)
            .isRuntimeRestarted());
    // 这里的处理逻辑为空
    mHandler.postSystemReady();
}

BatterySaverController 会监听屏幕亮灭以及 Doze 模式的广播。

不过只有屏幕亮灭,会实际地影响省电模式,因为屏幕的亮灭会影响交互模式,而省电模式策略会根据手机是否处于交互模式而配置不同的策略。目前,在策略中,只有 CPU 频率受影响。

再来看看 BatterySaverPolicy#systemReady()

public void systemReady() {
    ConcurrentUtils.wtfIfLockHeld(TAG, mLock);

    // 下面两个字段,目前没有值,但是会控制省电模式策略,进而影响省电模式
    mContentResolver.registerContentObserver(Settings.Global.getUriFor(
            Settings.Global.BATTERY_SAVER_CONSTANTS), false, this);
    mContentResolver.registerContentObserver(Settings.Global.getUriFor(
            Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS), false, this);

    // 无障碍相关
    final AccessibilityManager acm = mContext.getSystemService(AccessibilityManager.class);
    acm.addAccessibilityStateChangeListener(enabled -> mAccessibilityEnabled.update(enabled));
    mAccessibilityEnabled.initialize(acm.isEnabled());

    // 汽车相关
    UiModeManager uiModeManager = mContext.getSystemService(UiModeManager.class);
    uiModeManager.addOnProjectionStateChangedListener(UiModeManager.PROJECTION_TYPE_AUTOMOTIVE,
            mContext.getMainExecutor(), mOnProjectionStateChangedListener);
    mAutomotiveProjectionActive.initialize(
            uiModeManager.getActiveProjectionTypes() != UiModeManager.PROJECTION_TYPE_NONE);

    // 监听 SettingProvider 的 config 表中,关于 battery_saver 命名空间下的所有字段值。
    // 目前,这些字段都为空,但是这些字段会影响省电模式策略,进而控制省电模式
    DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_BATTERY_SAVER,
            mContext.getMainExecutor(), this);
    mLastDeviceConfigProperties =
            DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BATTERY_SAVER);
    onChange(true, null);
}

BatterySaverPolicy 本身有一个默认的策略,但是可以通过 SettingsProvider 中的一些字段来控制策略,从而控制省电模式影响的功能。但是目前,这些字段的值都为空,因此并不影响分析,后面或许我另写一篇文章,分析如何控制省电模式策略。

继续看 PowerManagerService 对省电模式环境的初始化代码

public void onBootPhase(int phase) {
    synchronized (mLock) {
        if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
            incrementBootCount();

        } else if (phase == PHASE_BOOT_COMPLETED) {
            // ...

            mBatterySaverStateMachine.onBootCompleted();
            
            // ...
        }
    }
}

BatterySaverStateMachine.onBootCompleted() 代码如下:

public void onBootCompleted() {
    putGlobalSetting(Settings.Global.LOW_POWER_MODE, 0);
    runOnBgThread(() -> {

        // 监听数据库字段
        final ContentResolver cr = mContext.getContentResolver();
        // Settings.Global.LOW_POWER_MODE 代表省电模式是否打开
        cr.registerContentObserver(Settings.Global.getUriFor(
                Settings.Global.LOW_POWER_MODE),
                false, mSettingsObserver, UserHandle.USER_SYSTEM);
        // Settings.Global.LOW_POWER_MODE_STICKY 代表 battery saver sticky 功能是否打开
        cr.registerContentObserver(Settings.Global.getUriFor(
                Settings.Global.LOW_POWER_MODE_STICKY),
                false, mSettingsObserver, UserHandle.USER_SYSTEM);
        // Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL 代表触发省电模式的电量百分比
        cr.registerContentObserver(Settings.Global.getUriFor(
                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
                false, mSettingsObserver, UserHandle.USER_SYSTEM);
        // Settings.Global.AUTOMATIC_POWER_SAVE_MODE 代表自动省电模式的类型
        // 类型有三个,根据电量百分比触发,动态省电模式模式,或者none
        cr.registerContentObserver(Settings.Global.getUriFor(
                Settings.Global.AUTOMATIC_POWER_SAVE_MODE),
                false, mSettingsObserver, UserHandle.USER_SYSTEM);
        // Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED 代表是否打开动态省电模式
        cr.registerContentObserver(Settings.Global.getUriFor(
                Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED),
                false, mSettingsObserver, UserHandle.USER_SYSTEM);
        // Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD 代表动态省电模式关闭的阈值
        cr.registerContentObserver(Settings.Global.getUriFor(
                Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD),
                false, mSettingsObserver, UserHandle.USER_SYSTEM);
        // Settings.Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED 表示是否打开了 battery saver sticky auto disable
        // 对应于 Settings->Battery->Battery Saver->Turn off when charging
        cr.registerContentObserver(Settings.Global.getUriFor(
                Settings.Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED),
                false, mSettingsObserver, UserHandle.USER_SYSTEM);
        // Settings.Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL 表示  battery saver sticky auto disable 的阈值
        cr.registerContentObserver(Settings.Global.getUriFor(
                Settings.Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL),
                false, mSettingsObserver, UserHandle.USER_SYSTEM);


        synchronized (mLock) {
            
            // battery saver sticky 功能是否被打开
            final boolean lowPowerModeEnabledSticky = getGlobalSetting(
                    Settings.Global.LOW_POWER_MODE_STICKY, 0) != 0;
            if (lowPowerModeEnabledSticky) {
                mState = STATE_PENDING_STICKY_ON;
            }

            mBootCompleted = true;

            // 读取数据库字段,并根据情况,打开/关闭省电模式
            refreshSettingsLocked();

            // 自动打开/关闭省电模式
            doAutoBatterySaverLocked();
        }
    });
}

这里主要是监听并读取与省电模式相关的数据库字段,由于现在是分析初始化环境,因此这里不分析触发省电模式的代码。这些字段值是什么意思,请注意看注释。

至此,省电模式环境的初始化代码已经分析完毕,你可能对代码中提到的一些概念非常迷惑,我刚开启接触的时候也是一样。为了后面代码分析的顺利进行,现在预备几个知识

  • 当省电模式开启后,只要插入了充电器,系统会自动关闭省电模式。
  • 当处于充电模式,系统是禁止开启省电模式。
  • Battery Saver Sticky : 在省电模式开启的情况下,拔掉充电器,或者系统重启,这个 Battery Saver Sticky 模式就会起效,它会再次开启省电模式。
  • Battery Saver Sticky Auto Disable : 从字面理解意思,就是自动关闭 Battery Saver Sticky 功能。当电量百分比大于某个阈值,默认是90%,在省电模式开启的情况狂下,拔掉充电器或者重启,那么不会再次开启省电模式。

结束

到此这篇关于初识Android  PowerManagerService省电模式的文章就介绍到这了,更多相关Andorra PowerManagerService内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

初识Android PowerManagerService省电模式

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

win10平板模式省电吗

本文小编为大家详细介绍“win10平板模式省电吗”,内容详细,步骤清晰,细节处理妥当,希望这篇“win10平板模式省电吗”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。win10平板模式会省电吗:答:不会省电,和桌
2023-07-01

初识Hadoop的三种安装模式

特点:高可靠性(不怕丢)、高效性(处理速度快)、高容错性ps:使用Hadoop版本:接下来所用到的Hadoop2.8.5,虽然目前Hadoop已经更新到3.x了;但是我们始终秉持一个观点“用旧不用新”,因为毕竟旧版本较为稳定(目前虽然jdk出到版本为16了,但
初识Hadoop的三种安装模式
2021-06-16

Java设计模式初识之备忘录模式详解

备忘录设计模式(MementoDesignPattern)也叫作快照(Snapshot)模式,主要用于实现防丢失、撤销、恢复等功能。本文将通过示例为大家介绍一些备忘录模式的定义与使用,需要的可以参考一下
2022-11-13

电脑显示器黑屏显示省电模式如何解决

这篇文章主要介绍“电脑显示器黑屏显示省电模式如何解决”,在日常操作中,相信很多人在电脑显示器黑屏显示省电模式如何解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”电脑显示器黑屏显示省电模式如何解决”的疑惑有所
2023-07-01

android在root模式下接听来电的方法

使用了Root Tools 来招待命令。https://code.google.com/p/roottools/代码如下:private void answerRingingCall(){ try {
2022-06-06

谷歌 Chrome 108 浏览器桌面端新增省内存 / 省电模式,提高新能 / 延长续航

在地址栏的右侧,Chrome 浏览器会用一个图标注明“内存节省模式已开启”。
谷歌 Chrome 108 浏览器桌面端新增省内存 / 省电模式,提高新能 / 延长续航
2024-04-23

win7系统边休息边下载的离开模式让你省电工作两不误

一、什么是电脑的离开模式Windows的“离开”模式类似于待机(或休眠),待机模式可以关闭大部分设备的电源以达到节电的目的,并且在需要的时候能快速返回到工作状态。但是离开模式更要比待机“技高一筹&rdqu
2023-06-01

Android开发中使用单例模式的一个小的注意点(在私有构造中做一些初始化的问题)

说在最前面:本篇文章不是讲单例模式有哪几种创建方式以及各自的利弊,也不说什么情况下单例模式失效以及内存泄漏等类似面试题,只说个人在应用中想要总结的一个小问题,如果冲着上面说的内容来的,那可以继续找其他的了[笑哭.gif]。 单例模式和其他设
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录