Android battery saver 简单记录

目录

一. battery saver模式的policy

(1) DEFAULT_FULL_POLICY 对应的配置和解释:

(2) OFF_POLICY 对应的配置也就说不使用policy

(3) 获取省电模式下的policy:

二. 对各个参数代码讲解

(1) adjustBrightnessFactor 

 (2) enableAdjustBrightness

(3) advertiseIsEnabled

(4) deferFullBackup

(5) deferKeyValueBackup 

 (6)  disableAnimation 

(7) disableAod

(8) disableLaunchBoost

(9) disableOptionalSensors

 (10) disableSoundTrigger

 (11) disableVibration

(12) enableDataSaver

(13) enableFirewall

 (14) enableNightMode

 (15) enableQuickDoze

(16) filesForInteractive

(17) filesForNoninteractive

(18) forceAllAppsStandby 

(19) forceBackgroundCheck

(20) locationMode

 三. 进入省电模式的入口

四. modem进入低电模式入口

五. 屏幕亮度将会变成原来的50%的流程 

六. 自动进入省电模式

七.低电量广播发送

八. 总结


一. battery saver模式的policy

(1) DEFAULT_FULL_POLICY 对应的配置和解释:

字段 描述 默认值
adjustBrightnessFactor 将亮度调节为原来的百分比 0.5f
advertiseIsEnabled 这是基本属性控制到部分省电的策略,譬如:控制location或者匹配不到对应type true
deferFullBackup 在省电模式下是否延迟备份 true
deferKeyValueBackup 在省电模式下是否延迟备份 true
disableAnimation 在省电模式下Window 动画是否被禁用 false
disableAod 在省电模式下,并且在doze 中是否禁用heads up true
disableLaunchBoost 在省电模式下是否禁用启动boost true
disableOptionalSensors 是否禁用非必要传感器(例如边缘传感器),但是,目前没有找到实现的代码. true
disableSoundTrigger 如果在省电模式下是否禁用声音触发的事件,譬如:语音识别 true
disableVibration 当省电模式模式下,除了来电显示的震动(有条件的震动) true
enableAdjustBrightness 如果在省电模式下,否打开低功耗模式亮度调节 false
enableDataSaver 在省电模式下,是否开启DataSaver模式 false
enableFirewall 是否应在省电模式下开启网络策略防火墙 true
enableNightMode 是否启用夜间模式 true
enableQuickDoze 是否启用快速打瞌睡模式 true
filesForInteractive 激活省电模式且设备处于交互状态时应写入的 [文件名 -> 内容] 列表。 我们用它来更改最大 CPU 频率。 new ArrayMap<>()
filesForNoninteractive 激活省电模式且设备非交互式时应写入的 [文件名 -> 内容] 列表。我们用它来更改最大 CPU 频率。 new ArrayMap<>()
forceAllAppsStandby 是否将所有应用程序置于待机模式 true
forceBackgroundCheck 是否强制后台检查,譬如:强制停止idle UIDs true
locationMode

这是决定省电模式下定位模式的标志。 这以前称为 gpsMode。默认是PowerManager.

LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF

(2) OFF_POLICY 对应的配置也就说不使用policy

字段 描述 默认值
adjustBrightnessFactor 将亮度调节为原来的百分比 1f
advertiseIsEnabled 这是基本属性控制到部分省电的策略,譬如:控制location或者匹配不到对应type false
deferFullBackup 在省电模式下是否延迟备份 false
deferKeyValueBackup 在省电模式下是否延迟备份 false
disableAnimation 在省电模式下Window 动画是否被禁用 false
disableAod 在省电模式下,并且在doze 中是否禁用heads up false
disableLaunchBoost 在省电模式下是否禁用启动boost false
disableOptionalSensors 是否禁用非必要传感器(例如边缘传感器),但是,目前没有找到实现的代码. false
disableSoundTrigger 如果在省电模式下是否禁用声音触发的事件,譬如:语音识别 false
disableVibration 当省电模式模式下,除了来电显示的震动(有条件的震动) false
enableAdjustBrightness 如果在省电模式下,否打开低功耗模式亮度调节 false
enableDataSaver 在省电模式下,是否开启DataSaver模式 false
enableFirewall 是否应在省电模式下开启网络策略防火墙 false
enableNightMode 是否启用夜间模式 false
enableQuickDoze 是否启用快速打瞌睡模式 false
filesForInteractive 激活省电模式且设备处于交互状态时应写入的 [文件名 -> 内容] 列表。 我们用它来更改最大 CPU 频率。 new ArrayMap<>()
filesForNoninteractive 激活省电模式且设备非交互式时应写入的 [文件名 -> 内容] 列表。我们用它来更改最大 CPU 频率。 new ArrayMap<>()
forceAllAppsStandby 是否将所有应用程序置于待机模式 false
forceBackgroundCheck 是否强制后台检查,譬如:强制停止idle UIDs false
locationMode

这是决定省电模式下定位模式的标志。 这以前称为 gpsMode。默认是PowerManager.

LOCATION_MODE_NO_CHANGE

(3) 获取省电模式下的policy:

 通过getBatterySaverPolicy函数获取各个type对应的参数:

SDM4100_AOSP_DEV/LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java

    /**
     * Get the {@link PowerSaveState} based on the current policy level.
     * The result will have {@link PowerSaveState#batterySaverEnabled} and some other
     * parameters when necessary.
     *
     * @param type   type of the service, one of {@link ServiceType}
     * @return State data that contains battery saver data
     */
    public PowerSaveState getBatterySaverPolicy(@ServiceType int type) {
        synchronized (mLock) {
            final Policy currPolicy = getCurrentPolicyLocked();
            final PowerSaveState.Builder builder = new PowerSaveState.Builder()
                    .setGlobalBatterySaverEnabled(currPolicy.advertiseIsEnabled);
            switch (type) {
                case ServiceType.LOCATION:
                    boolean isEnabled = currPolicy.advertiseIsEnabled
                            || currPolicy.locationMode != PowerManager.LOCATION_MODE_NO_CHANGE;
                    return builder.setBatterySaverEnabled(isEnabled)
                            .setLocationMode(currPolicy.locationMode)
                            .build();
                case ServiceType.ANIMATION:
                    return builder.setBatterySaverEnabled(currPolicy.disableAnimation)
                            .build();
                case ServiceType.FULL_BACKUP:
                    return builder.setBatterySaverEnabled(currPolicy.deferFullBackup)
                            .build();
                case ServiceType.KEYVALUE_BACKUP:
                    return builder.setBatterySaverEnabled(currPolicy.deferKeyValueBackup)
                            .build();
                case ServiceType.NETWORK_FIREWALL:
                    return builder.setBatterySaverEnabled(currPolicy.enableFirewall)
                            .build();
                case ServiceType.SCREEN_BRIGHTNESS:
                    return builder.setBatterySaverEnabled(currPolicy.enableAdjustBrightness)
                            .setBrightnessFactor(currPolicy.adjustBrightnessFactor)
                            .build();
                case ServiceType.DATA_SAVER:
                    return builder.setBatterySaverEnabled(currPolicy.enableDataSaver)
                            .build();
                case ServiceType.SOUND:
                    return builder.setBatterySaverEnabled(currPolicy.disableSoundTrigger)
                            .build();
                case ServiceType.VIBRATION:
                    return builder.setBatterySaverEnabled(currPolicy.disableVibration)
                            .build();
                case ServiceType.FORCE_ALL_APPS_STANDBY:
                    return builder.setBatterySaverEnabled(currPolicy.forceAllAppsStandby)
                            .build();
                case ServiceType.FORCE_BACKGROUND_CHECK:
                    return builder.setBatterySaverEnabled(currPolicy.forceBackgroundCheck)
                            .build();
                case ServiceType.NIGHT_MODE:
                    return builder.setBatterySaverEnabled(currPolicy.enableNightMode)
                            .build();
                case ServiceType.OPTIONAL_SENSORS:
                    return builder.setBatterySaverEnabled(currPolicy.disableOptionalSensors)
                            .build();
                case ServiceType.AOD:
                    return builder.setBatterySaverEnabled(currPolicy.disableAod)
                            .build();
                case ServiceType.QUICK_DOZE:
                    return builder.setBatterySaverEnabled(currPolicy.enableQuickDoze)
                            .build();
                default:
                    return builder.setBatterySaverEnabled(currPolicy.advertiseIsEnabled)
                            .build();
            }
        }
    }

二. 对各个参数代码讲解

(1) adjustBrightnessFactor 

    这是决定屏幕亮度调整多少的标志。 这是从 0 到 1 的浮点值,其中 1 表示不改变亮度.  1)  LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

    @VisibleForTesting
    void updatePowerRequestFromBatterySaverPolicy(DisplayPowerRequest displayPowerRequest) {
        PowerSaveState state = mBatterySaverPolicy.
                getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS);
        displayPowerRequest.lowPowerMode = state.batterySaverEnabled;
        displayPowerRequest.screenLowPowerBrightnessFactor = state.brightnessFactor;
    }

2) 更新power 状态

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java

    private void updatePowerState() {
...
        // If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor
        // as long as it is above the minimum threshold.
        if (mPowerRequest.lowPowerMode) {
            if (brightnessState > mScreenBrightnessRangeMinimum) {

              //获取screenLowPowerBrightnessFactor参数作为缩放亮度的因数
                final float brightnessFactor =
                        Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);

                //获取最小亮度值
                final float lowPowerBrightnessFloat = (brightnessState * brightnessFactor);

                //亮度值不能小于最小的亮度值
                brightnessState = Math.max(lowPowerBrightnessFloat,
                        mScreenBrightnessRangeMinimum);
            }
        
...
}

 3)分发powerFactor 的数值

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java

     private void notifyBrightnessChanged(int brightness, boolean userInitiated,
            boolean hadUserDataPoint) {
        final float brightnessInNits = convertToNits(brightness);
        if (mPowerRequest.useAutoBrightness && brightnessInNits >= 0.0f
                && mAutomaticBrightnessController != null) {
            // We only want to track changes on devices that can actually map the display backlight
            // values into a physical brightness unit since the value provided by the API is in
            // nits and not using the arbitrary backlight units.

           //若低电量模式,则获取policy中的配置值
            final float powerFactor = mPowerRequest.lowPowerMode
                    ? mPowerRequest.screenLowPowerBrightnessFactor
                    : 1.0f;

           //将更改的powerFactor 分发下去
            mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiated,
                    powerFactor, hadUserDataPoint,
                    mAutomaticBrightnessController.isDefaultConfig());
        }
    }

 (2) enableAdjustBrightness

   enableAdjustBrightness 和adjustBrightnessFactor是搭配起来用的。使用方法和adjustBrightnessFactor 一样。

    在省电模式下是否打开低功耗模式亮度调节应。

