Android P 省電模式(LowPowerMode)(一) ------ 開啟流程

省電模式手動(dòng)開啟流程

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

首先檢查調(diào)用者是否有 android.Manifest.permission.DEVICE_POWER 權(quán)限。

    private boolean setLowPowerModeInternal(boolean enabled) {
        synchronized (mLock) {
            if (DEBUG) {
                Slog.d(TAG, "setLowPowerModeInternal " + enabled + " mIsPowered=" + mIsPowered);
            }
            if (mIsPowered) {//充電狀態(tài)不允許改變 低電量模式 狀態(tài)
                return false;
            }

            mBatterySaverStateMachine.setBatterySaverEnabledManually(enabled);

            return true;
        }
    }

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

手動(dòng)開關(guān) 省電模式:

    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();

        //省電模式狀態(tài)沒有改變的話直接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;
        }
        //記錄此次改變省電模式狀態(tài)的 reason ,各個(gè) reason 的值定義在 BatterySaverController 中
        mLastChangedIntReason = intReason;
        mLastChangedStrReason = strReason;

        //mBatterySaverSnoozing 主要是用于記錄 低電量情況下,用戶是否手動(dòng)關(guān)閉 了省電模式,防止用戶手動(dòng)關(guān)閉 省電模式后,又被自動(dòng)打開
        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;
        //更新 省電模式狀態(tài) 到 settings 數(shù)據(jù)庫字段中
        putGlobalSetting(Global.LOW_POWER_MODE, enable ? 1 : 0);

        if (manual) {
            mSettingBatterySaverEnabledSticky = enable;
            putGlobalSetting(Global.LOW_POWER_MODE_STICKY, enable ? 1 : 0);
        }
        //好了,前面這些全部都是前戲,這里才開始真正的做 省電的動(dòng)作
        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);
        }
    }

消息經(jīng)過分發(fā),最終執(zhí)行 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 用于標(biāo)志設(shè)備是否處于可交互狀態(tài)
        final boolean isInteractive = getPowerManager().isInteractive();
        final ArrayMap<String, String> fileValues;

        synchronized (mLock) {
            //battery_saver_mode: [1,0,1,,1] event log的格式,大致含義根據(jù)變量名就可以看出來
            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 頻率相關(guān)的設(shè)置,下面是 到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);

            //回調(diào) 所有注冊(cè)了 LowPowerModeListener 的client
            //主要有 VibratorService,NetworkPolicyManagerService,WindowManagerService
            for (LowPowerModeListener listener : listeners) {
                final PowerSaveState result =
                        mBatterySaverPolicy.getBatterySaverPolicy(
                                listener.getServiceType(), enabled);
                listener.onLowPowerModeChanged(result);
            }
        }
    }

主要關(guān)注 ACTION_POWER_SAVE_MODE_CHANGED 這個(gè) 廣播的分發(fā):

接收類 作用
BatteryBroadcastReceiver(Settings) 通知了電池電量的改變,進(jìn)入power save的模式
PowerUI(SystemUI) 如果在power save的模式下,就忽略電池低電的提醒
DeviceStateMonitor(Telephony) 設(shè)置modem為power save的模式
SoundTriggerHelper (framework) 關(guān)閉語音互動(dòng)的功能
GnssLocationProvider(framework) 限制gps使用,滅屏后會(huì)關(guān)閉gps

總結(jié)一下 手動(dòng)打開 省電模式的過程:


  1. 先判斷是否有 android.Manifest.permission.DEVICE_POWER 權(quán)限
  2. 判斷是否允許改變 省電模式的狀態(tài) (檢查充電狀態(tài),原生 省電模式 和 充電是互斥的)
  3. 更新省電模式狀態(tài)到 System.Global.LOW_POWER_MODE
  4. 發(fā)送 ACTION_POWER_SAVE_MODE_CHANGING, ACTION_POWER_SAVE_MODE_CHANGED, ACTION_POWER_SAVE_MODE_CHANGED_INTERNAL三種廣播到 動(dòng)態(tài)注冊(cè)的組件中
  5. 回調(diào)所有注冊(cè)的 LowPowerModeListener(onLowPowerModeChanged)plugin(onBatterySaverChanged)

到這里我們還沒看到 省電模式 具體是如何省電的?下一篇我們繼續(xù).....

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容