Loading src/com/android/bluetooth/a2dp/A2dpService.java +60 −0 Original line number Original line Diff line number Diff line Loading @@ -278,6 +278,48 @@ public class A2dpService extends ProfileService { return mStateMachine.getConnectionState(device); return mStateMachine.getConnectionState(device); } } /** * Set the active device. * * @param device the active device * @return true on success, otherwise false */ public boolean setActiveDevice(BluetoothDevice device) { if (DBG) { Log.d(TAG, "setActiveDevice(): " + device); } enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) { return false; } ParcelUuid[] featureUuids = device.getUuids(); if ((BluetoothUuid.containsAnyUuid(featureUuids, A2DP_SOURCE_UUID)) && !(BluetoothUuid.containsAllUuids(featureUuids, A2DP_SOURCE_SINK_UUIDS))) { Log.e(TAG, "Remote does not have A2dp Sink UUID"); return false; } int connectionState = mStateMachine.getConnectionState(device); if (connectionState != BluetoothProfile.STATE_CONNECTED) { return false; } mStateMachine.sendMessage(A2dpStateMachine.SET_ACTIVE_DEVICE, device); return true; } /** * Get the active device. * * @return the active device or null if no device is active */ public BluetoothDevice getActiveDevice() { enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); return mStateMachine.getActiveDevice(); } public boolean setPriority(BluetoothDevice device, int priority) { public boolean setPriority(BluetoothDevice device, int priority) { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); Settings.Global.putInt(getContentResolver(), Settings.Global.putInt(getContentResolver(), Loading Loading @@ -472,6 +514,24 @@ public class A2dpService extends ProfileService { return service.getConnectionState(device); return service.getConnectionState(device); } } @Override public boolean setActiveDevice(BluetoothDevice device) { A2dpService service = getService(); if (service == null) { return false; } return service.setActiveDevice(device); } @Override public BluetoothDevice getActiveDevice() { A2dpService service = getService(); if (service == null) { return null; } return service.getActiveDevice(); } @Override @Override public boolean setPriority(BluetoothDevice device, int priority) { public boolean setPriority(BluetoothDevice device, int priority) { A2dpService service = getService(); A2dpService service = getService(); Loading src/com/android/bluetooth/a2dp/A2dpStateMachine.java +60 −2 Original line number Original line Diff line number Diff line Loading @@ -63,6 +63,7 @@ final class A2dpStateMachine extends StateMachine { static final int CONNECT = 1; static final int CONNECT = 1; static final int DISCONNECT = 2; static final int DISCONNECT = 2; static final int SET_ACTIVE_DEVICE = 3; @VisibleForTesting @VisibleForTesting static final int STACK_EVENT = 101; static final int STACK_EVENT = 101; private static final int CONNECT_TIMEOUT = 201; private static final int CONNECT_TIMEOUT = 201; Loading @@ -82,6 +83,8 @@ final class A2dpStateMachine extends StateMachine { private final AudioManager mAudioManager; private final AudioManager mAudioManager; private BluetoothCodecConfig[] mCodecConfigPriorities; private BluetoothCodecConfig[] mCodecConfigPriorities; // mActiveDevice is the connected device that is connected and selected // as active. // mCurrentDevice is the device connected before the state changes // mCurrentDevice is the device connected before the state changes // mTargetDevice is the device to be connected // mTargetDevice is the device to be connected // mIncomingDevice is the device connecting to us, valid only in Pending state // mIncomingDevice is the device connecting to us, valid only in Pending state Loading @@ -104,6 +107,7 @@ final class A2dpStateMachine extends StateMachine { // mCurrentDevice is not null, mTargetDevice is null // mCurrentDevice is not null, mTargetDevice is null // Incoming connections Pending // Incoming connections Pending // Both mCurrentDevice and mTargetDevice are null // Both mCurrentDevice and mTargetDevice are null private BluetoothDevice mActiveDevice = null; private BluetoothDevice mCurrentDevice = null; private BluetoothDevice mCurrentDevice = null; private BluetoothDevice mTargetDevice = null; private BluetoothDevice mTargetDevice = null; private BluetoothDevice mIncomingDevice = null; private BluetoothDevice mIncomingDevice = null; Loading Loading @@ -277,12 +281,15 @@ final class A2dpStateMachine extends StateMachine { if (DBG) { if (DBG) { Log.d(TAG, "Disconnected process message: " + message.what); Log.d(TAG, "Disconnected process message: " + message.what); } } if (mCurrentDevice != null || mTargetDevice != null || mIncomingDevice != null) { if (mCurrentDevice != null || mTargetDevice != null || mIncomingDevice != null || mActiveDevice != null) { Log.e(TAG, "ERROR: not null state in Disconnected: current = " + mCurrentDevice Log.e(TAG, "ERROR: not null state in Disconnected: current = " + mCurrentDevice + " target = " + mTargetDevice + " incoming = " + mIncomingDevice); + " target = " + mTargetDevice + " incoming = " + mIncomingDevice + " active = " + mActiveDevice); mCurrentDevice = null; mCurrentDevice = null; mTargetDevice = null; mTargetDevice = null; mIncomingDevice = null; mIncomingDevice = null; mActiveDevice = null; } } boolean retValue = HANDLED; boolean retValue = HANDLED; Loading @@ -309,6 +316,13 @@ final class A2dpStateMachine extends StateMachine { case DISCONNECT: case DISCONNECT: // ignore // ignore break; break; case SET_ACTIVE_DEVICE: BluetoothDevice activeDevice = (BluetoothDevice) message.obj; // Cannot set the active device: not connected Log.e(TAG, "Disconnected: Cannot set active device to " + activeDevice); broadcastActiveDevice(null); break; case STACK_EVENT: case STACK_EVENT: A2dpStackEvent event = (A2dpStackEvent) message.obj; A2dpStackEvent event = (A2dpStackEvent) message.obj; if (DBG) { if (DBG) { Loading Loading @@ -439,6 +453,13 @@ final class A2dpStateMachine extends StateMachine { deferMessage(message); deferMessage(message); } } break; break; case SET_ACTIVE_DEVICE: BluetoothDevice activeDevice = (BluetoothDevice) message.obj; // Cannot set the active device: not connected Log.e(TAG, "Pending: Cannot set active device to " + activeDevice); broadcastActiveDevice(null); break; case STACK_EVENT: case STACK_EVENT: A2dpStackEvent event = (A2dpStackEvent) message.obj; A2dpStackEvent event = (A2dpStackEvent) message.obj; if (DBG) { if (DBG) { Loading Loading @@ -704,6 +725,21 @@ final class A2dpStateMachine extends StateMachine { } } } } break; break; case SET_ACTIVE_DEVICE: { BluetoothDevice device = (BluetoothDevice) message.obj; if (!mCurrentDevice.equals(device)) { Log.e(TAG, "Connected: Cannot set active device to " + device + " : current connected device is " + mCurrentDevice); mActiveDevice = null; } else { if (DBG) { Log.d(TAG, "Connected: Active device set to " + device); } mActiveDevice = device; } broadcastActiveDevice(mActiveDevice); } break; case CONNECT_TIMEOUT: case CONNECT_TIMEOUT: if (mTargetDevice == null) { if (mTargetDevice == null) { Log.e(TAG, "CONNECT_TIMEOUT received for unknown device"); Log.e(TAG, "CONNECT_TIMEOUT received for unknown device"); Loading Loading @@ -844,6 +880,15 @@ final class A2dpStateMachine extends StateMachine { return devices; return devices; } } BluetoothDevice getActiveDevice() { synchronized (this) { if (getCurrentState() == mConnected) { return mActiveDevice; } } return null; } boolean isPlaying(BluetoothDevice device) { boolean isPlaying(BluetoothDevice device) { synchronized (this) { synchronized (this) { if (device.equals(mPlayingA2dpDevice)) { if (device.equals(mPlayingA2dpDevice)) { Loading Loading @@ -997,6 +1042,18 @@ final class A2dpStateMachine extends StateMachine { mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM); mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM); } } private void broadcastActiveDevice(BluetoothDevice device) { if (DBG) { Log.d(TAG, "Active device: " + device); } Intent intent = new Intent(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM); } private void broadcastAudioState(BluetoothDevice device, int newState, private void broadcastAudioState(BluetoothDevice device, int newState, int prevState) { int prevState) { if (DBG) { if (DBG) { Loading @@ -1013,6 +1070,7 @@ final class A2dpStateMachine extends StateMachine { } } public void dump(StringBuilder sb) { public void dump(StringBuilder sb) { ProfileService.println(sb, "mActiveDevice: " + mActiveDevice); ProfileService.println(sb, "mCurrentDevice: " + mCurrentDevice); ProfileService.println(sb, "mCurrentDevice: " + mCurrentDevice); ProfileService.println(sb, "mTargetDevice: " + mTargetDevice); ProfileService.println(sb, "mTargetDevice: " + mTargetDevice); ProfileService.println(sb, "mIncomingDevice: " + mIncomingDevice); ProfileService.println(sb, "mIncomingDevice: " + mIncomingDevice); Loading Loading
src/com/android/bluetooth/a2dp/A2dpService.java +60 −0 Original line number Original line Diff line number Diff line Loading @@ -278,6 +278,48 @@ public class A2dpService extends ProfileService { return mStateMachine.getConnectionState(device); return mStateMachine.getConnectionState(device); } } /** * Set the active device. * * @param device the active device * @return true on success, otherwise false */ public boolean setActiveDevice(BluetoothDevice device) { if (DBG) { Log.d(TAG, "setActiveDevice(): " + device); } enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) { return false; } ParcelUuid[] featureUuids = device.getUuids(); if ((BluetoothUuid.containsAnyUuid(featureUuids, A2DP_SOURCE_UUID)) && !(BluetoothUuid.containsAllUuids(featureUuids, A2DP_SOURCE_SINK_UUIDS))) { Log.e(TAG, "Remote does not have A2dp Sink UUID"); return false; } int connectionState = mStateMachine.getConnectionState(device); if (connectionState != BluetoothProfile.STATE_CONNECTED) { return false; } mStateMachine.sendMessage(A2dpStateMachine.SET_ACTIVE_DEVICE, device); return true; } /** * Get the active device. * * @return the active device or null if no device is active */ public BluetoothDevice getActiveDevice() { enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); return mStateMachine.getActiveDevice(); } public boolean setPriority(BluetoothDevice device, int priority) { public boolean setPriority(BluetoothDevice device, int priority) { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); Settings.Global.putInt(getContentResolver(), Settings.Global.putInt(getContentResolver(), Loading Loading @@ -472,6 +514,24 @@ public class A2dpService extends ProfileService { return service.getConnectionState(device); return service.getConnectionState(device); } } @Override public boolean setActiveDevice(BluetoothDevice device) { A2dpService service = getService(); if (service == null) { return false; } return service.setActiveDevice(device); } @Override public BluetoothDevice getActiveDevice() { A2dpService service = getService(); if (service == null) { return null; } return service.getActiveDevice(); } @Override @Override public boolean setPriority(BluetoothDevice device, int priority) { public boolean setPriority(BluetoothDevice device, int priority) { A2dpService service = getService(); A2dpService service = getService(); Loading
src/com/android/bluetooth/a2dp/A2dpStateMachine.java +60 −2 Original line number Original line Diff line number Diff line Loading @@ -63,6 +63,7 @@ final class A2dpStateMachine extends StateMachine { static final int CONNECT = 1; static final int CONNECT = 1; static final int DISCONNECT = 2; static final int DISCONNECT = 2; static final int SET_ACTIVE_DEVICE = 3; @VisibleForTesting @VisibleForTesting static final int STACK_EVENT = 101; static final int STACK_EVENT = 101; private static final int CONNECT_TIMEOUT = 201; private static final int CONNECT_TIMEOUT = 201; Loading @@ -82,6 +83,8 @@ final class A2dpStateMachine extends StateMachine { private final AudioManager mAudioManager; private final AudioManager mAudioManager; private BluetoothCodecConfig[] mCodecConfigPriorities; private BluetoothCodecConfig[] mCodecConfigPriorities; // mActiveDevice is the connected device that is connected and selected // as active. // mCurrentDevice is the device connected before the state changes // mCurrentDevice is the device connected before the state changes // mTargetDevice is the device to be connected // mTargetDevice is the device to be connected // mIncomingDevice is the device connecting to us, valid only in Pending state // mIncomingDevice is the device connecting to us, valid only in Pending state Loading @@ -104,6 +107,7 @@ final class A2dpStateMachine extends StateMachine { // mCurrentDevice is not null, mTargetDevice is null // mCurrentDevice is not null, mTargetDevice is null // Incoming connections Pending // Incoming connections Pending // Both mCurrentDevice and mTargetDevice are null // Both mCurrentDevice and mTargetDevice are null private BluetoothDevice mActiveDevice = null; private BluetoothDevice mCurrentDevice = null; private BluetoothDevice mCurrentDevice = null; private BluetoothDevice mTargetDevice = null; private BluetoothDevice mTargetDevice = null; private BluetoothDevice mIncomingDevice = null; private BluetoothDevice mIncomingDevice = null; Loading Loading @@ -277,12 +281,15 @@ final class A2dpStateMachine extends StateMachine { if (DBG) { if (DBG) { Log.d(TAG, "Disconnected process message: " + message.what); Log.d(TAG, "Disconnected process message: " + message.what); } } if (mCurrentDevice != null || mTargetDevice != null || mIncomingDevice != null) { if (mCurrentDevice != null || mTargetDevice != null || mIncomingDevice != null || mActiveDevice != null) { Log.e(TAG, "ERROR: not null state in Disconnected: current = " + mCurrentDevice Log.e(TAG, "ERROR: not null state in Disconnected: current = " + mCurrentDevice + " target = " + mTargetDevice + " incoming = " + mIncomingDevice); + " target = " + mTargetDevice + " incoming = " + mIncomingDevice + " active = " + mActiveDevice); mCurrentDevice = null; mCurrentDevice = null; mTargetDevice = null; mTargetDevice = null; mIncomingDevice = null; mIncomingDevice = null; mActiveDevice = null; } } boolean retValue = HANDLED; boolean retValue = HANDLED; Loading @@ -309,6 +316,13 @@ final class A2dpStateMachine extends StateMachine { case DISCONNECT: case DISCONNECT: // ignore // ignore break; break; case SET_ACTIVE_DEVICE: BluetoothDevice activeDevice = (BluetoothDevice) message.obj; // Cannot set the active device: not connected Log.e(TAG, "Disconnected: Cannot set active device to " + activeDevice); broadcastActiveDevice(null); break; case STACK_EVENT: case STACK_EVENT: A2dpStackEvent event = (A2dpStackEvent) message.obj; A2dpStackEvent event = (A2dpStackEvent) message.obj; if (DBG) { if (DBG) { Loading Loading @@ -439,6 +453,13 @@ final class A2dpStateMachine extends StateMachine { deferMessage(message); deferMessage(message); } } break; break; case SET_ACTIVE_DEVICE: BluetoothDevice activeDevice = (BluetoothDevice) message.obj; // Cannot set the active device: not connected Log.e(TAG, "Pending: Cannot set active device to " + activeDevice); broadcastActiveDevice(null); break; case STACK_EVENT: case STACK_EVENT: A2dpStackEvent event = (A2dpStackEvent) message.obj; A2dpStackEvent event = (A2dpStackEvent) message.obj; if (DBG) { if (DBG) { Loading Loading @@ -704,6 +725,21 @@ final class A2dpStateMachine extends StateMachine { } } } } break; break; case SET_ACTIVE_DEVICE: { BluetoothDevice device = (BluetoothDevice) message.obj; if (!mCurrentDevice.equals(device)) { Log.e(TAG, "Connected: Cannot set active device to " + device + " : current connected device is " + mCurrentDevice); mActiveDevice = null; } else { if (DBG) { Log.d(TAG, "Connected: Active device set to " + device); } mActiveDevice = device; } broadcastActiveDevice(mActiveDevice); } break; case CONNECT_TIMEOUT: case CONNECT_TIMEOUT: if (mTargetDevice == null) { if (mTargetDevice == null) { Log.e(TAG, "CONNECT_TIMEOUT received for unknown device"); Log.e(TAG, "CONNECT_TIMEOUT received for unknown device"); Loading Loading @@ -844,6 +880,15 @@ final class A2dpStateMachine extends StateMachine { return devices; return devices; } } BluetoothDevice getActiveDevice() { synchronized (this) { if (getCurrentState() == mConnected) { return mActiveDevice; } } return null; } boolean isPlaying(BluetoothDevice device) { boolean isPlaying(BluetoothDevice device) { synchronized (this) { synchronized (this) { if (device.equals(mPlayingA2dpDevice)) { if (device.equals(mPlayingA2dpDevice)) { Loading Loading @@ -997,6 +1042,18 @@ final class A2dpStateMachine extends StateMachine { mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM); mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM); } } private void broadcastActiveDevice(BluetoothDevice device) { if (DBG) { Log.d(TAG, "Active device: " + device); } Intent intent = new Intent(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM); } private void broadcastAudioState(BluetoothDevice device, int newState, private void broadcastAudioState(BluetoothDevice device, int newState, int prevState) { int prevState) { if (DBG) { if (DBG) { Loading @@ -1013,6 +1070,7 @@ final class A2dpStateMachine extends StateMachine { } } public void dump(StringBuilder sb) { public void dump(StringBuilder sb) { ProfileService.println(sb, "mActiveDevice: " + mActiveDevice); ProfileService.println(sb, "mCurrentDevice: " + mCurrentDevice); ProfileService.println(sb, "mCurrentDevice: " + mCurrentDevice); ProfileService.println(sb, "mTargetDevice: " + mTargetDevice); ProfileService.println(sb, "mTargetDevice: " + mTargetDevice); ProfileService.println(sb, "mIncomingDevice: " + mIncomingDevice); ProfileService.println(sb, "mIncomingDevice: " + mIncomingDevice); Loading