设置中代码文件:

./packages/apps/Settings/src/com/android/settings/fuelgauge/BatterySaverSettings.java

Android Battery android battery saver_泛型接口


节能助手开启或关闭时,调用onSwitchChanged方法,参数isChecked表示节能助手处于开启(true)或关闭(false)状态。开启时isChecked为true,发送消息mStartMode开启新线程开启省电模式,这里会等待500ms;否则关闭省电模式。


PowerMS 中提供调用接口文件:

./frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

frameworks\base\services\core\java\com\android\server\BatteryService.java

Android Battery android battery saver_泛型接口_02


Android Battery android battery saver_android_03



mIsPowered变量表示充电状态,true表示正在充电(已接入电源),否则为false;setLowPowerModeInternal方法中首先判断mIsPowered是否处于充电状态,如果正在充电则直接返回false,表示不允许设置省电模式(省电模式会在设备充电时自动关闭)。

接着根据参数mode的值设置系统变量”low_power”(LOW_POWER_MODE),并设置变量mLowPowerModeSetting(Current state of the low power mode setting.表示设置低电模式的当前状态)

接下来设置变量mAutoLowPowerModeSnoozing(The user turned off low power mode below the trigger level,表示电量低于省电模式的触发点时,关闭省电模式)。该变量值是由mAutoLowPowerModeConfigured(自动开启省电模式的当前状态,即数据库字段“low_power_trigger_level”是否为0的值;不为0时表示配置了低电量触发值,该变量为true)和mBatteryLevelLow(True if the battery level is currentlyconsidered low.如果电池电量低为true)这两个变量决定的。当电量低并且允许自动设置省电模式时,如果此时省电模式是开启的,就要设置mAutoLowPowerModeSnoozing的值为false;如果省电模式是关闭的,就要设置mAutoLowPowerModeSnoozing的值为true。就是要求mAutoLowPowerModeSnoozing变量与省电模式的逻辑保持一致。


mAutoLowPowerModeSnoozing  true ,就是表示是否在低电量模式值下时,用户关闭了battery saver 。

mAutoLowPowerModeConfigured  true,如果用户定制了低电量阈值low_power_trigger_level

BatteryService.java 中设置mBatteryLevelLow ,这个低电量的阈值是由 low_power_trigger_level与framework 中配置的 config_lowBatteryWarningLevel 较小者决定的。


调用updateLowPowerModeLocked方法。

最后直接返回true,表示省电模式设置成功。

首先判断如果当前正在充电并且开启了省电模式,则关闭省电模式,将“low_power”字段设置为0,mLowPowerModeSetting置为false。

接着创建两个临时变量autoLowPowerModeEnabled和lowPowerModeEnabled。autoLowPowerModeEnabled(当前没有充电,自动开启省电模式,电量低于省电模式的电量触发点时不关闭省电模式,电池电量低,以上条件均满足时为true);lowPowerModeEnabled(当mLowPowerModeSetting或autoLowPowerModeEnabled为真时,则设置为true);根据lowPowerModeEnabled临时变量值和mLowPowerModeEnabled(true表示设备处于省电模式,全局变量)判断是否执行省电模式的功能。当两者状态不一致时,更新mLowPowerModeEnabled状态值。


这里如果系统bootcomplete  没有完成,则等完成后再执行对应的runnable.


调用powerHintInternal方法;之后使用后台线程BackgroundThread处理事件,会先后发送action为ACTION_POWER_SAVE_MODE_CHANGING和ACTION_POWER_SAVE_MODE_CHANGED的广播,注意这两个广播中设置了addFlags为Intent.FLAG_RECEIVER_REGISTERED_ONLY,表示只有动态定义的广播接收器才能接收到该广播,在发送ACTION_POWER_SAVE_MODE_CHANGING广播的时候传递数据“mode”的值。在发送这两个广播中间设置LowPowerModeListener,调用该接口的onLowPowerModeChanged方法。


frameworks\base\services\core\java\com\android\server\power\BatterySaverPolicy.java

这个类指定了哪些模块进入battery Saver 模式会进入省电处理,listener.getServiceType()指定模块服务的类型

for (int i = 0; i < listeners.size(); i++) {
    final PowerManagerInternal.LowPowerModeListener listener = listeners.get(i);
    final PowerSaveState result =
            mBatterySaverPolicy.getBatterySaverPolicy(
                    listener.getServiceType(), lowPowerModeEnabled);
    listener.onLowPowerModeChanged(result);
}




