Add SDK sandbox network usage to corresponding apps.

SDK sandboxes run in a separate UID range. Their network usage should be
attributed to the corresponding app.

Make sure we collapse the usage collection of sandboxes to the
corresponding app UID in DataUsageList.

For AppDataUsage, make sure we add in the sandbox UID when being asked
to calculate data usage for a regular app UID. Invoke
DataUsageCycleLoader with all UIDs in AppItem, because there can now be
multiple UIDs associated with a regular app, too. Also make sure that
all new instances of AppItem for regular applications have their own
application UID.

Bug: 225319220
Test: manual
Change-Id: Id101a96ee4e3ba02376fa2ac64a9f9c2581acb61
This commit is contained in:
Martijn Coenen
2022-04-26 09:04:57 +00:00
parent b18b106300
commit bc9856104d
4 changed files with 38 additions and 14 deletions

View File

@@ -20,6 +20,7 @@ import android.content.Context;
import android.net.NetworkStats; import android.net.NetworkStats;
import android.net.NetworkTemplate; import android.net.NetworkTemplate;
import android.os.Bundle; import android.os.Bundle;
import android.os.Process;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.text.format.Formatter; import android.text.format.Formatter;
@@ -89,11 +90,19 @@ public class AppDataUsagePreferenceController extends AppInfoPreferenceControlle
@Override @Override
public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) { public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
final NetworkTemplate template = getTemplate(mContext); final NetworkTemplate template = getTemplate(mContext);
return NetworkCycleDataForUidLoader.builder(mContext) final int uid = mParent.getAppEntry().info.uid;
.addUid(mParent.getAppEntry().info.uid)
.setRetrieveDetail(false) final NetworkCycleDataForUidLoader.Builder builder =
.setNetworkTemplate(template) NetworkCycleDataForUidLoader.builder(mContext);
.build(); builder.setRetrieveDetail(false)
.setNetworkTemplate(template);
builder.addUid(uid);
if (Process.isApplicationUid(uid)) {
// Also add in network usage for the app's SDK sandbox
builder.addUid(Process.toSdkSandboxUid(uid));
}
return builder.build();
} }
@Override @Override

View File

@@ -25,6 +25,7 @@ import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.NetworkTemplate; import android.net.NetworkTemplate;
import android.os.Bundle; import android.os.Bundle;
import android.os.Process;
import android.os.UserHandle; import android.os.UserHandle;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
import android.util.ArraySet; import android.util.ArraySet;
@@ -140,6 +141,14 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC
} }
} }
if (mAppItem.key > 0 && UserHandle.isApp(mAppItem.key)) {
// In case we've been asked data usage for an app, automatically
// include data usage of the corresponding SDK sandbox
final int appSandboxUid = Process.toSdkSandboxUid(mAppItem.key);
if (!mAppItem.uids.get(appSandboxUid)) {
mAppItem.addUid(appSandboxUid);
}
}
mTotalUsage = findPreference(KEY_TOTAL_USAGE); mTotalUsage = findPreference(KEY_TOTAL_USAGE);
mForegroundUsage = findPreference(KEY_FOREGROUND_USAGE); mForegroundUsage = findPreference(KEY_FOREGROUND_USAGE);
mBackgroundUsage = findPreference(KEY_BACKGROUND_USAGE); mBackgroundUsage = findPreference(KEY_BACKGROUND_USAGE);
@@ -295,6 +304,10 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC
} }
private void addUid(int uid) { private void addUid(int uid) {
if (Process.isSdkSandboxUid(uid)) {
// For a sandbox process, get the associated app UID
uid = Process.getAppUidForSdkSandboxUid(uid);
}
String[] packages = mPackageManager.getPackagesForUid(uid); String[] packages = mPackageManager.getPackagesForUid(uid);
if (packages != null) { if (packages != null) {
for (int i = 0; i < packages.length; i++) { for (int i = 0; i < packages.length; i++) {
@@ -394,12 +407,8 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC
= NetworkCycleDataForUidLoader.builder(mContext); = NetworkCycleDataForUidLoader.builder(mContext);
builder.setRetrieveDetail(true) builder.setRetrieveDetail(true)
.setNetworkTemplate(mTemplate); .setNetworkTemplate(mTemplate);
if (mAppItem.category == AppItem.CATEGORY_USER) { for (int i = 0; i < mAppItem.uids.size(); i++) {
for (int i = 0; i < mAppItem.uids.size(); i++) { builder.addUid(mAppItem.uids.keyAt(i));
builder.addUid(mAppItem.uids.keyAt(i));
}
} else {
builder.addUid(mAppItem.key);
} }
if (mCycles != null) { if (mCycles != null) {
builder.setCycles(mCycles); builder.setCycles(mCycles);

View File

@@ -368,7 +368,7 @@ public class DataUsageList extends DataUsageBaseFragment
final int collapseKey; final int collapseKey;
final int category; final int category;
final int userId = UserHandle.getUserId(uid); final int userId = UserHandle.getUserId(uid);
if (UserHandle.isApp(uid)) { if (UserHandle.isApp(uid) || Process.isSdkSandboxUid(uid)) {
if (profiles.contains(new UserHandle(userId))) { if (profiles.contains(new UserHandle(userId))) {
if (userId != currentUserId) { if (userId != currentUserId) {
// Add to a managed user item. // Add to a managed user item.
@@ -376,8 +376,12 @@ public class DataUsageList extends DataUsageBaseFragment
largest = accumulate(managedKey, knownItems, bucket, largest = accumulate(managedKey, knownItems, bucket,
AppItem.CATEGORY_USER, items, largest); AppItem.CATEGORY_USER, items, largest);
} }
// Add to app item. // Map SDK sandbox back to its corresponding app
collapseKey = uid; if (Process.isSdkSandboxUid(uid)) {
collapseKey = Process.getAppUidForSdkSandboxUid(uid);
} else {
collapseKey = uid;
}
category = AppItem.CATEGORY_APP; category = AppItem.CATEGORY_APP;
} else { } else {
// If it is a removed user add it to the removed users' key // If it is a removed user add it to the removed users' key
@@ -415,6 +419,7 @@ public class DataUsageList extends DataUsageBaseFragment
if (item == null) { if (item == null) {
item = new AppItem(uid); item = new AppItem(uid);
item.total = -1; item.total = -1;
item.addUid(uid);
items.add(item); items.add(item);
knownItems.put(item.key, item); knownItems.put(item.key, item);
} }

View File

@@ -306,6 +306,7 @@ public class AppDataUsageTest {
final Context context = RuntimeEnvironment.application; final Context context = RuntimeEnvironment.application;
final int testUid = 123123; final int testUid = 123123;
final AppItem appItem = new AppItem(testUid); final AppItem appItem = new AppItem(testUid);
appItem.addUid(testUid);
appItem.category = AppItem.CATEGORY_APP; appItem.category = AppItem.CATEGORY_APP;
ReflectionHelpers.setField(mFragment, "mContext", context); ReflectionHelpers.setField(mFragment, "mContext", context);
ReflectionHelpers.setField(mFragment, "mAppItem", appItem); ReflectionHelpers.setField(mFragment, "mAppItem", appItem);