[MUSIC PLAYING]
Hi.
My name's Reto Meier, and I'm the tech lead for Google's
Android Developer Relations team.
This is the first of a series of DevBytes created to help
you improve the battery efficiency of your apps by
changing the way you handle your data transfers.
The mobile cell radio is one of the biggest sources of
battery drain on modern smartphones, so making sure
transfers use it efficiently can make a dramatic difference
to your app's impact on the battery life.
Now on the surface, this seems like a
pretty simple challenge.
If the cell radio drains the battery, just transfer as
little data as possible, as infrequently as possible.
Now that's a good start, but we want to balance that with
providing a great user experience, one where the data
your users need is available as soon as they need it
without them ever needing to hit refresh.
Now that requires understanding how to optimize
the timing of your data transfers, and that means
understanding the cell state machine.
In order to conserve power, the cell radio isn't kept on
permanently.
In fact, it goes through a series of state transitions in
order to compromise between low-latency data transfers and
minimizing the impact on battery life.
It begins over here on standby mode, where it's storing
minimal power until an app initiates a data transfer.
At this point, it transitions to full-power mode, a process
that takes around two seconds, before
performing the transfer.
Rather than dropping back to standby immediately after the
transfer is completed, the radio will remain in full
power mode for a set tail time, just in case further
transfers are initiated within that window.
This happens because dropping to a low-power state
reintroduces this power-up latency.
Not only that, but transitioning between states,
in and of itself, is a significant power drain.
If nothing happens during the 5 to 10 second tail time, the
radio drops to this intermediate low-power state
that uses less battery than full power, but has a lower
startup latency than standby.
If a new transfer is initiated, it will be promoted
back to full-power mode.
And if nothing happens for another 30 seconds to a
minute, it'll drop back to standby.
The exact latencies and tail times vary between carriers,
or even within carriers depending on where they are as
carriers try to balance low latency with longer battery
life based on things like cell congestion and typical
prevailing network conditions.
To understand how this might affect your app design
choices, you start with this simple equation, then take the
square root of the sum of the latency and idle times between
each state, and then throw all of that out.
Because it really doesn't require any math to do.
And it doesn't even matter what the specific latency or
tail times are for any users of your app.
The solution comes down to what I like to call the Cookie
Droid Conundrum.
When scheduling downloads, do you transfer as much as you
can as infrequently as possible, minimizing the
number of transfers at the expense of bandwidth?
Or do you take the opposite approach, transferring as
little as possible, performing transfers more frequently?
Well, on the surface, the "Little Cookie"
model appears sound.
Less data transferred means less bandwidth and less time
spent with the radio active to transfer our data.
And because we're downloading what we need on demand, we
never download and process more than we need.
Unfortunately, this results in a heavily fragmented use of
the cell radio.
From our knowledge of the cell radio state machine, we know
that every time we perform a data transfer, the radio stays
active for at least 5 seconds of tail time at full power,
followed by anywhere from 10 to 60 seconds at lower power
before it finally returns to standby.
That means every time you initiate a transfer, you're
powering the cell radio up for at least 20 seconds.
Now we look at this more closely, you can see how an
app like this one, whose radio use is indicated here, can
drain the battery without transferring very much data.
Each of these small peaks represents something like
analytics data being sent back to the server every 15
seconds, while the larger peaks, they represent
intermittent transfers based on user interaction, maybe
clicking on a news article or looking at
a restaurant listing.
Now beneath that, we can see how this affects the radio
state machine, with blue showing active transfer times,
the rate indicating the radio remaining in full power mode,
yellow, showing lower power mode, and the gaps between,
showing us where the radio is idle.
Now we can see straight away that there are no gaps,
meaning that while this app is running, it's keeping the cell
radio powered on continuously.
In fact, the regular updates alone are enough to prevent
the radio from ever returning to an idle state.
That shows us that the "Big Cookie" model is a far better
approach to coordinating our data transfers.
In this example, I've bundled all of the
repeating transfers together.
And the intermittent transfers have been largely replaced
with aggressive prefetching.
Obviously, you usually can't entirely predict what data
users might need, nor can you ignore either client or server
side changes that need to be synchronized.
But you can aim to minimize the number of radio state
transitions through a combination of aggressive
prefetching, in addition to batching and queuing any
transfers that aren't time critical and bundling these
with user-initiated time-critical transfers, or
those initiated from the server.
The result is a significant improvement in the amount of
battery drain your app is responsible for.
In comparison to the previous on-demand approach, the radio
is now idle nearly 2/3 of the time.
Even the active radio percentage has dropped
significantly, thanks to an improved download efficiency
as a result of transmitting more data in each shot.
So taking the cell radio into account, you can minimize the
battery impact associated with your app's data transfers by
transferring as little data as possible as
infrequently as possible.
Defragment your network access by prefetching, batching, and
bundling your transfers, and eliminate clients initiated
updates and polling as much as possible.
The most important thing to remember is that every time
you transfer data, no matter how small, the radio is
powered up for nearly half a minute.
So every decision you make should be based on minimizing
the number of times that this happens.
I dive into each of these topics in more detail in other
videos in the Efficient Data Transfer series of DevBytes,
including looking at ways you can analyze your own data
transfer profile, and how to implement some of these best
practices using simple code patterns, as well as
implementing SyncAdapters and Google
Cloud Messaging solutions.