PowerUI 的启动流程及其功用。

PowerUI

PowerUISystemUI 显示电池相关信息的模块,包括低电量提醒、危急电量关机提醒、高温关机提醒、省电模式等功能。

启动流程

上一篇介绍 SystemUI 启动时会加载众多功能模块其中就包含 PowerUI ,其会直接调用 PowerUI.start() 方法来启动。

PowerUI.start()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public void start() {
    // 获取  PowerManager 用于获取电池相关信息
    mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
    // 获取  HardwarePropertiesManager 用于获取电池温度
    mHardwarePropertiesManager = (HardwarePropertiesManager)
        mContext.getSystemService(Context.HARDWARE_PROPERTIES_SERVICE);
    // 获取自启动以来的毫秒数
    mScreenOffTime = mPowerManager.isScreenOn() ? -1 : SystemClock.elapsedRealtime();
    mWarnings = Dependency.get(WarningsUI.class);
    // 和混合通知相关,相关功能平台默认是关闭的,我们暂时也就不关注了
    mEnhancedEstimates = Dependency.get(EnhancedEstimates.class);
    mLastConfiguration.setTo(mContext.getResources().getConfiguration());
    // 监测低电量阀值的改变
    ContentObserver obs = new ContentObserver(mHandler) {
            @Override
            public void onChange(boolean selfChange) {
                updateBatteryWarningLevels();
            }
        };
    final ContentResolver resolver = mContext.getContentResolver();
    resolver.registerContentObserver(Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
                                     false, obs, UserHandle.USER_ALL);
    // 更新低电量等阀值
    updateBatteryWarningLevels();
    // 监听相关广播
    mReceiver.init();

    // Check to see if we need to let the user know that the phone previously shut down due
    // to the temperature being too high.
    // 如果上次因过热而关机则告知用户
    showThermalShutdownDialog();
    // 初始化温度阀值
    initTemperatureWarning();
}

低电量警告

  • updateBatteryWarningLevels()

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    void updateBatteryWarningLevels() {
        // 获取系统配置的危急电量值,默认:5
        int critLevel = mContext.getResources()
            .getInteger(com.android.internal.R.integer.config_criticalBatteryWarningLevel);
        // 获取系统配置的低电量值,默认:15
        int warnLevel = mContext.getResources()
            .getInteger(com.android.internal.R.integer.config_lowBatteryWarningLevel);
    
        if (warnLevel < critLevel) {
            warnLevel = critLevel;
        }
    
        mLowBatteryReminderLevels[0] = warnLevel;
        mLowBatteryReminderLevels[1] = critLevel;
        // 获取系统配置的关闭低电量警告状态的电量值,默认:20(15+5)
        mLowBatteryAlertCloseLevel = mLowBatteryReminderLevels[0]
            + mContext.getResources()
            .getInteger(com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
    }
  • 电池相关广播监听

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    
    final class Receiver extends BroadcastReceiver {
        public void init() {
            // Register for Intent broadcasts for...
            IntentFilter filter = new IntentFilter();
            // 省电模式改变
            filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
            // 电池状态改变
            filter.addAction(Intent.ACTION_BATTERY_CHANGED);
            // 开关屏
            filter.addAction(Intent.ACTION_SCREEN_OFF);
            filter.addAction(Intent.ACTION_SCREEN_ON);
            // 切换用户
            filter.addAction(Intent.ACTION_USER_SWITCHED);
            mContext.registerReceiver(this, filter, null, mHandler);
        }
    
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)) {
                ThreadUtils.postOnBackgroundThread(() -> {
                        if (mPowerManager.isPowerSaveMode()) {
                            // 开启省电模式则关闭低电量警告
                            mWarnings.dismissLowBatteryWarning();
                        }
                    });
            } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
                // 电量
                final int oldBatteryLevel = mBatteryLevel;
                mBatteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100);
                final int oldBatteryStatus = mBatteryStatus;
                mBatteryStatus = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
                                                    BatteryManager.BATTERY_STATUS_UNKNOWN);
                // 充电
                final int oldPlugType = mPlugType;
                mPlugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 1);
                final int oldInvalidCharger = mInvalidCharger;
                mInvalidCharger = intent.getIntExtra(BatteryManager.EXTRA_INVALID_CHARGER, 0);
    
                final boolean plugged = mPlugType != 0;
                final boolean oldPlugged = oldPlugType != 0;
                // 根据当前电量与危急电量、低电量、关闭低电量警告电量比较判断当前所处状态
                int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
                int bucket = findBatteryLevelBucket(mBatteryLevel);
                // 更新电池警告信息
                mWarnings.update(mBatteryLevel, bucket, mScreenOffTime);
                if (oldInvalidCharger == 0 && mInvalidCharger != 0) {
                    Slog.d(TAG, "showing invalid charger warning");
                    mWarnings.showInvalidChargerWarning();
                    return;
                } else if (oldInvalidCharger != 0 && mInvalidCharger == 0) {
                    mWarnings.dismissInvalidChargerWarning();
                } else if (mWarnings.isInvalidChargerWarningShowing()) {
                    // if invalid charger is showing, don't show low battery
                    return;
                }
    
                // Show the correct version of low battery warning if needed
                ThreadUtils.postOnBackgroundThread(() -> {
                        // 判断是否要显示低电量警告
                        maybeShowBatteryWarning(
                                                oldBatteryLevel, plugged, oldPlugged, oldBucket, bucket);
                    });
    
            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                mScreenOffTime = SystemClock.elapsedRealtime();
            } else if (Intent.ACTION_SCREEN_ON.equals(action)) {
                mScreenOffTime = -1;
            } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
                mWarnings.userSwitched();
            } else {
                Slog.w(TAG, "unknown intent: " + intent);
            }
        }
    }
  • maybeShowBatteryWarning()

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    
    protected void maybeShowBatteryWarning(int oldBatteryLevel, boolean plugged, boolean oldPlugged,
                                           int oldBucket, int bucket) {
        boolean isPowerSaver = mPowerManager.isPowerSaveMode();
        // only play SFX when the dialog comes up or the bucket changes
        final boolean playSound = bucket != oldBucket || oldPlugged;
        // ......
        if (shouldShowLowBatteryWarning(plugged, oldPlugged, oldBucket, bucket,
                                        mTimeRemaining, isPowerSaver, mBatteryStatus)) {
            mWarnings.showLowBatteryWarning(playSound);
        } else if (shouldDismissLowBatteryWarning(plugged, oldBucket, bucket, mTimeRemaining,
                                                  isPowerSaver)) {
            mWarnings.dismissLowBatteryWarning();
        } else {
            mWarnings.updateLowBatteryWarning();
        }
    }

