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 atargetModelattribute<linkAction>which can contain anactionTypeattribute such asnavigateorcall, along with alinkModelattribute<hmiAction>contains atargetModelattribute, and that model contains an ID of aStateto 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 startingvalueattribute<raDataModel>, can have an optionalmodelTypeattribute of:Info,Address,Phonenumber<raListModel>, can have an optionalmodelTypeattribute of:Richtext,EntICDetails,EntICPlaylist<raImageModel><raGaugeModel>, with the following attributes:modelType="Progress"min="0"min="100"value="0"increment="1"
<imageIdModel>, an optionalimageIdattribute references a IMAGEDB icon<textIdModel>can contain atextIdattribute that references a TEXTDB string, and can have aspeechTextIdattribute<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.