admin 管理员组

文章数量: 887021


2024年1月5日发(作者:随机数生成器破解版)

private boolean setupOrClearBcb(boolean isSetup, String command) { eCallingOrSelfPermission(RY, null); final boolean available = checkAndWaitForUncryptService(); if (!available) { Slog.e(TAG, "uncrypt service is unavailable."); return false; } //设置属性,启动setup-bcb服务 if (isSetup) { ("", "setup-bcb"); } else { ("", "clear-bcb"); } // Connect to the uncrypt service socket. // 连接uncrypt服务 LocalSocket socket = connectService(); if (socket == null) { Slog.e(TAG, "Failed to connect to uncrypt socket"); return false; } DataInputStream dis = null; DataOutputStream dos = null; try { dis = new DataInputStream(utStream()); dos = new DataOutputStream(putStream()); // Send the BCB commands if it's to setup BCB. // 发送BCB commands if (isSetup) { byte[] cmdUtf8 = es("UTF-8"); nt(); (cmdUtf8, 0, ); (); } // Read the status from the socket. int status = t(); // Ack receipt of the status code. uncrypt waits for the ack so // the socket won't be destroyed before we receive the code. nt(0); if (status == 100) { Slog.i(TAG, "uncrypt " + (isSetup ? "setup" : "clear") + " bcb successfully finished."); } else { // Error in /system/bin/uncrypt. Slog.e(TAG, "uncrypt failed with status: " + status); return false; } } catch (IOException e) { Slog.e(TAG, "IOException when communicating with uncrypt:", e); return false; } finally { uietly(dis); uietly(dos); uietly(socket); } return true; }

private static void beginShutdownSequence(Context context) { synchronized (sIsStartedGuard) { if (sIsStarted) { Log.d(TAG, "Shutdown sequence already running, returning."); return; } sIsStarted = true; } essDialog = showShutdownDialog(context); xt = context; Manager = (PowerManager)temService(_SERVICE); // make sure we never fall asleep again keLock = null; try { keLock = eLock( L_WAKE_LOCK, TAG + "-cpu"); erenceCounted(false); e(); } catch (SecurityException e) { Log.w(TAG, "No permission to acquire wake lock", e); keLock = null; } // also make sure the screen stays on for better user experience nWakeLock = null; if (enOn()) { try { nWakeLock = eLock( _WAKE_LOCK, TAG + "-screen"); erenceCounted(false); e(); } catch (SecurityException e) { Log.w(TAG, "No permission to acquire wake lock", e); nWakeLock = null; } } if (ingEnabled()) { vent(_OS_SHUTDOWN); } // start the thread that initiates shutdown er = new Handler() { }; //启动线程 (); }2.10.1 utdownDialog[->]private static ProgressDialog showShutdownDialog(Context context) { // Throw up a system dialog to indicate the device is rebooting / shutting down. ProgressDialog pd = new ProgressDialog(context); // Path 1: Reboot to recovery for update // Condition: mReason startswith REBOOT_RECOVERY_UPDATE // // Path 1a: uncrypt needed // Condition: if /cache/recovery/uncrypt_file exists but // /cache/recovery/ doesn't. // UI: determinate progress bar (mRebootHasProgressBar == True) //

(); return pd; }2.11 [->] /** * Makes sure we handle the shutdown gracefully. * Shuts off power regardless of radio state if the allotted time has passed. */ public void run() { TimingsTraceLog shutdownTimingLog = newTimingsLog(); egin("SystemServerShutdown"); metricShutdownStart(); metricStarted(METRIC_SYSTEM_SERVER); BroadcastReceiver br = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // We don't allow apps to cancel this, so ignore the result. actionDone(); } }; /* * Write a system property in case the system_server reboots before we * get to the actual hardware restart. If that happens, we'll retry at * the beginning of the SystemServer startup. */ { String reason = (mReboot ? "1" : "0") + (mReason != null ? mReason : ""); (SHUTDOWN_ACTION_PROPERTY, reason); } /* * If we are rebooting into safe mode, write a system property * indicating so. */ if (mRebootSafeMode) { (REBOOT_SAFEMODE_PROPERTY, "1"); } metricStarted(METRIC_SEND_BROADCAST); egin("SendShutdownBroadcast"); Log.i(TAG, "Sending "); // First send the high-level shut down broadcast. mActionDone = false; Intent intent = new Intent(_SHUTDOWN); gs(_RECEIVER_FOREGROUND | _RECEIVER_REGISTERED_ONLY); deredBroadcastAsUser(intent, , null, br, mHandler, 0, null, null); final long endTime = dRealtime() + MAX_BROADCAST_TIME; synchronized (mActionDoneSync) { while (!mActionDone) { long delay = endTime - dRealtime(); if (delay <= 0) { Log.w(TAG, "Shutdown broadcast timed out"); break; } else if (mRebootHasProgressBar) { int status = (int)((MAX_BROADCAST_TIME - delay) * 1.0 * BROADCAST_STOP_PERCENT / MAX_BROADCAST_TIME); ootProgress(status, null);

nd(); // SystemServerShutdown metricEnded(METRIC_SYSTEM_SERVER); saveMetrics(mReboot, mReason); // Remaining work will be done by init, including vold shutdown rebootOrShutdown(mContext, mReboot, mReason); }2.12 t[->]

private void uncrypt() { Log.i(TAG, "Calling uncrypt and monitoring "); final ssListener progressListener = new ssListener() { @Override public void onProgress(int status) { if (status >= 0 && status < 100) { // Scale down to [MOUNT_SERVICE_STOP_PERCENT, 100). status = (int)(status * (100.0 - MOUNT_SERVICE_STOP_PERCENT) / 100); status += MOUNT_SERVICE_STOP_PERCENT; CharSequence msg = t( _to_update_package); ootProgress(status, msg); } else if (status == 100) { CharSequence msg = t( _to_update_reboot); ootProgress(status, msg); } else { // Ignored } } }; final boolean[] done = new boolean[1]; done[0] = false; Thread t = new Thread() { @Override public void run() { RecoverySystem rs = (RecoverySystem) temService( RY_SERVICE); String filename = null; try { filename = xtFile(T_PACKAGE_FILE, 0, null); sPackage(mContext, new File(filename), progressListener); } catch (IOException e) { Log.e(TAG, "Error uncrypting file", e); } done[0] = true; } }; (); try { (MAX_UNCRYPT_WAIT_TIME); } catch (InterruptedException unused) { } if (!done[0]) { Log.w(TAG, "Timed out waiting for uncrypt."); final int uncryptTimeoutError = 100; String timeoutMessage = ("uncrypt_time: %d/n" + "uncrypt_error: %d/n", MAX_UNCRYPT_WAIT_TIME / 1000, uncryptTimeoutError); try { ToFile(T_STATUS_FILE, timeoutMessage); } catch (IOException e) { Log.e(TAG, "Failed to write timeout message to uncrypt status", e); } } }2.13 sPackage[->]

public boolean uncrypt(String filename, IRecoverySystemProgressListener listener) { if (DEBUG) Slog.d(TAG, "uncrypt: " + filename); synchronized (sRequestLock) { eCallingOrSelfPermission(RY, null); final boolean available = checkAndWaitForUncryptService(); if (!available) { Slog.e(TAG, "uncrypt service is unavailable."); return false; } // Write the filename into UNCRYPT_PACKAGE_FILE to be read by // uncrypt. T_PACKAGE_(); try (FileWriter uncryptFile = new FileWriter(T_PACKAGE_FILE)) { (filename + "/n"); } catch (IOException e) { Slog.e(TAG, "IOException when writing /"" + T_PACKAGE_FILE + "/":", e); return false; } // Trigger uncrypt via init. //通过设置属性,开启uncrypt服务 ("", "uncrypt"); // Connect to the uncrypt service socket. //连接服务 LocalSocket socket = connectService(); if (socket == null) { Slog.e(TAG, "Failed to connect to uncrypt socket"); return false; } // Read the status from the socket. DataInputStream dis = null; DataOutputStream dos = null; try { dis = new DataInputStream(utStream()); dos = new DataOutputStream(putStream()); int lastStatus = _VALUE; while (true) { // 读取进度 int status = t(); // Avoid flooding the log with the same message. if (status == lastStatus && lastStatus != _VALUE) { continue; } lastStatus = status; if (status >= 0 && status <= 100) { // Update status Slog.i(TAG, "uncrypt read status: " + status); if (listener != null) { try { ress(status); } catch (RemoteException ignored) { Slog.w(TAG, "RemoteException when posting progress"); } } if (status == 100) { Slog.i(TAG, "uncrypt successfully finished."); // Ack receipt of the final status code. uncrypt

// 49652 4096 # file size in bytes, block size// 3 # count of block ranges// 1000 1008 # block range 0// 2100 2102 # ... block range 1// 30 33 # ... block range 2//// Each block range represents a half-open interval; the line "30 33"// reprents the blocks [30, 31, 32].//// Recovery can take this block map file and retrieve the underlying// file data to use as an update package./** * In addition to the uncrypt work, uncrypt also takes care of setting and * clearing the bootloader control block (BCB) at /misc partition. * * uncrypt is triggered as init services on demand. It uses socket to * communicate with its caller (i.e. system_server). The socket is managed by * init (i.e. created prior to the service starts, and destroyed when uncrypt * exits). * * Below is the uncrypt protocol. * * a. caller b. init c. uncrypt * --------------- ------------ -------------- * a1. : * setup-bcb / * clear-bcb / * uncrypt * * b2. create socket at * /dev/socket/uncrypt * * c3. listen and accept * * a4. send a 4-byte int * (message length) * c5. receive message length * a6. send message * c7. receive message * c8. * a9. * c10. * send "100" or "-1" * * a11. receive status code * a12. send a 4-byte int to * ack the receive of the * final status code * c13. receive and exit * * b14. destroy the socket * * Note that a12 and c13 are necessary to ensure a11 happens before the socket * gets destroyed in b14. */int main(int argc, char** argv) { enum { UNCRYPT, SETUP_BCB, CLEAR_BCB, UNCRYPT_DEBUG } action; const char* input_path = nullptr; const char* map_file = CACHE_BLOCK_MAP.c_str(); //解析参数 if (argc == 2 && strcmp(argv[1], "--clear-bcb") == 0) { action = CLEAR_BCB;

} else if (argc == 2 && strcmp(argv[1], "--setup-bcb") == 0) { action = SETUP_BCB; } else if (argc == 1) { action = UNCRYPT; } else if (argc == 3) { input_path = argv[1]; map_file = argv[2]; action = UNCRYPT_DEBUG; } else { usage(argv[0]); return 2; } if ((fstab = read_fstab()) == nullptr) { log_uncrypt_error_code(kUncryptFstabReadError); return 1; } if (action == UNCRYPT_DEBUG) { LOG(INFO) << "uncrypt called in debug mode, skip socket communication"; bool success = uncrypt_wrapper(input_path, map_file, -1); if (success) { LOG(INFO) << "uncrypt succeeded"; } else{ LOG(INFO) << "uncrypt failed"; } return success ? 0 : 1; } // c3. The socket is created by init when starting the service. uncrypt // will use the socket to communicate with its caller. android::base::unique_fd service_socket(android_get_control_socket(UNCRYPT_SOCKET.c_str())); if (service_socket == -1) { PLOG(ERROR) << "failed to open socket /"" << UNCRYPT_SOCKET << "/""; log_uncrypt_error_code(kUncryptSocketOpenError); return 1; } fcntl(service_socket, F_SETFD, FD_CLOEXEC); if (listen(service_socket, 1) == -1) { PLOG(ERROR) << "failed to listen on socket " << service_(); log_uncrypt_error_code(kUncryptSocketListenError); return 1; } android::base::unique_fd socket_fd(accept4(service_socket, nullptr, nullptr, SOCK_CLOEXEC)); if (socket_fd == -1) { PLOG(ERROR) << "failed to accept on socket " << service_(); log_uncrypt_error_code(kUncryptSocketAcceptError); return 1; } bool success = false; switch (action) { //UNCRYPT操作 case UNCRYPT: success = uncrypt_wrapper(input_path, map_file, socket_fd); break; case SETUP_BCB: success = setup_bcb(socket_fd); break; case CLEAR_BCB: success = clear_bcb(socket_fd); break; default: // Should never happen. LOG(ERROR) << "Invalid uncrypt action code: " << action;

while (pos < _size) { // Update the status file, progress must be between [0, 99]. int progress = static_cast(100 * (double(pos) / double(_size))); if (progress > last_progress) { last_progress = progress; write_status_to_socket(progress, socket); } if ((tail+1) % WINDOW_SIZE == head) { // write out head buffer int block = head_block; if (ioctl(fd, FIBMAP, &block) != 0) { PLOG(ERROR) << "failed to find block " << head_block; return kUncryptIoctlError; } if (block == 0) { LOG(ERROR) << "failed to find block " << head_block << ", retrying"; int error = retry_fibmap(fd, path, &block, head_block); if (error != kUncryptNoError) { return error; } } add_block_to_ranges(ranges, block); //data分区是否加密 if (encrypted) { if (write_at_offset(buffers[head].data(), _blksize, wfd, static_cast(_blksize) * block) != 0) { return kUncryptWriteError; } } head = (head + 1) % WINDOW_SIZE; ++head_block; } // read next block to tail // data分区加密 if (encrypted) { size_t to_read = static_cast( std::min(static_cast(_blksize), _size - pos)); if (!android::base::ReadFully(fd, buffers[tail].data(), to_read)) { PLOG(ERROR) << "failed to read " << path; return kUncryptReadError; } pos += to_read; } else { // If we're not encrypting; we don't need to actually read // anything, just skip pos forward as if we'd read a // block. pos += _blksize; } tail = (tail+1) % WINDOW_SIZE; } while (head != tail) { // write out head buffer int block = head_block; if (ioctl(fd, FIBMAP, &block) != 0) { PLOG(ERROR) << "failed to find block " << head_block; return kUncryptIoctlError; } if (block == 0) { LOG(ERROR) << "failed to find block " << head_block << ", retrying"; int error = retry_fibmap(fd, path, &block, head_block);

int error = retry_fibmap(fd, path, &block, head_block); if (error != kUncryptNoError) { return error; } } add_block_to_ranges(ranges, block); //data分区是否加密 if (encrypted) { if (write_at_offset(buffers[head].data(), _blksize, wfd, static_cast(_blksize) * block) != 0) { return kUncryptWriteError; } } head = (head + 1) % WINDOW_SIZE; ++head_block; } if (!android::base::WriteStringToFd( android::base::StringPrintf("%zu/n", () / 2), mapfd)) { PLOG(ERROR) << "failed to write " << tmp_map_file; return kUncryptWriteError; } for (size_t i = 0; i < (); i += 2) { if (!android::base::WriteStringToFd( android::base::StringPrintf("%d %d/n", ranges[i], ranges[i+1]), mapfd)) { PLOG(ERROR) << "failed to write " << tmp_map_file; return kUncryptWriteError; } } if (fsync(mapfd) == -1) { PLOG(ERROR) << "failed to fsync /"" << tmp_map_file << "/""; return kUncryptFileSyncError; } if (close(e()) == -1) { PLOG(ERROR) << "failed to close " << tmp_map_file; return kUncryptFileCloseError; } if (encrypted) { if (fsync(wfd) == -1) { PLOG(ERROR) << "failed to fsync /"" << blk_dev << "/""; return kUncryptFileSyncError; } if (close(e()) == -1) { PLOG(ERROR) << "failed to close " << blk_dev; return kUncryptFileCloseError; } } if (rename(tmp_map_file.c_str(), map_file) == -1) { PLOG(ERROR) << "failed to rename " << tmp_map_file << " to " << map_file; return kUncryptFileRenameError; } // Sync dir to make rename() result written to disk. std::string file_name = map_file; std::string dir_name = dirname(&file_name[0]); android::base::unique_fd dfd(open(dir_name.c_str(), O_RDONLY | O_DIRECTORY)); if (dfd == -1) { PLOG(ERROR) << "failed to open dir " << dir_name; return kUncryptFileOpenError; } if (fsync(dfd) == -1) { PLOG(ERROR) << "failed to fsync " << dir_name; return kUncryptFileSyncError;

sizeof(y_panel));#endif#if ENABLE_WBC /* Wait if the display shutdown is in progress */ while(pm_app_display_shutdown_in_prgs()); if (!pm_appsbl_display_init_done()) target_display_init(y_panel); else display_image_on_screen();#else target_display_init(y_panel);#endif dprintf(SPEW, "Display Init: Done/n");#if NO_ALARM_DISPLAY }#endif#endif target_serialno((unsigned char *) sn_buf); dprintf(SPEW,"serial number: %s/n",sn_buf); memset(display_panel_buf, '/0', MAX_PANEL_BUF_SIZE); /* * Check power off reason if user force reset, * if yes phone will do normal boot. */ if (is_user_force_reset()) goto normal_boot; /* Check if we should do something other than booting up */ if (keys_get_state(KEY_VOLUMEUP) && keys_get_state(KEY_VOLUMEDOWN)) { dprintf(ALWAYS,"dload mode key sequence detected/n"); reboot_device(EMERGENCY_DLOAD); dprintf(CRITICAL,"Failed to reboot into dload mode/n"); boot_into_fastboot = true; } if (!boot_into_fastboot) { if (keys_get_state(KEY_HOME) || keys_get_state(KEY_VOLUMEUP)) boot_into_recovery = 1; if (!boot_into_recovery && (keys_get_state(KEY_BACK) || keys_get_state(KEY_VOLUMEDOWN))) boot_into_fastboot = true; } #if NO_KEYPAD_DRIVER if (fastboot_trigger()) boot_into_fastboot = true; #endif#if USE_PON_REBOOT_REG reboot_mode = check_hard_reboot_mode();#else reboot_mode = check_reboot_mode();#endif if (reboot_mode == RECOVERY_MODE) { boot_into_recovery = 1; } else if(reboot_mode == FASTBOOT_MODE) { boot_into_fastboot = true; } else if(reboot_mode == ALARM_BOOT)

else if(reboot_mode == ALARM_BOOT) { boot_reason_alarm = true; }#if VERIFIED_BOOT || VERIFIED_BOOT_2 else if (VB_M <= target_get_vb_version()) { if (reboot_mode == DM_VERITY_ENFORCING) { _mode = 1; write_device_info(&device); }#if ENABLE_VB_ATTEST else if (reboot_mode == DM_VERITY_EIO)#else else if (reboot_mode == DM_VERITY_LOGGING)#endif { _mode = 0; write_device_info(&device); } else if (reboot_mode == DM_VERITY_KEYSCLEAR) { if(send_delete_keys_to_tz()) ASSERT(0); } }#endifnormal_boot: if (!boot_into_fastboot) { if (target_is_emmc_boot()) { if(emmc_recovery_init()) dprintf(ALWAYS,"error in emmc_recovery_init/n"); if(target_use_signed_kernel()) { if((_unlocked) || (_tampered)) { #ifdef TZ_TAMPER_FUSE set_tamper_fuse_cmd(HLOS_IMG_TAMPER_FUSE); #endif #if USE_PCOM_SECBOOT set_tamper_flag(_tampered); #endif } }retry_boot: /* Trying to boot active partition */ if (partition_multislot_is_supported()) { boot_slot = partition_find_boot_slot(); partition_mark_active_slot(boot_slot); if (boot_slot == INVALID) goto fastboot; } boot_err_type = boot_linux_from_mmc(); switch (boot_err_type) { case ERR_INVALID_PAGE_SIZE: case ERR_DT_PARSE: case ERR_ABOOT_ADDR_OVERLAP: case ERR_INVALID_BOOT_MAGIC:

* (so as to not crash if the block is invalid or corrupt). * * The bootloader will have to publish the partition that contains * the recovery_message to the linux kernel so it can update it. * * if command == "boot-recovery" -> boot * else if command == "update-radio" -> update radio image (below) * else -> boot (normal boot) * * Radio Update Flow * 1. the bootloader will attempt to load and validate the header * 2. if the header is invalid, status="invalid-update", goto #8 * 3. display the busy image on-screen * 4. if the update image is invalid, status="invalid-radio-image", goto #8 * 5. attempt to update the firmware (depending on the command) * 6. if successful, status="okay", goto #8 * 7. if failed, and the old image can still boot, status="failed-update" * 8. write the recovery_message, leaving the recovery field * unchanged, updating status, and setting command to * "boot-recovery" * 9. reboot * * The bootloader will not modify or erase the cache partition. * It is recovery's responsibility to clean up the mess afterwards. */int recovery_init (void){ struct recovery_message msg; char partition_name[32]; unsigned valid_command = 0; int update_status = 0; // get recovery message if (get_recovery_message(&msg)) return -1; d[sizeof(d)-1] = '/0'; //Ensure termination if (d[0] != 0 && d[0] != 255) { dprintf(INFO,"Recovery command: %d %s/n", sizeof(d), d); } if (!strcmp("boot-recovery",d)) { if(!strcmp("RADIO",)) { /* We're now here due to radio update, so check for update status */ int ret = get_boot_info_apps(UPDATE_STATUS, (unsigned int *) &update_status); if(!ret && (update_status & 0x01)) { dprintf(INFO,"radio update success/n"); strlcpy(, "OKAY", sizeof()); } else { dprintf(INFO,"radio update failed/n"); strlcpy(, "failed-update", sizeof()); } strlcpy(d, "", sizeof(d)); // clearing recovery command set_recovery_message(&msg); // send recovery message boot_into_recovery = 1; // Boot in recovery mode return 0; } boot_into_recovery = 1; // Boot in recovery mode return 0;

* 4. get_args() writes BCB with "boot-recovery" and "--wipe_data" * -- after this, rebooting will restart the erase -- * 5. erase_volume() reformats /data * 6. erase_volume() reformats /cache * 7. finish_recovery() erases BCB * -- after this, rebooting will restart the main system -- * 8. main() calls reboot() to boot main system * * OTA INSTALL * 1. main system downloads OTA package to /cache/ * 2. main system writes "--update_package=/cache/" * 3. main system reboots into recovery * 4. get_args() writes BCB with "boot-recovery" and "--update_package=..." * -- after this, rebooting will attempt to reinstall the update -- * 5. install_package() attempts to install the update * NOTE: the package install must itself be restartable from any point * 6. finish_recovery() erases BCB * -- after this, rebooting will (try to) restart the main system -- * 7. ** if install failed ** * 7a. prompt_and_wait() shows an error icon and waits for the user * 7b. the user reboots (pulling the battery, etc) into the main system */

int main(int argc, char **argv) { // We don't have logcat yet under recovery; so we'll print error on screen and // log to stdout (which is redirected to ) as we used to do. android::base::InitLogging(argv, &UiLogger); // Take last pmsg contents and rewrite it to the current pmsg session. static const char filter[] = "recovery/"; // Do we need to rotate? bool doRotate = false; __android_log_pmsg_file_read(LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter, logbasename, &doRotate); // Take action to refresh pmsg contents __android_log_pmsg_file_read(LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter, logrotate, &doRotate); // 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) { minadbd_main(); return 0; } time_t start = time(nullptr); // redirect_stdio should be called only in non-sideload mode. Otherwise // we may have two logger instances with different timestamps. redirect_stdio(TEMPORARY_LOG_FILE); printf("Starting recovery (pid %d) on %s", getpid(), ctime(&start)); load_volume_table(); has_cache = volume_for_mount_point(CACHE_ROOT) != nullptr; std::vector args = get_args(argc, argv); std::vector args_to_parse(()); std::transform((), (), args_to_(), [](const std::string& arg) { return const_cast(arg.c_str()); }); const char* update_package = nullptr;

const char* update_package = nullptr; bool should_wipe_data = false; bool should_prompt_and_wipe_data = false; bool should_wipe_cache = false; bool should_wipe_ab = false; size_t wipe_package_size = 0; bool show_text = false; bool sideload = false; bool sideload_auto_reboot = false; bool just_exit = false; bool shutdown_after = false; int retry_count = 0; bool security_update = false; int status = INSTALL_SUCCESS; bool mount_required = true; if (has_cache && ensure_path_mounted(CACHE_ROOT) == 0) { //Create /cache/recovery specifically if it is not created //As in cases where device is booted into recovery directly after //flashing recovery folder is not created in init mkdir_recursively(CACHE_LOG_DIR, 0777, false, sehandle); } int arg; int option_index; //解析参数 while ((arg = getopt_long(args_to_(), args_to_(), "", OPTIONS, &option_index)) != -1) { switch (arg) { case 'n': android::base::ParseInt(optarg, &retry_count, 0); break; case 'u': update_package = optarg; break; case 'w': should_wipe_data = true; break; case 'c': should_wipe_cache = true; break; case 't': show_text = true; break; case 's': sideload = true; break; case 'a': sideload = true; sideload_auto_reboot = true; break; case 'x': just_exit = true; break; case 'l': locale = optarg; break; case 'p': shutdown_after = true; break; case 'r': reason = optarg; break; case 'e': security_update = true; break;

break; case 0: { std::string option = OPTIONS[option_index].name; if (option == "wipe_ab") { should_wipe_ab = true; } else if (option == "wipe_package_size") { android::base::ParseUint(optarg, &wipe_package_size); } else if (option == "prompt_and_wipe_data") { should_prompt_and_wipe_data = true; } break; } case '?': LOG(ERROR) << "Invalid command argument"; continue; } } if (()) { if (has_cache) { locale = load_locale_from_cache(); } if (()) { locale = DEFAULT_LOCALE; } } printf("locale is [%s]/n", locale.c_str()); printf("stage is [%s]/n", stage.c_str()); printf("reason is [%s]/n", reason); Device* device = make_device(); if (android::base::GetBoolProperty("ent", false)) { printf("Quiescent recovery mode./n"); ui = new StubRecoveryUI(); } else { ui = device->GetUI(); if (!ui->Init(locale)) { printf("Failed to initialize UI, use stub UI instead./n"); ui = new StubRecoveryUI(); } } // Set background string to "installing security update" for security update, // otherwise set it to "installing system update". ui->SetSystemUpdateText(security_update); int st_cur, st_max; if (!() && sscanf(stage.c_str(), "%d/%d", &st_cur, &st_max) == 2) { ui->SetStage(st_cur, st_max); } ui->SetBackground(RecoveryUI::NONE); if (show_text) ui->ShowText(true); sehandle = selinux_android_file_context_handle(); selinux_android_set_sehandle(sehandle); if (!sehandle) { ui->Print("Warning: No file_contexts/n"); } device->StartRecovery(); printf("Command:");

printf("Command:"); for (const auto& arg : args) { printf(" /"%s/"", arg.c_str()); } printf("/n/n"); if (update_package) { if (!strncmp("/sdcard", update_package, 7)) { //If this is a UFS device lets mount the sdcard ing //on if the device is UFS or EMMC based the path to the sdcard //device changes so we cannot rely on the block dev path from // file if (is_ufs_dev()) { if(do_sdcard_mount_for_ufs() != 0) { status = INSTALL_ERROR; goto error; } mount_required = false; } else { ui->Print("Update via sdcard on EMMC dev. Using path from fstab/n"); } } } property_list(print_property, nullptr); printf("/n"); ui->Print("Supported API: %d/n", kRecoveryApiVersion); if (update_package != nullptr) { // It's not entirely true that we will modify the flash. But we want // to log the update attempt since update_package is non-NULL. modified_flash = true; if (!is_battery_ok()) { ui->Print("battery capacity is not enough for installing package, needed is %d%%/n", BATTERY_OK_PERCENTAGE); // Log the error code to last_install when installation skips due to // low battery. log_failure_code(kLowBattery, update_package); status = INSTALL_SKIPPED; } else if (bootreason_in_blacklist()) { // Skip update-on-reboot when bootreason is kernel_panic or similar ui->Print("bootreason is in the blacklist; skip OTA installation/n"); log_failure_code(kBootreasonInBlacklist, update_package); status = INSTALL_SKIPPED; } else { // It's a fresh update. Initialize the retry_count in the BCB to 1; therefore we can later // identify the interrupted update due to unexpected reboots. if (retry_count == 0) { set_retry_bootloader_message(retry_count + 1, args); } //见3.4节,安装升级包 status = install_package(update_package, &should_wipe_cache, TEMPORARY_INSTALL_FILE, mount_required, retry_count); if (status == INSTALL_SUCCESS && should_wipe_cache) { wipe_cache(false, device); } if (status != INSTALL_SUCCESS) { ui->Print("Installation aborted./n"); // When I/O error happens, reboot and retry installation RETRY_LIMIT // times before we abandon this OTA update. if (status == INSTALL_RETRY && retry_count < RETRY_LIMIT) { copy_logs(); retry_count += 1;

retry_count += 1; set_retry_bootloader_message(retry_count, args); // Print retry count on screen. ui->Print("Retry attempt %d/n", retry_count); // Reboot and retry the update if (!reboot("reboot,recovery")) { ui->Print("Reboot failed/n"); } else { while (true) { pause(); } } } // 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. if (is_ro_debuggable()) { ui->ShowText(true); } } } } else if (should_wipe_data) { if (!wipe_data(device)) { status = INSTALL_ERROR; } } else if (should_prompt_and_wipe_data) { ui->ShowText(true); ui->SetBackground(RecoveryUI::ERROR); if (!prompt_and_wipe_data(device)) { status = INSTALL_ERROR; } ui->ShowText(false); } else if (should_wipe_cache) { if (!wipe_cache(false, device)) { status = INSTALL_ERROR; } } else if (should_wipe_ab) { if (!wipe_ab_device(wipe_package_size)) { status = INSTALL_ERROR; } } else if (sideload) { // 'adb reboot sideload' acts the same as user presses key combinations // to enter the sideload mode. When 'sideload-auto-reboot' is used, text // display will NOT be turned on by default. And it will reboot after // sideload finishes even if there are errors. Unless one turns on the // text display during the installation. This is to enable automated // testing. if (!sideload_auto_reboot) { ui->ShowText(true); } status = apply_from_adb(&should_wipe_cache, TEMPORARY_INSTALL_FILE); if (status == INSTALL_SUCCESS && should_wipe_cache) { if (!wipe_cache(false, device)) { status = INSTALL_ERROR; } } ui->Print("/nInstall from ADB complete (status: %d)./n", status); if (sideload_auto_reboot) { ui->Print("Rebooting automatically./n"); } } else if (!just_exit) { // If this is an eng or userdebug build, automatically turn on the text display if no command // is specified. Note that this should be called before setting the background to avoid // flickering the background image. if (is_ro_debuggable()) {

int install_package(const std::string& path, bool* wipe_cache, const std::string& install_file, bool needs_mount, int retry_count) { CHECK(!()); CHECK(!install_()); CHECK(wipe_cache != nullptr); modified_flash = true; auto start = std::chrono::system_clock::now(); int start_temperature = GetMaxValueFromThermalZone(); int max_temperature = start_temperature; int result = 0; std::vector log_buffer; if (needs_mount == true) result = setup_install_mounts(); if (result != 0 ) { LOG(ERROR) << "failed to set up expected mounts for install; aborting"; result = INSTALL_ERROR; } else { //见3.5节 result = really_install_package(path, wipe_cache, needs_mount, &log_buffer, retry_count, &max_temperature); } // Measure the time spent to apply OTA update in seconds. std::chrono::duration duration = std::chrono::system_clock::now() - start; int time_total = static_cast(()); bool has_cache = volume_for_mount_point("/cache") != nullptr; // Skip logging the uncrypt_status on devices without /cache. if (has_cache) { static constexpr const char* UNCRYPT_STATUS = "/cache/recovery/uncrypt_status"; if (ensure_path_mounted(UNCRYPT_STATUS) != 0) { LOG(WARNING) << "Can't mount " << UNCRYPT_STATUS; } else { std::string uncrypt_status; if (!android::base::ReadFileToString(UNCRYPT_STATUS, &uncrypt_status)) { PLOG(WARNING) << "failed to read uncrypt status"; } else if (!android::base::StartsWith(uncrypt_status, "uncrypt_")) { LOG(WARNING) << "corrupted uncrypt_status: " << uncrypt_status; } else { log__back(android::base::Trim(uncrypt_status)); } } } // The first two lines need to be the package name and install result. std::vector log_header = { path, result == INSTALL_SUCCESS ? "1" : "0", "time_total: " + std::to_string(time_total), "retry: " + std::to_string(retry_count), }; int end_temperature = GetMaxValueFromThermalZone(); max_temperature = std::max(end_temperature, max_temperature); if (start_temperature > 0) { log__back("temperature_start: " + std::to_string(start_temperature)); } if (end_temperature > 0) { log__back("temperature_end: " + std::to_string(end_temperature)); } if (max_temperature > 0) { log__back("temperature_max: " + std::to_string(max_temperature)); }

// should be between 0.0 and 1.0; sets the // progress bar within the segment defined by the most // recent progress command. // // ui_print // display on the screen. // // wipe_cache // a wipe of cache will be performed following a successful // installation. // // clear_display // turn off the text display. // // enable_reboot // packages can explicitly request that they want the user // to be able to reboot during installation (useful for // debugging packages that don't exit). // // retry_update // updater encounters some issue during the update. It requests // a reboot to retry the same package automatically. // // log // updater requests logging the string (e.g. cause of the // failure). // // - the name of the package zip file. // // - an optional argument "retry" if this update is a retry of a failed // update attempt. // // Convert the vector to a NULL-terminated char* array suitable for execv. const char* chr_args[() + 1]; chr_args[()] = nullptr; for (size_t i = 0; i < (); i++) { chr_args[i] = args[i].c_str(); } pid_t pid = fork(); if (pid == -1) { close(pipefd[0]); close(pipefd[1]); PLOG(ERROR) << "Failed to fork update binary"; log_buffer->push_back(android::base::StringPrintf("error: %d", kForkUpdateBinaryFailure)); return INSTALL_ERROR; } if (pid == 0) { umask(022); close(pipefd[0]); execv(chr_args[0], const_cast(chr_args)); // Bug: 34769056 // We shouldn't use LOG/PLOG in the forked process, since they may cause // the child process to hang. This deadlock results from an improperly // copied mutex in the ui functions. fprintf(stdout, "E:Can't run %s (%s)/n", chr_args[0], strerror(errno)); _exit(EXIT_FAILURE); } close(pipefd[1]); std::atomic logger_finished(false); std::thread temperature_logger(log_max_temperature, max_temperature, std::ref(logger_finished));

*wipe_cache = false; bool retry_update = false; char buffer[1024]; FILE* from_child = fdopen(pipefd[0], "r"); while (fgets(buffer, sizeof(buffer), from_child) != nullptr) { std::string line(buffer); size_t space = _first_of(" /n"); std::string command((0, space)); if (()) continue; // Get rid of the leading and trailing space and/or newline. std::string args = space == std::string::npos ? "" : android::base::Trim((space)); if (command == "progress") { std::vector tokens = android::base::Split(args, " "); double fraction; int seconds; if (() == 2 && android::base::ParseDouble(tokens[0].c_str(), &fraction) && android::base::ParseInt(tokens[1], &seconds)) { ui->ShowProgress(fraction * (1 - VERIFICATION_PROGRESS_FRACTION), seconds); } else { LOG(ERROR) << "invalid /"progress/" parameters: " << line; } } else if (command == "set_progress") { std::vector tokens = android::base::Split(args, " "); double fraction; if (() == 1 && android::base::ParseDouble(tokens[0].c_str(), &fraction)) { ui->SetProgress(fraction); } else { LOG(ERROR) << "invalid /"set_progress/" parameters: " << line; } } else if (command == "ui_print") { ui->PrintOnScreenOnly("%s/n", args.c_str()); fflush(stdout); } else if (command == "wipe_cache") { *wipe_cache = true; } else if (command == "clear_display") { ui->SetBackground(RecoveryUI::NONE); } else if (command == "enable_reboot") { // packages can explicitly request that they want the user // to be able to reboot during installation (useful for // debugging packages that don't exit). ui->SetEnableReboot(true); } else if (command == "retry_update") { retry_update = true; } else if (command == "log") { if (!()) { // Save the logging request from updater and write to last_install later. log_buffer->push_back(args); } else { LOG(ERROR) << "invalid /"log/" parameters: " << line; } } else { LOG(ERROR) << "unknown command [" << command << "]"; } } fclose(from_child); int status; waitpid(pid, &status, 0); logger_(true); finish_log__one();


本文标签: 服务 属性 启动 设置 加密