会简单的介绍 BatteryService ,重点会放在 BatteryStatsService 的源码分析上。

BatteryService

BatteryService 的启动流程和 PowerManagerService 差不多,其实大多数系统服务启动流程都大同小异,都是有 SystemServer 启动并运行在其进程中。我们直接从 BatteryService 的构造方法开始:

构造方法

 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
public BatteryService(Context context) {
    super(context);

    mContext = context;
    // 异步处理
    mHandler = new Handler(true /*async*/);
    // Led 是内部类但构造注入了  LightsManager 用于管理  Led 灯(键盘灯、通知灯等)
    mLed = new Led(context, getLocalService(LightsManager.class));
    // 获取  BatterStatsService 用于电量统计
    mBatteryStats = BatteryStatsService.getService();
    // 获取  ActivityManagerInternal 用于管理  Activity 信息,
    // 和  PowerManagerInternal 一样是单例的并且属于  SystemServer 内部管理工具不能用于外部,
    mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
    // 危急电量,低于此电量将自动关机
    mCriticalBatteryLevel = mContext.getResources().getInteger(
                                                               com.android.internal.R.integer.config_criticalBatteryWarningLevel);
    // 低电量,低于此电量将发出警告(弹窗、通知、状态栏电池图标变红等)
    mLowBatteryWarningLevel = mContext.getResources().getInteger(
                                                                 com.android.internal.R.integer.config_lowBatteryWarningLevel);
    // 脱离低电量间隔,由低电量升高多少电量后取消低电量警告
    mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel + mContext.getResources().getInteger(
                                                                                                com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
    // 紧急温度,电池温度高于此温度将强制关机(可能会直接断电关机)
    mShutdownBatteryTemperature = mContext.getResources().getInteger(
                                                                     com.android.internal.R.integer.config_shutdownBatteryTemperature);
    // 电池电量事件队列
    mBatteryLevelsEventQueue = new ArrayDeque<>();
    // 记录日志
    mMetricsLogger = new MetricsLogger();

    // watch for invalid charger messages if the invalid_charger switch exists
    // 监测无效充电器
    if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
        UEventObserver invalidChargerObserver = new UEventObserver() {
                @Override
                public void onUEvent(UEvent event) {
                    final int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0;
                    synchronized (mLock) {
                        if (mInvalidCharger != invalidCharger) {
                            mInvalidCharger = invalidCharger;
                        }
                    }
                }
            };
        invalidChargerObserver.startObserving(
                                              "DEVPATH=/devices/virtual/switch/invalid_charger");
    }
}

启动:

