/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.location;

import android.Manifest;
import android.content.Context;
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.ContextHubMessage;
import android.hardware.location.IContextHubCallback;
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;

import com.android.internal.util.DumpUtils;

import java.io.FileDescriptor;
import java.io.PrintWriter;
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;

/**
 * @hide
 */
public class ContextHubService extends IContextHubService.Stub {
    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";

    /*
     * 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 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<>();

    // 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;

        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());
        }
    }

    /**
     * @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());
        return 0;
    }

    @Override
    public int[] getContextHubHandles() throws RemoteException {
        checkPermissions();
        int[] returnArray = new int[mContextHubInfo.length];

        Log.d(TAG, "System supports " + returnArray.length + " hubs");
        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]));
        }

        return returnArray;
    }

    @Override
    public ContextHubInfo getContextHubInfo(int contextHubId) throws RemoteException {
        checkPermissions();
        if (!(contextHubId >= 0 && contextHubId < mContextHubInfo.length)) {
            Log.e(TAG, "Invalid context hub handle " + contextHubId);
            return null; // null means fail
        }

        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 contextHubId, NanoApp app) throws RemoteException {
        checkPermissions();
        if (mContextHubProxy == null) {
            return -1;
        }

        if (!(contextHubId >= 0 && contextHubId < mContextHubInfo.length)) {
            Log.e(TAG, "Invalid contextHubhandle " + contextHubId);
            return -1;
        }
        if (app == null) {
            Log.e(TAG, "Invalid null app");
            return -1;
        }

        // Create an internal IContextHubTransactionCallback for the old API clients
        NanoAppBinary nanoAppBinary = new NanoAppBinary(app.getAppBinary());
        IContextHubTransactionCallback onCompleteCallback =
                createLoadTransactionCallback(contextHubId, nanoAppBinary);

        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
        return 0;
    }

    @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
        }

        int contextHubId = info.getContexthubId();
        long nanoAppId = info.getAppId();
        IContextHubTransactionCallback onCompleteCallback =
                createUnloadTransactionCallback(contextHubId, nanoAppId);
        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
        return 0;
    }

    @Override
    public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle)
            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;
        }
    }

    @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);

            if (filter.testMatch(info)) {
                foundInstances.add(nanoAppInstance);
            }
        }

        int[] retArray = new int[foundInstances.size()];
        for (int i = 0; i < foundInstances.size(); i++) {
            retArray[i] = foundInstances.get(i).intValue();
        }

        Log.w(TAG, "Found " + retArray.length + " apps on hub handle " + hubHandle);
        return retArray;
    }

    /**
     * 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;
        }

        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 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);

                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
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;

        pw.println("Dumping ContextHub Service");

        pw.println("");
        // dump ContextHubInfo
        pw.println("=================== CONTEXT HUBS ====================");
        for (int i = 0; i < mContextHubInfo.length; i++) {
            pw.println("Handle " + i + " : " + mContextHubInfo[i].toString());
        }
        pw.println("");
        pw.println("=================== NANOAPPS ====================");
        // Dump nanoAppHash
        for (Integer nanoAppInstance : mNanoAppHash.keySet()) {
            pw.println(nanoAppInstance + " : " + mNanoAppHash.get(nanoAppInstance).toString());
        }

        // dump eventLog
    }

    private void checkPermissions() {
        mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
    }

    private int onMessageReceipt(int msgType, int hubHandle, int appInstance, byte[] data) {
        if (data == null) {
            return -1;
        }

        int msgVersion = 0;
        int callbacksCount = mCallbacksList.beginBroadcast();
        Log.d(TAG, "Sending message " + msgType + " version " + msgVersion + " from hubHandle " +
                hubHandle + ", appInstance " + appInstance + ", callBackCount " + callbacksCount);

        if (callbacksCount < 1) {
            Log.v(TAG, "No message callbacks registered.");
            return 0;
        }

        ContextHubMessage msg = new ContextHubMessage(msgType, msgVersion, data);
        for (int i = 0; i < callbacksCount; ++i) {
            IContextHubCallback callback = mCallbacksList.getBroadcastItem(i);
            try {
                callback.onMessageReceipt(hubHandle, appInstance, msg);
            } catch (RemoteException e) {
                Log.i(TAG, "Exception (" + e + ") calling remote callback (" + callback + ").");
                continue;
            }
        }
        mCallbacksList.finishBroadcast();
        return 0;
    }

    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;
    }
}
