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