前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android Healthd电池服务分析

Android Healthd电池服务分析

作者头像
233333
发布2019-12-11 14:20:46
2.3K0
发布2019-12-11 14:20:46
举报

healthd

healthd是安卓4.4之后提出来的,监听来自kernel的电池事件,并向上传递电池数据给framework层的BatteryService。BatteryService计算电池电量显示,剩余电量,电量级别以及绘制充电动画等信息,其代码位于/system/core/healthd。

代码语言:javascript
复制
android/system/core/healthd/
Android.mk          BatteryMonitor.h                BatteryPropertiesRegistrar.h  healthd.cpp  healthd_mode_android.cpp  images
BatteryMonitor.cpp  BatteryPropertiesRegistrar.cpp  healthd_board_default.cpp     healthd.h    healthd_mode_charger.cpp

下面一张图清晰的表示了Android电池系统框架

image
image

healthd服务入口:android/system/core/healthd/healthd.cpp 中main函数。

代码语言:javascript
复制
int main(int argc, char **argv) {
    int ch;
    int ret;
 
    klog_set_level(KLOG_LEVEL);
 
    
    //healthd_mode_ops是一个关于充电状态的结构体变量,
    healthd_mode_ops = &android_ops;//开机充电时,指向android_ops
 
    if (!strcmp(basename(argv[0]), "charger")) {
        healthd_mode_ops = &charger_ops; //
    } else {
        while ((ch = getopt(argc, argv, "cr")) != -1) {
            switch (ch) {
            case 'c':
                healthd_mode_ops = &charger_ops; //关机状态下的充电
                break;
            case 'r':
                healthd_mode_ops = &recovery_ops;//recovery下的操作
                break;
            case '?':
            default:
                KLOG_ERROR(LOG_TAG, "Unrecognized healthd option: %c\n",
                           optopt);
                exit(1);
            }
        }
    }
 
    ret = healthd_init(); //healthed初始化
    if (ret) {
        KLOG_ERROR("Initialization failed, exiting\n");
        exit(2);
    }
 
    healthd_mainloop(); //主循环
    KLOG_ERROR("Main loop terminated, exiting\n");
    return 3;
}

在main函数中,首先根据传入的参数不同区分:开机充电、recovery、关机充电。这三种情况,然后指定不同的healthd_mode_ops回调函数。因此有必要贴出来这三个重要的回调。

代码语言:javascript
复制
///////////////////////////////////////////////////////////////////////////三个相关的ops
static struct healthd_mode_ops android_ops = {            开机充电
    .init = healthd_mode_android_init,
    .preparetowait = healthd_mode_android_preparetowait,
    .heartbeat = healthd_mode_nop_heartbeat,
    .battery_update = healthd_mode_android_battery_update,
};
 
static struct healthd_mode_ops charger_ops = {             关机充电
    .init = healthd_mode_charger_init,
    .preparetowait = healthd_mode_charger_preparetowait,
    .heartbeat = healthd_mode_charger_heartbeat,
    .battery_update = healthd_mode_charger_battery_update,
};
 
static struct healthd_mode_ops recovery_ops = {            recover相关的
    .init = healthd_mode_nop_init,
    .preparetowait = healthd_mode_nop_preparetowait,
    .heartbeat = healthd_mode_nop_heartbeat,
    .battery_update = healthd_mode_nop_battery_update,
};

接着往下看healthd_init()

代码语言:javascript
复制
static int healthd_init() {
    epollfd = epoll_create(MAX_EPOLL_EVENTS);//创建一个epoll变量
    if (epollfd == -1) {
        KLOG_ERROR(LOG_TAG,
                   "epoll_create failed; errno=%d\n",
                   errno);
        return -1;
    }
    //和板子级别的初始化,里面其实是一个空函数,什么也没做
    healthd_board_init(&healthd_config);
    //根据系统所处的模式,有三种情况的init,开机充电,关机充电,recovery
    healthd_mode_ops->init(&healthd_config);
    //wakealarm定时器初始化
    wakealarm_init();
    //uevent事件初始化,用以监听电池的uevent事件。
    uevent_init();
    //BatteryMonitor初始化。
    gBatteryMonitor = new BatteryMonitor();//创建batteryMonitor对象
    gBatteryMonitor->init(&healthd_config);//初始化batteryMonitor,打开/sys/class/power_supply,
                                           //遍历该节点下的电池参数初始化healthd的config参数
    return 0;
}

healthd_mode_ops->init(&healthd_config);根据main函数中传入的参数 有三种模式,Android,charger,recovery。

android模式

代码语言:javascript
复制
void healthd_mode_android_init(struct healthd_config* /*config*/) {
    ProcessState::self()->setThreadPoolMaxThreadCount(0);//获取线程池最大线程数
    IPCThreadState::self()->disableBackgroundScheduling(true);//禁止后台调用
    IPCThreadState::self()->setupPolling(&gBinderFd);//将gBinderFd加入到epoll中
 
    if (gBinderFd >= 0) {
        //将binder_event事件注册到gBinderfd文件节点用以监听Binder事件。
        if (healthd_register_event(gBinderFd, binder_event))
            KLOG_ERROR(LOG_TAG,
                       "Register for binder events failed\n");
    }
 
    gBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar();
    //将batteryProperties注册到ServiceManager中 
    gBatteryPropertiesRegistrar->publish();
}

