Background on power consumption

Key battery metrics:

  • Battery capacity.
  • Charging time.
  • Life. Over time, battery capacity decreases. According to Apple, for example, the iPhone battery has 80% of its remaining capacity after 500 cycles.
  • Security. Samsung Note 7 explodes.

Power module

Electric energy = voltage * current * time

The power_profiler.xml file defines the current consumption of different modules and the estimated current consumption of that module over a period of time. You can refer to the Official Document Android Power Profile. The size of the current is also related to the current module state.

The screen

Adb shell dumpsys batterystats > battery. TXT // Total power consumption of each Uid, and this is a rough power calculation estimate. Estimated power use (mAh): Capacity: 3450, Computed drain: 501, actual drain: 552-587 ... Idle: 41.8 Uid 0: 135 (CPU =103 wake=31.5 wifi=0.346) Uid U0a208: 17.8 (CPU =17.7 wake=0.00460 wifi=0.0901) Uid U0A65:17.5 (CPU =12.7 wake=4.11 wifi=0.436 GPS =0.309)... Adb shell Dumpsys batteryStats --resetCopy the code

BatteryStatsService is an external electricity statistics service. The specific implementation logic is described in BatteryStatsImpl. BatteryStatsImpl uses the PowerProfile internally, creating a UID instance for each application to monitor application resource usage.

Optimization case: “Dianping App short video Power Consumption Optimization actual combat”.

Bug reports and Battery historians are the best ways to report power consumption problems.

$adb bugreport bugreport.zip $adb bugreport bugreport.zip $adb bugreport bugreport.zip $adb bugreport bugreport.zip $adb bugreport > bugreport. TXT-a bugreport.txt > battery.html
Copy the code

Android makes efforts to optimize battery life every year. There are several stages in the development of Android:

  • Savage Growth: Pre Android 5.0.
  • Gradually tighten: Android 5.0~8.0. 5.0 Specifically open a Volta program to improve battery life.
  • Most restrictive: Android 9.0. From 9.0 onwards, power management introduced stricter restrictions.

Optimize the power consumption

Priority of power consumption optimization:

  • Optimize the background power consumption of the application to meet the psychological expectations of users.

  • Comply with the system rules, let the system think your power consumption is normal, avoid the pop-up “high power consumption warning”.

Difficulties in power consumption optimization:

  • It’s impossible to reproduce without a scene.
  • Incomplete information, difficult to locate. Statistics cannot locate the stack, and cannot directly locate the specific cause.
  • The results cannot be evaluated.

Main causes of power consumption:

  • Demand-oriented, live. For example, push and background tasks.
  • Bugs in code. GPS is not turned off, WakeLock is not released.

Starting from the main problems, sorting out and optimizing ideas:

  • Find alternatives to requirements scenarios. Use vendor channel, foreground Service, or guide user whitelist. The idea of background task optimization is: reduction, delay, and merge. Reference: Android background Scheduling tasks and Power Saving.
  • Comply with Android rules. Refer to wechat’s “Monitoring battery Power and Charging Status”.
  • Abnormal situation monitoring. The system will allow some compliance with the background logic, refer to: Android P power management, power management.

Android Vitals actually doesn’t work on New Year’s day.

Reference:

Alarm Manager Wakeup Too many wakes

Frequent use of local wakeup locks

The background network usage is too high

Background WiFi scans are too many

Huawei power consumption red line

Methods for monitoring power consumption:

  • Java Hook. Mainly monitor WeakLock and Alarm, as well as some background hardware usage.