onStart()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public void onStart() {
    registerHealthCallback();
    // 将自己的  Binder 服务端注册到  ServiceManager,注意这里没有使用  AIDL。见  1
    mBinderService = new BinderService();
    publishBinderService("battery", mBinderService);
    // 注册  BatteryPropertiesRegistrar 服务到  ServiceManager,这个类似  PowerManagerService 是用  AIDL 实现的
    // 它只实现了在  BatteryManager 中使用的  getProperty
    mBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar();
    publishBinderService("batteryproperties", mBatteryPropertiesRegistrar);
    // 这个类似  PowerManagerServic
    publishLocalService(BatteryManagerInternal.class, new LocalService());
}
  1. registerHealthCallback()

     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
    
    private void registerHealthCallback() {
        traceBegin("HealthInitWrapper");
        // 构造函数是空的,应该在构造方法后调用  init() 方法,出于测试目的不在构造方法中调用  init() 方法
        mHealthServiceWrapper = new HealthServiceWrapper();
        mHealthHalCallback = new HealthHalCallback();
        // IHealth is lazily retrieved.
        try {
            mHealthServiceWrapper.init(mHealthHalCallback,
                                       new HealthServiceWrapper.IServiceManagerSupplier() {},
                                       new HealthServiceWrapper.IHealthSupplier() {});
        } finally {
            traceEnd();
        }
    
        traceBegin("HealthInitWaitUpdate");
        // init register for new service notifications, and IServiceManager should return the
        // existing service in a near future. Wait for this.update() to instantiate
        // the initial mHealthInfo.
        // 等待  mHealthInfo 初始化
        long beforeWait = SystemClock.uptimeMillis();
        synchronized (mLock) {
            while (mHealthInfo == null) {
                Slog.i(TAG, "health: Waited " + (SystemClock.uptimeMillis() - beforeWait) +
                       "ms for callbacks. Waiting another " + HEALTH_HAL_WAIT_MS + " ms...");
                try {
                    mLock.wait(HEALTH_HAL_WAIT_MS);
                } catch (InterruptedException ex) {}
            }
        }
        traceEnd();
    }
    1. HealthServiceWrapper.init()

       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
      
      void init(Callback callback,
                IServiceManagerSupplier managerSupplier,
                IHealthSupplier healthSupplier)
          throws RemoteException, NoSuchElementException, NullPointerException {
          if (callback == null || managerSupplier == null || healthSupplier == null)
              throw new NullPointerException();
      
          IServiceManager manager;
      
          mCallback = callback;
          mHealthSupplier = healthSupplier;
      
          // Initialize mLastService and call callback for the first time (in init thread)
          // 获取  IHealth 服务
          IHealth newService = null;
          for (String name : sAllInstances) {
              traceBegin("HealthInitGetService_" + name);
              try {
                  newService = healthSupplier.get(name);
              } catch (NoSuchElementException ex) {
                  /* ignored, handled below */
              } finally {
                  traceEnd();
              }
              if (newService != null) {
                  mInstanceName = name;
                  mLastService.set(newService);
                  break;
              }
          }
      
          if (mInstanceName == null || newService == null) {
              throw new NoSuchElementException(String.format(
                                                             "No IHealth service instance among %s is available. Perhaps no permission?",
                                                             sAllInstances.toString()));
          }
          // 回调注册
          mCallback.onRegistration(null, newService, mInstanceName);
      
          // Register for future service registrations
          traceBegin("HealthInitRegisterNotification");
          mHandlerThread.start();
          try {
              managerSupplier.get().registerForNotifications(
                                                             IHealth.kInterfaceName, mInstanceName, mNotification);
          } finally {
              traceEnd();
          }
          Slog.i(TAG, "health: HealthServiceWrapper listening to instance " + mInstanceName);
      }
    2. HealthHalCallback.onRegistration()

       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
      
      @Override public void onRegistration(IHealth oldService, IHealth newService,
                                           String instance) {
          if (newService == null) return;
      
          traceBegin("HealthUnregisterCallback");
          try {
              if (oldService != null) {
                  // 注销旧服务
                  int r = oldService.unregisterCallback(this);
                  if (r != Result.SUCCESS) {
                      Slog.w(TAG, "health: cannot unregister previous callback: " +
                             Result.toString(r));
                  }
              }
          } catch (RemoteException ex) {
              Slog.w(TAG, "health: cannot unregister previous callback (transaction error): "
                     + ex.getMessage());
          } finally {
              traceEnd();
          }
      
          traceBegin("HealthRegisterCallback");
          try {
              // IHealth 注册回调
              int r = newService.registerCallback(this);
              if (r != Result.SUCCESS) {
                  Slog.w(TAG, "health: cannot register callback: " + Result.toString(r));
                  return;
              }
              // registerCallback does NOT guarantee that update is called
              // immediately, so request a manual update here.
              //手动更新,会进入  hal 层,最终会回调  healthInfoChanged 方法
              newService.update();
          } catch (RemoteException ex) {
              Slog.e(TAG, "health: cannot register callback (transaction error): "
                     + ex.getMessage());
          } finally {
              traceEnd();
          }
      }
    3. HealthHalCallback.healthInfoChanged()

      1
      2
      3
      
      @Override public void healthInfoChanged(android.hardware.health.V2_0.HealthInfo props) {
          BatteryService.this.update(props);
      }
    4. update()

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      
      private void update(android.hardware.health.V2_0.HealthInfo info) {
          traceBegin("HealthInfoUpdate");
          synchronized (mLock) {
              if (!mUpdatesStopped) {
                  // mUpdatesStopped 默认  false
                  mHealthInfo = info.legacy;
                  // Process the new values.
                  // 更新电源相关信息,后面分析
                  processValuesLocked(false);
                  // 唤醒其它线程
                  mLock.notifyAll(); // for any waiters on new info
              } else {
                  copy(mLastHealthInfo, info.legacy);
              }
          }
          traceEnd();
      }
  2. BinderService() BatteryService 服务端远程调用流程: BinderService.onShellCommadnd() -> Shell.exec() -> ShellCommand.exec() -> Shell.onCommand() -> onShellCommand()

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    private final class BinderService extends Binder {
        @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
    
            if (args.length > 0 && "--proto".equals(args[0])) {
                dumpProto(fd);
            } else {
                dumpInternal(fd, pw, args);
            }
        }
    
        @Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
                                             FileDescriptor err, String[] args, ShellCallback callback,
                                             ResultReceiver resultReceiver) {
            (new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
        }
    }
    1. Shell()

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      
      class Shell extends ShellCommand {
          @Override
          public int onCommand(String cmd) {
              return onShellCommand(this, cmd);
          }
      
          @Override
          public void onHelp() {
              PrintWriter pw = getOutPrintWriter();
              dumpHelp(pw);
          }
      }
    2. ShellCommand.exec()

       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 int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
                      String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
          String cmd;
          int start;
          if (args != null && args.length > 0) {
              cmd = args[0];
              start = 1;
          } else {
              cmd = null;
              start = 0;
          }
          // 初始化
          init(target, in, out, err, args, callback, start);
          mCmd = cmd;
          mResultReceiver = resultReceiver;
      
          int res = -1;
          try {
              res = onCommand(mCmd);
          } catch (SecurityException e) {
          } catch (Throwable e) {
          } finally {
              if (mOutPrintWriter != null) {
                  mOutPrintWriter.flush();
              }
              if (mErrPrintWriter != null) {
                  mErrPrintWriter.flush();
              }
              if (mResultReceiver != null) {
                  mResultReceiver.send(res, null);
              }
          }
          return res;
      }

