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

Commit a0334be8 authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

Merge "Audio: use preferred device for strategy for communication route"

parents 27e15dfd c78b49af
Loading
Loading
Loading
Loading
+18 −10
Original line number Diff line number Diff line
@@ -298,20 +298,25 @@ static sp<JNIAudioPortCallback> setJniCallback(JNIEnv* env,
    return old;
}

#define check_AudioSystem_Command(status) _check_AudioSystem_Command(__func__, (status))
#define check_AudioSystem_Command(...) _check_AudioSystem_Command(__func__, __VA_ARGS__)

static int _check_AudioSystem_Command(const char* caller, status_t status)
{
    ALOGE_IF(status, "Command failed for %s: %d", caller, status);
static int _check_AudioSystem_Command(const char *caller, status_t status,
                                      std::vector<status_t> ignoredErrors = {}) {
    int jniStatus = kAudioStatusOk;
    switch (status) {
    case DEAD_OBJECT:
        return kAudioStatusMediaServerDied;
        jniStatus = kAudioStatusMediaServerDied;
        break;
    case NO_ERROR:
        return kAudioStatusOk;
        break;
    default:
        if (std::find(begin(ignoredErrors), end(ignoredErrors), status) == end(ignoredErrors)) {
            jniStatus = kAudioStatusError;
        }
        break;
    }
    return kAudioStatusError;
    ALOGE_IF(jniStatus != kAudioStatusOk, "Command failed for %s: %d", caller, status);
    return jniStatus;
}

static jint getVectorOfAudioDeviceTypeAddr(JNIEnv *env, jintArray deviceTypes,
@@ -2350,9 +2355,12 @@ static jint android_media_AudioSystem_setDevicesRoleForStrategy(JNIEnv *env, job

static jint android_media_AudioSystem_removeDevicesRoleForStrategy(JNIEnv *env, jobject thiz,
                                                                   jint strategy, jint role) {
    return (jint)check_AudioSystem_Command(
            AudioSystem::removeDevicesRoleForStrategy((product_strategy_t)strategy,
                                                      (device_role_t)role));
    return (jint)
            check_AudioSystem_Command(AudioSystem::removeDevicesRoleForStrategy((product_strategy_t)
                                                                                        strategy,
                                                                                (device_role_t)
                                                                                        role),
                                      {NAME_NOT_FOUND});
}

static jint android_media_AudioSystem_getDevicesForRoleAndStrategy(JNIEnv *env, jobject thiz,
+9 −5
Original line number Diff line number Diff line
@@ -120,7 +120,13 @@ public final class AudioDeviceAttributes implements Parcelable {
        mAddress = address;
    }

    /*package*/ AudioDeviceAttributes(int nativeType, @NonNull String address) {
    /**
     * @hide
     * Constructor from internal device type and address
     * @param type the internal device type, as defined in {@link AudioSystem}
     * @param address the address of the device, or an empty string for devices without one
     */
    public AudioDeviceAttributes(int nativeType, @NonNull String address) {
        mRole = (nativeType & AudioSystem.DEVICE_BIT_IN) != 0 ? ROLE_INPUT : ROLE_OUTPUT;
        mType = AudioDeviceInfo.convertInternalDeviceToDeviceType(nativeType);
        mAddress = address;
@@ -191,10 +197,8 @@ public final class AudioDeviceAttributes implements Parcelable {
    public String toString() {
        return new String("AudioDeviceAttributes:"
                + " role:" + roleToString(mRole)
                + " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName(
                        AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType))
                        : AudioSystem.getInputDeviceName(
                                AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType)))
                + " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName(mNativeType)
                        : AudioSystem.getInputDeviceName(mNativeType))
                + " addr:" + mAddress);
    }

+1 −1
Original line number Diff line number Diff line
@@ -1730,7 +1730,7 @@ public class AudioSystem
        int[] types = new int[devices.size()];
        String[] addresses = new String[devices.size()];
        for (int i = 0; i < devices.size(); ++i) {
            types[i] = AudioDeviceInfo.convertDeviceTypeToInternalDevice(devices.get(i).getType());
            types[i] = devices.get(i).getInternalType();
            addresses[i] = devices.get(i).getAddress();
        }
        return setDevicesRoleForStrategy(strategy, role, types, addresses);
+93 −37
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.server.audio;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
@@ -34,6 +35,7 @@ import android.media.ICapturePresetDevicesRoleDispatcher;
import android.media.ICommunicationDeviceDispatcher;
import android.media.IStrategyPreferredDevicesDispatcher;
import android.media.MediaMetrics;
import android.media.audiopolicy.AudioProductStrategy;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -51,6 +53,7 @@ import android.util.PrintWriterPrinter;
import com.android.internal.annotations.GuardedBy;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
@@ -77,7 +80,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
    private final @NonNull Context mContext;

    /** Forced device usage for communications sent to AudioSystem */
    private int mForcedUseForComm;
    private AudioDeviceAttributes mPreferredDeviceforComm;
    private int mCommunicationStrategyId = -1;

    // Manages all connected devices, only ever accessed on the message loop
    private final AudioDeviceInventory mDeviceInventory;
@@ -133,10 +137,23 @@ import java.util.concurrent.atomic.AtomicBoolean;
        init();
    }

    private void initCommunicationStrategyId() {
        List<AudioProductStrategy> strategies = AudioProductStrategy.getAudioProductStrategies();
        for (AudioProductStrategy strategy : strategies) {
            if (strategy.getAudioAttributesForLegacyStreamType(AudioSystem.STREAM_VOICE_CALL)
                    != null) {
                mCommunicationStrategyId = strategy.getId();
                return;
            }
        }
        mCommunicationStrategyId = -1;
    }

    private void init() {
        setupMessaging(mContext);

        mForcedUseForComm = AudioSystem.FORCE_NONE;
        mPreferredDeviceforComm = null;
        initCommunicationStrategyId();
    }

    /*package*/ Context getContext() {
@@ -221,8 +238,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
            synchronized (mDeviceStateLock) {
                AudioDeviceAttributes device = null;
                if (on) {
                    device = new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT,
                            AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "");
                    device = new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, "");
                } else {
                    CommunicationRouteClient client = getCommunicationRouteClientForPid(pid);
                    if (client == null || !client.requestsSpeakerphone()) {
@@ -275,6 +291,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
        if (AudioService.DEBUG_COMM_RTE) {
            Log.v(TAG, "setCommunicationRouteForClient: device: " + device);
        }
        AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
                                        "setCommunicationRouteForClient for pid: " + pid
                                        + " device: " + device
                                        + " from API: " + eventSource)).printLog(TAG));

        final boolean wasBtScoRequested = isBluetoothScoRequested();
        final boolean wasSpeakerphoneRequested = isSpeakerphoneRequested();
