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

Commit 4d22fe5f authored by Eric Laurent's avatar Eric Laurent Committed by Gerrit Code Review
Browse files

Merge "AudioDeviceBroker: Bluetooth LE communication route compatibility"

parents 31075f29 9dedc0af
Loading
Loading
Loading
Loading
+112 −38
Original line number Diff line number Diff line
@@ -17,9 +17,12 @@ package com.android.server.audio;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.compat.CompatChanges;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -118,8 +121,39 @@ import java.util.concurrent.atomic.AtomicBoolean;
    // TODO do not "share" the lock between AudioService and BtHelpr, see b/123769055
    /*package*/ final Object mSetModeLock = new Object();

    /** PID of current audio mode owner communicated by AudioService */
    private int mModeOwnerPid = 0;
    /** AudioModeInfo contains information on current audio mode owner
     * communicated by AudioService */
    /* package */ static final class AudioModeInfo {
        /** Current audio mode */
        final int mMode;
        /** PID of current audio mode owner */
        final int mPid;
        /** UID of current audio mode owner */
        final int mUid;

        AudioModeInfo(int mode, int pid, int uid) {
            mMode = mode;
            mPid = pid;
            mUid = uid;
        }

        @Override
        public String toString() {
            return "AudioModeInfo: mMode=" + AudioSystem.modeToString(mMode)
                    + ", mPid=" + mPid
                    + ", mUid=" + mUid;
        }
    };

    private AudioModeInfo mAudioModeOwner = new AudioModeInfo(AudioSystem.MODE_NORMAL, 0, 0);

    /**
     * Indicates that default communication device is chosen by routing rules in audio policy
     * manager and not forced by AudioDeviceBroker.
     */
    @ChangeId
    @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S_V2)
    public static final long USE_SET_COMMUNICATION_DEVICE = 243827847L;

    //-------------------------------------------------------------------
    /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service) {
@@ -187,7 +221,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
    /*package*/ void onSystemReady() {
        synchronized (mSetModeLock) {
            synchronized (mDeviceStateLock) {
                mModeOwnerPid = mAudioService.getModeOwnerPid();
                mAudioModeOwner = mAudioService.getAudioModeOwner();
                mBtHelper.onSystemReady();
            }
        }
@@ -368,11 +402,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
    @GuardedBy("mDeviceStateLock")
    private CommunicationRouteClient topCommunicationRouteClient() {
        for (CommunicationRouteClient crc : mCommunicationRouteClients) {
            if (crc.getPid() == mModeOwnerPid) {
            if (crc.getPid() == mAudioModeOwner.mPid) {
                return crc;
            }
        }
        if (!mCommunicationRouteClients.isEmpty() && mModeOwnerPid == 0) {
        if (!mCommunicationRouteClients.isEmpty() && mAudioModeOwner.mPid == 0) {
            return mCommunicationRouteClients.get(0);
        }
        return null;
@@ -390,7 +424,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
        AudioDeviceAttributes device = crc != null ? crc.getDevice() : null;
        if (AudioService.DEBUG_COMM_RTE) {
            Log.v(TAG, "requestedCommunicationDevice, device: "
                    + device + " mode owner pid: " + mModeOwnerPid);
                    + device + "mAudioModeOwner: " + mAudioModeOwner.toString());
        }
        return device;
    }
@@ -774,8 +808,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
        sendLMsgNoDelay(MSG_II_SET_LE_AUDIO_OUT_VOLUME, SENDMSG_REPLACE, info);
    }

    /*package*/ void postSetModeOwnerPid(int pid, int mode) {
        sendIIMsgNoDelay(MSG_I_SET_MODE_OWNER_PID, SENDMSG_REPLACE, pid, mode);
    /*package*/ void postSetModeOwner(int mode, int pid, int uid) {
        sendLMsgNoDelay(MSG_I_SET_MODE_OWNER, SENDMSG_REPLACE,
                new AudioModeInfo(mode, pid, uid));
    }

    /*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) {
@@ -1162,7 +1197,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
        pw.println(prefix + "mAccessibilityStrategyId: "
                +  mAccessibilityStrategyId);

        pw.println("\n" + prefix + "mModeOwnerPid: " + mModeOwnerPid);
        pw.println("\n" + prefix + "mAudioModeOwner: " + mAudioModeOwner);

        mBtHelper.dump(pw, prefix);
    }
@@ -1288,12 +1323,19 @@ import java.util.concurrent.atomic.AtomicBoolean;
                    }
                    break;
                case MSG_L_SET_BT_ACTIVE_DEVICE:
                    synchronized (mSetModeLock) {
                        synchronized (mDeviceStateLock) {
                            BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
                            mDeviceInventory.onSetBtActiveDevice(btInfo,
                                (btInfo.mProfile != BluetoothProfile.LE_AUDIO || btInfo.mIsLeOutput)
                                    (btInfo.mProfile
                                            != BluetoothProfile.LE_AUDIO || btInfo.mIsLeOutput)
                                            ? mAudioService.getBluetoothContextualVolumeStream()
                                            : AudioSystem.STREAM_DEFAULT);
                            if (btInfo.mProfile == BluetoothProfile.LE_AUDIO
                                    || btInfo.mProfile == BluetoothProfile.HEARING_AID) {
                                onUpdateCommunicationRouteClient("setBluetoothActiveDevice");
                            }
                        }
                    }
                    break;
                case MSG_BT_HEADSET_CNCT_FAILED:
@@ -1338,11 +1380,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
                        mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1);
                    }
                    break;
                case MSG_I_SET_MODE_OWNER_PID:
                case MSG_I_SET_MODE_OWNER:
                    synchronized (mSetModeLock) {
                        synchronized (mDeviceStateLock) {
                            mModeOwnerPid = msg.arg1;
                            if (msg.arg2 != AudioSystem.MODE_RINGTONE) {
                            mAudioModeOwner = (AudioModeInfo) msg.obj;
                            if (mAudioModeOwner.mMode != AudioSystem.MODE_RINGTONE) {
                                onUpdateCommunicationRouteClient("setNewModeOwner");
                            }
                        }
@@ -1504,7 +1546,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
    private static final int MSG_REPORT_NEW_ROUTES = 13;
    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_SET_MODE_OWNER_PID = 16;
    private static final int MSG_I_SET_MODE_OWNER = 16;

    private static final int MSG_I_BT_SERVICE_DISCONNECTED_PROFILE = 22;
    private static final int MSG_IL_BT_SERVICE_CONNECTED_PROFILE = 23;
@@ -1826,8 +1868,16 @@ import java.util.concurrent.atomic.AtomicBoolean;
            AudioSystem.setParameters("BT_SCO=on");
        }
        if (preferredCommunicationDevice == null) {
            AudioDeviceAttributes defaultDevice = getDefaultCommunicationDevice();
            if (defaultDevice != null) {
                setPreferredDevicesForStrategySync(
                        mCommunicationStrategyId, Arrays.asList(defaultDevice));
                setPreferredDevicesForStrategySync(
                        mAccessibilityStrategyId, Arrays.asList(defaultDevice));
            } else {
                removePreferredDevicesForStrategySync(mCommunicationStrategyId);
                removePreferredDevicesForStrategySync(mAccessibilityStrategyId);
            }
        } else {
            setPreferredDevicesForStrategySync(
                    mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice));
@@ -1856,9 +1906,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
        }
    }

    // @GuardedBy("mSetModeLock")
    @GuardedBy("mDeviceStateLock")
    private void onUpdatePhoneStrategyDevice(AudioDeviceAttributes device) {
        synchronized (mSetModeLock) {
            synchronized (mDeviceStateLock) {
        boolean wasSpeakerphoneActive = isSpeakerphoneActive();
        mPreferredCommunicationDevice = device;
        updateActiveCommunicationDevice();
@@ -1875,8 +1925,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
        mAudioService.postUpdateRingerModeServiceInt();
        dispatchCommunicationDevice();
    }
        }
    }

    private CommunicationRouteClient removeCommunicationRouteClient(
                    IBinder cb, boolean unregister) {
@@ -1915,6 +1963,32 @@ import java.util.concurrent.atomic.AtomicBoolean;
        return null;
    }

    @GuardedBy("mDeviceStateLock")
    private boolean communnicationDeviceCompatOn() {
        return mAudioModeOwner.mMode == AudioSystem.MODE_IN_COMMUNICATION
                && !(CompatChanges.isChangeEnabled(
                        USE_SET_COMMUNICATION_DEVICE, mAudioModeOwner.mUid)
                     || mAudioModeOwner.mUid == android.os.Process.SYSTEM_UID);
    }

    @GuardedBy("mDeviceStateLock")
    AudioDeviceAttributes getDefaultCommunicationDevice() {
        // For system server (Telecom) and APKs targeting S and above, we let the audio
        // policy routing rules select the default communication device.
        // For older APKs, we force Hearing Aid or LE Audio headset when connected as
        // those APKs cannot select a LE Audio or Hearing Aid device explicitly.
        AudioDeviceAttributes device = null;
        if (communnicationDeviceCompatOn()) {
            // If both LE and Hearing Aid are active (thie should not happen),
            // priority to Hearing Aid.
            device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_HEARING_AID);
            if (device == null) {
                device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_BLE_HEADSET);
            }
        }
        return device;
    }

    @Nullable UUID getDeviceSensorUuid(AudioDeviceAttributes device) {
        synchronized (mDeviceStateLock) {
            return mDeviceInventory.getDeviceSensorUuid(device);
+14 −0
Original line number Diff line number Diff line
@@ -294,6 +294,7 @@ public class AudioDeviceInventory {
        }
    }

    // @GuardedBy("AudioDeviceBroker.mSetModeLock")
    @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
    void onSetBtActiveDevice(@NonNull AudioDeviceBroker.BtDeviceInfo btInfo, int streamType) {
        if (AudioService.DEBUG_DEVICES) {
@@ -1526,6 +1527,19 @@ public class AudioDeviceInventory {
            return di.mSensorUuid;
        }
    }

    /* package */ AudioDeviceAttributes getDeviceOfType(int type) {
        synchronized (mDevicesLock) {
            for (DeviceInfo di : mConnectedDevices.values()) {
                if (di.mDeviceType == type) {
                    return new AudioDeviceAttributes(
                            di.mDeviceType, di.mDeviceAddress, di.mDeviceName);
                }
            }
        }
        return null;
    }

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

+12 −7
Original line number Diff line number Diff line
@@ -5053,16 +5053,17 @@ public class AudioService extends IAudioService.Stub
    }

    /**
     * Return the pid of the current audio mode owner
     * Return information on the current audio mode owner
     * @return 0 if nobody owns the mode
     */
    @GuardedBy("mDeviceBroker.mSetModeLock")
    /*package*/ int getModeOwnerPid() {
    /*package*/ AudioDeviceBroker.AudioModeInfo getAudioModeOwner() {
        SetModeDeathHandler hdlr = getAudioModeOwnerHandler();
        if (hdlr != null) {
            return hdlr.getPid();
            return new AudioDeviceBroker.AudioModeInfo(
                    hdlr.getMode(), hdlr.getPid(), hdlr.getUid());
        }
        return 0;
        return new AudioDeviceBroker.AudioModeInfo(AudioSystem.MODE_NORMAL, 0 , 0);
    }

    /**
@@ -5248,7 +5249,7 @@ public class AudioService extends IAudioService.Stub

                // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all SCO
                // connections not started by the application changing the mode when pid changes
                mDeviceBroker.postSetModeOwnerPid(pid, mode);
                mDeviceBroker.postSetModeOwner(mode, pid, uid);
            } else {
                Log.w(TAG, "onUpdateAudioMode: failed to set audio mode to: " + mode);
            }
@@ -5575,7 +5576,10 @@ public class AudioService extends IAudioService.Stub
        }
        return deviceIds.stream().mapToInt(Integer::intValue).toArray();
    }
        /** @see AudioManager#setCommunicationDevice(int) */
        /**
         * @see AudioManager#setCommunicationDevice(int)
         * @see AudioManager#clearCommunicationDevice()
         */
    public boolean setCommunicationDevice(IBinder cb, int portId) {
        final int uid = Binder.getCallingUid();
        final int pid = Binder.getCallingPid();
@@ -5590,7 +5594,8 @@ public class AudioService extends IAudioService.Stub
                throw new IllegalArgumentException("invalid device type " + device.getType());
            }
        }
        final String eventSource = new StringBuilder("setCommunicationDevice(")
        final String eventSource = new StringBuilder()
                .append(device == null ? "clearCommunicationDevice(" : "setCommunicationDevice(")
                .append(") from u/pid:").append(uid).append("/")
                .append(pid).toString();