一 系统架构图
下面来看看相关的重要的服务和类。
二 PowerManagerService服务
电源管理服务PowerManagerService,负责协调设备上的电源管理功能。如,控制系统的待机状态,控制显示屏的开关和亮度调节等。 PowerManagerService在SystemServer服务中创建和启动,SystemServer是system_server进程的入口类。system_server进程会启动android中使用的一系列服务,包括PowerManagerService。 主要是创建指定服务,并调用其onStart()方法。system_server进程以后再做介绍。下面我们看看PowerManagerService创建和onStart() 方法做了哪些事。
java
//PowerManagerService构造方法
@VisibleForTesting
PowerManagerService(Context context, Injector injector) {
super(context);
mContext = context;
mBinderService = new BinderService(mContext);
mLocalService = new LocalService();
mNativeWrapper = injector.createNativeWrapper();
mSystemProperties = injector.createSystemPropertiesWrapper();
mClock = injector.createClock();
mInjector = injector;
//创建启动ServiceThread线程
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_DISPLAY, /* allowIo= */ false);
mHandlerThread.start();
//创建hanlder
mHandler = injector.createHandler(mHandlerThread.getLooper(),
new PowerManagerHandlerCallback());
mConstants = new Constants(mHandler);
mAmbientDisplayConfiguration = mInjector.createAmbientDisplayConfiguration(context);
mAmbientDisplaySuppressionController =
mInjector.createAmbientDisplaySuppressionController(
mAmbientSuppressionChangedCallback);
mAttentionDetector = new AttentionDetector(this::onUserAttention, mLock);
mFaceDownDetector = new FaceDownDetector(this::onFlip);
mScreenUndimDetector = new ScreenUndimDetector();
//跟踪电池消耗率
mBatterySavingStats = new BatterySavingStats(mLock);
mBatterySaverPolicy =
mInjector.createBatterySaverPolicy(mLock, mContext, mBatterySavingStats);
//负责省电模式转换
mBatterySaverController = mInjector.createBatterySaverController(mLock, mContext,
mBatterySaverPolicy, mBatterySavingStats);
mBatterySaverStateMachine = mInjector.createBatterySaverStateMachine(mLock, mContext,
mBatterySaverController);
//控制低功耗待机状态
mLowPowerStandbyController = mInjector.createLowPowerStandbyController(mContext,
Looper.getMainLooper());
mInattentiveSleepWarningOverlayController =
mInjector.createInattentiveSleepWarningController();
mAppOpsManager = injector.createAppOpsManager(mContext);
...
mScreenBrightnessMinimum = min;
mScreenBrightnessMaximum = max;
mScreenBrightnessDefault = def;
....
mWakefulnessRaw = WAKEFULNESS_AWAKE;
...
mNativeWrapper.nativeInit(this);
mNativeWrapper.nativeSetAutoSuspend(false);
mNativeWrapper.nativeSetPowerMode(Mode.INTERACTIVE, true);
mNativeWrapper.nativeSetPowerMode(Mode.DOUBLE_TAP_TO_WAKE, false);
mInjector.invalidateIsInteractiveCaches();
}
}
PowerManagerService构造方法中,主要了一下事:
1.创建Handler,异步执行一些电源管理操作。比如用户活动超时以更新电源状态,等等
2.创建各种控制管理类,比如跟踪省电消耗,控制低功耗待机状态,息屏控制,app耗电控制等。这些类创建好后被PowerManagerService中的变量引用,用于后面的具体电源管理操作。
3.屏幕亮度初始值,最小,最大,默认值。
4.调用nativeInit方法,这个是个native方法,实现逻辑在PowerManagerService.cpp中的nativeInit函数,用来装载Power模块并将模块初始化。
创建完成PowerManagerService后。执行onStart()方法
java
@Override
public void onStart() {
publishBinderService(Context.POWER_SERVICE, mBinderService, /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_DEFAULT | DUMP_FLAG_PRIORITY_CRITICAL);
publishLocalService(PowerManagerInternal.class, mLocalService);
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
}
onStart()方法只是注册了mBinderService和mLocalService两个服务,用于其他的服务,app以及只有系统进程可以访问的服务。
当系统服务已经准备好时,需要执行一些系统服务的初始化动作,这时PowerManagerService的systemReady方法会被调用。
systemReady的主要工作:
1.通过getLocalService方法,获取一些在系统进程中注册的本地服务引用。如屏幕保护管理服务,屏幕显示设备管理服务,电池管理服务,等等。
2.创建Notifier,Notifier类的作用是,对重要的电源状态的改变发送广播。
3.注册设置的监听,当设置有变化时处理。如屏保,息屏显示,睡眠时间,屏幕亮度调整模式等等。
4.注册系统其他组件的广播。如电池电量变化,用户切换等
在架构图中,我们还可以看到PowerManager这类。它为android的应用提供接口。应用程序不直接使用PowerManagerService服务来管理电源。而是通过PowerManager提供的接口来管理。
三 BatteryService电池管理
BatteryService服务,用于监控电池充电状态,电池电量,当电量发生变化时,它会发出ACTION_BATTERY_CHANGED广播。它也是系统核心服务,在SystemServer中启动。而在PowerManagerService服务中的systemReady方法中就注册了这个广播,当接收到ACTION_BATTERY_CHANGED广播时,会调用BatteryReceiver这个类进行处理。我们来看一下BatteryService的构造方法代码:
java
public BatteryService(Context context) {
super(context);
mContext = context;
mHandler = new Handler(true /*async*/);
mLed = new Led(context, getLocalService(LightsManager.class));
mBatteryStats = BatteryStatsService.getService();
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
//监听设备插入了无效充电器的事件。事件发生时调用onUEvent方法。
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");
}
mBatteryInputSuspended = PowerProperties.battery_input_suspended().orElse(false);
}
构造函数主要做了以下工作:
1.获取BatteryStatsService服务。
2.获取设置的低电量的阀值,当电量达到这些值时,系统会根据这些值做相应的动作。
3.获取高的温度阀值。
4.监听设备插入了无效充电器的事件。
同样SystemServer进程创建BatteryService服务后,会调用其onStart方法:
java
@Override
public void onStart() {
registerHealthCallback();
mBinderService = new BinderService();
publishBinderService("battery", mBinderService);
mBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar();
publishBinderService("batteryproperties", mBatteryPropertiesRegistrar);
publishLocalService(BatteryManagerInternal.class, new LocalService());
}
//registerHealthCallback
private void registerHealthCallback() {
traceBegin("HealthInitWrapper");
// IHealth is lazily retrieved.
try {
mHealthServiceWrapper = HealthServiceWrapper.create(this::update);
} catch (RemoteException ex) {
Slog.e(TAG, "health: cannot register callback. (RemoteException)");
throw ex.rethrowFromSystemServer();
} catch (NoSuchElementException ex) {
Slog.e(TAG, "health: cannot register callback. (no supported health HAL service)");
throw ex;
} finally {
traceEnd();
}
}
在onStart方法中,注册一些服务,让其他模块可以访问这些服务。其中registerHealthCallback方法是向HealthService服务中注册回调。有回调时,调用BatteryService的update方法。
电量的改变是如何通知到BatteryService服务的?首先我们要了解一下Health AIDL HAL服务
四 Health AIDL HAL
Health AIDL HAL:Android 系统架构图:
Health AIDL HAL实际上是使用AIDL 实现 HAL功能。AIDL语言大家都比较熟悉,是在android中实现进程通信的一套框架,android系统一直在使用这套框架实现进程通信,是一套比较成熟的框架。也就是Health AIDL HAL服务使用了AIDL实现,使得其他进程访问电池等硬件信息时就像使用AIDL调用其他进程的接口一样方便。
下面我们看看Health AIDL HAL的具体实现。
在hardware/interfaces/health/aidl/default这个文件夹下的相关文件是health的默认实现。 首先看看main.cpp中的main方法。
c
int main(int argc, char** argv) {
...
// make a default health service
auto config = std::make_unique<healthd_config>();
::android::hardware::health::InitHealthdConfig(config.get()); //初始化healthd_config配置
// gInstanceName 的值是"default"
auto binder = ndk::SharedRefBase::make<Health>(gInstanceName, std::move(config)); // 创建Health binder服务
if (argc >= 2 && argv[1] == gChargerArg) {
#if !CHARGER_FORCE_NO_UI
// If charger shouldn't have UI for your device, simply drop the line below
// for your service implementation. This corresponds to
// ro.charger.no_ui=true
return ChargerModeMain(binder, std::make_shared<ChargerCallback>(binder));
#endif
LOG(INFO) << "Starting charger mode without UI.";
} else {
LOG(INFO) << "Starting health HAL.";
}
auto hal_health_loop = std::make_shared<HalHealthLoop>(binder, binder); //创建HalHealthLoop 实例
return hal_health_loop->StartLoop(); // 调用StartLoop() 函数
}
main函数首先初始化healthd_config,创建Health binder服务,创建HalHealthLoop实例,并调用StartLoop()函数进入无限循环,如果没有错误的话该方法不会退出。下面我们逐步来看看里面的代码实现。
1. 创建Health binder服务
auto binder = ndk::SharedRefBase::make(gInstanceName, std::move(config));该语句实际是调Health构造函数创建对象。
c
//Health构造函数
Health::Health(std::string_view instance_name, std::unique_ptr<struct healthd_config>&& config)
: instance_name_(instance_name),
healthd_config_(std::move(config)),
death_recipient_(AIBinder_DeathRecipient_new(&OnCallbackDiedWrapped)) {
battery_monitor_.init(healthd_config_.get());
}
其中battery_monitor_.init(healthd_config_.get())用来初始化battery_monitor_对象中的相关数据。battery_monitor_是BatteryMonitor类的用于管理监控电池信息的类,它的init方法中初始化了healthd_config配置数据
c
void BatteryMonitor::init(struct healthd_config *hc) {
String8 path;
char pval[PROPERTY_VALUE_MAX];
mHealthdConfig = hc;
//打开POWER_SUPPLY_SYSFS_PATH 文件夹
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(POWER_SUPPLY_SYSFS_PATH), closedir);
if (dir == NULL) {
KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
} else {
struct dirent* entry;
while ((entry = readdir(dir.get()))) {
const char* name = entry->d_name;
//跳过当前文件夹和父文件夹
if (!strcmp(name, ".") || !strcmp(name, ".."))
continue;
std::vector<String8>::iterator itIgnoreName =
find(hc->ignorePowerSupplyNames.begin(), hc->ignorePowerSupplyNames.end(),
String8(name));
//跳过指定的文件
if (itIgnoreName != hc->ignorePowerSupplyNames.end())
continue;
// Look for "type" file in each subdirectory
path.clear();
path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
switch(readPowerSupplyType(path)) {
case ANDROID_POWER_SUPPLY_TYPE_AC:
case ANDROID_POWER_SUPPLY_TYPE_USB:
case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
case ANDROID_POWER_SUPPLY_TYPE_DOCK:
path.clear();
path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
if (access(path.c_str(), R_OK) == 0) mChargerNames.add(String8(name));
break;
case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
// Some devices expose the battery status of sub-component like
// stylus. Such a device-scoped battery info needs to be skipped
// in BatteryMonitor, which is intended to report the status of
// the battery supplying the power to the whole system.
if (isScopedPowerSupply(name)) continue;
mBatteryDevicePresent = true;
if (mHealthdConfig->batteryStatusPath.empty()) {
path.clear();
path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH,
name);
if (access(path.c_str(), R_OK) == 0) mHealthdConfig->batteryStatusPath = path;
}
if (mHealthdConfig->batteryHealthPath.empty()) {
path.clear();
path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,
name);
if (access(path.c_str(), R_OK) == 0) mHealthdConfig->batteryHealthPath = path;
}
if (mHealthdConfig->batteryPresentPath.empty()) {
path.clear();
path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH,
name);
if (access(path.c_str(), R_OK) == 0) mHealthdConfig->batteryPresentPath = path;
}
if (mHealthdConfig->batteryCapacityPath.empty()) {
path.clear();
path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH,
name);
if (access(path.c_str(), R_OK) == 0) mHealthdConfig->batteryCapacityPath = path;
}
....
主要代码说明:
-
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(POWER_SUPPLY_SYSFS_PATH), closedir);
POWER_SUPPLY_SYSFS_PATH是宏定义,实际的值是"/sys/class/power_supply"。这句意思是打开POWER_SUPPLY_SYSFS_PATH指向的文件夹,dir的类型是DIR指向目录的指针,最终dir变量即指向了POWER_SUPPLY_SYSFS_PATH指向的文件夹。
-
while ((entry = readdir(dir.get()))) { const char* name = entry->d_name; 逐个读取dir文件夹中的子文件夹,赋值给entry。直到读取完退出while 循环。将子文件夹entry的名称赋值给name。
-
path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
switch(readPowerSupplyType(path)) {
case ANDROID_POWER_SUPPLY_TYPE_AC:
case ANDROID_POWER_SUPPLY_TYPE_USB:
case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
case ANDROID_POWER_SUPPLY_TYPE_DOCK:
...
case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
根据当前文件夹的名称,生成一个type文件路径。再通过readPowerSupplyType(path)获取系统电源支持类型。不同的type走不同的switch分支。如果的电池则type是ANDROID_POWER_SUPPLY_TYPE_BATTERY。
-
if (mHealthdConfig->batteryStatusPath.empty()) {
path.clear();
path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH, name);
if (access(path.c_str(), R_OK) == 0) mHealthdConfig->batteryStatusPath = path; }
如果mHealthdConfig->batteryStatusPath变量还没有配置,则进入配置逻辑。根据当前文件夹的名称,获取当前文件夹下的status文件路径。 access(path.c_str(), R_OK) 测试status文件是否可以访问。如果可以则返回0,然后将status的路径path保存到mHealthdConfig->batteryStatusPath中。status事实上是代表的是电池的状态。也就是说电池的状态存放在status中。要知道电池的状态只要读取status的值即可。其他的电池参数比如"voltage_now","capacity","present"也是一样的处理逻辑。
所以这段代码主要将代表电池的相关参数的文件路径保存到healthd_config结构体中,方便后续读取其中的值。
2. 创建HalHealthLoop实例
c
// Caller must ensure that the lifetime of service_ is not shorter than this object.
HalHealthLoop(std::shared_ptr<IHealth> service, std::shared_ptr<HalHealthLoopCallback> callback)
: service_(std::move(service)), callback_(std::move(callback)) {}
这个比较简单,初始化service_和callback_ ,根据main中的代码可以看到传入的都是binder,即Health对象。所以service_和callback_指向的都是Health对象
3. StartLoop()函数
该方法主要是做一些初始化工作,然后进入循环等待事件处理。
c
int HealthLoop::StartLoop() {
int ret;
klog_set_level(KLOG_LEVEL);
//初始化工作
ret = InitInternal();
if (ret) {
KLOG_ERROR(LOG_TAG, "Initialization failed, exiting\n");
return 2;
}
//进入无限循环
MainLoop();
KLOG_ERROR(LOG_TAG, "Main loop terminated, exiting\n");
return 3;
}
//InitInternal函数
int HealthLoop::InitInternal() {
//创建epoll监听epollfd_
epollfd_.reset(epoll_create1(EPOLL_CLOEXEC));
if (epollfd_ == -1) {
KLOG_ERROR(LOG_TAG, "epoll_create1 failed; errno=%d\n", errno);
return -1;
}
// Call subclass's init for any additional init steps.
// Note that healthd_config_ is initialized before wakealarm_fd_; see
// AdjustUeventWakealarmPeriods().
//在子类中实际初始化
Init(&healthd_config_);
//定时器初始化
WakeAlarmInit();
//Uevent初始化
UeventInit();
return 0;
}
StartLoop函数调用InitInternal() 做一些初始化工作,再调用MainLoop()函数进入等待事件的循环。再看看InitInternal()函数。调用epoll_create1系统函数,创建epoll监听对象 epollfd_,在MainLoop()函数中监听的就是这个对象。再调用3个初始化方法:Init(&healthd_config_),这个函数是在子类中实现,这里实际是HalHealthLoop类。然后是定时器初始化WakeAlarmInit(),再Uevent事件初始化UeventInit()。下面逐步看3个初始化函数的源码实现。首先是Init代码:
c
//Init 函数
void HalHealthLoop::Init(struct healthd_config* config) {
callback_->OnInit(this, config);
}
//callback_->OnInit 函数
void Health::OnInit(HalHealthLoop* hal_health_loop, struct healthd_config* config) {
LOG(INFO) << instance_name_ << " instance initializing with healthd_config...";
// Similar to HIDL's android::hardware::health::V2_1::implementation::HalHealthLoop::Init,
// copy configuration parameters to |config| for HealthLoop (e.g. uevent / wake alarm periods)
*config = *healthd_config_.get();
binder_status_t status = ABinderProcess_setupPolling(&binder_fd_);
if (status == ::STATUS_OK && binder_fd_ >= 0) {
std::shared_ptr<Health> thiz = ref<Health>();
auto binder_event = [thiz](auto*, uint32_t epevents) { thiz->BinderEvent(epevents); };
if (hal_health_loop->RegisterEvent(binder_fd_, binder_event, EVENT_NO_WAKEUP_FD) != 0) {
PLOG(ERROR) << instance_name_ << " instance: Register for binder events failed";
}
}
std::string health_name = IHealth::descriptor + "/"s + instance_name_;
//向ServiceManager注册binder服务
CHECK_EQ(STATUS_OK, AServiceManager_addService(this->asBinder().get(), health_name.c_str()))
<< instance_name_ << ": Failed to register HAL";
LOG(INFO) << instance_name_ << ": Hal init done";
}
Init的实现是在子类中,这里我们子类是HalHealthLoop,它的Init函数只是调用了callback_->OnInit()。在上面HalHealthLoop构造方法中已经知道callback_其实是传入的Health对象。再看看Health::OnInit函数,它做了2个重要的事,第一个调用hal_health_loop->RegisterEvent函数,注册监听变量binder_fd_,binder_fd_是当前进程binder轮询机制的文件描述符。 第2个是调用AServiceManager_addService来将Health注册为binder服务。也就是说,在其他进程中可以通过获取服务代理和Health进行进程通信。BatteryService中正是利用这种方法来获取电池数据的更新。
WakeAlarmInit代码:
c
void HealthLoop::WakeAlarmInit(void) {
wakealarm_fd_.reset(timerfd_create(CLOCK_BOOTTIME_ALARM, TFD_NONBLOCK));
if (wakealarm_fd_ == -1) {
KLOG_ERROR(LOG_TAG, "wakealarm_init: timerfd_create failed\n");
return;
}
if (RegisterEvent(wakealarm_fd_, &HealthLoop::WakeAlarmEvent, EVENT_WAKEUP_FD))
KLOG_ERROR(LOG_TAG, "Registration of wakealarm event failed\n");
WakeAlarmSetInterval(healthd_config_.periodic_chores_interval_fast);
}
首先使用timerfd_create创建一个定时器文件描述符wakealarm_fd_, 并将其注册到epoll中监听变化。然后调用WakeAlarmSetInterval设置定时器间隔。healthd_config_.periodic_chores_interval_fast的值是在宏DEFAULT_PERIODIC_CHORES_INTERVAL_FAST 中定义,它的值是60s。
UeventInit代码:
c
void HealthLoop::UeventInit(void) {
uevent_fd_.reset(uevent_open_socket(64 * 1024, true));
if (uevent_fd_ < 0) {
KLOG_ERROR(LOG_TAG, "uevent_init: uevent_open_socket failed\n");
return;
}
fcntl(uevent_fd_, F_SETFL, O_NONBLOCK);
if (RegisterEvent(uevent_fd_, &HealthLoop::UeventEvent, EVENT_WAKEUP_FD))
KLOG_ERROR(LOG_TAG, "register for uevent events failed\n");
}
uevent_open_socket(64 * 1024, true): 打开uevent套接字,设置缓冲区大小为64*1024字节,以及设置为非阻塞模式。
fcntl(uevent_fd_, F_SETFL, O_NONBLOCK):设置文件描述符uevent_fd_为非阻塞式。
RegisterEvent(uevent_fd_, &HealthLoop::UeventEvent, EVENT_WAKEUP_FD)注册epoll事件监听,当uevent_fd_有变化时,回调HealthLoop::UeventEvent。
uevent 套接字通常用于监听设备的事件通知。当硬件的状态发生变化,如设备的插入拔出,状态变化等,内核会向uevent套接字发送通知。应用监听到uevent事件就可以对变化做相应的处理。
如果在进入UeventEvent回调函数里查看会发现当事件的信息为"SUBSYSTEM=power_supply"时,会调用ScheduleBatteryUpdate()函数,来更新电池信息。所以这里应该监听处理的是电源的状态变化。
总体来说3个初始化方法 Init,WakeAlarmInit,UeventInit,为binder_fd_,wakealarm_fd_以及uevent_fd_这3个变量设置了监听,当它们发生变化时,处理对应的回调方法。而具体监听处理逻辑正在是MainLoop函数中,下面看看其代码实现:
c
void HealthLoop::MainLoop(void) {
int nevents = 0;
while (1) {
reject_event_register_ = true;
size_t eventct = event_handlers_.size();
struct epoll_event events[eventct];
int timeout = awake_poll_interval_;
int mode_timeout;
/* Don't wait for first timer timeout to run periodic chores */
if (!nevents) PeriodicChores();
Heartbeat();
mode_timeout = PrepareToWait();
if (timeout < 0 || (mode_timeout > 0 && mode_timeout < timeout)) timeout = mode_timeout;
nevents = epoll_wait(epollfd_, events, eventct, timeout);
if (nevents == -1) {
if (errno == EINTR) continue;
KLOG_ERROR(LOG_TAG, "healthd_mainloop: epoll_wait failed\n");
break;
}
for (int n = 0; n < nevents; ++n) {
if (events[n].data.ptr) {
auto* event_handler = reinterpret_cast<EventHandler*>(events[n].data.ptr);
event_handler->func(event_handler->object, events[n].events);
}
}
}
return;
}
while (1) 代表代码进入死循环,如果没有异常,循环不会推出。
nevents = epoll_wait(epollfd_, events, eventct, timeout): 调用epoll_wait等待epollfd_监听是事件到来,如果监听的文件描述符有变化,则调用之前注册的events回调。epollfd_监听的文件描述符就是前面3个初始化方法中注册的binder_fd_,wakealarm_fd_以及uevent_fd_。
for (int n = 0; n < nevents; ++n):监听的数据有变化,则处理变化的回调。通过events[n].data.ptr获取之前注册的回调函数。event_handler->func(event_handler->object, events[n].events),这段是执行回调函数。wakealarm_fd_对应的是HealthLoop::WakeAlarmEvent。binder_fd_对应的是binder_event, uevent_fd_对应的是ealthLoop::UeventEvent。这些在前面的初始化代码中可以找到。 PS:Heartbeat()和PrepareToWait() 没有找到对应在Health类中的具体实现,可能是在这里没有实现。有了解的可以评论区讨论。
这里我们基本可以判断出,电池信息的获取和分发是在注册的回调函数中处理。当定时事件到达或者电池状态改变时,会调用注册的回调函数。而在回调中都会调用到ScheduleBatteryUpdate函数。我们再来看看在这个函数中如何获取电池信息的。
4.ScheduleBatteryUpdate函数
c
void HalHealthLoop::ScheduleBatteryUpdate() {
// ignore errors. impl may not be able to handle any callbacks, so
// update() may return errors.
if (auto res = service_->update(); !res.isOk()) {
LOG(WARNING) << "update() on the health HAL implementation failed with "
<< res.getDescription();
}
HealthInfo health_info;
auto res = service_->getHealthInfo(&health_info);
CHECK(res.isOk()) << "getHealthInfo() on the health HAL implementation failed with "
<< res.getDescription();
OnHealthInfoChanged(health_info);
}
//Health::update函数
ndk::ScopedAStatus Health::update() {
HealthInfo health_info;
if (auto res = getHealthInfo(&health_info); !res.isOk()) {
LOG(DEBUG) << "Cannot call getHealthInfo for update(): " << res.getDescription();
// Propagate service specific errors. If there's none, report unknown error.
if (res.getServiceSpecificError() != 0 ||
res.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
return res;
}
return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
IHealth::STATUS_UNKNOWN, res.getDescription().c_str());
}
battery_monitor_.logValues();
OnHealthInfoChanged(health_info);
return ndk::ScopedAStatus::ok();
}
if (auto res = service_->update(); !res.isOk()) : service_ 是Health类的实例对象。update()函数里更新了电池信息,如果没有异常返回ok,有则返回指定的错误。在这段代码里如果有异常只是打印了log,不管有没有异常都会走到下面service_->getHealthInfo(&health_info)来获取电池信息。看一下getHealthInfo的代码。
c
ndk::ScopedAStatus Health::getHealthInfo(HealthInfo* out) {
battery_monitor_.updateValues();
*out = battery_monitor_.getHealthInfo();
...
return ndk::ScopedAStatus::ok();
}
//battery_monitor_.updateValues 函数
void BatteryMonitor::updateValues(void) {
//初始化HealthInfo对象,设置一些基本的值
initHealthInfo(mHealthInfo.get());
//根据文件路径获取对应的值
if (!mHealthdConfig->batteryPresentPath.empty())
mHealthInfo->batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
else
mHealthInfo->batteryPresent = mBatteryDevicePresent;
mHealthInfo->batteryLevel = mBatteryFixedCapacity
? mBatteryFixedCapacity
: getIntField(mHealthdConfig->batteryCapacityPath);
mHealthInfo->batteryVoltageMillivolts = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
if (!mHealthdConfig->batteryCurrentNowPath.empty())
mHealthInfo->batteryCurrentMicroamps = getIntField(mHealthdConfig->batteryCurrentNowPath);
if (!mHealthdConfig->batteryFullChargePath.empty())
mHealthInfo->batteryFullChargeUah = getIntField(mHealthdConfig->batteryFullChargePath);
if (!mHealthdConfig->batteryCycleCountPath.empty())
mHealthInfo->batteryCycleCount = getIntField(mHealthdConfig->batteryCycleCountPath);
if (!mHealthdConfig->batteryChargeCounterPath.empty())
mHealthInfo->batteryChargeCounterUah =
getIntField(mHealthdConfig->batteryChargeCounterPath);
if (!mHealthdConfig->batteryCurrentAvgPath.empty())
mHealthInfo->batteryCurrentAverageMicroamps =
getIntField(mHealthdConfig->batteryCurrentAvgPath);
...
}
battery_monitor_.updateValues(): battery_monitor_ 监控电池状态的类的实例。 在上面的代码中,我们介绍过battery_monitor_.init这个方法,主要是将代表电池各种状态的各种文件路径保存在mHealthdConfig对象中。而这里的battery_monitor_.updateValues()方法,则是按照保存的文件路径,读取文件的值,即电池的状态,然后保存在mHealthInfo对象中。BatteryMonitor::updateValues 里的代码相对简单,基本都是读取文件值的操作,读取文件的值后,保存到mHealthInfo对象对应的变量中。
*out = battery_monitor_.getHealthInfo(): 该方法只是简单的返回mHealthInfo对象,将其赋值给out指针变量。这样在调用完getHealthInfo(&health_info)函数后,外部传入的HealthInfo类型的变量health_info,就指向了保存有最新的电池状态信息的对象。获取到电池信息后接下来就是调用OnHealthInfoChanged(health_info)函数,将信息通知到需要更新的地方。
具体信息通知到哪里了?看看OnHealthInfoChanged代码中能不能找到答案。
c
void HalHealthLoop::OnHealthInfoChanged(const HealthInfo& health_info) {
//callback_为Health类的对象
callback_->OnHealthInfoChanged(health_info);
set_charger_online(health_info);
AdjustWakealarmPeriods(charger_online());
}
//callback_->OnHealthInfoChanged 函数实现
void Health::OnHealthInfoChanged(const HealthInfo& health_info) {
// Notify all callbacks
//获得锁
std::unique_lock<decltype(callbacks_lock_)> lock(callbacks_lock_);
// is_dead notifies a callback and return true if it is dead.
auto is_dead = [&](const auto& linked) {
//分发消息
auto res = linked->callback()->healthInfoChanged(health_info);
return IsDeadObjectLogged(res);
};
auto it = std::remove_if(callbacks_.begin(), callbacks_.end(), is_dead);
//删除dead的callback
callbacks_.erase(it, callbacks_.end()); // calls unlinkToDeath on deleted callbacks.
//释放锁
lock.unlock();
// Let HalHealthLoop::OnHealthInfoChanged() adjusts uevent / wakealarm periods
}
OnHealthInfoChanged调用了callback_->OnHealthInfoChanged(health_info),即调用了callback_对象即是Health类的OnHealthInfoChanged方法。
auto it = std::remove_if(callbacks_.begin(), callbacks_.end(), is_dead):对callbacks_数组进行遍历,从callbacks_.begin()开始,到callbacks_.end()结束,移除满足is_dead返回条件的元素。is_dead是个函数,用于检查是否满足条件,其返回true代码满足条件。在这里is_dead的作用是,当迭代callbacks_过程中会调用is_dead函数,is_dead函数调用linked->callback()->healthInfoChanged(health_info)把信息分发出去。如果linked->callback()->healthInfoChanged(health_info)返回的res的状态是STATUS_DEAD_OBJECT表明该callback是"dead"的,则is_dead函数返回true。这样后面callbacks_.erase会将"dead"的callback清除。"dead"的callback,可能是需要接收信息的进程不再运行。所以is_dead函数干了2件事,一个是调用linked->callback()->healthInfoChanged(health_info)发送信息,另一个是,标记不需要分发的元素,用于后面的清除工作。
这里又有个疑问,这个callbacks_集合是什么?里面的元素是什么?消息被分发到哪里去了?在源码中可以看到它的定义是: std::vector<std::unique_ptr> callbacks_。这是一个元素类型为LinkedCallback的集合。而它的元素的添加是在Health类的方法Health::registerCallback中实现。具体看一下元素的添加过程:
c
ndk::ScopedAStatus Health::registerCallback(const std::shared_ptr<IHealthInfoCallback>& callback) {
if (callback == nullptr) {
// For now, this shouldn't happen because argument is not nullable.
return ndk::ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
}
{
std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
auto linked_callback_result = LinkedCallback::Make(ref<Health>(), callback);
if (!linked_callback_result.ok()) {
return ndk::ScopedAStatus::fromStatus(-linked_callback_result.error().code());
}
callbacks_.emplace_back(std::move(*linked_callback_result));
// unlock
}
...
return ndk::ScopedAStatus::ok();
}
auto linked_callback_result = LinkedCallback::Make(ref(), callback):创建LinkedCallback对象,并赋给linked_callback_result变量。第2个callback参数为调用registerCallback时传入的值,类型为std::shared_ptr&。它被保存在LinkedCallback对象中的callback_变量中。
callbacks_.emplace_back(std::move(*linked_callback_result)): 创建好LinkedCallback对象后将它添加到callbacks_集合的尾部。
这里就解答了上面的疑问,callbacks_是LinkedCallback类的容器,添加在callbacks_中的元素是LinkedCallback实例对象。当函数is_dead中调用linked->callback()->healthInfoChanged(health_info)时,实际是调用的std::shared_ptr& callback的healthInfoChanged方法。也就是信息被发送到了registerCallback入参,IHealthInfoCallback:callback中去了。新的问题出现了。谁调用了registerCallback, std::shared_ptr& callback这个入参传入的实例在哪里?
这里我们必须回到上的第三节 "BatteryService电池管理" 中BatteryService类的 registerHealthCallback方法中找答案。忘记的可以回去再看看。
其中有个语句:mHealthServiceWrapper = HealthServiceWrapper.create(this::update)。 我看看这个create代码:
java
public static HealthServiceWrapper create(@Nullable HealthInfoCallback healthInfoCallback)
throws RemoteException, NoSuchElementException {
return create(
healthInfoCallback == null ? null : new HealthRegCallbackAidl(healthInfoCallback),
new HealthServiceWrapperAidl.ServiceManagerStub() {},
healthInfoCallback == null ? null : new HealthHalCallbackHidl(healthInfoCallback),
new HealthServiceWrapperHidl.IServiceManagerSupplier() {},
new HealthServiceWrapperHidl.IHealthSupplier() {});
}
@VisibleForTesting
static @NonNull HealthServiceWrapper create(
@Nullable HealthRegCallbackAidl aidlRegCallback,
@NonNull HealthServiceWrapperAidl.ServiceManagerStub aidlServiceManager,
@Nullable HealthServiceWrapperHidl.Callback hidlRegCallback,
@NonNull HealthServiceWrapperHidl.IServiceManagerSupplier hidlServiceManagerSupplier,
@NonNull HealthServiceWrapperHidl.IHealthSupplier hidlHealthSupplier)
throws RemoteException, NoSuchElementException {
try {
return new HealthServiceWrapperAidl(aidlRegCallback, aidlServiceManager);
} catch (NoSuchElementException e) {
// Ignore, try HIDL
}
return new HealthServiceWrapperHidl(
hidlRegCallback, hidlServiceManagerSupplier, hidlHealthSupplier);
}
一个参数的create方法调用了另一个5个参数的create方法,而5个参数的create方法,在正常情况下是AIDL实现,所以返回new HealthServiceWrapperAidl(aidlRegCallback, aidlServiceManager)。所以这个aidlRegCallback实例是new HealthRegCallbackAidl(healthInfoCallback)。
首先看看HealthServiceWrapperAidl构造函数:
java
HealthServiceWrapperAidl(
@Nullable HealthRegCallbackAidl regCallback, @NonNull ServiceManagerStub serviceManager)
throws RemoteException, NoSuchElementException {
traceBegin("HealthInitGetServiceAidl");
IHealth newService;
try {
//SERVICE_NAME的定义是 @VisibleForTesting static final String SERVICE_NAME = IHealth.DESCRIPTOR + "/default";
newService = serviceManager.waitForDeclaredService(SERVICE_NAME);
} finally {
traceEnd();
}
if (newService == null) {
throw new NoSuchElementException(
"IHealth service instance isn't available. Perhaps no permission?");
}
mLastService.set(newService);
mRegCallback = regCallback;
if (mRegCallback != null) {
mRegCallback.onRegistration(null /* oldService */, newService);
}
traceBegin("HealthInitRegisterNotificationAidl");
mHandlerThread.start();
try {
serviceManager.registerForNotifications(SERVICE_NAME, mServiceCallback);
} finally {
traceEnd();
}
Slog.i(TAG, "health: HealthServiceWrapper listening to AIDL HAL");
}
serviceManager.waitForDeclaredService(SERVICE_NAME): 获取名为SERVICE_NAME的服务。SERVICE_NAME的值是IHealth.DESCRIPTOR + "/default",这个正是上面介绍初始化方法Health::OnInit中的,注册Health binder服务的名字。也就是在这里获取的newService正式Health binder服务。而newService的类型也正是IHealth。
mRegCallback.onRegistration(null /* oldService */, newService):获取newService后,调用此方法注册callback,看一下里面代码:
java
public void onRegistration(@Nullable IHealth oldService, @NonNull IHealth newService) {
if (mServiceInfoCallback == null) return;
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "HealthUnregisterCallbackAidl");
try {
unregisterCallback(oldService, mHalInfoCallback);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "HealthRegisterCallbackAidl");
try {
registerCallback(newService, mHalInfoCallback);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}
//registerCallback(newService, mHalInfoCallback)方法
private static void registerCallback(@NonNull IHealth newService, IHealthInfoCallback cb) {
try {
newService.registerCallback(cb);
} catch (RemoteException e) {
Slog.e(
TAG,
"health: cannot register callback, framework may cease to"
+ " receive updates on health / battery info!",
e);
return;
}
// registerCallback does NOT guarantee that update is called immediately, so request a
// manual update here.
try {
newService.update();
} catch (RemoteException e) {
Slog.e(TAG, "health: cannot update after registering health info callback", e);
}
}
在onRegistration中调用了registerCallback(newService, mHalInfoCallback);方法。其中 是mHalInfoCallback定义是:private final IHealthInfoCallback mHalInfoCallback = new HalInfoCallback();这个mHalInfoCallback在声明变量是被赋值,并定义为final 常量。
registerCallback(@NonNull IHealth newService, IHealthInfoCallback cb) 方法中调用了newService.registerCallback(cb), 这时就清楚了,Health服务的registerCallback方法是在这里调用的。在这里将IHealthInfoCallback 实例对象cb注册到服务中。
当电池状态更新时,最终回调的是cb的healthInfoChanged方法。
java
private class HalInfoCallback extends IHealthInfoCallback.Stub {
@Override
public void healthInfoChanged(HealthInfo healthInfo) throws RemoteException {
mServiceInfoCallback.update(healthInfo);
}
@Override
public String getInterfaceHash() {
return IHealthInfoCallback.HASH;
}
@Override
public int getInterfaceVersion() {
return IHealthInfoCallback.VERSION;
}
}
cb的healthInfoChanged方法中直接调用:mServiceInfoCallback.update(healthInfo); 而mServiceInfoCallback则是在上面HealthServiceWrapper类create方法中的 new HealthRegCallbackAidl(healthInfoCallback) 传入的参数healthInfoCallback,而这个参数对应的是mHealthServiceWrapper = HealthServiceWrapper.create(this::update)语句的参数this::update。
也就是说最终调用到了BatteryService类的update方法。在这个update方法中,接收Health服务传来的最新的电池信息android.hardware.health.HealthInfo info,然后做相应的处理。到这里就终于搞清了最开始提的,电量的改变是如何通知到BatteryService服务的,这个问题。
回调层层调用容易搞晕,画个图总结一下:
备注:有迷糊的地方欢迎提意见,另外在文章的写法上有什么好的建议也欢迎留言。
源码路径
PowerManagerService:frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
PowerManagerService.cpp: frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp
SystemServer: frameworks/base/services/java/com/android/server/SystemServer.java
BatteryService.java: frameworks/base/services/core/java/com/android/server/BatteryService.java
main.cpp:hardware/interfaces/health/aidl/default/main.cpp HalHealthLoop.cpp : hardware/interfaces/health/aidl/default/HalHealthLoop.cpp
Health.cpp:hardware/interfaces/health/aidl/default/Health.cpp
LinkedCallback.cpp: hardware/interfaces/health/aidl/default/LinkedCallback.cpp
参考资料
《深入解析Android 5.0 系统》
Power Management:wladimir-tm4pda.github.io/porting/pow...
Android Power and Battery Management: A Look Underneath The Hood: khoshgozaran.com/android-pow...
Health2.0: source.android.com/docs/core/p...
Health AIDL HAL:android.googlesource.com/platform/ha...