SystemUI中的PowerUI简析

PowerUI

powerUI是SystemUI显示电池相关信息的模块,包括低电量提醒,危急电量关机提醒,高温关机提醒,省电模式等的功能。
在powerUI.java 中主要是两个函数start()和onReveice()

启动流程

SystemUI启动时会加载众多功能模块,其中就包含着PowerUI,会直接调用\

PowerUI.start()

start() 函数是在PowerUI 中最先触发的方法。在方法内进行了一些赋值操作,及注册对电量变化和屏幕开闭状态的广播监听
1)实例化PowerManager,因为是处理和Power相关的业务,必须实例化PowerManager.

2)初始化关屏时间,关屏时间会持续刷新。

3)实例化PowerNotificationWarnings,Power相关的事件会通过Notification方式进行处理。

4)监控电池电量,在电量不足是给出警告和提示。

5)更新电池电量等级。

public void start() {
        //获取PowerManager  用于获取电池的相关信息
        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_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();

        //检查我们是否需要让用户知道手机之前因温度过高而关闭
        showWarnOnThermalShutdown();

        // Register an observer to configure mEnableSkinTemperatureWarning and perform the
        // registration of skin thermal event listener upon Settings change.
        //注册观察者以配置 mEnableSkinTemperatureWarning 并在设置更改时执行皮肤热事件侦听器的注册。
        resolver.registerContentObserver(
                Settings.Global.getUriFor(Settings.Global.SHOW_TEMPERATURE_WARNING),
                false /*notifyForDescendants*/,
                new ContentObserver(mHandler) {
                    @Override
                    public void onChange(boolean selfChange) {
                        doSkinThermalEventListenerRegistration();
                    }
                });
        // Register an observer to configure mEnableUsbTemperatureAlarm and perform the
        // registration of usb thermal event listener upon Settings change.
        //注册观察者以配置 mEnableUsbTemperatureAlarm 并在设置更改时执行 USB 热事件侦听器的注册。
        resolver.registerContentObserver(
                Settings.Global.getUriFor(Settings.Global.SHOW_USB_TEMPERATURE_ALARM),
                false /*notifyForDescendants*/,
                new ContentObserver(mHandler) {
                    @Override
                    public void onChange(boolean selfChange) {
                        doUsbThermalEventListenerRegistration();
                    }
                });
        // 初始化温度阀值
        initThermalEventListeners();
        mCommandQueue.addCallback(this);
    }

电池电量有三个关键值定义如下(frameworks\base\core\res\res\valuesconfig.xml):

<integer name="config_criticalBatteryWarningLevel">5</integer>
<integer name="config_lowBatteryWarningLevel">15</integer>
<integer name="config_lowBatteryCloseWarningBump">5</integer>

低电量警告

updateBatteryWarningLevels

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

电池相关广播监听

final class Receiver extends BroadcastReceiver {

        private boolean mHasReceivedBattery = false;

        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);
            mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mHandler);
            // Force get initial values. Relying on Sticky behavior until API for getting info.
            if (!mHasReceivedBattery) {
                // Get initial state
                Intent intent = mContext.registerReceiver(
                        null,
                        new IntentFilter(Intent.ACTION_BATTERY_CHANGED)
                );
                if (intent != null) {
                    onReceive(mContext, intent);
                }
            }
        }

        @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)) {
                mHasReceivedBattery = true;
                // 电量
                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);
                mLastBatteryStateSnapshot = mCurrentBatteryStateSnapshot;

                final boolean plugged = mPlugType != 0;
                final boolean oldPlugged = oldPlugType != 0;
                // 根据当前电量与危急电量、低电量、关闭低电量警告电量比较判断当前所处状态
                int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
                int bucket = findBatteryLevelBucket(mBatteryLevel);

                if (DEBUG) {
                    Slog.d(TAG, "buckets   ....." + mLowBatteryAlertCloseLevel
                            + " .. " + mLowBatteryReminderLevels[0]
                            + " .. " + mLowBatteryReminderLevels[1]);
                    Slog.d(TAG, "level          " + oldBatteryLevel + " --> " + mBatteryLevel);
                    Slog.d(TAG, "status         " + oldBatteryStatus + " --> " + mBatteryStatus);
                    Slog.d(TAG, "plugType       " + oldPlugType + " --> " + mPlugType);
                    Slog.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger);
                    Slog.d(TAG, "bucket         " + oldBucket + " --> " + bucket);
                    Slog.d(TAG, "plugged        " + oldPlugged + " --> " + plugged);
                }
                // 更新电池警告信息
                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
                    if (DEBUG) {
                        Slog.d(TAG, "Bad Charger");
                    }
                    return;
                }

                // Show the correct version of low battery warning if needed
                if (mLastShowWarningTask != null) {
                    mLastShowWarningTask.cancel(true);
                    if (DEBUG) {
                        Slog.d(TAG, "cancelled task");
                    }
                }
                mLastShowWarningTask = ThreadUtils.postOnBackgroundThread(() -> {
                    // 判断是否要显示低电量警告
                    maybeShowBatteryWarningV2(
                            plugged, 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);
            }
        }
    }