(3) advertiseIsEnabled

    若获取的policy的type匹配不上则,则使用此值作为默认值。

(4) deferFullBackup

    在省电模式下是否推迟完整备份。

LAW.BR.5.1/LINUX/android/frameworks/base/services/backup/java/com/android/server/backup/UserBackupManagerService.java

    /**
     * Conditions are right for a full backup operation, so run one.  The model we use is
     * to perform one app backup per scheduled job execution, and to reschedule the job
     * with zero latency as long as conditions remain right and we still have work to do.
     *
     *

This is the "start a full backup operation" entry point called by the scheduled job.
     *
     * @return Whether ongoing work will continue.  The return value here will be passed
     * along as the return value to the scheduled job's onStartJob() callback.
     */
    public boolean beginFullBackup(FullBackupJob scheduledJob) {
        // Don't run the backup if we're in battery saver mode, but reschedule
        // to try again in the not-so-distant future.
        final PowerSaveState result =
                mPowerManager.getPowerSaveState(ServiceType.FULL_BACKUP);
        if (result.batterySaverEnabled) {

            //如果处于省电模式,请不要运行备份,但要重新安排在不久的将来重试。
            FullBackupJob.schedule(mUserId, mContext, keyValueBackupInterval, mConstants);
            return false;
        }
}

(5) deferKeyValueBackup 

在省电模式下是否推迟键值(Key-value Backup)备份。

关于Key-value Backup 可以参考: 全面复盘Android开发者容易忽视的Backup功能 - 掘金 

LAW.BR.5.1/LINUX/android/frameworks/base/services/backup/java/com/android/server/backup/UserBackupManagerService.java

    /**
     * Run a backup pass immediately for any applications that have declared that they have pending
     * updates.
     */
    public void backupNow() {
   ...
        try {
            final PowerSaveState result =
                    mPowerManager.getPowerSaveState(ServiceType.KEYVALUE_BACKUP);
            if (result.batterySaverEnabled) {
                // Try again in several hours.

                //推迟执行
                KeyValueBackupJob.schedule(mUserId, mContext, mConstants);
            } 
...
 

 (6)  disableAnimation 

    在省电模式下是否禁止window 动画。

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

    private WindowManagerService(Context context, InputManagerService inputManager,
            boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
            ActivityTaskManagerService atm, Supplier transactionFactory,
            Supplier surfaceFactory,
            Function surfaceControlFactory) {
...
        if (mPowerManagerInternal != null) {
            mPowerManagerInternal.registerLowPowerModeObserver(
                    new PowerManagerInternal.LowPowerModeListener() {
                @Override
                public int getServiceType() {
                    return ServiceType.ANIMATION;
                }

                @Override
                public void onLowPowerModeChanged(PowerSaveState result) {
                    synchronized (mGlobalLock) {
                        final boolean enabled = result.batterySaverEnabled;
                        if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
                            mAnimationsDisabled = enabled;
                            dispatchNewAnimatorScaleLocked(null);
                        }
                    }
                }
            });
            mAnimationsDisabled = mPowerManagerInternal
                    .getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled;
        }
...

}

   获取动画播放时长的缩放比例

    @Override
    public float getCurrentAnimatorScale() {
        synchronized (mGlobalLock) {
            return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting;
        }
    }

(7) disableAod

在省电模式下是否禁用 AOD。

当手机打瞌睡时,通知是否应在用户的显示屏上“闪烁”。 

代码在Systemui中实现

LAW.BR.5.1/LINUX/android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java

    private void setPowerSave(boolean powerSave) {
        if (powerSave == mPowerSave) return;
        mPowerSave = powerSave;

        // AOD power saving setting might be different from PowerManager power saving mode.
        PowerSaveState state = mPowerManager.getPowerSaveState(PowerManager.ServiceType.AOD);

        //获取aod的值
        mAodPowerSave = state.batterySaverEnabled;

        firePowerSaveChanged();
    }

LAW.BR.5.1/LINUX/android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java

    /**
     * Whether or not the notification should "pulse" on the user's display when the phone is
     * dozing.  This displays the ambient view of the notification.
     *
     * @param entry the entry to check
     * @return true if the entry should ambient pulse, false otherwise
     */
    private boolean shouldHeadsUpWhenDozing(NotificationEntry entry) {

        if (mBatteryController.isAodPowerSave()) {
            if (DEBUG_HEADS_UP) {
                Log.d(TAG, "No pulsing: disabled by battery saver: " + sbn.getKey());
            }
            return false;
        }

(8) disableLaunchBoost

在省电模式下是否禁用启动boost

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

    private void powerHintInternal(int hintId, int data) {
        // Maybe filter the event.
        switch (hintId) {
            case PowerHint.LAUNCH: // 1: activate launch boost 0: deactivate.
                if (data == 1 && mBatterySaverController.isLaunchBoostDisabled()) {
                    return;
                }
                break;
        }

        mNativeWrapper.nativeSendPowerHint(hintId, data);
    }
 

(9) disableOptionalSensors

   是否禁用非必要传感器(例如边缘传感器),但是,目前没有找到实现的代码.

 (10) disableSoundTrigger

    在省电模式下是否禁用声音触发的事件,譬如:语音识别

LAW.BR.5.1/LINUX/android/frameworks/base/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java

    class PowerSaveModeListener extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (!PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(intent.getAction())) {
                return;
            }
            boolean active = mPowerManager.getPowerSaveState(ServiceType.SOUND)
                    .batterySaverEnabled;
            if (DBG) Slog.d(TAG, "onPowerSaveModeChanged: " + active);
            synchronized (mLock) {
                onPowerSaveModeChangedLocked(active);
            }
        }
    }

    // Whether we are allowed to run any recognition at all. The conditions that let us run
    // a recognition include: no active phone call or not being in a power save mode. Also,
    // the native service should be enabled.
    private boolean isRecognitionAllowed() {
        // if mRecognitionRequested is false, call and power state listeners are not registered so
        // we read current state directly from services
        if (!mRecognitionRequested) {
            mCallActive = mTelephonyManager.getCallState() == TelephonyManager.CALL_STATE_OFFHOOK;
            mIsPowerSaveMode =
                mPowerManager.getPowerSaveState(ServiceType.SOUND).batterySaverEnabled;
        }
        return !mCallActive && !mServiceDisabled && !mIsPowerSaveMode;
    }
 

 (11) disableVibration

    当省电模式模式下,除了来电显示的震动(有条件的震动)

   1) 震动将取消(原来如果有震动的话)

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/VibratorService.java

    private boolean updateLowPowerModeLocked() {
        boolean lowPowerMode = mPowerManagerInternal
                .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled;
        if (lowPowerMode != mLowPowerMode) {
            mLowPowerMode = lowPowerMode;
            return true;
        }
        return false;
    }
  2)当省电模式模式下,除了来电显示的震动(有条件的震动),其它都将关闭震动。

 代码如下:

  //监听各种变化,取消震动.
    private void updateVibrators() {
        synchronized (mLock) {
            boolean devicesUpdated = updateInputDeviceVibratorsLocked();
            boolean lowPowerModeUpdated = updateLowPowerModeLocked();
            updateVibrationIntensityLocked();

            if (devicesUpdated || lowPowerModeUpdated) {
                // If the state changes out from under us then just reset.
                doCancelVibrateLocked();
            }

            updateAlwaysOnLocked();
        }
    }


    private boolean isAllowedToVibrateLocked(Vibration vib) {

        //若不是低电量模式,则直接允许
        if (!mLowPowerMode) {
            return true;
        }

        int usage = vib.attrs.getUsage();

       //若在低电量模式下,则允许USAGE_RINGTONE,USAGE_ALARM,USAGE_COMMUNICATION_REQUEST 模式下有震动.
        return usage == VibrationAttributes.USAGE_RINGTONE
                || usage == VibrationAttributes.USAGE_ALARM
                || usage == VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
    }

    private boolean shouldVibrate(Vibration vib, int intensity) {
        if (!isAllowedToVibrateLocked(vib)) {
            return false;
        }

       ...

        return true;
    }

(12) enableDataSaver

    是否开启data saver模式

1) 找到控制开关

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/net/NetworkPolicyManagerService.java

    private void initService(CountDownLatch initCompleteSignal) {
                    mRestrictBackgroundLowPowerMode = mPowerManagerInternal
                            .getLowPowerState(ServiceType.DATA_SAVER).batterySaverEnabled;

                    if (mRestrictBackgroundLowPowerMode && !mLoadedRestrictBackground) {
                        mLoadedRestrictBackground = true;
                    }

                    setRestrictBackgroundUL(mLoadedRestrictBackground, "init_service");

    }

2) 对后台UL进行限制

    @GuardedBy("mUidRulesFirstLock")
    private void setRestrictBackgroundUL(boolean restrictBackground, String reason) {
        Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setRestrictBackgroundUL");
        try {

             //restrictBackground 默认值是true
            if (restrictBackground == mRestrictBackground) {
                // Ideally, UI should never allow this scenario...
                return;
            }

            final boolean oldRestrictBackground = mRestrictBackground;
            mRestrictBackground = restrictBackground;
            // Must whitelist foreground apps before turning data saver mode on.
            // TODO: there is no need to iterate through all apps here, just those in the foreground,
            // so it could call AM to get the UIDs of such apps, and iterate through them instead.

           //
            updateRulesForRestrictBackgroundUL();
            try {

                 //
                if (!mNetworkManager.setDataSaverModeEnabled(mRestrictBackground)) {
                    Slog.e(TAG,
                            "Could not change Data Saver Mode on NMS to " + mRestrictBackground);
                    mRestrictBackground = oldRestrictBackground;
                    // TODO: if it knew the foreground apps (see TODO above), it could call
                    // updateRulesForRestrictBackgroundUL() again to restore state.
                    return;
                }
            } catch (RemoteException e) {
                // ignored; service lives in system_server
            }

     ...
    }

3) NetdService 对网络限制

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/NetworkManagementService.java 

    @Override
    public boolean setDataSaverModeEnabled(boolean enable) {
        mContext.enforceCallingOrSelfPermission(NETWORK_SETTINGS, TAG);

        if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
        synchronized (mQuotaLock) {
            if (mDataSaverMode == enable) {
                Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode);
                return true;
            }
            Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "bandwidthEnableDataSaver");
            try {

               //Enables or disables data saver mode on costly network interfaces.
                final boolean changed = mNetdService.bandwidthEnableDataSaver(enable);
                if (changed) {
                    mDataSaverMode = enable;
                } else {
                    Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed");
                }
                return changed;
            } catch (RemoteException e) {
                Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e);
                return false;
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
            }
        }
    }

