Loading jni/com_android_bluetooth_a2dp.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -305,7 +305,7 @@ static void informAudioFocusStateNative(JNIEnv *env, jobject object, int state) } static jboolean isSrcNative(JNIEnv *env, jobject object, jbyteArray address) { static jint isSrcNative(JNIEnv *env, jobject object, jbyteArray address) { jbyte *addr; bt_status_t status; Loading @@ -321,7 +321,7 @@ static jboolean isSrcNative(JNIEnv *env, jobject object, jbyteArray address) { ALOGE("Failed HF disconnection, status: %d", status); } env->ReleaseByteArrayElements(address, addr, 0); return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; return status; } static void suspendA2dpNative(JNIEnv *env, jobject object) { Loading Loading @@ -352,7 +352,7 @@ static JNINativeMethod sMethods[] = { {"connectA2dpNative", "([B)Z", (void *) connectA2dpNative}, {"disconnectA2dpNative", "([B)Z", (void *) disconnectA2dpNative}, {"allowConnectionNative", "(I)V", (void *) allowConnectionNative}, {"isSrcNative", "([B)Z", (void *) isSrcNative}, {"isSrcNative", "([B)I", (void *) isSrcNative}, {"suspendA2dpNative", "()V", (void *) suspendA2dpNative}, {"resumeA2dpNative", "()V", (void *) resumeA2dpNative}, {"informAudioFocusStateNative", "(I)V", (void *) informAudioFocusStateNative}, Loading src/com/android/bluetooth/a2dp/A2dpService.java +22 −0 Original line number Diff line number Diff line Loading @@ -201,6 +201,28 @@ public class A2dpService extends ProfileService { return priority; } public boolean setLastConnectedA2dpSepType(BluetoothDevice device, int sepType) { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); Log.d(TAG,"setLastConnectedA2dpSepType: " + sepType); Settings.Global.putInt(getContentResolver(), Settings.Global.getBluetoothLastConnectedA2dpSepTypeKey(device.getAddress()), sepType); return true; } public int getLastConnectedA2dpSepType(BluetoothDevice device) { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); int sepType = Settings.Global.getInt(getContentResolver(), Settings.Global.getBluetoothLastConnectedA2dpSepTypeKey(device.getAddress()), BluetoothProfile.PROFILE_A2DP_UNDEFINED); return sepType; } /* Absolute volume implementation */ public boolean isAvrcpAbsoluteVolumeSupported() { return mAvrcp.isAbsoluteVolumeSupported(); Loading src/com/android/bluetooth/a2dp/A2dpStateMachine.java +39 −10 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import android.os.ParcelUuid; import android.util.Log; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.AbstractionLayer; import com.android.bluetooth.btservice.ProfileService; import com.android.internal.util.IState; import com.android.internal.util.State; Loading Loading @@ -560,6 +561,11 @@ final class A2dpStateMachine extends StateMachine { BluetoothProfile.STATE_DISCONNECTING); break; } if (mPlayingA2dpDevice != null) { broadcastAudioState(mPlayingA2dpDevice, BluetoothA2dp.STATE_NOT_PLAYING, BluetoothA2dp.STATE_PLAYING); mPlayingA2dpDevice = null; } transitionTo(mPending); } break; Loading Loading @@ -609,7 +615,8 @@ final class A2dpStateMachine extends StateMachine { loge("Disconnected from unknown device: " + device); } if (isSrcNative(getByteAddress(device))) { if (isSrcNative(getByteAddress(device)) == AbstractionLayer.BT_STATUS_SUCCESS) { // in case PEER DEVICE is A2DP SRC we need to manager audio focus int status = mAudioManager.abandonAudioFocus(mAudioFocusListener); log("Status loss returned " + status); Loading @@ -625,7 +632,8 @@ final class A2dpStateMachine extends StateMachine { private void processAudioFocusRequestEvent(int enable, BluetoothDevice device) { if (mPlayingA2dpDevice != null) { if ((isSrcNative(getByteAddress(device))) && (enable == 1)){ if ((isSrcNative(getByteAddress(device)) == AbstractionLayer.BT_STATUS_SUCCESS) && (enable == 1)){ // in case PEER DEVICE is A2DP SRC we need to manager audio focus int status = mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,AudioManager.AUDIOFOCUS_GAIN); Loading Loading @@ -667,9 +675,14 @@ final class A2dpStateMachine extends StateMachine { } } // true if peer device is source boolean isConnectedSrc(BluetoothDevice device) { return isSrcNative(getByteAddress(device)); if (isSrcNative(getByteAddress(device)) == AbstractionLayer.BT_STATUS_SUCCESS) return true; else return false; } int getConnectionState(BluetoothDevice device) { Loading Loading @@ -768,17 +781,31 @@ final class A2dpStateMachine extends StateMachine { // This method does not check for error conditon (newState == prevState) private void broadcastConnectionState(BluetoothDevice device, int newState, int prevState) { int delay; // in case PEER DEVICE is A2DP SRC we don't need to tell AUDIO if (!isSrcNative(getByteAddress(device))) { int delay = 0; // in case PEER DEVICE is A2DP SNK we need to tell AUDIO if (isSrcNative(getByteAddress(device)) == AbstractionLayer.BT_STATUS_FAIL) { // do not update delay for disconecting as by time disconnect comes // Sep end point is cleared delay = mAudioManager.setBluetoothA2dpDeviceConnectionState(device, newState); if (newState == BluetoothProfile.STATE_DISCONNECTING) delay = 0; log("Peer Device is SNK"); if (newState == BluetoothProfile.STATE_CONNECTED) { mService.setLastConnectedA2dpSepType (device, BluetoothProfile.PROFILE_A2DP_SNK); } } else { delay = 0; log("Peer Device is SRC"); if (newState == BluetoothProfile.STATE_CONNECTED) { mService.setLastConnectedA2dpSepType (device, BluetoothProfile.PROFILE_A2DP_SRC); } log("Peer Device is SRC/Not ready yet"); } mWakeLock.acquire(); log("delay is " + delay + "for device " + device); mIntentBroadcastHandler.sendMessageDelayed(mIntentBroadcastHandler.obtainMessage( MSG_CONNECTION_STATE_CHANGED, prevState, Loading Loading @@ -888,7 +915,8 @@ final class A2dpStateMachine extends StateMachine { log("Command Received " + cmd); if (cmd.equals("pause")) { if (mCurrentDevice != null) { if (isSrcNative(getByteAddress(mCurrentDevice))) { if (isSrcNative(getByteAddress(mCurrentDevice)) == AbstractionLayer.BT_STATUS_SUCCESS) { //Camera Pauses the Playback before starting the Video recording //But it doesn't start the playback once recording is completed. //Disconnecting the A2dp to move the A2dpSink to proper state. Loading @@ -912,7 +940,8 @@ final class A2dpStateMachine extends StateMachine { switch(focusChange){ case AudioManager.AUDIOFOCUS_LOSS: if (mCurrentDevice != null) { if (isSrcNative(getByteAddress(mCurrentDevice))) { if (isSrcNative(getByteAddress(mCurrentDevice)) == AbstractionLayer.BT_STATUS_SUCCESS) { // in case of perm loss, disconnect the link disconnectA2dpNative(getByteAddress(mCurrentDevice)); // in case PEER DEVICE is A2DP SRC we need to manage audio focus Loading Loading @@ -973,7 +1002,7 @@ final class A2dpStateMachine extends StateMachine { private native boolean connectA2dpNative(byte[] address); private native boolean disconnectA2dpNative(byte[] address); private native void allowConnectionNative(int isValid); private native boolean isSrcNative(byte[] address); private native int isSrcNative(byte[] address); private native void suspendA2dpNative(); private native void resumeA2dpNative(); private native void informAudioFocusStateNative(int state); Loading src/com/android/bluetooth/btservice/AdapterService.java +1 −0 Original line number Diff line number Diff line Loading @@ -1279,6 +1279,7 @@ public class AdapterService extends Service { } else if((a2dpConnDevList.isEmpty()) && (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_ON) && (a2dpService.getLastConnectedA2dpSepType(device) == BluetoothProfile.PROFILE_A2DP_SNK)&& (hsConnected || (hsService.getPriority(device) == BluetoothProfile.PRIORITY_OFF))) { a2dpService.connect(device); } Loading Loading
jni/com_android_bluetooth_a2dp.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -305,7 +305,7 @@ static void informAudioFocusStateNative(JNIEnv *env, jobject object, int state) } static jboolean isSrcNative(JNIEnv *env, jobject object, jbyteArray address) { static jint isSrcNative(JNIEnv *env, jobject object, jbyteArray address) { jbyte *addr; bt_status_t status; Loading @@ -321,7 +321,7 @@ static jboolean isSrcNative(JNIEnv *env, jobject object, jbyteArray address) { ALOGE("Failed HF disconnection, status: %d", status); } env->ReleaseByteArrayElements(address, addr, 0); return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; return status; } static void suspendA2dpNative(JNIEnv *env, jobject object) { Loading Loading @@ -352,7 +352,7 @@ static JNINativeMethod sMethods[] = { {"connectA2dpNative", "([B)Z", (void *) connectA2dpNative}, {"disconnectA2dpNative", "([B)Z", (void *) disconnectA2dpNative}, {"allowConnectionNative", "(I)V", (void *) allowConnectionNative}, {"isSrcNative", "([B)Z", (void *) isSrcNative}, {"isSrcNative", "([B)I", (void *) isSrcNative}, {"suspendA2dpNative", "()V", (void *) suspendA2dpNative}, {"resumeA2dpNative", "()V", (void *) resumeA2dpNative}, {"informAudioFocusStateNative", "(I)V", (void *) informAudioFocusStateNative}, Loading
src/com/android/bluetooth/a2dp/A2dpService.java +22 −0 Original line number Diff line number Diff line Loading @@ -201,6 +201,28 @@ public class A2dpService extends ProfileService { return priority; } public boolean setLastConnectedA2dpSepType(BluetoothDevice device, int sepType) { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); Log.d(TAG,"setLastConnectedA2dpSepType: " + sepType); Settings.Global.putInt(getContentResolver(), Settings.Global.getBluetoothLastConnectedA2dpSepTypeKey(device.getAddress()), sepType); return true; } public int getLastConnectedA2dpSepType(BluetoothDevice device) { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); int sepType = Settings.Global.getInt(getContentResolver(), Settings.Global.getBluetoothLastConnectedA2dpSepTypeKey(device.getAddress()), BluetoothProfile.PROFILE_A2DP_UNDEFINED); return sepType; } /* Absolute volume implementation */ public boolean isAvrcpAbsoluteVolumeSupported() { return mAvrcp.isAbsoluteVolumeSupported(); Loading
src/com/android/bluetooth/a2dp/A2dpStateMachine.java +39 −10 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import android.os.ParcelUuid; import android.util.Log; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.AbstractionLayer; import com.android.bluetooth.btservice.ProfileService; import com.android.internal.util.IState; import com.android.internal.util.State; Loading Loading @@ -560,6 +561,11 @@ final class A2dpStateMachine extends StateMachine { BluetoothProfile.STATE_DISCONNECTING); break; } if (mPlayingA2dpDevice != null) { broadcastAudioState(mPlayingA2dpDevice, BluetoothA2dp.STATE_NOT_PLAYING, BluetoothA2dp.STATE_PLAYING); mPlayingA2dpDevice = null; } transitionTo(mPending); } break; Loading Loading @@ -609,7 +615,8 @@ final class A2dpStateMachine extends StateMachine { loge("Disconnected from unknown device: " + device); } if (isSrcNative(getByteAddress(device))) { if (isSrcNative(getByteAddress(device)) == AbstractionLayer.BT_STATUS_SUCCESS) { // in case PEER DEVICE is A2DP SRC we need to manager audio focus int status = mAudioManager.abandonAudioFocus(mAudioFocusListener); log("Status loss returned " + status); Loading @@ -625,7 +632,8 @@ final class A2dpStateMachine extends StateMachine { private void processAudioFocusRequestEvent(int enable, BluetoothDevice device) { if (mPlayingA2dpDevice != null) { if ((isSrcNative(getByteAddress(device))) && (enable == 1)){ if ((isSrcNative(getByteAddress(device)) == AbstractionLayer.BT_STATUS_SUCCESS) && (enable == 1)){ // in case PEER DEVICE is A2DP SRC we need to manager audio focus int status = mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,AudioManager.AUDIOFOCUS_GAIN); Loading Loading @@ -667,9 +675,14 @@ final class A2dpStateMachine extends StateMachine { } } // true if peer device is source boolean isConnectedSrc(BluetoothDevice device) { return isSrcNative(getByteAddress(device)); if (isSrcNative(getByteAddress(device)) == AbstractionLayer.BT_STATUS_SUCCESS) return true; else return false; } int getConnectionState(BluetoothDevice device) { Loading Loading @@ -768,17 +781,31 @@ final class A2dpStateMachine extends StateMachine { // This method does not check for error conditon (newState == prevState) private void broadcastConnectionState(BluetoothDevice device, int newState, int prevState) { int delay; // in case PEER DEVICE is A2DP SRC we don't need to tell AUDIO if (!isSrcNative(getByteAddress(device))) { int delay = 0; // in case PEER DEVICE is A2DP SNK we need to tell AUDIO if (isSrcNative(getByteAddress(device)) == AbstractionLayer.BT_STATUS_FAIL) { // do not update delay for disconecting as by time disconnect comes // Sep end point is cleared delay = mAudioManager.setBluetoothA2dpDeviceConnectionState(device, newState); if (newState == BluetoothProfile.STATE_DISCONNECTING) delay = 0; log("Peer Device is SNK"); if (newState == BluetoothProfile.STATE_CONNECTED) { mService.setLastConnectedA2dpSepType (device, BluetoothProfile.PROFILE_A2DP_SNK); } } else { delay = 0; log("Peer Device is SRC"); if (newState == BluetoothProfile.STATE_CONNECTED) { mService.setLastConnectedA2dpSepType (device, BluetoothProfile.PROFILE_A2DP_SRC); } log("Peer Device is SRC/Not ready yet"); } mWakeLock.acquire(); log("delay is " + delay + "for device " + device); mIntentBroadcastHandler.sendMessageDelayed(mIntentBroadcastHandler.obtainMessage( MSG_CONNECTION_STATE_CHANGED, prevState, Loading Loading @@ -888,7 +915,8 @@ final class A2dpStateMachine extends StateMachine { log("Command Received " + cmd); if (cmd.equals("pause")) { if (mCurrentDevice != null) { if (isSrcNative(getByteAddress(mCurrentDevice))) { if (isSrcNative(getByteAddress(mCurrentDevice)) == AbstractionLayer.BT_STATUS_SUCCESS) { //Camera Pauses the Playback before starting the Video recording //But it doesn't start the playback once recording is completed. //Disconnecting the A2dp to move the A2dpSink to proper state. Loading @@ -912,7 +940,8 @@ final class A2dpStateMachine extends StateMachine { switch(focusChange){ case AudioManager.AUDIOFOCUS_LOSS: if (mCurrentDevice != null) { if (isSrcNative(getByteAddress(mCurrentDevice))) { if (isSrcNative(getByteAddress(mCurrentDevice)) == AbstractionLayer.BT_STATUS_SUCCESS) { // in case of perm loss, disconnect the link disconnectA2dpNative(getByteAddress(mCurrentDevice)); // in case PEER DEVICE is A2DP SRC we need to manage audio focus Loading Loading @@ -973,7 +1002,7 @@ final class A2dpStateMachine extends StateMachine { private native boolean connectA2dpNative(byte[] address); private native boolean disconnectA2dpNative(byte[] address); private native void allowConnectionNative(int isValid); private native boolean isSrcNative(byte[] address); private native int isSrcNative(byte[] address); private native void suspendA2dpNative(); private native void resumeA2dpNative(); private native void informAudioFocusStateNative(int state); Loading
src/com/android/bluetooth/btservice/AdapterService.java +1 −0 Original line number Diff line number Diff line Loading @@ -1279,6 +1279,7 @@ public class AdapterService extends Service { } else if((a2dpConnDevList.isEmpty()) && (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_ON) && (a2dpService.getLastConnectedA2dpSepType(device) == BluetoothProfile.PROFILE_A2DP_SNK)&& (hsConnected || (hsService.getPriority(device) == BluetoothProfile.PRIORITY_OFF))) { a2dpService.connect(device); } Loading