Measuring Android Power Use using Perfettto: Questions

1,781 views
Skip to first unread message

Dave Null

unread,
Mar 23, 2021, 7:21:19 PM3/23/21
to Perfetto Development - www.perfetto.dev
Hello everyone,

Firstly, thank you for the creation of Perfetto! Really allows developers to inspect the performance of their Android apps. Great work! Secondly, I hope this is the right place to ask my questions. I know this is the dev mailing list but I came across some questions about general usage here as well so I assume its okay? If not, apologies :). 

Just FYI: to do measurements I'm using the record_android_trace help script :).

My questions:
1. How to get the battery counters data in a human readable format? I can access the data using the Perfetto UI and the SQL query engine. However, when using the trace conversion tool and convert my trace to json or systrace I get unexpected (to me atleast ;p) output:

When converting to json: https://pastebin.com/vb0i4Smm
When converting to systrace format: https://pastebin.com/auDuayCC

When converting to text I get the following error:
[982.531] trace_to_text.cc:153    Cannot open protos/perfetto/trace/trace_packet.proto.
[982.531] trace_to_text.cc:156    Text mode only works from the perfetto directory. Googlers, see b/131425913

Is there a way to get the battery counters data in a human readable format?

2. Does Android Perfetto provides a builtin way to get the amount of energy used in Joules during its runtime? 

3. How can I see whether the power rails data source is available on my device? The website states: This data source has been introduced in Android 10 (Q) and requires the dedicated hardware on the device. This hardware is not yet available on most production phones. Is there an overview of supported devices? I'm using a Pixel 5 running Android 11.

4. How do I do actually do power measurements using the power rails data source? Do I only need to set the collect_power_rails: to true in my android_power_config as mentioned here. Will this give me data for all available rails on the device (given of course, that the device contains the dedicated hardware for doing power rails measurements)

5. According to the website measuring power consumption using battery counters while the device is connected through USB can result in invalid measurements. Would using adb shell dumpsys battery unplug help in this case?

Thanks a lot!

Primiano Tucci

unread,
Mar 24, 2021, 2:30:18 PM3/24/21
to Dave Null, Perfetto Development - www.perfetto.dev
On Tue, Mar 23, 2021 at 11:21 PM Dave Null <foru...@gmail.com> wrote:
Hello everyone,

Hello.
 
Firstly, thank you for the creation of Perfetto! Really allows developers to inspect the performance of their Android apps. Great work! Secondly, I hope this is the right place to ask my questions. I know this is the dev mailing list but I came across some questions about general usage here as well so I assume its okay? If not, apologies :). 

Yes absolutely. If you want some more interactive interaction feel free to drop by our discord channel on https://discord.gg/35ShE3A 
This ML works as well.
 
Just FYI: to do measurements I'm using the record_android_trace help script :).

My questions:
1. How to get the battery counters data in a human readable format? I can access the data using the Perfetto UI and the SQL query engine. However, when using the trace conversion tool and convert my trace to json or systrace I get unexpected (to me atleast ;p) output:

The JSON or systrace exporter options in traceconv don't export everything. They only export the events that were supported in android systrace or chrome://Tracing (json). Newer feature (like power rails) that never had an equivalent in those tools are not exported. 
 
When converting to json: https://pastebin.com/vb0i4Smm
When converting to systrace format: https://pastebin.com/auDuayCC

When converting to text I get the following error:
[982.531] trace_to_text.cc:153    Cannot open protos/perfetto/trace/trace_packet.proto.
[982.531] trace_to_text.cc:156    Text mode only works from the perfetto directory. Googlers, see b/131425913

Yeah this is a bug / missing feature we should fix at some point. The "traceconv text" option requires a full git checkout of perfetto, because it depends on some proto files.
 
Is there a way to get the battery counters data in a human readable format?

In my opinion the best way is to create a .sql file with a query like
select * from counters where name like 'power.%' ;
and then just do `trace_processor_shell -q query-sql trace.file` to get a csv output.
There is a sample trace with power rails under //test/data/powe_rails.pb.

So this would look like:

$ cat /tmp/query.sql
select * from counters where name like 'power.%' ;

$ out/mac_debug/trace_processor_shell -q /tmp/query.sql test/data/power_rails.pb  > out.csv

