Audio: use preferred device for strategy for communication route
Replaced use of forced usage for communication by set preferred device for strategy to control communication route in audio policy manager. Also do not use forced usage for record which was redundant with forced usage for communication. Bug: 161358428 Test: audio smoke tests Change-Id: I665257fc5903b663096104b0424781d9799635a5
This commit is contained in:
@@ -298,20 +298,25 @@ static sp<JNIAudioPortCallback> setJniCallback(JNIEnv* env,
|
|||||||
return old;
|
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)
|
static int _check_AudioSystem_Command(const char *caller, status_t status,
|
||||||
{
|
std::vector<status_t> ignoredErrors = {}) {
|
||||||
ALOGE_IF(status, "Command failed for %s: %d", caller, status);
|
int jniStatus = kAudioStatusOk;
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case DEAD_OBJECT:
|
case DEAD_OBJECT:
|
||||||
return kAudioStatusMediaServerDied;
|
jniStatus = kAudioStatusMediaServerDied;
|
||||||
|
break;
|
||||||
case NO_ERROR:
|
case NO_ERROR:
|
||||||
return kAudioStatusOk;
|
break;
|
||||||
default:
|
default:
|
||||||
|
if (std::find(begin(ignoredErrors), end(ignoredErrors), status) == end(ignoredErrors)) {
|
||||||
|
jniStatus = kAudioStatusError;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return kAudioStatusError;
|
ALOGE_IF(jniStatus != kAudioStatusOk, "Command failed for %s: %d", caller, status);
|
||||||
|
return jniStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
static jint getVectorOfAudioDeviceTypeAddr(JNIEnv *env, jintArray deviceTypes,
|
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,
|
static jint android_media_AudioSystem_removeDevicesRoleForStrategy(JNIEnv *env, jobject thiz,
|
||||||
jint strategy, jint role) {
|
jint strategy, jint role) {
|
||||||
return (jint)check_AudioSystem_Command(
|
return (jint)
|
||||||
AudioSystem::removeDevicesRoleForStrategy((product_strategy_t)strategy,
|
check_AudioSystem_Command(AudioSystem::removeDevicesRoleForStrategy((product_strategy_t)
|
||||||
(device_role_t)role));
|
strategy,
|
||||||
|
(device_role_t)
|
||||||
|
role),
|
||||||
|
{NAME_NOT_FOUND});
|
||||||
}
|
}
|
||||||
|
|
||||||
static jint android_media_AudioSystem_getDevicesForRoleAndStrategy(JNIEnv *env, jobject thiz,
|
static jint android_media_AudioSystem_getDevicesForRoleAndStrategy(JNIEnv *env, jobject thiz,
|
||||||
|
|||||||
@@ -120,7 +120,13 @@ public final class AudioDeviceAttributes implements Parcelable {
|
|||||||
mAddress = address;
|
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;
|
mRole = (nativeType & AudioSystem.DEVICE_BIT_IN) != 0 ? ROLE_INPUT : ROLE_OUTPUT;
|
||||||
mType = AudioDeviceInfo.convertInternalDeviceToDeviceType(nativeType);
|
mType = AudioDeviceInfo.convertInternalDeviceToDeviceType(nativeType);
|
||||||
mAddress = address;
|
mAddress = address;
|
||||||
@@ -191,10 +197,8 @@ public final class AudioDeviceAttributes implements Parcelable {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return new String("AudioDeviceAttributes:"
|
return new String("AudioDeviceAttributes:"
|
||||||
+ " role:" + roleToString(mRole)
|
+ " role:" + roleToString(mRole)
|
||||||
+ " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName(
|
+ " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName(mNativeType)
|
||||||
AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType))
|
: AudioSystem.getInputDeviceName(mNativeType))
|
||||||
: AudioSystem.getInputDeviceName(
|
|
||||||
AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType)))
|
|
||||||
+ " addr:" + mAddress);
|
+ " addr:" + mAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1730,7 +1730,7 @@ public class AudioSystem
|
|||||||
int[] types = new int[devices.size()];
|
int[] types = new int[devices.size()];
|
||||||
String[] addresses = new String[devices.size()];
|
String[] addresses = new String[devices.size()];
|
||||||
for (int i = 0; i < devices.size(); ++i) {
|
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();
|
addresses[i] = devices.get(i).getAddress();
|
||||||
}
|
}
|
||||||
return setDevicesRoleForStrategy(strategy, role, types, addresses);
|
return setDevicesRoleForStrategy(strategy, role, types, addresses);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
package com.android.server.audio;
|
package com.android.server.audio;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.bluetooth.BluetoothA2dp;
|
import android.bluetooth.BluetoothA2dp;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.bluetooth.BluetoothHeadset;
|
import android.bluetooth.BluetoothHeadset;
|
||||||
@@ -34,6 +35,7 @@ import android.media.ICapturePresetDevicesRoleDispatcher;
|
|||||||
import android.media.ICommunicationDeviceDispatcher;
|
import android.media.ICommunicationDeviceDispatcher;
|
||||||
import android.media.IStrategyPreferredDevicesDispatcher;
|
import android.media.IStrategyPreferredDevicesDispatcher;
|
||||||
import android.media.MediaMetrics;
|
import android.media.MediaMetrics;
|
||||||
|
import android.media.audiopolicy.AudioProductStrategy;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
@@ -51,6 +53,7 @@ import android.util.PrintWriterPrinter;
|
|||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -77,7 +80,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
private final @NonNull Context mContext;
|
private final @NonNull Context mContext;
|
||||||
|
|
||||||
/** Forced device usage for communications sent to AudioSystem */
|
/** 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
|
// Manages all connected devices, only ever accessed on the message loop
|
||||||
private final AudioDeviceInventory mDeviceInventory;
|
private final AudioDeviceInventory mDeviceInventory;
|
||||||
@@ -133,10 +137,23 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
init();
|
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() {
|
private void init() {
|
||||||
setupMessaging(mContext);
|
setupMessaging(mContext);
|
||||||
|
|
||||||
mForcedUseForComm = AudioSystem.FORCE_NONE;
|
mPreferredDeviceforComm = null;
|
||||||
|
initCommunicationStrategyId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ Context getContext() {
|
/*package*/ Context getContext() {
|
||||||
@@ -221,8 +238,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
synchronized (mDeviceStateLock) {
|
synchronized (mDeviceStateLock) {
|
||||||
AudioDeviceAttributes device = null;
|
AudioDeviceAttributes device = null;
|
||||||
if (on) {
|
if (on) {
|
||||||
device = new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT,
|
device = new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, "");
|
||||||
AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "");
|
|
||||||
} else {
|
} else {
|
||||||
CommunicationRouteClient client = getCommunicationRouteClientForPid(pid);
|
CommunicationRouteClient client = getCommunicationRouteClientForPid(pid);
|
||||||
if (client == null || !client.requestsSpeakerphone()) {
|
if (client == null || !client.requestsSpeakerphone()) {
|
||||||
@@ -275,6 +291,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
if (AudioService.DEBUG_COMM_RTE) {
|
if (AudioService.DEBUG_COMM_RTE) {
|
||||||
Log.v(TAG, "setCommunicationRouteForClient: device: " + device);
|
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 wasBtScoRequested = isBluetoothScoRequested();
|
||||||
final boolean wasSpeakerphoneRequested = isSpeakerphoneRequested();
|
final boolean wasSpeakerphoneRequested = isSpeakerphoneRequested();
|
||||||
@@ -393,7 +413,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
* @return true if speakerphone is active, false otherwise.
|
* @return true if speakerphone is active, false otherwise.
|
||||||
*/
|
*/
|
||||||
/*package*/ boolean isSpeakerphoneOn() {
|
/*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.
|
* @return true if Bluetooth SCO is active , false otherwise.
|
||||||
*/
|
*/
|
||||||
/*package*/ boolean isBluetoothScoOn() {
|
/*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) {
|
/*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
|
||||||
@@ -612,8 +640,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
|
|
||||||
synchronized (mSetModeLock) {
|
synchronized (mSetModeLock) {
|
||||||
synchronized (mDeviceStateLock) {
|
synchronized (mDeviceStateLock) {
|
||||||
AudioDeviceAttributes device = new AudioDeviceAttributes(
|
AudioDeviceAttributes device =
|
||||||
AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_BLUETOOTH_SCO, "");
|
new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, "");
|
||||||
setCommunicationRouteForClient(cb, pid, device, scoAudioMode, eventSource);
|
setCommunicationRouteForClient(cb, pid, device, scoAudioMode, eventSource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -643,10 +671,19 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
return mDeviceInventory.setPreferredDevicesForStrategySync(strategy, devices);
|
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) {
|
/*package*/ int removePreferredDevicesForStrategySync(int strategy) {
|
||||||
return mDeviceInventory.removePreferredDevicesForStrategySync(strategy);
|
return mDeviceInventory.removePreferredDevicesForStrategySync(strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*package*/ void postRemovePreferredDevicesForStrategy(int strategy) {
|
||||||
|
sendIMsgNoDelay(MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_REPLACE, strategy);
|
||||||
|
}
|
||||||
|
|
||||||
/*package*/ void registerStrategyPreferredDevicesDispatcher(
|
/*package*/ void registerStrategyPreferredDevicesDispatcher(
|
||||||
@NonNull IStrategyPreferredDevicesDispatcher dispatcher) {
|
@NonNull IStrategyPreferredDevicesDispatcher dispatcher) {
|
||||||
mDeviceInventory.registerStrategyPreferredDevicesDispatcher(dispatcher);
|
mDeviceInventory.registerStrategyPreferredDevicesDispatcher(dispatcher);
|
||||||
@@ -971,9 +1008,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
pw.println(" " + prefix + "pid: " + cl.getPid() + " device: "
|
pw.println(" " + prefix + "pid: " + cl.getPid() + " device: "
|
||||||
+ cl.getDevice() + " cb: " + cl.getBinder()); });
|
+ cl.getDevice() + " cb: " + cl.getBinder()); });
|
||||||
|
|
||||||
pw.println("\n" + prefix + "mForcedUseForComm: "
|
pw.println("\n" + prefix + "mPreferredDeviceforComm: "
|
||||||
+ AudioSystem.forceUseConfigToString(mForcedUseForComm));
|
+ mPreferredDeviceforComm);
|
||||||
pw.println(prefix + "mModeOwnerPid: " + mModeOwnerPid);
|
pw.println(prefix + "mCommunicationStrategyId: "
|
||||||
|
+ mCommunicationStrategyId);
|
||||||
|
|
||||||
|
pw.println("\n" + prefix + "mModeOwnerPid: " + mModeOwnerPid);
|
||||||
|
|
||||||
mBtHelper.dump(pw, prefix);
|
mBtHelper.dump(pw, prefix);
|
||||||
}
|
}
|
||||||
@@ -1068,6 +1108,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
case MSG_RESTORE_DEVICES:
|
case MSG_RESTORE_DEVICES:
|
||||||
synchronized (mSetModeLock) {
|
synchronized (mSetModeLock) {
|
||||||
synchronized (mDeviceStateLock) {
|
synchronized (mDeviceStateLock) {
|
||||||
|
initCommunicationStrategyId();
|
||||||
mDeviceInventory.onRestoreDevices();
|
mDeviceInventory.onRestoreDevices();
|
||||||
mBtHelper.onAudioServerDiedRestoreA2dp();
|
mBtHelper.onAudioServerDiedRestoreA2dp();
|
||||||
onUpdateCommunicationRoute("MSG_RESTORE_DEVICES");
|
onUpdateCommunicationRoute("MSG_RESTORE_DEVICES");
|
||||||
@@ -1277,6 +1318,17 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
final int strategy = msg.arg1;
|
final int strategy = msg.arg1;
|
||||||
mDeviceInventory.onSaveRemovePreferredDevices(strategy);
|
mDeviceInventory.onSaveRemovePreferredDevices(strategy);
|
||||||
} break;
|
} 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:
|
case MSG_CHECK_MUTE_MUSIC:
|
||||||
checkMessagesMuteMusic(0);
|
checkMessagesMuteMusic(0);
|
||||||
break;
|
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_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET = 38;
|
||||||
|
|
||||||
private static final int MSG_L_UPDATE_COMMUNICATION_ROUTE = 39;
|
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) {
|
private static boolean isMessageHandledUnderWakelock(int msgId) {
|
||||||
switch(msgId) {
|
switch(msgId) {
|
||||||
@@ -1609,16 +1662,25 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
* @return selected forced usage for communication.
|
* @return selected forced usage for communication.
|
||||||
*/
|
*/
|
||||||
@GuardedBy("mDeviceStateLock")
|
@GuardedBy("mDeviceStateLock")
|
||||||
private int getForcedUseForComm() {
|
@Nullable private AudioDeviceAttributes getPreferredDeviceForComm() {
|
||||||
boolean btSCoOn = mBluetoothScoOn && mBtHelper.isBluetoothScoOn();
|
boolean btSCoOn = mBluetoothScoOn && mBtHelper.isBluetoothScoOn();
|
||||||
|
|
||||||
if (btSCoOn) {
|
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("mSetModeLock")
|
||||||
@GuardedBy("mDeviceStateLock")
|
@GuardedBy("mDeviceStateLock")
|
||||||
private void onUpdateCommunicationRoute(String eventSource) {
|
private void onUpdateCommunicationRoute(String eventSource) {
|
||||||
mForcedUseForComm = getForcedUseForComm();
|
mPreferredDeviceforComm = getPreferredDeviceForComm();
|
||||||
|
|
||||||
if (AudioService.DEBUG_COMM_RTE) {
|
if (AudioService.DEBUG_COMM_RTE) {
|
||||||
Log.v(TAG, "onUpdateCommunicationRoute, mForcedUseForComm: " + mForcedUseForComm
|
Log.v(TAG, "onUpdateCommunicationRoute, mPreferredDeviceforComm: "
|
||||||
+ " eventSource: " + eventSource);
|
+ mPreferredDeviceforComm + " eventSource: " + eventSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
|
if (mPreferredDeviceforComm == null
|
||||||
AudioSystem.setParameters("BT_SCO=on");
|
|| !AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(
|
||||||
setForceUse_Async(
|
mPreferredDeviceforComm.getInternalType())) {
|
||||||
AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_BT_SCO, eventSource);
|
|
||||||
setForceUse_Async(
|
|
||||||
AudioSystem.FOR_RECORD, AudioSystem.FORCE_BT_SCO, eventSource);
|
|
||||||
} else {
|
|
||||||
AudioSystem.setParameters("BT_SCO=off");
|
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 {
|
} else {
|
||||||
setForceUse_Async(
|
AudioSystem.setParameters("BT_SCO=on");
|
||||||
AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_NONE, eventSource);
|
|
||||||
}
|
}
|
||||||
|
if (mPreferredDeviceforComm == null) {
|
||||||
|
postRemovePreferredDevicesForStrategy(mCommunicationStrategyId);
|
||||||
|
} else {
|
||||||
|
postSetPreferredDevicesForStrategy(
|
||||||
|
mCommunicationStrategyId, Arrays.asList(mPreferredDeviceforComm));
|
||||||
}
|
}
|
||||||
mAudioService.postUpdateRingerModeServiceInt();
|
mAudioService.postUpdateRingerModeServiceInt();
|
||||||
dispatchCommunicationDevice();
|
dispatchCommunicationDevice();
|
||||||
|
|||||||
@@ -648,6 +648,10 @@ public class AudioDeviceInventory {
|
|||||||
/*package*/ int setPreferredDevicesForStrategySync(int strategy,
|
/*package*/ int setPreferredDevicesForStrategySync(int strategy,
|
||||||
@NonNull List<AudioDeviceAttributes> devices) {
|
@NonNull List<AudioDeviceAttributes> devices) {
|
||||||
final long identity = Binder.clearCallingIdentity();
|
final long identity = Binder.clearCallingIdentity();
|
||||||
|
|
||||||
|
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
|
||||||
|
"setPreferredDevicesForStrategySync, strategy: " + strategy
|
||||||
|
+ " devices: " + devices)).printLog(TAG));
|
||||||
final int status = mAudioSystem.setDevicesRoleForStrategy(
|
final int status = mAudioSystem.setDevicesRoleForStrategy(
|
||||||
strategy, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
|
strategy, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
|
||||||
Binder.restoreCallingIdentity(identity);
|
Binder.restoreCallingIdentity(identity);
|
||||||
|
|||||||
@@ -5121,8 +5121,7 @@ public class AudioService extends IAudioService.Stub
|
|||||||
switch (mPlatformType) {
|
switch (mPlatformType) {
|
||||||
case AudioSystem.PLATFORM_VOICE:
|
case AudioSystem.PLATFORM_VOICE:
|
||||||
if (isInCommunication()) {
|
if (isInCommunication()) {
|
||||||
if (mAudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
|
if (mDeviceBroker.isBluetoothScoOn()) {
|
||||||
== AudioSystem.FORCE_BT_SCO) {
|
|
||||||
// Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
|
// Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
|
||||||
return AudioSystem.STREAM_BLUETOOTH_SCO;
|
return AudioSystem.STREAM_BLUETOOTH_SCO;
|
||||||
} else {
|
} else {
|
||||||
@@ -5158,8 +5157,7 @@ public class AudioService extends IAudioService.Stub
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if (isInCommunication()) {
|
if (isInCommunication()) {
|
||||||
if (mAudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
|
if (mDeviceBroker.isBluetoothScoOn()) {
|
||||||
== AudioSystem.FORCE_BT_SCO) {
|
|
||||||
if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
|
if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
|
||||||
return AudioSystem.STREAM_BLUETOOTH_SCO;
|
return AudioSystem.STREAM_BLUETOOTH_SCO;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import android.bluetooth.BluetoothHeadset;
|
|||||||
import android.bluetooth.BluetoothHearingAid;
|
import android.bluetooth.BluetoothHearingAid;
|
||||||
import android.bluetooth.BluetoothProfile;
|
import android.bluetooth.BluetoothProfile;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.media.AudioDeviceAttributes;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.media.AudioSystem;
|
import android.media.AudioSystem;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
@@ -530,46 +531,64 @@ public class BtHelper {
|
|||||||
mDeviceBroker.postBroadcastScoConnectionState(state);
|
mDeviceBroker.postBroadcastScoConnectionState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable AudioDeviceAttributes getHeadsetAudioDevice() {
|
||||||
|
if (mBluetoothHeadsetDevice == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return btHeadsetDeviceToAudioDevice(mBluetoothHeadsetDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AudioDeviceAttributes btHeadsetDeviceToAudioDevice(BluetoothDevice btDevice) {
|
||||||
|
String address = btDevice.getAddress();
|
||||||
|
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
|
||||||
|
address = "";
|
||||||
|
}
|
||||||
|
BluetoothClass btClass = btDevice.getBluetoothClass();
|
||||||
|
int nativeType = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
|
||||||
|
if (btClass != null) {
|
||||||
|
switch (btClass.getDeviceClass()) {
|
||||||
|
case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
|
||||||
|
case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
|
||||||
|
nativeType = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
|
||||||
|
break;
|
||||||
|
case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
|
||||||
|
nativeType = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (AudioService.DEBUG_DEVICES) {
|
||||||
|
Log.i(TAG, "btHeadsetDeviceToAudioDevice btDevice: " + btDevice
|
||||||
|
+ " btClass: " + (btClass == null ? "Unknown" : btClass)
|
||||||
|
+ " nativeType: " + nativeType + " address: " + address);
|
||||||
|
}
|
||||||
|
return new AudioDeviceAttributes(nativeType, address);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) {
|
private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) {
|
||||||
if (btDevice == null) {
|
if (btDevice == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
String address = btDevice.getAddress();
|
|
||||||
BluetoothClass btClass = btDevice.getBluetoothClass();
|
|
||||||
int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
|
int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
|
||||||
|
AudioDeviceAttributes audioDevice = btHeadsetDeviceToAudioDevice(btDevice);
|
||||||
|
String btDeviceName = getName(btDevice);
|
||||||
|
boolean result = false;
|
||||||
|
if (isActive) {
|
||||||
|
result |= mDeviceBroker.handleDeviceConnection(isActive, audioDevice.getInternalType(),
|
||||||
|
audioDevice.getAddress(), btDeviceName);
|
||||||
|
} else {
|
||||||
int[] outDeviceTypes = {
|
int[] outDeviceTypes = {
|
||||||
AudioSystem.DEVICE_OUT_BLUETOOTH_SCO,
|
AudioSystem.DEVICE_OUT_BLUETOOTH_SCO,
|
||||||
AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
|
AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
|
||||||
AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT
|
AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT
|
||||||
};
|
};
|
||||||
if (btClass != null) {
|
|
||||||
switch (btClass.getDeviceClass()) {
|
|
||||||
case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
|
|
||||||
case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
|
|
||||||
outDeviceTypes = new int[] { AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET };
|
|
||||||
break;
|
|
||||||
case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
|
|
||||||
outDeviceTypes = new int[] { AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT };
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
|
|
||||||
address = "";
|
|
||||||
}
|
|
||||||
String btDeviceName = getName(btDevice);
|
|
||||||
boolean result = false;
|
|
||||||
if (isActive) {
|
|
||||||
result |= mDeviceBroker.handleDeviceConnection(
|
|
||||||
isActive, outDeviceTypes[0], address, btDeviceName);
|
|
||||||
} else {
|
|
||||||
for (int outDeviceType : outDeviceTypes) {
|
for (int outDeviceType : outDeviceTypes) {
|
||||||
result |= mDeviceBroker.handleDeviceConnection(
|
result |= mDeviceBroker.handleDeviceConnection(
|
||||||
isActive, outDeviceType, address, btDeviceName);
|
isActive, outDeviceType, audioDevice.getAddress(), btDeviceName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// handleDeviceConnection() && result to make sure the method get executed
|
// handleDeviceConnection() && result to make sure the method get executed
|
||||||
result = mDeviceBroker.handleDeviceConnection(
|
result = mDeviceBroker.handleDeviceConnection(
|
||||||
isActive, inDevice, address, btDeviceName) && result;
|
isActive, inDevice, audioDevice.getAddress(), btDeviceName) && result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user