Data Usage public API
Added new API consisting of android.app.usage.NetworkUsageManager and android.app.usage.NetworkUsageStats. Through them data usage on a network interface can be programmatically queried. Both summary and details are available. Bug: 19208876 Change-Id: I0e0c4b37ae23ad1e589d4b0c955b93f28ba4333e
This commit is contained in:
233
core/java/android/app/usage/NetworkStatsManager.java
Normal file
233
core/java/android/app/usage/NetworkStatsManager.java
Normal file
@@ -0,0 +1,233 @@
|
||||
/**
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package android.app.usage;
|
||||
|
||||
import android.app.usage.NetworkUsageStats.Bucket;
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkIdentity;
|
||||
import android.net.NetworkTemplate;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Provides access to network usage history and statistics. Usage data is collected in
|
||||
* discrete bins of time called 'Buckets'. See {@link NetworkUsageStats.Bucket} for details.
|
||||
* <p />
|
||||
* Queries can define a time interval in the form of start and end timestamps (Long.MIN_VALUE and
|
||||
* Long.MAX_VALUE can be used to simulate open ended intervals). All queries (except
|
||||
* {@link #querySummaryForDevice}) collect only network usage of apps belonging to the same user
|
||||
* as the client. In addition tethering usage, usage by removed users and apps, and usage by system
|
||||
* is also included in the results.
|
||||
* <h3>
|
||||
* Summary queries
|
||||
* </h3>
|
||||
* These queries aggregate network usage across the whole interval. Therefore there will be only one
|
||||
* bucket for a particular key and state combination. In case of the user-wide and device-wide
|
||||
* summaries a single bucket containing the totalised network usage is returned.
|
||||
* <h3>
|
||||
* History queries
|
||||
* </h3>
|
||||
* These queries do not aggregate over time but do aggregate over state. Therefore there can be
|
||||
* multiple buckets for a particular key but all Bucket's state is going to be
|
||||
* {@link NetworkUsageStats.Bucket#STATE_ALL}.
|
||||
* <p />
|
||||
* <b>NOTE:</b> This API requires the permission
|
||||
* {@link android.Manifest.permission#PACKAGE_USAGE_STATS}, which is a system-level permission and
|
||||
* will not be granted to third-party apps. However, declaring the permission implies intention to
|
||||
* use the API and the user of the device can grant permission through the Settings application.
|
||||
* Profile owner apps are automatically granted permission to query data on the profile they manage
|
||||
* (that is, for any query except {@link #querySummaryForDevice}). Device owner apps likewise get
|
||||
* access to usage data of the primary user.
|
||||
*/
|
||||
public class NetworkStatsManager {
|
||||
private final static String TAG = "NetworkStatsManager";
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public NetworkStatsManager(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
/**
|
||||
* Query network usage statistics summaries. Result is summarised data usage for the whole
|
||||
* device. Result is a single Bucket aggregated over time, state and uid.
|
||||
*
|
||||
* @param networkType As defined in {@link ConnectivityManager}, e.g.
|
||||
* {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
|
||||
* etc.
|
||||
* @param subscriberId If applicable, the subscriber id of the network interface.
|
||||
* @param startTime Start of period. Defined in terms of "Unix time", see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @param endTime End of period. Defined in terms of "Unix time", see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @return Bucket object or null if permissions are insufficient or error happened during
|
||||
* statistics collection.
|
||||
*/
|
||||
public Bucket querySummaryForDevice(int networkType, String subscriberId,
|
||||
long startTime, long endTime) throws SecurityException, RemoteException {
|
||||
NetworkTemplate template = createTemplate(networkType, subscriberId);
|
||||
if (template == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Bucket bucket = null;
|
||||
NetworkUsageStats stats = new NetworkUsageStats(mContext, template, startTime, endTime);
|
||||
bucket = stats.getDeviceSummaryForNetwork(startTime, endTime);
|
||||
|
||||
stats.close();
|
||||
return bucket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query network usage statistics summaries. Result is summarised data usage for all uids
|
||||
* belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
|
||||
*
|
||||
* @param networkType As defined in {@link ConnectivityManager}, e.g.
|
||||
* {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
|
||||
* etc.
|
||||
* @param subscriberId If applicable, the subscriber id of the network interface.
|
||||
* @param startTime Start of period. Defined in terms of "Unix time", see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @param endTime End of period. Defined in terms of "Unix time", see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @return Bucket object or null if permissions are insufficient or error happened during
|
||||
* statistics collection.
|
||||
*/
|
||||
public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
|
||||
long endTime) throws SecurityException, RemoteException {
|
||||
NetworkTemplate template = createTemplate(networkType, subscriberId);
|
||||
if (template == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
NetworkUsageStats stats;
|
||||
stats = new NetworkUsageStats(mContext, template, startTime, endTime);
|
||||
stats.startSummaryEnumeration(startTime, endTime);
|
||||
|
||||
stats.close();
|
||||
return stats.getSummaryAggregate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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. Not aggregated over state or uid.
|
||||
*
|
||||
* @param networkType As defined in {@link ConnectivityManager}, e.g.
|
||||
* {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
|
||||
* etc.
|
||||
* @param subscriberId If applicable, the subscriber id of the network interface.
|
||||
* @param startTime Start of period. Defined in terms of "Unix time", see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @param endTime End of period. Defined in terms of "Unix time", see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @return Statistics object or null if permissions are insufficient or error happened during
|
||||
* statistics collection.
|
||||
*/
|
||||
public NetworkUsageStats querySummary(int networkType, String subscriberId, long startTime,
|
||||
long endTime) throws SecurityException, RemoteException {
|
||||
NetworkTemplate template = createTemplate(networkType, subscriberId);
|
||||
if (template == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
NetworkUsageStats result;
|
||||
result = new NetworkUsageStats(mContext, template, startTime, endTime);
|
||||
result.startSummaryEnumeration(startTime, endTime);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query network usage statistics details. Only usable for uids belonging to calling user.
|
||||
* Result is aggregated over state but not aggregated over time.
|
||||
*
|
||||
* @param networkType As defined in {@link ConnectivityManager}, e.g.
|
||||
* {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
|
||||
* etc.
|
||||
* @param subscriberId If applicable, the subscriber id of the network interface.
|
||||
* @param startTime Start of period. Defined in terms of "Unix time", see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @param endTime End of period. Defined in terms of "Unix time", see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @param uid UID of app
|
||||
* @return Statistics object or null if permissions are insufficient or error happened during
|
||||
* statistics collection.
|
||||
*/
|
||||
public NetworkUsageStats queryDetailsForUid(int networkType, String subscriberId,
|
||||
long startTime, long endTime, int uid) throws SecurityException, RemoteException {
|
||||
NetworkTemplate template = createTemplate(networkType, subscriberId);
|
||||
if (template == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
NetworkUsageStats result;
|
||||
result = new NetworkUsageStats(mContext, template, startTime, endTime);
|
||||
result.startHistoryEnumeration(uid);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query network usage statistics details. Result filtered to include only uids belonging to
|
||||
* calling user. Result is aggregated over state but not aggregated over time or uid.
|
||||
*
|
||||
* @param networkType As defined in {@link ConnectivityManager}, e.g.
|
||||
* {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
|
||||
* etc.
|
||||
* @param subscriberId If applicable, the subscriber id of the network interface.
|
||||
* @param startTime Start of period. Defined in terms of "Unix time", see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @param endTime End of period. Defined in terms of "Unix time", see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @return Statistics object or null if permissions are insufficient or error happened during
|
||||
* statistics collection.
|
||||
*/
|
||||
public NetworkUsageStats queryDetails(int networkType, String subscriberId, long startTime,
|
||||
long endTime) throws SecurityException, RemoteException {
|
||||
NetworkTemplate template = createTemplate(networkType, subscriberId);
|
||||
if (template == null) {
|
||||
return null;
|
||||
}
|
||||
NetworkUsageStats result;
|
||||
result = new NetworkUsageStats(mContext, template, startTime, endTime);
|
||||
result.startUserUidEnumeration();
|
||||
return result;
|
||||
}
|
||||
|
||||
private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
|
||||
NetworkTemplate template = null;
|
||||
switch (networkType) {
|
||||
case ConnectivityManager.TYPE_MOBILE: {
|
||||
template = NetworkTemplate.buildTemplateMobileAll(subscriberId);
|
||||
} break;
|
||||
case ConnectivityManager.TYPE_WIFI: {
|
||||
template = NetworkTemplate.buildTemplateWifiWildcard();
|
||||
} break;
|
||||
default: {
|
||||
Log.w(TAG, "Cannot create template for network type " + networkType
|
||||
+ ", subscriberId '" + NetworkIdentity.scrubSubscriberId(subscriberId) +
|
||||
"'.");
|
||||
}
|
||||
}
|
||||
return template;
|
||||
}
|
||||
}
|
||||
479
core/java/android/app/usage/NetworkUsageStats.java
Normal file
479
core/java/android/app/usage/NetworkUsageStats.java
Normal file
@@ -0,0 +1,479 @@
|
||||
/**
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package android.app.usage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.INetworkStatsService;
|
||||
import android.net.INetworkStatsSession;
|
||||
import android.net.NetworkStats;
|
||||
import android.net.NetworkStatsHistory;
|
||||
import android.net.NetworkTemplate;
|
||||
import android.net.TrafficStats;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import dalvik.system.CloseGuard;
|
||||
|
||||
/**
|
||||
* Class providing enumeration over buckets of network usage statistics. NetworkUsageStats objects
|
||||
* are returned as results to various queries in {@link NetworkStatsManager}.
|
||||
*/
|
||||
public final class NetworkUsageStats implements AutoCloseable {
|
||||
private final static String TAG = "NetworkUsageStats";
|
||||
|
||||
private final CloseGuard mCloseGuard = CloseGuard.get();
|
||||
|
||||
/**
|
||||
* Start timestamp of stats collected
|
||||
*/
|
||||
private final long mStartTimeStamp;
|
||||
|
||||
/**
|
||||
* End timestamp of stats collected
|
||||
*/
|
||||
private final long mEndTimeStamp;
|
||||
|
||||
|
||||
/**
|
||||
* Non-null array indicates the query enumerates over uids.
|
||||
*/
|
||||
private int[] mUids;
|
||||
|
||||
/**
|
||||
* Index of the current uid in mUids when doing uid enumeration or a single uid value,
|
||||
* depending on query type.
|
||||
*/
|
||||
private int mUidOrUidIndex;
|
||||
|
||||
/**
|
||||
* The session while the query requires it, null if all the stats have been collected or close()
|
||||
* has been called.
|
||||
*/
|
||||
private INetworkStatsSession mSession;
|
||||
private NetworkTemplate mTemplate;
|
||||
|
||||
/**
|
||||
* Results of a summary query.
|
||||
*/
|
||||
private NetworkStats mSummary = null;
|
||||
|
||||
/**
|
||||
* Results of detail queries.
|
||||
*/
|
||||
private NetworkStatsHistory mHistory = null;
|
||||
|
||||
/**
|
||||
* Where we are in enumerating over the current result.
|
||||
*/
|
||||
private int mEnumerationIndex = 0;
|
||||
|
||||
/**
|
||||
* Recycling entry objects to prevent heap fragmentation.
|
||||
*/
|
||||
private NetworkStats.Entry mRecycledSummaryEntry = null;
|
||||
private NetworkStatsHistory.Entry mRecycledHistoryEntry = null;
|
||||
|
||||
/** @hide */
|
||||
NetworkUsageStats(Context context, NetworkTemplate template, long startTimestamp,
|
||||
long endTimestamp) throws RemoteException, SecurityException {
|
||||
final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
|
||||
// Open network stats session
|
||||
mSession = statsService.openSessionForUsageStats(context.getOpPackageName());
|
||||
mCloseGuard.open("close");
|
||||
mTemplate = template;
|
||||
mStartTimeStamp = startTimestamp;
|
||||
mEndTimeStamp = endTimestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
if (mCloseGuard != null) {
|
||||
mCloseGuard.warnIfOpen();
|
||||
}
|
||||
close();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------BEGINNING OF PUBLIC API-----------------------------------
|
||||
|
||||
/**
|
||||
* Buckets are the smallest elements of a query result. As some dimensions of a result may be
|
||||
* aggregated (e.g. time or state) some values may be equal across all buckets.
|
||||
*/
|
||||
public static class Bucket {
|
||||
/**
|
||||
* Combined usage across all other states.
|
||||
*/
|
||||
public static final int STATE_ALL = -1;
|
||||
|
||||
/**
|
||||
* Usage not accounted in any other states.
|
||||
*/
|
||||
public static final int STATE_DEFAULT = 0x1;
|
||||
|
||||
/**
|
||||
* Foreground usage.
|
||||
*/
|
||||
public static final int STATE_FOREGROUND = 0x2;
|
||||
|
||||
/**
|
||||
* Special UID value for removed apps.
|
||||
*/
|
||||
public static final int UID_REMOVED = -4;
|
||||
|
||||
/**
|
||||
* Special UID value for data usage by tethering.
|
||||
*/
|
||||
public static final int UID_TETHERING = -5;
|
||||
|
||||
private int mUid;
|
||||
private int mState;
|
||||
private long mBeginTimeStamp;
|
||||
private long mEndTimeStamp;
|
||||
private long mRxBytes;
|
||||
private long mRxPackets;
|
||||
private long mTxBytes;
|
||||
private long mTxPackets;
|
||||
|
||||
private static int convertState(int networkStatsSet) {
|
||||
switch (networkStatsSet) {
|
||||
case NetworkStats.SET_ALL : return STATE_ALL;
|
||||
case NetworkStats.SET_DEFAULT : return STATE_DEFAULT;
|
||||
case NetworkStats.SET_FOREGROUND : return STATE_FOREGROUND;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int convertUid(int uid) {
|
||||
switch (uid) {
|
||||
case TrafficStats.UID_REMOVED: return UID_REMOVED;
|
||||
case TrafficStats.UID_TETHERING: return UID_TETHERING;
|
||||
}
|
||||
return uid;
|
||||
}
|
||||
|
||||
public Bucket() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Key of the bucket. Usually an app uid or one of the following special values:<p />
|
||||
* <ul>
|
||||
* <li>{@link #UID_REMOVED}</li>
|
||||
* <li>{@link #UID_TETHERING}</li>
|
||||
* <li>{@link android.os.Process#SYSTEM_UID}</li>
|
||||
* </ul>
|
||||
* @return Bucket key.
|
||||
*/
|
||||
public int getUid() {
|
||||
return mUid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Usage state. One of the following values:<p/>
|
||||
* <ul>
|
||||
* <li>{@link #STATE_ALL}</li>
|
||||
* <li>{@link #STATE_DEFAULT}</li>
|
||||
* <li>{@link #STATE_FOREGROUND}</li>
|
||||
* </ul>
|
||||
* @return Usage state.
|
||||
*/
|
||||
public int getState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start timestamp of the bucket's time interval. Defined in terms of "Unix time", see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @return Start of interval.
|
||||
*/
|
||||
public long getStartTimeStamp() {
|
||||
return mBeginTimeStamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* End timestamp of the bucket's time interval. Defined in terms of "Unix time", see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @return End of interval.
|
||||
*/
|
||||
public long getEndTimeStamp() {
|
||||
return mEndTimeStamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of bytes received during the bucket's time interval. Statistics are measured at
|
||||
* the network layer, so they include both TCP and UDP usage.
|
||||
* @return Number of bytes.
|
||||
*/
|
||||
public long getRxBytes() {
|
||||
return mRxBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of bytes transmitted during the bucket's time interval. Statistics are measured at
|
||||
* the network layer, so they include both TCP and UDP usage.
|
||||
* @return Number of bytes.
|
||||
*/
|
||||
public long getTxBytes() {
|
||||
return mTxBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of packets received during the bucket's time interval. Statistics are measured at
|
||||
* the network layer, so they include both TCP and UDP usage.
|
||||
* @return Number of packets.
|
||||
*/
|
||||
public long getRxPackets() {
|
||||
return mRxPackets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of packets transmitted during the bucket's time interval. Statistics are measured
|
||||
* at the network layer, so they include both TCP and UDP usage.
|
||||
* @return Number of packets.
|
||||
*/
|
||||
public long getTxPackets() {
|
||||
return mTxPackets;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills the recycled bucket with data of the next bin in the enumeration.
|
||||
* @param bucketOut Bucket to be filled with data.
|
||||
* @return true if successfully filled the bucket, false otherwise.
|
||||
*/
|
||||
public boolean getNextBucket(Bucket bucketOut) {
|
||||
if (mSummary != null) {
|
||||
return getNextSummaryBucket(bucketOut);
|
||||
} else {
|
||||
return getNextHistoryBucket(bucketOut);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if it is possible to ask for a next bucket in the enumeration.
|
||||
* @return true if there is at least one more bucket.
|
||||
*/
|
||||
public boolean hasNextBucket() {
|
||||
if (mSummary != null) {
|
||||
return mEnumerationIndex < mSummary.size();
|
||||
} else if (mHistory != null) {
|
||||
return mEnumerationIndex < mHistory.size()
|
||||
|| hasNextUid();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the enumeration. Call this method before this object gets out of scope.
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
if (mSession != null) {
|
||||
try {
|
||||
mSession.close();
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, e);
|
||||
// Otherwise, meh
|
||||
}
|
||||
}
|
||||
mSession = null;
|
||||
if (mCloseGuard != null) {
|
||||
mCloseGuard.close();
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------END OF PUBLIC API-----------------------------------
|
||||
|
||||
/**
|
||||
* Collects device summary results into a Bucket.
|
||||
* @param startTime
|
||||
* @param endTime
|
||||
* @throws RemoteException
|
||||
*/
|
||||
Bucket getDeviceSummaryForNetwork(long startTime, long endTime) throws RemoteException {
|
||||
mSummary = mSession.getDeviceSummaryForNetwork(mTemplate, startTime, endTime);
|
||||
|
||||
// Setting enumeration index beyond end to avoid accidental enumeration over data that does
|
||||
// not belong to the calling user.
|
||||
mEnumerationIndex = mSummary.size();
|
||||
|
||||
return getSummaryAggregate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects summary results and sets summary enumeration mode.
|
||||
* @param startTime
|
||||
* @param endTime
|
||||
* @throws RemoteException
|
||||
*/
|
||||
void startSummaryEnumeration(long startTime, long endTime) throws RemoteException {
|
||||
mSummary = mSession.getSummaryForAllUid(mTemplate, startTime, endTime, false);
|
||||
|
||||
mEnumerationIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects history results for uid and resets history enumeration index.
|
||||
*/
|
||||
void startHistoryEnumeration(int uid) {
|
||||
mHistory = null;
|
||||
try {
|
||||
mHistory = mSession.getHistoryForUid(mTemplate, uid, NetworkStats.SET_ALL,
|
||||
NetworkStats.TAG_NONE, NetworkStatsHistory.FIELD_ALL);
|
||||
setSingleUid(uid);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, e);
|
||||
// Leaving mHistory null
|
||||
}
|
||||
mEnumerationIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts uid enumeration for current user.
|
||||
* @throws RemoteException
|
||||
*/
|
||||
void startUserUidEnumeration() throws RemoteException {
|
||||
setUidEnumeration(mSession.getRelevantUids());
|
||||
stepHistory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Steps to next uid in enumeration and collects history for that.
|
||||
*/
|
||||
private void stepHistory(){
|
||||
if (hasNextUid()) {
|
||||
stepUid();
|
||||
mHistory = null;
|
||||
try {
|
||||
mHistory = mSession.getHistoryForUid(mTemplate, getUid(), NetworkStats.SET_ALL,
|
||||
NetworkStats.TAG_NONE, NetworkStatsHistory.FIELD_ALL);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, e);
|
||||
// Leaving mHistory null
|
||||
}
|
||||
mEnumerationIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void fillBucketFromSummaryEntry(Bucket bucketOut) {
|
||||
bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid);
|
||||
bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set);
|
||||
bucketOut.mBeginTimeStamp = mStartTimeStamp;
|
||||
bucketOut.mEndTimeStamp = mEndTimeStamp;
|
||||
bucketOut.mRxBytes = mRecycledSummaryEntry.rxBytes;
|
||||
bucketOut.mRxPackets = mRecycledSummaryEntry.rxPackets;
|
||||
bucketOut.mTxBytes = mRecycledSummaryEntry.txBytes;
|
||||
bucketOut.mTxPackets = mRecycledSummaryEntry.txPackets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getting the next item in summary enumeration.
|
||||
* @param bucketOut Next item will be set here.
|
||||
* @return true if a next item could be set.
|
||||
*/
|
||||
private boolean getNextSummaryBucket(Bucket bucketOut) {
|
||||
if (bucketOut != null && mEnumerationIndex < mSummary.size()) {
|
||||
mRecycledSummaryEntry = mSummary.getValues(mEnumerationIndex++, mRecycledSummaryEntry);
|
||||
fillBucketFromSummaryEntry(bucketOut);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Bucket getSummaryAggregate() {
|
||||
if (mSummary == null) {
|
||||
return null;
|
||||
}
|
||||
Bucket bucket = new Bucket();
|
||||
if (mRecycledSummaryEntry == null) {
|
||||
mRecycledSummaryEntry = new NetworkStats.Entry();
|
||||
}
|
||||
mSummary.getTotal(mRecycledSummaryEntry);
|
||||
fillBucketFromSummaryEntry(bucket);
|
||||
return bucket;
|
||||
}
|
||||
/**
|
||||
* Getting the next item in a history enumeration.
|
||||
* @param bucketOut Next item will be set here.
|
||||
* @return true if a next item could be set.
|
||||
*/
|
||||
private boolean getNextHistoryBucket(Bucket bucketOut) {
|
||||
if (bucketOut != null && mHistory != null) {
|
||||
if (mEnumerationIndex < mHistory.size()) {
|
||||
mRecycledHistoryEntry = mHistory.getValues(mEnumerationIndex++,
|
||||
mRecycledHistoryEntry);
|
||||
bucketOut.mUid = Bucket.convertUid(getUid());
|
||||
bucketOut.mState = Bucket.STATE_ALL;
|
||||
bucketOut.mBeginTimeStamp = mRecycledHistoryEntry.bucketStart;
|
||||
bucketOut.mEndTimeStamp = mRecycledHistoryEntry.bucketStart +
|
||||
mRecycledHistoryEntry.bucketDuration;
|
||||
bucketOut.mRxBytes = mRecycledHistoryEntry.rxBytes;
|
||||
bucketOut.mRxPackets = mRecycledHistoryEntry.rxPackets;
|
||||
bucketOut.mTxBytes = mRecycledHistoryEntry.txBytes;
|
||||
bucketOut.mTxPackets = mRecycledHistoryEntry.txPackets;
|
||||
return true;
|
||||
} else if (hasNextUid()) {
|
||||
stepHistory();
|
||||
return getNextHistoryBucket(bucketOut);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------ UID LOGIC------------------------
|
||||
|
||||
private boolean isUidEnumeration() {
|
||||
return mUids != null;
|
||||
}
|
||||
|
||||
private boolean hasNextUid() {
|
||||
return isUidEnumeration() && (mUidOrUidIndex + 1) < mUids.length;
|
||||
}
|
||||
|
||||
private int getUid() {
|
||||
// Check if uid enumeration.
|
||||
if (isUidEnumeration()) {
|
||||
if (mUidOrUidIndex < 0 || mUidOrUidIndex >= mUids.length) {
|
||||
throw new IndexOutOfBoundsException(
|
||||
"Index=" + mUidOrUidIndex + " mUids.length=" + mUids.length);
|
||||
}
|
||||
return mUids[mUidOrUidIndex];
|
||||
}
|
||||
// Single uid mode.
|
||||
return mUidOrUidIndex;
|
||||
}
|
||||
|
||||
private void setSingleUid(int uid) {
|
||||
mUidOrUidIndex = uid;
|
||||
}
|
||||
|
||||
private void setUidEnumeration(int[] uids) {
|
||||
mUids = uids;
|
||||
mUidOrUidIndex = -1;
|
||||
}
|
||||
|
||||
private void stepUid() {
|
||||
if (mUids != null) {
|
||||
++mUidOrUidIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,14 @@ interface INetworkStatsService {
|
||||
/** Start a statistics query session. */
|
||||
INetworkStatsSession openSession();
|
||||
|
||||
/** Start a statistics query session. If calling package is profile or device owner then it is
|
||||
* granted automatic access if apiLevel is NetworkStatsManager.API_LEVEL_DPC_ALLOWED. If
|
||||
* apiLevel is at least NetworkStatsManager.API_LEVEL_REQUIRES_PACKAGE_USAGE_STATS then
|
||||
* PACKAGE_USAGE_STATS permission is always checked. If PACKAGE_USAGE_STATS is not granted
|
||||
* READ_NETWORK_USAGE_STATS is checked for.
|
||||
*/
|
||||
INetworkStatsSession openSessionForUsageStats(String callingPackage);
|
||||
|
||||
/** Return network layer usage total for traffic that matches template. */
|
||||
long getNetworkTotalBytes(in NetworkTemplate template, long start, long end);
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@ import android.net.NetworkTemplate;
|
||||
/** {@hide} */
|
||||
interface INetworkStatsSession {
|
||||
|
||||
/** Return device aggregated network layer usage summary for traffic that matches template. */
|
||||
NetworkStats getDeviceSummaryForNetwork(in NetworkTemplate template, long start, long end);
|
||||
|
||||
/** Return network layer usage summary for traffic that matches template. */
|
||||
NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end);
|
||||
/** Return historical network layer stats for traffic that matches template. */
|
||||
@@ -33,6 +36,9 @@ interface INetworkStatsSession {
|
||||
/** Return historical network layer stats for specific UID traffic that matches template. */
|
||||
NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int set, int tag, int fields);
|
||||
|
||||
/** Return array of uids that have stats and are accessible to the calling user */
|
||||
int[] getRelevantUids();
|
||||
|
||||
void close();
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user