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 <linux/input.h> 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) && key == KEY_VOLUMEUP) { 229 return TOGGLE; 230 } 231 if (key == KEY_POWER) { 232 ++consecutive_power_keys; 233 if (consecutive_power_keys >= 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) && 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 <stdlib.h> 692 #include <string.h> 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, &key, &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->data is a NUL-terminated string 776 // image->data and image->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