基于Android 11 BatteryService 分析 关机

  private void shutdownIfNoPowerLocked() {
385        // shut down gracefully if our battery is critically low and we are not powered.
386        // wait until the system has booted before attempting to display the shutdown dialog.
387        if (shouldShutdownLocked()) {
388            mHandler.post(new Runnable() {
389                @Override
390                public void run() {
391                    if (mActivityManagerInternal.isSystemReady()) {
392                        Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
393                        intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
394                        intent.putExtra(Intent.EXTRA_REASON,
395                                PowerManager.SHUTDOWN_LOW_BATTERY);
396                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
397                        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
398                    }
399                }
400            });
401        }
402    }
//判断电量
348    private boolean shouldSendBatteryLowLocked() {
349        final boolean plugged = mPlugType != BATTERY_PLUGGED_NONE;
350        final boolean oldPlugged = mLastPlugType != BATTERY_PLUGGED_NONE;
351
352        /* The ACTION_BATTERY_LOW broadcast is sent in these situations:
353         * - is just un-plugged (previously was plugged) and battery level is
354         *   less than or equal to WARNING, or
355         * - is not plugged and battery level falls to WARNING boundary
356         *   (becomes <= mLowBatteryWarningLevel).
357         */
358        return !plugged
359                && mHealthInfo.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
360                && mHealthInfo.batteryLevel <= mLowBatteryWarningLevel
361                && (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel);
362    }

如果当前电量小于警告电量(在config.xml中 <integer name="config_lowBatteryWarningLevel">15</integer>)则弹出电量低提示,或者电量为0(当然这个有误差也可能是5%时就自动关机)时自动关机。如果低电量的话就发送一个广播出去:

631            if (shouldSendBatteryLowLocked()) {
632                mSentLowBatteryBroadcast = true;
633                final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW);
634                statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
635                statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
636                mHandler.post(new Runnable() {
637                    @Override
638                    public void run() {
639                        mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
640                    }
641                });

 下面 这段代码是电量过低而自动关机:

384    private void shutdownIfNoPowerLocked() {
385        // shut down gracefully if our battery is critically low and we are not powered.
386        // wait until the system has booted before attempting to display the shutdown dialog.
387        if (shouldShutdownLocked()) {
388            mHandler.post(new Runnable() {
389                @Override
390                public void run() {
391                    if (mActivityManagerInternal.isSystemReady()) {
392                        Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
393                        intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
394                        intent.putExtra(Intent.EXTRA_REASON,
395                                PowerManager.SHUTDOWN_LOW_BATTERY);
396                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
397                        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
398                    }
399                }
400            });
401        }
402    }

PowerUI

        @Override
253        public void onReceive(Context context, Intent intent) {
254            String action = intent.getAction();
255            if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)) {
256                ThreadUtils.postOnBackgroundThread(() -> {
257                    if (mPowerManager.isPowerSaveMode()) {
258                        mWarnings.dismissLowBatteryWarning();
259                    }
260                });
261            } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
262                mHasReceivedBattery = true;
263                final int oldBatteryLevel = mBatteryLevel;
264                mBatteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100);
265                final int oldBatteryStatus = mBatteryStatus;
266                mBatteryStatus = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
267                        BatteryManager.BATTERY_STATUS_UNKNOWN);
268                final int oldPlugType = mPlugType;
269                mPlugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 1);
270                final int oldInvalidCharger = mInvalidCharger;
271                mInvalidCharger = intent.getIntExtra(BatteryManager.EXTRA_INVALID_CHARGER, 0);
272                mLastBatteryStateSnapshot = mCurrentBatteryStateSnapshot;
273
274                final boolean plugged = mPlugType != 0;
275                final boolean oldPlugged = oldPlugType != 0;
276
277                int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
278                int bucket = findBatteryLevelBucket(mBatteryLevel);
279
280                if (DEBUG) {
281                    Slog.d(TAG, "buckets   ....." + mLowBatteryAlertCloseLevel
282                            + " .. " + mLowBatteryReminderLevels[0]
283                            + " .. " + mLowBatteryReminderLevels[1]);
284                    Slog.d(TAG, "level          " + oldBatteryLevel + " --> " + mBatteryLevel);
285                    Slog.d(TAG, "status         " + oldBatteryStatus + " --> " + mBatteryStatus);
286                    Slog.d(TAG, "plugType       " + oldPlugType + " --> " + mPlugType);
287                    Slog.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger);
288                    Slog.d(TAG, "bucket         " + oldBucket + " --> " + bucket);
289                    Slog.d(TAG, "plugged        " + oldPlugged + " --> " + plugged);
290                }
291
292                mWarnings.update(mBatteryLevel, bucket, mScreenOffTime);
293                if (oldInvalidCharger == 0 && mInvalidCharger != 0) {
294                    Slog.d(TAG, "showing invalid charger warning");
295                    mWarnings.showInvalidChargerWarning();
296                    return;
297                } else if (oldInvalidCharger != 0 && mInvalidCharger == 0) {
298                    mWarnings.dismissInvalidChargerWarning();
299                } else if (mWarnings.isInvalidChargerWarningShowing()) {
300                    // if invalid charger is showing, don't show low battery
301                    if (DEBUG) {
302                        Slog.d(TAG, "Bad Charger");
303                    }
304                    return;
305                }
306
307                // Show the correct version of low battery warning if needed
308                if (mLastShowWarningTask != null) {
309                    mLastShowWarningTask.cancel(true);
310                    if (DEBUG) {
311                        Slog.d(TAG, "cancelled task");
312                    }
313                }
314                mLastShowWarningTask = ThreadUtils.postOnBackgroundThread(() -> {
315                    maybeShowBatteryWarningV2(
316                            plugged, bucket);
317                });
318
319            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
320                mScreenOffTime = SystemClock.elapsedRealtime();
321            } else if (Intent.ACTION_SCREEN_ON.equals(action)) {
322                mScreenOffTime = -1;
323            } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
324                mWarnings.userSwitched();
325            } else {
326                Slog.w(TAG, "unknown intent: " + intent);
327            }
328        }
329    }
330

 

