Implements queryNanoApps API

Bug: 67734082
Test: Run a test app to use the new query API, verify returns the
expected set of nanoapps
Change-Id: I2a808b9f80dd0d9168466f80b79ca1fa35da242c
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index fcf1f14..08c18a6 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -752,15 +752,8 @@
             int contextHubId, IContextHubTransactionCallback transactionCallback,
             NanoAppBinary nanoAppBinary) throws RemoteException {
         checkPermissions();
-        if (mContextHubProxy == null) {
-            transactionCallback.onTransactionComplete(
-                    ContextHubTransaction.TRANSACTION_FAILED_HAL_UNAVAILABLE);
-            return;
-        }
-        if (!isValidContextHubId(contextHubId)) {
-            Log.e(TAG, "Cannot load nanoapp for invalid hub ID " + contextHubId);
-            transactionCallback.onTransactionComplete(
-                    ContextHubTransaction.TRANSACTION_FAILED_BAD_PARAMS);
+        if (!checkHalProxyAndContextHubId(
+                contextHubId, transactionCallback, ContextHubTransaction.TYPE_LOAD_NANOAPP)) {
             return;
         }
         if (nanoAppBinary == null) {
@@ -772,7 +765,6 @@
 
         ContextHubServiceTransaction transaction = mTransactionManager.createLoadTransaction(
                 contextHubId, nanoAppBinary, transactionCallback);
-
         addTransaction(transaction);
     }
 
@@ -790,21 +782,35 @@
             int contextHubId, IContextHubTransactionCallback transactionCallback, long nanoAppId)
             throws RemoteException {
         checkPermissions();
-        if (mContextHubProxy == null) {
-            transactionCallback.onTransactionComplete(
-                    ContextHubTransaction.TRANSACTION_FAILED_HAL_UNAVAILABLE);
-            return;
-        }
-        if (!isValidContextHubId(contextHubId)) {
-            Log.e(TAG, "Cannot unload nanoapp for invalid hub ID " + contextHubId);
-            transactionCallback.onTransactionComplete(
-                    ContextHubTransaction.TRANSACTION_FAILED_BAD_PARAMS);
+        if (!checkHalProxyAndContextHubId(
+                contextHubId, transactionCallback, ContextHubTransaction.TYPE_UNLOAD_NANOAPP)) {
             return;
         }
 
         ContextHubServiceTransaction transaction = mTransactionManager.createUnloadTransaction(
                 contextHubId, nanoAppId, transactionCallback);
+        addTransaction(transaction);
+    }
 
+    /**
+     * Queries for a list of nanoapps from the specified Context hub.
+     *
+     * @param contextHubId the ID of the hub to query
+     * @param transactionCallback the client-facing transaction callback interface
+     *
+     * @throws RemoteException
+     */
+    @Override
+    public void queryNanoApps(int contextHubId, IContextHubTransactionCallback transactionCallback)
+            throws RemoteException {
+        checkPermissions();
+        if (!checkHalProxyAndContextHubId(
+                contextHubId, transactionCallback, ContextHubTransaction.TYPE_QUERY_NANOAPPS)) {
+            return;
+        }
+
+        ContextHubServiceTransaction transaction =
+                mTransactionManager.createQueryTransaction(contextHubId, transactionCallback);
         addTransaction(transaction);
     }
 
@@ -863,6 +869,42 @@
         return 0;
     }
 
+    /**
+     * Validates the HAL proxy state and context hub ID to see if we can start the transaction.
+     *
+     * @param contextHubId    the ID of the hub to start the transaction
+     * @param callback        the client transaction callback interface
+     * @param transactionType the type of the transaction
+     *
+     * @return {@code true} if mContextHubProxy and contextHubId is valid, {@code false} otherwise
+     */
+    private boolean checkHalProxyAndContextHubId(
+            int contextHubId, IContextHubTransactionCallback callback,
+            @ContextHubTransaction.Type int transactionType) {
+        if (mContextHubProxy == null) {
+            try {
+                callback.onTransactionComplete(
+                        ContextHubTransaction.TRANSACTION_FAILED_HAL_UNAVAILABLE);
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException while calling onTransactionComplete", e);
+            }
+            return false;
+        }
+        if (!isValidContextHubId(contextHubId)) {
+            Log.e(TAG, "Cannot start "
+                    + ContextHubTransaction.typeToString(transactionType, false /* upperCase */)
+                    + " transaction for invalid hub ID " + contextHubId);
+            try {
+                callback.onTransactionComplete(ContextHubTransaction.TRANSACTION_FAILED_BAD_PARAMS);
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException while calling onTransactionComplete", e);
+            }
+            return false;
+        }
+
+        return true;
+    }
+
     private int addAppInstance(int hubHandle, int appInstanceHandle, long appId, int appVersion) {
         // App Id encodes vendor & version
         NanoAppInstanceInfo appInfo = new NanoAppInstanceInfo();