Watch out for deleted user when exiting async task
Fixes a problem where the async task can take a while to execute and in the meantime the user can be removed. On exiting the async task and updating the UI, make sure the user hasn't been deleted. Bug: 18411181 Change-Id: I1831f3e53084c49e27557cb7aacec78c753a611b
This commit is contained in:
@@ -1023,4 +1023,21 @@ public final class Utils {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries for the UserInfo of a user. Returns null if the user doesn't exist (was removed).
|
||||||
|
* @param userManager Instance of UserManager
|
||||||
|
* @param checkUser The user to check the existence of.
|
||||||
|
* @return UserInfo of the user or null for non-existent user.
|
||||||
|
*/
|
||||||
|
public static UserInfo getExistingUser(UserManager userManager, UserHandle checkUser) {
|
||||||
|
final List<UserInfo> users = userManager.getUsers(true /* excludeDying */);
|
||||||
|
final int checkUserId = checkUser.getIdentifier();
|
||||||
|
for (UserInfo user : users) {
|
||||||
|
if (user.id == checkUserId) {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -58,6 +58,7 @@ import android.widget.Switch;
|
|||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.SettingsPreferenceFragment;
|
import com.android.settings.SettingsPreferenceFragment;
|
||||||
|
import com.android.settings.Utils;
|
||||||
import com.android.settings.drawable.CircleFramedDrawable;
|
import com.android.settings.drawable.CircleFramedDrawable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -643,75 +644,81 @@ public class AppRestrictionsFragment extends SettingsPreferenceFragment implemen
|
|||||||
if (context == null) return;
|
if (context == null) return;
|
||||||
final PackageManager pm = mPackageManager;
|
final PackageManager pm = mPackageManager;
|
||||||
final IPackageManager ipm = mIPm;
|
final IPackageManager ipm = mIPm;
|
||||||
|
final int userId = mUser.getIdentifier();
|
||||||
|
|
||||||
|
// Check if the user was removed in the meantime.
|
||||||
|
if (Utils.getExistingUser(mUserManager, mUser) == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
mAppList.removeAll();
|
mAppList.removeAll();
|
||||||
Intent restrictionsIntent = new Intent(Intent.ACTION_GET_RESTRICTION_ENTRIES);
|
Intent restrictionsIntent = new Intent(Intent.ACTION_GET_RESTRICTION_ENTRIES);
|
||||||
final List<ResolveInfo> receivers = pm.queryBroadcastReceivers(restrictionsIntent, 0);
|
final List<ResolveInfo> receivers = pm.queryBroadcastReceivers(restrictionsIntent, 0);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (mVisibleApps.size() > 0) {
|
for (SelectableAppInfo app : mVisibleApps) {
|
||||||
for (SelectableAppInfo app : mVisibleApps) {
|
String packageName = app.packageName;
|
||||||
String packageName = app.packageName;
|
if (packageName == null) continue;
|
||||||
if (packageName == null) continue;
|
final boolean isSettingsApp = packageName.equals(context.getPackageName());
|
||||||
final boolean isSettingsApp = packageName.equals(context.getPackageName());
|
AppRestrictionsPreference p = new AppRestrictionsPreference(context, this);
|
||||||
AppRestrictionsPreference p = new AppRestrictionsPreference(context, this);
|
final boolean hasSettings = resolveInfoListHasPackage(receivers, packageName);
|
||||||
final boolean hasSettings = resolveInfoListHasPackage(receivers, packageName);
|
p.setIcon(app.icon != null ? app.icon.mutate() : null);
|
||||||
p.setIcon(app.icon != null ? app.icon.mutate() : null);
|
p.setChecked(false);
|
||||||
p.setChecked(false);
|
p.setTitle(app.activityName);
|
||||||
p.setTitle(app.activityName);
|
if (app.masterEntry != null) {
|
||||||
if (app.masterEntry != null) {
|
p.setSummary(context.getString(R.string.user_restrictions_controlled_by,
|
||||||
p.setSummary(context.getString(R.string.user_restrictions_controlled_by,
|
app.masterEntry.activityName));
|
||||||
app.masterEntry.activityName));
|
|
||||||
}
|
|
||||||
p.setKey(getKeyForPackage(packageName));
|
|
||||||
p.setSettingsEnabled((hasSettings || isSettingsApp) && app.masterEntry == null);
|
|
||||||
p.setPersistent(false);
|
|
||||||
p.setOnPreferenceChangeListener(this);
|
|
||||||
p.setOnPreferenceClickListener(this);
|
|
||||||
PackageInfo pi = null;
|
|
||||||
try {
|
|
||||||
pi = ipm.getPackageInfo(packageName,
|
|
||||||
PackageManager.GET_UNINSTALLED_PACKAGES
|
|
||||||
| PackageManager.GET_SIGNATURES, mUser.getIdentifier());
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
}
|
|
||||||
if (pi != null && (pi.requiredForAllUsers || isPlatformSigned(pi))) {
|
|
||||||
p.setChecked(true);
|
|
||||||
p.setImmutable(true);
|
|
||||||
// If the app is required and has no restrictions, skip showing it
|
|
||||||
if (!hasSettings && !isSettingsApp) continue;
|
|
||||||
// Get and populate the defaults, since the user is not going to be
|
|
||||||
// able to toggle this app ON (it's ON by default and immutable).
|
|
||||||
// Only do this for restricted profiles, not single-user restrictions
|
|
||||||
// Also don't do this for slave icons
|
|
||||||
if (hasSettings && app.masterEntry == null) {
|
|
||||||
requestRestrictionsForApp(packageName, p, false);
|
|
||||||
}
|
|
||||||
} else if (!mNewUser && isAppEnabledForUser(pi)) {
|
|
||||||
p.setChecked(true);
|
|
||||||
}
|
|
||||||
if (mRestrictedProfile
|
|
||||||
&& pi.requiredAccountType != null && pi.restrictedAccountType == null) {
|
|
||||||
p.setChecked(false);
|
|
||||||
p.setImmutable(true);
|
|
||||||
p.setSummary(R.string.app_not_supported_in_limited);
|
|
||||||
}
|
|
||||||
if (mRestrictedProfile && pi.restrictedAccountType != null) {
|
|
||||||
p.setSummary(R.string.app_sees_restricted_accounts);
|
|
||||||
}
|
|
||||||
if (app.masterEntry != null) {
|
|
||||||
p.setImmutable(true);
|
|
||||||
p.setChecked(mSelectedPackages.get(packageName));
|
|
||||||
}
|
|
||||||
mAppList.addPreference(p);
|
|
||||||
if (isSettingsApp) {
|
|
||||||
p.setOrder(MAX_APP_RESTRICTIONS * 1);
|
|
||||||
} else {
|
|
||||||
p.setOrder(MAX_APP_RESTRICTIONS * (i + 2));
|
|
||||||
}
|
|
||||||
mSelectedPackages.put(packageName, p.isChecked());
|
|
||||||
mAppListChanged = true;
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
p.setKey(getKeyForPackage(packageName));
|
||||||
|
p.setSettingsEnabled((hasSettings || isSettingsApp) && app.masterEntry == null);
|
||||||
|
p.setPersistent(false);
|
||||||
|
p.setOnPreferenceChangeListener(this);
|
||||||
|
p.setOnPreferenceClickListener(this);
|
||||||
|
PackageInfo pi = null;
|
||||||
|
try {
|
||||||
|
pi = ipm.getPackageInfo(packageName,
|
||||||
|
PackageManager.GET_UNINSTALLED_PACKAGES
|
||||||
|
| PackageManager.GET_SIGNATURES, userId);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
}
|
||||||
|
if (pi == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pi.requiredForAllUsers || isPlatformSigned(pi)) {
|
||||||
|
p.setChecked(true);
|
||||||
|
p.setImmutable(true);
|
||||||
|
// If the app is required and has no restrictions, skip showing it
|
||||||
|
if (!hasSettings && !isSettingsApp) continue;
|
||||||
|
// Get and populate the defaults, since the user is not going to be
|
||||||
|
// able to toggle this app ON (it's ON by default and immutable).
|
||||||
|
// Only do this for restricted profiles, not single-user restrictions
|
||||||
|
// Also don't do this for slave icons
|
||||||
|
if (hasSettings && app.masterEntry == null) {
|
||||||
|
requestRestrictionsForApp(packageName, p, false);
|
||||||
|
}
|
||||||
|
} else if (!mNewUser && isAppEnabledForUser(pi)) {
|
||||||
|
p.setChecked(true);
|
||||||
|
}
|
||||||
|
if (mRestrictedProfile
|
||||||
|
&& pi.requiredAccountType != null && pi.restrictedAccountType == null) {
|
||||||
|
p.setChecked(false);
|
||||||
|
p.setImmutable(true);
|
||||||
|
p.setSummary(R.string.app_not_supported_in_limited);
|
||||||
|
}
|
||||||
|
if (mRestrictedProfile && pi.restrictedAccountType != null) {
|
||||||
|
p.setSummary(R.string.app_sees_restricted_accounts);
|
||||||
|
}
|
||||||
|
if (app.masterEntry != null) {
|
||||||
|
p.setImmutable(true);
|
||||||
|
p.setChecked(mSelectedPackages.get(packageName));
|
||||||
|
}
|
||||||
|
mAppList.addPreference(p);
|
||||||
|
if (isSettingsApp) {
|
||||||
|
p.setOrder(MAX_APP_RESTRICTIONS * 1);
|
||||||
|
} else {
|
||||||
|
p.setOrder(MAX_APP_RESTRICTIONS * (i + 2));
|
||||||
|
}
|
||||||
|
mSelectedPackages.put(packageName, p.isChecked());
|
||||||
|
mAppListChanged = true;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
// If this is the first time for a new profile, install/uninstall default apps for profile
|
// If this is the first time for a new profile, install/uninstall default apps for profile
|
||||||
// to avoid taking the hit in onPause(), which can cause race conditions on user switch.
|
// to avoid taking the hit in onPause(), which can cause race conditions on user switch.
|
||||||
|
@@ -87,7 +87,7 @@ public class RestrictedProfileSettings extends AppRestrictionsFragment
|
|||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
// Check if user still exists
|
// Check if user still exists
|
||||||
UserInfo info = getExistingUser(mUser);
|
UserInfo info = Utils.getExistingUser(mUserManager, mUser);
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
finishFragment();
|
finishFragment();
|
||||||
} else {
|
} else {
|
||||||
@@ -97,16 +97,6 @@ public class RestrictedProfileSettings extends AppRestrictionsFragment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private UserInfo getExistingUser(UserHandle thisUser) {
|
|
||||||
final List<UserInfo> users = mUserManager.getUsers(true); // Only get non-dying
|
|
||||||
for (UserInfo user : users) {
|
|
||||||
if (user.id == thisUser.getIdentifier()) {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startActivityForResult(Intent intent, int requestCode) {
|
public void startActivityForResult(Intent intent, int requestCode) {
|
||||||
mEditUserInfoController.startingActivityForResult();
|
mEditUserInfoController.startingActivityForResult();
|
||||||
|
Reference in New Issue
Block a user