summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Arthur Ishiguro <arthuri@google.com> 2018-10-16 11:08:28 -0700
committer Arthur Ishiguro <arthuri@google.com> 2018-11-02 11:29:21 -0700
commitd3464c7c938f3facb3dc26f449249b93774d35da (patch)
tree35d31c3e46d3a7843ea341f4a866825fa54f2932
parentd752e1f95b80b302213cab7446267471b2630bef (diff)
Adds bindClient method to service AIDL
Will be used to recreate client with a PendingIntent. Bug: 117612105 Test: Compile only Change-Id: Iad9ada1fe113275790336663112f276327d4f558
-rw-r--r--core/java/android/hardware/location/ContextHubManager.java4
-rw-r--r--core/java/android/hardware/location/IContextHubService.aidl6
-rw-r--r--services/core/java/com/android/server/location/ContextHubClientBroker.java58
-rw-r--r--services/core/java/com/android/server/location/ContextHubClientManager.java67
-rw-r--r--services/core/java/com/android/server/location/ContextHubService.java32
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