🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
BatteryService由SystemServer创建,代码如下: ~~~ battery = new BatteryService(context, lights); ServiceManager.addService("battery",battery); ~~~ 下面来看BatteryService的构造函数: **BatteryService.java** ~~~ public BatteryService(Context context,LightsService lights) { mContext =context; mLed = newLed(context, lights);//提示灯控制,感兴趣的读者可自行阅读相关代码 //BatteryService也需要和BatteryStatsService交互 mBatteryStats = BatteryStatsService.getService(); //获取一些配置参数 mCriticalBatteryLevel = mContext.getResources().getInteger( com.android.internal.R.integer.config_criticalBatteryWarningLevel); mLowBatteryWarningLevel = mContext.getResources().getInteger( com.android.internal.R.integer.config_lowBatteryWarningLevel); mLowBatteryCloseWarningLevel = mContext.getResources().getInteger( com.android.internal.R.integer.config_lowBatteryCloseWarningLevel); //启动uevent监听对象,监视power_supply信息 mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //如果下列文件存在,那么启动另一个uevent监听对象。该uevent事件来自invalid charger //switch设备(即不匹配的充电设备) if (newFile("/sys/devices/virtual/switch/invalid_charger/state").exists()) { mInvalidChargerObserver.startObserving( "DEVPATH=/devices/virtual/switch/invalid_charger"); } update();//①查询HAL层,获取此时的电池信息 } ~~~ BatteryService定义了3个非常重要的阈值,分别是: - mCriticalBatteryLevel表示严重低电,其值为4。当电量低于该值时会强制关机。该值由config.xml中的config_criticalBatteryWarningLevel控制。 - mLowBatteryWarningLevel表示低电,值为15,当电量低于该值时,系统会报警,例如闪烁LED灯。该值由config.xml中的config_lowBatteryWarningLevel控制。 - mLowBatteryCloseWarningLevel表示一旦电量大于此值,就脱离低电状态,即可停止警示灯。该值为20,表示由config.xml中的config_lowBatteryCloseWarningLevel控制。 在BatteryService构造函数的最后调用了update函数,该函数将查询系统电池信息,以更新BatteryService内部的成员变量。此函数代码如下: **BatteryService.java::update** ~~~ private synchronized final void update() { native_update();//到Native层查询并更新内部变量的值 processValues();//处理更新后的状态 } ~~~ 1. native_update函数分析 native_update的实现代码如下: **com_android_server_BatteryService.cpp** ~~~ static voidandroid_server_BatteryService_update(JNIEnv* env, jobject obj) { setBooleanField(env, obj, gPaths.acOnlinePath, gFieldIds.mAcOnline); ......//获取电池信息,并通过JNI设置到Java层对应的变量中 setIntField(env, obj, gPaths.batteryTemperaturePath, gFieldIds.mBatteryTemperature); constint SIZE = 128; charbuf[SIZE]; //获取信息,以下参数并不是所有手机都支持的 if(readFromFile(gPaths.batteryStatusPath, buf, SIZE) > 0) env->SetIntField(obj, gFieldIds.mBatteryStatus,getBatteryStatus(buf)); else env->SetIntField(obj, gFieldIds.mBatteryStatus, gConstants.statusUnknown); ...... } ~~~ 一共有哪些电池信息呢?如表5-4所示。 :-: ![Android系统中的电池信息](https://box.kancloud.cn/383058eb84260cab264a75ae32beb183_951x401.png =951x401) 表5-4 Android系统中的电池信息 mBatteryStatus和mBatteryHealth均有几种不同状态,详细信息可查看getBatteryStatus和getBatteryHealth函数的实现。 上述信息均通过从/sys/class/power_supply目录读取对应文件得到。和以往使用固定路径(可能是Android 2.2版本之前)不同的是,先读取power_supply目录中各个子目录中的type文件,然后根据type文件的内容,再做对应处理: - 如果type文件的内容为“Mains”:则读取对应子目录中的online文件,可判断是否为AC充电。 - 如果type文件的内容为“Battery”:则从对应子目录中其他的文件中读取电池相关的信息,例如从temp文件获取电池温度,从technology文件读取电池制造技术等。 - 如果type文件的内容为“USB”:读取该子目录中的online文件内容,可判断是否为USB充电。 >[info] **提示**: 读者可通过dumpsys battery查看自己手机的电池信息。 2. processValues分析 获取了电池信息后,BatteryService就要做一些处理,此项工作通过processValues完成,其代码如下: **BatteryService.java::processValues** ~~~ private void processValues() { longdischargeDuration = 0; mBatteryLevelCritical = mBatteryLevel <= mCriticalBatteryLevel; if (mAcOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_AC; } elseif (mUsbOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_USB; } else { mPlugType = BATTERY_PLUGGED_NONE; } //通知BatteryStatsService,该函数以后再分析 mBatteryStats.setBatteryState(mBatteryStatus, mBatteryHealth, mPlugType, mBatteryLevel, mBatteryTemperature, mBatteryVoltage ); shutdownIfNoPower();//如果电量不够,弹出关机对话框 shutdownIfOverTemp();//如果电池过热,弹出关机对话框 ......//根据当前电池信息与上次电池信息比较,判断是否需要发送广播等 if (比较前后两次电池信息是否发生变化) { ......//记录信息到日志文件 Intent statusIntent = new Intent(); statusIntent.setFlags( Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); if (mPlugType != 0 && mLastPlugType ==0) { statusIntent.setAction(Intent.ACTION_POWER_CONNECTED); mContext.sendBroadcast(statusIntent); }...... if(sendBatteryLow) { mSentLowBatteryBroadcast = true;//发送低电提醒 statusIntent.setAction(Intent.ACTION_BATTERY_LOW); mContext.sendBroadcast(statusIntent); } ...... mLed.updateLightsLocked();//更新LED灯状态 mLastBatteryStatus= mBatteryStatus;//保存新的电池信息 ...... } ~~~ processValues函数非常简单,此处不再详述。另外,当电池信息发生改变时,系统会发送uevent事件给BatteryService,此时BatteryService只要重新调用update即可完成工作。