RHMI Resources
Each Connected App can upload an XML description of additional menus and windows to add to the iDrive system. These UI Descriptions essentially describe a set of components
, grouped into pages called hmiStates
, which present data from models
. The Connected App, from the phone, presents this description, and then subscribes to event callbacks from user interaction. At any time, the Connected App can update the state of the display.
These UI Description files, and accompanying ImageDBs and TextDBs, are protected from modification by a SHA256 hash that is specified in the Connected app's SAS authentication cert.
For examples, look inside the assets/carapplications/*/rhmi
directory of any Connected App APK. There is usually a ui_description.xml
file with an example layout.
RPC Setup and Interaction
The Connected App first calls rhmi_create
to begin loading a Remote Human-Machine Interface description into the car's dashboard. Using the returned handle, the app uses rhmi_setResource
to upload the XML layout describing the new menu functionality, a zip file of translated strings, a zip file of icons, and some other data. To save time, the app can use rhmi_checkResource
to validate that the car's cache has the correct TextDB and ImageDB from previous launches. The app uses rhmi_addActionEventHandler
and rhmi_addHmiEventHandler
to establish callbacks from user interactions, and can use rhmi_setData
and rhmi_setProperty
to change the displayed information dynamically.
UI Description
The main XML layout file, termed DESCRIPTION
, is broken into several parts. The top level element is <pluginApps>
, and contains several <pluginApp>
nodes. Each pluginApp
has some high-level descriptive attributes, including applicationType
or applicationType
, text="basecore"
and applicationWeight="500"
. Each pluginApp
node contains a set of child nodes named actions
, models
, events
, and hmiStates
. There can also be a single entryButton
element to describe the icon used to enter the application, and an instrumentCluster
element to populate the three-line display in the instrument cluster.
entryButton
attributes:
- id
- action - What action should be triggered when selected
- model - The label text for this menu entry
- imageModel - The menu entry's icon
pluginApp
types:
- Addressbook
- Multimedia
- Navigation
- OnlineServices
- Phone
- Radio
- Settings
- VehicleInformation
Actions
Each app defines a big list of <actions>
at the top, containing multiple childs of the following types. These events are referenced in the later sections.
<raAction>
is just a plain callback from a component<combinedAction>
contains both an<raAction>
and an<hmiAction>
with atargetModel
attribute<linkAction>
which can contain anactionType
attribute such asnavigate
orcall
, along with alinkModel
attribute<hmiAction>
contains atargetModel
attribute, and that model contains an ID of aState
to show
More details about actions and events can be found here.
Models
Next is a list of models
, which define structured locations for the app to provide data. Each model has a unique id
which is referenced in the rhmi_setData
call
<raIntModel>
can have a startingvalue
attribute<raDataModel>
, can have an optionalmodelType
attribute of:Info
,Address
,Phonenumber
<raListModel>
, can have an optionalmodelType
attribute of:Richtext
,EntICDetails
,EntICPlaylist
<raImageModel>
<raGaugeModel>
, with the following attributes:modelType="Progress"
min="0"
min="100"
value="0"
increment="1"
<imageIdModel>
, an optionalimageId
attribute references a IMAGEDB icon<textIdModel>
can contain atextId
attribute that references a TEXTDB string, and can have aspeechTextId
attribute<formatDataModel>
contains aformatString="%0%1"
attribute that combines some inner-nested<models>
in some way
HMI States
An RHMI App is split into several different states, which act as windows, and these definitions are found inside <hmiStates>
. Each main page of the app is described in each <hmiState>
, and there are also <popupHmiState>
and <toolbarHmiState>
specializations. Each hmiState
has a numeric id
and a textModel
attribute.
hmiState
shows an unadorned screen, while toolbarHmiState
shows a navigation bar along the left side of the screen. popupHmiState
can not be the destination of an hmiAction
.
Each state
contains a <components>
node containing nodes to represent each graphical widget, termed a component
.
States can additionally contain <properties>
and <optionComponents>
.
Audio HMI State
ID5+ additionally supports an <audioHmiState>
high-level state which omits a list of components, and instead has a list of semantic models for the car to place and style as needed.
Attribute | Example | Description |
textModel | "iHeartRadio" | The title of the screen |
statusBarImageModel | IMAGEID | Perhaps shows the app icon in the status bar |
providerLogoImageModel | IMAGEDATA | Shows the app icon in the playback screen |
artistImageModel | IMAGEDATA | The icon next to the artistTextModel |
artistTextModel | "Artist" | First row of the playback screen, shows up in the Multimedia sidebar |
albumImageModel | IMAGEDATA | The icon next to the albumTextModel |
albumTextModel | "Album" | Second row of the playback screen |
trackTextModel | "Title" | Shows up in the Multimedia sidebar |
alternativeTextModel | " \n \n " | 3 text lines joined by newlines, not seen in the wild |
coverImageModel | IMAGEDATA | The track's cover art, shows in the sidebar and the home screen |
currentTimeModel | "0:00" | Te left side of a progress bar, visible when the sidebar is hidden |
elapsingTimeModel | "2:30" | Te right side of a progress bar |
playListModel | RHMIDataTable | A list of elements to show in the middle of the screen, such as Back/Title/Next |
playListFocusRowModel | 1 | An index for the car to use as the highlighted row of the playlist |
playListTextModel | "" | The text to show when the playlist is empty |
playListProgressTextModel | "" | |
playbackProgressModel | 0.5 | A percentage of progress, from 0.0 to 1.0 |
The playListModel
has a format for each row: [isAnimationEnabled, leftImage, firstText, firstRightImage, firstRightImageVisible, secondRightImage, secondRightImageVisible, secondText, secondTextVisible, isItemEnabled]
Components
Every component has an id
parameter, and the behavior can be modified by these component-specific attributes and properties.
Name | Attributes | Properties |
label | model:textIdModel|raDataModel |
SELECTABLE VISIBLE WIDTH HEIGHT POSITION_X POSITION_Y |
list | model:raListModel action:raAction selectAction:raAction |
SELECTABLE VISIBLE LIST_COLUMNWIDTH |
button | model:textIdModel tooltipModel:textIdModel imageModel:imageIdModel action:combinedAction selectAction:raAction |
ENABLED SELECTABLE |
checkbox | model:raBoolModel textModel:raDataModel action:raAction |
VISIBLE |
image | model:imageIdModel|raImageModel |
WIDTH HEIGHT POSITION_X POSITION_Y |
separator | ||
gauge | model:raGaugeModel textModel:raDataModel action:raAction changeAction:raAction |
WIDTH HEIGHT POSITION_X POSITION_Y |
input | textModel:raDataModel action:raAction resultModel:raDataModel resultAction:combinedAction suggestModel:raListModel suggestAction:combinedAction |
Note that the image
component does not do any image resizing, and will just crop the image. The mobile app must handle any resizing.
Component Properties
Inside each component
can be found a <properties>
with a list of <property>
nodes. Each node has an id
attribute from the following table, with a value
attribute with the setting. Different properties interpret the value
differently, most are true
or false
.
These definitions are found in com.bmwgroup.connected.internal.ui.RhmiPropertyType
ID | Name | Example Values |
1 | ENABLED |
true false |
2 | SELECTABLE |
true false |
3 | VISIBLE |
true false |
4 | VALID |
|
5 | TOOLBARHMISTATE_PAGING |
|
6 | LIST_COLUMNWIDTH |
57,100,* |
7 | LIST_HASIDCOLUMN |
|
8 | LABEL_WAITINGANIMATION |
true false |
9 | WIDTH |
320 |
10 | HEIGHT |
240 |
11 | TERMINALUI_VIDEOVIEWPORT |
|
12 | TERMINALUI_SCREENVIEWPORT |
|
13 | TERMINALUI_FULLSCREEN |
|
14 | TERMINALUI_AUDIOMODE |
|
15 | TERMINALUI_VIDEOMODE |
|
16 | TERMINALUI_LEAVE |
|
17 | ALIGNMENT |
An index from an enum with these values: [LEFT_TOP , CENTER_TOP , RIGHT_TOP , LEFT_CENTER , CENTER_CENTER , RIGHT_CENTER , LEFT_BOTTOM , CENTER_BOTTOM , RIGHT_BOTTOM ] |
18 | OFFSET_X |
|
19 | OFFSET_Y |
|
20 | POSITION_X |
0 |
21 | POSITION_Y |
0 |
22 | BOOKMARKABLE |
true false |
23 | SPEAKABLE |
An index from an enum with these values: [NOT_SPEAKABLE , LOCALLY_SPEAKABLE , GLOBALLY_SPEAKABLE ] |
24 | HMISTATE_TABLETYPE |
3 |
25 | CURSOR_WIDTH |
|
26 | HMISTATE_TABLELAYOUT |
|
35 | TOOLBARHMISTATE_PAGING_LIMITED |
|
36 | SPEEDLOCK |
true false |
37 | CUTTYPE |
An index from an enum with these values: [DOTS , NO_CUTTING , WORDS_DOTS , BACKWARDS_DOTS , WORDS_AUTO_STATIC_TEXT , WORDS_AUTO_DYNAMIC_TEXT ] |
38 | TABSTOPOFFSET |
1 |
39 | BACKGROUND |
1 |
40 | TERMINALUI_REGISTER_INPUTEVENT |
|
41 | TERMINALUI_DEREGISTER_INPUTEVENT |
|
42 | LIST_RICHTEXT_MAX_ROWCOUNT |
|
43 | LIST_RICHTEXT_LAST_LINE_WITH_THREE_DOTS |
-1 |
44 | TERMINALUI_SET_CONTRAST |
|
45 | TERMINALUI_SET_BRIGHTNESS |
|
46 | TERMINALUI_SET_COLOR |
|
47 | TERMINALUI_SET_TINT |
|
48 | TERMINALUI_STATUSBAR |
|
49 | TERMINALUI_VIDEOVISIBLE |
|
50 | TERMINALUI_SET_TUIMODE |
|
51 | GET_VALUES |
|
52 | TERMINALUI_SET_TUIUSER |
|
53 | CHECKED |
true false seen on toolbar buttons |
55 | UUID |
|
56 | MODAL |
An index from an enum with these values: [NO_RESTRICTIONS , DISABLE_LEFT_SHIFT , DISABLE_STATE_REQUEST , DISABLE_LEFT_SHIFT_AND_STATE_REQUEST ] |
Some properties, such as ALIGNMENT
and CUTTYPE
when applied to a List component, are observed to use a comma-separated list of numbers to apply their respective property to a specific column of the table.
Some properties, such as POSITION_X
and POSITION_Y
, can contain a child node <condition conditionType="LAYOUTBAG">
. This is perhaps to support dynamic positioning based on the size of the viewport. For example:
<properties>
<property id="20" value="0">
<condition conditionType="LAYOUTBAG">
<assignments>
<assignment conditionValue="0" value="361"/>
<assignment conditionValue="1" value="2000"/>
<assignment conditionValue="2" value="361"/>
<assignment conditionValue="3" value="2000"/>
</assignments>
</condition>
</property>
</properties>
It seems that conditionValue="0"
or conditionValue="2"
is triggered when the right sidebar is not displayed, and conditionValue="1"
or conditionValue="3"
is triggered when the right sidebar is visible.