A2DP switch device refactor
Bluetooth mainline effort to reduce AudioManager API Test: Manual Tag: #refactor Bug: 190422401 Fix: 197715842 Fix: 197932292 Merged-In: I65c6561969d443e80f0a49256770279cd0959352 Change-Id: I65c6561969d443e80f0a49256770279cd0959352
This commit is contained in:
committed by
William Escande
parent
8aa04b89e0
commit
3fe5af4890
@@ -113,6 +113,7 @@ package android.media {
|
|||||||
public class AudioManager {
|
public class AudioManager {
|
||||||
method public void adjustStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
|
method public void adjustStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
|
||||||
method public void adjustSuggestedStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
|
method public void adjustSuggestedStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
|
||||||
|
method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void handleBluetoothActiveDeviceChanged(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothDevice, @NonNull android.media.BtProfileConnectionInfo);
|
||||||
method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setA2dpSuspended(boolean);
|
method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setA2dpSuspended(boolean);
|
||||||
method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setBluetoothHeadsetProperties(@NonNull String, boolean, boolean);
|
method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setBluetoothHeadsetProperties(@NonNull String, boolean, boolean);
|
||||||
method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setHfpEnabled(boolean);
|
method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setHfpEnabled(boolean);
|
||||||
@@ -122,6 +123,19 @@ package android.media {
|
|||||||
field public static final int FLAG_FROM_KEY = 4096; // 0x1000
|
field public static final int FLAG_FROM_KEY = 4096; // 0x1000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class BtProfileConnectionInfo implements android.os.Parcelable {
|
||||||
|
method @NonNull public static android.media.BtProfileConnectionInfo a2dpInfo(boolean, int);
|
||||||
|
method public int describeContents();
|
||||||
|
method public boolean getIsLeOutput();
|
||||||
|
method public int getProfile();
|
||||||
|
method public boolean getSuppressNoisyIntent();
|
||||||
|
method public int getVolume();
|
||||||
|
method @NonNull public static android.media.BtProfileConnectionInfo hearingAidInfo(boolean);
|
||||||
|
method @NonNull public static android.media.BtProfileConnectionInfo leAudio(boolean, boolean);
|
||||||
|
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||||
|
field @NonNull public static final android.os.Parcelable.Creator<android.media.BtProfileConnectionInfo> CREATOR;
|
||||||
|
}
|
||||||
|
|
||||||
public class MediaMetadataRetriever implements java.lang.AutoCloseable {
|
public class MediaMetadataRetriever implements java.lang.AutoCloseable {
|
||||||
field public static final int METADATA_KEY_VIDEO_CODEC_MIME_TYPE = 40; // 0x28
|
field public static final int METADATA_KEY_VIDEO_CODEC_MIME_TYPE = 40; // 0x28
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import android.app.NotificationManager;
|
|||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.bluetooth.BluetoothCodecConfig;
|
import android.bluetooth.BluetoothCodecConfig;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.bluetooth.BluetoothProfile;
|
|
||||||
import android.compat.annotation.UnsupportedAppUsage;
|
import android.compat.annotation.UnsupportedAppUsage;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -5796,112 +5795,25 @@ public class AudioManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicate Hearing Aid connection state change and eventually suppress
|
|
||||||
* the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
|
|
||||||
* This operation is asynchronous but its execution will still be sequentially scheduled
|
|
||||||
* relative to calls to {@link #setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
|
|
||||||
* * BluetoothDevice, int, int, boolean, int)} and
|
|
||||||
* and {@link #handleBluetoothA2dpDeviceConfigChange(BluetoothDevice)}.
|
|
||||||
* @param device Bluetooth device connected/disconnected
|
|
||||||
* @param state new connection state (BluetoothProfile.STATE_xxx)
|
|
||||||
* @param musicDevice Default get system volume for the connecting device.
|
|
||||||
* (either {@link android.bluetooth.BluetoothProfile.hearingaid} or
|
|
||||||
* {@link android.bluetooth.BluetoothProfile.HEARING_AID})
|
|
||||||
* @param suppressNoisyIntent if true the
|
|
||||||
* {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be sent.
|
|
||||||
* {@hide}
|
|
||||||
*/
|
|
||||||
public void setBluetoothHearingAidDeviceConnectionState(
|
|
||||||
BluetoothDevice device, int state, boolean suppressNoisyIntent,
|
|
||||||
int musicDevice) {
|
|
||||||
final IAudioService service = getService();
|
|
||||||
try {
|
|
||||||
service.setBluetoothHearingAidDeviceConnectionState(device,
|
|
||||||
state, suppressNoisyIntent, musicDevice);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicate Le Audio output device connection state change and eventually suppress
|
* Indicate Bluetooth profile connection state change.
|
||||||
* the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
|
* Configuration changes for A2DP are indicated by having the same <code>newDevice</code> and
|
||||||
* @param device Bluetooth device connected/disconnected
|
* <code>previousDevice</code>
|
||||||
* @param state new connection state (BluetoothProfile.STATE_xxx)
|
* This operation is asynchronous.
|
||||||
* @param suppressNoisyIntent if true the
|
*
|
||||||
* {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be sent.
|
* @param newDevice Bluetooth device connected or null if there is no new devices
|
||||||
* {@hide}
|
* @param previousDevice Bluetooth device disconnected or null if there is no disconnected
|
||||||
*/
|
* devices
|
||||||
public void setBluetoothLeAudioOutDeviceConnectionState(BluetoothDevice device, int state,
|
* @param info contain all info related to the device. {@link BtProfileConnectionInfo}
|
||||||
boolean suppressNoisyIntent) {
|
|
||||||
final IAudioService service = getService();
|
|
||||||
try {
|
|
||||||
service.setBluetoothLeAudioOutDeviceConnectionState(device, state, suppressNoisyIntent);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicate Le Audio input connection state change.
|
|
||||||
* @param device Bluetooth device connected/disconnected
|
|
||||||
* @param state new connection state (BluetoothProfile.STATE_xxx)
|
|
||||||
* {@hide}
|
|
||||||
*/
|
|
||||||
public void setBluetoothLeAudioInDeviceConnectionState(BluetoothDevice device, int state) {
|
|
||||||
final IAudioService service = getService();
|
|
||||||
try {
|
|
||||||
service.setBluetoothLeAudioInDeviceConnectionState(device, state);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicate A2DP source or sink connection state change and eventually suppress
|
|
||||||
* the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
|
|
||||||
* This operation is asynchronous but its execution will still be sequentially scheduled
|
|
||||||
* relative to calls to {@link #setBluetoothHearingAidDeviceConnectionState(BluetoothDevice,
|
|
||||||
* int, boolean, int)} and
|
|
||||||
* {@link #handleBluetoothA2dpDeviceConfigChange(BluetoothDevice)}.
|
|
||||||
* @param device Bluetooth device connected/disconnected
|
|
||||||
* @param state new connection state, {@link BluetoothProfile#STATE_CONNECTED}
|
|
||||||
* or {@link BluetoothProfile#STATE_DISCONNECTED}
|
|
||||||
* @param profile profile for the A2DP device
|
|
||||||
* @param a2dpVolume New volume for the connecting device. Does nothing if disconnecting.
|
|
||||||
* (either {@link android.bluetooth.BluetoothProfile.A2DP} or
|
|
||||||
* {@link android.bluetooth.BluetoothProfile.A2DP_SINK})
|
|
||||||
* @param suppressNoisyIntent if true the
|
|
||||||
* {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be sent.
|
|
||||||
* {@hide}
|
* {@hide}
|
||||||
*/
|
*/
|
||||||
public void setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
|
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
||||||
BluetoothDevice device, int state,
|
@RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK)
|
||||||
int profile, boolean suppressNoisyIntent, int a2dpVolume) {
|
public void handleBluetoothActiveDeviceChanged(@Nullable BluetoothDevice newDevice,
|
||||||
|
@Nullable BluetoothDevice previousDevice, @NonNull BtProfileConnectionInfo info) {
|
||||||
final IAudioService service = getService();
|
final IAudioService service = getService();
|
||||||
try {
|
try {
|
||||||
service.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device,
|
service.handleBluetoothActiveDeviceChanged(newDevice, previousDevice, info);
|
||||||
state, profile, suppressNoisyIntent, a2dpVolume);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicate A2DP device configuration has changed.
|
|
||||||
* This operation is asynchronous but its execution will still be sequentially scheduled
|
|
||||||
* relative to calls to
|
|
||||||
* {@link #setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(BluetoothDevice, int, int,
|
|
||||||
* boolean, int)} and
|
|
||||||
* {@link #setBluetoothHearingAidDeviceConnectionState(BluetoothDevice, int, boolean, int)}
|
|
||||||
* @param device Bluetooth device whose configuration has changed.
|
|
||||||
* {@hide}
|
|
||||||
*/
|
|
||||||
public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device) {
|
|
||||||
final IAudioService service = getService();
|
|
||||||
try {
|
|
||||||
service.handleBluetoothA2dpDeviceConfigChange(device);
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowFromSystemServer();
|
throw e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
|
|||||||
20
media/java/android/media/BtProfileConnectionInfo.aidl
Normal file
20
media/java/android/media/BtProfileConnectionInfo.aidl
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.media;
|
||||||
|
|
||||||
|
parcelable BtProfileConnectionInfo;
|
||||||
|
|
||||||
163
media/java/android/media/BtProfileConnectionInfo.java
Normal file
163
media/java/android/media/BtProfileConnectionInfo.java
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package android.media;
|
||||||
|
|
||||||
|
import android.annotation.IntDef;
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.SystemApi;
|
||||||
|
import android.bluetooth.BluetoothProfile;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains information about Bluetooth profile connection state changed
|
||||||
|
* {@hide}
|
||||||
|
*/
|
||||||
|
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
||||||
|
public final class BtProfileConnectionInfo implements Parcelable {
|
||||||
|
/** @hide */
|
||||||
|
@IntDef({
|
||||||
|
BluetoothProfile.A2DP,
|
||||||
|
BluetoothProfile.A2DP_SINK, // Can only be set by BtHelper
|
||||||
|
BluetoothProfile.HEADSET, // Can only be set by BtHelper
|
||||||
|
BluetoothProfile.HEARING_AID,
|
||||||
|
BluetoothProfile.LE_AUDIO,
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface BtProfile {}
|
||||||
|
|
||||||
|
private final @BtProfile int mProfile;
|
||||||
|
private final boolean mSupprNoisy;
|
||||||
|
private final int mVolume;
|
||||||
|
private final boolean mIsLeOutput;
|
||||||
|
|
||||||
|
private BtProfileConnectionInfo(@BtProfile int profile, boolean suppressNoisyIntent, int volume,
|
||||||
|
boolean isLeOutput) {
|
||||||
|
mProfile = profile;
|
||||||
|
mSupprNoisy = suppressNoisyIntent;
|
||||||
|
mVolume = volume;
|
||||||
|
mIsLeOutput = isLeOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor used by BtHelper when a profile is connected
|
||||||
|
* {@hide}
|
||||||
|
*/
|
||||||
|
public BtProfileConnectionInfo(@BtProfile int profile) {
|
||||||
|
this(profile, false, -1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final @NonNull Parcelable.Creator<BtProfileConnectionInfo> CREATOR =
|
||||||
|
new Parcelable.Creator<BtProfileConnectionInfo>() {
|
||||||
|
@Override
|
||||||
|
public BtProfileConnectionInfo createFromParcel(Parcel source) {
|
||||||
|
return new BtProfileConnectionInfo(source.readInt(), source.readBoolean(),
|
||||||
|
source.readInt(), source.readBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BtProfileConnectionInfo[] newArray(int size) {
|
||||||
|
return new BtProfileConnectionInfo[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(@NonNull Parcel dest, @WriteFlags int flags) {
|
||||||
|
dest.writeInt(mProfile);
|
||||||
|
dest.writeBoolean(mSupprNoisy);
|
||||||
|
dest.writeInt(mVolume);
|
||||||
|
dest.writeBoolean(mIsLeOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for A2dp info
|
||||||
|
*
|
||||||
|
* @param suppressNoisyIntent if true the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY}
|
||||||
|
* intent will not be sent.
|
||||||
|
*
|
||||||
|
* @param volume of device -1 to ignore value
|
||||||
|
*/
|
||||||
|
public static @NonNull BtProfileConnectionInfo a2dpInfo(boolean suppressNoisyIntent,
|
||||||
|
int volume) {
|
||||||
|
return new BtProfileConnectionInfo(BluetoothProfile.A2DP, suppressNoisyIntent, volume,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for hearing aid info
|
||||||
|
*
|
||||||
|
* @param suppressNoisyIntent if true the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY}
|
||||||
|
* intent will not be sent.
|
||||||
|
*/
|
||||||
|
public static @NonNull BtProfileConnectionInfo hearingAidInfo(boolean suppressNoisyIntent) {
|
||||||
|
return new BtProfileConnectionInfo(BluetoothProfile.HEARING_AID, suppressNoisyIntent, -1,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor for le audio info
|
||||||
|
*
|
||||||
|
* @param suppressNoisyIntent if true the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY}
|
||||||
|
* intent will not be sent.
|
||||||
|
*
|
||||||
|
* @param isLeOutput if true mean the device is an output device, if false it's an input device
|
||||||
|
*/
|
||||||
|
public static @NonNull BtProfileConnectionInfo leAudio(boolean suppressNoisyIntent,
|
||||||
|
boolean isLeOutput) {
|
||||||
|
return new BtProfileConnectionInfo(BluetoothProfile.LE_AUDIO, suppressNoisyIntent, -1,
|
||||||
|
isLeOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The profile connection
|
||||||
|
*/
|
||||||
|
public @BtProfile int getProfile() {
|
||||||
|
return mProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@code true} if {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be
|
||||||
|
* sent
|
||||||
|
*/
|
||||||
|
public boolean getSuppressNoisyIntent() {
|
||||||
|
return mSupprNoisy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only for {@link BluetoothProfile.A2DP} profile
|
||||||
|
* @return the volume of the connection or -1 if the value is ignored
|
||||||
|
*/
|
||||||
|
public int getVolume() {
|
||||||
|
return mVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only for {@link BluetoothProfile.LE_AUDIO} profile
|
||||||
|
* @return {@code true} is the LE device is an output device, {@code false} if it's an input
|
||||||
|
* device
|
||||||
|
*/
|
||||||
|
public boolean getIsLeOutput() {
|
||||||
|
return mIsLeOutput;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ import android.media.AudioFocusInfo;
|
|||||||
import android.media.AudioPlaybackConfiguration;
|
import android.media.AudioPlaybackConfiguration;
|
||||||
import android.media.AudioRecordingConfiguration;
|
import android.media.AudioRecordingConfiguration;
|
||||||
import android.media.AudioRoutesInfo;
|
import android.media.AudioRoutesInfo;
|
||||||
|
import android.media.BtProfileConnectionInfo;
|
||||||
import android.media.IAudioFocusDispatcher;
|
import android.media.IAudioFocusDispatcher;
|
||||||
import android.media.IAudioModeDispatcher;
|
import android.media.IAudioModeDispatcher;
|
||||||
import android.media.IAudioRoutesObserver;
|
import android.media.IAudioRoutesObserver;
|
||||||
@@ -207,8 +208,6 @@ interface IAudioService {
|
|||||||
void setWiredDeviceConnectionState(int type, int state, String address, String name,
|
void setWiredDeviceConnectionState(int type, int state, String address, String name,
|
||||||
String caller);
|
String caller);
|
||||||
|
|
||||||
void handleBluetoothA2dpDeviceConfigChange(in BluetoothDevice device);
|
|
||||||
|
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer);
|
AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer);
|
||||||
|
|
||||||
@@ -268,16 +267,8 @@ interface IAudioService {
|
|||||||
|
|
||||||
oneway void playerHasOpPlayAudio(in int piid, in boolean hasOpPlayAudio);
|
oneway void playerHasOpPlayAudio(in int piid, in boolean hasOpPlayAudio);
|
||||||
|
|
||||||
void setBluetoothHearingAidDeviceConnectionState(in BluetoothDevice device,
|
void handleBluetoothActiveDeviceChanged(in BluetoothDevice newDevice,
|
||||||
int state, boolean suppressNoisyIntent, int musicDevice);
|
in BluetoothDevice previousDevice, in BtProfileConnectionInfo info);
|
||||||
|
|
||||||
void setBluetoothLeAudioOutDeviceConnectionState(in BluetoothDevice device, int state,
|
|
||||||
boolean suppressNoisyIntent);
|
|
||||||
|
|
||||||
void setBluetoothLeAudioInDeviceConnectionState(in BluetoothDevice device, int state);
|
|
||||||
|
|
||||||
void setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(in BluetoothDevice device,
|
|
||||||
int state, int profile, boolean suppressNoisyIntent, int a2dpVolume);
|
|
||||||
|
|
||||||
oneway void setFocusRequestResultFromExtPolicy(in AudioFocusInfo afi, int requestResult,
|
oneway void setFocusRequestResultFromExtPolicy(in AudioFocusInfo afi, int requestResult,
|
||||||
in IAudioPolicyCallback pcb);
|
in IAudioPolicyCallback pcb);
|
||||||
|
|||||||
@@ -17,12 +17,9 @@ package com.android.server.audio;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.bluetooth.BluetoothA2dp;
|
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.bluetooth.BluetoothHeadset;
|
import android.bluetooth.BluetoothHeadset;
|
||||||
import android.bluetooth.BluetoothHearingAid;
|
|
||||||
import android.bluetooth.BluetoothProfile;
|
import android.bluetooth.BluetoothProfile;
|
||||||
import android.bluetooth.BluetoothLeAudio;
|
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -32,6 +29,7 @@ import android.media.AudioDeviceInfo;
|
|||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.media.AudioRoutesInfo;
|
import android.media.AudioRoutesInfo;
|
||||||
import android.media.AudioSystem;
|
import android.media.AudioSystem;
|
||||||
|
import android.media.BtProfileConnectionInfo;
|
||||||
import android.media.IAudioRoutesObserver;
|
import android.media.IAudioRoutesObserver;
|
||||||
import android.media.ICapturePresetDevicesRoleDispatcher;
|
import android.media.ICapturePresetDevicesRoleDispatcher;
|
||||||
import android.media.ICommunicationDeviceDispatcher;
|
import android.media.ICommunicationDeviceDispatcher;
|
||||||
@@ -516,29 +514,82 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*package*/ static final class BtDeviceConnectionInfo {
|
/*package*/ static final class BtDeviceChangedData {
|
||||||
final @NonNull BluetoothDevice mDevice;
|
final @Nullable BluetoothDevice mNewDevice;
|
||||||
final @AudioService.BtProfileConnectionState int mState;
|
final @Nullable BluetoothDevice mPreviousDevice;
|
||||||
final int mProfile;
|
final @NonNull BtProfileConnectionInfo mInfo;
|
||||||
final boolean mSupprNoisy;
|
final @NonNull String mEventSource;
|
||||||
final int mVolume;
|
|
||||||
|
|
||||||
BtDeviceConnectionInfo(@NonNull BluetoothDevice device,
|
BtDeviceChangedData(@Nullable BluetoothDevice newDevice,
|
||||||
@AudioService.BtProfileConnectionState int state,
|
@Nullable BluetoothDevice previousDevice,
|
||||||
int profile, boolean suppressNoisyIntent, int vol) {
|
@NonNull BtProfileConnectionInfo info, @NonNull String eventSource) {
|
||||||
mDevice = device;
|
mNewDevice = newDevice;
|
||||||
mState = state;
|
mPreviousDevice = previousDevice;
|
||||||
mProfile = profile;
|
mInfo = info;
|
||||||
mSupprNoisy = suppressNoisyIntent;
|
mEventSource = eventSource;
|
||||||
mVolume = vol;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BtDeviceConnectionInfo(@NonNull BtDeviceConnectionInfo info) {
|
@Override
|
||||||
mDevice = info.mDevice;
|
public String toString() {
|
||||||
mState = info.mState;
|
return "BtDeviceChangedData profile=" + BluetoothProfile.getProfileName(
|
||||||
mProfile = info.mProfile;
|
mInfo.getProfile())
|
||||||
mSupprNoisy = info.mSupprNoisy;
|
+ ", switch device: [" + mPreviousDevice + "] -> [" + mNewDevice + "]";
|
||||||
mVolume = info.mVolume;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ static final class BtDeviceInfo {
|
||||||
|
final @NonNull BluetoothDevice mDevice;
|
||||||
|
final @AudioService.BtProfileConnectionState int mState;
|
||||||
|
final @AudioService.BtProfile int mProfile;
|
||||||
|
final boolean mSupprNoisy;
|
||||||
|
final int mVolume;
|
||||||
|
final boolean mIsLeOutput;
|
||||||
|
final @NonNull String mEventSource;
|
||||||
|
final @AudioSystem.AudioFormatNativeEnumForBtCodec int mCodec;
|
||||||
|
final int mAudioSystemDevice;
|
||||||
|
final int mMusicDevice;
|
||||||
|
|
||||||
|
BtDeviceInfo(@NonNull BtDeviceChangedData d, @NonNull BluetoothDevice device, int state,
|
||||||
|
int audioDevice, @AudioSystem.AudioFormatNativeEnumForBtCodec int codec) {
|
||||||
|
mDevice = device;
|
||||||
|
mState = state;
|
||||||
|
mProfile = d.mInfo.getProfile();
|
||||||
|
mSupprNoisy = d.mInfo.getSuppressNoisyIntent();
|
||||||
|
mVolume = d.mInfo.getVolume();
|
||||||
|
mIsLeOutput = d.mInfo.getIsLeOutput();
|
||||||
|
mEventSource = d.mEventSource;
|
||||||
|
mAudioSystemDevice = audioDevice;
|
||||||
|
mMusicDevice = AudioSystem.DEVICE_NONE;
|
||||||
|
mCodec = codec;
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor used by AudioDeviceBroker to search similar message
|
||||||
|
BtDeviceInfo(@NonNull BluetoothDevice device, int profile) {
|
||||||
|
mDevice = device;
|
||||||
|
mProfile = profile;
|
||||||
|
mEventSource = "";
|
||||||
|
mMusicDevice = AudioSystem.DEVICE_NONE;
|
||||||
|
mCodec = AudioSystem.AUDIO_FORMAT_DEFAULT;
|
||||||
|
mAudioSystemDevice = 0;
|
||||||
|
mState = 0;
|
||||||
|
mSupprNoisy = false;
|
||||||
|
mVolume = -1;
|
||||||
|
mIsLeOutput = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor used by AudioDeviceInventory when config change failed
|
||||||
|
BtDeviceInfo(@NonNull BluetoothDevice device, int profile, int state, int musicDevice,
|
||||||
|
int audioSystemDevice) {
|
||||||
|
mDevice = device;
|
||||||
|
mProfile = profile;
|
||||||
|
mEventSource = "";
|
||||||
|
mMusicDevice = musicDevice;
|
||||||
|
mCodec = AudioSystem.AUDIO_FORMAT_DEFAULT;
|
||||||
|
mAudioSystemDevice = audioSystemDevice;
|
||||||
|
mState = state;
|
||||||
|
mSupprNoisy = false;
|
||||||
|
mVolume = -1;
|
||||||
|
mIsLeOutput = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// redefine equality op so we can match messages intended for this device
|
// redefine equality op so we can match messages intended for this device
|
||||||
@@ -550,16 +601,52 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
if (this == o) {
|
if (this == o) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (o instanceof BtDeviceConnectionInfo) {
|
if (o instanceof BtDeviceInfo) {
|
||||||
return mDevice.equals(((BtDeviceConnectionInfo) o).mDevice);
|
return mProfile == ((BtDeviceInfo) o).mProfile
|
||||||
|
&& mDevice.equals(((BtDeviceInfo) o).mDevice);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
BtDeviceInfo createBtDeviceInfo(@NonNull BtDeviceChangedData d, @NonNull BluetoothDevice device,
|
||||||
public String toString() {
|
int state) {
|
||||||
return "BtDeviceConnectionInfo dev=" + mDevice.toString();
|
int audioDevice;
|
||||||
|
int codec = AudioSystem.AUDIO_FORMAT_DEFAULT;
|
||||||
|
switch (d.mInfo.getProfile()) {
|
||||||
|
case BluetoothProfile.A2DP_SINK:
|
||||||
|
audioDevice = AudioSystem.DEVICE_IN_BLUETOOTH_A2DP;
|
||||||
|
break;
|
||||||
|
case BluetoothProfile.A2DP:
|
||||||
|
audioDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
|
||||||
|
synchronized (mDeviceStateLock) {
|
||||||
|
codec = mBtHelper.getA2dpCodec(device);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BluetoothProfile.HEARING_AID:
|
||||||
|
audioDevice = AudioSystem.DEVICE_OUT_HEARING_AID;
|
||||||
|
break;
|
||||||
|
case BluetoothProfile.LE_AUDIO:
|
||||||
|
if (d.mInfo.getIsLeOutput()) {
|
||||||
|
audioDevice = AudioSystem.DEVICE_OUT_BLE_HEADSET;
|
||||||
|
} else {
|
||||||
|
audioDevice = AudioSystem.DEVICE_IN_BLE_HEADSET;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: throw new IllegalArgumentException("Invalid profile " + d.mInfo.getProfile());
|
||||||
}
|
}
|
||||||
|
return new BtDeviceInfo(d, device, state, audioDevice, codec);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btMediaMetricRecord(@NonNull BluetoothDevice device, String state,
|
||||||
|
@NonNull BtDeviceChangedData data) {
|
||||||
|
final String name = TextUtils.emptyIfNull(device.getName());
|
||||||
|
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR
|
||||||
|
+ "queueOnBluetoothActiveDeviceChanged")
|
||||||
|
.set(MediaMetrics.Property.STATE, state)
|
||||||
|
.set(MediaMetrics.Property.STATUS, data.mInfo.getProfile())
|
||||||
|
.set(MediaMetrics.Property.NAME, name)
|
||||||
|
.record();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -567,116 +654,37 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
* not just a simple message post
|
* not just a simple message post
|
||||||
* @param info struct with the (dis)connection information
|
* @param info struct with the (dis)connection information
|
||||||
*/
|
*/
|
||||||
/*package*/ void queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
|
/*package*/ void queueOnBluetoothActiveDeviceChanged(@NonNull BtDeviceChangedData data) {
|
||||||
@NonNull BtDeviceConnectionInfo info) {
|
if (data.mInfo.getProfile() == BluetoothProfile.A2DP && data.mPreviousDevice != null
|
||||||
final String name = TextUtils.emptyIfNull(info.mDevice.getName());
|
&& data.mPreviousDevice.equals(data.mNewDevice)) {
|
||||||
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR
|
final String name = TextUtils.emptyIfNull(data.mNewDevice.getName());
|
||||||
+ "postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent")
|
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR
|
||||||
.set(MediaMetrics.Property.STATE, info.mState == BluetoothProfile.STATE_CONNECTED
|
+ "queueOnBluetoothActiveDeviceChanged_update")
|
||||||
? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED)
|
.set(MediaMetrics.Property.NAME, name)
|
||||||
.set(MediaMetrics.Property.INDEX, info.mVolume)
|
.set(MediaMetrics.Property.STATUS, data.mInfo.getProfile())
|
||||||
.set(MediaMetrics.Property.NAME, name)
|
.record();
|
||||||
.record();
|
synchronized (mDeviceStateLock) {
|
||||||
|
postBluetoothA2dpDeviceConfigChange(data.mNewDevice);
|
||||||
// operations of removing and posting messages related to A2DP device state change must be
|
}
|
||||||
// mutually exclusive
|
} else {
|
||||||
synchronized (mDeviceStateLock) {
|
synchronized (mDeviceStateLock) {
|
||||||
// when receiving a request to change the connection state of a device, this last
|
if (data.mPreviousDevice != null) {
|
||||||
// request is the source of truth, so cancel all previous requests that are already in
|
btMediaMetricRecord(data.mPreviousDevice, MediaMetrics.Value.DISCONNECTED,
|
||||||
// the handler
|
data);
|
||||||
removeScheduledA2dpEvents(info.mDevice);
|
sendLMsgNoDelay(MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT, SENDMSG_QUEUE,
|
||||||
|
createBtDeviceInfo(data, data.mPreviousDevice,
|
||||||
sendLMsgNoDelay(
|
BluetoothProfile.STATE_DISCONNECTED));
|
||||||
info.mState == BluetoothProfile.STATE_CONNECTED
|
}
|
||||||
? MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION
|
if (data.mNewDevice != null) {
|
||||||
: MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION,
|
btMediaMetricRecord(data.mNewDevice, MediaMetrics.Value.CONNECTED, data);
|
||||||
SENDMSG_QUEUE, info);
|
sendLMsgNoDelay(MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT, SENDMSG_QUEUE,
|
||||||
|
createBtDeviceInfo(data, data.mNewDevice,
|
||||||
|
BluetoothProfile.STATE_CONNECTED));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** remove all previously scheduled connection and state change events for the given device */
|
|
||||||
@GuardedBy("mDeviceStateLock")
|
|
||||||
private void removeScheduledA2dpEvents(@NonNull BluetoothDevice device) {
|
|
||||||
mBrokerHandler.removeEqualMessages(MSG_L_A2DP_DEVICE_CONFIG_CHANGE, device);
|
|
||||||
|
|
||||||
final BtDeviceConnectionInfo connectionInfoToRemove = new BtDeviceConnectionInfo(device,
|
|
||||||
// the next parameters of the constructor will be ignored when finding the message
|
|
||||||
// to remove as the equality of the message's object is tested on the device itself
|
|
||||||
// (see BtDeviceConnectionInfo.equals() method override)
|
|
||||||
BluetoothProfile.STATE_CONNECTED, 0, false, -1);
|
|
||||||
mBrokerHandler.removeEqualMessages(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION,
|
|
||||||
connectionInfoToRemove);
|
|
||||||
mBrokerHandler.removeEqualMessages(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION,
|
|
||||||
connectionInfoToRemove);
|
|
||||||
|
|
||||||
final BtHelper.BluetoothA2dpDeviceInfo devInfoToRemove =
|
|
||||||
new BtHelper.BluetoothA2dpDeviceInfo(device);
|
|
||||||
mBrokerHandler.removeEqualMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED,
|
|
||||||
devInfoToRemove);
|
|
||||||
mBrokerHandler.removeEqualMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED,
|
|
||||||
devInfoToRemove);
|
|
||||||
mBrokerHandler.removeEqualMessages(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE,
|
|
||||||
devInfoToRemove);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class HearingAidDeviceConnectionInfo {
|
|
||||||
final @NonNull BluetoothDevice mDevice;
|
|
||||||
final @AudioService.BtProfileConnectionState int mState;
|
|
||||||
final boolean mSupprNoisy;
|
|
||||||
final int mMusicDevice;
|
|
||||||
final @NonNull String mEventSource;
|
|
||||||
|
|
||||||
HearingAidDeviceConnectionInfo(@NonNull BluetoothDevice device,
|
|
||||||
@AudioService.BtProfileConnectionState int state,
|
|
||||||
boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource) {
|
|
||||||
mDevice = device;
|
|
||||||
mState = state;
|
|
||||||
mSupprNoisy = suppressNoisyIntent;
|
|
||||||
mMusicDevice = musicDevice;
|
|
||||||
mEventSource = eventSource;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void postBluetoothHearingAidDeviceConnectionState(
|
|
||||||
@NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
|
|
||||||
boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource) {
|
|
||||||
final HearingAidDeviceConnectionInfo info = new HearingAidDeviceConnectionInfo(
|
|
||||||
device, state, suppressNoisyIntent, musicDevice, eventSource);
|
|
||||||
sendLMsgNoDelay(MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class LeAudioDeviceConnectionInfo {
|
|
||||||
final @NonNull BluetoothDevice mDevice;
|
|
||||||
final @AudioService.BtProfileConnectionState int mState;
|
|
||||||
final boolean mSupprNoisy;
|
|
||||||
final @NonNull String mEventSource;
|
|
||||||
|
|
||||||
LeAudioDeviceConnectionInfo(@NonNull BluetoothDevice device,
|
|
||||||
@AudioService.BtProfileConnectionState int state,
|
|
||||||
boolean suppressNoisyIntent, @NonNull String eventSource) {
|
|
||||||
mDevice = device;
|
|
||||||
mState = state;
|
|
||||||
mSupprNoisy = suppressNoisyIntent;
|
|
||||||
mEventSource = eventSource;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void postBluetoothLeAudioOutDeviceConnectionState(
|
|
||||||
@NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
|
|
||||||
boolean suppressNoisyIntent, @NonNull String eventSource) {
|
|
||||||
final LeAudioDeviceConnectionInfo info = new LeAudioDeviceConnectionInfo(
|
|
||||||
device, state, suppressNoisyIntent, eventSource);
|
|
||||||
sendLMsgNoDelay(MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void postBluetoothLeAudioInDeviceConnectionState(
|
|
||||||
@NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
|
|
||||||
@NonNull String eventSource) {
|
|
||||||
final LeAudioDeviceConnectionInfo info = new LeAudioDeviceConnectionInfo(
|
|
||||||
device, state, false, eventSource);
|
|
||||||
sendLMsgNoDelay(MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current Bluetooth SCO audio active state indicated by BtHelper via setBluetoothScoOn().
|
* Current Bluetooth SCO audio active state indicated by BtHelper via setBluetoothScoOn().
|
||||||
*/
|
*/
|
||||||
@@ -926,19 +934,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("mDeviceStateLock")
|
@GuardedBy("mDeviceStateLock")
|
||||||
/*package*/ void postA2dpSinkConnection(@AudioService.BtProfileConnectionState int state,
|
/*package*/ void postBluetoothActiveDevice(BtDeviceInfo info, int delay) {
|
||||||
@NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) {
|
sendLMsg(MSG_L_SET_BT_ACTIVE_DEVICE, SENDMSG_QUEUE, info, delay);
|
||||||
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(@AudioService.BtProfileConnectionState int state,
|
|
||||||
@NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) {
|
|
||||||
sendILMsg(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE,
|
|
||||||
state, btDeviceInfo, delay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ void postSetWiredDeviceConnectionState(
|
/*package*/ void postSetWiredDeviceConnectionState(
|
||||||
@@ -946,72 +943,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
sendLMsg(MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE, SENDMSG_QUEUE, connectionState, delay);
|
sendLMsg(MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE, SENDMSG_QUEUE, connectionState, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ void postSetHearingAidConnectionState(
|
/*package*/ void postBtProfileDisconnected(int profile) {
|
||||||
@AudioService.BtProfileConnectionState int state,
|
sendIMsgNoDelay(MSG_I_BT_SERVICE_DISCONNECTED_PROFILE, SENDMSG_QUEUE, profile);
|
||||||
@NonNull BluetoothDevice device, int delay) {
|
|
||||||
sendILMsg(MSG_IL_SET_HEARING_AID_CONNECTION_STATE, SENDMSG_QUEUE,
|
|
||||||
state,
|
|
||||||
device,
|
|
||||||
delay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ void postSetLeAudioOutConnectionState(
|
/*package*/ void postBtProfileConnected(int profile, BluetoothProfile proxy) {
|
||||||
@AudioService.BtProfileConnectionState int state,
|
sendILMsgNoDelay(MSG_IL_BT_SERVICE_CONNECTED_PROFILE, SENDMSG_QUEUE, profile, proxy);
|
||||||
@NonNull BluetoothDevice device, int delay) {
|
|
||||||
sendILMsg(MSG_IL_SET_LE_AUDIO_OUT_CONNECTION_STATE, SENDMSG_QUEUE,
|
|
||||||
state,
|
|
||||||
device,
|
|
||||||
delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void postSetLeAudioInConnectionState(
|
|
||||||
@AudioService.BtProfileConnectionState int state,
|
|
||||||
@NonNull BluetoothDevice device) {
|
|
||||||
sendILMsgNoDelay(MSG_IL_SET_LE_AUDIO_IN_CONNECTION_STATE, SENDMSG_QUEUE,
|
|
||||||
state,
|
|
||||||
device);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void postDisconnectA2dp() {
|
|
||||||
sendMsgNoDelay(MSG_DISCONNECT_A2DP, SENDMSG_QUEUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void postDisconnectA2dpSink() {
|
|
||||||
sendMsgNoDelay(MSG_DISCONNECT_A2DP_SINK, SENDMSG_QUEUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void postDisconnectHearingAid() {
|
|
||||||
sendMsgNoDelay(MSG_DISCONNECT_BT_HEARING_AID, SENDMSG_QUEUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void postDisconnectLeAudio() {
|
|
||||||
sendMsgNoDelay(MSG_DISCONNECT_BT_LE_AUDIO, SENDMSG_QUEUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void postDisconnectHeadset() {
|
|
||||||
sendMsgNoDelay(MSG_DISCONNECT_BT_HEADSET, SENDMSG_QUEUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void postBtA2dpProfileConnected(BluetoothA2dp a2dpProfile) {
|
|
||||||
sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP, SENDMSG_QUEUE, a2dpProfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void postBtA2dpSinkProfileConnected(BluetoothProfile profile) {
|
|
||||||
sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK, SENDMSG_QUEUE, profile);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void postBtHeasetProfileConnected(BluetoothHeadset headsetProfile) {
|
|
||||||
sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET, SENDMSG_QUEUE, headsetProfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void postBtHearingAidProfileConnected(BluetoothHearingAid hearingAidProfile) {
|
|
||||||
sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID, SENDMSG_QUEUE,
|
|
||||||
hearingAidProfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void postBtLeAudioProfileConnected(BluetoothLeAudio leAudioProfile) {
|
|
||||||
sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_LE_AUDIO, SENDMSG_QUEUE,
|
|
||||||
leAudioProfile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ void postCommunicationRouteClientDied(CommunicationRouteClient client) {
|
/*package*/ void postCommunicationRouteClientDied(CommunicationRouteClient client) {
|
||||||
@@ -1069,13 +1006,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ void postSetA2dpSourceConnectionState(@BluetoothProfile.BtProfileState int state,
|
|
||||||
@NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
|
|
||||||
final int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0;
|
|
||||||
sendILMsgNoDelay(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE, state,
|
|
||||||
btDeviceInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void handleFailureToConnectToBtHeadsetService(int delay) {
|
/*package*/ void handleFailureToConnectToBtHeadsetService(int delay) {
|
||||||
sendMsg(MSG_BT_HEADSET_CNCT_FAILED, SENDMSG_REPLACE, delay);
|
sendMsg(MSG_BT_HEADSET_CNCT_FAILED, SENDMSG_REPLACE, delay);
|
||||||
}
|
}
|
||||||
@@ -1088,19 +1018,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
sendMsgNoDelay(fromA2dp ? MSG_REPORT_NEW_ROUTES_A2DP : MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP);
|
sendMsgNoDelay(fromA2dp ? MSG_REPORT_NEW_ROUTES_A2DP : MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ void postA2dpActiveDeviceChange(
|
|
||||||
@NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
|
|
||||||
sendLMsgNoDelay(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE, SENDMSG_QUEUE, btDeviceInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
// must be called synchronized on mConnectedDevices
|
// must be called synchronized on mConnectedDevices
|
||||||
/*package*/ boolean hasScheduledA2dpSinkConnectionState(BluetoothDevice btDevice) {
|
/*package*/ boolean hasScheduledA2dpConnection(BluetoothDevice btDevice) {
|
||||||
final BtHelper.BluetoothA2dpDeviceInfo devInfoToCheck =
|
final BtDeviceInfo devInfoToCheck = new BtDeviceInfo(btDevice, BluetoothProfile.A2DP);
|
||||||
new BtHelper.BluetoothA2dpDeviceInfo(btDevice);
|
return mBrokerHandler.hasEqualMessages(MSG_L_SET_BT_ACTIVE_DEVICE, devInfoToCheck);
|
||||||
return (mBrokerHandler.hasEqualMessages(
|
|
||||||
MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED, devInfoToCheck)
|
|
||||||
|| mBrokerHandler.hasEqualMessages(
|
|
||||||
MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED, devInfoToCheck));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ void setA2dpTimeout(String address, int a2dpCodec, int delayMs) {
|
/*package*/ void setA2dpTimeout(String address, int a2dpCodec, int delayMs) {
|
||||||
@@ -1124,12 +1045,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ int getA2dpCodec(@NonNull BluetoothDevice device) {
|
|
||||||
synchronized (mDeviceStateLock) {
|
|
||||||
return mBtHelper.getA2dpCodec(device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void broadcastStickyIntentToCurrentProfileGroup(Intent intent) {
|
/*package*/ void broadcastStickyIntentToCurrentProfileGroup(Intent intent) {
|
||||||
mSystemServer.broadcastStickyIntentToCurrentProfileGroup(intent);
|
mSystemServer.broadcastStickyIntentToCurrentProfileGroup(intent);
|
||||||
}
|
}
|
||||||
@@ -1285,39 +1200,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
mDeviceInventory.onReportNewRoutes();
|
mDeviceInventory.onReportNewRoutes();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED:
|
case MSG_L_SET_BT_ACTIVE_DEVICE:
|
||||||
case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED:
|
|
||||||
synchronized (mDeviceStateLock) {
|
synchronized (mDeviceStateLock) {
|
||||||
mDeviceInventory.onSetA2dpSinkConnectionState(
|
mDeviceInventory.onSetBtActiveDevice((BtDeviceInfo) msg.obj,
|
||||||
(BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE:
|
|
||||||
synchronized (mDeviceStateLock) {
|
|
||||||
mDeviceInventory.onSetA2dpSourceConnectionState(
|
|
||||||
(BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MSG_IL_SET_HEARING_AID_CONNECTION_STATE:
|
|
||||||
synchronized (mDeviceStateLock) {
|
|
||||||
mDeviceInventory.onSetHearingAidConnectionState(
|
|
||||||
(BluetoothDevice) msg.obj, msg.arg1,
|
|
||||||
mAudioService.getBluetoothContextualVolumeStream());
|
mAudioService.getBluetoothContextualVolumeStream());
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case MSG_IL_SET_LE_AUDIO_OUT_CONNECTION_STATE:
|
|
||||||
synchronized (mDeviceStateLock) {
|
|
||||||
mDeviceInventory.onSetLeAudioOutConnectionState(
|
|
||||||
(BluetoothDevice) msg.obj, msg.arg1,
|
|
||||||
mAudioService.getBluetoothContextualVolumeStream());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MSG_IL_SET_LE_AUDIO_IN_CONNECTION_STATE:
|
|
||||||
synchronized (mDeviceStateLock) {
|
|
||||||
mDeviceInventory.onSetLeAudioInConnectionState(
|
|
||||||
(BluetoothDevice) msg.obj, msg.arg1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MSG_BT_HEADSET_CNCT_FAILED:
|
case MSG_BT_HEADSET_CNCT_FAILED:
|
||||||
synchronized (mSetModeLock) {
|
synchronized (mSetModeLock) {
|
||||||
synchronized (mDeviceStateLock) {
|
synchronized (mDeviceStateLock) {
|
||||||
@@ -1332,14 +1219,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
|
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
|
||||||
final int a2dpCodec;
|
|
||||||
final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
|
final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
|
||||||
synchronized (mDeviceStateLock) {
|
synchronized (mDeviceStateLock) {
|
||||||
a2dpCodec = mBtHelper.getA2dpCodec(btDevice);
|
final int a2dpCodec = mBtHelper.getA2dpCodec(btDevice);
|
||||||
// TODO: name of method being called on AudioDeviceInventory is currently
|
mDeviceInventory.onBluetoothA2dpDeviceConfigChange(
|
||||||
// misleading (config change vs active device change), to be
|
|
||||||
// reconciliated once the BT side has been updated.
|
|
||||||
mDeviceInventory.onBluetoothA2dpActiveDeviceChange(
|
|
||||||
new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec),
|
new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec),
|
||||||
BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
|
BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
|
||||||
}
|
}
|
||||||
@@ -1392,96 +1275,47 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
mDeviceInventory.onToggleHdmi();
|
mDeviceInventory.onToggleHdmi();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
|
case MSG_I_BT_SERVICE_DISCONNECTED_PROFILE:
|
||||||
synchronized (mDeviceStateLock) {
|
if (msg.arg1 != BluetoothProfile.HEADSET) {
|
||||||
mDeviceInventory.onBluetoothA2dpActiveDeviceChange(
|
|
||||||
(BtHelper.BluetoothA2dpDeviceInfo) msg.obj,
|
|
||||||
BtHelper.EVENT_ACTIVE_DEVICE_CHANGE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MSG_DISCONNECT_A2DP:
|
|
||||||
synchronized (mDeviceStateLock) {
|
|
||||||
mDeviceInventory.disconnectA2dp();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MSG_DISCONNECT_A2DP_SINK:
|
|
||||||
synchronized (mDeviceStateLock) {
|
|
||||||
mDeviceInventory.disconnectA2dpSink();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MSG_DISCONNECT_BT_HEARING_AID:
|
|
||||||
synchronized (mDeviceStateLock) {
|
|
||||||
mDeviceInventory.disconnectHearingAid();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MSG_DISCONNECT_BT_HEADSET:
|
|
||||||
synchronized (mSetModeLock) {
|
|
||||||
synchronized (mDeviceStateLock) {
|
synchronized (mDeviceStateLock) {
|
||||||
mBtHelper.disconnectHeadset();
|
mDeviceInventory.onBtProfileDisconnected(msg.arg1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
synchronized (mSetModeLock) {
|
||||||
|
synchronized (mDeviceStateLock) {
|
||||||
|
mBtHelper.disconnectHeadset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MSG_DISCONNECT_BT_LE_AUDIO:
|
case MSG_IL_BT_SERVICE_CONNECTED_PROFILE:
|
||||||
synchronized(mDeviceStateLock) {
|
if (msg.arg1 != BluetoothProfile.HEADSET) {
|
||||||
mDeviceInventory.disconnectLeAudio();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP:
|
|
||||||
synchronized (mDeviceStateLock) {
|
|
||||||
mBtHelper.onA2dpProfileConnected((BluetoothA2dp) msg.obj);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK:
|
|
||||||
synchronized (mDeviceStateLock) {
|
|
||||||
mBtHelper.onA2dpSinkProfileConnected((BluetoothProfile) msg.obj);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID:
|
|
||||||
synchronized (mDeviceStateLock) {
|
|
||||||
mBtHelper.onHearingAidProfileConnected((BluetoothHearingAid) msg.obj);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MSG_L_BT_SERVICE_CONNECTED_PROFILE_LE_AUDIO:
|
|
||||||
synchronized(mDeviceStateLock) {
|
|
||||||
mBtHelper.onLeAudioProfileConnected((BluetoothLeAudio) msg.obj);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET:
|
|
||||||
synchronized (mSetModeLock) {
|
|
||||||
synchronized (mDeviceStateLock) {
|
synchronized (mDeviceStateLock) {
|
||||||
mBtHelper.onHeadsetProfileConnected((BluetoothHeadset) msg.obj);
|
mBtHelper.onBtProfileConnected(msg.arg1, (BluetoothProfile) msg.obj);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
synchronized (mSetModeLock) {
|
||||||
|
synchronized (mDeviceStateLock) {
|
||||||
|
mBtHelper.onHeadsetProfileConnected((BluetoothHeadset) msg.obj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION:
|
case MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT: {
|
||||||
case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION: {
|
final BtDeviceInfo info = (BtDeviceInfo) msg.obj;
|
||||||
final BtDeviceConnectionInfo info = (BtDeviceConnectionInfo) msg.obj;
|
if (info.mDevice == null) break;
|
||||||
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
|
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
|
||||||
"msg: setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent "
|
"msg: onBluetoothActiveDeviceChange "
|
||||||
+ " state=" + info.mState
|
+ " state=" + info.mState
|
||||||
// only querying address as this is the only readily available
|
// only querying address as this is the only readily available
|
||||||
// field on the device
|
// field on the device
|
||||||
+ " addr=" + info.mDevice.getAddress()
|
+ " addr=" + info.mDevice.getAddress()
|
||||||
+ " prof=" + info.mProfile + " supprNoisy=" + info.mSupprNoisy
|
+ " prof=" + info.mProfile
|
||||||
+ " vol=" + info.mVolume)).printLog(TAG));
|
|
||||||
synchronized (mDeviceStateLock) {
|
|
||||||
mDeviceInventory.setBluetoothA2dpDeviceConnectionState(
|
|
||||||
info.mDevice, info.mState, info.mProfile, info.mSupprNoisy,
|
|
||||||
AudioSystem.DEVICE_NONE, info.mVolume);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: {
|
|
||||||
final HearingAidDeviceConnectionInfo info =
|
|
||||||
(HearingAidDeviceConnectionInfo) msg.obj;
|
|
||||||
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
|
|
||||||
"msg: setHearingAidDeviceConnectionState state=" + info.mState
|
|
||||||
+ " addr=" + info.mDevice.getAddress()
|
|
||||||
+ " supprNoisy=" + info.mSupprNoisy
|
+ " supprNoisy=" + info.mSupprNoisy
|
||||||
+ " src=" + info.mEventSource)).printLog(TAG));
|
+ " src=" + info.mEventSource
|
||||||
|
)).printLog(TAG));
|
||||||
synchronized (mDeviceStateLock) {
|
synchronized (mDeviceStateLock) {
|
||||||
mDeviceInventory.setBluetoothHearingAidDeviceConnectionState(
|
mDeviceInventory.setBluetoothActiveDevice(info);
|
||||||
info.mDevice, info.mState, info.mSupprNoisy, info.mMusicDevice);
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY: {
|
case MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY: {
|
||||||
@@ -1524,31 +1358,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
final int capturePreset = msg.arg1;
|
final int capturePreset = msg.arg1;
|
||||||
mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset);
|
mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset);
|
||||||
} break;
|
} break;
|
||||||
case MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT: {
|
|
||||||
final LeAudioDeviceConnectionInfo info =
|
|
||||||
(LeAudioDeviceConnectionInfo) msg.obj;
|
|
||||||
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
|
|
||||||
"setLeAudioDeviceOutConnectionState state=" + info.mState
|
|
||||||
+ " addr=" + info.mDevice.getAddress()
|
|
||||||
+ " supprNoisy=" + info.mSupprNoisy
|
|
||||||
+ " src=" + info.mEventSource)).printLog(TAG));
|
|
||||||
synchronized (mDeviceStateLock) {
|
|
||||||
mDeviceInventory.setBluetoothLeAudioOutDeviceConnectionState(
|
|
||||||
info.mDevice, info.mState, info.mSupprNoisy);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT: {
|
|
||||||
final LeAudioDeviceConnectionInfo info =
|
|
||||||
(LeAudioDeviceConnectionInfo) msg.obj;
|
|
||||||
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
|
|
||||||
"setLeAudioDeviceInConnectionState state=" + info.mState
|
|
||||||
+ " addr=" + info.mDevice.getAddress()
|
|
||||||
+ " src=" + info.mEventSource)).printLog(TAG));
|
|
||||||
synchronized (mDeviceStateLock) {
|
|
||||||
mDeviceInventory.setBluetoothLeAudioInDeviceConnectionState(info.mDevice,
|
|
||||||
info.mState);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
default:
|
default:
|
||||||
Log.wtf(TAG, "Invalid message " + msg.what);
|
Log.wtf(TAG, "Invalid message " + msg.what);
|
||||||
}
|
}
|
||||||
@@ -1579,8 +1388,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
private static final int MSG_IIL_SET_FORCE_USE = 4;
|
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_IIL_SET_FORCE_BT_A2DP_USE = 5;
|
||||||
private static final int MSG_TOGGLE_HDMI = 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_L_SET_BT_ACTIVE_DEVICE = 7;
|
||||||
private static final int MSG_IL_SET_HEARING_AID_CONNECTION_STATE = 8;
|
|
||||||
private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
|
private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
|
||||||
private static final int MSG_IL_BTA2DP_TIMEOUT = 10;
|
private static final int MSG_IL_BTA2DP_TIMEOUT = 10;
|
||||||
|
|
||||||
@@ -1593,25 +1401,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15;
|
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_PID = 16;
|
||||||
|
|
||||||
// process active A2DP device change, obj is BtHelper.BluetoothA2dpDeviceInfo
|
private static final int MSG_I_BT_SERVICE_DISCONNECTED_PROFILE = 22;
|
||||||
private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE = 18;
|
private static final int MSG_IL_BT_SERVICE_CONNECTED_PROFILE = 23;
|
||||||
|
|
||||||
private static final int MSG_DISCONNECT_A2DP = 19;
|
|
||||||
private static final int MSG_DISCONNECT_A2DP_SINK = 20;
|
|
||||||
private static final int MSG_DISCONNECT_BT_HEARING_AID = 21;
|
|
||||||
private static final int MSG_DISCONNECT_BT_HEADSET = 22;
|
|
||||||
private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP = 23;
|
|
||||||
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;
|
|
||||||
|
|
||||||
// process change of state, obj is BtHelper.BluetoothA2dpDeviceInfo
|
|
||||||
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, obj is BtDeviceConnectionInfo
|
// process external command to (dis)connect an A2DP device, obj is BtDeviceConnectionInfo
|
||||||
private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION = 29;
|
private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 29;
|
||||||
private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION = 30;
|
|
||||||
|
|
||||||
// process external command to (dis)connect a hearing aid device
|
// process external command to (dis)connect a hearing aid device
|
||||||
private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 31;
|
private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 31;
|
||||||
@@ -1630,33 +1424,21 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
private static final int MSG_IL_SET_PREF_DEVICES_FOR_STRATEGY = 40;
|
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 final int MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY = 41;
|
||||||
|
|
||||||
private static final int MSG_IL_SET_LE_AUDIO_OUT_CONNECTION_STATE = 42;
|
private static final int MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT = 45;
|
||||||
private static final int MSG_IL_SET_LE_AUDIO_IN_CONNECTION_STATE = 43;
|
//
|
||||||
private static final int MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT = 44;
|
|
||||||
private static final int MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT = 45;
|
|
||||||
// process set volume for Le Audio, obj is BleVolumeInfo
|
// process set volume for Le Audio, obj is BleVolumeInfo
|
||||||
private static final int MSG_II_SET_LE_AUDIO_OUT_VOLUME = 46;
|
private static final int MSG_II_SET_LE_AUDIO_OUT_VOLUME = 46;
|
||||||
|
|
||||||
private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_LE_AUDIO = 47;
|
|
||||||
private static final int MSG_DISCONNECT_BT_LE_AUDIO = 48;
|
|
||||||
|
|
||||||
private static boolean isMessageHandledUnderWakelock(int msgId) {
|
private static boolean isMessageHandledUnderWakelock(int msgId) {
|
||||||
switch(msgId) {
|
switch(msgId) {
|
||||||
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
|
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
|
||||||
case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED:
|
case MSG_L_SET_BT_ACTIVE_DEVICE:
|
||||||
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_TIMEOUT:
|
case MSG_IL_BTA2DP_TIMEOUT:
|
||||||
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
|
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
|
||||||
case MSG_TOGGLE_HDMI:
|
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:
|
case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
|
||||||
case MSG_CHECK_MUTE_MUSIC:
|
case MSG_CHECK_MUTE_MUSIC:
|
||||||
case MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT:
|
|
||||||
case MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT:
|
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -1739,14 +1521,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
long time = SystemClock.uptimeMillis() + delay;
|
long time = SystemClock.uptimeMillis() + delay;
|
||||||
|
|
||||||
switch (msg) {
|
switch (msg) {
|
||||||
case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE:
|
case MSG_L_SET_BT_ACTIVE_DEVICE:
|
||||||
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_L_SET_WIRED_DEVICE_CONNECTION_STATE:
|
||||||
case MSG_IL_BTA2DP_TIMEOUT:
|
case MSG_IL_BTA2DP_TIMEOUT:
|
||||||
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
|
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
|
||||||
case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
|
|
||||||
if (sLastDeviceConnectMsgTime >= time) {
|
if (sLastDeviceConnectMsgTime >= time) {
|
||||||
// add a little delay to make sure messages are ordered as expected
|
// add a little delay to make sure messages are ordered as expected
|
||||||
time = sLastDeviceConnectMsgTime + 30;
|
time = sLastDeviceConnectMsgTime + 30;
|
||||||
@@ -1765,14 +1543,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
private static final Set<Integer> MESSAGES_MUTE_MUSIC;
|
private static final Set<Integer> MESSAGES_MUTE_MUSIC;
|
||||||
static {
|
static {
|
||||||
MESSAGES_MUTE_MUSIC = new HashSet<>();
|
MESSAGES_MUTE_MUSIC = new HashSet<>();
|
||||||
MESSAGES_MUTE_MUSIC.add(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED);
|
MESSAGES_MUTE_MUSIC.add(MSG_L_SET_BT_ACTIVE_DEVICE);
|
||||||
MESSAGES_MUTE_MUSIC.add(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED);
|
|
||||||
MESSAGES_MUTE_MUSIC.add(MSG_IL_SET_LE_AUDIO_OUT_CONNECTION_STATE);
|
|
||||||
MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONFIG_CHANGE);
|
MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONFIG_CHANGE);
|
||||||
MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE);
|
MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT);
|
||||||
MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION);
|
|
||||||
MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION);
|
|
||||||
MESSAGES_MUTE_MUSIC.add(MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT);
|
|
||||||
MESSAGES_MUTE_MUSIC.add(MSG_IIL_SET_FORCE_BT_A2DP_USE);
|
MESSAGES_MUTE_MUSIC.add(MSG_IIL_SET_FORCE_BT_A2DP_USE);
|
||||||
MESSAGES_MUTE_MUSIC.add(MSG_REPORT_NEW_ROUTES_A2DP);
|
MESSAGES_MUTE_MUSIC.add(MSG_REPORT_NEW_ROUTES_A2DP);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,8 @@
|
|||||||
package com.android.server.audio;
|
package com.android.server.audio;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.bluetooth.BluetoothA2dp;
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.bluetooth.BluetoothHearingAid;
|
|
||||||
import android.bluetooth.BluetoothLeAudio;
|
|
||||||
import android.bluetooth.BluetoothProfile;
|
import android.bluetooth.BluetoothProfile;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.media.AudioDeviceAttributes;
|
import android.media.AudioDeviceAttributes;
|
||||||
@@ -286,186 +283,102 @@ public class AudioDeviceInventory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// only public for mocking/spying
|
|
||||||
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
|
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
|
||||||
@VisibleForTesting
|
void onSetBtActiveDevice(@NonNull AudioDeviceBroker.BtDeviceInfo btInfo, int streamType) {
|
||||||
public void onSetA2dpSinkConnectionState(@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo,
|
|
||||||
@AudioService.BtProfileConnectionState int state) {
|
|
||||||
final BluetoothDevice btDevice = btInfo.getBtDevice();
|
|
||||||
int a2dpVolume = btInfo.getVolume();
|
|
||||||
if (AudioService.DEBUG_DEVICES) {
|
if (AudioService.DEBUG_DEVICES) {
|
||||||
Log.d(TAG, "onSetA2dpSinkConnectionState btDevice=" + btDevice + " state="
|
Log.d(TAG, "onSetBtActiveDevice"
|
||||||
+ state + " vol=" + a2dpVolume);
|
+ " btDevice=" + btInfo.mDevice
|
||||||
}
|
+ " profile=" + BluetoothProfile.getProfileName(btInfo.mProfile)
|
||||||
String address = btDevice.getAddress();
|
+ " state=" + BluetoothProfile.getConnectionStateName(btInfo.mState));
|
||||||
if (address == null) {
|
|
||||||
address = "";
|
|
||||||
}
|
}
|
||||||
|
String address = btInfo.mDevice.getAddress();
|
||||||
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
|
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
|
||||||
address = "";
|
address = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
final @AudioSystem.AudioFormatNativeEnumForBtCodec int a2dpCodec = btInfo.getCodec();
|
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent("BT connected:"
|
||||||
|
+ " addr=" + address
|
||||||
|
+ " profile=" + btInfo.mProfile
|
||||||
|
+ " state=" + btInfo.mState
|
||||||
|
+ " codec=" + AudioSystem.audioFormatToString(btInfo.mCodec)));
|
||||||
|
|
||||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
new MediaMetrics.Item(mMetricsId + "onSetBtActiveDevice")
|
||||||
"A2DP sink connected: device addr=" + address + " state=" + state
|
.set(MediaMetrics.Property.STATUS, btInfo.mProfile)
|
||||||
+ " codec=" + AudioSystem.audioFormatToString(a2dpCodec)
|
.set(MediaMetrics.Property.DEVICE,
|
||||||
+ " vol=" + a2dpVolume));
|
AudioSystem.getDeviceName(btInfo.mAudioSystemDevice))
|
||||||
|
|
||||||
new MediaMetrics.Item(mMetricsId + "a2dp")
|
|
||||||
.set(MediaMetrics.Property.ADDRESS, address)
|
.set(MediaMetrics.Property.ADDRESS, address)
|
||||||
.set(MediaMetrics.Property.ENCODING, AudioSystem.audioFormatToString(a2dpCodec))
|
.set(MediaMetrics.Property.ENCODING,
|
||||||
.set(MediaMetrics.Property.EVENT, "onSetA2dpSinkConnectionState")
|
AudioSystem.audioFormatToString(btInfo.mCodec))
|
||||||
.set(MediaMetrics.Property.INDEX, a2dpVolume)
|
.set(MediaMetrics.Property.EVENT, "onSetBtActiveDevice")
|
||||||
|
.set(MediaMetrics.Property.STREAM_TYPE,
|
||||||
|
AudioSystem.streamToString(streamType))
|
||||||
.set(MediaMetrics.Property.STATE,
|
.set(MediaMetrics.Property.STATE,
|
||||||
state == BluetoothProfile.STATE_CONNECTED
|
btInfo.mState == BluetoothProfile.STATE_CONNECTED
|
||||||
? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED)
|
? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED)
|
||||||
.record();
|
.record();
|
||||||
|
|
||||||
synchronized (mDevicesLock) {
|
synchronized (mDevicesLock) {
|
||||||
final String key = DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
final String key = DeviceInfo.makeDeviceListKey(btInfo.mAudioSystemDevice, address);
|
||||||
btDevice.getAddress());
|
|
||||||
final DeviceInfo di = mConnectedDevices.get(key);
|
final DeviceInfo di = mConnectedDevices.get(key);
|
||||||
boolean isConnected = di != null;
|
|
||||||
|
|
||||||
if (isConnected) {
|
final boolean isConnected = di != null;
|
||||||
if (state == BluetoothProfile.STATE_CONNECTED) {
|
|
||||||
// device is already connected, but we are receiving a connection again,
|
final boolean switchToUnavailable = isConnected
|
||||||
// it could be for a codec change
|
&& btInfo.mState != BluetoothProfile.STATE_CONNECTED;
|
||||||
if (a2dpCodec != di.mDeviceCodecFormat) {
|
final boolean switchToAvailable = !isConnected
|
||||||
mDeviceBroker.postBluetoothA2dpDeviceConfigChange(btDevice);
|
&& btInfo.mState == BluetoothProfile.STATE_CONNECTED;
|
||||||
|
|
||||||
|
switch (btInfo.mProfile) {
|
||||||
|
case BluetoothProfile.A2DP_SINK:
|
||||||
|
if (switchToUnavailable) {
|
||||||
|
makeA2dpSrcUnavailable(address);
|
||||||
|
} else if (switchToAvailable) {
|
||||||
|
makeA2dpSrcAvailable(address);
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
makeA2dpDeviceUnavailableNow(address, di.mDeviceCodecFormat);
|
case BluetoothProfile.A2DP:
|
||||||
}
|
if (switchToUnavailable) {
|
||||||
} else if (state == BluetoothProfile.STATE_CONNECTED) {
|
makeA2dpDeviceUnavailableNow(address, di.mDeviceCodecFormat);
|
||||||
// device is not already connected
|
} else if (switchToAvailable) {
|
||||||
if (a2dpVolume != -1) {
|
// device is not already connected
|
||||||
mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC,
|
if (btInfo.mVolume != -1) {
|
||||||
// convert index to internal representation in VolumeStreamState
|
mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC,
|
||||||
a2dpVolume * 10,
|
// convert index to internal representation in VolumeStreamState
|
||||||
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "onSetA2dpSinkConnectionState");
|
btInfo.mVolume * 10, btInfo.mAudioSystemDevice,
|
||||||
}
|
"onSetBtActiveDevice");
|
||||||
makeA2dpDeviceAvailable(address, BtHelper.getName(btDevice),
|
}
|
||||||
"onSetA2dpSinkConnectionState", a2dpCodec);
|
makeA2dpDeviceAvailable(address, BtHelper.getName(btInfo.mDevice),
|
||||||
|
"onSetBtActiveDevice", btInfo.mCodec);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BluetoothProfile.HEARING_AID:
|
||||||
|
if (switchToUnavailable) {
|
||||||
|
makeHearingAidDeviceUnavailable(address);
|
||||||
|
} else if (switchToAvailable) {
|
||||||
|
makeHearingAidDeviceAvailable(address, BtHelper.getName(btInfo.mDevice),
|
||||||
|
streamType, "onSetBtActiveDevice");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BluetoothProfile.LE_AUDIO:
|
||||||
|
if (switchToUnavailable) {
|
||||||
|
makeLeAudioDeviceUnavailable(address, btInfo.mAudioSystemDevice);
|
||||||
|
} else if (switchToAvailable) {
|
||||||
|
makeLeAudioDeviceAvailable(address, BtHelper.getName(btInfo.mDevice),
|
||||||
|
streamType, btInfo.mAudioSystemDevice, "onSetBtActiveDevice");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: throw new IllegalArgumentException("Invalid profile "
|
||||||
|
+ BluetoothProfile.getProfileName(btInfo.mProfile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ void onSetA2dpSourceConnectionState(
|
|
||||||
@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo, int state) {
|
|
||||||
final BluetoothDevice btDevice = btInfo.getBtDevice();
|
|
||||||
if (AudioService.DEBUG_DEVICES) {
|
|
||||||
Log.d(TAG, "onSetA2dpSourceConnectionState btDevice=" + btDevice + " state="
|
|
||||||
+ state);
|
|
||||||
}
|
|
||||||
String address = btDevice.getAddress();
|
|
||||||
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
|
|
||||||
address = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (mDevicesLock) {
|
|
||||||
final String key = DeviceInfo.makeDeviceListKey(
|
|
||||||
AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address);
|
|
||||||
final DeviceInfo di = mConnectedDevices.get(key);
|
|
||||||
boolean isConnected = di != null;
|
|
||||||
|
|
||||||
new MediaMetrics.Item(mMetricsId + "onSetA2dpSourceConnectionState")
|
|
||||||
.set(MediaMetrics.Property.ADDRESS, address)
|
|
||||||
.set(MediaMetrics.Property.DEVICE,
|
|
||||||
AudioSystem.getDeviceName(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP))
|
|
||||||
.set(MediaMetrics.Property.STATE,
|
|
||||||
state == BluetoothProfile.STATE_CONNECTED
|
|
||||||
? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED)
|
|
||||||
.record();
|
|
||||||
|
|
||||||
if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
|
|
||||||
makeA2dpSrcUnavailable(address);
|
|
||||||
} else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
|
|
||||||
makeA2dpSrcAvailable(address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void onSetHearingAidConnectionState(BluetoothDevice btDevice,
|
|
||||||
@AudioService.BtProfileConnectionState int state, int streamType) {
|
|
||||||
String address = btDevice.getAddress();
|
|
||||||
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
|
|
||||||
address = "";
|
|
||||||
}
|
|
||||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
|
||||||
"onSetHearingAidConnectionState addr=" + address));
|
|
||||||
|
|
||||||
new MediaMetrics.Item(mMetricsId + "onSetHearingAidConnectionState")
|
|
||||||
.set(MediaMetrics.Property.ADDRESS, address)
|
|
||||||
.set(MediaMetrics.Property.DEVICE,
|
|
||||||
AudioSystem.getDeviceName(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP))
|
|
||||||
.set(MediaMetrics.Property.STATE,
|
|
||||||
state == BluetoothProfile.STATE_CONNECTED
|
|
||||||
? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED)
|
|
||||||
.set(MediaMetrics.Property.STREAM_TYPE,
|
|
||||||
AudioSystem.streamToString(streamType))
|
|
||||||
.record();
|
|
||||||
|
|
||||||
synchronized (mDevicesLock) {
|
|
||||||
final String key = DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID,
|
|
||||||
btDevice.getAddress());
|
|
||||||
final DeviceInfo di = mConnectedDevices.get(key);
|
|
||||||
boolean isConnected = di != null;
|
|
||||||
|
|
||||||
if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
|
|
||||||
makeHearingAidDeviceUnavailable(address);
|
|
||||||
} else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
|
|
||||||
makeHearingAidDeviceAvailable(address, BtHelper.getName(btDevice), streamType,
|
|
||||||
"onSetHearingAidConnectionState");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void onSetLeAudioConnectionState(BluetoothDevice btDevice,
|
|
||||||
@AudioService.BtProfileConnectionState int state, int streamType, int device) {
|
|
||||||
String address = btDevice.getAddress();
|
|
||||||
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
|
|
||||||
address = "";
|
|
||||||
}
|
|
||||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
|
||||||
"onSetLeAudioConnectionState addr=" + address));
|
|
||||||
|
|
||||||
synchronized (mDevicesLock) {
|
|
||||||
DeviceInfo di = null;
|
|
||||||
boolean isConnected = false;
|
|
||||||
|
|
||||||
String key = DeviceInfo.makeDeviceListKey(device, btDevice.getAddress());
|
|
||||||
di = mConnectedDevices.get(key);
|
|
||||||
isConnected = di != null;
|
|
||||||
|
|
||||||
if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
|
|
||||||
makeLeAudioDeviceUnavailable(address, device);
|
|
||||||
} else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
|
|
||||||
makeLeAudioDeviceAvailable(address, BtHelper.getName(btDevice), streamType,
|
|
||||||
device, "onSetLeAudioConnectionState");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void onSetLeAudioOutConnectionState(BluetoothDevice btDevice,
|
|
||||||
@AudioService.BtProfileConnectionState int state, int streamType) {
|
|
||||||
// TODO: b/198610537 clarify DEVICE_OUT_BLE_HEADSET vs DEVICE_OUT_BLE_SPEAKER criteria
|
|
||||||
onSetLeAudioConnectionState(btDevice, state, streamType,
|
|
||||||
AudioSystem.DEVICE_OUT_BLE_HEADSET);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void onSetLeAudioInConnectionState(BluetoothDevice btDevice,
|
|
||||||
@AudioService.BtProfileConnectionState int state) {
|
|
||||||
onSetLeAudioConnectionState(btDevice, state, AudioSystem.STREAM_DEFAULT,
|
|
||||||
AudioSystem.DEVICE_IN_BLE_HEADSET);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
|
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
|
||||||
/*package*/ void onBluetoothA2dpActiveDeviceChange(
|
/*package*/ void onBluetoothA2dpDeviceConfigChange(
|
||||||
@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo, int event) {
|
@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo, int event) {
|
||||||
MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId
|
MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId
|
||||||
+ "onBluetoothA2dpActiveDeviceChange")
|
+ "onBluetoothA2dpDeviceConfigChange")
|
||||||
.set(MediaMetrics.Property.EVENT, BtHelper.a2dpDeviceEventToString(event));
|
.set(MediaMetrics.Property.EVENT, BtHelper.a2dpDeviceEventToString(event));
|
||||||
|
|
||||||
final BluetoothDevice btDevice = btInfo.getBtDevice();
|
final BluetoothDevice btDevice = btInfo.getBtDevice();
|
||||||
@@ -474,7 +387,7 @@ public class AudioDeviceInventory {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (AudioService.DEBUG_DEVICES) {
|
if (AudioService.DEBUG_DEVICES) {
|
||||||
Log.d(TAG, "onBluetoothA2dpActiveDeviceChange btDevice=" + btDevice);
|
Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice);
|
||||||
}
|
}
|
||||||
int a2dpVolume = btInfo.getVolume();
|
int a2dpVolume = btInfo.getVolume();
|
||||||
@AudioSystem.AudioFormatNativeEnumForBtCodec final int a2dpCodec = btInfo.getCodec();
|
@AudioSystem.AudioFormatNativeEnumForBtCodec final int a2dpCodec = btInfo.getCodec();
|
||||||
@@ -484,11 +397,11 @@ public class AudioDeviceInventory {
|
|||||||
address = "";
|
address = "";
|
||||||
}
|
}
|
||||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
||||||
"onBluetoothA2dpActiveDeviceChange addr=" + address
|
"onBluetoothA2dpDeviceConfigChange addr=" + address
|
||||||
+ " event=" + BtHelper.a2dpDeviceEventToString(event)));
|
+ " event=" + BtHelper.a2dpDeviceEventToString(event)));
|
||||||
|
|
||||||
synchronized (mDevicesLock) {
|
synchronized (mDevicesLock) {
|
||||||
if (mDeviceBroker.hasScheduledA2dpSinkConnectionState(btDevice)) {
|
if (mDeviceBroker.hasScheduledA2dpConnection(btDevice)) {
|
||||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
||||||
"A2dp config change ignored (scheduled connection change)")
|
"A2dp config change ignored (scheduled connection change)")
|
||||||
.printLog(TAG));
|
.printLog(TAG));
|
||||||
@@ -500,7 +413,7 @@ public class AudioDeviceInventory {
|
|||||||
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
|
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
|
||||||
final DeviceInfo di = mConnectedDevices.get(key);
|
final DeviceInfo di = mConnectedDevices.get(key);
|
||||||
if (di == null) {
|
if (di == null) {
|
||||||
Log.e(TAG, "invalid null DeviceInfo in onBluetoothA2dpActiveDeviceChange");
|
Log.e(TAG, "invalid null DeviceInfo in onBluetoothA2dpDeviceConfigChange");
|
||||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, "null DeviceInfo").record();
|
mmi.set(MediaMetrics.Property.EARLY_RETURN, "null DeviceInfo").record();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -518,7 +431,7 @@ public class AudioDeviceInventory {
|
|||||||
// convert index to internal representation in VolumeStreamState
|
// convert index to internal representation in VolumeStreamState
|
||||||
a2dpVolume * 10,
|
a2dpVolume * 10,
|
||||||
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
||||||
"onBluetoothA2dpActiveDeviceChange");
|
"onBluetoothA2dpDeviceConfigChange");
|
||||||
}
|
}
|
||||||
} else if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) {
|
} else if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) {
|
||||||
if (di.mDeviceCodecFormat != a2dpCodec) {
|
if (di.mDeviceCodecFormat != a2dpCodec) {
|
||||||
@@ -539,10 +452,9 @@ public class AudioDeviceInventory {
|
|||||||
int musicDevice = mDeviceBroker.getDeviceForStream(AudioSystem.STREAM_MUSIC);
|
int musicDevice = mDeviceBroker.getDeviceForStream(AudioSystem.STREAM_MUSIC);
|
||||||
// force A2DP device disconnection in case of error so that AudioService state is
|
// force A2DP device disconnection in case of error so that AudioService state is
|
||||||
// consistent with audio policy manager state
|
// consistent with audio policy manager state
|
||||||
setBluetoothA2dpDeviceConnectionState(
|
setBluetoothActiveDevice(new AudioDeviceBroker.BtDeviceInfo(btDevice,
|
||||||
btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP,
|
BluetoothProfile.A2DP, BluetoothProfile.STATE_DISCONNECTED,
|
||||||
false /* suppressNoisyIntent */, musicDevice,
|
musicDevice, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
|
||||||
-1 /* a2dpVolume */);
|
|
||||||
} else {
|
} else {
|
||||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
||||||
"APM handleDeviceConfigChange success for A2DP device addr=" + address
|
"APM handleDeviceConfigChange success for A2DP device addr=" + address
|
||||||
@@ -828,7 +740,7 @@ public class AudioDeviceInventory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*package*/ void disconnectA2dp() {
|
private void disconnectA2dp() {
|
||||||
synchronized (mDevicesLock) {
|
synchronized (mDevicesLock) {
|
||||||
final ArraySet<String> toRemove = new ArraySet<>();
|
final ArraySet<String> toRemove = new ArraySet<>();
|
||||||
// Disconnect ALL DEVICE_OUT_BLUETOOTH_A2DP devices
|
// Disconnect ALL DEVICE_OUT_BLUETOOTH_A2DP devices
|
||||||
@@ -850,7 +762,7 @@ public class AudioDeviceInventory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ void disconnectA2dpSink() {
|
private void disconnectA2dpSink() {
|
||||||
synchronized (mDevicesLock) {
|
synchronized (mDevicesLock) {
|
||||||
final ArraySet<String> toRemove = new ArraySet<>();
|
final ArraySet<String> toRemove = new ArraySet<>();
|
||||||
// Disconnect ALL DEVICE_IN_BLUETOOTH_A2DP devices
|
// Disconnect ALL DEVICE_IN_BLUETOOTH_A2DP devices
|
||||||
@@ -865,7 +777,7 @@ public class AudioDeviceInventory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ void disconnectHearingAid() {
|
private void disconnectHearingAid() {
|
||||||
synchronized (mDevicesLock) {
|
synchronized (mDevicesLock) {
|
||||||
final ArraySet<String> toRemove = new ArraySet<>();
|
final ArraySet<String> toRemove = new ArraySet<>();
|
||||||
// Disconnect ALL DEVICE_OUT_HEARING_AID devices
|
// Disconnect ALL DEVICE_OUT_HEARING_AID devices
|
||||||
@@ -887,6 +799,28 @@ public class AudioDeviceInventory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*package*/ synchronized void onBtProfileDisconnected(int profile) {
|
||||||
|
switch (profile) {
|
||||||
|
case BluetoothProfile.A2DP:
|
||||||
|
disconnectA2dp();
|
||||||
|
break;
|
||||||
|
case BluetoothProfile.A2DP_SINK:
|
||||||
|
disconnectA2dpSink();
|
||||||
|
break;
|
||||||
|
case BluetoothProfile.HEARING_AID:
|
||||||
|
disconnectHearingAid();
|
||||||
|
break;
|
||||||
|
case BluetoothProfile.LE_AUDIO:
|
||||||
|
disconnectLeAudio();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Not a valid profile to disconnect
|
||||||
|
Log.e(TAG, "onBtProfileDisconnected: Not a valid profile to disconnect "
|
||||||
|
+ BluetoothProfile.getProfileName(profile));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*package*/ void disconnectLeAudio() {
|
/*package*/ void disconnectLeAudio() {
|
||||||
synchronized (mDevicesLock) {
|
synchronized (mDevicesLock) {
|
||||||
final ArraySet<String> toRemove = new ArraySet<>();
|
final ArraySet<String> toRemove = new ArraySet<>();
|
||||||
@@ -934,46 +868,39 @@ public class AudioDeviceInventory {
|
|||||||
// only public for mocking/spying
|
// only public for mocking/spying
|
||||||
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
|
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public void setBluetoothA2dpDeviceConnectionState(
|
public int setBluetoothActiveDevice(@NonNull AudioDeviceBroker.BtDeviceInfo info) {
|
||||||
@NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
|
|
||||||
int profile, boolean suppressNoisyIntent, int musicDevice, int a2dpVolume) {
|
|
||||||
int delay;
|
int delay;
|
||||||
if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) {
|
|
||||||
throw new IllegalArgumentException("invalid profile " + profile);
|
|
||||||
}
|
|
||||||
synchronized (mDevicesLock) {
|
synchronized (mDevicesLock) {
|
||||||
if (profile == BluetoothProfile.A2DP && !suppressNoisyIntent) {
|
if (!info.mSupprNoisy
|
||||||
|
&& ((info.mProfile == BluetoothProfile.LE_AUDIO && info.mIsLeOutput)
|
||||||
|
|| info.mProfile == BluetoothProfile.HEARING_AID
|
||||||
|
|| info.mProfile == BluetoothProfile.A2DP)) {
|
||||||
@AudioService.ConnectionState int asState =
|
@AudioService.ConnectionState int asState =
|
||||||
(state == BluetoothA2dp.STATE_CONNECTED)
|
(info.mState == BluetoothProfile.STATE_CONNECTED)
|
||||||
? AudioService.CONNECTION_STATE_CONNECTED
|
? AudioService.CONNECTION_STATE_CONNECTED
|
||||||
: AudioService.CONNECTION_STATE_DISCONNECTED;
|
: AudioService.CONNECTION_STATE_DISCONNECTED;
|
||||||
delay = checkSendBecomingNoisyIntentInt(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
delay = checkSendBecomingNoisyIntentInt(info.mAudioSystemDevice, asState,
|
||||||
asState, musicDevice);
|
info.mMusicDevice);
|
||||||
} else {
|
} else {
|
||||||
delay = 0;
|
delay = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int a2dpCodec = mDeviceBroker.getA2dpCodec(device);
|
|
||||||
|
|
||||||
if (AudioService.DEBUG_DEVICES) {
|
if (AudioService.DEBUG_DEVICES) {
|
||||||
Log.i(TAG, "setBluetoothA2dpDeviceConnectionState device: " + device
|
Log.i(TAG, "setBluetoothActiveDevice device: " + info.mDevice
|
||||||
+ " state: " + state + " delay(ms): " + delay
|
+ " profile: " + BluetoothProfile.getProfileName(info.mProfile)
|
||||||
+ " codec:" + Integer.toHexString(a2dpCodec)
|
+ " state: " + BluetoothProfile.getConnectionStateName(info.mState)
|
||||||
+ " suppressNoisyIntent: " + suppressNoisyIntent);
|
+ " delay(ms): " + delay
|
||||||
|
+ " codec:" + Integer.toHexString(info.mCodec)
|
||||||
|
+ " suppressNoisyIntent: " + info.mSupprNoisy);
|
||||||
}
|
}
|
||||||
|
mDeviceBroker.postBluetoothActiveDevice(info, delay);
|
||||||
final BtHelper.BluetoothA2dpDeviceInfo a2dpDeviceInfo =
|
if (info.mProfile == BluetoothProfile.HEARING_AID
|
||||||
new BtHelper.BluetoothA2dpDeviceInfo(device, a2dpVolume, a2dpCodec);
|
&& info.mState == BluetoothProfile.STATE_CONNECTED) {
|
||||||
if (profile == BluetoothProfile.A2DP) {
|
mDeviceBroker.setForceUse_Async(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_NONE,
|
||||||
mDeviceBroker.postA2dpSinkConnection(state,
|
"HEARING_AID set to CONNECTED");
|
||||||
a2dpDeviceInfo,
|
|
||||||
delay);
|
|
||||||
} else { //profile == BluetoothProfile.A2DP_SINK
|
|
||||||
mDeviceBroker.postA2dpSourceConnection(state,
|
|
||||||
a2dpDeviceInfo,
|
|
||||||
delay);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ int setWiredDeviceConnectionState(int type, @AudioService.ConnectionState int state,
|
/*package*/ int setWiredDeviceConnectionState(int type, @AudioService.ConnectionState int state,
|
||||||
@@ -987,50 +914,6 @@ public class AudioDeviceInventory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ int setBluetoothHearingAidDeviceConnectionState(
|
|
||||||
@NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
|
|
||||||
boolean suppressNoisyIntent, int musicDevice) {
|
|
||||||
int delay;
|
|
||||||
synchronized (mDevicesLock) {
|
|
||||||
if (!suppressNoisyIntent) {
|
|
||||||
int intState = (state == BluetoothHearingAid.STATE_CONNECTED) ? 1 : 0;
|
|
||||||
delay = checkSendBecomingNoisyIntentInt(AudioSystem.DEVICE_OUT_HEARING_AID,
|
|
||||||
intState, musicDevice);
|
|
||||||
} else {
|
|
||||||
delay = 0;
|
|
||||||
}
|
|
||||||
mDeviceBroker.postSetHearingAidConnectionState(state, device, delay);
|
|
||||||
if (state == BluetoothHearingAid.STATE_CONNECTED) {
|
|
||||||
mDeviceBroker.setForceUse_Async(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_NONE,
|
|
||||||
"HEARING_AID set to CONNECTED");
|
|
||||||
}
|
|
||||||
return delay;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ int setBluetoothLeAudioOutDeviceConnectionState(
|
|
||||||
@NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
|
|
||||||
boolean suppressNoisyIntent) {
|
|
||||||
synchronized (mDevicesLock) {
|
|
||||||
/* Active device become null and it's previous device is not connected anymore */
|
|
||||||
int delay = 0;
|
|
||||||
if (!suppressNoisyIntent) {
|
|
||||||
int intState = (state == BluetoothLeAudio.STATE_CONNECTED) ? 1 : 0;
|
|
||||||
delay = checkSendBecomingNoisyIntentInt(AudioSystem.DEVICE_OUT_BLE_HEADSET,
|
|
||||||
intState, AudioSystem.DEVICE_NONE);
|
|
||||||
}
|
|
||||||
mDeviceBroker.postSetLeAudioOutConnectionState(state, device, delay);
|
|
||||||
return delay;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ void setBluetoothLeAudioInDeviceConnectionState(
|
|
||||||
@NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state) {
|
|
||||||
synchronized (mDevicesLock) {
|
|
||||||
mDeviceBroker.postSetLeAudioInConnectionState(state, device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Internal utilities
|
// Internal utilities
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ import android.media.AudioPlaybackConfiguration;
|
|||||||
import android.media.AudioRecordingConfiguration;
|
import android.media.AudioRecordingConfiguration;
|
||||||
import android.media.AudioRoutesInfo;
|
import android.media.AudioRoutesInfo;
|
||||||
import android.media.AudioSystem;
|
import android.media.AudioSystem;
|
||||||
|
import android.media.BtProfileConnectionInfo;
|
||||||
import android.media.IAudioFocusDispatcher;
|
import android.media.IAudioFocusDispatcher;
|
||||||
import android.media.IAudioModeDispatcher;
|
import android.media.IAudioModeDispatcher;
|
||||||
import android.media.IAudioRoutesObserver;
|
import android.media.IAudioRoutesObserver;
|
||||||
@@ -309,8 +310,8 @@ public class AudioService extends IAudioService.Stub
|
|||||||
private static final int MSG_UPDATE_A11Y_SERVICE_UIDS = 35;
|
private static final int MSG_UPDATE_A11Y_SERVICE_UIDS = 35;
|
||||||
private static final int MSG_UPDATE_AUDIO_MODE = 36;
|
private static final int MSG_UPDATE_AUDIO_MODE = 36;
|
||||||
private static final int MSG_RECORDING_CONFIG_CHANGE = 37;
|
private static final int MSG_RECORDING_CONFIG_CHANGE = 37;
|
||||||
private static final int MSG_SET_A2DP_DEV_CONNECTION_STATE = 38;
|
private static final int MSG_BT_DEV_CHANGED = 38;
|
||||||
private static final int MSG_A2DP_DEV_CONFIG_CHANGE = 39;
|
|
||||||
private static final int MSG_DISPATCH_AUDIO_MODE = 40;
|
private static final int MSG_DISPATCH_AUDIO_MODE = 40;
|
||||||
|
|
||||||
// start of messages handled under wakelock
|
// start of messages handled under wakelock
|
||||||
@@ -6266,77 +6267,44 @@ public class AudioService extends IAudioService.Stub
|
|||||||
public @interface BtProfileConnectionState {}
|
public @interface BtProfileConnectionState {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See AudioManager.setBluetoothHearingAidDeviceConnectionState()
|
* @hide
|
||||||
|
* The profiles that can be used with AudioService.handleBluetoothActiveDeviceChanged()
|
||||||
*/
|
*/
|
||||||
public void setBluetoothHearingAidDeviceConnectionState(
|
@IntDef({
|
||||||
@NonNull BluetoothDevice device, @BtProfileConnectionState int state,
|
BluetoothProfile.HEARING_AID,
|
||||||
boolean suppressNoisyIntent, int musicDevice)
|
BluetoothProfile.A2DP,
|
||||||
{
|
BluetoothProfile.A2DP_SINK,
|
||||||
if (device == null) {
|
BluetoothProfile.LE_AUDIO,
|
||||||
throw new IllegalArgumentException("Illegal null device");
|
})
|
||||||
}
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
if (state != BluetoothProfile.STATE_CONNECTED
|
public @interface BtProfile {}
|
||||||
&& state != BluetoothProfile.STATE_DISCONNECTED) {
|
|
||||||
throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
|
|
||||||
+ " (dis)connection, got " + state);
|
|
||||||
}
|
|
||||||
mDeviceBroker.postBluetoothHearingAidDeviceConnectionState(
|
|
||||||
device, state, suppressNoisyIntent, musicDevice, "AudioService");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setBluetoothLeAudioDeviceConnectionState(@NonNull BluetoothDevice device,
|
|
||||||
@BtProfileConnectionState int state) {
|
|
||||||
if (device == null) {
|
|
||||||
throw new IllegalArgumentException("Illegal null device");
|
|
||||||
}
|
|
||||||
if (state != BluetoothProfile.STATE_CONNECTED
|
|
||||||
&& state != BluetoothProfile.STATE_DISCONNECTED) {
|
|
||||||
throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
|
|
||||||
+ " (dis)connection, got " + state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See AudioManager.setBluetoothLeAudioOutDeviceConnectionState()
|
* See AudioManager.handleBluetoothActiveDeviceChanged(...)
|
||||||
*/
|
*/
|
||||||
public void setBluetoothLeAudioOutDeviceConnectionState(
|
public void handleBluetoothActiveDeviceChanged(BluetoothDevice newDevice,
|
||||||
@NonNull BluetoothDevice device, @BtProfileConnectionState int state,
|
BluetoothDevice previousDevice, @NonNull BtProfileConnectionInfo info) {
|
||||||
boolean suppressNoisyIntent) {
|
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.BLUETOOTH_STACK)
|
||||||
setBluetoothLeAudioDeviceConnectionState(device, state);
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
mDeviceBroker.postBluetoothLeAudioOutDeviceConnectionState(device, state,
|
throw new SecurityException("Bluetooth is the only caller allowed");
|
||||||
suppressNoisyIntent, "AudioService");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See AudioManager.setBluetoothLeAudioInDeviceConnectionState()
|
|
||||||
*/
|
|
||||||
public void setBluetoothLeAudioInDeviceConnectionState(
|
|
||||||
@NonNull BluetoothDevice device, @BtProfileConnectionState int state) {
|
|
||||||
setBluetoothLeAudioDeviceConnectionState(device, state);
|
|
||||||
mDeviceBroker.postBluetoothLeAudioInDeviceConnectionState(device, state, "AudioService");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent()
|
|
||||||
*/
|
|
||||||
public void setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
|
|
||||||
@NonNull BluetoothDevice device, @BtProfileConnectionState int state,
|
|
||||||
int profile, boolean suppressNoisyIntent, int a2dpVolume) {
|
|
||||||
if (device == null) {
|
|
||||||
throw new IllegalArgumentException("Illegal null device");
|
|
||||||
}
|
}
|
||||||
if (state != BluetoothProfile.STATE_CONNECTED
|
if (info == null) {
|
||||||
&& state != BluetoothProfile.STATE_DISCONNECTED) {
|
throw new IllegalArgumentException("Illegal null BtProfileConnectionInfo for device "
|
||||||
throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
|
+ previousDevice + " -> " + newDevice);
|
||||||
+ " (dis)connection, got " + state);
|
|
||||||
}
|
}
|
||||||
|
final int profile = info.getProfile();
|
||||||
AudioDeviceBroker.BtDeviceConnectionInfo info =
|
if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK
|
||||||
new AudioDeviceBroker.BtDeviceConnectionInfo(device, state,
|
&& profile != BluetoothProfile.LE_AUDIO
|
||||||
profile, suppressNoisyIntent, a2dpVolume);
|
&& profile != BluetoothProfile.HEARING_AID) {
|
||||||
sendMsg(mAudioHandler, MSG_SET_A2DP_DEV_CONNECTION_STATE, SENDMSG_QUEUE,
|
throw new IllegalArgumentException("Illegal BluetoothProfile profile for device "
|
||||||
0 /*arg1*/, 0 /*arg2*/,
|
+ previousDevice + " -> " + newDevice + ". Got: " + profile);
|
||||||
/*obj*/ info, 0 /*delay*/);
|
}
|
||||||
|
AudioDeviceBroker.BtDeviceChangedData data =
|
||||||
|
new AudioDeviceBroker.BtDeviceChangedData(newDevice, previousDevice, info,
|
||||||
|
"AudioService");
|
||||||
|
sendMsg(mAudioHandler, MSG_BT_DEV_CHANGED, SENDMSG_QUEUE, 0, 0,
|
||||||
|
/*obj*/ data, /*delay*/ 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** only public for mocking/spying, do not call outside of AudioService */
|
/** only public for mocking/spying, do not call outside of AudioService */
|
||||||
@@ -6345,19 +6313,6 @@ public class AudioService extends IAudioService.Stub
|
|||||||
mStreamStates[AudioSystem.STREAM_MUSIC].muteInternally(mute);
|
mStreamStates[AudioSystem.STREAM_MUSIC].muteInternally(mute);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* See AudioManager.handleBluetoothA2dpDeviceConfigChange()
|
|
||||||
* @param device
|
|
||||||
*/
|
|
||||||
public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device)
|
|
||||||
{
|
|
||||||
if (device == null) {
|
|
||||||
throw new IllegalArgumentException("Illegal null device");
|
|
||||||
}
|
|
||||||
sendMsg(mAudioHandler, MSG_A2DP_DEV_CONFIG_CHANGE, SENDMSG_QUEUE, 0, 0,
|
|
||||||
/*obj*/ device, /*delay*/ 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Set<Integer> DEVICE_MEDIA_UNMUTED_ON_PLUG_SET;
|
private static final Set<Integer> DEVICE_MEDIA_UNMUTED_ON_PLUG_SET;
|
||||||
static {
|
static {
|
||||||
DEVICE_MEDIA_UNMUTED_ON_PLUG_SET = new HashSet<>();
|
DEVICE_MEDIA_UNMUTED_ON_PLUG_SET = new HashSet<>();
|
||||||
@@ -7709,13 +7664,9 @@ public class AudioService extends IAudioService.Stub
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSG_SET_A2DP_DEV_CONNECTION_STATE:
|
case MSG_BT_DEV_CHANGED:
|
||||||
mDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
|
mDeviceBroker.queueOnBluetoothActiveDeviceChanged(
|
||||||
(AudioDeviceBroker.BtDeviceConnectionInfo) msg.obj);
|
(AudioDeviceBroker.BtDeviceChangedData) msg.obj);
|
||||||
break;
|
|
||||||
|
|
||||||
case MSG_A2DP_DEV_CONFIG_CHANGE:
|
|
||||||
mDeviceBroker.postBluetoothA2dpDeviceConfigChange((BluetoothDevice) msg.obj);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSG_DISPATCH_AUDIO_MODE:
|
case MSG_DISPATCH_AUDIO_MODE:
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import android.content.Intent;
|
|||||||
import android.media.AudioDeviceAttributes;
|
import android.media.AudioDeviceAttributes;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.media.AudioSystem;
|
import android.media.AudioSystem;
|
||||||
|
import android.media.BtProfileConnectionInfo;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@@ -451,11 +452,11 @@ public class BtHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ synchronized void disconnectAllBluetoothProfiles() {
|
/*package*/ synchronized void disconnectAllBluetoothProfiles() {
|
||||||
mDeviceBroker.postDisconnectA2dp();
|
mDeviceBroker.postBtProfileDisconnected(BluetoothProfile.A2DP);
|
||||||
mDeviceBroker.postDisconnectA2dpSink();
|
mDeviceBroker.postBtProfileDisconnected(BluetoothProfile.A2DP_SINK);
|
||||||
mDeviceBroker.postDisconnectHeadset();
|
mDeviceBroker.postBtProfileDisconnected(BluetoothProfile.HEADSET);
|
||||||
mDeviceBroker.postDisconnectHearingAid();
|
mDeviceBroker.postBtProfileDisconnected(BluetoothProfile.HEARING_AID);
|
||||||
mDeviceBroker.postDisconnectLeAudio();
|
mDeviceBroker.postBtProfileDisconnected(BluetoothProfile.LE_AUDIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
|
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
|
||||||
@@ -474,63 +475,32 @@ public class BtHelper {
|
|||||||
mBluetoothHeadset = null;
|
mBluetoothHeadset = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ synchronized void onA2dpProfileConnected(BluetoothA2dp a2dp) {
|
/*package*/ synchronized void onBtProfileConnected(int profile, BluetoothProfile proxy) {
|
||||||
mA2dp = a2dp;
|
if (profile == BluetoothProfile.HEADSET) {
|
||||||
final List<BluetoothDevice> deviceList = mA2dp.getConnectedDevices();
|
onHeadsetProfileConnected((BluetoothHeadset) proxy);
|
||||||
if (deviceList.isEmpty()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final BluetoothDevice btDevice = deviceList.get(0);
|
if (profile == BluetoothProfile.A2DP) {
|
||||||
// the device is guaranteed CONNECTED
|
mA2dp = (BluetoothA2dp) proxy;
|
||||||
mDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
|
} else if (profile == BluetoothProfile.LE_AUDIO) {
|
||||||
new AudioDeviceBroker.BtDeviceConnectionInfo(btDevice,
|
mLeAudio = (BluetoothLeAudio) proxy;
|
||||||
BluetoothA2dp.STATE_CONNECTED, BluetoothProfile.A2DP_SINK,
|
}
|
||||||
true, -1));
|
final List<BluetoothDevice> deviceList = proxy.getConnectedDevices();
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ synchronized void onA2dpSinkProfileConnected(BluetoothProfile profile) {
|
|
||||||
final List<BluetoothDevice> deviceList = profile.getConnectedDevices();
|
|
||||||
if (deviceList.isEmpty()) {
|
if (deviceList.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final BluetoothDevice btDevice = deviceList.get(0);
|
final BluetoothDevice btDevice = deviceList.get(0);
|
||||||
final @BluetoothProfile.BtProfileState int state =
|
final @BluetoothProfile.BtProfileState int state =
|
||||||
profile.getConnectionState(btDevice);
|
proxy.getConnectionState(btDevice);
|
||||||
mDeviceBroker.postSetA2dpSourceConnectionState(
|
if (state == BluetoothProfile.STATE_CONNECTED) {
|
||||||
state, new BluetoothA2dpDeviceInfo(btDevice));
|
mDeviceBroker.queueOnBluetoothActiveDeviceChanged(
|
||||||
}
|
new AudioDeviceBroker.BtDeviceChangedData(btDevice, null,
|
||||||
|
new BtProfileConnectionInfo(profile), "mBluetoothProfileServiceListener"));
|
||||||
/*package*/ synchronized void onHearingAidProfileConnected(BluetoothHearingAid hearingAid) {
|
} else {
|
||||||
mHearingAid = hearingAid;
|
mDeviceBroker.queueOnBluetoothActiveDeviceChanged(
|
||||||
final List<BluetoothDevice> deviceList = mHearingAid.getConnectedDevices();
|
new AudioDeviceBroker.BtDeviceChangedData(null, btDevice,
|
||||||
if (deviceList.isEmpty()) {
|
new BtProfileConnectionInfo(profile), "mBluetoothProfileServiceListener"));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
final BluetoothDevice btDevice = deviceList.get(0);
|
|
||||||
final @BluetoothProfile.BtProfileState int state =
|
|
||||||
mHearingAid.getConnectionState(btDevice);
|
|
||||||
mDeviceBroker.postBluetoothHearingAidDeviceConnectionState(
|
|
||||||
btDevice, state,
|
|
||||||
/*suppressNoisyIntent*/ false,
|
|
||||||
/*musicDevice*/ android.media.AudioSystem.DEVICE_NONE,
|
|
||||||
/*eventSource*/ "mBluetoothProfileServiceListener");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ synchronized void onLeAudioProfileConnected(BluetoothLeAudio leAudio) {
|
|
||||||
mLeAudio = leAudio;
|
|
||||||
final List<BluetoothDevice> deviceList = mLeAudio.getConnectedDevices();
|
|
||||||
if (deviceList.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final BluetoothDevice btDevice = deviceList.get(0);
|
|
||||||
final @BluetoothProfile.BtProfileState int state =
|
|
||||||
mLeAudio.getConnectionState(btDevice);
|
|
||||||
mDeviceBroker.postBluetoothLeAudioOutDeviceConnectionState(
|
|
||||||
btDevice, state,
|
|
||||||
/*suppressNoisyIntent*/ false,
|
|
||||||
/*musicDevice android.media.AudioSystem.DEVICE_NONE,*/
|
|
||||||
/*eventSource*/ "mBluetoothProfileServiceListener");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
|
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
|
||||||
@@ -677,36 +647,16 @@ public class BtHelper {
|
|||||||
public void onServiceConnected(int profile, BluetoothProfile proxy) {
|
public void onServiceConnected(int profile, BluetoothProfile proxy) {
|
||||||
switch(profile) {
|
switch(profile) {
|
||||||
case BluetoothProfile.A2DP:
|
case BluetoothProfile.A2DP:
|
||||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
|
||||||
"BT profile service: connecting A2DP profile"));
|
|
||||||
mDeviceBroker.postBtA2dpProfileConnected((BluetoothA2dp) proxy);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BluetoothProfile.A2DP_SINK:
|
case BluetoothProfile.A2DP_SINK:
|
||||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
|
||||||
"BT profile service: connecting A2DP_SINK profile"));
|
|
||||||
mDeviceBroker.postBtA2dpSinkProfileConnected(proxy);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BluetoothProfile.HEADSET:
|
case BluetoothProfile.HEADSET:
|
||||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
|
||||||
"BT profile service: connecting HEADSET profile"));
|
|
||||||
mDeviceBroker.postBtHeasetProfileConnected((BluetoothHeadset) proxy);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BluetoothProfile.HEARING_AID:
|
case BluetoothProfile.HEARING_AID:
|
||||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
|
||||||
"BT profile service: connecting HEARING_AID profile"));
|
|
||||||
mDeviceBroker.postBtHearingAidProfileConnected(
|
|
||||||
(BluetoothHearingAid) proxy);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BluetoothProfile.LE_AUDIO:
|
case BluetoothProfile.LE_AUDIO:
|
||||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
||||||
"BT profile service: connecting LE_AUDIO profile"));
|
"BT profile service: connecting "
|
||||||
mDeviceBroker.postBtLeAudioProfileConnected(
|
+ BluetoothProfile.getProfileName(profile) + " profile"));
|
||||||
(BluetoothLeAudio) proxy);
|
mDeviceBroker.postBtProfileConnected(profile, proxy);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -715,22 +665,11 @@ public class BtHelper {
|
|||||||
|
|
||||||
switch (profile) {
|
switch (profile) {
|
||||||
case BluetoothProfile.A2DP:
|
case BluetoothProfile.A2DP:
|
||||||
mDeviceBroker.postDisconnectA2dp();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BluetoothProfile.A2DP_SINK:
|
case BluetoothProfile.A2DP_SINK:
|
||||||
mDeviceBroker.postDisconnectA2dpSink();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BluetoothProfile.HEADSET:
|
case BluetoothProfile.HEADSET:
|
||||||
mDeviceBroker.postDisconnectHeadset();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BluetoothProfile.HEARING_AID:
|
case BluetoothProfile.HEARING_AID:
|
||||||
mDeviceBroker.postDisconnectHearingAid();
|
|
||||||
break;
|
|
||||||
case BluetoothProfile.LE_AUDIO:
|
case BluetoothProfile.LE_AUDIO:
|
||||||
mDeviceBroker.postDisconnectLeAudio();
|
mDeviceBroker.postBtProfileDisconnected(profile);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -26,11 +26,11 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.bluetooth.BluetoothProfile;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.media.AudioSystem;
|
import android.media.AudioSystem;
|
||||||
|
import android.media.BtProfileConnectionInfo;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
import androidx.test.InstrumentationRegistry;
|
||||||
@@ -98,16 +98,12 @@ public class AudioDeviceBrokerTest {
|
|||||||
Log.i(TAG, "starting testPostA2dpDeviceConnectionChange");
|
Log.i(TAG, "starting testPostA2dpDeviceConnectionChange");
|
||||||
Assert.assertNotNull("invalid null BT device", mFakeBtDevice);
|
Assert.assertNotNull("invalid null BT device", mFakeBtDevice);
|
||||||
|
|
||||||
mAudioDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
|
mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged(
|
||||||
new AudioDeviceBroker.BtDeviceConnectionInfo(mFakeBtDevice,
|
new AudioDeviceBroker.BtDeviceChangedData(mFakeBtDevice, null,
|
||||||
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 1));
|
BtProfileConnectionInfo.a2dpInfo(true, 1), "testSource"));
|
||||||
Thread.sleep(2 * MAX_MESSAGE_HANDLING_DELAY_MS);
|
Thread.sleep(2 * MAX_MESSAGE_HANDLING_DELAY_MS);
|
||||||
verify(mSpyDevInventory, times(1)).setBluetoothA2dpDeviceConnectionState(
|
verify(mSpyDevInventory, times(1)).setBluetoothActiveDevice(
|
||||||
any(BluetoothDevice.class),
|
any(AudioDeviceBroker.BtDeviceInfo.class)
|
||||||
ArgumentMatchers.eq(BluetoothProfile.STATE_CONNECTED) /*state*/,
|
|
||||||
ArgumentMatchers.eq(BluetoothProfile.A2DP) /*profile*/,
|
|
||||||
ArgumentMatchers.eq(true) /*suppressNoisyIntent*/, anyInt() /*musicDevice*/,
|
|
||||||
ArgumentMatchers.eq(1) /*a2dpVolume*/
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// verify the connection was reported to AudioSystem
|
// verify the connection was reported to AudioSystem
|
||||||
@@ -210,30 +206,29 @@ public class AudioDeviceBrokerTest {
|
|||||||
((NoOpAudioSystemAdapter) mSpyAudioSystem).configureIsStreamActive(mockMediaPlayback);
|
((NoOpAudioSystemAdapter) mSpyAudioSystem).configureIsStreamActive(mockMediaPlayback);
|
||||||
|
|
||||||
// first connection: ensure the device is connected as a starting condition for the test
|
// first connection: ensure the device is connected as a starting condition for the test
|
||||||
mAudioDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
|
mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged(
|
||||||
new AudioDeviceBroker.BtDeviceConnectionInfo(mFakeBtDevice,
|
new AudioDeviceBroker.BtDeviceChangedData(mFakeBtDevice, null,
|
||||||
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 1));
|
BtProfileConnectionInfo.a2dpInfo(true, 1), "testSource"));
|
||||||
Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS);
|
Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS);
|
||||||
|
|
||||||
// disconnection
|
// disconnection
|
||||||
mAudioDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
|
mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged(
|
||||||
new AudioDeviceBroker.BtDeviceConnectionInfo(mFakeBtDevice,
|
new AudioDeviceBroker.BtDeviceChangedData(null, mFakeBtDevice,
|
||||||
BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.A2DP, false, -1));
|
BtProfileConnectionInfo.a2dpInfo(false, -1), "testSource"));
|
||||||
if (delayAfterDisconnection > 0) {
|
if (delayAfterDisconnection > 0) {
|
||||||
Thread.sleep(delayAfterDisconnection);
|
Thread.sleep(delayAfterDisconnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reconnection
|
// reconnection
|
||||||
mAudioDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
|
mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged(
|
||||||
new AudioDeviceBroker.BtDeviceConnectionInfo(mFakeBtDevice,
|
new AudioDeviceBroker.BtDeviceChangedData(mFakeBtDevice, null,
|
||||||
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 2));
|
BtProfileConnectionInfo.a2dpInfo(true, 2), "testSource"));
|
||||||
Thread.sleep(AudioService.BECOMING_NOISY_DELAY_MS + MAX_MESSAGE_HANDLING_DELAY_MS);
|
Thread.sleep(AudioService.BECOMING_NOISY_DELAY_MS + MAX_MESSAGE_HANDLING_DELAY_MS);
|
||||||
|
|
||||||
// Verify disconnection has been cancelled and we're seeing two connections attempts,
|
// Verify disconnection has been cancelled and we're seeing two connections attempts,
|
||||||
// with the device connected at the end of the test
|
// with the device connected at the end of the test
|
||||||
verify(mSpyDevInventory, times(2)).onSetA2dpSinkConnectionState(
|
verify(mSpyDevInventory, times(2)).onSetBtActiveDevice(
|
||||||
any(BtHelper.BluetoothA2dpDeviceInfo.class),
|
any(AudioDeviceBroker.BtDeviceInfo.class), anyInt());
|
||||||
ArgumentMatchers.eq(BluetoothProfile.STATE_CONNECTED));
|
|
||||||
Assert.assertTrue("Mock device not connected",
|
Assert.assertTrue("Mock device not connected",
|
||||||
mSpyDevInventory.isA2dpDeviceConnected(mFakeBtDevice));
|
mSpyDevInventory.isA2dpDeviceConnected(mFakeBtDevice));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user