charger模式就是关机充电模式,Android层只跑一个healthd服务用来显示充电动画和电量百分比。

代码语言:javascript
复制
charger模式
 
void healthd_mode_charger_init(struct healthd_config* config) //做充电动画相关的设置
{
    int ret;
    struct charger *charger = &charger_state;
    int i;
    int epollfd;
 
    dump_last_kmsg();
 
    LOGW("--------------- STARTING CHARGER MODE ---------------\n");
 
    ret = ev_init(input_callback, charger);
    if (!ret) {
        epollfd = ev_get_epollfd();
        healthd_register_event(epollfd, charger_event_handler);
    }
 
    ret = res_create_display_surface("charger/battery_fail", &charger->surf_unknown);
    if (ret < 0) {
        LOGE("Cannot load battery_fail image\n");
        charger->surf_unknown = NULL;
    }
 
    charger->batt_anim = &battery_animation; //指定充电动画相关的属性
 
    gr_surface* scale_frames;
    int scale_count;
    ret = res_create_multi_display_surface("charger/battery_scale", &scale_count, &scale_frames);//读取充电动画资源
    if (ret < 0) {
        LOGE("Cannot load battery_scale image\n");
        charger->batt_anim->num_frames = 0;
        charger->batt_anim->num_cycles = 1;
    } else if (scale_count != charger->batt_anim->num_frames) {
        LOGE("battery_scale image has unexpected frame count (%d, expected %d)\n",
             scale_count, charger->batt_anim->num_frames);
        charger->batt_anim->num_frames = 0;
        charger->batt_anim->num_cycles = 1;
    } else {
        for (i = 0; i < charger->batt_anim->num_frames; i++) {  //读取资源成功,存放起来
            charger->batt_anim->frames[i].surface = scale_frames[i];
        }
    }
 
    ev_sync_key_state(set_key_callback, charger);
 
    charger->next_screen_transition = -1;
    charger->next_key_check = -1;
    charger->next_pwr_check = -1;
    healthd_config = config;
}
代码语言:javascript
复制
//接着到wakealarm_init
static void wakealarm_init(void) {
    //创建一个月wakealarm对应的定时器描述符
    wakealarm_fd = timerfd_create(CLOCK_BOOTTIME_ALARM, TFD_NONBLOCK);
    if (wakealarm_fd == -1) {
        KLOG_ERROR(LOG_TAG, "wakealarm_init: timerfd_create failed\n");
        return;
    }
    //将wakealarm事件注册到wakealarm_fd文件节点上以监听wakealarm事件。
    if (healthd_register_event(wakealarm_fd, wakealarm_event))
        KLOG_ERROR(LOG_TAG,
                   "Registration of wakealarm event failed\n");
    //设置alarm唤醒间隔
    wakealarm_set_interval(healthd_config.periodic_chores_interval_fast);
}

如果是关机充电模式,则healthd_mode_ops->heartbeat(); 执行的是healthd_mode_charger_heartbeat()函数

代码语言:javascript
复制
void healthd_mode_charger_heartbeat()
{
    struct charger *charger = &charger_state;
    int64_t now = curr_time_ms();
    int ret;
 
    handle_input_state(charger, now);      //处理按键相关的事情,长按开机
    handle_power_supply_state(charger, now);
 
    /* do screen update last in case any of the above want to start
     * screen transitions (animations, etc)
     */
    update_screen_state(charger, now); //绘制充电动画
}
代码语言:javascript
复制
frameworks/base/services/core/java/com/android/server/BatteryService.java 
//将电池监听注册到底层
public void onStart() {
    IBinder b = ServiceManager.getService("batteryproperties");
    final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =
            IBatteryPropertiesRegistrar.Stub.asInterface(b);
    try {
        //注册电池监听,当底层电池电量发生变化调用此监听,并调用update。
        batteryPropertiesRegistrar.registerListener(new BatteryListener());
    } catch (RemoteException e) {
        // Should never happen.
    }
 
    publishBinderService("battery", new BinderService());
    publishLocalService(BatteryManagerInternal.class, new LocalService());
}
//当底层有信息时,会调用update更新BatteryService中相关值。
    private void update(BatteryProperties props) {
        synchronized (mLock) {
            if (!mUpdatesStopped) {
                mBatteryProps = props;
                // Process the new values.
                processValuesLocked(false);
            } else {
                mLastBatteryProps.set(props);
            }
        }
    }
