of is based on BatteryService to update battery power information

  • 2020-10-23 21:12:36
  • OfStack

An example of Android programming is presented in this paper. To share for your reference, the details are as follows:

The battery information, voltage, temperature, charging status, etc., is provided by BatteryService. BatteryService is run in system_process and is started at system initialization as shown below

In SystemServer. java, you can see the code to start BatteryService:


Log.i(TAG, "Starting Battery Service.");
BatteryService battery = new BatteryService(context);
ServiceManager.addService("battery", battery);

1. Data sources

BatteryService reads data from JNI (ES20en_android_ES22en_BatteryService.cpp). BatteryService registers not only functions but also variables through JNI. As follows:


//############## in BatteryService.java Variables declared in ################
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;

The variable declared in ES30en.java is used in ES32en_android_server_BatteryService.cpp, that is, the variable declared in ES37en_android_server_BatteryService.cpp is also operated on


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");

The values of the above variables correspond to reading from the following file, with 1 file storing only 1 value.


#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"

Android is running on top of the Linux kernel, /sys/class/power_supply is also the directory under the Linux kernel. How these files are generated is controlled by Platform.

Data transfer

How this information about the battery is obtained by other applications. There are two ways to think about it. First, the application actively obtains data from BatteryService. Second, BatteryService takes the initiative to transmit data to the application of interest.

BatteryService USES the second method, and all the battery information data is transmitted through Intent. In ES68en. java, Code is as follows:


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);

3. Data reception

If the application wants to receive the battery information sent by BatteryService, it needs to register 1 Intent as ES78en.ACTION_ES80en_ES81en's BroadcastReceiver.

Registration method is as follows:


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..."); 
     } 
   } 
  } 
};

4. Data update

Battery information changes over time, and naturally, you need to think about how to update the battery data in real time. When BatteryService is started, one onUEvent Thread is started simultaneously via UEventObserver.

There can be at most one onUEvent Thread per Process, even if there are multiple instances of UEventObserver in this Process. The UEvent thread is started after the first Call startObserving() method in an Process.

And once this UEvent thread starts, it doesn't stop.


// in BatteryService.java In the  
mUEventObserver.startObserving("SUBSYSTEM=power_supply");
private UEventObserver mUEventObserver = new UEventObserver() { 
  @Override 
  public void onUEvent(UEventObserver.UEvent event) { 
   update(); 
  } 
};

In UEvent thread, the update() method is called repeatedly to update the battery information data.

I hope this article is helpful for Android programming.


Related articles: