/*
 * Copyright (C) 2015 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.car;

import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.bluetooth.BluetoothDevice;
import android.car.projection.ProjectionOptions;
import android.car.projection.ProjectionStatus;
import android.car.projection.ProjectionStatus.ProjectionState;
import android.content.Intent;
import android.net.wifi.WifiConfiguration;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
import android.view.KeyEvent;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;

/**
 * CarProjectionManager allows applications implementing projection to register/unregister itself
 * with projection manager, listen for voice notification.
 *
 * A client must have {@link Car#PERMISSION_CAR_PROJECTION} permission in order to access this
 * manager.
 *
 * @hide
 */
@SystemApi
public final class CarProjectionManager extends CarManagerBase {
    private static final String TAG = CarProjectionManager.class.getSimpleName();

    private final Binder mToken = new Binder();
    private final Object mLock = new Object();

    /**
     * Listener to get projected notifications.
     *
     * Currently only voice search request is supported.
     */
    public interface CarProjectionListener {
        /**
         * Voice search was requested by the user.
         */
        void onVoiceAssistantRequest(boolean fromLongPress);
    }

    /**
     * Interface for projection apps to receive and handle key events from the system.
     */
    public interface ProjectionKeyEventHandler {
        /**
         * Called when a projection key event occurs.
         *
         * @param event The projection key event that occurred.
         */
        void onKeyEvent(@KeyEventNum int event);
    }
    /**
     * Flag for {@link #registerProjectionListener(CarProjectionListener, int)}: subscribe to
     * voice-search short-press requests.
     *
     * @deprecated Use {@link #addKeyEventHandler(Set, ProjectionKeyEventHandler)} with the
     * {@link #KEY_EVENT_VOICE_SEARCH_SHORT_PRESS_KEY_UP} event instead.
     */
    @Deprecated
    public static final int PROJECTION_VOICE_SEARCH = 0x1;
    /**
     * Flag for {@link #registerProjectionListener(CarProjectionListener, int)}: subscribe to
     * voice-search long-press requests.
     *
     * @deprecated Use {@link #addKeyEventHandler(Set, ProjectionKeyEventHandler)} with the
     * {@link #KEY_EVENT_VOICE_SEARCH_LONG_PRESS_KEY_DOWN} event instead.
     */
    @Deprecated
    public static final int PROJECTION_LONG_PRESS_VOICE_SEARCH = 0x2;

    /**
     * Event for {@link #addKeyEventHandler}: fired when the {@link KeyEvent#KEYCODE_VOICE_ASSIST}
     * key is pressed down.
     *
     * If the key is released before the long-press timeout,
     * {@link #KEY_EVENT_VOICE_SEARCH_SHORT_PRESS_KEY_UP} will be fired. If the key is held past the
     * long-press timeout, {@link #KEY_EVENT_VOICE_SEARCH_LONG_PRESS_KEY_DOWN} will be fired,
     * followed by {@link #KEY_EVENT_VOICE_SEARCH_LONG_PRESS_KEY_UP}.
     */
    public static final int KEY_EVENT_VOICE_SEARCH_KEY_DOWN = 0;
    /**
     * Event for {@link #addKeyEventHandler}: fired when the {@link KeyEvent#KEYCODE_VOICE_ASSIST}
     * key is released after a short-press.
     */
    public static final int KEY_EVENT_VOICE_SEARCH_SHORT_PRESS_KEY_UP = 1;
    /**
     * Event for {@link #addKeyEventHandler}: fired when the {@link KeyEvent#KEYCODE_VOICE_ASSIST}
     * key is held down past the long-press timeout.
     */
    public static final int KEY_EVENT_VOICE_SEARCH_LONG_PRESS_KEY_DOWN = 2;
    /**
     * Event for {@link #addKeyEventHandler}: fired when the {@link KeyEvent#KEYCODE_VOICE_ASSIST}
     * key is released after a long-press.
     */
    public static final int KEY_EVENT_VOICE_SEARCH_LONG_PRESS_KEY_UP = 3;
    /**
     * Event for {@link #addKeyEventHandler}: fired when the {@link KeyEvent#KEYCODE_CALL} key is
     * pressed down.
     *
     * If the key is released before the long-press timeout,
     * {@link #KEY_EVENT_CALL_SHORT_PRESS_KEY_UP} will be fired. If the key is held past the
     * long-press timeout, {@link #KEY_EVENT_CALL_LONG_PRESS_KEY_DOWN} will be fired, followed by
     * {@link #KEY_EVENT_CALL_LONG_PRESS_KEY_UP}.
     */
    public static final int KEY_EVENT_CALL_KEY_DOWN = 4;
    /**
     * Event for {@link #addKeyEventHandler}: fired when the {@link KeyEvent#KEYCODE_CALL} key is
     * released after a short-press.
     */
    public static final int KEY_EVENT_CALL_SHORT_PRESS_KEY_UP = 5;
    /**
     * Event for {@link #addKeyEventHandler}: fired when the {@link KeyEvent#KEYCODE_CALL} key is
     * held down past the long-press timeout.
     */
    public static final int KEY_EVENT_CALL_LONG_PRESS_KEY_DOWN = 6;
    /**
     * Event for {@link #addKeyEventHandler}: fired when the {@link KeyEvent#KEYCODE_CALL} key is
     * released after a long-press.
     */
    public static final int KEY_EVENT_CALL_LONG_PRESS_KEY_UP = 7;