这里先分析一下powerHintInternal方法的处理。

powerHintInternal(POWER_HINT_LOW_POWER,lowPowerModeEnabled ? 1 : 0)。注意:POWER_HINT_LOW_POWER是在hardware/libhardware/include/hardware/power.h中定义的。

JNI层函数调用

frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp。

调用静态方法nativeSendPowerHint,gPowerModule是power_module类型的结构体,

下面分析一下power_module(电源模块)结构体。每个硬件模块必须有一个名为HAL_MODULE_INFO_SYM的数据结构,这个数据结构的字段必须以hw_module_t开始后跟模块的详细信息。该结构体中定义了一个hw_module_t结构体(common)和三个函数(init,setInteractive,powerHint)。Power_module的定义如下:

Typedefstruct power_module {

         Struct hw_module_t common;

         Void (*init) (struct power_module*module);

         Void (*setInteractive)(structpower_module *module, int on);

         Void (*powerHint)(struct power_module*module, power_hint_t hint, void *data);

}power_module_t;

1)        (*init)():设置电源管理在运行时启动的设置动作,例如设置默认的CPU频率参数。只供由PowerManagerService加载的Power HAL实例调用。

2)        (*setInteractive)():该方法用来执行关闭屏幕后进入非交互状态,同时打开屏幕之前进入交互状态;参数on表示当系统转变为交互状态或唤醒状态时是一个非0值,当转变为非交互状态或asleep状态时为0;该方法典型的操作就是打开或关闭设备,调整CPU频率参数。当系统进入非交互状态时该函数还可以调用相应接口允许内核挂起系统进入低电睡眠状态;当系统进入交互状态时禁止低电挂起。

3)        (*powerHint)():根据电源需求传递提示信息,这可能会导致  CPU频率的调整和一些控制项的功耗/性能的调整。可能的提示是:

POWER_HINT_VSYNC(垂直同步):前台应用从SurfaceFlinger中启动或停止请求一个VSYNC脉冲。如果该应用已开始请求VSYNC,然后CPU和GPU很快加载,可能会适当加快CPU和存储器速度。该参数为非0值表示需要请求VSYNC,若为0表示不再需要请求VSYNC。

POWER_HINT_INTERACTION:用户与设备交互,例如触摸屏事件。CPU和GPU会加速加载,适当提高CPU频率,存储器总线,此参数暂时没有使用。

POWER_HINT_LOW_POWER:省电模式的激活或关闭。省电模式是以消耗性能为代价的。非0值表示开启省电模式,为0时表示已关闭省电模式。


Native层函数调用IPowerManager.cpp

frameworks/native/services/powermanager/IPowerManager.cpp

采用binder通信方式,将POWER_HINT_LOW_POWER和开启标志发送到服务端处理。


frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\policy\CallbackController.java

package com.android.systemui.statusbar.policy;

public interface CallbackController<T> {
    void addCallback(T listener);
    void removeCallback(T listener);
}

frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\policy\BatteryController.java


public interface BatteryController extends DemoMode, Dumpable,
        CallbackController<BatteryStateChangeCallback> {

...

interface BatteryStateChangeCallback {
    default void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {}
    default void onPowerSaveChanged(boolean isPowerSave) {}
}

}

frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\policy\BatteryControllerImpl.java

public class BatteryControllerImpl extends BroadcastReceiver implements BatteryController {
    private static final String TAG = "BatteryController";

