Replace JNI code with Java HIDL at ContextHubService
This CL does the following:
- Use Java HIDL to communicate with the Context Hub
- Reimplement required JNI functionality in Java
Bug: 67734082
Test: Flash device and run CHQTS, verify pass on walleye-userdebug
Change-Id: I8b7563d04e9e3a22295b81af283fd3168e179957
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index 5e9f355..da481a8 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -18,15 +18,25 @@
import android.Manifest;
import android.content.Context;
-import android.content.pm.PackageManager;
+import android.hardware.contexthub.V1_0.AsyncEventType;
+import android.hardware.contexthub.V1_0.ContextHub;
+import android.hardware.contexthub.V1_0.ContextHubMsg;
+import android.hardware.contexthub.V1_0.HostEndPoint;
+import android.hardware.contexthub.V1_0.HubAppInfo;
+import android.hardware.contexthub.V1_0.IContexthub;
+import android.hardware.contexthub.V1_0.IContexthubCallback;
+import android.hardware.contexthub.V1_0.Result;
+import android.hardware.contexthub.V1_0.TransactionResult;
import android.hardware.location.ContextHubInfo;
-import android.hardware.location.ContextHubManager;
import android.hardware.location.ContextHubMessage;
-import android.hardware.location.IContextHubService;
import android.hardware.location.IContextHubCallback;
-import android.hardware.location.NanoAppFilter;
+import android.hardware.location.IContextHubService;
+import android.hardware.location.IContextHubTransactionCallback;
import android.hardware.location.NanoApp;
+import android.hardware.location.NanoAppBinary;
+import android.hardware.location.NanoAppFilter;
import android.hardware.location.NanoAppInstanceInfo;
+import android.hardware.location.NanoAppState;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;
@@ -38,8 +48,10 @@
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.HashMap;
/**
* @hide
@@ -48,55 +60,152 @@
private static final String TAG = "ContextHubService";
private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
- + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
+ + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
- public static final int ANY_HUB = -1;
- public static final int MSG_LOAD_NANO_APP = 3;
+ /*
+ * Constants for the type of transaction that is defined by ContextHubService.
+ * This is used to report the transaction callback to clients, and is different from
+ * ContextHubTransaction.Type.
+ */
+ public static final int MSG_ENABLE_NANO_APP = 1;
+ public static final int MSG_DISABLE_NANO_APP = 2;
+ public static final int MSG_LOAD_NANO_APP = 3;
public static final int MSG_UNLOAD_NANO_APP = 4;
+ public static final int MSG_QUERY_NANO_APPS = 5;
+ public static final int MSG_QUERY_MEMORY = 6;
+ public static final int MSG_HUB_RESET = 7;
private static final String PRE_LOADED_GENERIC_UNKNOWN = "Preloaded app, unknown";
private static final String PRE_LOADED_APP_NAME = PRE_LOADED_GENERIC_UNKNOWN;
private static final String PRE_LOADED_APP_PUBLISHER = PRE_LOADED_GENERIC_UNKNOWN;
private static final int PRE_LOADED_APP_MEM_REQ = 0;
- private static final int MSG_HEADER_SIZE = 4;
- private static final int HEADER_FIELD_MSG_TYPE = 0;
- private static final int HEADER_FIELD_MSG_VERSION = 1;
- private static final int HEADER_FIELD_HUB_HANDLE = 2;
- private static final int HEADER_FIELD_APP_INSTANCE = 3;
-
- private static final int HEADER_FIELD_LOAD_APP_ID_LO = MSG_HEADER_SIZE;
- private static final int HEADER_FIELD_LOAD_APP_ID_HI = MSG_HEADER_SIZE + 1;
- private static final int MSG_LOAD_APP_HEADER_SIZE = MSG_HEADER_SIZE + 2;
-
private static final int OS_APP_INSTANCE = -1;
private final Context mContext;
+
+ // TODO(b/69270990): Remove once old ContextHubManager API is deprecated
+ // Service cache maintaining of instance ID to nanoapp infos
private final ConcurrentHashMap<Integer, NanoAppInstanceInfo> mNanoAppHash =
new ConcurrentHashMap<>();
+ // The next available instance ID (managed by the service) to assign to a nanoapp
+ private int mNextAvailableInstanceId = 0;
+ // A map of the long nanoapp ID to instance ID managed by the service
+ private final ConcurrentHashMap<Long, Integer> mNanoAppIdToInstanceMap =
+ new ConcurrentHashMap<>();
+
private final ContextHubInfo[] mContextHubInfo;
private final RemoteCallbackList<IContextHubCallback> mCallbacksList =
new RemoteCallbackList<>();
- private native int nativeSendMessage(int[] header, byte[] data);
- private native ContextHubInfo[] nativeInitialize();
+ // Proxy object to communicate with the Context Hub HAL
+ private final IContexthub mContextHubProxy;
+
+ // The manager for transaction queue
+ private final ContextHubTransactionManager mTransactionManager;
+
+ /**
+ * Class extending the callback to register with a Context Hub.
+ */
+ private class ContextHubServiceCallback extends IContexthubCallback.Stub {
+ private final int mContextHubId;
+
+ ContextHubServiceCallback(int contextHubId) {
+ mContextHubId = contextHubId;
+ }
+
+ @Override
+ public void handleClientMsg(ContextHubMsg message) {
+ handleClientMessageCallback(mContextHubId, message);
+ }
+
+ @Override
+ public void handleTxnResult(int transactionId, int result) {
+ handleTransactionResultCallback(mContextHubId, transactionId, result);
+ }
+
+ @Override
+ public void handleHubEvent(int eventType) {
+ handleHubEventCallback(mContextHubId, eventType);
+ }
+
+ @Override
+ public void handleAppAbort(long nanoAppId, int abortCode) {
+ handleAppAbortCallback(mContextHubId, nanoAppId, abortCode);
+ }
+
+ @Override
+ public void handleAppsInfo(ArrayList<HubAppInfo> nanoAppInfoList) {
+ handleQueryAppsCallback(mContextHubId, nanoAppInfoList);
+ }
+ }
public ContextHubService(Context context) {
mContext = context;
- mContextHubInfo = nativeInitialize();
+
+ mContextHubProxy = getContextHubProxy();
+ if (mContextHubProxy == null) {
+ mTransactionManager = null;
+ mContextHubInfo = new ContextHubInfo[0];
+ return;
+ }
+
+ mTransactionManager = new ContextHubTransactionManager(mContextHubProxy);
+
+ List<ContextHub> hubList;
+ try {
+ hubList = mContextHubProxy.getHubs();
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException while getting Context Hub info");
+ hubList = Collections.emptyList();
+ }
+ mContextHubInfo = ContextHubServiceUtil.createContextHubInfoArray(hubList);
+
+ for (ContextHubInfo contextHubInfo : mContextHubInfo) {
+ int contextHubId = contextHubInfo.getId();
+ try {
+ mContextHubProxy.registerCallback(
+ contextHubId, new ContextHubServiceCallback(contextHubId));
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException while registering service callback for hub (ID = "
+ + contextHubId + ")");
+ }
+ }
+
+ // Do a query to initialize the service cache list of nanoapps
+ // TODO(b/69270990): Remove this when old API is deprecated
+ for (ContextHubInfo contextHubInfo : mContextHubInfo) {
+ queryNanoAppsInternal(contextHubInfo.getId());
+ }
for (int i = 0; i < mContextHubInfo.length; i++) {
Log.d(TAG, "ContextHub[" + i + "] id: " + mContextHubInfo[i].getId()
- + ", name: " + mContextHubInfo[i].getName());
+ + ", name: " + mContextHubInfo[i].getName());
}
}
+ /**
+ * @return the IContexthub proxy interface
+ */
+ private IContexthub getContextHubProxy() {
+ IContexthub proxy = null;
+ try {
+ proxy = IContexthub.getService(true /* retry */);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException while attaching to Context Hub HAL proxy");
+ } catch (NoSuchElementException e) {
+ Log.i(TAG, "Context Hub HAL service not found");
+ }
+
+ return proxy;
+ }
+
@Override
public int registerCallback(IContextHubCallback callback) throws RemoteException {
checkPermissions();
mCallbacksList.register(callback);
Log.d(TAG, "Added callback, total callbacks " +
- mCallbacksList.getRegisteredCallbackCount());
+ mCallbacksList.getRegisteredCallbackCount());
return 0;
}
@@ -109,29 +218,112 @@
for (int i = 0; i < returnArray.length; ++i) {
returnArray[i] = i;
Log.d(TAG, String.format("Hub %s is mapped to %d",
- mContextHubInfo[i].getName(), returnArray[i]));
+ mContextHubInfo[i].getName(), returnArray[i]));
}
return returnArray;
}
@Override
- public ContextHubInfo getContextHubInfo(int contextHubHandle) throws RemoteException {
+ public ContextHubInfo getContextHubInfo(int contextHubId) throws RemoteException {
checkPermissions();
- if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
- Log.e(TAG, "Invalid context hub handle " + contextHubHandle);
+ if (!(contextHubId >= 0 && contextHubId < mContextHubInfo.length)) {
+ Log.e(TAG, "Invalid context hub handle " + contextHubId);
return null; // null means fail
}
- return mContextHubInfo[contextHubHandle];
+ return mContextHubInfo[contextHubId];
+ }
+
+ /**
+ * Creates an internal load transaction callback to be used for old API clients
+ *
+ * @param contextHubId the ID of the hub to load the binary
+ * @param nanoAppBinary the binary to load
+ * @return the callback interface
+ */
+ private IContextHubTransactionCallback createLoadTransactionCallback(
+ int contextHubId, NanoAppBinary nanoAppBinary) {
+ return new IContextHubTransactionCallback.Stub() {
+ @Override
+ public void onTransactionComplete(int result) {
+ handleLoadResponseOldApi(contextHubId, result, nanoAppBinary);
+ }
+
+ @Override
+ public void onQueryResponse(int result, List<NanoAppState> nanoAppStateList) {
+ }
+ };
+ }
+
+ /**
+ * Creates an internal unload transaction callback to be used for old API clients
+ *
+ * @param contextHubId the ID of the hub to unload the nanoapp
+ * @param nanoAppId the ID of the nanoapp to unload
+ * @return the callback interface
+ */
+ private IContextHubTransactionCallback createUnloadTransactionCallback(
+ int contextHubId, long nanoAppId) {
+ return new IContextHubTransactionCallback.Stub() {
+ @Override
+ public void onTransactionComplete(int result) {
+ handleUnloadResponseOldApi(contextHubId, result, nanoAppId);
+ }
+
+ @Override
+ public void onQueryResponse(int result, List<NanoAppState> nanoAppStateList) {
+ }
+ };
+ }
+
+ /**
+ * Creates an internal query transaction callback to be used for old API clients
+ *
+ * @param contextHubId the ID of the hub to query
+ * @return the callback interface
+ */
+ private IContextHubTransactionCallback createQueryTransactionCallback(int contextHubId) {
+ return new IContextHubTransactionCallback.Stub() {
+ @Override
+ public void onTransactionComplete(int result) {
+ }
+
+ @Override
+ public void onQueryResponse(int result, List<NanoAppState> nanoAppStateList) {
+ byte[] data = {(byte) result};
+ onMessageReceipt(MSG_QUERY_NANO_APPS, contextHubId, OS_APP_INSTANCE, data);
+ }
+ };
+ }
+
+ /**
+ * Adds a new transaction to the transaction manager queue
+ *
+ * @param transaction the transaction to add
+ * @return the result of adding the transaction
+ */
+ private int addTransaction(ContextHubServiceTransaction transaction) {
+ int result = Result.OK;
+ try {
+ mTransactionManager.addTransaction(transaction);
+ } catch (IllegalStateException e) {
+ Log.e(TAG, e.getMessage());
+ result = Result.TRANSACTION_PENDING; /* failed */
+ }
+
+ return result;
}
@Override
- public int loadNanoApp(int contextHubHandle, NanoApp app) throws RemoteException {
+ public int loadNanoApp(int contextHubId, NanoApp app) throws RemoteException {
checkPermissions();
+ if (mContextHubProxy == null) {
+ return -1;
+ }
- if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
- Log.e(TAG, "Invalid contextHubhandle " + contextHubHandle);
+ if (!(contextHubId >= 0 && contextHubId < mContextHubInfo.length)) {
+ Log.e(TAG, "Invalid contextHubhandle " + contextHubId);
return -1;
}
if (app == null) {
@@ -139,20 +331,17 @@
return -1;
}
- int[] msgHeader = new int[MSG_LOAD_APP_HEADER_SIZE];
- msgHeader[HEADER_FIELD_HUB_HANDLE] = contextHubHandle;
- msgHeader[HEADER_FIELD_APP_INSTANCE] = OS_APP_INSTANCE;
- msgHeader[HEADER_FIELD_MSG_VERSION] = 0;
- msgHeader[HEADER_FIELD_MSG_TYPE] = MSG_LOAD_NANO_APP;
+ // Create an internal IContextHubTransactionCallback for the old API clients
+ NanoAppBinary nanoAppBinary = new NanoAppBinary(app.getAppBinary());
+ IContextHubTransactionCallback onCompleteCallback =
+ createLoadTransactionCallback(contextHubId, nanoAppBinary);
- long appId = app.getAppId();
+ ContextHubServiceTransaction transaction = mTransactionManager.createLoadTransaction(
+ contextHubId, nanoAppBinary, onCompleteCallback);
- msgHeader[HEADER_FIELD_LOAD_APP_ID_LO] = (int)(appId & 0xFFFFFFFF);
- msgHeader[HEADER_FIELD_LOAD_APP_ID_HI] = (int)((appId >> 32) & 0xFFFFFFFF);
-
- int errVal = nativeSendMessage(msgHeader, app.getAppBinary());
- if (errVal != 0) {
- Log.e(TAG, "Send Message returns error" + contextHubHandle);
+ int result = addTransaction(transaction);
+ if (result != Result.OK) {
+ Log.e(TAG, "Failed to load nanoapp with error code " + result);
return -1;
}
@@ -163,23 +352,26 @@
@Override
public int unloadNanoApp(int nanoAppInstanceHandle) throws RemoteException {
checkPermissions();
+ if (mContextHubProxy == null) {
+ return -1;
+ }
+
NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstanceHandle);
if (info == null) {
Log.e(TAG, "Cannot find app with handle " + nanoAppInstanceHandle);
return -1; //means failed
}
- // Call Native interface here
- int[] msgHeader = new int[MSG_HEADER_SIZE];
- msgHeader[HEADER_FIELD_HUB_HANDLE] = ANY_HUB;
- msgHeader[HEADER_FIELD_APP_INSTANCE] = nanoAppInstanceHandle;
- msgHeader[HEADER_FIELD_MSG_VERSION] = 0;
- msgHeader[HEADER_FIELD_MSG_TYPE] = MSG_UNLOAD_NANO_APP;
+ int contextHubId = info.getContexthubId();
+ long nanoAppId = info.getAppId();
+ IContextHubTransactionCallback onCompleteCallback =
+ createUnloadTransactionCallback(contextHubId, nanoAppId);
+ ContextHubServiceTransaction transaction = mTransactionManager.createUnloadTransaction(
+ contextHubId, nanoAppId, onCompleteCallback);
- byte msg[] = new byte[0];
-
- if (nativeSendMessage(msgHeader, msg) != 0) {
- Log.e(TAG, "native send message fails");
+ int result = addTransaction(transaction);
+ if (result != Result.OK) {
+ Log.e(TAG, "Failed to unload nanoapp with error code " + result);
return -1;
}
@@ -189,7 +381,7 @@
@Override
public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle)
- throws RemoteException {
+ throws RemoteException {
checkPermissions();
// This assumes that all the nanoAppInfo is current. This is reasonable
// for the use cases for tightly controlled nanoApps.
@@ -206,7 +398,7 @@
checkPermissions();
ArrayList<Integer> foundInstances = new ArrayList<Integer>();
- for (Integer nanoAppInstance: mNanoAppHash.keySet()) {
+ for (Integer nanoAppInstance : mNanoAppHash.keySet()) {
NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstance);
if (filter.testMatch(info)) {
@@ -223,23 +415,230 @@
return retArray;
}
- @Override
- public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg)
- throws RemoteException {
- checkPermissions();
+ /**
+ * Performs a query at the specified hub.
+ *
+ * This method should only be invoked internally by the service, either to update the service
+ * cache or as a result of an explicit query requested by a client through the sendMessage API.
+ *
+ * @param contextHubId the ID of the hub to do the query
+ * @return the result of the query
+ */
+ private int queryNanoAppsInternal(int contextHubId) {
+ if (mContextHubProxy == null) {
+ return Result.UNKNOWN_FAILURE;
+ }
- if (msg == null || msg.getData() == null) {
- Log.w(TAG, "null ptr");
+ IContextHubTransactionCallback onCompleteCallback =
+ createQueryTransactionCallback(contextHubId);
+ ContextHubServiceTransaction transaction = mTransactionManager.createQueryTransaction(
+ contextHubId, onCompleteCallback);
+
+ return addTransaction(transaction);
+ }
+
+ @Override
+ public int sendMessage(
+ int hubHandle, int nanoAppHandle, ContextHubMessage msg) throws RemoteException {
+ checkPermissions();
+ if (mContextHubProxy == null) {
+ return -1;
+ }
+ if (msg == null) {
+ Log.e(TAG, "ContextHubMessage cannot be null");
+ return -1;
+ }
+ if (msg.getData() == null) {
+ Log.w(TAG, "ContextHubMessage message body cannot be null");
return -1;
}
- int[] msgHeader = new int[MSG_HEADER_SIZE];
- msgHeader[HEADER_FIELD_HUB_HANDLE] = hubHandle;
- msgHeader[HEADER_FIELD_APP_INSTANCE] = nanoAppHandle;
- msgHeader[HEADER_FIELD_MSG_VERSION] = msg.getVersion();
- msgHeader[HEADER_FIELD_MSG_TYPE] = msg.getMsgType();
+ int result;
+ if (nanoAppHandle == OS_APP_INSTANCE) {
+ if (msg.getMsgType() == MSG_QUERY_NANO_APPS) {
+ result = queryNanoAppsInternal(hubHandle);
+ } else {
+ Log.e(TAG, "Invalid OS message params of type " + msg.getMsgType());
+ result = Result.BAD_PARAMS;
+ }
+ } else {
+ NanoAppInstanceInfo info = getNanoAppInstanceInfo(nanoAppHandle);
+ if (info != null) {
+ ContextHubMsg hubMessage = new ContextHubMsg();
+ hubMessage.appName = info.getAppId();
+ hubMessage.msgType = msg.getMsgType();
+ hubMessage.hostEndPoint = HostEndPoint.UNSPECIFIED;
+ ContextHubServiceUtil.copyToByteArrayList(msg.getData(), hubMessage.msg);
- return nativeSendMessage(msgHeader, msg.getData());
+ try {
+ result = mContextHubProxy.sendMessageToHub(hubHandle, hubMessage);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send nanoapp message - RemoteException");
+ result = Result.UNKNOWN_FAILURE;
+ }
+ } else {
+ Log.e(TAG, "Failed to send nanoapp message - nanoapp with instance ID "
+ + nanoAppHandle + " does not exist.");
+ result = Result.BAD_PARAMS;
+ }
+ }
+
+ return (result == Result.OK ? 0 : -1);
+ }
+
+ /**
+ * Handles a unicast or broadcast message from a nanoapp.
+ *
+ * @param contextHubId the ID of the hub the message came from
+ * @param message the message contents
+ */
+ private void handleClientMessageCallback(int contextHubId, ContextHubMsg message) {
+ // TODO(b/67734082): Send to new API clients
+ byte[] data = ContextHubServiceUtil.createPrimitiveByteArray(message.msg);
+
+ int nanoAppInstanceId = mNanoAppIdToInstanceMap.containsKey(message.appName) ?
+ mNanoAppIdToInstanceMap.get(message.appName) : -1;
+ onMessageReceipt(message.msgType, contextHubId, nanoAppInstanceId, data);
+ }
+
+ /**
+ * A helper function to handle a load response from the Context Hub for the old API.
+ *
+ * TODO(b/69270990): Remove this once the old APIs are obsolete.
+ */
+ private void handleLoadResponseOldApi(
+ int contextHubId, int result, NanoAppBinary nanoAppBinary) {
+ if (nanoAppBinary == null) {
+ Log.e(TAG, "Nanoapp binary field was null for a load transaction");
+ return;
+ }
+
+ // NOTE: The legacy JNI code used to do a query right after a load success
+ // to synchronize the service cache. Instead store the binary that was requested to
+ // load to update the cache later without doing a query.
+ int instanceId = 0;
+ long nanoAppId = nanoAppBinary.getNanoAppId();
+ int nanoAppVersion = nanoAppBinary.getNanoAppVersion();
+ if (result == TransactionResult.SUCCESS) {
+ if (mNanoAppIdToInstanceMap.containsKey(nanoAppId)) {
+ instanceId = mNanoAppIdToInstanceMap.get(nanoAppId);
+ } else {
+ instanceId = mNextAvailableInstanceId++;
+ mNanoAppIdToInstanceMap.put(nanoAppId, instanceId);
+ }
+
+ addAppInstance(contextHubId, instanceId, nanoAppId, nanoAppVersion);
+ }
+
+ byte[] data = new byte[5];
+ data[0] = (byte) result;
+ ByteBuffer.wrap(data, 1, 4).order(ByteOrder.nativeOrder()).putInt(instanceId);
+
+ onMessageReceipt(MSG_LOAD_NANO_APP, contextHubId, OS_APP_INSTANCE, data);
+ }
+
+ /**
+ * A helper function to handle an unload response from the Context Hub for the old API.
+ *
+ * TODO(b/69270990): Remove this once the old APIs are obsolete.
+ */
+ private void handleUnloadResponseOldApi(
+ int contextHubId, int result, long nanoAppId) {
+ if (result == TransactionResult.SUCCESS) {
+ int instanceId = mNanoAppIdToInstanceMap.get(nanoAppId);
+ deleteAppInstance(instanceId);
+ mNanoAppIdToInstanceMap.remove(nanoAppId);
+ }
+
+ byte[] data = new byte[1];
+ data[0] = (byte) result;
+ onMessageReceipt(MSG_UNLOAD_NANO_APP, contextHubId, OS_APP_INSTANCE, data);
+ }
+
+ /**
+ * Handles a transaction response from a Context Hub.
+ *
+ * @param contextHubId the ID of the hub the response came from
+ * @param transactionId the ID of the transaction
+ * @param result the result of the transaction reported by the hub
+ */
+ private void handleTransactionResultCallback(int contextHubId, int transactionId, int result) {
+ mTransactionManager.onTransactionResponse(transactionId, result);
+ }
+
+ /**
+ * Handles an asynchronous event from a Context Hub.
+ *
+ * @param contextHubId the ID of the hub the response came from
+ * @param eventType the type of the event as defined in Context Hub HAL AsyncEventType
+ */
+ private void handleHubEventCallback(int contextHubId, int eventType) {
+ if (eventType == AsyncEventType.RESTARTED) {
+ mTransactionManager.onHubReset();
+ queryNanoAppsInternal(contextHubId);
+
+ byte[] data = {TransactionResult.SUCCESS};
+ onMessageReceipt(MSG_HUB_RESET, contextHubId, OS_APP_INSTANCE, data);
+ } else {
+ Log.i(TAG, "Received unknown hub event (hub ID = " + contextHubId + ", type = "
+ + eventType + ")");
+ }
+ }
+
+ /**
+ * Handles an asynchronous abort event of a nanoapp.
+ *
+ * @param contextHubId the ID of the hub that the nanoapp aborted in
+ * @param nanoAppId the ID of the aborted nanoapp
+ * @param abortCode the nanoapp-specific abort code
+ */
+ private void handleAppAbortCallback(int contextHubId, long nanoAppId, int abortCode) {
+ // TODO(b/31049861): Implement this
+ }
+
+ /**
+ * Handles a query response from a Context Hub.
+ *
+ * @param contextHubId the ID of the hub of the response
+ * @param nanoAppInfoList the list of loaded nanoapps
+ */
+ private void handleQueryAppsCallback(int contextHubId, List<HubAppInfo> nanoAppInfoList) {
+ List<NanoAppState> nanoAppStateList =
+ ContextHubServiceUtil.createNanoAppStateList(nanoAppInfoList);
+
+ updateServiceCache(contextHubId, nanoAppInfoList);
+ mTransactionManager.onQueryResponse(nanoAppStateList);
+ }
+
+ /**
+ * Updates the service's cache of the list of loaded nanoapps using a nanoapp list response.
+ *
+ * TODO(b/69270990): Remove this when the old API functionality is removed.
+ *
+ * @param contextHubId the ID of the hub the response came from
+ * @param nanoAppInfoList the list of loaded nanoapps
+ */
+ private void updateServiceCache(int contextHubId, List<HubAppInfo> nanoAppInfoList) {
+ synchronized (mNanoAppHash) {
+ for (int instanceId : mNanoAppHash.keySet()) {
+ if (mNanoAppHash.get(instanceId).getContexthubId() == contextHubId) {
+ deleteAppInstance(instanceId);
+ }
+ }
+
+ for (HubAppInfo appInfo : nanoAppInfoList) {
+ int instanceId;
+ long nanoAppId = appInfo.appId;
+ if (mNanoAppIdToInstanceMap.containsKey(nanoAppId)) {
+ instanceId = mNanoAppIdToInstanceMap.get(nanoAppId);
+ } else {
+ instanceId = mNextAvailableInstanceId++;
+ mNanoAppIdToInstanceMap.put(nanoAppId, instanceId);
+ }
+
+ addAppInstance(contextHubId, instanceId, nanoAppId, appInfo.version);
+ }
+ }
}
@Override
@@ -257,7 +656,7 @@
pw.println("");
pw.println("=================== NANOAPPS ====================");
// Dump nanoAppHash
- for (Integer nanoAppInstance: mNanoAppHash.keySet()) {
+ for (Integer nanoAppInstance : mNanoAppHash.keySet()) {
pw.println(nanoAppInstance + " : " + mNanoAppHash.get(nanoAppInstance).toString());
}
@@ -268,19 +667,15 @@
mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
}
- private int onMessageReceipt(int[] header, byte[] data) {
- if (header == null || data == null || header.length < MSG_HEADER_SIZE) {
- return -1;
+ private int onMessageReceipt(int msgType, int hubHandle, int appInstance, byte[] data) {
+ if (data == null) {
+ return -1;
}
+ int msgVersion = 0;
int callbacksCount = mCallbacksList.beginBroadcast();
- int msgType = header[HEADER_FIELD_MSG_TYPE];
- int msgVersion = header[HEADER_FIELD_MSG_VERSION];
- int hubHandle = header[HEADER_FIELD_HUB_HANDLE];
- int appInstance = header[HEADER_FIELD_APP_INSTANCE];
-
Log.d(TAG, "Sending message " + msgType + " version " + msgVersion + " from hubHandle " +
- hubHandle + ", appInstance " + appInstance + ", callBackCount " + callbacksCount);
+ hubHandle + ", appInstance " + appInstance + ", callBackCount " + callbacksCount);
if (callbacksCount < 1) {
Log.v(TAG, "No message callbacks registered.");
@@ -323,8 +718,8 @@
}
mNanoAppHash.put(appInstanceHandle, appInfo);
- Log.d(TAG, action + " app instance " + appInstanceHandle + " with id "
- + appId + " version " + appVersion);
+ Log.d(TAG, action + " app instance " + appInstanceHandle + " with id 0x"
+ + Long.toHexString(appId) + " version 0x" + Integer.toHexString(appVersion));
return 0;
}