Loading AndroidManifest.xml +2 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> Loading Loading @@ -72,7 +73,7 @@ android:exported="true" android:process="@string/process"> <path-permission android:path="/btopp" android:pathPrefix="/btopp" android:permission="android.permission.ACCESS_BLUETOOTH_SHARE" /> </provider> <service Loading jni/com_android_bluetooth_gatt.cpp +23 −13 Original line number Diff line number Diff line Loading @@ -158,7 +158,7 @@ static jmethodID method_onGetDescriptor; static jmethodID method_onGetIncludedService; static jmethodID method_onRegisterForNotifications; static jmethodID method_onReadRemoteRssi; static jmethodID method_onClientListen; static jmethodID method_onAdvertiseCallback; /** * Server callback methods Loading Loading @@ -423,11 +423,10 @@ void btgattc_remote_rssi_cb(int client_if,bt_bdaddr_t* bda, int rssi, int status checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); } void btgattc_listen_cb(int status, int client_if) void btgattc_advertise_cb(int status, int client_if) { CHECK_CALLBACK_ENV sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClientListen , status, client_if); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAdvertiseCallback, status, client_if); checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); } Loading @@ -449,7 +448,7 @@ static const btgatt_client_callbacks_t sGattClientCallbacks = { btgattc_write_descriptor_cb, btgattc_execute_write_cb, btgattc_remote_rssi_cb, btgattc_listen_cb btgattc_advertise_cb }; Loading Loading @@ -680,7 +679,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) { method_onAttributeRead= env->GetMethodID(clazz, "onAttributeRead", "(Ljava/lang/String;IIIIZ)V"); method_onAttributeWrite= env->GetMethodID(clazz, "onAttributeWrite", "(Ljava/lang/String;IIIIIZZ[B)V"); method_onExecuteWrite= env->GetMethodID(clazz, "onExecuteWrite", "(Ljava/lang/String;III)V"); method_onClientListen = env->GetMethodID(clazz, "onClientListen", "(II)V"); method_onAdvertiseCallback = env->GetMethodID(clazz, "onAdvertiseCallback", "(II)V"); info("classInitNative: Success!"); } Loading Loading @@ -1058,7 +1057,7 @@ static void gattClientReadRemoteRssiNative(JNIEnv* env, jobject object, jint cli sGattIf->client->read_remote_rssi(clientif, &bda); } static void gattClientListenNative(JNIEnv *env, jobject object, static void gattAdvertiseNative(JNIEnv *env, jobject object, jint client_if, jboolean start) { if (!sGattIf) return; Loading @@ -1066,17 +1065,28 @@ static void gattClientListenNative(JNIEnv *env, jobject object, } static void gattSetAdvDataNative(JNIEnv *env, jobject object, jint client_if, jboolean setScanRsp, jboolean inclName, jboolean inclTxPower, jint minInterval, jint maxInterval, jint appearance, jbyteArray manufacturerData) jboolean inclName, jboolean inclTxPower, jint minInterval, jint maxInterval, jint appearance, jbyteArray manufacturerData, jbyteArray serviceData, jbyteArray serviceUuid) { if (!sGattIf) return; jbyte* arr_data = env->GetByteArrayElements(manufacturerData, 0); jbyte* arr_data = env->GetByteArrayElements(manufacturerData, NULL); uint16_t arr_len = (uint16_t) env->GetArrayLength(manufacturerData); jbyte* service_data = env->GetByteArrayElements(serviceData, NULL); uint16_t service_data_len = (uint16_t) env->GetArrayLength(serviceData); jbyte* service_uuid = env->GetByteArrayElements(serviceUuid, NULL); uint16_t service_uuid_len = (uint16_t) env->GetArrayLength(serviceUuid); sGattIf->client->set_adv_data(client_if, setScanRsp, inclName, inclTxPower, minInterval, maxInterval, appearance, arr_len, (char*)arr_data); minInterval, maxInterval, appearance, arr_len, (char*)arr_data, service_data_len, (char*)service_data, service_uuid_len, (char*)service_uuid); env->ReleaseByteArrayElements(manufacturerData, arr_data, JNI_ABORT); env->ReleaseByteArrayElements(serviceData, service_data, JNI_ABORT); env->ReleaseByteArrayElements(serviceUuid, service_uuid, JNI_ABORT); } Loading Loading @@ -1292,7 +1302,7 @@ static JNINativeMethod sMethods[] = { {"gattClientExecuteWriteNative", "(IZ)V", (void *) gattClientExecuteWriteNative}, {"gattClientRegisterForNotificationsNative", "(ILjava/lang/String;IIJJIJJZ)V", (void *) gattClientRegisterForNotificationsNative}, {"gattClientReadRemoteRssiNative", "(ILjava/lang/String;)V", (void *) gattClientReadRemoteRssiNative}, {"gattClientListenNative", "(IZ)V", (void *) gattClientListenNative}, {"gattAdvertiseNative", "(IZ)V", (void *) gattAdvertiseNative}, {"gattServerRegisterAppNative", "(JJ)V", (void *) gattServerRegisterAppNative}, {"gattServerUnregisterAppNative", "(I)V", (void *) gattServerUnregisterAppNative}, Loading @@ -1309,7 +1319,7 @@ static JNINativeMethod sMethods[] = { {"gattServerSendNotificationNative", "(III[B)V", (void *) gattServerSendNotificationNative}, {"gattServerSendResponseNative", "(IIIIII[BI)V", (void *) gattServerSendResponseNative}, {"gattSetAdvDataNative", "(IZZZIII[B)V", (void *) gattSetAdvDataNative}, {"gattSetAdvDataNative", "(IZZZIII[B[B[B)V", (void *) gattSetAdvDataNative}, {"gattTestNative", "(IJJLjava/lang/String;IIIII)V", (void *) gattTestNative}, }; Loading src/com/android/bluetooth/a2dp/A2dpService.java +5 −1 Original line number Diff line number Diff line Loading @@ -51,8 +51,8 @@ public class A2dpService extends ProfileService { } protected boolean start() { mStateMachine = A2dpStateMachine.make(this, this); mAvrcp = Avrcp.make(this); mStateMachine = A2dpStateMachine.make(this, this); setA2dpService(this); return true; } Loading Loading @@ -189,6 +189,10 @@ public class A2dpService extends ProfileService { mAvrcp.setAbsoluteVolume(volume); } public void setAvrcpAudioState(int state) { mAvrcp.setA2dpAudioState(state); } synchronized boolean isA2dpPlaying(BluetoothDevice device) { enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); Loading src/com/android/bluetooth/a2dp/A2dpStateMachine.java +6 −4 Original line number Diff line number Diff line Loading @@ -562,6 +562,7 @@ final class A2dpStateMachine extends StateMachine { case AUDIO_STATE_STARTED: if (mPlayingA2dpDevice == null) { mPlayingA2dpDevice = device; mService.setAvrcpAudioState(BluetoothA2dp.STATE_PLAYING); broadcastAudioState(device, BluetoothA2dp.STATE_PLAYING, BluetoothA2dp.STATE_NOT_PLAYING); } Loading @@ -569,6 +570,7 @@ final class A2dpStateMachine extends StateMachine { case AUDIO_STATE_STOPPED: if (mPlayingA2dpDevice != null) { mPlayingA2dpDevice = null; mService.setAvrcpAudioState(BluetoothA2dp.STATE_NOT_PLAYING); broadcastAudioState(device, BluetoothA2dp.STATE_NOT_PLAYING, BluetoothA2dp.STATE_PLAYING); } Loading src/com/android/bluetooth/a2dp/Avrcp.java +38 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import java.util.Timer; import java.util.TimerTask; import android.app.PendingIntent; import android.bluetooth.BluetoothA2dp; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; Loading Loading @@ -117,6 +118,7 @@ final class Avrcp { private static final int MESSAGE_FAST_FORWARD = 10; private static final int MESSAGE_REWIND = 11; private static final int MESSAGE_CHANGE_PLAY_POS = 12; private static final int MESSAGE_SET_A2DP_AUDIO_STATE = 13; private static final int MSG_UPDATE_STATE = 100; private static final int MSG_SET_METADATA = 101; private static final int MSG_SET_TRANSPORT_CONTROLS = 102; Loading Loading @@ -447,8 +449,22 @@ final class Avrcp { sendMessageDelayed(posMsg, SKIP_PERIOD); } break; case MESSAGE_SET_A2DP_AUDIO_STATE: if (DEBUG) Log.v(TAG, "MESSAGE_SET_A2DP_AUDIO_STATE:" + msg.arg1); updateA2dpAudioState(msg.arg1); break; } } } private void updateA2dpAudioState(int state) { boolean isPlaying = (state == BluetoothA2dp.STATE_PLAYING); if (isPlaying != isPlayingState(mCurrentPlayState)) { updatePlayPauseState(isPlaying ? RemoteControlClient.PLAYSTATE_PLAYING : RemoteControlClient.PLAYSTATE_PAUSED, RemoteControlClient.PLAYBACK_POSITION_INVALID); } } private void updatePlayPauseState(int state, long currentPosMs) { Loading Loading @@ -735,6 +751,20 @@ final class Avrcp { return playStatus; } private boolean isPlayingState(int playState) { boolean isPlaying = false; switch (playState) { case RemoteControlClient.PLAYSTATE_PLAYING: case RemoteControlClient.PLAYSTATE_BUFFERING: isPlaying = true; break; default: isPlaying = false; break; } return isPlaying; } /** * This is called from AudioService. It will return whether this device supports abs volume. * NOT USED AT THE MOMENT. Loading Loading @@ -788,6 +818,14 @@ final class Avrcp { return (int) Math.ceil((double) volume*AVRCP_MAX_VOL/mAudioStreamMax); } /** * This is called from A2dpStateMachine to set A2dp audio state. */ public void setA2dpAudioState(int state) { Message msg = mHandler.obtainMessage(MESSAGE_SET_A2DP_AUDIO_STATE, state, 0); mHandler.sendMessage(msg); } // Do not modify without updating the HAL bt_rc.h files. // match up with btrc_play_status_t enum of bt_rc.h Loading Loading
AndroidManifest.xml +2 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> Loading Loading @@ -72,7 +73,7 @@ android:exported="true" android:process="@string/process"> <path-permission android:path="/btopp" android:pathPrefix="/btopp" android:permission="android.permission.ACCESS_BLUETOOTH_SHARE" /> </provider> <service Loading
jni/com_android_bluetooth_gatt.cpp +23 −13 Original line number Diff line number Diff line Loading @@ -158,7 +158,7 @@ static jmethodID method_onGetDescriptor; static jmethodID method_onGetIncludedService; static jmethodID method_onRegisterForNotifications; static jmethodID method_onReadRemoteRssi; static jmethodID method_onClientListen; static jmethodID method_onAdvertiseCallback; /** * Server callback methods Loading Loading @@ -423,11 +423,10 @@ void btgattc_remote_rssi_cb(int client_if,bt_bdaddr_t* bda, int rssi, int status checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); } void btgattc_listen_cb(int status, int client_if) void btgattc_advertise_cb(int status, int client_if) { CHECK_CALLBACK_ENV sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClientListen , status, client_if); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAdvertiseCallback, status, client_if); checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); } Loading @@ -449,7 +448,7 @@ static const btgatt_client_callbacks_t sGattClientCallbacks = { btgattc_write_descriptor_cb, btgattc_execute_write_cb, btgattc_remote_rssi_cb, btgattc_listen_cb btgattc_advertise_cb }; Loading Loading @@ -680,7 +679,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) { method_onAttributeRead= env->GetMethodID(clazz, "onAttributeRead", "(Ljava/lang/String;IIIIZ)V"); method_onAttributeWrite= env->GetMethodID(clazz, "onAttributeWrite", "(Ljava/lang/String;IIIIIZZ[B)V"); method_onExecuteWrite= env->GetMethodID(clazz, "onExecuteWrite", "(Ljava/lang/String;III)V"); method_onClientListen = env->GetMethodID(clazz, "onClientListen", "(II)V"); method_onAdvertiseCallback = env->GetMethodID(clazz, "onAdvertiseCallback", "(II)V"); info("classInitNative: Success!"); } Loading Loading @@ -1058,7 +1057,7 @@ static void gattClientReadRemoteRssiNative(JNIEnv* env, jobject object, jint cli sGattIf->client->read_remote_rssi(clientif, &bda); } static void gattClientListenNative(JNIEnv *env, jobject object, static void gattAdvertiseNative(JNIEnv *env, jobject object, jint client_if, jboolean start) { if (!sGattIf) return; Loading @@ -1066,17 +1065,28 @@ static void gattClientListenNative(JNIEnv *env, jobject object, } static void gattSetAdvDataNative(JNIEnv *env, jobject object, jint client_if, jboolean setScanRsp, jboolean inclName, jboolean inclTxPower, jint minInterval, jint maxInterval, jint appearance, jbyteArray manufacturerData) jboolean inclName, jboolean inclTxPower, jint minInterval, jint maxInterval, jint appearance, jbyteArray manufacturerData, jbyteArray serviceData, jbyteArray serviceUuid) { if (!sGattIf) return; jbyte* arr_data = env->GetByteArrayElements(manufacturerData, 0); jbyte* arr_data = env->GetByteArrayElements(manufacturerData, NULL); uint16_t arr_len = (uint16_t) env->GetArrayLength(manufacturerData); jbyte* service_data = env->GetByteArrayElements(serviceData, NULL); uint16_t service_data_len = (uint16_t) env->GetArrayLength(serviceData); jbyte* service_uuid = env->GetByteArrayElements(serviceUuid, NULL); uint16_t service_uuid_len = (uint16_t) env->GetArrayLength(serviceUuid); sGattIf->client->set_adv_data(client_if, setScanRsp, inclName, inclTxPower, minInterval, maxInterval, appearance, arr_len, (char*)arr_data); minInterval, maxInterval, appearance, arr_len, (char*)arr_data, service_data_len, (char*)service_data, service_uuid_len, (char*)service_uuid); env->ReleaseByteArrayElements(manufacturerData, arr_data, JNI_ABORT); env->ReleaseByteArrayElements(serviceData, service_data, JNI_ABORT); env->ReleaseByteArrayElements(serviceUuid, service_uuid, JNI_ABORT); } Loading Loading @@ -1292,7 +1302,7 @@ static JNINativeMethod sMethods[] = { {"gattClientExecuteWriteNative", "(IZ)V", (void *) gattClientExecuteWriteNative}, {"gattClientRegisterForNotificationsNative", "(ILjava/lang/String;IIJJIJJZ)V", (void *) gattClientRegisterForNotificationsNative}, {"gattClientReadRemoteRssiNative", "(ILjava/lang/String;)V", (void *) gattClientReadRemoteRssiNative}, {"gattClientListenNative", "(IZ)V", (void *) gattClientListenNative}, {"gattAdvertiseNative", "(IZ)V", (void *) gattAdvertiseNative}, {"gattServerRegisterAppNative", "(JJ)V", (void *) gattServerRegisterAppNative}, {"gattServerUnregisterAppNative", "(I)V", (void *) gattServerUnregisterAppNative}, Loading @@ -1309,7 +1319,7 @@ static JNINativeMethod sMethods[] = { {"gattServerSendNotificationNative", "(III[B)V", (void *) gattServerSendNotificationNative}, {"gattServerSendResponseNative", "(IIIIII[BI)V", (void *) gattServerSendResponseNative}, {"gattSetAdvDataNative", "(IZZZIII[B)V", (void *) gattSetAdvDataNative}, {"gattSetAdvDataNative", "(IZZZIII[B[B[B)V", (void *) gattSetAdvDataNative}, {"gattTestNative", "(IJJLjava/lang/String;IIIII)V", (void *) gattTestNative}, }; Loading
src/com/android/bluetooth/a2dp/A2dpService.java +5 −1 Original line number Diff line number Diff line Loading @@ -51,8 +51,8 @@ public class A2dpService extends ProfileService { } protected boolean start() { mStateMachine = A2dpStateMachine.make(this, this); mAvrcp = Avrcp.make(this); mStateMachine = A2dpStateMachine.make(this, this); setA2dpService(this); return true; } Loading Loading @@ -189,6 +189,10 @@ public class A2dpService extends ProfileService { mAvrcp.setAbsoluteVolume(volume); } public void setAvrcpAudioState(int state) { mAvrcp.setA2dpAudioState(state); } synchronized boolean isA2dpPlaying(BluetoothDevice device) { enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); Loading
src/com/android/bluetooth/a2dp/A2dpStateMachine.java +6 −4 Original line number Diff line number Diff line Loading @@ -562,6 +562,7 @@ final class A2dpStateMachine extends StateMachine { case AUDIO_STATE_STARTED: if (mPlayingA2dpDevice == null) { mPlayingA2dpDevice = device; mService.setAvrcpAudioState(BluetoothA2dp.STATE_PLAYING); broadcastAudioState(device, BluetoothA2dp.STATE_PLAYING, BluetoothA2dp.STATE_NOT_PLAYING); } Loading @@ -569,6 +570,7 @@ final class A2dpStateMachine extends StateMachine { case AUDIO_STATE_STOPPED: if (mPlayingA2dpDevice != null) { mPlayingA2dpDevice = null; mService.setAvrcpAudioState(BluetoothA2dp.STATE_NOT_PLAYING); broadcastAudioState(device, BluetoothA2dp.STATE_NOT_PLAYING, BluetoothA2dp.STATE_PLAYING); } Loading
src/com/android/bluetooth/a2dp/Avrcp.java +38 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import java.util.Timer; import java.util.TimerTask; import android.app.PendingIntent; import android.bluetooth.BluetoothA2dp; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; Loading Loading @@ -117,6 +118,7 @@ final class Avrcp { private static final int MESSAGE_FAST_FORWARD = 10; private static final int MESSAGE_REWIND = 11; private static final int MESSAGE_CHANGE_PLAY_POS = 12; private static final int MESSAGE_SET_A2DP_AUDIO_STATE = 13; private static final int MSG_UPDATE_STATE = 100; private static final int MSG_SET_METADATA = 101; private static final int MSG_SET_TRANSPORT_CONTROLS = 102; Loading Loading @@ -447,8 +449,22 @@ final class Avrcp { sendMessageDelayed(posMsg, SKIP_PERIOD); } break; case MESSAGE_SET_A2DP_AUDIO_STATE: if (DEBUG) Log.v(TAG, "MESSAGE_SET_A2DP_AUDIO_STATE:" + msg.arg1); updateA2dpAudioState(msg.arg1); break; } } } private void updateA2dpAudioState(int state) { boolean isPlaying = (state == BluetoothA2dp.STATE_PLAYING); if (isPlaying != isPlayingState(mCurrentPlayState)) { updatePlayPauseState(isPlaying ? RemoteControlClient.PLAYSTATE_PLAYING : RemoteControlClient.PLAYSTATE_PAUSED, RemoteControlClient.PLAYBACK_POSITION_INVALID); } } private void updatePlayPauseState(int state, long currentPosMs) { Loading Loading @@ -735,6 +751,20 @@ final class Avrcp { return playStatus; } private boolean isPlayingState(int playState) { boolean isPlaying = false; switch (playState) { case RemoteControlClient.PLAYSTATE_PLAYING: case RemoteControlClient.PLAYSTATE_BUFFERING: isPlaying = true; break; default: isPlaying = false; break; } return isPlaying; } /** * This is called from AudioService. It will return whether this device supports abs volume. * NOT USED AT THE MOMENT. Loading Loading @@ -788,6 +818,14 @@ final class Avrcp { return (int) Math.ceil((double) volume*AVRCP_MAX_VOL/mAudioStreamMax); } /** * This is called from A2dpStateMachine to set A2dp audio state. */ public void setA2dpAudioState(int state) { Message msg = mHandler.obtainMessage(MESSAGE_SET_A2DP_AUDIO_STATE, state, 0); mHandler.sendMessage(msg); } // Do not modify without updating the HAL bt_rc.h files. // match up with btrc_play_status_t enum of bt_rc.h Loading