protected void maybeShowBatteryWarningV2(boolean plugged, int bucket) {
        final boolean hybridEnabled = mEnhancedEstimates.isHybridNotificationEnabled();
        final boolean isPowerSaverMode = mPowerManager.isPowerSaveMode();

        // Stick current battery state into an immutable container to determine if we should show
        // a warning.
        if (DEBUG) {
            Slog.d(TAG, "evaluating which notification to show");
        }
        if (hybridEnabled) {
            if (DEBUG) {
                Slog.d(TAG, "using hybrid");
            }
            Estimate estimate = refreshEstimateIfNeeded();
            mCurrentBatteryStateSnapshot = new BatteryStateSnapshot(mBatteryLevel, isPowerSaverMode,
                    plugged, bucket, mBatteryStatus, mLowBatteryReminderLevels[1],
                    mLowBatteryReminderLevels[0], estimate.getEstimateMillis(),
                    estimate.getAverageDischargeTime(),
                    mEnhancedEstimates.getSevereWarningThreshold(),
                    mEnhancedEstimates.getLowWarningThreshold(), estimate.isBasedOnUsage(),
                    mEnhancedEstimates.getLowWarningEnabled());
        } else {
            if (DEBUG) {
                Slog.d(TAG, "using standard");
            }
            mCurrentBatteryStateSnapshot = new BatteryStateSnapshot(mBatteryLevel, isPowerSaverMode,
                    plugged, bucket, mBatteryStatus, mLowBatteryReminderLevels[1],
                    mLowBatteryReminderLevels[0]);
        }

        mWarnings.updateSnapshot(mCurrentBatteryStateSnapshot);
        if (mCurrentBatteryStateSnapshot.isHybrid()) {
            maybeShowHybridWarning(mCurrentBatteryStateSnapshot, mLastBatteryStateSnapshot);
        } else {
            maybeShowBatteryWarning(mCurrentBatteryStateSnapshot, mLastBatteryStateSnapshot);
        }
    }
 protected void maybeShowBatteryWarning(
            BatteryStateSnapshot currentSnapshot,
            BatteryStateSnapshot lastSnapshot) {
        final boolean playSound = currentSnapshot.getBucket() != lastSnapshot.getBucket()
                || lastSnapshot.getPlugged();

        if (shouldShowLowBatteryWarning(currentSnapshot, lastSnapshot)) {
            mWarnings.showLowBatteryWarning(playSound);
        } else if (shouldDismissLowBatteryWarning(currentSnapshot, lastSnapshot)) {
            mWarnings.dismissLowBatteryWarning();
        } else {
            mWarnings.updateLowBatteryWarning();
        }
    }

