diff options
4 files changed, 73 insertions, 67 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 51cfa31ae4cf..c4458b30c2db 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -2429,7 +2429,7 @@ public class DevicePolicyManager { PERSONAL_APPS_SUSPENDED_PROFILE_TIMEOUT }) @Retention(RetentionPolicy.SOURCE) - public @interface PersonalAppSuspensionReason {} + public @interface PersonalAppsSuspensionReason {} /** * Return true if the given administrator component is currently active (enabled) in the system. @@ -11961,7 +11961,7 @@ public class DevicePolicyManager { * {@link #PERSONAL_APPS_NOT_SUSPENDED} if apps are not suspended. * @see #setPersonalAppsSuspended */ - public @PersonalAppSuspensionReason int getPersonalAppsSuspendedReasons( + public @PersonalAppsSuspensionReason int getPersonalAppsSuspendedReasons( @NonNull ComponentName admin) { throwIfParentInstance("getPersonalAppsSuspendedReasons"); if (mService != null) { diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 9f151cf073bd..370469ebe840 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -7088,7 +7088,7 @@ public abstract class PackageManager { * Returns any packages in a given set of packages that cannot be suspended via a call to {@link * #setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle, * SuspendDialogInfo) setPackagesSuspended}. The platform prevents suspending certain critical - * packages to keep the device in a functioning state, e.g. the default dialer. + * packages to keep the device in a functioning state, e.g. the default dialer and launcher. * Apps need to hold {@link Manifest.permission#SUSPEND_APPS SUSPEND_APPS} to call this API. * * <p> @@ -7106,7 +7106,7 @@ public abstract class PackageManager { @RequiresPermission(Manifest.permission.SUSPEND_APPS) @NonNull public String[] getUnsuspendablePackages(@NonNull String[] packageNames) { - throw new UnsupportedOperationException("canSuspendPackages not implemented"); + throw new UnsupportedOperationException("getUnsuspendablePackages not implemented"); } /** diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 740c5cb3e75a..023a1e8ede9f 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -136,7 +136,7 @@ import android.app.admin.DevicePolicyCache; import android.app.admin.DevicePolicyEventLogger; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager.PasswordComplexity; -import android.app.admin.DevicePolicyManager.PersonalAppSuspensionReason; +import android.app.admin.DevicePolicyManager.PersonalAppsSuspensionReason; import android.app.admin.DevicePolicyManagerInternal; import android.app.admin.DeviceStateCache; import android.app.admin.FactoryResetProtectionPolicy; @@ -935,10 +935,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) { handlePackagesChanged(null /* check all admins */, userHandle); - } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action) - || (Intent.ACTION_PACKAGE_ADDED.equals(action) - && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false))) { + } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) { handlePackagesChanged(intent.getData().getSchemeSpecificPart(), userHandle); + } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) { + if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { + handlePackagesChanged(intent.getData().getSchemeSpecificPart(), userHandle); + } else { + handleNewPackageInstalled(intent.getData().getSchemeSpecificPart(), userHandle); + } } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action) && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { handlePackagesChanged(intent.getData().getSchemeSpecificPart(), userHandle); @@ -2028,6 +2032,26 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } + private void handleNewPackageInstalled(String packageName, int userHandle) { + // If personal apps were suspended by the admin, suspend the newly installed one. + if (!getUserData(userHandle).mAppsSuspended) { + return; + } + final String[] packagesToSuspend = { packageName }; + // Check if package is considered not suspendable? + if (mInjector.getPackageManager(userHandle) + .getUnsuspendablePackages(packagesToSuspend).length != 0) { + Slog.i(LOG_TAG, "Newly installed package is unsuspendable: " + packageName); + return; + } + try { + mIPackageManager.setPackagesSuspendedAsUser(packagesToSuspend, true /*suspend*/, + null, null, null, PLATFORM_PACKAGE_NAME, userHandle); + } catch (RemoteException ignored) { + // shouldn't happen. + } + } + /** * Unit test will subclass it to inject mocks. */ @@ -2110,6 +2134,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return mContext.getPackageManager(); } + PackageManager getPackageManager(int userId) { + return mContext + .createContextAsUser(UserHandle.of(userId), 0 /* flags */).getPackageManager(); + } + PowerManagerInternal getPowerManagerInternal() { return LocalServices.getService(PowerManagerInternal.class); } @@ -15650,7 +15679,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override - public @PersonalAppSuspensionReason int getPersonalAppsSuspendedReasons(ComponentName who) { + public @PersonalAppsSuspensionReason int getPersonalAppsSuspendedReasons(ComponentName who) { synchronized (getLockObject()) { final ActiveAdmin admin = getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER, @@ -15669,7 +15698,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - private @PersonalAppSuspensionReason int makeSuspensionReasons( + private @PersonalAppsSuspensionReason int makeSuspensionReasons( boolean explicit, boolean timeout) { int result = PERSONAL_APPS_NOT_SUSPENDED; if (explicit) { @@ -15793,7 +15822,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } private void applyPersonalAppsSuspension( - int profileUserId, @PersonalAppSuspensionReason int suspensionState) { + int profileUserId, @PersonalAppsSuspensionReason int suspensionState) { final boolean suspended = getUserData(UserHandle.USER_SYSTEM).mAppsSuspended; final boolean shouldSuspend = suspensionState != PERSONAL_APPS_NOT_SUSPENDED; if (suspended != shouldSuspend) { @@ -15813,8 +15842,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mInjector.binderWithCleanCallingIdentity(() -> { try { final String[] appsToSuspend = - new PersonalAppsSuspensionHelper(mContext, mInjector.getPackageManager()) - .getPersonalAppsForSuspension(userId); + new PersonalAppsSuspensionHelper( + mContext.createContextAsUser(UserHandle.of(userId), 0 /* flags */)) + .getPersonalAppsForSuspension(); final String[] failedPackages = mIPackageManager.setPackagesSuspendedAsUser( appsToSuspend, suspended, null, null, null, PLATFORM_PACKAGE_NAME, userId); if (!ArrayUtils.isEmpty(failedPackages)) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java b/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java index 180acc85e5f6..d9db17eba887 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java @@ -20,7 +20,6 @@ import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL import android.accessibilityservice.AccessibilityServiceInfo; import android.annotation.Nullable; -import android.annotation.UserIdInt; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -32,7 +31,7 @@ import android.os.IBinder; import android.os.ServiceManager; import android.provider.Settings; import android.text.TextUtils; -import android.util.Log; +import android.util.ArraySet; import android.util.Slog; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.IAccessibilityManager; @@ -43,7 +42,6 @@ import com.android.server.inputmethod.InputMethodManagerInternal; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashSet; import java.util.List; import java.util.Set; @@ -56,18 +54,21 @@ public class PersonalAppsSuspensionHelper { private final Context mContext; private final PackageManager mPackageManager; - public PersonalAppsSuspensionHelper(Context context, PackageManager packageManager) { + /** + * @param context Context for the user whose apps should to be suspended. + */ + public PersonalAppsSuspensionHelper(Context context) { mContext = context; - mPackageManager = packageManager; + mPackageManager = context.getPackageManager(); } /** * @return List of packages that should be suspended to limit personal use. */ - String[] getPersonalAppsForSuspension(@UserIdInt int userId) { + String[] getPersonalAppsForSuspension() { final List<PackageInfo> installedPackageInfos = - mPackageManager.getInstalledPackagesAsUser(0 /* flags */, userId); - final Set<String> result = new HashSet<>(); + mPackageManager.getInstalledPackages(0 /* flags */); + final Set<String> result = new ArraySet<>(); for (final PackageInfo packageInfo : installedPackageInfos) { final ApplicationInfo info = packageInfo.applicationInfo; if ((!info.isSystemApp() && !info.isUpdatedSystemApp()) @@ -77,11 +78,15 @@ public class PersonalAppsSuspensionHelper { } result.removeAll(getCriticalPackages()); result.removeAll(getSystemLauncherPackages()); - result.removeAll(getAccessibilityServices(userId)); - result.removeAll(getInputMethodPackages(userId)); - result.remove(getActiveLauncherPackages(userId)); - result.remove(getDialerPackage(userId)); - result.remove(getSettingsPackageName(userId)); + result.removeAll(getAccessibilityServices()); + result.removeAll(getInputMethodPackages()); + result.remove(getSettingsPackageName()); + + final String[] unsuspendablePackages = + mPackageManager.getUnsuspendablePackages(result.toArray(new String[0])); + for (final String pkg : unsuspendablePackages) { + result.remove(pkg); + } Slog.i(LOG_TAG, "Packages subject to suspension: " + String.join(",", result)); return result.toArray(new String[0]); @@ -104,7 +109,6 @@ public class PersonalAppsSuspensionHelper { final ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(packageName, 0); if (applicationInfo.isSystemApp() || applicationInfo.isUpdatedSystemApp()) { - Log.d(LOG_TAG, "Not suspending system launcher package: " + packageName); result.add(packageName); } } catch (PackageManager.NameNotFoundException e) { @@ -114,81 +118,53 @@ public class PersonalAppsSuspensionHelper { return result; } - private List<String> getAccessibilityServices(int userId) { + private List<String> getAccessibilityServices() { final List<AccessibilityServiceInfo> accessibilityServiceInfos = - getAccessibilityManagerForUser(userId) + getAccessibilityManagerForUser(mContext.getUserId()) .getEnabledAccessibilityServiceList(FEEDBACK_ALL_MASK); final List<String> result = new ArrayList<>(); for (final AccessibilityServiceInfo serviceInfo : accessibilityServiceInfos) { final ComponentName componentName = ComponentName.unflattenFromString(serviceInfo.getId()); if (componentName != null) { - final String packageName = componentName.getPackageName(); - Slog.d(LOG_TAG, "Not suspending a11y service: " + packageName); - result.add(packageName); + result.add(componentName.getPackageName()); } } return result; } - private List<String> getInputMethodPackages(int userId) { - final List<InputMethodInfo> enabledImes = - InputMethodManagerInternal.get().getEnabledInputMethodListAsUser(userId); + private List<String> getInputMethodPackages() { + final List<InputMethodInfo> enabledImes = InputMethodManagerInternal.get() + .getEnabledInputMethodListAsUser(mContext.getUserId()); final List<String> result = new ArrayList<>(); for (final InputMethodInfo info : enabledImes) { - Slog.d(LOG_TAG, "Not suspending IME: " + info.getPackageName()); result.add(info.getPackageName()); } return result; } @Nullable - private String getActiveLauncherPackages(int userId) { - final Intent intent = new Intent(Intent.ACTION_MAIN); - intent.addCategory(Intent.CATEGORY_HOME); - intent.addCategory(Intent.CATEGORY_DEFAULT); - return getPackageNameForIntent("active launcher", intent, userId); - } - - @Nullable - private String getSettingsPackageName(int userId) { + private String getSettingsPackageName() { final Intent intent = new Intent(Settings.ACTION_SETTINGS); intent.addCategory(Intent.CATEGORY_DEFAULT); - return getPackageNameForIntent("settings", intent, userId); - } - - @Nullable - private String getDialerPackage(int userId) { - final Intent intent = new Intent(Intent.ACTION_DIAL); - intent.addCategory(Intent.CATEGORY_DEFAULT); - return getPackageNameForIntent("dialer", intent, userId); - } - - @Nullable - private String getPackageNameForIntent(String name, Intent intent, int userId) { - final ResolveInfo resolveInfo = - mPackageManager.resolveActivityAsUser(intent, /* flags= */ 0, userId); + final ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, /* flags= */ 0); if (resolveInfo != null) { - final String packageName = resolveInfo.activityInfo.packageName; - Slog.d(LOG_TAG, "Not suspending " + name + " package: " + packageName); - return packageName; + return resolveInfo.activityInfo.packageName; } return null; } private List<String> getCriticalPackages() { - final List<String> result = Arrays.asList(mContext.getResources() + return Arrays.asList(mContext.getResources() .getStringArray(R.array.config_packagesExemptFromSuspension)); - Slog.d(LOG_TAG, "Not suspending critical packages: " + String.join(",", result)); - return result; } private boolean hasLauncherIntent(String packageName) { final Intent intentToResolve = new Intent(Intent.ACTION_MAIN); intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER); intentToResolve.setPackage(packageName); - final List<ResolveInfo> resolveInfos = mPackageManager.queryIntentActivities( - intentToResolve, PackageManager.GET_UNINSTALLED_PACKAGES); + final List<ResolveInfo> resolveInfos = + mPackageManager.queryIntentActivities(intentToResolve, /* flags= */ 0); return resolveInfos != null && !resolveInfos.isEmpty(); } |