/*
 * 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 android.hardware.location;

import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.app.PendingIntent;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.util.Log;

import com.android.internal.util.Preconditions;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.concurrent.Executor;

/**
 * A class that exposes the Context hubs on a device to applications.
 *
 * Please note that this class is not expected to be used by unbundled applications. Also, calling
 * applications are expected to have LOCATION_HARDWARE permissions to use this class.
 *
 * @hide
 */
@SystemApi
@SystemService(Context.CONTEXTHUB_SERVICE)
public final class ContextHubManager {
    private static final String TAG = "ContextHubManager";

    /**
     * An extra of type {@link ContextHubInfo} describing the source of the event.
     *
     * @hide
     */
    public static final String EXTRA_CONTEXT_HUB_INFO =
            "android.hardware.location.extra.CONTEXT_HUB_INFO";

    /**
     * An extra of type {@link ContextHubManager.Event} describing the event type.
     *
     * @hide
     */
    public static final String EXTRA_EVENT_TYPE = "android.hardware.location.extra.EVENT_TYPE";

    /**
     * An extra of type long describing the ID of the nanoapp an event is for.
     *
     * @hide
     */
    public static final String EXTRA_NANOAPP_ID = "android.hardware.location.extra.NANOAPP_ID";

    /**
     * An extra of type int describing the nanoapp-specific abort code.
     *
     * @hide
     */
    public static final String EXTRA_NANOAPP_ABORT_CODE =
            "android.hardware.location.extra.NANOAPP_ABORT_CODE";

    /**
     * An extra of type {@link NanoAppMessage} describing contents of a message from a nanoapp.
     *
     * @hide
     */
    public static final String EXTRA_MESSAGE = "android.hardware.location.extra.MESSAGE";

    /**
     * Constants describing the type of events from a Context Hub.
     * {@hide}
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "EVENT_" }, value = {
        EVENT_NANOAPP_LOADED,
        EVENT_NANOAPP_UNLOADED,
        EVENT_NANOAPP_ENABLED,
        EVENT_NANOAPP_DISABLED,
        EVENT_NANOAPP_ABORTED,
        EVENT_NANOAPP_MESSAGE,
        EVENT_HUB_RESET,
    })
    public @interface Event { }

    /**
     * An event describing that a nanoapp has been loaded. Contains the EXTRA_NANOAPP_ID extra.
     *
     * @hide
     */
    public static final int EVENT_NANOAPP_LOADED = 0;

    /**
     * An event describing that a nanoapp has been unloaded. Contains the EXTRA_NANOAPP_ID extra.
     *
     * @hide
     */
    public static final int EVENT_NANOAPP_UNLOADED = 1;

    /**
     * An event describing that a nanoapp has been enabled. Contains the EXTRA_NANOAPP_ID extra.
     *
     * @hide
     */
    public static final int EVENT_NANOAPP_ENABLED = 2;

    /**
     * An event describing that a nanoapp has been disabled. Contains the EXTRA_NANOAPP_ID extra.
     *
     * @hide
     */
    public static final int EVENT_NANOAPP_DISABLED = 3;

    /**
     * An event describing that a nanoapp has aborted. Contains the EXTRA_NANOAPP_ID and
     * EXTRA_NANOAPP_ABORT_CODE extras.
     *
     * @hide
     */
    public static final int EVENT_NANOAPP_ABORTED = 4;

    /**
     * An event containing a message sent from a nanoapp. Contains the EXTRA_NANOAPP_ID and
     * EXTRA_NANOAPP_MESSAGE extras.
     *
     * @hide
     */
    public static final int EVENT_NANOAPP_MESSAGE = 5;

    /**
     * An event describing that the Context Hub has reset.
     *
     * @hide
     */
    public static final int EVENT_HUB_RESET = 6;


    private final Looper mMainLooper;
    private final IContextHubService mService;
    private Callback mCallback;
    private Handler mCallbackHandler;

    /**
     * @deprecated Use {@code mCallback} instead.
     */
    @Deprecated
    private ICallback mLocalCallback;

    /**
     * An interface to receive asynchronous communication from the context hub.
     *
     * @deprecated Use the more refined {@link android.hardware.location.ContextHubClientCallback}
     *             instead for notification callbacks.
     */
    @Deprecated
    public abstract static class Callback {
        protected Callback() {}

        /**
         * 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
         */
        public abstract void onMessageReceipt(
                int hubHandle,
                int nanoAppHandle,
                @NonNull ContextHubMessage message);
    }

