Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 88a149f2 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes Iff6557fc,Ie1686e82,I88972653,Iab60b4df,Ie25460e7

* changes:
  Handles failure for transaction queue full
  Reorganize use of error code enums
  Removes setters from NanoAppInstanceInfo
  Renames nanoapp instance IDs to handles in ContextHubService
  Creates a NanoAppStateManager at ContextHubService
parents 326057f7 e60f91a6
Loading
Loading
Loading
Loading
+25 −140
Original line number Diff line number Diff line
@@ -16,9 +16,7 @@

package android.hardware.location;


import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -26,50 +24,51 @@ import android.os.Parcelable;
import libcore.util.EmptyArray;

/**
 * Describes an instance of a nanoapp, used by the internal state manged by ContextHubService.
 *
 * TODO(b/69270990) Remove this class once the old API is deprecated.
 * TODO(b/70624255) Clean up toString() by removing unnecessary fields
 *
 * @hide
 */
@SystemApi
public class NanoAppInstanceInfo {
    private String mPublisher;
    private String mName;
    private static final String PRE_LOADED_GENERIC_UNKNOWN = "Preloaded app, unknown";
    private String mPublisher = PRE_LOADED_GENERIC_UNKNOWN;
    private String mName = PRE_LOADED_GENERIC_UNKNOWN;

    private int mHandle;
    private long mAppId;
    private int mAppVersion;
    private int mContexthubId;

    private int mNeededReadMemBytes;
    private int mNeededWriteMemBytes;
    private int mNeededExecMemBytes;
    private int mNeededReadMemBytes = 0;
    private int mNeededWriteMemBytes = 0;
    private int mNeededExecMemBytes = 0;

    private int[] mNeededSensors;
    private int[] mOutputEvents;

    private int mContexthubId;
    private int mHandle;
    private int[] mNeededSensors = EmptyArray.INT;
    private int[] mOutputEvents = EmptyArray.INT;

    public NanoAppInstanceInfo() {
        mNeededSensors = EmptyArray.INT;
        mOutputEvents = EmptyArray.INT;
    }

