getUidRxBytes() and getUidTxBytes() always return 0 in Android 4.3
Asked Answered
S

3

9

I feel like I am on crazy pills right now. A specific part of my application has been working just fine for several days, and today it just stopped working and I can not figure out why. This part of my code used to output the total data since boot that each specific app has sent and received. Now, the values always show up as 0.

A couple things that may or may not be affecting this:

1.) My Nexus 4 was just updated to Android 4.3 today, but I doubt this is an issue because this worked just fine right after I updated.

2.) With the Android API 18 update, some methods from the Traffic Stats API are now deprecated, but these are methods I am not even using, so this should have no effect. http://developer.android.com/reference/android/net/TrafficStats.html

All help is greatly appreciated.

PackageManager packageManager=this.getPackageManager();
List<ApplicationInfo> appList=packageManager.getInstalledApplications(0);

for (ApplicationInfo appInfo : appList) {
    String appLabel = (String) packageManager.getApplicationLabel(appInfo);
    int uid = appInfo.uid;
    Log.d("data", String.valueOf(TrafficStats.getUidRxBytes(uid) + TrafficStats.getUidTxBytes(uid)));

Update[January 23, 2014]: Testing the getUidRxBytes() and getUidTxBytes() on my Nexus 4 running Android 4.4.2 shows that the values are no longer 0, but are reporting the correct statistics.

Stedmann answered 27/7, 2013 at 6:30 Comment(5)
Despite your objections, I think the two things you mentioned are probably the most likely causes.Yorgen
I appreciate the response Robert, but like I said, I don't think these could be the issues, because everything worked after I updated to 4.3. It was a few hours later when it started reporting 0 for some reason.Stedmann
gonna flash the nexus back to 4.2 to see if that works, brbStedmann
Aaahh hell no. The above code works perfectly when run on Android 4.2.2. But on Android 4.3, it reports all the apps as having transferred 0 bytes since boot. This is disconcerting, considering none of the methods used in the above code have been deprecated and there is no indication here: developer.android.com/reference/android/net/TrafficStats.html or anywhere else that any of the methods used should be working any differnetly in 4.3.Stedmann
Update: I have reported this on the AOSP issue tracker. I will update as I learn more: code.google.com/p/android/issues/…Stedmann
B
3

The TrafficStats class get the information about network traffic from the /proc/uid_stat/<uid> directory. This contains information about the tcp, udp bytes and packets sent and received. If the files are not present the TrafficStats class can't get the network stats. You can check if the files are present, If not you are out of luck and should look for other way.

If the files are present you can try to read it yourself.

Also the getUidTxBytes() and getUIDRxBytes() report only the TCP traffic and miss UDP traffic. So if your app is doing lots of UDP traffic (like voip) then you'll not get any info. There is already a bug filed for this : https://code.google.com/p/android/issues/detail?id=32410

Bresnahan answered 30/7, 2013 at 6:37 Comment(2)
The files do exist in the directory you specified. Each uid has a folder named after itself, e.g. 10033. Within each folder there are two text files, one called "tcp_rcv" and another "tcp_snd", each containing a number in them. And these numbers are not 0, so getUidRxBytes() and getUidTxBytes() should be returning proper values. Thank you for your help.Stedmann
Does any one about fixes for 6.0.x ? Or alternative methods? thanksDissimilate
S
6

I have reported the issue to the AOSP issue tracker: here

I have also created an alternate solution to the problem which I have pasted below:

private Long getTotalBytesManual(int localUid){

File dir = new File("/proc/uid_stat/");
String[] children = dir.list();
if(!Arrays.asList(children).contains(String.valueOf(localUid))){
    return 0L;
}
File uidFileDir = new File("/proc/uid_stat/"+String.valueOf(localUid));
File uidActualFileReceived = new File(uidFileDir,"tcp_rcv");
File uidActualFileSent = new File(uidFileDir,"tcp_snd");

 String textReceived = "0";
 String textSent = "0";

 try {
        BufferedReader brReceived = new BufferedReader(new FileReader(uidActualFileReceived));
        BufferedReader brSent = new BufferedReader(new FileReader(uidActualFileSent));
        String receivedLine;
        String sentLine;

        if ((receivedLine = brReceived.readLine()) != null) {
            textReceived = receivedLine;
        }
        if ((sentLine = brSent.readLine()) != null) {
            textSent = sentLine;
        }

    }
    catch (IOException e) {

    }
 return Long.valueOf(textReceived).longValue() + Long.valueOf(textReceived).longValue();

}
Stedmann answered 3/8, 2013 at 2:22 Comment(2)
You've written "textReceived" twice at the last line of code. Also you didn't close the readers, and used "String.valueOf" (and twice) instead of calling "Long.toString" . I also have a question about this: the official documentation says it gets the data since last boot, but it seems this method takes the whole number, eevn before the current session of the OS. How could it be?Privation
I checked the issue status and tested your code, it seems for security reasons they don't want anyone to know which app is using internet, hence the uid_stat directory is empty, and even your code failed to work (or maybe needs the device to be rooted).Allergic
B
3

The TrafficStats class get the information about network traffic from the /proc/uid_stat/<uid> directory. This contains information about the tcp, udp bytes and packets sent and received. If the files are not present the TrafficStats class can't get the network stats. You can check if the files are present, If not you are out of luck and should look for other way.

If the files are present you can try to read it yourself.

Also the getUidTxBytes() and getUIDRxBytes() report only the TCP traffic and miss UDP traffic. So if your app is doing lots of UDP traffic (like voip) then you'll not get any info. There is already a bug filed for this : https://code.google.com/p/android/issues/detail?id=32410

Bresnahan answered 30/7, 2013 at 6:37 Comment(2)
The files do exist in the directory you specified. Each uid has a folder named after itself, e.g. 10033. Within each folder there are two text files, one called "tcp_rcv" and another "tcp_snd", each containing a number in them. And these numbers are not 0, so getUidRxBytes() and getUidTxBytes() should be returning proper values. Thank you for your help.Stedmann
Does any one about fixes for 6.0.x ? Or alternative methods? thanksDissimilate
H
2

I have done some detailed research about this, and to clarify some details, since Android 4.3 the TrafficStats API has changed in the way it extracts details from the device.

Prior to Android 4.3 the UID traffic stats were available for TCP and UDP and included API for bytes and packets & sent and received. That data was extracted from the /proc/uid_stat/[pid]/* files.

In Android 4.3, the developers has decided to switch to a better and more safe API, using the xt_qtaguid UID statistics, which is part of the netfilter kernel module in Linux. This API (procfs) allows access based on process UID, and this is why when you try to access to TrafficStats API in Android=>4.3 you will get zero information for not-own UID.

btw, the commit that caused the issue is the following: https://github.com/android/platform_frameworks_base/commit/92be93a94edafb5906e8bc48e6fee9dd07f5049e

*Improve TrafficStats UID APIs. Deprecate transport layer statistics, leaving only the summarized network layer statistics. Improve documentation to be clear about layers where measurements occur, and their behavior since boot. Under the hood, move to using xt_qtaguid UID statistics. Bug: 6818637, 7013662 Change-Id: I9f26992e5fcdebd88c671e5765bd91229e7b0016*

Hilda answered 27/10, 2013 at 0:58 Comment(1)
So the official framework return 0 for all applications except the current one? why is it considered safer ? they are just statistical numbers, and they are even available via the settings of the OS. Also, will reading from the "/proc/uid_stat" still work and return the correct results? Some people claim the whole thing got fixed on Android 4.4, but I don't see that it got fixed (returns 0 for all apps).Privation

© 2022 - 2024 — McMap. All rights reserved.