diff options
author | Mehdi Alizadeh <mett@google.com> | 2019-08-23 14:44:50 -0700 |
---|---|---|
committer | Mehdi Alizadeh <mett@google.com> | 2019-08-28 20:21:49 +0000 |
commit | 23e044d09dc5002af27df3add4d0537604a10404 (patch) | |
tree | 9bc433399caaf5f58b83ac495717887af1b35019 | |
parent | a58013ae18dbeb87cf3b103d4764428e76a87efe (diff) |
Rebind to the remote service if AppPrediction is restarted or updated
Rebind to the remote AppPredictionService when the service package is
updated. Also adds new restart policy flags in
AbstractMasterSystemService to be able to keep per-user instances in the
cache when service restarts as a result of package data getting cleared,
so that we can revive the existing sessions. This would potentially fix
the issue for other services that try to keep the sessions over data
resets.
Bug: 139445447
Test: Reinstall the AiAi package and verify that suggested apps in launcher are getting updated
Test: Clear data for Device Personalization Services and verify that suggested apps in launcher are getting updated
Test: atest CtsAppPredictionServiceTestCases CtsContentCaptureServiceTestCases
Change-Id: Ie835cb159faa9c0718cd63a3045251444b89e505
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); |