RHMI Audio Interaction
BMW Connected has the concept of an Audio Focus to signal to apps that they are the current audio source and should begin playback.
RHMI Audio Connection
The official Connected app is the primary endpoint that handles the audio connection in the car. Other apps can technically request audio context, and it'll work, but the official apps all rely on the main Connected app to handle it for them.
sequenceDiagram
participant BMWApp as BMW Connected
participant Car as BMW Car
BMWApp ->> Car: av_create(instanceID: int, name:string)
Car ->> BMWApp: _result_av_create(handle:int)
Note right of BMWApp: User selects an app in the dashboard
BMWApp ->> Car: av_requestConnection(name:string, connectionType:AVConnectionType)
Car ->> BMWApp: _result_av_requestConnection()
Note right of BMWApp: Car begins listening to the phone for audio
Car ->> BMWApp: av_connectionGranted(handle:int, connectionType:AVConnectionType)
Note right of BMWApp: Car requests that music should begin playing
Car ->> BMWApp: av_requestPlayerState(handle:int, connectionType:AVConnectionType, playerState:AVPlayerState)
BMWApp ->> Car: av_playerStateChanged(handle:int, connectionType:AVConnectionType, playerState:AVPlayerState)
BMWApp ->> Car: _result_av_playerStateChanged()
Note right of BMWApp: User pushes a button in the dashboard
Car ->> BMWApp: av_multimediaButtonEvent(handle:int, event:AVButtonEvent)
The instanceID
has to be valid and must be no greater than the current ID that is found in the ACTION_CAR_ACCESSORY_ATTACHED
announcement, or else the car will send av_connectionDenied
in response to av_requestConnection
.
Connected Apps - Creating the Audio Focus
When a multimedia Connected app starts, it sends out a broadcast intent named com.bmwgroup.connected.app.ACTION_CAR_AUDIO_FOCUS_REQUEST
. This intent contains some metadata about the multimedia app:
Name | Type | Description |
EXTRA_APPLICATION_ID |
String | The name of this app |
EXTRA_AUDIO_CONNECTION_FOCUS |
int | A number from 0-4, representing an enum of: GAIN, LOSS, LOSS_TRANSIENT, LOSS_TRANSIENT_CAN_DUCK, GAIN_ON_LUM |
EXTRA_AUDIO_CONNECTION_TYPE |
int | A number from 0-2, representing an enum of: ENTERTAINMENT, INTERRUPT, UNKNOWN |
After the main BMW Connected app hears this request, it creates (if necessary) an AV Context in the car. It uses this handle to tell the car to switch the audio input to the appropriate input for the Connected app (such as USB or Bluetooth).
sequenceDiagram
participant App as Connected App
participant BMWApp as BMW Connected
participant Car as BMW Car
App -->> BMWApp: Intent("com.bmwgroup.connected.app.ACTION_CAR_AUDIO_FOCUS_REQUEST")
BMWApp ->> Car: av_create(name:string)
Car ->> BMWApp: _result_av_create(handle:int)
Note right of BMWApp: User selects the app in the dashboard
BMWApp ->> Car: av_requestConnection(name:string, connectionType:AVConnectionType)
Car ->> BMWApp: _result_av_requestConnection()
Note right of BMWApp: Car begins listening to the phone for audio
Car ->> BMWApp: av_connectionGranted(handle:int, connectionType:AVConnectionType)
Note right of BMWApp: Car requests that music should begin playing
Car ->> BMWApp: av_requestPlayerState(handle:int, connectionType:AVConnectionType, playerState:AVPlayerState)
BMWApp ->> Car: av_playerStateChanged(handle:int, connectionType:AVConnectionType, playerState:AVPlayerState)
BMWApp ->> Car: _result_av_playerStateChanged()
App Title Display
At any point, an RHMI app can trigger a statusbarEvent
to replace displayed music app name.
Based on an event definition such as: <statusbarEvent id="577" textModel="571"/>
, the app would do the following steps:
setData(571, "App Name")
stages the app name into an RaDataModelMap args = new HashMap(); args.put(0, null);
prepares an arguments payload, it always contains{0:null}
rhmi_triggerEvent(577, args);
takes over the status label with this app's information
Similarly, the RHMI app should trigger the notificationIconEvent
, to update the displayed music player icon alongside the status bar. This event typically points to a hard-coded imageIdModel, and does not need to be changed to point a different icon. For example, based on <notificationIconEvent id="4" imageIdModel="62"/>
:
Map args = new Hashmap(); args.put(0, true);
rhmi_triggerEvent(4, args);
Currently Playing Song Display
While an app is holding the active audio context, it can trigger a multimediaInfoEvent
to update the car's knowledge of the currently-playing track. This is primarily used by the Instrument Cluster to show a track between the Back and next selections., but may also be tied into the EntICPlaylist feature.
Similar to the App Title display, the multimediaInfoEvent
contains both a textModel1
and a textModel2
attribute. These point to RaDataModel fields that can be filled with data, and then the event can be triggered to enact the change. textModel1
seems to contain the track title, while textModel2
usually contains the artist. After setting those two models, the multimediaInfoEvent
can be triggered with the same {0:null}
args payload as with the statusbarEvent
.
Multimedia Button Presses
While an app is holding the active audio context, it will receive Multimedia Button Events when a user selects Back or Next in the Instrument Cluster display, or presses or holds the Back or Next physical buttons. These will be sent to the av_multimediaButtonEvent
callback, and simply contain the integer av_handle
and the AVButtonEvent
enum of the specific button that was pressed. AV_EVENT_SKIP_DOWN
is sent for Back, and AV_EVENT_SKIP_UP
is sent for Next.
Alternatively, if the app is relying on BMW Connected to manage the audio context on its behalf, BMW Connected graciously broadcasts an Intent with the event information. This is announced to the com.bmwgroup.connected.app.ACTION_CAR_AUDIO_MULTIMEDIA_BUTTON_NOTIFICATION
Intent name, and contains the following extras:
Name | Type | Description |
EXTRA_APPLICATION_ID |
String | The name of the app that has the audio context, and that this event is intended for |
EXTRA_MULTIMEDIA_BUTTON_EVENT |
int | A number from 0-4, representing an enum of: AV_EVENT_SKIP_DOWN, AV_EVENT_SKIP_UP, AV_EVENT_SKIP_LONG_UP, AV_EVENT_SKIP_LONG_DOWN, AV_EVENT_SKIP_LONG_STOP |
Resuming Music Playback
The car remembers which audio context was last active when it is turned off, and waits for that audio context to show back up when the car is turned on again.
After the app is initialized, and it calls av_create
, the car will notice if the given name matches the previously-remembered audio context. If so, the app will automatically receive an av_connectionGranted
callback, even without needing to call av_requestConnection
. The car may also call av_requestPlayerState
to initiate playback.