Android OTA升級包製作指令碼詳解(五,升級指令碼updater-script的執行<1>)

來源:互聯網
上載者:User

標籤:

寫在前面:

    首先當我們執行升級指令碼updater-script的時候,就表示我們已經進入了升級安裝狀態。那麼在我們就從實際的安裝作為入口開始分析。也就是說我們從install.cpp中的install_package函數開始一步步來分析。

    這裡主要分析與指令碼相關的部分,其他的請參考這位朋友的博文http://blog.chinaunix.net/uid-22028566-id-3533856.html,我也很受啟發。這裡也借用一張圖來協助流程上的分析。


   下面是調用的流程:install_package()-->really_install_package(),那麼在really_install_package()函數中真正開始安裝的邏輯如下:

    /* Verify and install the contents of the package.     */    ui->Print("Installing update...\n");    err = try_update_binary(path, &zip, wipe_cache);    if(err != INSTALL_SUCCESS)        return err;
    try_update_binary是真正實現讀取升級包中的指令檔並執行相應的函數。在此函數中,通過調用fork函數建立出一個子進程,在子進程中開始讀取並執行升級指令檔。在此需要注意的是函數fork的用法,fork被調用一次,將做兩次返回,在父進程中返回的是子進程的進程ID,為正數;而在子進程中,則返回0。子進程中所進行的操作,即execv(binary, args)。子進程建立成功後,開始執行升級代碼,並通過管道與父進程互動(建立管道,並將pipefd[1]作為參數傳遞給子進程,子進程則將相關資訊寫入到此管道描述符中);而父進程則通過讀取子進程傳遞過來的資訊更新UI。

    那麼下面我們來具體來分析一下這個方法具體的邏輯。

