diff options
4 files changed, 185 insertions, 32 deletions
diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java index d7e68f896c6c..5844f9873001 100644 --- a/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java +++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java @@ -23,6 +23,7 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.app.prediction.AppPredictionContext; import android.app.prediction.AppPredictionSessionId; import android.app.prediction.AppTargetEvent; @@ -61,7 +62,8 @@ public class AppPredictionManagerService extends public AppPredictionManagerService(Context context) { super(context, new FrameworkResourcesServiceNameResolver(context, - com.android.internal.R.string.config_defaultAppPredictionService), null); + com.android.internal.R.string.config_defaultAppPredictionService), null, + PACKAGE_UPDATE_POLICY_NO_REFRESH | PACKAGE_RESTART_POLICY_NO_REFRESH); mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class); } @@ -80,6 +82,22 @@ public class AppPredictionManagerService extends getContext().enforceCallingPermission(MANAGE_APP_PREDICTIONS, TAG); } + @Override // from AbstractMasterSystemService + protected void onServicePackageUpdatedLocked(@UserIdInt int userId) { + final AppPredictionPerUserService service = peekServiceForUserLocked(userId); + if (service != null) { + service.onPackageUpdatedLocked(); + } + } + + @Override // from AbstractMasterSystemService + protected void onServicePackageRestartedLocked(@UserIdInt int userId) { + final AppPredictionPerUserService service = peekServiceForUserLocked(userId); + if (service != null) { + service.onPackageRestartedLocked(); + } + } + @Override protected int getMaximumTemporaryServiceDurationMs() { return MAX_TEMP_SERVICE_DURATION_MS; diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java index 03c4542a50d4..4f49fb7578a1 100644 --- a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java +++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java @@ -251,6 +251,40 @@ public class AppPredictionPerUserService extends // Do nothing, eventually the system will bind to the remote service again... } + void onPackageUpdatedLocked() { + if (isDebug()) { + Slog.v(TAG, "onPackageUpdatedLocked()"); + } + destroyAndRebindRemoteService(); + } + + void onPackageRestartedLocked() { + if (isDebug()) { + Slog.v(TAG, "onPackageRestartedLocked()"); + } + destroyAndRebindRemoteService(); + } + + private void destroyAndRebindRemoteService() { + if (mRemoteService == null) { + return; + } + + if (isDebug()) { + Slog.d(TAG, "Destroying the old remote service."); + } + mRemoteService.destroy(); + mRemoteService = null; + + mRemoteService = getRemoteServiceLocked(); + if (mRemoteService != null) { + if (isDebug()) { + Slog.d(TAG, "Rebinding to the new remote service."); + } + mRemoteService.reconnect(); + } + } + /** * Called after the remote service connected, it's used to restore state from a 'zombie' * service (i.e., after it died). diff --git a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java index c82e7a012fff..04e0e7f7102f 100644 --- a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java +++ b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java @@ -135,6 +135,13 @@ public class RemoteAppPredictionService extends } /** + * Schedules a request to bind to the remote service. + */ + public void reconnect() { + super.scheduleBind(); + } + + /** * Failure callback */ public interface RemoteAppPredictionServiceCallbacks diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java index 9782f30d3074..259527a5f217 100644 --- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java +++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java @@ -79,7 +79,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem S extends AbstractPerUserSystemService<S, M>> extends SystemService { /** On a package update, does not refresh the per-user service in the cache. */ - public static final int PACKAGE_UPDATE_POLICY_NO_REFRESH = 0; + public static final int PACKAGE_UPDATE_POLICY_NO_REFRESH = 0x00000001; /** * On a package update, removes any existing per-user services in the cache. @@ -87,20 +87,40 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem * <p>This does not immediately recreate these services. It is assumed they will be recreated * for the next user request. */ - public static final int PACKAGE_UPDATE_POLICY_REFRESH_LAZY = 1; + public static final int PACKAGE_UPDATE_POLICY_REFRESH_LAZY = 0x00000002; /** * On a package update, removes and recreates any existing per-user services in the cache. */ - public static final int PACKAGE_UPDATE_POLICY_REFRESH_EAGER = 2; + public static final int PACKAGE_UPDATE_POLICY_REFRESH_EAGER = 0x00000004; - @IntDef(flag = true, prefix = { "PACKAGE_UPDATE_POLICY_" }, value = { + /** On a package restart, does not refresh the per-user service in the cache. */ + public static final int PACKAGE_RESTART_POLICY_NO_REFRESH = 0x00000010; + + /** + * On a package restart, removes any existing per-user services in the cache. + * + * <p>This does not immediately recreate these services. It is assumed they will be recreated + * for the next user request. + */ + public static final int PACKAGE_RESTART_POLICY_REFRESH_LAZY = 0x00000020; + + /** + * On a package restart, removes and recreates any existing per-user services in the cache. + */ + public static final int PACKAGE_RESTART_POLICY_REFRESH_EAGER = 0x00000040; + + @IntDef(flag = true, prefix = { "PACKAGE_" }, value = { PACKAGE_UPDATE_POLICY_NO_REFRESH, PACKAGE_UPDATE_POLICY_REFRESH_LAZY, - PACKAGE_UPDATE_POLICY_REFRESH_EAGER + PACKAGE_UPDATE_POLICY_REFRESH_EAGER, + PACKAGE_RESTART_POLICY_NO_REFRESH, + PACKAGE_RESTART_POLICY_REFRESH_LAZY, + PACKAGE_RESTART_POLICY_REFRESH_EAGER }) + @Retention(RetentionPolicy.SOURCE) - public @interface PackageUpdatePolicy {} + public @interface ServicePackagePolicyFlags {} /** * Log tag @@ -153,12 +173,10 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem private final SparseArray<S> mServicesCache = new SparseArray<>(); /** - * Whether the per-user service should be removed from the cache when its apk is updated. - * - * <p>One of {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH}, - * {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY} or {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER}. + * Value that determines whether the per-user service should be removed from the cache when its + * apk is updated or restarted. */ - private final @PackageUpdatePolicy int mPackageUpdatePolicy; + private final @ServicePackagePolicyFlags int mServicePackagePolicyFlags; /** * Name of the service packages whose APK are being updated, keyed by user id. @@ -184,11 +202,11 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem @Nullable ServiceNameResolver serviceNameResolver, @Nullable String disallowProperty) { this(context, serviceNameResolver, disallowProperty, - /*packageUpdatePolicy=*/ PACKAGE_UPDATE_POLICY_REFRESH_LAZY); + PACKAGE_UPDATE_POLICY_REFRESH_LAZY | PACKAGE_RESTART_POLICY_REFRESH_LAZY); } /** - * Full constructor. + * Full Constructor. * * @param context system context. * @param serviceNameResolver resolver for @@ -197,19 +215,32 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem * @param disallowProperty when not {@code null}, defines a {@link UserManager} restriction that * disables the service. <b>NOTE: </b> you'll also need to add it to * {@code UserRestrictionsUtils.USER_RESTRICTIONS}. - * @param packageUpdatePolicy when {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY}, the - * {@link AbstractPerUserSystemService} is removed from the cache when the service - * package is updated; when {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER}, the - * {@link AbstractPerUserSystemService} is removed from the cache and immediately - * re-added when the service package is updated; when - * {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH}, the service is untouched during the update. + * @param servicePackagePolicyFlags a combination of + * {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH}, + * {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY}, + * {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER}, + * {@link #PACKAGE_RESTART_POLICY_NO_REFRESH}, + * {@link #PACKAGE_RESTART_POLICY_REFRESH_LAZY} or + * {@link #PACKAGE_RESTART_POLICY_REFRESH_EAGER} */ protected AbstractMasterSystemService(@NonNull Context context, - @Nullable ServiceNameResolver serviceNameResolver, - @Nullable String disallowProperty, @PackageUpdatePolicy int packageUpdatePolicy) { + @Nullable ServiceNameResolver serviceNameResolver, @Nullable String disallowProperty, + @ServicePackagePolicyFlags int servicePackagePolicyFlags) { super(context); - mPackageUpdatePolicy = packageUpdatePolicy; + final int updatePolicyMask = PACKAGE_UPDATE_POLICY_NO_REFRESH + | PACKAGE_UPDATE_POLICY_REFRESH_LAZY | PACKAGE_UPDATE_POLICY_REFRESH_EAGER; + if ((servicePackagePolicyFlags & updatePolicyMask) == 0) { + // If the package update policy is not set, add the default flag + servicePackagePolicyFlags |= PACKAGE_UPDATE_POLICY_REFRESH_LAZY; + } + final int restartPolicyMask = PACKAGE_RESTART_POLICY_NO_REFRESH + | PACKAGE_RESTART_POLICY_REFRESH_LAZY | PACKAGE_RESTART_POLICY_REFRESH_EAGER; + if ((servicePackagePolicyFlags & restartPolicyMask) == 0) { + // If the package restart policy is not set, add the default flag + servicePackagePolicyFlags |= PACKAGE_RESTART_POLICY_REFRESH_LAZY; + } + mServicePackagePolicyFlags = servicePackagePolicyFlags; mServiceNameResolver = serviceNameResolver; if (mServiceNameResolver != null) { @@ -606,6 +637,20 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem } /** + * Called after the package data that provides the service for the given user is cleared. + */ + protected void onServicePackageDataClearedLocked(@UserIdInt int userId) { + if (verbose) Slog.v(mTag, "onServicePackageDataCleared(" + userId + ")"); + } + + /** + * Called after the package that provides the service for the given user is restarted. + */ + protected void onServicePackageRestartedLocked(@UserIdInt int userId) { + if (verbose) Slog.v(mTag, "onServicePackageRestarted(" + userId + ")"); + } + + /** * Called after the service is removed from the cache. */ @SuppressWarnings("unused") @@ -677,7 +722,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem final int size = mServicesCache.size(); pw.print(prefix); pw.print("Debug: "); pw.print(realDebug); pw.print(" Verbose: "); pw.println(realVerbose); - pw.print("Refresh on package update: "); pw.println(mPackageUpdatePolicy); + pw.print("Package policy flags: "); pw.println(mServicePackagePolicyFlags); if (mUpdatingPackageNames != null) { pw.print("Packages being updated: "); pw.println(mUpdatingPackageNames); } @@ -733,7 +778,12 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem } mUpdatingPackageNames.put(userId, packageName); onServicePackageUpdatingLocked(userId); - if (mPackageUpdatePolicy != PACKAGE_UPDATE_POLICY_NO_REFRESH) { + if ((mServicePackagePolicyFlags & PACKAGE_UPDATE_POLICY_NO_REFRESH) != 0) { + if (debug) { + Slog.d(mTag, "Holding service for user " + userId + " while package " + + activePackageName + " is being updated"); + } + } else { if (debug) { Slog.d(mTag, "Removing service for user " + userId + " because package " + activePackageName @@ -741,18 +791,14 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem } removeCachedServiceLocked(userId); - if (mPackageUpdatePolicy == PACKAGE_UPDATE_POLICY_REFRESH_EAGER) { + if ((mServicePackagePolicyFlags & PACKAGE_UPDATE_POLICY_REFRESH_EAGER) + != 0) { if (debug) { Slog.d(mTag, "Eagerly recreating service for user " + userId); } getServiceForUserLocked(userId); } - } else { - if (debug) { - Slog.d(mTag, "Holding service for user " + userId + " while package " - + activePackageName + " is being updated"); - } } } } @@ -804,7 +850,13 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem if (!doit) { return true; } - removeCachedServiceLocked(getChangingUserId()); + final String action = intent.getAction(); + final int userId = getChangingUserId(); + if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) { + handleActiveServiceRestartedLocked(activePackageName, userId); + } else { + removeCachedServiceLocked(userId); + } } else { handlePackageUpdateLocked(pkg); } @@ -813,6 +865,23 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem return false; } + @Override + public void onPackageDataCleared(String packageName, int uid) { + if (verbose) Slog.v(mTag, "onPackageDataCleared(): " + packageName); + final int userId = getChangingUserId(); + synchronized (mLock) { + final S service = peekServiceForUserLocked(userId); + if (service != null) { + final ComponentName componentName = service.getServiceComponentName(); + if (componentName != null) { + if (packageName.equals(componentName.getPackageName())) { + onServicePackageDataClearedLocked(userId); + } + } + } + } + } + private void handleActiveServiceRemoved(@UserIdInt int userId) { synchronized (mLock) { removeCachedServiceLocked(userId); @@ -824,6 +893,31 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem } } + private void handleActiveServiceRestartedLocked(String activePackageName, + @UserIdInt int userId) { + if ((mServicePackagePolicyFlags & PACKAGE_RESTART_POLICY_NO_REFRESH) != 0) { + if (debug) { + Slog.d(mTag, "Holding service for user " + userId + " while package " + + activePackageName + " is being restarted"); + } + } else { + if (debug) { + Slog.d(mTag, "Removing service for user " + userId + + " because package " + activePackageName + + " is being restarted"); + } + removeCachedServiceLocked(userId); + + if ((mServicePackagePolicyFlags & PACKAGE_RESTART_POLICY_REFRESH_EAGER) != 0) { + if (debug) { + Slog.d(mTag, "Eagerly recreating service for user " + userId); + } + getServiceForUserLocked(userId); + } + } + onServicePackageRestartedLocked(userId); + } + private String getActiveServicePackageNameLocked() { final int userId = getChangingUserId(); final S service = peekServiceForUserLocked(userId); |