美文网首页
Android P 省电模式(LowPowerMode)(一)

Android P 省电模式(LowPowerMode)(一)

作者: 最忆是深秋 | 来源:发表于2019-03-15 16:03 被阅读0次

    省电模式手动开启流程

    `frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java

            public boolean setPowerSaveMode(boolean enabled) {
                mContext.enforceCallingOrSelfPermission(
                        android.Manifest.permission.DEVICE_POWER, null);
                final long ident = Binder.clearCallingIdentity();
                try {
                    return setLowPowerModeInternal(enabled);
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
            }
    

    首先检查调用者是否有 android.Manifest.permission.DEVICE_POWER 权限。

        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;
            }
        }
    

    frameworks\base\services\core\java\com\android\server\power\batterysaver\BatterySaverStateMachine.java

    手动开关 省电模式:

        public void setBatterySaverEnabledManually(boolean enabled) {
            if (DEBUG) {
                Slog.d(TAG, "setBatterySaverEnabledManually: enabled=" + enabled);
            }
            synchronized (mLock) {
                enableBatterySaverLocked(/*enable=*/ enabled, /*manual=*/ true,
                        (enabled ? BatterySaverController.REASON_MANUAL_ON
                                : BatterySaverController.REASON_MANUAL_OFF),
                        (enabled ? "Manual ON" : "Manual OFF"));
            }
        }
    
        /**
         * Actually enable / disable battery saver. Write the new state to the global settings
         * and propagate it to {@link #mBatterySaverController}.
         */
        private void enableBatterySaverLocked(boolean enable, boolean manual, int intReason,
                String strReason) {
            if (DEBUG) {
                Slog.d(TAG, "enableBatterySaver: enable=" + enable + " manual=" + manual
                        + " reason=" + strReason + "(" + intReason + ")");
            }
            final boolean wasEnabled = mBatterySaverController.isEnabled();
    
            //省电模式状态没有改变的话直接return
            if (wasEnabled == enable) {
                if (DEBUG) {
                    Slog.d(TAG, "Already " + (enable ? "enabled" : "disabled"));
                }
                return;
            }
            //充电情况下尝试打开 省电模式 直接return
            if (enable && mIsPowered) {
                if (DEBUG) Slog.d(TAG, "Can't enable: isPowered");
                return;
            }
            //记录此次改变省电模式状态的 reason ,各个 reason 的值定义在 BatterySaverController 中
            mLastChangedIntReason = intReason;
            mLastChangedStrReason = strReason;
    
            //mBatterySaverSnoozing 主要是用于记录 低电量情况下,用户是否手动关闭 了省电模式,防止用户手动关闭 省电模式后,又被自动打开
            if (manual) {
                if (enable) {
                    updateSnoozingLocked(false, "Manual snooze OFF");
                } else {
                    // 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.
                    if (isBatterySaverEnabled() && mIsBatteryLevelLow) {
                        updateSnoozingLocked(true, "Manual snooze");
                    }
                }
            }
    
            mSettingBatterySaverEnabled = enable;
            //更新 省电模式状态 到 settings 数据库字段中
            putGlobalSetting(Global.LOW_POWER_MODE, enable ? 1 : 0);
    
            if (manual) {
                mSettingBatterySaverEnabledSticky = enable;
                putGlobalSetting(Global.LOW_POWER_MODE_STICKY, enable ? 1 : 0);
            }
            //好了,前面这些全部都是前戏,这里才开始真正的做 省电的动作
            mBatterySaverController.enableBatterySaver(enable, intReason);
    
            if (DEBUG) {
                Slog.d(TAG, "Battery saver: Enabled=" + enable
                        + " manual=" + manual
                        + " reason=" + strReason + "(" + intReason + ")");
            }
        }
    

    frameworks\base\services\core\java\com\android\server\power\batterysaver\BatterySaverController.java

        /**
         * Called by {@link PowerManagerService} to update the battery saver stete.
         */
        public void enableBatterySaver(boolean enable, int reason) {
            synchronized (mLock) {
                if (mEnabled == enable) {
                    return;
                }
                mEnabled = enable;
    
                mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
            }
        }
    

    消息经过分发,最终执行 handleBatterySaverStateChanged

        /**
         * 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 the interactive state changes.
         * - When battery saver is on the battery saver policy changes.
         */
        void handleBatterySaverStateChanged(boolean sendBroadcast, int reason) {
            final LowPowerModeListener[] listeners;
    
            final boolean enabled;
            //isInteractive 用于标志设备是否处于可交互状态
            final boolean isInteractive = getPowerManager().isInteractive();
            final ArrayMap<String, String> fileValues;
    
            synchronized (mLock) {
                //battery_saver_mode: [1,0,1,,1] event log的格式,大致含义根据变量名就可以看出来
                EventLogTags.writeBatterySaverMode(
                        mPreviouslyEnabled ? 1 : 0, // Previously off or on.
                        mEnabled ? 1 : 0, // Now off or on.
                        isInteractive ?  1 : 0, // Device interactive state.
                        mEnabled ? mBatterySaverPolicy.toEventLogString() : "",
                        reason);
                mPreviouslyEnabled = mEnabled;
    
                listeners = mListeners.toArray(new LowPowerModeListener[mListeners.size()]);
    
                enabled = mEnabled;
                mIsInteractive = isInteractive;
    
                if (enabled) {
                    fileValues = mBatterySaverPolicy.getFileValues(isInteractive);
                } else {
                    fileValues = null;
                }
            }
    
            //似乎是 CPU 频率相关的设置,下面是 到JNI里,没有去跟
            final PowerManagerInternal pmi = LocalServices.getService(PowerManagerInternal.class);
            if (pmi != null) {
                pmi.powerHint(PowerHint.LOW_POWER, enabled ? 1 : 0);
            }
    
            updateBatterySavingStats();
    
            if (ArrayUtils.isEmpty(fileValues)) {
                mFileUpdater.restoreDefault();
            } else {
                mFileUpdater.writeFiles(fileValues);
            }
    
            //目前来看,原生的代码里只有一种 BatterySaverLocationPlugin
            // plugins.add(new BatterySaverLocationPlugin(mContext));
            for (Plugin p : mPlugins) {
                p.onBatterySaverChanged(this);
            }
    
            if (sendBroadcast) {
    
                if (DEBUG) {
                    Slog.i(TAG, "Sending broadcasts for mode: " + enabled);
                }
    
                // 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, enabled)
                        .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 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);
    
                //回调 所有注册了 LowPowerModeListener 的client
                //主要有 VibratorService,NetworkPolicyManagerService,WindowManagerService
                for (LowPowerModeListener listener : listeners) {
                    final PowerSaveState result =
                            mBatterySaverPolicy.getBatterySaverPolicy(
                                    listener.getServiceType(), enabled);
                    listener.onLowPowerModeChanged(result);
                }
            }
        }
    

    主要关注 ACTION_POWER_SAVE_MODE_CHANGED 这个 广播的分发:

    接收类 作用
    BatteryBroadcastReceiver(Settings) 通知了电池电量的改变,进入power save的模式
    PowerUI(SystemUI) 如果在power save的模式下,就忽略电池低电的提醒
    DeviceStateMonitor(Telephony) 设置modem为power save的模式
    SoundTriggerHelper (framework) 关闭语音互动的功能
    GnssLocationProvider(framework) 限制gps使用,灭屏后会关闭gps

    总结一下 手动打开 省电模式的过程:


    1. 先判断是否有 android.Manifest.permission.DEVICE_POWER 权限
    2. 判断是否允许改变 省电模式的状态 (检查充电状态,原生 省电模式 和 充电是互斥的)
    3. 更新省电模式状态到 System.Global.LOW_POWER_MODE
    4. 发送 ACTION_POWER_SAVE_MODE_CHANGING, ACTION_POWER_SAVE_MODE_CHANGED, ACTION_POWER_SAVE_MODE_CHANGED_INTERNAL三种广播到 动态注册的组件中
    5. 回调所有注册的 LowPowerModeListener(onLowPowerModeChanged)plugin(onBatterySaverChanged)

    到这里我们还没看到 省电模式 具体是如何省电的?下一篇我们继续.....

    相关文章

      网友评论

          本文标题:Android P 省电模式(LowPowerMode)(一)

          本文链接:https://www.haomeiwen.com/subject/eehrmqtx.html