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

import static android.car.settings.CarSettings.Secure.KEY_BLUETOOTH_A2DP_SINK_DEVICES;
import static android.car.settings.CarSettings.Secure.KEY_BLUETOOTH_HFP_CLIENT_DEVICES;
import static android.car.settings.CarSettings.Secure.KEY_BLUETOOTH_MAP_CLIENT_DEVICES;
import static android.car.settings.CarSettings.Secure.KEY_BLUETOOTH_PAN_DEVICES;
import static android.car.settings.CarSettings.Secure.KEY_BLUETOOTH_PBAP_CLIENT_DEVICES;

import android.bluetooth.BluetoothA2dpSink;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothMapClient;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothPbapClient;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.car.ICarBluetoothUserService;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.ParcelUuid;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * BluetoothProfileDeviceManager - Manages a list of devices, sorted by connection attempt priority.
 * Provides a means for other applications to request connection events and adjust the device
 * connection priorities. Access to these functions is provided through CarBluetoothManager.
 */
public class BluetoothProfileDeviceManager {
    private static final String TAG = CarLog.tagFor(BluetoothProfileDeviceManager.class);
    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
    private final Context mContext;
    private final int mUserId;
    private Set<String> mBondingDevices = new HashSet<>();

    private static final String SETTINGS_DELIMITER = ",";

    private static final int AUTO_CONNECT_TIMEOUT_MS = 8000;
    private static final Object AUTO_CONNECT_TOKEN = new Object();

    private static class BluetoothProfileInfo {
        final String mSettingsKey;
        final String mConnectionAction;
        final ParcelUuid[] mUuids;
        final int[] mProfileTriggers;

        private BluetoothProfileInfo(String action, String settingsKey, ParcelUuid[] uuids,
                int[] profileTriggers) {
            mSettingsKey = settingsKey;
            mConnectionAction = action;
            mUuids = uuids;
            mProfileTriggers = profileTriggers;
        }
    }

    private static final SparseArray<BluetoothProfileInfo> sProfileActions = new SparseArray();
    static {
        sProfileActions.put(BluetoothProfile.A2DP_SINK,
                new BluetoothProfileInfo(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED,
                        KEY_BLUETOOTH_A2DP_SINK_DEVICES, new ParcelUuid[] {
                            BluetoothUuid.A2DP_SOURCE
                        }, new int[] {}));
        sProfileActions.put(BluetoothProfile.HEADSET_CLIENT,
                new BluetoothProfileInfo(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED,
                        KEY_BLUETOOTH_HFP_CLIENT_DEVICES, new ParcelUuid[] {
                            BluetoothUuid.HFP_AG,
                            BluetoothUuid.HSP_AG
                        }, new int[] {BluetoothProfile.MAP_CLIENT, BluetoothProfile.PBAP_CLIENT}));
        sProfileActions.put(BluetoothProfile.MAP_CLIENT,
                new BluetoothProfileInfo(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED,
                        KEY_BLUETOOTH_MAP_CLIENT_DEVICES, new ParcelUuid[] {
                            BluetoothUuid.MAS
                        }, new int[] {}));
        sProfileActions.put(BluetoothProfile.PAN,
                new BluetoothProfileInfo(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED,
                        KEY_BLUETOOTH_PAN_DEVICES, new ParcelUuid[] {
                            BluetoothUuid.PANU
                        }, new int[] {}));
        sProfileActions.put(BluetoothProfile.PBAP_CLIENT,
                new BluetoothProfileInfo(BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED,
                        KEY_BLUETOOTH_PBAP_CLIENT_DEVICES, new ParcelUuid[] {
                            BluetoothUuid.PBAP_PSE
                        }, new int[] {}));
    }

    // Fixed per-profile information for the profile this object manages
    private final int mProfileId;
    private final String mSettingsKey;
    private final String mProfileConnectionAction;
    private final ParcelUuid[] mProfileUuids;
    private final int[] mProfileTriggers;

    // Central priority list of devices
    private final Object mPrioritizedDevicesLock = new Object();
    @GuardedBy("mPrioritizedDevicesLock")
    private ArrayList<BluetoothDevice> mPrioritizedDevices;

