Loading services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java +34 −53 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading @@ -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) { Loading Loading @@ -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 Loading Loading @@ -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); } } Loading Loading @@ -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); } } } Loading @@ -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); } } Loading @@ -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(); Loading Loading @@ -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. * Loading @@ -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); } } + " for " + packageName); } finally { Binder.restoreCallingIdentity(token); } Loading services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java +122 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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, Loading @@ -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 Loading @@ -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( Loading @@ -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); Loading Loading @@ -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. */ Loading Loading
services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java +34 −53 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading @@ -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) { Loading Loading @@ -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 Loading Loading @@ -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); } } Loading Loading @@ -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); } } } Loading @@ -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); } } Loading @@ -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(); Loading Loading @@ -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. * Loading @@ -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); } } + " for " + packageName); } finally { Binder.restoreCallingIdentity(token); } Loading
services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java +122 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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, Loading @@ -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 Loading @@ -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( Loading @@ -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); Loading Loading @@ -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. */ Loading