(13) enableFirewall

    在省电模式下是否开启网络策略防火墙 

1) 获取引用enableFirewall 值。

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/net/NetworkPolicyManagerService.java

    private void initService(CountDownLatch initCompleteSignal) {
                    mRestrictPower = mPowerManagerInternal.getLowPowerState(
                            ServiceType.NETWORK_FIREWALL).batterySaverEnabled;
}

2) 触发调用Restrict Power的函数:

 [1] 当处于省电模式发生变化

                                public void onLowPowerModeChanged(PowerSaveState result) {
                                    final boolean enabled = result.batterySaverEnabled;
                                    if (LOGD) {
                                        Slog.d(TAG, "onLowPowerModeChanged(" + enabled + ")");
                                    }
                                    synchronized (mUidRulesFirstLock) {
                                        if (mRestrictPower != enabled) {
                                            mRestrictPower = enabled;
                                            updateRulesForRestrictPowerUL();
                                        }
                                    }
                                }
                            });

[2]  当收到ACTION_POWER_SAVE_WHITELIST_CHANGED action时:

    final private BroadcastReceiver mPowerSaveWhitelistReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected
            synchronized (mUidRulesFirstLock) {
                updatePowerSaveWhitelistUL();
                updateRulesForRestrictPowerUL();
                updateRulesForAppIdleUL();
            }
        }
    };

 [3] 当触发updateRulesForGlobalChangeAL 时:

    /**
     * Update rules that might be changed by {@link #mRestrictBackground},
     * {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
     */
    @GuardedBy({"mUidRulesFirstLock", "mNetworkPoliciesSecondLock"})
    private void updateRulesForGlobalChangeAL(boolean restrictedNetworksChanged) {

        try {
            updateRulesForAppIdleUL();
            updateRulesForRestrictPowerUL();
            updateRulesForRestrictBackgroundUL();

            // If the set of restricted networks may have changed, re-evaluate those.
            if (restrictedNetworksChanged) {
                normalizePoliciesNL();
                updateNetworkRulesNL();
            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
        }
    }

3) updateRulesForRestrictPowerUL函数解析:

    // TODO: rename / document to make it clear these are global (not app-specific) rules
    @GuardedBy("mUidRulesFirstLock")
    private void updateRulesForRestrictPowerUL() {
        Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictPowerUL");
        try {
            updateRulesForDeviceIdleUL();
            updateRulesForPowerSaveUL();
            updateRulesForAllAppsUL(TYPE_RESTRICT_POWER);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
        }
    } 

4)   updateRulesForPowerSaveUL 就是调用updateRulesForWhitelistedPowerSaveUL

    @GuardedBy("mUidRulesFirstLock")
    void updateRulesForPowerSaveUL() {
        Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForPowerSaveUL");
        try {
            updateRulesForWhitelistedPowerSaveUL(mRestrictPower, FIREWALL_CHAIN_POWERSAVE,
                    mUidFirewallPowerSaveRules);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
        }
    }

5)  更新白名单范围(允许访问的网络的范围),范围之外的通过防火墙停止网络链接

    // NOTE: since both fw_dozable and fw_powersave uses the same map
    // (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method.
    @GuardedBy("mUidRulesFirstLock")
    private void updateRulesForWhitelistedPowerSaveUL(boolean enabled, int chain,
            SparseIntArray rules) {
        if (enabled) {
            // Sync the whitelists before enabling the chain.  We don't care about the rules if
            // we are disabling the chain.
            final SparseIntArray uidRules = rules;
            uidRules.clear();
            final List users = mUserManager.getUsers();
            for (int ui = users.size() - 1; ui >= 0; ui--) {
                UserInfo user = users.get(ui);
                updateRulesForWhitelistedAppIds(uidRules, mPowerSaveTempWhitelistAppIds, user.id);
                updateRulesForWhitelistedAppIds(uidRules, mPowerSaveWhitelistAppIds, user.id);

                //若是FIREWALL_CHAIN_POWERSAVE chain 则将mPowerSaveWhitelistExceptIdleAppIds里面的UID 增加在uidRules 白名单中.
                if (chain == FIREWALL_CHAIN_POWERSAVE) {
                    updateRulesForWhitelistedAppIds(uidRules,
                            mPowerSaveWhitelistExceptIdleAppIds, user.id);
                }
            }
            for (int i = mUidState.size() - 1; i >= 0; i--) {
                if (isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.valueAt(i))) {
                    uidRules.put(mUidState.keyAt(i), FIREWALL_RULE_ALLOW);
                }
            }
            setUidFirewallRulesUL(chain, uidRules, CHAIN_TOGGLE_ENABLE);
        } else {
            setUidFirewallRulesUL(chain, null, CHAIN_TOGGLE_DISABLE);
        }
    }

6)增加白名单

    private void updateRulesForWhitelistedAppIds(final SparseIntArray uidRules,
            final SparseBooleanArray whitelistedAppIds, int userId) {
        for (int i = whitelistedAppIds.size() - 1; i >= 0; --i) {
            if (whitelistedAppIds.valueAt(i)) {
                final int appId = whitelistedAppIds.keyAt(i);
                final int uid = UserHandle.getUid(userId, appId);
                uidRules.put(uid, FIREWALL_RULE_ALLOW);
            }
        }
    }

7) 更新所有应用的访问规则,除了前台进程和在白名单内的进程,都将不允许访问网络

    @GuardedBy("mUidRulesFirstLock")
    private int updateRulesForPowerRestrictionsULInner(int uid, int oldUidRules,
            boolean isUidIdle) {
        if (!isUidValidForBlacklistRulesUL(uid)) {
            if (LOGD) Slog.d(TAG, "no need to update restrict power rules for uid " + uid);
            return RULE_NONE;
        }

        //mRestrictPower 表示低电量模式

        final boolean restrictMode = isUidIdle || mRestrictPower || mDeviceIdleMode;
        final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);

        final boolean isWhitelisted = isWhitelistedFromPowerSaveUL(uid, mDeviceIdleMode);
        final int oldRule = oldUidRules & MASK_ALL_NETWORKS;
        int newRule = RULE_NONE;

        // First step: define the new rule based on user restrictions and foreground state.

        // NOTE: if statements below could be inlined, but it's easier to understand the logic
        // by considering the foreground and non-foreground states.
        if (isForeground) {

           //针对前台进程会放开
            if (restrictMode) {
                newRule = RULE_ALLOW_ALL;
            }
        } else if (restrictMode) {

           //表示若低电量模式下,会限制规则。但是,对白名单会放开限制.
            newRule = isWhitelisted ? RULE_ALLOW_ALL : RULE_REJECT_ALL;
        }

        final int newUidRules = (oldUidRules & MASK_METERED_NETWORKS) | newRule;

        // Second step: notify listeners if state changed.

            mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget();
        }

        return newUidRules;
    }

 (14) enableNightMode

     是否启用夜间模式,不包含汽车模式.

1) 获取引用enableNightMode 值。

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/UiModeManagerService.java

    private void initPowerSave() {
        mPowerSave =
                mLocalPowerManager.getLowPowerState(ServiceType.NIGHT_MODE)
                        .batterySaverEnabled;
        mLocalPowerManager.registerLowPowerModeObserver(ServiceType.NIGHT_MODE, state -> {
            synchronized (mLock) {
                if (mPowerSave == state.batterySaverEnabled) {
                    return;
                }
                mPowerSave = state.batterySaverEnabled;
                if (mSystemReady) {
                    updateLocked(0, 0);
                }
            }
        });
    }

 2)更改uiMode

    private void updateConfigurationLocked() {

        // Override night mode in power save mode if not in car mode

       //如果不在汽车模式下,则在省电模式下覆盖夜间模式
        if (mPowerSave && !mCarModeEnabled && !mCar) {
            uiMode &= ~Configuration.UI_MODE_NIGHT_NO;
            uiMode |= Configuration.UI_MODE_NIGHT_YES;
        } else {
            uiMode = getComputedUiModeConfiguration(uiMode);
        }

 (15) enableQuickDoze

    是否启用快速打瞌睡模式

 LAW.BR.5.1/LINUX/android/frameworks/base/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java

 1)  获取引用enableQuickDoze 值。

                mLocalPowerManager.registerLowPowerModeObserver(ServiceType.QUICK_DOZE,
                        state -> {
                            synchronized (DeviceIdleController.this) {
                                updateQuickDozeFlagLocked(state.batterySaverEnabled);
                            }
                        });
                updateQuickDozeFlagLocked(
                        mLocalPowerManager.getLowPowerState(
                                ServiceType.QUICK_DOZE).batterySaverEnabled);

2) 省电模式下,否可以快速进入doze

    /** Updates the quick doze flag and enters deep doze if appropriate. */
    @VisibleForTesting
    void updateQuickDozeFlagLocked(boolean enabled) {
        if (DEBUG) Slog.i(TAG, "updateQuickDozeFlagLocked: enabled=" + enabled);
        mQuickDozeActivated = enabled;
        mQuickDozeActivatedWhileIdling =
                mQuickDozeActivated && (mState == STATE_IDLE || mState == STATE_IDLE_MAINTENANCE);
        if (enabled) {
            // If Quick Doze is enabled, see if we should go straight into it.
            becomeInactiveIfAppropriateLocked();
        }
        // Going from Deep Doze to Light Idle (if quick doze becomes disabled) is tricky and
        // probably not worth the overhead, so leave in deep doze if that's the case until the
        // next natural time to come out of it.
    } 

(16) filesForInteractive

 激活省电模式且设备处于交互状态时应写入的 [文件名 -> 内容] 列表。 用它来更改最大 CPU 频率。 目前没有理解filesForInteractive的作用.

1) filesForInteractive定义:

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java

    public ArrayMap getFileValues(boolean interactive) {
        synchronized (mLock) {
            return interactive ? getCurrentPolicyLocked().filesForInteractive
                    : getCurrentPolicyLocked().filesForNoninteractive;
        }
    }