    /**
     * @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
     *
     * @deprecated Use {@link #getContextHubs()} instead. The use of handles are deprecated in the
     *             new APIs.
     */
    @Deprecated
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    public int[] getContextHubHandles() {
        try {
            return mService.getContextHubHandles();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Get more information about a specific hub.
     *
     * @param hubHandle Handle (system-wide unique identifier) of a context hub.
     * @return ContextHubInfo Information about the requested context hub.
     *
     * @see ContextHubInfo
     *
     * @deprecated Use {@link #getContextHubs()} instead. The use of handles are deprecated in the
     *             new APIs.
     */
    @Deprecated
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    public ContextHubInfo getContextHubInfo(int hubHandle) {
        try {
            return mService.getContextHubInfo(hubHandle);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Load a nano app on a specified context hub.
     *
     * Note that loading is asynchronous.  When we return from this method,
     * the nano app (probably) hasn't loaded yet.  Assuming a return of 0
     * from this method, then the final success/failure for the load, along
     * with the "handle" for the nanoapp, is all delivered in a byte
     * string via a call to Callback.onMessageReceipt.
     *
     * TODO(b/30784270): Provide a better success/failure and "handle" delivery.
     *
     * @param hubHandle handle of context hub to load the app on.
     * @param app the nanoApp to load on the hub
     *
     * @return 0 if the command for loading was sent to the context hub;
     *         -1 otherwise
     *
     * @see NanoApp
     *
     * @deprecated Use {@link #loadNanoApp(ContextHubInfo, NanoAppBinary)} instead.
     */
    @Deprecated
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    public int loadNanoApp(int hubHandle, @NonNull NanoApp app) {
        try {
            return mService.loadNanoApp(hubHandle, app);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Unload a specified nanoApp
     *
     * Note that unloading is asynchronous.  When we return from this method,
     * the nano app (probably) hasn't unloaded yet.  Assuming a return of 0
     * from this method, then the final success/failure for the unload is
     * delivered in a byte string via a call to Callback.onMessageReceipt.
     *
     * TODO(b/30784270): Provide a better success/failure delivery.
     *
     * @param nanoAppHandle handle of the nanoApp to unload
     *
     * @return 0 if the command for unloading was sent to the context hub;
     *         -1 otherwise
     *
     * @deprecated Use {@link #unloadNanoApp(ContextHubInfo, long)} instead.
     */
    @Deprecated
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    public int unloadNanoApp(int nanoAppHandle) {
        try {
            return mService.unloadNanoApp(nanoAppHandle);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * get information about the nano app instance
     *
     * NOTE: The returned NanoAppInstanceInfo does _not_ contain correct
     * information for several fields, specifically:
     * - getName()
     * - getPublisher()
     * - getNeededExecMemBytes()
     * - getNeededReadMemBytes()
     * - getNeededWriteMemBytes()
     *
     * For example, say you call loadNanoApp() with a NanoApp that has
     * getName() returning "My Name".  Later, if you call getNanoAppInstanceInfo
     * for that nanoapp, the returned NanoAppInstanceInfo's getName()
     * method will claim "Preloaded app, unknown", even though you would
     * have expected "My Name".  For now, as the user, you'll need to
     * separately track the above fields if they are of interest to you.
     *
     * TODO(b/30943489): Have the returned NanoAppInstanceInfo contain the
     *     correct information.
     *
     * @param nanoAppHandle handle of the nanoapp instance
     * @return NanoAppInstanceInfo the NanoAppInstanceInfo of the nanoapp, or null if the nanoapp
     *                             does not exist
     *
     * @see NanoAppInstanceInfo
     *
     * @deprecated Use {@link #queryNanoApps(ContextHubInfo)} instead to explicitly query the hub
     *             for loaded nanoapps.
     */
    @Deprecated
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    @Nullable public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
        try {
            return mService.getNanoAppInstanceInfo(nanoAppHandle);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Find a specified nano app on the system
     *
     * @param hubHandle handle of hub to search for nano app
     * @param filter filter specifying the search criteria for app
     *
     * @see NanoAppFilter
     *
     * @return int[] Array of handles to any found nano apps
     *
     * @deprecated Use {@link #queryNanoApps(ContextHubInfo)} instead to explicitly query the hub
     *             for loaded nanoapps.
     */
    @Deprecated
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    @NonNull public int[] findNanoAppOnHub(int hubHandle, @NonNull NanoAppFilter filter) {
        try {
            return mService.findNanoAppOnHub(hubHandle, filter);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Send a message to a specific nano app instance on a context hub.
     *
     * Note that the return value of this method only speaks of success
     * up to the point of sending this to the Context Hub.  It is not
     * an assurance that the Context Hub successfully sent this message
     * on to the nanoapp.  If assurance is desired, a protocol should be
     * established between your code and the nanoapp, with the nanoapp
     * sending a confirmation message (which will be reported via
     * Callback.onMessageReceipt).
     *
     * @param hubHandle handle of the hub to send the message to
     * @param nanoAppHandle  handle of the nano app to send to
     * @param message Message to be sent
     *
     * @see ContextHubMessage
     *
     * @return int 0 on success, -1 otherwise
     *
     * @deprecated Use {@link android.hardware.location.ContextHubClient#sendMessageToNanoApp(
     *             NanoAppMessage)} instead, after creating a
     *             {@link android.hardware.location.ContextHubClient} with
     *             {@link #createClient(ContextHubInfo, ContextHubClientCallback, Executor)}
     *             or {@link #createClient(ContextHubInfo, ContextHubClientCallback)}.
     */
    @Deprecated
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    public int sendMessage(int hubHandle, int nanoAppHandle, @NonNull ContextHubMessage message) {
        try {
            return mService.sendMessage(hubHandle, nanoAppHandle, message);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Returns the list of ContextHubInfo objects describing the available Context Hubs.
     *
     * @return the list of ContextHubInfo objects
     *
     * @see ContextHubInfo
     */
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    @NonNull public List<ContextHubInfo> getContextHubs() {
        try {
            return mService.getContextHubs();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Helper function to generate a stub for a non-query transaction callback.
     *
     * @param transaction the transaction to unblock when complete
     *
     * @return the callback
     *
     * @hide
     */
    private IContextHubTransactionCallback createTransactionCallback(
            ContextHubTransaction<Void> transaction) {
        return new IContextHubTransactionCallback.Stub() {
            @Override
            public void onQueryResponse(int result, List<NanoAppState> nanoappList) {
                Log.e(TAG, "Received a query callback on a non-query request");
                transaction.setResponse(new ContextHubTransaction.Response<Void>(
                        ContextHubTransaction.RESULT_FAILED_SERVICE_INTERNAL_FAILURE, null));
            }

            @Override
            public void onTransactionComplete(int result) {
                transaction.setResponse(new ContextHubTransaction.Response<Void>(result, null));
            }
        };
    }

   /**
    * Helper function to generate a stub for a query transaction callback.
    *
    * @param transaction the transaction to unblock when complete
    *
    * @return the callback
    *
    * @hide
    */
    private IContextHubTransactionCallback createQueryCallback(
            ContextHubTransaction<List<NanoAppState>> transaction) {
        return new IContextHubTransactionCallback.Stub() {
            @Override
            public void onQueryResponse(int result, List<NanoAppState> nanoappList) {
                transaction.setResponse(new ContextHubTransaction.Response<List<NanoAppState>>(
                        result, nanoappList));
            }

            @Override
            public void onTransactionComplete(int result) {
                Log.e(TAG, "Received a non-query callback on a query request");
                transaction.setResponse(new ContextHubTransaction.Response<List<NanoAppState>>(
                        ContextHubTransaction.RESULT_FAILED_SERVICE_INTERNAL_FAILURE, null));
            }
        };
    }

    /**
     * Loads a nanoapp at the specified Context Hub.
     *
     * After the nanoapp binary is successfully loaded at the specified hub, the nanoapp will be in
     * the enabled state.
     *
     * @param hubInfo the hub to load the nanoapp on
     * @param appBinary The app binary to load
     *
     * @return the ContextHubTransaction of the request
     *
     * @throws NullPointerException if hubInfo or NanoAppBinary is null
     *
     * @see NanoAppBinary
     */
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    @NonNull public ContextHubTransaction<Void> loadNanoApp(
            @NonNull ContextHubInfo hubInfo, @NonNull NanoAppBinary appBinary) {
        Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
        Preconditions.checkNotNull(appBinary, "NanoAppBinary cannot be null");

        ContextHubTransaction<Void> transaction =
                new ContextHubTransaction<>(ContextHubTransaction.TYPE_LOAD_NANOAPP);
        IContextHubTransactionCallback callback = createTransactionCallback(transaction);

        try {
            mService.loadNanoAppOnHub(hubInfo.getId(), callback, appBinary);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

        return transaction;
    }

    /**
     * Unloads a nanoapp at the specified Context Hub.
     *
     * @param hubInfo the hub to unload the nanoapp from
     * @param nanoAppId the app to unload
     *
     * @return the ContextHubTransaction of the request
     *
     * @throws NullPointerException if hubInfo is null
     */
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    @NonNull public ContextHubTransaction<Void> unloadNanoApp(
            @NonNull ContextHubInfo hubInfo, long nanoAppId) {
        Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");

        ContextHubTransaction<Void> transaction =
                new ContextHubTransaction<>(ContextHubTransaction.TYPE_UNLOAD_NANOAPP);
        IContextHubTransactionCallback callback = createTransactionCallback(transaction);

        try {
            mService.unloadNanoAppFromHub(hubInfo.getId(), callback, nanoAppId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

        return transaction;
    }

    /**
     * Enables a nanoapp at the specified Context Hub.
     *
     * @param hubInfo the hub to enable the nanoapp on
     * @param nanoAppId the app to enable
     *
     * @return the ContextHubTransaction of the request
     *
     * @throws NullPointerException if hubInfo is null
     */
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    @NonNull public ContextHubTransaction<Void> enableNanoApp(
            @NonNull ContextHubInfo hubInfo, long nanoAppId) {
        Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");

        ContextHubTransaction<Void> transaction =
                new ContextHubTransaction<>(ContextHubTransaction.TYPE_ENABLE_NANOAPP);
        IContextHubTransactionCallback callback = createTransactionCallback(transaction);

        try {
            mService.enableNanoApp(hubInfo.getId(), callback, nanoAppId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

        return transaction;
    }

    /**
     * Disables a nanoapp at the specified Context Hub.
     *
     * @param hubInfo the hub to disable the nanoapp on
     * @param nanoAppId the app to disable
     *
     * @return the ContextHubTransaction of the request
     *
     * @throws NullPointerException if hubInfo is null
     */
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    @NonNull public ContextHubTransaction<Void> disableNanoApp(
            @NonNull ContextHubInfo hubInfo, long nanoAppId) {
        Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");

        ContextHubTransaction<Void> transaction =
                new ContextHubTransaction<>(ContextHubTransaction.TYPE_DISABLE_NANOAPP);
        IContextHubTransactionCallback callback = createTransactionCallback(transaction);

        try {
            mService.disableNanoApp(hubInfo.getId(), callback, nanoAppId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

        return transaction;
    }

    /**
     * Requests a query for nanoapps loaded at the specified Context Hub.
     *
     * @param hubInfo the hub to query a list of nanoapps from
     *
     * @return the ContextHubTransaction of the request
     *
     * @throws NullPointerException if hubInfo is null
     */
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    @NonNull public ContextHubTransaction<List<NanoAppState>> queryNanoApps(
            @NonNull ContextHubInfo hubInfo) {
        Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");

        ContextHubTransaction<List<NanoAppState>> transaction =
                new ContextHubTransaction<>(ContextHubTransaction.TYPE_QUERY_NANOAPPS);
        IContextHubTransactionCallback callback = createQueryCallback(transaction);

        try {
            mService.queryNanoApps(hubInfo.getId(), callback);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

        return transaction;
    }

    /**
     * Set a callback to receive messages from the context hub
     *
     * @param callback Callback object
     *
     * @see Callback
     *
     * @return int 0 on success, -1 otherwise
     *
     * @deprecated Use {@link #createClient(ContextHubInfo, ContextHubClientCallback, Executor)}
     *             or {@link #createClient(ContextHubInfo, ContextHubClientCallback)} instead to
     *             register a {@link android.hardware.location.ContextHubClientCallback}.
     */
    @Deprecated
    @SuppressLint("Doclava125")
    public int registerCallback(@NonNull Callback callback) {
        return registerCallback(callback, null);
    }

    /**
     * @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
     * @param handler Handler object, if null uses the Handler of the main Looper
     *
     * @see Callback
     *
     * @return int 0 on success, -1 otherwise
     *
     * @deprecated Use {@link #createClient(ContextHubInfo, ContextHubClientCallback, Executor)}
     *             or {@link #createClient(ContextHubInfo, ContextHubClientCallback)} instead to
     *             register a {@link android.hardware.location.ContextHubClientCallback}.
     */
    @Deprecated
    @SuppressLint("Doclava125")
    public int registerCallback(Callback callback, Handler handler) {
        synchronized(this) {
            if (mCallback != null) {
                Log.w(TAG, "Max number of callbacks reached!");
                return -1;
            }
            mCallback = callback;
            mCallbackHandler = (handler == null) ? new Handler(mMainLooper) : handler;
        }
        return 0;
    }

    /**
     * Creates an interface to the ContextHubClient to send down to the service.
     *
     * @param client the ContextHubClient object associated with this callback
     * @param callback the callback to invoke at the client process
     * @param executor the executor to invoke callbacks for this client
     *
     * @return the callback interface
     */
    private IContextHubClientCallback createClientCallback(
            ContextHubClient client, ContextHubClientCallback callback, Executor executor) {
        return new IContextHubClientCallback.Stub() {
            @Override
            public void onMessageFromNanoApp(NanoAppMessage message) {
                executor.execute(() -> callback.onMessageFromNanoApp(client, message));
            }

            @Override
            public void onHubReset() {
                executor.execute(() -> callback.onHubReset(client));
            }

            @Override
            public void onNanoAppAborted(long nanoAppId, int abortCode) {
                executor.execute(() -> callback.onNanoAppAborted(client, nanoAppId, abortCode));
            }

            @Override
            public void onNanoAppLoaded(long nanoAppId) {
                executor.execute(() -> callback.onNanoAppLoaded(client, nanoAppId));
            }

            @Override
            public void onNanoAppUnloaded(long nanoAppId) {
                executor.execute(() -> callback.onNanoAppUnloaded(client, nanoAppId));
            }

            @Override
            public void onNanoAppEnabled(long nanoAppId) {
                executor.execute(() -> callback.onNanoAppEnabled(client, nanoAppId));
            }

            @Override
            public void onNanoAppDisabled(long nanoAppId) {
                executor.execute(() -> callback.onNanoAppDisabled(client, nanoAppId));
            }
        };
    }

    /**
     * Creates and registers a client and its callback with the Context Hub Service.
     *
     * A client is registered with the Context Hub Service for a specified Context Hub. When the
     * registration succeeds, the client can send messages to nanoapps through the returned
     * {@link ContextHubClient} object, and receive notifications through the provided callback.
     *
     * @param hubInfo  the hub to attach this client to
     * @param callback the notification callback to register
     * @param executor the executor to invoke the callback
     * @return the registered client object
     *
     * @throws IllegalArgumentException if hubInfo does not represent a valid hub
     * @throws IllegalStateException    if there were too many registered clients at the service
     * @throws NullPointerException     if callback, hubInfo, or executor is null
     *
     * @see ContextHubClientCallback
     */
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    @NonNull public ContextHubClient createClient(
            @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback,
            @NonNull @CallbackExecutor Executor executor) {
        Preconditions.checkNotNull(callback, "Callback cannot be null");
        Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
        Preconditions.checkNotNull(executor, "Executor cannot be null");

        ContextHubClient client = new ContextHubClient(hubInfo);
        IContextHubClientCallback clientInterface = createClientCallback(
                client, callback, executor);

        IContextHubClient clientProxy;
        try {
            clientProxy = mService.createClient(clientInterface, hubInfo.getId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

        client.setClientProxy(clientProxy);
        return client;
    }

    /**
     * Equivalent to {@link #createClient(ContextHubInfo, ContextHubClientCallback, Executor)}
     * with the executor using the main thread's Looper.
     *
     * @param hubInfo  the hub to attach this client to
     * @param callback the notification callback to register
     * @return the registered client object
     *
     * @throws IllegalArgumentException if hubInfo does not represent a valid hub
     * @throws IllegalStateException    if there were too many registered clients at the service
     * @throws NullPointerException     if callback or hubInfo is null
     *
     * @see ContextHubClientCallback
     */
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    @NonNull public ContextHubClient createClient(
            @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback) {
        return createClient(hubInfo, callback, new HandlerExecutor(Handler.getMain()));
    }

    /**
     * Creates a ContextHubClient based on an Intent received by the Context Hub Service.
     *
     * This method is intended to be used after receiving an Intent received as a result of
     * {@link ContextHubClient.registerIntent(PendingIntent, long)}, and must have been created
     * through {@link #createClient(ContextHubInfo, ContextHubClientCallback, Executor)} or
     * equivalent at an earlier time.
     *
     * @param pendingIntent the PendingIntent that has been registered with a client
     * @param hubInfo       the hub to attach this client to
     * @param callback      the notification callback to register
     * @param executor      the executor to invoke the callback
     * @return the registered client object
     *
     * @throws IllegalArgumentException if hubInfo does not represent a valid hub, or pendingIntent
     *                                  was not associated with a client
     * @throws IllegalStateException    if the client is already registered to a valid callback
     * @throws NullPointerException     if pendingIntent, hubInfo, callback, or executor is null
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    @NonNull public ContextHubClient createClient(
            @NonNull PendingIntent pendingIntent, @NonNull ContextHubInfo hubInfo,
            @NonNull ContextHubClientCallback callback,
            @NonNull @CallbackExecutor Executor executor) {
        Preconditions.checkNotNull(pendingIntent, "PendingIntent cannot be null");
        Preconditions.checkNotNull(callback, "Callback cannot be null");
        Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
        Preconditions.checkNotNull(executor, "Executor cannot be null");

        ContextHubClient client = new ContextHubClient(hubInfo);
        IContextHubClientCallback clientInterface = createClientCallback(
                client, callback, executor);

        IContextHubClient clientProxy;
        try {
            clientProxy = mService.bindClient(pendingIntent, clientInterface, hubInfo.getId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

        client.setClientProxy(clientProxy);
        return client;
    }

    /**
     * Equivalent to {@link #createClient(PendingIntent, ContextHubInfo, ContextHubClientCallback,
     * Executor)} with the executor using the main thread's Looper.
     *
     * @param pendingIntent the PendingIntent that has been registered with a client
     * @param hubInfo       the hub to attach this client to
     * @param callback      the notification callback to register
     * @return the registered client object
     *
     * @throws IllegalArgumentException if hubInfo does not represent a valid hub, or pendingIntent
     *                                  was not associated with a client
     * @throws IllegalStateException    if the client is already registered to a valid callback
     * @throws NullPointerException     if pendingIntent, hubInfo, or callback is null
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    @NonNull public ContextHubClient createClient(
            @NonNull PendingIntent pendingIntent, @NonNull ContextHubInfo hubInfo,
            @NonNull ContextHubClientCallback callback) {
        return createClient(
                pendingIntent, hubInfo, callback, new HandlerExecutor(Handler.getMain()));
    }

    /**
     * Unregister a callback for receive messages from the context hub.
     *
     * @see Callback
     *
     * @param callback method to deregister
     *
     * @return int 0 on success, -1 otherwise
     *
     * @deprecated Use {@link android.hardware.location.ContextHubClient#close()} to unregister
     *             a {@link android.hardware.location.ContextHubClientCallback}.
     */
    @SuppressLint("Doclava125")
    @Deprecated
    public int unregisterCallback(@NonNull Callback callback) {
      synchronized(this) {
          if (callback != mCallback) {
              Log.w(TAG, "Cannot recognize callback!");
              return -1;
          }

          mCallback = null;
          mCallbackHandler = null;
      }
      return 0;
    }

    /**
     * @deprecated Use {@link #unregisterCallback(Callback)} instead.
     * @hide
     */
    @Deprecated
    public synchronized int unregisterCallback(ICallback callback) {
        if (callback != mLocalCallback) {
            Log.w(TAG, "Cannot recognize local callback!");
            return -1;
        }
        mLocalCallback = null;
        return 0;
    }

    /**
     * Invokes the ContextHubManager.Callback callback registered with the ContextHubManager.
     *
     * @param hubId The ID of the Context Hub the message came from
     * @param nanoAppId The instance ID of the nanoapp the message came from
     * @param message The message to provide the callback
     */
    private synchronized void invokeOnMessageReceiptCallback(
            int hubId, int nanoAppId, ContextHubMessage message) {
        if (mCallback != null) {
            mCallback.onMessageReceipt(hubId, nanoAppId, message);
        }
    }

    private final IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
        @Override
        public void onMessageReceipt(
                final int hubId, final int nanoAppId, final ContextHubMessage message) {
            synchronized (ContextHubManager.this) {
                if (mCallback != null) {
                    mCallbackHandler.post(
                            () -> invokeOnMessageReceiptCallback(hubId, nanoAppId, message));
                } else if (mLocalCallback != null) {
                    // We always ensure that mCallback takes precedence, because mLocalCallback is
                    // only for internal compatibility
                    mLocalCallback.onMessageReceipt(hubId, nanoAppId, message);
                }
            }
        }
    };

    /** @throws ServiceNotFoundException
     * @hide */
    public ContextHubManager(Context context, Looper mainLooper) throws ServiceNotFoundException {
        mMainLooper = mainLooper;
        mService = IContextHubService.Stub.asInterface(
                ServiceManager.getServiceOrThrow(Context.CONTEXTHUB_SERVICE));
        try {
            mService.registerCallback(mClientCallback);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}