在ACTION_SCREEN_OFF、ACTION_SCREEN_ON这两个广播事件处理中只是简单的对 mScreenOffTime 进行了重新赋值,当屏幕关闭时设置为从系统启动到现在的时间,当屏幕开启时设置为 -1。该值用于在其他位置做差值判断如播放低电量声音时是否播放。

      final ContentResolver cr = mContext.getContentResolver();
 
        final int silenceAfter = Settings.Global.getInt(cr,
                Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0);
        final long offTime = SystemClock.elapsedRealtime() - mScreenOffTime;
        if (silenceAfter > 0
                && mScreenOffTime > 0
                && offTime > silenceAfter) {
            Slog.i(TAG, "screen off too long (" + offTime + "ms, limit " + silenceAfter
                    + "ms): not waking up the user with low battery sound"); // 屏幕休眠时间太久了,不使用低电量声音唤醒使用者
            return;
        }

ACTION_BATTERY_CHANGED 广播

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); // 获取电量等级判断

相关判断如下

 if (DEBUG) { // debug 环境下输出更多的日志信息
                    Slog.d(TAG, "buckets   ....." + mLowBatteryAlertCloseLevel
                            + " .. " + mLowBatteryReminderLevels[0]
                            + " .. " + mLowBatteryReminderLevels[1]);
                    Slog.d(TAG, "level          " + oldBatteryLevel + " --> " + mBatteryLevel);
                    Slog.d(TAG, "status         " + oldBatteryStatus + " --> " + mBatteryStatus);
                    Slog.d(TAG, "plugType       " + oldPlugType + " --> " + mPlugType);
                    Slog.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger);
                    Slog.d(TAG, "bucket         " + oldBucket + " --> " + bucket);
                    Slog.d(TAG, "plugged        " + oldPlugged + " --> " + plugged);
                }
 
                if (oldBatteryStatus == BatteryManager.BATTERY_STATUS_FULL
                    && mBatteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) {
                    mIfDisChargeHappen = 1; // 如果电池满并且没有再充电状态下 mIfDisChanrgeHappen =1
                }
                if (oldInvalidCharger == 0 && mInvalidCharger != 0) { // 判断新旧充电是否可用
                    Slog.d(TAG, "showing invalid charger warning");
                    showInvalidChargerDialog(); // 不可用弹出充电不可用的对话框
                    return;
                } else if (oldInvalidCharger != 0 && mInvalidCharger == 0) {
                    dismissInvalidChargerDialog(); // 充电可用后 让对话框消失
                } else if (mInvalidChargerDialog != null) {
                    // if invalid charger is showing, don't show low battery
                    // 如果不可用的对话框已经存在就不提示低电量
                    return;
                }

下面判断是否弹出电量低及充电满和播放声音

 if (!plugged
                        && ((bucket < oldBucket || oldPlugged) || (mBatteryLevel==1 || oldPlugged))
                        && mBatteryStatus != BatteryManager.BATTERY_STATUS_CHARGING
                        && bucket < 0) {
                    showLowBatteryWarning(); // 弹出低电量报警
 
                    // only play SFX when the dialog comes up or the bucket changes
                    if (bucket != oldBucket || oldPlugged) {
                        playLowBatterySound(); // 播放低电量报警声音
                    }
                } else if (plugged || (bucket > oldBucket && bucket > 0)) {
                    dismissLowBatteryWarning(); // 让低电量报警消失
                } else if (mBatteryLevelTextView != null) {
                    showLowBatteryWarning();
                }
                if(!plugged) {
                    mOldPluggedFull = 0;
                    dismissFullBatteryWarning(); // 让满电提示消失
                }
                if(mBatteryLevel >= 100 && plugged
                   && mOldPluggedFull == 0 && mIfDisChargeHappen == 1) {
                   mOldPluggedFull = 1 ;
                   showFullBatteryWarning(); // 显示满电提示
                   playLowBatterySound(); //播放声音
                   mIfDisChargeHappen = 0;
                } else if ( mBatteryLevel < 100 && isChargerConnected(mPlugType)) {
                    if (mUsbPlugged == 1) {
                        playChargerConnectedSound(); // 播放连接充电时的声音
                      }
                        mUsbPlugged ++;
                }


上一篇:算法-桶排序(C++)


下一篇:数据结构,哈希表(笔记)