2)  写入fileValues

 LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java

    void handleBatterySaverStateChanged(boolean sendBroadcast, int reason) {  
          if (enabled) {
                fileValues = mBatterySaverPolicy.getFileValues(isInteractive);
            } else {
                fileValues = null;
            }

        if (ArrayUtils.isEmpty(fileValues)) {
            mFileUpdater.restoreDefault();
        } else {
            mFileUpdater.writeFiles(fileValues);
        }
}

(17) filesForNoninteractive

激活省电模式且设备非交互式时应写入的 [文件名 -> 内容] 列表。我们用它来更改最大 CPU 频率。 目前没有理解filesForNoninteractive的作用.

和filesForInteractive 一样的,只不过getFileValues函数的传参不一样

(18) forceAllAppsStandby 

     是否将所有应用程序置于待机模式

1) forceAllAppsStandby 获取地方

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/AppStateTracker.java

    public void onSystemServicesReady() {
...

            mPowerManagerInternal.registerLowPowerModeObserver(
                    ServiceType.FORCE_ALL_APPS_STANDBY,
                    (state) -> {
                        synchronized (mLock) {
                            mBatterySaverEnabled = state.batterySaverEnabled;
                            updateForceAllAppStandbyState();
                        }
                    });

            mBatterySaverEnabled = mPowerManagerInternal.getLowPowerState(
                    ServiceType.FORCE_ALL_APPS_STANDBY).batterySaverEnabled;

            updateForceAllAppStandbyState();

...
}

2)  updateForceAllAppStandbyState 函数

    private void updateForceAllAppStandbyState() {
        synchronized (mLock) {
            if (mForceAllAppStandbyForSmallBattery && isSmallBatteryDevice()) {
                toggleForceAllAppsStandbyLocked(!mIsPluggedIn);
            } else {
                toggleForceAllAppsStandbyLocked(mBatterySaverEnabled);
            }
        }
    }

3) 对mForceAllAppsStandby 赋值,并且 便利onForceAllAppsStandbyChanged callback

    /**
     * Update {@link #mForceAllAppsStandby} and notifies the listeners.
     */
    @GuardedBy("mLock")
    private void toggleForceAllAppsStandbyLocked(boolean enable) {
        if (enable == mForceAllAppsStandby) {
            return;
        }
        mForceAllAppsStandby = enable;

        mHandler.notifyForceAllAppsStandbyChanged();
    }
 

        public void notifyForceAllAppsStandbyChanged() {
            removeMessages(MSG_FORCE_ALL_CHANGED);
            obtainMessage(MSG_FORCE_ALL_CHANGED).sendToTarget();
        } 

                case MSG_FORCE_ALL_CHANGED:
                    for (Listener l : cloneListeners()) {
                        l.onForceAllAppsStandbyChanged(sender);
                    }
                    return; 

(19) forceBackgroundCheck

   是否强制后台检查,譬如:强制停止idle UIDs

 LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    public void systemReady(final Runnable goingCallback, @NonNull TimingsTraceAndSlog t) {
...
        if (pmi != null) {
            pmi.registerLowPowerModeObserver(ServiceType.FORCE_BACKGROUND_CHECK,
                    state -> updateForceBackgroundCheck(state.batterySaverEnabled));
            updateForceBackgroundCheck(
                    pmi.getLowPowerState(ServiceType.FORCE_BACKGROUND_CHECK).batterySaverEnabled);
        } else {
            Slog.wtf(TAG, "PowerManagerInternal not found.");
        }
...

2) updateForceBackgroundCheck

   private void updateForceBackgroundCheck(boolean enabled) {
        synchronized (this) {
            if (mForceBackgroundCheck != enabled) {
                mForceBackgroundCheck = enabled;

                if (DEBUG_BACKGROUND_CHECK) {
                    Slog.i(TAG, "Force background check " + (enabled ? "enabled" : "disabled"));
                }

                if (mForceBackgroundCheck) {
                    // Stop background services for idle UIDs.
                    mProcessList.doStopUidForIdleUidsLocked();
                }
            }
        }
    }

(20) locationMode

有三处定义,分别从三处分析:

1) 定义来自PowerManager.

[1] PowerManager.java 中getLocationPowerSaveMode函数

LAW.BR.5.1/LINUX/android/frameworks/base/core/java/android/os/PowerManager.java

    /**
     * Returns how location features should behave when battery saver is on. When battery saver
     * is off, this will always return {@link #LOCATION_MODE_NO_CHANGE}.
     *
     *

This API is normally only useful for components that provide location features.
     *
     * @see #isPowerSaveMode()
     * @see #ACTION_POWER_SAVE_MODE_CHANGED
     */
    @LocationPowerSaveMode
    public int getLocationPowerSaveMode() {
        final PowerSaveState powerSaveState = getPowerSaveState(ServiceType.LOCATION);
        if (!powerSaveState.batterySaverEnabled) {
            return LOCATION_MODE_NO_CHANGE;
        }
        return powerSaveState.locationMode;
    }

[2] getLocationPowerSaveMode 作为公共接口,为LocationManagerService.java 提供使用函数.

2) GnssLocationProvider.java 中updateLowPowerMode

[1] 定义:

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java

    private void updateLowPowerMode() {
        // Disable GPS if we are in device idle mode and the device is stationary.
        boolean disableGpsForPowerManager = mPowerManager.isDeviceIdleMode() && mIsDeviceStationary;
        final PowerSaveState result = mPowerManager.getPowerSaveState(ServiceType.LOCATION);
        switch (result.locationMode) {
            case PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF:
            case PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF:
                // If we are in battery saver mode and the screen is off, disable GPS.
                disableGpsForPowerManager |=
                        result.batterySaverEnabled && !mPowerManager.isInteractive();
                break;
        }
        if (disableGpsForPowerManager != mDisableGpsForPowerManager) {
            mDisableGpsForPowerManager = disableGpsForPowerManager;
            updateEnabled();
            updateRequirements();
        }
    }

 [2] 当收到mDeviceIdleStationaryListener 变化和ACTION_POWER_SAVE_MODE_CHANGED/ACTION_SCREEN_OFF/ACTION_SCREEN_ON时,会触发UPDATE_LOW_POWER_MODE handle

    private final DeviceIdleInternal.StationaryListener mDeviceIdleStationaryListener =
            isStationary -> {
                mIsDeviceStationary = isStationary;
                // Call updateLowPowerMode on handler thread so it's always called from the same
                // thread.
                mHandler.sendEmptyMessage(UPDATE_LOW_POWER_MODE);
            };

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

 ...
                case PowerManager.ACTION_POWER_SAVE_MODE_CHANGED:
                case Intent.ACTION_SCREEN_OFF:
                case Intent.ACTION_SCREEN_ON:
                    // Call updateLowPowerMode on handler thread so it's always called from the
                    // same thread.
                    mHandler.sendEmptyMessage(UPDATE_LOW_POWER_MODE);
                    break;

        }
    };

[3] 收到UPDATE_LOW_POWER_MODE 之后更新updateLowPowerMode

SDM4100_AOSP_DEV/LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java

    private final class ProviderHandler extends Handler {

        @Override
        public void handleMessage(Message msg) {
            int message = msg.what;
            switch (message) {

                case UPDATE_LOW_POWER_MODE:
                    updateLowPowerMode();
                    break;

[4]  updateLowPowerMode函数更新mDisableGpsForPowerManager变量

private void updateLowPowerMode() {
        // Disable GPS if we are in device idle mode and the device is stationary.
        boolean disableGpsForPowerManager = mPowerManager.isDeviceIdleMode() && mIsDeviceStationary;
        final PowerSaveState result = mPowerManager.getPowerSaveState(ServiceType.LOCATION);
        switch (result.locationMode) {
            case PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF:
            case PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF:
                // If we are in battery saver mode and the screen is off, disable GPS.
                disableGpsForPowerManager |=
                        result.batterySaverEnabled && !mPowerManager.isInteractive();
                break;
        }
        if (disableGpsForPowerManager != mDisableGpsForPowerManager) {
            mDisableGpsForPowerManager = disableGpsForPowerManager;
            updateEnabled();
            updateRequirements();
        }
    }

 [5] 更新enabled 数据并且做相应的逻辑。

    private void updateEnabled() {
        // Generally follow location setting for current user
        boolean enabled = mContext.getSystemService(LocationManager.class)
                .isLocationEnabledForUser(UserHandle.CURRENT);

        // ... but disable if PowerManager overrides
        enabled &= !mDisableGpsForPowerManager;

        // .. but enable anyway, if there's an active settings-ignored request (e.g. ELS)
        enabled |= (mProviderRequest != null && mProviderRequest.reportLocation
                && mProviderRequest.locationSettingsIgnored);

        // ... and, finally, disable anyway, if device is being shut down
        enabled &= !mShutdown;

        if (enabled == isGpsEnabled()) {
            return;
        }

        if (enabled) {
            handleEnable();
        } else {
            handleDisable();
        }
    }

  [5] 处理禁止的事情

    private void handleDisable() {
        if (DEBUG) Log.d(TAG, "handleDisable");

        setGpsEnabled(false);
        updateClientUids(new WorkSource());
        stopNavigating();
        mAlarmManager.cancel(mWakeupIntent);
        mAlarmManager.cancel(mTimeoutIntent);

        if (mGnssVisibilityControl != null) {
            mGnssVisibilityControl.onGpsEnabledChanged(/* isEnabled= */ false);
        }
        mGnssBatchingProvider.disable();
        // do this before releasing wakelock
        native_cleanup();

        mGnssAntennaInfoProvider.onGpsEnabledChanged();
        mGnssMeasurementsProvider.onGpsEnabledChanged();
        mGnssNavigationMessageProvider.onGpsEnabledChanged();
    }

3) LocationManagerService 中onSystemReady函数

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/location/LocationManagerService.java

  LocalServices.getService(PowerManagerInternal.class).registerLowPowerModeObserver(
                    ServiceType.LOCATION,
                    state -> {
                        // listener invoked on ui thread, move to our thread to reduce risk of
                        // blocking ui thread
                        mHandler.post(() -> {
                            synchronized (mLock) {
                                onBatterySaverModeChangedLocked(state.locationMode);
                            }
                        });
                    });

 三. 进入省电模式的入口

 (1)通过  PowerManager 进入,需要DEVICE_POWERPOWER_SAVER权限.

  LAW.BR.5.1/LINUX/android/frameworks/base/core/java/android/os/PowerManager.java

  

    /**
     * Set the current power save mode.
     *
     * @return True if the set was allowed.
     *
     * @hide
     * @see #isPowerSaveMode()
     */
    @SystemApi
    @TestApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.DEVICE_POWER,
            android.Manifest.permission.POWER_SAVER
    })
    public boolean setPowerSaveModeEnabled(boolean mode) {
        try {
            return mService.setPowerSaveModeEnabled(mode);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

 (2) 进入PowerManagerService:

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

        @Override // Binder call
        public boolean setPowerSaveModeEnabled(boolean enabled) {
            if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.POWER_SAVER)
                    != PackageManager.PERMISSION_GRANTED) {
                mContext.enforceCallingOrSelfPermission(
                        android.Manifest.permission.DEVICE_POWER, null);
            }
            final long ident = Binder.clearCallingIdentity();
            try {
                return setLowPowerModeInternal(enabled);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        } 

    private boolean setLowPowerModeInternal(boolean enabled) {
        synchronized (mLock) {
            if (DEBUG) {
                Slog.d(TAG, "setLowPowerModeInternal " + enabled + " mIsPowered=" + mIsPowered);
            }
            if (mIsPowered) {
                return false;
            }

            mBatterySaverStateMachine.setBatterySaverEnabledManually(enabled);

            return true;
        }
    }

 (3) 进入:/LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java

    /**
     * {@link com.android.server.power.PowerManagerService} calls it when
     * {@link android.os.PowerManager#setPowerSaveModeEnabled} is called.
     *
     * Note this could? be called before {@link #onBootCompleted} too.
     */
    public void setBatterySaverEnabledManually(boolean enabled) {
        if (DEBUG) {
            Slog.d(TAG, "setBatterySaverEnabledManually: enabled=" + enabled);
        }
        synchronized (mLock) {
            updateStateLocked(true, enabled);
            // TODO: maybe turn off adaptive if it's on and advertiseIsEnabled is true and
            //  enabled is false
        }
    }

 4)updateStateLocked  函数下面内容再讲.