$ head out.csv
"id","type","ts","track_id","value","arg_set_id","counter_id","id:1","type:1","name","source_arg_set_id","unit","description"
3,"counter",1675230000000,3,194087866.000000,"[NULL]",3,3,"counter_track","power.PPVAR_VPH_PWR_OLED_uws","[NULL]","[NULL]","[NULL]"
4,"counter",1675230000000,4,7119085.000000,"[NULL]",4,4,"counter_track","power.PPVAR_VPH_PWR_ABH_uws","[NULL]","[NULL]","[NULL]"
8,"counter",1676004000000,3,194145111.000000,"[NULL]",3,3,"counter_track","power.PPVAR_VPH_PWR_OLED_uws","[NULL]","[NULL]","[NULL]"

To get something fancier than csv (e.g. structured json) things see https://perfetto.dev/docs/analysis/metrics


2. Does Android Perfetto provides a builtin way to get the amount of energy used in Joules during its runtime? 

Not sure what you mean with "builtin way". We have two power-related data sources, both enabled by same the power toggle in the configurator, relevant here. 
1. Polling the coulomb counter  / fuel gauge
2. Polling power rails

They depend on HW availability. My experience that most devices have the coulomb counter, extremely few have power rails (more below)
1. is generally more slow moving but it's more complete (you get visiblity of the whole power draw. Power rails don't cover 100% of the draw, they only instrument specific subsystems. In my experience is useful only for measurements of workloads of several minutes or more.

Re Joules:

(1) is the closest approximation. You won't get Joules, but you will get micro-AmpereHour. The difference lies is the voltage. That's a limitation of the HW which measures only current flowing, not voltage and current. So the best you can do is getting the uAH and assume the voltage is 3.7V (it's not 100% correct, it varies over time, but there is no way to know that afaik)

3. How can I see whether the power rails data source is available on my device? The website states: This data source has been introduced in Android 10 (Q) and requires the dedicated hardware on the device. This hardware is not yet available on most production phones. Is there an overview of supported devices? I'm using a Pixel 5 running Android 11.

The quick answer is: if you enable the trace and no "power.xxx" tracks show up they are not supported. 
I am not fully sure (don't have a device with rails right now) but  `adb shell dumpsys powerstats` should show something in this regard.

As far as I am aware, none of the current production Pixel devices have rails. Only their pre-production variants do. 

  
4. How do I do actually do power measurements using the power rails data source? Do I only need to set the collect_power_rails: to true in my android_power_config as mentioned here.  
Will this give me data for all available rails on the device (given of course, that the device contains the dedicated hardware for doing power rails measurements)

Correct
 
5. According to the website measuring power consumption using battery counters while the device is connected through USB can result in invalid measurements.

Only for the coulomb counter (but then you might now have the rails). The measurement will be "technically correct", as in, you will see current flowing "into" the battery (charging it), OR the delta between current flowing in and power draw. In any case, it's not what you want to see (unless you are debugging a USB power supply :D)
 
Would using adb shell dumpsys battery unplug help in this case?

I think battery unplug only fakes it at the SW level, but doesn't actually unplug the charger.
I know a way to make that happen but:
1. requires root (a userdebug/eng device)
2. it's very device specific (but you can easily make guesses)

For instance on my Pixel 3 the trick is:

echo 1 >/sys/devices/platform/soc/c440000.qcom,spmi/spmi-0/spmi0-02/c440000.qcom,spmi:qcom,pmi8998@2:qcom,qpnp-smb2/power_supply/battery/input_suspend

In general `find sys | grep input_suspend` gets you in the right place.

Another thing to remember is that there is a caveat about that trick: the phone will never go in full suspend mode (even if you press the power button). This is because the kernel USB driver will hold a wakelock and keep the device alive. So as long as you have a USB connection the phone won't fully suspend.
But this is relevant only if you want to debug suspend cases, not active workloads.
 

Hope this helps

Thanks a lot!

--
You received this message because you are subscribed to the Google Groups "Perfetto Development - www.perfetto.dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to perfetto-dev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/perfetto-dev/138591e5-bf7a-4912-8136-abe047c0c0b2n%40googlegroups.com.


--
Primiano Tucci
Software Engineer
Google UK Limited

Dave Null

unread,
Apr 10, 2021, 4:58:48 PM4/10/21
to Perfetto Development - www.perfetto.dev
Hello Primiano,

Thanks a lot for your quick and detailed response and apologies for my slow one... Thanks to your help I've been doing some experiments with Perfetto and I really like the way your can customize your measurement setup. However, I still have a few questions which I can't figure out reading the docs.

>> Yes absolutely. If you want some more interactive interaction feel free to drop by our discord channel on https://discord.gg/35ShE3A 
>> This ML works as well.
Thats great! I will join the channel! However, I will also ask my questions here as I like how a ML functions as a knowledge base :). Maybe other people find our discussion useful as well.

1. Regarding the measuring power consumption when the device is connected through USB. Right now I'm programmatically disabling the USB ports of my laptop before starting the trace using ADB WiFi debugging. However, this actually results in my batt.current_ua values to become negative numbers! When I keep my device connected through USB and run a perfetto trace the batt.current_ua values are positive. Isn't this the opposite of what is expected to happen? I'm using a Google Pixel 5 running Android 11. 

2. When running experiments (with my USB ports disabled so the device is not receiving power through USB) my traces show a constant batt.charge_uah value: it does not change overtime. Even when doing longer traces (1 minute or longer) the value stays the same. Is this to be expected? Am I missing something?

3. When querying my data for ex:

select ts, t.name, value from counter as c left join counter_track t on c.track_id = t.id

I also receive a timestamp (ts). From what I've read this is time according to BUILTIN_CLOCK_BOOTTIME? Is it possible to instead timestamp the data from the point of starting the trace in ms? So when tracing for 60 seconds. we have ts values between 0 and 60000? So similarly as when viewing your trace in the ui.perfetto.dev viewer? Or can I convert these existing timestamps to this format I? I've already looked at the primary_trace_clock from the builtin_data_sources but it didn't work. For example I added the following lines to my perfetto_config.pbtx:

builtin_data_sources:
{
    primary_trace_clock: BUILTIN_CLOCK_REALTIME
}

But I didn't see any differences. 

4. I assumed that the value set for battery_poll_ms corresponds with the number of measurements. So when setting it to 250ms (4 times per second) over a period of 1 minute I would assume 60*4=240 measurements. However, for a 1 minute
trace I just get 124 measurements. Are my assumptions incorrect? If so why ;p?

Thanks a lot!





Op woensdag 24 maart 2021 om 19:30:18 UTC+1 schreef primiano:

Primiano Tucci

unread,
Apr 12, 2021, 3:29:28 PM4/12/21
to Dave Null, Perfetto Development - www.perfetto.dev
On Sat, Apr 10, 2021 at 9:58 PM Dave Null <foru...@gmail.com> wrote:
Hello Primiano,

Thanks a lot for your quick and detailed response and apologies for my slow one... Thanks to your help I've been doing some experiments with Perfetto and I really like the way your can customize your measurement setup. However, I still have a few questions which I can't figure out reading the docs.

>> Yes absolutely. If you want some more interactive interaction feel free to drop by our discord channel on https://discord.gg/35ShE3A 
>> This ML works as well.
Thats great! I will join the channel! However, I will also ask my questions here as I like how a ML functions as a knowledge base :). Maybe other people find our discussion useful as well.