    /** @hide */
    public static final int NUM_KEY_EVENTS = 8;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = "KEY_EVENT_", value = {
            KEY_EVENT_VOICE_SEARCH_KEY_DOWN,
            KEY_EVENT_VOICE_SEARCH_SHORT_PRESS_KEY_UP,
            KEY_EVENT_VOICE_SEARCH_LONG_PRESS_KEY_DOWN,
            KEY_EVENT_VOICE_SEARCH_LONG_PRESS_KEY_UP,
            KEY_EVENT_CALL_KEY_DOWN,
            KEY_EVENT_CALL_SHORT_PRESS_KEY_UP,
            KEY_EVENT_CALL_LONG_PRESS_KEY_DOWN,
            KEY_EVENT_CALL_LONG_PRESS_KEY_UP,
    })
    @Target({ElementType.TYPE_USE})
    public @interface KeyEventNum {}

    /** @hide */
    public static final int PROJECTION_AP_STARTED = 0;
    /** @hide */
    public static final int PROJECTION_AP_STOPPED = 1;
    /** @hide */
    public static final int PROJECTION_AP_FAILED = 2;

    private final ICarProjection mService;
    private final Executor mHandlerExecutor;

    @GuardedBy("mLock")
    private CarProjectionListener mListener;
    @GuardedBy("mLock")
    private int mVoiceSearchFilter;
    private final ProjectionKeyEventHandler mLegacyListenerTranslator =
            this::translateKeyEventToLegacyListener;

    private final ICarProjectionKeyEventHandlerImpl mBinderHandler =
            new ICarProjectionKeyEventHandlerImpl(this);

    @GuardedBy("mLock")
    private final Map<ProjectionKeyEventHandler, KeyEventHandlerRecord> mKeyEventHandlers =
            new HashMap<>();
    @GuardedBy("mLock")
    private BitSet mHandledEvents = new BitSet();

    private ProjectionAccessPointCallbackProxy mProjectionAccessPointCallbackProxy;

    private final Set<ProjectionStatusListener> mProjectionStatusListeners = new LinkedHashSet<>();
    private CarProjectionStatusListenerImpl mCarProjectionStatusListener;

    // Only one access point proxy object per process.
    private static final IBinder mAccessPointProxyToken = new Binder();

    /**
     * Interface to receive for projection status updates.
     */
    public interface ProjectionStatusListener {
        /**
         * This method gets invoked if projection status has been changed.
         *
         * @param state - current projection state
         * @param packageName - if projection is currently running either in the foreground or
         *                      in the background this argument will contain its package name
         * @param details - contains detailed information about all currently registered projection
         *                  receivers.
         */
        void onProjectionStatusChanged(@ProjectionState int state, @Nullable String packageName,
                @NonNull List<ProjectionStatus> details);
    }

    /**
     * @hide
     */
    public CarProjectionManager(Car car, IBinder service) {
        super(car);
        mService = ICarProjection.Stub.asInterface(service);
        Handler handler = getEventHandler();
        mHandlerExecutor = handler::post;
    }

    /**
     * Compatibility with previous APIs due to typo
     * @hide
     */
    public void regsiterProjectionListener(CarProjectionListener listener, int voiceSearchFilter) {
        registerProjectionListener(listener, voiceSearchFilter);
    }

    /**
     * Register listener to monitor projection. Only one listener can be registered and
     * registering multiple times will lead into only the last listener to be active.
     * @param listener
     * @param voiceSearchFilter Flags of voice search requests to get notification.
     */
    @RequiresPermission(Car.PERMISSION_CAR_PROJECTION)
    public void registerProjectionListener(@NonNull CarProjectionListener listener,
            int voiceSearchFilter) {
        Preconditions.checkNotNull(listener, "listener cannot be null");
        synchronized (mLock) {
            if (mListener == null || mVoiceSearchFilter != voiceSearchFilter) {
                addKeyEventHandler(
                        translateVoiceSearchFilter(voiceSearchFilter),
                        mLegacyListenerTranslator);
            }
            mListener = listener;
            mVoiceSearchFilter = voiceSearchFilter;
        }
    }

    /**
     * Compatibility with previous APIs due to typo
     * @hide
     */
    public void unregsiterProjectionListener() {
       unregisterProjectionListener();
    }

    /**
     * Unregister listener and stop listening projection events.
     */
    @RequiresPermission(Car.PERMISSION_CAR_PROJECTION)
    public void unregisterProjectionListener() {
        synchronized (mLock) {
            removeKeyEventHandler(mLegacyListenerTranslator);
            mListener = null;
            mVoiceSearchFilter = 0;
        }
    }

    @SuppressWarnings("deprecation")
    private static Set<Integer> translateVoiceSearchFilter(int voiceSearchFilter) {
        Set<Integer> rv = new ArraySet<>(Integer.bitCount(voiceSearchFilter));
        int i = 0;
        if ((voiceSearchFilter & PROJECTION_VOICE_SEARCH) != 0) {
            rv.add(KEY_EVENT_VOICE_SEARCH_SHORT_PRESS_KEY_UP);
        }
        if ((voiceSearchFilter & PROJECTION_LONG_PRESS_VOICE_SEARCH) != 0) {
            rv.add(KEY_EVENT_VOICE_SEARCH_LONG_PRESS_KEY_DOWN);
        }
        return rv;
    }

    private void translateKeyEventToLegacyListener(@KeyEventNum int keyEvent) {
        CarProjectionListener legacyListener;
        boolean fromLongPress;

        synchronized (mLock) {
            if (mListener == null) {
                return;
            }
            legacyListener = mListener;

            if (keyEvent == KEY_EVENT_VOICE_SEARCH_SHORT_PRESS_KEY_UP) {
                fromLongPress = false;
            } else if (keyEvent == KEY_EVENT_VOICE_SEARCH_LONG_PRESS_KEY_DOWN) {
                fromLongPress = true;
            } else {
                Log.e(TAG, "Unexpected key event " + keyEvent);
                return;
            }
        }

        Log.d(TAG, "Voice assistant request, long-press = " + fromLongPress);

        legacyListener.onVoiceAssistantRequest(fromLongPress);
    }

    /**
     * Adds a {@link ProjectionKeyEventHandler} to be called for the given set of key events.
     *
     * If the given event handler is already registered, the event set and {@link Executor} for that
     * event handler will be replaced with those provided.
     *
     * For any event with a defined event handler, the system will suppress its default behavior for
     * that event, and call the event handler instead. (For instance, if an event handler is defined
     * for {@link #KEY_EVENT_CALL_SHORT_PRESS_KEY_UP}, the system will not open the dialer when the
     * {@link KeyEvent#KEYCODE_CALL CALL} key is short-pressed.)
     *
     * Callbacks on the event handler will be run on the {@link Handler} designated to run callbacks
     * from {@link Car}.
     *
     * @param events        The set of key events to which to subscribe.
     * @param eventHandler  The {@link ProjectionKeyEventHandler} to call when those events occur.
     */
    @RequiresPermission(Car.PERMISSION_CAR_PROJECTION)
    public void addKeyEventHandler(
            @NonNull Set<@KeyEventNum Integer> events,
            @NonNull ProjectionKeyEventHandler eventHandler) {
        addKeyEventHandler(events, null, eventHandler);
    }

    /**
     * Adds a {@link ProjectionKeyEventHandler} to be called for the given set of key events.
     *
     * If the given event handler is already registered, the event set and {@link Executor} for that
     * event handler will be replaced with those provided.
     *
     * For any event with a defined event handler, the system will suppress its default behavior for
     * that event, and call the event handler instead. (For instance, if an event handler is defined
     * for {@link #KEY_EVENT_CALL_SHORT_PRESS_KEY_UP}, the system will not open the dialer when the
     * {@link KeyEvent#KEYCODE_CALL CALL} key is short-pressed.)
     *
     * Callbacks on the event handler will be run on the given {@link Executor}, or, if it is null,
     * the {@link Handler} designated to run callbacks for {@link Car}.
     *
     * @param events        The set of key events to which to subscribe.
     * @param executor      An {@link Executor} on which to run callbacks.
     * @param eventHandler  The {@link ProjectionKeyEventHandler} to call when those events occur.
     */
    @RequiresPermission(Car.PERMISSION_CAR_PROJECTION)
    public void addKeyEventHandler(
            @NonNull Set<@KeyEventNum Integer> events,
            @CallbackExecutor @Nullable Executor executor,
            @NonNull ProjectionKeyEventHandler eventHandler) {
        BitSet eventMask = new BitSet();
        for (int event : events) {
            Preconditions.checkArgument(event >= 0 && event < NUM_KEY_EVENTS, "Invalid key event");
            eventMask.set(event);
        }

        if (eventMask.isEmpty()) {
            removeKeyEventHandler(eventHandler);
            return;
        }

        if (executor == null) {
            executor = mHandlerExecutor;
        }

        synchronized (mLock) {
            KeyEventHandlerRecord record = mKeyEventHandlers.get(eventHandler);
            if (record == null) {
                record = new KeyEventHandlerRecord(executor, eventMask);
                mKeyEventHandlers.put(eventHandler, record);
            } else {
                record.mExecutor = executor;
                record.mSubscribedEvents = eventMask;
            }

            updateHandledEventsLocked();
        }
    }

    /**
     * Removes a previously registered {@link ProjectionKeyEventHandler}.
     *
     * @param eventHandler The listener to remove.
     */
    @RequiresPermission(Car.PERMISSION_CAR_PROJECTION)
    public void removeKeyEventHandler(@NonNull ProjectionKeyEventHandler eventHandler) {
        synchronized (mLock) {
            KeyEventHandlerRecord record = mKeyEventHandlers.remove(eventHandler);
            if (record != null) {
                updateHandledEventsLocked();
            }
        }
    }

    @GuardedBy("mLock")
    private void updateHandledEventsLocked() {
        BitSet events = new BitSet();

        for (KeyEventHandlerRecord record : mKeyEventHandlers.values()) {
            events.or(record.mSubscribedEvents);
        }

        if (events.equals(mHandledEvents)) {
            // No changes.
            return;
        }

        try {
            if (!events.isEmpty()) {
                Log.d(TAG, "Registering handler with system for " + events);
                byte[] eventMask = events.toByteArray();
                mService.registerKeyEventHandler(mBinderHandler, eventMask);
            } else {
                Log.d(TAG, "Unregistering handler with system");
                mService.unregisterKeyEventHandler(mBinderHandler);
            }
        } catch (RemoteException e) {
            handleRemoteExceptionFromCarService(e);
            return;
        }

        mHandledEvents = events;
    }

    /**
     * Registers projection runner on projection start with projection service
     * to create reverse binding.
     * @param serviceIntent
     */
    @RequiresPermission(Car.PERMISSION_CAR_PROJECTION)
    public void registerProjectionRunner(@NonNull Intent serviceIntent) {
        Preconditions.checkNotNull("serviceIntent cannot be null");
        synchronized (mLock) {
            try {
                mService.registerProjectionRunner(serviceIntent);
            } catch (RemoteException e) {
                handleRemoteExceptionFromCarService(e);
            }
        }
    }

    /**
     * Unregisters projection runner on projection stop with projection service to create
     * reverse binding.
     * @param serviceIntent
     */
    @RequiresPermission(Car.PERMISSION_CAR_PROJECTION)
    public void unregisterProjectionRunner(@NonNull Intent serviceIntent) {
        Preconditions.checkNotNull("serviceIntent cannot be null");
        synchronized (mLock) {
            try {
                mService.unregisterProjectionRunner(serviceIntent);
            } catch (RemoteException e) {
                handleRemoteExceptionFromCarService(e);
            }
        }
    }

    /** @hide */
    @Override
    public void onCarDisconnected() {
        // nothing to do
    }

    /**
     * Request to start Wi-Fi access point if it hasn't been started yet for wireless projection
     * receiver app.
     *
     * <p>A process can have only one request to start an access point, subsequent call of this
     * method will invalidate previous calls.
     *
     * @param callback to receive notifications when access point status changed for the request
     */
    @RequiresPermission(Car.PERMISSION_CAR_PROJECTION)
    public void startProjectionAccessPoint(@NonNull ProjectionAccessPointCallback callback) {
        Preconditions.checkNotNull(callback, "callback cannot be null");
        synchronized (mLock) {
            Looper looper = getEventHandler().getLooper();
            ProjectionAccessPointCallbackProxy proxy =
                    new ProjectionAccessPointCallbackProxy(this, looper, callback);
            try {
                mService.startProjectionAccessPoint(proxy.getMessenger(), mAccessPointProxyToken);
                mProjectionAccessPointCallbackProxy = proxy;
            } catch (RemoteException e) {
                handleRemoteExceptionFromCarService(e);
            }
        }
    }

    /**
     * Returns a list of available Wi-Fi channels. A channel is specified as frequency in MHz,
     * e.g. channel 1 will be represented as 2412 in the list.
     *
     * @param band one of the values from {@code android.net.wifi.WifiScanner#WIFI_BAND_*}
     */
    @RequiresPermission(Car.PERMISSION_CAR_PROJECTION)
    public @NonNull List<Integer> getAvailableWifiChannels(int band) {
        try {
            int[] channels = mService.getAvailableWifiChannels(band);
            List<Integer> channelList = new ArrayList<>(channels.length);
            for (int v : channels) {
                channelList.add(v);
            }
            return channelList;
        } catch (RemoteException e) {
            return handleRemoteExceptionFromCarService(e, Collections.emptyList());
        }
    }

    /**
     * Stop Wi-Fi Access Point for wireless projection receiver app.
     */
    @RequiresPermission(Car.PERMISSION_CAR_PROJECTION)
    public void stopProjectionAccessPoint() {
        ProjectionAccessPointCallbackProxy proxy;
        synchronized (mLock) {
            proxy = mProjectionAccessPointCallbackProxy;
            mProjectionAccessPointCallbackProxy = null;
        }
        if (proxy == null) {
            return;
        }

        try {
            mService.stopProjectionAccessPoint(mAccessPointProxyToken);
        } catch (RemoteException e) {
            handleRemoteExceptionFromCarService(e);
        }
    }

    /**
     * Request to disconnect the given profile on the given device, and prevent it from reconnecting
     * until either the request is released, or the process owning the given token dies.
     *
     * @param device  The device on which to inhibit a profile.
     * @param profile The {@link android.bluetooth.BluetoothProfile} to inhibit.
     * @return True if the profile was successfully inhibited, false if an error occurred.
     */
    @RequiresPermission(Car.PERMISSION_CAR_PROJECTION)
    public boolean requestBluetoothProfileInhibit(
            @NonNull BluetoothDevice device, int profile) {
        Preconditions.checkNotNull(device, "device cannot be null");
        try {
            return mService.requestBluetoothProfileInhibit(device, profile, mToken);
        } catch (RemoteException e) {
            return handleRemoteExceptionFromCarService(e, false);
        }
    }

    /**
     * Release an inhibit request made by {@link #requestBluetoothProfileInhibit}, and reconnect the
     * profile if no other inhibit requests are active.
     *
     * @param device  The device on which to release the inhibit request.
     * @param profile The profile on which to release the inhibit request.
     * @return True if the request was released, false if an error occurred.
     */
    @RequiresPermission(Car.PERMISSION_CAR_PROJECTION)
    public boolean releaseBluetoothProfileInhibit(@NonNull BluetoothDevice device, int profile) {
        Preconditions.checkNotNull(device, "device cannot be null");
        try {
            return mService.releaseBluetoothProfileInhibit(device, profile, mToken);
        } catch (RemoteException e) {
            return handleRemoteExceptionFromCarService(e, false);
        }
    }

    /**
     * Call this method to report projection status of your app. The aggregated status (from other
     * projection apps if available) will be broadcasted to interested parties.
     *
     * @param status the reported status that will be distributed to the interested listeners
     *
     * @see #registerProjectionStatusListener(ProjectionStatusListener)
     */
    @RequiresPermission(Car.PERMISSION_CAR_PROJECTION)
    public void updateProjectionStatus(@NonNull ProjectionStatus status) {
        Preconditions.checkNotNull(status, "status cannot be null");
        try {
            mService.updateProjectionStatus(status, mToken);
        } catch (RemoteException e) {
            handleRemoteExceptionFromCarService(e);
        }
    }

    /**
     * Register projection status listener. See {@link ProjectionStatusListener} for details. It is
     * allowed to register multiple listeners.
     *
     * <p>Note: provided listener will be called immediately with the most recent status.
     *
     * @param listener the listener to receive notification for any projection status changes
     */
    @RequiresPermission(Car.PERMISSION_CAR_PROJECTION_STATUS)
    public void registerProjectionStatusListener(@NonNull ProjectionStatusListener listener) {
        Preconditions.checkNotNull(listener, "listener cannot be null");
        synchronized (mLock) {
            mProjectionStatusListeners.add(listener);

            if (mCarProjectionStatusListener == null) {
                mCarProjectionStatusListener = new CarProjectionStatusListenerImpl(this);
                try {
                    mService.registerProjectionStatusListener(mCarProjectionStatusListener);
                } catch (RemoteException e) {
                    handleRemoteExceptionFromCarService(e);
                }
            } else {
                // Already subscribed to Car Service, immediately notify listener with the current
                // projection status in the event handler thread.
                getEventHandler().post(() ->
                        listener.onProjectionStatusChanged(
                                mCarProjectionStatusListener.mCurrentState,
                                mCarProjectionStatusListener.mCurrentPackageName,
                                mCarProjectionStatusListener.mDetails));
            }
        }
    }

    /**
     * Unregister provided listener from projection status notifications
     *
     * @param listener the listener for projection status notifications that was previously
     * registered with {@link #unregisterProjectionStatusListener(ProjectionStatusListener)}
     */
    @RequiresPermission(Car.PERMISSION_CAR_PROJECTION_STATUS)
    public void unregisterProjectionStatusListener(@NonNull ProjectionStatusListener listener) {
        Preconditions.checkNotNull(listener, "listener cannot be null");
        synchronized (mLock) {
            if (!mProjectionStatusListeners.remove(listener)
                    || !mProjectionStatusListeners.isEmpty()) {
                return;
            }
            unregisterProjectionStatusListenerFromCarServiceLocked();
        }
    }

    private void unregisterProjectionStatusListenerFromCarServiceLocked() {
        try {
            mService.unregisterProjectionStatusListener(mCarProjectionStatusListener);
            mCarProjectionStatusListener = null;
        } catch (RemoteException e) {
            handleRemoteExceptionFromCarService(e);
        }
    }

    private void handleProjectionStatusChanged(@ProjectionState int state,
            String packageName, List<ProjectionStatus> details) {
        List<ProjectionStatusListener> listeners;
        synchronized (mLock) {
            listeners = new ArrayList<>(mProjectionStatusListeners);
        }
        for (ProjectionStatusListener listener : listeners) {
            listener.onProjectionStatusChanged(state, packageName, details);
        }
    }

    /**
     * Returns {@link Bundle} object that contains customization for projection app. This bundle
     * can be parsed using {@link ProjectionOptions}.
     */
    @RequiresPermission(Car.PERMISSION_CAR_PROJECTION)
    public @NonNull Bundle getProjectionOptions() {
        try {
            return mService.getProjectionOptions();
        } catch (RemoteException e) {
            return handleRemoteExceptionFromCarService(e, Bundle.EMPTY);
        }
    }

    /**
     * Callback class for applications to receive updates about the LocalOnlyHotspot status.
     */
    public abstract static class ProjectionAccessPointCallback {
        public static final int ERROR_NO_CHANNEL = 1;
        public static final int ERROR_GENERIC = 2;
        public static final int ERROR_INCOMPATIBLE_MODE = 3;
        public static final int ERROR_TETHERING_DISALLOWED = 4;

        /** Called when access point started successfully. */
        public void onStarted(WifiConfiguration wifiConfiguration) {}
        /** Called when access point is stopped. No events will be sent after that. */
        public void onStopped() {}
        /** Called when access point failed to start. No events will be sent after that. */
        public void onFailed(int reason) {}
    }

    /**
     * Callback proxy for LocalOnlyHotspotCallback objects.
     */
    private static class ProjectionAccessPointCallbackProxy {
        private static final String LOG_PREFIX =
                ProjectionAccessPointCallbackProxy.class.getSimpleName() + ": ";

        private final Handler mHandler;
        private final WeakReference<CarProjectionManager> mCarProjectionManagerRef;
        private final Messenger mMessenger;

        ProjectionAccessPointCallbackProxy(CarProjectionManager manager, Looper looper,
                final ProjectionAccessPointCallback callback) {
            mCarProjectionManagerRef = new WeakReference<>(manager);

            mHandler = new Handler(looper) {
                @Override
                public void handleMessage(Message msg) {
                    Log.d(TAG, LOG_PREFIX + "handle message what: " + msg.what + " msg: " + msg);

                    CarProjectionManager manager = mCarProjectionManagerRef.get();
                    if (manager == null) {
                        Log.w(TAG, LOG_PREFIX + "handle message post GC");
                        return;
                    }

                    switch (msg.what) {
                        case PROJECTION_AP_STARTED:
                            WifiConfiguration config = (WifiConfiguration) msg.obj;
                            if (config == null) {
                                Log.e(TAG, LOG_PREFIX + "config cannot be null.");
                                callback.onFailed(ProjectionAccessPointCallback.ERROR_GENERIC);
                                return;
                            }
                            callback.onStarted(config);
                            break;
                        case PROJECTION_AP_STOPPED:
                            Log.i(TAG, LOG_PREFIX + "hotspot stopped");
                            callback.onStopped();
                            break;
                        case PROJECTION_AP_FAILED:
                            int reasonCode = msg.arg1;
                            Log.w(TAG, LOG_PREFIX + "failed to start.  reason: "
                                    + reasonCode);
                            callback.onFailed(reasonCode);
                            break;
                        default:
                            Log.e(TAG, LOG_PREFIX + "unhandled message.  type: " + msg.what);
                    }
                }
            };
            mMessenger = new Messenger(mHandler);
        }

        Messenger getMessenger() {
            return mMessenger;
        }
    }

    private static class ICarProjectionKeyEventHandlerImpl
            extends ICarProjectionKeyEventHandler.Stub {

        private final WeakReference<CarProjectionManager> mManager;

        private ICarProjectionKeyEventHandlerImpl(CarProjectionManager manager) {
            mManager = new WeakReference<>(manager);
        }

        @Override
        public void onKeyEvent(@KeyEventNum int event) {
            Log.d(TAG, "Received projection key event " + event);
            final CarProjectionManager manager = mManager.get();
            if (manager == null) {
                return;
            }

            List<Pair<ProjectionKeyEventHandler, Executor>> toDispatch = new ArrayList<>();
            synchronized (manager.mLock) {
                for (Map.Entry<ProjectionKeyEventHandler, KeyEventHandlerRecord> entry :
                        manager.mKeyEventHandlers.entrySet()) {
                    if (entry.getValue().mSubscribedEvents.get(event)) {
                        toDispatch.add(Pair.create(entry.getKey(), entry.getValue().mExecutor));
                    }
                }
            }

            for (Pair<ProjectionKeyEventHandler, Executor> entry : toDispatch) {
                ProjectionKeyEventHandler listener = entry.first;
                entry.second.execute(() -> listener.onKeyEvent(event));
            }
        }
    }

    private static class KeyEventHandlerRecord {
        @NonNull Executor mExecutor;
        @NonNull BitSet mSubscribedEvents;

        KeyEventHandlerRecord(@NonNull Executor executor, @NonNull BitSet subscribedEvents) {
            mExecutor = executor;
            mSubscribedEvents = subscribedEvents;
        }
    }

    private static class CarProjectionStatusListenerImpl
            extends ICarProjectionStatusListener.Stub {

        private @ProjectionState int mCurrentState;
        private @Nullable String mCurrentPackageName;
        private List<ProjectionStatus> mDetails = new ArrayList<>(0);

        private final WeakReference<CarProjectionManager> mManagerRef;

        private CarProjectionStatusListenerImpl(CarProjectionManager mgr) {
            mManagerRef = new WeakReference<>(mgr);
        }

        @Override
        public void onProjectionStatusChanged(int projectionState,
                String packageName,
                List<ProjectionStatus> details) {
            CarProjectionManager mgr = mManagerRef.get();
            if (mgr != null) {
                mgr.getEventHandler().post(() -> {
                    mCurrentState = projectionState;
                    mCurrentPackageName = packageName;
                    mDetails = Collections.unmodifiableList(details);

                    mgr.handleProjectionStatusChanged(projectionState, packageName, mDetails);
                });
            }
        }
    }
}
