Files
android_bootable_recovery/data.cpp
bigbiff bigbiff 56cf564658 twrpDigest refactor
This patch is to refactor twrpDigest using polymorphism
and inheritance to use the same call patterns for creating and
reading a digest. Now a library.
Use SHA2 from libcrypto. SHA2 is default if device has libcrypto.

Change string MD5 everywhere to use digest or Digest instead. Updated
string tags to digest. Translation will be required.

Switch out digest code into a driver class from partitionmanager.

SHA2 is better for digest creation due to decreased collision space
compared to MD5 and SHA1.

See https://en.wikipedia.org/wiki/SHA-2

Change-Id: I74b5546789990b12aa4ce2e389d25f80a3fe213f
2017-06-17 07:05:45 -05:00

1056 lines
30 KiB
C++

/*
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
// 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 str, 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\n");
#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;
}
unsigned long long 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);
}
int DataManager::SetProgress(const float Fraction) {
return SetValue("ui_progress", (float) (Fraction * 100.0));
}
int DataManager::ShowProgress(const float Portion, const float Seconds)
{
float Starting_Portion;
GetValue("ui_progress_portion", Starting_Portion);
if (SetValue("ui_progress_portion", (float)(Portion * 100.0) + Starting_Portion) != 0)
return -1;
if (SetValue("ui_progress_frames", Seconds * 30) != 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 += "/TWRP/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);
mPersist.SetValue("tw_button_vibrate", "80");
mPersist.SetValue("tw_keyboard_vibrate", "40");
mPersist.SetValue("tw_action_vibrate", "160");
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
str = GetCurrentStoragePath();
mPersist.SetValue(TW_ZIP_LOCATION_VAR, str);
str += "/TWRP/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_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
mPersist.SetValue("tw_backup_list", "/system;/data;/boot;");
#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");
#ifdef TW_INCLUDE_CRYPTO
mConst.SetValue(TW_USE_SHA2, "1");
mConst.SetValue(TW_NO_SHA2, "0");
#else
mConst.SetValue(TW_NO_SHA2, "1");
#endif
#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");
// 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_OEM_BUILD
LOGINFO("TW_OEM_BUILD := true\n");
mConst.SetValue("tw_oem_build", "1");
#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
#endif
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];
if (!PartitionManager.Mount_By_Path("/cache", false)) {
LOGINFO("Unable to mount '%s' to write version number.\n", Path.c_str());
return;
}
if (!TWFunc::Path_Exists("/cache/recovery/.")) {
LOGINFO("Recreating /cache/recovery folder.\n");
if (mkdir("/cache/recovery", S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP) != 0) {
LOGERR("DataManager::Output_Version -- Unable to make /cache/recovery\n");
return;
}
}
Path = "/cache/recovery/.version";
if (TWFunc::Path_Exists(Path)) {
unlink(Path.c_str());
}
FILE *fp = fopen(Path.c_str(), "w");
if (fp == NULL) {
gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Path)(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", "/cache/recovery/recovery.fstab", 0644);
PartitionManager.Output_Storage_Fstab();
sync();
LOGINFO("Version number saved to '%s'\n", Path.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);
if (is_enc == 1 && has_data_media == 1) {
LOGINFO("Cannot load settings -- encrypted.\n");
return;
}
memset(mkdir_path, 0, sizeof(mkdir_path));
memset(settings_file, 0, sizeof(settings_file));
sprintf(mkdir_path, "%s/TWRP", GetSettingsStoragePath().c_str());
sprintf(settings_file, "%s/.twrps", mkdir_path);
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)
{
int vib_value = 0;
GetValue(varName, vib_value);
if (vib_value) {
vibrate(vib_value);
}
}