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

Commit 88bc7eaf authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 12385180 from 63705494 to 24Q4-release

Change-Id: Ibc523114958b5bd20cac6275f15f9dc8f8e438bc
parents 729a51df 63705494
Loading
Loading
Loading
Loading
+35 −17
Original line number Diff line number Diff line
@@ -117,6 +117,8 @@ public class AudioRoute {
    public static final int TYPE_BLUETOOTH_HA = 6;
    public static final int TYPE_BLUETOOTH_LE = 7;
    public static final int TYPE_STREAMING = 8;
    // Used by auto
    public static final int TYPE_BUS = 9;
    @IntDef(prefix = "TYPE", value = {
            TYPE_INVALID,
            TYPE_EARPIECE,
@@ -126,7 +128,8 @@ public class AudioRoute {
            TYPE_BLUETOOTH_SCO,
            TYPE_BLUETOOTH_HA,
            TYPE_BLUETOOTH_LE,
            TYPE_STREAMING
            TYPE_STREAMING,
            TYPE_BUS
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface AudioRouteType {}
@@ -155,35 +158,38 @@ public class AudioRoute {
        DEVICE_TYPE_STRINGS.put(TYPE_WIRED, "TYPE_WIRED_HEADSET");
        DEVICE_TYPE_STRINGS.put(TYPE_SPEAKER, "TYPE_SPEAKER");
        DEVICE_TYPE_STRINGS.put(TYPE_DOCK, "TYPE_DOCK");
        DEVICE_TYPE_STRINGS.put(TYPE_BUS, "TYPE_BUS");
        DEVICE_TYPE_STRINGS.put(TYPE_BLUETOOTH_SCO, "TYPE_BLUETOOTH_SCO");
        DEVICE_TYPE_STRINGS.put(TYPE_BLUETOOTH_HA, "TYPE_BLUETOOTH_HA");
        DEVICE_TYPE_STRINGS.put(TYPE_BLUETOOTH_LE, "TYPE_BLUETOOTH_LE");
        DEVICE_TYPE_STRINGS.put(TYPE_STREAMING, "TYPE_STREAMING");
    }

    public static final HashMap<Integer, Integer> DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE;
    public static final HashMap<Integer, Integer> DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE;
    static {
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE = new HashMap<>();
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE,
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE = new HashMap<>();
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE,
                TYPE_EARPIECE);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, TYPE_SPEAKER);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_WIRED_HEADSET, TYPE_WIRED);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_WIRED_HEADPHONES, TYPE_WIRED);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
                TYPE_SPEAKER);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_WIRED_HEADSET, TYPE_WIRED);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_WIRED_HEADPHONES, TYPE_WIRED);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
                TYPE_BLUETOOTH_SCO);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_USB_DEVICE, TYPE_WIRED);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_USB_ACCESSORY, TYPE_WIRED);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_DOCK, TYPE_DOCK);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_USB_HEADSET, TYPE_WIRED);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_HEARING_AID,
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_USB_DEVICE, TYPE_WIRED);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_USB_ACCESSORY, TYPE_WIRED);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_DOCK, TYPE_DOCK);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_USB_HEADSET, TYPE_WIRED);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_HEARING_AID,
                TYPE_BLUETOOTH_HA);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BLE_HEADSET,
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BLE_HEADSET,
                TYPE_BLUETOOTH_LE);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BLE_SPEAKER,
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BLE_SPEAKER,
                TYPE_BLUETOOTH_LE);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BLE_BROADCAST,
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BLE_BROADCAST,
                TYPE_BLUETOOTH_LE);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_DOCK_ANALOG, TYPE_DOCK);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_DOCK_ANALOG, TYPE_DOCK);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BUS, TYPE_BUS);
    }

    private static final HashMap<Integer, List<Integer>> AUDIO_ROUTE_TYPE_TO_DEVICE_INFO_TYPE;
