[システム]アンドロイドAndroidシステムのアップグレード解析工程(a)のアップグレードプロセス更新パケットモード用---リカバリ分析

免責事項:この記事はブロガーオリジナル記事ですが、許可ブロガーなく再生してはなりません。https://blog.csdn.net/twk121109281/article/details/90748513

今日、我々は直接のAndroid固有のアップグレード手順であるかを見ています。


アップグレードプロセスの概要

フローチャートアップグレード:

アップグレードプロセス分析

最初のステップ:アップグレードパッケージを取得

リモートダウンロードでアップグレードするか、指定したディレクトリに直接コピーしましょう。

ステップ2:アップグレードの準備

その後RecoverySystem.installPackageディレクトリパラメータ渡しモード受け継が呼び出します。これは、アプリケーション層のコードで、次のとおりです。

public void updateSystem(String updateSavePath) {
    File packageFile = new File(updateSavePath);
    try {
        //调用升级接口
        RecoverySystem.installPackage(this, packageFile);
    } catch (IOException e) {
        LOG.e(TAG, "RecoverySystem ERROR!!!");
        e.printStackTrace();
        String errDesc =String.format("execute system update fail. reason-> %s", e.toString());
        reportUpdateError(errDesc);
    }

    LOG.d(TAG, "RecoverySystem OK!!!");
    copyUpdateFileIsSuccess = false;
}

アプリケーション層の後アップグレードパッケージをダウンロードし、インストールプロセスを開始する機能(パッケージファイルをファイル、コンテキストコンテキスト)RecoverySystem.installPackageを呼び出して、このプロセスの主な原則は、実際には、単に/キャッシュ/回復/コマ​​ンドに、その後、パッケージのストレージ・パスをアップグレード書き込みリカバリモード、そして何よりもに再起動します。

public static void installPackage(Context context, File packageFile)
    throws IOException {
    String filename = packageFile.getCanonicalPath();
    Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");

    //升级包路径
    final String filenameArg = "--update_package=" + filename;
    final String localeArg = "--locale=" + Locale.getDefault().toString();
    bootCommand(context, filenameArg, localeArg);
}

private static void bootCommand(Context context, String... args) throws IOException {
    RECOVERY_DIR.mkdirs();  // In case we need it
    COMMAND_FILE.delete();  // In case it's not writable
    LOG_FILE.delete();
    FileWriter command = new FileWriter(COMMAND_FILE);
    try {
        for (String arg : args) {
            if (!TextUtils.isEmpty(arg)) {
                command.write(arg);
                command.write("\n");
            }
        }
    } finally {
        command.close();
    }
    // Having written the command file, go ahead and reboot
    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    //重启到recovery模式
    pm.reboot(PowerManager.REBOOT_RECOVERY);
    throw new IOException("Reboot failed (no permissions?)");
}

PowerManager.REBOOT_RECOVERYは、文字列「回復」、回復のpm.reboot()メソッドが最後BCB雑貨パーティションに書き込まれますが含まれています。BCBすなわちブートローダ制御ブロック、コードから見た起動制御ブロック、配置パーティションその他は、構造体です。次のように:

struct bootloader_message {  
    char command[32];  
    char status[32];  
    char recovery[1024];  
}; 

bootloader_message構造は、特に次のような意味では、三つのフィールドを含みます:

コマンドは、フィールドに格納されたコマンドである、それは次の値があります。 
*ブート回復:システムが復旧モードを開始します 
*更新のRadiaまたは更新hboot:システムがファームウェアアップデートモード、ブートローダによって更新プロセスを入力して開始します完全な 
* NULL:NULL値、システムはメインシステムが正常に起動するメインシステムを起動します。

ステータス記憶フィールドは、結果を更新しています。更新後、更新結果ブートローダーの回復またはこのフィールドに書き込まれます。

回復フィールドは、一般的なアップグレードパッケージパスを含め、ブートパラメータrecovryモジュールに格納されます。最初の行格納された文字列「回復」、第二ラインストレージ・パス情報「-update_package =を/ mnt / SDカード/ update.zip」等を次のように構成格納。したがって、引数が「\ n」は、セグメンテーションの間にあります。

第三段階:システムがリカバリモードを再起動し、アップグレード

 Androidのシステムをアップグレードする場合、2つの方法があります。

一つは、自動的にアップグレード後に再起動インタフェースの伝送路を自動的にアップグレードアップグレードパッケージ(Androidシステムは、SDカードをアップグレードする)、完全なシステムを介して行われます。

もう一つは、リカバリモードを手動で入力することで、アップグレードするアップグレードパッケージを選択し、アップグレードが回復インターフェイスでの滞在が完了した後で、手動で再起動するを選択する必要があります。

開発とテストスタッフのために使用されているエンドラインをアップグレードするための携帯電話メーカーの元のクライアント。しかし、原則は同じであるか、関係なくは、回復モードにアップグレードされます。

