aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin F. Haggerty <haggertk@lineageos.org>2020-06-01 21:07:15 -0600
committerKevin F. Haggerty <haggertk@lineageos.org>2020-06-01 21:38:40 -0600
commit165d84ba502e3ad181ac4c1b355f1dfc3c130637 (patch)
treeef2b8dcca182837aba80ce886e0345fb3552b48b
parentb7913a0de39ba0b53989c5b4f4260221b7109796 (diff)
parent6943af1f7d00de4fabccbcfe03077983a5ae771a (diff)
downloadandroid_bootable_recovery-165d84ba502e3ad181ac4c1b355f1dfc3c130637.tar.gz
android_bootable_recovery-165d84ba502e3ad181ac4c1b355f1dfc3c130637.tar.bz2
android_bootable_recovery-165d84ba502e3ad181ac4c1b355f1dfc3c130637.zip
Merge tag 'android-10.0.0_r37' into staging/lineage-17.1_merge-android-10.0.0_r37
Android 10.0.0 Release 37 (QQ3A.200605.001) * tag 'android-10.0.0_r37': Import translations. DO NOT MERGE Force package installation with FUSE unless the package stores on device Conflicts: install/include/install/install.h recovery.cpp Change-Id: I8db96fa3db40754daff714872970965d169557ab
-rw-r--r--Android.bp2
-rw-r--r--install/include/install/install.h6
-rw-r--r--install/install.cpp47
-rw-r--r--recovery.cpp27
-rw-r--r--tests/Android.bp1
-rw-r--r--tests/component/install_test.cpp28
-rw-r--r--tools/recovery_l10n/res/values-ar/strings.xml4
-rw-r--r--tools/recovery_l10n/res/values-hy/strings.xml2
8 files changed, 111 insertions, 6 deletions
diff --git a/Android.bp b/Android.bp
index 045299a8..e098ddf0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -71,6 +71,7 @@ cc_defaults {
],
static_libs: [
+ "libc++fs",
"libinstall",
"librecovery_fastboot",
"libminui",
@@ -96,6 +97,7 @@ cc_library_static {
],
shared_libs: [
+ "libfusesideload",
"librecovery_ui",
],
}
diff --git a/install/include/install/install.h b/install/include/install/install.h
index 85c197de..84ff7134 100644
--- a/install/include/install/install.h
+++ b/install/include/install/install.h
@@ -74,6 +74,10 @@ bool verify_package_compatibility(ZipArchiveHandle package_zip);
int CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type,
bool allow_ab_downgrade = false);
+// Ensures the path to the update package is mounted. Also set the |should_use_fuse| to true if the
+// package stays on a removable media.
+bool SetupPackageMount(const std::string& package_path, bool* should_use_fuse);
+
// Defined in recovery.cpp, just declare it and it will eventually link fine.
bool ask_to_continue_unverified(Device* device);
-bool ask_to_continue_downgrade(Device* device); \ No newline at end of file
+bool ask_to_continue_downgrade(Device* device);
diff --git a/install/install.cpp b/install/install.cpp
index a417d18e..762c4572 100644
--- a/install/install.cpp
+++ b/install/install.cpp
@@ -30,6 +30,7 @@
#include <atomic>
#include <chrono>
#include <condition_variable>
+#include <filesystem>
#include <functional>
#include <limits>
#include <mutex>
@@ -732,3 +733,49 @@ bool verify_package(Package* package, RecoveryUI* ui) {
}
return true;
}
+
+bool SetupPackageMount(const std::string& package_path, bool* should_use_fuse) {
+ CHECK(should_use_fuse != nullptr);
+
+ if (package_path.empty()) {
+ return false;
+ }
+
+ *should_use_fuse = true;
+ if (package_path[0] == '@') {
+ auto block_map_path = package_path.substr(1);
+ if (ensure_path_mounted(block_map_path) != 0) {
+ LOG(ERROR) << "Failed to mount " << block_map_path;
+ return false;
+ }
+ // uncrypt only produces block map only if the package stays on /data.
+ *should_use_fuse = false;
+ return true;
+ }
+
+ // Package is not a block map file.
+ if (ensure_path_mounted(package_path) != 0) {
+ LOG(ERROR) << "Failed to mount " << package_path;
+ return false;
+ }
+
+ // Reject the package if the input path doesn't equal the canonicalized path.
+ // e.g. /cache/../sdcard/update_package.
+ std::error_code ec;
+ auto canonical_path = std::filesystem::canonical(package_path, ec);
+ if (ec) {
+ LOG(ERROR) << "Failed to get canonical of " << package_path << ", " << ec.message();
+ return false;
+ }
+ if (canonical_path.string() != package_path) {
+ LOG(ERROR) << "Installation aborts. The canonical path " << canonical_path.string()
+ << " doesn't equal the original path " << package_path;
+ return false;
+ }
+
+ constexpr const char* CACHE_ROOT = "/cache";
+ if (android::base::StartsWith(package_path, CACHE_ROOT)) {
+ *should_use_fuse = false;
+ }
+ return true;
+}
diff --git a/recovery.cpp b/recovery.cpp
index 6e8b17c9..60553b7f 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -51,6 +51,7 @@
#include "common.h"
#include "fsck_unshare_blocks.h"
+#include "fuse_sideload.h"
#include "install/adb_install.h"
#include "install/fuse_sdcard_install.h"
#include "install/install.h"
@@ -984,8 +985,30 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri
set_retry_bootloader_message(retry_count + 1, args);
}
- status = install_package(update_package, should_wipe_cache, true, retry_count,
- true /* verify */, false /* allow_ab_downgrade */, ui);
+ bool should_use_fuse = false;
+ if (!SetupPackageMount(update_package, &should_use_fuse)) {
+ LOG(INFO) << "Failed to set up the package access, skipping installation";
+ status = INSTALL_ERROR;
+ } else if (should_use_fuse) {
+ LOG(INFO) << "Installing package " << update_package << " with fuse";
+ auto file_data_reader = std::make_unique<FuseFileDataProvider>(update_package, 65536);
+ status = run_fuse_sideload(std::move(file_data_reader));
+ } else if (auto memory_package = Package::CreateMemoryPackage(
+ update_package,
+ std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1));
+ memory_package != nullptr) {
+ status = install_package(update_package, should_wipe_cache, true, retry_count,
+ true /* verify */, false /* allow_ab_downgrade */, ui);
+ } else {
+ // We may fail to memory map the package on 32 bit builds for packages with 2GiB+ size.
+ // In such cases, we will try to install the package with fuse. This is not the default
+ // installation method because it introduces a layer of indirection from the kernel space.
+ LOG(WARNING) << "Failed to memory map package " << update_package
+ << "; falling back to install with fuse";
+ auto file_data_reader = std::make_unique<FuseFileDataProvider>(update_package, 65536);
+ status = run_fuse_sideload(std::move(file_data_reader));
+ }
+
if (status != INSTALL_SUCCESS) {
ui->Print("Installation aborted.\n");
diff --git a/tests/Android.bp b/tests/Android.bp
index 09ef716d..a0d82d5f 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -99,6 +99,7 @@ librecovery_static_libs = [
"liblp",
"libvndksupport",
"libtinyxml2",
+ "libc++fs",
]
cc_test {
diff --git a/tests/component/install_test.cpp b/tests/component/install_test.cpp
index 38513293..c1f0ca81 100644
--- a/tests/component/install_test.cpp
+++ b/tests/component/install_test.cpp
@@ -34,6 +34,7 @@
#include "install/install.h"
#include "otautil/paths.h"
+#include "otautil/roots.h"
#include "private/setup_commands.h"
static void BuildZipArchive(const std::map<std::string, std::string>& file_map, int fd,
@@ -595,3 +596,30 @@ TEST(InstallTest, CheckPackageMetadata_ab_post_timestamp) {
"\n");
test_check_package_metadata(metadata, OtaType::AB, 0);
}
+
+TEST(InstallTest, SetupPackageMount_package_path) {
+ load_volume_table();
+ bool install_with_fuse;
+
+ // Setup should fail if the input path doesn't exist.
+ ASSERT_FALSE(SetupPackageMount("/does_not_exist", &install_with_fuse));
+
+ // Package should be installed with fuse if it's not in /cache.
+ TemporaryDir temp_dir;
+ TemporaryFile update_package(temp_dir.path);
+ ASSERT_TRUE(SetupPackageMount(update_package.path, &install_with_fuse));
+ ASSERT_TRUE(install_with_fuse);
+
+ // Setup should fail if the input path isn't canonicalized.
+ std::string uncanonical_package_path = android::base::Join(
+ std::vector<std::string>{
+ temp_dir.path,
+ "..",
+ android::base::Basename(temp_dir.path),
+ android::base::Basename(update_package.path),
+ },
+ '/');
+
+ ASSERT_EQ(0, access(uncanonical_package_path.c_str(), R_OK));
+ ASSERT_FALSE(SetupPackageMount(uncanonical_package_path, &install_with_fuse));
+}
diff --git a/tools/recovery_l10n/res/values-ar/strings.xml b/tools/recovery_l10n/res/values-ar/strings.xml
index 2af36d64..a9cd2d13 100644
--- a/tools/recovery_l10n/res/values-ar/strings.xml
+++ b/tools/recovery_l10n/res/values-ar/strings.xml
@@ -6,9 +6,9 @@
<string name="recovery_no_command" msgid="4465476568623024327">"ليس هناك أي أمر"</string>
<string name="recovery_error" msgid="5748178989622716736">"خطأ!"</string>
<string name="recovery_installing_security" msgid="9184031299717114342">"جارٍ تثبيت تحديث الأمان"</string>
- <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"‏يتعذَّر تحميل نظام Android، حيث قد تكون بياناتك تالفة. وإذا استمر ظهور هذه الرسالة، قد يتعيَّن عليك إجراء إعادة الضبط بحسب بيانات المصنع ومحو جميع بيانات المستخدم المُخزَّنة على هذا الجهاز."</string>
+ <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"‏يتعذَّر تحميل نظام Android، حيث قد تكون بياناتك تالفة. وإذا استمر ظهور هذه الرسالة، قد يتعيَّن عليك إجراء إعادة الضبط على الإعدادات الأصلية ومحو جميع بيانات المستخدم المُخزَّنة على هذا الجهاز."</string>
<string name="recovery_try_again" msgid="7168248750158873496">"إعادة المحاولة"</string>
- <string name="recovery_factory_data_reset" msgid="7321351565602894783">"إعادة الضبط بحسب بيانات المصنع"</string>
+ <string name="recovery_factory_data_reset" msgid="7321351565602894783">"إعادة الضبط على الإعدادات الأصلية"</string>
<string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"هل تريد حجب كل بيانات المستخدم؟\n\n لا يمكن التراجع عن هذا الإجراء."</string>
<string name="recovery_cancel_wipe_data" msgid="66987687653647384">"إلغاء"</string>
</resources>
diff --git a/tools/recovery_l10n/res/values-hy/strings.xml b/tools/recovery_l10n/res/values-hy/strings.xml
index 35a0ab11..76c28a70 100644
--- a/tools/recovery_l10n/res/values-hy/strings.xml
+++ b/tools/recovery_l10n/res/values-hy/strings.xml
@@ -9,6 +9,6 @@
<string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Չհաջողվեց բեռնել Android համակարգը։ Հնարավոր է՝ ձեր տվյալները վնասված են։ Եթե նորից տեսնեք այս հաղորդագրությունը, փորձեք վերակայել սարքի կարգավորումները և ջնջել օգտատիրոջ բոլոր տվյալները։"</string>
<string name="recovery_try_again" msgid="7168248750158873496">"Նորից փորձել"</string>
<string name="recovery_factory_data_reset" msgid="7321351565602894783">"Վերակայել բոլոր տվյալները"</string>
- <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"Մաքրե՞լ օգտատիրոջ բոլոր տվյալները։\n\n ԱՅՍ ԳՈՐԾՈՂՈՒԹՅՈՒՆԸ ՀՆԱՐԱՎՈՐ ՉԻ ԼԻՆԻ ՀԵՏԱՐԿԵԼ"</string>
+ <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"Ջնջե՞լ օգտատիրոջ բոլոր տվյալները։\n\n ԱՅՍ ԳՈՐԾՈՂՈՒԹՅՈՒՆԸ ՀՆԱՐԱՎՈՐ ՉԻ ԼԻՆԻ ՀԵՏԱՐԿԵԼ"</string>
<string name="recovery_cancel_wipe_data" msgid="66987687653647384">"Չեղարկել"</string>
</resources>