关键词:android电池系统电池系统架构 uevent power_supply驱动

平台信息:

内核:linux2.6/linux3.0
系统:android/android4.0 
平台:S5PV310(samsungexynos4210) samsung exynos4412

作者:xubin341719(欢迎转载,请注明作者)

欢迎指正错误,共同学习、共同进步!!

android 电池(一):锂电池基本原理篇

android 电池(二):android关机充电流程、充电画面显示

android 电池(三):android电池系统

android电池(四):电池 电量计(MAX17040)驱动分析篇

android电池(五):电池 充电IC(PM2301)驱动分析篇


一、电池系统结构

       Android中的电池使用方式主要有三种:AC、USB、Battery 等不同的模式。在应用程序层次,通常包括了电池状态显示的功能。因此从 Android 系统的软件方面(包括驱动程序和用户空间内容)需要在一定程度上获得电池的状态,电池系统主要负责电池信息统计、显示。电池系统的架构如下所示:


自下而上, Android 的电池系统分成以下几个部分:

1、驱动程序

特定硬件平台电池的驱动程序,用 Linux的Power Supply 驱动程序,实现向用户空间提供信息。Battery 驱动程序需要通过sys文件系 统向用户空间提供接口, sys文件系统的路径是由上层的程序指定的。Linux标准的 Power Supply驱动程序 所使用的文件系统路径为:/sys/class/power_supply ,其中的每个子目录表示一种能源供应设备的名称。


Power Supply 驱动程序的头文件在 include/linux/power_supply.h中定义,注册和注销驱动程序的函数如下所示: 

int power_supply_register(struct device *parent,struct power_supply *psy); void power_supply_unregister(struct power_supply *psy); struct power_supply { const char *name; /* 设备名称 */ enum power_supply_type type; /* 类型 */ enum power_supply_property *properties; /* 属性指针 */ size_t num_properties; /* 属性的数目 */ char **supplied_to; size_t num_supplicants; int (*get_property)(struct power_supply *psy, /* 获得属性 */ enum power_supply_property psp, union power_supply_propval *val); void (*external_power_changed)(struct power_supply *psy); /* ...... 省略部分内容 */ }; 

Linux中驱动程序:power_supply


2、本地代码 - JNI

代码路径: frameworks/base/services/jni/com_android_server_BatteryService.cpp 这个类调用sys文件系统访问驱动程序,也同时提供了JNI的接口。

这个文件提供的方法列表如下所示: 

static JNINativeMethod sMethods[] = { {"native_update", "()V", (void*)android_server_BatteryService_update}, };  

处理的流程为根据设备类型判定设备后, 得到各个设备的相关属性,则需要得到更多得 信息。例如:果是交流或者 USB 设备,只需 要得到它们是否在线( onLine );如果是电 池设备,则需要得到更多的信息,例如状态 ( status ),健康程度( health ),容 量( capacity ),电压 ( voltage_now )等。

Linux 驱动 driver 维护着保存电池信息的一组文件 sysfs,供应用程序获取电源相关状态: 

#define AC_ONLINE_PATH "/sys/class/power_supply/ac/online" AC 电源连接状态 #define USB_ONLINE_PATH "/sys/class/power_supply/usb/online" USB电源连接状态 #define BATTERY_STATUS_PATH "/sys/class/power_supply/battery/status"充电状态 #define BATTERY_HEALTH_PATH "/sys/class/power_supply/battery/health"电池状态 #define BATTERY_PRESENT_PATH "/sys/class/power_supply/battery/present"使用状态 #define BATTERY_CAPACITY_PATH "/sys/class/power_supply/battery/capacity"电池 level #define BATTERY_VOLTAGE_PATH "/sys/class/power_supply/battery/batt_vol"电池电压 #define BATTERY_TEMPERATURE_PATH "/sys/class/power_supply/battery/batt_temp"电池温度 #define BATTERY_TECHNOLOGY_PATH "/sys/class/power_supply/battery/technology"电池技术 当电池状态发生变化时,driver 会更新这些文件。传送信息到java 

3 、JAVA 代码

代码路径:

frameworks/base/services/java/com/android/server/BatteryService.java

frameworks/base/core/java/android/os/ : android.os :包中和Battery 相关的部分

frameworks/base/core/java/com/android/internal/os/:和Battery 相关的内部部分 BatteryService.java 通过调用, BatteryService JNI来实现com.android.server包中的 BatteryService类。BatteryManager.java中定义了一些 JAVA 应用程序层可以使用的常量。

       电池系统在驱动程序层以上的部分都是Android 系统中默认的内容。在移植的过程中基本不需要改动。电池系统需要移植的部分仅有Battery驱动程序。Battery 驱动程序用Linux 标准的Power Supply驱动程序与上层的接口是sys文件系统,主要用于读取sys文件系统中的文件来获取电池相关的信息。整个系统中各部件的联系:

BatteryService 作为电池及充电相关的服务: 监听 Uevent、读取sysfs 里中的状态 、广播Intent.ACTION_BATTERY_CHANGED。

(1)、mUEventObserver

