diff options
2 files changed, 156 insertions, 53 deletions
diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java index 766283b92d91..028288f73564 100644 --- a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java +++ b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java @@ -43,7 +43,6 @@ import android.os.RemoteException; import android.service.ambientcontext.AmbientContextDetectionResult; import android.service.ambientcontext.AmbientContextDetectionServiceStatus; import android.text.TextUtils; -import android.util.ArraySet; import android.util.IndentingPrintWriter; import android.util.Slog; @@ -54,7 +53,6 @@ import com.android.server.infra.AbstractPerUserSystemService; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; -import java.util.Set; /** * Per-user manager service for {@link AmbientContextEvent}s. @@ -69,19 +67,13 @@ final class AmbientContextManagerPerUserService extends RemoteAmbientContextDetectionService mRemoteService; private ComponentName mComponentName; - private Set<PendingIntent> mExistingPendingIntents; AmbientContextManagerPerUserService( @NonNull AmbientContextManagerService master, Object lock, @UserIdInt int userId) { super(master, lock, userId); - mExistingPendingIntents = new ArraySet<>(); } void destroyLocked() { - if (isVerbose()) { - Slog.v(TAG, "destroyLocked()"); - } - Slog.d(TAG, "Trying to cancel the remote request. Reason: Service destroyed."); if (mRemoteService != null) { synchronized (mLock) { @@ -118,7 +110,19 @@ final class AmbientContextManagerPerUserService extends if (mComponentName == null) { mComponentName = updateServiceInfoLocked(); } - return mComponentName != null; + if (mComponentName == null) { + return false; + } + + ServiceInfo serviceInfo; + try { + serviceInfo = AppGlobals.getPackageManager().getServiceInfo( + mComponentName, 0, mUserId); + } catch (RemoteException e) { + Slog.w(TAG, "RemoteException while setting up service"); + return false; + } + return serviceInfo != null; } @Override @@ -171,18 +175,10 @@ final class AmbientContextManagerPerUserService extends return; } - // Remove any existing PendingIntent for this package. - String callingPackage = pendingIntent.getCreatorPackage(); - PendingIntent duplicatePendingIntent = findExistingRequestByPackage(callingPackage); - if (duplicatePendingIntent != null) { - Slog.d(TAG, "Replace duplicate request from " + callingPackage); - mExistingPendingIntents.remove(duplicatePendingIntent); - } - - // Register package and add pendingIntent to mExistingPendingIntents - startDetection(request, callingPackage, createDetectionResultRemoteCallback(), - getServerStatusCallback(clientStatusCallback)); - mExistingPendingIntents.add(pendingIntent); + // Register package and add to existing ClientRequests cache + startDetection(request, pendingIntent.getCreatorPackage(), + createDetectionResultRemoteCallback(), clientStatusCallback); + mMaster.newClientAdded(mUserId, request, pendingIntent, clientStatusCallback); } } @@ -214,15 +210,17 @@ final class AmbientContextManagerPerUserService extends @VisibleForTesting void startDetection(AmbientContextEventRequest request, String callingPackage, - RemoteCallback detectionResultCallback, RemoteCallback statusCallback) { + RemoteCallback detectionResultCallback, RemoteCallback clientStatusCallback) { Slog.d(TAG, "Requested detection of " + request.getEventTypes()); synchronized (mLock) { if (setUpServiceIfNeeded()) { ensureRemoteServiceInitiated(); mRemoteService.startDetection(request, callingPackage, detectionResultCallback, - statusCallback); + getServerStatusCallback(clientStatusCallback)); } else { Slog.w(TAG, "No valid component found for AmbientContextDetectionService"); + sendStatusToCallback(clientStatusCallback, + AmbientContextManager.STATUS_NOT_SUPPORTED); } } } @@ -245,15 +243,8 @@ final class AmbientContextManagerPerUserService extends */ public void onUnregisterObserver(String callingPackage) { synchronized (mLock) { - PendingIntent pendingIntent = findExistingRequestByPackage(callingPackage); - if (pendingIntent == null) { - Slog.d(TAG, "No registration found for " + callingPackage); - return; - } - - // Remove from existing requests - mExistingPendingIntents.remove(pendingIntent); - stopDetection(pendingIntent.getCreatorPackage()); + stopDetection(callingPackage); + mMaster.clientRemoved(mUserId, callingPackage); } } @@ -265,7 +256,7 @@ final class AmbientContextManagerPerUserService extends if (!setUpServiceIfNeeded()) { Slog.w(TAG, "Detection service is not available at this moment."); sendStatusToCallback(statusCallback, - AmbientContextManager.STATUS_SERVICE_UNAVAILABLE); + AmbientContextManager.STATUS_NOT_SUPPORTED); return; } ensureRemoteServiceInitiated(); @@ -382,16 +373,6 @@ final class AmbientContextManagerPerUserService extends } } - @Nullable - private PendingIntent findExistingRequestByPackage(String callingPackage) { - for (PendingIntent pendingIntent : mExistingPendingIntents) { - if (pendingIntent.getCreatorPackage().equals(callingPackage)) { - return pendingIntent; - } - } - return null; - } - /** * Sends out the Intent to the client after the event is detected. * @@ -418,22 +399,22 @@ final class AmbientContextManagerPerUserService extends } @NonNull - private RemoteCallback createDetectionResultRemoteCallback() { + RemoteCallback createDetectionResultRemoteCallback() { return new RemoteCallback(result -> { AmbientContextDetectionResult detectionResult = (AmbientContextDetectionResult) result.get( AmbientContextDetectionResult.RESULT_RESPONSE_BUNDLE_KEY); + String packageName = detectionResult.getPackageName(); + PendingIntent pendingIntent = mMaster.getPendingIntent(mUserId, packageName); + if (pendingIntent == null) { + return; + } + final long token = Binder.clearCallingIdentity(); try { - for (PendingIntent pendingIntent : mExistingPendingIntents) { - // Send PendingIntent to requesting packages - String creatorPackage = pendingIntent.getCreatorPackage(); - if (detectionResult.getPackageName().equals(creatorPackage)) { - sendDetectionResultIntent(pendingIntent, detectionResult); - Slog.i(TAG, "Got detection result of " + detectionResult.getEvents() - + " for " + creatorPackage); - } - } + sendDetectionResultIntent(pendingIntent, detectionResult); + Slog.i(TAG, "Got detection result of " + detectionResult.getEvents() + + " for " + packageName); } finally { Binder.restoreCallingIdentity(token); } diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java index cfca7ec6f568..4206262398c7 100644 --- a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java +++ b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java @@ -20,6 +20,7 @@ import static android.provider.DeviceConfig.NAMESPACE_AMBIENT_CONTEXT_MANAGER_SE import android.Manifest; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.PendingIntent; import android.app.ambientcontext.AmbientContextEvent; @@ -34,6 +35,7 @@ import android.os.ResultReceiver; import android.os.ShellCallback; import android.os.UserHandle; import android.provider.DeviceConfig; +import android.util.ArraySet; import android.util.Slog; import com.android.internal.R; @@ -60,9 +62,50 @@ public class AmbientContextManagerService extends /** Default value in absence of {@link DeviceConfig} override. */ private static final boolean DEFAULT_SERVICE_ENABLED = true; + public static final int MAX_TEMPORARY_SERVICE_DURATION_MS = 30000; + + static class ClientRequest { + private final int mUserId; + private final AmbientContextEventRequest mRequest; + private final PendingIntent mPendingIntent; + private final RemoteCallback mClientStatusCallback; + + ClientRequest(int userId, AmbientContextEventRequest request, + PendingIntent pendingIntent, RemoteCallback clientStatusCallback) { + this.mUserId = userId; + this.mRequest = request; + this.mPendingIntent = pendingIntent; + this.mClientStatusCallback = clientStatusCallback; + } + + String getPackageName() { + return mPendingIntent.getCreatorPackage(); + } + + AmbientContextEventRequest getRequest() { + return mRequest; + } + + PendingIntent getPendingIntent() { + return mPendingIntent; + } + + RemoteCallback getClientStatusCallback() { + return mClientStatusCallback; + } + + boolean hasUserId(int userId) { + return mUserId == userId; + } + + boolean hasUserIdAndPackageName(int userId, String packageName) { + return (userId == mUserId) && packageName.equals(getPackageName()); + } + } private final Context mContext; boolean mIsServiceEnabled; + private Set<ClientRequest> mExistingClientRequests; public AmbientContextManagerService(Context context) { super(context, @@ -73,6 +116,7 @@ public class AmbientContextManagerService extends PACKAGE_UPDATE_POLICY_REFRESH_EAGER | /*To avoid high latency*/ PACKAGE_RESTART_POLICY_REFRESH_EAGER); mContext = context; + mExistingClientRequests = new ArraySet<>(); } @Override @@ -94,6 +138,44 @@ public class AmbientContextManagerService extends } } + void newClientAdded(int userId, AmbientContextEventRequest request, + PendingIntent pendingIntent, RemoteCallback clientStatusCallback) { + Slog.d(TAG, "New client added: " + pendingIntent.getCreatorPackage()); + + // Remove any existing ClientRequest for this user and package. + mExistingClientRequests.removeAll( + findExistingRequests(userId, pendingIntent.getCreatorPackage())); + + // Add to existing ClientRequests + mExistingClientRequests.add( + new ClientRequest(userId, request, pendingIntent, clientStatusCallback)); + } + + void clientRemoved(int userId, String packageName) { + Slog.d(TAG, "Remove client: " + packageName); + mExistingClientRequests.removeAll(findExistingRequests(userId, packageName)); + } + + private Set<ClientRequest> findExistingRequests(int userId, String packageName) { + Set<ClientRequest> existingRequests = new ArraySet<>(); + for (ClientRequest clientRequest : mExistingClientRequests) { + if (clientRequest.hasUserIdAndPackageName(userId, packageName)) { + existingRequests.add(clientRequest); + } + } + return existingRequests; + } + + @Nullable + PendingIntent getPendingIntent(int userId, String packageName) { + for (ClientRequest clientRequest : mExistingClientRequests) { + if (clientRequest.hasUserIdAndPackageName(userId, packageName)) { + return clientRequest.getPendingIntent(); + } + } + return null; + } + private void onDeviceConfigChange(@NonNull Set<String> keys) { if (keys.contains(KEY_SERVICE_ENABLED)) { mIsServiceEnabled = DeviceConfig.getBoolean( @@ -111,9 +193,33 @@ public class AmbientContextManagerService extends @Override protected void onServiceRemoved( AmbientContextManagerPerUserService service, @UserIdInt int userId) { + Slog.d(TAG, "onServiceRemoved"); service.destroyLocked(); } + @Override + protected void onServicePackageRestartedLocked(@UserIdInt int userId) { + Slog.d(TAG, "Restoring remote request. Reason: Service package restarted."); + restorePreviouslyEnabledClients(userId); + } + + @Override + protected void onServicePackageUpdatedLocked(@UserIdInt int userId) { + Slog.d(TAG, "Restoring remote request. Reason: Service package updated."); + restorePreviouslyEnabledClients(userId); + } + + @Override + protected void enforceCallingPermissionForManagement() { + getContext().enforceCallingPermission( + Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG); + } + + @Override + protected int getMaximumTemporaryServiceDurationMs() { + return MAX_TEMPORARY_SERVICE_DURATION_MS; + } + /** Returns {@code true} if the detection service is configured on this device. */ public static boolean isDetectionServiceConfigured() { final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class); @@ -182,6 +288,22 @@ public class AmbientContextManagerService extends } } + private void restorePreviouslyEnabledClients(int userId) { + synchronized (mLock) { + final AmbientContextManagerPerUserService service = getServiceForUserLocked(userId); + for (ClientRequest clientRequest : mExistingClientRequests) { + // Start detection for previously enabled clients + if (clientRequest.hasUserId(userId)) { + Slog.d(TAG, "Restoring detection for " + clientRequest.getPackageName()); + service.startDetection(clientRequest.getRequest(), + clientRequest.getPackageName(), + service.createDetectionResultRemoteCallback(), + clientRequest.getClientStatusCallback()); + } + } + } + } + /** * Returns the AmbientContextManagerPerUserService component for this user. */ |