Background on power consumption

  1. Battery technology: battery capacity, charging time, life, safety;
  2. Power and hardware: Applications do not consume the battery directly, but use the corresponding power through the use of hardware modules; Cpus, screens, WiFi and data networks, GPS, and audio and video calls are all our daily power hogs.
  3. Power and application: Power = voltage * current * time, mobile phone voltage generally does not change, so module power (mAh) = module current (mA) * module time (h);
    • How should the module current be obtained? Android system require different vendors must/frameworks/base/core/res/res/XML/power_profile. The power of the provide components in the XML configuration file.
    • The Android PowerProfile is calculated by reading the value of power_profile.xml.
    (1) Different vendors have different specific values, which can be obtained by the following methods: 1. Derived from mobile phone/system/framework/framework - res. The apk. 2. Use a decompile tool, such as apkTool, to decompile framework-res.apk. 3. View the power_profile. XML file in /res/ XML /power_profile. XML directory of the Framework -res decompile directory. Adb shell Dumpsys batteryStats > battery.txt // The total power consumption of each Uid, and it 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) 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 --reset (3). Bug reports combined with Battery Historian are the best way to do this when testing or other people are reporting electricity usage problems. // $adb bugreport bugreport.zip // $adb bugreport $adb bugreport > bugreport.txt // Graphically display results through historian python valid. Py -a bugreport.txt > batteryCopy the code

The evolution of Android power consumption

  1. Wild Growth: Pre Android 5.0
    • Before Android 5.0, the system is not so perfect, for the power optimization is relatively less. In particular, there were no strict restrictions on the backend of the application, and multiple processes, fork Native processes, and broadcast pull became popular.
  2. Gradual tightening: Android 5.0 to Android 8.0
    • Android 5.0 kicked off a project called Volta, which aims to improve battery life. In addition to optimizing power, tools such as Dumpsys Batteryst have been added to generate device battery usage statistics.

    (5.0: Volta project, JobScheduler dumpsys batterystats, BatteryHistorian, repair process to protect native fork live bugs)

    • Starting with Android 6.0, Google started cleaning up background apps and broadcasts to further optimize power savings.

    (6.0: power saving function, Doze low power consumption mode, AppStandby application standby mode) (7.0: power saving function, Doze enhanced version, Implicit compilation limit, mixed compilation) (8.0: more power saving function, background execution limit, background position limit)

  3. Most restrictive: Android 9.0
    • Starting with Android 9.0, Google introduced several tighter restrictions on power management.

    (9.0: Application standby group AppStandbyBueckets, application background restriction, power saving mode BatterySaver)

Optimize the power consumption

What is power consumption optimization

  • Isn’t power optimization about reducing your app’s power consumption and increasing your battery life?
  • But in practice, if our app needs to play videos, get GPS information, and take pictures, it seems inevitable.

What aspects to optimize

1. Background power consumption:
  • Users have expectations for the power consumption of frequently used applications, but it is easy to attract attention if an uncommon application consumes a lot of power. Therefore, the first direction of power optimization is to optimize the power consumption of applications in the background. For example, long time access to WakeLock, WiFi and Bluetooth scanning.
2. Comply with the rules of the system
  • Android P monitors power consumption in the background through Android Vitals, so we need to comply with the rules of Android Vitals
Background Alarm Wakeup, background network, background WiFi scanning, and some long-term WakeLock prevent the system from background hibernation: 1. Alarm Manager Wakeup excessive: When the phone is not charged, the number of wakeups is more than 10 per hour; 2. 2. Frequent use of partial wake lock: When the phone is not charged, the partial wake lock will be held for 1 hour timeout; 3. Excessive background network usage: When the phone is not charged and the application is in the background, the network usage per hour exceeds 50MB; 4. Background wifi scans are excessive: when the mobile phone is not charging and is applied in the background, more than 4 times per hour;Copy the code
Some problems of power consumption optimization
  1. Lack of scene, can not be reproduced;
  2. Incomplete information, difficult to locate;
  3. Unable to assess the results;
Why do you need power in the background
  1. A requirement scenario. The most common scenario is push, in order to achieve push we can only do all kinds of protection. In front of demand, the value of the user may be second.
  2. A Bug in the code. The GPS may not be turned off and the WakeLock may not be released due to some ill-considered logic.

