ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SystemUI中的PowerUI简析

2022-01-18 16:34:57  阅读:312  来源: 互联网

标签:bucket Slog SystemUI 低电量 简析 TAG PowerUI else final


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


标签:bucket,Slog,SystemUI,低电量,简析,TAG,PowerUI,else,final
来源: https://blog.csdn.net/yht1364488/article/details/122553569

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有