四. modem进入低电模式入口

SDM4100_AOSP_DEV/LAW.BR.5.1/LINUX/android/frameworks/opt/telephony/src/java/com/android/internal/telephony/DeviceStateMonitor.java

(1)定义mBroadcastReceiver,当收到ACTION_POWER_SAVE_MODE_CHANGED 之后,则使用handle发送EVENT_POWER_SAVE_MODE_CHANGED.

    /**
     * Device state broadcast receiver
     */
    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            log("received: " + intent, true);

            Message msg;
            switch (intent.getAction()) {
                case PowerManager.ACTION_POWER_SAVE_MODE_CHANGED:
                    msg = obtainMessage(EVENT_POWER_SAVE_MODE_CHANGED);
                    msg.arg1 = isPowerSaveModeOn() ? 1 : 0;
                    log("Power Save mode " + ((msg.arg1 == 1) ? "on" : "off"), true);
                    break;
                case BatteryManager.ACTION_CHARGING:
                    msg = obtainMessage(EVENT_CHARGING_STATE_CHANGED);
                    msg.arg1 = 1;   // charging
                    break;
                ...
                default:
                    log("Unexpected broadcast intent: " + intent, false);
                    return;
            }
            sendMessage(msg);
        }
    };

(2) 注册mBroadcastReceiver

    /**
     * Device state monitor constructor. Note that each phone object should have its own device
     * state monitor, meaning there will be two device monitors on the multi-sim device.
     *
     * @param phone Phone object
     */
    public DeviceStateMonitor(Phone phone) {
        mPhone = phone;
        mPhone.getContext().registerReceiver(mBroadcastReceiver, filter, null, mPhone);
}

 (3)接收到EVENT_POWER_SAVE_MODE_CHANGED

    /**
     * Message handler
     *
     * @param msg The message
     */
    @Override
    public void handleMessage(Message msg) {
        log("handleMessage msg=" + msg, false);
        switch (msg.what) {
            case EVENT_RIL_CONNECTED:
            case EVENT_RADIO_AVAILABLE:
                onReset();
                break;
            case EVENT_SCREEN_STATE_CHANGED:
            case EVENT_POWER_SAVE_MODE_CHANGED:
            case EVENT_CHARGING_STATE_CHANGED:
            case EVENT_TETHERING_STATE_CHANGED:
            case EVENT_UPDATE_ALWAYS_REPORT_SIGNAL_STRENGTH:
            case EVENT_CAR_MODE_CHANGED:
                onUpdateDeviceState(msg.what, msg.arg1 != 0);
                break;
            case EVENT_WIFI_CONNECTION_CHANGED:
                onUpdateDeviceState(msg.what, msg.arg1 != WIFI_UNAVAILABLE);
                break;
            default:
                throw new IllegalStateException("Unexpected message arrives. msg = " + msg.what);
        }
    }

(4) onUpdateDeviceState函数

    /**
     * Update the device and send the information to the modem.
     *
     * @param eventType Device state event type
     * @param state True if enabled/on, otherwise disabled/off.
     */
    private void onUpdateDeviceState(int eventType, boolean state) {
        final boolean shouldEnableBarringInfoReportsOld = shouldEnableBarringInfoReports();
        switch (eventType) {

         ...

            case EVENT_POWER_SAVE_MODE_CHANGED:
                if (mIsPowerSaveOn == state) return;
                mIsPowerSaveOn = state;
                sendDeviceState(POWER_SAVE_MODE, mIsPowerSaveOn);
                break;

}

(5) sendDeviceState函数

    /**
     * Send the device state to the modem.
     *
     * @param type Device state type. See DeviceStateType defined in types.hal.
     * @param state True if enabled/on, otherwise disabled/off
     */
    private void sendDeviceState(int type, boolean state) {
        log("send type: " + deviceTypeToString(type) + ", state=" + state, true);
        mPhone.mCi.sendDeviceState(type, state, null);
    }

五. 屏幕亮度将会变成原来的50%的流程 

(1) 监听电池变化.

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

    public void systemReady(IAppOpsService appOps) {
...
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler);

...}

    @VisibleForTesting
    final class BatteryReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            synchronized (mLock) {
                handleBatteryStateChangedLocked();
            }
        }
    }

    private void handleBatteryStateChangedLocked() {
        mDirty |= DIRTY_BATTERY_STATE;
        updatePowerStateLocked();
    } 

     /**
     * Updates the global power state based on dirty bits recorded in mDirty.
     *
     * This is the main function that performs power state transitions.
     * We centralize them here so that we can recompute the power state completely
     * each time something important changes, and ensure that we do it the same
     * way each time.  The point is to gather all of the transition logic here.
     */
    private void updatePowerStateLocked() {
    ...
            // Phase 3: Update display power state.
            final boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
   ...

    /**
     * Updates the display power state asynchronously.
     * When the update is finished, mDisplayReady will be set to true.  The display
     * controller posts a message to tell us when the actual display power state
     * has been updated so we come back here to double-check and finish up.
     *
     * This function recalculates the display power state each time.
     *
     * @return True if the display became ready.
     */
    private boolean updateDisplayPowerStateLocked(int dirty) {
...
            updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);

          //

            mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
                    mRequestWaitForNegativeProximity);
..

//向 lowPowerMode赋值看是否低电量模式

     @VisibleForTesting
    void updatePowerRequestFromBatterySaverPolicy(DisplayPowerRequest displayPowerRequest) {
        PowerSaveState state = mBatterySaverPolicy.
                getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS);
        displayPowerRequest.lowPowerMode = state.batterySaverEnabled;
        displayPowerRequest.screenLowPowerBrightnessFactor = state.brightnessFactor;
    }

(2) updatePowerState函数

SDM4100_AOSP_DEV/LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java

    private void updatePowerState() {

  ...

        // If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor
        // as long as it is above the minimum threshold.

       //对于低电量模式进行定制
        if (mPowerRequest.lowPowerMode) {
            if (brightnessState > mScreenBrightnessRangeMinimum) {

              //使用screenLowPowerBrightnessFactor参数作为缩放亮度的因数
                final float brightnessFactor =
                        Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
                final float lowPowerBrightnessFloat = (brightnessState * brightnessFactor);

              //
                brightnessState = Math.max(lowPowerBrightnessFloat,
                        mScreenBrightnessRangeMinimum);
                mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_LOW_POWER);
            }
            if (!mAppliedLowPower) {
                slowChange = false;
            }
            mAppliedLowPower = true;
        } else if (mAppliedLowPower) {
            slowChange = false;
            mAppliedLowPower = false;
        }

...

(3) screenLowPowerBrightnessFactor 的默认值

LAW.BR.5.1/LINUX/android/frameworks/base/core/java/android/hardware/display/DisplayManagerInternal.java

// The factor to adjust the screen brightness in low power mode in the range 

// 0 (screen off) to 1 (no change)
public float screenLowPowerBrightnessFactor;

public DisplayPowerRequest() {

...

screenLowPowerBrightnessFactor = 0.5f

}

六. 自动进入省电模式

(1) 配置文件:

LAW.BR.5.1/LINUX/android/frameworks/base/core/res/res/values/config.xml

     
      config_lowBatteryWarningLevel">15

     
     config_lowBatteryCloseWarningBump">5

     

   
     config_dynamicPowerSavingsDefaultDisableThreshold">80

(2) 分析BatteryService.java 

/LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/BatteryService.java 

1) 初始化:

