|
23 | 23 | import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; |
24 | 24 | import static android.content.Intent.ACTION_SHUTDOWN; |
25 | 25 | import static android.content.Intent.ACTION_UID_REMOVED; |
| 26 | +import static android.content.Intent.ACTION_USER_REMOVED; |
26 | 27 | import static android.content.Intent.EXTRA_UID; |
27 | 28 | import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; |
28 | 29 | import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; |
|
76 | 77 | import android.content.Context; |
77 | 78 | import android.content.Intent; |
78 | 79 | import android.content.IntentFilter; |
| 80 | +import android.content.pm.ApplicationInfo; |
| 81 | +import android.content.pm.PackageManager; |
79 | 82 | import android.net.IConnectivityManager; |
80 | 83 | import android.net.INetworkManagementEventObserver; |
81 | 84 | import android.net.INetworkStatsService; |
|
112 | 115 | import android.util.SparseIntArray; |
113 | 116 | import android.util.TrustedTime; |
114 | 117 |
|
| 118 | +import com.android.internal.util.ArrayUtils; |
115 | 119 | import com.android.internal.util.FileRotator; |
116 | 120 | import com.android.internal.util.IndentingPrintWriter; |
117 | 121 | import com.android.server.EventLogTags; |
|
122 | 126 | import java.io.FileDescriptor; |
123 | 127 | import java.io.IOException; |
124 | 128 | import java.io.PrintWriter; |
| 129 | +import java.util.Arrays; |
125 | 130 | import java.util.HashMap; |
126 | 131 | import java.util.HashSet; |
| 132 | +import java.util.List; |
127 | 133 |
|
128 | 134 | /** |
129 | 135 | * Collect and persist detailed network statistics, and provide this data to |
@@ -322,6 +328,10 @@ public void systemReady() { |
322 | 328 | final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED); |
323 | 329 | mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler); |
324 | 330 |
|
| 331 | + // listen for user changes to clean stats |
| 332 | + final IntentFilter userFilter = new IntentFilter(ACTION_USER_REMOVED); |
| 333 | + mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler); |
| 334 | + |
325 | 335 | // persist stats during clean shutdown |
326 | 336 | final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN); |
327 | 337 | mContext.registerReceiver(mShutdownReceiver, shutdownFilter); |
@@ -739,11 +749,34 @@ public void onReceive(Context context, Intent intent) { |
739 | 749 | public void onReceive(Context context, Intent intent) { |
740 | 750 | // on background handler thread, and UID_REMOVED is protected |
741 | 751 | // broadcast. |
742 | | - final int uid = intent.getIntExtra(EXTRA_UID, 0); |
| 752 | + |
| 753 | + final int uid = intent.getIntExtra(EXTRA_UID, -1); |
| 754 | + if (uid == -1) return; |
| 755 | + |
| 756 | + synchronized (mStatsLock) { |
| 757 | + mWakeLock.acquire(); |
| 758 | + try { |
| 759 | + removeUidsLocked(uid); |
| 760 | + } finally { |
| 761 | + mWakeLock.release(); |
| 762 | + } |
| 763 | + } |
| 764 | + } |
| 765 | + }; |
| 766 | + |
| 767 | + private BroadcastReceiver mUserReceiver = new BroadcastReceiver() { |
| 768 | + @Override |
| 769 | + public void onReceive(Context context, Intent intent) { |
| 770 | + // On background handler thread, and USER_REMOVED is protected |
| 771 | + // broadcast. |
| 772 | + |
| 773 | + final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); |
| 774 | + if (userId == -1) return; |
| 775 | + |
743 | 776 | synchronized (mStatsLock) { |
744 | 777 | mWakeLock.acquire(); |
745 | 778 | try { |
746 | | - removeUidLocked(uid); |
| 779 | + removeUserLocked(userId); |
747 | 780 | } finally { |
748 | 781 | mWakeLock.release(); |
749 | 782 | } |
@@ -1034,15 +1067,37 @@ private void performSampleLocked() { |
1034 | 1067 | /** |
1035 | 1068 | * Clean up {@link #mUidRecorder} after UID is removed. |
1036 | 1069 | */ |
1037 | | - private void removeUidLocked(int uid) { |
1038 | | - // perform one last poll before removing |
| 1070 | + private void removeUidsLocked(int... uids) { |
| 1071 | + if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids)); |
| 1072 | + |
| 1073 | + // Perform one last poll before removing |
1039 | 1074 | performPollLocked(FLAG_PERSIST_ALL); |
1040 | 1075 |
|
1041 | | - mUidRecorder.removeUidLocked(uid); |
1042 | | - mUidTagRecorder.removeUidLocked(uid); |
| 1076 | + mUidRecorder.removeUidsLocked(uids); |
| 1077 | + mUidTagRecorder.removeUidsLocked(uids); |
| 1078 | + |
| 1079 | + // Clear kernel stats associated with UID |
| 1080 | + for (int uid : uids) { |
| 1081 | + resetKernelUidStats(uid); |
| 1082 | + } |
| 1083 | + } |
| 1084 | + |
| 1085 | + /** |
| 1086 | + * Clean up {@link #mUidRecorder} after user is removed. |
| 1087 | + */ |
| 1088 | + private void removeUserLocked(int userId) { |
| 1089 | + if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId); |
| 1090 | + |
| 1091 | + // Build list of UIDs that we should clean up |
| 1092 | + int[] uids = new int[0]; |
| 1093 | + final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications( |
| 1094 | + PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS); |
| 1095 | + for (ApplicationInfo app : apps) { |
| 1096 | + final int uid = UserHandle.getUid(userId, app.uid); |
| 1097 | + uids = ArrayUtils.appendInt(uids, uid); |
| 1098 | + } |
1043 | 1099 |
|
1044 | | - // clear kernel stats associated with UID |
1045 | | - resetKernelUidStats(uid); |
| 1100 | + removeUidsLocked(uids); |
1046 | 1101 | } |
1047 | 1102 |
|
1048 | 1103 | @Override |
|
0 commit comments