static void wipe_data(int confirm) { if (confirm && !confirm_selection( "Confirm wipe of all user data?", "Yes - Wipe all user data")) return; ui_print("\n-- Wiping data...\n"); erase_volume("/cache"); ensure_path_mounted("/cache"); write_string_to_file(UBUNTU_COMMAND_FILE, "format data\n"); reboot_main_system(ANDROID_RB_RESTART2, 0, "recovery"); }
void show_advanced_menu() { static char* headers[] = { "Advanced Menu", "", NULL }; static char* list[] = { "reboot recovery", "reboot to bootloader", "power off", "wipe dalvik cache", "report error", "key test", "show log", "partition sdcard", "partition external sdcard", "partition internal sdcard", NULL }; char bootloader_mode[PROPERTY_VALUE_MAX]; property_get("ro.bootloader.mode", bootloader_mode, ""); if (!strcmp(bootloader_mode, "download")) { list[1] = "reboot to download mode"; } if (!can_partition("/sdcard")) { list[7] = NULL; } if (!can_partition("/external_sd")) { list[8] = NULL; } if (!can_partition("/emmc")) { list[9] = NULL; } for (;;) { int chosen_item = get_filtered_menu_selection(headers, list, 0, 0, sizeof(list) / sizeof(char*)); if (chosen_item == GO_BACK) break; switch (chosen_item) { case 0: { ui_print("Rebooting recovery...\n"); reboot_main_system(ANDROID_RB_RESTART2, 0, "recovery"); break; } case 1: { if (!strcmp(bootloader_mode, "download")) { ui_print("Rebooting to download mode...\n"); reboot_main_system(ANDROID_RB_RESTART2, 0, "download"); } else { ui_print("Rebooting to bootloader...\n"); reboot_main_system(ANDROID_RB_RESTART2, 0, "bootloader"); } break; } case 2: { ui_print("Shutting down...\n"); reboot_main_system(ANDROID_RB_POWEROFF, 0, 0); break; } case 3: if (0 != ensure_path_mounted("/data")) break; ensure_path_mounted("/sd-ext"); ensure_path_mounted("/cache"); if (confirm_selection( "Confirm wipe?", "Yes - Wipe Dalvik Cache")) { __system("rm -r /data/dalvik-cache"); __system("rm -r /cache/dalvik-cache"); __system("rm -r /sd-ext/dalvik-cache"); ui_print("Dalvik Cache wiped.\n"); } ensure_path_unmounted("/data"); break; case 4: handle_failure(1); break; case 5: { ui_print("Outputting key codes.\n"); ui_print("Go back to end debugging.\n"); int key; int action; do { key = ui_wait_key(); action = device_handle_key(key, 1); ui_print("Key: %d\n", key); } while (action != GO_BACK); break; } case 6: ui_printlogtail(12); break; case 7: partition_sdcard("/sdcard"); break; case 8: partition_sdcard("/external_sd"); break; case 9: partition_sdcard("/emmc"); break; } } }
int get_menu_selection(const char** headers, char** items, int menu_only, int initial_selection) { // throw away keys pressed previously, so user doesn't // accidentally trigger menu items. ui_clear_key_queue(); int item_count = ui_start_menu(headers, items, initial_selection); int selected = initial_selection; int chosen_item = -1; // NO_ACTION #ifdef NOT_ENOUGH_RAINBOWS int wrap_count = 0; #endif while (chosen_item < 0 && chosen_item != GO_BACK) { int key = ui_wait_key(); int visible = ui_IsTextVisible(); if (key == -1) { // ui_wait_key() timed out, always reboot to main system LOGI("timed out waiting for key input; rebooting.\n"); ui_end_menu(); reboot_main_system(ANDROID_RB_RESTART, 0, 0); sleep(5); LOGE("Failed to reboot system on timed out key input!!\n"); return GO_BACK; } else if (key == -2) { // we are returning from ui_cancel_wait_key(): trigger a GO_BACK return GO_BACK; } else if (key == -3) { // an USB device was plugged in (returning from ui_wait_key()) return REFRESH; } int action = ui_handle_key(key, visible); int old_selected = selected; selected = ui_get_selected_item(); if (action < 0) { switch (action) { case HIGHLIGHT_UP: --selected; selected = ui_menu_select(selected); break; case HIGHLIGHT_DOWN: ++selected; selected = ui_menu_select(selected); break; #ifdef PHILZ_TOUCH_RECOVERY case HIGHLIGHT_ON_TOUCH: selected = ui_menu_touch_select(); break; #endif case SELECT_ITEM: chosen_item = selected; if (ui_is_showing_back_button()) { if (chosen_item == item_count) { chosen_item = GO_BACK; } } break; case NO_ACTION: break; case GO_BACK: chosen_item = GO_BACK; break; #ifdef PHILZ_TOUCH_RECOVERY case GESTURE_ACTIONS: handle_gesture_actions(headers, items, initial_selection); break; #endif } } else if (!menu_only) { chosen_item = action; } #ifdef NOT_ENOUGH_RAINBOWS if (abs(selected - old_selected) > 1) { wrap_count++; if (wrap_count == 5) { wrap_count = 0; if (ui_get_rainbow_mode()) { ui_set_rainbow_mode(0); ui_print("Rainbow mode disabled\n"); } else { ui_set_rainbow_mode(1); ui_print("Rainbow mode enabled!\n"); } } } #endif } ui_end_menu(); ui_clear_key_queue(); return chosen_item; }
int main(int argc, char **argv) { time_t start = time(NULL); // If this binary is started with the single argument "--adbd", // instead of being the normal recovery binary, it turns into kind // of a stripped-down version of adbd that only supports the // 'sideload' command. Note this must be a real argument, not // anything in the command file or bootloader control block; the // only way recovery should be run with this argument is when it // starts a copy of itself from the apply_from_adb() function. if (argc == 2 && strcmp(argv[1], "--adbd") == 0) { adb_main(); return 0; } // Handle alternative invocations char* command = argv[0]; char* stripped = strrchr(argv[0], '/'); if (stripped) command = stripped + 1; if (strcmp(command, "recovery") != 0) { struct recovery_cmd cmd = get_command(command); if (cmd.name) return cmd.main_func(argc, argv); #ifdef BOARD_RECOVERY_HANDLES_MOUNT if (!strcmp(command, "mount") && argc == 2) { load_volume_table(); return ensure_path_mounted(argv[1]); } #endif if (!strcmp(command, "setup_adbd")) { load_volume_table(); setup_adbd(); return 0; } if (strstr(argv[0], "start")) { property_set("ctl.start", argv[1]); return 0; } if (strstr(argv[0], "stop")) { property_set("ctl.stop", argv[1]); return 0; } return busybox_driver(argc, argv); } // devices can run specific tasks on recovery start __system("/sbin/postrecoveryboot.sh"); // Clear umask for packages that copy files out to /tmp and then over // to /system without properly setting all permissions (eg. gapps). umask(0); // If these fail, there's not really anywhere to complain... freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL); freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL); printf("Starting recovery on %s", ctime(&start)); load_volume_table(); setup_data_media(1); vold_client_start(&v_callbacks, 0); vold_set_automount(1); setup_legacy_storage_paths(); ensure_path_mounted(LAST_LOG_FILE); rotate_last_logs(10); get_args(&argc, &argv); const char *send_intent = NULL; const char *update_package = NULL; int wipe_data = 0, wipe_cache = 0, wipe_media = 0, show_text = 0, sideload = 0; bool just_exit = false; bool shutdown_after = false; printf("Checking arguments.\n"); int arg; while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) { switch (arg) { case 's': send_intent = optarg; break; case 'u': update_package = optarg; break; case 'w': wipe_data = wipe_cache = 1; break; case 'm': wipe_media = 1; break; case 'c': wipe_cache = 1; break; case 't': show_text = 1; break; case 'x': just_exit = true; break; case 'a': sideload = 1; break; case 'p': shutdown_after = true; break; case 'g': { if (stage == NULL || *stage == '\0') { char buffer[20] = "1/"; strncat(buffer, optarg, sizeof(buffer)-3); stage = strdup(buffer); } break; } case '?': LOGE("Invalid command argument\n"); continue; } } printf("stage is [%s]\n", stage); device_ui_init(&ui_parameters); ui_init(); ui_print(EXPAND(RECOVERY_MOD_VERSION_BUILD) "\n"); ui_print("ClockworkMod " EXPAND(CWM_BASE_VERSION) "\n"); LOGI("Device target: " EXPAND(TARGET_COMMON_NAME) "\n"); #ifdef PHILZ_TOUCH_RECOVERY print_libtouch_version(0); #endif int st_cur, st_max; if (stage != NULL && sscanf(stage, "%d/%d", &st_cur, &st_max) == 2) { ui_SetStage(st_cur, st_max); } // ui_SetStage(5, 8); // debug if (show_text) ui_ShowText(true); struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "/file_contexts" } }; sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); if (!sehandle) { ui_print("Warning: No file_contexts\n"); } LOGI("device_recovery_start()\n"); device_recovery_start(); printf("Command:"); for (arg = 0; arg < argc; arg++) { printf(" \"%s\"", argv[arg]); } printf("\n"); if (update_package) { // For backwards compatibility on the cache partition only, if // we're given an old 'root' path "CACHE:foo", change it to // "/cache/foo". if (strncmp(update_package, "CACHE:", 6) == 0) { int len = strlen(update_package) + 10; char* modified_path = (char*)malloc(len); strlcpy(modified_path, "/cache/", len); strlcat(modified_path, update_package+6, len); printf("(replacing path \"%s\" with \"%s\")\n", update_package, modified_path); update_package = modified_path; } } printf("\n"); property_list(print_property, NULL); printf("\n"); int status = INSTALL_SUCCESS; if (update_package != NULL) { status = install_package(update_package, &wipe_cache, TEMPORARY_INSTALL_FILE); if (status == INSTALL_SUCCESS && wipe_cache) { if (erase_volume("/cache")) { LOGE("Cache wipe (requested by package) failed.\n"); } } if (status != INSTALL_SUCCESS) { ui_print("Installation aborted.\n"); // If this is an eng or userdebug build, then automatically // turn the text display on if the script fails so the error // message is visible. char buffer[PROPERTY_VALUE_MAX+1]; property_get("ro.build.fingerprint", buffer, ""); if (strstr(buffer, ":userdebug/") || strstr(buffer, ":eng/")) { ui_ShowText(true); } } } else if (wipe_data) { if (device_wipe_data()) status = INSTALL_ERROR; if (erase_volume("/data")) status = INSTALL_ERROR; if (has_datadata() && erase_volume("/datadata")) status = INSTALL_ERROR; if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) ui_print("Data wipe failed.\n"); } else if (wipe_cache) { if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) ui_print("Cache wipe failed.\n"); } else if (wipe_media) { if (is_data_media() && erase_volume("/data/media")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) ui_print("Media wipe failed.\n"); } else if (sideload) { status = enter_sideload_mode(status); } else if (!just_exit) { // let's check recovery start up scripts (openrecoveryscript and ROM Manager extendedcommands) status = INSTALL_NONE; // No command specified, it is a normal recovery boot unless we find a boot script to run LOGI("Checking for extendedcommand & OpenRecoveryScript...\n"); // we need show_text to show boot scripts log bool text_visible = ui_IsTextVisible(); ui_SetShowText(true); if (0 == check_boot_script_file(EXTENDEDCOMMAND_SCRIPT)) { LOGI("Running extendedcommand...\n"); status = INSTALL_ERROR; if (0 == run_and_remove_extendedcommand()) status = INSTALL_SUCCESS; } if (0 == check_boot_script_file(ORS_BOOT_SCRIPT_FILE)) { LOGI("Running openrecoveryscript....\n"); status = INSTALL_ERROR; if (0 == run_ors_boot_script()) status = INSTALL_SUCCESS; } ui_SetShowText(text_visible); } if (status == INSTALL_ERROR || status == INSTALL_CORRUPT) { copy_logs(); // ui_set_background(BACKGROUND_ICON_ERROR); // will be set in prompt_and_wait() after recovery lock check handle_failure(); } if (status != INSTALL_SUCCESS || ui_IsTextVisible()) { ui_SetShowText(true); #ifdef PHILZ_TOUCH_RECOVERY check_recovery_lock(); #endif prompt_and_wait(status); } // We reach here when in main menu we choose reboot main system or on success install of boot scripts and recovery commands finish_recovery(send_intent); if (shutdown_after) { ui_print("Shutting down...\n"); reboot_main_system(ANDROID_RB_POWEROFF, 0, 0); } else { ui_print("Rebooting...\n"); reboot_main_system(ANDROID_RB_RESTART, 0, 0); } return EXIT_SUCCESS; }
int main(int argc, char **argv) { if (argc == 2 && strcmp(argv[1], "adbd") == 0) { adb_main(); return 0; } // Recovery needs to install world-readable files, so clear umask // set by init umask(0); char* command = argv[0]; char* stripped = strrchr(argv[0], '/'); if (stripped) command = stripped + 1; if (strcmp(command, "recovery") != 0) { struct recovery_cmd cmd = get_command(command); if (cmd.name) return cmd.main_func(argc, argv); #ifdef BOARD_RECOVERY_HANDLES_MOUNT if (!strcmp(command, "mount") && argc == 2) { load_volume_table(); return ensure_path_mounted(argv[1]); } #endif if (!strcmp(command, "setup_adbd")) { load_volume_table(); setup_adbd(); return 0; } if (!strcmp(command, "start")) { property_set("ctl.start", argv[1]); return 0; } if (!strcmp(command, "stop")) { property_set("ctl.stop", argv[1]); return 0; } return busybox_driver(argc, argv); } //__system("/sbin/postrecoveryboot.sh"); int is_user_initiated_recovery = 0; time_t start = time(NULL); // If these fail, there's not really anywhere to complain... freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL); freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL); printf("Starting recovery on %s\n", ctime(&start)); device_ui_init(&ui_parameters); ui_init(); ui_print(EXPAND(RECOVERY_VERSION)"\n"); ui_print("Builder: "EXPAND(RECOVERY_BUILDER)"\n"); ui_print("Date: "EXPAND(RECOVERY_BUILD_TIME)"\n"); ui_print("weibo:@nx-baby\n"); __system("/sbin/postrecoveryboot.sh"); //#ifdef BOARD_RECOVERY_SWIPE //#ifndef BOARD_TOUCH_RECOVERY //display directions for swipe controls ui_print("Swipe up/down to change selections.\n"); ui_print("Swipe to the right for enter.\n"); ui_print("Swipe to the left for back.\n"); //#endif //#endif load_volume_table(); process_volumes(); vold_init(); setup_legacy_storage_paths(); #ifdef QCOM_HARDWARE parse_t_daemon_data_files(); apply_time_zone(); #endif LOGI("Processing arguments.\n"); ensure_path_mounted(LAST_LOG_FILE); rotate_last_logs(10); get_args(&argc, &argv); const char *send_intent = NULL; const char *update_package = NULL; int wipe_data = 0, wipe_cache = 0; int sideload = 0; int headless = 0; int shutdown_after = 0; LOGI("Checking arguments.\n"); int arg; while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) { switch (arg) { case 's': send_intent = optarg; break; case 'u': if (update_package == NULL) update_package = optarg; break; case 'w': #ifndef BOARD_RECOVERY_ALWAYS_WIPES wipe_data = wipe_cache = 1; #endif break; case 'h': ui_set_background(BACKGROUND_ICON_CID); ui_show_text(0); headless = 1; break; case 'c': wipe_cache = 1; break; case 't': ui_show_text(1); break; case 'l': sideload = 1; break; case 'p': shutdown_after = 1; break; case '?': LOGE("Invalid command argument\n"); continue; } } struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "/file_contexts" } }; sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); if (!sehandle) { fprintf(stderr, "Warning: No file_contexts\n"); //ui_print("Warning: No file_contexts\n"); } LOGI("device_recovery_start()\n"); device_recovery_start(); printf("Command:"); for (arg = 0; arg < argc; arg++) { printf(" \"%s\"", argv[arg]); } printf("\n"); if (update_package) { // For backwards compatibility on the cache partition only, if // we're given an old 'root' path "CACHE:foo", change it to // "/cache/foo". if (strncmp(update_package, "CACHE:", 6) == 0) { int len = strlen(update_package) + 10; char* modified_path = malloc(len); strlcpy(modified_path, "/cache/", len); strlcat(modified_path, update_package+6, len); printf("(replacing path \"%s\" with \"%s\")\n", update_package, modified_path); update_package = modified_path; } } printf("\n"); property_list(print_property, NULL); printf("\n"); int status = INSTALL_SUCCESS; if (update_package != NULL) { status = install_package(update_package); if (status != INSTALL_SUCCESS) { copy_logs(); ui_print("Installation aborted.\n"); } else if (!strcmp(TARGET_DEVICE, "A0001")) { //hack for a0001 ota if (strstr(update_package, "/.OTA/")) send_intent = "0"; } } else if (wipe_data) { if (device_wipe_data()) status = INSTALL_ERROR; preserve_data_media(0); if (erase_volume("/data")) status = INSTALL_ERROR; preserve_data_media(1); if (has_datadata() && erase_volume("/datadata")) status = INSTALL_ERROR; if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) { copy_logs(); ui_print("Data wipe failed.\n"); } } else if (wipe_cache) { if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) { copy_logs(); ui_print("Cache wipe failed.\n"); } } else { LOGI("Checking for extendedcommand...\n"); status = INSTALL_ERROR; // No command specified // we are starting up in user initiated recovery here // let's set up some default options signature_check_enabled = 0; is_user_initiated_recovery = 1; if (!headless) { ui_set_show_text(1); ui_set_background(BACKGROUND_ICON_CLOCKWORK); } if (extendedcommand_file_exists()) { LOGI("Running extendedcommand...\n"); int ret; if (0 == (ret = run_and_remove_extendedcommand())) { status = INSTALL_SUCCESS; ui_set_show_text(0); } else { handle_failure(ret); } } else { LOGI("Skipping execution of extendedcommand, file not found...\n"); } } if (sideload) { signature_check_enabled = 0; if (!headless) ui_set_show_text(1); if (0 == apply_from_adb()) { status = INSTALL_SUCCESS; ui_set_show_text(0); } } if (headless) { headless_wait(); } if (status != INSTALL_SUCCESS && !is_user_initiated_recovery) { ui_set_show_text(1); ui_set_background(BACKGROUND_ICON_ERROR); } else if (status != INSTALL_SUCCESS || ui_text_visible()) { prompt_and_wait(); } // We reach here when in main menu we choose reboot main system or for some wipe commands on start // If there is a radio image pending, reboot now to install it. maybe_install_firmware_update(send_intent); // Otherwise, get ready to boot the main system... finish_recovery(send_intent); if (shutdown_after) { ui_print("Shutting down...\n"); reboot_main_system(ANDROID_RB_POWEROFF, 0, 0); } else { ui_print("Rebooting...\n"); reboot_main_system(ANDROID_RB_RESTART, 0, 0); } return EXIT_SUCCESS; }
static int input_callback(int fd, short revents, void *data) { struct input_event ev; int ret; int fake_key = 0; ret = ev_get_input(fd, revents, &ev); if (ret) return -1; #ifdef BOARD_TOUCH_RECOVERY if (touch_handle_input(fd, ev)) return 0; #else #ifdef BOARD_RECOVERY_SWIPE swipe_handle_input(fd, &ev); #endif #endif if (ev.type == EV_SYN) { return 0; } else if (ev.type == EV_REL) { if (ev.code == REL_Y) { // accumulate the up or down motion reported by // the trackball. When it exceeds a threshold // (positive or negative), fake an up/down // key event. rel_sum += ev.value; if (rel_sum > 3) { fake_key = 1; ev.type = EV_KEY; ev.code = KEY_DOWN; ev.value = 1; rel_sum = 0; } else if (rel_sum < -3) { fake_key = 1; ev.type = EV_KEY; ev.code = KEY_UP; ev.value = 1; rel_sum = 0; } } } else { rel_sum = 0; } if (ev.type != EV_KEY || ev.code > KEY_MAX) return 0; if (ev.value == 2) { boardEnableKeyRepeat = 0; } pthread_mutex_lock(&key_queue_mutex); if (!fake_key) { // our "fake" keys only report a key-down event (no // key-up), so don't record them in the key_pressed // table. key_pressed[ev.code] = ev.value; } const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]); if (ev.value > 0 && key_queue_len < queue_max) { key_queue[key_queue_len++] = ev.code; if (boardEnableKeyRepeat) { struct timeval now; gettimeofday(&now, NULL); key_press_time[ev.code] = (now.tv_sec * 1000) + (now.tv_usec / 1000); key_last_repeat[ev.code] = 0; } pthread_cond_signal(&key_queue_cond); } pthread_mutex_unlock(&key_queue_mutex); if (ev.value > 0 && device_toggle_display(key_pressed, ev.code)) { pthread_mutex_lock(&gUpdateMutex); show_text = !show_text; if (show_text) show_text_ever = 1; update_screen_locked(); pthread_mutex_unlock(&gUpdateMutex); } if (ev.value > 0 && device_reboot_now(key_pressed, ev.code)) { reboot_main_system(ANDROID_RB_RESTART, 0, 0); } return 0; }
int main(int argc, char **argv) { if (argc == 2 && strcmp(argv[1], "adbd") == 0) { adb_main(); return 0; } // Recovery needs to install world-readable files, so clear umask // set by init umask(0); char* command = argv[0]; char* stripped = strrchr(argv[0], '/'); if (stripped) command = stripped + 1; if (strcmp(command, "recovery") != 0) { struct recovery_cmd cmd = get_command(command); if (cmd.name) return cmd.main_func(argc, argv); #ifdef BOARD_RECOVERY_HANDLES_MOUNT if (!strcmp(command, "mount") && argc == 2) { load_volume_table(); return ensure_path_mounted(argv[1]); } #endif if (!strcmp(command, "setup_adbd")) { load_volume_table(); setup_adbd(); return 0; } if (!strcmp(command, "start")) { property_set("ctl.start", argv[1]); return 0; } if (!strcmp(command, "stop")) { property_set("ctl.stop", argv[1]); return 0; } /* Make sure stdout is not fully buffered, we don't want to * have issues when calling busybox commands */ setlinebuf(stdout); return busybox_driver(argc, argv); } __system("/sbin/postrecoveryboot.sh"); int is_user_initiated_recovery = 0; time_t start = time(NULL); // If these fail, there's not really anywhere to complain... freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL); freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL); printf("Starting recovery on %s\n", ctime(&start)); device_ui_init(&ui_parameters); ui_init(); ui_print(EXPAND(RECOVERY_VERSION)"\n"); #ifdef BOARD_RECOVERY_SWIPE #ifndef BOARD_TOUCH_RECOVERY //display directions for swipe controls ui_print("Swipe up/down to change selections.\n"); ui_print("Swipe to the right for enter.\n"); ui_print("Swipe to the left for back.\n"); #endif #endif load_volume_table(); process_volumes(); vold_client_start(&v_callbacks, 0); vold_set_automount(1); setup_legacy_storage_paths(); LOGI("Processing arguments.\n"); ensure_path_mounted(LAST_LOG_FILE); rotate_last_logs(10); get_args(&argc, &argv); int previous_runs = 0; const char *send_intent = NULL; const char *update_package = NULL; const char *update_ubuntu_package = NULL; const char *user_data_update_package = NULL; int wipe_data = 0, wipe_cache = 0; int sideload = 0; int headless = 0; try_autodeploy(AUTODEPLOY_PACKAGE_FILE); try_autodeploy(AUTODEPLOY_PACKAGE_FILE_MULTI); LOGI("Checking arguments.\n"); int arg; while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) { switch (arg) { case 'p': previous_runs = atoi(optarg); break; case 's': send_intent = optarg; break; case 'u': update_package = optarg; break; case 'd': user_data_update_package = optarg; break; case 'w': #ifndef BOARD_RECOVERY_ALWAYS_WIPES wipe_data = wipe_cache = 1; #endif break; case 'h': ui_set_background(BACKGROUND_ICON_CID); ui_show_text(0); headless = 1; break; case 'c': wipe_cache = 1; break; case 't': ui_show_text(1); break; case 'l': sideload = 1; break; case 'v': update_ubuntu_package = UBUNTU_UPDATE_SCRIPT; break; case '?': LOGE("Invalid command argument\n"); continue; } } struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "/file_contexts" } }; sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); if (!sehandle) { fprintf(stderr, "Warning: No file_contexts\n"); ui_print("Warning: No file_contexts\n"); } LOGI("device_recovery_start()\n"); device_recovery_start(); printf("Command:"); for (arg = 0; arg < argc; arg++) { printf(" \"%s\"", argv[arg]); } printf("\n"); if (update_package) { // For backwards compatibility on the cache partition only, if // we're given an old 'root' path "CACHE:foo", change it to // "/cache/foo". if (strncmp(update_package, "CACHE:", 6) == 0) { int len = strlen(update_package) + 10; char* modified_path = malloc(len); strlcpy(modified_path, "/cache/", len); strlcat(modified_path, update_package+6, len); printf("(replacing path \"%s\" with \"%s\")\n", update_package, modified_path); update_package = modified_path; } } printf("\n"); property_list(print_property, NULL); printf("\n"); int status = INSTALL_SUCCESS; if (update_package != NULL) { status = install_package(update_package); if (status != INSTALL_SUCCESS) { copy_logs(); ui_print("Installation aborted.\n"); } } else if (update_ubuntu_package != NULL) { LOGI("Performing Ubuntu update"); ui_set_background(BACKGROUND_ICON_INSTALLING); ui_show_indeterminate_progress(); ui_print("Installing Ubuntu update.\n"); char tmp[PATH_MAX]; sprintf(tmp, "%s %s", UBUNTU_UPDATE_SCRIPT, UBUNTU_COMMAND_FILE ); __system(tmp); LOGI("Ubuntu update complete"); ui_print("Ubuntu update complete.\n"); } else if (wipe_data) { if (device_wipe_data()) status = INSTALL_ERROR; ignore_data_media_workaround(1); if (erase_volume("/data")) status = INSTALL_ERROR; ignore_data_media_workaround(0); if (has_datadata() && erase_volume("/datadata")) status = INSTALL_ERROR; if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) { copy_logs(); ui_print("Data wipe failed.\n"); } } else if (wipe_cache) { if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) { copy_logs(); ui_print("Cache wipe failed.\n"); } } else { LOGI("Checking for extendedcommand...\n"); status = INSTALL_ERROR; // No command specified // we are starting up in user initiated recovery here // let's set up some default options signature_check_enabled = 0; script_assert_enabled = 0; is_user_initiated_recovery = 1; if (!headless) { ui_set_show_text(1); ui_set_background(BACKGROUND_ICON_UBUNTU); } if (extendedcommand_file_exists()) { LOGI("Running extendedcommand...\n"); int ret; if (0 == (ret = run_and_remove_extendedcommand())) { status = INSTALL_SUCCESS; ui_set_show_text(0); } else { handle_failure(ret); } } else { LOGI("Skipping execution of extendedcommand, file not found...\n"); } } if (sideload) { signature_check_enabled = 0; if (!headless) ui_set_show_text(1); if (0 == apply_from_adb()) { status = INSTALL_SUCCESS; ui_set_show_text(0); } } if (headless) { headless_wait(); } if (user_data_update_package != NULL) { status = install_package(user_data_update_package); if (status != INSTALL_SUCCESS) ui_print("Installation aborted.\n"); } if (status != INSTALL_SUCCESS && !is_user_initiated_recovery) { ui_set_show_text(1); ui_set_background(BACKGROUND_ICON_ERROR); } else if (status != INSTALL_SUCCESS || ui_text_visible()) { prompt_and_wait(); } // We reach here when in main menu we choose reboot main system or for some wipe commands on start // If there is a radio image pending, reboot now to install it. maybe_install_firmware_update(send_intent); // Otherwise, get ready to boot the main system... finish_recovery(send_intent); ui_print("Rebooting...\n"); reboot_main_system(ANDROID_RB_RESTART, 0, 0); return EXIT_SUCCESS; }
int twrp_restore(const char* backup_path) { Backup_Size = 0; // by default, do not calculate size // progress bar will be of indeterminate progress // setting nandroid_files_total = 0 will force this in nandroid_callback() ui_set_background(BACKGROUND_ICON_INSTALLING); nandroid_files_total = 0; nandroid_start_msec = timenow_msec(); #ifdef PHILZ_TOUCH_RECOVERY // support dim screen timeout during nandroid operation last_key_ev = timenow_msec(); #endif if (ensure_path_mounted(backup_path) != 0) return print_and_error("Can't mount backup path\n", NANDROID_ERROR_GENERAL); char tmp[PATH_MAX]; if (enable_md5sum.value) { if (0 != check_twrp_md5sum(backup_path)) return print_and_error("MD5 mismatch!\n", NANDROID_ERROR_GENERAL); } ui_show_indeterminate_progress(); // call after verify_nandroid_md5sum() as it will reset the progress int ret; if (backup_boot && volume_for_path(BOOT_PARTITION_MOUNT_POINT) != NULL && 0 != (ret = nandroid_restore_partition(backup_path, BOOT_PARTITION_MOUNT_POINT))) return print_and_error(NULL, ret); if (backup_recovery && volume_for_path("/recovery") != NULL && 0 != (ret = nandroid_restore_partition(backup_path, "/recovery"))) return print_and_error(NULL, ret); #ifdef BOARD_USE_MTK_LAYOUT if ((backup_boot || backup_recovery) && volume_for_path("/uboot") != NULL && 0 != (ret = nandroid_restore_partition(backup_path, "/uboot"))) return print_and_error(NULL, ret); #endif Volume *vol = volume_for_path("/efs"); if (backup_efs == RESTORE_EFS_TAR && vol != NULL) { if (0 != (ret = nandroid_restore_partition(backup_path, "/efs"))) return print_and_error(NULL, ret); } vol = volume_for_path("/misc"); if (backup_misc && vol != NULL) { if (0 != (ret = nandroid_restore_partition(backup_path, "/misc"))) return print_and_error(NULL, ret); } vol = volume_for_path("/modem"); if (backup_modem == RAW_IMG_FILE && vol != NULL) { if (0 != (ret = nandroid_restore_partition(backup_path, "/modem"))) return print_and_error(NULL, ret); } vol = volume_for_path("/radio"); if (backup_radio == RAW_IMG_FILE && vol != NULL) { if (0 != (ret = nandroid_restore_partition(backup_path, "/radio"))) return print_and_error(NULL, ret); } if (backup_system && 0 != (ret = nandroid_restore_partition(backup_path, "/system"))) return print_and_error(NULL, ret); vol = volume_for_path("/preload"); if (backup_preload && vol != NULL) { if (0 != (ret = nandroid_restore_partition(backup_path, "/preload"))) return print_and_error(NULL, ret); } if (backup_data && 0 != (ret = nandroid_restore_partition(backup_path, "/data"))) return print_and_error(NULL, ret); if (has_datadata()) { if (backup_data && 0 != (ret = nandroid_restore_partition(backup_path, "/datadata"))) return print_and_error(NULL, ret); } // handle .android_secure on external and internal storage set_android_secure_path(tmp); if (backup_data && android_secure_ext) { if (0 != (ret = nandroid_restore_partition_extended(backup_path, tmp, 0))) return print_and_error(NULL, ret); } if (backup_cache && 0 != (ret = nandroid_restore_partition_extended(backup_path, "/cache", 0))) return print_and_error(NULL, ret); if (backup_sdext && 0 != (ret = nandroid_restore_partition(backup_path, "/sd-ext"))) return print_and_error(NULL, ret); // handle extra partitions int i; int extra_partitions_num = get_extra_partitions_state(); for (i = 0; i < extra_partitions_num; ++i) { if (extra_partition[i].backup_state && 0 != (ret = nandroid_restore_partition(backup_path, extra_partition[i].mount_point))) return print_and_error(NULL, ret); } finish_nandroid_job(); show_restore_stats(); if (reboot_after_nandroid) reboot_main_system(ANDROID_RB_RESTART, 0, 0); return 0; }
int twrp_backup(const char* backup_path) { // keep this for extra security and keep close to stock code // refresh_default_backup_handler() mounts /sdcard. We stat it in nandroid_backup_partition_extended() for callback nandroid_backup_bitfield = 0; refresh_default_backup_handler(); if (ensure_path_mounted(backup_path) != 0) return print_and_error("Can't mount backup path.\n", NANDROID_ERROR_GENERAL); int ret; struct statfs s; // refresh size stats for backup_path // this will also ensure volume for backup path != NULL if (0 != Get_Size_Via_statfs(backup_path)) return print_and_error("Unable to stat backup path.\n", NANDROID_ERROR_GENERAL); // estimate backup size and ensure we have enough free space available on backup_path if (check_backup_size(backup_path) < 0) return print_and_error("Not enough free space: backup cancelled.\n", NANDROID_ERROR_GENERAL); // moved after backup size check to fix pause before showing low space prompt // this is caused by friendly log view triggering on ui_set_background(BACKGROUND_ICON_INSTALLING) call // also, it is expected to have the background installing icon when we actually start backup ui_set_background(BACKGROUND_ICON_INSTALLING); nandroid_start_msec = timenow_msec(); // starts backup monitoring timer for total backup time #ifdef PHILZ_TOUCH_RECOVERY last_key_ev = nandroid_start_msec; // support dim screen timeout during nandroid operation #endif char tmp[PATH_MAX]; ensure_directory(backup_path, 0755); if (backup_boot && volume_for_path(BOOT_PARTITION_MOUNT_POINT) != NULL && 0 != (ret = nandroid_backup_partition(backup_path, BOOT_PARTITION_MOUNT_POINT))) return print_and_error(NULL, ret); if (backup_recovery && volume_for_path("/recovery") != NULL && 0 != (ret = nandroid_backup_partition(backup_path, "/recovery"))) return print_and_error(NULL, ret); #ifdef BOARD_USE_MTK_LAYOUT if ((backup_boot || backup_recovery) && volume_for_path("/uboot") != NULL && 0 != (ret = nandroid_backup_partition(backup_path, "/uboot"))) return print_and_error(NULL, ret); #endif Volume *vol = volume_for_path("/efs"); if (backup_efs && NULL != vol) { if (0 != (ret = nandroid_backup_partition(backup_path, "/efs"))) return print_and_error(NULL, ret); } vol = volume_for_path("/misc"); if (backup_misc && NULL != vol) { if (0 != (ret = nandroid_backup_partition(backup_path, "/misc"))) return print_and_error(NULL, ret); } vol = volume_for_path("/modem"); if (backup_modem && NULL != vol) { if (0 != (ret = nandroid_backup_partition(backup_path, "/modem"))) return print_and_error(NULL, ret); } vol = volume_for_path("/radio"); if (backup_radio && NULL != vol) { if (0 != (ret = nandroid_backup_partition(backup_path, "/radio"))) return print_and_error(NULL, ret); } if (backup_system && 0 != (ret = nandroid_backup_partition(backup_path, "/system"))) return print_and_error(NULL, ret); vol = volume_for_path("/preload"); if (backup_preload && NULL != vol) { if (0 != (ret = nandroid_backup_partition(backup_path, "/preload"))) return print_and_error(NULL, ret); } if (backup_data && 0 != (ret = nandroid_backup_partition(backup_path, "/data"))) return print_and_error(NULL, ret); if (has_datadata()) { if (backup_data && 0 != (ret = nandroid_backup_partition(backup_path, "/datadata"))) return print_and_error(NULL, ret); } // handle .android_secure on external and internal storage set_android_secure_path(tmp); if (backup_data && android_secure_ext) { if (0 != (ret = nandroid_backup_partition_extended(backup_path, tmp, 0))) return print_and_error(NULL, ret); } if (backup_cache && 0 != (ret = nandroid_backup_partition_extended(backup_path, "/cache", 0))) return print_and_error(NULL, ret); if (backup_sdext) { if (0 != ensure_path_mounted("/sd-ext")) { LOGI("No sd-ext found. Skipping backup of sd-ext.\n"); } else if (0 != (ret = nandroid_backup_partition(backup_path, "/sd-ext"))) { return print_and_error(NULL, ret); } } // handle extra partitions int i; int extra_partitions_num = get_extra_partitions_state(); for (i = 0; i < extra_partitions_num; ++i) { if (extra_partition[i].backup_state && 0 != (ret = nandroid_backup_partition(backup_path, extra_partition[i].mount_point))) return print_and_error(NULL, ret); } if (enable_md5sum.value) { if (0 != (ret = gen_twrp_md5sum(backup_path))) return print_and_error(NULL, ret); } sprintf(tmp, "chmod -R 777 %s", backup_path); __system(tmp); finish_nandroid_job(); show_backup_stats(backup_path); if (reboot_after_nandroid) reboot_main_system(ANDROID_RB_RESTART, 0, 0); return 0; }
static int input_callback(int fd, short revents, void *data) { struct input_event ev; int ret; int fake_key = 0; ret = ev_get_input(fd, revents, &ev); if (ret) return -1; input_device dev; dev.fd = fd; if(!dev.touch_calibrated) dev.touch_calibrated = calibrate_touch(&dev); if (ev.type == EV_SYN) { if (ev.code == SYN_MT_REPORT) { dev.saw_mt_report = 1; if (!dev.saw_mt_tracking_id) { if (dev.saw_pos_x && dev.saw_pos_y) { dev.saw_pos_x = 0; dev.saw_pos_y = 0; } else handle_release(&dev, &ev); } } } else if (ev.type == EV_REL) { if (ev.code == REL_Y) { // accumulate the up or down motion reported by // the trackball. When it exceeds a threshold // (positive or negative), fake an up/down // key event. rel_sum += ev.value; if (rel_sum > 3) { fake_key = 1; ev.type = EV_KEY; ev.code = KEY_DOWN; ev.value = 1; rel_sum = 0; } else if (rel_sum < -3) { fake_key = 1; ev.type = EV_KEY; ev.code = KEY_UP; ev.value = 1; rel_sum = 0; } } } else if (ev.type == EV_ABS) { switch(ev.code){ case ABS_MT_SLOT: dev.slot_current = ev.value; break; case ABS_MT_TRACKING_ID: dev.saw_mt_tracking_id = 1; dev.tracking_id = ev.value; if (dev.tracking_id == -1 && dev.slot_current == 0) handle_release(&dev, &ev); break; case ABS_MT_POSITION_X: dev.saw_pos_x = 1; if (dev.slot_current != 0) break; if(dev.touch_start.x == 0) dev.touch_start.x = dev.touch_pos.x; float touch_rel = (float)ev.value / ((float)dev.touch_max.x - (float)dev.touch_min.x); dev.touch_pos.x = touch_rel * gr_fb_width(); if (dev.touch_start.x == 0) break; //first touch. diff_x += dev.touch_pos.x - dev.touch_start.x; if (abs(diff_x) > abs(diff_y) && dev.touch_pos.y < (gr_fb_height() - virtualkey_h)) { if(diff_x > min_x_swipe_px) { dev.slide_right = 1; } else if (diff_x < -min_x_swipe_px) { dev.slide_left = 1; } } break; case ABS_MT_POSITION_Y: dev.saw_pos_y = 1; if (dev.slot_current != 0) break; if(dev.touch_start.y == 0) dev.touch_start.y = dev.touch_pos.y; touch_rel = (float)ev.value / ((float)dev.touch_max.y - (float)dev.touch_min.y); dev.touch_pos.y = touch_rel * gr_fb_height(); #ifdef USE_VIRTUAL_KEY ui_get_virtualkey_pressed(&dev); #endif if (dev.touch_start.y == 0) break; //first touch. diff_y += dev.touch_pos.y - dev.touch_start.y; if (abs(diff_y) >= abs(diff_x) && dev.touch_pos.y < (gr_fb_height() - virtualkey_h)) { if (diff_y > min_y_swipe_px) { ev.type = EV_KEY; ev.code = KEY_VOLUMEDOWN; ev.value = 2; reset_touch(&dev); } else if (diff_y < -min_y_swipe_px) { ev.type = EV_KEY; ev.code = KEY_VOLUMEUP; ev.value = 2; reset_touch(&dev); } } break; default: break; } } else if (ev.type == EV_KEY) { if (dev.saw_mt_report && dev.saw_mt_tracking_id && ev.code == BTN_TOUCH && ev.value == 0) handle_release(&dev, &ev); } else { rel_sum = 0; } if (ev.type != EV_KEY || ev.code > KEY_MAX) return 0; if (ev.value == 2) { boardEnableKeyRepeat = 0; } pthread_mutex_lock(&key_queue_mutex); if (!fake_key) { // our "fake" keys only report a key-down event (no // key-up), so don't record them in the key_pressed // table. key_pressed[ev.code] = ev.value; } const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]); if (ev.value > 0 && key_queue_len < queue_max) { key_queue[key_queue_len++] = ev.code; if (boardEnableKeyRepeat) { struct timeval now; gettimeofday(&now, NULL); key_press_time[ev.code] = (now.tv_sec * 1000) + (now.tv_usec / 1000); key_last_repeat[ev.code] = 0; } pthread_cond_signal(&key_queue_cond); } pthread_mutex_unlock(&key_queue_mutex); if (ev.value > 0 && device_reboot_now(key_pressed, ev.code)) { reboot_main_system(ANDROID_RB_RESTART, 0, 0); } return 0; }