aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTao Bao2016-12-28 22:55:51 -0600
committerTao Bao2017-01-06 11:25:32 -0600
commit20c581e35dc441548ee2608456c55347007911e1 (patch)
treec77ada78e783d03d0e447a8ce01f1a6bfa1e45eb /install.cpp
parent91f74c82cd7518a0cbfb8239bbbc27190a1b112a (diff)
downloadplatform-bootable-recovery-20c581e35dc441548ee2608456c55347007911e1.tar.gz
platform-bootable-recovery-20c581e35dc441548ee2608456c55347007911e1.tar.xz
platform-bootable-recovery-20c581e35dc441548ee2608456c55347007911e1.zip
recovery: Clean up try_update_binary() in install.cpp.
Move functions over to android::base versions. - strtok(3) => android::base::Split() - strtol(3) => android::base::ParseInt() - strtof(3) => android::base::ParseDouble() Test: Build recovery image and apply a package that calls ui_print / progress / set_progress commands. Change-Id: I953b4985e0bd9e277362ae53e233d755cf27d80c
Diffstat (limited to 'install.cpp')
-rw-r--r--install.cpp311
1 files changed, 166 insertions, 145 deletions
diff --git a/install.cpp b/install.cpp
index b23586c6..008db4d8 100644
--- a/install.cpp
+++ b/install.cpp
@@ -14,6 +14,8 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include "install.h"
18
17#include <ctype.h> 19#include <ctype.h>
18#include <errno.h> 20#include <errno.h>
19#include <fcntl.h> 21#include <fcntl.h>
@@ -32,6 +34,7 @@
32 34
33#include <android-base/file.h> 35#include <android-base/file.h>
34#include <android-base/logging.h> 36#include <android-base/logging.h>
37#include <android-base/parsedouble.h>
35#include <android-base/parseint.h> 38#include <android-base/parseint.h>
36#include <android-base/stringprintf.h> 39#include <android-base/stringprintf.h>
37#include <android-base/strings.h> 40#include <android-base/strings.h>
@@ -40,7 +43,6 @@
40 43
41#include "common.h" 44#include "common.h"
42#include "error_code.h" 45#include "error_code.h"
43#include "install.h"
44#include "minui/minui.h" 46#include "minui/minui.h"
45#include "otautil/SysUtil.h" 47#include "otautil/SysUtil.h"
46#include "roots.h" 48#include "roots.h"
@@ -55,10 +57,10 @@ static constexpr const char* METADATA_PATH = "META-INF/com/android/metadata";
55static constexpr const char* UNCRYPT_STATUS = "/cache/recovery/uncrypt_status"; 57static constexpr const char* UNCRYPT_STATUS = "/cache/recovery/uncrypt_status";
56 58
57// Default allocation of progress bar segments to operations 59// Default allocation of progress bar segments to operations
58static const int VERIFICATION_PROGRESS_TIME = 60; 60static constexpr int VERIFICATION_PROGRESS_TIME = 60;
59static const float VERIFICATION_PROGRESS_FRACTION = 0.25; 61static constexpr float VERIFICATION_PROGRESS_FRACTION = 0.25;
60static const float DEFAULT_FILES_PROGRESS_FRACTION = 0.4; 62static constexpr float DEFAULT_FILES_PROGRESS_FRACTION = 0.4;
61static const float DEFAULT_IMAGE_PROGRESS_FRACTION = 0.1; 63static constexpr float DEFAULT_IMAGE_PROGRESS_FRACTION = 0.1;
62 64
63// This function parses and returns the build.version.incremental 65// This function parses and returns the build.version.incremental
64static int parse_build_number(const std::string& str) { 66static int parse_build_number(const std::string& str) {
@@ -299,149 +301,168 @@ update_binary_command(const char* path, ZipArchiveHandle zip, int retry_count,
299#endif // !AB_OTA_UPDATER 301#endif // !AB_OTA_UPDATER
300 302
301// If the package contains an update binary, extract it and run it. 303// If the package contains an update binary, extract it and run it.
302static int 304static int try_update_binary(const char* path, ZipArchiveHandle zip, bool* wipe_cache,
303try_update_binary(const char* path, ZipArchiveHandle zip, bool* wipe_cache, 305 std::vector<std::string>& log_buffer, int retry_count) {
304 std::vector<std::string>& log_buffer, int retry_count) 306 read_source_target_build(zip, log_buffer);
305{
306 read_source_target_build(zip, log_buffer);
307 307
308 int pipefd[2]; 308 int pipefd[2];
309 pipe(pipefd); 309 pipe(pipefd);
310 310
311 std::vector<std::string> args; 311 std::vector<std::string> args;
312 int ret = update_binary_command(path, zip, retry_count, pipefd[1], &args); 312 int ret = update_binary_command(path, zip, retry_count, pipefd[1], &args);
313 if (ret) { 313 if (ret) {
314 close(pipefd[0]); 314 close(pipefd[0]);
315 close(pipefd[1]);
316 return ret;
317 }
318
319 // When executing the update binary contained in the package, the
320 // arguments passed are:
321 //
322 // - the version number for this interface
323 //
324 // - an fd to which the program can write in order to update the
325 // progress bar. The program can write single-line commands:
326 //
327 // progress <frac> <secs>
328 // fill up the next <frac> part of of the progress bar
329 // over <secs> seconds. If <secs> is zero, use
330 // set_progress commands to manually control the
331 // progress of this segment of the bar.
332 //
333 // set_progress <frac>
334 // <frac> should be between 0.0 and 1.0; sets the
335 // progress bar within the segment defined by the most
336 // recent progress command.
337 //
338 // ui_print <string>
339 // display <string> on the screen.
340 //
341 // wipe_cache
342 // a wipe of cache will be performed following a successful
343 // installation.
344 //
345 // clear_display
346 // turn off the text display.
347 //
348 // enable_reboot
349 // packages can explicitly request that they want the user
350 // to be able to reboot during installation (useful for
351 // debugging packages that don't exit).
352 //
353 // - the name of the package zip file.
354 //
355 // - an optional argument "retry" if this update is a retry of a failed
356 // update attempt.
357 //
358
359 // Convert the vector to a NULL-terminated char* array suitable for execv.
360 const char* chr_args[args.size() + 1];
361 chr_args[args.size()] = NULL;
362 for (size_t i = 0; i < args.size(); i++) {
363 chr_args[i] = args[i].c_str();
364 }
365
366 pid_t pid = fork();
367
368 if (pid == -1) {
369 close(pipefd[0]);
370 close(pipefd[1]);
371 PLOG(ERROR) << "Failed to fork update binary";
372 return INSTALL_ERROR;
373 }
374
375 if (pid == 0) {
376 umask(022);
377 close(pipefd[0]);
378 execv(chr_args[0], const_cast<char**>(chr_args));
379 fprintf(stdout, "E:Can't run %s (%s)\n", chr_args[0], strerror(errno));
380 _exit(-1);
381 }
382 close(pipefd[1]); 315 close(pipefd[1]);
383 316 return ret;
384 *wipe_cache = false; 317 }
385 bool retry_update = false; 318
386 319 // When executing the update binary contained in the package, the
387 char buffer[1024]; 320 // arguments passed are:
388 FILE* from_child = fdopen(pipefd[0], "r"); 321 //
389 while (fgets(buffer, sizeof(buffer), from_child) != NULL) { 322 // - the version number for this interface
390 char* command = strtok(buffer, " \n"); 323 //
391 if (command == NULL) { 324 // - an FD to which the program can write in order to update the
392 continue; 325 // progress bar. The program can write single-line commands:
393 } else if (strcmp(command, "progress") == 0) { 326 //
394 char* fraction_s = strtok(NULL, " \n"); 327 // progress <frac> <secs>
395 char* seconds_s = strtok(NULL, " \n"); 328 // fill up the next <frac> part of of the progress bar
396 329 // over <secs> seconds. If <secs> is zero, use
397 float fraction = strtof(fraction_s, NULL); 330 // set_progress commands to manually control the
398 int seconds = strtol(seconds_s, NULL, 10); 331 // progress of this segment of the bar.
399 332 //
400 ui->ShowProgress(fraction * (1-VERIFICATION_PROGRESS_FRACTION), seconds); 333 // set_progress <frac>
401 } else if (strcmp(command, "set_progress") == 0) { 334 // <frac> should be between 0.0 and 1.0; sets the
402 char* fraction_s = strtok(NULL, " \n"); 335 // progress bar within the segment defined by the most
403 float fraction = strtof(fraction_s, NULL); 336 // recent progress command.
404 ui->SetProgress(fraction); 337 //
405 } else if (strcmp(command, "ui_print") == 0) { 338 // ui_print <string>
406 char* str = strtok(NULL, "\n"); 339 // display <string> on the screen.
407 if (str) { 340 //
408 ui->PrintOnScreenOnly("%s", str); 341 // wipe_cache
409 } else { 342 // a wipe of cache will be performed following a successful
410 ui->PrintOnScreenOnly("\n"); 343 // installation.
411 } 344 //
412 fflush(stdout); 345 // clear_display
413 } else if (strcmp(command, "wipe_cache") == 0) { 346 // turn off the text display.
414 *wipe_cache = true; 347 //
415 } else if (strcmp(command, "clear_display") == 0) { 348 // enable_reboot
416 ui->SetBackground(RecoveryUI::NONE); 349 // packages can explicitly request that they want the user
417 } else if (strcmp(command, "enable_reboot") == 0) { 350 // to be able to reboot during installation (useful for
418 // packages can explicitly request that they want the user 351 // debugging packages that don't exit).
419 // to be able to reboot during installation (useful for 352 //
420 // debugging packages that don't exit). 353 // retry_update
421 ui->SetEnableReboot(true); 354 // updater encounters some issue during the update. It requests
422 } else if (strcmp(command, "retry_update") == 0) { 355 // a reboot to retry the same package automatically.
423 retry_update = true; 356 //
424 } else if (strcmp(command, "log") == 0) { 357 // log <string>
425 // Save the logging request from updater and write to 358 // updater requests logging the string (e.g. cause of the
426 // last_install later. 359 // failure).
427 log_buffer.push_back(std::string(strtok(NULL, "\n"))); 360 //
428 } else { 361 // - the name of the package zip file.
429 LOG(ERROR) << "unknown command [" << command << "]"; 362 //
430 } 363 // - an optional argument "retry" if this update is a retry of a failed
431 } 364 // update attempt.
432 fclose(from_child); 365 //
433 366
434 int status; 367 // Convert the vector to a NULL-terminated char* array suitable for execv.
435 waitpid(pid, &status, 0); 368 const char* chr_args[args.size() + 1];
436 if (retry_update) { 369 chr_args[args.size()] = nullptr;
437 return INSTALL_RETRY; 370 for (size_t i = 0; i < args.size(); i++) {
438 } 371 chr_args[i] = args[i].c_str();
439 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { 372 }
440 LOG(ERROR) << "Error in " << path << " (Status " << WEXITSTATUS(status) << ")"; 373
441 return INSTALL_ERROR; 374 pid_t pid = fork();
442 } 375
443 376 if (pid == -1) {
444 return INSTALL_SUCCESS; 377 close(pipefd[0]);
378 close(pipefd[1]);
379 PLOG(ERROR) << "Failed to fork update binary";
380 return INSTALL_ERROR;
381 }
382
383 if (pid == 0) {
384 umask(022);
385 close(pipefd[0]);
386 execv(chr_args[0], const_cast<char**>(chr_args));
387 PLOG(ERROR) << "Can't run " << chr_args[0];
388 _exit(-1);
389 }
390 close(pipefd[1]);
391
392 *wipe_cache = false;
393 bool retry_update = false;
394
395 char buffer[1024];
396 FILE* from_child = fdopen(pipefd[0], "r");
397 while (fgets(buffer, sizeof(buffer), from_child) != nullptr) {
398 std::string line(buffer);
399 size_t space = line.find_first_of(" \n");
400 std::string command(line.substr(0, space));
401 if (command.empty()) continue;
402
403 // Get rid of the leading and trailing space and/or newline.
404 std::string args = space == std::string::npos ? "" : android::base::Trim(line.substr(space));
405
406 if (command == "progress") {
407 std::vector<std::string> tokens = android::base::Split(args, " ");
408 double fraction;
409 int seconds;
410 if (tokens.size() == 2 && android::base::ParseDouble(tokens[0].c_str(), &fraction) &&
411 android::base::ParseInt(tokens[1], &seconds)) {
412 ui->ShowProgress(fraction * (1 - VERIFICATION_PROGRESS_FRACTION), seconds);
413 } else {
414 LOG(ERROR) << "invalid \"progress\" parameters: " << line;
415 }
416 } else if (command == "set_progress") {
417 std::vector<std::string> tokens = android::base::Split(args, " ");
418 double fraction;
419 if (tokens.size() == 1 && android::base::ParseDouble(tokens[0].c_str(), &fraction)) {
420 ui->SetProgress(fraction);
421 } else {
422 LOG(ERROR) << "invalid \"set_progress\" parameters: " << line;
423 }
424 } else if (command == "ui_print") {
425 if (!args.empty()) {
426 ui->PrintOnScreenOnly("%s", args.c_str());
427 } else {
428 ui->PrintOnScreenOnly("\n");
429 }
430 fflush(stdout);
431 } else if (command == "wipe_cache") {
432 *wipe_cache = true;
433 } else if (command == "clear_display") {
434 ui->SetBackground(RecoveryUI::NONE);
435 } else if (command == "enable_reboot") {
436 // packages can explicitly request that they want the user
437 // to be able to reboot during installation (useful for
438 // debugging packages that don't exit).
439 ui->SetEnableReboot(true);
440 } else if (command == "retry_update") {
441 retry_update = true;
442 } else if (command == "log") {
443 if (!args.empty()) {
444 // Save the logging request from updater and write to last_install later.
445 log_buffer.push_back(args);
446 } else {
447 LOG(ERROR) << "invalid \"log\" parameters: " << line;
448 }
449 } else {
450 LOG(ERROR) << "unknown command [" << command << "]";
451 }
452 }
453 fclose(from_child);
454
455 int status;
456 waitpid(pid, &status, 0);
457 if (retry_update) {
458 return INSTALL_RETRY;
459 }
460 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
461 LOG(ERROR) << "Error in " << path << " (Status " << WEXITSTATUS(status) << ")";
462 return INSTALL_ERROR;
463 }
464
465 return INSTALL_SUCCESS;
445} 466}
446 467
447static int 468static int