From 78cebca7204f85ebb7c583bab2fc9891367cd403 Mon Sep 17 00:00:00 2001 From: destradaa Date: Thu, 14 Apr 2016 18:40:14 -0700 Subject: [PATCH] Add support for multiple callback registration in. - Allows several callbacks from different processes to register with the ContextHub service. - Add an 'internal' callback that can be used for primary clients. - Fix issue with parceling NanoApp info Change-Id: Iec203e8b8bc847cb9274f3f4157d0773984dd87c --- .../hardware/location/ContextHubManager.java | 57 ++++++++++++++++++++++ .../hardware/location/ContextHubService.java | 51 +++++++++---------- .../hardware/location/NanoAppInstanceInfo.java | 26 ++++++---- 3 files changed, 98 insertions(+), 36 deletions(-) diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java index 89edaa9780f6..0c3d4b3d7be6 100644 --- a/core/java/android/hardware/location/ContextHubManager.java +++ b/core/java/android/hardware/location/ContextHubManager.java @@ -43,6 +43,12 @@ public final class ContextHubManager { private Handler mCallbackHandler; /** + * @deprecated Use {@code mCallback} instead. + */ + @Deprecated + private ICallback mLocalCallback; + + /** * An interface to receive asynchronous communication from the context hub. */ public abstract static class Callback { @@ -64,6 +70,24 @@ public final class ContextHubManager { } /** + * @deprecated Use {@link Callback} instead. + * @hide + */ + @Deprecated + public interface ICallback { + /** + * Callback function called on message receipt from context hub. + * + * @param hubHandle Handle (system-wide unique identifier) of the hub of the message. + * @param nanoAppHandle Handle (unique identifier) for app instance that sent the message. + * @param message The context hub message. + * + * @see ContextHubMessage + */ + void onMessageReceipt(int hubHandle, int nanoAppHandle, ContextHubMessage message); + } + + /** * Get a handle to all the context hubs in the system * @return array of context hub handles */ @@ -223,6 +247,20 @@ public final class ContextHubManager { } /** + * @deprecated Use {@link #registerCallback(Callback)} instead. + * @hide + */ + @Deprecated + public int registerCallback(ICallback callback) { + if (mLocalCallback != null) { + Log.w(TAG, "Max number of local callbacks reached!"); + return -1; + } + mLocalCallback = callback; + return 0; + } + + /** * Set a callback to receive messages from the context hub * * @param callback Callback object @@ -266,6 +304,19 @@ public final class ContextHubManager { return 0; } + /** + * @deprecated Use {@link #unregisterCallback(Callback)} instead. + * @hide + */ + public synchronized int unregisterCallback(ICallback callback) { + if (callback != mLocalCallback) { + Log.w(TAG, "Cannot recognize local callback!"); + return -1; + } + mLocalCallback = null; + return 0; + } + private IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() { @Override public void onMessageReceipt(final int hubId, final int nanoAppId, @@ -282,6 +333,12 @@ public final class ContextHubManager { } }); } + } else if (mLocalCallback != null) { + // we always ensure that mCallback takes precedence, because mLocalCallback is only + // for internal compatibility + synchronized (this) { + mLocalCallback.onMessageReceipt(hubId, nanoAppId, message); + } } else { Log.d(TAG, "Context hub manager client callback is NULL"); } diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java index 2b9b97463888..8176189dffa0 100644 --- a/core/java/android/hardware/location/ContextHubService.java +++ b/core/java/android/hardware/location/ContextHubService.java @@ -19,6 +19,7 @@ package android.hardware.location; import android.Manifest; import android.content.Context; import android.content.pm.PackageManager; +import android.os.RemoteCallbackList; import android.os.RemoteException; import android.util.Log; @@ -57,19 +58,17 @@ public class ContextHubService extends IContextHubService.Stub { private static final int OS_APP_INSTANCE = -1; private final Context mContext; - - private HashMap mNanoAppHash; - private ContextHubInfo[] mContextHubInfo; - private IContextHubCallback mCallback; + private final HashMap mNanoAppHash = new HashMap<>(); + private final ContextHubInfo[] mContextHubInfo; + private final RemoteCallbackList mCallbacksList = + new RemoteCallbackList<>(); private native int nativeSendMessage(int[] header, byte[] data); private native ContextHubInfo[] nativeInitialize(); - public ContextHubService(Context context) { mContext = context; mContextHubInfo = nativeInitialize(); - mNanoAppHash = new HashMap(); for (int i = 0; i < mContextHubInfo.length; i++) { Log.d(TAG, "ContextHub[" + i + "] id: " + mContextHubInfo[i].getId() @@ -80,9 +79,7 @@ public class ContextHubService extends IContextHubService.Stub { @Override public int registerCallback(IContextHubCallback callback) throws RemoteException { checkPermissions(); - synchronized (this) { - mCallback = callback; - } + mCallbacksList.register(callback); return 0; } @@ -237,26 +234,26 @@ public class ContextHubService extends IContextHubService.Stub { if (header == null || data == null || header.length < MSG_HEADER_SIZE) { return -1; } - - synchronized (this) { - if (mCallback != null) { - ContextHubMessage msg = new ContextHubMessage(header[MSG_FIELD_TYPE], - header[MSG_FIELD_VERSION], - data); - - try { - mCallback.onMessageReceipt(header[MSG_FIELD_HUB_HANDLE], - header[MSG_FIELD_APP_INSTANCE], - msg); - } catch (Exception e) { - Log.w(TAG, "Exception " + e + " when calling remote callback"); - return -1; - } - } else { - Log.d(TAG, "Message Callback is NULL"); + int callbacksCount = mCallbacksList.beginBroadcast(); + if (callbacksCount < 1) { + Log.v(TAG, "No message callbacks registered."); + return 0; + } + ContextHubMessage message = + new ContextHubMessage(header[MSG_FIELD_TYPE], header[MSG_FIELD_VERSION], data); + for (int i = 0; i < callbacksCount; ++i) { + IContextHubCallback callback = mCallbacksList.getBroadcastItem(i); + try { + callback.onMessageReceipt( + header[MSG_FIELD_HUB_HANDLE], + header[MSG_FIELD_APP_INSTANCE], + message); + } catch (RemoteException e) { + Log.i(TAG, "Exception (" + e + ") calling remote callback (" + callback + ")."); + continue; } } - + mCallbacksList.finishBroadcast(); return 0; } diff --git a/core/java/android/hardware/location/NanoAppInstanceInfo.java b/core/java/android/hardware/location/NanoAppInstanceInfo.java index e842ec65a3e7..71a5a8816f58 100644 --- a/core/java/android/hardware/location/NanoAppInstanceInfo.java +++ b/core/java/android/hardware/location/NanoAppInstanceInfo.java @@ -17,10 +17,14 @@ package android.hardware.location; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; +import libcore.util.EmptyArray; + /** * @hide */ @@ -43,6 +47,8 @@ public class NanoAppInstanceInfo { private int mHandle; public NanoAppInstanceInfo() { + mNeededSensors = EmptyArray.INT; + mOutputEvents = EmptyArray.INT; } /** @@ -193,6 +199,7 @@ public class NanoAppInstanceInfo { * * @return int[] all the required sensors needed by this app */ + @NonNull public int[] getNeededSensors() { return mNeededSensors; } @@ -204,8 +211,8 @@ public class NanoAppInstanceInfo { * * @hide */ - public void setNeededSensors(int[] neededSensors) { - mNeededSensors = neededSensors; + public void setNeededSensors(@Nullable int[] neededSensors) { + mNeededSensors = neededSensors != null ? neededSensors : EmptyArray.INT; } /** @@ -213,6 +220,7 @@ public class NanoAppInstanceInfo { * * @return all the events that can be generated by this app */ + @NonNull public int[] getOutputEvents() { return mOutputEvents; } @@ -225,8 +233,8 @@ public class NanoAppInstanceInfo { * * @hide */ - public void setOutputEvents(int[] outputEvents) { - mOutputEvents = outputEvents; + public void setOutputEvents(@Nullable int[] outputEvents) { + mOutputEvents = outputEvents != null ? outputEvents : EmptyArray.INT; } /** @@ -280,12 +288,12 @@ public class NanoAppInstanceInfo { mNeededWriteMemBytes = in.readInt(); mNeededExecMemBytes = in.readInt(); - int mNeededSensorsLength = in.readInt(); - mNeededSensors = new int[mNeededSensorsLength]; + int neededSensorsLength = in.readInt(); + mNeededSensors = new int[neededSensorsLength]; in.readIntArray(mNeededSensors); - int mOutputEventsLength = in.readInt(); - mOutputEvents = new int[mOutputEventsLength]; + int outputEventsLength = in.readInt(); + mOutputEvents = new int[outputEventsLength]; in.readIntArray(mOutputEvents); } @@ -303,9 +311,9 @@ public class NanoAppInstanceInfo { out.writeInt(mNeededWriteMemBytes); out.writeInt(mNeededExecMemBytes); + // arrays are never null out.writeInt(mNeededSensors.length); out.writeIntArray(mNeededSensors); - out.writeInt(mOutputEvents.length); out.writeIntArray(mOutputEvents); } -- 2.11.0