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

Commit 0cfb40f2 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "AudioService: fix disconnect/connect of A2DP device"

parents 165f56a0 dc552e9d
Loading
Loading
Loading
Loading
+72 −42
Original line number Diff line number Diff line
@@ -15,9 +15,6 @@
 */
package com.android.server.audio;

import static com.android.server.audio.AudioService.CONNECTION_STATE_CONNECTED;
import static com.android.server.audio.AudioService.CONNECTION_STATE_DISCONNECTED;

import android.annotation.NonNull;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothDevice;
@@ -95,13 +92,28 @@ import java.io.PrintWriter;
    /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service) {
        mContext = context;
        mAudioService = service;
        setupMessaging(context);
        mBtHelper = new BtHelper(this);
        mDeviceInventory = new AudioDeviceInventory(this);

        init();
    }

    /** for test purposes only, inject AudioDeviceInventory */
    AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service,
                      @NonNull AudioDeviceInventory mockDeviceInventory) {
        mContext = context;
        mAudioService = service;
        mBtHelper = new BtHelper(this);
        mDeviceInventory = mockDeviceInventory;

        init();
    }

    private void init() {
        setupMessaging(mContext);

        mForcedUseForComm = AudioSystem.FORCE_NONE;
        mForcedUseForCommExt = mForcedUseForComm;

    }

    /*package*/ Context getContext() {
@@ -232,17 +244,42 @@ import java.io.PrintWriter;
            mSupprNoisy = suppressNoisyIntent;
            mVolume = vol;
        }

        // redefine equality op so we can match messages intended for this device
        @Override
        public boolean equals(Object o) {
            return mDevice.equals(o);
        }
    }


    /*package*/ void postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
            @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
            int profile, boolean suppressNoisyIntent, int a2dpVolume) {
        final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile,
                suppressNoisyIntent, a2dpVolume);

        // TODO add a check to try to remove unprocessed messages for the same device (the old
        //      check didn't work), and  make sure it doesn't conflict with config change message
        sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
        // when receiving a request to change the connection state of a device, this last request
        // is the source of truth, so cancel all previous requests
        removeAllA2dpConnectionEvents(device);

        sendLMsgNoDelay(
                state == BluetoothProfile.STATE_CONNECTED
                        ? MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION
                        : MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION,
                SENDMSG_QUEUE, info);
    }

    /** remove all previously scheduled connection and disconnection events for the given device */
    private void removeAllA2dpConnectionEvents(@NonNull BluetoothDevice device) {
        mBrokerHandler.removeMessages(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION,
                device);
        mBrokerHandler.removeMessages(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION,
                device);
        mBrokerHandler.removeMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED,
                device);
        mBrokerHandler.removeMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED,
                device);
    }

    private static final class HearingAidDeviceConnectionInfo {
@@ -430,13 +467,16 @@ import java.io.PrintWriter;
        sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE);
    }

    /*package*/ void postA2dpSinkConnection(int state,
    /*package*/ void postA2dpSinkConnection(@AudioService.BtProfileConnectionState int state,
            @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) {
        sendILMsg(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE, SENDMSG_QUEUE,
        sendILMsg(state == BluetoothA2dp.STATE_CONNECTED
                        ? MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED
                        : MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED,
                SENDMSG_QUEUE,
                state, btDeviceInfo, delay);
    }

    /*package*/ void postA2dpSourceConnection(int state,
    /*package*/ void postA2dpSourceConnection(@AudioService.BtProfileConnectionState int state,
            @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) {
        sendILMsg(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE,
                state, btDeviceInfo, delay);
@@ -522,25 +562,6 @@ import java.io.PrintWriter;
        }
    }

    @GuardedBy("mDeviceStateLock")
    /*package*/ void handleSetA2dpSinkConnectionState(@BluetoothProfile.BtProfileState int state,
                @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
        final int intState = (state == BluetoothA2dp.STATE_CONNECTED)
                ? CONNECTION_STATE_CONNECTED : CONNECTION_STATE_DISCONNECTED;
        final int delay = mDeviceInventory.checkSendBecomingNoisyIntent(
                    AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, intState,
                    AudioSystem.DEVICE_NONE);
        final String addr = btDeviceInfo == null ? "null" : btDeviceInfo.getBtDevice().getAddress();

        if (AudioService.DEBUG_DEVICES) {
            Log.d(TAG, "handleSetA2dpSinkConnectionState btDevice= " + btDeviceInfo
                    + " state= " + state
                    + " is dock: " + btDeviceInfo.getBtDevice().isBluetoothDock());
        }
        sendILMsg(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE, SENDMSG_QUEUE,
                state, btDeviceInfo, delay);
    }

    /*package*/ void postSetA2dpSourceConnectionState(@BluetoothProfile.BtProfileState int state,
            @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
        final int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0;
@@ -575,8 +596,10 @@ import java.io.PrintWriter;

    // must be called synchronized on mConnectedDevices
    /*package*/ boolean hasScheduledA2dpSinkConnectionState(BluetoothDevice btDevice) {
        return mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE,
                new BtHelper.BluetoothA2dpDeviceInfo(btDevice));
        return (mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED,
                        new BtHelper.BluetoothA2dpDeviceInfo(btDevice))
                || mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED,
                        new BtHelper.BluetoothA2dpDeviceInfo(btDevice)));
    }

    /*package*/ void setA2dpDockTimeout(String address, int a2dpCodec, int delayMs) {
@@ -711,7 +734,8 @@ import java.io.PrintWriter;
                        mDeviceInventory.onReportNewRoutes();
                    }
                    break;
                case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE:
                case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED:
                case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED:
                    synchronized (mDeviceStateLock) {
                        mDeviceInventory.onSetA2dpSinkConnectionState(
                                (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1);
@@ -836,7 +860,8 @@ import java.io.PrintWriter;
                        }
                    }
                    break;
                case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT: {
                case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION:
                case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION: {
                    final BtDeviceConnectionInfo info = (BtDeviceConnectionInfo) msg.obj;
                    AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
                            "setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent "
@@ -887,7 +912,7 @@ import java.io.PrintWriter;
    private static final int MSG_I_BROADCAST_BT_CONNECTION_STATE = 3;
    private static final int MSG_IIL_SET_FORCE_USE = 4;
    private static final int MSG_IIL_SET_FORCE_BT_A2DP_USE = 5;
    private static final int MSG_IL_SET_A2DP_SINK_CONNECTION_STATE = 6;
    private static final int MSG_TOGGLE_HDMI = 6;
    private static final int MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE = 7;
    private static final int MSG_IL_SET_HEARING_AID_CONNECTION_STATE = 8;
    private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
@@ -898,7 +923,6 @@ import java.io.PrintWriter;
    private static final int MSG_II_SET_HEARING_AID_VOLUME = 14;
    private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15;
    private static final int MSG_I_DISCONNECT_BT_SCO = 16;
    private static final int MSG_TOGGLE_HDMI = 17;
    private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE = 18;
    private static final int MSG_DISCONNECT_A2DP = 19;
    private static final int MSG_DISCONNECT_A2DP_SINK = 20;
@@ -908,25 +932,30 @@ import java.io.PrintWriter;
    private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK = 24;
    private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID = 25;
    private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET = 26;
    private static final int MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED = 27;
    private static final int MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED = 28;
    // process external command to (dis)connect an A2DP device
    private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 27;
    private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION = 29;
    private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION = 30;
    // process external command to (dis)connect a hearing aid device
    private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 28;
    private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 31;
    // a ScoClient died in BtHelper
    private static final int MSG_L_SCOCLIENT_DIED = 29;
    private static final int MSG_L_SCOCLIENT_DIED = 32;


    private static boolean isMessageHandledUnderWakelock(int msgId) {
        switch(msgId) {
            case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
            case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE:
            case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED:
            case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED:
            case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE:
            case MSG_IL_SET_HEARING_AID_CONNECTION_STATE:
            case MSG_IL_BTA2DP_DOCK_TIMEOUT:
            case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
            case MSG_TOGGLE_HDMI:
            case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
            case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
            case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION:
            case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION:
            case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
                return true;
            default:
@@ -1007,7 +1036,8 @@ import java.io.PrintWriter;

            switch (msg) {
                case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE:
                case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE:
                case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED:
                case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED:
                case MSG_IL_SET_HEARING_AID_CONNECTION_STATE:
                case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
                case MSG_IL_BTA2DP_DOCK_TIMEOUT:
+70 −26
Original line number Diff line number Diff line
@@ -41,14 +41,16 @@ import android.util.Log;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;

/**
 * Class to manage the inventory of all connected devices.
 * This class is thread-safe.
 * (non final for mocking/spying)
 */
public final class AudioDeviceInventory {
public class AudioDeviceInventory {

    private static final String TAG = "AS.AudioDeviceInventory";

@@ -56,11 +58,7 @@ public final class AudioDeviceInventory {
    // Key for map created from DeviceInfo.makeDeviceListKey()
    private final ArrayMap<String, DeviceInfo> mConnectedDevices = new ArrayMap<>();

    private final @NonNull AudioDeviceBroker mDeviceBroker;

    AudioDeviceInventory(@NonNull AudioDeviceBroker broker) {
        mDeviceBroker = broker;
    }
    private @NonNull AudioDeviceBroker mDeviceBroker;

    // cache of the address of the last dock the device was connected to
    private String mDockAddress;
@@ -70,6 +68,20 @@ public final class AudioDeviceInventory {
    final RemoteCallbackList<IAudioRoutesObserver> mRoutesObservers =
            new RemoteCallbackList<IAudioRoutesObserver>();

    /*package*/ AudioDeviceInventory(@NonNull AudioDeviceBroker broker) {
        mDeviceBroker = broker;
    }

    //-----------------------------------------------------------
    /** for mocking only */
    /*package*/ AudioDeviceInventory() {
        mDeviceBroker = null;
    }

    /*package*/ void setDeviceBroker(@NonNull AudioDeviceBroker broker) {
        mDeviceBroker = broker;
    }

    //------------------------------------------------------------
    /**
     * Class to store info about connected devices.
@@ -146,8 +158,10 @@ public final class AudioDeviceInventory {
        }
    }

    // only public for mocking/spying
    @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
    /*package*/ void onSetA2dpSinkConnectionState(@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo,
    @VisibleForTesting
    public void onSetA2dpSinkConnectionState(@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo,
            @AudioService.BtProfileConnectionState int state) {
        final BluetoothDevice btDevice = btInfo.getBtDevice();
        int a2dpVolume = btInfo.getVolume();
@@ -159,19 +173,28 @@ public final class AudioDeviceInventory {
        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
            address = "";
        }

        final int a2dpCodec = btInfo.getCodec();

        AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
                "A2DP sink connected: device addr=" + address + " state=" + state
                        + " codec=" + a2dpCodec
                        + " vol=" + a2dpVolume));

        final int a2dpCodec = btInfo.getCodec();

        synchronized (mConnectedDevices) {
            final String key = DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
                    btDevice.getAddress());
            final DeviceInfo di = mConnectedDevices.get(key);
            boolean isConnected = di != null;

            if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
            if (isConnected) {
                if (state == BluetoothProfile.STATE_CONNECTED) {
                    // device is already connected, but we are receiving a connection again,
                    // it could be for a codec change
                    if (a2dpCodec != di.mDeviceCodecFormat) {
                        mDeviceBroker.postBluetoothA2dpDeviceConfigChange(btDevice);
                    }
                } else {
                    if (btDevice.isBluetoothDock()) {
                        if (state == BluetoothProfile.STATE_DISCONNECTED) {
                            // introduction of a delay for transient disconnections of docks when
@@ -184,6 +207,7 @@ public final class AudioDeviceInventory {
                    } else {
                        makeA2dpDeviceUnavailableNow(address, di.mDeviceCodecFormat);
                    }
                }
            } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
                if (btDevice.isBluetoothDock()) {
                    // this could be a reconnection after a transient disconnection
@@ -282,11 +306,9 @@ public final class AudioDeviceInventory {
                    + " event=" + BtHelper.a2dpDeviceEventToString(event)));

        synchronized (mConnectedDevices) {
            //TODO original CL is not consistent between BluetoothDevice and BluetoothA2dpDeviceInfo
            // for this type of message
            if (mDeviceBroker.hasScheduledA2dpSinkConnectionState(btDevice)) {
                AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
                        "A2dp config change ignored"));
                        "A2dp config change ignored (scheduled connection change)"));
                return;
            }
            final String key = DeviceInfo.makeDeviceListKey(
@@ -534,8 +556,10 @@ public final class AudioDeviceInventory {
        return mCurAudioRoutes;
    }

    // only public for mocking/spying
    @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
    /*package*/ void setBluetoothA2dpDeviceConnectionState(
    @VisibleForTesting
    public void setBluetoothA2dpDeviceConnectionState(
            @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
            int profile, boolean suppressNoisyIntent, int musicDevice, int a2dpVolume) {
        int delay;
@@ -544,9 +568,12 @@ public final class AudioDeviceInventory {
        }
        synchronized (mConnectedDevices) {
            if (profile == BluetoothProfile.A2DP && !suppressNoisyIntent) {
                int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0;
                @AudioService.ConnectionState int asState =
                        (state == BluetoothA2dp.STATE_CONNECTED)
                                ? AudioService.CONNECTION_STATE_CONNECTED
                                : AudioService.CONNECTION_STATE_DISCONNECTED;
                delay = checkSendBecomingNoisyIntentInt(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
                        intState, musicDevice);
                        asState, musicDevice);
            } else {
                delay = 0;
            }
@@ -785,7 +812,7 @@ public final class AudioDeviceInventory {
                return 0;
            }
            mDeviceBroker.postBroadcastBecomingNoisy();
            delay = 1000;
            delay = AudioService.BECOMING_NOISY_DELAY_MS;
        }

        return delay;
@@ -943,4 +970,21 @@ public final class AudioDeviceInventory {
            intent.putExtra(AudioManager.EXTRA_MAX_CHANNEL_COUNT, maxChannels);
        }
    }

    //----------------------------------------------------------
    // For tests only

    /**
     * Check if device is in the list of connected devices
     * @param device
     * @return true if connected
     */
    @VisibleForTesting
    public boolean isA2dpDeviceConnected(@NonNull BluetoothDevice device) {
        final String key = DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
                device.getAddress());
        synchronized (mConnectedDevices) {
            return (mConnectedDevices.get(key) != null);
        }
    }
}
+29 −7
Original line number Diff line number Diff line
@@ -128,6 +128,7 @@ import android.view.accessibility.AccessibilityManager;
import android.widget.Toast;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.server.EventLogTags;
@@ -189,6 +190,13 @@ public class AudioService extends IAudioService.Stub
    /** How long to delay after a volume down event before unmuting a stream */
    private static final int UNMUTE_STREAM_DELAY = 350;

    /**
     * Delay before disconnecting a device that would cause BECOMING_NOISY intent to be sent,
     * to give a chance to applications to pause.
     */
    @VisibleForTesting
    public static final int BECOMING_NOISY_DELAY_MS = 1000;

    /**
     * Only used in the result from {@link #checkForRingerModeChange(int, int, int)}
     */
@@ -3950,7 +3958,9 @@ public class AudioService extends IAudioService.Stub
                || adjust == AudioManager.ADJUST_TOGGLE_MUTE;
    }

    /*package*/ boolean isInCommunication() {
    /** only public for mocking/spying, do not call outside of AudioService */
    @VisibleForTesting
    public boolean isInCommunication() {
        boolean IsInCall = false;

        TelecomManager telecomManager =
@@ -4119,7 +4129,9 @@ public class AudioService extends IAudioService.Stub
        return false;
    }

    /*package*/ int getDeviceForStream(int stream) {
    /** only public for mocking/spying, do not call outside of AudioService */
    @VisibleForTesting
    public int getDeviceForStream(int stream) {
        int device = getDevicesForStream(stream);
        if ((device & (device - 1)) != 0) {
            // Multiple device selection is either:
@@ -4164,7 +4176,9 @@ public class AudioService extends IAudioService.Stub
        }
    }

    /*package*/ void postObserveDevicesForAllStreams() {
    /** only public for mocking/spying, do not call outside of AudioService */
    @VisibleForTesting
    public void postObserveDevicesForAllStreams() {
        sendMsg(mAudioHandler,
                MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS,
                SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/, null /*obj*/,
@@ -4275,7 +4289,9 @@ public class AudioService extends IAudioService.Stub
            AudioSystem.DEVICE_OUT_ALL_USB |
            AudioSystem.DEVICE_OUT_HDMI;

    /*package*/ void postAccessoryPlugMediaUnmute(int newDevice) {
    /** only public for mocking/spying, do not call outside of AudioService */
    @VisibleForTesting
    public void postAccessoryPlugMediaUnmute(int newDevice) {
        sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
                newDevice, 0, null, 0);
    }
@@ -4825,7 +4841,9 @@ public class AudioService extends IAudioService.Stub
        }
    }

    /*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device,
    /** only public for mocking/spying, do not call outside of AudioService */
    @VisibleForTesting
    public void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device,
                                                String caller) {
        sendMsg(mAudioHandler,
                MSG_SET_DEVICE_STREAM_VOLUME,
@@ -5183,7 +5201,9 @@ public class AudioService extends IAudioService.Stub
     * @return true if there is currently a registered dynamic mixing policy that affects media
     * and is not a render + loopback policy
     */
    /*package*/ boolean hasMediaDynamicPolicy() {
    // only public for mocking/spying
    @VisibleForTesting
    public boolean hasMediaDynamicPolicy() {
        synchronized (mAudioPolicies) {
            if (mAudioPolicies.isEmpty()) {
                return false;
@@ -5516,7 +5536,9 @@ public class AudioService extends IAudioService.Stub
        return mMediaFocusControl.getFocusRampTimeMs(focusGain, attr);
    }

    /*package*/ boolean hasAudioFocusUsers() {
    /** only public for mocking/spying, do not call outside of AudioService */
    @VisibleForTesting
    public boolean hasAudioFocusUsers() {
        return mMediaFocusControl.hasAudioFocusUsers();
    }

+9 −3
Original line number Diff line number Diff line
@@ -139,6 +139,12 @@ public class BtHelper {
        public int getCodec() {
            return mCodec;
        }

        // redefine equality op so we can match messages intended for this device
        @Override
        public boolean equals(Object o) {
            return mBtDevice.equals(o);
        }
    }

    // A2DP device events
@@ -441,9 +447,9 @@ public class BtHelper {
            return;
        }
        final BluetoothDevice btDevice = deviceList.get(0);
        final @BluetoothProfile.BtProfileState int state = mA2dp.getConnectionState(btDevice);
        mDeviceBroker.handleSetA2dpSinkConnectionState(
                state, new BluetoothA2dpDeviceInfo(btDevice));
        // the device is guaranteed CONNECTED
        mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(btDevice,
                BluetoothA2dp.STATE_CONNECTED, BluetoothProfile.A2DP_SINK, true, -1);
    }

    /*package*/ synchronized void onA2dpSinkProfileConnected(BluetoothProfile profile) {
+1 −0
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@
    <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
    <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
    <uses-permission android:name="android.permission.HARDWARE_TEST"/>
    <uses-permission android:name="android.permission.BLUETOOTH"/>

    <!-- Uses API introduced in O (26) -->
    <uses-sdk android:minSdkVersion="1"
Loading