Handle removed UIDs in network stats and policy.
When UID_REMOVED, clean up any existing UID network policy so it doesn't linger for future apps. Also move any NetworkStatsHistory to special UID_REMOVED tracking bucket. Tests for new removal code. Also test detailed UID stats, including network changes to verify template matching logic. Bug: 4584212 Change-Id: I9faadf6b6f3830eb45d86c7f1980a27cdbcdb11e
This commit is contained in:
@@ -95,9 +95,13 @@ public class NetworkIdentity {
|
|||||||
|
|
||||||
final String subscriberId;
|
final String subscriberId;
|
||||||
if (isNetworkTypeMobile(type)) {
|
if (isNetworkTypeMobile(type)) {
|
||||||
|
if (state.subscriberId != null) {
|
||||||
|
subscriberId = state.subscriberId;
|
||||||
|
} else {
|
||||||
final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
|
final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
|
||||||
Context.TELEPHONY_SERVICE);
|
Context.TELEPHONY_SERVICE);
|
||||||
subscriberId = telephony.getSubscriberId();
|
subscriberId = telephony.getSubscriberId();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
subscriberId = null;
|
subscriberId = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,14 @@ public class TrafficStats {
|
|||||||
*/
|
*/
|
||||||
public final static int UNSUPPORTED = -1;
|
public final static int UNSUPPORTED = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special UID value used when collecting {@link NetworkStatsHistory} for
|
||||||
|
* removed applications.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final int UID_REMOVED = -4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Snapshot of {@link NetworkStats} when the currently active profiling
|
* Snapshot of {@link NetworkStats} when the currently active profiling
|
||||||
* session started, or {@code null} if no session active.
|
* session started, or {@code null} if no session active.
|
||||||
|
|||||||
@@ -19,11 +19,14 @@ package com.android.server.net;
|
|||||||
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
|
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
|
||||||
import static android.Manifest.permission.DUMP;
|
import static android.Manifest.permission.DUMP;
|
||||||
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
|
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
|
||||||
import static android.Manifest.permission.SHUTDOWN;
|
import static android.content.Intent.ACTION_SHUTDOWN;
|
||||||
|
import static android.content.Intent.ACTION_UID_REMOVED;
|
||||||
|
import static android.content.Intent.EXTRA_UID;
|
||||||
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
|
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
|
||||||
import static android.net.NetworkStats.IFACE_ALL;
|
import static android.net.NetworkStats.IFACE_ALL;
|
||||||
import static android.net.NetworkStats.TAG_NONE;
|
import static android.net.NetworkStats.TAG_NONE;
|
||||||
import static android.net.NetworkStats.UID_ALL;
|
import static android.net.NetworkStats.UID_ALL;
|
||||||
|
import static android.net.TrafficStats.UID_REMOVED;
|
||||||
import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
|
import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
|
||||||
import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
|
import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
|
||||||
import static android.provider.Settings.Secure.NETSTATS_PERSIST_THRESHOLD;
|
import static android.provider.Settings.Secure.NETSTATS_PERSIST_THRESHOLD;
|
||||||
@@ -206,17 +209,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// watch for network interfaces to be claimed
|
// watch for network interfaces to be claimed
|
||||||
final IntentFilter ifaceFilter = new IntentFilter();
|
final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
|
||||||
ifaceFilter.addAction(CONNECTIVITY_ACTION);
|
mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
|
||||||
mContext.registerReceiver(mIfaceReceiver, ifaceFilter, CONNECTIVITY_INTERNAL, mHandler);
|
|
||||||
|
|
||||||
// listen for periodic polling events
|
// listen for periodic polling events
|
||||||
final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
|
final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
|
||||||
mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
|
mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
|
||||||
|
|
||||||
|
// listen for uid removal to clean stats
|
||||||
|
final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
|
||||||
|
mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
|
||||||
|
|
||||||
// persist stats during clean shutdown
|
// persist stats during clean shutdown
|
||||||
final IntentFilter shutdownFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
|
final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN);
|
||||||
mContext.registerReceiver(mShutdownReceiver, shutdownFilter, SHUTDOWN, null);
|
mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
registerPollAlarmLocked();
|
registerPollAlarmLocked();
|
||||||
@@ -226,8 +232,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void shutdownLocked() {
|
private void shutdownLocked() {
|
||||||
mContext.unregisterReceiver(mIfaceReceiver);
|
mContext.unregisterReceiver(mConnReceiver);
|
||||||
mContext.unregisterReceiver(mPollReceiver);
|
mContext.unregisterReceiver(mPollReceiver);
|
||||||
|
mContext.unregisterReceiver(mRemovedReceiver);
|
||||||
mContext.unregisterReceiver(mShutdownReceiver);
|
mContext.unregisterReceiver(mShutdownReceiver);
|
||||||
|
|
||||||
writeNetworkStatsLocked();
|
writeNetworkStatsLocked();
|
||||||
@@ -352,7 +359,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
* interfaces. Used to associate {@link TelephonyManager#getSubscriberId()}
|
* interfaces. Used to associate {@link TelephonyManager#getSubscriberId()}
|
||||||
* with mobile interfaces.
|
* with mobile interfaces.
|
||||||
*/
|
*/
|
||||||
private BroadcastReceiver mIfaceReceiver = new BroadcastReceiver() {
|
private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
// on background handler thread, and verified CONNECTIVITY_INTERNAL
|
// on background handler thread, and verified CONNECTIVITY_INTERNAL
|
||||||
@@ -375,10 +382,22 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
// on background handler thread, and UID_REMOVED is protected
|
||||||
|
// broadcast.
|
||||||
|
final int uid = intent.getIntExtra(EXTRA_UID, 0);
|
||||||
|
synchronized (mStatsLock) {
|
||||||
|
removeUidLocked(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
|
private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
// verified SHUTDOWN permission above.
|
// SHUTDOWN is protected broadcast.
|
||||||
synchronized (mStatsLock) {
|
synchronized (mStatsLock) {
|
||||||
shutdownLocked();
|
shutdownLocked();
|
||||||
}
|
}
|
||||||
@@ -545,6 +564,31 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
mLastUidPoll = uidStats;
|
mLastUidPoll = uidStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up {@link #mUidStats} after UID is removed.
|
||||||
|
*/
|
||||||
|
private void removeUidLocked(int uid) {
|
||||||
|
ensureUidStatsLoadedLocked();
|
||||||
|
|
||||||
|
// migrate all UID stats into special "removed" bucket
|
||||||
|
for (NetworkIdentitySet ident : mUidStats.keySet()) {
|
||||||
|
final SparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
|
||||||
|
final NetworkStatsHistory uidHistory = uidStats.get(uid);
|
||||||
|
if (uidHistory != null) {
|
||||||
|
final NetworkStatsHistory removedHistory = findOrCreateUidStatsLocked(
|
||||||
|
ident, UID_REMOVED);
|
||||||
|
removedHistory.recordEntireHistory(uidHistory);
|
||||||
|
uidStats.remove(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: push kernel event to wipe stats for UID, otherwise we risk
|
||||||
|
// picking them up again during next poll.
|
||||||
|
|
||||||
|
// since this was radical rewrite, push to disk
|
||||||
|
writeUidStatsLocked();
|
||||||
|
}
|
||||||
|
|
||||||
private NetworkStatsHistory findOrCreateNetworkStatsLocked(NetworkIdentitySet ident) {
|
private NetworkStatsHistory findOrCreateNetworkStatsLocked(NetworkIdentitySet ident) {
|
||||||
final long bucketDuration = mSettings.getNetworkBucketDuration();
|
final long bucketDuration = mSettings.getNetworkBucketDuration();
|
||||||
final NetworkStatsHistory existing = mNetworkStats.get(ident);
|
final NetworkStatsHistory existing = mNetworkStats.get(ident);
|
||||||
@@ -568,6 +612,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private NetworkStatsHistory findOrCreateUidStatsLocked(NetworkIdentitySet ident, int uid) {
|
private NetworkStatsHistory findOrCreateUidStatsLocked(NetworkIdentitySet ident, int uid) {
|
||||||
|
ensureUidStatsLoadedLocked();
|
||||||
|
|
||||||
// find bucket for identity first, then find uid
|
// find bucket for identity first, then find uid
|
||||||
SparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
|
SparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
|
||||||
if (uidStats == null) {
|
if (uidStats == null) {
|
||||||
@@ -734,6 +780,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
private void writeUidStatsLocked() {
|
private void writeUidStatsLocked() {
|
||||||
if (LOGV) Slog.v(TAG, "writeUidStatsLocked()");
|
if (LOGV) Slog.v(TAG, "writeUidStatsLocked()");
|
||||||
|
|
||||||
|
if (!mUidStatsLoaded) {
|
||||||
|
Slog.w(TAG, "asked to write UID stats when not loaded; skipping");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: consider duplicating stats and releasing lock while writing
|
// TODO: consider duplicating stats and releasing lock while writing
|
||||||
|
|
||||||
FileOutputStream fos = null;
|
FileOutputStream fos = null;
|
||||||
|
|||||||
Reference in New Issue
Block a user