maybeShowBatteryWarningV2
 mWarnings.updateSnapshot(mCurrentBatteryStateSnapshot);
362        if (mCurrentBatteryStateSnapshot.isHybrid()) {
363            maybeShowHybridWarning(mCurrentBatteryStateSnapshot, mLastBatteryStateSnapshot);
364        } else {
365            maybeShowBatteryWarning(mCurrentBatteryStateSnapshot, mLastBatteryStateSnapshot);
366        }
367    }
368

476    protected void maybeShowBatteryWarning(
477            BatteryStateSnapshot currentSnapshot,
478            BatteryStateSnapshot lastSnapshot) {
479        final boolean playSound = currentSnapshot.getBucket() != lastSnapshot.getBucket()
480                || lastSnapshot.getPlugged();
481
482        if (shouldShowLowBatteryWarning(currentSnapshot, lastSnapshot)) {
483            mWarnings.showLowBatteryWarning(playSound);
484        } else if (shouldDismissLowBatteryWarning(currentSnapshot, lastSnapshot)) {
485            mWarnings.dismissLowBatteryWarning();
486        } else {
487            mWarnings.updateLowBatteryWarning();
488        }
489    }
490
491    @VisibleForTesting
492    boolean shouldShowLowBatteryWarning(
493            BatteryStateSnapshot currentSnapshot,
494            BatteryStateSnapshot lastSnapshot) {
495        return !currentSnapshot.getPlugged()
496                && !currentSnapshot.isPowerSaver()
497                && (((currentSnapshot.getBucket() < lastSnapshot.getBucket()
498                        || lastSnapshot.getPlugged())
499                && currentSnapshot.getBucket() < 0))
500                && currentSnapshot.getBatteryStatus() != BatteryManager.BATTERY_STATUS_UNKNOWN;
501    }
protected void showWarningNotification() {
255        final String percentage = NumberFormat.getPercentInstance()
256                .format((double) mCurrentBatterySnapshot.getBatteryLevel() / 100.0);
257
258        // get shared standard notification copy
259        String title = mContext.getString(R.string.battery_low_title);
260        String contentText;
261
262        // get correct content text if notification is hybrid or not
263        if (mCurrentBatterySnapshot.isHybrid()) {
264            contentText = getHybridContentString(percentage);
265        } else {
266            contentText = mContext.getString(R.string.battery_low_percent_format, percentage);
267        }
268
269        final Notification.Builder nb =
270                new Notification.Builder(mContext, NotificationChannels.BATTERY)
271                        .setSmallIcon(R.drawable.ic_power_low)
272                        // Bump the notification when the bucket dropped.
273                        .setWhen(mWarningTriggerTimeMs)
274                        .setShowWhen(false)
275                        .setContentText(contentText)
276                        .setContentTitle(title)
277                        .setOnlyAlertOnce(true)
278                        .setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_WARNING))
279                        .setStyle(new Notification.BigTextStyle().bigText(contentText))
280                        .setVisibility(Notification.VISIBILITY_PUBLIC);
281        if (hasBatterySettings()) {
282            nb.setContentIntent(pendingBroadcast(ACTION_SHOW_BATTERY_SETTINGS));
283        }
284        // Make the notification red if the percentage goes below a certain amount or the time
285        // remaining estimate is disabled
286        if (!mCurrentBatterySnapshot.isHybrid() || mBucket < 0
287                || mCurrentBatterySnapshot.getTimeRemainingMillis()
288                        < mCurrentBatterySnapshot.getSevereThresholdMillis()) {
289            nb.setColor(Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorError));
290        }
291
292        if (!mPowerMan.isPowerSaveMode()) {
293            nb.addAction(0,
294                    mContext.getString(R.string.battery_saver_start_action),
295                    pendingBroadcast(ACTION_START_SAVER));
296        }
297        nb.setOnlyAlertOnce(!mPlaySound);
298        mPlaySound = false;
299        SystemUI.overrideNotificationAppName(mContext, nb, false);
300        final Notification n = nb.build();
301        mNoMan.cancelAsUser(TAG_BATTERY, SystemMessage.NOTE_BAD_CHARGER, UserHandle.ALL);
302        mNoMan.notifyAsUser(TAG_BATTERY, SystemMessage.NOTE_POWER_LOW, n, UserHandle.ALL);
303    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值