blob: e7b2f613089e35686b1041e9f073565f608ac1c1 [file] [log] [blame]
/*
Copyright 2012 to 2016 bigbiff/Dees_Troy TeamWin
This file is part of TWRP/TeamWin Recovery Project.
TWRP is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
TWRP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with TWRP. If not, see <http://www.gnu.org/licenses/>.
*/
#include <pthread.h>
#include <time.h>
#include <string>
#include <sstream>
#include <fstream>
#include <cctype>
#include <cutils/properties.h>
#include <unistd.h>
#include "variables.h"
#include "data.hpp"
#include "partitions.hpp"
#include "twrp-functions.hpp"
#ifndef TW_NO_SCREEN_TIMEOUT
#include "gui/blanktimer.hpp"
#endif
#include "find_file.hpp"
#include "set_metadata.h"
#include "gui/gui.hpp"
#include "infomanager.hpp"
#define DEVID_MAX 64
#define HWID_MAX 32
extern "C"
{
#include "twcommon.h"
#include "gui/pages.h"
void gui_notifyVarChange(const char *name, const char* value);
}
#include "minuitwrp/minui.h"
#define FILE_VERSION 0x00010010 // Do not set to 0
using namespace std;
string DataManager::mBackingFile;
int DataManager::mInitialized = 0;
InfoManager DataManager::mPersist; // Data that that is not constant and will be saved to the settings file
InfoManager DataManager::mData; // Data that is not constant and will not be saved to settings file
InfoManager DataManager::mConst; // Data that is constant and will not be saved to settings file
extern bool datamedia;
#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
pthread_mutex_t DataManager::m_valuesLock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
#else
pthread_mutex_t DataManager::m_valuesLock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
#endif
// Device ID functions
void DataManager::sanitize_device_id(char* device_id) {
const char* whitelist ="-._";
char str[DEVID_MAX];
char* c = str;
snprintf(str, DEVID_MAX, "%s", device_id);
memset(device_id, 0, strlen(device_id));
while (*c) {
if (isalnum(*c) || strchr(whitelist, *c))
strncat(device_id, c, 1);
c++;
}
return;
}
#define CMDLINE_SERIALNO "androidboot.serialno="
#define CMDLINE_SERIALNO_LEN (strlen(CMDLINE_SERIALNO))
#define CPUINFO_SERIALNO "Serial"
#define CPUINFO_SERIALNO_LEN (strlen(CPUINFO_SERIALNO))
#define CPUINFO_HARDWARE "Hardware"
#define CPUINFO_HARDWARE_LEN (strlen(CPUINFO_HARDWARE))
void DataManager::get_device_id(void) {
FILE *fp;
char line[2048];
char hardware_id[HWID_MAX] = { 0 };
char device_id[DEVID_MAX] = { 0 };
char* token;
#ifdef TW_USE_MODEL_HARDWARE_ID_FOR_DEVICE_ID
// Use (product_model)_(hardware_id) as device id
char model_id[PROPERTY_VALUE_MAX];
property_get("ro.product.model", model_id, "error");
if (strcmp(model_id, "error") != 0) {
LOGINFO("=> product model: '%s'\n", model_id);
// Replace spaces with underscores
for (size_t i = 0; i < strlen(model_id); i++) {
if (model_id[i] == ' ')
model_id[i] = '_';
}
snprintf(device_id, DEVID_MAX, "%s", model_id);
if (strlen(device_id) < DEVID_MAX) {
fp = fopen("proc_cpuinfo.txt", "rt");
if (fp != NULL) {
while (fgets(line, sizeof(line), fp) != NULL) {
if (memcmp(line, CPUINFO_HARDWARE,
CPUINFO_HARDWARE_LEN) == 0) {
// skip past "Hardware", spaces, and colon
token = line + CPUINFO_HARDWARE_LEN;
while (*token && (!isgraph(*token) || *token == ':'))
token++;
if (*token && *token != '\n'
&& strcmp("UNKNOWN\n", token)) {
snprintf(hardware_id, HWID_MAX, "%s", token);
if (hardware_id[strlen(hardware_id)-1] == '\n')
hardware_id[strlen(hardware_id)-1] = 0;
LOGINFO("=> hardware id from cpuinfo: '%s'\n",
hardware_id);
}
break;
}
}
fclose(fp);
}
}
if (hardware_id[0] != 0)
snprintf(device_id, DEVID_MAX, "%s_%s", model_id, hardware_id);
sanitize_device_id(device_id);
mConst.SetValue("device_id", device_id);
LOGINFO("=> using device id: '%s'\n", device_id);
return;
}
#endif
#ifndef TW_FORCE_CPUINFO_FOR_DEVICE_ID
#ifdef TW_USE_SERIALNO_PROPERTY_FOR_DEVICE_ID
// Check serial number system property
if (property_get("ro.serialno", line, "")) {
snprintf(device_id, DEVID_MAX, "%s", line);
sanitize_device_id(device_id);
mConst.SetValue("device_id", device_id);
return;
}
#endif
// Check the cmdline to see if the serial number was supplied
fp = fopen("/proc/cmdline", "rt");
if (fp != NULL) {
fgets(line, sizeof(line), fp);
fclose(fp); // cmdline is only one line long
token = strtok(line, " ");
while (token) {
if (memcmp(token, CMDLINE_SERIALNO, CMDLINE_SERIALNO_LEN) == 0) {
token += CMDLINE_SERIALNO_LEN;
snprintf(device_id, DEVID_MAX, "%s", token);
sanitize_device_id(device_id); // also removes newlines
mConst.SetValue("device_id", device_id);
return;
}
token = strtok(NULL, " ");
}
}
#endif
// Check cpuinfo for serial number; if found, use as device_id
// If serial number is not found, fallback to hardware_id for the device_id
fp = fopen("/proc/cpuinfo", "rt");
if (fp != NULL) {
while (fgets(line, sizeof(line), fp) != NULL) {
if (memcmp(line, CPUINFO_SERIALNO, CPUINFO_SERIALNO_LEN) == 0) {
// skip past "Serial", spaces, and colon
token = line + CPUINFO_SERIALNO_LEN;
while (*token && (!isgraph(*token) || *token == ':'))
token++;
if (*token && *token != '\n') {
snprintf(device_id, DEVID_MAX, "%s", token);
sanitize_device_id(device_id); // also removes newlines
LOGINFO("=> serial from cpuinfo: '%s'\n", device_id);
mConst.SetValue("device_id", device_id);
fclose(fp);
return;
}
} else if (memcmp(line, CPUINFO_HARDWARE,
CPUINFO_HARDWARE_LEN) == 0) {
// skip past "Hardware", spaces, and colon
token = line + CPUINFO_HARDWARE_LEN;
while (*token && (!isgraph(*token) || *token == ':'))
token++;
if (*token && *token != '\n') {
snprintf(hardware_id, HWID_MAX, "%s", token);
if (hardware_id[strlen(hardware_id)-1] == '\n')
hardware_id[strlen(hardware_id)-1] = 0;
LOGINFO("=> hardware id from cpuinfo: '%s'\n", hardware_id);
}
}
}
fclose(fp);
}
if (hardware_id[0] != 0) {
LOGINFO("\nusing hardware id for device id: '%s'\n", hardware_id);
snprintf(device_id, DEVID_MAX, "%s", hardware_id);
sanitize_device_id(device_id);
mConst.SetValue("device_id", device_id);
return;
}
strcpy(device_id, "serialno");
LOGINFO("=> device id not found, using '%s'\n", device_id);
mConst.SetValue("device_id", device_id);
return;
}
int DataManager::ResetDefaults()
{
pthread_mutex_lock(&m_valuesLock);
mPersist.Clear();
mData.Clear();
mConst.Clear();
pthread_mutex_unlock(&m_valuesLock);
SetDefaultValues();
return 0;
}
int DataManager::LoadValues(const string& filename)
{
string dev_id;
if (!mInitialized)
SetDefaultValues();
GetValue("device_id", dev_id);
// Save off the backing file for set operations
mBackingFile = filename;
mPersist.SetFile(filename);
mPersist.SetFileVersion(FILE_VERSION);
// Read in the file, if possible
pthread_mutex_lock(&m_valuesLock);
mPersist.LoadValues();
#ifndef TW_NO_SCREEN_TIMEOUT
blankTimer.setTime(mPersist.GetIntValue("tw_screen_timeout_secs"));
#endif
pthread_mutex_unlock(&m_valuesLock);
string current = GetCurrentStoragePath();
TWPartition* Part = PartitionManager.Find_Partition_By_Path(current);
if (!Part)
Part = PartitionManager.Get_Default_Storage_Partition();
if (Part && current != Part->Storage_Path && Part->Mount(false)) {
LOGINFO("LoadValues setting storage path to '%s'\n", Part->Storage_Path.c_str());
SetValue("tw_storage_path", Part->Storage_Path);
} else {
SetBackupFolder();
}
return 0;
}
int DataManager::Flush()
{
return SaveValues();
}
int DataManager::SaveValues()
{
#ifndef TW_OEM_BUILD
if (mBackingFile.empty())
return -1;
string mount_path = GetSettingsStoragePath();
PartitionManager.Mount_By_Path(mount_path.c_str(), 1);
mPersist.SetFile(mBackingFile);
mPersist.SetFileVersion(FILE_VERSION);
pthread_mutex_lock(&m_valuesLock);
mPersist.SaveValues();
pthread_mutex_unlock(&m_valuesLock);
tw_set_default_metadata(mBackingFile.c_str());
LOGINFO("Saved settings file values to '%s'\n", mBackingFile.c_str());
#endif // ifdef TW_OEM_BUILD
return 0;
}
int DataManager::GetValue(const string& varName, string& value)
{
string localStr = varName;
int ret = 0;
if (!mInitialized)
SetDefaultValues();
// Strip off leading and trailing '%' if provided
if (localStr.length() > 2 && localStr[0] == '%' && localStr[localStr.length()-1] == '%')
{
localStr.erase(0, 1);
localStr.erase(localStr.length() - 1, 1);
}
// Handle magic values
if (GetMagicValue(localStr, value) == 0)
return 0;
// Handle property
if (localStr.length() > 9 && localStr.substr(0, 9) == "property.") {
char property_value[PROPERTY_VALUE_MAX];
property_get(localStr.substr(9).c_str(), property_value, "");
value = property_value;
return 0;
}
pthread_mutex_lock(&m_valuesLock);
ret = mConst.GetValue(localStr, value);
if (ret == 0)
goto exit;
ret = mPersist.GetValue(localStr, value);
if (ret == 0)
goto exit;
ret = mData.GetValue(localStr, value);
exit:
pthread_mutex_unlock(&m_valuesLock);
return ret;
}
int DataManager::GetValue(const string& varName, int& value)
{
string data;
if (GetValue(varName,data) != 0)
return -1;
value = atoi(data.c_str());
return 0;
}
int DataManager::GetValue(const string& varName, float& value)
{
string data;
if (GetValue(varName,data) != 0)
return -1;
value = atof(data.c_str());
return 0;
}
int DataManager::GetValue(const string& varName, unsigned long long& value)
{
string data;
if (GetValue(varName,data) != 0)
return -1;
value = strtoull(data.c_str(), NULL, 10);
return 0;
}
// This function will return an empty string if the value doesn't exist
string DataManager::GetStrValue(const string& varName)
{
string retVal;
GetValue(varName, retVal);
return retVal;
}
// This function will return 0 if the value doesn't exist
int DataManager::GetIntValue(const string& varName)
{
string retVal;
GetValue(varName, retVal);
return atoi(retVal.c_str());
}
int DataManager::SetValue(const string& varName, const string& value, const int persist /* = 0 */)
{
if (!mInitialized)
SetDefaultValues();
// Handle property
if (varName.length() > 9 && varName.substr(0, 9) == "property.") {
int ret = property_set(varName.substr(9).c_str(), value.c_str());
if (ret)
LOGERR("Error setting property '%s' to '%s'\n", varName.substr(9).c_str(), value.c_str());
return ret;
}
// Don't allow empty values or numerical starting values
if (varName.empty() || (varName[0] >= '0' && varName[0] <= '9'))
return -1;
string test;
pthread_mutex_lock(&m_valuesLock);
int constChk = mConst.GetValue(varName, test);
if (constChk == 0) {
pthread_mutex_unlock(&m_valuesLock);
return -1;
}
if (persist) {
mPersist.SetValue(varName, value);
} else {
int persistChk = mPersist.GetValue(varName, test);
if (persistChk == 0) {
mPersist.SetValue(varName, value);
} else {
mData.SetValue(varName, value);
}
}
pthread_mutex_unlock(&m_valuesLock);
#ifndef TW_NO_SCREEN_TIMEOUT
if (varName == "tw_screen_timeout_secs") {
blankTimer.setTime(atoi(value.c_str()));
} else
#endif
if (varName == "tw_storage_path") {
SetBackupFolder();
}
gui_notifyVarChange(varName.c_str(), value.c_str());
return 0;
}
int DataManager::SetValue(const string& varName, const int value, const int persist /* = 0 */)
{
ostringstream valStr;
valStr << value;
return SetValue(varName, valStr.str(), persist);
}
int DataManager::SetValue(const string& varName, const float value, const int persist /* = 0 */)
{
ostringstream valStr;
valStr << value;
return SetValue(varName, valStr.str(), persist);;
}
int DataManager::SetValue(const string& varName, const unsigned long long& value, const int persist /* = 0 */)
{
ostringstream valStr;
valStr << value;
return SetValue(varName, valStr.str(), persist);
}
// For legacy code that doesn't set a scope
int DataManager::SetProgress(const float Fraction) {
if (SetValue("ui_portion_size", 0) != 0)
return -1;
if (SetValue("ui_portion_start", 0) != 0)
return -1;
ShowProgress(1, 0);
int res = _SetProgress(Fraction);
if (SetValue("ui_portion_size", 0) != 0)
return -1;
if (SetValue("ui_portion_start", 0) != 0)
return -1;
return res;
}
int DataManager::_SetProgress(float Fraction) {
float Portion_Start, Portion_Size;
GetValue("ui_portion_size", Portion_Size);
GetValue("ui_portion_start", Portion_Start);
//LOGINFO("SetProgress(%.2lf): Portion_Size: %.2lf Portion_Start: %.2lf\n", Fraction, Portion_Size, Portion_Start);
if (Fraction < 0.0)
Fraction = 0;
if (Fraction > 1.0)
Fraction = 1;
if (SetValue("ui_progress", (float) ((Portion_Start + (Portion_Size * Fraction)) * 100.0)) != 0)
return -1;
return (SetValue("ui_progress_portion", 0) != 0);
}
int DataManager::ShowProgress(float Portion, const float Seconds)
{
float Portion_Start, Portion_Size;
GetValue("ui_portion_size", Portion_Size);
GetValue("ui_portion_start", Portion_Start);
Portion_Start += Portion_Size;
if(Portion + Portion_Start > 1.0)
Portion = 1.0 - Portion_Start;
//LOGINFO("ShowProgress(%.2lf, %.2lf): Portion_Start: %.2lf\n", Portion, Seconds, Portion_Start);
if (SetValue("ui_portion_start", Portion_Start) != 0)
return -1;
if (SetValue("ui_portion_size", Portion) != 0)
return -1;
if (SetValue("ui_progress", (float)(Portion_Start * 100.0)) != 0)
return -1;
if(Seconds) {
if (SetValue("ui_progress_portion", (float)((Portion * 100.0) + Portion_Start)) != 0)
return -1;
if (SetValue("ui_progress_frames", Seconds * 48) != 0)
return -1;
}
return 0;
}
void DataManager::update_tz_environment_variables(void)
{
setenv("TZ", GetStrValue(TW_TIME_ZONE_VAR).c_str(), 1);
tzset();
}
void DataManager::SetBackupFolder()
{
string str = GetCurrentStoragePath();
TWPartition* partition = PartitionManager.Find_Partition_By_Path(str);
str += TWFunc::Check_For_TwrpFolder() + "/BACKUPS/";
string dev_id;
GetValue("device_id", dev_id);
str += dev_id;
LOGINFO("Backup folder set to '%s'\n", str.c_str());
SetValue(TW_BACKUPS_FOLDER_VAR, str, 0);
if (partition != NULL) {
SetValue("tw_storage_display_name", partition->Storage_Name);
char free_space[255];
sprintf(free_space, "%llu", partition->Free / 1024 / 1024);
SetValue("tw_storage_free_size", free_space);
string zip_path, zip_root, storage_path;
GetValue(TW_ZIP_LOCATION_VAR, zip_path);
if (partition->Has_Data_Media && !partition->Symlink_Mount_Point.empty())
storage_path = partition->Symlink_Mount_Point;
else
storage_path = partition->Storage_Path;
if (zip_path.size() < storage_path.size()) {
SetValue(TW_ZIP_LOCATION_VAR, storage_path);
} else {
zip_root = TWFunc::Get_Root_Path(zip_path);
if (zip_root != storage_path) {
LOGINFO("DataManager::SetBackupFolder zip path was %s changing to %s, %s\n", zip_path.c_str(), storage_path.c_str(), zip_root.c_str());
SetValue(TW_ZIP_LOCATION_VAR, storage_path);
}
}
} else {
if (PartitionManager.Fstab_Processed() != 0) {
LOGINFO("Storage partition '%s' not found\n", str.c_str());
gui_err("unable_locate_storage=Unable to locate storage device.");
}
}
}
void DataManager::SetDefaultValues()
{
string str, path;
mConst.SetConst();
get_device_id();
pthread_mutex_lock(&m_valuesLock);
mInitialized = 1;
mConst.SetValue("true", "1");
mConst.SetValue("false", "0");
mConst.SetValue(TW_VERSION_VAR, TW_VERSION_STR);
#ifndef TW_NO_HAPTICS
mPersist.SetValue("tw_button_vibrate", "80");
mPersist.SetValue("tw_keyboard_vibrate", "40");
mPersist.SetValue("tw_action_vibrate", "160");
mConst.SetValue("tw_disable_haptics", "0");
#else
LOGINFO("TW_NO_HAPTICS := true\n");
mConst.SetValue("tw_disable_haptics", "1");
#endif
TWPartition *store = PartitionManager.Get_Default_Storage_Partition();
if (store)
mPersist.SetValue("tw_storage_path", store->Storage_Path);
else
mPersist.SetValue("tw_storage_path", "/");
#ifdef TW_FORCE_CPUINFO_FOR_DEVICE_ID
printf("TW_FORCE_CPUINFO_FOR_DEVICE_ID := true\n");
#endif
#ifdef BOARD_HAS_NO_REAL_SDCARD
printf("BOARD_HAS_NO_REAL_SDCARD := true\n");
mConst.SetValue(TW_ALLOW_PARTITION_SDCARD, "0");
#else
mConst.SetValue(TW_ALLOW_PARTITION_SDCARD, "1");
#endif
#ifdef TW_INCLUDE_DUMLOCK
printf("TW_INCLUDE_DUMLOCK := true\n");
mConst.SetValue(TW_SHOW_DUMLOCK, "1");
#else
mConst.SetValue(TW_SHOW_DUMLOCK, "0");
#endif
mData.SetValue(TW_RECOVERY_FOLDER_VAR, TW_DEFAULT_RECOVERY_FOLDER);
str = GetCurrentStoragePath();
mPersist.SetValue(TW_ZIP_LOCATION_VAR, str);
str += DataManager::GetStrValue(TW_RECOVERY_FOLDER_VAR) + "/BACKUPS/";
string dev_id;
mConst.GetValue("device_id", dev_id);
str += dev_id;
mData.SetValue(TW_BACKUPS_FOLDER_VAR, str);
mConst.SetValue(TW_REBOOT_SYSTEM, "1");
#ifdef TW_NO_REBOOT_RECOVERY
printf("TW_NO_REBOOT_RECOVERY := true\n");
mConst.SetValue(TW_REBOOT_RECOVERY, "0");
#else
mConst.SetValue(TW_REBOOT_RECOVERY, "1");
#endif
mConst.SetValue(TW_REBOOT_POWEROFF, "1");
#ifdef TW_NO_REBOOT_BOOTLOADER
printf("TW_NO_REBOOT_BOOTLOADER := true\n");
mConst.SetValue(TW_REBOOT_BOOTLOADER, "0");
#else
mConst.SetValue(TW_REBOOT_BOOTLOADER, "1");
#endif
#ifdef RECOVERY_SDCARD_ON_DATA
printf("RECOVERY_SDCARD_ON_DATA := true\n");
mConst.SetValue(TW_HAS_DATA_MEDIA, "1");
datamedia = true;
#else
mData.SetValue(TW_HAS_DATA_MEDIA, "0");
#endif
#ifdef TW_NO_BATT_PERCENT
printf("TW_NO_BATT_PERCENT := true\n");
mConst.SetValue(TW_NO_BATTERY_PERCENT, "1");
#else
mConst.SetValue(TW_NO_BATTERY_PERCENT, "0");
#endif
#ifdef TW_NO_CPU_TEMP
printf("TW_NO_CPU_TEMP := true\n");
mConst.SetValue("tw_no_cpu_temp", "1");
#else
string cpu_temp_file;
#ifdef TW_CUSTOM_CPU_TEMP_PATH
cpu_temp_file = EXPAND(TW_CUSTOM_CPU_TEMP_PATH);
#else
cpu_temp_file = "/sys/class/thermal/thermal_zone0/temp";
#endif
if (TWFunc::Path_Exists(cpu_temp_file)) {
mConst.SetValue("tw_no_cpu_temp", "0");
} else {
LOGINFO("CPU temperature file '%s' not found, disabling CPU temp.\n", cpu_temp_file.c_str());
mConst.SetValue("tw_no_cpu_temp", "1");
}
#endif
#ifdef TW_CUSTOM_POWER_BUTTON
printf("TW_POWER_BUTTON := %s\n", EXPAND(TW_CUSTOM_POWER_BUTTON));
mConst.SetValue(TW_POWER_BUTTON, EXPAND(TW_CUSTOM_POWER_BUTTON));
#else
mConst.SetValue(TW_POWER_BUTTON, "0");
#endif
#ifdef TW_ALWAYS_RMRF
printf("TW_ALWAYS_RMRF := true\n");
mConst.SetValue(TW_RM_RF_VAR, "1");
#endif
#ifdef TW_NEVER_UNMOUNT_SYSTEM
printf("TW_NEVER_UNMOUNT_SYSTEM := true\n");
mConst.SetValue(TW_DONT_UNMOUNT_SYSTEM, "1");
#else
mConst.SetValue(TW_DONT_UNMOUNT_SYSTEM, "0");
#endif
#ifdef TW_NO_USB_STORAGE
printf("TW_NO_USB_STORAGE := true\n");
mConst.SetValue(TW_HAS_USB_STORAGE, "0");
#else
char lun_file[255];
string Lun_File_str = CUSTOM_LUN_FILE;
size_t found = Lun_File_str.find("%");
if (found != string::npos) {
sprintf(lun_file, CUSTOM_LUN_FILE, 0);
Lun_File_str = lun_file;
}
if (!TWFunc::Path_Exists(Lun_File_str)) {
LOGINFO("Lun file '%s' does not exist, USB storage mode disabled\n", Lun_File_str.c_str());
mConst.SetValue(TW_HAS_USB_STORAGE, "0");
} else {
LOGINFO("Lun file '%s'\n", Lun_File_str.c_str());
mData.SetValue(TW_HAS_USB_STORAGE, "1");
}
#endif
#ifdef TW_INCLUDE_INJECTTWRP
printf("TW_INCLUDE_INJECTTWRP := true\n");
mConst.SetValue(TW_HAS_INJECTTWRP, "1");
mPersist(TW_INJECT_AFTER_ZIP, "1");
#else
mConst.SetValue(TW_HAS_INJECTTWRP, "0");
#endif
#ifdef TW_HAS_DOWNLOAD_MODE
printf("TW_HAS_DOWNLOAD_MODE := true\n");
mConst.SetValue(TW_DOWNLOAD_MODE, "1");
#endif
#ifdef TW_HAS_EDL_MODE
printf("TW_HAS_EDL_MODE := true\n");
mConst.SetValue(TW_EDL_MODE, "1");
#endif
#ifdef PRODUCT_USE_DYNAMIC_PARTITIONS
printf("PRODUCT_USE_DYNAMIC_PARTITIONS := true\n");
mConst.SetValue(TW_FASTBOOT_MODE, "1");
#endif
#ifdef TW_INCLUDE_CRYPTO
mConst.SetValue(TW_HAS_CRYPTO, "1");
printf("TW_INCLUDE_CRYPTO := true\n");
#endif
#ifdef TW_SDEXT_NO_EXT4
printf("TW_SDEXT_NO_EXT4 := true\n");
mConst.SetValue(TW_SDEXT_DISABLE_EXT4, "1");
#else
mConst.SetValue(TW_SDEXT_DISABLE_EXT4, "0");
#endif
#ifdef TW_HAS_NO_BOOT_PARTITION
mPersist.SetValue("tw_backup_list", "/system;/data;");
#else
#ifdef PRODUCT_USE_DYNAMIC_PARTITIONS
mPersist.SetValue("tw_backup_list", "/data;");
#else
mPersist.SetValue("tw_backup_list", "/system;/data;/boot;");
#endif
#endif
mConst.SetValue(TW_MIN_SYSTEM_VAR, TW_MIN_SYSTEM_SIZE);
mData.SetValue(TW_BACKUP_NAME, "(Auto Generate)");
mPersist.SetValue(TW_INSTALL_REBOOT_VAR, "0");
mPersist.SetValue(TW_SIGNED_ZIP_VERIFY_VAR, "0");
mPersist.SetValue(TW_DISABLE_FREE_SPACE_VAR, "0");
mPersist.SetValue(TW_FORCE_DIGEST_CHECK_VAR, "0");
mPersist.SetValue(TW_USE_COMPRESSION_VAR, "0");
mPersist.SetValue(TW_TIME_ZONE_VAR, "CST6CDT,M3.2.0,M11.1.0");
mPersist.SetValue(TW_GUI_SORT_ORDER, "1");
mPersist.SetValue(TW_RM_RF_VAR, "0");
mPersist.SetValue(TW_SKIP_DIGEST_CHECK_VAR, "0");
mPersist.SetValue(TW_SKIP_DIGEST_GENERATE_VAR, "0");
mPersist.SetValue(TW_SDEXT_SIZE, "0");
mPersist.SetValue(TW_SWAP_SIZE, "0");
mPersist.SetValue(TW_SDPART_FILE_SYSTEM, "ext3");
mPersist.SetValue(TW_TIME_ZONE_GUISEL, "CST6;CDT,M3.2.0,M11.1.0");
mPersist.SetValue(TW_TIME_ZONE_GUIOFFSET, "0");
mPersist.SetValue(TW_TIME_ZONE_GUIDST, "1");
mData.SetValue(TW_ACTION_BUSY, "0");
mData.SetValue("tw_wipe_cache", "0");
mData.SetValue("tw_wipe_dalvik", "0");
mData.SetValue(TW_ZIP_INDEX, "0");
mData.SetValue(TW_ZIP_QUEUE_COUNT, "0");
mData.SetValue(TW_FILENAME, "/sdcard");
mData.SetValue(TW_SIMULATE_ACTIONS, "0");
mData.SetValue(TW_SIMULATE_FAIL, "0");
mData.SetValue(TW_IS_ENCRYPTED, "0");
mData.SetValue(TW_IS_DECRYPTED, "0");
mData.SetValue(TW_CRYPTO_PASSWORD, "0");
mData.SetValue("tw_terminal_state", "0");
mData.SetValue("tw_background_thread_running", "0");
mData.SetValue(TW_RESTORE_FILE_DATE, "0");
mPersist.SetValue("tw_military_time", "0");
mData.SetValue(TW_IS_SUPER, "0");
#ifdef TW_INCLUDE_CRYPTO
mPersist.SetValue(TW_USE_SHA2, "1");
mPersist.SetValue(TW_NO_SHA2, "0");
#else
mPersist.SetValue(TW_NO_SHA2, "1");
#endif
mPersist.SetValue(TW_UNMOUNT_SYSTEM, "1");
#ifdef TW_NO_SCREEN_TIMEOUT
mConst.SetValue("tw_screen_timeout_secs", "0");
mConst.SetValue("tw_no_screen_timeout", "1");
#else
mPersist.SetValue("tw_screen_timeout_secs", "60");
mPersist.SetValue("tw_no_screen_timeout", "0");
#endif
mData.SetValue("tw_gui_done", "0");
mData.SetValue("tw_encrypt_backup", "0");
mData.SetValue("tw_sleep_total", "5");
mData.SetValue("tw_sleep", "5");
mData.SetValue("tw_enable_fastboot", "0");
// Brightness handling
string findbright;
#ifdef TW_BRIGHTNESS_PATH
findbright = EXPAND(TW_BRIGHTNESS_PATH);
LOGINFO("TW_BRIGHTNESS_PATH := %s\n", findbright.c_str());
if (!TWFunc::Path_Exists(findbright)) {
LOGINFO("Specified brightness file '%s' not found.\n", findbright.c_str());
findbright = "";
}
#endif
if (findbright.empty()) {
// Attempt to locate the brightness file
findbright = Find_File::Find("brightness", "/sys/class/backlight");
if (findbright.empty()) findbright = Find_File::Find("brightness", "/sys/class/leds/lcd-backlight");
}
if (findbright.empty()) {
LOGINFO("Unable to locate brightness file\n");
mConst.SetValue("tw_has_brightnesss_file", "0");
} else {
LOGINFO("Found brightness file at '%s'\n", findbright.c_str());
mConst.SetValue("tw_has_brightnesss_file", "1");
mConst.SetValue("tw_brightness_file", findbright);
string maxBrightness;
#ifdef TW_MAX_BRIGHTNESS
ostringstream maxVal;
maxVal << TW_MAX_BRIGHTNESS;
maxBrightness = maxVal.str();
#else
// Attempt to locate the max_brightness file
string maxbrightpath = findbright.insert(findbright.rfind('/') + 1, "max_");
if (TWFunc::Path_Exists(maxbrightpath)) {
ifstream maxVal(maxbrightpath.c_str());
if (maxVal >> maxBrightness) {
LOGINFO("Got max brightness %s from '%s'\n", maxBrightness.c_str(), maxbrightpath.c_str());
} else {
// Something went wrong, set that to indicate error
maxBrightness = "-1";
}
}
if (atoi(maxBrightness.c_str()) <= 0)
{
// Fallback into default
ostringstream maxVal;
maxVal << 255;
maxBrightness = maxVal.str();
}
#endif
mConst.SetValue("tw_brightness_max", maxBrightness);
mPersist.SetValue("tw_brightness", maxBrightness);
mPersist.SetValue("tw_brightness_pct", "100");
#ifdef TW_SECONDARY_BRIGHTNESS_PATH
string secondfindbright = EXPAND(TW_SECONDARY_BRIGHTNESS_PATH);
if (secondfindbright != "" && TWFunc::Path_Exists(secondfindbright)) {
LOGINFO("Will use a second brightness file at '%s'\n", secondfindbright.c_str());
mConst.SetValue("tw_secondary_brightness_file", secondfindbright);
} else {
LOGINFO("Specified secondary brightness file '%s' not found.\n", secondfindbright.c_str());
}
#endif
#ifdef TW_DEFAULT_BRIGHTNESS
int defValInt = TW_DEFAULT_BRIGHTNESS;
int maxValInt = atoi(maxBrightness.c_str());
// Deliberately int so the % is always a whole number
int defPctInt = ( ( (double)defValInt / maxValInt ) * 100 );
ostringstream defPct;
defPct << defPctInt;
mPersist.SetValue("tw_brightness_pct", defPct.str());
ostringstream defVal;
defVal << TW_DEFAULT_BRIGHTNESS;
mPersist.SetValue("tw_brightness", defVal.str());
TWFunc::Set_Brightness(defVal.str());
#else
TWFunc::Set_Brightness(maxBrightness);
#endif
}
#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
mConst.SetValue("tw_include_encrypted_backup", "1");
#else
LOGINFO("TW_EXCLUDE_ENCRYPTED_BACKUPS := true\n");
mConst.SetValue("tw_include_encrypted_backup", "0");
#endif
#ifdef TW_HAS_MTP
mConst.SetValue("tw_has_mtp", "1");
mPersist.SetValue("tw_mtp_enabled", "1");
mPersist.SetValue("tw_mtp_debug", "0");
#else
LOGINFO("TW_EXCLUDE_MTP := true\n");
mConst.SetValue("tw_has_mtp", "0");
mConst.SetValue("tw_mtp_enabled", "0");
#endif
mPersist.SetValue("tw_mount_system_ro", "2");
mPersist.SetValue("tw_never_show_system_ro_page", "0");
mPersist.SetValue("tw_language", EXPAND(TW_DEFAULT_LANGUAGE));
LOGINFO("LANG: %s\n", EXPAND(TW_DEFAULT_LANGUAGE));
mData.SetValue("tw_has_adopted_storage", "0");
#ifdef AB_OTA_UPDATER
LOGINFO("AB_OTA_UPDATER := true\n");
mConst.SetValue("tw_has_boot_slots", "1");
#else
mConst.SetValue("tw_has_boot_slots", "0");
#endif
#ifdef TW_NO_LEGACY_PROPS
LOGINFO("TW_NO_LEGACY_PROPS := true\n");
#endif
#ifdef TW_OEM_BUILD
LOGINFO("TW_OEM_BUILD := true\n");
mConst.SetValue("tw_oem_build", "1");
mConst.SetValue("tw_app_installed_in_system", "0");
#else
mConst.SetValue("tw_oem_build", "0");
mPersist.SetValue("tw_app_prompt", "1");
mPersist.SetValue("tw_app_install_system", "1");
mData.SetValue("tw_app_install_status", "0"); // 0 = no status, 1 = not installed, 2 = already installed
mData.SetValue("tw_app_installed_in_system", "0");
#endif
#ifndef TW_EXCLUDE_NANO
mConst.SetValue("tw_include_nano", "1");
#else
LOGINFO("TW_EXCLUDE_NANO := true\n");
mConst.SetValue("tw_include_nano", "0");
#endif
mData.SetValue("tw_enable_adb_backup", "0");
if (TWFunc::Path_Exists("/system/bin/magiskboot"))
mConst.SetValue("tw_has_repack_tools", "1");
else
mConst.SetValue("tw_has_repack_tools", "0");
pthread_mutex_unlock(&m_valuesLock);
}
// Magic Values
int DataManager::GetMagicValue(const string& varName, string& value)
{
// Handle special dynamic cases
if (varName == "tw_time")
{
char tmp[32];
struct tm *current;
time_t now;
int tw_military_time;
now = time(0);
current = localtime(&now);
GetValue(TW_MILITARY_TIME, tw_military_time);
if (current->tm_hour >= 12)
{
if (tw_military_time == 1)
sprintf(tmp, "%d:%02d", current->tm_hour, current->tm_min);
else
sprintf(tmp, "%d:%02d PM", current->tm_hour == 12 ? 12 : current->tm_hour - 12, current->tm_min);
}
else
{
if (tw_military_time == 1)
sprintf(tmp, "%d:%02d", current->tm_hour, current->tm_min);
else
sprintf(tmp, "%d:%02d AM", current->tm_hour == 0 ? 12 : current->tm_hour, current->tm_min);
}
value = tmp;
return 0;
}
else if (varName == "tw_cpu_temp")
{
int tw_no_cpu_temp;
GetValue("tw_no_cpu_temp", tw_no_cpu_temp);
if (tw_no_cpu_temp == 1) return -1;
string cpu_temp_file;
static unsigned long convert_temp = 0;
static time_t cpuSecCheck = 0;
struct timeval curTime;
string results;
gettimeofday(&curTime, NULL);
if (curTime.tv_sec > cpuSecCheck)
{
#ifdef TW_CUSTOM_CPU_TEMP_PATH
cpu_temp_file = EXPAND(TW_CUSTOM_CPU_TEMP_PATH);
if (TWFunc::read_file(cpu_temp_file, results) != 0)
return -1;
#else
cpu_temp_file = "/sys/class/thermal/thermal_zone0/temp";
if (TWFunc::read_file(cpu_temp_file, results) != 0)
return -1;
#endif
convert_temp = strtoul(results.c_str(), NULL, 0) / 1000;
if (convert_temp <= 0)
convert_temp = strtoul(results.c_str(), NULL, 0);
if (convert_temp >= 150)
convert_temp = strtoul(results.c_str(), NULL, 0) / 10;
cpuSecCheck = curTime.tv_sec + 5;
}
value = TWFunc::to_string(convert_temp);
return 0;
}
else if (varName == "tw_battery")
{
char tmp[16];
static char charging = ' ';
static int lastVal = -1;
static time_t nextSecCheck = 0;
struct timeval curTime;
gettimeofday(&curTime, NULL);
if (curTime.tv_sec > nextSecCheck)
{
char cap_s[4];
#ifdef TW_CUSTOM_BATTERY_PATH
string capacity_file = EXPAND(TW_CUSTOM_BATTERY_PATH);
capacity_file += "/capacity";
FILE * cap = fopen(capacity_file.c_str(),"rt");
#else
FILE * cap = fopen("/sys/class/power_supply/battery/capacity","rt");
#endif
if (cap) {
fgets(cap_s, 4, cap);
fclose(cap);
lastVal = atoi(cap_s);
if (lastVal > 100) lastVal = 101;
if (lastVal < 0) lastVal = 0;
}
#ifdef TW_CUSTOM_BATTERY_PATH
string status_file = EXPAND(TW_CUSTOM_BATTERY_PATH);
status_file += "/status";
cap = fopen(status_file.c_str(),"rt");
#else
cap = fopen("/sys/class/power_supply/battery/status","rt");
#endif
if (cap) {
fgets(cap_s, 2, cap);
fclose(cap);
if (cap_s[0] == 'C')
charging = '+';
else
charging = ' ';
}
nextSecCheck = curTime.tv_sec + 60;
}
sprintf(tmp, "%i%%%c", lastVal, charging);
value = tmp;
return 0;
}
return -1;
}
void DataManager::Output_Version(void)
{
#ifndef TW_OEM_BUILD
string Path;
char version[255];
std::string logDir = TWFunc::get_log_dir();
if (logDir.empty()) {
LOGINFO("Unable to find cache directory\n");
return;
}
std::string recoveryLogDir = logDir + "recovery/";
if (logDir == CACHE_LOGS_DIR) {
if (!PartitionManager.Mount_By_Path(CACHE_LOGS_DIR, false)) {
LOGINFO("Unable to mount '%s' to write version number.\n", Path.c_str());
return;
}
if (!TWFunc::Path_Exists(recoveryLogDir)) {
LOGINFO("Recreating %s folder.\n", recoveryLogDir.c_str());
if (!TWFunc::Create_Dir_Recursive(recoveryLogDir.c_str(), S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP, 0, 0)) {
LOGERR("DataManager::Output_Version -- Unable to make %s: %s\n", recoveryLogDir.c_str(), strerror(errno));
return;
}
}
}
std::string verPath = recoveryLogDir + ".version";
if (TWFunc::Path_Exists(verPath)) {
unlink(verPath.c_str());
}
FILE *fp = fopen(verPath.c_str(), "w");
if (fp == NULL) {
gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(verPath)(strerror(errno)));
return;
}
strcpy(version, TW_VERSION_STR);
fwrite(version, sizeof(version[0]), strlen(version) / sizeof(version[0]), fp);
fclose(fp);
TWFunc::copy_file("/etc/recovery.fstab", recoveryLogDir + "recovery.fstab", 0644);
PartitionManager.Output_Storage_Fstab();
sync();
LOGINFO("Version number saved to '%s'\n", verPath.c_str());
#endif
}
void DataManager::ReadSettingsFile(void)
{
#ifndef TW_OEM_BUILD
// Load up the values for TWRP - Sleep to let the card be ready
char mkdir_path[255], settings_file[255];
int is_enc, has_data_media;
GetValue(TW_IS_ENCRYPTED, is_enc);
GetValue(TW_HAS_DATA_MEDIA, has_data_media);
memset(mkdir_path, 0, sizeof(mkdir_path));
memset(settings_file, 0, sizeof(settings_file));
sprintf(mkdir_path, "%s%s", GetSettingsStoragePath().c_str(), GetStrValue(TW_RECOVERY_FOLDER_VAR).c_str());
sprintf(settings_file, "%s/%s", mkdir_path, TW_SETTINGS_FILE);
if (!PartitionManager.Mount_Settings_Storage(false))
{
usleep(500000);
if (!PartitionManager.Mount_Settings_Storage(false))
gui_msg(Msg(msg::kError, "unable_to_mount=Unable to mount {1}")(settings_file));
}
mkdir(mkdir_path, 0777);
LOGINFO("Attempt to load settings from settings file...\n");
LoadValues(settings_file);
Output_Version();
#endif // ifdef TW_OEM_BUILD
PartitionManager.Mount_All_Storage();
update_tz_environment_variables();
TWFunc::Set_Brightness(GetStrValue("tw_brightness"));
}
string DataManager::GetCurrentStoragePath(void)
{
return GetStrValue("tw_storage_path");
}
string DataManager::GetSettingsStoragePath(void)
{
return GetStrValue("tw_settings_path");
}
void DataManager::Vibrate(const string& varName)
{
#ifndef TW_NO_HAPTICS
int vib_value = 0;
GetValue(varName, vib_value);
if (vib_value) {
vibrate(vib_value);
}
#endif
}
void DataManager::LoadTWRPFolderInfo(void)
{
string mainPath = GetCurrentStoragePath();
SetValue(TW_RECOVERY_FOLDER_VAR, TWFunc::Check_For_TwrpFolder());
mBackingFile = mainPath + GetStrValue(TW_RECOVERY_FOLDER_VAR) + '/' + TW_SETTINGS_FILE;
}