BatteryService实现了一个UevenObserver mUEventObserver。uevent是Linux 内核用来向用户空间主动上报事件的机制,对于JAVA程序来说,只实现 UEventObserver的虚函数 onUEvent,然后注册即可。

BatteryService只关注 power_supply 的事件,所以在构造函数注册:

(2)、update()

update读取sysfs文件做到同步取得电池信息, 然后根据读到的状态更新 BatteryService 的成员变量,并广播一个Intent来通知其它关注电源状态的 组件。

当kernel有power_supply事件上报时, mUEventObserver调用update()函数,然后update 调用native_update从sysfs中读取相关状态(com_android_server_BatteryService.cpp):

(3)、sysfs

Linux 驱动 driver 维护着保存电池信息的一组文件 sysfs,供应用程序获

取电源相关状态:

二、Uevent部分

Uevent是内核通知android有状态变化的一种方法,比如USB线插入、拔出,电池电量变化等等。其本质是内核发送(可以通过socket)一个字符串,应用层(android)接收并解释该字符串,获取相应信息。如下图所示,如果其中有信息变化,uevent触发,做出相应的数更新。


Android中的BatteryService及相关组件


1、Androiduevent架构

     Android很多事件都是通过uevent跟kernel来异步通信的。其中类UEventObserver是核心。UEventObserver接收kernel的uevent信息的抽象类。

(1)、server层代码
       battery server:
       frameworks/frameworks/base/services/java/com/android/server/SystemServer.java
       frameworks/frameworks/base/services/java/com/android/server/BatteryService.java

(2)、java层代码
      frameworks/base/core/java/android/os/UEventObserver.java
(3)、JNI层代码
        frameworks/base/core/jni/android_os_UEventObserver.cpp
(4)、底层代码
         hardware/libhardware_legacy/uevent/uevent.c