1. Regarding the measuring power consumption when the device is connected through USB. Right now I'm programmatically disabling the USB ports of my laptop before starting the trace using ADB WiFi debugging.

WDYM with "disabling"? If you mean via software, that most of the time doesn't disable the power feed of the USB port. I suspect that's what's happening here, you are disabling the port logically but not electrically.
  
However, this actually results in my batt.current_ua values to become negative numbers! When I keep my device connected through USB and run a perfetto trace the batt.current_ua values are positive. Isn't this the opposite of what is expected to happen? I'm using a Google Pixel 5 running Android 11.

I think what's happening there is that the port is still charging the device and you see current flowing *into* the battery (Because of the charge) not out.
A good workaround with that is to use a smart USB HUB that has a dedicated USB HID endpoint that can be used to electrically disconnect (and reconnect) each port. THey are rare but they exist (sry don't have any link to existing products handy right now)
 
2. When running experiments (with my USB ports disabled so the device is not receiving power through USB) my traces show a constant batt.charge_uah value: it does not change overtime. Even when doing longer traces (1 minute or longer) the value stays the same. Is this to be expected? Am I missing something?

See above
 

3. When querying my data for ex:

select ts, t.name, value from counter as c left join counter_track t on c.track_id = t.id

I also receive a timestamp (ts). From what I've read this is time according to BUILTIN_CLOCK_BOOTTIME? Is it possible to instead timestamp the data from the point of starting the trace in ms? So when tracing for 60 seconds. we have ts values between 0 and 60000? So similarly as when viewing your trace in the ui.perfetto.dev viewer? Or can I convert these existing timestamps to this format I? I've already looked at the primary_trace_clock from the builtin_data_sources but it didn't work. For example I added the following lines to my perfetto_config.pbtx:

You can convert by subtracting the result of `start_ts FROM trace_bounds` 

builtin_data_sources:
{
    primary_trace_clock: BUILTIN_CLOCK_REALTIME
}

But I didn't see any differences. 

4. I assumed that the value set for battery_poll_ms corresponds with the number of measurements. So when setting it to 250ms (4 times per second) over a period of 1 minute I would assume 60*4=240 measurements. However, for a 1 minute
trace I just get 124 measurements. Are my assumptions incorrect? If so why ;p?

Your assumptions are correct, You should have seen 240 measurements, it's very weird. Can you tell if they are equally spaced  or where's the missing data (by querying the counters table) ? 


 

Dave Null

unread,
Apr 12, 2021, 8:35:55 PM4/12/21
to Perfetto Development - www.perfetto.dev
Again thanks for the response!

>> WDYM with "disabling"? If you mean via software, that most of the time doesn't disable the power feed of the USB port. I suspect that's what's happening here, you are disabling the port logically but not electrically.

I was looking over the documentation again and I found the following about the current_ua on the TracePacket documentation page[1]:
Instantaneous battery current in microamperes(µA). Positive values indicate net current entering the battery from a charge source, negative values indicate net current discharging from the battery.

On the "Battery counters and rails" page [2] however it states:
Battery counters measure the charge flowing in and out of the battery. If the device is plugged to a USB cable, you will likely observe a negative instantaneous current and an increase of the total charge, denoting the fact that charge is flowing in the battery (i.e. charging it) rather than out.

Maybe I'm reading it incorrectly (I'm not an English native speaker and its midnight here ;p) but don't these sources say the opposite? 

