diff --git a/Android.mk b/Android.mk
index f81bcadc..442d2cff 100755
--- a/Android.mk
+++ b/Android.mk
@@ -383,6 +383,9 @@ ifneq ($(TW_DEFAULT_LANGUAGE),)
else
LOCAL_CFLAGS += -DTW_DEFAULT_LANGUAGE=en
endif
+ifneq ($(TW_QCOM_ATS_OFFSET),)
+ LOCAL_CFLAGS += -DTW_QCOM_ATS_OFFSET=$(TW_QCOM_ATS_OFFSET)
+endif
ifneq ($(TW_CLOCK_OFFSET),)
LOCAL_CFLAGS += -DTW_CLOCK_OFFSET=$(TW_CLOCK_OFFSET)
endif
@@ -390,6 +393,9 @@ ifneq ($(TW_OVERRIDE_SYSTEM_PROPS),)
TW_INCLUDE_LIBRESETPROP := true
LOCAL_CFLAGS += -DTW_OVERRIDE_SYSTEM_PROPS=$(TW_OVERRIDE_SYSTEM_PROPS)
endif
+ifneq ($(TW_OVERRIDE_PROPS_ADDITIONAL_PARTITIONS),)
+ LOCAL_CFLAGS += -DTW_OVERRIDE_PROPS_ADDITIONAL_PARTITIONS='"$(TW_OVERRIDE_PROPS_ADDITIONAL_PARTITIONS)"'
+endif
ifneq ($(TW_INCLUDE_LIBRESETPROP),)
LOCAL_SHARED_LIBRARIES += libresetprop
LOCAL_C_INCLUDES += external/magisk-prebuilt/include
@@ -398,6 +404,9 @@ endif
ifeq ($(TW_EXCLUDE_NANO), true)
LOCAL_CFLAGS += -DTW_EXCLUDE_NANO
endif
+ifneq ($(TARGET_OTA_ASSERT_DEVICE),)
+ LOCAL_CFLAGS += -DTARGET_OTA_ASSERT_DEVICE='"$(TARGET_OTA_ASSERT_DEVICE)"'
+endif
ifeq ($(TW_EXCLUDE_TWRPAPP), true)
LOCAL_CFLAGS += -DTW_EXCLUDE_TWRPAPP
endif
@@ -557,6 +566,12 @@ endif
LOCAL_REQUIRED_MODULES += $(TWRP_REQUIRED_MODULES)
+TW_THEME_VERSION := $(shell grep TW_THEME_VERSION bootable/recovery/variables.h | cut -d ' ' -f 3)
+
+LOCAL_POST_INSTALL_CMD += \
+ sed -i "s/{themeversion}/$(TW_THEME_VERSION)/" $(TARGET_RECOVERY_ROOT_OUT)/twres/splash.xml; \
+ sed -i "s/{themeversion}/$(TW_THEME_VERSION)/" $(TARGET_RECOVERY_ROOT_OUT)/twres/ui.xml;
+
include $(BUILD_EXECUTABLE)
# Symlink for file_contexts
diff --git a/gui/libguitwrp_defaults.go b/gui/libguitwrp_defaults.go
index 9e8fd0b1..4c64f50f 100644
--- a/gui/libguitwrp_defaults.go
+++ b/gui/libguitwrp_defaults.go
@@ -42,6 +42,7 @@ func printCustomThemeWarning(theme string, location string) {
func copyThemeResources(ctx android.BaseContext, dirs []string, files []string) {
outDir := ctx.Config().Getenv("OUT")
twRes := outDir + "/recovery/root/twres/"
+ os.MkdirAll(twRes, os.ModePerm)
recoveryDir := getRecoveryAbsDir(ctx)
theme := determineTheme(ctx)
for idx, dir := range dirs {
@@ -68,6 +69,7 @@ func copyThemeResources(ctx android.BaseContext, dirs []string, files []string)
func copyCustomTheme(ctx android.BaseContext, customTheme string) {
outDir := ctx.Config().Getenv("OUT")
twRes := outDir + "/recovery/root/twres/"
+ os.MkdirAll(twRes, os.ModePerm)
fileDest := twRes + path.Base(customTheme)
fileToCopy := fmt.Sprintf("%s%s", getBuildAbsDir(ctx), customTheme)
copyFile(fileToCopy, fileDest)
diff --git a/gui/pages.cpp b/gui/pages.cpp
index bc4a9360..8b9ce464 100755
--- a/gui/pages.cpp
+++ b/gui/pages.cpp
@@ -53,9 +53,7 @@ extern "C" {
#include "objects.hpp"
#include "blanktimer.hpp"
-// version 2 requires theme to handle power button as action togglebacklight
-// version 4 adds fastbootd support
-#define TW_THEME_VERSION 4
+#include "../variables.h"
#define TW_THEME_VER_ERR -2
diff --git a/gui/theme/extra-languages/languages/zh_CN.xml b/gui/theme/extra-languages/languages/zh_CN.xml
index bbd8fb01..a998be37 100644
--- a/gui/theme/extra-languages/languages/zh_CN.xml
+++ b/gui/theme/extra-languages/languages/zh_CN.xml
@@ -35,7 +35,7 @@
Team Win Recovery Project
TWRP %tw_version%
- 温度: %tw_cpu_temp% °C
+ CPU温度: %tw_cpu_temp% °C
电量: %tw_battery%
按名称排序
按日期排序
@@ -226,6 +226,7 @@
启用压缩
当备份时跳过生成 Digest
在备份之前禁用剩余空间检查
+ 安装 ZIP 之前跳过 Digest 校验
当前槽位: %tw_active_slot%
槽位 A
槽位 B
@@ -316,6 +317,7 @@
常规
常规
使用 rm -rf 命令代替格式化
+ 刷入 ROM 后自动重装 TWRP
使用 24 小时制
反转底部按钮布局
为测试主题使用模拟操作
@@ -459,6 +461,8 @@
设置权限
权限:
操作完成
+ 在此处打开终端
+ 编辑文件
解密 Data 分区
请输入密码。
密码错误,请重试!
@@ -506,6 +510,11 @@
正在解包 {1}…
正在打包 {1}…
选择镜像
+ 如果设备之前有root权限,现在可能被覆盖,请重新获取root权限。
+ 刷入当前的 TWRP
+ 是否刷入当前的 TWRP?
+ 正在刷入 TWRP...
+ TWRP 刷入完成!
修复 Recovery 无限重启
是否修复 Recovery 无限重启?
正在修复 Recovery 无限重启…
@@ -729,15 +738,18 @@
无法写入 adb 控制通道
启用 TWRP ADB 备份需使用 --twrp 选项
分区列表中未发现路径: {1}
- 已导出内核日志至 {1}
- 包含内核日志
+ 已导出 kernel 日志到 {1}
+ 已导出 logcat 日志到 {1}
+ 包含 Kernel 日志
+ 包含 Logcat 日志
使用 SHA2 进行散列校验
更改 Bootloader 启动槽位至 {1} 错误
在安装 Zip 刷机包之前先解除挂载 System
正在解除挂载 System…
解除挂载 System 失败
正在刷入 A/B Zip 刷机包至非活动槽位: {1}
- 如需刷入其它的 Zip 刷机包,请重启 Recovery 切换到新槽位。
+ 请重启 TWRP 切换到新槽位后,再刷入其它的 ZIP。
+ 刷入到2个槽位
正在解密 Ozip…
Ozip 解密完成!
Fastboot
@@ -750,5 +762,30 @@
2. 格式化 Data 分区;
3. 重新刷入您的 ROM。
报告的问题为:
+ 无法获取 {1} 的默认 context -- Android 可能无法启动。
+ 更改 TWRP 文件夹
+ 正在更改 TWRP 文件夹
+ TWRP文件夹已改为
+ 已存在同名文件夹!
+ 取消 Super Devices 映射
+ 是否取消所有 Super Devices 映射?
+ 正在取消映射 Super Devices...
+ 取消所有 Super Devices 映射完成!
+ 合并快照
+ 是否合并快照?
+ 正在合并快照...
+ 合并快照完成!
+ 在重新启动 TWRP 之前,Super Devices 上的分区可能不会挂载。
+ 是否在 PIN码/混合密码 启用时进行恢复?
+ 是否在 图案密码 启用时恢复?
+ 是否在 PIN码 启用时恢复?
+ 是否继续恢复?
+ ROM中的 PIN码/混合密码 已启用
+ 恢复前应该在 ROM 中禁用 PIN码/混合密码
+ ROM中的 PIN码 已启用
+ 恢复前应该在 ROM 中禁用 PIN码
+ ROM 中的 图案密码 已启用
+ 恢复前应该在 ROM 中禁用 图案密码
+ 建议在 Android 首次启动后再重启一次。
diff --git a/gui/theme/landscape_hdpi/splash.xml b/gui/theme/landscape_hdpi/splash.xml
index b9d78536..56391bde 100644
--- a/gui/theme/landscape_hdpi/splash.xml
+++ b/gui/theme/landscape_hdpi/splash.xml
@@ -5,7 +5,7 @@
TeamWin
TWRP
splash screen
- 4
+ {themeversion}
diff --git a/gui/theme/landscape_hdpi/ui.xml b/gui/theme/landscape_hdpi/ui.xml
index da3c5fca..bd055bd5 100755
--- a/gui/theme/landscape_hdpi/ui.xml
+++ b/gui/theme/landscape_hdpi/ui.xml
@@ -6,7 +6,7 @@
Backup Naowz
Default basic theme
preview.png
- 4
+ {themeversion}
diff --git a/gui/theme/landscape_mdpi/splash.xml b/gui/theme/landscape_mdpi/splash.xml
index a2098fbb..ea87310d 100644
--- a/gui/theme/landscape_mdpi/splash.xml
+++ b/gui/theme/landscape_mdpi/splash.xml
@@ -5,7 +5,7 @@
TeamWin
TWRP
splash screen
- 4
+ {themeversion}
diff --git a/gui/theme/landscape_mdpi/ui.xml b/gui/theme/landscape_mdpi/ui.xml
index e29aa6bf..9ab8863d 100755
--- a/gui/theme/landscape_mdpi/ui.xml
+++ b/gui/theme/landscape_mdpi/ui.xml
@@ -6,7 +6,7 @@
Backup Naowz
Default basic theme
preview.png
- 4
+ {themeversion}
diff --git a/gui/theme/portrait_hdpi/splash.xml b/gui/theme/portrait_hdpi/splash.xml
index f0b07568..f793afaa 100644
--- a/gui/theme/portrait_hdpi/splash.xml
+++ b/gui/theme/portrait_hdpi/splash.xml
@@ -5,7 +5,7 @@
TeamWin
TWRP
splash screen
- 4
+ {themeversion}
diff --git a/gui/theme/portrait_hdpi/ui.xml b/gui/theme/portrait_hdpi/ui.xml
index 70df4e88..f7d21da3 100755
--- a/gui/theme/portrait_hdpi/ui.xml
+++ b/gui/theme/portrait_hdpi/ui.xml
@@ -6,7 +6,7 @@
Backup Naowz
Default basic theme
preview.png
- 4
+ {themeversion}
diff --git a/gui/theme/portrait_mdpi/splash.xml b/gui/theme/portrait_mdpi/splash.xml
index 4ce64b35..b0b97ee5 100644
--- a/gui/theme/portrait_mdpi/splash.xml
+++ b/gui/theme/portrait_mdpi/splash.xml
@@ -5,7 +5,7 @@
TeamWin
TWRP
splash screen
- 4
+ {themeversion}
diff --git a/gui/theme/portrait_mdpi/ui.xml b/gui/theme/portrait_mdpi/ui.xml
index 9ed1a20a..9189df0c 100755
--- a/gui/theme/portrait_mdpi/ui.xml
+++ b/gui/theme/portrait_mdpi/ui.xml
@@ -6,7 +6,7 @@
Backup Naowz
Default basic theme
preview.png
- 4
+ {themeversion}
diff --git a/gui/theme/watch_mdpi/splash.xml b/gui/theme/watch_mdpi/splash.xml
index 62e8dc37..2ce71b38 100644
--- a/gui/theme/watch_mdpi/splash.xml
+++ b/gui/theme/watch_mdpi/splash.xml
@@ -5,7 +5,7 @@
TeamWin
TWRP
splash screen
- 3
+ {themeversion}
diff --git a/gui/theme/watch_mdpi/ui.xml b/gui/theme/watch_mdpi/ui.xml
index 8ec73dff..ed7ac825 100644
--- a/gui/theme/watch_mdpi/ui.xml
+++ b/gui/theme/watch_mdpi/ui.xml
@@ -7,7 +7,7 @@
Backup Naowz
Default basic theme
preview.png
- 4
+ {themeversion}
diff --git a/kernel_module_loader.cpp b/kernel_module_loader.cpp
index 1f30d0df..ebcf4066 100644
--- a/kernel_module_loader.cpp
+++ b/kernel_module_loader.cpp
@@ -1,4 +1,5 @@
#include "kernel_module_loader.hpp"
+#include "common.h"
const std::vector kernel_modules_requested = TWFunc::split_string(EXPAND(TW_LOAD_VENDOR_MODULES), ' ', true);
@@ -33,6 +34,9 @@ bool KernelModuleLoader::Load_Vendor_Modules() {
std::vector release = TWFunc::split_string(rls, '.', true);
int expected_module_count = kernel_modules_requested.size();
module_dirs.push_back(base_dir + "/" + release[0] + "." + release[1]);
+ std::string gki = "/" + release[0] + "." + release[1] + "-gki";
+ module_dirs.push_back(base_dir + gki);
+ vendor_module_dirs.push_back(vendor_base_dir + gki);
for (auto&& module_dir:module_dirs) {
modules_loaded += Try_And_Load_Modules(module_dir, false);
@@ -58,6 +62,10 @@ exit:
if (ven)
ven->UnMount(false);
+ android::base::SetProperty("twrp.modules.loaded", "true");
+
+ TWFunc::Wait_For_Battery(3s);
+
return true;
}
diff --git a/partition.cpp b/partition.cpp
index 89c8b9b4..074cf9f9 100755
--- a/partition.cpp
+++ b/partition.cpp
@@ -133,12 +133,14 @@ enum TW_FSTAB_FLAGS {
TWFLAG_DISPLAY,
TWFLAG_ENCRYPTABLE,
TWFLAG_FILEENCRYPTION,
+ TWFLAG_METADATA_ENCRYPTION,
TWFLAG_FLASHIMG,
TWFLAG_FORCEENCRYPT,
TWFLAG_FSFLAGS,
TWFLAG_IGNOREBLKID,
TWFLAG_LENGTH,
TWFLAG_MOUNTTODECRYPT,
+ TWFLAG_QUOTA,
TWFLAG_REMOVABLE,
TWFLAG_SETTINGSSTORAGE,
TWFLAG_STORAGE,
@@ -180,12 +182,14 @@ const struct flag_list tw_flags[] = {
{ "display=", TWFLAG_DISPLAY },
{ "encryptable=", TWFLAG_ENCRYPTABLE },
{ "fileencryption=", TWFLAG_FILEENCRYPTION },
+ { "metadata_encryption=", TWFLAG_METADATA_ENCRYPTION },
{ "flashimg", TWFLAG_FLASHIMG },
{ "forceencrypt=", TWFLAG_FORCEENCRYPT },
{ "fsflags=", TWFLAG_FSFLAGS },
{ "ignoreblkid", TWFLAG_IGNOREBLKID },
{ "length=", TWFLAG_LENGTH },
{ "mounttodecrypt", TWFLAG_MOUNTTODECRYPT },
+ { "quota", TWFLAG_QUOTA },
{ "removable", TWFLAG_REMOVABLE },
{ "settingsstorage", TWFLAG_SETTINGSSTORAGE },
{ "storage", TWFLAG_STORAGE },
@@ -658,8 +662,6 @@ void TWPartition::Setup_Data_Partition(bool Display_Error) {
UnMount(false);
#ifdef TW_INCLUDE_CRYPTO
- if (datamedia)
- Setup_Data_Media();
Can_Be_Encrypted = true;
char crypto_blkdev[255];
property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error");
@@ -667,6 +669,8 @@ void TWPartition::Setup_Data_Partition(bool Display_Error) {
Set_FBE_Status();
Decrypted_Block_Device = crypto_blkdev;
LOGINFO("Data already decrypted, new block device: '%s'\n", crypto_blkdev);
+ if (datamedia)
+ Setup_Data_Media();
DataManager::SetValue(TW_IS_ENCRYPTED, 0);
} else if (!Mount(false)) {
if (Is_Present) {
@@ -683,18 +687,24 @@ void TWPartition::Setup_Data_Partition(bool Display_Error) {
DataManager::SetValue("tw_crypto_pwtype_0", cryptfs_get_password_type());
DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
DataManager::SetValue("tw_crypto_display", "");
+ if (datamedia)
+ Setup_Data_Media();
} else {
gui_err("mount_data_footer=Could not mount /data and unable to find crypto footer.");
}
} else {
Is_Encrypted = true;
Is_Decrypted = false;
+ if (datamedia)
+ Setup_Data_Media();
}
} else if (Key_Directory.empty()) {
LOGERR("Primary block device '%s' for mount point '%s' is not present!\n",
Primary_Block_Device.c_str(), Mount_Point.c_str());
}
} else {
+ if (Is_Mounted())
+ UnMount(true);
Set_FBE_Status();
int is_device_fbe;
DataManager::GetValue(TW_IS_FBE, is_device_fbe);
@@ -705,6 +715,9 @@ void TWPartition::Setup_Data_Partition(bool Display_Error) {
LOGERR("Unable to decrypt FBE device\n");
} else {
DataManager::SetValue(TW_IS_ENCRYPTED, 0);
+ if (datamedia)
+ Setup_Data_Media();
+
}
}
if (datamedia && (!Is_Encrypted || (Is_Encrypted && Is_Decrypted))) {
@@ -929,6 +942,26 @@ void TWPartition::Apply_TW_Flag(const unsigned flag, const char* str, const bool
LOGINFO("FBE contents '%s', filenames '%s'\n", FBE_contents.c_str(), FBE_filenames.c_str());
}
break;
+ case TWFLAG_METADATA_ENCRYPTION:
+ // This flag isn't used by TWRP but is needed for FBEv2 metadata decryption
+ // metadata_encryption=aes-256-xts:wrappedkey_v0
+ {
+ std::string META = str;
+ size_t colon_loc = META.find(":");
+ if (colon_loc == std::string::npos) {
+ property_set("metadata.contents", META.c_str());
+ property_set("metadata.filenames", "");
+ LOGINFO("Metadata contents '%s', filenames ''\n", META.c_str());
+ break;
+ }
+ std::string META_contents, META_filenames;
+ META_contents = META.substr(0, colon_loc);
+ META_filenames = META.substr(colon_loc + 1);
+ property_set("metadata.contents", META_contents.c_str());
+ property_set("metadata.filenames", META_filenames.c_str());
+ LOGINFO("Metadata contents '%s', filenames '%s'\n", META_contents.c_str(), META_filenames.c_str());
+ }
+ break;
case TWFLAG_WRAPPEDKEY:
// no more processing needed. leaving it here in case we want to do something in the future
break;
@@ -947,6 +980,9 @@ void TWPartition::Apply_TW_Flag(const unsigned flag, const char* str, const bool
case TWFLAG_MOUNTTODECRYPT:
Mount_To_Decrypt = val;
break;
+ case TWFLAG_QUOTA:
+ // Filesystem flag - TWRP does not need to process
+ break;
case TWFLAG_REMOVABLE:
Removable = val;
break;
@@ -1194,7 +1230,8 @@ void TWPartition::Setup_Data_Media() {
Make_Dir("/sdcard", false);
Symlink_Mount_Point = "/sdcard";
}
- if (Mount(false) && TWFunc::Path_Exists(Mount_Point + "/media/0")) {
+ Mount(false);
+ if (TWFunc::Path_Exists(Mount_Point + "/media/0")) {
Storage_Path = Mount_Point + "/media/0";
Symlink_Path = Storage_Path;
DataManager::SetValue(TW_INTERNAL_PATH, Mount_Point + "/media/0");
@@ -1206,6 +1243,7 @@ void TWPartition::Setup_Data_Media() {
backup_exclusions.add_absolute_dir("/data/per_boot"); // DJ9,14Jan2020 - exclude this dir to prevent "error 255" on AOSP ROMs that create and lock it
backup_exclusions.add_absolute_dir("/data/vendor/dumpsys");
backup_exclusions.add_absolute_dir("/data/cache");
+ backup_exclusions.add_absolute_dir("/data/misc/apexdata/com.android.art"); // exclude this dir to prevent "error 255" on AOSP Android 12
wipe_exclusions.add_absolute_dir(Mount_Point + "/misc/vold"); // adopted storage keys
ExcludeAll(Mount_Point + "/system/storage.xml");
} else {
@@ -1604,7 +1642,7 @@ bool TWPartition::Mount(bool Display_Error) {
if (Removable)
Update_Size(Display_Error);
- if (!Symlink_Mount_Point.empty() && Symlink_Mount_Point != "/sdcard") {
+ if (!Symlink_Mount_Point.empty()) {
if (!Bind_Mount(false))
return false;
}
diff --git a/partitionmanager.cpp b/partitionmanager.cpp
index 8d1b6c43..b24beb3e 100755
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -421,8 +421,12 @@ void TWPartitionManager::Decrypt_Data() {
TWPartition* Decrypt_Data = Find_Partition_By_Path("/data");
if (Decrypt_Data && Decrypt_Data->Is_Encrypted && !Decrypt_Data->Is_Decrypted) {
Set_Crypto_State();
- if (!Decrypt_Data->Key_Directory.empty() && Mount_By_Path(Decrypt_Data->Key_Directory, false)) {
- Set_Crypto_Type("file");
+ TWPartition* Key_Directory_Partition = Find_Partition_By_Path(Decrypt_Data->Key_Directory);
+ if (Key_Directory_Partition != nullptr)
+ if (!Key_Directory_Partition->Is_Mounted())
+ Mount_By_Path(Decrypt_Data->Key_Directory, false);
+ if (!Decrypt_Data->Key_Directory.empty()) {
+ Set_Crypto_Type("file");
#ifdef TW_INCLUDE_FBE_METADATA_DECRYPT
#ifdef USE_FSCRYPT
if (fscrypt_mount_metadata_encrypted(Decrypt_Data->Actual_Block_Device, Decrypt_Data->Mount_Point, false)) {
@@ -477,8 +481,7 @@ void TWPartitionManager::Decrypt_Data() {
}
}
}
- if (Decrypt_Data && (!Decrypt_Data->Is_Encrypted || Decrypt_Data->Is_Decrypted) &&
- Decrypt_Data->Mount(false)) {
+ if (Decrypt_Data && (!Decrypt_Data->Is_Encrypted || Decrypt_Data->Is_Decrypted)) {
Decrypt_Adopted();
}
#endif
@@ -1817,8 +1820,10 @@ void TWPartitionManager::Post_Decrypt(const string& Block_Device) {
DataManager::LoadTWRPFolderInfo();
Update_System_Details();
Output_Partition(dat);
- if (!dat->Bind_Mount(false))
- LOGERR("Unable to bind mount /sdcard to %s\n", dat->Storage_Path.c_str());
+ if (!android::base::StartsWith(dat->Actual_Block_Device, "/dev/block/mmcblk")) {
+ if (!dat->Bind_Mount(false))
+ LOGERR("Unable to bind mount /sdcard to %s\n", dat->Storage_Path.c_str());
+ }
} else
LOGERR("Unable to locate data partition.\n");
}
diff --git a/startupArgs.cpp b/startupArgs.cpp
index bf74f871..954f3f5a 100755
--- a/startupArgs.cpp
+++ b/startupArgs.cpp
@@ -58,7 +58,7 @@ bool startupArgs::processRecoveryArgs(std::vector args, int index)
LOGERR("argument error specifying zip file\n");
} else {
std::string ORSCommand = "install " + arg;
- SkipDecryption = arg.find("@") == 1;
+ SkipDecryption = arg.find("@") == 0;
if (!OpenRecoveryScript::Insert_ORS_Command(ORSCommand))
return false;
}
diff --git a/twrp-functions.cpp b/twrp-functions.cpp
index df7d1e2c..2b75cda9 100755
--- a/twrp-functions.cpp
+++ b/twrp-functions.cpp
@@ -38,8 +38,10 @@
#include
#include
#include
+#include
#include
+#include
#include "twrp-functions.hpp"
#include "twcommon.h"
@@ -407,6 +409,30 @@ int32_t TWFunc::timespec_diff_ms(timespec& start, timespec& end)
((start.tv_sec * 1000) + start.tv_nsec/1000000);
}
+bool TWFunc::Wait_For_File(const string& path, std::chrono::nanoseconds timeout) {
+ android::base::Timer t;
+ while (t.duration() < timeout) {
+ struct stat sb;
+ if (stat(path.c_str(), &sb) != -1) {
+ return true;
+ }
+ std::this_thread::sleep_for(10ms);
+ }
+ return false;
+}
+
+bool TWFunc::Wait_For_Battery(std::chrono::nanoseconds timeout) {
+ std::string battery_path;
+#ifdef TW_CUSTOM_BATTERY_PATH
+ battery_path = EXPAND(TW_CUSTOM_BATTERY_PATH);
+#else
+ battery_path = "/sys/class/power_supply/battery";
+#endif
+ if (!battery_path.empty()) return TWFunc::Wait_For_File(battery_path, timeout);
+
+ return false;
+}
+
#ifndef BUILD_TWRPTAR_MAIN
// Returns "/path" from a full /path/to/file.name
@@ -859,16 +885,21 @@ string TWFunc::Get_Current_Date() {
}
string TWFunc::System_Property_Get(string Prop_Name) {
- return System_Property_Get(Prop_Name, PartitionManager, PartitionManager.Get_Android_Root_Path(), "build.prop");
+ return Partition_Property_Get(Prop_Name, PartitionManager, PartitionManager.Get_Android_Root_Path(), "build.prop");
}
-string TWFunc::System_Property_Get(string Prop_Name, TWPartitionManager &PartitionManager, string Mount_Point, string prop_file_name) {
+string TWFunc::Partition_Property_Get(string Prop_Name, TWPartitionManager &PartitionManager, string Mount_Point, string prop_file_name) {
bool mount_state = PartitionManager.Is_Mounted_By_Path(Mount_Point);
std::vector buildprop;
string propvalue;
+ string prop_file;
if (!PartitionManager.Mount_By_Path(Mount_Point, true))
return propvalue;
- string prop_file = Mount_Point + "/system/" + prop_file_name;
+ if (Mount_Point == PartitionManager.Get_Android_Root_Path()) {
+ prop_file = Mount_Point + "/system/" + prop_file_name;
+ } else {
+ prop_file = Mount_Point + "/" + prop_file_name;
+ }
if (!TWFunc::Path_Exists(prop_file)) {
LOGINFO("Unable to locate file: %s\n", prop_file.c_str());
return propvalue;
@@ -1030,6 +1061,16 @@ void TWFunc::Fixup_Time_On_Boot(const string& time_paths /* = "" */)
}
if (!fixed) {
+#ifdef TW_QCOM_ATS_OFFSET
+ // Offset is the difference between the current time and the time since_epoch
+ // To calculate the offset in Android, the following expression (from a root shell) can be used:
+ // echo "$(( ($(date +%s) - $(cat /sys/class/rtc/rtc0/since_epoch)) ))"
+ // Add 3 zeros to the output and use that in the TW_QCOM_ATS_OFFSET flag in your BoardConfig.mk
+ // For example, if the result of the calculation is 1642433544, use 1642433544000 as the offset
+ offset = (uint64_t) TW_QCOM_ATS_OFFSET;
+ DataManager::SetValue("tw_qcom_ats_offset", (unsigned long long) offset, 1);
+ LOGINFO("TWFunc::Fixup_Time: Setting time offset from TW_QCOM_ATS_OFFSET, offset %llu\n", (unsigned long long) offset);
+#else
// Failed to get offset from ats file, check twrp settings
unsigned long long value;
if (DataManager::GetValue("tw_qcom_ats_offset", value) < 0) {
@@ -1039,6 +1080,7 @@ void TWFunc::Fixup_Time_On_Boot(const string& time_paths /* = "" */)
LOGINFO("TWFunc::Fixup_Time: Setting time offset from twrp setting file, offset %llu\n", (unsigned long long) offset);
// Do not consider the settings file as a definitive answer, keep fixed=false so next run will try ats files again
}
+#endif
}
gettimeofday(&tv, NULL);
diff --git a/twrp-functions.hpp b/twrp-functions.hpp
index 01afb7aa..4c25cf42 100755
--- a/twrp-functions.hpp
+++ b/twrp-functions.hpp
@@ -74,6 +74,8 @@ public:
static vector split_string(const string &in, char del, bool skip_empty);
static timespec timespec_diff(timespec& start, timespec& end); // Return a diff for 2 times
static int32_t timespec_diff_ms(timespec& start, timespec& end); // Returns diff in ms
+ static bool Wait_For_File(const string& path, std::chrono::nanoseconds timeout); // Wait For File, True is success, False is timeout;
+ static bool Wait_For_Battery(std::chrono::nanoseconds timeout); // Wait For /sys/class/power_supply/battery or TW_CUSTOM_BATTERY_PATH, True is success, False is timeout;
#ifndef BUILD_TWRPTAR_MAIN
static void install_htc_dumlock(void); // Installs HTC Dumlock
@@ -96,7 +98,7 @@ public:
static bool write_to_file(const string& fn, const std::vector lines); // write vector of strings line by line with newlines
static bool Try_Decrypting_Backup(string Restore_Path, string Password); // true for success, false for failed to decrypt
static string System_Property_Get(string Prop_Name); // Returns value of Prop_Name from reading /system/build.prop
- static string System_Property_Get(string Prop_Name, TWPartitionManager &PartitionManager, string Mount_Point, string prop_file_name); // Returns value of Prop_Name from reading provided prop file
+ static string Partition_Property_Get(string Prop_Name, TWPartitionManager &PartitionManager, string Mount_Point, string prop_file_name); // Returns value of Prop_Name from reading provided prop file
static string Get_Current_Date(void); // Returns the current date in ccyy-m-dd--hh-nn-ss format
static void Auto_Generate_Backup_Name(); // Populates TW_BACKUP_NAME with a backup name based on current date and ro.build.display.id from /system/build.prop
static void Fixup_Time_On_Boot(const string& time_paths = ""); // Fixes time on devices which need it (time_paths is a space separated list of paths to check for ats_* files)
diff --git a/twrp.cpp b/twrp.cpp
index d2cbf526..9a317e89 100644
--- a/twrp.cpp
+++ b/twrp.cpp
@@ -122,6 +122,9 @@ static void process_fastbootd_mode() {
#endif
gui_msg(Msg("fastboot_console_msg=Entered Fastboot mode..."));
+ // Check for and run startup script if script exists
+ TWFunc::check_and_run_script("/system/bin/runatboot.sh", "boot");
+ TWFunc::check_and_run_script("/system/bin/postfastboot.sh", "fastboot");
if (gui_startPage("fastboot", 1, 1) != 0) {
LOGERR("Failed to start fastbootd page.\n");
}
@@ -172,42 +175,62 @@ static void process_recovery_mode(twrpAdbBuFifo* adb_bu_fifo, bool skip_decrypti
// We are doing this here to allow super partition to be set up prior to overriding properties
#if defined(TW_INCLUDE_LIBRESETPROP) && defined(TW_OVERRIDE_SYSTEM_PROPS)
- if (!PartitionManager.Mount_By_Path(PartitionManager.Get_Android_Root_Path(), true)) {
- LOGERR("Unable to mount %s\n", PartitionManager.Get_Android_Root_Path().c_str());
- } else {
- stringstream override_props(EXPAND(TW_OVERRIDE_SYSTEM_PROPS));
- string current_prop;
- std::vector build_prop_list = {"build.prop"};
-#ifdef TW_SYSTEM_BUILD_PROP_ADDITIONAL_PATHS
- std::vector additional_build_prop_list = TWFunc::Split_String(TW_SYSTEM_BUILD_PROP_ADDITIONAL_PATHS, ";");
- build_prop_list.insert(build_prop_list.end(), additional_build_prop_list.begin(), additional_build_prop_list.end());
-#endif
- while (getline(override_props, current_prop, ';')) {
- string other_prop;
- if (current_prop.find("=") != string::npos) {
- other_prop = current_prop.substr(current_prop.find("=") + 1);
- current_prop = current_prop.substr(0, current_prop.find("="));
- } else {
- other_prop = current_prop;
- }
- other_prop = android::base::Trim(other_prop);
- current_prop = android::base::Trim(current_prop);
+ stringstream override_props(EXPAND(TW_OVERRIDE_SYSTEM_PROPS));
+ string current_prop;
+ std::vector partition_list;
+ partition_list.push_back (PartitionManager.Get_Android_Root_Path().c_str());
+#ifdef TW_OVERRIDE_PROPS_ADDITIONAL_PARTITIONS
+ std::vector additional_partition_list = TWFunc::Split_String(TW_OVERRIDE_PROPS_ADDITIONAL_PARTITIONS, " ");
+ partition_list.insert(partition_list.end(), additional_partition_list.begin(), additional_partition_list.end());
+#endif
+ std::vector build_prop_list = {"build.prop"};
+#ifdef TW_SYSTEM_BUILD_PROP_ADDITIONAL_PATHS
+ std::vector additional_build_prop_list = TWFunc::Split_String(TW_SYSTEM_BUILD_PROP_ADDITIONAL_PATHS, ";");
+ build_prop_list.insert(build_prop_list.end(), additional_build_prop_list.begin(), additional_build_prop_list.end());
+#endif
+ while (getline(override_props, current_prop, ';')) {
+ string other_prop;
+ if (current_prop.find("=") != string::npos) {
+ other_prop = current_prop.substr(current_prop.find("=") + 1);
+ current_prop = current_prop.substr(0, current_prop.find("="));
+ } else {
+ other_prop = current_prop;
+ }
+ other_prop = android::base::Trim(other_prop);
+ current_prop = android::base::Trim(current_prop);
+
+ for (auto&& partition_mount_point:partition_list) {
for (auto&& prop_file:build_prop_list) {
- string sys_val = TWFunc::System_Property_Get(other_prop, PartitionManager, PartitionManager.Get_Android_Root_Path().c_str(), prop_file);
+ string sys_val = TWFunc::Partition_Property_Get(other_prop, PartitionManager, partition_mount_point.c_str(), prop_file);
if (!sys_val.empty()) {
- LOGINFO("Overriding %s with value: \"%s\" from system property %s from %s\n", current_prop.c_str(), sys_val.c_str(), other_prop.c_str(), prop_file.c_str());
+ if (partition_mount_point == "/system_root") {
+ LOGINFO("Overriding %s with value: \"%s\" from property %s in /system/%s\n", current_prop.c_str(), sys_val.c_str(), other_prop.c_str(),
+ prop_file.c_str());
+ } else {
+ LOGINFO("Overriding %s with value: \"%s\" from property %s in /%s/%s\n", current_prop.c_str(), sys_val.c_str(), other_prop.c_str(),
+ partition_mount_point.c_str(), prop_file.c_str());
+ }
int error = TWFunc::Property_Override(current_prop, sys_val);
if (error) {
LOGERR("Failed overriding property %s, error_code: %d\n", current_prop.c_str(), error);
}
- break;
+ if (partition_mount_point == partition_list.back()) {
+ PartitionManager.UnMount_By_Path(partition_mount_point, false);
+ }
+ goto exit;
} else {
- LOGINFO("Not overriding %s with empty value from system property %s from %s\n", current_prop.c_str(), other_prop.c_str(), prop_file.c_str());
+ if (partition_mount_point == "/system_root") {
+ LOGINFO("Unable to override property %s: property not found in /system/%s\n", current_prop.c_str(), prop_file.c_str());
+ } else {
+ LOGINFO("Unable to override property %s: property not found in /%s/%s\n", current_prop.c_str(), partition_mount_point.c_str(), prop_file.c_str());
+ }
}
}
+ PartitionManager.UnMount_By_Path(partition_mount_point, false);
}
- PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), false);
+ exit:
+ continue;
}
#endif
@@ -377,6 +400,10 @@ int main(int argc, char **argv) {
property_set("ro.twrp.boot", "1");
property_set("ro.twrp.version", TW_VERSION_STR);
+#ifdef TARGET_OTA_ASSERT_DEVICE
+ property_set("ro.twrp.target.devices", TARGET_OTA_ASSERT_DEVICE);
+#endif
+
time_t StartupTime = time(NULL);
printf("Starting TWRP %s-%s on %s (pid %d)\n", TW_VERSION_STR, TW_GIT_REVISION, ctime(&StartupTime), getpid());
diff --git a/twrpRepacker.cpp b/twrpRepacker.cpp
index 5a59fc6b..6ac2ce90 100755
--- a/twrpRepacker.cpp
+++ b/twrpRepacker.cpp
@@ -208,56 +208,53 @@ bool twrpRepacker::Repack_Image_And_Flash(const std::string& Target_Image, const
}
DataManager::SetProgress(1);
TWFunc::removeDir(REPACK_ORIG_DIR, false);
- if (part->Is_SlotSelect()) { if (Repack_Options.Type == REPLACE_RAMDISK || Repack_Options.Type == REPLACE_RAMDISK_UNPACKED) {
- LOGINFO("Switching slots to flash ramdisk to both partitions\n");
- string Current_Slot = PartitionManager.Get_Active_Slot_Display();
- if (Current_Slot == "A")
- PartitionManager.Override_Active_Slot("B");
- else
- PartitionManager.Override_Active_Slot("A");
- DataManager::SetProgress(.25);
- if (!Backup_Image_For_Repack(part, REPACK_ORIG_DIR, Repack_Options.Backup_First, gui_lookup("repack", "Repack")))
- return false;
- if (TWFunc::copy_file(REPACK_NEW_DIR "ramdisk.cpio", REPACK_ORIG_DIR "ramdisk.cpio", 0644)) {
- LOGERR("Failed to copy ramdisk\n");
- return false;
- }
- path = REPACK_ORIG_DIR;
- std::string command = "cd " + path + " && /system/bin/magiskboot repack ";
+ if (part->Is_SlotSelect()) {
+ if (Repack_Options.Type == REPLACE_RAMDISK || Repack_Options.Type == REPLACE_RAMDISK_UNPACKED) {
+ LOGINFO("Switching slots to flash ramdisk to both partitions\n");
+ string Current_Slot = PartitionManager.Get_Active_Slot_Display();
+ if (Current_Slot == "A")
+ PartitionManager.Override_Active_Slot("B");
+ else
+ PartitionManager.Override_Active_Slot("A");
+ DataManager::SetProgress(.25);
+ if (!Backup_Image_For_Repack(part, REPACK_ORIG_DIR, Repack_Options.Backup_First, gui_lookup("repack", "Repack")))
+ return false;
+ if (TWFunc::copy_file(REPACK_NEW_DIR "ramdisk.cpio", REPACK_ORIG_DIR "ramdisk.cpio", 0644)) {
+ LOGERR("Failed to copy ramdisk\n");
+ return false;
+ }
+ path = REPACK_ORIG_DIR;
+ std::string command = "cd " + path + " && /system/bin/magiskboot repack ";
- if (original_ramdisk_format != image_ramdisk_format) {
- recompress = true;
- }
- command += path + "boot.img";
+ if (original_ramdisk_format != image_ramdisk_format) {
+ recompress = true;
+ }
+ command += path + "boot.img";
- if (recompress) {
- std::string decompress_cmd = "/system/bin/magiskboot decompress " + orig_compressed_image + " " + copy_compressed_image;
- if (TWFunc::Exec_Cmd(decompress_cmd) != 0) {
+ if (recompress) {
+ std::string decompress_cmd = "/system/bin/magiskboot decompress " + orig_compressed_image + " " + copy_compressed_image;
+ if (TWFunc::Exec_Cmd(decompress_cmd) != 0) {
+ gui_msg(Msg(msg::kError, "repack_error=Error repacking image."));
+ return false;
+ }
+ std::rename(copy_compressed_image.c_str(), orig_compressed_image.c_str());
+ }
+
+ if (TWFunc::Exec_Cmd(command) != 0) {
gui_msg(Msg(msg::kError, "repack_error=Error repacking image."));
return false;
}
- std::rename(copy_compressed_image.c_str(), orig_compressed_image.c_str());
+ DataManager::SetProgress(.75);
+ std::string file = "new-boot.img";
+ DataManager::SetValue("tw_flash_partition", "/boot;");
+ if (!PartitionManager.Flash_Image(path, file)) {
+ LOGINFO("Error flashing new image\n");
+ return false;
+ }
+ DataManager::SetProgress(1);
+ TWFunc::removeDir(REPACK_ORIG_DIR, false);
}
-
- if (TWFunc::Exec_Cmd(command) != 0) {
- gui_msg(Msg(msg::kError, "repack_error=Error repacking image."));
- return false;
- }
-
- if (TWFunc::Exec_Cmd(command) != 0) {
- gui_msg(Msg(msg::kError, "repack_error=Error repacking image."));
- return false;
- }
- DataManager::SetProgress(.75);
- std::string file = "new-boot.img";
- DataManager::SetValue("tw_flash_partition", "/boot;");
- if (!PartitionManager.Flash_Image(path, file)) {
- LOGINFO("Error flashing new image\n");
- return false;
- }
- DataManager::SetProgress(1);
- TWFunc::removeDir(REPACK_ORIG_DIR, false);
- }}
+ }
TWFunc::removeDir(REPACK_NEW_DIR, false);
gui_msg(Msg(msg::kWarning, "repack_overwrite_warning=If device was previously rooted, then root has been overwritten and will need to be reinstalled."));
string Current_Slot = PartitionManager.Get_Active_Slot_Display();
diff --git a/twrpinstall/installcommand.cpp b/twrpinstall/installcommand.cpp
index d577b383..88c90f8c 100755
--- a/twrpinstall/installcommand.cpp
+++ b/twrpinstall/installcommand.cpp
@@ -132,6 +132,15 @@ static int check_newer_ab_build(ZipArchiveHandle zip)
bool deviceExists = false;
+ // twrp.target.devices
+ bool has_target_devices = false;
+ char tw_devices[PROPERTY_VALUE_MAX * 2];
+ property_get("ro.twrp.target.devices", tw_devices, "");
+ std::vector TWRP_devices = android::base::Split(tw_devices, ",");
+ if (strlen(tw_devices) > 1) {
+ has_target_devices = true;
+ }
+
for(const std::string& deviceAssert : assertResults)
{
std::string assertName = android::base::Trim(deviceAssert);
@@ -139,6 +148,17 @@ static int check_newer_ab_build(ZipArchiveHandle zip)
deviceExists = true;
break;
}
+ // twrp.target.devices
+ else if (has_target_devices) {
+ for(const std::string& twrpDevice_x : TWRP_devices) {
+ std::string twrpName = android::base::Trim(twrpDevice_x);
+ if (!twrpName.empty() && !assertName.empty() && assertName == twrpName) {
+ deviceExists = true;
+ printf("Package is for product %s. The selected TWRP target device is %s\n", pkg_device.c_str(), twrpName.c_str());
+ break;
+ }
+ }
+ }
}
if (!deviceExists) {
diff --git a/twrpinstall/twinstall.cpp b/twrpinstall/twinstall.cpp
index e1f84150..7975a978 100755
--- a/twrpinstall/twinstall.cpp
+++ b/twrpinstall/twinstall.cpp
@@ -354,7 +354,7 @@ int TWinstall_zip(const char* path, int* wipe_cache, bool check_for_digest) {
} else {
std::string binary_name("ui.xml");
ZipEntry64 binary_entry;
- if (FindEntry(Zip, binary_name, &binary_entry) != 0) {
+ if (FindEntry(Zip, binary_name, &binary_entry) == 0) {
LOGINFO("TWRP theme zip\n");
ret_val = Install_Theme(path, Zip);
} else {
diff --git a/variables.h b/variables.h
index aeb26693..8da69e94 100755
--- a/variables.h
+++ b/variables.h
@@ -149,6 +149,12 @@
#define TW_IS_SUPER "tw_is_super"
#define TW_AUTO_REFLASHTWRP_VAR "tw_auto_reflashtwrp"
+// Theme versioning
+// version 2 requires theme to handle power button as action togglebacklight
+// version 4 adds listbox support to reboot page
+// version 5 adds File Manager options, nano & Flash Current TWRP
+#define TW_THEME_VERSION 5
+
// Also used:
// tw_boot_is_mountable
// tw_system_is_mountable