Incorporating USB battery charging protocols into an Android-based design
Editorial Note: Excerpted from Unboxing Android: A hands on approach with real world examples,
by Rajaram Regupathy, the author takes you through the process
incorporating effective power management into a design using the Android
distribution of the Linux operating system using either its native
power management framework or the widely used Universal Serial Bus
USB technology has evolved over the years as the standard for connecting peripherals like keyboards, printers, and so on, to personal computers, and as a result, USB has replaced serial and parallel ports. Modern devices like smart phones and game controllers have also adopted this technology as a primary transport mechanism. As part of their evolution, USB evolved from a data interface to an important source of power to charge portable devices like a smart phones, or even to power up an external audio speaker. In Battery Charging Specification, the Battery Charging Working Group of the USB Implementers Forum (USB-IF) has standardized how a USB power source has to behave, the different types of USB power sources, and how much power a device can consume when connected to a USB source.
This article explores USB-based charging that you, as an Android developer, need to know to develop applications related to charging in various user contexts: wall charger, personal computer, and charging dock. Because both will be important, this article will discuss battery charging in the context of both the USB.org formal spec as well as the native one included within the Android framework.
USB Battery Specification overview
In a way, the main focus of the USB Battery Charging 1.2 specification is to define the characteristics of different chargers and describe their mechanisms for how to detect the chargers. This section focuses on the different types of charging options (USB ports and chargers) and their characteristics in brief. The specification also details the mechanism that can differentiate the different types, but that is beyond the scope of this book. Before you study the different types of charging ports, you should first understand some key USB terms relevant to this section.
Downstream Port - A port that data flows away from the host. In laymen terms, a USB port on a host PC or on a hub, with ports that are farthest from the host, are downstream ports.
Upstream Port - A port that sends data toward the host. Generally, a port on a USB device and on a hub, with the port that is closest to the host, are upstream ports.
Here are the different types of charging options (USB ports and chargers) and their characteristics:
Standard Downstream Port (SDP) refers to a port on a host or hub that’s compliant with USB 2.0 specifications. This means a SDP port can provide different power, depending upon the state of connection with the USB device. An SDP port expects a downstream device to have the following maximum current consumption in different states:
- 2.5mA when the device is in a suspended state
- 100mA when connected and not configured
- 500mA or the amount of current requested by the device’s configuration descriptor, whichever is less, when configured
When a USB device is connected to a SDP, the device can draw 100mA and up to 500mA once the device is enumerated successfully by the host. The charging setup as described for the personal computer example of the previous section represents a Standard Downstream Port.
Charging Downstream Port (CDP) refers to a port on a host or hub that’s compliant with USB 2.0 specifications. But unlike the SDP, a CDP port allows a USB device to draw more current, thereby facilitating faster charging. When a portable device is connected to a charging port, it is expected to behave in the following way:
- 2.5mA when the device is in a suspended state
- 100mA when it is connected and not configured
- Maximum of 1.5A when configured
When a USB device is connected to a CDP, the device will be enumerated successfully by the host. The charging setup as described for the personal computer example of the previous section can also represent a Charging Downstream Port. A CDP port is generally marked with a symbol to indicate to the user that it can supply more power.
Dedicated Charging Port (DCP) A downstream port that provides power over a USB connection to a portable device. When a portable device is connected to a DCP, a maximum of 1.5A can be consumed by the device. The key difference between a DCP and the other two charging ports is that the D+ and the D- lines are shorted, which means there is no support for enumeration. The wall charger example in the previous section is an example of a DCP.
Accessory Charger Adapter (ACA)
With portable devices becoming smaller to be more attractive and convenient to users, the number of ports available to the user becomes limited. On any given PD, you will generally find a single USB port in which you can connect a charger to charge the device or connect a USB device like a mouse or keyboard. Herein lies the problem of how to use a USB port for connecting a USB keyboard when the device requires charging.
Accessory Charging Adapter (ACA) is aimed at addressing this problem by expanding a single USB port to be attached to a charger and a USB device at the same time, as shown in Figure 1. Figure A-5.
The dock examples discussed earlier in the first section of this appendix belong to this class of device, and it supports the following three ports:
- OTG port: This port allows users to dock the device with a Micro AB receptacle.
- Accessory port: This port allows users to connect any device to the PD.
- Charger port: This port allows users to connect a charger that can power up the PD and the accessory device.
An ACA is classified into two types, based on the features it supports. If an accessory port of an ACA has a Mirco-AB receptacle, allowing connection of A and B devices, it is referred to as Micro ACA. When the accessory port has only a Standard-A receptacle, which allows connection of a B device, the ACA device is referred to as a Standard ACA. Figure 1 shows is a typical standard ACA setup.
The USB battery-charging specification also talks about handling dead batteries, along with mechanisms to differentiate charging ports, and you can refer to the specification for more details. .
Android Battery Charging Overview
Android’s USB battery charging requirement is very straightforward. According to Android CDD 4.2, the Android platform’s USB charging requirement is as follows:
“It SHOULD implement support for USB battery charging specification. Existing and new devices that run Android 4.2 are very strongly encouraged to meet these requirements in Android 4.2 so they will be able to upgrade to the future platform releases.”
A device that claims to be compatible with Android CDD 4.2 supports all modes of USB charging, as explained in the previous section. Inside the Android platform, most of the charging-related activities like detecting the charger type and managing the battery, are done by the hardware and the Android Linux kernel. The Android kernel shares information related to battery charging using system file entries in the user space. The user space Android framework presents the user details of the hardware and kernel changes related to charging by reading the information exported by the kernel. This is managed by the following two blocks of the Android Battery framework:
Battery Manager This framework is implemented through the frameworks/ base/core/java/android/os/BatteryManager.java file and acts as an interface between an application and the Battery Service framework. The BatteryManager class defines the constants for applications to extract information from the ACTION_BATTERY_CHANGED intent, which is generated by the Battery Service.
The Battery Service framework is the core part of the Android Battery framework. The Battery Service framework is responsible for generating battery state-related intents and broadcasting them to other Android frameworks. Internally, the battery service is divided into a class and a JNI implementation. The battery service java class is implemented in
and the JNI part is implemented through
The role of the JNI part is to read appropriate battery driver-related files exported by the Android kernel and pass them to the java class over global variables. The java class in turn interprets the values and generates the appropriate intents related to the battery state. It will shut down the device when the battery is critically low.
Before getting into the details of the Android USB Battery Charging framework, it’s important you understand what kind of information the Android kernel exports that is related to battery charging in the user space. The following snippet lists files and folders under /sys/class/power_supply using the ADB shell of a Samsung Grand mobile:
shell@android:/sys/class/power_supply $ ls
shell@android:/sys/class/power_supply/battery $ ls
Few of the file entries listed here are specific to the vendor, and this section focuses only on the entries that the Android framework uses. Internally, the Android framework reads these files using a JNI implementation
(frameworks/base/services/jni/com_android_server_BatteryService.cpp) and stores them internally for sharing with other applications. In the following section, you’ll explore how a Battery Manager and Battery Service, as represented in Figure 2, generate battery charging-related intents. Android Battery Charger framework uses the following intent.actions intents to pass on the status of battery charging.
This intent is generated to indicate that some of the battery-related information has changed and any interested receiver has to recalculate. The intent bundles the following extra data for the receiver, which can be used to develop advanced battery applications:
STATUS - The status field holds one of the following values:
- BATTERY_STATUS_UNKNOWN = 1;
- BATTERY_STATUS_CHARGING = 2;
- BATTERY_STATUS_DISCHARGING = 3;
- BATTERY_STATUS_NOT_CHARGING = 4;
- BATTERY_STATUS_FULL = 5;
HEALTH - The health field holds one of the following values:
- BATTERY_HEALTH_UNKNOWN = 1;
- BATTERY_HEALTH_GOOD = 2;
- BATTERY_HEALTH_OVERHEAT = 3;
- BATTERY_HEALTH_DEAD = 4;
- BATTERY_HEALTH_OVER_VOLTAGE = 5;
- BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6;
- BATTERY_HEALTH_COLD = 7;
PRESENT – The present field indicates the presence of the battery. LEVEL – The level field indicates current battery level.
SCALE – The scale field indicates the maximum battery level,indicated as BATTERY_SCALE = 100 in BatteryService.java.
ICON_SMALL – The icon field hold the resource id of the battery icon
based on the current battery status retreived by getIconLocked in BatteryService.java
PLUGGED – The plugged field indicates the type of power source and the value could be one of the following:
/** Power source is an AC charger. */
- BATTERY_PLUGGED_AC = 1;
/** Power source is a USB port. */
- BATTERY_PLUGGED_USB = 2;
/** Power source is wireless. */
- BATTERY_PLUGGED_WIRELESS = 4;
VOLTAGE – The voltage field indicates current battery voltage in Millivolts.
TEMPERATURE - The temperature field indicates current battery temperature in tenths of a degree Centigrade.
TECHNOLOGY – The technology field specifices the technology that battery is made of.
INVALID_CHARGER – When the charge is unsupported, the charger variable is set to non-zero numeral.
An important point to note about this intent is a protected intent can be sent only by the system. This intent cannot be received through manifest declarations and has to be explicitly registered.
This intent is generated by the Android Battery framework to indicate that the device has reached a low battery level. This intent can be sent only by the system and is a protected intent.
This intent is generated by the Android Battery framework to indicate that the device has recovered from a low battery level and is now OK. This intent can be sent only by the system and is a protected intent.
This intent is generated by the Android Battery framework when an external power source is connected to the system. Any application registered for this intent will be woken up and this protected intent can be sent only by the system.
This intent is generated by the Android Battery framework when an external power source is disconnected from the system. Any application registered for this intent will be woken up, and this protected intent can be sent only by the system.