I indeed disable it via software using uhubctl[0] however I just did a trace with the phone completely disconnected from USB, using just WiFi debugging. This gives me the same problem: a negative batt.current_ua. According to the TracePacket documentation page this is correct but according to the Battery counters and rails page this is incorrect?

>> See above
I see that there is a change in the the batt.charge_uah value! However, over a period of 60 seconds its just a single change. After 46 seconds it goes directly from 4,002,240uah to 3,960,550uah. Is there a way to get this to be more accurate i.e. more finegrained/higher granularity, so also the values between 4,002,240uah to 3,960,550uah?

>> You can convert by subtracting the result of `start_ts FROM trace_bounds
Thanks!

>> Your assumptions are correct, You should have seen 240 measurements, it's very weird. Can you tell if they are equally spaced  or where's the missing data (by querying the counters table) ? 
Sorry I made a mistake! I did an experiment of 60 seconds, set the battery_poll_ms to 100 and it indeed gave me ~ 600 values (601). Awesome!

Thanks!

[1] https://perfetto.dev/docs/reference/trace-packet-proto#BatteryCounters
Op maandag 12 april 2021 om 21:29:28 UTC+2 schreef primiano:

Primiano Tucci

unread,
Apr 13, 2021, 4:43:13 AM4/13/21
to Dave Null, Perfetto Development - www.perfetto.dev
On Tue, Apr 13, 2021 at 1:36 AM Dave Null <foru...@gmail.com> wrote:
Again thanks for the response!

>> WDYM with "disabling"? If you mean via software, that most of the time doesn't disable the power feed of the USB port. I suspect that's what's happening here, you are disabling the port logically but not electrically.

I was looking over the documentation again and I found the following about the current_ua on the TracePacket documentation page[1]:
Instantaneous battery current in microamperes(µA). Positive values indicate net current entering the battery from a charge source, negative values indicate net current discharging from the battery.

On the "Battery counters and rails" page [2] however it states:
Battery counters measure the charge flowing in and out of the battery. If the device is plugged to a USB cable, you will likely observe a negative instantaneous current and an increase of the total charge, denoting the fact that charge is flowing in the battery (i.e. charging it) rather than out.

Maybe I'm reading it incorrectly (I'm not an English native speaker and its midnight here ;p) but don't these sources say the opposite? 

Oh very well spotted, one of them is wrong (the TracePacket comment/documentation).
I just tried on my Pixel3 playing with "echo 1 > /sys/devices/platform/soc/c440000.qcom,spmi/spmi-0/spmi0-02/c440000.qcom,spmi:qcom,pmi8998@2:qcom,qpnp-smb2/power_supply/battery/input_suspend) I confirm that the right version is:

Negative number: the battery is charging / drawing current from USB port
Positive number: the battery is discharging / powering the system

I'll fix the docs ASAP. Thanks for pointing out the discrepancy here.

Note that it's not as clear-cut either. If the USB port doesn't supply a lot of power (e.g. you use an old cable that caps at 500ma) you can be in the situation where the phone is charging from the USB port (so most of the time you see a negative value) however if all the CPU cores are busy and the display is bright, that might draw more than 500mA and you could see a slighly positive current draw from the battery (the total current minus 500mA)
 
 
I indeed disable it via software using uhubctl[0] however I just did a trace with the phone completely disconnected from USB, using just WiFi debugging. This gives me the same problem: a negative batt.current_ua. According to the TracePacket documentation page this is correct but according to the Battery counters and rails page this is incorrect?

>> See above
I see that there is a change in the the batt.charge_uah value! However, over a period of 60 seconds its just a single change. After 46 seconds it goes directly from 4,002,240uah to 3,960,550uah. Is there a way to get this to be more accurate i.e. more finegrained/higher granularity, so also the values between 4,002,240uah to 3,960,550uah?

This is a HW limitation of the fuel gauge chip and I don't think you can do anything more granular. This Android doc [1] has some more details about the specs of various  ICs. But they are known to be slow. Even on Pixel devices, my anecdotal experience is that it doesn't really make sense to do observations less than several minutes. Even if you get values every second there is still some quantization error in the instantaneous values being read. It's a HW limitation and there aren't many ways around that right now. Those power ICs are historically designed to keep track of the battery % indicator, so they are accurate in the long run, but not designed for high rate polling.

 

Dave Null

unread,
Apr 13, 2021, 5:57:09 PM4/13/21
to Perfetto Development - www.perfetto.dev
>> I just tried on my Pixel3 playing with "echo 1 > /sys/devices/platform/soc/c440000.qcom,spmi/spmi-0/spmi0-02/c440000.qcom,spmi:qcom,pmi8998@2:qcom,qpnp-smb2/power_supply/battery/input_suspend) I confirm that the right version is:
>> Negative number: the battery is charging / drawing current from USB port
>> Positive number: the battery is discharging / powering the system

Hmm, this is so weird. I just did multiple traces on my Pixel 5 using WiFi debugging (so completely disconnected from USB, I even put the cable on the other side of the room ;p) and every time I get negative batt.current_ua values. I don't want to sound rude but are you sure ""echo 1 > /sys/devices/platform/soc/c440000.qcom,spmi/spmi-0/spmi0-02/c440000.qcom,spmi:qcom,pmi8998@2:qcom,qpnp-smb2/power_supply/battery/input_suspend" really disables USB charging? I am not allowed to root my phone so I cannot test it unfortunately. I know its a lot to ask but could you maybe completely disconnect the USB and do a trace using ADB WiFi? (adb tcpip 5555 then adb connect <local_phone_ip>:5555 then completely disconnect from USB and start trace).

If this still gives you positive current_ua values then I'm almost starting to think its caused by the device itself. Maybe there is a different fuel gauge chip (just thinking out loud here) in the Pixel 5 in comparison to the Pixel 3? I only have an Pixel 5 unfortunately.

I've attached my trace config file and output trace just in case.

>> This is a HW limitation of the fuel gauge chip and I don't think you can do anything more granular. This Android doc [1] has some more details about the specs of various  ICs. But they are known to be slow. Even on Pixel devices, my anecdotal        >> experience is that it doesn't really make sense to do observations less than several minutes. Even if you get values every second there is still some quantization error in the instantaneous values being read. It's a HW limitation and there aren't many   
>> ways around that right now. Those power ICs are historically designed to keep track of the battery % indicator, so they are accurate in the long run, but not designed for high rate polling.

Thanks a lot for this detailed explanation! Thats really interesting. This puts my experiments in another perspective with regards to used tooling. I will do some more research. Thanks!



Op dinsdag 13 april 2021 om 10:43:13 UTC+2 schreef primiano:
Reply all
Reply to author
Forward
0 new messages