Data usage multi-user support.
Switch to storing policy per-user instead of per-app, meaning each user has control over their own set of apps. Summarize the usage of non-current users. Only allow owner to make changes to overall network policy. Hide auto-sync menu when viewing app details. Search for MANAGE_NETWORK_USAGE intent across all package names sharing a UID. Bug: 7121279, 5419594, 6978663 Change-Id: Ia70f04df70d27da27faccb947cd27021c628a41a
This commit is contained in:
@@ -48,6 +48,7 @@ import static com.android.internal.util.Preconditions.checkNotNull;
|
|||||||
import static com.android.settings.Utils.prepareCustomPreferencesList;
|
import static com.android.settings.Utils.prepareCustomPreferencesList;
|
||||||
|
|
||||||
import android.animation.LayoutTransition;
|
import android.animation.LayoutTransition;
|
||||||
|
import android.app.ActivityManager;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.DialogFragment;
|
import android.app.DialogFragment;
|
||||||
@@ -127,7 +128,6 @@ import android.widget.TabHost.TabSpec;
|
|||||||
import android.widget.TabWidget;
|
import android.widget.TabWidget;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.android.internal.telephony.Phone;
|
|
||||||
import com.android.internal.telephony.PhoneConstants;
|
import com.android.internal.telephony.PhoneConstants;
|
||||||
import com.android.settings.drawable.InsetBoundsDrawable;
|
import com.android.settings.drawable.InsetBoundsDrawable;
|
||||||
import com.android.settings.net.ChartData;
|
import com.android.settings.net.ChartData;
|
||||||
@@ -447,20 +447,24 @@ public class DataUsageSummary extends Fragment {
|
|||||||
public void onPrepareOptionsMenu(Menu menu) {
|
public void onPrepareOptionsMenu(Menu menu) {
|
||||||
final Context context = getActivity();
|
final Context context = getActivity();
|
||||||
final boolean appDetailMode = isAppDetailMode();
|
final boolean appDetailMode = isAppDetailMode();
|
||||||
|
final boolean isOwner = ActivityManager.getCurrentUser() == UserHandle.USER_OWNER;
|
||||||
|
|
||||||
mMenuDataRoaming = menu.findItem(R.id.data_usage_menu_roaming);
|
mMenuDataRoaming = menu.findItem(R.id.data_usage_menu_roaming);
|
||||||
mMenuDataRoaming.setVisible(hasReadyMobileRadio(context) && !appDetailMode);
|
mMenuDataRoaming.setVisible(hasReadyMobileRadio(context) && !appDetailMode);
|
||||||
mMenuDataRoaming.setChecked(getDataRoaming());
|
mMenuDataRoaming.setChecked(getDataRoaming());
|
||||||
|
mMenuDataRoaming.setVisible(isOwner);
|
||||||
|
|
||||||
mMenuRestrictBackground = menu.findItem(R.id.data_usage_menu_restrict_background);
|
mMenuRestrictBackground = menu.findItem(R.id.data_usage_menu_restrict_background);
|
||||||
mMenuRestrictBackground.setVisible(hasReadyMobileRadio(context) && !appDetailMode);
|
mMenuRestrictBackground.setVisible(hasReadyMobileRadio(context) && !appDetailMode);
|
||||||
mMenuRestrictBackground.setChecked(mPolicyManager.getRestrictBackground());
|
mMenuRestrictBackground.setChecked(mPolicyManager.getRestrictBackground());
|
||||||
|
mMenuRestrictBackground.setVisible(isOwner);
|
||||||
|
|
||||||
mMenuAutoSync = menu.findItem(R.id.data_usage_menu_auto_sync);
|
mMenuAutoSync = menu.findItem(R.id.data_usage_menu_auto_sync);
|
||||||
mMenuAutoSync.setChecked(ContentResolver.getMasterSyncAutomatically());
|
mMenuAutoSync.setChecked(ContentResolver.getMasterSyncAutomatically());
|
||||||
|
mMenuAutoSync.setVisible(isOwner && !appDetailMode);
|
||||||
|
|
||||||
final MenuItem split4g = menu.findItem(R.id.data_usage_menu_split_4g);
|
final MenuItem split4g = menu.findItem(R.id.data_usage_menu_split_4g);
|
||||||
split4g.setVisible(hasReadyMobile4gRadio(context) && !appDetailMode);
|
split4g.setVisible(hasReadyMobile4gRadio(context) && isOwner && !appDetailMode);
|
||||||
split4g.setChecked(isMobilePolicySplit());
|
split4g.setChecked(isMobilePolicySplit());
|
||||||
|
|
||||||
final MenuItem showWifi = menu.findItem(R.id.data_usage_menu_show_wifi);
|
final MenuItem showWifi = menu.findItem(R.id.data_usage_menu_show_wifi);
|
||||||
@@ -481,7 +485,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
|
|
||||||
final MenuItem metered = menu.findItem(R.id.data_usage_menu_metered);
|
final MenuItem metered = menu.findItem(R.id.data_usage_menu_metered);
|
||||||
if (hasReadyMobileRadio(context) || hasWifiRadio(context)) {
|
if (hasReadyMobileRadio(context) || hasWifiRadio(context)) {
|
||||||
metered.setVisible(!appDetailMode);
|
metered.setVisible(isOwner && !appDetailMode);
|
||||||
} else {
|
} else {
|
||||||
metered.setVisible(false);
|
metered.setVisible(false);
|
||||||
}
|
}
|
||||||
@@ -681,6 +685,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
|
|
||||||
final Context context = getActivity();
|
final Context context = getActivity();
|
||||||
final String currentTab = mTabHost.getCurrentTabTag();
|
final String currentTab = mTabHost.getCurrentTabTag();
|
||||||
|
final boolean isOwner = ActivityManager.getCurrentUser() == UserHandle.USER_OWNER;
|
||||||
|
|
||||||
if (currentTab == null) {
|
if (currentTab == null) {
|
||||||
Log.w(TAG, "no tab selected; hiding body");
|
Log.w(TAG, "no tab selected; hiding body");
|
||||||
@@ -695,7 +700,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
|
|
||||||
if (LOGD) Log.d(TAG, "updateBody() with currentTab=" + currentTab);
|
if (LOGD) Log.d(TAG, "updateBody() with currentTab=" + currentTab);
|
||||||
|
|
||||||
mDataEnabledView.setVisibility(View.VISIBLE);
|
mDataEnabledView.setVisibility(isOwner ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
// TODO: remove mobile tabs when SIM isn't ready
|
// TODO: remove mobile tabs when SIM isn't ready
|
||||||
final TelephonyManager tele = TelephonyManager.from(context);
|
final TelephonyManager tele = TelephonyManager.from(context);
|
||||||
@@ -774,8 +779,8 @@ public class DataUsageSummary extends Fragment {
|
|||||||
mChart.bindNetworkPolicy(null);
|
mChart.bindNetworkPolicy(null);
|
||||||
|
|
||||||
// show icon and all labels appearing under this app
|
// show icon and all labels appearing under this app
|
||||||
final int appId = mCurrentApp.appId;
|
final int uid = mCurrentApp.key;
|
||||||
final UidDetail detail = mUidDetailProvider.getUidDetail(appId, true);
|
final UidDetail detail = mUidDetailProvider.getUidDetail(uid, true);
|
||||||
mAppIcon.setImageDrawable(detail.icon);
|
mAppIcon.setImageDrawable(detail.icon);
|
||||||
|
|
||||||
mAppTitles.removeAllViews();
|
mAppTitles.removeAllViews();
|
||||||
@@ -788,14 +793,21 @@ public class DataUsageSummary extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// enable settings button when package provides it
|
// enable settings button when package provides it
|
||||||
// TODO: target torwards entire UID instead of just first package
|
final String[] packageNames = pm.getPackagesForUid(uid);
|
||||||
final String[] packageNames = pm.getPackagesForUid(appId);
|
|
||||||
if (packageNames != null && packageNames.length > 0) {
|
if (packageNames != null && packageNames.length > 0) {
|
||||||
mAppSettingsIntent = new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE);
|
mAppSettingsIntent = new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE);
|
||||||
mAppSettingsIntent.setPackage(packageNames[0]);
|
|
||||||
mAppSettingsIntent.addCategory(Intent.CATEGORY_DEFAULT);
|
mAppSettingsIntent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||||
|
|
||||||
final boolean matchFound = pm.resolveActivity(mAppSettingsIntent, 0) != null;
|
// Search for match across all packages
|
||||||
|
boolean matchFound = false;
|
||||||
|
for (String packageName : packageNames) {
|
||||||
|
mAppSettingsIntent.setPackage(packageName);
|
||||||
|
if (pm.resolveActivity(mAppSettingsIntent, 0) != null) {
|
||||||
|
matchFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mAppSettings.setEnabled(matchFound);
|
mAppSettings.setEnabled(matchFound);
|
||||||
mAppSettings.setVisibility(View.VISIBLE);
|
mAppSettings.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
@@ -806,7 +818,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
|
|
||||||
updateDetailData();
|
updateDetailData();
|
||||||
|
|
||||||
if (UserHandle.isApp(appId) && !mPolicyManager.getRestrictBackground()
|
if (UserHandle.isApp(uid) && !mPolicyManager.getRestrictBackground()
|
||||||
&& isBandwidthControlEnabled() && hasReadyMobileRadio(context)) {
|
&& isBandwidthControlEnabled() && hasReadyMobileRadio(context)) {
|
||||||
setPreferenceTitle(mAppRestrictView, R.string.data_usage_app_restrict_background);
|
setPreferenceTitle(mAppRestrictView, R.string.data_usage_app_restrict_background);
|
||||||
setPreferenceSummary(mAppRestrictView,
|
setPreferenceSummary(mAppRestrictView,
|
||||||
@@ -855,7 +867,8 @@ public class DataUsageSummary extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isNetworkPolicyModifiable(NetworkPolicy policy) {
|
private boolean isNetworkPolicyModifiable(NetworkPolicy policy) {
|
||||||
return policy != null && isBandwidthControlEnabled() && mDataEnabled.isChecked();
|
return policy != null && isBandwidthControlEnabled() && mDataEnabled.isChecked()
|
||||||
|
&& ActivityManager.getCurrentUser() == UserHandle.USER_OWNER;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isBandwidthControlEnabled() {
|
private boolean isBandwidthControlEnabled() {
|
||||||
@@ -886,16 +899,16 @@ public class DataUsageSummary extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean getAppRestrictBackground() {
|
private boolean getAppRestrictBackground() {
|
||||||
final int appId = mCurrentApp.appId;
|
final int uid = mCurrentApp.key;
|
||||||
final int uidPolicy = mPolicyManager.getAppPolicy(appId);
|
final int uidPolicy = mPolicyManager.getUidPolicy(uid);
|
||||||
return (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
|
return (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAppRestrictBackground(boolean restrictBackground) {
|
private void setAppRestrictBackground(boolean restrictBackground) {
|
||||||
if (LOGD) Log.d(TAG, "setAppRestrictBackground()");
|
if (LOGD) Log.d(TAG, "setAppRestrictBackground()");
|
||||||
final int appId = mCurrentApp.appId;
|
final int uid = mCurrentApp.key;
|
||||||
mPolicyManager.setAppPolicy(appId,
|
mPolicyManager.setUidPolicy(
|
||||||
restrictBackground ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE);
|
uid, restrictBackground ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE);
|
||||||
mAppRestrict.setChecked(restrictBackground);
|
mAppRestrict.setChecked(restrictBackground);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1080,7 +1093,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
// TODO: sigh, remove this hack once we understand 6450986
|
// TODO: sigh, remove this hack once we understand 6450986
|
||||||
if (mUidDetailProvider == null || app == null) return;
|
if (mUidDetailProvider == null || app == null) return;
|
||||||
|
|
||||||
final UidDetail detail = mUidDetailProvider.getUidDetail(app.appId, true);
|
final UidDetail detail = mUidDetailProvider.getUidDetail(app.key, true);
|
||||||
AppDetailsFragment.show(DataUsageSummary.this, app, detail.label);
|
AppDetailsFragment.show(DataUsageSummary.this, app, detail.label);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1224,9 +1237,9 @@ public class DataUsageSummary extends Fragment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadFinished(Loader<NetworkStats> loader, NetworkStats data) {
|
public void onLoadFinished(Loader<NetworkStats> loader, NetworkStats data) {
|
||||||
final int[] restrictedAppIds = mPolicyManager.getAppsWithPolicy(
|
final int[] restrictedUids = mPolicyManager.getUidsWithPolicy(
|
||||||
POLICY_REJECT_METERED_BACKGROUND);
|
POLICY_REJECT_METERED_BACKGROUND);
|
||||||
mAdapter.bindStats(data, restrictedAppIds);
|
mAdapter.bindStats(data, restrictedUids);
|
||||||
updateEmptyVisible();
|
updateEmptyVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1408,17 +1421,17 @@ public class DataUsageSummary extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class AppItem implements Comparable<AppItem>, Parcelable {
|
public static class AppItem implements Comparable<AppItem>, Parcelable {
|
||||||
public final int appId;
|
public final int key;
|
||||||
public boolean restricted;
|
public boolean restricted;
|
||||||
public SparseBooleanArray uids = new SparseBooleanArray();
|
public SparseBooleanArray uids = new SparseBooleanArray();
|
||||||
public long total;
|
public long total;
|
||||||
|
|
||||||
public AppItem(int appId) {
|
public AppItem(int key) {
|
||||||
this.appId = appId;
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AppItem(Parcel parcel) {
|
public AppItem(Parcel parcel) {
|
||||||
appId = parcel.readInt();
|
key = parcel.readInt();
|
||||||
uids = parcel.readSparseBooleanArray();
|
uids = parcel.readSparseBooleanArray();
|
||||||
total = parcel.readLong();
|
total = parcel.readLong();
|
||||||
}
|
}
|
||||||
@@ -1429,7 +1442,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
dest.writeInt(appId);
|
dest.writeInt(key);
|
||||||
dest.writeSparseBooleanArray(uids);
|
dest.writeSparseBooleanArray(uids);
|
||||||
dest.writeLong(total);
|
dest.writeLong(total);
|
||||||
}
|
}
|
||||||
@@ -1475,49 +1488,56 @@ public class DataUsageSummary extends Fragment {
|
|||||||
/**
|
/**
|
||||||
* Bind the given {@link NetworkStats}, or {@code null} to clear list.
|
* Bind the given {@link NetworkStats}, or {@code null} to clear list.
|
||||||
*/
|
*/
|
||||||
public void bindStats(NetworkStats stats, int[] restrictedAppIds) {
|
public void bindStats(NetworkStats stats, int[] restrictedUids) {
|
||||||
mItems.clear();
|
mItems.clear();
|
||||||
|
|
||||||
final AppItem systemItem = new AppItem(android.os.Process.SYSTEM_UID);
|
final int currentUserId = ActivityManager.getCurrentUser();
|
||||||
final SparseArray<AppItem> knownUids = new SparseArray<AppItem>();
|
final SparseArray<AppItem> knownItems = new SparseArray<AppItem>();
|
||||||
|
|
||||||
NetworkStats.Entry entry = null;
|
NetworkStats.Entry entry = null;
|
||||||
final int size = stats != null ? stats.size() : 0;
|
final int size = stats != null ? stats.size() : 0;
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
entry = stats.getValues(i, entry);
|
entry = stats.getValues(i, entry);
|
||||||
|
|
||||||
final boolean isApp = UserHandle.isApp(entry.uid);
|
// Decide how to collapse items together
|
||||||
final int appId = isApp ? UserHandle.getAppId(entry.uid) : entry.uid;
|
final int uid = entry.uid;
|
||||||
if (isApp || appId == UID_REMOVED || appId == UID_TETHERING) {
|
final int collapseKey;
|
||||||
AppItem item = knownUids.get(appId);
|
if (UserHandle.isApp(uid)) {
|
||||||
if (item == null) {
|
if (UserHandle.getUserId(uid) == currentUserId) {
|
||||||
item = new AppItem(appId);
|
collapseKey = uid;
|
||||||
knownUids.put(appId, item);
|
} else {
|
||||||
mItems.add(item);
|
collapseKey = UidDetailProvider.buildKeyForUser(UserHandle.getUserId(uid));
|
||||||
}
|
}
|
||||||
|
} else if (uid == UID_REMOVED || uid == UID_TETHERING) {
|
||||||
item.total += entry.rxBytes + entry.txBytes;
|
collapseKey = uid;
|
||||||
item.addUid(entry.uid);
|
|
||||||
} else {
|
} else {
|
||||||
systemItem.total += entry.rxBytes + entry.txBytes;
|
collapseKey = android.os.Process.SYSTEM_UID;
|
||||||
systemItem.addUid(entry.uid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AppItem item = knownItems.get(collapseKey);
|
||||||
|
if (item == null) {
|
||||||
|
item = new AppItem(collapseKey);
|
||||||
|
mItems.add(item);
|
||||||
|
knownItems.put(item.key, item);
|
||||||
|
}
|
||||||
|
item.addUid(uid);
|
||||||
|
item.total += entry.rxBytes + entry.txBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int appId : restrictedAppIds) {
|
for (int uid : restrictedUids) {
|
||||||
AppItem item = knownUids.get(appId);
|
// Only splice in restricted state for current user
|
||||||
|
if (UserHandle.getUserId(uid) != currentUserId) continue;
|
||||||
|
|
||||||
|
AppItem item = knownItems.get(uid);
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
item = new AppItem(appId);
|
item = new AppItem(uid);
|
||||||
item.total = -1;
|
item.total = -1;
|
||||||
mItems.add(item);
|
mItems.add(item);
|
||||||
|
knownItems.put(item.key, item);
|
||||||
}
|
}
|
||||||
item.restricted = true;
|
item.restricted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (systemItem.total > 0) {
|
|
||||||
mItems.add(systemItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.sort(mItems);
|
Collections.sort(mItems);
|
||||||
mLargest = (mItems.size() > 0) ? mItems.get(0).total : 0;
|
mLargest = (mItems.size() > 0) ? mItems.get(0).total : 0;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
@@ -1535,7 +1555,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getItemId(int position) {
|
public long getItemId(int position) {
|
||||||
return mItems.get(position).appId;
|
return mItems.get(position).key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -2126,7 +2146,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
existing.cancel(false);
|
existing.cancel(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
final UidDetail cachedDetail = provider.getUidDetail(item.appId, false);
|
final UidDetail cachedDetail = provider.getUidDetail(item.key, false);
|
||||||
if (cachedDetail != null) {
|
if (cachedDetail != null) {
|
||||||
bindView(cachedDetail, target);
|
bindView(cachedDetail, target);
|
||||||
} else {
|
} else {
|
||||||
@@ -2155,7 +2175,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected UidDetail doInBackground(Void... params) {
|
protected UidDetail doInBackground(Void... params) {
|
||||||
return mProvider.getUidDetail(mItem.appId, true);
|
return mProvider.getUidDetail(mItem.key, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -100,6 +100,7 @@ public class Settings extends PreferenceActivity
|
|||||||
R.id.wireless_section,
|
R.id.wireless_section,
|
||||||
R.id.wifi_settings,
|
R.id.wifi_settings,
|
||||||
R.id.bluetooth_settings,
|
R.id.bluetooth_settings,
|
||||||
|
R.id.data_usage_settings,
|
||||||
R.id.device_section,
|
R.id.device_section,
|
||||||
R.id.sound_settings,
|
R.id.sound_settings,
|
||||||
R.id.display_settings,
|
R.id.display_settings,
|
||||||
|
@@ -20,6 +20,7 @@ import static android.net.NetworkPolicyManager.POLICY_NONE;
|
|||||||
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
|
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.ActivityManager;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.app.INotificationManager;
|
import android.app.INotificationManager;
|
||||||
@@ -41,6 +42,7 @@ import android.os.Handler;
|
|||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
|
import android.os.UserHandle;
|
||||||
import android.preference.PreferenceActivity;
|
import android.preference.PreferenceActivity;
|
||||||
import android.preference.PreferenceFrameLayout;
|
import android.preference.PreferenceFrameLayout;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@@ -1119,11 +1121,15 @@ public class ManageApplications extends Fragment implements
|
|||||||
+ prefActivities.get(i).getPackageName());
|
+ prefActivities.get(i).getPackageName());
|
||||||
pm.clearPackagePreferredActivities(prefActivities.get(i).getPackageName());
|
pm.clearPackagePreferredActivities(prefActivities.get(i).getPackageName());
|
||||||
}
|
}
|
||||||
final int[] restrictedAppIds = npm.getAppsWithPolicy(
|
final int[] restrictedUids = npm.getUidsWithPolicy(
|
||||||
POLICY_REJECT_METERED_BACKGROUND);
|
POLICY_REJECT_METERED_BACKGROUND);
|
||||||
for (int i : restrictedAppIds) {
|
final int currentUserId = ActivityManager.getCurrentUser();
|
||||||
if (DEBUG) Log.v(TAG, "Clearing data policy: " + i);
|
for (int uid : restrictedUids) {
|
||||||
npm.setAppPolicy(i, POLICY_NONE);
|
// Only reset for current user
|
||||||
|
if (UserHandle.getUserId(uid) == currentUserId) {
|
||||||
|
if (DEBUG) Log.v(TAG, "Clearing data policy: " + uid);
|
||||||
|
npm.setUidPolicy(uid, POLICY_NONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
handler.post(new Runnable() {
|
handler.post(new Runnable() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
|
@@ -21,20 +21,30 @@ import android.content.pm.ApplicationInfo;
|
|||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
|
import android.content.pm.UserInfo;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.TrafficStats;
|
import android.net.TrafficStats;
|
||||||
|
import android.os.UserManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.Utils;
|
import com.android.settings.Utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return details about a specific UID, handling special cases like
|
||||||
|
* {@link TrafficStats#UID_TETHERING} and {@link UserInfo}.
|
||||||
|
*/
|
||||||
public class UidDetailProvider {
|
public class UidDetailProvider {
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final SparseArray<UidDetail> mUidDetailCache;
|
private final SparseArray<UidDetail> mUidDetailCache;
|
||||||
|
|
||||||
|
public static int buildKeyForUser(int userHandle) {
|
||||||
|
return -(2000 + userHandle);
|
||||||
|
}
|
||||||
|
|
||||||
public UidDetailProvider(Context context) {
|
public UidDetailProvider(Context context) {
|
||||||
mContext = context.getApplicationContext();
|
mContext = context.getApplicationContext();
|
||||||
mUidDetailCache = new SparseArray<UidDetail>();
|
mUidDetailCache = new SparseArray<UidDetail>();
|
||||||
@@ -101,10 +111,21 @@ public class UidDetailProvider {
|
|||||||
return detail;
|
return detail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle keys that are actually user handles
|
||||||
|
if (uid <= -2000) {
|
||||||
|
final int userHandle = (-uid) - 2000;
|
||||||
|
final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
|
||||||
|
final UserInfo info = um.getUserInfo(userHandle);
|
||||||
|
if (info != null) {
|
||||||
|
detail.label = res.getString(R.string.running_process_item_user_label, info.name);
|
||||||
|
detail.icon = Drawable.createFromPath(info.iconPath);
|
||||||
|
return detail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// otherwise fall back to using packagemanager labels
|
// otherwise fall back to using packagemanager labels
|
||||||
final String[] packageNames = pm.getPackagesForUid(uid);
|
final String[] packageNames = pm.getPackagesForUid(uid);
|
||||||
final int length = packageNames != null ? packageNames.length : 0;
|
final int length = packageNames != null ? packageNames.length : 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (length == 1) {
|
if (length == 1) {
|
||||||
final ApplicationInfo info = pm.getApplicationInfo(packageNames[0], 0);
|
final ApplicationInfo info = pm.getApplicationInfo(packageNames[0], 0);
|
||||||
|
Reference in New Issue
Block a user