Skip to content

Commit cee7203

Browse files
Eric LaurentAndroid (Google) Code Review
authored andcommitted
Merge "Send device connection intents from AudioService" into jb-dev
2 parents 43cee47 + b1fbaac commit cee7203

File tree

5 files changed

+251
-134
lines changed

5 files changed

+251
-134
lines changed

core/java/android/server/BluetoothA2dpService.java

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@
3333
import android.content.Intent;
3434
import android.content.IntentFilter;
3535
import android.media.AudioManager;
36+
import android.os.Handler;
37+
import android.os.Message;
3638
import android.os.ParcelUuid;
39+
import android.os.PowerManager;
40+
import android.os.PowerManager.WakeLock;
3741
import android.provider.Settings;
3842
import android.util.Log;
3943

@@ -65,6 +69,10 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
6569
private final BluetoothAdapter mAdapter;
6670
private int mTargetA2dpState;
6771
private BluetoothDevice mPlayingA2dpDevice;
72+
private IntentBroadcastHandler mIntentBroadcastHandler;
73+
private final WakeLock mWakeLock;
74+
75+
private static final int MSG_CONNECTION_STATE_CHANGED = 0;
6876

6977
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
7078
@Override
@@ -131,6 +139,11 @@ private boolean isPhoneDocked(BluetoothDevice device) {
131139
public BluetoothA2dpService(Context context, BluetoothService bluetoothService) {
132140
mContext = context;
133141

142+
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
143+
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "BluetoothA2dpService");
144+
145+
mIntentBroadcastHandler = new IntentBroadcastHandler();
146+
134147
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
135148

136149
mBluetoothService = bluetoothService;
@@ -514,17 +527,15 @@ private void handleSinkStateChange(BluetoothDevice device, int prevState, int st
514527
adjustOtherSinkPriorities(device);
515528
}
516529

517-
Intent intent = new Intent(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
518-
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
519-
intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
520-
intent.putExtra(BluetoothProfile.EXTRA_STATE, state);
521-
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
522-
mContext.sendBroadcast(intent, BLUETOOTH_PERM);
530+
int delay = mAudioManager.setBluetoothA2dpDeviceConnectionState(device, state);
523531

524-
if (DBG) log("A2DP state : device: " + device + " State:" + prevState + "->" + state);
525-
526-
mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.A2DP, state,
527-
prevState);
532+
mWakeLock.acquire();
533+
mIntentBroadcastHandler.sendMessageDelayed(mIntentBroadcastHandler.obtainMessage(
534+
MSG_CONNECTION_STATE_CHANGED,
535+
prevState,
536+
state,
537+
device),
538+
delay);
528539
}
529540
}
530541

@@ -586,6 +597,34 @@ private void onConnectSinkResult(String deviceObjectPath, boolean result) {
586597
}
587598
}
588599

600+
/** Handles A2DP connection state change intent broadcasts. */
601+
private class IntentBroadcastHandler extends Handler {
602+
603+
private void onConnectionStateChanged(BluetoothDevice device, int prevState, int state) {
604+
Intent intent = new Intent(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
605+
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
606+
intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
607+
intent.putExtra(BluetoothProfile.EXTRA_STATE, state);
608+
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
609+
mContext.sendBroadcast(intent, BLUETOOTH_PERM);
610+
611+
if (DBG) log("A2DP state : device: " + device + " State:" + prevState + "->" + state);
612+
613+
mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.A2DP, state,
614+
prevState);
615+
}
616+
617+
@Override
618+
public void handleMessage(Message msg) {
619+
switch (msg.what) {
620+
case MSG_CONNECTION_STATE_CHANGED:
621+
onConnectionStateChanged((BluetoothDevice) msg.obj, msg.arg1, msg.arg2);
622+
mWakeLock.release();
623+
break;
624+
}
625+
}
626+
}
627+
589628
@Override
590629
protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
591630
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);