public BatteryService(Context context) {
...

         //进入低电量模式的阈值,默认值是15%
          mLowBatteryWarningLevel = mContext.getResources().getInteger(
                  com.android.internal.R.integer.config_lowBatteryWarningLevel);

          //退出低电量模式的阈值,默认值是20%
          mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel + mContext.getResources().getInteger(
                  com.android.internal.R.integer.config_lowBatteryCloseWarningBump);

..
}

 2) healthInfoChanged()函数回调

    private final class HealthHalCallback extends IHealthInfoCallback.Stub
            implements HealthServiceWrapper.Callback {
        @Override public void healthInfoChanged(android.hardware.health.V2_0.HealthInfo props) {
            android.hardware.health.V2_1.HealthInfo propsLatest =
                    new android.hardware.health.V2_1.HealthInfo();
            propsLatest.legacy = props;

            propsLatest.batteryCapacityLevel = BatteryCapacityLevel.UNSUPPORTED;
            propsLatest.batteryChargeTimeToFullNowSeconds =
                Constants.BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED;

            BatteryService.this.update(propsLatest);
        }

 3) update 函数调用

    private void update(android.hardware.health.V2_1.HealthInfo info) {

        synchronized (mLock) {
            if (!mUpdatesStopped) {
                mHealthInfo = info.legacy.legacy;
                mHealthInfo2p1 = info;
                // Process the new values.
                processValuesLocked(false);
                mLock.notifyAll(); // for any waiters on new info
            } else {
                copy(mLastHealthInfo, info.legacy.legacy);
            }
        }
    }

 4) processValuesLocked函数

    private void processValuesLocked(boolean force) {
    ...
            if (!mBatteryLevelLow) {
                // Should we now switch in to low battery mode?
                if (mPlugType == BATTERY_PLUGGED_NONE
                        && mHealthInfo.batteryStatus !=
                           BatteryManager.BATTERY_STATUS_UNKNOWN
                        && mHealthInfo.batteryLevel <= mLowBatteryWarningLevel) {
                    mBatteryLevelLow = true;
                }
            } 
     ...
    } 

 5) getBatteryLevelLow函数暴露给其他对象

        @Override
        public boolean getBatteryLevelLow() {
            synchronized (mLock) {
                return mBatteryLevelLow;
            }
        }
 

 (3) 同7 (1) 中监听电池信息变化.

   1)当电池信息发生改变时,会触发updatePowerStateLocked函数,在上面已经讲过。

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

private void updatePowerStateLocked() {
...
         // Phase 0: Basic state updates.
         updateIsPoweredLocked(mDirty);
...
}

 2) 获取低电量模式,并传递至BatterySaverStateMachine

/**
       * Updates the value of mIsPowered.
       * Sets DIRTY_IS_POWERED if a change occurred.
*/
private void updateIsPoweredLocked(int dirty) {
...
//获取Battery Level
mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();
//获取当前是否处于低电量模式
mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();

...

//更新BatterySaverStateMachine中的Battery Status

mBatterySaverStateMachine.setBatteryStatus(mIsPowered, mBatteryLevel, mBatteryLevelLow);

...

}

 (3)分析 BatterySaverStateMachine.java:

 1) setBatteryStatus函数 

    /**
     * {@link com.android.server.power.PowerManagerService} calls it when battery state changes.
     *
     * Note this may be called before {@link #onBootCompleted} too.
     */
    public void setBatteryStatus(boolean newPowered, int newLevel, boolean newBatteryLevelLow) {

        synchronized (mLock) {
            mBatteryStatusSet = true;

            final boolean poweredChanged = mIsPowered != newPowered;
            final boolean levelChanged = mBatteryLevel != newLevel;
            final boolean lowChanged = mIsBatteryLevelLow != newBatteryLevelLow;

            if (!(poweredChanged || levelChanged || lowChanged)) {
                return;
            }

            mIsPowered = newPowered;
            mBatteryLevel = newLevel;
            mIsBatteryLevelLow = newBatteryLevelLow;

            doAutoBatterySaverLocked();
        }
    }

2) 变量定义:

    /** Whether the device is connected to any power source. */
    @GuardedBy("mLock")

    //是否处于充电状态
    private boolean mIsPowered

    /** Current battery level in %, 0-100. (Currently only used in dumpsys.) */
    @GuardedBy("mLock")

    //当前电池电量的level
    private int mBatteryLevel;

    /** Whether the battery level is considered to be "low" or not. */
    @GuardedBy("mLock")

    //是否处于低电量
    private boolean mIsBatteryLevelLow;

3) doAutoBatterySaverLocked函数:

    /**
     * Decide whether to auto-start / stop battery saver.
     */
    @GuardedBy("mLock")
    private void doAutoBatterySaverLocked() {
 

        updateStateLocked(false, false);

        // Adaptive control.

        //统计时间是否超过ADAPTIVE_CHANGE_TIMEOUT_MS(24小时)
        if (SystemClock.elapsedRealtime() - mLastAdaptiveBatterySaverChangedExternallyElapsed
                > ADAPTIVE_CHANGE_TIMEOUT_MS) {

            //退出POLICY_LEVEL_ADAPTIVE模式
            mBatterySaverController.setAdaptivePolicyEnabledLocked(
                    false, BatterySaverController.REASON_TIMEOUT);
            mBatterySaverController.resetAdaptivePolicyLocked(
                    BatterySaverController.REASON_TIMEOUT);
        } else if (mIsPowered && mBatteryLevel >= ADAPTIVE_AUTO_DISABLE_BATTERY_LEVEL) {

           //若是充电 并且电池电量超过80%

           //退出POLICY_LEVEL_ADAPTIVE模式
            mBatterySaverController.setAdaptivePolicyEnabledLocked(false,
                    BatterySaverController.REASON_PLUGGED_IN);
        }
    }

 4) updateStateLocked 函数

    /**
     * Update the state machine based on the current settings and battery/charge status.
     *
     * @param manual Whether the change was made by the user.
     * @param enable Whether the user wants to turn battery saver on or off. Is only used if {@param
     *               manual} is true.
     */
    @GuardedBy("mLock")
    private void updateStateLocked(boolean manual, boolean enable) {
        if (!manual && !(mBootCompleted && mSettingsLoaded && mBatteryStatusSet)) {
            return; // Not fully initialized yet.
        }

        switch (mState) {
            case STATE_OFF: {

                //没有充电
                if (!mIsPowered) {
                    if (manual) {
                        if (!enable) {
                            Slog.e(TAG, "Tried to disable BS when it's already OFF");
                            return;
                        }
                        enableBatterySaverLocked(/*enable*/ true, /*manual*/ true,
                                BatterySaverController.REASON_MANUAL_ON);
                        hideStickyDisabledNotification();
                        mState = STATE_MANUAL_ON;
                    } else if (isAutomaticModeActiveLocked() && isInAutomaticLowZoneLocked()) {

                       //若是自动模式 并且 属于低电量
                        enableBatterySaverLocked(/*enable*/ true, /*manual*/ false,
                                BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_ON);
                        hideStickyDisabledNotification();
                        mState = STATE_AUTOMATIC_ON;
                    } else if (isDynamicModeActiveLocked() && isInDynamicLowZoneLocked()) {
                        enableBatterySaverLocked(/*enable*/ true, /*manual*/ false,
                                BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON);
                        hideStickyDisabledNotification();
                        mState = STATE_AUTOMATIC_ON;
                    }
                }
                break;
            }

            case STATE_MANUAL_ON: {
                if (manual) {
                    if (enable) {
                        Slog.e(TAG, "Tried to enable BS when it's already MANUAL_ON");
                        return;
                    }
                    enableBatterySaverLocked(/*enable*/ false, /*manual*/ true,
                            BatterySaverController.REASON_MANUAL_OFF);
                    mState = STATE_OFF;
                } else if (mIsPowered) {
                    enableBatterySaverLocked(/*enable*/ false, /*manual*/ false,
                            BatterySaverController.REASON_PLUGGED_IN);
                    if (mSettingBatterySaverEnabledSticky
                            && !mBatterySaverStickyBehaviourDisabled) {
                        mState = STATE_PENDING_STICKY_ON;
                    } else {
                        mState = STATE_OFF;
                    }
                }
                break;
            }

            case STATE_AUTOMATIC_ON: {
                if (mIsPowered) {
                    enableBatterySaverLocked(/*enable*/ false, /*manual*/ false,
                            BatterySaverController.REASON_PLUGGED_IN);
                    mState = STATE_OFF;
                } else if (manual) {
                    if (enable) {
                        Slog.e(TAG, "Tried to enable BS when it's already AUTO_ON");
                        return;
                    }
                    enableBatterySaverLocked(/*enable*/ false, /*manual*/ true,
                            BatterySaverController.REASON_MANUAL_OFF);
                    // When battery saver is disabled manually (while battery saver is enabled)
                    // when the battery level is low, we "snooze" BS -- i.e. disable auto battery
                    // saver.
                    // We resume auto-BS once the battery level is not low, or the device is
                    // plugged in.
                    mState = STATE_OFF_AUTOMATIC_SNOOZED;
                } else if (isAutomaticModeActiveLocked() && !isInAutomaticLowZoneLocked()) {
                    enableBatterySaverLocked(/*enable*/ false, /*manual*/ false,
                            BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_OFF);
                    mState = STATE_OFF;
                } else if (isDynamicModeActiveLocked() && !isInDynamicLowZoneLocked()) {
                    enableBatterySaverLocked(/*enable*/ false, /*manual*/ false,
                            BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_OFF);
                    mState = STATE_OFF;
                } else if (!isAutomaticModeActiveLocked() && !isDynamicModeActiveLocked()) {
                    enableBatterySaverLocked(/*enable*/ false, /*manual*/ false,
                            BatterySaverController.REASON_SETTING_CHANGED);
                    mState = STATE_OFF;
                }
                break;
            }

            case STATE_OFF_AUTOMATIC_SNOOZED: {
                if (manual) {
                    if (!enable) {
                        Slog.e(TAG, "Tried to disable BS when it's already AUTO_SNOOZED");
                        return;
                    }
                    enableBatterySaverLocked(/*enable*/ true, /*manual*/ true,
                            BatterySaverController.REASON_MANUAL_ON);
                    mState = STATE_MANUAL_ON;
                } else if (mIsPowered // Plugging in resets snooze.
                        || (isAutomaticModeActiveLocked() && !isInAutomaticLowZoneLocked())
                        || (isDynamicModeActiveLocked() && !isInDynamicLowZoneLocked())
                        || (!isAutomaticModeActiveLocked() && !isDynamicModeActiveLocked())) {
                    mState = STATE_OFF;
                }
                break;
            }

            case STATE_PENDING_STICKY_ON: {
                if (manual) {
                    // This shouldn't be possible. We'll only be in this state when the device is
                    // plugged in, so the user shouldn't be able to manually change state.
                    Slog.e(TAG, "Tried to manually change BS state from PENDING_STICKY_ON");
                    return;
                }
                final boolean shouldTurnOffSticky = mSettingBatterySaverStickyAutoDisableEnabled
                        && mBatteryLevel >= mSettingBatterySaverStickyAutoDisableThreshold;
                final boolean isStickyDisabled =
                        mBatterySaverStickyBehaviourDisabled || !mSettingBatterySaverEnabledSticky;
                if (isStickyDisabled || shouldTurnOffSticky) {
                    mState = STATE_OFF;
                    setStickyActive(false);
                    triggerStickyDisabledNotification();
                } else if (!mIsPowered) {
                    // Re-enable BS.
                    enableBatterySaverLocked(/*enable*/ true, /*manual*/ true,
                            BatterySaverController.REASON_STICKY_RESTORE);
                    mState = STATE_MANUAL_ON;
                }
                break;
            }

            default:
                Slog.wtf(TAG, "Unknown state: " + mState);
                break;
        }

 4) isAutomaticModeActiveLocked 函数:

    /** @return true if the automatic percentage based mode should be used */
    private boolean isAutomaticModeActiveLocked() {


        return mSettingAutomaticBatterySaver == PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE
                && mSettingBatterySaverTriggerThreshold > 0;
    }