    public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";

    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    private final ArrayList<BatteryController.BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
    private final PowerManager mPowerManager;
    private final Handler mHandler;
...............
@Override
public void addCallback(BatteryController.BatteryStateChangeCallback cb) {
    synchronized (mChangeCallbacks) {
        mChangeCallbacks.add(cb);
    }
    if (!mHasReceivedBattery) return;
    cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
    cb.onPowerSaveChanged(mPowerSave);
}

@Override
public void removeCallback(BatteryController.BatteryStateChangeCallback cb) {
    synchronized (mChangeCallbacks) {
        mChangeCallbacks.remove(cb);
    }
}

@Override
public void onReceive(final Context context, Intent intent) {
    final String action = intent.getAction();
    if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
        if (mTestmode && !intent.getBooleanExtra("testmode", false)) return;
        mHasReceivedBattery = true;
        mLevel = (int)(100f

}


这里是一种很巧妙的利用接口的设计,CallbackController  类是一个泛型接口类,需要继承者实现添加与移除对应的泛型接口的方法,但是泛型类只需等待调用移除与添加接口调用者去实现。

BatteryController 继承CallbackController 同时定义了CallbackController 的泛型类,从而使相互继承实现。


BatteryControllerImpl 实现BatteryController ,从而实现了add 与remove 接口的函数实现,其泛型接口的具体实现等待注册者去实现,泛型接口就要是根据监听广播再回调其接口

ACTION_POWER_SAVE_MODE_CHANGING

ACTION_POWER_SAVE_MODE_CHANGED

ACTION_BATTERY_CHANGED

出发firePowerSaveChanged方法,遍历BatteryStateChangeCallback对象,并调用接口的onPowerSaveChanged方法。这里为什么是一个列表呢? (凡实现了该接口的类,并调用添加接口均在这个列表中保存)。

ArrayList<BatteryStateChangeCallback>mChangeCallbacks =newArrayList<>();


frameworks\base\packages\SystemUI\src\com\android\systemui\BatteryMeterView.java

BatteryMeterView类实现了BatteryController.BatteryStateChangeCallback接口,回调onPowerSaveChanged方法,在onPowerSaveChanged方法中调用invalidate方法会刷新界面。

在getColorForLevel方法中,如果处于省电模式,则返回省电模式设置的颜色值:battery_saver_mode_color(#fff4511e)


frameworks\base\packages\SystemUI\src\com\android\systemui\power\PowerUI.java

frameworks\base\packages\SystemUI\src\com\android\systemui\power\PowerNotificationWarnings.java

这里显示低电量通知,并可以根据通知来打开batterySaver.


判断hasBatterySettings方法返回值,在该方法中调用了Intent.resolveActivity方法,该方法的含义是:如果当前设备上不存在可接收某种隐式Intent的应用程序,则调用startActivity()的应用程序将会崩溃。为了预先判断一下是否存在可接收Intent的应用程序,调用Intent对象的resolveActivity方法。如果结果非空,则表示至少存在一个可处理该Intent的应用程序,并且可安全调用startActivity方法。如果结果为null,请勿再使用该Intent,并尽可能关闭那些会发起该Intent的功能。

为该Notification添加一个PendingIntent(android.settings.BATTERY_SAVER_SETTINGS),因此调用Notification.Builder.setContentIntent方法。目前没有该action的广播接收器。 因此点击该通知时没有反应。




省电的模块服务:


降低屏幕亮度

在PowerManagerService中更新电源状态的时候调用updateDisplayPowerStateLocked方法时,会获取省电模式状态,保存在DisplayPowerRequest的lowPowerMode属性中。

mDisplayPowerRequest.lowPowerMode =mLowPowerModeEnabled;

最终调用到DisplayPowerController类中,在updatePowerState方法中设置屏幕亮度值,如果处于省电模式状态,设置屏幕亮度值减半处理;PowerMnagerInternal.LowPowerModeListener

此处回过头来看看PowerManagerService的updateLowPowerModeLocked方法中生成的PowerMnagerInternal.LowPowerModeListener数组。该数组是由所有实现PowerMnagerInternal.LowPowerModeListener接口的类组成的。

取消震动效果:VibratorService.java


frameworks/base/services/core/java/com/android/server/VibratorService.java

在systemReady方法中注册省电模式监听器,当省电模式发生改变时回调onLowPowerModeChanged方法,该方法中调用updateInputDeviceVibrators方法。

在updateInputDeviceVibrators方法中获取省电模式状态。

mLowPowerMode = mPowerManagerInternal.getLowPowerModeEnabled();

VibratorService类中startVibrationLocked方法负责震动效果,首先判断是否处于省电模式,若为省电模式直接返回,不再做震动操作。

取消动画设置:WindowManagerService.java

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

         在WindowManagerService的构造方法中,注册省电模式的监听器,当回调onLowPowerModeChanged方法时,比较mAnimationDisabled(窗口动画的使能状态)与省电模式使能状态,如果不相等则为mAnimationDisabled赋值并调用dispatchNewAnimatorScaleLocked方法。

在diapatchNewAnimatorScaleLocked方法中发送H.NEW_ANIMATOR_SCALE消息。

mH接收到H.NEW_ANIMATOR_SCALE消息时,是如何处理的呢?首先调用getCurrentAnimatorScale方法获取当前动画持续时间比,如果处于省电模式状态则返回0,不再开启动画效果。