diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index a840382704c8..62811d8fa283 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + @@ -23,7 +23,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 16be74455f3c..bfbcce6d3fb7 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,13 +19,13 @@ - + - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 5d1f4f2b87c2..a9ab9a179972 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,10 +17,10 @@ - + - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 50b84e85dab8..aa692e4a947f 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + @@ -23,7 +23,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 16be74455f3c..bfbcce6d3fb7 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,13 +19,13 @@ - + - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 8a3f371adc25..6a7e53c3c4ac 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + @@ -23,7 +23,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 1be6c92a12e1..50d72278824a 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,10 +17,10 @@ - + - + @@ -122,7 +122,7 @@ - + diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 9336f8428c08..c624c4a4b6b0 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "bce92f813f48346b36ce9dffc16b0c93d0ac8330", + "revision": "14400ee07e836d74039e2317feebc0a13fcb60c8", "repo_path": "/integration/gaia-central" } diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index ada352510cfb..1a072435d2e2 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,12 +17,12 @@ - + - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index fa3ce0781c32..6d3ddcb11a11 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index dc69b0b317cd..293c7beff0d5 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,10 +17,10 @@ - + - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index b4b0695a8ee0..2aa0fb97bcc2 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,12 +17,12 @@ - + - + diff --git a/dom/bluetooth/BluetoothCommon.h b/dom/bluetooth/BluetoothCommon.h index e15273ec2299..9667957694c7 100644 --- a/dom/bluetooth/BluetoothCommon.h +++ b/dom/bluetooth/BluetoothCommon.h @@ -339,6 +339,19 @@ enum BluetoothObjectType { TYPE_INVALID }; +enum BluetoothA2dpAudioState { + A2DP_AUDIO_STATE_REMOTE_SUSPEND, + A2DP_AUDIO_STATE_STOPPED, + A2DP_AUDIO_STATE_STARTED, +}; + +enum BluetoothA2dpConnectionState { + A2DP_CONNECTION_STATE_DISCONNECTED, + A2DP_CONNECTION_STATE_CONNECTING, + A2DP_CONNECTION_STATE_CONNECTED, + A2DP_CONNECTION_STATE_DISCONNECTING +}; + enum ControlPlayStatus { PLAYSTATUS_STOPPED = 0x00, PLAYSTATUS_PLAYING = 0x01, @@ -349,6 +362,16 @@ enum ControlPlayStatus { PLAYSTATUS_ERROR = 0xFF, }; +enum BluetoothAvrcpMediaAttribute { + AVRCP_MEDIA_ATTRIBUTE_TITLE, + AVRCP_MEDIA_ATTRIBUTE_ARTIST, + AVRCP_MEDIA_ATTRIBUTE_ALBUM, + AVRCP_MEDIA_ATTRIBUTE_TRACK_NUM, + AVRCP_MEDIA_ATTRIBUTE_NUM_TRACKS, + AVRCP_MEDIA_ATTRIBUTE_GENRE, + AVRCP_MEDIA_ATTRIBUTE_PLAYING_TIME +}; + enum BluetoothAvrcpPlayerAttribute { AVRCP_PLAYER_ATTRIBUTE_EQUALIZER, AVRCP_PLAYER_ATTRIBUTE_REPEAT, @@ -378,6 +401,13 @@ enum BluetoothAvrcpNotification { AVRCP_NTF_CHANGED }; +enum BluetoothAvrcpRemoteFeature { + AVRCP_REMOTE_FEATURE_NONE, + AVRCP_REMOTE_FEATURE_METADATA, + AVRCP_REMOTE_FEATURE_ABSOLUTE_VOLUME, + AVRCP_REMOTE_FEATURE_BROWSE +}; + struct BluetoothAvrcpElementAttribute { uint32_t mId; nsString mValue; @@ -392,6 +422,12 @@ struct BluetoothAvrcpNotificationParam { uint8_t mValues[256]; }; +struct BluetoothAvrcpPlayerSettings { + uint8_t mNumAttr; + uint8_t mIds[256]; + uint8_t mValues[256]; +}; + END_BLUETOOTH_NAMESPACE #endif // mozilla_dom_bluetooth_bluetoothcommon_h__ diff --git a/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp b/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp index 882274386237..f82d6ae7cc59 100644 --- a/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp +++ b/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp @@ -7,7 +7,6 @@ #include "base/basictypes.h" #include "BluetoothA2dpManager.h" -#include "BluetoothInterface.h" #include "BluetoothCommon.h" #include "BluetoothService.h" #include "BluetoothSocket.h" @@ -37,171 +36,42 @@ namespace { #endif } // anonymous namespace -class SinkPropertyChangedHandler : public nsRunnable -{ -public: - SinkPropertyChangedHandler(const BluetoothSignal& aSignal) - : mSignal(aSignal) - { - } - - NS_IMETHOD - Run() - { - MOZ_ASSERT(NS_IsMainThread()); - - BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get(); - NS_ENSURE_TRUE(a2dp, NS_ERROR_FAILURE); - a2dp->HandleSinkPropertyChanged(mSignal); - - return NS_OK; - } - -private: - BluetoothSignal mSignal; -}; - -class RequestPlayStatusTask : public nsRunnable -{ -public: - RequestPlayStatusTask() - { - MOZ_ASSERT(!NS_IsMainThread()); - } - - nsresult Run() - { - MOZ_ASSERT(NS_IsMainThread()); - - BluetoothSignal signal(NS_LITERAL_STRING(REQUEST_MEDIA_PLAYSTATUS_ID), - NS_LITERAL_STRING(KEY_ADAPTER), - InfallibleTArray()); - - BluetoothService* bs = BluetoothService::Get(); - NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE); - bs->DistributeSignal(signal); - - return NS_OK; - } -}; - #if ANDROID_VERSION > 17 -class UpdateRegisterNotificationTask : public nsRunnable -{ -public: - UpdateRegisterNotificationTask(BluetoothAvrcpEvent aEvent, uint32_t aParam) - : mEvent(aEvent) - , mParam(aParam) - { - MOZ_ASSERT(!NS_IsMainThread()); - } - - nsresult Run() - { - MOZ_ASSERT(NS_IsMainThread()); - - BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get(); - NS_ENSURE_TRUE(a2dp, NS_OK); - a2dp->UpdateRegisterNotification(mEvent, mParam); - return NS_OK; - } -private: - BluetoothAvrcpEvent mEvent; - uint32_t mParam; -}; - /* * This function maps attribute id and returns corresponding values - * Attribute id refers to btrc_media_attr_t in bt_rc.h */ static void -ConvertAttributeString(int aAttrId, nsAString& aAttrStr) +ConvertAttributeString(BluetoothAvrcpMediaAttribute aAttrId, + nsAString& aAttrStr) { BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get(); NS_ENSURE_TRUE_VOID(a2dp); switch (aAttrId) { - case BTRC_MEDIA_ATTR_TITLE: + case AVRCP_MEDIA_ATTRIBUTE_TITLE: a2dp->GetTitle(aAttrStr); break; - case BTRC_MEDIA_ATTR_ARTIST: + case AVRCP_MEDIA_ATTRIBUTE_ARTIST: a2dp->GetArtist(aAttrStr); break; - case BTRC_MEDIA_ATTR_ALBUM: + case AVRCP_MEDIA_ATTRIBUTE_ALBUM: a2dp->GetAlbum(aAttrStr); break; - case BTRC_MEDIA_ATTR_TRACK_NUM: + case AVRCP_MEDIA_ATTRIBUTE_TRACK_NUM: aAttrStr.AppendInt(a2dp->GetMediaNumber()); break; - case BTRC_MEDIA_ATTR_NUM_TRACKS: + case AVRCP_MEDIA_ATTRIBUTE_NUM_TRACKS: aAttrStr.AppendInt(a2dp->GetTotalMediaNumber()); break; - case BTRC_MEDIA_ATTR_GENRE: + case AVRCP_MEDIA_ATTRIBUTE_GENRE: // TODO: we currently don't support genre from music player aAttrStr.Truncate(); break; - case BTRC_MEDIA_ATTR_PLAYING_TIME: + case AVRCP_MEDIA_ATTRIBUTE_PLAYING_TIME: aAttrStr.AppendInt(a2dp->GetDuration()); break; } } - -class UpdateElementAttrsTask : public nsRunnable -{ -public: - UpdateElementAttrsTask(uint8_t aNumAttr, const btrc_media_attr_t* aPlayerAttrs) - : mNumAttr(aNumAttr) - { - MOZ_ASSERT(!NS_IsMainThread()); - - mAttrs = new BluetoothAvrcpElementAttribute[mNumAttr]; - - for (uint8_t i = 0; i < mNumAttr; ++i) { - mAttrs[i].mId = aPlayerAttrs[i]; - } - } - - nsresult Run() - { - MOZ_ASSERT(NS_IsMainThread()); - - for (uint8_t i = 0; i < mNumAttr; ++i) { - ConvertAttributeString(mAttrs[i].mId, mAttrs[i].mValue); - } - - NS_ENSURE_TRUE(sBtAvrcpInterface, NS_OK); - sBtAvrcpInterface->GetElementAttrRsp(mNumAttr, mAttrs, nullptr); - - return NS_OK; - } - -private: - uint8_t mNumAttr; - nsAutoArrayPtr mAttrs; -}; - -class UpdatePassthroughCmdTask : public nsRunnable -{ -public: - UpdatePassthroughCmdTask(const nsAString& aName) - : mName(aName) - { - MOZ_ASSERT(!NS_IsMainThread()); - } - - nsresult Run() - { - MOZ_ASSERT(NS_IsMainThread()); - - NS_NAMED_LITERAL_STRING(type, "media-button"); - BroadcastSystemMessage(type, BluetoothValue(mName)); - - return NS_OK; - } -private: - nsString mName; -}; - #endif NS_IMETHODIMP @@ -233,288 +103,21 @@ BluetoothA2dpManager::Reset() } static void -AvStatusToSinkString(btav_connection_state_t aStatus, nsAString& aState) +AvStatusToSinkString(BluetoothA2dpConnectionState aState, nsAString& aString) { - nsAutoString state; - if (aStatus == BTAV_CONNECTION_STATE_DISCONNECTED) { - aState = NS_LITERAL_STRING("disconnected"); - } else if (aStatus == BTAV_CONNECTION_STATE_CONNECTING) { - aState = NS_LITERAL_STRING("connecting"); - } else if (aStatus == BTAV_CONNECTION_STATE_CONNECTED) { - aState = NS_LITERAL_STRING("connected"); - } else if (aStatus == BTAV_CONNECTION_STATE_DISCONNECTING) { - aState = NS_LITERAL_STRING("disconnecting"); - } else { - BT_WARNING("Unknown sink state"); + static const nsLiteralString sString[] = { + [A2DP_CONNECTION_STATE_DISCONNECTED] = NS_LITERAL_STRING("disconnected"), + [A2DP_CONNECTION_STATE_CONNECTING] = NS_LITERAL_STRING("connecting"), + [A2DP_CONNECTION_STATE_CONNECTED] = NS_LITERAL_STRING("connected"), + [A2DP_CONNECTION_STATE_DISCONNECTING] = NS_LITERAL_STRING("disconnecting") + }; + if (aState >= MOZ_ARRAY_LENGTH(sString)) { + BT_WARNING("Unknown sink state %d", static_cast(aState)); + return; } + aString = sString[aState]; } -static void -A2dpConnectionStateCallback(btav_connection_state_t aState, - bt_bdaddr_t* aBdAddress) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - nsString remoteDeviceBdAddress; - BdAddressTypeToString(aBdAddress, remoteDeviceBdAddress); - - nsString a2dpState; - AvStatusToSinkString(aState, a2dpState); - - InfallibleTArray props; - BT_APPEND_NAMED_VALUE(props, "State", a2dpState); - - BluetoothSignal signal(NS_LITERAL_STRING("AudioSink"), - remoteDeviceBdAddress, props); - NS_DispatchToMainThread(new SinkPropertyChangedHandler(signal)); -} - -static void -A2dpAudioStateCallback(btav_audio_state_t aState, - bt_bdaddr_t* aBdAddress) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - nsString remoteDeviceBdAddress; - BdAddressTypeToString(aBdAddress, remoteDeviceBdAddress); - - nsString a2dpState; - - if (aState == BTAV_AUDIO_STATE_STARTED) { - a2dpState = NS_LITERAL_STRING("playing"); - } else if (aState == BTAV_AUDIO_STATE_STOPPED) { - // for avdtp state stop stream - a2dpState = NS_LITERAL_STRING("connected"); - } else if (aState == BTAV_AUDIO_STATE_REMOTE_SUSPEND) { - // for avdtp state suspend stream from remote side - a2dpState = NS_LITERAL_STRING("connected"); - } - - InfallibleTArray props; - BT_APPEND_NAMED_VALUE(props, "State", a2dpState); - - BluetoothSignal signal(NS_LITERAL_STRING("AudioSink"), - remoteDeviceBdAddress, props); - NS_DispatchToMainThread(new SinkPropertyChangedHandler(signal)); -} - -#if ANDROID_VERSION > 17 -/* - * Avrcp 1.3 callbacks - */ - -/* - * This function is to request Gaia player application to update - * current play status. - * Callback for play status request - */ -static void -AvrcpGetPlayStatusCallback() -{ - MOZ_ASSERT(!NS_IsMainThread()); - - NS_DispatchToMainThread(new RequestPlayStatusTask()); -} - -/* - * This function is trying to get element attributes, which request from CT - * Unlike BlueZ only calls UpdateMetaData, bluedroid does not cache meta data - * information, but instead uses callback AvrcpGetElementAttrCallback and - * call get_element_attr_rsp() to reply request. - * - * Callback to fetch the get element attributes of the current song - * aNumAttr: It represents the number of attributes requested in aPlayerAttrs - * aPlayerAttrs: It represents Attribute Ids - */ -static void -AvrcpGetElementAttrCallback(uint8_t aNumAttr, btrc_media_attr_t* aPlayerAttrs) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - NS_DispatchToMainThread(new UpdateElementAttrsTask(aNumAttr, aPlayerAttrs)); -} - -/* - * Callback for register notification (Play state change/track change/...) - * To reply RegisterNotification INTERIM response - * See AVRCP 1.3 Spec 25.2 - * aParam: It only valids if event_id is BTRC_EVT_PLAY_POS_CHANGED, - * which is playback interval time - */ -static void -AvrcpRegisterNotificationCallback(btrc_event_id_t aEventId, uint32_t aParam) -{ - BluetoothAvrcpEvent event; - - MOZ_ASSERT(!NS_IsMainThread()); - - switch (aEventId) { - case BTRC_EVT_PLAY_STATUS_CHANGED: - event = AVRCP_EVENT_PLAY_STATUS_CHANGED; - case BTRC_EVT_TRACK_CHANGE: - event = AVRCP_EVENT_TRACK_CHANGE; - case BTRC_EVT_TRACK_REACHED_END: - event = AVRCP_EVENT_TRACK_REACHED_END; - case BTRC_EVT_TRACK_REACHED_START: - event = AVRCP_EVENT_TRACK_REACHED_START; - case BTRC_EVT_PLAY_POS_CHANGED: - event = AVRCP_EVENT_PLAY_POS_CHANGED; - case BTRC_EVT_APP_SETTINGS_CHANGED: - event = AVRCP_EVENT_APP_SETTINGS_CHANGED; - break; - default: - BT_LOGR("Unknown event 0x%x", aEventId); - return; - } - - NS_DispatchToMainThread(new UpdateRegisterNotificationTask(event, aParam)); -} - -/* - * Player application settings is optional for Avrcp 1.3 - * B2G 1.3 currently does not support Player application setting - * related functions. Support Player Setting in the future version - */ -static void -AvrcpListPlayerAppAttributeCallback() -{ - MOZ_ASSERT(!NS_IsMainThread()); - -// TODO: Support avrcp application setting related functions -} - -static void -AvrcpListPlayerAppValuesCallback(btrc_player_attr_t aAttrId) -{ - MOZ_ASSERT(!NS_IsMainThread()); - -// TODO: Support avrcp application setting related functions -} - -static void -AvrcpGetPlayerAppValueCallback(uint8_t aNumAttr, - btrc_player_attr_t* aPlayerAttrs) -{ - MOZ_ASSERT(!NS_IsMainThread()); - -// TODO: Support avrcp application setting related functions -} - -static void -AvrcpGetPlayerAppAttrsTextCallback(uint8_t aNumAttr, - btrc_player_attr_t* PlayerAttrs) -{ - MOZ_ASSERT(!NS_IsMainThread()); - -// TODO: Support avrcp application setting related functions -} - -static void -AvrcpGetPlayerAppValuesTextCallback(uint8_t aAttrId, uint8_t aNumVal, - uint8_t* PlayerVals) -{ - MOZ_ASSERT(!NS_IsMainThread()); - -// TODO: Support avrcp application setting related functions -} - -static void -AvrcpSetPlayerAppValueCallback(btrc_player_settings_t* aPlayerVals) -{ - MOZ_ASSERT(!NS_IsMainThread()); - -// TODO: Support avrcp application setting related functions -} -#endif - -#if ANDROID_VERSION > 18 -/* - * This callback function is to get CT features from Feature Bit Mask. - * If Advanced Control Player bit is set, CT supports - * volume sync (absolute volume feature). If Browsing bit is set, Avrcp 1.4 - * Browse feature will be supported - */ -static void -AvrcpRemoteFeaturesCallback(bt_bdaddr_t* aBdAddress, - btrc_remote_features_t aFeatures) -{ -// TODO: Support avrcp 1.4 absolute volume/browse -} - -/* - * This callback function is to get notification that volume changed on the - * remote car kit (if it supports Avrcp 1.4), not notification from phone. - */ -static void -AvrcpRemoteVolumeChangedCallback(uint8_t aVolume, uint8_t aCType) -{ -// TODO: Support avrcp 1.4 absolute volume/browse -} - -/* - * This callback function is to handle passthrough commands. - */ -static void -AvrcpPassThroughCallback(int aId, int aKeyState) -{ - // Fast-forward and rewind key events won't be generated from bluedroid - // stack after ANDROID_VERSION > 18, but via passthrough callback. - nsAutoString name; - NS_ENSURE_TRUE_VOID(aKeyState == AVRC_KEY_PRESS_STATE || - aKeyState == AVRC_KEY_RELEASE_STATE); - switch (aId) { - case AVRC_ID_FAST_FOR: - if (aKeyState == AVRC_KEY_PRESS_STATE) { - name.AssignLiteral("media-fast-forward-button-press"); - } else { - name.AssignLiteral("media-fast-forward-button-release"); - } - break; - case AVRC_ID_REWIND: - if (aKeyState == AVRC_KEY_PRESS_STATE) { - name.AssignLiteral("media-rewind-button-press"); - } else { - name.AssignLiteral("media-rewind-button-release"); - } - break; - default: - BT_WARNING("Unable to handle the unknown PassThrough command %d", aId); - break; - } - if (!name.IsEmpty()) { - NS_DispatchToMainThread(new UpdatePassthroughCmdTask(name)); - } -} -#endif - -static btav_callbacks_t sBtA2dpCallbacks = { - sizeof(sBtA2dpCallbacks), - A2dpConnectionStateCallback, - A2dpAudioStateCallback -}; - -#if ANDROID_VERSION > 17 -static btrc_callbacks_t sBtAvrcpCallbacks = { - sizeof(sBtAvrcpCallbacks), -#if ANDROID_VERSION > 18 - AvrcpRemoteFeaturesCallback, -#endif - AvrcpGetPlayStatusCallback, - AvrcpListPlayerAppAttributeCallback, - AvrcpListPlayerAppValuesCallback, - AvrcpGetPlayerAppValueCallback, - AvrcpGetPlayerAppAttrsTextCallback, - AvrcpGetPlayerAppValuesTextCallback, - AvrcpSetPlayerAppValueCallback, - AvrcpGetElementAttrCallback, - AvrcpRegisterNotificationCallback, -#if ANDROID_VERSION > 18 - AvrcpRemoteVolumeChangedCallback, - AvrcpPassThroughCallback -#endif -}; -#endif - #if ANDROID_VERSION > 17 class InitAvrcpResultHandler MOZ_FINAL : public BluetoothAvrcpResultHandler { @@ -570,8 +173,8 @@ public: sBtAvrcpInterface = btInf->GetBluetoothAvrcpInterface(); NS_ENSURE_TRUE_VOID(sBtAvrcpInterface); - sBtAvrcpInterface->Init(&sBtAvrcpCallbacks, - new InitAvrcpResultHandler(mRes)); + BluetoothA2dpManager* a2dpManager = BluetoothA2dpManager::Get(); + sBtAvrcpInterface->Init(a2dpManager, new InitAvrcpResultHandler(mRes)); #else /* ...or signal success otherwise. */ if (mRes) { @@ -600,7 +203,8 @@ BluetoothA2dpManager::InitA2dpInterface(BluetoothProfileResultHandler* aRes) sBtA2dpInterface = btInf->GetBluetoothA2dpInterface(); NS_ENSURE_TRUE_VOID(sBtA2dpInterface); - sBtA2dpInterface->Init(&sBtA2dpCallbacks, new InitA2dpResultHandler(aRes)); + BluetoothA2dpManager* a2dpManager = BluetoothA2dpManager::Get(); + sBtA2dpInterface->Init(a2dpManager, new InitA2dpResultHandler(aRes)); } BluetoothA2dpManager::~BluetoothA2dpManager() @@ -1305,5 +909,230 @@ BluetoothA2dpManager::GetArtist(nsAString& aArtist) aArtist.Assign(mArtist); } +/* + * A2DP Notifications + */ + +void +BluetoothA2dpManager::ConnectionStateNotification(BluetoothA2dpConnectionState aState, + const nsAString& aBdAddr) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsString a2dpState; + AvStatusToSinkString(aState, a2dpState); + + InfallibleTArray props; + BT_APPEND_NAMED_VALUE(props, "State", a2dpState); + + HandleSinkPropertyChanged(BluetoothSignal(NS_LITERAL_STRING("AudioSink"), + nsString(aBdAddr), props)); +} + +void +BluetoothA2dpManager::AudioStateNotification(BluetoothA2dpAudioState aState, + const nsAString& aBdAddr) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsString a2dpState; + + if (aState == A2DP_AUDIO_STATE_STARTED) { + a2dpState = NS_LITERAL_STRING("playing"); + } else if (aState == A2DP_AUDIO_STATE_STOPPED) { + // for avdtp state stop stream + a2dpState = NS_LITERAL_STRING("connected"); + } else if (aState == A2DP_AUDIO_STATE_REMOTE_SUSPEND) { + // for avdtp state suspend stream from remote side + a2dpState = NS_LITERAL_STRING("connected"); + } + + InfallibleTArray props; + BT_APPEND_NAMED_VALUE(props, "State", a2dpState); + + HandleSinkPropertyChanged(BluetoothSignal(NS_LITERAL_STRING("AudioSink"), + nsString(aBdAddr), props)); +} + +/* + * AVRCP Notifications + */ + +void +BluetoothA2dpManager::GetPlayStatusNotification() +{ + MOZ_ASSERT(NS_IsMainThread()); + + BluetoothService* bs = BluetoothService::Get(); + if (!bs) { + return; + } + + bs->DistributeSignal( + BluetoothSignal(NS_LITERAL_STRING(REQUEST_MEDIA_PLAYSTATUS_ID), + NS_LITERAL_STRING(KEY_ADAPTER), + InfallibleTArray())); +} + +/* Player application settings is optional for AVRCP 1.3. B2G + * currently does not support player-application-setting related + * functionality. + */ +void +BluetoothA2dpManager::ListPlayerAppAttrNotification() +{ + MOZ_ASSERT(NS_IsMainThread()); + + // TODO: Support AVRCP application-setting-related functions +} + +void +BluetoothA2dpManager::ListPlayerAppValuesNotification( + BluetoothAvrcpPlayerAttribute aAttrId) +{ + MOZ_ASSERT(NS_IsMainThread()); + + // TODO: Support AVRCP application-setting-related functions +} + +void +BluetoothA2dpManager::GetPlayerAppValueNotification( + uint8_t aNumAttrs, const BluetoothAvrcpPlayerAttribute* aAttrs) +{ + MOZ_ASSERT(NS_IsMainThread()); + + // TODO: Support AVRCP application-setting-related functions +} + +void +BluetoothA2dpManager::GetPlayerAppAttrsTextNotification( + uint8_t aNumAttrs, const BluetoothAvrcpPlayerAttribute* aAttrs) +{ + MOZ_ASSERT(NS_IsMainThread()); + + // TODO: Support AVRCP application-setting-related functions +} + +void +BluetoothA2dpManager::GetPlayerAppValuesTextNotification( + uint8_t aAttrId, uint8_t aNumVals, const uint8_t* aValues) +{ + MOZ_ASSERT(NS_IsMainThread()); + + // TODO: Support AVRCP application-setting-related functions +} + +void +BluetoothA2dpManager::SetPlayerAppValueNotification( + const BluetoothAvrcpPlayerSettings& aSettings) +{ + MOZ_ASSERT(NS_IsMainThread()); + + // TODO: Support AVRCP application-setting-related functions +} + +/* This method returns element attributes, which are requested from + * CT. Unlike BlueZ it calls only UpdateMetaData. Bluedroid does not cache + * meta-data information, but instead uses |GetElementAttrNotifications| + * and |GetElementAttrRsp| request them. + */ +void +BluetoothA2dpManager::GetElementAttrNotification( + uint8_t aNumAttrs, const BluetoothAvrcpMediaAttribute* aAttrs) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoArrayPtr attrs( + new BluetoothAvrcpElementAttribute[aNumAttrs]); + + for (uint8_t i = 0; i < aNumAttrs; ++i) { + attrs[i].mId = aAttrs[i]; + ConvertAttributeString( + static_cast(attrs[i].mId), + attrs[i].mValue); + } + +#if ANDROID_VERSION >= 18 + MOZ_ASSERT(sBtAvrcpInterface); + sBtAvrcpInterface->GetElementAttrRsp(aNumAttrs, attrs, nullptr); +#endif // ANDROID_VERSION >= 18 +} + +void +BluetoothA2dpManager::RegisterNotificationNotification( + BluetoothAvrcpEvent aEvent, uint32_t aParam) +{ + MOZ_ASSERT(NS_IsMainThread()); + + BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get(); + if (!a2dp) { + return; + } + +#if ANDROID_VERSION >= 18 + a2dp->UpdateRegisterNotification(aEvent, aParam); +#endif // ANDROID_VERSION >= 18 +} + +/* This method is used to get CT features from the Feature Bit Mask. If + * Advanced Control Player bit is set, the CT supports volume sync (absolute + * volume feature). If Browsing bit is set, AVRCP 1.4 Browse feature will be + * supported. + */ +void +BluetoothA2dpManager::RemoteFeatureNotification( + const nsAString& aBdAddr, unsigned long aFeatures) +{ + MOZ_ASSERT(NS_IsMainThread()); + + // TODO: Support AVRCP 1.4 absolute volume/browse +} + +/* This method is used to get notifications about volume changes on the + * remote car kit (if it supports AVRCP 1.4), not notification from phone. + */ +void +BluetoothA2dpManager::VolumeChangeNotification(uint8_t aVolume, + uint8_t aCType) +{ + MOZ_ASSERT(NS_IsMainThread()); + + // TODO: Support AVRCP 1.4 absolute volume/browse +} + +void +BluetoothA2dpManager::PassthroughCmdNotification(int aId, int aKeyState) +{ + MOZ_ASSERT(NS_IsMainThread()); + + // Fast-forward and rewind key events won't be generated from bluedroid + // stack after ANDROID_VERSION > 18, but via passthrough callback. + nsAutoString name; + NS_ENSURE_TRUE_VOID(aKeyState == AVRC_KEY_PRESS_STATE || + aKeyState == AVRC_KEY_RELEASE_STATE); + switch (aId) { + case AVRC_ID_FAST_FOR: + if (aKeyState == AVRC_KEY_PRESS_STATE) { + name.AssignLiteral("media-fast-forward-button-press"); + } else { + name.AssignLiteral("media-fast-forward-button-release"); + } + break; + case AVRC_ID_REWIND: + if (aKeyState == AVRC_KEY_PRESS_STATE) { + name.AssignLiteral("media-rewind-button-press"); + } else { + name.AssignLiteral("media-rewind-button-release"); + } + break; + default: + BT_WARNING("Unable to handle the unknown PassThrough command %d", aId); + return; + } + + NS_NAMED_LITERAL_STRING(type, "media-button"); + BroadcastSystemMessage(type, BluetoothValue(name)); +} + NS_IMPL_ISUPPORTS(BluetoothA2dpManager, nsIObserver) diff --git a/dom/bluetooth/bluedroid/BluetoothA2dpManager.h b/dom/bluetooth/bluedroid/BluetoothA2dpManager.h index b37decab42a4..1c34607a5c68 100644 --- a/dom/bluetooth/bluedroid/BluetoothA2dpManager.h +++ b/dom/bluetooth/bluedroid/BluetoothA2dpManager.h @@ -8,11 +8,14 @@ #define mozilla_dom_bluetooth_bluetootha2dpmanager_h__ #include "BluetoothCommon.h" +#include "BluetoothInterface.h" #include "BluetoothProfileController.h" #include "BluetoothProfileManagerBase.h" BEGIN_BLUETOOTH_NAMESPACE class BluetoothA2dpManager : public BluetoothProfileManagerBase + , public BluetoothA2dpNotificationHandler + , public BluetoothAvrcpNotificationHandler { public: BT_DECL_PROFILE_MGR_BASE @@ -63,7 +66,6 @@ public: void GetArtist(nsAString& aArtist); private: - class SinkPropertyChangedHandler; BluetoothA2dpManager(); void ResetA2dp(); void ResetAvrcp(); @@ -71,6 +73,46 @@ private: void HandleShutdown(); void NotifyConnectionStatusChanged(); + void ConnectionStateNotification(BluetoothA2dpConnectionState aState, + const nsAString& aBdAddr) MOZ_OVERRIDE; + void AudioStateNotification(BluetoothA2dpAudioState aState, + const nsAString& aBdAddr) MOZ_OVERRIDE; + + void GetPlayStatusNotification() MOZ_OVERRIDE; + + void ListPlayerAppAttrNotification() MOZ_OVERRIDE; + + void ListPlayerAppValuesNotification( + BluetoothAvrcpPlayerAttribute aAttrId) MOZ_OVERRIDE; + + void GetPlayerAppValueNotification( + uint8_t aNumAttrs, + const BluetoothAvrcpPlayerAttribute* aAttrs) MOZ_OVERRIDE; + + void GetPlayerAppAttrsTextNotification( + uint8_t aNumAttrs, + const BluetoothAvrcpPlayerAttribute* aAttrs) MOZ_OVERRIDE; + + void GetPlayerAppValuesTextNotification( + uint8_t aAttrId, uint8_t aNumVals, const uint8_t* aValues) MOZ_OVERRIDE; + + void SetPlayerAppValueNotification( + const BluetoothAvrcpPlayerSettings& aSettings) MOZ_OVERRIDE; + + void GetElementAttrNotification( + uint8_t aNumAttrs, + const BluetoothAvrcpMediaAttribute* aAttrs) MOZ_OVERRIDE; + + void RegisterNotificationNotification( + BluetoothAvrcpEvent aEvent, uint32_t aParam) MOZ_OVERRIDE; + + void RemoteFeatureNotification( + const nsAString& aBdAddr, unsigned long aFeatures) MOZ_OVERRIDE; + + void VolumeChangeNotification(uint8_t aVolume, uint8_t aCType) MOZ_OVERRIDE; + + void PassthroughCmdNotification(int aId, int aKeyState) MOZ_OVERRIDE; + nsString mDeviceAddress; nsRefPtr mController; diff --git a/dom/bluetooth/bluedroid/BluetoothInterface.cpp b/dom/bluetooth/bluedroid/BluetoothInterface.cpp index 4802cdbb5e80..6a520b9f7e93 100644 --- a/dom/bluetooth/bluedroid/BluetoothInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothInterface.cpp @@ -436,18 +436,6 @@ Convert(bt_device_type_t aIn, BluetoothDeviceType& aOut) return NS_OK; } -#if ANDROID_VERSION >= 18 -static nsresult -Convert(const bt_remote_version_t& aIn, BluetoothRemoteInfo& aOut) -{ - aOut.mVerMajor = aIn.version; - aOut.mVerMinor = aIn.sub_ver; - aOut.mManufacturer = aIn.manufacturer; - - return NS_OK; -} -#endif - static nsresult Convert(const bt_service_record_t& aIn, BluetoothServiceRecord& aOut) { @@ -715,7 +703,52 @@ Convert(bthf_volume_type_t aIn, BluetoothHandsfreeVolumeType& aOut) return NS_OK; } +static nsresult +Convert(btav_connection_state_t aIn, BluetoothA2dpConnectionState& aOut) +{ + static const BluetoothA2dpConnectionState sConnectionState[] = { + CONVERT(BTAV_CONNECTION_STATE_DISCONNECTED, + A2DP_CONNECTION_STATE_DISCONNECTED), + CONVERT(BTAV_CONNECTION_STATE_CONNECTING, + A2DP_CONNECTION_STATE_CONNECTING), + CONVERT(BTAV_CONNECTION_STATE_CONNECTED, + A2DP_CONNECTION_STATE_CONNECTED), + CONVERT(BTAV_CONNECTION_STATE_DISCONNECTING, + A2DP_CONNECTION_STATE_DISCONNECTING), + }; + if (aIn >= MOZ_ARRAY_LENGTH(sConnectionState)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sConnectionState[aIn]; + return NS_OK; +} + +static nsresult +Convert(btav_audio_state_t aIn, BluetoothA2dpAudioState& aOut) +{ + static const BluetoothA2dpAudioState sAudioState[] = { + CONVERT(BTAV_AUDIO_STATE_REMOTE_SUSPEND, A2DP_AUDIO_STATE_REMOTE_SUSPEND), + CONVERT(BTAV_AUDIO_STATE_STOPPED, A2DP_AUDIO_STATE_STOPPED), + CONVERT(BTAV_AUDIO_STATE_STARTED, A2DP_AUDIO_STATE_STARTED), + }; + if (aIn >= MOZ_ARRAY_LENGTH(sAudioState)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sAudioState[aIn]; + return NS_OK; +} + #if ANDROID_VERSION >= 18 +static nsresult +Convert(const bt_remote_version_t& aIn, BluetoothRemoteInfo& aOut) +{ + aOut.mVerMajor = aIn.version; + aOut.mVerMinor = aIn.sub_ver; + aOut.mManufacturer = aIn.manufacturer; + + return NS_OK; +} + static nsresult Convert(ControlPlayStatus aIn, btrc_play_status_t& aOut) { @@ -749,6 +782,23 @@ Convert(enum BluetoothAvrcpPlayerAttribute aIn, btrc_player_attr_t& aOut) return NS_OK; } +static nsresult +Convert(btrc_player_attr_t aIn, enum BluetoothAvrcpPlayerAttribute& aOut) +{ + static const BluetoothAvrcpPlayerAttribute sPlayerAttr[] = { + CONVERT(0, static_cast(0)), // invalid, [0] required by gcc + CONVERT(BTRC_PLAYER_ATTR_EQUALIZER, AVRCP_PLAYER_ATTRIBUTE_EQUALIZER), + CONVERT(BTRC_PLAYER_ATTR_REPEAT, AVRCP_PLAYER_ATTRIBUTE_REPEAT), + CONVERT(BTRC_PLAYER_ATTR_SHUFFLE, AVRCP_PLAYER_ATTRIBUTE_SHUFFLE), + CONVERT(BTRC_PLAYER_ATTR_SCAN, AVRCP_PLAYER_ATTRIBUTE_SCAN) + }; + if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sPlayerAttr)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sPlayerAttr[aIn]; + return NS_OK; +} + static nsresult Convert(enum BluetoothAvrcpStatus aIn, btrc_status_t& aOut) { @@ -784,6 +834,47 @@ Convert(enum BluetoothAvrcpEvent aIn, btrc_event_id_t& aOut) return NS_OK; } +static nsresult +Convert(btrc_event_id_t aIn, enum BluetoothAvrcpEvent& aOut) +{ + static const BluetoothAvrcpEvent sEventId[] = { + CONVERT(0, static_cast(0)), // invalid, [0] required by gcc + CONVERT(BTRC_EVT_PLAY_STATUS_CHANGED, AVRCP_EVENT_PLAY_STATUS_CHANGED), + CONVERT(BTRC_EVT_TRACK_CHANGE, AVRCP_EVENT_TRACK_CHANGE), + CONVERT(BTRC_EVT_TRACK_REACHED_END, AVRCP_EVENT_TRACK_REACHED_END), + CONVERT(BTRC_EVT_TRACK_REACHED_START, AVRCP_EVENT_TRACK_REACHED_START), + CONVERT(BTRC_EVT_PLAY_POS_CHANGED, AVRCP_EVENT_PLAY_POS_CHANGED), + CONVERT(6, static_cast(0)), // invalid, [6] required by gcc + CONVERT(7, static_cast(0)), // invalid, [7] required by gcc + CONVERT(BTRC_EVT_APP_SETTINGS_CHANGED, AVRCP_EVENT_APP_SETTINGS_CHANGED) + }; + if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sEventId)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sEventId[aIn]; + return NS_OK; +} + +static nsresult +Convert(btrc_media_attr_t aIn, enum BluetoothAvrcpMediaAttribute& aOut) +{ + static const BluetoothAvrcpMediaAttribute sEventId[] = { + CONVERT(0, static_cast(0)), // invalid, [0] required by gcc + CONVERT(BTRC_MEDIA_ATTR_TITLE, AVRCP_MEDIA_ATTRIBUTE_TITLE), + CONVERT(BTRC_MEDIA_ATTR_ARTIST, AVRCP_MEDIA_ATTRIBUTE_ARTIST), + CONVERT(BTRC_MEDIA_ATTR_ALBUM, AVRCP_MEDIA_ATTRIBUTE_ALBUM), + CONVERT(BTRC_MEDIA_ATTR_TRACK_NUM, AVRCP_MEDIA_ATTRIBUTE_TRACK_NUM), + CONVERT(BTRC_MEDIA_ATTR_NUM_TRACKS, AVRCP_MEDIA_ATTRIBUTE_NUM_TRACKS), + CONVERT(BTRC_MEDIA_ATTR_GENRE, AVRCP_MEDIA_ATTRIBUTE_GENRE), + CONVERT(BTRC_MEDIA_ATTR_PLAYING_TIME, AVRCP_MEDIA_ATTRIBUTE_PLAYING_TIME) + }; + if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sEventId)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sEventId[aIn]; + return NS_OK; +} + static nsresult Convert(enum BluetoothAvrcpNotification aIn, btrc_notification_type_t& aOut) { @@ -811,7 +902,28 @@ Convert(const BluetoothAvrcpElementAttribute& aIn, btrc_element_attr_val_t& aOut return NS_OK; } -#endif +static nsresult +Convert(const btrc_player_settings_t& aIn, BluetoothAvrcpPlayerSettings& aOut) +{ + aOut.mNumAttr = aIn.num_attr; + memcpy(aOut.mIds, aIn.attr_ids, aIn.num_attr); + memcpy(aOut.mValues, aIn.attr_values, aIn.num_attr); + + return NS_OK; +} +#endif // ANDROID_VERSION >= 18 + +#if ANDROID_VERSION >= 19 +static nsresult +Convert(btrc_remote_features_t aIn, unsigned long& aOut) +{ + /* The input type's name is misleading. The converted value is + * actually a bitmask. + */ + aOut = static_cast(aIn); + return NS_OK; +} +#endif // ANDROID_VERSION >= 19 /* |ConvertArray| is a helper for converting arrays. Pass an * instance of this structure as the first argument to |Convert| @@ -2716,6 +2828,69 @@ DispatchBluetoothA2dpResult( return rv; } +// Notification handling +// + +BluetoothA2dpNotificationHandler::~BluetoothA2dpNotificationHandler() +{ } + +static BluetoothA2dpNotificationHandler* sA2dpNotificationHandler; + +struct BluetoothA2dpCallback +{ + class A2dpNotificationHandlerWrapper + { + public: + typedef BluetoothA2dpNotificationHandler ObjectType; + + static ObjectType* GetInstance() + { + MOZ_ASSERT(NS_IsMainThread()); + + return sA2dpNotificationHandler; + } + }; + + // Notifications + + typedef BluetoothNotificationRunnable2 + ConnectionStateNotification; + + typedef BluetoothNotificationRunnable2 + AudioStateNotification; + + // Bluedroid A2DP callbacks + + static void + ConnectionState(btav_connection_state_t aState, bt_bdaddr_t* aBdAddr) + { + ConnectionStateNotification::Dispatch( + &BluetoothA2dpNotificationHandler::ConnectionStateNotification, + aState, aBdAddr); + } + + static void + AudioState(btav_audio_state_t aState, bt_bdaddr_t* aBdAddr) + { + AudioStateNotification::Dispatch( + &BluetoothA2dpNotificationHandler::AudioStateNotification, + aState, aBdAddr); + } +}; + +// Interface +// + BluetoothA2dpInterface::BluetoothA2dpInterface( const btav_interface_t* aInterface) : mInterface(aInterface) @@ -2727,10 +2902,19 @@ BluetoothA2dpInterface::~BluetoothA2dpInterface() { } void -BluetoothA2dpInterface::Init(btav_callbacks_t* aCallbacks, - BluetoothA2dpResultHandler* aRes) +BluetoothA2dpInterface::Init( + BluetoothA2dpNotificationHandler* aNotificationHandler, + BluetoothA2dpResultHandler* aRes) { - bt_status_t status = mInterface->init(aCallbacks); + static btav_callbacks_t sCallbacks = { + sizeof(sCallbacks), + BluetoothA2dpCallback::ConnectionState, + BluetoothA2dpCallback::AudioState + }; + + sA2dpNotificationHandler = aNotificationHandler; + + bt_status_t status = mInterface->init(&sCallbacks); if (aRes) { DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Init, @@ -2834,6 +3018,199 @@ DispatchBluetoothAvrcpResult( } return rv; } +#endif + +// Notification handling +// + +BluetoothAvrcpNotificationHandler::~BluetoothAvrcpNotificationHandler() +{ } + +#if ANDROID_VERSION >= 18 +static BluetoothAvrcpNotificationHandler* sAvrcpNotificationHandler; + +struct BluetoothAvrcpCallback +{ + class AvrcpNotificationHandlerWrapper + { + public: + typedef BluetoothAvrcpNotificationHandler ObjectType; + + static ObjectType* GetInstance() + { + MOZ_ASSERT(NS_IsMainThread()); + + return sAvrcpNotificationHandler; + } + }; + + // Notifications + + typedef BluetoothNotificationRunnable0 + GetPlayStatusNotification; + + typedef BluetoothNotificationRunnable0 + ListPlayerAppAttrNotification; + + typedef BluetoothNotificationRunnable1 + ListPlayerAppValuesNotification; + + typedef BluetoothNotificationRunnable2, + uint8_t, const BluetoothAvrcpPlayerAttribute*> + GetPlayerAppValueNotification; + + typedef BluetoothNotificationRunnable2, + uint8_t, const BluetoothAvrcpPlayerAttribute*> + GetPlayerAppAttrsTextNotification; + + typedef BluetoothNotificationRunnable3, + uint8_t, uint8_t, const uint8_t*> + GetPlayerAppValuesTextNotification; + + typedef BluetoothNotificationRunnable1 + SetPlayerAppValueNotification; + + typedef BluetoothNotificationRunnable2, + uint8_t, const BluetoothAvrcpMediaAttribute*> + GetElementAttrNotification; + + typedef BluetoothNotificationRunnable2 + RegisterNotificationNotification; + +#if ANDROID_VERSION >= 19 + typedef BluetoothNotificationRunnable2 + RemoteFeatureNotification; + + typedef BluetoothNotificationRunnable2 + VolumeChangeNotification; + + typedef BluetoothNotificationRunnable2 + PassthroughCmdNotification; +#endif // ANDROID_VERSION >= 19 + + // Bluedroid AVRCP callbacks + + static void + GetPlayStatus() + { + GetPlayStatusNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::GetPlayStatusNotification); + } + + static void + ListPlayerAppAttr() + { + ListPlayerAppAttrNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::ListPlayerAppAttrNotification); + } + + static void + ListPlayerAppValues(btrc_player_attr_t aAttrId) + { + ListPlayerAppValuesNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::ListPlayerAppValuesNotification, + aAttrId); + } + + static void + GetPlayerAppValue(uint8_t aNumAttrs, btrc_player_attr_t* aAttrs) + { + GetPlayerAppValueNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::GetPlayerAppValueNotification, + aNumAttrs, ConvertArray(aAttrs, aNumAttrs)); + } + + static void + GetPlayerAppAttrsText(uint8_t aNumAttrs, btrc_player_attr_t* aAttrs) + { + GetPlayerAppAttrsTextNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::GetPlayerAppAttrsTextNotification, + aNumAttrs, ConvertArray(aAttrs, aNumAttrs)); + } + + static void + GetPlayerAppValuesText(uint8_t aAttrId, uint8_t aNumVals, uint8_t* aVals) + { + GetPlayerAppValuesTextNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::GetPlayerAppValuesTextNotification, + aAttrId, aNumVals, ConvertArray(aVals, aNumVals)); + } + + static void + SetPlayerAppValue(btrc_player_settings_t* aVals) + { + SetPlayerAppValueNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::SetPlayerAppValueNotification, + *aVals); + } + + static void + GetElementAttr(uint8_t aNumAttrs, btrc_media_attr_t* aAttrs) + { + GetElementAttrNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::GetElementAttrNotification, + aNumAttrs, ConvertArray(aAttrs, aNumAttrs)); + } + + static void + RegisterNotification(btrc_event_id_t aEvent, uint32_t aParam) + { + RegisterNotificationNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::RegisterNotificationNotification, + aEvent, aParam); + } + +#if ANDROID_VERSION >= 19 + static void + RemoteFeature(bt_bdaddr_t* aBdAddr, btrc_remote_features_t aFeatures) + { + RemoteFeatureNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::RemoteFeatureNotification, + aBdAddr, aFeatures); + } + + static void + VolumeChange(uint8_t aVolume, uint8_t aCType) + { + VolumeChangeNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::VolumeChangeNotification, + aVolume, aCType); + } + + static void + PassthroughCmd(int aId, int aKeyState) + { + PassthroughCmdNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::PassthroughCmdNotification, + aId, aKeyState); + } +#endif // ANDROID_VERSION >= 19 +}; + +// Interface +// BluetoothAvrcpInterface::BluetoothAvrcpInterface( const btrc_interface_t* aInterface) @@ -2846,10 +3223,34 @@ BluetoothAvrcpInterface::~BluetoothAvrcpInterface() { } void -BluetoothAvrcpInterface::Init(btrc_callbacks_t* aCallbacks, - BluetoothAvrcpResultHandler* aRes) +BluetoothAvrcpInterface::Init( + BluetoothAvrcpNotificationHandler* aNotificationHandler, + BluetoothAvrcpResultHandler* aRes) { - bt_status_t status = mInterface->init(aCallbacks); + static btrc_callbacks_t sCallbacks = { + sizeof(sCallbacks), +#if ANDROID_VERSION >= 19 + BluetoothAvrcpCallback::RemoteFeature, +#endif + BluetoothAvrcpCallback::GetPlayStatus, + BluetoothAvrcpCallback::ListPlayerAppAttr, + BluetoothAvrcpCallback::ListPlayerAppValues, + BluetoothAvrcpCallback::GetPlayerAppValue, + BluetoothAvrcpCallback::GetPlayerAppAttrsText, + BluetoothAvrcpCallback::GetPlayerAppValuesText, + BluetoothAvrcpCallback::SetPlayerAppValue, + BluetoothAvrcpCallback::GetElementAttr, + BluetoothAvrcpCallback::RegisterNotification +#if ANDROID_VERSION >= 19 + , + BluetoothAvrcpCallback::VolumeChange, + BluetoothAvrcpCallback::PassthroughCmd +#endif + }; + + sAvrcpNotificationHandler = aNotificationHandler; + + bt_status_t status = mInterface->init(&sCallbacks); if (aRes) { DispatchBluetoothAvrcpResult(aRes, &BluetoothAvrcpResultHandler::Init, diff --git a/dom/bluetooth/bluedroid/BluetoothInterface.h b/dom/bluetooth/bluedroid/BluetoothInterface.h index 2b04fb144713..677c57ff3ff5 100644 --- a/dom/bluetooth/bluedroid/BluetoothInterface.h +++ b/dom/bluetooth/bluedroid/BluetoothInterface.h @@ -265,6 +265,26 @@ private: // Bluetooth Advanced Audio Interface // +class BluetoothA2dpNotificationHandler +{ +public: + virtual ~BluetoothA2dpNotificationHandler(); + + virtual void + ConnectionStateNotification(BluetoothA2dpConnectionState aState, + const nsAString& aBdAddr) + { } + + virtual void + AudioStateNotification(BluetoothA2dpAudioState aState, + const nsAString& aBdAddr) + { } + +protected: + BluetoothA2dpNotificationHandler() + { } +}; + class BluetoothA2dpResultHandler { public: @@ -288,7 +308,7 @@ class BluetoothA2dpInterface public: friend class BluetoothInterface; - void Init(btav_callbacks_t *aCallbacks, + void Init(BluetoothA2dpNotificationHandler* aNotificationHandler, BluetoothA2dpResultHandler* aRes); void Cleanup(BluetoothA2dpResultHandler* aRes); @@ -309,6 +329,69 @@ private: // Bluetooth AVRCP Interface // +class BluetoothAvrcpNotificationHandler +{ +public: + virtual ~BluetoothAvrcpNotificationHandler(); + + virtual void + GetPlayStatusNotification() + { } + + virtual void + ListPlayerAppAttrNotification() + { } + + virtual void + ListPlayerAppValuesNotification(BluetoothAvrcpPlayerAttribute aAttrId) + { } + + virtual void + GetPlayerAppValueNotification(uint8_t aNumAttrs, + const BluetoothAvrcpPlayerAttribute* aAttrs) + { } + + virtual void + GetPlayerAppAttrsTextNotification(uint8_t aNumAttrs, + const BluetoothAvrcpPlayerAttribute* aAttrs) + { } + + virtual void + GetPlayerAppValuesTextNotification(uint8_t aAttrId, uint8_t aNumVals, + const uint8_t* aValues) + { } + + virtual void + SetPlayerAppValueNotification(const BluetoothAvrcpPlayerSettings& aSettings) + { } + + virtual void + GetElementAttrNotification(uint8_t aNumAttrs, + const BluetoothAvrcpMediaAttribute* aAttrs) + { } + + virtual void + RegisterNotificationNotification(BluetoothAvrcpEvent aEvent, + uint32_t aParam) + { } + + virtual void + RemoteFeatureNotification(const nsAString& aBdAddr, unsigned long aFeatures) + { } + + virtual void + VolumeChangeNotification(uint8_t aVolume, uint8_t aCType) + { } + + virtual void + PassthroughCmdNotification(int aId, int aKeyState) + { } + +protected: + BluetoothAvrcpNotificationHandler() + { } +}; + class BluetoothAvrcpResultHandler { public: @@ -348,7 +431,7 @@ class BluetoothAvrcpInterface public: friend class BluetoothInterface; - void Init(btrc_callbacks_t* aCallbacks, + void Init(BluetoothAvrcpNotificationHandler* aNotificationHandler, BluetoothAvrcpResultHandler* aRes); void Cleanup(BluetoothAvrcpResultHandler* aRes); diff --git a/dom/bluetooth/bluedroid/BluetoothUtils.cpp b/dom/bluetooth/bluedroid/BluetoothUtils.cpp index 7853ebf098ee..7054cb6f13b5 100644 --- a/dom/bluetooth/bluedroid/BluetoothUtils.cpp +++ b/dom/bluetooth/bluedroid/BluetoothUtils.cpp @@ -22,19 +22,6 @@ BEGIN_BLUETOOTH_NAMESPACE -void -BdAddressTypeToString(bt_bdaddr_t* aBdAddressType, nsAString& aRetBdAddress) -{ - uint8_t* addr = aBdAddressType->address; - char bdstr[18]; - - sprintf(bdstr, "%02x:%02x:%02x:%02x:%02x:%02x", - (int)addr[0],(int)addr[1],(int)addr[2], - (int)addr[3],(int)addr[4],(int)addr[5]); - - aRetBdAddress = NS_ConvertUTF8toUTF16(bdstr); -} - uint16_t UuidToServiceClassInt(const BluetoothUuid& mUuid) { diff --git a/dom/bluetooth/bluedroid/BluetoothUtils.h b/dom/bluetooth/bluedroid/BluetoothUtils.h index 4cf0c470cb19..6d141a44e31e 100644 --- a/dom/bluetooth/bluedroid/BluetoothUtils.h +++ b/dom/bluetooth/bluedroid/BluetoothUtils.h @@ -7,8 +7,6 @@ #ifndef mozilla_dom_bluetooth_bluetoothutils_h__ #define mozilla_dom_bluetooth_bluetoothutils_h__ -#include - #include "BluetoothCommon.h" #include "js/TypeDecls.h" @@ -18,10 +16,6 @@ class BluetoothNamedValue; class BluetoothValue; class BluetoothReplyRunnable; -void -BdAddressTypeToString(bt_bdaddr_t* aBdAddressType, - nsAString& aRetBdAddress); - uint16_t UuidToServiceClassInt(const BluetoothUuid& mUuid); diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index ba6bb7c0b8fa..bb5df03ced41 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -2383,9 +2383,15 @@ RilObject.prototype = { let request = options.attach ? RIL_REQUEST_GPRS_ATTACH : RIL_REQUEST_GPRS_DETACH; this.context.Buf.simpleRequest(request, options); + return; } else if (RILQUIRKS_SUBSCRIPTION_CONTROL && options.attach) { this.context.Buf.simpleRequest(REQUEST_SET_DATA_SUBSCRIPTION, options); + return; } + + // We don't really send a request to rild, so instantly reply success to + // RadioInterfaceLayer. + this.sendChromeMessage(options); }, /**