    // Auto connection process state
    private final Object mAutoConnectLock = new Object();
    @GuardedBy("mAutoConnectLock")
    private boolean mConnecting = false;
    @GuardedBy("mAutoConnectLock")
    private int mAutoConnectPriority;
    @GuardedBy("mAutoConnectLock")
    private ArrayList<BluetoothDevice> mAutoConnectingDevices;

    private final BluetoothAdapter mBluetoothAdapter;
    private final BluetoothBroadcastReceiver mBluetoothBroadcastReceiver;
    private final ICarBluetoothUserService mBluetoothUserProxies;
    private final Handler mHandler = new Handler(
            CarServiceUtils.getHandlerThread(CarBluetoothService.THREAD_NAME).getLooper());
    /**
     * A BroadcastReceiver that listens specifically for actions related to the profile we're
     * tracking and uses them to update the status.
     */
    private class BluetoothBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (mProfileConnectionAction.equals(action)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
                        BluetoothProfile.STATE_DISCONNECTED);
                handleDeviceConnectionStateChange(device, state);
            } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
                        BluetoothDevice.ERROR);
                handleDeviceBondStateChange(device, state);
            } else if (BluetoothDevice.ACTION_UUID.equals(action)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                Parcelable[] uuids = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
                handleDeviceUuidEvent(device, uuids);
            } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
                handleAdapterStateChange(state);
            }
        }
    }

    /**
     * Handles an incoming Profile-Device connection event.
     *
     * On <BluetoothProfile>.ACTION_CONNECTION_STATE_CHANGED coming from the BroadcastReceiver:
     *    On connected, if we're auto connecting and this is the current device we're managing, then
     *    see if we can move on to the next device in the list. Otherwise, If the device connected
     *    then add it to our priority list if it's not on their already.
     *
     *    On disconnected, if the device that disconnected also has had its profile priority set to
     *    PRIORITY_OFF, then remove it from our list.
     *
     * @param device - The Bluetooth device the state change is for
     * @param state - The new profile connection state of the device
     */
    private void handleDeviceConnectionStateChange(BluetoothDevice device, int state) {
        logd("Connection state changed [device: " + device + ", state: "
                        + Utils.getConnectionStateName(state) + "]");
        if (state == BluetoothProfile.STATE_CONNECTED) {
            if (isAutoConnecting() && isAutoConnectingDevice(device)) {
                continueAutoConnecting();
            } else {
                if (getProfilePriority(device) >= BluetoothProfile.PRIORITY_ON) {
                    addDevice(device); // No-op if device is in the list.
                }
                triggerConnections(device);
            }
        }
        // NOTE: We wanted check on disconnect if a device is priority off and use that as an
        // indicator to remove a device from the list, but priority reporting can be flaky and
        // was leading to us removing devices when we didn't want to.
    }

    /**
     * Handles an incoming device bond status event.
     *
     * On BluetoothDevice.ACTION_BOND_STATE_CHANGED:
     *    - If a device becomes unbonded, remove it from our list if it's there.
     *    - If it's bonded, then add it to our list if the UUID set says it supports us.
     *
     * @param device - The Bluetooth device the state change is for
     * @param state - The new bond state of the device
     */
    private void handleDeviceBondStateChange(BluetoothDevice device, int state) {
        logd("Bond state has changed [device: " + device + ", state: "
                + Utils.getBondStateName(state) + "]");
        if (state == BluetoothDevice.BOND_NONE) {
            mBondingDevices.remove(device.getAddress());
            // Note: We have seen cases of unbonding events being sent without actually
            // unbonding the device.
            removeDevice(device);
        } else if (state == BluetoothDevice.BOND_BONDING) {
            mBondingDevices.add(device.getAddress());
        } else if (state == BluetoothDevice.BOND_BONDED) {
            addBondedDeviceIfSupported(device);
            mBondingDevices.remove(device.getAddress());
        }
    }

    /**
     * Handles an incoming device UUID set update event for bonding devices.
     *
     * On BluetoothDevice.ACTION_UUID:
     *    If the UUID is one this profile cares about, set the profile priority for the device that
     *    the UUID was found on to PRIORITY_ON if its not PRIORITY_OFF already (meaning inhibited or
     *    disabled by the user through settings).
     *
     * @param device - The Bluetooth device the UUID event is for
     * @param uuids - The incoming set of supported UUIDs for the device
     */
    private void handleDeviceUuidEvent(BluetoothDevice device, Parcelable[] uuids) {
        logd("UUIDs found, device: " + device);
        if (!mBondingDevices.remove(device.getAddress())) return;
        if (uuids != null) {
            ParcelUuid[] uuidsToSend = new ParcelUuid[uuids.length];
            for (int i = 0; i < uuidsToSend.length; i++) {
                uuidsToSend[i] = (ParcelUuid) uuids[i];
            }
            provisionDeviceIfSupported(device, uuidsToSend);
        }
    }

    /**
     * Handle an adapter state change event.
     *
     * On BluetoothAdapter.ACTION_STATE_CHANGED:
     *    If the adapter is going into the OFF state, then cancel any auto connecting, commit our
     *    priority list and go idle.
     *
     * @param state - The new state of the Bluetooth adapter
     */
    private void handleAdapterStateChange(int state) {
        logd("Bluetooth Adapter state changed: " + Utils.getAdapterStateName(state));
        // Crashes of the BT stack mean we're not promised to see all the state changes we
        // might want to see. In order to be a bit more robust to crashes, we'll treat any
        // non-ON state as a time to cancel auto-connect. This gives us a better chance of
        // seeing a cancel state before a crash, as well as makes sure we're "cancelled"
        // before we see an ON.
        if (state != BluetoothAdapter.STATE_ON) {
            cancelAutoConnecting();
        }
        // To reduce how many times we're committing the list, we'll only write back on off
        if (state == BluetoothAdapter.STATE_OFF) {
            commit();
        }
    }

    /**
     * Creates an instance of BluetoothProfileDeviceManager that will manage devices
     * for the given profile ID.
     *
     * @param context - context of calling code
     * @param userId - ID of user we want to manage devices for
     * @param bluetoothUserProxies - Set of per-user bluetooth proxies for calling into the
     *                               bluetooth stack as the current user.
     * @param profileId - BluetoothProfile integer that represents the profile we're managing
     * @return A new instance of a BluetoothProfileDeviceManager, or null on any error
     */
    public static BluetoothProfileDeviceManager create(Context context, int userId,
            ICarBluetoothUserService bluetoothUserProxies, int profileId) {
        try {
            return new BluetoothProfileDeviceManager(context, userId, bluetoothUserProxies,
                    profileId);
        } catch (NullPointerException | IllegalArgumentException e) {
            return null;
        }
    }

    /**
     * Creates an instance of BluetoothProfileDeviceManager that will manage devices
     * for the given profile ID.
     *
     * @param context - context of calling code
     * @param userId - ID of user we want to manage devices for
     * @param bluetoothUserProxies - Set of per-user bluetooth proxies for calling into the
     *                               bluetooth stack as the current user.
     * @param profileId - BluetoothProfile integer that represents the profile we're managing
     * @return A new instance of a BluetoothProfileDeviceManager
     */
    private BluetoothProfileDeviceManager(Context context, int userId,
            ICarBluetoothUserService bluetoothUserProxies, int profileId) {
        mContext = Objects.requireNonNull(context);
        mUserId = userId;
        mBluetoothUserProxies = bluetoothUserProxies;

        mPrioritizedDevices = new ArrayList<>();
        BluetoothProfileInfo bpi = sProfileActions.get(profileId);
        if (bpi == null) {
            throw new IllegalArgumentException("Provided profile " + Utils.getProfileName(profileId)
                    + " is unrecognized");
        }
        mProfileId = profileId;
        mSettingsKey = bpi.mSettingsKey;
        mProfileConnectionAction = bpi.mConnectionAction;
        mProfileUuids = bpi.mUuids;
        mProfileTriggers = bpi.mProfileTriggers;

        mBluetoothBroadcastReceiver = new BluetoothBroadcastReceiver();
        mBluetoothAdapter = Objects.requireNonNull(BluetoothAdapter.getDefaultAdapter());
    }

    /**
     * Begin managing devices for this profile. Sets the start state from persistent memory.
     */
    public void start() {
        logd("Starting device management");
        load();
        synchronized (mAutoConnectLock) {
            mConnecting = false;
            mAutoConnectPriority = -1;
            mAutoConnectingDevices = null;
        }

        IntentFilter profileFilter = new IntentFilter();
        profileFilter.addAction(mProfileConnectionAction);
        profileFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        profileFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        profileFilter.addAction(BluetoothDevice.ACTION_UUID);
        mContext.registerReceiverAsUser(mBluetoothBroadcastReceiver, UserHandle.CURRENT,
                profileFilter, null, null);
    }

    /**
     * Stop managing devices for this profile. Commits the final priority list to persistent memory
     * and cleans up local resources.
     */
    public void stop() {
        logd("Stopping device management");
        if (mBluetoothBroadcastReceiver != null) {
            if (mContext != null) {
                mContext.unregisterReceiver(mBluetoothBroadcastReceiver);
            }
        }
        cancelAutoConnecting();
        commit();
        return;
    }

    /**
     * Loads the current device priority list from persistent memory in {@link Settings.Secure}.
     *
     * This will overwrite the contents of the local priority list. It does not attempt to take the
     * union of the file and existing set. As such, you likely do not want to load after starting.
     * Failed attempts to load leave the prioritized device list unchanged.
     *
     * @return true on success, false otherwise
     */
    private boolean load() {
        logd("Loading device priority list snapshot using key '" + mSettingsKey + "'");

        // Read from Settings.Secure for our profile, as the current user.
        String devicesStr = Settings.Secure.getStringForUser(mContext.getContentResolver(),
                mSettingsKey, mUserId);
        logd("Found Device String: '" + devicesStr + "'");
        if (devicesStr == null || "".equals(devicesStr)) {
            return false;
        }

        // Split string into list of device MAC addresses
        List<String> deviceList = Arrays.asList(devicesStr.split(SETTINGS_DELIMITER));
        if (deviceList == null) {
            return false;
        }

        // Turn the strings into full blown Bluetooth devices
        ArrayList<BluetoothDevice> devices = new ArrayList<>();
        for (String address : deviceList) {
            try {
                BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
                devices.add(device);
            } catch (IllegalArgumentException e) {
                logw("Unable to parse address '" + address + "' to a device");
                continue;
            }
        }

        synchronized (mPrioritizedDevicesLock) {
            mPrioritizedDevices = devices;
        }

        logd("Loaded Priority list: " + devices);
        return true;
    }

    /**
     * Commits the current device priority list to persistent memory in {@link Settings.Secure}.
     *
     * @return true on success, false otherwise
     */
    private boolean commit() {
        StringBuilder sb = new StringBuilder();
        String delimiter = "";
        synchronized (mPrioritizedDevicesLock) {
            for (BluetoothDevice device : mPrioritizedDevices) {
                sb.append(delimiter);
                sb.append(device.getAddress());
                delimiter = SETTINGS_DELIMITER;
            }
        }

        String devicesStr = sb.toString();
        Settings.Secure.putStringForUser(mContext.getContentResolver(), mSettingsKey, devicesStr,
                mUserId);
        logd("Committed key: " + mSettingsKey + ", value: '" + devicesStr + "'");
        return true;
    }

    /**
     * Syncs the current priority list against the list of bonded devices from the adapter so that
     * we can make sure things haven't changed on us between the last two times we've ran.
     */
    private void sync() {
        logd("Syncing the priority list with the adapter's list of bonded devices");
        Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices();
        for (BluetoothDevice device : bondedDevices) {
            addDevice(device); // No-op if device is already in the priority list
        }

        synchronized (mPrioritizedDevicesLock) {
            ArrayList<BluetoothDevice> devices = getDeviceListSnapshot();
            for (BluetoothDevice device : devices) {
                if (!bondedDevices.contains(device)) {
                    removeDevice(device);
                }
            }
        }
    }

    /**
     * Makes a clone of the current prioritized device list in a synchronized fashion
     *
     * @return A clone of the most up to date prioritized device list
     */
    public ArrayList<BluetoothDevice> getDeviceListSnapshot() {
        ArrayList<BluetoothDevice> devices = new ArrayList<>();
        synchronized (mPrioritizedDevicesLock) {
            devices = (ArrayList) mPrioritizedDevices.clone();
        }
        return devices;
    }

    /**
     * Adds a device to the end of the priority list.
     *
     * @param device - The device you wish to add
     */
    public void addDevice(BluetoothDevice device) {
        if (device == null) return;
        synchronized (mPrioritizedDevicesLock) {
            if (mPrioritizedDevices.contains(device)) return;
            logd("Add device " + device);
            mPrioritizedDevices.add(device);
            commit();
        }
    }

    /**
     * Removes a device from the priority list.
     *
     * @param device - The device you wish to remove
     */
    public void removeDevice(BluetoothDevice device) {
        if (device == null) return;
        synchronized (mPrioritizedDevicesLock) {
            if (!mPrioritizedDevices.contains(device)) return;
            logd("Remove device " + device);
            mPrioritizedDevices.remove(device);
            commit();
        }
    }

    /**
     * Get the connection priority of a device.
     *
     * @param device - The device you want the priority of
     * @return The priority of the device, or -1 if the device is not in the list
     */
    public int getDeviceConnectionPriority(BluetoothDevice device) {
        if (device == null) return -1;
        logd("Get connection priority of " + device);
        synchronized (mPrioritizedDevicesLock) {
            return mPrioritizedDevices.indexOf(device);
        }
    }

    /**
     * Set the connection priority of a device.
     *
     * If the devide does not exist, it will be added. If the priority is less than zero,
     * no priority will be set. If the priority exceeds the bounds of the list, no priority will be
     * set.
     *
     * @param device - The device you want to set the priority of
     * @param priority - The priority you want to the device to have
     */
    public void setDeviceConnectionPriority(BluetoothDevice device, int priority) {
        synchronized (mPrioritizedDevicesLock) {
            if (device == null || priority < 0 || priority > mPrioritizedDevices.size()
                    || getDeviceConnectionPriority(device) == priority) return;
            if (mPrioritizedDevices.contains(device)) {
                mPrioritizedDevices.remove(device);
                if (priority > mPrioritizedDevices.size()) priority = mPrioritizedDevices.size();
            }
            logd("Set connection priority of " + device + " to " + priority);
            mPrioritizedDevices.add(priority, device);
            commit();
        }
    }

    /**
     * Connect a specific device on this profile.
     *
     * @param device - The device to connect
     * @return true on success, false otherwise
     */
    private boolean connect(BluetoothDevice device) {
        logd("Connecting " + device);
        try {
            return mBluetoothUserProxies.bluetoothConnectToProfile(mProfileId, device);
        } catch (RemoteException e) {
            logw("Failed to connect " + device + ", Reason: " + e);
        }
        return false;
    }

    /**
     * Disconnect a specific device from this profile.
     *
     * @param device - The device to disconnect
     * @return true on success, false otherwise
     */
    private boolean disconnect(BluetoothDevice device) {
        logd("Disconnecting " + device);
        try {
            return mBluetoothUserProxies.bluetoothDisconnectFromProfile(mProfileId, device);
        } catch (RemoteException e) {
            logw("Failed to disconnect " + device + ", Reason: " + e);
        }
        return false;
    }

    /**
     * Gets the Bluetooth stack priority on this profile for a specific device.
     *
     * @param device - The device to get the Bluetooth stack priority of
     * @return The Bluetooth stack priority on this profile for the given device
     */
    private int getProfilePriority(BluetoothDevice device) {
        try {
            return mBluetoothUserProxies.getProfilePriority(mProfileId, device);
        } catch (RemoteException e) {
            logw("Failed to get bluetooth stack priority for " + device + ", Reason: " + e);
        }
        return BluetoothProfile.PRIORITY_UNDEFINED;
    }

    /**
     * Gets the Bluetooth stack priority on this profile for a specific device.
     *
     * @param device - The device to set the Bluetooth stack priority of
     * @return true on success, false otherwise
     */
    private boolean setProfilePriority(BluetoothDevice device, int priority) {
        logd("Set " + device + " stack priority to " + Utils.getProfilePriorityName(priority));
        try {
            mBluetoothUserProxies.setProfilePriority(mProfileId, device, priority);
        } catch (RemoteException e) {
            logw("Failed to set bluetooth stack priority for " + device + ", Reason: " + e);
            return false;
        }
        return true;
    }

    /**
     * Begins the process of connecting to devices, one by one, in the order that the priority
     * list currently specifies.
     *
     * If we are already connecting, or no devices are present, then no work is done.
     */
    public void beginAutoConnecting() {
        logd("Request to begin auto connection process");
        synchronized (mAutoConnectLock) {
            if (isAutoConnecting()) {
                logd("Auto connect requested while we are already auto connecting.");
                return;
            }
            if (mBluetoothAdapter.getState() != BluetoothAdapter.STATE_ON) {
                logd("Bluetooth Adapter is not on, cannot connect devices");
                return;
            }
            mAutoConnectingDevices = getDeviceListSnapshot();
            if (mAutoConnectingDevices.size() == 0) {
                logd("No saved devices to auto-connect to.");
                cancelAutoConnecting();
                return;
            }
            mConnecting = true;
            mAutoConnectPriority = 0;
        }
        autoConnectWithTimeout();
    }

    /**
     * Connects the current priority device and sets a timeout timer to indicate when to give up and
     * move on to the next one.
     */
    private void autoConnectWithTimeout() {
        synchronized (mAutoConnectLock) {
            if (!isAutoConnecting()) {
                logd("Autoconnect process was cancelled, skipping connecting next device.");
                return;
            }
            if (mAutoConnectPriority < 0 || mAutoConnectPriority >= mAutoConnectingDevices.size()) {
                return;
            }

            BluetoothDevice device = mAutoConnectingDevices.get(mAutoConnectPriority);
            logd("Auto connecting (" + mAutoConnectPriority + ") device: " + device);

            mHandler.post(() -> {
                boolean connectStatus = connect(device);
                if (!connectStatus) {
                    logw("Connection attempt immediately failed, moving to the next device");
                    continueAutoConnecting();
                }
            });
            mHandler.postDelayed(() -> {
                logw("Auto connect process has timed out connecting to " + device);
                continueAutoConnecting();
            }, AUTO_CONNECT_TOKEN, AUTO_CONNECT_TIMEOUT_MS);
        }
    }

    /**
     * Will forcibly move the auto connect process to the next device, or finish it if no more
     * devices are available.
     */
    private void continueAutoConnecting() {
        logd("Continue auto-connect process on next device");
        synchronized (mAutoConnectLock) {
            if (!isAutoConnecting()) {
                logd("Autoconnect process was cancelled, no need to continue.");
                return;
            }
            mHandler.removeCallbacksAndMessages(AUTO_CONNECT_TOKEN);
            mAutoConnectPriority++;
            if (mAutoConnectPriority >= mAutoConnectingDevices.size()) {
                logd("No more devices to connect to");
                cancelAutoConnecting();
                return;
            }
        }
        autoConnectWithTimeout();
    }

    /**
     * Cancels the auto-connection process. Any in-flight connection attempts will still be tried.
     *
     * Canceling is defined as deleting the snapshot of devices, resetting the device to connect
     * index, setting the connecting boolean to null, and removing any pending timeouts if they
     * exist.
     *
     * If there are no auto-connects in process this will do nothing.
     */
    private void cancelAutoConnecting() {
        logd("Cleaning up any auto-connect process");
        synchronized (mAutoConnectLock) {
            if (!isAutoConnecting()) return;
            mHandler.removeCallbacksAndMessages(AUTO_CONNECT_TOKEN);
            mConnecting = false;
            mAutoConnectPriority = -1;
            mAutoConnectingDevices = null;
        }
    }

    /**
     * Get the auto-connect status of thie profile device manager
     *
     * @return true on success, false otherwise
     */
    public boolean isAutoConnecting() {
        synchronized (mAutoConnectLock) {
            return mConnecting;
        }
    }

    /**
     * Determine if a device is the currently auto-connecting device
     *
     * @param device - A BluetoothDevice object to compare against any know auto connecting device
     * @return true if the input device is the device we're currently connecting, false otherwise
     */
    private boolean isAutoConnectingDevice(BluetoothDevice device) {
        synchronized (mAutoConnectLock) {
            if (mAutoConnectingDevices == null) return false;
            return mAutoConnectingDevices.get(mAutoConnectPriority).equals(device);
        }
    }

    /**
     * Given a device, will check the cached UUID set and see if it supports this profile. If it
     * does then we will add it to the end of our prioritized set and attempt a connection if and
     * only if the Bluetooth device priority allows a connection.
     *
     * Will do nothing if the device isn't bonded.
     */
    private void addBondedDeviceIfSupported(BluetoothDevice device) {
        logd("Add device " + device + " if it is supported");
        if (device.getBondState() != BluetoothDevice.BOND_BONDED) return;
        if (BluetoothUuid.containsAnyUuid(device.getUuids(), mProfileUuids)
                && getProfilePriority(device) >= BluetoothProfile.PRIORITY_ON) {
            addDevice(device);
        }
    }

    /**
     * Checks the reported UUIDs for a device to see if the device supports this profile. If it does
     * then it will update the underlying Bluetooth stack with PRIORITY_ON so long as the device
     * doesn't have a PRIORITY_OFF value set.
     *
     * @param device - The device that may support our profile
     * @param uuids - The set of UUIDs for the device, which may include our profile
     */
    private void provisionDeviceIfSupported(BluetoothDevice device, ParcelUuid[] uuids) {
        logd("Checking UUIDs for device: " + device);
        if (BluetoothUuid.containsAnyUuid(uuids, mProfileUuids)) {
            int devicePriority = getProfilePriority(device);
            logd("Device " + device + " supports this profile. Priority: "
                    + Utils.getProfilePriorityName(devicePriority));
            // Transition from PRIORITY_OFF to any other Bluetooth stack priority value is supposed
            // to be a user choice, enabled through the Settings applications. That's why we don't
            // do it here for them.
            if (devicePriority == BluetoothProfile.PRIORITY_UNDEFINED) {
                // As a note, UUID updates happen during pairing, as well as each time the adapter
                // turns on. Initiating connections to bonded device following UUID verification
                // would defeat the purpose of the priority list. They don't arrive in a predictable
                // order either. Since we call this function on UUID discovery, don't connect here!
                setProfilePriority(device, BluetoothProfile.PRIORITY_ON);
                return;
            }
        }
        logd("Provisioning of " + device + " has ended without priority being set");
    }

    /**
     * Trigger connections of related Bluetooth profiles on a device
     *
     * @param device - The Bluetooth device you would like to connect to
     */
    private void triggerConnections(BluetoothDevice device) {
        for (int profile : mProfileTriggers) {
            logd("Trigger connection to " + Utils.getProfileName(profile) + "on " + device);
            try {
                mBluetoothUserProxies.bluetoothConnectToProfile(profile, device);
            } catch (RemoteException e) {
                logw("Failed to connect " + device + ", Reason: " + e);
            }
        }
    }

    /**
     * Writes the verbose current state of the object to the PrintWriter
     *
     * @param writer PrintWriter object to write lines to
     */
    public void dump(PrintWriter writer, String indent) {
        writer.println(indent + "BluetoothProfileDeviceManager [" + Utils.getProfileName(mProfileId)
                + "]");
        writer.println(indent + "\tUser: " + mUserId);
        writer.println(indent + "\tSettings Location: " + mSettingsKey);
        writer.println(indent + "\tUser Proxies Exist: "
                + (mBluetoothUserProxies != null ? "Yes" : "No"));
        writer.println(indent + "\tAuto-Connecting: " + (isAutoConnecting() ? "Yes" : "No"));
        writer.println(indent + "\tPriority List:");
        ArrayList<BluetoothDevice> devices = getDeviceListSnapshot();
        for (BluetoothDevice device : devices) {
            writer.println(indent + "\t\t" + device.getAddress() + " - " + device.getName());
        }
    }

    /**
     * Log a message to DEBUG
     */
    private void logd(String msg) {
        if (DBG) {
            Slog.d(TAG, "[" + Utils.getProfileName(mProfileId) + " - User: " + mUserId + "] "
                    + msg);
        }
    }

    /**
     * Log a message to WARN
     */
    private void logw(String msg) {
        Slog.w(TAG, "[" + Utils.getProfileName(mProfileId) + " - User: " + mUserId + "] " + msg);
    }
}