读写kernel的接口socket(PF_NETLINK,SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
2、UEventObserver的使用

类UEventObserver提供了三个接口给子类来调用:
(1)、onUEvent(UEvent event): 子类必须重写这个onUEvent来处理uevent。
(2)、startObserving(Stringmatch): 启动进程,要提供一个字符串参数。
(3)、stopObserving(): 停止进程。
   例子://在BatteryService.java中

 mUEventObserver.startObserving("SUBSYSTEM=power_supply");         private UEventObserver mUEventObserver = new UEventObserver() {         @Override               public void onUEvent(UEventObserver.UEvent event) {                update();               }         };

 在UEvent thread中会不停调用 update()方法,来更新电池的信息数据。

3、vold server分析
(1)、在system/vold/NetlinkManager.cpp中:

 if ((mSock = socket(PF_NETLINK,SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {               SLOGE("Unable to create uevent socket: %s", strerror(errno));               return -1;       }       if (setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) {               SLOGE("Unable to set uevent socket options: %s", strerror(errno));               return -1;       }       if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {               SLOGE("Unable to bind uevent socket: %s", strerror(errno));               return -1;       }
 (2)、然后在system/vold/NetlinkHandler.cpp的NetlinkHandler::onEvent中处理  
             void NetlinkHandler::onEvent(NetlinkEvent *evt) {                      VolumeManager *vm = VolumeManager::Instance();                     const char *subsys = evt->getSubsystem();                     if (!subsys) {                           SLOGW("No subsystem found in netlink event");                           return;                     }                     if (!strcmp(subsys, "block")) {                           vm->handleBlockEvent(evt);                     } else if (!strcmp(subsys, "switch")) {                           vm->handleSwitchEvent(evt);                     } else if (!strcmp(subsys, "battery")) {                     } else if (!strcmp(subsys, "power_supply")) {                     }             }

(3)、在system/core/libsysutils/src/NetlinkListener.cpp中监听。
4、batteryserver分析

   java代码:frameworks/frameworks/base/services/java/com/android/server/BatteryService.java
   JNI代码: frameworks/base/services/jni/com_android_server_BatteryService.cpp

  (1)、BatteryService是跑在system_process当中,在系统初始化的时候启动

如下在BatteryService.java中:

        Log.i(TAG, “Starting Battery Service.”);        BatteryService battery = new BatteryService(context);        ServiceManager.addService(“battery”, battery);
    (2)、数据来源
       BatteryService通过JNI(com_android_server_BatteryService.cpp)读取数据。
        BatteryService通过JNI注册的不仅有函数,还有变量。 如下: BatteryService是跑在system_process当中,在系统初始化的时候启动,如下在BatteryService.java中:
        //##############在BatteryService.java中声明的变量################        private boolean mAcOnline;        private boolean mUsbOnline;        private int mBatteryStatus;        private int mBatteryHealth;        private boolean mBatteryPresent;        private int mBatteryLevel;        private int mBatteryVoltage;        private int mBatteryTemperature;        private String mBatteryTechnology;      //在BatteryService.java中声明的变量,在com_android_server_BatteryService.cpp中共用,即在com_android_server_BatteryService.cpp中其实操作的也是BatteryService.java中声明的变量。      gFieldIds.mAcOnline = env->GetFieldID(clazz, “mAcOnline”, “Z”);      gFieldIds.mUsbOnline = env->GetFieldID(clazz, “mUsbOnline”, “Z”);      gFieldIds.mBatteryStatus = env->GetFieldID(clazz, “mBatteryStatus”, “I”);      gFieldIds.mBatteryHealth = env->GetFieldID(clazz, “mBatteryHealth”, “I”);      gFieldIds.mBatteryPresent = env->GetFieldID(clazz, “mBatteryPresent”, “Z”);      gFieldIds.mBatteryLevel = env->GetFieldID(clazz, “mBatteryLevel”, “I”);      gFieldIds.mBatteryTechnology = env->GetFieldID(clazz, “mBatteryTechnology”, Ljava/lang/String;”);      gFieldIds.mBatteryVoltage = env->GetFieldID(clazz, “mBatteryVoltage”, “I”);      gFieldIds.mBatteryTemperature = env->GetFieldID(clazz, “mBatteryTemperature”, “I”);      //上面这些变量的值,对应是从下面的文件中读取的,一只文件存储一个数值。      #define AC_ONLINE_PATH “/sys/class/power_supply/ac/online”      #define USB_ONLINE_PATH “/sys/class/power_supply/usb/online”      #define BATTERY_STATUS_PATH “/sys/class/power_supply/battery/status”      #define BATTERY_HEALTH_PATH “/sys/class/power_supply/battery/health”      #define BATTERY_PRESENT_PATH “/sys/class/power_supply/battery/present”      #define BATTERY_CAPACITY_PATH “/sys/class/power_supply/battery/capacity”      #define BATTERY_VOLTAGE_PATH “/sys/class/power_supply/battery/batt_vol”      #define BATTERY_TEMPERATURE_PATH “/sys/class/power_supply/battery/batt_temp”      #define BATTERY_TECHNOLOGY_PATH “/sys/class/power_supply/battery/technology”
  (3)、数据传送
     BatteryService主动把数据传送给所关心的应用程序,所有的电池的信息数据是通过Intent传送出去的。在BatteryService.java中,Code如下:

        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);        intent.putExtra(“status”, mBatteryStatus);        intent.putExtra(“health”, mBatteryHealth);        intent.putExtra(“present”, mBatteryPresent);        intent.putExtra(“level”, mBatteryLevel);        intent.putExtra(“scale”, BATTERY_SCALE);        intent.putExtra(“icon-small”, icon);        intent.putExtra(“plugged”, mPlugType);        intent.putExtra(“voltage”, mBatteryVoltage);        intent.putExtra(“temperature”, mBatteryTemperature);        intent.putExtra(“technology”, mBatteryTechnology);        ActivityManagerNative.broadcastStickyIntent(intent, null);

(4)、数据接收

 应用如果想要接收到BatteryService发送出来的电池信息,则需要注册一个Intent为Intent.ACTION_BATTERY_CHANGED的BroadcastReceiver。

       注册方法如下:
        IntentFilter mIntentFilter = new IntentFilter();        mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);        registerReceiver(mIntentReceiver, mIntentFilter);        private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {            @Override            public void onReceive(Context context, Intent intent) {                // TODO Auto-generated method stub                String action = intent.getAction();                if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {                    int nVoltage = intent.getIntExtra(“voltage”, 0);                    if(nVoltage!=0){                        mVoltage.setText(“V: ” + nVoltage + “mV – Success…”);                    }                    else{                        mVoltage.setText(“V: ” + nVoltage + “mV – fail…”);                    }                }            }        };

(5)、数据更新
        电池的信息会随着时间不停变化,自然地,就需要考虑如何实时的更新电池的数据信息。在BatteryService启动的时候,会同时通过UEventObserver启动一个onUEvent Thread。每一个Process最多只能有一个onUEvent Thread,即使这个Process中有多个UEventObserver的实例。当在一个Process中,第一次Call startObserving()方法后,这个UEvent thread就启动了。而一旦这个UEvent thread启动之后,就不会停止。

       //在BatteryService.java中

        mUEventObserver.startObserving(“SUBSYSTEM=power_supply”);        private UEventObserver mUEventObserver = new UEventObserver() {            @Override            public void onUEvent(UEventObserver.UEvent event) {                update();            }        };

    在UEvent thread中会不停调用 update()方法,来更新电池的信息数据。


更多相关文章

  1. 详解 Android(安卓)的 Activity 组件
  2. Android架构分析之Android驱动程序开发
  3. Android(安卓)shape使用
  4. android状态栏工具类
  5. android检查手机网络状态
  6. Android之记录ListView的checkbox选择位置问题
  7. 开关
  8. 有关XML的点击状态背景图的设置
  9. Android调用打电话(Call Phone)

随机推荐

  1. Android的App列表之拖拽ListView(上)
  2. keytool错误: java.lang.RuntimeException
  3. Repo on Ubuntu
  4. ] Android(安卓)高手进阶篇 1-Service
  5. Flutter PageView使用案例
  6. Android中SQLite数据库介绍和使用
  7. android万能的Listview适配器
  8. Content Provider 基础
  9. Android(安卓)分享实现,微信、微博、腾讯
  10. Android(安卓)IPC进程间通信详解最新Andr