static inttry_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) {    //定義一個常量用來封裝尋找相zip關資訊的結果如“META-INF/com/google/android/update-binary”,便於後面進行解壓,因為之前mzOpenZipArchive函數並沒有對更新包進行解壓操作,*zip是之前mzOpenZipArchive方法返回的一個ZipArchive對象。mzOpenZipArchive是開啟升級包,並將相關的資訊拷貝到一個臨時的ZipArchinve變數中。//ASSUMED_UPDATE_BINARY_NAME="META-INF/com/google/android/update-binary"    const ZipEntry* binary_entry =            mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);    if (binary_entry == NULL) {        mzCloseZipArchive(zip);        return INSTALL_CORRUPT;    }    const char* binary = "/tmp/update_binary";    unlink(binary);//建立“/tmp/update_binary”檔案    int fd = creat(binary, 0755);    if (fd < 0) {        mzCloseZipArchive(zip);        LOGE("Can't make %s\n", binary);        return INSTALL_ERROR;    }//將META-INF/com/google/android/update-binary中的內容解壓縮到"/tmp/update_binary"下面。其實這個方法中主要是對update_binary操作的,如解壓和執行等。    bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd);    close(fd);    mzCloseZipArchive(zip);    if (!ok) {        LOGE("Can't copy %s\n", ASSUMED_UPDATE_BINARY_NAME);        return INSTALL_ERROR;    }    int pipefd[2];//建立管道,用於下面的子進程和父進程之間的通訊    pipe(pipefd);    // When executing the update binary contained in the package, the    // arguments passed are:    //    //   - the version number for this interface    //    //   - an fd to which the program can write in order to update the    //     progress bar.  The program can write single-line commands:    //    //        progress <frac> <secs>    //            fill up the next <frac> part of of the progress bar    //            over <secs> seconds.  If <secs> is zero, use    //            set_progress commands to manually control the    //            progress of this segment of the bar    //    //        set_progress <frac>    //            <frac> should be between 0.0 and 1.0; sets the    //            progress bar within the segment defined by the most    //            recent progress command.    //    //        firmware <"hboot"|"radio"> <filename>    //            arrange to install the contents of <filename> in the    //            given partition on reboot.    //    //            (API v2: <filename> may start with "PACKAGE:" to    //            indicate taking a file from the OTA package.)    //    //            (API v3: this command no longer exists.)    //    //        ui_print <string>    //            display <string> on the screen.    //    //   - the name of the package zip file.    //    const char** args = (const char**)malloc(sizeof(char*) * 5);    args[0] = binary;    args[1] = EXPAND(RECOVERY_API_VERSION);   // defined in Android.mk    char* temp = (char*)malloc(10);    sprintf(temp, "%d", pipefd[1]);    args[2] = temp;    args[3] = (char*)path;    args[4] = NULL;//建立子進程。其中的子進程主要負責執行binary(execv(binary,args),即執行我們的安裝命令指令碼),父進程負責接受子進程發送的命令去更新ui顯示(顯示當前的進度)。子父處理序間通訊依靠管道。    pid_t pid = fork();    if (pid == 0) {        close(pipefd[0]);//執行<span style="font-family: Arial, Helvetica, sans-serif;">update-binary</span><span style="font-family: Arial, Helvetica, sans-serif;">,這個程式的實質就是去解析update.zip包中的updater-script指令碼中的命令並執行。由此,Recovery服務就進入了實際安裝update.zip包的過程。</span><span style="font-family: Arial, Helvetica, sans-serif;">在執行execv函數時,execv會停止執行當前的進程,並且以progname應用進程替換被停止執行的進程,進程ID沒有改變。這裡的progname就是指</span><span style="font-family: Arial, Helvetica, sans-serif;">update-binary</span><span style="font-family: Arial, Helvetica, sans-serif;">,也就是被執行的應用程式。第二個參數argv,是指運行</span><span style="font-family: Arial, Helvetica, sans-serif;">update-binary</span><span style="font-family: Arial, Helvetica, sans-serif;">t時,傳遞給執行程式的參數列表, 注意,這個數組的第一個參數應該是應用程式名稱字本身,並且最後一個參數應該為NULL,不參將多個參數合并為一個參數放入數組。</span><span style="font-family: Arial, Helvetica, sans-serif;"></span>此外,如果應用程式正常執行完畢,那麼execv是永遠不會返回的;當execv在調用進程中返回時,那麼這個應用程式應該出錯了(可能是程式本身沒找到,許可權不夠...),此時它的傳回值應該是-1,具體的錯誤碼可以通過全域變數errno查看,還可以通過stderr得到具體的錯誤描述字串。        execv(binary, (char* const*)args);//其實我的理解就是<span style="font-family: Arial, Helvetica, sans-serif;">update-binary相當一個exe可執行程式,這裡就是一個雙擊可執行程式的動作</span>        fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno));        _exit(-1);    }    close(pipefd[1]);    *wipe_cache = 0;    char buffer[1024];    FILE* from_child = fdopen(pipefd[0], "r");    while (fgets(buffer, sizeof(buffer), from_child) != NULL) {        char* command = strtok(buffer, " \n");        if (command == NULL) {            continue;        } else if (strcmp(command, "progress") == 0) {            char* fraction_s = strtok(NULL, " \n");            char* seconds_s = strtok(NULL, " \n");            float fraction = strtof(fraction_s, NULL);            int seconds = strtol(seconds_s, NULL, 10);            ui->ShowProgress(fraction * (1-VERIFICATION_PROGRESS_FRACTION), seconds);        } else if (strcmp(command, "set_progress") == 0) {            char* fraction_s = strtok(NULL, " \n");            float fraction = strtof(fraction_s, NULL);            ui->SetProgress(fraction);        } else if (strcmp(command, "ui_print") == 0) {            char* str = strtok(NULL, "\n");            if (str) {                ui->Print("%s", str);            } else {                ui->Print("\n");            }            fflush(stdout);        } else if (strcmp(command, "wipe_cache") == 0) {            *wipe_cache = 1;#if 1 //wschen 2012-07-25        } else if (strcmp(command, "special_factory_reset") == 0) {            *wipe_cache = 2;#endif        } else if (strcmp(command, "clear_display") == 0) {            ui->SetBackground(RecoveryUI::NONE);        } else {            LOGE("unknown command [%s]\n", command);        }    }    fclose(from_child);    int status;    waitpid(pid, &status, 0);    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {        LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status));        return INSTALL_ERROR;    }#ifdef SUPPORT_DATA_BACKUP_RESTORE //wschen 2011-03-09 //Skip userdata restore if updating from /data with no /data layout changeif(!usrdata_changed && update_from_data){    ui->Print("/data offset remains the same no need to restore usrdata\n");}else{    if (part_size_changed) {        if (ensure_path_mounted("/sdcard") != 0) {            LOGE("Can't mount %s\n", path);            return INSTALL_NO_SDCARD;        }        if (userdata_restore(backup_path, 1)) {            return INSTALL_FILE_SYSTEM_ERROR;        }    }}#endif //SUPPORT_DATA_BACKUP_RESTORE    /* ----------------------------- */    /* SECURE BOOT UPDATE            */        /* ----------------------------- */            #ifdef SUPPORT_SBOOT_UPDATE    sec_update(false);#endif    return INSTALL_SUCCESS;}

Android OTA升級包製作指令碼詳解(五,升級指令碼updater-script的執行<1>)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.