summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java4
-rw-r--r--core/java/android/content/pm/PackageManager.java4
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java48
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java84
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();
}