{"id":3591,"date":"2023-07-27T11:12:42","date_gmt":"2023-07-27T03:12:42","guid":{"rendered":"https:\/\/learn-house.idv.tw\/?p=3591"},"modified":"2023-09-08T14:16:02","modified_gmt":"2023-09-08T06:16:02","slug":"android%e5%a6%82%e4%bd%95%e5%9c%a8app%e9%80%8f%e9%81%8eusb-ota-zip%e5%af%a6%e4%bd%9cab-update","status":"publish","type":"post","link":"https:\/\/learn-house.idv.tw\/?p=3591","title":{"rendered":"[Android]\u5982\u4f55\u5728APP\u900f\u904eUSB OTA zip\u5be6\u4f5cAB update"},"content":{"rendered":"<p>\u7531\u65bc\u4e00\u958b\u59cb\u662f\u5728trace\u539f\u751f\u7684AOSP\u5728recovery mode\u4e0b\u662f\u5982\u4f55\u900f\u904eUSB\u66f4\u65b0\uff0c\u56e0\u6b64\u9019\u88e1\u9084\u662f\u6703\u7d00\u9304\u4e00\u4e0bnative\u4e0b\u662f\u5982\u4f55\u9032\u884c\u7684\uff0c\u7136\u5f8c\u518d\u8aaa\u5982\u4f55\u4f7f\u7528UpdateEngine\u9019\u500bJava layer\u7684API\u4f86\u5be6\u4f5c\u3002<\/p>\n<p><!--more-->\u9996\u5148\uff0crecovery\u7684\u4e3b\u7a0b\u5f0f\u4f4d\u5728bootable\/recovery\uff0c\u5728recovery_main.cpp\u6c7a\u5b9a\u8981\u9032\u5165fastboot\u9084\u662frecovery\u6a21\u5f0f<\/p>\n<pre>[c]auto ret = fastboot ? StartFastboot(device, args) : start_recovery(device, args);[\/c]<\/pre>\n<p>\u9032\u5230recovery.cpp<\/p>\n<pre>[c]\nDevice::BuiltinAction start_recovery(Device* device, const std::vector\u3008std::string\u3009\uff06 args) {\n...\u7565...\nstatus = InstallPackage(memory_package.get(), update_package, should_wipe_cache, retry_count, ui);\n...\u7565...\n}[\/c]<\/pre>\n<p>install.cpp\u9032\u884c\u9a57\u8b49\u548c\u5b89\u88ddpackage<\/p>\n<pre>[c]InstallResult InstallPackage(Package* package, const std::string_view package_id,\nbool should_wipe_cache, int retry_count, RecoveryUI* ui) {\n...\u7565...\nresult = VerifyAndInstallPackage(package, \uff06updater_wipe_cache, \uff06log_buffer, retry_count,\n\uff06max_temperature, ui);\n...\u7565...\n}[\/c]<\/pre>\n<pre>[c]static InstallResult VerifyAndInstallPackage(Package* package, bool* wipe_cache,\nstd::vector\uff06lt;std::string\uff06gt;* log_buffer, int retry_count,\nint* max_temperature, RecoveryUI* ui) {\n...\u7565...\nauto result = TryUpdateBinary(package, wipe_cache, log_buffer, retry_count, max_temperature, ui);\n...\u7565...\n}[\/c]<\/pre>\n<pre>[c]static InstallResult TryUpdateBinary(Package* package, bool* wipe_cache,\nstd::vector\u3008std::string\u3009* log_buffer, int retry_count,\nint* max_temperature, RecoveryUI* ui) {\n...\u7565...\n\n\/\/\u78ba\u8a8ddevice\u662f\u5426\u652f\u63f4ab update\nbool package_is_ab = get_value(metadata, \"ota-type\") == OtaTypeToString(OtaType::AB);\nbool device_supports_ab = android::base::GetBoolProperty(\"ro.build.ab_update\", false);\nbool ab_device_supports_nonab =\nandroid::base::GetBoolProperty(\"ro.virtual_ab.allow_non_ab\", false);\nbool device_only_supports_ab = device_supports_ab \uff06\uff06 !ab_device_supports_nonab;\n\n\/\/\u67e5\u770b\u76ee\u524dsecurity_patch\u7248\u672c\uff0c\u4e0d\u5141\u8a31\u505adowngrade\nconst auto current_spl = android::base::GetProperty(\"ro.build.version.security_patch\", \"\");\nif (ViolatesSPLDowngrade(zip, current_spl)) {\nLOG(ERROR) \u3008\u3008 \"Denying OTA because it's SPL downgrade\";\nreturn INSTALL_ERROR;\n}\n...\u7565...\n\n\/\/\u5982\u679c\u662fAB update\u5c31\u8d70SetUpAbUpdateCommands\nif (auto setup_result =\npackage_is_ab\n? SetUpAbUpdateCommands(package_path, zip, pipe_write.get(), \uff06args)\n: SetUpNonAbUpdateCommands(package_path, zip, retry_count, pipe_write.get(), \uff06args);\n!setup_result) {\nlog_buffer-\u3009push_back(android::base::StringPrintf(\"error: %d\", kUpdateBinaryCommandFailure));\nreturn INSTALL_CORRUPT;\n}\n...\u7565...\n}[\/c]<\/pre>\n<pre>[c]bool SetUpAbUpdateCommands(const std::string\uff06 package, ZipArchiveHandle zip, int status_fd,\nstd::vector\u3008std::string\u3009* cmd) {\n\n\/\/\u53d6\u51fapayload properties\nstatic constexpr const char* AB_OTA_PAYLOAD_PROPERTIES = \"payload_properties.txt\";\nZipEntry64 properties_entry;\nif (FindEntry(zip, AB_OTA_PAYLOAD_PROPERTIES, \uff06properties_entry) != 0) {\nLOG(ERROR) \u3008\u3008 \"Failed to find \" \u3008\u3008 AB_OTA_PAYLOAD_PROPERTIES;\nreturn false;\n}\nauto properties_entry_length = properties_entry.uncompressed_length;\nif (properties_entry_length \u3009 std::numeric_limits\u3008size_t\u3009::max()) {\nLOG(ERROR) \u3008\u3008 \"Failed to extract \" \u3008\u3008 AB_OTA_PAYLOAD_PROPERTIES\n\u3008\u3008 \" because's uncompressed size exceeds size of address space. \"\n\u3008\u3008 properties_entry_length;\nreturn false;\n}\nstd::vector\u3008uint8_t\u3009 payload_properties(properties_entry_length);\nint32_t err =\nExtractToMemory(zip, \uff06properties_entry, payload_properties.data(), properties_entry_length);\nif (err != 0) {\nLOG(ERROR) \u3008\u3008 \"Failed to extract \" \u3008\u3008 AB_OTA_PAYLOAD_PROPERTIES \u3008\u3008 \": \" \u3008\u3008 ErrorCodeString(err);\nreturn false;\n}\n\n\/\/\u53d6\u51fapayload.bin\u5728zip\u6a94\u88e1\u7684offset\u4f4d\u5740\nstatic constexpr const char* AB_OTA_PAYLOAD = \"payload.bin\";\nZipEntry64 payload_entry;\nif (FindEntry(zip, AB_OTA_PAYLOAD, \uff06payload_entry) != 0) {\nLOG(ERROR) \u3008\u3008 \"Failed to find \" \u3008\u3008 AB_OTA_PAYLOAD;\nreturn false;\n}\nlong payload_offset = payload_entry.offset;\n\n\/\/\u57f7\u884cupdate_engine_sideload\u6307\u4ee4\u9032\u884cAB update\n*cmd = {\n\"\/system\/bin\/update_engine_sideload\",\n\"--payload=file:\/\/\" + package,\nandroid::base::StringPrintf(\"--offset=%ld\", payload_offset),\n\"--headers=\" + std::string(payload_properties.begin(), payload_properties.end()),\nandroid::base::StringPrintf(\"--status_fd=%d\", status_fd),\n};\n}[\/c]<\/pre>\n<p>\u800c\u4e3b\u8981\u5728\u9032\u884c\u66f4\u65b0\u7684\u4e3b\u7a0b\u5f0f\u4f4d\u5728system\/update_engine<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u7531\u65bc\u4e00\u958b\u59cb\u662f\u5728trace\u539f\u751f\u7684AOSP\u5728recovery mode\u4e0b\u662f\u5982\u4f55\u900f\u904eUSB\u66f4\u65b0\uff0c\u56e0\u6b64\u9019\u88e1\u9084\u662f\u6703\u7d00\u9304\u4e00<span class=\"post-excerpt-end\">&hellip;<\/span><\/p>\n<p class=\"more-link\"><a href=\"https:\/\/learn-house.idv.tw\/?p=3591\" class=\"themebutton\">Read More<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-3591","post","type-post","status-publish","format-standard","hentry","category-5"],"_links":{"self":[{"href":"https:\/\/learn-house.idv.tw\/index.php?rest_route=\/wp\/v2\/posts\/3591","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/learn-house.idv.tw\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/learn-house.idv.tw\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/learn-house.idv.tw\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/learn-house.idv.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3591"}],"version-history":[{"count":0,"href":"https:\/\/learn-house.idv.tw\/index.php?rest_route=\/wp\/v2\/posts\/3591\/revisions"}],"wp:attachment":[{"href":"https:\/\/learn-house.idv.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3591"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/learn-house.idv.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3591"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/learn-house.idv.tw\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3591"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}