diff options
| author | 2018-10-16 11:08:28 -0700 | |
|---|---|---|
| committer | 2018-11-02 11:29:21 -0700 | |
| commit | d3464c7c938f3facb3dc26f449249b93774d35da (patch) | |
| tree | 35d31c3e46d3a7843ea341f4a866825fa54f2932 | |
| parent | d752e1f95b80b302213cab7446267471b2630bef (diff) | |
Adds bindClient method to service AIDL
Will be used to recreate client with a PendingIntent.
Bug: 117612105
Test: Compile only
Change-Id: Iad9ada1fe113275790336663112f276327d4f558
5 files changed, 138 insertions, 29 deletions
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java index b0b77f31c24d..18e1b9fecb93 100644 --- a/core/java/android/hardware/location/ContextHubManager.java +++ b/core/java/android/hardware/location/ContextHubManager.java @@ -808,7 +808,7 @@ public final class ContextHubManager { * * @throws IllegalArgumentException if hubInfo does not represent a valid hub, or pendingIntent * was not associated with a client - * @throws IllegalStateException if there were too many registered clients at the service + * @throws IllegalStateException if the client is already registered to a valid callback * @throws NullPointerException if pendingIntent, hubInfo, callback, or executor is null * * @hide @@ -833,7 +833,7 @@ public final class ContextHubManager { * * @throws IllegalArgumentException if hubInfo does not represent a valid hub, or pendingIntent * was not associated with a client - * @throws IllegalStateException if there were too many registered clients at the service + * @throws IllegalStateException if the client is already registered to a valid callback * @throws NullPointerException if pendingIntent, hubInfo, or callback is null * * @hide diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl index 233e857d8e67..9b0acdf14724 100644 --- a/core/java/android/hardware/location/IContextHubService.aidl +++ b/core/java/android/hardware/location/IContextHubService.aidl @@ -17,6 +17,7 @@ package android.hardware.location; // Declare any non-default types here with import statements +import android.app.PendingIntent; import android.hardware.location.ContextHubInfo; import android.hardware.location.ContextHubMessage; import android.hardware.location.NanoApp; @@ -60,6 +61,11 @@ interface IContextHubService { // Creates a client to send and receive messages IContextHubClient createClient(in IContextHubClientCallback client, int contextHubId); + // Binds an existing client to a new callback interface, provided a previously registered + // PendingIntent + IContextHubClient bindClient( + in PendingIntent pendingIntent, in IContextHubClientCallback client, int contextHubId); + // Returns a list of ContextHub objects of available hubs List<ContextHubInfo> getContextHubs(); diff --git a/services/core/java/com/android/server/location/ContextHubClientBroker.java b/services/core/java/com/android/server/location/ContextHubClientBroker.java index 01ea8f41ca82..642347021201 100644 --- a/services/core/java/com/android/server/location/ContextHubClientBroker.java +++ b/services/core/java/com/android/server/location/ContextHubClientBroker.java @@ -159,25 +159,12 @@ public class ContextHubClientBroker extends IContextHubClient.Stub /* package */ ContextHubClientBroker( Context context, IContexthub contextHubProxy, ContextHubClientManager clientManager, - ContextHubInfo contextHubInfo, short hostEndPointId, - IContextHubClientCallback callback) { + ContextHubInfo contextHubInfo, short hostEndPointId) { mContext = context; mContextHubProxy = contextHubProxy; mClientManager = clientManager; mAttachedContextHubInfo = contextHubInfo; mHostEndPointId = hostEndPointId; - mCallbackInterface = callback; - } - - /** - * Attaches a death recipient for this client - * - * @throws RemoteException if the client has already died - */ - /* package */ synchronized void attachDeathRecipient() throws RemoteException { - if (mCallbackInterface != null) { - mCallbackInterface.asBinder().linkToDeath(this, 0 /* flags */); - } } /** @@ -282,6 +269,37 @@ public class ContextHubClientBroker extends IContextHubClient.Stub } /** + * Sets the callback interface for this client, only if the callback is currently unregistered. + * + * Also attaches a death recipient to a ContextHubClientBroker object. If unsuccessful, the + * connection is closed. + * + * @param callback the callback interface + * @return true if the callback was successfully set, false otherwise + * + * @throws IllegalStateException if the client has already been registered to a callback + */ + /* package */ + synchronized boolean setCallback(IContextHubClientCallback callback) { + boolean success = false; + if (mCallbackInterface != null) { + throw new IllegalStateException("Client is already registered with a callback"); + } else { + mCallbackInterface = callback; + try { + mCallbackInterface.asBinder().linkToDeath(this, 0 /* flags */); + success = true; + } catch (RemoteException e) { + // The client process has died, so we close the connection. + Log.e(TAG, "Failed to attach death recipient to client"); + close(); + } + } + + return success; + } + + /** * @return the ID of the context hub this client is attached to */ /* package */ int getAttachedContextHubId() { @@ -353,6 +371,18 @@ public class ContextHubClientBroker extends IContextHubClient.Stub } /** + * @param intent the PendingIntent to compare to + * @return true if the given PendingIntent is currently registered, false otherwise + */ + /* package */ boolean hasPendingIntent(PendingIntent intent) { + PendingIntent pendingIntent = null; + synchronized (this) { + pendingIntent = mPendingIntentRequest.getPendingIntent(); + } + return (pendingIntent != null) && pendingIntent.equals(intent); + } + + /** * Helper function to invoke a specified client callback, if the connection is open. * * @param consumer the consumer specifying the callback to invoke diff --git a/services/core/java/com/android/server/location/ContextHubClientManager.java b/services/core/java/com/android/server/location/ContextHubClientManager.java index eda8c6f8b418..72879ddc2018 100644 --- a/services/core/java/com/android/server/location/ContextHubClientManager.java +++ b/services/core/java/com/android/server/location/ContextHubClientManager.java @@ -16,6 +16,7 @@ package com.android.server.location; +import android.app.PendingIntent; import android.content.Context; import android.hardware.contexthub.V1_0.ContextHubMsg; import android.hardware.contexthub.V1_0.IContexthub; @@ -88,15 +89,9 @@ import java.util.function.Consumer; */ /* package */ IContextHubClient registerClient( IContextHubClientCallback clientCallback, ContextHubInfo contextHubInfo) { - ContextHubClientBroker broker = createNewClientBroker(clientCallback, contextHubInfo); - - try { - broker.attachDeathRecipient(); - } catch (RemoteException e) { - // The client process has died, so we close the connection and return null. - Log.e(TAG, "Failed to attach death recipient to client"); - broker.close(); - return null; + ContextHubClientBroker broker = createNewClientBroker(contextHubInfo); + if (!broker.setCallback(clientCallback)) { + return null; // Client process has died, so we return null } Log.d(TAG, "Registered client with host endpoint ID " + broker.getHostEndPointId()); @@ -104,6 +99,36 @@ import java.util.function.Consumer; } /** + * Binds a existing and registered client with a new callback interface, provided a previously + * registered PendingIntent. + * + * @param pendingIntent a previously registered PendingIntent for a registered client + * @param clientCallback the callback interface of the client to bind to + * @param contextHubId the ID of the hub this client is attached to + * + * @return the client interface + * + * @throws IllegalArgumentException if no matching client is found + * @throws IllegalStateException if the client has already been registered to a callback + */ + /* package */ IContextHubClient bindClient( + PendingIntent pendingIntent, IContextHubClientCallback clientCallback, + int contextHubId) { + ContextHubClientBroker broker = getClientBroker(pendingIntent, contextHubId); + if (broker == null) { + throw new IllegalArgumentException("Could not find client of Context Hub (ID = " + + contextHubId + ") with PendingIntent"); + } + + if (!broker.setCallback(clientCallback)) { + return null; // Client process has died, so we return null + } + + Log.d(TAG, "Re-registered client with host endpoint ID " + broker.getHostEndPointId()); + return IContextHubClient.Stub.asInterface(broker); + } + + /** * Handles a message sent from a nanoapp. * * @param contextHubId the ID of the hub where the nanoapp sent the message from @@ -182,7 +207,6 @@ import java.util.function.Consumer; * Creates a new ContextHubClientBroker object for a client and registers it with the client * manager. * - * @param clientCallback the callback interface of the client to register * @param contextHubInfo the object describing the hub this client is attached to * * @return the ContextHubClientBroker object @@ -190,7 +214,7 @@ import java.util.function.Consumer; * @throws IllegalStateException if max number of clients have already registered */ private synchronized ContextHubClientBroker createNewClientBroker( - IContextHubClientCallback clientCallback, ContextHubInfo contextHubInfo) { + ContextHubInfo contextHubInfo) { if (mHostEndPointIdToClientMap.size() == MAX_CLIENT_ID + 1) { throw new IllegalStateException("Could not register client - max limit exceeded"); } @@ -200,8 +224,7 @@ import java.util.function.Consumer; for (int i = 0; i <= MAX_CLIENT_ID; i++) { if (!mHostEndPointIdToClientMap.containsKey((short) id)) { broker = new ContextHubClientBroker( - mContext, mContextHubProxy, this, contextHubInfo, (short) id, - clientCallback); + mContext, mContextHubProxy, this, contextHubInfo, (short) id); mHostEndPointIdToClientMap.put((short) id, broker); mNextHostEndpointId = (id == MAX_CLIENT_ID) ? 0 : id + 1; break; @@ -236,4 +259,22 @@ import java.util.function.Consumer; } } } + + /** + * Retrieves a ContextHubClientBroker object with a matching PendingIntent and Context Hub ID. + * + * @param pendingIntent the PendingIntent to match + * @param contextHubId the ID of the Context Hub the client is attached to + * @return the matching ContextHubClientBroker, null if not found + */ + private ContextHubClientBroker getClientBroker(PendingIntent pendingIntent, int contextHubId) { + for (ContextHubClientBroker broker : mHostEndPointIdToClientMap.values()) { + if (broker.hasPendingIntent(pendingIntent) + && broker.getAttachedContextHubId() == contextHubId) { + return broker; + } + } + + return null; + } } diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java index e3c2863e7c72..215e67c0884f 100644 --- a/services/core/java/com/android/server/location/ContextHubService.java +++ b/services/core/java/com/android/server/location/ContextHubService.java @@ -16,6 +16,7 @@ package com.android.server.location; +import android.app.PendingIntent; import android.content.Context; import android.hardware.contexthub.V1_0.AsyncEventType; import android.hardware.contexthub.V1_0.ContextHub; @@ -631,6 +632,37 @@ public class ContextHubService extends IContextHubService.Stub { } /** + * Recreates and binds a IContextHubClientCallback interface to an existing and registered + * client at the service for the specified Context Hub, provided a previously registered + * PendingIntent. + * + * @param pendingIntent the PendingIntent previously registered for the client + * @param clientCallback the client interface to register with the service + * @param contextHubId the ID of the hub this client is attached to + * @return the generated client interface, null if registration was unsuccessful + * + * @throws IllegalArgumentException if contextHubId is not a valid ID + * @throws NullPointerException if clientCallback or pendingIntent is null + */ + @Override + public IContextHubClient bindClient( + PendingIntent pendingIntent, IContextHubClientCallback clientCallback, + int contextHubId) throws RemoteException { + checkPermissions(); + if (!isValidContextHubId(contextHubId)) { + throw new IllegalArgumentException("Invalid context hub ID " + contextHubId); + } + if (pendingIntent == null) { + throw new NullPointerException("Cannot create client with null pending intent"); + } + if (clientCallback == null) { + throw new NullPointerException("Cannot create client with null callback"); + } + + return mClientManager.bindClient(pendingIntent, clientCallback, contextHubId); + } + + /** * Loads a nanoapp binary at the specified Context hub. * * @param contextHubId the ID of the hub to load the binary |