    /**
     * get the publisher of this app
     *
     * @return String - name of the publisher
     * @hide
     */
    public String getPublisher() {
        return mPublisher;
    public NanoAppInstanceInfo(int handle, long appId, int appVersion, int contextHubId) {
        mHandle = handle;
        mAppId = appId;
        mAppVersion = appVersion;
        mContexthubId = contextHubId;
    }


    /**
     * set the publisher name for the app
     *
     * @param publisher - name of the publisher
     * get the publisher of this app
     *
     * @hide
     * @return String - name of the publisher
     */
    public void setPublisher(String publisher) {
        mPublisher = publisher;
    public String getPublisher() {
        return mPublisher;
    }

    /**
@@ -81,17 +80,6 @@ public class NanoAppInstanceInfo {
        return mName;
    }

    /**
     * set the name of the app
     *
     * @param name - name of the app
     *
     * @hide
     */
    public void setName(String name) {
        mName = name;
    }

    /**
     * Get the application identifier
     *
@@ -101,17 +89,6 @@ public class NanoAppInstanceInfo {
        return mAppId;
    }

    /**
     * Set the application identifier
     *
     * @param appId - application identifier
     *
     * @hide
     */
    public void setAppId(long appId) {
        mAppId = appId;
    }

    /**
     * Get the application version
     *
@@ -126,17 +103,6 @@ public class NanoAppInstanceInfo {
        return mAppVersion;
    }

    /**
     * Set the application version
     *
     * @param appVersion - version of the app
     *
     * @hide
     */
    public void setAppVersion(int appVersion) {
        mAppVersion = appVersion;
    }

    /**
     * Get the read memory needed by the app
     *
@@ -146,17 +112,6 @@ public class NanoAppInstanceInfo {
        return mNeededReadMemBytes;
    }

    /**
     * Set the read memory needed by the app
     *
     * @param neededReadMemBytes - readable Memory needed in bytes
     *
     * @hide
     */
    public void setNeededReadMemBytes(int neededReadMemBytes) {
        mNeededReadMemBytes = neededReadMemBytes;
    }

    /**
     *  get writable memory needed by the app
     *
@@ -166,18 +121,6 @@ public class NanoAppInstanceInfo {
        return mNeededWriteMemBytes;
    }

    /**
     * set writable memory needed by the app
     *
     * @param neededWriteMemBytes - writable memory needed by the
     *                            app
     *
     * @hide
     */
    public void setNeededWriteMemBytes(int neededWriteMemBytes) {
        mNeededWriteMemBytes = neededWriteMemBytes;
    }

    /**
     * get executable memory needed by the app
     *
@@ -187,18 +130,6 @@ public class NanoAppInstanceInfo {
        return mNeededExecMemBytes;
    }

    /**
     * set executable memory needed by the app
     *
     * @param neededExecMemBytes - executable memory needed by the
     *                           app
     *
     * @hide
     */
    public void setNeededExecMemBytes(int neededExecMemBytes) {
        mNeededExecMemBytes = neededExecMemBytes;
    }

    /**
     * Get the sensors needed by this app
     *
@@ -209,17 +140,6 @@ public class NanoAppInstanceInfo {
        return mNeededSensors;
    }

    /**
     * set the sensors needed by this app
     *
     * @param neededSensors - all the sensors needed by this app
     *
     * @hide
     */
    public void setNeededSensors(@Nullable int[] neededSensors) {
        mNeededSensors = neededSensors != null ? neededSensors : EmptyArray.INT;
    }

    /**
     * get the events generated by this app
     *
@@ -230,18 +150,6 @@ public class NanoAppInstanceInfo {
        return mOutputEvents;
    }

    /**
     * set the output events that can be generated by this app
     *
     * @param outputEvents - the events that may be generated by
     *                     this app
     *
     * @hide
     */
    public void setOutputEvents(@Nullable int[] outputEvents) {
        mOutputEvents = outputEvents != null ? outputEvents : EmptyArray.INT;
    }

    /**
     * get the context hub identifier
     *
@@ -251,17 +159,6 @@ public class NanoAppInstanceInfo {
        return mContexthubId;
    }

    /**
     * set the context hub identifier
     *
     * @param contexthubId - system wide unique identifier
     *
     * @hide
     */
    public void setContexthubId(int contexthubId) {
        mContexthubId = contexthubId;
    }

    /**
     * get a handle to the nano app instance
     *
@@ -271,18 +168,6 @@ public class NanoAppInstanceInfo {
        return mHandle;
    }

    /**
     * set the handle for an app instance
     *
     * @param handle - handle to this instance
     *
     * @hide
     */
    public void setHandle(int handle) {
        mHandle = handle;
    }


    private NanoAppInstanceInfo(Parcel in) {
        mPublisher = in.readString();
        mName = in.readString();
+42 −178
Original line number Diff line number Diff line
@@ -55,7 +55,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @hide
@@ -76,25 +75,10 @@ public class ContextHubService extends IContextHubService.Stub {
    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 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<>();
@@ -111,6 +95,9 @@ public class ContextHubService extends IContextHubService.Stub {
    // The default client for old API clients
    private final Map<Integer, IContextHubClient> mDefaultClientMap;

    // The manager for the internal nanoapp state cache
    private final NanoAppStateManager mNanoAppStateManager = new NanoAppStateManager();

    /**
     * Class extending the callback to register with a Context Hub.
     */
@@ -160,7 +147,8 @@ public class ContextHubService extends IContextHubService.Stub {
        }

        mClientManager = new ContextHubClientManager(mContext, mContextHubProxy);
        mTransactionManager = new ContextHubTransactionManager(mContextHubProxy, mClientManager);
        mTransactionManager = new ContextHubTransactionManager(
                mContextHubProxy, mClientManager, mNanoAppStateManager);

        List<ContextHub> hubList;
        try {
@@ -214,12 +202,11 @@ public class ContextHubService extends IContextHubService.Stub {
        return new IContextHubClientCallback.Stub() {
            @Override
            public void onMessageFromNanoApp(NanoAppMessage message) {
                int nanoAppInstanceId =
                        mNanoAppIdToInstanceMap.containsKey(message.getNanoAppId()) ?
                        mNanoAppIdToInstanceMap.get(message.getNanoAppId()) : -1;
                int nanoAppHandle = mNanoAppStateManager.getNanoAppHandle(
                        contextHubId, message.getNanoAppId());

                onMessageReceiptOldApi(
                        message.getMessageType(), contextHubId, nanoAppInstanceId,
                        message.getMessageType(), contextHubId, nanoAppHandle,
                        message.getMessageBody());
            }

@@ -328,15 +315,13 @@ public class ContextHubService extends IContextHubService.Stub {
     * 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) {
    private IContextHubTransactionCallback createUnloadTransactionCallback(int contextHubId) {
        return new IContextHubTransactionCallback.Stub() {
            @Override
            public void onTransactionComplete(int result) {
                handleUnloadResponseOldApi(contextHubId, result, nanoAppId);
                handleUnloadResponseOldApi(contextHubId, result);
            }

            @Override
@@ -365,24 +350,6 @@ public class ContextHubService extends IContextHubService.Stub {
        };
    }

    /**
     * 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 contextHubId, NanoApp app) throws RemoteException {
        checkPermissions();
@@ -407,70 +374,50 @@ public class ContextHubService extends IContextHubService.Stub {
        ContextHubServiceTransaction transaction = mTransactionManager.createLoadTransaction(
                contextHubId, nanoAppBinary, onCompleteCallback);

        int result = addTransaction(transaction);
        if (result != Result.OK) {
            Log.e(TAG, "Failed to load nanoapp with error code " + result);
            return -1;
        }

        // Do not add an entry to mNanoAppInstance Hash yet. The HAL may reject the app
        mTransactionManager.addTransaction(transaction);
        return 0;
    }

    @Override
    public int unloadNanoApp(int nanoAppInstanceHandle) throws RemoteException {
    public int unloadNanoApp(int nanoAppHandle) throws RemoteException {
        checkPermissions();
        if (mContextHubProxy == null) {
            return -1;
        }

        NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstanceHandle);
        NanoAppInstanceInfo info =
                mNanoAppStateManager.getNanoAppInstanceInfo(nanoAppHandle);
        if (info == null) {
            Log.e(TAG, "Cannot find app with handle " + nanoAppInstanceHandle);
            return -1; //means failed
            Log.e(TAG, "Cannot find nanoapp with handle " + nanoAppHandle);
            return -1;
        }

        int contextHubId = info.getContexthubId();
        long nanoAppId = info.getAppId();
        IContextHubTransactionCallback onCompleteCallback =
                createUnloadTransactionCallback(contextHubId, nanoAppId);
                createUnloadTransactionCallback(contextHubId);
        ContextHubServiceTransaction transaction = mTransactionManager.createUnloadTransaction(
                contextHubId, nanoAppId, onCompleteCallback);

        int result = addTransaction(transaction);
        if (result != Result.OK) {
            Log.e(TAG, "Failed to unload nanoapp with error code " + result);
            return -1;
        }

        // Do not add an entry to mNanoAppInstance Hash yet. The HAL may reject the app
        mTransactionManager.addTransaction(transaction);
        return 0;
    }

    @Override
    public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle)
            throws RemoteException {
    public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) throws RemoteException {
        checkPermissions();
        // This assumes that all the nanoAppInfo is current. This is reasonable
        // for the use cases for tightly controlled nanoApps.
        if (mNanoAppHash.containsKey(nanoAppInstanceHandle)) {
            return mNanoAppHash.get(nanoAppInstanceHandle);
        } else {
            Log.e(TAG, "Could not find nanoApp with handle " + nanoAppInstanceHandle);
            return null;
        }

        return mNanoAppStateManager.getNanoAppInstanceInfo(nanoAppHandle);
    }

    @Override
    public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) throws RemoteException {
        checkPermissions();
        ArrayList<Integer> foundInstances = new ArrayList<Integer>();

        for (Integer nanoAppInstance : mNanoAppHash.keySet()) {
            NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstance);

        ArrayList<Integer> foundInstances = new ArrayList<>();
        for (NanoAppInstanceInfo info : mNanoAppStateManager.getNanoAppInstanceInfoCollection()) {
            if (filter.testMatch(info)) {
                foundInstances.add(nanoAppInstance);
                foundInstances.add(info.getHandle());
            }
        }

@@ -495,6 +442,8 @@ public class ContextHubService extends IContextHubService.Stub {
     *
     * @param contextHubId the ID of the hub to do the query
     * @return the result of the query
     *
     * @throws IllegalStateException if the transaction queue is full
     */
    private int queryNanoAppsInternal(int contextHubId) {
        if (mContextHubProxy == null) {
@@ -506,7 +455,8 @@ public class ContextHubService extends IContextHubService.Stub {
        ContextHubServiceTransaction transaction = mTransactionManager.createQueryTransaction(
                contextHubId, onCompleteCallback);

        return addTransaction(transaction);
        mTransactionManager.addTransaction(transaction);
        return Result.OK;
    }

    @Override
@@ -546,7 +496,7 @@ public class ContextHubService extends IContextHubService.Stub {
                success = (client.sendMessageToNanoApp(message) ==
                        ContextHubTransaction.TRANSACTION_SUCCESS);
            } else {
                Log.e(TAG, "Failed to send nanoapp message - nanoapp with instance ID "
                Log.e(TAG, "Failed to send nanoapp message - nanoapp with handle "
                        + nanoAppHandle + " does not exist.");
            }
        }
@@ -576,26 +526,11 @@ public class ContextHubService extends IContextHubService.Stub {
            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);
        int nanoAppHandle = mNanoAppStateManager.getNanoAppHandle(
                contextHubId, nanoAppBinary.getNanoAppId());
        ByteBuffer.wrap(data, 1, 4).order(ByteOrder.nativeOrder()).putInt(nanoAppHandle);

        onMessageReceiptOldApi(MSG_LOAD_NANO_APP, contextHubId, OS_APP_INSTANCE, data);
    }
@@ -605,14 +540,7 @@ public class ContextHubService extends IContextHubService.Stub {
     *
     * 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);
        }

    private void handleUnloadResponseOldApi(int contextHubId, int result) {
        byte[] data = new byte[1];
        data[0] = (byte) result;
        onMessageReceiptOldApi(MSG_UNLOAD_NANO_APP, contextHubId, OS_APP_INSTANCE, data);
@@ -668,41 +596,10 @@ public class ContextHubService extends IContextHubService.Stub {
        List<NanoAppState> nanoAppStateList =
                ContextHubServiceUtil.createNanoAppStateList(nanoAppInfoList);

        updateServiceCache(contextHubId, nanoAppInfoList);
        mNanoAppStateManager.updateCache(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);
            }
        }
    }

    /**
     * @param contextHubId the hub ID to validate
     * @return {@code true} if the ID represents that of an available hub, {@code false} otherwise
@@ -750,6 +647,7 @@ public class ContextHubService extends IContextHubService.Stub {
     * @param nanoAppBinary the binary to load
     *
     * @throws RemoteException
     * @throws IllegalStateException if the transaction queue is full
     */
    @Override
    public void loadNanoAppOnHub(
@@ -769,7 +667,7 @@ public class ContextHubService extends IContextHubService.Stub {

        ContextHubServiceTransaction transaction = mTransactionManager.createLoadTransaction(
                contextHubId, nanoAppBinary, transactionCallback);
        addTransaction(transaction);
        mTransactionManager.addTransaction(transaction);
    }

    /**
@@ -780,6 +678,7 @@ public class ContextHubService extends IContextHubService.Stub {
     * @param nanoAppId the ID of the nanoapp to unload
     *
     * @throws RemoteException
     * @throws IllegalStateException if the transaction queue is full
     */
    @Override
    public void unloadNanoAppFromHub(
@@ -793,7 +692,7 @@ public class ContextHubService extends IContextHubService.Stub {

        ContextHubServiceTransaction transaction = mTransactionManager.createUnloadTransaction(
                contextHubId, nanoAppId, transactionCallback);
        addTransaction(transaction);
        mTransactionManager.addTransaction(transaction);
    }

    /**
@@ -803,6 +702,7 @@ public class ContextHubService extends IContextHubService.Stub {
     * @param transactionCallback the client-facing transaction callback interface
     *
     * @throws RemoteException
     * @throws IllegalStateException if the transaction queue is full
     */
    @Override
    public void queryNanoApps(int contextHubId, IContextHubTransactionCallback transactionCallback)
@@ -815,7 +715,7 @@ public class ContextHubService extends IContextHubService.Stub {

        ContextHubServiceTransaction transaction =
                mTransactionManager.createQueryTransaction(contextHubId, transactionCallback);
        addTransaction(transaction);
        mTransactionManager.addTransaction(transaction);
    }

    @Override
@@ -833,8 +733,8 @@ public class ContextHubService extends IContextHubService.Stub {
        pw.println("");
        pw.println("=================== NANOAPPS ====================");
        // Dump nanoAppHash
        for (Integer nanoAppInstance : mNanoAppHash.keySet()) {
            pw.println(nanoAppInstance + " : " + mNanoAppHash.get(nanoAppInstance).toString());
        for (NanoAppInstanceInfo info : mNanoAppStateManager.getNanoAppInstanceInfoCollection()) {
            pw.println(info);
        }

        // dump eventLog
@@ -908,40 +808,4 @@ public class ContextHubService extends IContextHubService.Stub {

        return true;
    }

    private int addAppInstance(int hubHandle, int appInstanceHandle, long appId, int appVersion) {
        // App Id encodes vendor & version
        NanoAppInstanceInfo appInfo = new NanoAppInstanceInfo();

        appInfo.setAppId(appId);
        appInfo.setAppVersion(appVersion);
        appInfo.setName(PRE_LOADED_APP_NAME);
        appInfo.setContexthubId(hubHandle);
        appInfo.setHandle(appInstanceHandle);
        appInfo.setPublisher(PRE_LOADED_APP_PUBLISHER);
        appInfo.setNeededExecMemBytes(PRE_LOADED_APP_MEM_REQ);
        appInfo.setNeededReadMemBytes(PRE_LOADED_APP_MEM_REQ);
        appInfo.setNeededWriteMemBytes(PRE_LOADED_APP_MEM_REQ);

        String action;
        if (mNanoAppHash.containsKey(appInstanceHandle)) {
            action = "Updated";
        } else {
            action = "Added";
        }

        mNanoAppHash.put(appInstanceHandle, appInfo);
        Log.d(TAG, action + " app instance " + appInstanceHandle + " with id 0x"
                + Long.toHexString(appId) + " version 0x" + Integer.toHexString(appVersion));

        return 0;
    }

    private int deleteAppInstance(int appInstanceHandle) {
        if (mNanoAppHash.remove(appInstanceHandle) == null) {
            return -1;
        }

        return 0;
    }
}
+3 −2
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ import java.util.concurrent.TimeUnit;
     *
     * @param result the result of the transaction
     */
    /* package */ void onTransactionComplete(int result) {
    /* package */ void onTransactionComplete(@ContextHubTransaction.Result int result) {
    }

    /**
@@ -72,7 +72,8 @@ import java.util.concurrent.TimeUnit;
     * @param result           the result of the query
     * @param nanoAppStateList the list of nanoapps given by the query response
     */
    /* package */ void onQueryResponse(int result, List<NanoAppState> nanoAppStateList) {
    /* package */ void onQueryResponse(
            @ContextHubTransaction.Result int result, List<NanoAppState> nanoAppStateList) {
    }

    /**
+36 −13

File changed.

Preview size limit exceeded, changes collapsed.

+190 −0

File added.

Preview size limit exceeded, changes collapsed.