Merge "Make Settings > Security > Apps with Usage Access multiprofile aware"
This commit is contained in:
committed by
Android (Google) Code Review
commit
10045bc2f1
@@ -17,6 +17,7 @@
|
|||||||
package com.android.settings;
|
package com.android.settings;
|
||||||
|
|
||||||
import com.android.internal.content.PackageMonitor;
|
import com.android.internal.content.PackageMonitor;
|
||||||
|
import com.android.settings.DataUsageSummary.AppItem;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.app.ActivityThread;
|
import android.app.ActivityThread;
|
||||||
@@ -28,6 +29,7 @@ import android.app.Fragment;
|
|||||||
import android.app.FragmentTransaction;
|
import android.app.FragmentTransaction;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.IPackageManager;
|
import android.content.pm.IPackageManager;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
@@ -35,18 +37,24 @@ import android.os.AsyncTask;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.os.UserManager;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceScreen;
|
import android.preference.PreferenceScreen;
|
||||||
import android.preference.SwitchPreference;
|
import android.preference.SwitchPreference;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
||||||
Preference.OnPreferenceChangeListener {
|
Preference.OnPreferenceChangeListener {
|
||||||
|
|
||||||
private static final String TAG = "UsageAccessSettings";
|
private static final String TAG = "UsageAccessSettings";
|
||||||
|
private static final String BUNDLE_KEY_PROFILEID = "profileId";
|
||||||
|
|
||||||
private static final String[] PM_USAGE_STATS_PERMISSION = new String[] {
|
private static final String[] PM_USAGE_STATS_PERMISSION = new String[] {
|
||||||
Manifest.permission.PACKAGE_USAGE_STATS
|
Manifest.permission.PACKAGE_USAGE_STATS
|
||||||
@@ -56,16 +64,23 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
AppOpsManager.OP_GET_USAGE_STATS
|
AppOpsManager.OP_GET_USAGE_STATS
|
||||||
};
|
};
|
||||||
|
|
||||||
private static class PackageEntry {
|
private static class PackageEntry implements Comparable<PackageEntry> {
|
||||||
public PackageEntry(String packageName) {
|
public PackageEntry(String packageName, UserHandle userHandle) {
|
||||||
this.packageName = packageName;
|
this.packageName = packageName;
|
||||||
this.appOpMode = AppOpsManager.MODE_DEFAULT;
|
this.appOpMode = AppOpsManager.MODE_DEFAULT;
|
||||||
|
this.userHandle = userHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(PackageEntry another) {
|
||||||
|
return packageName.compareTo(another.packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
final String packageName;
|
final String packageName;
|
||||||
PackageInfo packageInfo;
|
PackageInfo packageInfo;
|
||||||
boolean permissionGranted;
|
boolean permissionGranted;
|
||||||
int appOpMode;
|
int appOpMode;
|
||||||
|
UserHandle userHandle;
|
||||||
|
|
||||||
SwitchPreference preference;
|
SwitchPreference preference;
|
||||||
}
|
}
|
||||||
@@ -75,69 +90,102 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
* the PreferenceScreen with the results when complete.
|
* the PreferenceScreen with the results when complete.
|
||||||
*/
|
*/
|
||||||
private class AppsRequestingAccessFetcher extends
|
private class AppsRequestingAccessFetcher extends
|
||||||
AsyncTask<Void, Void, ArrayMap<String, PackageEntry>> {
|
AsyncTask<Void, Void, SparseArray<ArrayMap<String, PackageEntry>>> {
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final PackageManager mPackageManager;
|
private final PackageManager mPackageManager;
|
||||||
private final IPackageManager mIPackageManager;
|
private final IPackageManager mIPackageManager;
|
||||||
|
private final UserManager mUserManager;
|
||||||
|
private final List<UserHandle> mProfiles;
|
||||||
|
|
||||||
public AppsRequestingAccessFetcher(Context context) {
|
public AppsRequestingAccessFetcher(Context context) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mPackageManager = context.getPackageManager();
|
mPackageManager = context.getPackageManager();
|
||||||
mIPackageManager = ActivityThread.getPackageManager();
|
mIPackageManager = ActivityThread.getPackageManager();
|
||||||
|
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||||
|
mProfiles = mUserManager.getUserProfiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ArrayMap<String, PackageEntry> doInBackground(Void... params) {
|
protected SparseArray<ArrayMap<String, PackageEntry>> doInBackground(Void... params) {
|
||||||
final String[] packages;
|
final String[] packages;
|
||||||
|
SparseArray<ArrayMap<String, PackageEntry>> entries;
|
||||||
try {
|
try {
|
||||||
packages = mIPackageManager.getAppOpPermissionPackages(
|
packages = mIPackageManager.getAppOpPermissionPackages(
|
||||||
Manifest.permission.PACKAGE_USAGE_STATS);
|
Manifest.permission.PACKAGE_USAGE_STATS);
|
||||||
|
|
||||||
|
if (packages == null) {
|
||||||
|
// No packages are requesting permission to use the UsageStats API.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
entries = new SparseArray<>();
|
||||||
|
for (final UserHandle profile : mProfiles) {
|
||||||
|
final ArrayMap<String, PackageEntry> entriesForProfile = new ArrayMap<>();
|
||||||
|
final int profileId = profile.getIdentifier();
|
||||||
|
entries.put(profileId, entriesForProfile);
|
||||||
|
for (final String packageName : packages) {
|
||||||
|
final boolean isAvailable = mIPackageManager.isPackageAvailable(packageName,
|
||||||
|
profileId);
|
||||||
|
if (!shouldIgnorePackage(packageName) && isAvailable) {
|
||||||
|
final PackageEntry newEntry = new PackageEntry(packageName, profile);
|
||||||
|
entriesForProfile.put(packageName, newEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.w(TAG, "PackageManager is dead. Can't get list of packages requesting "
|
Log.w(TAG, "PackageManager is dead. Can't get list of packages requesting "
|
||||||
+ Manifest.permission.PACKAGE_USAGE_STATS);
|
+ Manifest.permission.PACKAGE_USAGE_STATS);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packages == null) {
|
|
||||||
// No packages are requesting permission to use the UsageStats API.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayMap<String, PackageEntry> entries = new ArrayMap<>();
|
|
||||||
for (final String packageName : packages) {
|
|
||||||
if (!shouldIgnorePackage(packageName)) {
|
|
||||||
entries.put(packageName, new PackageEntry(packageName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the packages that have been granted the PACKAGE_USAGE_STATS permission.
|
// Load the packages that have been granted the PACKAGE_USAGE_STATS permission.
|
||||||
final List<PackageInfo> packageInfos = mPackageManager.getPackagesHoldingPermissions(
|
try {
|
||||||
PM_USAGE_STATS_PERMISSION, 0);
|
for (final UserHandle profile : mProfiles) {
|
||||||
final int packageInfoCount = packageInfos != null ? packageInfos.size() : 0;
|
final int profileId = profile.getIdentifier();
|
||||||
for (int i = 0; i < packageInfoCount; i++) {
|
final ArrayMap<String, PackageEntry> entriesForProfile = entries.get(profileId);
|
||||||
final PackageInfo packageInfo = packageInfos.get(i);
|
if (entriesForProfile == null) {
|
||||||
final PackageEntry pe = entries.get(packageInfo.packageName);
|
continue;
|
||||||
if (pe != null) {
|
}
|
||||||
pe.packageInfo = packageInfo;
|
final List<PackageInfo> packageInfos = mIPackageManager
|
||||||
pe.permissionGranted = true;
|
.getPackagesHoldingPermissions(PM_USAGE_STATS_PERMISSION, 0, profileId)
|
||||||
|
.getList();
|
||||||
|
final int packageInfoCount = packageInfos != null ? packageInfos.size() : 0;
|
||||||
|
for (int i = 0; i < packageInfoCount; i++) {
|
||||||
|
final PackageInfo packageInfo = packageInfos.get(i);
|
||||||
|
final PackageEntry pe = entriesForProfile.get(packageInfo.packageName);
|
||||||
|
if (pe != null) {
|
||||||
|
pe.packageInfo = packageInfo;
|
||||||
|
pe.permissionGranted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.w(TAG, "PackageManager is dead. Can't get list of packages granted "
|
||||||
|
+ Manifest.permission.PACKAGE_USAGE_STATS);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the remaining packages that have requested but don't have the
|
// Load the remaining packages that have requested but don't have the
|
||||||
// PACKAGE_USAGE_STATS permission.
|
// PACKAGE_USAGE_STATS permission.
|
||||||
int packageCount = entries.size();
|
for (final UserHandle profile : mProfiles) {
|
||||||
for (int i = 0; i < packageCount; i++) {
|
final int profileId = profile.getIdentifier();
|
||||||
final PackageEntry pe = entries.valueAt(i);
|
final ArrayMap<String, PackageEntry> entriesForProfile = entries.get(profileId);
|
||||||
if (pe.packageInfo == null) {
|
if (entriesForProfile == null) {
|
||||||
try {
|
continue;
|
||||||
pe.packageInfo = mPackageManager.getPackageInfo(pe.packageName, 0);
|
}
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
int packageCount = entriesForProfile.size();
|
||||||
// This package doesn't exist. This may occur when an app is uninstalled for
|
for (int i = packageCount - 1; i >= 0; --i) {
|
||||||
// one user, but it is not removed from the system.
|
final PackageEntry pe = entriesForProfile.valueAt(i);
|
||||||
entries.removeAt(i);
|
if (pe.packageInfo == null) {
|
||||||
i--;
|
try {
|
||||||
packageCount--;
|
pe.packageInfo = mIPackageManager.getPackageInfo(pe.packageName, 0,
|
||||||
|
profileId);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// This package doesn't exist. This may occur when an app is
|
||||||
|
// uninstalled for one user, but it is not removed from the system.
|
||||||
|
entriesForProfile.removeAt(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,15 +196,21 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
final int packageOpsCount = packageOps != null ? packageOps.size() : 0;
|
final int packageOpsCount = packageOps != null ? packageOps.size() : 0;
|
||||||
for (int i = 0; i < packageOpsCount; i++) {
|
for (int i = 0; i < packageOpsCount; i++) {
|
||||||
final AppOpsManager.PackageOps packageOp = packageOps.get(i);
|
final AppOpsManager.PackageOps packageOp = packageOps.get(i);
|
||||||
final PackageEntry pe = entries.get(packageOp.getPackageName());
|
final int userId = UserHandle.getUserId(packageOp.getUid());
|
||||||
if (pe == null) {
|
if (!isThisUserAProfileOfCurrentUser(userId)) {
|
||||||
Log.w(TAG, "AppOp permission exists for package " + packageOp.getPackageName()
|
// This AppOp does not belong to any of this user's profiles.
|
||||||
+ " but package doesn't exist or did not request UsageStats access");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packageOp.getUid() != pe.packageInfo.applicationInfo.uid) {
|
final ArrayMap<String, PackageEntry> entriesForProfile = entries.get(userId);
|
||||||
// This AppOp does not belong to this user.
|
if (entriesForProfile == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final PackageEntry pe = entriesForProfile.get(packageOp.getPackageName());
|
||||||
|
if (pe == null) {
|
||||||
|
Log.w(TAG, "AppOp permission exists for package " + packageOp.getPackageName()
|
||||||
|
+ " of user " + userId +
|
||||||
|
" but package doesn't exist or did not request UsageStats access");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +227,7 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(ArrayMap<String, PackageEntry> newEntries) {
|
protected void onPostExecute(SparseArray<ArrayMap<String, PackageEntry>> newEntries) {
|
||||||
mLastFetcherTask = null;
|
mLastFetcherTask = null;
|
||||||
|
|
||||||
if (getActivity() == null) {
|
if (getActivity() == null) {
|
||||||
@@ -188,41 +242,126 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find the deleted entries and remove them from the PreferenceScreen.
|
// Find the deleted entries and remove them from the PreferenceScreen.
|
||||||
final int oldPackageCount = mPackageEntryMap.size();
|
final int oldProfileCount = mPackageEntryMap.size();
|
||||||
for (int i = 0; i < oldPackageCount; i++) {
|
for (int profileIndex = 0; profileIndex < oldProfileCount; ++profileIndex) {
|
||||||
final PackageEntry oldPackageEntry = mPackageEntryMap.valueAt(i);
|
final int profileId = mPackageEntryMap.keyAt(profileIndex);
|
||||||
final PackageEntry newPackageEntry = newEntries.get(oldPackageEntry.packageName);
|
final ArrayMap<String, PackageEntry> oldEntriesForProfile = mPackageEntryMap
|
||||||
if (newPackageEntry == null) {
|
.valueAt(profileIndex);
|
||||||
// This package has been removed.
|
final int oldPackageCount = oldEntriesForProfile.size();
|
||||||
mPreferenceScreen.removePreference(oldPackageEntry.preference);
|
|
||||||
} else {
|
final ArrayMap<String, PackageEntry> newEntriesForProfile = newEntries.get(
|
||||||
// This package already exists in the preference hierarchy, so reuse that
|
profileId);
|
||||||
// Preference.
|
|
||||||
newPackageEntry.preference = oldPackageEntry.preference;
|
for (int i = 0; i < oldPackageCount; i++) {
|
||||||
|
final PackageEntry oldPackageEntry = oldEntriesForProfile.valueAt(i);
|
||||||
|
|
||||||
|
PackageEntry newPackageEntry = null;
|
||||||
|
if (newEntriesForProfile != null) {
|
||||||
|
newPackageEntry = newEntriesForProfile.get(oldPackageEntry.packageName);
|
||||||
|
}
|
||||||
|
if (newPackageEntry == null) {
|
||||||
|
// This package has been removed.
|
||||||
|
mPreferenceScreen.removePreference(oldPackageEntry.preference);
|
||||||
|
} else {
|
||||||
|
// This package already exists in the preference hierarchy, so reuse that
|
||||||
|
// Preference.
|
||||||
|
newPackageEntry.preference = oldPackageEntry.preference;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now add new packages to the PreferenceScreen.
|
// Now add new packages to the PreferenceScreen.
|
||||||
final int packageCount = newEntries.size();
|
final int newProfileCount = newEntries.size();
|
||||||
for (int i = 0; i < packageCount; i++) {
|
for (int profileIndex = 0; profileIndex < newProfileCount; ++profileIndex) {
|
||||||
final PackageEntry packageEntry = newEntries.valueAt(i);
|
final int profileId = newEntries.keyAt(profileIndex);
|
||||||
if (packageEntry.preference == null) {
|
final ArrayMap<String, PackageEntry> newEntriesForProfile = newEntries.get(
|
||||||
packageEntry.preference = new SwitchPreference(mContext);
|
profileId);
|
||||||
packageEntry.preference.setPersistent(false);
|
final int packageCount = newEntriesForProfile.size();
|
||||||
packageEntry.preference.setOnPreferenceChangeListener(UsageAccessSettings.this);
|
for (int i = 0; i < packageCount; i++) {
|
||||||
mPreferenceScreen.addPreference(packageEntry.preference);
|
final PackageEntry packageEntry = newEntriesForProfile.valueAt(i);
|
||||||
|
if (packageEntry.preference == null) {
|
||||||
|
packageEntry.preference = new SwitchPreference(mContext);
|
||||||
|
packageEntry.preference.setPersistent(false);
|
||||||
|
packageEntry.preference.setOnPreferenceChangeListener(
|
||||||
|
UsageAccessSettings.this);
|
||||||
|
mPreferenceScreen.addPreference(packageEntry.preference);
|
||||||
|
}
|
||||||
|
updatePreference(packageEntry);
|
||||||
}
|
}
|
||||||
updatePreference(packageEntry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mPackageEntryMap.clear();
|
mPackageEntryMap.clear();
|
||||||
mPackageEntryMap = newEntries;
|
mPackageEntryMap = newEntries;
|
||||||
|
|
||||||
|
// Add/remove headers if necessary. If there are package entries only for one user and
|
||||||
|
// that user is not the managed profile then do not show headers.
|
||||||
|
if (mPackageEntryMap.size() == 1 &&
|
||||||
|
mPackageEntryMap.keyAt(0) == UserHandle.myUserId()) {
|
||||||
|
for (int i = 0; i < mCategoryHeaders.length; ++i) {
|
||||||
|
if (mCategoryHeaders[i] != null) {
|
||||||
|
mPreferenceScreen.removePreference(mCategoryHeaders[i]);
|
||||||
|
}
|
||||||
|
mCategoryHeaders[i] = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < mCategoryHeaders.length; ++i) {
|
||||||
|
if (mCategoryHeaders[i] == null) {
|
||||||
|
final Preference preference = new Preference(mContext, null,
|
||||||
|
com.android.internal.R.attr.preferenceCategoryStyle, 0);
|
||||||
|
mCategoryHeaders[i] = preference;
|
||||||
|
preference.setTitle(mCategoryHeaderTitleResIds[i]);
|
||||||
|
preference.setEnabled(false);
|
||||||
|
mPreferenceScreen.addPreference(preference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort preferences alphabetically within categories
|
||||||
|
int order = 0;
|
||||||
|
final int profileCount = mProfiles.size();
|
||||||
|
for (int i = 0; i < profileCount; ++i) {
|
||||||
|
Preference header = mCategoryHeaders[i];
|
||||||
|
if (header != null) {
|
||||||
|
header.setOrder(order++);
|
||||||
|
}
|
||||||
|
ArrayMap<String, PackageEntry> entriesForProfile =
|
||||||
|
mPackageEntryMap.get(mProfiles.get(i).getIdentifier());
|
||||||
|
if (entriesForProfile != null) {
|
||||||
|
List<PackageEntry> sortedEntries = Collections.list(
|
||||||
|
Collections.enumeration(entriesForProfile.values()));
|
||||||
|
Collections.sort(sortedEntries);
|
||||||
|
for (PackageEntry pe : sortedEntries) {
|
||||||
|
pe.preference.setOrder(order++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePreference(PackageEntry pe) {
|
private void updatePreference(PackageEntry pe) {
|
||||||
pe.preference.setIcon(pe.packageInfo.applicationInfo.loadIcon(mPackageManager));
|
final int profileId = pe.userHandle.getIdentifier();
|
||||||
pe.preference.setTitle(pe.packageInfo.applicationInfo.loadLabel(mPackageManager));
|
// Set something as default
|
||||||
|
pe.preference.setEnabled(false);
|
||||||
|
pe.preference.setTitle(pe.packageName);
|
||||||
|
pe.preference.setIcon(mUserManager.getBadgedIconForUser(mPackageManager
|
||||||
|
.getDefaultActivityIcon(), pe.userHandle));
|
||||||
|
try {
|
||||||
|
// Try setting real title and icon
|
||||||
|
final ApplicationInfo info = mIPackageManager.getApplicationInfo(pe.packageName,
|
||||||
|
0 /* no flags */, profileId);
|
||||||
|
if (info != null) {
|
||||||
|
pe.preference.setEnabled(true);
|
||||||
|
pe.preference.setTitle(info.loadLabel(mPackageManager).toString());
|
||||||
|
pe.preference.setIcon(mUserManager.getBadgedIconForUser(info.loadIcon(
|
||||||
|
mPackageManager), pe.userHandle));
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.w(TAG, "PackageManager is dead. Can't get app info for package " +
|
||||||
|
pe.packageName + " of user " + profileId);
|
||||||
|
// Keep going to update other parts of the preference
|
||||||
|
}
|
||||||
|
|
||||||
pe.preference.setKey(pe.packageName);
|
pe.preference.setKey(pe.packageName);
|
||||||
|
Bundle extra = pe.preference.getExtras();
|
||||||
|
extra.putInt(BUNDLE_KEY_PROFILEID, profileId);
|
||||||
|
|
||||||
boolean check = false;
|
boolean check = false;
|
||||||
if (pe.appOpMode == AppOpsManager.MODE_ALLOWED) {
|
if (pe.appOpMode == AppOpsManager.MODE_ALLOWED) {
|
||||||
@@ -237,6 +376,16 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
pe.preference.setChecked(check);
|
pe.preference.setChecked(check);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isThisUserAProfileOfCurrentUser(final int userId) {
|
||||||
|
final int profilesMax = mProfiles.size();
|
||||||
|
for (int i = 0; i < profilesMax; ++i) {
|
||||||
|
if (mProfiles.get(i).getIdentifier() == userId) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean shouldIgnorePackage(String packageName) {
|
static boolean shouldIgnorePackage(String packageName) {
|
||||||
@@ -244,9 +393,14 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private AppsRequestingAccessFetcher mLastFetcherTask;
|
private AppsRequestingAccessFetcher mLastFetcherTask;
|
||||||
ArrayMap<String, PackageEntry> mPackageEntryMap = new ArrayMap<>();
|
SparseArray<ArrayMap<String, PackageEntry>> mPackageEntryMap = new SparseArray<>();
|
||||||
AppOpsManager mAppOpsManager;
|
AppOpsManager mAppOpsManager;
|
||||||
PreferenceScreen mPreferenceScreen;
|
PreferenceScreen mPreferenceScreen;
|
||||||
|
private Preference[] mCategoryHeaders = new Preference[2];
|
||||||
|
private static int[] mCategoryHeaderTitleResIds = new int[] {
|
||||||
|
R.string.category_personal,
|
||||||
|
R.string.category_work
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle icicle) {
|
public void onCreate(Bundle icicle) {
|
||||||
@@ -293,16 +447,16 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
final String packageName = preference.getKey();
|
final String packageName = preference.getKey();
|
||||||
final PackageEntry pe = mPackageEntryMap.get(packageName);
|
final int profileId = preference.getExtras().getInt(BUNDLE_KEY_PROFILEID);
|
||||||
|
final PackageEntry pe = getPackageEntry(packageName, profileId);
|
||||||
if (pe == null) {
|
if (pe == null) {
|
||||||
Log.w(TAG, "Preference change event for package " + packageName
|
Log.w(TAG, "Preference change event handling failed");
|
||||||
+ " but that package is no longer valid.");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(newValue instanceof Boolean)) {
|
if (!(newValue instanceof Boolean)) {
|
||||||
Log.w(TAG, "Preference change event for package " + packageName
|
Log.w(TAG, "Preference change event for package " + packageName + " of user " +
|
||||||
+ " had non boolean value of type " + newValue.getClass().getName());
|
profileId + " had non boolean value of type " + newValue.getClass().getName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +477,7 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
if (prev != null) {
|
if (prev != null) {
|
||||||
ft.remove(prev);
|
ft.remove(prev);
|
||||||
}
|
}
|
||||||
WarningDialogFragment.newInstance(pe.packageName).show(ft, "warning");
|
WarningDialogFragment.newInstance(pe).show(ft, "warning");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -335,10 +489,10 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
pe.appOpMode = newMode;
|
pe.appOpMode = newMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void allowAccess(String packageName) {
|
void allowAccess(String packageName, int profileId) {
|
||||||
final PackageEntry entry = mPackageEntryMap.get(packageName);
|
final PackageEntry entry = getPackageEntry(packageName, profileId);
|
||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
Log.w(TAG, "Unable to give access to package " + packageName + ": it does not exist.");
|
Log.w(TAG, "Unable to give access");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,6 +500,21 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
entry.preference.setChecked(true);
|
entry.preference.setChecked(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PackageEntry getPackageEntry(String packageName, int profileId) {
|
||||||
|
ArrayMap<String, PackageEntry> entriesForProfile = mPackageEntryMap.get(profileId);
|
||||||
|
if (entriesForProfile == null) {
|
||||||
|
Log.w(TAG, "getPackageEntry fails for package " + packageName + " of user " +
|
||||||
|
profileId + ": user does not seem to be valid.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final PackageEntry entry = entriesForProfile.get(packageName);
|
||||||
|
if (entry == null) {
|
||||||
|
Log.w(TAG, "getPackageEntry fails for package " + packageName + " of user " +
|
||||||
|
profileId + ": package does not exist.");
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
|
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
|
||||||
@Override
|
@Override
|
||||||
public void onPackageAdded(String packageName, int uid) {
|
public void onPackageAdded(String packageName, int uid) {
|
||||||
@@ -361,11 +530,13 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
public static class WarningDialogFragment extends DialogFragment
|
public static class WarningDialogFragment extends DialogFragment
|
||||||
implements DialogInterface.OnClickListener {
|
implements DialogInterface.OnClickListener {
|
||||||
private static final String ARG_PACKAGE_NAME = "package";
|
private static final String ARG_PACKAGE_NAME = "package";
|
||||||
|
private static final String ARG_PROFILE_ID = "profileId";
|
||||||
|
|
||||||
public static WarningDialogFragment newInstance(String packageName) {
|
public static WarningDialogFragment newInstance(PackageEntry pe) {
|
||||||
WarningDialogFragment dialog = new WarningDialogFragment();
|
WarningDialogFragment dialog = new WarningDialogFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(ARG_PACKAGE_NAME, packageName);
|
args.putString(ARG_PACKAGE_NAME, pe.packageName);
|
||||||
|
args.putInt(ARG_PROFILE_ID, pe.userHandle.getIdentifier());
|
||||||
dialog.setArguments(args);
|
dialog.setArguments(args);
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
@@ -385,7 +556,8 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
if (which == DialogInterface.BUTTON_POSITIVE) {
|
if (which == DialogInterface.BUTTON_POSITIVE) {
|
||||||
((UsageAccessSettings) getParentFragment()).allowAccess(
|
((UsageAccessSettings) getParentFragment()).allowAccess(
|
||||||
getArguments().getString(ARG_PACKAGE_NAME));
|
getArguments().getString(ARG_PACKAGE_NAME),
|
||||||
|
getArguments().getInt(ARG_PROFILE_ID));
|
||||||
} else {
|
} else {
|
||||||
dialog.cancel();
|
dialog.cancel();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user