@@ -393,7 +413,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
     * @return true if speakerphone is active, false otherwise.
     */
    /*package*/ boolean isSpeakerphoneOn() {
        return getForcedUseForComm() == AudioSystem.FORCE_SPEAKER;
        AudioDeviceAttributes device = getPreferredDeviceForComm();
        if (device == null) {
            return false;
        }
        return device.getInternalType() == AudioSystem.DEVICE_OUT_SPEAKER;
    }

    /**
@@ -560,7 +584,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
     * @return true if Bluetooth SCO is active , false otherwise.
     */
    /*package*/ boolean isBluetoothScoOn() {
        return getForcedUseForComm() == AudioSystem.FORCE_BT_SCO;
        AudioDeviceAttributes device = getPreferredDeviceForComm();
        if (device == null) {
            return false;
        }
        return AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(device.getInternalType());
    }

    /*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
@@ -612,8 +640,8 @@ import java.util.concurrent.atomic.AtomicBoolean;

        synchronized (mSetModeLock) {
            synchronized (mDeviceStateLock) {
                AudioDeviceAttributes device = new AudioDeviceAttributes(
                        AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_BLUETOOTH_SCO, "");
                AudioDeviceAttributes device =
                        new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, "");
                setCommunicationRouteForClient(cb, pid, device, scoAudioMode, eventSource);
            }
        }
@@ -643,10 +671,19 @@ import java.util.concurrent.atomic.AtomicBoolean;
        return mDeviceInventory.setPreferredDevicesForStrategySync(strategy, devices);
    }

    /*package*/ void postSetPreferredDevicesForStrategy(int strategy,
            @NonNull List<AudioDeviceAttributes> devices) {
        sendILMsgNoDelay(MSG_IL_SET_PREF_DEVICES_FOR_STRATEGY, SENDMSG_REPLACE, strategy, devices);
    }

    /*package*/ int removePreferredDevicesForStrategySync(int strategy) {
        return mDeviceInventory.removePreferredDevicesForStrategySync(strategy);
    }

    /*package*/ void postRemovePreferredDevicesForStrategy(int strategy) {
        sendIMsgNoDelay(MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_REPLACE, strategy);
    }

    /*package*/ void registerStrategyPreferredDevicesDispatcher(
            @NonNull IStrategyPreferredDevicesDispatcher dispatcher) {
        mDeviceInventory.registerStrategyPreferredDevicesDispatcher(dispatcher);
@@ -971,9 +1008,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
            pw.println("  " + prefix + "pid: " + cl.getPid() + " device: "
                        + cl.getDevice() + " cb: " + cl.getBinder()); });

        pw.println("\n" + prefix + "mForcedUseForComm: "
                +  AudioSystem.forceUseConfigToString(mForcedUseForComm));
        pw.println(prefix + "mModeOwnerPid: " + mModeOwnerPid);
        pw.println("\n" + prefix + "mPreferredDeviceforComm: "
                +  mPreferredDeviceforComm);
        pw.println(prefix + "mCommunicationStrategyId: "
                +  mCommunicationStrategyId);

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

        mBtHelper.dump(pw, prefix);
    }
