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

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

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

    在上篇文章Android P 省电模式(LowPowerMode)(一) ------ 省电模式手动开启流程 中最后分析到,开启省电模式后,会在 BatterySaverController 中回调所有注册的 LowPowerModeListener(onLowPowerModeChanged)和 plugin(onBatterySaverChanged),并发出广播。 我们看一下 系统做了哪些事情来实现省电。
    主要有 振动,亮度,网络访问,GPS位置信息,动画,语音识别几个方面。

    1. 限制振动 VibratorService.java

    VibratorService.java中回调:

        public void systemReady() {
            Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "VibratorService#systemReady");
            try {
            
                ..........................
                
                mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
                mPowerManagerInternal.registerLowPowerModeObserver(
                        new PowerManagerInternal.LowPowerModeListener() {
                            @Override
                            public int getServiceType() {
                                return ServiceType.VIBRATION;
                            }
    
                            @Override
                            public void onLowPowerModeChanged(PowerSaveState result) {
                                updateVibrators();//更改低电量状态
                            }
                });
    
                ..........................
        }
    
        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();
                }
            }
        }
    
        private boolean updateLowPowerModeLocked() {
            boolean lowPowerMode = mPowerManagerInternal
                    .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled;//看看这个值怎么拿到的
            if (lowPowerMode != mLowPowerMode) {
                mLowPowerMode = lowPowerMode;//mLowPowerMode这个变量判断要不要震动会用到
                return true;
            }
            return false;
        }
    

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

        @Override
        public PowerSaveState getLowPowerState(@ServiceType int serviceType) {
            return mBatterySaverPolicy.getBatterySaverPolicy(serviceType,
                 mBatterySaverController.isEnabled());//这个方法根据传入的serviceType 决定要不要对省电模式做出反应,很关键的方法
        }
    

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

    
        /**
         * Get the {@link PowerSaveState} based on {@paramref type} and {@paramref realMode}.
         * The result will have {@link PowerSaveState#batterySaverEnabled} and some other
         * parameters when necessary.
         *
         * @param type     type of the service, one of {@link ServiceType}
         * @param realMode whether the battery saver is on by default
         * @return State data that contains battery saver data
         */
        public PowerSaveState getBatterySaverPolicy(@ServiceType int type, boolean realMode) {
            synchronized (mLock) {
                final PowerSaveState.Builder builder = new PowerSaveState.Builder()
                        .setGlobalBatterySaverEnabled(realMode);
                if (!realMode) {
                    return builder.setBatterySaverEnabled(realMode)
                            .build();
                }
                switch (type) {
                    case ServiceType.GPS:
                        return builder.setBatterySaverEnabled(realMode)
                                .setGpsMode(mGpsMode)
                                .build();
                    case ServiceType.ANIMATION:
                        return builder.setBatterySaverEnabled(mAnimationDisabled)
                                .build();//mVibrationDisabledEffective决定省电模式下要不要取消动画
                    case ServiceType.FULL_BACKUP:
                        return builder.setBatterySaverEnabled(mFullBackupDeferred)
                                .build();
                    case ServiceType.KEYVALUE_BACKUP:
                        return builder.setBatterySaverEnabled(mKeyValueBackupDeferred)
                                .build();
                    case ServiceType.NETWORK_FIREWALL:
                        return builder.setBatterySaverEnabled(!mFireWallDisabled)
                                .build();
                    case ServiceType.SCREEN_BRIGHTNESS:
                        return builder.setBatterySaverEnabled(!mAdjustBrightnessDisabled)
                                .setBrightnessFactor(mAdjustBrightnessFactor)
                                .build();
                    case ServiceType.DATA_SAVER:
                        return builder.setBatterySaverEnabled(!mDataSaverDisabled)
                                .build();
                    case ServiceType.SOUND:
                        return builder.setBatterySaverEnabled(mSoundTriggerDisabled)
                                .build();
                    case ServiceType.VIBRATION:
                        return builder.setBatterySaverEnabled(mVibrationDisabledEffective)
                                .build();//mVibrationDisabledEffective决定省电模式下要不要禁止振动
                    case ServiceType.FORCE_ALL_APPS_STANDBY:
                        return builder.setBatterySaverEnabled(mForceAllAppsStandby)
                                .build();
                    case ServiceType.FORCE_BACKGROUND_CHECK:
                        return builder.setBatterySaverEnabled(mForceBackgroundCheck)
                                .build();
                    case ServiceType.OPTIONAL_SENSORS:
                        return builder.setBatterySaverEnabled(mOptionalSensorsDisabled)
                                .build();
                    case ServiceType.AOD:
                        return builder.setBatterySaverEnabled(mAodDisabled)
                                .build();
                    default:
                        return builder.setBatterySaverEnabled(realMode)
                                .build();
                }
            }
        }
    

    BatterySaverPolicy.java 这个类很关键,所有关于省电模式的默认配置都在这个类里面初始化,如果要定制省电模式行为的话,这个类会被用到。

    回调的流程的最终目的就是根据配置修改了 mLowPowerMode 变量的值,这个值会在调用振动时使用,用以决定要不要振动。

        @GuardedBy("mLock")
        private void startVibrationLocked(final Vibration vib) {
            Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationLocked");
            try {
                //关于省电模式下是否允许振动在这个方法里判断
                if (!isAllowedToVibrateLocked(vib)) {
                    return;
                }
                //
                final int intensity = getCurrentIntensityLocked(vib);
                if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) {
                    return;
                }
    
                //如果是来电且响铃时振动开关未打开,则不振动
                if (vib.isRingtone() && !shouldVibrateForRingtone()) {
                    if (DEBUG) {
                        Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones");
                    }
                    return;
                }
    
                ........................
        }
    
        private boolean isAllowedToVibrateLocked(Vibration vib) {
            //如果不在省电模式则允许振动,如果在省电模式,排除掉以下几种情况外都不允许震动
            if (!mLowPowerMode) {
                return true;
            }
    
            //省电模式对铃声振动不影响
            if (vib.usageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
                return true;
            }
            //省电模式对 闹钟,辅助功能和 VoIP通话,视频通话 的振动不影响
            if (vib.usageHint == AudioAttributes.USAGE_ALARM ||
                    vib.usageHint == AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY ||
                    vib.usageHint == AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST) {
                return true;
            }
    
            return false;
        }
    
    2. 降低屏幕亮度

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

        /**
         * 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);
            
            ..........................
        }
    
        @VisibleForTesting
        void updatePowerRequestFromBatterySaverPolicy(DisplayPowerRequest displayPowerRequest) {
            PowerSaveState state = mBatterySaverPolicy.
                    getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS,
                            mBatterySaverController.isEnabled());
            displayPowerRequest.lowPowerMode = state.batterySaverEnabled;
            displayPowerRequest.screenLowPowerBrightnessFactor = state.brightnessFactor;
        }
    

    frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java :

            public boolean requestPowerState(DisplayPowerRequest request,
                    boolean waitForNegativeProximity) {
                synchronized (mSyncRoot) {
                    return mDisplayPowerController.requestPowerState(request,
                            waitForNegativeProximity);
                }
            }
    

    frameworks\base\services\core\java\com\android\server\display\DisplayPowerController.java

        public boolean requestPowerState(DisplayPowerRequest request,
                boolean waitForNegativeProximity) {
            ................................
    
                if (changed && !mPendingRequestChangedLocked) {
                    mPendingRequestChangedLocked = true;
                    sendUpdatePowerStateLocked();
                }
    
            .................................
            }
        }
    

    sendUpdatePowerStateLocked 内部交由 Handler 消息处理,最终会调用 updatePowerState 方法:

        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 (brightness > mScreenBrightnessRangeMinimum) {
                    final float brightnessFactor =
                            Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);// 亮度缩放比例
                    final int lowPowerBrightness = (int) (brightness * brightnessFactor);
                    brightness = Math.max(lowPowerBrightness, mScreenBrightnessRangeMinimum);
                }
            } 
            ............................
    
        }
    

    BatterySaverPolicy.java 中定义的 默认亮度缩放比例是 0.5,亮度降低一半

    mAdjustBrightnessDisabled = parser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED, true); //原生的配置是省电模式情况下默认不调节亮度

    mAdjustBrightnessFactor = parser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR, 0.5f);

    3. WindowManagerService 动画

    frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java :

                mPowerManagerInternal.registerLowPowerModeObserver(
                        new PowerManagerInternal.LowPowerModeListener() {
                    @Override
                    public int getServiceType() {
                        return ServiceType.ANIMATION;
                    }
    
                    @Override
                    public void onLowPowerModeChanged(PowerSaveState result) {
                        synchronized (mWindowMap) {
                            //BatterySaverPolicy中配置的是否要在低电量中关闭动画,android P上是 false,默认不关闭动画,8.0上是true的
                            final boolean enabled = result.batterySaverEnabled;
                            //mAllowAnimationsInLowPowerMode代表是否在允许在低电模式下继续使用动画(默认是false,就是不允许),如果在低电模式下会把WMS的动画都关闭
                            if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
                                mAnimationsDisabled = enabled;
                                dispatchNewAnimatorScaleLocked(null);
                            }
                        }
                    }
                });
    

    9.0上低电量模式下是不关闭动画的,8.0上是关闭的。

    4. NetworkPolicyManagerService.java 网络防火墙

    frameworks\base\services\core\java\com\android\server\net\NetworkPolicyManagerService.java

        private void updateRulesForRestrictPowerUL() {
            Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictPowerUL");
            try {
                updateRulesForDeviceIdleUL();
                updateRulesForPowerSaveUL();
                updateRulesForAllAppsUL(TYPE_RESTRICT_POWER);
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
            }
        }
    

    低电量模式下主要就是去更新网络访问的规则,没仔细研究,不敢妄言,Android P上也是默认没有打开限制的,开启低电量模式不去限制网络。

    5. GPS 位置信息相关限制

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

        private void updateLocationState(BatterySaverController caller) {
            final boolean kill =
                    (caller.getBatterySaverPolicy().getGpsMode()
                            == PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF) &&
                    caller.isEnabled() && !caller.isInteractive();
    
            if (DEBUG) {
                Slog.d(TAG, "Battery saver " + (kill ? "stopping" : "restoring") + " location.");
            }
            Settings.Global.putInt(mContext.getContentResolver(),
                    Global.LOCATION_GLOBAL_KILL_SWITCH, kill ? 1 : 0);
        }
    
            /**
             * If set to 1, {@link Secure#LOCATION_MODE} will be set to {@link Secure#LOCATION_MODE_OFF}
             * temporarily for all users.
             *
             * @hide
             */
            @TestApi
            public static final String LOCATION_GLOBAL_KILL_SWITCH =
                    "location_global_kill_switch";
    

    低电量情况下,灭屏后会关闭GPS,临时限制所有应用访问位置信息。

    以上都是 开启低电量模式后,BatterySaverController.java 中主动去回调的,以下是 各模块自己监听 ACTION_POWER_SAVE_MODE_CHANGED 广播后自己处理的

    6. 语音互动的功能

    frameworks\base\services\voiceinteraction\java\com\android\server\soundtrigger\SoundTriggerHelper.java :

     // A single routine that implements the start recognition logic for both generic and keyphrase
        // models.
        private int startRecognitionLocked(ModelData modelData, boolean notify) {
            ...........................
    
            if (!isRecognitionAllowed()) {
                // Nothing to do here.
                Slog.w(TAG, "startRecognition requested but not allowed.");
                MetricsLogger.count(mContext, "sth_start_recognition_not_allowed", 1);
                return STATUS_OK;
            }
        }
    
        // 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() {
            return !mCallActive && !mServiceDisabled && !mIsPowerSaveMode;
        }
    

    低电量模式下不识别语音

    其他各上层模块,如settings,systemUI 也监听了 ACTION_POWER_SAVE_MODE_CHANGED 广播,主要是做一些 UI上的变化。

    相关文章

      网友评论

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

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