5) refreshSettingsLocked 函数: 

   主要获取变量automaticBatterySaverMode

    @GuardedBy("mLock")
    private void refreshSettingsLocked() {
        final boolean lowPowerModeEnabled = getGlobalSetting(
                Settings.Global.LOW_POWER_MODE, 0) != 0;
        final boolean lowPowerModeEnabledSticky = getGlobalSetting(
                Settings.Global.LOW_POWER_MODE_STICKY, 0) != 0;
        final boolean dynamicPowerSavingsBatterySaver = getGlobalSetting(
                Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0) != 0;
        final int lowPowerModeTriggerLevel = getGlobalSetting(
                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);

       //默认值:POWER_SAVE_MODE_TRIGGER_PERCENTAGE 为0
        final int automaticBatterySaverMode = getGlobalSetting(
                Settings.Global.AUTOMATIC_POWER_SAVE_MODE,
                PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
        final int dynamicPowerSavingsDisableThreshold = getGlobalSetting(
                Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
                mDynamicPowerSavingsDefaultDisableThreshold);
        final boolean isStickyAutoDisableEnabled = getGlobalSetting(
                Settings.Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED, 1) != 0;
        final int stickyAutoDisableThreshold = getGlobalSetting(
                Settings.Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL, 90);

        setSettingsLocked(lowPowerModeEnabled, lowPowerModeEnabledSticky,
                lowPowerModeTriggerLevel,
                isStickyAutoDisableEnabled, stickyAutoDisableThreshold,
                automaticBatterySaverMode,
                dynamicPowerSavingsBatterySaver, dynamicPowerSavingsDisableThreshold);
    }

 6) mSettingsObserver对象监听url 变化

     意图是动态刷新变量值:

    private final ContentObserver mSettingsObserver = new ContentObserver(null) {
        @Override
        public void onChange(boolean selfChange) {
            synchronized (mLock) {
                refreshSettingsLocked();
            }
        }
    };

7) setSettingsLocked 函数:

    在此流程中主要的目的是mSettingAutomaticBatterySaver 赋值:

    /**
     * {@link com.android.server.power.PowerManagerService} calls it when relevant global settings
     * have changed.
     *
     * Note this will be called before {@link #onBootCompleted} too.
     */
    @GuardedBy("mLock")
    @VisibleForTesting
    void setSettingsLocked(boolean batterySaverEnabled, boolean batterySaverEnabledSticky,
            int batterySaverTriggerThreshold,
            boolean isStickyAutoDisableEnabled, int stickyAutoDisableThreshold,
            int automaticBatterySaver,
            boolean dynamicPowerSavingsBatterySaver, int dynamicPowerSavingsDisableThreshold) {
...

mSettingAutomaticBatterySaver = automaticBatterySaver;

...


}

8) enableBatterySaverLocked 函数分析:

    @GuardedBy("mLock")
    private void enableBatterySaverLocked(boolean enable, boolean manual, int intReason) {
        enableBatterySaverLocked(enable, manual, intReason, reasonToString(intReason));
    } 

    /**
     * Actually enable / disable battery saver. Write the new state to the global settings
     * and propagate it to {@link #mBatterySaverController}.
     */
    @GuardedBy("mLock")
    private void enableBatterySaverLocked(boolean enable, boolean manual, int intReason,
            String strReason) {

        final boolean wasEnabled = mBatterySaverController.isFullEnabled();

        if (wasEnabled == enable) {
            return;
        }
        if (enable && mIsPowered) {
            return;
        }
        mLastChangedIntReason = intReason;
        mLastChangedStrReason = strReason;

        mSettingBatterySaverEnabled = enable;
        putGlobalSetting(Settings.Global.LOW_POWER_MODE, enable ? 1 : 0);

        if (manual) {
            setStickyActive(!mBatterySaverStickyBehaviourDisabled && enable);
        }

        //会发送低电量广播,后面会讲解:
        mBatterySaverController.enableBatterySaver(enable, intReason);

        // Handle triggering the notification to show/hide when appropriate

       //UI上控制
        if (intReason == BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON) {
            triggerDynamicModeNotification();
        } else if (!enable) {
            hideDynamicModeNotification();
        }
    }

 (4) BatterySaverController.java 中涉及到的流程讲解:

 LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java

1) enableBatterySaver 函数:

      /** Enable or disable full battery saver. */
      @VisibleForTesting
      public void enableBatterySaver(boolean enable, int reason) {
          synchronized (mLock) {
              if (getFullEnabledLocked() == enable) {
                  return;
              }

             //在此流程中enabletrue
              setFullEnabledLocked(enable);
             //updatePolicyLevelLocked 函数下面会讲解
              if (updatePolicyLevelLocked()) {
                  mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
              }
          }
      }

 2) setFullEnabledLocked 函数:

     主要目的是mFullEnabledRaw赋值为true

      @GuardedBy("mLock")
      private void setFullEnabledLocked(boolean value) {
          if (mFullEnabledRaw == value) {
              return;
          }
          PowerManager.invalidatePowerSaveModeCaches();
          mFullEnabledRaw = value;
      } 

3) getFullEnabledLocked 函数:

    主要目的是判断full 策略是否支持: 在此流程中,是支持的(true)

      /** Non-blocking getter exists as a reminder not to directly modify the cached field */
      private boolean getFullEnabledLocked() {
          return mFullEnabledRaw;
      }
 

4) updatePolicyLevelLocked函数:

  上面讲到:enableBatterySaver 函数里面会调用到updatePolicyLevelLocked

      private boolean updatePolicyLevelLocked() {

          //从上面流程可以看到getFullEnabledLocked()获取值是true
          if (getFullEnabledLocked()) {

            //配置策略为POLICY_LEVEL_FULL
              return      mBatterySaverPolicy.setPolicyLevel(BatterySaverPolicy.POLICY_LEVEL_FULL);
          } else if (getAdaptiveEnabledLocked()) {
              return mBatterySaverPolicy.setPolicyLevel(BatterySaverPolicy.POLICY_LEVEL_ADAPTIVE);
          } else {
              return mBatterySaverPolicy.setPolicyLevel(BatterySaverPolicy.POLICY_LEVEL_OFF);
          }
      } 

 (5) BatterySaverPolicy.java 涉及到流程:

  1)setPolicyLevel 函数讲解:

     其目的mPolicyLevel赋值updatePolicyDependenciesLocked函数执行

      /**
       * Sets the current policy.
       *
       * @return true if the policy level was changed.
       */
      boolean setPolicyLevel(@PolicyLevel int level) {
          synchronized (mLock) {
              if (mPolicyLevel == level) {
                  return false;
              }
              switch (level) {
                  case POLICY_LEVEL_FULL:
                  case POLICY_LEVEL_ADAPTIVE:
                  case POLICY_LEVEL_OFF:
                      mPolicyLevel = level;
                      break;
                  default:
                      Slog.wtf(TAG, "setPolicyLevel invalid level given: " + level);
                      return false;
              }
              updatePolicyDependenciesLocked();
              return true;
          }
      }

2) updatePolicyDependenciesLocked 函数:

   其目的:    

      @GuardedBy("mLock")
      private void updatePolicyDependenciesLocked() {

         //获取当前Policy
          final Policy rawPolicy = getCurrentRawPolicyLocked();
          final int locationMode;
  
          invalidatePowerSaveModeCaches();
          if (mCarModeEnabled
                  && rawPolicy.locationMode != PowerManager.LOCATION_MODE_NO_CHANGE
                  && rawPolicy.locationMode != PowerManager.LOCATION_MODE_FOREGROUND_ONLY) {
              // If car projection is enabled, ensure that navigation works.
              locationMode = PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
          } else {
              locationMode = rawPolicy.locationMode;
          }
        //mEffectivePolicyRaw重新赋值
          mEffectivePolicyRaw = new Policy(
                  rawPolicy.adjustBrightnessFactor,
                  rawPolicy.advertiseIsEnabled,
                  rawPolicy.deferFullBackup,
                  rawPolicy.deferKeyValueBackup,
                  rawPolicy.disableAnimation,
                  rawPolicy.disableAod,
                  rawPolicy.disableLaunchBoost,
                  rawPolicy.disableOptionalSensors,
                  rawPolicy.disableSoundTrigger,
                  // Don't disable vibration when accessibility is on.
                  rawPolicy.disableVibration && !mAccessibilityEnabled,
                  rawPolicy.enableAdjustBrightness,
                  rawPolicy.enableDataSaver,
                  rawPolicy.enableFirewall,
                  // Don't force night mode when car projection is enabled.
                  rawPolicy.enableNightMode && !mCarModeEnabled,
                  rawPolicy.enableQuickDoze,
                  rawPolicy.filesForInteractive,
                  rawPolicy.filesForNoninteractive,
                  rawPolicy.forceAllAppsStandby,
                  rawPolicy.forceBackgroundCheck,
                  locationMode
          );

      }

3) getCurrentRawPolicyLocked 函数:

    其目的是获取对应的policy,当前流程policy是mFullPolicy

       private Policy getCurrentRawPolicyLocked() {
          switch (mPolicyLevel) {
              case POLICY_LEVEL_FULL:
                  return mFullPolicy;
              case POLICY_LEVEL_ADAPTIVE:
                  return mAdaptivePolicy;
              case POLICY_LEVEL_OFF:
              default:
                  return OFF_POLICY;
          }
      }

4) mFullPolicy 的定义:

      /** The policy to be used for full battery saver. */
      @GuardedBy("mLock")

      //这是默认值:
      private Policy mFullPolicy = DEFAULT_FULL_POLICY;
        //通过deviceSpecificSetting 动态获取,若配置信息没有则从DEFAULT_FULL_POLICY中获取信息.在源码中没有发现有客户端触发deviceSpecificSetting。 预留接口: PowerManager.java::setAdaptivePowerSavePolicy(@NonNull BatterySaverPolicyConfig config), 目前逻辑就认为是polic 就复制DEFAULT_FULL_POLICY 里面的内容。
          Policy newFullPolicy = Policy.fromSettings(setting, deviceSpecificSetting,
                  DEFAULT_FULL_POLICY);
          mFullPolicy = newFullPolicy;

