Michael Chinigo
Michael Chinigo

Reputation: 81

Detailed battery usage - iOS

My current project is a constant-presence application (think Tinder or Foursquare), and the battery consumption is through the roof. We think the main draw on power are the GPS and WiFi antennas. We'd like to be able to measure our app's energy usage under several different configurations.

But how to do this? We want a process that:

Quite the list, I know.

Those are the requirements, and here are the options that I'm aware of:

1. Turning on untethered Energy Diagnostics Logging on an iOS device, and exporting to Instruments

This is the obvious answer, but it has one gigantic flaw.

Pros:

Cons:

2. Monitoring a plugged-in phone through Instruments

Pros:

Cons:

3. Using public Cocoa APIs to record energy usage in our app – [UIDevice.currentDevice batteryLevel]

This is the most common answer on SO. I've looked at Estimated battery time on iOS, iphone: Calculating battery life and about a dozen others.

Pros:

Cons:

4. Using private Cocoa APIs to record energy usage

As we'll only ever be doing this during development, it doesn't matter if Apple would reject the app for using a private API. Presumably there's some private API for this, as Apple is able to record the data with Untethered Energy Diagnostics turned on.

Pros:

Cons:

5. Combined approach

We could use the untethered diagnostics to quantify the marginal energy cost for each action. "Ok, spinning up the GPS antenna takes 150mW•H. Calculating position takes 50mW•H. Sending a Mixpanel event takes 25mW•H, unless we made another network call within the previous 30sec, in which case it takes 15mW•H." (all numbers invented on the spot.) Then we can use the tethered monitoring to record when each of those actions takes place, plug into a linear equation, and estimate the amount of energy it should have taken.

Pros:

Cons:

Anyhow, I've blathered enough. Has anybody done this before? How?

Upvotes: 7

Views: 4146

Answers (3)

ldoogy
ldoogy

Reputation: 2869

Not sure if this is applicable to this exact use-case, but I've developed a library called UIDeviceListener that allows you to easily (basically with one line of code), retrieve data from the operating system regarding power consumption and many other battery/charging related data points: https://github.com/eldoogy/PowerData

Here is a sample dictionary to give you an idea of the kind of information you can get. I will point your attention to the InstantAmperage key. This shows real-time power consumption in mA for the entire device (while the device is unplugged). That might help accomplish what you're looking for here.

{
AdapterDetails =     {
    Amperage = 1000;
    Description = "usb host";
    FamilyCode = "-536854528";
    PMUConfiguration = 1000;
    Watts = 5;
};
AdapterInfo = 16384;
Amperage = 1000;
AppleRawCurrentCapacity = 1279;
AppleRawMaxCapacity = 1275;
AtCriticalLevel = 0;
AtWarnLevel = 0;
BatteryData =     {
    BatterySerialNumber = REDACTED;
    ChemID = 355;
    CycleCount = 524;
    DesignCapacity = 1420;
    Flags = 640;
    FullAvailableCapacity = 1325;
    ManufactureDate = REDACTED;
    MaxCapacity = 1273;
    MfgData = REDACTED;
    QmaxCell0 = 1350;
    StateOfCharge = 100;
    Voltage = 4194;
};
BatteryInstalled = 1;
BatteryKey = "0003-default";
BootBBCapacity = 52;
BootCapacityEstimate = 2;
BootVoltage = 3518;
CFBundleIdentifier = "com.apple.driver.AppleD1815PMU";
ChargerConfiguration = 990;
CurrentCapacity = 1275;
CycleCount = 524;
DesignCapacity = 1420;
ExternalChargeCapable = 1;
ExternalConnected = 1;
FullyCharged = 1;
IOClass = AppleD1815PMUPowerSource;
IOFunctionParent64000000 = <>;
IOGeneralInterest = "IOCommand is not serializable";
IOInterruptControllers =     (
    IOInterruptController34000000,
    IOInterruptController34000000,
    IOInterruptController34000000,
    IOInterruptController34000000
);
IOInterruptSpecifiers =     (
    <03000000>,
    <26000000>,
    <04000000>,
    <24000000>
);
IOMatchCategory = AppleD1815PMUPowerSource;
IOPowerManagement =     {
    CurrentPowerState = 2;
    DevicePowerState = 2;
    MaxPowerState = 2;
};
IOProbeScore = 0;
IOProviderClass = AppleD1815PMU;
InstantAmperage = 0;
IsCharging = 0;
Location = 0;
Manufacturer = A;
MaxCapacity = 1275;
Model = "0003-A";
Serial = REDACTED;
Temperature = 2590;
TimeRemaining = 0;
UpdateTime = 1461830702;
Voltage = 4182;
"battery-data" =     {
    "0003-default" = <...>;
    "0004-default" = <...>;
    "0005-default" = <...};
"built-in" = 1;
}

UIDeviceListener supports regular, non jailbroken iOS devices and does not invoke any private APIs.

Upvotes: 3

AlexWien
AlexWien

Reputation: 28767

GPS needs 10% battery per hour, so will last about 10h of high precise location recording once a second. location polling intervall has nothing to do with battery consumption. either the GPS chip is enabled or not. There is no low power gps mode!! you can disable gps if you know that the user does not need it.

for permanent recording of location data, you can only save battery if you decide to go with low accuarcy ( 1000m cell tower or wlan locationing) instead of high (3-6m = GPS)

of course during measurement you wil kill all 3d party apps, especially messenger apps, the most famous one connects to internet every each second!!

Upvotes: 1

Taylor Kidd
Taylor Kidd

Reputation: 1511

I can't make suggestions on making power measurements on iOS, but can point out some possible sources of power consumption, as well as point out some issues to think about when making measurements.

Common sources of excessive power consumption:

  • Polling instead of using interrupts. this prevents the processor from entering lower power states. Low power states can reduce processor consumption by over an order of magnitude

  • Using interrupt intervals that are too small. A common mistake is believing that a smaller polling interval, say 10ms, results in faster response. If the ability of your app/user to respond is 500ms, then 10ms serves only to keep the processor awake and chewing up energy.

  • Anything that transmits is a hog, receiving less so but still bad (WiFi, GPS, Bluetooth, etc as said above). Minimize their usage.

  • Peripherals also have low power states. Uses them sparingly to keep them in a lower power state.

Comments on measuring power consumption:

  • Monitoring itself can cause excessive power consumption. Monitoring power is very tricky. Monitoring uses interrupts or polling which keep the processor/device awake and in a high power state.

  • Most monitoring is from the OS, which may or may not be from "real" HW measurements vs SW "guesses".

  • Trying to be really really accurate means more frequent measurements which cause, you guessed it, the processor and devices to stay awake.

I suggest you take a close look at what sampling interval you really need, and design your app to allow the processor and devices to rest as much as possible.

Upvotes: 1

Related Questions