Power consumption optimization method

  1. Find alternatives to requirements scenarios, and the general guideline for background tasks is to reduce, delay, and merge
    • Push:
      1. Manufacturer channel;
      2. Pull the latest news regularly;
      3. Foreground service or guide the user to add to the whitelist;
    • To run in the background:
      1. Long downloads: DownloadManager
      2. Data synchronization: SyncAdapter(package all tasks to be synchronized in one cycle as much as possible)
      3. Local task: JobScheduler(minApi21,Google official recommendation network request related services to JobScheduler)
      /** * Enable JobScheduler */ private void startJobScheduler() {if (build.version.sdk_int >= build.version_codes.lollipop) {  JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); JobInfo.Builder builder = new JobInfo.Builder(1, new ComponentName(getPackageName(), JobSchedulerService.class.getName())); / / set only charging and WIFI for batch task processing using JobScheduler builder. SetRequiresCharging (true) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); jobScheduler.schedule(builder.build()); /** * JobSchedulerService */ @requiresAPI (API =); /** * JobSchedulerService */ @requiresAPI (API = Build.VERSION_CODES.LOLLIPOP) public class JobSchedulerService extends JobService { @Override public boolean OnStartJob (JobParameters params) {// Execute on main thread // Simulate some processing: batch network request, APM log report return false; } @Override public boolean onStopJob(JobParameters params) { return false; }}Copy the code
      1. Specific execution time: AlarmManager (holding a Wake Lock, time interval | repetitive tasks, using network request is not recommended)
      2. Real-time communication: FCM, MiPush
      3. Execute immediately: foreground service
  2. Follow Android rules
    • Most of the power consumption monitoring system is not charged, so we can do some power consumption work when charging;
    IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); Intent batteryStatus = context.registerReceiver(null, ifilter); / / get the user is in the state of charge or have charged int status = batteryStatus. GetIntExtra (BatteryManager EXTRA_STATUS, - 1); boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL;Copy the code
    • Adapt the latest TargetAPI as soon as possible. The higher the version, the more restrictive the system will be.
  3. Abnormal condition monitoring
    • Monitor anomalies and report logs to locate online faults.

Power monitoring

  • Specify your own rules like Android Vitals;
Use Java Hook to realize power consumption monitoring:
  1. WakeLock is used to prevent CPU, screen, and even keyboard sleep. For example, Alarm and JobService also apply for WakeLock to perform background CPU operations.
//WakeLock's core control code is in PowerManagerService. // Agent PowerManagerService ProxyHook().proxyHook(context.getSystemService(context.power_service), "mService", this); @Override public void beforeInvoke(Method method, Object[] args) {// Apply for Wakelock if (method.getName().equals("acquireWakeLock")) {if (isAppBackground()); } else {// Application foreground logic, } else if (method.getName().equals("releaseWakeLock")) {else if (method.getName().equals("releaseWakeLock")) {Copy the code
  1. Alarm is used to do scheduled repetitive tasks. There are four types of Alarm. The ELAPSED_REALTIME_WAKEUP and RTC_WAKEUP types both wake up the device.
// AlarmManagerService new ProxyHook().proxyHook(context.getSystemService (Context. ALARM_SERVICE), "mService", this); public void beforeInvoke(Method method, Object[] args) {// Set Alarm if (method.getName().equals("set")) { Else if (method.getName().equals("remove")) {else if (method.getName().equals("remove")) {Copy the code
  1. other
    • For the background CPU, we can use the method learned by catton monitoring.
    • For the background network, we can also learn the method through network monitoring.
    • For GPS monitoring, we can proxy LOCATION_SERVICE via Hook.
    • For sensors, we can get some information through “mSensorListeners” in Hook SENSOR_SERVICE.
  2. With hooks, we can save the stack information when the resource is requested. When we trigger a rule to report a problem, we can use the collected stack information,

The auxiliary information, such as whether the battery is charged, CPU information, and the time before and after the application, is also brought.

Power consumption monitoring is realized through pile insertion
  • While using hooks is very simple, some rules can be difficult to find suitable Hook points. And after Android P, many Hook points are not supported.
  • WakeLock, for example
Public class WakelockMetrics {// Wakelock acquire(powermanager.wakelock) {Wakelock.acquire(); Public void release(powerManager.wakelock Wakelock, powerManager.wakelock, powerManager.wakelock, powerManager.wakelock, powerManager.wakelock, powerManager.wakelock, powerManager.wakelock, powerManager.wakelock, powerManager.wakelock, powerManager.wakelock int flags) { wakelock.release(); }}}}}}}}}Copy the code
  • Facebook also has an open source Battery Metrics library that monitors power consumption
  • Practice after class github.com/AndroidAdva…

Electric quantity detection Scheme

  1. Settings – Power consumption ranking: intuitive, but without detailed data, not much help to solve the problem
  2. Use broadcast to listen for power changes – ACTION_BATTERY_CHANGED: Little value: for the overall power consumption of the phone, not a single App
  3. Dumpsys batterystats: ADB shell Dumpsys batteryStats > battery.txt
  4. ‘Historian:github.com/google/batt…

Gradle power consumption statistics in a plug-in BatteryCreateMethodVisitor core implementation code

@Override public void visitMethodInsn(int opcode, String owner, String name, String descriptor, Boolean isInterface) {// Monitor Wakelock String monitorClass = "com/ss/android/ugc/bytex/example/battery_monitor/WakelockMetrics"; if (! monitorClass.equals(className) && "android/os/PowerManager$WakeLock".equals(owner) && opcode == Opcodes.INVOKEVIRTUAL &&  "acquire".equals(name)) { mv.visitMethodInsn( Opcodes.INVOKESTATIC, monitorClass, name, "(Landroid/os/PowerManager$WakeLock; J)V", isInterface ); return; } if (! monitorClass.equals(className) && "android/os/PowerManager$WakeLock".equals(owner) && opcode == Opcodes.INVOKEVIRTUAL &&  "release".equals(name)) { mv.visitMethodInsn( Opcodes.INVOKESTATIC, monitorClass, name, "(Landroid/os/PowerManager$WakeLock;) V", isInterface ); return; } / / monitor Gps monitorClass = "com/ss/android/ugc/bytex/example/battery_monitor/GpsMetrics"; if (! monitorClass.equals(className) && "android/location/LocationManager".equals(owner) && opcode == Opcodes.INVOKEVIRTUAL &&  "requestLocationUpdates".equals(name)) { mv.visitMethodInsn( Opcodes.INVOKESTATIC, monitorClass, name, "(Landroid/location/LocationManager; Ljava/lang/String; JFLandroid/location/LocationListener;) V", isInterface ); return; } if (! monitorClass.equals(className) && "android/location/LocationManager".equals(owner) && opcode == Opcodes.INVOKEVIRTUAL &&  "removeUpdates".equals(name)) { mv.visitMethodInsn( Opcodes.INVOKESTATIC, monitorClass, name, "(Landroid/location/LocationManager; Landroid/location/LocationListener;) V", isInterface ); return; } / / monitor Alarm Service monitorClass = "com/ss/android/ugc/bytex/example/battery_monitor/AlarmMetrics"; if (! monitorClass.equals(className) && "android/app/AlarmManager".equals(owner) && opcode == Opcodes.INVOKEVIRTUAL && "set".equals(name)) { mv.visitMethodInsn( Opcodes.INVOKESTATIC, monitorClass, name, "(Landroid/app/AlarmManager; IJLandroid/app/PendingIntent;) V", isInterface ); return; } if (! monitorClass.equals(className) && "android/app/AlarmManager".equals(owner) && opcode == Opcodes.INVOKEVIRTUAL && "cancel".equals(name)) { mv.visitMethodInsn( Opcodes.INVOKESTATIC, monitorClass, name, "(Landroid/app/AlarmManager; Landroid/app/PendingIntent;) V", isInterface ); return; } super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); }Copy the code

Refer to the article

  • Power consumption Optimization (1) : Power consumption analysis from the evolution of power optimization
  • Power consumption optimization (2) : Power consumption optimization method and online monitoring
  • Dianping App’s short video power consumption optimization combat
  • Android Vitals
  • Battery Historian
  • Android background scheduling tasks and power saving
  • Android P power management
  • Power Management Limitations
  • An in-depth look at Android power optimization

I am Jinyang, if you want to advance and learn more about dry goods, welcome to follow the wechat public account “jinyang said” to receive my latest articles