失效链接处理 |
Android OTA代码简单分析 PDF 下载
本站整理下载:
相关截图:
主要内容:
Android 代码OTA: 已验证。
一、OTA版本编译及包制作(Android 11代码为例)
./build.sh dist -j32 2>&1 | tee build.txt
或
source build/envsetup.sh
lunch qssi-userdebug /lito-userdebug
./build.sh dist -qssi_only -j24 2>&1 | tee build.txt
./build.sh dist -target_only -j24 2>&1 | tee build.txt
./build.sh dist -merge_only -j24 2>&1 | tee build.txt
相关的OTA包会生成在:
out\dist\merged-qssi_lito-ota.zip
--->OTA全量升级包
out\dist\merged-qssi_lito-target_files.zip
--->OTA差分升级原始包
差分包制作命令参考:./build/tools/releasetools/ota_from_target_files -v --block -p out/host/linux-x86 -i \
oldrignal.zip newrignal.zip update.zip
OTA升级包文件结构AB模式与非AB模式有明显的差别:
OTA 差分升级包目录结构-AB模式:
META-INF文件夹:
OTA 差分升级包目录结构-非AB模式:
META-INF文件夹:
PATCH文件夹:
注意:工具烧录时是要用make otapackage或 ./build.sh dist编译后生成的IMG,否则差分升级是无法成功的。
二、OTA包升级过程分析(旧升级模式);Android 11 A/B模式没有走这个流程。
OTA重启前流程:
1. APK或SD升级最终都会调用到RecoverySystem.installPackage方法:
Frameworks/base/core/java/android/os/RecoverySystem.java
public static void installPackage(Context context, File packageFile, boolean processed)
throws IOException {
synchronized (sRequestLock) {
LOG_FILE.delete();
// Must delete the file in case it was created by system server.
UNCRYPT_PACKAGE_FILE.delete();
String filename = packageFile.getCanonicalPath();
Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
// If the package name ends with "_s.zip", it's a security update.
boolean securityUpdate = filename.endsWith("_s.zip");
// If the package is on the /data partition, the package needs to
// be processed (i.e. uncrypt'd). The caller specifies if that has
// been done in 'processed' parameter.
if (filename.startsWith("/data/")) {
if (processed) {
if (!BLOCK_MAP_FILE.exists()) {
Log.e(TAG, "Package claimed to have been processed but failed to find "
+ "the block map file.");
throw new IOException("Failed to find block map file");
}
} else {
FileWriter uncryptFile = new FileWriter(UNCRYPT_PACKAGE_FILE);
try {
uncryptFile.write(filename + "\n");
} finally {
uncryptFile.close();
}
// UNCRYPT_PACKAGE_FILE needs to be readable and writable
// by system server.
if (!UNCRYPT_PACKAGE_FILE.setReadable(true, false)
|| !UNCRYPT_PACKAGE_FILE.setWritable(true, false)) {
Log.e(TAG, "Error setting permission for " + UNCRYPT_PACKAGE_FILE);
}
BLOCK_MAP_FILE.delete();
}
// If the package is on the /data partition, use the block map
// file as the package name instead.
filename = "@/cache/recovery/block.map";
}
final String filenameArg = "--update_package=" + filename + "\n";
final String localeArg = "--locale=" + Locale.getDefault().toLanguageTag() + "\n";
final String securityArg = "--security\n";
String command = filenameArg + localeArg;
if (securityUpdate) {
command += securityArg;
}
RecoverySystem rs = (RecoverySystem) context.getSystemService(
Context.RECOVERY_SERVICE);
if (!rs.setupBcb(command)) { //------>向bootloader contral block写入相关的参数值command
throw new IOException("Setup BCB failed");
}
// Having set up the BCB (bootloader control block), go ahead and reboot
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
String reason = PowerManager.REBOOT_RECOVERY_UPDATE;
// On TV, reboot quiescently if the screen is off
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
DisplayManager dm = context.getSystemService(DisplayManager.class);
if (dm.getDisplay(DEFAULT_DISPLAY).getState() != Display.STATE_ON) {
reason += ",quiescent";
}
}
pm.reboot(reason);//---> 以reason=”recovery-update”方式重启进入recovery模式
throw new IOException("Reboot failed (no permissions?)");
}
}
|