Our previous blog on the battery-draining tests of three popular music apps Pandora, Spotify, and Google Play Music showed that the Google Play Music app is more energy-efficient and battery-friendly than competing apps, in streaming music from the Internet.
Readers in Reddit asked what about the energy drain when playing Music stored locally on the device, a feature supported by several apps such as Google Play Music. Such a feature allows users to enjoy listening to preloaded music when there is no network connection, or play prepaid albums.
On the contrary, our testing results (shown in Figure 1) shows that playing music from local actually drains slightly more battery than streaming music from the Internet, for Google Play Music 6.1! The battery-drain test was the same as before (see sidebar for methodology).
Solving the mystery using Eprof
To understand why playing local music drains unexpectedly high energy, we used the Eprof source-code-level energy diagnostic tool. Eprof accurately breaks down the total energy drain of an app run at the source-code-level, e.g., by each app method.
The app energy breakdown by component output of Eprof (Figure 2) shows that while playing music from local indeed incurs no network energy, the app process incurs 56% higher CPU energy than streaming music from the Internet (in light blue).
To find the root causes for the high CPU energy in playing local music, we next looked at the method-level energy breakdown of Eprof. Table 1 shows the top 10 (inclusive) energy draining methods during 1-minute local music playing in Google Play Music output by Eprof. We see that at top of the list are standard Android framework methods of class android.os.Handler and android.view.Choreographer, which perform generic message and callback handling for the app and will always be the top methods for most Android apps. What is interesting is that there are 3 methods of class android.graphics.drawable.AnimationDrawable among the top 10 (in blue), which indicates that the app spends a major chunk of energy in rendering animations.
However, there is no visible animation in the music player view we profiled, shown in the app screenshot in Figure 3(a). In fact, the only animations during music playing are the playing indicators in the album screen and play queue screen, circled in Figure 3(b) and 3(c). All three screens belong to the same activity and users can navigate between them with 1 or 2 clicks. Our observations suggest that Google Play Music spends a major chunk of the CPU energy on rendering animations that are invisible to users, which could be an “invisible animation UI energy bug”.
The impact of the energy bug
By hacking the app apk, we confirmed the energy bug is due to the app failing to consider the visibility of the play indicator animations, which results in a considerable amount of energy spent on animations that are invisible to users.
To confirm the bug’s impact on energy drain, we removed it by making the following 2 changes to the app:
- Adding code to check whether the play indicator is visible to user before starting its animation;
- Adding visibility change callback (i.e. onVisibilityChanged()) in the play indicator to handle its visibility change, i.e. start, stop its animation when it becomes visible, invisible, respectively.
We then repeated the battery drain test as before. The fix reduced the CPU energy of the Google Play Music process by 4.3X (Figure 2 in blue), and the total app energy drain by 15% (Figure 1).
Interestingly, after we learned the intricacies of the invisible animation energy bug in playing local music, we went back to the online streaming playing mode, and found the bug also exists in Google Play Music when streaming music from the Internet. The impact on energy drain is less, since there is only one invisible animation in play queue screen, as opposed to multiple invisible animation in both play queue screen and album screen when playing local music.
We have reported this issue to Google Play Music team.
Do you have an app?