高温警告

  • initTemperatureWarning()

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    
    private void initTemperatureWarning() {
        // 是否开启高温警告,默认关闭
        ContentResolver resolver = mContext.getContentResolver();
        Resources resources = mContext.getResources();
        if (Settings.Global.getInt(resolver, Settings.Global.SHOW_TEMPERATURE_WARNING,
                                   resources.getInteger(R.integer.config_showTemperatureWarning)) == 0) {
            return;
        }
        // 获取高温警告阀值,默认:-1
        mThresholdTemp = Settings.Global.getFloat(resolver, Settings.Global.WARNING_TEMPERATURE,
                                                  resources.getInteger(R.integer.config_warningTemperature));
    
        if (mThresholdTemp < 0f) {
            // Get the shutdown temperature, adjust for warning tolerance.
            // 获取关机温度
            float[] throttlingTemps = mHardwarePropertiesManager
                .getDeviceTemperatures(HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
                                       HardwarePropertiesManager.TEMPERATURE_SHUTDOWN);
            if (throttlingTemps == null
                || throttlingTemps.length == 0
                || throttlingTemps[0] == HardwarePropertiesManager.UNDEFINED_TEMPERATURE) {
                return;
            }
            // 高温警告的温度阀值
            mThresholdTemp = throttlingTemps[0] -
                resources.getInteger(R.integer.config_warningTemperatureTolerance);
        }
    
        if (mThermalService == null) {
            // Enable push notifications of throttling from vendor thermal
            // management subsystem via thermalservice, in addition to our
            // usual polling, to react to temperature jumps more quickly.
            IBinder b = ServiceManager.getService("thermalservice");
    
            if (b != null) {
                mThermalService = IThermalService.Stub.asInterface(b);
                try {
                    mThermalService.registerThermalEventListener(
                                                                 new ThermalEventListener());
                } catch (RemoteException e) {
                    // Should never happen.
                }
            }
        }
    
        setNextLogTime();
    
        // This initialization method may be called on a configuration change. Only one set of
        // ongoing callbacks should be occurring, so remove any now. updateTemperatureWarning will
        // schedule an ongoing callback.
        mHandler.removeCallbacks(mUpdateTempCallback);
    
        // We have passed all of the checks, start checking the temp
        // 轮询检查温度
        updateTemperatureWarning();
    }
  • updateTemperatureWarning()

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    
    protected void updateTemperatureWarning() {
        // 获取当前温度
        float[] temps = mHardwarePropertiesManager
            .getDeviceTemperatures(HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
                                   HardwarePropertiesManager.TEMPERATURE_CURRENT);
        if (temps.length != 0) {
            float temp = temps[0];
            // 记录温度
            mRecentTemps[mNumTemps++] = temp;
    
            StatusBar statusBar = getComponent(StatusBar.class);
            if (statusBar != null && !statusBar.isDeviceInVrMode()
                && temp >= mThresholdTemp) {
                logAtTemperatureThreshold(temp);
                // 开启高温警告
                mWarnings.showHighTemperatureWarning();
            } else {
                // 关闭高温警告
                mWarnings.dismissHighTemperatureWarning();
            }
        }
    
        logTemperatureStats();
        // 每  30s 检查一次
        mHandler.postDelayed(mUpdateTempCallback, TEMPERATURE_INTERVAL);
    }