ここで、アップグレードパッケージがキャッシュ・ディレクトリに格納され、そして方法でパス/キャッシュ/リカバリ/コマンドに格納された更新パッケージ(ストレージ・パスアップグレードパッケージは、又はBCB /キャッシュ/リカバリ/コマンドから内部構文解析します)。

メジャーアップグレードプロセスに再起動します:

  1. リカバリモードにシステムの再起動。コマンドBCBを読んだ後、「ブート・リカバリー」、ロードrecovery.imgを読んで、リカバリを開始します。
  2. install.cppでアップグレードします
  3. アップグレードスクリプトを実行try_update_binary
  4. finish_recovery呼び出し方法、BCB明確な情報、再起動

1、回復モードにシステムの再起動

    それはそれ以外の場合は正常に起動し、リカバリモードに入ることがあれば、システムが、再起動時にコマンドファイル/キャッシュ/回復ディレクトリがあるかどうかを判断します。

    リカバリモードに、主な機能は、以下のキーコードの断片を入れ、recovery.cppを行いました。

... ...
while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {  
    switch (arg) {  
    case 's': send_intent = optarg; break;  
    case 'u': update_package = optarg; break;  
    ... ... 
} 
... ...

2、install.cppをアップグレードします

主な機能には、最終的に方法をinstall_packageして呼び出します。

... ...
if (update_package != NULL) {  
    status = install_package(update_package, &wipe_cache, TEMPORARY_INSTALL_FILE, true);  
    ... ...
} 
    ... ...

特定のアップグレード手順は、install.cppにinstall_package方法を見て行っています。

int install_package(const char* path, int* wipe_cache, const char* install_file,  
                bool needs_mount)  
{  
    ... ...
    if (setup_install_mounts() != 0) {  
        ... ...
    } else {  
        result = really_install_package(path, wipe_cache, needs_mount);  
    }
    ... ...
}  

install_package方法は、ログファイル(アップグレードログ情報を与えられている)を作成します。そして、really_install_packageメソッドを呼び出します。

static int really_install_package(const char *path, int* wipe_cache, bool needs_mount)  
{  
    ... ...
    // 装入签名文件
    Certificate* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys);
    ... ...
    // 验证签名
    err = verify_file(map.addr, map.length, loadedKeys, numKeys);
    ... ...
    // 打开升级包  
    err = mzOpenZipArchive(map.addr, map.length, &zip);
    ... ... 
    // 执行升级脚本文件,开始升级  
    int result = try_update_binary(path, &zip, wipe_cache);
    ... ...
}  

really_install_package方法、最初の署名を検証した後、アップグレードパッケージを読み、[try_update_binaryをアップグレードするためのメソッドを呼び出します

3、アップグレードスクリプトを実行try_update_binary

static int try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) {

    const ZipEntry* binary_entry = mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);
    ... ...
    const char* binary = "/tmp/update_binary";
    unlink(binary);
    int fd = creat(binary, 0755); 
    ... ...
    //将升级包里面的update_binary解压到/tmp/update_binary
    bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd);
    ... ...

    const char** args = (const char**)malloc(sizeof(char*) * 5);
    args[0] = binary; //update_binary存放路径
    args[1] = EXPAND(RECOVERY_API_VERSION);  // Recovery版本号
    char* temp = (char*)malloc(10);
    sprintf(temp, "%d", pipefd[1]);
    args[2] = temp;
    args[3] = (char*)path; //升级包存放路径
    args[4] = NULL;

    pid_t pid = fork();//fork一个子进程
    if (pid == 0) {
        close(pipefd[0]);
        //子进程调用update-binary执行升级操作
        execv(binary, (char* const*)args);
        fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno));
        _exit(-1);
    }
    //父进程负责接受子进程发送的命令去更新ui显示 
    ... ...
    int status;
    waitpid(pid, &status, 0);
    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
        //安装失败,返回INSTALL_ERROR
        return INSTALL_ERROR;
    }
     //安装成功,返回INSTALL_SUCCESS
    return INSTALL_SUCCESS;
}

4、finish_recovery呼び出す方法、BCB明確な情報、再起動

OTAのアップグレードが成功し、miscの空のパーティション(BCBゼロ)だった、とアップグレードログは、メモリシステム/tmp/recovery.log /キャッシュ/回復/ last_logに保存されて保存します。アップグレードが完了すると、メインシステムにデバイスを再起動します。

結論

これらは、私たちが手助けをしたい、アップグレードプロセスの分析です。また、当社のマイクロチャネル公共番号を集中することができ、システムのアップグレードプロセスに関連する、興味のある学生をもたらすためのフォローアップをご紹介します。

å¨è¿éæå¥å¾çæè¿°

前:目次

次:[システム] Androidのシステムアップグレード・プロセス分析(二)---更新パケット解析

おすすめ

転載: blog.csdn.net/twk121109281/article/details/90748513