代码语言:javascript
复制
private void processValuesLocked(boolean force) {
        boolean logOutlier = false;
        long dischargeDuration = 0;
        //获取电池电量是否低于critical界限。
        mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel);
        //获取电池充电状态,AC,USB,无线,以及什么都没接。
        if (mBatteryProps.chargerAcOnline) {
            mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
        } else if (mBatteryProps.chargerUsbOnline) {
            mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
        } else if (mBatteryProps.chargerWirelessOnline) {
            mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
        } else {
            mPlugType = BATTERY_PLUGGED_NONE;
        }
 
        if (DEBUG) {
            Slog.d(TAG, "Processing new values: "
                    + "chargerAcOnline=" + mBatteryProps.chargerAcOnline
                    + ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline
                    + ", chargerWirelessOnline=" + mBatteryProps.chargerWirelessOnline
                    + ", batteryStatus=" + mBatteryProps.batteryStatus
                    + ", batteryHealth=" + mBatteryProps.batteryHealth
                    + ", batteryPresent=" + mBatteryProps.batteryPresent
                    + ", batteryLevel=" + mBatteryProps.batteryLevel
                    + ", batteryTechnology=" + mBatteryProps.batteryTechnology
                    + ", batteryVoltage=" + mBatteryProps.batteryVoltage
                    + ", batteryTemperature=" + mBatteryProps.batteryTemperature
                    + ", mBatteryLevelCritical=" + mBatteryLevelCritical
                    + ", mPlugType=" + mPlugType);
        }
 
        // Let the battery stats keep track of the current level.
        try {
            mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth,
                    mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature,
                    mBatteryProps.batteryVoltage);
        } catch (RemoteException e) {
            // Should never happen.
        }
        //低电关机
        shutdownIfNoPowerLocked();
        //电池温度过高关机
        shutdownIfOverTempLocked();
 
        if (force || (mBatteryProps.batteryStatus != mLastBatteryStatus ||
                mBatteryProps.batteryHealth != mLastBatteryHealth ||
                mBatteryProps.batteryPresent != mLastBatteryPresent ||
                mBatteryProps.batteryLevel != mLastBatteryLevel ||
                mPlugType != mLastPlugType ||
                mBatteryProps.batteryVoltage != mLastBatteryVoltage ||
                mBatteryProps.batteryTemperature != mLastBatteryTemperature ||
                mInvalidCharger != mLastInvalidCharger)) {
            //适配器插入状态有更改
            if (mPlugType != mLastPlugType) {
                if (mLastPlugType == BATTERY_PLUGGED_NONE) {
                    // discharging -> charging
 
                    // 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 != mBatteryProps.batteryLevel) {
                        dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
                        logOutlier = true;
                        EventLog.writeEvent(EventLogTags.BATTERY_DISCHARGE, dischargeDuration,
                                mDischargeStartLevel, mBatteryProps.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 = mBatteryProps.batteryLevel;
                }
            }
            //电池状态更新
            if (mBatteryProps.batteryStatus != mLastBatteryStatus ||
                    mBatteryProps.batteryHealth != mLastBatteryHealth ||
                    mBatteryProps.batteryPresent != mLastBatteryPresent ||
                    mPlugType != mLastPlugType) {
                EventLog.writeEvent(EventLogTags.BATTERY_STATUS,
                        mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mBatteryProps.batteryPresent ? 1 : 0,
                        mPlugType, mBatteryProps.batteryTechnology);
            }
            if (mBatteryProps.batteryLevel != mLastBatteryLevel) {
                // Don't do this just from voltage or temperature changes, that is
                // too noisy.
                EventLog.writeEvent(EventLogTags.BATTERY_LEVEL,
                        mBatteryProps.batteryLevel, mBatteryProps.batteryVoltage, mBatteryProps.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
                        && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel) {
                    mBatteryLevelLow = true;
                }
            } else {
                // Should we now switch out of low battery mode?
                if (mPlugType != BATTERY_PLUGGED_NONE) {
                    mBatteryLevelLow = false;
                } else if (mBatteryProps.batteryLevel >= mLowBatteryCloseWarningLevel)  {
                    mBatteryLevelLow = false;
                } else if (force && mBatteryProps.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;
                }
            }
            //发送电池状态变换广播
            sendIntentLocked();
 
            // 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) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);
                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                        mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                    }
                });
            }
            else if (mPlugType == 0 && mLastPlugType != 0) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                        mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                    }
                });
            }
            //低电量电池事件通知
            if (shouldSendBatteryLowLocked()) {
                mSentLowBatteryBroadcast = true;
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW);
                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                        mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                    }
                });
            } else if (mSentLowBatteryBroadcast && mLastBatteryLevel >= mLowBatteryCloseWarningLevel) {
                mSentLowBatteryBroadcast = false;
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);
                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                        mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                    }
                });
            }
 
            // 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 = mBatteryProps.batteryStatus;
            mLastBatteryHealth = mBatteryProps.batteryHealth;
            mLastBatteryPresent = mBatteryProps.batteryPresent;
            mLastBatteryLevel = mBatteryProps.batteryLevel;
            mLastPlugType = mPlugType;
            mLastBatteryVoltage = mBatteryProps.batteryVoltage;
            mLastBatteryTemperature = mBatteryProps.batteryTemperature;
            mLastBatteryLevelCritical = mBatteryLevelCritical;
            mLastInvalidCharger = mInvalidCharger;
        }
    }

recovery模式不再分析。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-12-07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • healthd
    • android模式
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档