1page.title=Device-Specific Code
2@jd:body
3
4<!--
5    Copyright 2015 The Android Open Source Project
6
7    Licensed under the Apache License, Version 2.0 (the "License");
8    you may not use this file except in compliance with the License.
9    You may obtain a copy of the License at
10
11        http://www.apache.org/licenses/LICENSE-2.0
12
13    Unless required by applicable law or agreed to in writing, software
14    distributed under the License is distributed on an "AS IS" BASIS,
15    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16    See the License for the specific language governing permissions and
17    limitations under the License.
18-->
19
20<div id="qv-wrapper">
21  <div id="qv">
22    <h2>In this document</h2>
23    <ol id="auto-toc">
24    </ol>
25  </div>
26</div>
27
28<p>The recovery system includes several hooks for inserting device-specific
29code so that OTA updates can also update parts of the device other than the
30Android system (e.g., the baseband or radio processor).</p>
31<p>The following sections and examples customize the <b>tardis</b> device
32produced by the <b>yoyodyne</b> vendor.</p>
33
34<h2>Partition map</h2>
35<p>As of Android 2.3, the platform supports eMMC flash devices and the ext4
36filesystem that runs on those devices. It also supports Memory Technology Device
37(MTD) flash devices and the yaffs2 filesystem from older releases.</p>
38<p>The partition map file is specified by TARGET_RECOVERY_FSTAB; this file is
39used by both the recovery binary and the package-building tools. You can
40specify the name of the map file in TARGET_RECOVERY_FSTAB in BoardConfig.mk.</p>
41<p>A sample partition map file might look like this:</p>
42
43<p><code>device/yoyodyne/tardis/recovery.fstab</code></p>
44
45<pre>
46# mount point       fstype  device       [device2]        [options (3.0+ only)]
47
48/sdcard     vfat    /dev/block/mmcblk0p1 /dev/block/mmcblk0
49/cache      yaffs2  cache
50/misc       mtd misc
51/boot       mtd boot
52/recovery   emmc    /dev/block/platform/s3c-sdhci.0/by-name/recovery
53/system     ext4    /dev/block/platform/s3c-sdhci.0/by-name/system length=-4096
54/data       ext4    /dev/block/platform/s3c-sdhci.0/by-name/userdata
55</pre>
56
57<p>With the exception of <code>/sdcard</code>, which is optional, all mount
58points in this example must be defined (devices may also add extra partitions).
59There are five supported filesystem types:</p>
60<dl>
61<dt>yaffs2</dt>
62<dd>A yaffs2 filesystem atop an MTD flash device. "device" must be the name of
63the MTD partition and must appear in <code>/proc/mtd</code>.</dd>
64<dt>mtd</dt>
65<dd>A raw MTD partition, used for bootable partitions such as boot and
66recovery. MTD is not actually mounted, but the mount point is used as a key to
67locate the partition. "device" must be the name of the MTD partition in
68<code>/proc/mtd</code>.</dd>
69<dt>ext4</dt>
70<dd>An ext4 filesystem atop an eMMC flash device. "device" must be the path of
71the block device.</dd>
72<dt>emmc</dt>
73<dd>A raw eMMC block device, used for bootable partitions such as boot and
74recovery. Similar to the mtd type, eMMc is never actually mounted, but the
75mount point string is used to locate the device in the table.</dd>
76<dt>vfat</dt>
77<dd>A FAT filesystem atop a block device, typically for external storage such
78as an SD card. The device is the block device; device2 is a second block
79device the system attempts to mount if mounting the primary device fails (for
80compatibility with SD cards which may or may not be formatted with a partition
81table).
82<p>All partitions must be mounted in the root directory (i.e. the mount point
83value must begin with a slash and have no other slashes). This restriction
84applies only to mounting filesystems in recovery; the main system is free to
85mount them anywhere. The directories <code>/boot</code>, <code>/recovery</code>,
86and <code>/misc</code> should be raw types (mtd or emmc), while the
87directories <code>/system</code>, <code>/data</code>, <code>/cache</code>, and
88<code>/sdcard</code> (if available) should be filesystem types (yaffs2, ext4,
89or vfat).</p></dd></dl>
90
91<p>Starting in Android 3.0, the recovery.fstab file gains an additional
92optional field, <i>options</i>. Currently the only defined option is <i>length
93</i>, which lets you explicitly specify the length of the partition.
94This length is used when reformatting the partition (e.g., for the userdata
95partition during a data wipe/factory reset operation, or for the system
96partition during installation of a full OTA package). If the length value is
97negative, then the size to format is taken by adding the length value to the
98true partition size. For instance, setting "length=-16384" means the last 16k
99of that partition will <i>not</i> be overwritten when that partition is
100reformatted. This supports features such as encryption of the userdata
101partition (where encryption metadata is stored at the end of the
102partition that should not be overwritten).</p>
103
104<p class="note"><strong>Note:</strong> The <b>device2</b> and <b>options</b>
105fields are optional, creating ambiguity in parsing. If the entry in the fourth
106field on the line begins with a ‘/' character, it is considered a <b>device2
107</b> entry; if the entry does not begin with a ‘/' character, it is considered
108an <b>options</b> field.</p>
109
110<h2 id="recovery-ui">Recovery UI</h2>
111<p>To support devices with different available hardware (physical buttons,
112LEDs, screens, etc.), you can customize the recovery interface to display
113status and access the manually-operated hidden features for each device.</p>
114<p>Your goal is to build a small static library with a couple of C++ objects
115to provide the device-specific functionality. The file <code>
116<b>bootable/recovery/default_device.cpp</b></code> is used by default, and
117makes a good starting point to copy when writing a version of this file for
118your device.</p>
119
120<p><code>device/yoyodyne/tardis/recovery/recovery_ui.cpp</code></p>
121
122<pre>
123#include &lt;linux/input.h&gt;
124
125#include "common.h"
126#include "device.h"
127#include "screen_ui.h"
128</pre>
129
130
131<h3 id="header-item-functions">Header and item functions</h3>
132<p>The Device class requires functions for returning headers and items that
133appear in the hidden recovery menu. Headers describe how to operate the menu
134(i.e. controls to change/select the highlighted item).</p>
135
136<pre>
137static const char* HEADERS[] = { "Volume up/down to move highlight;",
138                                 "power button to select.",
139                                 "",
140                                 NULL };
141
142static const char* ITEMS[] =  {"reboot system now",
143                               "apply update from ADB",
144                               "wipe data/factory reset",
145                               "wipe cache partition",
146                               NULL };
147</pre>
148
149<p class="note"><strong>Note:</strong> Long lines are truncated (not wrapped),
150so keep the width of your device screen in mind.</p>
151
152<h3 id="customize-checkkey">Customizing CheckKey</h3>
153<p>Next, define your device's RecoveryUI implementation. This example assumes
154the <b>tardis</b> device has a screen, so you can inherit from the built-in
155ScreenRecoveryUIimplementation (see instructions for
156<a href="#devices-without-screens">devices without a screen</a>.) The only
157function to customize from ScreenRecoveryUI is <code>CheckKey()</code>, which
158does the initial asynchronous key handling:</p>
159
160<pre>
161class TardisUI : public ScreenRecoveryUI {
162  public:
163    virtual KeyAction CheckKey(int key) {
164        if (key == KEY_HOME) {
165            return TOGGLE;
166        }
167        return ENQUEUE;
168    }
169};
170</pre>
171
172
173<h4 id="key-constants">KEY constants</h4>
174<p>The KEY_* constants are defined in <code>linux/input.h</code>.<code>
175CheckKey()</code> is called no matter what is going on in the rest of
176recovery: when the menu is toggled off, when it is on, during package
177installation, during userdata wiping, etc. It can return one of four constants:
178</p>
179
180<ul>
181<li><b>TOGGLE</b>. Toggle the display of the menu and/or text log on or off
182</li>
183<li><b>REBOOT</b>. Immediately reboot the device</li>
184<li><b>IGNORE</b>. Ignore this keypress</li>
185<li><b>ENQUEUE</b>. Enqueue this keypress to be consumed synchronously (i.e.,
186by the recovery menu system if the display is enabled)</li>
187</ul>
188
189<p><code>CheckKey()</code> is called each time a key-down event is followed by
190a key-up event for the same key. (The sequence of events A-down B-down B-up
191A-up results only in <code>CheckKey(B)</code> being called.) <code>CheckKey()
192</code> can call <code>IsKeyPressed()</code>, to find out if other keys are
193being held down. (In the above sequence of key events, if <code>CheckKey(B)
194</code> called <code>IsKeyPressed(A)</code> it would have returned true.)</p>
195<p><code>CheckKey()</code> can maintain state in its class; this can be useful
196to detect sequences of keys. This example shows a slightly more complex
197setup: the display is toggled by holding down power and pressing volume-up,
198and the device can be rebooted immediately by pressing the power button five
199times in a row (with no other intervening keys):</p>
200
201<pre>
202class TardisUI : public ScreenRecoveryUI {
203  private:
204    int consecutive_power_keys;
205
206  public:
207    TardisUI() : consecutive_power_keys(0) {}
208
209    virtual KeyAction CheckKey(int key) {
210        if (IsKeyPressed(KEY_POWER) &amp;&amp; key == KEY_VOLUMEUP) {
211            return TOGGLE;
212        }
213        if (key == KEY_POWER) {
214            ++consecutive_power_keys;
215            if (consecutive_power_keys &gt;= 5) {
216                return REBOOT;
217            }
218        } else {
219            consecutive_power_keys = 0;
220        }
221        return ENQUEUE;
222    }
223};
224</pre>
225
226
227<h3 id="screenrecoveryui">ScreenRecoveryUI</h3>
228<p>When using your own images (error icon, installation animation, progress
229bars) with ScreenRecoveryUI, you might need to set some member variables to
230specify attributes such as the number of frames, speed, and overlay offsets.
231You can set the following variables:</p>
232
233<table>
234<tbody>
235<tr>
236<th>Variable Name</th>
237<th>Purpose</th>
238<th>Release</th>
239</tr>
240<tr>
241<td>animation_fps
242</td>
243<td>speed (in frames per second) of animations
244</td>
245<td>Android 5.x and earlier</td>
246</tr>
247<tr>
248<td>installing_frames
249</td>
250<td>number of frames in the installation animation
251</td>
252<td>Android 4.x and earlier</td>
253</tr>
254<tr>
255<td>install_overlay_offset_x,
256install_overlay_offset_y
257</td>
258<td>offset of the per-frame overlay (relative to the base image) for the
259installation animation
260</td>
261<td>Android 4.x and earlier</td>
262</tr>
263</tbody>
264</table>
265
266<p>To set variables, override the <code>ScreenRecoveryUI::Init()</code>
267function in your subclass. Set the values, then call the <code>parent Init()
268</code> function to complete initialization:</p>
269
270<pre>
271class TardisUI : public ScreenRecoveryUI {
272  ...
273  void Init() {
274    // change the speed at which animations run
275    animation_fps = 30;
276
277    ScreenRecoveryUI::Init();
278  }
279</pre>
280
281<p>The default values correspond to the default recovery images; when using
282these images you don't need to provide an <code>Init()</code> function. For
283details on images, see <a href="#recovery-ui-images">Recovery UI Images</a>.
284</p>
285
286<h3 id="device-class">Device Class</h3>
287<p>After you have a RecoveryUI implementation, define your device class
288(subclassed from the built-in Device class). It should create a single
289instance of your UI class and return that from the <code>GetUI()</code>
290function:</p>
291
292<pre>
293class TardisDevice : public Device {
294  private:
295    TardisUI* ui;
296
297  public:
298    TardisDevice() :
299        ui(new TardisUI) {
300    }
301
302    RecoveryUI* GetUI() { return ui; }
303</pre>
304
305<h3 id="startrecovery">StartRecovery</h3>
306<p>The <code>StartRecovery()</code> method is called at the start of recovery,
307after the UI has been initialized and after the arguments have been parsed,
308but before any action has been taken. The default implementation does nothing,
309so you do not need to provide this in your subclass if you have nothing to do:
310</p>
311
312<pre>
313   void StartRecovery() {
314       // ... do something tardis-specific here, if needed ....
315    }
316</pre>
317
318<h3 id="supply-manage-recovery-menu">Supplying and managing recovery menu</h3>
319<p>The system calls two methods to get the list of header lines and the list
320of items. In this implementation, it returns the static arrays defined at the
321top of the file:</p>
322
323<pre>
324const char* const* GetMenuHeaders() { return HEADERS; }
325const char* const* GetMenuItems() { return ITEMS; }
326</pre>
327
328<h4 id="handlemenukey">HandleMenuKey</h4>
329<p>Next, provide a <code>HandleMenuKey()</code> function, which takes a
330keypress and the current menu visibility, and decides what action to take:</p>
331
332<pre>
333   int HandleMenuKey(int key, int visible) {
334        if (visible) {
335            switch (key) {
336              case KEY_VOLUMEDOWN: return kHighlightDown;
337              case KEY_VOLUMEUP:   return kHighlightUp;
338              case KEY_POWER:      return kInvokeItem;
339            }
340        }
341        return kNoAction;
342    }
343</pre>
344
345<p>The method takes a key code (which has previously been processed and
346enqueued by the <code>CheckKey()</code> method of the UI object), and the
347current state of the menu/text log visibility. The return value is an integer.
348If the value is 0 or higher, that is taken as the position of a menu item,
349which is invoked immediately (see the <code>InvokeMenuItem()</code> method
350below). Otherwise it can be one of the following predefined constants:</p>
351
352<ul>
353<li><b>kHighlightUp</b>. Move the menu highlight to the previous item</li>
354<li><b>kHighlightDown</b>. Move the menu highlight to the next item</li>
355<li><b>kInvokeItem</b>. Invoke the currently highlighted item</li>
356<li><b>kNoAction</b>. Do nothing with this keypress</li>
357</ul>
358
359<p>As implied by the the visible argument, <code>HandleMenuKey()</code> is
360called even if the menu is not visible. Unlike <code>CheckKey()</code>, it is
361<i>not</i> called while recovery is doing something such as wiping data or
362installing a package—it's called only when recovery is idle and waiting for
363input.</p>
364
365<h4 id="trackball-mechanism">Trackball Mechanisms</h4>
366<p>If your device has a trackball-like input mechanism (generates input events
367with type EV_REL and code REL_Y), recovery synthesizes KEY_UP and KEY_DOWN
368keypresses whenever the trackball-like input device reports motion in the Y
369axis. All you need to do is map KEY_UP and KEY_DOWN events onto menu actions.
370This mapping does <i>not</i> happen for <code>CheckKey()</code>, so you can't
371use trackball motions as triggers for rebooting or toggling the display.</p>
372
373<h4 id="modifier-keys">Modifier Keys</h4>
374<p>To check for keys being held down as modifiers, call the <code>IsKeyPressed()
375</code> method of your own UI object. For example, on some
376devices pressing Alt-W in recovery would start a data wipe whether the menu
377was visible or not. YOu could implement like this:</p>
378
379<pre>
380   int HandleMenuKey(int key, int visible) {
381        if (ui->IsKeyPressed(KEY_LEFTALT) &amp;&amp; key == KEY_W) {
382            return 2;  // position of the "wipe data" item in the menu
383        }
384        ...
385    }
386</pre>
387
388<p class="note"><strong>Note:</strong> If <b>visible</b> is false, it doesn't
389make sense to return the special values that manipulate the menu (move
390highlight, invoke highlighted item) since the user can't see the highlight.
391However, you can return the values if desired.</p>
392
393<h4 id="invokemenuitem">InvokeMenuItem</h4>
394<p>Next, provide an <code>InvokeMenuItem()</code> method that maps integer
395positions in the array of items returned by <code>GetMenuItems()</code> to
396actions. For the array of items in the tardis example, use:</p>
397
398<pre>
399   BuiltinAction InvokeMenuItem(int menu_position) {
400        switch (menu_position) {
401          case 0: return REBOOT;
402          case 1: return APPLY_ADB_SIDELOAD;
403          case 2: return WIPE_DATA;
404          case 3: return WIPE_CACHE;
405          default: return NO_ACTION;
406        }
407    }
408</pre>
409
410<p>This method can return any member of the BuiltinAction enum to tell the
411system to take that action (or the NO_ACTION member if you want the system to
412do nothing). This is the place to provide additional recovery functionality
413beyond what's in the system: Add an item for it in your menu, execute it here
414when that menu item is invoked, and return NO_ACTION so the system does nothing
415else.</p>
416<p>BuiltinAction contains the following values:</p>
417<ul>
418<li><b>NO_ACTION</b>. Do nothing.</li>
419<li><b>REBOOT</b>. Exit recovery and reboot the device normally.</li>
420<li><b>APPLY_EXT, APPLY_CACHE, APPLY_ADB_SIDELOAD</b>. Install an update
421package from various places. For details, see
422<a href="#sideloading">Sideloading</a>.</li>
423<li><b>WIPE_CACHE</b>. Reformat the cache partition only. No confirmation
424required as this is relatively harmless.</li>
425<li><b>WIPE_DATA</b>. Reformat the userdata and cache partitions, also known
426as a factory data reset. The user is asked to confirm this action before
427proceeding.</li>
428</ul>
429<p>The last method, <code>WipeData()</code>, is optional and is called
430whenever a data wipe operation is initiated (either from recovery via the menu
431or when the user has chosen to do a factory data reset from the main system).
432This method is called before the user data and cache partitions are wiped. If
433your device stores user data anywhere other than those two partitions, you
434should erase it here. You should return 0 to indicate success and another
435value for failure, though currently the return value is ignored. The user data
436and cache partitions are wiped whether you return success or failure.</p>
437
438<pre>
439   int WipeData() {
440       // ... do something tardis-specific here, if needed ....
441       return 0;
442    }
443</pre>
444
445<h4 id="make-device">Make Device</h4>
446<p>Finally, include some boilerplate at the end of the recovery_ui.cpp file
447for the <code>make_device()</code> function that creates and returns an
448instance of your Device class:</p>
449
450<pre>
451class TardisDevice : public Device {
452   // ... all the above methods ...
453};
454
455Device* make_device() {
456    return new TardisDevice();
457}
458</pre>
459
460<h3 id="build-link-device-recovery">Build and link to device recovery</h3>
461<p>After completing the recovery_ui.cpp file, built it and link it to recovery
462on your device. In Android.mk, create a static library that contains only this
463C++ file:</p>
464
465<p><code>device/yoyodyne/tardis/recovery/Android.mk</code></p>
466
467<pre>
468LOCAL_PATH := $(call my-dir)
469include $(CLEAR_VARS)
470
471LOCAL_MODULE_TAGS := eng
472LOCAL_C_INCLUDES += bootable/recovery
473LOCAL_SRC_FILES := recovery_ui.cpp
474
475# should match TARGET_RECOVERY_UI_LIB set in BoardConfig.mk
476LOCAL_MODULE := librecovery_ui_tardis
477
478include $(BUILD_STATIC_LIBRARY)
479</pre>
480
481<p>Then, in the board configuration for this device, specify your static
482library as the value of TARGET_RECOVERY_UI_LIB.</p>
483
484<pre>
485device/yoyodyne/tardis/BoardConfig.mk
486 [...]
487
488# device-specific extensions to the recovery UI
489TARGET_RECOVERY_UI_LIB := librecovery_ui_tardis
490</pre>
491
492
493<h2 id="recovery-ui-images">Recovery UI images</h2>
494<p>The recovery user interface consists images. Ideally, users never interact
495with the UI: During a normal update, the phone boots into recovery, fills the
496installation progress bar, and boots back into the new system without input
497from the user. In the event of a system update problem, the only user action
498that can be taken is to call customer care.</p>
499<p>An image-only interface obviates the need for localization. However, as of
500Android 5.x the update can display a string of text (e.g. "Installing system
501update...") along with the image. For details, see <a href="#recovery-text">
502Localized recovery text</a>.</p>
503
504<h3 id="recovery-5.x">Android 5.x</h3>
505<p>The Android 5.x recovery UI uses two main images: the <b>error</b> image
506and the <b>installing</b> animation.</p>
507
508<table>
509<tbody>
510<tr>
511<td>
512<img src="../images/icon_error.png" alt="image shown during ota error">
513<p class="img-caption"><strong>Figure 1.</strong> icon_error.png</p>
514</td>
515<td>
516<img src="../images/icon_installing_5x.png" alt="image shown during ota install"
517height="275">
518<p class="img-caption"><strong>Figure 2.</strong> icon_installing.png</p>
519</td>
520</tr>
521</tbody>
522</table>
523
524<p>The installing animation is represented as a single PNG image with
525different frames of the animation interlaced by row. For example, for a
5267-frame animation that is 200x200, create a single 200x1400 image where first
527frame is rows 0, 7, 14, 21, ...; the second frame is rows 1, 8, 15, 22, ...;
528etc. The combined image includes a text chunk that indicates the number of
529animation frames. The tool <code>bootable/recovery/interlace-frames.py</code>
530takes a set of input frames and combines them into the necessary composite
531image used by recovery.</p>
532
533<p>Default images are available in different densities and are located in
534<code>bootable/recovery/res-$DENSITY/images</code> (e.g.,
535<code>bootable/recovery/res-hdpi/images</code>). To use a static image during
536installation, you need only provide the icon_installing.png image and set the
537number of frames in the animation to 0 (the error icon is not animated; it is
538always a static image).</p>
539
540
541<h3 id="recovery-4.x">Android 4.x and earlier</h3>
542<p>The Android 4.x and earlier recovery UI uses the <b>error</b> image (shown
543above) and the <b>installing</b> animation plus several overlay images:</p>
544
545<table>
546<tbody>
547<tr>
548<td rowspan="2">
549<img src="../images/icon_installing.png" alt="image shown during ota install">
550<p class="img-caption"><strong>Figure 3.</strong> icon_installing.png</p>
551</td>
552<td>
553<img src="../images/icon_installing_overlay01.png" alt="image shown as first
554overlay">
555<p class="img-caption"><strong>Figure 4.</strong> icon-installing_overlay01.png
556</p>
557</td>
558</tr>
559<tr>
560<td>
561<img src="../images/icon_installing_overlay07.png" alt="image shown as seventh
562overlay">
563<p class="img-caption"><strong>Figure 5.</strong> icon_installing_overlay07.png
564</p>
565</td>
566</tr>
567</tbody>
568</table>
569
570
571<p>During installation, the on-screen display is constructed by drawing the
572icon_installing.png image, then drawing one of the overlay frames on top of it
573at the proper offset. Here, a red box is superimposed to highlight where the
574overlay is placed on top of the base image:</p>
575
576<table style="border-collapse:collapse;">
577<tbody>
578<tr>
579<td><img align="center" src="../images/composite01.png" alt="composite image of
580install plus first overlay">
581<p class="img-caption"><strong>Figure 6.</strong> Installing animation frame 1
582(icon_installing.png + icon_installing_overlay01.png)
583</td>
584<td><img align="center" src="../images/composite01.png" alt="composite image of
585install plus seventh overlay">
586<p class="img-caption"><strong>Figure 7.</strong> Installing animation frame 7
587(icon_installing.png + icon_installing_overlay07.png)
588</td>
589</tr>
590</tbody>
591</table>
592
593<p>Subsequent frames are displayed by drawing <i>only</i> the next overlay
594image atop what's already there; the base image is not redrawn.</p>
595
596<p>The number of frames in the animation, desired speed, and x- and y-offsets
597of the overlay relative to the base are set by member variables of the
598ScreenRecoveryUI class. When using custom images instead of default images,
599override the <code>Init()</code> method in your subclass to change these
600values for your custom images (for details, see <a href="#screenrecoveryui">
601ScreenRecoveryUI</a>). The script <code>bootable/recovery/make-overlay.py
602</code> can assist in converting a set of image frames to the "base image +
603overlay images" form needed by recovery, including computing of the necessary
604offsets.</p>
605
606<p>Default images are located in <code>bootable/recovery/res/images</code>. To
607use a static image during installation, you need only provide the
608icon_installing.png image and set the number of frames in the animation to 0
609(the error icon is not animated; it is always a static image).</p>
610
611
612<h3 id="recovery-text">Localized recovery text</h3>
613<p>Android 5.x displays a string of text (e.g., "Installing system update...")
614along with the image.  When the main system boots into recovery it passes the
615user's current locale as a command-line option to recovery. For each message
616to display, recovery includes a second composite image with pre-rendered text
617strings for that message in each locale.</p>
618
619<p>Sample image of recovery text strings:</p>
620
621<img src="../images/installing_text.png" alt="image of recovery text">
622<p class="img-caption"><strong>Figure 8.</strong> Localized text for recovery
623messages</p>
624
625<p>Recovery text can display the following messages:</p>
626<ul>
627<li>Installing system update...</li>
628<li>Error!</li>
629<li>Erasing... (when doing a data wipe/factory reset)</li>
630<li>No command (when a user boots into recovery manually)</li>
631</ul>
632
633<p>The Android app in <code>development/tools/recovery_l10/</code> renders
634localizations of a message and creates the composite image. For details on
635using this app, refer to the comments in <code>development/tools/recovery_l10n/
636src/com/android/recovery_l10n/Main.java</code>.
637
638<p>When a user boots into recovery manually, the locale might not be available
639and no text is displayed. Do not make the text messages critical to the
640recovery process.</p>
641
642<p class="note"><strong>Note:</strong> The hidden interface that displays log
643messages and allows the user to select actions from the menu is available only
644in English.</p>
645
646
647<h2 id="progress-bars">Progress bars</h2>
648<p>Progress bars can appear below the main image (or animation). The progress
649bar is made by combining two input images, which must be of the same size:</p>
650
651<img src="../images/progress_empty.png" alt="empty progress bar">
652<p class="img-caption"><strong>Figure 9.</strong> progress_empty.png</p>
653<img src="../images/progress_fill.png" alt="full progress bar">
654<p class="img-caption"><strong>Figure 10.</strong> progress_fill.png</p>
655
656<p>The left end of the <i>fill</i> image is displayed next to the right end of
657the <i>empty</i> image to make the progress bar. The position of the boundary
658between the two images is changed to indicate the progress. For example, with
659the above pairs of input images, display:</p>
660
661<img src="../images/progress_1.png" alt="progress bar at 1%">
662<p class="img-caption"><strong>Figure 11.</strong> Progress bar at 1%></p>
663<img src="../images/progress_10.png" alt="progress bar at 10%">
664<p class="img-caption"><strong>Figure 12.</strong> Progress bar at 10%</p>
665<img src="../images/progress_50.png" alt="progress bar at 50%">
666<p class="img-caption"><strong>Figure 13.</strong> Progress bar at 50%</p>
667
668<p>You can provide device-specific versions of these images by placing them
669into (in this example) <code>device/yoyodyne/tardis/recovery/res/images</code>
670. Filenames must match the ones listed above; when a file is found in that
671directory, the build system uses it in preference to the corresponding default
672image. Only PNGs in RGB or RGBA format with 8-bit color depth are supported.
673</p>
674
675<p class="note"><strong>Note:</strong> In Android 5.x, if the locale is known
676to recovery and is a right-to-left (RTL) language (Arabic, Hebrew, etc.), the
677progress bar fills from right to left.</p>
678
679
680<h2 id="devices-without-screens">Devices without screens</h2>
681<p>Not all Android devices have screens. If your device is a headless appliance
682or has an audio-only interface, you may need to do more extensive customization
683of recovery UI. Instead of creating a subclass of ScreenRecoveryUI, subclass its
684parent class RecoveryUI directly.</p>
685<p>RecoveryUI has methods for handling a lower-level UI operations such as
686"toggle the display," "update the progress bar," "show the menu," "change the
687menu selection," etc. You can override these to provide an appropriate
688interface for your device. Maybe your device has LEDs where you can use
689different colors or patterns of flashing to indicate state, or maybe you can
690play audio. (Perhaps you don't want to support a menu or the "text display"
691mode at all; you can prevent accessing them with <code>CheckKey()</code> and
692<code>HandleMenuKey()</code> implementations that never toggle the display on
693or select a menu item. In this case, many of the RecoveryUI methods you need
694to provide can just be empty stubs.)</p>
695<p>See <code>bootable/recovery/ui.h</code> for the declaration of RecoveryUI
696to see what methods you must support. RecoveryUI is abstract—some methods are
697pure virtual and must be provided by subclasses—but it does contain the code
698to do processing of key inputs. You can override that too, if your device
699doesn't have keys or you want to process them differently.</p>
700
701<h2 id="updater">Updater</h2>
702<p>You can use device-specific code in the installation of the update package
703by providing your own extension functions that can be called from within your
704updater script. Here's a sample function for the tardis device:</p>
705
706<p><code>device/yoyodyne/tardis/recovery/recovery_updater.c</code></p>
707<pre>
708#include &lt;stdlib.h&gt;
709#include &lt;string.h&gt;
710
711#include "edify/expr.h"
712</pre>
713
714<p>Every extension function has the same signature. The arguments are the name
715by which the function was called, a <code>State*</code> cookie, the number of
716incoming arguments, and an array of <code>Expr*</code> pointers representing
717the arguments. The return value is a newly-allocated <code>Value*</code>.</p>
718
719<pre>
720Value* ReprogramTardisFn(const char* name, State* state, int argc, Expr* argv[]) {
721    if (argc != 2) {
722        return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
723    }
724</pre>
725
726<p>Your arguments have not been evaluated at the time your function is
727called—your function's logic determines which of them get evaluated and how
728many times. Thus, you can use extension functions to implement your own
729control structures. <code>Call Evaluate()</code> to evaluate an <code>Expr*
730</code> argument, returning a <code>Value*</code>. If <code>Evaluate()</code>
731returns NULL, you should free any resources you're holding and immediately
732return NULL (this propagates aborts up the edify stack). Otherwise, you take
733ownership of the Value returned and are responsible for eventually calling
734<code>FreeValue()</code> on it.</p>
735
736<p>Suppose the function needs two arguments: a string-valued <b>key</b> and a
737blob-valued <b>image</b>. You could read arguments like this:</p>
738
739<pre>
740   Value* key = EvaluateValue(state, argv[0]);
741    if (key == NULL) {
742        return NULL;
743    }
744    if (key->type != VAL_STRING) {
745        ErrorAbort(state, "first arg to %s() must be string", name);
746        FreeValue(key);
747        return NULL;
748    }
749    Value* image = EvaluateValue(state, argv[1]);
750    if (image == NULL) {
751        FreeValue(key);    // must always free Value objects
752        return NULL;
753    }
754    if (image->type != VAL_BLOB) {
755        ErrorAbort(state, "second arg to %s() must be blob", name);
756        FreeValue(key);
757        FreeValue(image)
758        return NULL;
759    }
760</pre>
761
762<p>Checking for NULL and freeing previously evaluated arguments can get tedious
763for multiple arguments. The <code>ReadValueArgs()</code> function can make this
764easier. Instead of the code above, you could have written this:</p>
765
766<pre>
767   Value* key;
768    Value* image;
769    if (ReadValueArgs(state, argv, 2, &amp;key, &amp;image) != 0) {
770        return NULL;     // ReadValueArgs() will have set the error message
771    }
772    if (key->type != VAL_STRING || image->type != VAL_BLOB) {
773        ErrorAbort(state, "arguments to %s() have wrong type", name);
774        FreeValue(key);
775        FreeValue(image)
776        return NULL;
777    }
778</pre>
779
780<p><code>ReadValueArgs()</code> doesn't do type-checking, so you must do that
781here; it's more convenient to do it with one <b>if</b> statement at
782the cost of producing a somewhat less specific error message when it fails.
783But <code>ReadValueArgs()</code> does handle evaluating each argument and
784freeing all the previously-evaluated arguments (as well as setting a useful
785error message) if any of the evaluations fail. You can use a <code>
786ReadValueVarArgs()</code> convenience function for evaluating a variable
787number of arguments (it returns an array of <code>Value*</code>).</p>
788
789<p>After evaluating the arguments, do the work of the function:</p>
790
791<pre>
792   // key-&gt;data is a NUL-terminated string
793    // image-&gt;data and image-&gt;size define a block of binary data
794    //
795    // ... some device-specific magic here to
796    // reprogram the tardis using those two values ...
797</pre>
798
799<p>The return value must be a <code>Value*</code> object; ownership of this
800object will pass to the caller. The caller takes ownership of any data pointed
801to by this <code>Value*</code>—specifically the datamember.</p>
802<p>In this instance, you want to return a true or false value to indicate
803success. Remember the convention that the empty string is <i>false</i> and all
804other strings are <i>true</i>. You must malloc a Value object with a malloc'd
805copy of the constant string to return, since the caller will <code>free()
806</code> both. Don't forget to call <code>FreeValue()</code> on the objects you
807got by evaluating your arguments!</p>
808
809<pre>
810   FreeValue(key);
811    FreeValue(image);
812
813    Value* result = malloc(sizeof(Value));
814    result->type = VAL_STRING;
815    result->data = strdup(successful ? "t" : "");
816    result->size = strlen(result->data);
817    return result;
818}
819</pre>
820
821<p>The convenience function <code>StringValue()</code> wraps a string into a
822new Value object. Use to write the above code more succinctly:</p>
823
824<pre>
825   FreeValue(key);
826    FreeValue(image);
827
828    return StringValue(strdup(successful ? "t" : ""));
829}
830</pre>
831
832<p>To hook functions into the edify interpreter, provide the function
833<code>Register_<i>foo</i></code> where <i>foo</i> is the name of the
834static library containing this code. Call <code>RegisterFunction()</code> to
835register each extension function. By convention, name device-specific
836functions <code><i>device</i>.<i>whatever</i></code> to avoid conflicts with
837future built-in functions added.</p>
838
839<pre>
840void Register_librecovery_updater_tardis() {
841    RegisterFunction("tardis.reprogram", ReprogramTardisFn);
842}
843</pre>
844
845<p>You can now configure the makefile to build a static library with your
846code. (This is the same makefile used to customize the recovery UI in the
847previous section; your device may have both static libraries defined here.)</p>
848
849<p><code>device/yoyodyne/tardis/recovery/Android.mk</code></p>
850
851<pre>
852include $(CLEAR_VARS)
853LOCAL_SRC_FILES := recovery_updater.c
854LOCAL_C_INCLUDES += bootable/recovery
855</pre>
856
857<p>The name of the static library must match the name of the
858<code>Register_<i>libname</i></code> function contained within it.</p>
859
860<pre>
861LOCAL_MODULE := librecovery_updater_tardis
862include $(BUILD_STATIC_LIBRARY)
863</pre>
864
865<p>Finally, configure the build of recovery to pull in your library. Add your
866library to TARGET_RECOVERY_UPDATER_LIBS (which may contain multiple libraries;
867they all get registered). If your code depends on other static libraries that
868are not themselves edify extensions (i.e., they don't have a
869<code>Register_<i>libname</i></code> function), you can list those in
870TARGET_RECOVERY_UPDATER_EXTRA_LIBS to link them to updater without calling
871their (non-existent) registration function. For example, if your
872device-specific code wanted to use zlib to decompress data, you would include
873libz here.</p>
874
875<p><code>device/yoyodyne/tardis/BoardConfig.mk</code></p>
876
877<pre>
878 [...]
879
880# add device-specific extensions to the updater binary
881TARGET_RECOVERY_UPDATER_LIBS += librecovery_updater_tardis
882TARGET_RECOVERY_UPDATER_EXTRA_LIBS +=
883</pre>
884
885<p>The updater scripts in your OTA package can now call your function as any
886other. To reprogram your tardis device, the update script might contain:
887<code>tardis.reprogram("the-key", package_extract_file("tardis-image.dat"))
888</code>. This uses the single-argument version of the built-in function <code>
889package_extract_file()</code>, which returns the contents of a file extracted
890from the update package as a blob to produce the second argument to the new
891extension function.</p>
892
893<h2>OTA package generation</h2>
894<p>The final component is getting the OTA package generation tools to know
895about your device-specific data and emit updater scripts that include calls to
896your extension functions.</p>
897<p>First, get the build system to know about a device-specific blob of data.
898Assuming your data file is in <code>device/yoyodyne/tardis/tardis.dat</code>,
899declare the following in your device's AndroidBoard.mk:</p>
900
901<p><code>device/yoyodyne/tardis/AndroidBoard.mk</code></p>
902<pre>
903  [...]
904
905$(call add-radio-file,tardis.dat)
906</pre>
907
908<p>You could also put it in an Android.mk instead, but then it must to be
909guarded by a device check, since all the Android.mk files in the tree are
910loaded no matter what device is being built. (If your tree includes multiple
911devices, you only want the tardis.dat file added when building the tardis
912device.)</p>
913
914<p><code>device/yoyodyne/tardis/Android.mk</code></p>
915<pre>
916  [...]
917
918# an alternative to specifying it in AndroidBoard.mk
919ifeq (($TARGET_DEVICE),tardis)
920  $(call add-radio-file,tardis.dat)
921endif
922</pre>
923
924<p>These are called radio files for historical reasons; they may have nothing
925to do with the device radio (if present). They are simply opaque blobs of data
926the build system copies into the target-files .zip used by the OTA generation
927tools. When you do a build, tardis.dat is stored in the target-files.zip as
928<code>RADIO/tardis.dat</code>. You can call <code>add-radio-file</code>
929multiple times to add as many files as you want.</p>
930
931<h3 id="python-module">Python module</h3>
932<p>To extend the release tools, write a Python module (must be named
933releasetools.py) the tools can call into if present. Example:</p>
934
935<p><code>device/yoyodyne/tardis/releasetools.py</code></p>
936<pre>
937import common
938
939def FullOTA_InstallEnd(info):
940  # copy the data into the package.
941  tardis_dat = info.input_zip.read("RADIO/tardis.dat")
942  common.ZipWriteStr(info.output_zip, "tardis.dat", tardis_dat)
943
944  # emit the script code to install this data on the device
945  info.script.AppendExtra(
946      """tardis.reprogram("the-key", package_extract_file("tardis.dat"));""")
947</pre>
948
949<p>A separate function handles the case of generating an incremental OTA
950package. For this example, suppose you need to reprogram the tardis only when
951the tardis.dat file has changed between two builds.</p>
952<pre>
953def IncrementalOTA_InstallEnd(info):
954  # copy the data into the package.
955  source_tardis_dat = info.source_zip.read("RADIO/tardis.dat")
956  target_tardis_dat = info.target_zip.read("RADIO/tardis.dat")
957
958  if source_tardis_dat == target_tardis_dat:
959      # tardis.dat is unchanged from previous build; no
960      # need to reprogram it
961      return
962
963  # include the new tardis.dat in the OTA package
964  common.ZipWriteStr(info.output_zip, "tardis.dat", target_tardis_dat)
965
966  # emit the script code to install this data on the device
967  info.script.AppendExtra(
968      """tardis.reprogram("the-key", package_extract_file("tardis.dat"));""")
969</pre>
970
971<h4 id="module-functions">Module functions</h4>
972<p>You can provide the following functions in the module (implement only the
973ones you need).</p>
974<dl>
975<dt><code>FullOTA_Assertions()</code></dt>
976<dd>Called near the start of generating a full OTA. This is a good place to
977emit assertions about the current state of the device. Do not emit script
978commands that make changes to the device.</dd>
979<dt><code>FullOTA_InstallBegin()</code></dt>
980<dd>Called after all the assertions about the device state have passed but
981before any changes have been made. You can emit commands for device-specific
982updates that must run before anything else on the device has been changed.</dd>
983<dt><code>FullOTA_InstallEnd()</code></dt>
984<dd>Called at the end of the script generation, after the script commands to
985update the boot and system partitions have been emitted. You can also emit
986additional commands for device-specific updates.</dd>
987<dt><code>IncrementalOTA_Assertions()</code></dt>
988<dd>Similar to <code>FullOTA_Assertions()</code> but called when generating an
989incremental update package.</dd>
990<dt><code>IncrementalOTA_VerifyBegin()</code></dt>
991<dd>Called after all assertions about the device state have passed but before
992any changes have been made. You can emit commands for device-specific updates
993that must run before anything else on the device has been changed.</dd>
994<dt><code>IncrementalOTA_VerifyEnd()</code></dt>
995<dd>Called at the end of the verification phase, when the script has finished
996confirming the files it is going to touch have the expected starting contents.
997At this point nothing on the device has been changed. You can also emit code for
998additional device-specific verifications.</dd>
999<dt><code>IncrementalOTA_InstallBegin()</code></dt>
1000<dd>Called after files to be patched have been verified as having the expected
1001<i>before</i> state but before any changes have been made. You can emit
1002commands for device-specific updates that must run before anything else on the
1003device has been changed.</dd>
1004<dt><code>IncrementalOTA_InstallEnd()</code></dt>
1005<dd>Similar to its full OTA package counterpart, this is called at the end of
1006the script generation, after the script commands to update the boot and system
1007partitions have been emitted. You can also emit additional commands for
1008device-specific updates.</dd>
1009</dl>
1010
1011<p class="note"><strong>Note:</strong> If the device loses power, OTA
1012installation may restart from the beginning. Be prepared to cope with devices
1013on which these commands have already been run, fully or partially.</p>
1014
1015<h4 id="pass-functions-to-info">Pass functions to info objects</h4>
1016<p>Pass functions to a single info object that contains various useful items:
1017</p>
1018<ul>
1019<li><b>info.input_zip</b>. (Full OTAs only) The <code>zipfile.ZipFile</code>
1020object for the input target-files .zip.</li>
1021<li><b>info.source_zip</b>. (Incremental OTAs only) The <code>zipfile.ZipFile
1022</code> object for the source target-files .zip (the build already on the
1023device when the incremental package is being installed).</li>
1024<li><b>info.target_zip</b>. (Incremental OTAs only) The <code>zipfile.ZipFile
1025</code> object for the target target-files .zip (the build the incremental
1026package puts on the device).</li>
1027<li><b>info.output_zip</b>. Package being created; a <code>zipfile.ZipFile
1028</code> object opened for writing. Use common.ZipWriteStr(info.output_zip,
1029<i>filename</i>, <i>data</i>) to add a file to the package.</li>
1030<li><b>info.script</b>. Script object to which you can append commands. Call
1031<code>info.script.AppendExtra(<i>script_text</i>)</code> to output text into
1032the script. Make sure output text ends with a semicolon so it does not run
1033into commands emitted afterwards.</li>
1034</ul>
1035
1036<p>For details on the info object, refer to the
1037<a href="http://docs.python.org/library/zipfile.html">Python Software Foundation
1038documentation for ZIP archives</a>.</p>
1039
1040<h4 id="specify-module-location">Specify module location</h4>
1041<p>Specify the location of your device's releasetools.py script in your
1042BoardConfig.mk file:</p>
1043
1044<p><code>device/yoyodyne/tardis/BoardConfig.mk</code></p>
1045
1046<pre>
1047 [...]
1048
1049TARGET_RELEASETOOLS_EXTENSIONS := device/yoyodyne/tardis
1050</pre>
1051
1052<p>If TARGET_RELEASETOOLS_EXTENSIONS is not set, it defaults to the <code>
1053$(TARGET_DEVICE_DIR)/../common</code> directory (<code>device/yoyodyne/common
1054</code> in this example). It's best to explicitly define the location of the
1055releasetools.py script. When building the tardis device, the releasetools.py
1056script is included in the target-files .zip file (<code>META/releasetools.py
1057</code>).</p>
1058<p>When you run the release tools (either <code>img_from_target_files</code>
1059or <code>ota_from_target_files</code>), the releasetools.py script in the
1060target-files .zip, if present, is preferred over the one from the Android
1061source tree. You can also explicitly specify the path to the device-specific
1062extensions with the <code>-s</code> (or <code>--device_specific</code>)
1063option, which takes the top priority. This enables you to correct errors and
1064make changes in the releasetools extensions and apply those changes to old
1065target-files.</p>
1066<p>Now, when you run <code>ota_from_target_files</code>, it automatically
1067picks up the device-specific module from the target_files .zip file and uses
1068it when generating OTA packages:</p>
1069
1070<pre>
1071% <b>./build/tools/releasetools/ota_from_target_files \
1072    -i PREVIOUS-tardis-target_files.zip \
1073    dist_output/tardis-target_files.zip incremental_ota_update.zip</b>
1074unzipping target target-files...
1075<b>using device-specific extensions from target_files</b>
1076unzipping source target-files...
1077   [...]
1078done.
1079</pre>
1080
1081<p>Alternatively, you can specify device-specific extensions when you run
1082<code>ota_from_target_files</code>.</p>
1083
1084<pre>
1085% <b>./build/tools/releasetools/ota_from_target_files \
1086    -s device/yoyodyne/tardis \  # specify the path to device-specific extensions
1087    -i PREVIOUS-tardis-target_files.zip \
1088    dist_output/tardis-target_files.zip incremental_ota_update.zip</b>
1089unzipping target target-files...
1090<b>loaded device-specific extensions from device/yoyodyne/tardis</b>
1091unzipping source target-files...
1092   [...]
1093done.
1094</pre>
1095
1096<p class="note"><strong>Note:</strong> For a complete list of options, refer
1097to the <code>ota_from_target_files</code> comments in <code>
1098build/tools/releasetools/ota_from_target_files</code>.</p>
1099
1100
1101<h2 id="sideloading">Sideloading</h2>
1102<p>Recovery has a <b>sideloading</b> mechanism for manually installing an
1103update package without downloading it over-the-air by the main system.
1104Sideloading is useful for debugging or making changes on devices where the
1105main system can't be booted.</p>
1106<p>Historically, sideloading has been done through loading packages off the
1107device's SD card; in the case of a non-booting device, the package can be put
1108onto the SD card using some other computer and then the SD card inserted into
1109the device. To accommodate Android devices without removable external storage,
1110recovery supports two additional mechanisms for sideloading: loading packages
1111from the cache partition, and loading them over USB using adb.</p>
1112<p>To invoke each sideload mechanism, your device's <code>
1113Device::InvokeMenuItem()</code> method can return the following values of
1114BuiltinAction:</p>
1115
1116<ul>
1117<li><b>APPLY_EXT</b>. Sideload an update package from external storage (<code>
1118/sdcard</code> directory). Your recovery.fstab must define the <code>/sdcard
1119</code> mount point. This is not usable on devices that emulate an SD card
1120with a symlink to <code>/data</code> (or some similar mechanism). <code>/data
1121</code> is typically not available to recovery because it may be encrypted.
1122The recovery UI displays a menu of .zip files in <code>/sdcard</code> and
1123allows the user to select one.</li>
1124<li><b>APPLY_CACHE</b>. Similar to loading a package from <code>/sdcard</code>
1125except that the <code>/cache</code> directory (which <i>is</i> always
1126available to recovery) is used instead. From the regular system, <code>/cache
1127</code> is only writable by privileged users, and if the device isn't bootable
1128then the <code>/cache</code> directory can't be written to at all (which makes
1129this mechanism of limited utility).</li>
1130<li><b>APPLY_ADB_SIDELOAD</b>. Allows user to send a package to the device via
1131a USB cable and the adb development tool. When this mechanism is invoked,
1132recovery starts up its own mini version of the adbd daemon to let adb on a
1133connected host computer talk to it. This mini version supports only a single
1134command: <code>adb sideload <i>filename</i></code>. The named file is sent
1135from the host machine to the device, which then verifies and installs it just
1136as if it had been on local storage.</li>
1137</ul>
1138
1139<p>A few caveats:</p>
1140<ul>
1141<li>Only USB transport is supported.</li>
1142<li>If your recovery runs adbd normally (usually true for userdebug and eng
1143builds), that will be shut down while the device is in adb sideload mode and
1144will be restarted when adb sideload has finished receiving a package. While in
1145adb sideload mode, no adb commands other than <code>sideload</code> work (
1146<code>logcat</code>, <code>reboot</code>, <code>push</code>, <code>pull</code>
1147, <code>shell</code>, etc. all fail).</li>
1148<li>You cannot exit adb sideload mode on the device. To abort, you can send
1149<code>/dev/null</code> (or anything else that's not a valid package) as the
1150package, and then the device will fail to verify it and stop the installation
1151procedure. The RecoveryUI implementation's <code>CheckKey()</code> method
1152will continue to be called for keypresses, so you can provide a key sequence
1153that reboots the device and works in adb sideload mode.</li>
1154</ul>