summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTianjie Xu2017-11-28 19:23:06 -0600
committerTianjie Xu2017-11-30 18:25:47 -0600
commit99b73be3a8f3a97ff11f3e50a4169292a2f36fb1 (patch)
treee9880840a1c77ce51810def4d873dad21e5fa9b8
parent5ce9fe355caf09efdb3679bec620ee486cedb731 (diff)
downloadplatform-bootable-recovery-99b73be3a8f3a97ff11f3e50a4169292a2f36fb1.tar.gz
platform-bootable-recovery-99b73be3a8f3a97ff11f3e50a4169292a2f36fb1.tar.xz
platform-bootable-recovery-99b73be3a8f3a97ff11f3e50a4169292a2f36fb1.zip
Detect interrupted update due to power off
An interrupted update may stash extra blocks in /cache, leading to a failure when checking the cache size. We can save the incremented retry_count in the BCB before installing the update; and distinguish a fresh update from an interrupted one this way. Bug: 68679601 Test: An interrupted update reapplies successfully. Change-Id: Ic1403e1fd25a937c91ef34c14b92a0f6c8f1c0f4
-rw-r--r--recovery.cpp565
-rw-r--r--updater/install.cpp6
2 files changed, 302 insertions, 269 deletions
diff --git a/recovery.cpp b/recovery.cpp
index a8991633..6bd29146 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -1313,6 +1313,7 @@ static bool is_battery_ok() {
1313 } 1313 }
1314} 1314}
1315 1315
1316// Set the retry count to |retry_count| in BCB.
1316static void set_retry_bootloader_message(int retry_count, const std::vector<std::string>& args) { 1317static void set_retry_bootloader_message(int retry_count, const std::vector<std::string>& args) {
1317 std::vector<std::string> options; 1318 std::vector<std::string> options;
1318 for (const auto& arg : args) { 1319 for (const auto& arg : args) {
@@ -1321,8 +1322,8 @@ static void set_retry_bootloader_message(int retry_count, const std::vector<std:
1321 } 1322 }
1322 } 1323 }
1323 1324
1324 // Increment the retry counter by 1. 1325 // Update the retry counter in BCB.
1325 options.push_back(android::base::StringPrintf("--retry_count=%d", retry_count + 1)); 1326 options.push_back(android::base::StringPrintf("--retry_count=%d", retry_count));
1326 std::string err; 1327 std::string err;
1327 if (!update_bootloader_message(options, &err)) { 1328 if (!update_bootloader_message(options, &err)) {
1328 LOG(ERROR) << err; 1329 LOG(ERROR) << err;
@@ -1357,303 +1358,331 @@ static void log_failure_code(ErrorCode code, const char *update_package) {
1357} 1358}
1358 1359
1359int main(int argc, char **argv) { 1360int main(int argc, char **argv) {
1360 // We don't have logcat yet under recovery; so we'll print error on screen and 1361 // We don't have logcat yet under recovery; so we'll print error on screen and
1361 // log to stdout (which is redirected to recovery.log) as we used to do. 1362 // log to stdout (which is redirected to recovery.log) as we used to do.
1362 android::base::InitLogging(argv, &UiLogger); 1363 android::base::InitLogging(argv, &UiLogger);
1363 1364
1364 // Take last pmsg contents and rewrite it to the current pmsg session. 1365 // Take last pmsg contents and rewrite it to the current pmsg session.
1365 static const char filter[] = "recovery/"; 1366 static const char filter[] = "recovery/";
1366 // Do we need to rotate? 1367 // Do we need to rotate?
1367 bool doRotate = false; 1368 bool doRotate = false;
1368 1369
1369 __android_log_pmsg_file_read( 1370 __android_log_pmsg_file_read(LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter, logbasename, &doRotate);
1370 LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter, 1371 // Take action to refresh pmsg contents
1371 logbasename, &doRotate); 1372 __android_log_pmsg_file_read(LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter, logrotate, &doRotate);
1372 // Take action to refresh pmsg contents 1373
1373 __android_log_pmsg_file_read( 1374 // If this binary is started with the single argument "--adbd",
1374 LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter, 1375 // instead of being the normal recovery binary, it turns into kind
1375 logrotate, &doRotate); 1376 // of a stripped-down version of adbd that only supports the
1376 1377 // 'sideload' command. Note this must be a real argument, not
1377 // If this binary is started with the single argument "--adbd", 1378 // anything in the command file or bootloader control block; the
1378 // instead of being the normal recovery binary, it turns into kind 1379 // only way recovery should be run with this argument is when it
1379 // of a stripped-down version of adbd that only supports the 1380 // starts a copy of itself from the apply_from_adb() function.
1380 // 'sideload' command. Note this must be a real argument, not 1381 if (argc == 2 && strcmp(argv[1], "--adbd") == 0) {
1381 // anything in the command file or bootloader control block; the 1382 minadbd_main();
1382 // only way recovery should be run with this argument is when it 1383 return 0;
1383 // starts a copy of itself from the apply_from_adb() function. 1384 }
1384 if (argc == 2 && strcmp(argv[1], "--adbd") == 0) { 1385
1385 minadbd_main(); 1386 time_t start = time(nullptr);
1386 return 0; 1387
1387 } 1388 // redirect_stdio should be called only in non-sideload mode. Otherwise
1388 1389 // we may have two logger instances with different timestamps.
1389 time_t start = time(NULL); 1390 redirect_stdio(TEMPORARY_LOG_FILE);
1390 1391
1391 // redirect_stdio should be called only in non-sideload mode. Otherwise 1392 printf("Starting recovery (pid %d) on %s", getpid(), ctime(&start));
1392 // we may have two logger instances with different timestamps. 1393
1393 redirect_stdio(TEMPORARY_LOG_FILE); 1394 load_volume_table();
1394 1395 has_cache = volume_for_mount_point(CACHE_ROOT) != nullptr;
1395 printf("Starting recovery (pid %d) on %s", getpid(), ctime(&start)); 1396
1396 1397 std::vector<std::string> args = get_args(argc, argv);
1397 load_volume_table(); 1398 std::vector<char*> args_to_parse(args.size());
1398 has_cache = volume_for_mount_point(CACHE_ROOT) != nullptr; 1399 std::transform(args.cbegin(), args.cend(), args_to_parse.begin(),
1399 1400 [](const std::string& arg) { return const_cast<char*>(arg.c_str()); });
1400 std::vector<std::string> args = get_args(argc, argv); 1401
1401 std::vector<char*> args_to_parse(args.size()); 1402 const char* update_package = nullptr;
1402 std::transform(args.cbegin(), args.cend(), args_to_parse.begin(), 1403 bool should_wipe_data = false;
1403 [](const std::string& arg) { return const_cast<char*>(arg.c_str()); }); 1404 bool should_prompt_and_wipe_data = false;
1404 1405 bool should_wipe_cache = false;
1405 const char *update_package = NULL; 1406 bool should_wipe_ab = false;
1406 bool should_wipe_data = false; 1407 size_t wipe_package_size = 0;
1407 bool should_prompt_and_wipe_data = false; 1408 bool show_text = false;
1408 bool should_wipe_cache = false; 1409 bool sideload = false;
1409 bool should_wipe_ab = false; 1410 bool sideload_auto_reboot = false;
1410 size_t wipe_package_size = 0; 1411 bool just_exit = false;
1411 bool show_text = false; 1412 bool shutdown_after = false;
1412 bool sideload = false; 1413 int retry_count = 0;
1413 bool sideload_auto_reboot = false; 1414 bool security_update = false;
1414 bool just_exit = false; 1415
1415 bool shutdown_after = false; 1416 int arg;
1416 int retry_count = 0; 1417 int option_index;
1417 bool security_update = false; 1418 while ((arg = getopt_long(args_to_parse.size(), args_to_parse.data(), "", OPTIONS,
1418 1419 &option_index)) != -1) {
1419 int arg; 1420 switch (arg) {
1420 int option_index; 1421 case 'n':
1421 while ((arg = getopt_long(args_to_parse.size(), args_to_parse.data(), "", OPTIONS, 1422 android::base::ParseInt(optarg, &retry_count, 0);
1422 &option_index)) != -1) { 1423 break;
1423 switch (arg) { 1424 case 'u':
1424 case 'n': android::base::ParseInt(optarg, &retry_count, 0); break; 1425 update_package = optarg;
1425 case 'u': update_package = optarg; break; 1426 break;
1426 case 'w': should_wipe_data = true; break; 1427 case 'w':
1427 case 'c': should_wipe_cache = true; break; 1428 should_wipe_data = true;
1428 case 't': show_text = true; break; 1429 break;
1429 case 's': sideload = true; break; 1430 case 'c':
1430 case 'a': sideload = true; sideload_auto_reboot = true; break; 1431 should_wipe_cache = true;
1431 case 'x': just_exit = true; break; 1432 break;
1432 case 'l': locale = optarg; break; 1433 case 't':
1433 case 'p': shutdown_after = true; break; 1434 show_text = true;
1434 case 'r': reason = optarg; break; 1435 break;
1435 case 'e': security_update = true; break; 1436 case 's':
1436 case 0: { 1437 sideload = true;
1437 std::string option = OPTIONS[option_index].name; 1438 break;
1438 if (option == "wipe_ab") { 1439 case 'a':
1439 should_wipe_ab = true; 1440 sideload = true;
1440 } else if (option == "wipe_package_size") { 1441 sideload_auto_reboot = true;
1441 android::base::ParseUint(optarg, &wipe_package_size); 1442 break;
1442 } else if (option == "prompt_and_wipe_data") { 1443 case 'x':
1443 should_prompt_and_wipe_data = true; 1444 just_exit = true;
1444 } 1445 break;
1445 break; 1446 case 'l':
1446 } 1447 locale = optarg;
1447 case '?': 1448 break;
1448 LOG(ERROR) << "Invalid command argument"; 1449 case 'p':
1449 continue; 1450 shutdown_after = true;
1451 break;
1452 case 'r':
1453 reason = optarg;
1454 break;
1455 case 'e':
1456 security_update = true;
1457 break;
1458 case 0: {
1459 std::string option = OPTIONS[option_index].name;
1460 if (option == "wipe_ab") {
1461 should_wipe_ab = true;
1462 } else if (option == "wipe_package_size") {
1463 android::base::ParseUint(optarg, &wipe_package_size);
1464 } else if (option == "prompt_and_wipe_data") {
1465 should_prompt_and_wipe_data = true;
1450 } 1466 }
1467 break;
1468 }
1469 case '?':
1470 LOG(ERROR) << "Invalid command argument";
1471 continue;
1451 } 1472 }
1473 }
1452 1474
1453 if (locale.empty()) { 1475 if (locale.empty()) {
1454 if (has_cache) { 1476 if (has_cache) {
1455 locale = load_locale_from_cache(); 1477 locale = load_locale_from_cache();
1456 } 1478 }
1457 1479
1458 if (locale.empty()) { 1480 if (locale.empty()) {
1459 locale = DEFAULT_LOCALE; 1481 locale = DEFAULT_LOCALE;
1460 }
1461 } 1482 }
1483 }
1462 1484
1463 printf("locale is [%s]\n", locale.c_str()); 1485 printf("locale is [%s]\n", locale.c_str());
1464 printf("stage is [%s]\n", stage.c_str()); 1486 printf("stage is [%s]\n", stage.c_str());
1465 printf("reason is [%s]\n", reason); 1487 printf("reason is [%s]\n", reason);
1466 1488
1467 Device* device = make_device(); 1489 Device* device = make_device();
1468 if (android::base::GetBoolProperty("ro.boot.quiescent", false)) { 1490 if (android::base::GetBoolProperty("ro.boot.quiescent", false)) {
1469 printf("Quiescent recovery mode.\n"); 1491 printf("Quiescent recovery mode.\n");
1470 ui = new StubRecoveryUI(); 1492 ui = new StubRecoveryUI();
1471 } else { 1493 } else {
1472 ui = device->GetUI(); 1494 ui = device->GetUI();
1473 1495
1474 if (!ui->Init(locale)) { 1496 if (!ui->Init(locale)) {
1475 printf("Failed to initialize UI, use stub UI instead.\n"); 1497 printf("Failed to initialize UI, use stub UI instead.\n");
1476 ui = new StubRecoveryUI(); 1498 ui = new StubRecoveryUI();
1477 }
1478 } 1499 }
1500 }
1479 1501
1480 // Set background string to "installing security update" for security update, 1502 // Set background string to "installing security update" for security update,
1481 // otherwise set it to "installing system update". 1503 // otherwise set it to "installing system update".
1482 ui->SetSystemUpdateText(security_update); 1504 ui->SetSystemUpdateText(security_update);
1483 1505
1484 int st_cur, st_max; 1506 int st_cur, st_max;
1485 if (!stage.empty() && sscanf(stage.c_str(), "%d/%d", &st_cur, &st_max) == 2) { 1507 if (!stage.empty() && sscanf(stage.c_str(), "%d/%d", &st_cur, &st_max) == 2) {
1486 ui->SetStage(st_cur, st_max); 1508 ui->SetStage(st_cur, st_max);
1487 } 1509 }
1488 1510
1489 ui->SetBackground(RecoveryUI::NONE); 1511 ui->SetBackground(RecoveryUI::NONE);
1490 if (show_text) ui->ShowText(true); 1512 if (show_text) ui->ShowText(true);
1491 1513
1492 sehandle = selinux_android_file_context_handle(); 1514 sehandle = selinux_android_file_context_handle();
1493 selinux_android_set_sehandle(sehandle); 1515 selinux_android_set_sehandle(sehandle);
1494 if (!sehandle) { 1516 if (!sehandle) {
1495 ui->Print("Warning: No file_contexts\n"); 1517 ui->Print("Warning: No file_contexts\n");
1496 } 1518 }
1497 1519
1498 device->StartRecovery(); 1520 device->StartRecovery();
1499 1521
1500 printf("Command:"); 1522 printf("Command:");
1501 for (const auto& arg : args) { 1523 for (const auto& arg : args) {
1502 printf(" \"%s\"", arg.c_str()); 1524 printf(" \"%s\"", arg.c_str());
1503 } 1525 }
1504 printf("\n\n"); 1526 printf("\n\n");
1505 1527
1506 property_list(print_property, NULL); 1528 property_list(print_property, nullptr);
1507 printf("\n"); 1529 printf("\n");
1508 1530
1509 ui->Print("Supported API: %d\n", kRecoveryApiVersion); 1531 ui->Print("Supported API: %d\n", kRecoveryApiVersion);
1510 1532
1511 int status = INSTALL_SUCCESS; 1533 int status = INSTALL_SUCCESS;
1512 1534
1513 if (update_package != NULL) { 1535 if (update_package != nullptr) {
1514 // It's not entirely true that we will modify the flash. But we want 1536 // It's not entirely true that we will modify the flash. But we want
1515 // to log the update attempt since update_package is non-NULL. 1537 // to log the update attempt since update_package is non-NULL.
1516 modified_flash = true; 1538 modified_flash = true;
1517 1539
1518 if (!is_battery_ok()) { 1540 if (!is_battery_ok()) {
1519 ui->Print("battery capacity is not enough for installing package, needed is %d%%\n", 1541 ui->Print("battery capacity is not enough for installing package, needed is %d%%\n",
1520 BATTERY_OK_PERCENTAGE); 1542 BATTERY_OK_PERCENTAGE);
1521 // Log the error code to last_install when installation skips due to 1543 // Log the error code to last_install when installation skips due to
1522 // low battery. 1544 // low battery.
1523 log_failure_code(kLowBattery, update_package); 1545 log_failure_code(kLowBattery, update_package);
1524 status = INSTALL_SKIPPED; 1546 status = INSTALL_SKIPPED;
1525 } else if (bootreason_in_blacklist()) { 1547 } else if (bootreason_in_blacklist()) {
1526 // Skip update-on-reboot when bootreason is kernel_panic or similar 1548 // Skip update-on-reboot when bootreason is kernel_panic or similar
1527 ui->Print("bootreason is in the blacklist; skip OTA installation\n"); 1549 ui->Print("bootreason is in the blacklist; skip OTA installation\n");
1528 log_failure_code(kBootreasonInBlacklist, update_package); 1550 log_failure_code(kBootreasonInBlacklist, update_package);
1529 status = INSTALL_SKIPPED; 1551 status = INSTALL_SKIPPED;
1530 } else { 1552 } else {
1531 status = install_package(update_package, &should_wipe_cache, 1553 // It's a fresh update. Initialize the retry_count in the BCB to 1; therefore we can later
1532 TEMPORARY_INSTALL_FILE, true, retry_count); 1554 // identify the interrupted update due to unexpected reboots.
1533 if (status == INSTALL_SUCCESS && should_wipe_cache) { 1555 if (retry_count == 0) {
1534 wipe_cache(false, device); 1556 set_retry_bootloader_message(retry_count + 1, args);
1535 } 1557 }
1536 if (status != INSTALL_SUCCESS) { 1558
1537 ui->Print("Installation aborted.\n"); 1559 status = install_package(update_package, &should_wipe_cache, TEMPORARY_INSTALL_FILE, true,
1538 // When I/O error happens, reboot and retry installation RETRY_LIMIT 1560 retry_count);
1539 // times before we abandon this OTA update. 1561 if (status == INSTALL_SUCCESS && should_wipe_cache) {
1540 if (status == INSTALL_RETRY && retry_count < RETRY_LIMIT) { 1562 wipe_cache(false, device);
1541 copy_logs(); 1563 }
1542 set_retry_bootloader_message(retry_count, args); 1564 if (status != INSTALL_SUCCESS) {
1543 // Print retry count on screen. 1565 ui->Print("Installation aborted.\n");
1544 ui->Print("Retry attempt %d\n", retry_count); 1566 // When I/O error happens, reboot and retry installation RETRY_LIMIT
1545 1567 // times before we abandon this OTA update.
1546 // Reboot and retry the update 1568 if (status == INSTALL_RETRY && retry_count < RETRY_LIMIT) {
1547 if (!reboot("reboot,recovery")) { 1569 copy_logs();
1548 ui->Print("Reboot failed\n"); 1570 retry_count += 1;
1549 } else { 1571 set_retry_bootloader_message(retry_count, args);
1550 while (true) { 1572 // Print retry count on screen.
1551 pause(); 1573 ui->Print("Retry attempt %d\n", retry_count);
1552 } 1574
1553 } 1575 // Reboot and retry the update
1554 } 1576 if (!reboot("reboot,recovery")) {
1555 // If this is an eng or userdebug build, then automatically 1577 ui->Print("Reboot failed\n");
1556 // turn the text display on if the script fails so the error 1578 } else {
1557 // message is visible. 1579 while (true) {
1558 if (is_ro_debuggable()) { 1580 pause();
1559 ui->ShowText(true);
1560 }
1561 }
1562 }
1563 } else if (should_wipe_data) {
1564 if (!wipe_data(device)) {
1565 status = INSTALL_ERROR;
1566 }
1567 } else if (should_prompt_and_wipe_data) {
1568 ui->ShowText(true);
1569 ui->SetBackground(RecoveryUI::ERROR);
1570 if (!prompt_and_wipe_data(device)) {
1571 status = INSTALL_ERROR;
1572 }
1573 ui->ShowText(false);
1574 } else if (should_wipe_cache) {
1575 if (!wipe_cache(false, device)) {
1576 status = INSTALL_ERROR;
1577 }
1578 } else if (should_wipe_ab) {
1579 if (!wipe_ab_device(wipe_package_size)) {
1580 status = INSTALL_ERROR;
1581 }
1582 } else if (sideload) {
1583 // 'adb reboot sideload' acts the same as user presses key combinations
1584 // to enter the sideload mode. When 'sideload-auto-reboot' is used, text
1585 // display will NOT be turned on by default. And it will reboot after
1586 // sideload finishes even if there are errors. Unless one turns on the
1587 // text display during the installation. This is to enable automated
1588 // testing.
1589 if (!sideload_auto_reboot) {
1590 ui->ShowText(true);
1591 }
1592 status = apply_from_adb(&should_wipe_cache, TEMPORARY_INSTALL_FILE);
1593 if (status == INSTALL_SUCCESS && should_wipe_cache) {
1594 if (!wipe_cache(false, device)) {
1595 status = INSTALL_ERROR;
1596 } 1581 }
1582 }
1597 } 1583 }
1598 ui->Print("\nInstall from ADB complete (status: %d).\n", status); 1584 // If this is an eng or userdebug build, then automatically
1599 if (sideload_auto_reboot) { 1585 // turn the text display on if the script fails so the error
1600 ui->Print("Rebooting automatically.\n"); 1586 // message is visible.
1587 if (is_ro_debuggable()) {
1588 ui->ShowText(true);
1601 } 1589 }
1602 } else if (!just_exit) {
1603 // If this is an eng or userdebug build, automatically turn on the text display if no command
1604 // is specified. Note that this should be called before setting the background to avoid
1605 // flickering the background image.
1606 if (is_ro_debuggable()) {
1607 ui->ShowText(true);
1608 } 1590 }
1609 status = INSTALL_NONE; // No command specified
1610 ui->SetBackground(RecoveryUI::NO_COMMAND);
1611 } 1591 }
1592 } else if (should_wipe_data) {
1593 if (!wipe_data(device)) {
1594 status = INSTALL_ERROR;
1595 }
1596 } else if (should_prompt_and_wipe_data) {
1597 ui->ShowText(true);
1598 ui->SetBackground(RecoveryUI::ERROR);
1599 if (!prompt_and_wipe_data(device)) {
1600 status = INSTALL_ERROR;
1601 }
1602 ui->ShowText(false);
1603 } else if (should_wipe_cache) {
1604 if (!wipe_cache(false, device)) {
1605 status = INSTALL_ERROR;
1606 }
1607 } else if (should_wipe_ab) {
1608 if (!wipe_ab_device(wipe_package_size)) {
1609 status = INSTALL_ERROR;
1610 }
1611 } else if (sideload) {
1612 // 'adb reboot sideload' acts the same as user presses key combinations
1613 // to enter the sideload mode. When 'sideload-auto-reboot' is used, text
1614 // display will NOT be turned on by default. And it will reboot after
1615 // sideload finishes even if there are errors. Unless one turns on the
1616 // text display during the installation. This is to enable automated
1617 // testing.
1618 if (!sideload_auto_reboot) {
1619 ui->ShowText(true);
1620 }
1621 status = apply_from_adb(&should_wipe_cache, TEMPORARY_INSTALL_FILE);
1622 if (status == INSTALL_SUCCESS && should_wipe_cache) {
1623 if (!wipe_cache(false, device)) {
1624 status = INSTALL_ERROR;
1625 }
1626 }
1627 ui->Print("\nInstall from ADB complete (status: %d).\n", status);
1628 if (sideload_auto_reboot) {
1629 ui->Print("Rebooting automatically.\n");
1630 }
1631 } else if (!just_exit) {
1632 // If this is an eng or userdebug build, automatically turn on the text display if no command
1633 // is specified. Note that this should be called before setting the background to avoid
1634 // flickering the background image.
1635 if (is_ro_debuggable()) {
1636 ui->ShowText(true);
1637 }
1638 status = INSTALL_NONE; // No command specified
1639 ui->SetBackground(RecoveryUI::NO_COMMAND);
1640 }
1612 1641
1613 if (status == INSTALL_ERROR || status == INSTALL_CORRUPT) { 1642 if (status == INSTALL_ERROR || status == INSTALL_CORRUPT) {
1614 ui->SetBackground(RecoveryUI::ERROR); 1643 ui->SetBackground(RecoveryUI::ERROR);
1615 if (!ui->IsTextVisible()) { 1644 if (!ui->IsTextVisible()) {
1616 sleep(5); 1645 sleep(5);
1617 }
1618 } 1646 }
1647 }
1619 1648
1620 Device::BuiltinAction after = shutdown_after ? Device::SHUTDOWN : Device::REBOOT; 1649 Device::BuiltinAction after = shutdown_after ? Device::SHUTDOWN : Device::REBOOT;
1621 // 1. If the recovery menu is visible, prompt and wait for commands. 1650 // 1. If the recovery menu is visible, prompt and wait for commands.
1622 // 2. If the state is INSTALL_NONE, wait for commands. (i.e. In user build, manually reboot into 1651 // 2. If the state is INSTALL_NONE, wait for commands. (i.e. In user build, manually reboot into
1623 // recovery to sideload a package.) 1652 // recovery to sideload a package.)
1624 // 3. sideload_auto_reboot is an option only available in user-debug build, reboot the device 1653 // 3. sideload_auto_reboot is an option only available in user-debug build, reboot the device
1625 // without waiting. 1654 // without waiting.
1626 // 4. In all other cases, reboot the device. Therefore, normal users will observe the device 1655 // 4. In all other cases, reboot the device. Therefore, normal users will observe the device
1627 // reboot after it shows the "error" screen for 5s. 1656 // reboot after it shows the "error" screen for 5s.
1628 if ((status == INSTALL_NONE && !sideload_auto_reboot) || ui->IsTextVisible()) { 1657 if ((status == INSTALL_NONE && !sideload_auto_reboot) || ui->IsTextVisible()) {
1629 Device::BuiltinAction temp = prompt_and_wait(device, status); 1658 Device::BuiltinAction temp = prompt_and_wait(device, status);
1630 if (temp != Device::NO_ACTION) { 1659 if (temp != Device::NO_ACTION) {
1631 after = temp; 1660 after = temp;
1632 }
1633 } 1661 }
1662 }
1634 1663
1635 // Save logs and clean up before rebooting or shutting down. 1664 // Save logs and clean up before rebooting or shutting down.
1636 finish_recovery(); 1665 finish_recovery();
1637 1666
1638 switch (after) { 1667 switch (after) {
1639 case Device::SHUTDOWN: 1668 case Device::SHUTDOWN:
1640 ui->Print("Shutting down...\n"); 1669 ui->Print("Shutting down...\n");
1641 android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,"); 1670 android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,");
1642 break; 1671 break;
1643 1672
1644 case Device::REBOOT_BOOTLOADER: 1673 case Device::REBOOT_BOOTLOADER:
1645 ui->Print("Rebooting to bootloader...\n"); 1674 ui->Print("Rebooting to bootloader...\n");
1646 android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader"); 1675 android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader");
1647 break; 1676 break;
1648 1677
1649 default: 1678 default:
1650 ui->Print("Rebooting...\n"); 1679 ui->Print("Rebooting...\n");
1651 reboot("reboot,"); 1680 reboot("reboot,");
1652 break; 1681 break;
1653 } 1682 }
1654 while (true) { 1683 while (true) {
1655 pause(); 1684 pause();
1656 } 1685 }
1657 // Should be unreachable. 1686 // Should be unreachable.
1658 return EXIT_SUCCESS; 1687 return EXIT_SUCCESS;
1659} 1688}
diff --git a/updater/install.cpp b/updater/install.cpp
index a111f4b7..870b8579 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -569,7 +569,11 @@ Value* ApplyPatchSpaceFn(const char* name, State* state, const std::vector<std::
569 name, bytes_str.c_str()); 569 name, bytes_str.c_str());
570 } 570 }
571 571
572 return StringValue(CacheSizeCheck(bytes) ? "" : "t"); 572 // Skip the cache size check if the update is a retry.
573 if (state->is_retry || CacheSizeCheck(bytes) == 0) {
574 return StringValue("t");
575 }
576 return StringValue("");
573} 577}
574 578
575// apply_patch(src_file, tgt_file, tgt_sha1, tgt_size, patch1_sha1, patch1_blob, [...]) 579// apply_patch(src_file, tgt_file, tgt_sha1, tgt_size, patch1_sha1, patch1_blob, [...])