zoukankan      html  css  js  c++  java
  • Android Healthd电池服务分析

    healthd

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

    
    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

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

    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
    ",
                               optopt);
                    exit(1);
                }
            }
        }
     
        ret = healthd_init(); //healthed初始化
        if (ret) {
            KLOG_ERROR("Initialization failed, exiting
    ");
            exit(2);
        }
     
        healthd_mainloop(); //主循环
        KLOG_ERROR("Main loop terminated, exiting
    ");
        return 3;
    }
    

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

    ///////////////////////////////////////////////////////////////////////////三个相关的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()

    static int healthd_init() {
        epollfd = epoll_create(MAX_EPOLL_EVENTS);//创建一个epoll变量
        if (epollfd == -1) {
            KLOG_ERROR(LOG_TAG,
                       "epoll_create failed; errno=%d
    ",
                       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模式

    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
    ");
        }
     
        gBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar();
    	//将batteryProperties注册到ServiceManager中 
        gBatteryPropertiesRegistrar->publish();
    }
    
    

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

    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 ---------------
    ");
     
        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
    ");
            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
    ");
            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)
    ",
                 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;
    }
    
    //接着到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
    ");
            return;
        }
    	//将wakealarm事件注册到wakealarm_fd文件节点上以监听wakealarm事件。
        if (healthd_register_event(wakealarm_fd, wakealarm_event))
            KLOG_ERROR(LOG_TAG,
                       "Registration of wakealarm event failed
    ");
        //设置alarm唤醒间隔
        wakealarm_set_interval(healthd_config.periodic_chores_interval_fast);
    }
    

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

    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); //绘制充电动画
    }
    
    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);
                }
            }
        }
    
    
    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模式不再分析。

  • 相关阅读:
    数据结构-连续子数组的最大和
    数据结构-并查集
    nginx开启代理后,出现net::ERR_CONTENT_LENGTH_MISMATCH 200 (OK)错误
    计算出n阶乘中尾部零的个数
    常见的加密方式总结
    idea中lombok不生效
    纯真ip地址数据库使用
    go mod使用
    exec: "gcc": executable file not found in %PATH%解决办法
    java多线程系列1-初识多线程多线程4种实现方式
  • 原文地址:https://www.cnblogs.com/linhaostudy/p/12002068.html
Copyright © 2011-2022 走看看