@@ -210,6 +216,10 @@ public class AudioRoute {
        dockDeviceInfoTypes.add(AudioDeviceInfo.TYPE_DOCK_ANALOG);
        AUDIO_ROUTE_TYPE_TO_DEVICE_INFO_TYPE.put(TYPE_DOCK, dockDeviceInfoTypes);

        List<Integer> busDeviceInfoTypes = new ArrayList<>();
        busDeviceInfoTypes.add(AudioDeviceInfo.TYPE_BUS);
        AUDIO_ROUTE_TYPE_TO_DEVICE_INFO_TYPE.put(TYPE_BUS, busDeviceInfoTypes);

        List<Integer> bluetoothScoDeviceInfoTypes = new ArrayList<>();
        bluetoothScoDeviceInfoTypes.add(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP);
        bluetoothScoDeviceInfoTypes.add(AudioDeviceInfo.TYPE_BLUETOOTH_SCO);
@@ -241,6 +251,10 @@ public class AudioRoute {
            BluetoothRouteManager bluetoothRouteManager, boolean isScoAudioConnected) {
        Log.i(this, "onDestRouteAsPendingRoute: active (%b), type (%s)", active,
                DEVICE_TYPE_STRINGS.get(mAudioRouteType));
        if (mAudioRouteType == TYPE_BUS) {
            Log.i(this, "onDestRouteAsPendingRoute: Ignore processing dest route for TYPE_BUS");
            return;
        }
        if (pendingAudioRoute.isActive() && !active) {
            clearCommunicationDevice(pendingAudioRoute, bluetoothRouteManager, audioManager);
        } else if (active) {
@@ -302,6 +316,10 @@ public class AudioRoute {
    void onOrigRouteAsPendingRoute(boolean active, PendingAudioRoute pendingAudioRoute,
            AudioManager audioManager, BluetoothRouteManager bluetoothRouteManager) {
        Log.i(this, "onOrigRouteAsPendingRoute: active (%b), type (%d)", active, mAudioRouteType);
        if (mAudioRouteType == TYPE_BUS) {
            Log.i(this, "onOrigRouteAsPendingRoute: Ignore processing dest route for TYPE_BUS");
            return;
        }
        if (active) {
            if (mAudioRouteType == TYPE_SPEAKER) {
                pendingAudioRoute.addMessage(SPEAKER_OFF, null);
+87 −40
Original line number Diff line number Diff line
@@ -63,7 +63,6 @@ import java.util.Objects;
import java.util.Set;

public class CallAudioRouteController implements CallAudioRouteAdapter {
    private static final long TIMEOUT_LIMIT = 2000L;
    private static final AudioRoute DUMMY_ROUTE = new AudioRoute(TYPE_INVALID, null, null);
    private static final Map<Integer, Integer> ROUTE_MAP;
    static {
@@ -73,6 +72,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
        ROUTE_MAP.put(AudioRoute.TYPE_WIRED, CallAudioState.ROUTE_WIRED_HEADSET);
        ROUTE_MAP.put(AudioRoute.TYPE_SPEAKER, CallAudioState.ROUTE_SPEAKER);
        ROUTE_MAP.put(AudioRoute.TYPE_DOCK, CallAudioState.ROUTE_SPEAKER);
        ROUTE_MAP.put(AudioRoute.TYPE_BUS, CallAudioState.ROUTE_SPEAKER);
        ROUTE_MAP.put(AudioRoute.TYPE_BLUETOOTH_SCO, CallAudioState.ROUTE_BLUETOOTH);
        ROUTE_MAP.put(AudioRoute.TYPE_BLUETOOTH_HA, CallAudioState.ROUTE_BLUETOOTH);
        ROUTE_MAP.put(AudioRoute.TYPE_BLUETOOTH_LE, CallAudioState.ROUTE_BLUETOOTH);
@@ -109,6 +109,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
    private int mFocusType;
    private int mCallSupportedRouteMask = -1;
    private boolean mIsScoAudioConnected;
    private boolean mAvailableRoutesUpdated;
    private final Object mLock = new Object();
    private final TelecomSystem.SyncRoot mTelecomLock;
    private final BroadcastReceiver mSpeakerPhoneChangeReceiver = new BroadcastReceiver() {
@@ -352,14 +353,22 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {

        int supportMask = calculateSupportedRouteMaskInit();
        if ((supportMask & CallAudioState.ROUTE_SPEAKER) != 0) {
            int audioRouteType = AudioRoute.TYPE_SPEAKER;
            // Create speaker routes
            mSpeakerDockRoute = mAudioRouteFactory.create(AudioRoute.TYPE_SPEAKER, null,
                    mAudioManager);
            // Todo(b/364562758): Represent TYPE_BUS as CallAudioState.ROUTE_SPEAKER (moving
            // forward, we may rework this if audio fwk team decides to allow list this as a
            // valid communication device.
            if (mSpeakerDockRoute != null || hasBusAudioDevice()) {
                if (mSpeakerDockRoute == null){
                Log.w(this, "Can't find available audio device info for route TYPE_SPEAKER");
                    mSpeakerDockRoute = new AudioRoute(AudioRoute.TYPE_BUS, null, null);
                    audioRouteType = AudioRoute.TYPE_BUS;
                }
                mTypeRoutes.put(audioRouteType, mSpeakerDockRoute);
                updateAvailableRoutes(mSpeakerDockRoute, true);
            } else {
                mTypeRoutes.put(AudioRoute.TYPE_SPEAKER, mSpeakerDockRoute);
                mAvailableRoutes.add(mSpeakerDockRoute);
                Log.w(this, "Can't find available audio device info for route TYPE_SPEAKER");
            }
        }

@@ -371,7 +380,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
                Log.w(this, "Can't find available audio device info for route TYPE_WIRED_HEADSET");
            } else {
                mTypeRoutes.put(AudioRoute.TYPE_WIRED, mEarpieceWiredRoute);
                mAvailableRoutes.add(mEarpieceWiredRoute);
                updateAvailableRoutes(mEarpieceWiredRoute, true);
            }
        } else if ((supportMask & CallAudioState.ROUTE_EARPIECE) != 0) {
            // Create earpiece routes
@@ -381,7 +390,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
                Log.w(this, "Can't find available audio device info for route TYPE_EARPIECE");
            } else {
                mTypeRoutes.put(AudioRoute.TYPE_EARPIECE, mEarpieceWiredRoute);
                mAvailableRoutes.add(mEarpieceWiredRoute);
                updateAvailableRoutes(mEarpieceWiredRoute, true);
            }
        }

@@ -546,8 +555,8 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
        }

        if (wiredHeadsetRoute != null) {
            mAvailableRoutes.add(wiredHeadsetRoute);
            mAvailableRoutes.remove(mEarpieceWiredRoute);
            updateAvailableRoutes(wiredHeadsetRoute, true);
            updateAvailableRoutes(mEarpieceWiredRoute, false);
            mTypeRoutes.put(AudioRoute.TYPE_WIRED, wiredHeadsetRoute);
            mEarpieceWiredRoute = wiredHeadsetRoute;
            routeTo(mIsActive, wiredHeadsetRoute);
@@ -559,12 +568,12 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
        // Update audio route states
        AudioRoute wiredHeadsetRoute = mTypeRoutes.remove(AudioRoute.TYPE_WIRED);
        if (wiredHeadsetRoute != null) {
            mAvailableRoutes.remove(wiredHeadsetRoute);
            updateAvailableRoutes(wiredHeadsetRoute, false);
            mEarpieceWiredRoute = null;
        }
        AudioRoute earpieceRoute = mTypeRoutes.get(AudioRoute.TYPE_EARPIECE);
        if (earpieceRoute != null) {
            mAvailableRoutes.add(earpieceRoute);
            updateAvailableRoutes(earpieceRoute, true);
            mEarpieceWiredRoute = earpieceRoute;
        }
        onAvailableRoutesChanged();
@@ -585,8 +594,8 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
        }

        if (dockRoute != null) {
            mAvailableRoutes.add(dockRoute);
            mAvailableRoutes.remove(mSpeakerDockRoute);
            updateAvailableRoutes(dockRoute, true);
            updateAvailableRoutes(mSpeakerDockRoute, false);
            mTypeRoutes.put(AudioRoute.TYPE_DOCK, dockRoute);
            mSpeakerDockRoute = dockRoute;
            routeTo(mIsActive, dockRoute);
@@ -598,12 +607,12 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
        // Update audio route states
        AudioRoute dockRoute = mTypeRoutes.get(AudioRoute.TYPE_DOCK);
        if (dockRoute != null) {
            mAvailableRoutes.remove(dockRoute);
            updateAvailableRoutes(dockRoute, false);
            mSpeakerDockRoute = null;
        }
        AudioRoute speakerRoute = mTypeRoutes.get(AudioRoute.TYPE_SPEAKER);
        if (speakerRoute != null) {
            mAvailableRoutes.add(speakerRoute);
            updateAvailableRoutes(speakerRoute, true);
            mSpeakerDockRoute = speakerRoute;
        }
        onAvailableRoutesChanged();
@@ -691,7 +700,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
                    + AudioRoute.DEVICE_TYPE_STRINGS.get(type));
        } else {
            Log.i(this, "bluetooth route added: " + bluetoothRoute);
            mAvailableRoutes.add(bluetoothRoute);
            updateAvailableRoutes(bluetoothRoute, true);
            mBluetoothRoutes.put(bluetoothRoute, bluetoothDevice);
            onAvailableRoutesChanged();
        }
@@ -712,7 +721,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
        if (bluetoothRoute != null) {
            Log.i(this, "bluetooth route removed: " + bluetoothRoute);
            mBluetoothRoutes.remove(bluetoothRoute);
            mAvailableRoutes.remove(bluetoothRoute);
            updateAvailableRoutes(bluetoothRoute, false);
            onAvailableRoutesChanged();
        }

@@ -811,7 +820,8 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
                    Log.i(this, "handleSwitchFocus (ACTIVE_FOCUS): mBluetoothAddressForRinging = "
                            + "%s, mCurrentRoute = %s", mBluetoothAddressForRinging, mCurrentRoute);
                    AudioRoute audioRoute = mBluetoothAddressForRinging != null
                        && mBluetoothAddressForRinging.equals(mCurrentRoute.getBluetoothAddress())
                            && mBluetoothAddressForRinging.equals(
                                    mCurrentRoute.getBluetoothAddress())
                            ? mCurrentRoute
                            : getBaseRoute(true, null);
                    routeTo(true, audioRoute);
@@ -903,7 +913,8 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
    }

    private void handleSwitchSpeaker() {
        if (mSpeakerDockRoute != null && getCallSupportedRoutes().contains(mSpeakerDockRoute)) {
        if (mSpeakerDockRoute != null && getCallSupportedRoutes().contains(mSpeakerDockRoute)
                && mSpeakerDockRoute.getType() == AudioRoute.TYPE_SPEAKER) {
            routeTo(mIsActive, mSpeakerDockRoute);
        } else {
            Log.i(this, "ignore switch speaker request");
@@ -921,8 +932,8 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
            // Update status bar notification if we are in a call.
            mStatusBarNotifier.notifySpeakerphone(mCallsManager.hasAnyCalls());
        } else {
            if (mSpeakerDockRoute != null && getCallSupportedRoutes()
                    .contains(mSpeakerDockRoute)) {
            if (mSpeakerDockRoute != null && getCallSupportedRoutes().contains(mSpeakerDockRoute)
                    && mSpeakerDockRoute.getType() == AudioRoute.TYPE_SPEAKER) {
                routeTo(mIsActive, mSpeakerDockRoute);
                // Since the route switching triggered by this message, we need to manually send it
                // again so that we won't stuck in the pending route
@@ -1042,6 +1053,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
    private boolean updateCallSupportedAudioRoutes() {
        int availableRouteMask = 0;
        Call foregroundCall = mCallsManager.getForegroundCall();
        mCallSupportedRoutes.clear();
        if (foregroundCall != null) {
            int foregroundCallSupportedRouteMask = foregroundCall.getSupportedAudioRoutes();
            for (AudioRoute route : getAvailableRoutes()) {
@@ -1054,7 +1066,6 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
            mCallSupportedRouteMask = availableRouteMask & foregroundCallSupportedRouteMask;
            return true;
        } else {
            mCallSupportedRoutes.clear();
            mCallSupportedRouteMask = -1;
            return false;
        }
@@ -1082,6 +1093,24 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
    }

    private AudioRoute getPreferredAudioRouteFromStrategy() {
        // Get preferred device
        AudioDeviceAttributes deviceAttr = getPreferredDeviceForStrategy();
        Log.i(this, "getPreferredAudioRouteFromStrategy: preferred device is %s", deviceAttr);
        if (deviceAttr == null) {
            return null;
        }

        // Get corresponding audio route
        @AudioRoute.AudioRouteType int type = AudioRoute.DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.get(
                deviceAttr.getType());
        if (BT_AUDIO_ROUTE_TYPES.contains(type)) {
            return getBluetoothRoute(type, deviceAttr.getAddress());
        } else {
            return mTypeRoutes.get(type);
        }
    }

    private AudioDeviceAttributes getPreferredDeviceForStrategy() {
        // Get audio produce strategy
        AudioProductStrategy strategy = null;
        final AudioAttributes attr = new AudioAttributes.Builder()
@@ -1097,21 +1126,26 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
            return null;
        }

        // Get preferred device
        AudioDeviceAttributes deviceAttr = mAudioManager.getPreferredDeviceForStrategy(strategy);
        Log.i(this, "getPreferredAudioRouteFromStrategy: preferred device is %s", deviceAttr);
        if (deviceAttr == null) {
            return null;
        return mAudioManager.getPreferredDeviceForStrategy(strategy);
    }

        // Get corresponding audio route
        @AudioRoute.AudioRouteType int type = AudioRoute.DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.get(
                deviceAttr.getType());
        if (BT_AUDIO_ROUTE_TYPES.contains(type)) {
            return getBluetoothRoute(type, deviceAttr.getAddress());
        } else {
            return mTypeRoutes.get(type);
    /**
     * For auto, there is no earpiece or speakerphone routes available. The audio is routed to the
     * bus but because this isn't a valid communication device,
     * {@link AudioManager#getCommunicationDevice()} will not provide this device even if audio fwk
     * reports it as the active communication device (refer to
     * AudioDeviceBroker#getCommunicationDeviceInt()}. Check if the device is the preferred device
     * for strategy instead.
     */
    private boolean hasBusAudioDevice() {
        AudioDeviceAttributes deviceAttr = getPreferredDeviceForStrategy();
        if (deviceAttr == null) {
            return false;
        }
        // Get corresponding audio route mapping
        @AudioRoute.AudioRouteType int type = AudioRoute.DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.get(
                deviceAttr.getType());
        return type == AudioRoute.TYPE_BUS;
    }

    private AudioRoute getPreferredAudioRouteFromDefault(boolean includeBluetooth,
@@ -1193,6 +1227,10 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
        if (mCurrentRoute.equals(mStreamingRoute)) {
            return mStreamingRoutes;
        } else {
            if (mAvailableRoutesUpdated) {
                updateCallSupportedAudioRoutes();
                mAvailableRoutesUpdated = false;
            }
            return mCallSupportedRoutes.isEmpty() ? mAvailableRoutes : mCallSupportedRoutes;
        }
    }
@@ -1420,6 +1458,15 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
        }
    }

    private void updateAvailableRoutes(AudioRoute route, boolean includeRoute) {
        if (includeRoute) {
            mAvailableRoutes.add(route);
        } else {
            mAvailableRoutes.remove(route);
        }
        mAvailableRoutesUpdated = true;
    }

    @VisibleForTesting
    public void setActive(boolean active) {
        if (active) {
+48 −16
Original line number Diff line number Diff line
@@ -1571,8 +1571,22 @@ public class InCallController extends CallsManagerListenerBase implements
                    }
                    UserHandle userHandle = getUserFromCall(call);
                    if (mBTInCallServiceConnections.containsKey(userHandle)) {
                        Log.i(this, "onDisconnectedTonePlaying: Unbinding BT service");
                        mBTInCallServiceConnections.get(userHandle).disconnect();
                        Log.i(this, "onDisconnectedTonePlaying: Schedule unbind BT service");
                        final InCallServiceConnection connection =
                                mBTInCallServiceConnections.get(userHandle);

                        // Similar to in onCallRemoved when we unbind from the other ICS, we need to
                        // delay unbinding from the BT ICS because we need to give the ICS a
                        // moment to finish the onCallRemoved signal it got just prior.
                        mHandler.postDelayed(new Runnable("ICC.oDCTP", mLock) {
                            @Override
                            public void loggedRun() {
                                Log.i(this, "onDisconnectedTonePlaying: unbinding");
                                connection.disconnect();
                            }
                        }.prepare(), mTimeoutsAdapter.getCallRemoveUnbindInCallServicesDelay(
                                mContext.getContentResolver()));

                        mBTInCallServiceConnections.remove(userHandle);
                    }
                    // Ensure that BT ICS instance is cleaned up
@@ -2743,21 +2757,39 @@ public class InCallController extends CallsManagerListenerBase implements
                        info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI ||
                        info.getType() == IN_CALL_SERVICE_TYPE_NON_UI);
                IInCallService inCallService = entry.getValue();
                componentsUpdated.add(componentName);

                if (info.getType() == IN_CALL_SERVICE_TYPE_BLUETOOTH
                        && call.getState() == CallState.DISCONNECTED
                        && !mDisconnectedToneBtFutures.containsKey(call.getId())) {
                    CompletableFuture<Void> disconnectedToneFuture = new CompletableFuture<Void>()
                boolean isDisconnectingBtIcs = info.getType() == IN_CALL_SERVICE_TYPE_BLUETOOTH
                        && call.getState() == CallState.DISCONNECTED;

                if (isDisconnectingBtIcs) {
                    // If this is the first we heard about the disconnect for the BT ICS, then we
                    // will setup a future to notify the disconnet later.
                    if (!mDisconnectedToneBtFutures.containsKey(call.getId())) {
                        // Create the base future with timeout, we will chain more operations on to
                        // this.
                        CompletableFuture<Void> disconnectedToneFuture =
                                new CompletableFuture<Void>()
                                        .completeOnTimeout(null, DISCONNECTED_TONE_TIMEOUT,
                                                TimeUnit.MILLISECONDS);
                    mDisconnectedToneBtFutures.put(call.getId(), disconnectedToneFuture);
                    mDisconnectedToneBtFutures.get(call.getId()).thenRunAsync(() -> {
                        Log.i(this, "updateCall: Sending call disconnected update to BT ICS.");
                        // Note: DO NOT chain async work onto this future; using thenRun ensures
                        // when disconnectedToneFuture is completed that the chained work is run
                        // synchronously.
                        disconnectedToneFuture.thenRun(() -> {
                            Log.i(this,
                                    "updateCall: (deferred) Sending call disconnected update "
                                            + "to BT ICS.");
                            updateCallToIcs(inCallService, info, parcelableCall, componentName);
                            mDisconnectedToneBtFutures.remove(call.getId());
                    }, new LoggedHandlerExecutor(mHandler, "ICC.uC", mLock));
                        });
                        mDisconnectedToneBtFutures.put(call.getId(), disconnectedToneFuture);
                    } else {
                        // If we have already cached a disconnect signal for the BT ICS, don't sent
                        // any other updates (ie due to extras or whatnot) to the BT ICS.  If we do
                        // then it will hear about the disconnect in advance and not play the call
                        // end tone.
                        Log.i(this, "updateCall: skip update for disconnected call to BT ICS");
                    }
                } else {
                    componentsUpdated.add(componentName);
                    updateCallToIcs(inCallService, info, parcelableCall, componentName);
                }
            }
+31 −2

File changed.

Preview size limit exceeded, changes collapsed.