media/java/android/media/AudioManager.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import android.annotation.SdkConstant;
2020
import android.annotation.SdkConstant.SdkConstantType;
2121
import android.app.PendingIntent;
22+
import android.bluetooth.BluetoothDevice;
2223
import android.content.ComponentName;
2324
import android.content.Context;
2425
import android.content.Intent;
@@ -2376,6 +2377,42 @@ public int getDevicesForStream(int streamType) {
23762377
}
23772378
}
23782379

2380+
/**
2381+
* Indicate wired accessory connection state change.
2382+
* @param device type of device connected/disconnected (AudioManager.DEVICE_OUT_xxx)
2383+
* @param state new connection state: 1 connected, 0 disconnected
2384+
* @param name device name
2385+
* {@hide}
2386+
*/
2387+
public void setWiredDeviceConnectionState(int device, int state, String name) {
2388+
IAudioService service = getService();
2389+
try {
2390+
service.setWiredDeviceConnectionState(device, state, name);
2391+
} catch (RemoteException e) {
2392+
Log.e(TAG, "Dead object in setWiredDeviceConnectionState "+e);
2393+
}
2394+
}
2395+
2396+
/**
2397+
* Indicate A2DP sink connection state change.
2398+
* @param device Bluetooth device connected/disconnected
2399+
* @param state new connection state (BluetoothProfile.STATE_xxx)
2400+
* @return a delay in ms that the caller should wait before broadcasting
2401+
* BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent.
2402+
* {@hide}
2403+
*/
2404+
public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state) {
2405+
IAudioService service = getService();
2406+
int delay = 0;
2407+
try {
2408+
delay = service.setBluetoothA2dpDeviceConnectionState(device, state);
2409+
} catch (RemoteException e) {
2410+
Log.e(TAG, "Dead object in setBluetoothA2dpDeviceConnectionState "+e);
2411+
} finally {
2412+
return delay;
2413+
}
2414+
}
2415+
23792416
/** {@hide} */
23802417
public IRingtonePlayer getRingtonePlayer() {
23812418
try {

media/java/android/media/AudioService.java

Lines changed: 125 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
135135
private static final int MSG_RCDISPLAY_UPDATE = 13;
136136
private static final int MSG_SET_ALL_VOLUMES = 14;
137137
private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 15;
138+
private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 16;
139+
private static final int MSG_SET_A2DP_CONNECTION_STATE = 17;
138140

139141

140142
// flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be
@@ -442,15 +444,9 @@ public AudioService(Context context) {
442444

443445
// Register for device connection intent broadcasts.
444446
IntentFilter intentFilter =
445-
new IntentFilter(Intent.ACTION_HEADSET_PLUG);
446-
447-
intentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
448-
intentFilter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
447+
new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
449448
intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
450449
intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
451-
intentFilter.addAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG);
452-
intentFilter.addAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
453-
intentFilter.addAction(Intent.ACTION_HDMI_AUDIO_PLUG);
454450
intentFilter.addAction(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG);
455451
intentFilter.addAction(Intent.ACTION_USB_AUDIO_DEVICE_PLUG);
456452
intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
@@ -1961,7 +1957,19 @@ public void onServiceConnected(int profile, BluetoothProfile proxy) {
19611957
deviceList = a2dp.getConnectedDevices();
19621958
if (deviceList.size() > 0) {
19631959
btDevice = deviceList.get(0);
1964-
handleA2dpConnectionStateChange(btDevice, a2dp.getConnectionState(btDevice));
1960+
synchronized (mConnectedDevices) {
1961+
int state = a2dp.getConnectionState(btDevice);
1962+
int delay = checkSendBecomingNoisyIntent(
1963+
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
1964+
(state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
1965+
sendMsg(mAudioHandler,
1966+
MSG_SET_A2DP_CONNECTION_STATE,
1967+
SENDMSG_QUEUE,
1968+
state,
1969+
0,
1970+
btDevice,
1971+
delay);
1972+
}
19651973
}
19661974
break;
19671975

@@ -2262,6 +2270,36 @@ private int getDeviceForStream(int stream) {
22622270
return device;
22632271
}
22642272

2273+
public void setWiredDeviceConnectionState(int device, int state, String name) {
2274+
synchronized (mConnectedDevices) {
2275+
int delay = checkSendBecomingNoisyIntent(device, state);
2276+
sendMsg(mAudioHandler,
2277+
MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
2278+
SENDMSG_QUEUE,
2279+
device,
2280+
state,
2281+
name,
2282+
delay);
2283+
}
2284+
}
2285+
2286+
public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state)
2287+
{
2288+
int delay;
2289+
synchronized (mConnectedDevices) {
2290+
delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
2291+
(state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
2292+
sendMsg(mAudioHandler,
2293+
MSG_SET_A2DP_CONNECTION_STATE,
2294+
SENDMSG_QUEUE,
2295+
state,
2296+
0,
2297+
device,
2298+
delay);
2299+
}
2300+
return delay;
2301+
}
2302+
22652303
///////////////////////////////////////////////////////////////////////////
22662304
// Inner classes
22672305
///////////////////////////////////////////////////////////////////////////
@@ -2959,6 +2997,14 @@ public void handleMessage(Message msg) {
29592997
case MSG_BT_HEADSET_CNCT_FAILED:
29602998
resetBluetoothSco();
29612999
break;
3000+
3001+
case MSG_SET_WIRED_DEVICE_CONNECTION_STATE:
3002+
onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj);
3003+
break;
3004+
3005+
case MSG_SET_A2DP_CONNECTION_STATE:
3006+
onSetA2dpConnectionState((BluetoothDevice)msg.obj, msg.arg1);
3007+
break;
29623008
}
29633009
}
29643010
}
@@ -3020,7 +3066,6 @@ private void sendBecomingNoisyIntent() {
30203066

30213067
// must be called synchronized on mConnectedDevices
30223068
private void makeA2dpDeviceUnavailableNow(String address) {
3023-
sendBecomingNoisyIntent();
30243069
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
30253070
AudioSystem.DEVICE_STATE_UNAVAILABLE,
30263071
address);
@@ -3050,7 +3095,7 @@ private boolean hasScheduledA2dpDockTimeout() {
30503095
return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT);
30513096
}
30523097

3053-
private void handleA2dpConnectionStateChange(BluetoothDevice btDevice, int state)
3098+
private void onSetA2dpConnectionState(BluetoothDevice btDevice, int state)
30543099
{
30553100
if (btDevice == null) {
30563101
return;
@@ -3116,6 +3161,76 @@ private boolean handleDeviceConnection(boolean connected, int device, String par
31163161
return false;
31173162
}
31183163

3164+
// Devices which removal triggers intent ACTION_AUDIO_BECOMING_NOISY. The intent is only
3165+
// sent if none of these devices is connected.
3166+
int mBecomingNoisyIntentDevices =
3167+
AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
3168+
AudioSystem.DEVICE_OUT_ALL_A2DP;
3169+
3170+
// must be called before removing the device from mConnectedDevices
3171+
private int checkSendBecomingNoisyIntent(int device, int state) {
3172+
int delay = 0;
3173+
if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) {
3174+
int devices = 0;
3175+
for (int dev : mConnectedDevices.keySet()) {
3176+
if ((dev & mBecomingNoisyIntentDevices) != 0) {
3177+
devices |= dev;
3178+
}
3179+
}
3180+
if (devices == device) {
3181+
delay = 1000;
3182+
sendBecomingNoisyIntent();
3183+
}
3184+
}
3185+
3186+
if (mAudioHandler.hasMessages(MSG_SET_A2DP_CONNECTION_STATE) ||
3187+
mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) {
3188+
delay = 1000;
3189+
}
3190+
return delay;
3191+
}
3192+
3193+
private void sendDeviceConnectionIntent(int device, int state, String name)
3194+
{
3195+
Intent intent = new Intent();
3196+
3197+
intent.putExtra("state", state);
3198+
intent.putExtra("name", name);
3199+
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3200+
3201+
if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) {
3202+
intent.setAction(Intent.ACTION_HEADSET_PLUG);
3203+
intent.putExtra("microphone", 1);
3204+
} else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) {
3205+
intent.setAction(Intent.ACTION_HEADSET_PLUG);
3206+
intent.putExtra("microphone", 0);
3207+
} else if (device == AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET) {
3208+
intent.setAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG);
3209+
} else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) {
3210+
intent.setAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
3211+
} else if (device == AudioSystem.DEVICE_OUT_AUX_DIGITAL) {
3212+
intent.setAction(Intent.ACTION_HDMI_AUDIO_PLUG);
3213+
}
3214+
3215+
ActivityManagerNative.broadcastStickyIntent(intent, null);
3216+
}
3217+
3218+
private void onSetWiredDeviceConnectionState(int device, int state, String name)
3219+
{
3220+
synchronized (mConnectedDevices) {
3221+
if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
3222+
(device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) {
3223+
setBluetoothA2dpOnInt(true);
3224+
}
3225+
handleDeviceConnection((state == 1), device, "");
3226+
if ((state != 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
3227+
(device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) {
3228+
setBluetoothA2dpOnInt(false);
3229+
}
3230+
sendDeviceConnectionIntent(device, state, name);
3231+
}
3232+
}
3233+
31193234
/* cache of the address of the last dock the device was connected to */
31203235
private String mDockAddress;
31213236

@@ -3151,12 +3266,6 @@ public void onReceive(Context context, Intent intent) {
31513266
config = AudioSystem.FORCE_NONE;
31523267
}
31533268
AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config);
3154-
} else if (action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) {
3155-
state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
3156-
BluetoothProfile.STATE_DISCONNECTED);
3157-
BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
3158-
3159-
handleA2dpConnectionStateChange(btDevice, state);
31603269
} else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
31613270
state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
31623271
BluetoothProfile.STATE_DISCONNECTED);
@@ -3197,43 +3306,9 @@ public void onReceive(Context context, Intent intent) {
31973306
}
31983307
}
31993308
}
3200-
} else if (action.equals(Intent.ACTION_HEADSET_PLUG)) {
3201-
state = intent.getIntExtra("state", 0);
3202-
int microphone = intent.getIntExtra("microphone", 0);
3203-
3204-
if (microphone != 0) {
3205-
device = AudioSystem.DEVICE_OUT_WIRED_HEADSET;
3206-
} else {
3207-
device = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
3208-
}
3209-
// enable A2DP before notifying headset disconnection to avoid glitches
3210-
if (state == 0) {
3211-
setBluetoothA2dpOnInt(true);
3212-
}
3213-
handleDeviceConnection((state == 1), device, "");
3214-
// disable A2DP after notifying headset connection to avoid glitches
3215-
if (state != 0) {
3216-
setBluetoothA2dpOnInt(false);
3217-
}
3218-
} else if (action.equals(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG)) {
3219-
state = intent.getIntExtra("state", 0);
3220-
Log.v(TAG, "Broadcast Receiver: Got ACTION_ANALOG_AUDIO_DOCK_PLUG, state = "+state);
3221-
handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET, "");
3222-
} else if (action.equals(Intent.ACTION_HDMI_AUDIO_PLUG)) {
3223-
state = intent.getIntExtra("state", 0);
3224-
Log.v(TAG, "Broadcast Receiver: Got ACTION_HDMI_AUDIO_PLUG, state = "+state);
3225-
handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_AUX_DIGITAL, "");
3226-
} else if (action.equals(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG)) {
3227-
state = intent.getIntExtra("state", 0);
3228-
Log.v(TAG,
3229-
"Broadcast Receiver Got ACTION_DIGITAL_AUDIO_DOCK_PLUG, state = " + state);
3230-
handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET, "");
32313309
} else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ||
32323310
action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) {
32333311
state = intent.getIntExtra("state", 0);
3234-
if (state == 0) {
3235-
sendBecomingNoisyIntent();
3236-
}
32373312
int alsaCard = intent.getIntExtra("card", -1);
32383313
int alsaDevice = intent.getIntExtra("device", -1);
32393314
String params = (alsaCard == -1 && alsaDevice == -1 ? ""

0 commit comments

Comments
 (0)