@@ -1068,6 +1108,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
                case MSG_RESTORE_DEVICES:
                    synchronized (mSetModeLock) {
                        synchronized (mDeviceStateLock) {
                            initCommunicationStrategyId();
                            mDeviceInventory.onRestoreDevices();
                            mBtHelper.onAudioServerDiedRestoreA2dp();
                            onUpdateCommunicationRoute("MSG_RESTORE_DEVICES");
@@ -1277,6 +1318,17 @@ import java.util.concurrent.atomic.AtomicBoolean;
                    final int strategy = msg.arg1;
                    mDeviceInventory.onSaveRemovePreferredDevices(strategy);
                } break;
                case MSG_IL_SET_PREF_DEVICES_FOR_STRATEGY: {
                    final int strategy = msg.arg1;
                    final List<AudioDeviceAttributes> devices =
                            (List<AudioDeviceAttributes>) msg.obj;
                    setPreferredDevicesForStrategySync(strategy, devices);

                } break;
                case MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY: {
                    final int strategy = msg.arg1;
                    removePreferredDevicesForStrategySync(strategy);
                } break;
                case MSG_CHECK_MUTE_MUSIC:
                    checkMessagesMuteMusic(0);
                    break;
@@ -1369,7 +1421,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
    private static final int MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET = 38;

    private static final int MSG_L_UPDATE_COMMUNICATION_ROUTE = 39;

    private static final int MSG_IL_SET_PREF_DEVICES_FOR_STRATEGY = 40;
    private static final int MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY = 41;

    private static boolean isMessageHandledUnderWakelock(int msgId) {
        switch(msgId) {
@@ -1609,16 +1662,25 @@ import java.util.concurrent.atomic.AtomicBoolean;
     * @return selected forced usage for communication.
     */
    @GuardedBy("mDeviceStateLock")
    private int getForcedUseForComm() {
    @Nullable private AudioDeviceAttributes getPreferredDeviceForComm() {
        boolean btSCoOn = mBluetoothScoOn && mBtHelper.isBluetoothScoOn();

        if (btSCoOn) {
            return AudioSystem.FORCE_BT_SCO;
            // Use the SCO device known to BtHelper so that it matches exactly
            // what has been communicated to audio policy manager. The device
            // returned by requestedCommunicationDevice() can be a dummy SCO device if legacy
            // APIs are used to start SCO audio.
            AudioDeviceAttributes device = mBtHelper.getHeadsetAudioDevice();
            if (device != null) {
                return device;
            }
        if (isSpeakerphoneRequested()) {
            return AudioSystem.FORCE_SPEAKER;
        }
        return AudioSystem.FORCE_NONE;
        AudioDeviceAttributes device = requestedCommunicationDevice();
        if (device == null
                || AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(device.getInternalType())) {
            // Do not indicate BT SCO selection if SCO is requested but SCO is not ON
            return null;
        }
        return device;
    }

    /**
@@ -1628,30 +1690,24 @@ import java.util.concurrent.atomic.AtomicBoolean;
    // @GuardedBy("mSetModeLock")
    @GuardedBy("mDeviceStateLock")
    private void onUpdateCommunicationRoute(String eventSource) {
        mForcedUseForComm = getForcedUseForComm();

        mPreferredDeviceforComm = getPreferredDeviceForComm();
        if (AudioService.DEBUG_COMM_RTE) {
            Log.v(TAG, "onUpdateCommunicationRoute, mForcedUseForComm: " + mForcedUseForComm
                    + " eventSource: " + eventSource);
            Log.v(TAG, "onUpdateCommunicationRoute, mPreferredDeviceforComm: "
                    + mPreferredDeviceforComm + " eventSource: " + eventSource);
        }

        if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
            AudioSystem.setParameters("BT_SCO=on");
            setForceUse_Async(
                    AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_BT_SCO, eventSource);
            setForceUse_Async(
                    AudioSystem.FOR_RECORD, AudioSystem.FORCE_BT_SCO, eventSource);
        } else {
        if (mPreferredDeviceforComm == null
                || !AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(
                        mPreferredDeviceforComm.getInternalType())) {
            AudioSystem.setParameters("BT_SCO=off");
            setForceUse_Async(
                    AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, eventSource);
            if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) {
                setForceUse_Async(
                        AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_SPEAKER, eventSource);
        } else {
                setForceUse_Async(
                        AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_NONE, eventSource);
            AudioSystem.setParameters("BT_SCO=on");
        }
        if (mPreferredDeviceforComm == null) {
            postRemovePreferredDevicesForStrategy(mCommunicationStrategyId);
        } else {
            postSetPreferredDevicesForStrategy(
                    mCommunicationStrategyId, Arrays.asList(mPreferredDeviceforComm));
        }
        mAudioService.postUpdateRingerModeServiceInt();
        dispatchCommunicationDevice();
+4 −0
Original line number Diff line number Diff line
@@ -648,6 +648,10 @@ public class AudioDeviceInventory {
    /*package*/ int setPreferredDevicesForStrategySync(int strategy,
            @NonNull List<AudioDeviceAttributes> devices) {
        final long identity = Binder.clearCallingIdentity();

        AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
                                "setPreferredDevicesForStrategySync, strategy: " + strategy
                                + " devices: " + devices)).printLog(TAG));
        final int status = mAudioSystem.setDevicesRoleForStrategy(
                strategy, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
        Binder.restoreCallingIdentity(identity);
Loading