Merge changes If4deb106,Ib25d7658 am: 0388f0e47b am: 41a57af66a
am: ae278410f5
Change-Id: I4fa34b647e7b2408d4493cfb148ae7d8c24bd6e8
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 840413a..6cd4e92 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -34,6 +34,7 @@
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.util.Log;
/**
@@ -96,10 +97,10 @@
/**
* {@hide}
*/
- public NetworkStatsManager(Context context) {
+ public NetworkStatsManager(Context context) throws ServiceNotFoundException {
mContext = context;
mService = INetworkStatsService.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+ ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE));
}
/**
@@ -181,10 +182,10 @@
/**
* Query network usage statistics summaries. Result filtered to include only uids belonging to
* calling user. Result is aggregated over time, hence all buckets will have the same start and
- * end timestamps. State is going to be {@link NetworkStats.Bucket#STATE_ALL},
- * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE},
- * metered {@link NetworkStats.Bucket#METERED_ALL}, and roaming
- * {@link NetworkStats.Bucket#ROAMING_ALL}.
+ * end timestamps. Not aggregated over state, uid, metered, or roaming. This means buckets'
+ * start and end timestamps are going to be the same as the 'startTime' and 'endTime'
+ * parameters. State, uid, metered, and roaming are going to vary, and tag is going to be the
+ * same.
*
* @param networkType As defined in {@link ConnectivityManager}, e.g.
* {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
@@ -230,7 +231,9 @@
* belonging to calling user. Result is aggregated over state but not aggregated over time.
* This means buckets' start and end timestamps are going to be between 'startTime' and
* 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid the
- * same as the 'uid' parameter and tag the same as 'tag' parameter.
+ * same as the 'uid' parameter and tag the same as 'tag' parameter. metered is going to be
+ * {@link NetworkStats.Bucket#METERED_ALL}, and roaming is going to be
+ * {@link NetworkStats.Bucket#ROAMING_ALL}.
* <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
* interpolate across partial buckets. Since bucket length is in the order of hours, this
* method cannot be used to measure data usage on a fine grained time scale.
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index c704ef0..0775bda 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -24,8 +24,10 @@
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
+import android.service.NetworkIdentityProto;
import android.telephony.TelephonyManager;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import java.util.Objects;
@@ -110,6 +112,23 @@
return builder.append("}").toString();
}
+ public void writeToProto(ProtoOutputStream proto, long tag) {
+ final long start = proto.start(tag);
+
+ proto.write(NetworkIdentityProto.TYPE, mType);
+
+ // Not dumping mSubType, subtypes are no longer supported.
+
+ if (mSubscriberId != null) {
+ proto.write(NetworkIdentityProto.SUBSCRIBER_ID, scrubSubscriberId(mSubscriberId));
+ }
+ proto.write(NetworkIdentityProto.NETWORK_ID, mNetworkId);
+ proto.write(NetworkIdentityProto.ROAMING, mRoaming);
+ proto.write(NetworkIdentityProto.METERED, mMetered);
+
+ proto.end(start);
+ }
+
public int getType() {
return mType;
}
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index 4a4accb..5f521de 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -31,7 +31,10 @@
import android.os.Parcel;
import android.os.Parcelable;
+import android.service.NetworkStatsHistoryBucketProto;
+import android.service.NetworkStatsHistoryProto;
import android.util.MathUtils;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.util.IndentingPrintWriter;
@@ -628,6 +631,33 @@
}
}
+ public void writeToProto(ProtoOutputStream proto, long tag) {
+ final long start = proto.start(tag);
+
+ proto.write(NetworkStatsHistoryProto.BUCKET_DURATION_MS, bucketDuration);
+
+ for (int i = 0; i < bucketCount; i++) {
+ final long startBucket = proto.start(NetworkStatsHistoryProto.BUCKETS);
+
+ proto.write(NetworkStatsHistoryBucketProto.BUCKET_START_MS, bucketStart[i]);
+ writeToProto(proto, NetworkStatsHistoryBucketProto.RX_BYTES, rxBytes, i);
+ writeToProto(proto, NetworkStatsHistoryBucketProto.RX_PACKETS, rxPackets, i);
+ writeToProto(proto, NetworkStatsHistoryBucketProto.TX_BYTES, txBytes, i);
+ writeToProto(proto, NetworkStatsHistoryBucketProto.TX_PACKETS, txPackets, i);
+ writeToProto(proto, NetworkStatsHistoryBucketProto.OPERATIONS, operations, i);
+
+ proto.end(startBucket);
+ }
+
+ proto.end(start);
+ }
+
+ private static void writeToProto(ProtoOutputStream proto, long tag, long[] array, int index) {
+ if (array != null) {
+ proto.write(tag, array[index]);
+ }
+ }
+
@Override
public String toString() {
final CharArrayWriter writer = new CharArrayWriter();
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index e7436be..fc66395 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -168,6 +168,24 @@
/**
* Set active tag to use when accounting {@link Socket} traffic originating
+ * from the current thread. Only one active tag per thread is supported.
+ * <p>
+ * Changes only take effect during subsequent calls to
+ * {@link #tagSocket(Socket)}.
+ * <p>
+ * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
+ * used internally by system services like {@link DownloadManager} when
+ * performing traffic on behalf of an application.
+ *
+ * @return the current tag for the calling thread, which can be used to
+ * restore any existing values after a nested operation is finished
+ */
+ public static int getAndSetThreadStatsTag(int tag) {
+ return NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
+ }
+
+ /**
+ * Set active tag to use when accounting {@link Socket} traffic originating
* from the current thread. The tag used internally is well-defined to
* distinguish all backup-related traffic.
*
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index 5f6bd59..3efef01 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -47,6 +47,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -762,13 +763,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump ServiceDiscoverService from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
for (ClientInfo client : mClients.values()) {
pw.println("Client Info");
diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java
index c48f430..ee00fdc 100644
--- a/services/core/java/com/android/server/net/NetworkIdentitySet.java
+++ b/services/core/java/com/android/server/net/NetworkIdentitySet.java
@@ -17,6 +17,8 @@
package com.android.server.net;
import android.net.NetworkIdentity;
+import android.service.NetworkIdentitySetProto;
+import android.util.proto.ProtoOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -143,4 +145,14 @@
final NetworkIdentity anotherIdent = another.iterator().next();
return ident.compareTo(anotherIdent);
}
+
+ public void writeToProto(ProtoOutputStream proto, long tag) {
+ final long start = proto.start(tag);
+
+ for (NetworkIdentity ident : this) {
+ ident.writeToProto(proto, NetworkIdentitySetProto.IDENTITIES);
+ }
+
+ proto.end(start);
+ }
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index c45b416..0354300 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -34,9 +34,13 @@
import android.net.NetworkTemplate;
import android.net.TrafficStats;
import android.os.Binder;
+import android.service.NetworkStatsCollectionKeyProto;
+import android.service.NetworkStatsCollectionProto;
+import android.service.NetworkStatsCollectionStatsProto;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.IntArray;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FileRotator;
@@ -532,12 +536,15 @@
/ mBucketDuration);
}
- public void dump(IndentingPrintWriter pw) {
+ private ArrayList<Key> getSortedKeys() {
final ArrayList<Key> keys = Lists.newArrayList();
keys.addAll(mStats.keySet());
Collections.sort(keys);
+ return keys;
+ }
- for (Key key : keys) {
+ public void dump(IndentingPrintWriter pw) {
+ for (Key key : getSortedKeys()) {
pw.print("ident="); pw.print(key.ident.toString());
pw.print(" uid="); pw.print(key.uid);
pw.print(" set="); pw.print(NetworkStats.setToString(key.set));
@@ -550,6 +557,29 @@
}
}
+ public void writeToProto(ProtoOutputStream proto, long tag) {
+ final long start = proto.start(tag);
+
+ for (Key key : getSortedKeys()) {
+ final long startStats = proto.start(NetworkStatsCollectionProto.STATS);
+
+ // Key
+ final long startKey = proto.start(NetworkStatsCollectionStatsProto.KEY);
+ key.ident.writeToProto(proto, NetworkStatsCollectionKeyProto.IDENTITY);
+ proto.write(NetworkStatsCollectionKeyProto.UID, key.uid);
+ proto.write(NetworkStatsCollectionKeyProto.SET, key.set);
+ proto.write(NetworkStatsCollectionKeyProto.TAG, key.tag);
+ proto.end(startKey);
+
+ // Value
+ final NetworkStatsHistory history = mStats.get(key);
+ history.writeToProto(proto, NetworkStatsCollectionStatsProto.HISTORY);
+ proto.end(startStats);
+ }
+
+ proto.end(start);
+ }
+
public void dumpCheckin(PrintWriter pw, long start, long end) {
dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateMobileWildcard(), "cell");
dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateWifiWildcard(), "wifi");
diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/services/core/java/com/android/server/net/NetworkStatsObservers.java
index 3360584..a256cbc 100644
--- a/services/core/java/com/android/server/net/NetworkStatsObservers.java
+++ b/services/core/java/com/android/server/net/NetworkStatsObservers.java
@@ -68,7 +68,7 @@
private final AtomicInteger mNextDataUsageRequestId = new AtomicInteger();
// Lazily instantiated when an observer is registered.
- private Handler mHandler;
+ private volatile Handler mHandler;
/**
* Creates a wrapper that contains the caller context and a normalized request.
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index 090a076..80309e1 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -29,9 +29,11 @@
import android.net.NetworkTemplate;
import android.net.TrafficStats;
import android.os.DropBoxManager;
+import android.service.NetworkStatsRecorderProto;
import android.util.Log;
import android.util.MathUtils;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.net.VpnInfo;
import com.android.internal.util.FileRotator;
@@ -465,6 +467,15 @@
}
}
+ public void writeToProtoLocked(ProtoOutputStream proto, long tag) {
+ final long start = proto.start(tag);
+ if (mPending != null) {
+ proto.write(NetworkStatsRecorderProto.PENDING_TOTAL_BYTES, mPending.getTotalBytes());
+ }
+ getOrLoadCompleteLocked().writeToProto(proto, NetworkStatsRecorderProto.COMPLETE_HISTORY);
+ proto.end(start);
+ }
+
public void dumpCheckin(PrintWriter pw, long start, long end) {
// Only load and dump stats from the requested window
getOrLoadPartialLocked(start, end).dumpCheckin(pw, start, end);
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 060dd73..e746355 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -104,6 +104,8 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Global;
+import android.service.NetworkInterfaceProto;
+import android.service.NetworkStatsServiceDumpProto;
import android.telephony.TelephonyManager;
import android.text.format.DateUtils;
import android.util.ArrayMap;
@@ -115,10 +117,12 @@
import android.util.Slog;
import android.util.SparseIntArray;
import android.util.TrustedTime;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.net.VpnInfo;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FileRotator;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.EventLogTags;
@@ -554,15 +558,21 @@
@Override
public NetworkStats getSummaryForAllUid(
NetworkTemplate template, long start, long end, boolean includeTags) {
- @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage);
- final NetworkStats stats =
- getUidComplete().getSummary(template, start, end, accessLevel);
- if (includeTags) {
- final NetworkStats tagStats = getUidTagComplete()
- .getSummary(template, start, end, accessLevel);
- stats.combineAllValues(tagStats);
+ try {
+ @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage);
+ final NetworkStats stats =
+ getUidComplete().getSummary(template, start, end, accessLevel);
+ if (includeTags) {
+ final NetworkStats tagStats = getUidTagComplete()
+ .getSummary(template, start, end, accessLevel);
+ stats.combineAllValues(tagStats);
+ }
+ return stats;
+ } catch (NullPointerException e) {
+ // TODO: Track down and fix the cause of this crash and remove this catch block.
+ Slog.wtf(TAG, "NullPointerException in getSummaryForAllUid", e);
+ throw e;
}
- return stats;
}
@Override
@@ -1213,7 +1223,8 @@
// Build list of UIDs that we should clean up
int[] uids = new int[0];
final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
- PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS);
+ PackageManager.MATCH_ANY_USER
+ | PackageManager.MATCH_DISABLED_COMPONENTS);
for (ApplicationInfo app : apps) {
final int uid = UserHandle.getUid(userId, app.uid);
uids = ArrayUtils.appendInt(uids, uid);
@@ -1224,7 +1235,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) {
- mContext.enforceCallingOrSelfPermission(DUMP, TAG);
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, rawWriter)) return;
long duration = DateUtils.DAY_IN_MILLIS;
final HashSet<String> argSet = new HashSet<String>();
@@ -1249,6 +1260,12 @@
final IndentingPrintWriter pw = new IndentingPrintWriter(rawWriter, " ");
synchronized (mStatsLock) {
+ if (args.length > 0 && "--proto".equals(args[0])) {
+ // In this case ignore all other arguments.
+ dumpProto(fd);
+ return;
+ }
+
if (poll) {
performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE);
pw.println("Forced poll");
@@ -1321,6 +1338,33 @@
}
}
+ private void dumpProto(FileDescriptor fd) {
+ final ProtoOutputStream proto = new ProtoOutputStream(fd);
+
+ // TODO Right now it writes all history. Should it limit to the "since-boot" log?
+
+ dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_INTERFACES, mActiveIfaces);
+ dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_UID_INTERFACES, mActiveUidIfaces);
+ mDevRecorder.writeToProtoLocked(proto, NetworkStatsServiceDumpProto.DEV_STATS);
+ mXtRecorder.writeToProtoLocked(proto, NetworkStatsServiceDumpProto.XT_STATS);
+ mUidRecorder.writeToProtoLocked(proto, NetworkStatsServiceDumpProto.UID_STATS);
+ mUidTagRecorder.writeToProtoLocked(proto, NetworkStatsServiceDumpProto.UID_TAG_STATS);
+
+ proto.flush();
+ }
+
+ private static void dumpInterfaces(ProtoOutputStream proto, long tag,
+ ArrayMap<String, NetworkIdentitySet> ifaces) {
+ for (int i = 0; i < ifaces.size(); i++) {
+ final long start = proto.start(tag);
+
+ proto.write(NetworkInterfaceProto.INTERFACE, ifaces.keyAt(i));
+ ifaces.valueAt(i).writeToProto(proto, NetworkInterfaceProto.IDENTITIES);
+
+ proto.end(start);
+ }
+ }
+
/**
* Return snapshot of current UID statistics, including any
* {@link TrafficStats#UID_TETHERING} and {@link #mUidOperations} values.