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

Commit 51b5fb54 authored by Derek Jedral's avatar Derek Jedral Committed by Android (Google) Code Review
Browse files

Merge "Add methods for suggested devices called from UMO" into main

parents e35b0e57 985485b5
Loading
Loading
Loading
Loading
+8 −2
Original line number Original line Diff line number Diff line
@@ -54,12 +54,18 @@ public class ComplexMediaDevice extends MediaDevice {


    @Override
    @Override
    public Drawable getIcon() {
    public Drawable getIcon() {
        return mContext.getDrawable(R.drawable.ic_media_avr_device);
        return getIcon(mContext);
    }
    }


    @Override
    @Override
    public Drawable getIconWithoutBackground() {
    public Drawable getIconWithoutBackground() {
        return mContext.getDrawable(R.drawable.ic_media_avr_device);
        return getIcon(mContext);
    }

    /** Gets the drawable associated with the complex media device. */
    @NonNull
    public static Drawable getIcon(Context context) {
        return context.getDrawable(R.drawable.ic_media_avr_device);
    }
    }


    @Override
    @Override
+7 −1
Original line number Original line Diff line number Diff line
@@ -33,6 +33,7 @@ import android.graphics.drawable.Drawable;
import android.media.MediaRoute2Info;
import android.media.MediaRoute2Info;
import android.media.RouteListingPreference;
import android.media.RouteListingPreference;


import androidx.annotation.DrawableRes;
import androidx.annotation.VisibleForTesting;
import androidx.annotation.VisibleForTesting;


import com.android.settingslib.R;
import com.android.settingslib.R;
@@ -75,9 +76,14 @@ public class InfoMediaDevice extends MediaDevice {


    @VisibleForTesting
    @VisibleForTesting
    @SuppressWarnings("NewApi")
    @SuppressWarnings("NewApi")
    @DrawableRes
    int getDrawableResIdByType() {
    int getDrawableResIdByType() {
        return getDrawableResIdByType(mRouteInfo.getType());
    }

    static int getDrawableResIdByType(@MediaRoute2Info.Type int type) {
        int resId;
        int resId;
        switch (mRouteInfo.getType()) {
        switch (type) {
            case TYPE_GROUP:
            case TYPE_GROUP:
                resId = R.drawable.ic_media_group_device;
                resId = R.drawable.ic_media_group_device;
                break;
                break;
+111 −44
Original line number Original line Diff line number Diff line
@@ -52,6 +52,7 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothDevice;
import android.content.ComponentName;
import android.content.ComponentName;
import android.content.Context;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.media.MediaRoute2Info;
import android.media.MediaRoute2Info;
import android.media.RouteListingPreference;
import android.media.RouteListingPreference;
import android.media.RoutingSessionInfo;
import android.media.RoutingSessionInfo;
@@ -69,6 +70,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.RequiresApi;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.R;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.media.flags.Flags;
import com.android.settingslib.media.flags.Flags;
@@ -161,6 +163,12 @@ public abstract class InfoMediaManager {
            return mConnectionState;
            return mConnectionState;
        }
        }


        /** Gets the drawable associated with the suggested device type. */
        @NonNull
        public Drawable getIcon(Context context) {
            return getDrawableForSuggestion(context, this);
        }

        @Override
        @Override
        public boolean equals(Object obj) {
        public boolean equals(Object obj) {
            if (this == obj) {
            if (this == obj) {
@@ -681,6 +689,11 @@ public abstract class InfoMediaManager {
        return getActiveRoutingSession().getName();
        return getActiveRoutingSession().getName();
    }
    }


    @Nullable
    public SuggestedDeviceState getSuggestedDevice() {
        return mSuggestedDeviceState;
    }

    @TargetApi(Build.VERSION_CODES.R)
    @TargetApi(Build.VERSION_CODES.R)
    boolean shouldEnableVolumeSeekBar(RoutingSessionInfo sessionInfo) {
    boolean shouldEnableVolumeSeekBar(RoutingSessionInfo sessionInfo) {
        return sessionInfo.isSystemSession() // System sessions are not remote
        return sessionInfo.isSystemSession() // System sessions are not remote
@@ -717,6 +730,11 @@ public abstract class InfoMediaManager {
                }
                }
            }
            }
            if (newSuggestedDeviceState == null) {
            if (newSuggestedDeviceState == null) {
                if (topSuggestion
                        .getRouteId()
                        .equals(previousState.getSuggestedDeviceInfo().getRouteId())) {
                    return;
                }
                newSuggestedDeviceState = new SuggestedDeviceState(topSuggestion);
                newSuggestedDeviceState = new SuggestedDeviceState(topSuggestion);
            }
            }
        }
        }
@@ -862,6 +880,59 @@ public abstract class InfoMediaManager {
    void addMediaDevice(@NonNull MediaRoute2Info route, @NonNull RoutingSessionInfo activeSession) {
    void addMediaDevice(@NonNull MediaRoute2Info route, @NonNull RoutingSessionInfo activeSession) {
        final int deviceType = route.getType();
        final int deviceType = route.getType();
        MediaDevice mediaDevice = null;
        MediaDevice mediaDevice = null;
        if (isInfoMediaDevice(deviceType)) {
            mediaDevice =
                    new InfoMediaDevice(mContext, route, mPreferenceItemMap.get(route.getId()));

        } else if (isPhoneMediaDevice(deviceType)) {
            mediaDevice =
                    new PhoneMediaDevice(
                            mContext, route, mPreferenceItemMap.getOrDefault(route.getId(), null));

        } else if (isBluetoothMediaDevice(deviceType)) {
            if (route.getAddress() == null) {
                Log.e(TAG, "Ignoring bluetooth route with no set address: " + route);
            } else {
                final BluetoothDevice device =
                        BluetoothAdapter.getDefaultAdapter().getRemoteDevice(route.getAddress());
                final CachedBluetoothDevice cachedDevice =
                        mBluetoothManager.getCachedDeviceManager().findDevice(device);
                if (cachedDevice != null) {
                    mediaDevice =
                            new BluetoothMediaDevice(
                                    mContext,
                                    cachedDevice,
                                    route,
                                    mPreferenceItemMap.getOrDefault(route.getId(), null));
                }
            }
        } else if (isComplexMediaDevice(deviceType)) {
            mediaDevice =
                    new ComplexMediaDevice(mContext, route, mPreferenceItemMap.get(route.getId()));

        } else {
            Log.w(TAG, "addMediaDevice() unknown device type : " + deviceType);
        }
        if (mediaDevice != null) {
            if (activeSession.getSelectedRoutes().contains(route.getId())) {
                setDeviceState(mediaDevice, STATE_SELECTED);
            }
            mMediaDevices.add(mediaDevice);
        }
    }

    /** Updates the state of the device and updates liteners of the updated device state. */
    public void setDeviceState(MediaDevice device, @LocalMediaManager.MediaDeviceState int state) {
        if (device.getState() == state) {
            return;
        }
        device.setState(state);
        if (device.isSuggestedDevice()) {
            updateDeviceSuggestion();
        }
    }

    private static boolean isInfoMediaDevice(int deviceType) {
        switch (deviceType) {
        switch (deviceType) {
            case TYPE_UNKNOWN:
            case TYPE_UNKNOWN:
            case TYPE_REMOTE_TV:
            case TYPE_REMOTE_TV:
@@ -874,12 +945,14 @@ public abstract class InfoMediaManager {
            case TYPE_REMOTE_CAR:
            case TYPE_REMOTE_CAR:
            case TYPE_REMOTE_SMARTWATCH:
            case TYPE_REMOTE_SMARTWATCH:
            case TYPE_REMOTE_SMARTPHONE:
            case TYPE_REMOTE_SMARTPHONE:
                mediaDevice =
                return true;
                        new InfoMediaDevice(
            default:
                                mContext,
                return false;
                                route,
        }
                                mPreferenceItemMap.get(route.getId()));
    }
                break;

    private static boolean isPhoneMediaDevice(int deviceType) {
        switch (deviceType) {
            case TYPE_BUILTIN_SPEAKER:
            case TYPE_BUILTIN_SPEAKER:
            case TYPE_USB_DEVICE:
            case TYPE_USB_DEVICE:
            case TYPE_USB_HEADSET:
            case TYPE_USB_HEADSET:
@@ -893,51 +966,45 @@ public abstract class InfoMediaManager {
            case TYPE_AUX_LINE:
            case TYPE_AUX_LINE:
            case TYPE_WIRED_HEADSET:
            case TYPE_WIRED_HEADSET:
            case TYPE_WIRED_HEADPHONES:
            case TYPE_WIRED_HEADPHONES:
                mediaDevice =
                return true;
                        new PhoneMediaDevice(
            default:
                                mContext,
                return false;
                                route,
        }
                                mPreferenceItemMap.getOrDefault(route.getId(), null));
    }
                break;

    private static boolean isBluetoothMediaDevice(int deviceType) {
        switch (deviceType) {
            case TYPE_HEARING_AID:
            case TYPE_HEARING_AID:
            case TYPE_BLUETOOTH_A2DP:
            case TYPE_BLUETOOTH_A2DP:
            case TYPE_BLE_HEADSET:
            case TYPE_BLE_HEADSET:
                if (route.getAddress() == null) {
                return true;
                    Log.e(TAG, "Ignoring bluetooth route with no set address: " + route);
            default:
                    break;
                return false;
        }
        }
                final BluetoothDevice device =
                        BluetoothAdapter.getDefaultAdapter()
                                .getRemoteDevice(route.getAddress());
                final CachedBluetoothDevice cachedDevice =
                        mBluetoothManager.getCachedDeviceManager().findDevice(device);
                if (cachedDevice != null) {
                    mediaDevice =
                            new BluetoothMediaDevice(
                                    mContext,
                                    cachedDevice,
                                    route,
                                    mPreferenceItemMap.getOrDefault(route.getId(), null));
    }
    }
                break;

            case TYPE_REMOTE_AUDIO_VIDEO_RECEIVER:
    private static boolean isComplexMediaDevice(int deviceType) {
                mediaDevice =
        return deviceType == TYPE_REMOTE_AUDIO_VIDEO_RECEIVER;
                        new ComplexMediaDevice(
                                mContext,
                                route,
                                mPreferenceItemMap.get(route.getId()));
                break;
            default:
                Log.w(TAG, "addMediaDevice() unknown device type : " + deviceType);
                break;
    }
    }


        if (mediaDevice != null) {
    private static Drawable getDrawableForSuggestion(
            if (activeSession.getSelectedRoutes().contains(route.getId())) {
            Context context, SuggestedDeviceState suggestion) {
                mediaDevice.setState(STATE_SELECTED);
        if (suggestion.getConnectionState()
                == LocalMediaManager.MediaDeviceState.STATE_CONNECTING_FAILED) {
            return context.getDrawable(android.R.drawable.ic_info);
        }
        }
            mMediaDevices.add(mediaDevice);
        int deviceType = suggestion.getSuggestedDeviceInfo().getType();
        if (isInfoMediaDevice(deviceType)) {
            return context.getDrawable(InfoMediaDevice.getDrawableResIdByType(deviceType));
        }
        if (isPhoneMediaDevice(deviceType)) {
            return context.getDrawable(
                    new DeviceIconUtil(context).getIconResIdFromMediaRouteType(deviceType));
        }
        if (isBluetoothMediaDevice(deviceType)) {
            return ComplexMediaDevice.getIcon(context);
        }
        }
        return context.getDrawable(R.drawable.ic_media_speaker_device);
    }
    }


    @RequiresApi(34)
    @RequiresApi(34)
+8 −2
Original line number Original line Diff line number Diff line
@@ -62,6 +62,8 @@ public final class InputRouteManager {


    private final AudioManager mAudioManager;
    private final AudioManager mAudioManager;


    private final InfoMediaManager mInfoMediaManager;

    @VisibleForTesting final List<MediaDevice> mInputMediaDevices = new CopyOnWriteArrayList<>();
    @VisibleForTesting final List<MediaDevice> mInputMediaDevices = new CopyOnWriteArrayList<>();


    private @AudioDeviceType int mSelectedInputDeviceType;
    private @AudioDeviceType int mSelectedInputDeviceType;
@@ -107,9 +109,13 @@ public final class InputRouteManager {
                }
                }
            };
            };


    public InputRouteManager(@NonNull Context context, @NonNull AudioManager audioManager) {
    public InputRouteManager(
            @NonNull Context context,
            @NonNull AudioManager audioManager,
            @NonNull InfoMediaManager infoMediaManager) {
        mContext = context;
        mContext = context;
        mAudioManager = audioManager;
        mAudioManager = audioManager;
        mInfoMediaManager = infoMediaManager;
        Handler handler = new Handler(context.getMainLooper());
        Handler handler = new Handler(context.getMainLooper());


        mAudioManager.registerAudioDeviceCallback(mAudioDeviceCallback, handler);
        mAudioManager.registerAudioDeviceCallback(mAudioDeviceCallback, handler);
@@ -210,7 +216,7 @@ public final class InputRouteManager {
                            getProductNameFromAudioDeviceInfo(info));
                            getProductNameFromAudioDeviceInfo(info));
            if (mediaDevice != null) {
            if (mediaDevice != null) {
                if (info.getType() == mSelectedInputDeviceType) {
                if (info.getType() == mSelectedInputDeviceType) {
                    mediaDevice.setState(STATE_SELECTED);
                    mInfoMediaManager.setDeviceState(mediaDevice, STATE_SELECTED);
                }
                }
                mInputMediaDevices.add(mediaDevice);
                mInputMediaDevices.add(mediaDevice);
            }
            }
+112 −8
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@ import android.media.AudioDeviceAttributes;
import android.media.AudioManager;
import android.media.AudioManager;
import android.media.RoutingSessionInfo;
import android.media.RoutingSessionInfo;
import android.os.Build;
import android.os.Build;
import android.os.Handler;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.Log;
import android.util.Log;


@@ -35,6 +36,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.RequiresApi;


import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.BluetoothCallback;
@@ -44,12 +46,14 @@ import com.android.settingslib.bluetooth.HearingAidProfile;
import com.android.settingslib.bluetooth.LeAudioProfile;
import com.android.settingslib.bluetooth.LeAudioProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfile;
import com.android.settingslib.bluetooth.LocalBluetoothProfile;
import com.android.settingslib.media.InfoMediaManager.SuggestedDeviceState;


import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collection;
import java.util.List;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArrayList;


/**
/**
@@ -98,6 +102,13 @@ public class LocalMediaManager implements BluetoothCallback {
    @VisibleForTesting
    @VisibleForTesting
    DeviceAttributeChangeCallback mDeviceAttributeChangeCallback =
    DeviceAttributeChangeCallback mDeviceAttributeChangeCallback =
            new DeviceAttributeChangeCallback();
            new DeviceAttributeChangeCallback();

    @GuardedBy("mMediaDevicesLock")
    @Nullable
    ConnectingSuggestedDeviceState mConnectingSuggestedDeviceState;

    @VisibleForTesting Handler mConnectSuggestedDeviceHandler;

    @VisibleForTesting
    @VisibleForTesting
    BluetoothAdapter mBluetoothAdapter;
    BluetoothAdapter mBluetoothAdapter;


@@ -140,6 +151,7 @@ public class LocalMediaManager implements BluetoothCallback {
                LocalBluetoothManager.getInstance(context, /* onInitCallback= */ null);
                LocalBluetoothManager.getInstance(context, /* onInitCallback= */ null);
        mAudioManager = context.getSystemService(AudioManager.class);
        mAudioManager = context.getSystemService(AudioManager.class);
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        mConnectSuggestedDeviceHandler = new Handler(context.getMainLooper());
        if (mLocalBluetoothManager == null) {
        if (mLocalBluetoothManager == null) {
            Log.e(TAG, "Bluetooth is not supported on this device");
            Log.e(TAG, "Bluetooth is not supported on this device");
            return;
            return;
@@ -169,6 +181,7 @@ public class LocalMediaManager implements BluetoothCallback {
        mPackageName = packageName;
        mPackageName = packageName;
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        mAudioManager = context.getSystemService(AudioManager.class);
        mAudioManager = context.getSystemService(AudioManager.class);
        mConnectSuggestedDeviceHandler = new Handler(context.getMainLooper());
    }
    }


    /**
    /**
@@ -187,7 +200,7 @@ public class LocalMediaManager implements BluetoothCallback {
                    ((BluetoothMediaDevice) device).getCachedDevice();
                    ((BluetoothMediaDevice) device).getCachedDevice();
            if (!cachedDevice.isConnected() && !cachedDevice.isBusy()) {
            if (!cachedDevice.isConnected() && !cachedDevice.isBusy()) {
                mOnTransferBluetoothDevice = connectDevice;
                mOnTransferBluetoothDevice = connectDevice;
                device.setState(MediaDeviceState.STATE_CONNECTING);
                mInfoMediaManager.setDeviceState(device, MediaDeviceState.STATE_CONNECTING);
                cachedDevice.connect();
                cachedDevice.connect();
                return true;
                return true;
            }
            }
@@ -198,11 +211,53 @@ public class LocalMediaManager implements BluetoothCallback {
            return false;
            return false;
        }
        }


        device.setState(MediaDeviceState.STATE_CONNECTING);
        mInfoMediaManager.setDeviceState(device, MediaDeviceState.STATE_CONNECTING);
        mInfoMediaManager.connectToDevice(device);
        mInfoMediaManager.connectToDevice(device);
        return true;
        return true;
    }
    }


    /**
     * Connects to a suggested device. If the device is not already scanned, a scan will be started
     * to attempt to discover the device.
     *
     * @param suggestion the suggested device to connect to.
     */
    public void connectSuggestedDevice(SuggestedDeviceState suggestion) {
        synchronized (mMediaDevicesLock) {
            if (suggestion == null || mConnectingSuggestedDeviceState != null) {
                return;
            }
            SuggestedDeviceState currentSuggestion = mInfoMediaManager.getSuggestedDevice();
            if (!Objects.equals(suggestion, currentSuggestion)) {
                return;
            }
            for (MediaDevice device : mMediaDevices) {
                if (suggestion.getSuggestedDeviceInfo().getRouteId().equals(device.getId())) {
                    connectDevice(device);
                    return;
                }
            }
            mConnectingSuggestedDeviceState =
                    new ConnectingSuggestedDeviceState(
                            currentSuggestion, mConnectSuggestedDeviceHandler);
            mConnectingSuggestedDeviceState.tryConnect();
        }
    }

    private boolean connectToDeviceIfConnectionPending(MediaDevice device) {
        synchronized (mMediaDevicesLock) {
            if (mConnectingSuggestedDeviceState != null
                    && mConnectingSuggestedDeviceState
                            .mSuggestedDeviceState
                            .getSuggestedDeviceInfo()
                            .getRouteId()
                            .equals(device.getId())) {
                return connectDevice(device);
            }
            return false;
        }
    }

    void dispatchSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state) {
    void dispatchSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state) {
        for (DeviceCallback callback : getCallbacks()) {
        for (DeviceCallback callback : getCallbacks()) {
            callback.onSelectedDeviceStateChanged(device, state);
            callback.onSelectedDeviceStateChanged(device, state);
@@ -327,7 +382,7 @@ public class LocalMediaManager implements BluetoothCallback {
     * @return If add device successful return {@code true}, otherwise return {@code false}
     * @return If add device successful return {@code true}, otherwise return {@code false}
     */
     */
    public boolean addDeviceToPlayMedia(MediaDevice device) {
    public boolean addDeviceToPlayMedia(MediaDevice device) {
        device.setState(MediaDeviceState.STATE_GROUPING);
        mInfoMediaManager.setDeviceState(device, MediaDeviceState.STATE_GROUPING);
        return mInfoMediaManager.addDeviceToPlayMedia(device);
        return mInfoMediaManager.addDeviceToPlayMedia(device);
    }
    }


@@ -338,7 +393,7 @@ public class LocalMediaManager implements BluetoothCallback {
     * @return If device stop successful return {@code true}, otherwise return {@code false}
     * @return If device stop successful return {@code true}, otherwise return {@code false}
     */
     */
    public boolean removeDeviceFromPlayMedia(MediaDevice device) {
    public boolean removeDeviceFromPlayMedia(MediaDevice device) {
        device.setState(MediaDeviceState.STATE_GROUPING);
        mInfoMediaManager.setDeviceState(device, MediaDeviceState.STATE_GROUPING);
        return mInfoMediaManager.removeDeviceFromPlayMedia(device);
        return mInfoMediaManager.removeDeviceFromPlayMedia(device);
    }
    }


@@ -556,7 +611,8 @@ public class LocalMediaManager implements BluetoothCallback {
            dispatchDeviceListUpdate();
            dispatchDeviceListUpdate();
            if (mOnTransferBluetoothDevice != null && mOnTransferBluetoothDevice.isConnected()) {
            if (mOnTransferBluetoothDevice != null && mOnTransferBluetoothDevice.isConnected()) {
                connectDevice(mOnTransferBluetoothDevice);
                connectDevice(mOnTransferBluetoothDevice);
                mOnTransferBluetoothDevice.setState(MediaDeviceState.STATE_CONNECTED);
                mInfoMediaManager.setDeviceState(
                        mOnTransferBluetoothDevice, MediaDeviceState.STATE_CONNECTED);
                dispatchSelectedDeviceStateChanged(mOnTransferBluetoothDevice,
                dispatchSelectedDeviceStateChanged(mOnTransferBluetoothDevice,
                        MediaDeviceState.STATE_CONNECTED);
                        MediaDeviceState.STATE_CONNECTED);
                mOnTransferBluetoothDevice = null;
                mOnTransferBluetoothDevice = null;
@@ -671,7 +727,7 @@ public class LocalMediaManager implements BluetoothCallback {


            mCurrentConnectedDevice = connectDevice;
            mCurrentConnectedDevice = connectDevice;
            if (connectDevice != null) {
            if (connectDevice != null) {
                connectDevice.setState(MediaDeviceState.STATE_CONNECTED);
                mInfoMediaManager.setDeviceState(connectDevice, MediaDeviceState.STATE_CONNECTED);


                dispatchSelectedDeviceStateChanged(mCurrentConnectedDevice,
                dispatchSelectedDeviceStateChanged(mCurrentConnectedDevice,
                        MediaDeviceState.STATE_CONNECTED);
                        MediaDeviceState.STATE_CONNECTED);
@@ -683,7 +739,8 @@ public class LocalMediaManager implements BluetoothCallback {
            synchronized (mMediaDevicesLock) {
            synchronized (mMediaDevicesLock) {
                for (MediaDevice device : mMediaDevices) {
                for (MediaDevice device : mMediaDevices) {
                    if (device.getState() == MediaDeviceState.STATE_CONNECTING) {
                    if (device.getState() == MediaDeviceState.STATE_CONNECTING) {
                        device.setState(MediaDeviceState.STATE_CONNECTING_FAILED);
                        mInfoMediaManager.setDeviceState(
                                device, MediaDeviceState.STATE_CONNECTING_FAILED);
                    }
                    }
                }
                }
            }
            }
@@ -782,11 +839,58 @@ public class LocalMediaManager implements BluetoothCallback {
                    .isBusy()
                    .isBusy()
                    && !mOnTransferBluetoothDevice.isConnected()) {
                    && !mOnTransferBluetoothDevice.isConnected()) {
                // Failed to connect
                // Failed to connect
                mOnTransferBluetoothDevice.setState(MediaDeviceState.STATE_CONNECTING_FAILED);
                mInfoMediaManager.setDeviceState(
                        mOnTransferBluetoothDevice, MediaDeviceState.STATE_CONNECTING_FAILED);
                mOnTransferBluetoothDevice = null;
                mOnTransferBluetoothDevice = null;
                dispatchOnRequestFailed(REASON_UNKNOWN_ERROR);
                dispatchOnRequestFailed(REASON_UNKNOWN_ERROR);
            }
            }
            dispatchDeviceAttributesChanged();
            dispatchDeviceAttributesChanged();
        }
        }
    }
    }

    private class ConnectingSuggestedDeviceState {
        private static final int SCAN_DURATION_MS = 10000;

        @NonNull final SuggestedDeviceState mSuggestedDeviceState;
        @NonNull final Handler mConnectSuggestedDeviceHandler;
        @NonNull final DeviceCallback mDeviceCallback;
        @NonNull final Runnable mConnectionAttemptFinishedRunnable;

        ConnectingSuggestedDeviceState(SuggestedDeviceState suggestedDeviceState, Handler handler) {
            mSuggestedDeviceState = suggestedDeviceState;
            mConnectSuggestedDeviceHandler = handler;
            mDeviceCallback =
                    new DeviceCallback() {
                        @Override
                        public void onDeviceListUpdate(List<MediaDevice> mediaDevices) {
                            for (MediaDevice mediaDevice : mediaDevices) {
                                if (connectToDeviceIfConnectionPending(mediaDevice)) {
                                    mConnectSuggestedDeviceHandler.removeCallbacks(
                                            mConnectionAttemptFinishedRunnable);
                                    mConnectionAttemptFinishedRunnable.run();
                                    break;
                                }
                            }
                        }
                    };
            mConnectionAttemptFinishedRunnable =
                    new Runnable() {
                        @Override
                        public void run() {
                            synchronized (mMediaDevicesLock) {
                                mConnectingSuggestedDeviceState = null;
                            }
                            unregisterCallback(mDeviceCallback);
                            stopScan();
                        }
                    };
        }

        void tryConnect() {
            registerCallback(mDeviceCallback);
            startScan();
            mConnectSuggestedDeviceHandler.postDelayed(
                    mConnectionAttemptFinishedRunnable, SCAN_DURATION_MS);
        }
    }
}
}
Loading