5) DEFAULT_FULL_POLICY 定义:

    private static final Policy DEFAULT_FULL_POLICY = new Policy(
            0.5f,  /* adjustBrightnessFactor */
            true,  /* advertiseIsEnabled */
            true,  /* deferFullBackup */
            true,  /* deferKeyValueBackup */
            false, /* disableAnimation */
            true,  /* disableAod */
            true,  /* disableLaunchBoost */
            true,  /* disableOptionalSensors */
            true,  /* disableSoundTrigger */
            true,  /* disableVibration */
            false, /* enableAdjustBrightness */
            false, /* enableDataSaver */
            true,  /* enableFirewall */
            true, /* enableNightMode */
            true, /* enableQuickDoze */
            new ArrayMap<>(), /* filesForInteractive */
            new ArrayMap<>(), /* filesForNoninteractive */
            true, /* forceAllAppsStandby */
            true, /* forceBackgroundCheck */
            PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF /* locationMode */
    ); 

6) 前面讲了那么多,其实是为updatePowerRequestFromBatterySaverPolicy 函数里面,获取PowerSaveState 铺垫:

再此阅读updatePowerRequestFromBatterySaverPolicy

     @VisibleForTesting
    void updatePowerRequestFromBatterySaverPolicy(DisplayPowerRequest displayPowerRequest) {

       //很明显mBatterySaverPolicy 的值就是来自DEFAULT_FULL_POLICY,
        PowerSaveState state = mBatterySaverPolicy.
                getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS);

        //若是使用默认DEFAULT_FULL_POLICY的获取到state.batterySaverEnabled 为false
        displayPowerRequest.lowPowerMode = state.batterySaverEnabled;
        displayPowerRequest.screenLowPowerBrightnessFactor = state.brightnessFactor;
    }

     /**
     * Get the {@link PowerSaveState} based on the current policy level.
     * The result will have {@link PowerSaveState#batterySaverEnabled} and some other
     * parameters when necessary.
     *
     * @param type   type of the service, one of {@link ServiceType}
     * @return State data that contains battery saver data
     */
    public PowerSaveState getBatterySaverPolicy(@ServiceType int type) {
        synchronized (mLock) {
            final Policy currPolicy = getCurrentPolicyLocked();
            final PowerSaveState.Builder builder = new PowerSaveState.Builder()
                    .setGlobalBatterySaverEnabled(currPolicy.advertiseIsEnabled);
            switch (type) {
..
                case ServiceType.SCREEN_BRIGHTNESS:

                   //enableAdjustBrightness是false ,adjustBrightnessFactor 是0.5
                    return builder.setBatterySaverEnabled(currPolicy.enableAdjustBrightness)
                            .setBrightnessFactor(currPolicy.adjustBrightnessFactor)
                            .build();
..

七.低电量广播发送

(1)  广播发送定义: 在handleBatterySaverStateChanged函数中.

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java

1)广播发送:

    /**
     * Dispatch power save events to the listeners.
     *
     * This method is always called on the handler thread.
     *
     * This method is called only in the following cases:
     * - When battery saver becomes activated.
     * - When battery saver becomes deactivated.
     * - When battery saver is on and the interactive state changes.
     * - When battery saver is on and the battery saver policy changes.
     * - When adaptive battery saver becomes activated.
     * - When adaptive battery saver becomes deactivated.
     * - When adaptive battery saver is active (and full is off) and the policy changes.
     */
    void handleBatterySaverStateChanged(boolean sendBroadcast, int reason) {
        final LowPowerModeListener[] listeners;

        final boolean enabled;
        final boolean isInteractive = getPowerManager().isInteractive();
        final ArrayMap fileValues;

        synchronized (mLock) {
            enabled = getFullEnabledLocked() || getAdaptiveEnabledLocked();

            EventLogTags.writeBatterySaverMode(
                    mFullPreviouslyEnabled ? 1 : 0, // Previously off or on.
                    mAdaptivePreviouslyEnabled ? 1 : 0, // Previously off or on.
                    getFullEnabledLocked() ? 1 : 0, // Now off or on.
                    getAdaptiveEnabledLocked() ? 1 : 0, // Now off or on.
                    isInteractive ?  1 : 0, // Device interactive state.
                    enabled ? mBatterySaverPolicy.toEventLogString() : "",
                    reason);

            mFullPreviouslyEnabled = getFullEnabledLocked();
            mAdaptivePreviouslyEnabled = getAdaptiveEnabledLocked();

            listeners = mListeners.toArray(new LowPowerModeListener[0]);

            mIsInteractive = isInteractive;

            if (enabled) {
                fileValues = mBatterySaverPolicy.getFileValues(isInteractive);
            } else {
                fileValues = null;
            }
        }

        final PowerManagerInternal pmi = LocalServices.getService(PowerManagerInternal.class);
        if (pmi != null) {
            pmi.powerHint(PowerHint.LOW_POWER, isEnabled() ? 1 : 0);
        }

        updateBatterySavingStats();

        if (ArrayUtils.isEmpty(fileValues)) {
            mFileUpdater.restoreDefault();
        } else {
            mFileUpdater.writeFiles(fileValues);
        }

        for (Plugin p : mPlugins) {
            p.onBatterySaverChanged(this);
        }

       //sendBroadcast 为true 时才发送广播

        if (sendBroadcast) {

            if (DEBUG) {
                Slog.i(TAG, "Sending broadcasts for mode: " + isEnabled());
            }

            // Send the broadcasts and notify the listeners. We only do this when the battery saver
            // mode changes, but not when only the screen state changes.
            Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)
                    .putExtra(PowerManager.EXTRA_POWER_SAVE_MODE, isEnabled())
                    .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);

            intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);

            // Send the broadcast to a manifest-registered receiver that is specified in the config.
            if (getPowerSaveModeChangedListenerPackage().isPresent()) {
                intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)
                        .setPackage(getPowerSaveModeChangedListenerPackage().get())
                        .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
                                | Intent.FLAG_RECEIVER_FOREGROUND);
                mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
            }

            // Send internal version that requires signature permission.
            intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED_INTERNAL);
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
            mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
                    Manifest.permission.DEVICE_POWER);

             //对listeners做callback

            for (LowPowerModeListener listener : listeners) {
                final PowerSaveState result =
                        mBatterySaverPolicy.getBatterySaverPolicy(listener.getServiceType());
                listener.onLowPowerModeChanged(result);
            }
        }
    }

2) 通过接收MSG_STATE_CHANGED进行判断是否要发送广播;postStateChanged 函数触发MSG_STATE_CHANGED handle 机制。

    private class MyHandler extends Handler {
        private static final int MSG_STATE_CHANGED = 1;

        void postStateChanged(boolean sendBroadcast, int reason) {
            obtainMessage(MSG_STATE_CHANGED, sendBroadcast ?
                    ARG_SEND_BROADCAST : ARG_DONT_SEND_BROADCAST, reason).sendToTarget();
        }
        @Override
        public void dispatchMessage(Message msg) {
            switch (msg.what) {
                case MSG_STATE_CHANGED:
                    handleBatterySaverStateChanged(
                            msg.arg1 == ARG_SEND_BROADCAST,
                            msg.arg2);
                    break;
            }
        }
    }

 3) 触发postStateChanged函数的地方:    onBatterySaverPolicyChanged/enableBatterySaver/setAdaptivePolicyLocked/resetAdaptivePolicyLocked/setAdaptivePolicyEnabledLocked

    @Override
    public void onBatterySaverPolicyChanged(BatterySaverPolicy policy) {
        if (!isPolicyEnabled()) {
            return; // No need to send it if not enabled.
        }
        mHandler.postStateChanged(/*sendBroadcast=*/ true, REASON_POLICY_CHANGED);
    }


    /** Enable or disable full battery saver. */
    @VisibleForTesting
    public void enableBatterySaver(boolean enable, int reason) {
        synchronized (mLock) {
            if (getFullEnabledLocked() == enable) {
                return;
            }
            setFullEnabledLocked(enable);

            if (updatePolicyLevelLocked()) {
                mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
            }
        }
    }

    boolean setAdaptivePolicyLocked(Policy policy, int reason) {
        if (mBatterySaverPolicy.setAdaptivePolicyLocked(policy)) {
            mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
            return true;
        }
        return false;
    }

    boolean resetAdaptivePolicyLocked(int reason) {
        if (mBatterySaverPolicy.resetAdaptivePolicyLocked()) {
            mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
            return true;
        }
        return false;
    }

    boolean setAdaptivePolicyEnabledLocked(boolean enabled, int reason) {
        if (getAdaptiveEnabledLocked() == enabled) {
            return false;
        }
        setAdaptiveEnabledLocked(enabled);
        if (updatePolicyLevelLocked()) {
            mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
            return true;
        }
        return false;
    }

八. 总结

1.低电量广播何时发送?

 当处于低电量时,电量小于15%时, 会触发ACTION_POWER_SAVE_MODE_CHANGED,下发给各个接受者。

2. 已经处于低电量状态,是否重复下发ACTION_POWER_SAVE_MODE_CHANGED 下发给各个接受者,告知还是处于低电量模式?

从源码上看,是不会重新下发告知是处于低电量,除非当手机充电或者手动关闭等退出省电模式。

3.  自动进入省电模式,都会影响那些方面?

     主要看使用那种省电模式的policy,默认是full policy ,主要影响的有:DEFAULT_FULL_POLICY 和OFF_POLICY .当然,可以自定义policy.

4. 什么情况下会退出省电模式?

  (1) 有充电行为,譬如: AC ,USB ,无线充电。

  (2) 电量大于等于20%(默认)

  (3) 当电量大于等于15%(默认) 并且在Setting中手动关闭省电模式。

5. 在哪里配置进入省电模式和退出省电模式的等级? 

LAW.BR.5.1/LINUX/android/frameworks/base/core/res/res/values/config.xml

     
      config_lowBatteryWarningLevel">15

     
     config_lowBatteryCloseWarningBump">5

     

 6. 省电模式的policy 动态配置信息,保存在哪里?

adb shell settings get Global battery_saver_device_specific_constants

你可能感兴趣的:(framework,android)