onBootPhase()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
public void onBootPhase(int phase) {
    if (phase == PHASE_ACTIVITY_MANAGER_READY) {
        // check our power situation now that it is safe to display the shutdown dialog.
        synchronized (mLock) {
            ContentObserver obs = new ContentObserver(mHandler) {
                    @Override
                    public void onChange(boolean selfChange) {
                        synchronized (mLock) {
                            updateBatteryWarningLevelLocked();
                        }
                    }
                };
            final ContentResolver resolver = mContext.getContentResolver();
            // 监听设置中低电量值的改变
            resolver.registerContentObserver(Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
                                             false, obs, UserHandle.USER_ALL);
            updateBatteryWarningLevelLocked();
        }
    }
}
  1. updateBatteryWarningLevelLocked()

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    private void updateBatteryWarningLevelLocked() {
        final ContentResolver resolver = mContext.getContentResolver();
        // 默认低电量值
        int defWarnLevel = mContext.getResources()
            .getInteger(com.android.internal.R.integer.config_lowBatteryWarningLevel);
        // 用户设置的低电量值
        mLowBatteryWarningLevel = Settings.Global
            .getInt(resolver, Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, defWarnLevel);
        if (mLowBatteryWarningLevel == 0) {
            mLowBatteryWarningLevel = defWarnLevel;
        }
        // 低电量值不应小于危急电量值
        if (mLowBatteryWarningLevel < mCriticalBatteryLevel) {
            mLowBatteryWarningLevel = mCriticalBatteryLevel;
        }
        // 计算出取消低电量状态的电量值
        mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel + mContext.getResources()
            .getInteger(com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
        // 更新电量信息
        processValuesLocked(true);
    }
  2. processValuesLocked()

      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
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    
    private void processValuesLocked(boolean force) {
        // 默认不记录日志
        boolean logOutlier = false;
        long dischargeDuration = 0;
        // 当前电量值是否是危急电量
        mBatteryLevelCritical =
            mHealthInfo.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
            && mHealthInfo.batteryLevel <= mCriticalBatteryLevel;
        if (mHealthInfo.chargerAcOnline) {
            // AC 交流充电
            mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
        } else if (mHealthInfo.chargerUsbOnline) {
            // USB 充电
            mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
        } else if (mHealthInfo.chargerWirelessOnline) {
            // 无线充电
            mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
        } else {
            // 未充电
            mPlugType = BATTERY_PLUGGED_NONE;
        }
    
        // Let the battery stats keep track of the current level.
        try {
            // 将当前电池信息传给  BatteryStatsService 电量统计服务
            mBatteryStats.setBatteryState(mHealthInfo.batteryStatus, mHealthInfo.batteryHealth,
                                          mPlugType, mHealthInfo.batteryLevel, mHealthInfo.batteryTemperature,
                                          mHealthInfo.batteryVoltage, mHealthInfo.batteryChargeCounter,
                                          mHealthInfo.batteryFullCharge);
        } catch (RemoteException e) {
            // Should never happen.
        }
        // 电池电量为零,且不处于充电状态,则弹出关机对话框
        shutdownIfNoPowerLocked();
        // 电池温度超过关机温度(默认:68°C),则弹出关机对话框
        shutdownIfOverTempLocked();
        // 电池信息发生改变或要求强制更新时
        if (force || (mHealthInfo.batteryStatus != mLastBatteryStatus ||
                      mHealthInfo.batteryHealth != mLastBatteryHealth ||
                      mHealthInfo.batteryPresent != mLastBatteryPresent ||
                      mHealthInfo.batteryLevel != mLastBatteryLevel ||
                      mPlugType != mLastPlugType ||
                      mHealthInfo.batteryVoltage != mLastBatteryVoltage ||
                      mHealthInfo.batteryTemperature != mLastBatteryTemperature ||
                      mHealthInfo.maxChargingCurrent != mLastMaxChargingCurrent ||
                      mHealthInfo.maxChargingVoltage != mLastMaxChargingVoltage ||
                      mHealthInfo.batteryChargeCounter != mLastChargeCounter ||
                      mInvalidCharger != mLastInvalidCharger)) {
    
            if (mPlugType != mLastPlugType) {
                // 充电状态发生改变
                if (mLastPlugType == BATTERY_PLUGGED_NONE) {
                    // discharging -> charging
                    // 未充电 -> 充电
                    // 充电开始的电量和时间
                    mChargeStartLevel = mHealthInfo.batteryLevel;
                    mChargeStartTime = SystemClock.elapsedRealtime();
                    // 记录日志
                    final LogMaker builder = new LogMaker(MetricsEvent.ACTION_CHARGE);
                    builder.setType(MetricsEvent.TYPE_ACTION);
                    builder.addTaggedData(MetricsEvent.FIELD_PLUG_TYPE, mPlugType);
                    builder.addTaggedData(MetricsEvent.FIELD_BATTERY_LEVEL_START,
                                          mHealthInfo.batteryLevel);
                    mMetricsLogger.write(builder);
    
                    // There's no value in this data unless we've discharged at least once and the
                    // battery level has changed; so don't log until it does.
                    // 在至少有过一次未充电状态并且电量有改变前,记录日志是无意义的,所以在此之后才开始记录日志
                    if (mDischargeStartTime != 0 && mDischargeStartLevel != mHealthInfo.batteryLevel) {
                        dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
                        logOutlier = true;
                        EventLog.writeEvent(EventLogTags.BATTERY_DISCHARGE, dischargeDuration,
                                            mDischargeStartLevel, mHealthInfo.batteryLevel);
                        // make sure we see a discharge event before logging again
                        // 再次确保在记录日志钱有过未充电状态
                        mDischargeStartTime = 0;
                    }
                } else if (mPlugType == BATTERY_PLUGGED_NONE) {
                    // charging -> discharging or we just powered up
                    // 充电 -> 未充电
                    mDischargeStartTime = SystemClock.elapsedRealtime();
                    mDischargeStartLevel = mHealthInfo.batteryLevel;
    
                    long chargeDuration = SystemClock.elapsedRealtime() - mChargeStartTime;
                    if (mChargeStartTime != 0 && chargeDuration != 0) {
                        final LogMaker builder = new LogMaker(MetricsEvent.ACTION_CHARGE);
                        builder.setType(MetricsEvent.TYPE_DISMISS);
                        builder.addTaggedData(MetricsEvent.FIELD_PLUG_TYPE, mLastPlugType);
                        builder.addTaggedData(MetricsEvent.FIELD_CHARGING_DURATION_MILLIS,
                                              chargeDuration);
                        builder.addTaggedData(MetricsEvent.FIELD_BATTERY_LEVEL_START,
                                              mChargeStartLevel);
                        builder.addTaggedData(MetricsEvent.FIELD_BATTERY_LEVEL_END,
                                              mHealthInfo.batteryLevel);
                        mMetricsLogger.write(builder);
                    }
                    mChargeStartTime = 0;
                }
            }
            // 记录电池状态信息
            if (mHealthInfo.batteryStatus != mLastBatteryStatus ||
                mHealthInfo.batteryHealth != mLastBatteryHealth ||
                mHealthInfo.batteryPresent != mLastBatteryPresent ||
                mPlugType != mLastPlugType) {
                EventLog.writeEvent(EventLogTags.BATTERY_STATUS,
                                    mHealthInfo.batteryStatus, mHealthInfo.batteryHealth, mHealthInfo.batteryPresent ? 1 : 0,
                                    mPlugType, mHealthInfo.batteryTechnology);
            }
            // 记录电量信息
            if (mHealthInfo.batteryLevel != mLastBatteryLevel) {
                // Don't do this just from voltage or temperature changes, that is
                // too noisy.
                EventLog.writeEvent(EventLogTags.BATTERY_LEVEL,
                                    mHealthInfo.batteryLevel, mHealthInfo.batteryVoltage, mHealthInfo.batteryTemperature);
            }
            // 电量处于危急状态并且没有充电,上次状态改变后也没处于危急电量
            if (mBatteryLevelCritical && !mLastBatteryLevelCritical &&
                mPlugType == BATTERY_PLUGGED_NONE) {
                // We want to make sure we log discharge cycle outliers
                // if the battery is about to die.
                // 确保能记录电池即将停止工作时的日志
                dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
                logOutlier = true;
            }
    
            if (!mBatteryLevelLow) {
                // Should we now switch in to low battery mode?
                // 当前不是处于低电量状态,判断是否要置于低电量状态
                if (mPlugType == BATTERY_PLUGGED_NONE
                    && mHealthInfo.batteryStatus !=
                    BatteryManager.BATTERY_STATUS_UNKNOWN
                    && mHealthInfo.batteryLevel <= mLowBatteryWarningLevel) {
                    // 当前处于未充电状态,电池状态已知,电量低于低电量值则标记为低电量
                    mBatteryLevelLow = true;
                }
            } else {
                // Should we now switch out of low battery mode?
                // 当前处于低电量状态,判断是否要退出低电量状态
                if (mPlugType != BATTERY_PLUGGED_NONE) {
                    // 处于充电状态,退出低电量状态
                    mBatteryLevelLow = false;
                } else if (mHealthInfo.batteryLevel >= mLowBatteryCloseWarningLevel)  {
                    // 当前电量高于取消低电量警告值,退出低电量状态
                    mBatteryLevelLow = false;
                } else if (force && mHealthInfo.batteryLevel >= mLowBatteryWarningLevel) {
                    // If being forced, the previous state doesn't matter, we will just
                    // absolutely check to see if we are now above the warning level.
                    // 如果是强制更新电池状态,则忽略之前的状态,重新检查是否高于低电量值
                    mBatteryLevelLow = false;
                }
            }
            // 状态更新计数加一
            mSequence++;
    
            // Separate broadcast is sent for power connected / not connected
            // since the standard intent will not wake any applications and some
            // applications may want to have smart behavior based on this.
            // 为 连接电源/未连接电源 单独发送广播
            if (mPlugType != 0 && mLastPlugType == 0) {
                final Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);
                statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
                mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                        }
                    });
            }
            else if (mPlugType == 0 && mLastPlugType != 0) {
                final Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
                statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
                mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                        }
                    });
            }
            // 发送低电量状态改变广播
            if (shouldSendBatteryLowLocked()) {
                mSentLowBatteryBroadcast = true;
                final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW);
                statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
                mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                        }
                    });
            } else if (mSentLowBatteryBroadcast &&
                       mHealthInfo.batteryLevel >= mLowBatteryCloseWarningLevel) {
                mSentLowBatteryBroadcast = false;
                final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);
                statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
                mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                        }
                    });
            }
    
            // We are doing this after sending the above broadcasts, so anything processing
            // them will get the new sequence number at that point.  (See for example how testing
            // of JobScheduler's BatteryController works.)
            // 发送电池状态改变广播
            sendBatteryChangedIntentLocked();
            if (mLastBatteryLevel != mHealthInfo.batteryLevel) {
                // 发送电池电量值改变广播
                sendBatteryLevelChangedIntentLocked();
            }
    
    
            // Update the battery LED
            // 更新电池通知灯状态
            mLed.updateLightsLocked();
    
            // This needs to be done after sendIntent() so that we get the lastest battery stats.
            if (logOutlier && dischargeDuration != 0) {
                // 记录电池耗电日志
                logOutlierLocked(dischargeDuration);
            }
            // 更新本地变量,记录当前电池状态
            mLastBatteryStatus = mHealthInfo.batteryStatus;
            mLastBatteryHealth = mHealthInfo.batteryHealth;
            mLastBatteryPresent = mHealthInfo.batteryPresent;
            mLastBatteryLevel = mHealthInfo.batteryLevel;
            mLastPlugType = mPlugType;
            mLastBatteryVoltage = mHealthInfo.batteryVoltage;
            mLastBatteryTemperature = mHealthInfo.batteryTemperature;
            mLastMaxChargingCurrent = mHealthInfo.maxChargingCurrent;
            mLastMaxChargingVoltage = mHealthInfo.maxChargingVoltage;
            mLastChargeCounter = mHealthInfo.batteryChargeCounter;
            mLastBatteryLevelCritical = mBatteryLevelCritical;
            mLastInvalidCharger = mInvalidCharger;
        }
    }