// Proxy PowerManagerService ProxyHook().proxyhook (context.getSystemService(context.power_service),"mService", this); @override public void beforeInvoke(Method Method, Object[] args) {// Apply for Wakelockif (method.getName().equals("acquireWakeLock")) {
        if(isAppBackground()) {// Apply background logic, get application stack, etc.}else{// Apply foreground logic, get application stack, etc.} // Release Wakelock}else if (method.getName().equals("releaseWakeLock") {// Free logic}}Copy the code

// Proxy AlarmManagerService new ProxyHook().proxyhook (context.getSystemService (context.alarm_service),"mService", this);

public void beforeInvoke(Method method, Object[] args) {
    // 设置 Alarm
    if (method.getName().equals("set") {// Different versions of the argument type adaptation, get application stack, etc. // clear Alarm}else if (method.getName().equals("remove") {// Clear logic}}Copy the code

  • Pile. After solving Android P, many Hook means do not support the problem. Take a look at Battery-Metrics, Facebook’s open source library for monitoring power consumption

Public class WakelockMetrics {// Wakelock request public void acquire(PowerManager.wakelock Wakelock) {wakelock.acquire (); Public void release(powerManager.wakelock Wakelock, int flags) { wakelock.release(); // Add Wakelock release monitoring logic here}}Copy the code

steps

implementation

Hook

Realize IAlarmManagerHook, IPowerManagerHook, ILocationManagerHook these three agents, respectively realize AlarmManager, PowerManager, LocationManager monitoring.

Public class BatteryHookManager {/** * Initializes * @param context */ public void initHook(context context){// Initializes the log BatteryLogUtil.init(context); // Initialize Hook new IAlarmManagerHook(context).oninstall (); new IPowerManagerHook(context).onInstall(); new ILocationManagerHook(context).onInstall(); } privateBatteryHookManager(){}
    private static class BatteryHookManagerHolder{
        private static final BatteryHookManager INSTANCE= new BatteryHookManager();
    }

    public static BatteryHookManager getImp() {returnBatteryHookManagerHolder.INSTANCE; }}Copy the code

Initialize BatteryHook in the project’s application

public class BatteryApplication extends Application {

    @Override
    public void onCreate() { super.onCreate(); BatteryHookManager.getImp().initHook(this); }}Copy the code

Detect power consumption caused by incorrect UI drawing refresh

Exclude excessive CPU usage due to incorrect drawing method, which leads to high power consumption

The detection method refers to the power consumption optimization combat of short video on DIANping App

First turn on the developer option, turn on the GPU view update switch, and then see if there are any unnecessary UI refreshes in the app,

Scenario 1 (Custom TextView)

Home page quick team page, view more in the list has been refreshing, directly look at the code,

There’s a custom View, so let’s go ahead and look at the code for TextViewWideContent

SetPadding () is called inside onDraw().

As you can see, the page invalidate() is called, which causes the onDraw() method to be called in a loop, so the page keeps refreshing. The conclusion is that in the onDraw() method of the custom View, calling setPadding() will cause the page to repeat. The solution is also easy to put setPadding inside onLayout().

Scenario 2 (CoordinatorLayout+AppBarLayout error dependency)

In the CoordinatorLayout+AppBarLayout page structure, the bottom is incorrectly dependent on the head control, causing the bottom to refresh all the time, remove app:layout_anchor=” @ID /user_appbar_layout” and it is fine.

Android battery optimization related suggestions

(1) In the program that needs network connection, first check whether the network connection is normal, if there is no network connection, then there is no need to execute the corresponding program;

② Determine the network type and request specific data in a specific network. For example: a large amount of data transmission in the wifi request; Wifi downloads consume only a third of the power of 2, 3 and 4 gigabytes.

3) Use efficient data formats and parsing methods, JSON and Protobuf are recommended;

④ When downloading large amounts of data, try to use GZIP download mode;

⑤ Use push instead of circular requests

6. Other:

Try not to use floating point arithmetic;

To reclaim Java objects, especially large Java objects, use the reset method.

Actively recycle Java objects, especially large ones such as Bitmaps. Reduce the operating frequency of GC;

Avoid memory jitter, because a large number of objects are created and released in a short time.

Avoid creating objects in for loops, onDraw methods; It is unavoidable to create object pools and release them when they are not in use;

If the positioning requirements are not too high, try not to use GPS positioning, you can use wifi and mobile network cell positioning;

Information such as screen size can be retrieved using caching techniques without requiring multiple requests;

AlarmManager is used to start the scheduled service instead of the scheduled task in sleep mode.