blob: c4e78cf2674877daed07cdc69d592991c65cf16f [file] [log] [blame]
Ethan Yonker6e8c27a2016-12-22 17:55:57 -06001/*
Dees_Troya13d74f2013-03-24 08:54:55 -05002 Copyright 2013 bigbiff/Dees_Troy TeamWin
3 This file is part of TWRP/TeamWin Recovery Project.
4
5 TWRP is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 TWRP is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
17*/
Dees_Troy51a0e822012-09-05 15:24:24 -040018
19#include <stdarg.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <fcntl.h>
24#include <sys/stat.h>
25#include <sys/time.h>
26#include <sys/mman.h>
27#include <sys/types.h>
28#include <sys/ioctl.h>
29#include <linux/input.h>
30#include <time.h>
31#include <unistd.h>
32#include <stdlib.h>
Dees_Troy657c3092012-09-10 20:32:10 -040033#include <sys/wait.h>
Dees_Troy83bd4832013-05-04 12:39:56 +000034#include <dirent.h>
Matt Mower0c88b842017-01-15 16:00:49 -060035#include <private/android_filesystem_config.h>
Dees_Troy51a0e822012-09-05 15:24:24 -040036
37#include <string>
38#include <sstream>
39#include "../partitions.hpp"
Dees_Troy38bd7602012-09-14 13:33:53 -040040#include "../twrp-functions.hpp"
Dees_Troy812660f2012-09-20 09:55:17 -040041#include "../openrecoveryscript.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040042
Dees_Troy43d8b002012-09-17 16:00:01 -040043#include "../adb_install.h"
thatcc8ddca2015-01-03 01:59:36 +010044#include "../fuse_sideload.h"
bigbiff bigbiff8a68c312013-02-10 14:28:30 -050045#include "blanktimer.hpp"
Ethan Yonker8373cfe2017-09-08 06:50:54 -050046#include "../twinstall.h"
Ethan Yonkerfbb43532015-12-28 21:54:50 +010047
Dees_Troy51a0e822012-09-05 15:24:24 -040048extern "C" {
Dees_Troy2673cec2013-04-02 20:22:16 +000049#include "../twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040050#include "../variables.h"
Dees_Troy2673cec2013-04-02 20:22:16 +000051#include "cutils/properties.h"
Ethan Yonker24813422014-11-07 17:19:07 -060052#include "../adb_install.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040053};
Ethan Yonkerf1179622016-08-25 15:32:21 -050054#include "../set_metadata.h"
Ethan Yonkerfbb43532015-12-28 21:54:50 +010055#include "../minuitwrp/minui.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040056
57#include "rapidxml.hpp"
58#include "objects.hpp"
bigbiff7abc5fe2015-01-17 16:53:12 -050059#include "../tw_atomic.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040060
that3f7b1ac2014-12-30 11:30:13 +010061GUIAction::mapFunc GUIAction::mf;
thatc6085482015-01-09 22:12:43 +010062std::set<string> GUIAction::setActionsRunningInCallerThread;
that3f7b1ac2014-12-30 11:30:13 +010063static string zip_queue[10];
64static int zip_queue_index;
thatcc8ddca2015-01-03 01:59:36 +010065pid_t sideload_child_pid;
that3f7b1ac2014-12-30 11:30:13 +010066
that73a52952015-01-28 23:07:34 +010067static void *ActionThread_work_wrapper(void *data);
68
69class ActionThread
70{
71public:
72 ActionThread();
73 ~ActionThread();
74
75 void threadActions(GUIAction *act);
76 void run(void *data);
77private:
78 friend void *ActionThread_work_wrapper(void*);
79 struct ThreadData
80 {
81 ActionThread *this_;
82 GUIAction *act;
83 ThreadData(ActionThread *this_, GUIAction *act) : this_(this_), act(act) {}
84 };
85
86 pthread_t m_thread;
87 bool m_thread_running;
88 pthread_mutex_t m_act_lock;
89};
90
91static ActionThread action_thread; // for all kinds of longer running actions
92static ActionThread cancel_thread; // for longer running "cancel" actions
thatc6085482015-01-09 22:12:43 +010093
94static void *ActionThread_work_wrapper(void *data)
95{
that73a52952015-01-28 23:07:34 +010096 static_cast<ActionThread::ThreadData*>(data)->this_->run(data);
thatc6085482015-01-09 22:12:43 +010097 return NULL;
98}
99
100ActionThread::ActionThread()
101{
102 m_thread_running = false;
103 pthread_mutex_init(&m_act_lock, NULL);
104}
105
106ActionThread::~ActionThread()
107{
108 pthread_mutex_lock(&m_act_lock);
Matt Mowera8a89d12016-12-30 18:10:37 -0600109 if (m_thread_running) {
thatc6085482015-01-09 22:12:43 +0100110 pthread_mutex_unlock(&m_act_lock);
111 pthread_join(m_thread, NULL);
112 } else {
113 pthread_mutex_unlock(&m_act_lock);
114 }
115 pthread_mutex_destroy(&m_act_lock);
116}
117
that7d3b54f2015-01-09 22:52:51 +0100118void ActionThread::threadActions(GUIAction *act)
thatc6085482015-01-09 22:12:43 +0100119{
120 pthread_mutex_lock(&m_act_lock);
121 if (m_thread_running) {
122 pthread_mutex_unlock(&m_act_lock);
that7d3b54f2015-01-09 22:52:51 +0100123 LOGERR("Another threaded action is already running -- not running %u actions starting with '%s'\n",
124 act->mActions.size(), act->mActions[0].mFunction.c_str());
thatc6085482015-01-09 22:12:43 +0100125 } else {
126 m_thread_running = true;
127 pthread_mutex_unlock(&m_act_lock);
that73a52952015-01-28 23:07:34 +0100128 ThreadData *d = new ThreadData(this, act);
thatc6085482015-01-09 22:12:43 +0100129 pthread_create(&m_thread, NULL, &ActionThread_work_wrapper, d);
130 }
131}
132
133void ActionThread::run(void *data)
134{
135 ThreadData *d = (ThreadData*)data;
136 GUIAction* act = d->act;
137
138 std::vector<GUIAction::Action>::iterator it;
that7d3b54f2015-01-09 22:52:51 +0100139 for (it = act->mActions.begin(); it != act->mActions.end(); ++it)
thatc6085482015-01-09 22:12:43 +0100140 act->doAction(*it);
141
142 pthread_mutex_lock(&m_act_lock);
143 m_thread_running = false;
144 pthread_mutex_unlock(&m_act_lock);
145 delete d;
146}
147
Dees_Troy51a0e822012-09-05 15:24:24 -0400148GUIAction::GUIAction(xml_node<>* node)
Vojtech Bocekede51c52014-02-07 23:58:09 +0100149 : GUIObject(node)
Dees_Troy51a0e822012-09-05 15:24:24 -0400150{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200151 xml_node<>* child;
152 xml_node<>* actions;
153 xml_attribute<>* attr;
Dees_Troy51a0e822012-09-05 15:24:24 -0400154
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200155 if (!node) return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400156
that3f7b1ac2014-12-30 11:30:13 +0100157 if (mf.empty()) {
Vojtech Bocekecd89182015-01-15 16:28:54 +0100158#define ADD_ACTION(n) mf[#n] = &GUIAction::n
159#define ADD_ACTION_EX(name, func) mf[name] = &GUIAction::func
thatc6085482015-01-09 22:12:43 +0100160 // These actions will be run in the caller's thread
Vojtech Bocekecd89182015-01-15 16:28:54 +0100161 ADD_ACTION(reboot);
162 ADD_ACTION(home);
163 ADD_ACTION(key);
164 ADD_ACTION(page);
165 ADD_ACTION(reload);
166 ADD_ACTION(readBackup);
167 ADD_ACTION(set);
168 ADD_ACTION(clear);
169 ADD_ACTION(mount);
170 ADD_ACTION(unmount);
171 ADD_ACTION_EX("umount", unmount);
172 ADD_ACTION(restoredefaultsettings);
173 ADD_ACTION(copylog);
174 ADD_ACTION(compute);
175 ADD_ACTION_EX("addsubtract", compute);
176 ADD_ACTION(setguitimezone);
177 ADD_ACTION(overlay);
178 ADD_ACTION(queuezip);
179 ADD_ACTION(cancelzip);
180 ADD_ACTION(queueclear);
181 ADD_ACTION(sleep);
Matt Mower9a2a2052016-05-31 21:31:22 -0500182 ADD_ACTION(sleepcounter);
Vojtech Bocekecd89182015-01-15 16:28:54 +0100183 ADD_ACTION(appenddatetobackupname);
184 ADD_ACTION(generatebackupname);
185 ADD_ACTION(checkpartitionlist);
186 ADD_ACTION(getpartitiondetails);
187 ADD_ACTION(screenshot);
188 ADD_ACTION(setbrightness);
189 ADD_ACTION(fileexists);
190 ADD_ACTION(killterminal);
191 ADD_ACTION(checkbackupname);
192 ADD_ACTION(adbsideloadcancel);
193 ADD_ACTION(fixsu);
194 ADD_ACTION(startmtp);
195 ADD_ACTION(stopmtp);
196 ADD_ACTION(cancelbackup);
Ethan Yonkereb32b1f2015-05-18 10:23:03 -0500197 ADD_ACTION(checkpartitionlifetimewrites);
198 ADD_ACTION(mountsystemtoggle);
Ethan Yonker74db1572015-10-28 12:44:49 -0500199 ADD_ACTION(setlanguage);
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -0600200 ADD_ACTION(checkforapp);
Matt Mower9472ba12016-01-20 18:12:47 -0600201 ADD_ACTION(togglebacklight);
thatc6085482015-01-09 22:12:43 +0100202
203 // remember actions that run in the caller thread
204 for (mapFunc::const_iterator it = mf.begin(); it != mf.end(); ++it)
205 setActionsRunningInCallerThread.insert(it->first);
206
207 // These actions will run in a separate thread
Vojtech Bocekecd89182015-01-15 16:28:54 +0100208 ADD_ACTION(flash);
209 ADD_ACTION(wipe);
210 ADD_ACTION(refreshsizes);
211 ADD_ACTION(nandroid);
Ethan Yonkerb5fab762016-01-28 14:03:33 -0600212 ADD_ACTION(fixcontexts);
Vojtech Bocekecd89182015-01-15 16:28:54 +0100213 ADD_ACTION(fixpermissions);
214 ADD_ACTION(dd);
215 ADD_ACTION(partitionsd);
216 ADD_ACTION(installhtcdumlock);
217 ADD_ACTION(htcdumlockrestoreboot);
218 ADD_ACTION(htcdumlockreflashrecovery);
219 ADD_ACTION(cmd);
220 ADD_ACTION(terminalcommand);
221 ADD_ACTION(reinjecttwrp);
222 ADD_ACTION(decrypt);
223 ADD_ACTION(adbsideload);
224 ADD_ACTION(openrecoveryscript);
225 ADD_ACTION(installsu);
226 ADD_ACTION(decrypt_backup);
227 ADD_ACTION(repair);
Ethan Yonkera2719152015-05-28 09:44:41 -0500228 ADD_ACTION(resize);
Vojtech Bocekecd89182015-01-15 16:28:54 +0100229 ADD_ACTION(changefilesystem);
230 ADD_ACTION(flashimage);
that10ae24f2015-12-26 20:53:51 +0100231 ADD_ACTION(twcmd);
Ethan Yonker1b190162016-12-05 15:25:19 -0600232 ADD_ACTION(setbootslot);
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -0600233 ADD_ACTION(installapp);
Ethan Yonker53796e72019-01-11 22:49:52 -0600234 ADD_ACTION(repackimage);
235 ADD_ACTION(fixabrecoverybootloop);
that3f7b1ac2014-12-30 11:30:13 +0100236 }
237
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200238 // First, get the action
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600239 actions = FindNode(node, "actions");
240 if (actions) child = FindNode(actions, "action");
241 else child = FindNode(node, "action");
Dees_Troy51a0e822012-09-05 15:24:24 -0400242
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200243 if (!child) return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400244
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200245 while (child)
246 {
247 Action action;
Dees_Troy51a0e822012-09-05 15:24:24 -0400248
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200249 attr = child->first_attribute("function");
250 if (!attr) return;
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500251
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200252 action.mFunction = attr->value();
253 action.mArg = child->value();
254 mActions.push_back(action);
Dees_Troy51a0e822012-09-05 15:24:24 -0400255
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200256 child = child->next_sibling("action");
257 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400258
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200259 // Now, let's get either the key or region
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600260 child = FindNode(node, "touch");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200261 if (child)
262 {
263 attr = child->first_attribute("key");
264 if (attr)
265 {
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100266 std::vector<std::string> keys = TWFunc::Split_String(attr->value(), "+");
Matt Mowera8a89d12016-12-30 18:10:37 -0600267 for (size_t i = 0; i < keys.size(); ++i)
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100268 {
269 const int key = getKeyByName(keys[i]);
270 mKeys[key] = false;
271 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200272 }
273 else
274 {
275 attr = child->first_attribute("x");
276 if (!attr) return;
277 mActionX = atol(attr->value());
278 attr = child->first_attribute("y");
279 if (!attr) return;
280 mActionY = atol(attr->value());
281 attr = child->first_attribute("w");
282 if (!attr) return;
283 mActionW = atol(attr->value());
284 attr = child->first_attribute("h");
285 if (!attr) return;
286 mActionH = atol(attr->value());
287 }
288 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400289}
290
Matt Mower25036b72016-06-24 12:30:18 -0500291int GUIAction::NotifyTouch(TOUCH_STATE state, int x __unused, int y __unused)
Dees_Troy51a0e822012-09-05 15:24:24 -0400292{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200293 if (state == TOUCH_RELEASE)
294 doActions();
Dees_Troy51a0e822012-09-05 15:24:24 -0400295
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200296 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400297}
298
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100299int GUIAction::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -0400300{
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100301 std::map<int, bool>::iterator itr = mKeys.find(key);
Matt Mowera8a89d12016-12-30 18:10:37 -0600302 if (itr == mKeys.end())
that8834a0f2016-01-05 23:29:30 +0100303 return 1;
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100304
305 bool prevState = itr->second;
306 itr->second = down;
307
308 // If there is only one key for this action, wait for key up so it
309 // doesn't trigger with multi-key actions.
310 // Else, check if all buttons are pressed, then consume their release events
311 // so they don't trigger one-button actions and reset mKeys pressed status
Matt Mowera8a89d12016-12-30 18:10:37 -0600312 if (mKeys.size() == 1) {
313 if (!down && prevState) {
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100314 doActions();
thatd4725ca2016-01-19 00:15:21 +0100315 return 0;
316 }
Matt Mowera8a89d12016-12-30 18:10:37 -0600317 } else if (down) {
318 for (itr = mKeys.begin(); itr != mKeys.end(); ++itr) {
319 if (!itr->second)
that8834a0f2016-01-05 23:29:30 +0100320 return 1;
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100321 }
322
323 // Passed, all req buttons are pressed, reset them and consume release events
324 HardwareKeyboard *kb = PageManager::GetHardwareKeyboard();
Matt Mowera8a89d12016-12-30 18:10:37 -0600325 for (itr = mKeys.begin(); itr != mKeys.end(); ++itr) {
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100326 kb->ConsumeKeyRelease(itr->first);
327 itr->second = false;
328 }
329
330 doActions();
thatd4725ca2016-01-19 00:15:21 +0100331 return 0;
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100332 }
333
thatd4725ca2016-01-19 00:15:21 +0100334 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400335}
336
Vojtech Bocek07220562014-02-08 02:05:33 +0100337int GUIAction::NotifyVarChange(const std::string& varName, const std::string& value)
Dees_Troy51a0e822012-09-05 15:24:24 -0400338{
Vojtech Bocek07220562014-02-08 02:05:33 +0100339 GUIObject::NotifyVarChange(varName, value);
340
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100341 if (varName.empty() && !isConditionValid() && mKeys.empty() && !mActionW)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200342 doActions();
Matt Mowera8a89d12016-12-30 18:10:37 -0600343 else if ((varName.empty() || IsConditionVariable(varName)) && isConditionValid() && isConditionTrue())
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200344 doActions();
Dees_Troy51a0e822012-09-05 15:24:24 -0400345
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200346 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400347}
348
349void GUIAction::simulate_progress_bar(void)
350{
Ethan Yonker74db1572015-10-28 12:44:49 -0500351 gui_msg("simulating=Simulating actions...");
Dees_Troy51a0e822012-09-05 15:24:24 -0400352 for (int i = 0; i < 5; i++)
353 {
bigbiff7abc5fe2015-01-17 16:53:12 -0500354 if (PartitionManager.stop_backup.get_value()) {
355 DataManager::SetValue("tw_cancel_backup", 1);
Matt Mower3c366972015-12-25 19:28:31 -0600356 gui_msg("backup_cancel=Backup Cancelled");
bigbiff7abc5fe2015-01-17 16:53:12 -0500357 DataManager::SetValue("ui_progress", 0);
358 PartitionManager.stop_backup.set_value(0);
359 return;
360 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400361 usleep(500000);
362 DataManager::SetValue("ui_progress", i * 20);
363 }
364}
365
Ethan Yonker0d47eb52015-01-09 11:23:19 -0600366int GUIAction::flash_zip(std::string filename, int* wipe_cache)
Dees_Troy51a0e822012-09-05 15:24:24 -0400367{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200368 int ret_val = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400369
370 DataManager::SetValue("ui_progress", 0);
371
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200372 if (filename.empty())
373 {
374 LOGERR("No file specified.\n");
375 return -1;
376 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400377
Ethan Yonker9598c072016-01-15 21:54:34 -0600378 if (!TWFunc::Path_Exists(filename)) {
379 if (!PartitionManager.Mount_By_Path(filename, true)) {
380 return -1;
381 }
382 if (!TWFunc::Path_Exists(filename)) {
383 gui_msg(Msg(msg::kError, "unable_to_locate=Unable to locate {1}.")(filename));
384 return -1;
385 }
386 }
Dees_Troy657c3092012-09-10 20:32:10 -0400387
Dees_Troy51a0e822012-09-05 15:24:24 -0400388 if (simulate) {
389 simulate_progress_bar();
390 } else {
Dees_Troy657c3092012-09-10 20:32:10 -0400391 ret_val = TWinstall_zip(filename.c_str(), wipe_cache);
Dees_Troy51a0e822012-09-05 15:24:24 -0400392
393 // Now, check if we need to ensure TWRP remains installed...
394 struct stat st;
395 if (stat("/sbin/installTwrp", &st) == 0)
396 {
397 DataManager::SetValue("tw_operation", "Configuring TWRP");
398 DataManager::SetValue("tw_partition", "");
Ethan Yonker74db1572015-10-28 12:44:49 -0500399 gui_msg("config_twrp=Configuring TWRP...");
Vojtech Bocek05534202013-09-11 08:11:56 +0200400 if (TWFunc::Exec_Cmd("/sbin/installTwrp reinstall") < 0)
Dees_Troy51a0e822012-09-05 15:24:24 -0400401 {
Ethan Yonker74db1572015-10-28 12:44:49 -0500402 gui_msg("config_twrp_err=Unable to configure TWRP with this kernel.");
Dees_Troy51a0e822012-09-05 15:24:24 -0400403 }
404 }
405 }
406
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200407 // Done
408 DataManager::SetValue("ui_progress", 100);
409 DataManager::SetValue("ui_progress", 0);
410 return ret_val;
Dees_Troy51a0e822012-09-05 15:24:24 -0400411}
412
that73a52952015-01-28 23:07:34 +0100413GUIAction::ThreadType GUIAction::getThreadType(const GUIAction::Action& action)
thatc6085482015-01-09 22:12:43 +0100414{
that73a52952015-01-28 23:07:34 +0100415 string func = gui_parse_text(action.mFunction);
416 bool needsThread = setActionsRunningInCallerThread.find(func) == setActionsRunningInCallerThread.end();
417 if (needsThread) {
418 if (func == "cancelbackup")
419 return THREAD_CANCEL;
420 else
421 return THREAD_ACTION;
422 }
423 return THREAD_NONE;
thatc6085482015-01-09 22:12:43 +0100424}
425
Dees_Troy51a0e822012-09-05 15:24:24 -0400426int GUIAction::doActions()
427{
that3f7b1ac2014-12-30 11:30:13 +0100428 if (mActions.size() < 1)
429 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400430
that73a52952015-01-28 23:07:34 +0100431 // Determine in which thread to run the actions.
432 // Do it for all actions at once before starting, so that we can cancel the whole batch if the thread is already busy.
433 ThreadType threadType = THREAD_NONE;
that3f7b1ac2014-12-30 11:30:13 +0100434 std::vector<Action>::iterator it;
that73a52952015-01-28 23:07:34 +0100435 for (it = mActions.begin(); it != mActions.end(); ++it) {
436 ThreadType tt = getThreadType(*it);
437 if (tt == THREAD_NONE)
438 continue;
439 if (threadType == THREAD_NONE)
440 threadType = tt;
441 else if (threadType != tt) {
442 LOGERR("Can't mix normal and cancel actions in the same list.\n"
443 "Running the whole batch in the cancel thread.\n");
444 threadType = THREAD_CANCEL;
thatc6085482015-01-09 22:12:43 +0100445 break;
446 }
that7d3b54f2015-01-09 22:52:51 +0100447 }
that73a52952015-01-28 23:07:34 +0100448
449 // Now run the actions in the desired thread.
450 switch (threadType) {
451 case THREAD_ACTION:
452 action_thread.threadActions(this);
453 break;
454
455 case THREAD_CANCEL:
456 cancel_thread.threadActions(this);
457 break;
458
459 default: {
460 // no iterators here because theme reloading might kill our object
461 const size_t cnt = mActions.size();
462 for (size_t i = 0; i < cnt; ++i)
463 doAction(mActions[i]);
464 }
thatc6085482015-01-09 22:12:43 +0100465 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400466
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200467 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400468}
469
that3f7b1ac2014-12-30 11:30:13 +0100470int GUIAction::doAction(Action action)
Dees_Troy51a0e822012-09-05 15:24:24 -0400471{
that3f7b1ac2014-12-30 11:30:13 +0100472 DataManager::GetValue(TW_SIMULATE_ACTIONS, simulate);
Dees_Troy51a0e822012-09-05 15:24:24 -0400473
that3f7b1ac2014-12-30 11:30:13 +0100474 std::string function = gui_parse_text(action.mFunction);
475 std::string arg = gui_parse_text(action.mArg);
Dees_Troy51a0e822012-09-05 15:24:24 -0400476
that3f7b1ac2014-12-30 11:30:13 +0100477 // find function and execute it
478 mapFunc::const_iterator funcitr = mf.find(function);
479 if (funcitr != mf.end())
480 return (this->*funcitr->second)(arg);
481
482 LOGERR("Unknown action '%s'\n", function.c_str());
483 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400484}
485
486void GUIAction::operation_start(const string operation_name)
487{
that3f7b1ac2014-12-30 11:30:13 +0100488 LOGINFO("operation_start: '%s'\n", operation_name.c_str());
Samer Diab (S.a.M.e.R_d)71e9b042014-01-07 20:18:47 +0000489 time(&Start);
Dees_Troy51a0e822012-09-05 15:24:24 -0400490 DataManager::SetValue(TW_ACTION_BUSY, 1);
491 DataManager::SetValue("ui_progress", 0);
492 DataManager::SetValue("tw_operation", operation_name);
Dees_Troy51a0e822012-09-05 15:24:24 -0400493 DataManager::SetValue("tw_operation_state", 0);
Ethan Yonkerd83c9ea2015-01-02 15:22:31 -0600494 DataManager::SetValue("tw_operation_status", 0);
bigbiff bigbiff19874f12019-01-08 20:06:57 -0500495 bool tw_ab_device = TWFunc::get_cache_dir() != NON_AB_CACHE_DIR;
496 DataManager::SetValue("tw_ab_device", tw_ab_device);
Dees_Troy51a0e822012-09-05 15:24:24 -0400497}
498
that3f7b1ac2014-12-30 11:30:13 +0100499void GUIAction::operation_end(const int operation_status)
Dees_Troy51a0e822012-09-05 15:24:24 -0400500{
Samer Diab (S.a.M.e.R_d)71e9b042014-01-07 20:18:47 +0000501 time_t Stop;
Dees_Troy51a0e822012-09-05 15:24:24 -0400502 int simulate_fail;
Dees_Troy51a0e822012-09-05 15:24:24 -0400503 DataManager::SetValue("ui_progress", 100);
504 if (simulate) {
505 DataManager::GetValue(TW_SIMULATE_FAIL, simulate_fail);
506 if (simulate_fail != 0)
507 DataManager::SetValue("tw_operation_status", 1);
508 else
509 DataManager::SetValue("tw_operation_status", 0);
510 } else {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500511 if (operation_status != 0) {
Dees_Troy51a0e822012-09-05 15:24:24 -0400512 DataManager::SetValue("tw_operation_status", 1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500513 }
514 else {
Dees_Troy51a0e822012-09-05 15:24:24 -0400515 DataManager::SetValue("tw_operation_status", 0);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500516 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400517 }
518 DataManager::SetValue("tw_operation_state", 1);
519 DataManager::SetValue(TW_ACTION_BUSY, 0);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500520 blankTimer.resetTimerAndUnblank();
LuK133762326f42015-09-30 19:57:46 +0200521 property_set("twrp.action_complete", "1");
Samer Diab (S.a.M.e.R_d)71e9b042014-01-07 20:18:47 +0000522 time(&Stop);
bigbiff bigbiff3ed778a2019-03-12 19:28:31 -0400523
524#ifndef TW_NO_HAPTICS
Samer Diab (S.a.M.e.R_d)71e9b042014-01-07 20:18:47 +0000525 if ((int) difftime(Stop, Start) > 10)
Ethan Yonker03db3262014-02-05 08:02:06 -0600526 DataManager::Vibrate("tw_action_vibrate");
bigbiff bigbiff3ed778a2019-03-12 19:28:31 -0400527#endif
528
that3f7b1ac2014-12-30 11:30:13 +0100529 LOGINFO("operation_end - status=%d\n", operation_status);
Dees_Troy51a0e822012-09-05 15:24:24 -0400530}
531
that3f7b1ac2014-12-30 11:30:13 +0100532int GUIAction::reboot(std::string arg)
Dees_Troy51a0e822012-09-05 15:24:24 -0400533{
that3f7b1ac2014-12-30 11:30:13 +0100534 sync();
535 DataManager::SetValue("tw_gui_done", 1);
536 DataManager::SetValue("tw_reboot_arg", arg);
Dees_Troy51a0e822012-09-05 15:24:24 -0400537
that3f7b1ac2014-12-30 11:30:13 +0100538 return 0;
539}
Dees_Troy51a0e822012-09-05 15:24:24 -0400540
Ethan Yonkerd0514ba2015-10-22 14:17:47 -0500541int GUIAction::home(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +0100542{
that3f7b1ac2014-12-30 11:30:13 +0100543 gui_changePage("main");
544 return 0;
545}
Dees_Troy51a0e822012-09-05 15:24:24 -0400546
that3f7b1ac2014-12-30 11:30:13 +0100547int GUIAction::key(std::string arg)
548{
549 const int key = getKeyByName(arg);
550 PageManager::NotifyKey(key, true);
551 PageManager::NotifyKey(key, false);
552 return 0;
553}
554
555int GUIAction::page(std::string arg)
556{
LuK133762326f42015-09-30 19:57:46 +0200557 property_set("twrp.action_complete", "0");
that3f7b1ac2014-12-30 11:30:13 +0100558 std::string page_name = gui_parse_text(arg);
559 return gui_changePage(page_name);
560}
561
Ethan Yonkerd0514ba2015-10-22 14:17:47 -0500562int GUIAction::reload(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +0100563{
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -0500564 PageManager::RequestReload();
565 // The actual reload is handled in pages.cpp in PageManager::RunReload()
566 // The reload will occur on the next Update or Render call and will
567 // be performed in the rendoer thread instead of the action thread
568 // to prevent crashing which could occur when we start deleting
569 // GUI resources in the action thread while we attempt to render
570 // with those same resources in another thread.
that3f7b1ac2014-12-30 11:30:13 +0100571 return 0;
572}
Dees_Troy51a0e822012-09-05 15:24:24 -0400573
Ethan Yonkerd0514ba2015-10-22 14:17:47 -0500574int GUIAction::readBackup(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +0100575{
576 string Restore_Name;
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -0400577
that3f7b1ac2014-12-30 11:30:13 +0100578 DataManager::GetValue("tw_restore", Restore_Name);
579 PartitionManager.Set_Restore_Files(Restore_Name);
580 return 0;
581}
582
583int GUIAction::set(std::string arg)
584{
585 if (arg.find('=') != string::npos)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200586 {
that3f7b1ac2014-12-30 11:30:13 +0100587 string varName = arg.substr(0, arg.find('='));
588 string value = arg.substr(arg.find('=') + 1, string::npos);
Dees_Troy51a0e822012-09-05 15:24:24 -0400589
that3f7b1ac2014-12-30 11:30:13 +0100590 DataManager::GetValue(value, value);
591 DataManager::SetValue(varName, value);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200592 }
that3f7b1ac2014-12-30 11:30:13 +0100593 else
594 DataManager::SetValue(arg, "1");
595 return 0;
596}
Dees_Troy51a0e822012-09-05 15:24:24 -0400597
that3f7b1ac2014-12-30 11:30:13 +0100598int GUIAction::clear(std::string arg)
599{
600 DataManager::SetValue(arg, "0");
601 return 0;
602}
Dees_Troy51a0e822012-09-05 15:24:24 -0400603
that3f7b1ac2014-12-30 11:30:13 +0100604int GUIAction::mount(std::string arg)
605{
606 if (arg == "usb") {
607 DataManager::SetValue(TW_ACTION_BUSY, 1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400608 if (!simulate)
that3f7b1ac2014-12-30 11:30:13 +0100609 PartitionManager.usb_storage_enable();
610 else
Ethan Yonker74db1572015-10-28 12:44:49 -0500611 gui_msg("simulating=Simulating actions...");
that3f7b1ac2014-12-30 11:30:13 +0100612 } else if (!simulate) {
613 PartitionManager.Mount_By_Path(arg, true);
614 PartitionManager.Add_MTP_Storage(arg);
615 } else
Ethan Yonker74db1572015-10-28 12:44:49 -0500616 gui_msg("simulating=Simulating actions...");
that3f7b1ac2014-12-30 11:30:13 +0100617 return 0;
618}
619
620int GUIAction::unmount(std::string arg)
621{
622 if (arg == "usb") {
623 if (!simulate)
624 PartitionManager.usb_storage_disable();
625 else
Ethan Yonker74db1572015-10-28 12:44:49 -0500626 gui_msg("simulating=Simulating actions...");
that3f7b1ac2014-12-30 11:30:13 +0100627 DataManager::SetValue(TW_ACTION_BUSY, 0);
628 } else if (!simulate) {
629 PartitionManager.UnMount_By_Path(arg, true);
630 } else
Ethan Yonker74db1572015-10-28 12:44:49 -0500631 gui_msg("simulating=Simulating actions...");
that3f7b1ac2014-12-30 11:30:13 +0100632 return 0;
633}
634
Ethan Yonkerd0514ba2015-10-22 14:17:47 -0500635int GUIAction::restoredefaultsettings(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +0100636{
637 operation_start("Restore Defaults");
638 if (simulate) // Simulated so that people don't accidently wipe out the "simulation is on" setting
Ethan Yonker74db1572015-10-28 12:44:49 -0500639 gui_msg("simulating=Simulating actions...");
that3f7b1ac2014-12-30 11:30:13 +0100640 else {
641 DataManager::ResetDefaults();
642 PartitionManager.Update_System_Details();
643 PartitionManager.Mount_Current_Storage(true);
644 }
645 operation_end(0);
646 return 0;
647}
648
Ethan Yonkerd0514ba2015-10-22 14:17:47 -0500649int GUIAction::copylog(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +0100650{
651 operation_start("Copy Log");
652 if (!simulate)
653 {
bigbiff bigbiffbad332a2016-07-29 21:18:13 -0400654 string dst, curr_storage;
655 int copy_kernel_log = 0;
656
657 DataManager::GetValue("tw_include_kernel_log", copy_kernel_log);
that3f7b1ac2014-12-30 11:30:13 +0100658 PartitionManager.Mount_Current_Storage(true);
bigbiff bigbiffbad332a2016-07-29 21:18:13 -0400659 curr_storage = DataManager::GetCurrentStoragePath();
660 dst = curr_storage + "/recovery.log";
that3f7b1ac2014-12-30 11:30:13 +0100661 TWFunc::copy_file("/tmp/recovery.log", dst.c_str(), 0755);
662 tw_set_default_metadata(dst.c_str());
bigbiff bigbiffbad332a2016-07-29 21:18:13 -0400663 if (copy_kernel_log)
664 TWFunc::copy_kernel_log(curr_storage);
that3f7b1ac2014-12-30 11:30:13 +0100665 sync();
bigbiff bigbiffbad332a2016-07-29 21:18:13 -0400666 gui_msg(Msg("copy_log=Copied recovery log to {1}")(dst));
that3f7b1ac2014-12-30 11:30:13 +0100667 } else
668 simulate_progress_bar();
669 operation_end(0);
670 return 0;
671}
672
673
674int GUIAction::compute(std::string arg)
675{
676 if (arg.find("+") != string::npos)
677 {
678 string varName = arg.substr(0, arg.find('+'));
679 string string_to_add = arg.substr(arg.find('+') + 1, string::npos);
680 int amount_to_add = atoi(string_to_add.c_str());
681 int value;
682
683 DataManager::GetValue(varName, value);
684 DataManager::SetValue(varName, value + amount_to_add);
Dees_Troy51a0e822012-09-05 15:24:24 -0400685 return 0;
686 }
that3f7b1ac2014-12-30 11:30:13 +0100687 if (arg.find("-") != string::npos)
Dees_Troy51a0e822012-09-05 15:24:24 -0400688 {
that3f7b1ac2014-12-30 11:30:13 +0100689 string varName = arg.substr(0, arg.find('-'));
690 string string_to_subtract = arg.substr(arg.find('-') + 1, string::npos);
691 int amount_to_subtract = atoi(string_to_subtract.c_str());
692 int value;
Dees_Troy51a0e822012-09-05 15:24:24 -0400693
that3f7b1ac2014-12-30 11:30:13 +0100694 DataManager::GetValue(varName, value);
695 value -= amount_to_subtract;
696 if (value <= 0)
697 value = 0;
698 DataManager::SetValue(varName, value);
699 return 0;
700 }
701 if (arg.find("*") != string::npos)
702 {
703 string varName = arg.substr(0, arg.find('*'));
704 string multiply_by_str = gui_parse_text(arg.substr(arg.find('*') + 1, string::npos));
705 int multiply_by = atoi(multiply_by_str.c_str());
706 int value;
707
708 DataManager::GetValue(varName, value);
709 DataManager::SetValue(varName, value*multiply_by);
710 return 0;
711 }
712 if (arg.find("/") != string::npos)
713 {
714 string varName = arg.substr(0, arg.find('/'));
715 string divide_by_str = gui_parse_text(arg.substr(arg.find('/') + 1, string::npos));
716 int divide_by = atoi(divide_by_str.c_str());
717 int value;
718
Matt Mowera8a89d12016-12-30 18:10:37 -0600719 if (divide_by != 0)
that3f7b1ac2014-12-30 11:30:13 +0100720 {
Dees_Troy51a0e822012-09-05 15:24:24 -0400721 DataManager::GetValue(varName, value);
that3f7b1ac2014-12-30 11:30:13 +0100722 DataManager::SetValue(varName, value/divide_by);
Dees_Troy51a0e822012-09-05 15:24:24 -0400723 }
724 return 0;
725 }
that3f7b1ac2014-12-30 11:30:13 +0100726 LOGERR("Unable to perform compute '%s'\n", arg.c_str());
727 return -1;
728}
Dees_Troy51a0e822012-09-05 15:24:24 -0400729
Ethan Yonkerd0514ba2015-10-22 14:17:47 -0500730int GUIAction::setguitimezone(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +0100731{
732 string SelectedZone;
733 DataManager::GetValue(TW_TIME_ZONE_GUISEL, SelectedZone); // read the selected time zone into SelectedZone
734 string Zone = SelectedZone.substr(0, SelectedZone.find(';')); // parse to get time zone
735 string DSTZone = SelectedZone.substr(SelectedZone.find(';') + 1, string::npos); // parse to get DST component
736
737 int dst;
738 DataManager::GetValue(TW_TIME_ZONE_GUIDST, dst); // check wether user chose to use DST
739
740 string offset;
741 DataManager::GetValue(TW_TIME_ZONE_GUIOFFSET, offset); // pull in offset
742
743 string NewTimeZone = Zone;
744 if (offset != "0")
745 NewTimeZone += ":" + offset;
746
747 if (dst != 0)
748 NewTimeZone += DSTZone;
749
750 DataManager::SetValue(TW_TIME_ZONE_VAR, NewTimeZone);
751 DataManager::update_tz_environment_variables();
752 return 0;
753}
754
755int GUIAction::overlay(std::string arg)
756{
757 return gui_changeOverlay(arg);
758}
759
Ethan Yonkerd0514ba2015-10-22 14:17:47 -0500760int GUIAction::queuezip(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +0100761{
762 if (zip_queue_index >= 10) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500763 gui_msg("max_queue=Maximum zip queue reached!");
Dees_Troy51a0e822012-09-05 15:24:24 -0400764 return 0;
765 }
that3f7b1ac2014-12-30 11:30:13 +0100766 DataManager::GetValue("tw_filename", zip_queue[zip_queue_index]);
767 if (strlen(zip_queue[zip_queue_index].c_str()) > 0) {
768 zip_queue_index++;
Dees_Troy51a0e822012-09-05 15:24:24 -0400769 DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
that3f7b1ac2014-12-30 11:30:13 +0100770 }
771 return 0;
772}
773
Ethan Yonkerd0514ba2015-10-22 14:17:47 -0500774int GUIAction::cancelzip(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +0100775{
776 if (zip_queue_index <= 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500777 gui_msg("min_queue=Minimum zip queue reached!");
Dees_Troy51a0e822012-09-05 15:24:24 -0400778 return 0;
that3f7b1ac2014-12-30 11:30:13 +0100779 } else {
780 zip_queue_index--;
781 DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
Dees_Troy51a0e822012-09-05 15:24:24 -0400782 }
that3f7b1ac2014-12-30 11:30:13 +0100783 return 0;
784}
Dees_Troy51a0e822012-09-05 15:24:24 -0400785
Ethan Yonkerd0514ba2015-10-22 14:17:47 -0500786int GUIAction::queueclear(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +0100787{
788 zip_queue_index = 0;
789 DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
790 return 0;
791}
Dees_Troy51a0e822012-09-05 15:24:24 -0400792
that3f7b1ac2014-12-30 11:30:13 +0100793int GUIAction::sleep(std::string arg)
794{
795 operation_start("Sleep");
796 usleep(atoi(arg.c_str()));
797 operation_end(0);
798 return 0;
799}
Dees Troyb21cc642013-09-10 17:36:41 +0000800
Matt Mower9a2a2052016-05-31 21:31:22 -0500801int GUIAction::sleepcounter(std::string arg)
802{
803 operation_start("SleepCounter");
804 // Ensure user notices countdown in case it needs to be cancelled
805 blankTimer.resetTimerAndUnblank();
806 int total = atoi(arg.c_str());
807 for (int t = total; t > 0; t--) {
808 int progress = (int)(((float)(total-t)/(float)total)*100.0);
809 DataManager::SetValue("ui_progress", progress);
810 ::sleep(1);
811 DataManager::SetValue("tw_sleep", t-1);
812 }
813 DataManager::SetValue("ui_progress", 100);
814 operation_end(0);
815 return 0;
816}
817
Ethan Yonkerd0514ba2015-10-22 14:17:47 -0500818int GUIAction::appenddatetobackupname(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +0100819{
820 operation_start("AppendDateToBackupName");
821 string Backup_Name;
822 DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
823 Backup_Name += TWFunc::Get_Current_Date();
824 if (Backup_Name.size() > MAX_BACKUP_NAME_LEN)
825 Backup_Name.resize(MAX_BACKUP_NAME_LEN);
826 DataManager::SetValue(TW_BACKUP_NAME, Backup_Name);
Matt Mower76b8afc2016-06-24 12:04:27 -0500827 PageManager::NotifyKey(KEY_END, true);
828 PageManager::NotifyKey(KEY_END, false);
that3f7b1ac2014-12-30 11:30:13 +0100829 operation_end(0);
830 return 0;
831}
Ethan Yonker87c7bac2014-05-25 21:41:08 -0500832
Ethan Yonkerd0514ba2015-10-22 14:17:47 -0500833int GUIAction::generatebackupname(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +0100834{
835 operation_start("GenerateBackupName");
836 TWFunc::Auto_Generate_Backup_Name();
837 operation_end(0);
838 return 0;
839}
Ethan Yonker87c7bac2014-05-25 21:41:08 -0500840
Ethan Yonker483e9f42016-01-11 22:21:18 -0600841int GUIAction::checkpartitionlist(std::string arg)
that3f7b1ac2014-12-30 11:30:13 +0100842{
Ethan Yonker483e9f42016-01-11 22:21:18 -0600843 string List, part_path;
that3f7b1ac2014-12-30 11:30:13 +0100844 int count = 0;
Ethan Yonker87c7bac2014-05-25 21:41:08 -0500845
Ethan Yonker483e9f42016-01-11 22:21:18 -0600846 if (arg.empty())
847 arg = "tw_wipe_list";
848 DataManager::GetValue(arg, List);
849 LOGINFO("checkpartitionlist list '%s'\n", List.c_str());
850 if (!List.empty()) {
851 size_t start_pos = 0, end_pos = List.find(";", start_pos);
852 while (end_pos != string::npos && start_pos < List.size()) {
853 part_path = List.substr(start_pos, end_pos - start_pos);
854 LOGINFO("checkpartitionlist part_path '%s'\n", part_path.c_str());
855 if (part_path == "/and-sec" || part_path == "DALVIK" || part_path == "INTERNAL") {
that3f7b1ac2014-12-30 11:30:13 +0100856 // Do nothing
Dees_Troy51a0e822012-09-05 15:24:24 -0400857 } else {
that3f7b1ac2014-12-30 11:30:13 +0100858 count++;
859 }
860 start_pos = end_pos + 1;
Ethan Yonker483e9f42016-01-11 22:21:18 -0600861 end_pos = List.find(";", start_pos);
that3f7b1ac2014-12-30 11:30:13 +0100862 }
863 DataManager::SetValue("tw_check_partition_list", count);
864 } else {
865 DataManager::SetValue("tw_check_partition_list", 0);
866 }
Matt Mowera8a89d12016-12-30 18:10:37 -0600867 return 0;
that3f7b1ac2014-12-30 11:30:13 +0100868}
Dees_Troy51a0e822012-09-05 15:24:24 -0400869
Ethan Yonker483e9f42016-01-11 22:21:18 -0600870int GUIAction::getpartitiondetails(std::string arg)
that3f7b1ac2014-12-30 11:30:13 +0100871{
Ethan Yonker483e9f42016-01-11 22:21:18 -0600872 string List, part_path;
Dees_Troy51a0e822012-09-05 15:24:24 -0400873
Ethan Yonker483e9f42016-01-11 22:21:18 -0600874 if (arg.empty())
875 arg = "tw_wipe_list";
876 DataManager::GetValue(arg, List);
877 LOGINFO("getpartitiondetails list '%s'\n", List.c_str());
878 if (!List.empty()) {
879 size_t start_pos = 0, end_pos = List.find(";", start_pos);
880 part_path = List;
881 while (end_pos != string::npos && start_pos < List.size()) {
882 part_path = List.substr(start_pos, end_pos - start_pos);
883 LOGINFO("getpartitiondetails part_path '%s'\n", part_path.c_str());
884 if (part_path == "/and-sec" || part_path == "DALVIK" || part_path == "INTERNAL") {
that3f7b1ac2014-12-30 11:30:13 +0100885 // Do nothing
886 } else {
Ethan Yonker483e9f42016-01-11 22:21:18 -0600887 DataManager::SetValue("tw_partition_path", part_path);
that3f7b1ac2014-12-30 11:30:13 +0100888 break;
889 }
890 start_pos = end_pos + 1;
Ethan Yonker483e9f42016-01-11 22:21:18 -0600891 end_pos = List.find(";", start_pos);
that3f7b1ac2014-12-30 11:30:13 +0100892 }
Ethan Yonker483e9f42016-01-11 22:21:18 -0600893 if (!part_path.empty()) {
894 TWPartition* Part = PartitionManager.Find_Partition_By_Path(part_path);
that3f7b1ac2014-12-30 11:30:13 +0100895 if (Part) {
896 unsigned long long mb = 1048576;
Dees_Troya13d74f2013-03-24 08:54:55 -0500897
that3f7b1ac2014-12-30 11:30:13 +0100898 DataManager::SetValue("tw_partition_name", Part->Display_Name);
899 DataManager::SetValue("tw_partition_mount_point", Part->Mount_Point);
900 DataManager::SetValue("tw_partition_file_system", Part->Current_File_System);
901 DataManager::SetValue("tw_partition_size", Part->Size / mb);
902 DataManager::SetValue("tw_partition_used", Part->Used / mb);
903 DataManager::SetValue("tw_partition_free", Part->Free / mb);
904 DataManager::SetValue("tw_partition_backup_size", Part->Backup_Size / mb);
905 DataManager::SetValue("tw_partition_removable", Part->Removable);
906 DataManager::SetValue("tw_partition_is_present", Part->Is_Present);
907
908 if (Part->Can_Repair())
909 DataManager::SetValue("tw_partition_can_repair", 1);
910 else
911 DataManager::SetValue("tw_partition_can_repair", 0);
Ethan Yonkera2719152015-05-28 09:44:41 -0500912 if (Part->Can_Resize())
913 DataManager::SetValue("tw_partition_can_resize", 1);
914 else
915 DataManager::SetValue("tw_partition_can_resize", 0);
Matt Mower18794c82015-11-11 16:22:45 -0600916 if (TWFunc::Path_Exists("/sbin/mkfs.fat"))
that3f7b1ac2014-12-30 11:30:13 +0100917 DataManager::SetValue("tw_partition_vfat", 1);
918 else
919 DataManager::SetValue("tw_partition_vfat", 0);
Matt Mower80f7b362015-12-12 15:38:01 -0600920 if (TWFunc::Path_Exists("/sbin/mkexfatfs"))
that3f7b1ac2014-12-30 11:30:13 +0100921 DataManager::SetValue("tw_partition_exfat", 1);
922 else
923 DataManager::SetValue("tw_partition_exfat", 0);
924 if (TWFunc::Path_Exists("/sbin/mkfs.f2fs"))
925 DataManager::SetValue("tw_partition_f2fs", 1);
926 else
927 DataManager::SetValue("tw_partition_f2fs", 0);
928 if (TWFunc::Path_Exists("/sbin/mke2fs"))
929 DataManager::SetValue("tw_partition_ext", 1);
930 else
931 DataManager::SetValue("tw_partition_ext", 0);
932 return 0;
933 } else {
Ethan Yonker483e9f42016-01-11 22:21:18 -0600934 LOGERR("Unable to locate partition: '%s'\n", part_path.c_str());
that3f7b1ac2014-12-30 11:30:13 +0100935 }
936 }
937 }
938 DataManager::SetValue("tw_partition_name", "");
939 DataManager::SetValue("tw_partition_file_system", "");
Ethan Yonker483e9f42016-01-11 22:21:18 -0600940 // Set this to 0 to prevent trying to partition this device, just in case
941 DataManager::SetValue("tw_partition_removable", 0);
that3f7b1ac2014-12-30 11:30:13 +0100942 return 0;
943}
944
Ethan Yonkerd0514ba2015-10-22 14:17:47 -0500945int GUIAction::screenshot(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +0100946{
947 time_t tm;
948 char path[256];
949 int path_len;
Matt Mower0c88b842017-01-15 16:00:49 -0600950 uid_t uid = AID_MEDIA_RW;
951 gid_t gid = AID_MEDIA_RW;
that3f7b1ac2014-12-30 11:30:13 +0100952
953 const std::string storage = DataManager::GetCurrentStoragePath();
Matt Mowera8a89d12016-12-30 18:10:37 -0600954 if (PartitionManager.Is_Mounted_By_Path(storage)) {
that3f7b1ac2014-12-30 11:30:13 +0100955 snprintf(path, sizeof(path), "%s/Pictures/Screenshots/", storage.c_str());
956 } else {
957 strcpy(path, "/tmp/");
958 }
959
Matt Mowera8a89d12016-12-30 18:10:37 -0600960 if (!TWFunc::Create_Dir_Recursive(path, 0775, uid, gid))
that3f7b1ac2014-12-30 11:30:13 +0100961 return 0;
962
963 tm = time(NULL);
964 path_len = strlen(path);
965
966 // Screenshot_2014-01-01-18-21-38.png
967 strftime(path+path_len, sizeof(path)-path_len, "Screenshot_%Y-%m-%d-%H-%M-%S.png", localtime(&tm));
968
969 int res = gr_save_screenshot(path);
Matt Mowera8a89d12016-12-30 18:10:37 -0600970 if (res == 0) {
that3f7b1ac2014-12-30 11:30:13 +0100971 chmod(path, 0666);
972 chown(path, uid, gid);
973
that677b13f2015-12-26 23:57:31 +0100974 gui_msg(Msg("screenshot_saved=Screenshot was saved to {1}")(path));
that3f7b1ac2014-12-30 11:30:13 +0100975
976 // blink to notify that the screenshow was taken
977 gr_color(255, 255, 255, 255);
978 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
979 gr_flip();
980 gui_forceRender();
981 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -0500982 gui_err("screenshot_err=Failed to take a screenshot!");
that3f7b1ac2014-12-30 11:30:13 +0100983 }
984 return 0;
985}
986
987int GUIAction::setbrightness(std::string arg)
988{
989 return TWFunc::Set_Brightness(arg);
990}
991
992int GUIAction::fileexists(std::string arg)
993{
994 struct stat st;
995 string newpath = arg + "/.";
996
997 operation_start("FileExists");
998 if (stat(arg.c_str(), &st) == 0 || stat(newpath.c_str(), &st) == 0)
999 operation_end(0);
1000 else
1001 operation_end(1);
1002 return 0;
1003}
1004
thatcc8ddca2015-01-03 01:59:36 +01001005void GUIAction::reinject_after_flash()
1006{
1007 if (DataManager::GetIntValue(TW_HAS_INJECTTWRP) == 1 && DataManager::GetIntValue(TW_INJECT_AFTER_ZIP) == 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001008 gui_msg("injecttwrp=Injecting TWRP into boot image...");
thatcc8ddca2015-01-03 01:59:36 +01001009 if (simulate) {
1010 simulate_progress_bar();
1011 } else {
1012 TWPartition* Boot = PartitionManager.Find_Partition_By_Path("/boot");
1013 if (Boot == NULL || Boot->Current_File_System != "emmc")
1014 TWFunc::Exec_Cmd("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash");
1015 else {
1016 string injectcmd = "injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash bd=" + Boot->Actual_Block_Device;
1017 TWFunc::Exec_Cmd(injectcmd);
1018 }
Ethan Yonker74db1572015-10-28 12:44:49 -05001019 gui_msg("done=Done.");
thatcc8ddca2015-01-03 01:59:36 +01001020 }
1021 }
1022}
1023
that3f7b1ac2014-12-30 11:30:13 +01001024int GUIAction::flash(std::string arg)
1025{
1026 int i, ret_val = 0, wipe_cache = 0;
Ethan Yonker0d47eb52015-01-09 11:23:19 -06001027 // We're going to jump to this page first, like a loading page
1028 gui_changePage(arg);
that3f7b1ac2014-12-30 11:30:13 +01001029 for (i=0; i<zip_queue_index; i++) {
thatc7b631b2015-06-01 23:36:57 +02001030 string zip_path = zip_queue[i];
1031 size_t slashpos = zip_path.find_last_of('/');
1032 string zip_filename = (slashpos == string::npos) ? zip_path : zip_path.substr(slashpos + 1);
that3f7b1ac2014-12-30 11:30:13 +01001033 operation_start("Flashing");
thatc7b631b2015-06-01 23:36:57 +02001034 DataManager::SetValue("tw_filename", zip_path);
1035 DataManager::SetValue("tw_file", zip_filename);
that3f7b1ac2014-12-30 11:30:13 +01001036 DataManager::SetValue(TW_ZIP_INDEX, (i + 1));
1037
1038 TWFunc::SetPerformanceMode(true);
thatc7b631b2015-06-01 23:36:57 +02001039 ret_val = flash_zip(zip_path, &wipe_cache);
that3f7b1ac2014-12-30 11:30:13 +01001040 TWFunc::SetPerformanceMode(false);
1041 if (ret_val != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001042 gui_msg(Msg(msg::kError, "zip_err=Error installing zip file '{1}'")(zip_path));
that3f7b1ac2014-12-30 11:30:13 +01001043 ret_val = 1;
Ethan Yonker0d47eb52015-01-09 11:23:19 -06001044 break;
that3f7b1ac2014-12-30 11:30:13 +01001045 }
1046 }
1047 zip_queue_index = 0;
that3f7b1ac2014-12-30 11:30:13 +01001048
Ethan Yonker0d47eb52015-01-09 11:23:19 -06001049 if (wipe_cache) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001050 gui_msg("zip_wipe_cache=One or more zip requested a cache wipe -- Wiping cache now.");
that3f7b1ac2014-12-30 11:30:13 +01001051 PartitionManager.Wipe_By_Path("/cache");
Ethan Yonker0d47eb52015-01-09 11:23:19 -06001052 }
that3f7b1ac2014-12-30 11:30:13 +01001053
thatcc8ddca2015-01-03 01:59:36 +01001054 reinject_after_flash();
that3f7b1ac2014-12-30 11:30:13 +01001055 PartitionManager.Update_System_Details();
1056 operation_end(ret_val);
bigbiffa869fc72016-03-01 19:40:36 -05001057 // This needs to be after the operation_end call so we change pages before we change variables that we display on the screen
Ethan Yonker0d47eb52015-01-09 11:23:19 -06001058 DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
that3f7b1ac2014-12-30 11:30:13 +01001059 return 0;
1060}
1061
1062int GUIAction::wipe(std::string arg)
1063{
1064 operation_start("Format");
1065 DataManager::SetValue("tw_partition", arg);
that3f7b1ac2014-12-30 11:30:13 +01001066 int ret_val = false;
1067
1068 if (simulate) {
1069 simulate_progress_bar();
1070 } else {
1071 if (arg == "data")
1072 ret_val = PartitionManager.Factory_Reset();
1073 else if (arg == "battery")
1074 ret_val = PartitionManager.Wipe_Battery_Stats();
1075 else if (arg == "rotate")
1076 ret_val = PartitionManager.Wipe_Rotate_Data();
1077 else if (arg == "dalvik")
1078 ret_val = PartitionManager.Wipe_Dalvik_Cache();
1079 else if (arg == "DATAMEDIA") {
1080 ret_val = PartitionManager.Format_Data();
1081 } else if (arg == "INTERNAL") {
Matt Mower23d8aae2017-01-06 14:30:33 -06001082 int has_datamedia;
that3f7b1ac2014-12-30 11:30:13 +01001083
1084 DataManager::GetValue(TW_HAS_DATA_MEDIA, has_datamedia);
1085 if (has_datamedia) {
1086 ret_val = PartitionManager.Wipe_Media_From_Data();
1087 } else {
1088 ret_val = PartitionManager.Wipe_By_Path(DataManager::GetSettingsStoragePath());
1089 }
1090 } else if (arg == "EXTERNAL") {
1091 string External_Path;
1092
1093 DataManager::GetValue(TW_EXTERNAL_PATH, External_Path);
1094 ret_val = PartitionManager.Wipe_By_Path(External_Path);
1095 } else if (arg == "ANDROIDSECURE") {
1096 ret_val = PartitionManager.Wipe_Android_Secure();
1097 } else if (arg == "LIST") {
1098 string Wipe_List, wipe_path;
1099 bool skip = false;
1100 ret_val = true;
that3f7b1ac2014-12-30 11:30:13 +01001101
1102 DataManager::GetValue("tw_wipe_list", Wipe_List);
1103 LOGINFO("wipe list '%s'\n", Wipe_List.c_str());
1104 if (!Wipe_List.empty()) {
1105 size_t start_pos = 0, end_pos = Wipe_List.find(";", start_pos);
1106 while (end_pos != string::npos && start_pos < Wipe_List.size()) {
1107 wipe_path = Wipe_List.substr(start_pos, end_pos - start_pos);
1108 LOGINFO("wipe_path '%s'\n", wipe_path.c_str());
1109 if (wipe_path == "/and-sec") {
1110 if (!PartitionManager.Wipe_Android_Secure()) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001111 gui_msg("and_sec_wipe_err=Unable to wipe android secure");
that3f7b1ac2014-12-30 11:30:13 +01001112 ret_val = false;
1113 break;
1114 } else {
1115 skip = true;
1116 }
1117 } else if (wipe_path == "DALVIK") {
1118 if (!PartitionManager.Wipe_Dalvik_Cache()) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001119 gui_err("dalvik_wipe_err=Failed to wipe dalvik");
that3f7b1ac2014-12-30 11:30:13 +01001120 ret_val = false;
1121 break;
1122 } else {
1123 skip = true;
1124 }
1125 } else if (wipe_path == "INTERNAL") {
1126 if (!PartitionManager.Wipe_Media_From_Data()) {
1127 ret_val = false;
1128 break;
1129 } else {
1130 skip = true;
Dees_Troya13d74f2013-03-24 08:54:55 -05001131 }
1132 }
that3f7b1ac2014-12-30 11:30:13 +01001133 if (!skip) {
1134 if (!PartitionManager.Wipe_By_Path(wipe_path)) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001135 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(wipe_path));
that3f7b1ac2014-12-30 11:30:13 +01001136 ret_val = false;
1137 break;
1138 } else if (wipe_path == DataManager::GetSettingsStoragePath()) {
1139 arg = wipe_path;
1140 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001141 } else {
that3f7b1ac2014-12-30 11:30:13 +01001142 skip = false;
Dees_Troy38bd7602012-09-14 13:33:53 -04001143 }
that3f7b1ac2014-12-30 11:30:13 +01001144 start_pos = end_pos + 1;
1145 end_pos = Wipe_List.find(";", start_pos);
Dees_Troy51a0e822012-09-05 15:24:24 -04001146 }
1147 }
that3f7b1ac2014-12-30 11:30:13 +01001148 } else
1149 ret_val = PartitionManager.Wipe_By_Path(arg);
that73a52952015-01-28 23:07:34 +01001150#ifndef TW_OEM_BUILD
that3f7b1ac2014-12-30 11:30:13 +01001151 if (arg == DataManager::GetSettingsStoragePath()) {
1152 // If we wiped the settings storage path, recreate the TWRP folder and dump the settings
1153 string Storage_Path = DataManager::GetSettingsStoragePath();
Dees_Troy51a0e822012-09-05 15:24:24 -04001154
that3f7b1ac2014-12-30 11:30:13 +01001155 if (PartitionManager.Mount_By_Path(Storage_Path, true)) {
1156 LOGINFO("Making TWRP folder and saving settings.\n");
1157 Storage_Path += "/TWRP";
1158 mkdir(Storage_Path.c_str(), 0777);
1159 DataManager::Flush();
Dees_Troy51a0e822012-09-05 15:24:24 -04001160 } else {
that3f7b1ac2014-12-30 11:30:13 +01001161 LOGERR("Unable to recreate TWRP folder and save settings.\n");
1162 }
1163 }
1164#endif
1165 }
1166 PartitionManager.Update_System_Details();
1167 if (ret_val)
1168 ret_val = 0; // 0 is success
1169 else
1170 ret_val = 1; // 1 is failure
1171 operation_end(ret_val);
1172 return 0;
1173}
Samer Diab (S.a.M.e.R_d)71e9b042014-01-07 20:18:47 +00001174
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001175int GUIAction::refreshsizes(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001176{
1177 operation_start("Refreshing Sizes");
1178 if (simulate) {
1179 simulate_progress_bar();
1180 } else
1181 PartitionManager.Update_System_Details();
1182 operation_end(0);
1183 return 0;
1184}
1185
1186int GUIAction::nandroid(std::string arg)
1187{
that3f7b1ac2014-12-30 11:30:13 +01001188 if (simulate) {
that73a52952015-01-28 23:07:34 +01001189 PartitionManager.stop_backup.set_value(0);
that3f7b1ac2014-12-30 11:30:13 +01001190 DataManager::SetValue("tw_partition", "Simulation");
1191 simulate_progress_bar();
that73a52952015-01-28 23:07:34 +01001192 operation_end(0);
that3f7b1ac2014-12-30 11:30:13 +01001193 } else {
bigbiff7abc5fe2015-01-17 16:53:12 -05001194 operation_start("Nandroid");
1195 int ret = 0;
1196
that3f7b1ac2014-12-30 11:30:13 +01001197 if (arg == "backup") {
1198 string Backup_Name;
1199 DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
Ethan Yonker4adc33e2016-01-22 16:07:11 -06001200 string auto_gen = gui_lookup("auto_generate", "(Auto Generate)");
Ethan Yonker53796e72019-01-11 22:49:52 -06001201 if (Backup_Name == auto_gen || Backup_Name == gui_lookup("curr_date", "(Current Date)") || Backup_Name == "0" || Backup_Name == "(" || PartitionManager.Check_Backup_Name(Backup_Name, true, true) == 0) {
bigbiffce8f83c2015-12-12 18:30:21 -05001202 ret = PartitionManager.Run_Backup(false);
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -04001203 DataManager::SetValue("tw_encrypt_backup", 0); // reset value so we don't encrypt every subsequent backup
1204 if (!PartitionManager.stop_backup.get_value()) {
1205 if (ret == false)
1206 ret = 1; // 1 for failure
1207 else
1208 ret = 0; // 0 for success
1209 DataManager::SetValue("tw_cancel_backup", 0);
1210 } else {
1211 DataManager::SetValue("tw_cancel_backup", 1);
1212 gui_msg("backup_cancel=Backup Cancelled");
1213 ret = 0;
1214 }
bigbiffce8f83c2015-12-12 18:30:21 -05001215 } else {
that3f7b1ac2014-12-30 11:30:13 +01001216 operation_end(1);
1217 return -1;
that3f7b1ac2014-12-30 11:30:13 +01001218 }
Ethan Yonker74db1572015-10-28 12:44:49 -05001219 DataManager::SetValue(TW_BACKUP_NAME, auto_gen);
that3f7b1ac2014-12-30 11:30:13 +01001220 } else if (arg == "restore") {
1221 string Restore_Name;
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -04001222 int gui_adb_backup;
1223
that3f7b1ac2014-12-30 11:30:13 +01001224 DataManager::GetValue("tw_restore", Restore_Name);
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -04001225 DataManager::GetValue("tw_enable_adb_backup", gui_adb_backup);
1226 if (gui_adb_backup) {
1227 DataManager::SetValue("tw_operation_state", 1);
1228 if (TWFunc::stream_adb_backup(Restore_Name) == 0)
1229 ret = 0; // success
1230 else
1231 ret = 1; // failure
1232 DataManager::SetValue("tw_enable_adb_backup", 0);
1233 ret = 0; // assume success???
1234 } else {
1235 if (PartitionManager.Run_Restore(Restore_Name))
1236 ret = 0; // success
1237 else
1238 ret = 1; // failure
1239 }
that3f7b1ac2014-12-30 11:30:13 +01001240 } else {
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -04001241 operation_end(1); // invalid arg specified, fail
bigbiff7abc5fe2015-01-17 16:53:12 -05001242 return -1;
1243 }
that73a52952015-01-28 23:07:34 +01001244 operation_end(ret);
bigbiff7abc5fe2015-01-17 16:53:12 -05001245 return ret;
1246 }
1247 return 0;
1248}
1249
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001250int GUIAction::cancelbackup(std::string arg __unused) {
bigbiff7abc5fe2015-01-17 16:53:12 -05001251 if (simulate) {
bigbiff7abc5fe2015-01-17 16:53:12 -05001252 PartitionManager.stop_backup.set_value(1);
bigbiff7abc5fe2015-01-17 16:53:12 -05001253 }
1254 else {
bigbiff7abc5fe2015-01-17 16:53:12 -05001255 int op_status = PartitionManager.Cancel_Backup();
1256 if (op_status != 0)
1257 op_status = 1; // failure
bigbiff7abc5fe2015-01-17 16:53:12 -05001258 }
1259
1260 return 0;
that3f7b1ac2014-12-30 11:30:13 +01001261}
Dees_Troy51a0e822012-09-05 15:24:24 -04001262
Ethan Yonkerb5fab762016-01-28 14:03:33 -06001263int GUIAction::fixcontexts(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001264{
that73a52952015-01-28 23:07:34 +01001265 int op_status = 0;
1266
Ethan Yonkerb5fab762016-01-28 14:03:33 -06001267 operation_start("Fix Contexts");
1268 LOGINFO("fix contexts started!\n");
that3f7b1ac2014-12-30 11:30:13 +01001269 if (simulate) {
1270 simulate_progress_bar();
1271 } else {
Ethan Yonkerb5fab762016-01-28 14:03:33 -06001272 op_status = PartitionManager.Fix_Contexts();
that3f7b1ac2014-12-30 11:30:13 +01001273 if (op_status != 0)
1274 op_status = 1; // failure
that3f7b1ac2014-12-30 11:30:13 +01001275 }
that73a52952015-01-28 23:07:34 +01001276 operation_end(op_status);
that3f7b1ac2014-12-30 11:30:13 +01001277 return 0;
1278}
1279
Ethan Yonkerb5fab762016-01-28 14:03:33 -06001280int GUIAction::fixpermissions(std::string arg)
1281{
1282 return fixcontexts(arg);
1283}
1284
that3f7b1ac2014-12-30 11:30:13 +01001285int GUIAction::dd(std::string arg)
1286{
1287 operation_start("imaging");
1288
1289 if (simulate) {
1290 simulate_progress_bar();
1291 } else {
1292 string cmd = "dd " + arg;
1293 TWFunc::Exec_Cmd(cmd);
1294 }
1295 operation_end(0);
1296 return 0;
1297}
1298
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001299int GUIAction::partitionsd(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001300{
1301 operation_start("Partition SD Card");
1302 int ret_val = 0;
1303
1304 if (simulate) {
1305 simulate_progress_bar();
1306 } else {
1307 int allow_partition;
1308 DataManager::GetValue(TW_ALLOW_PARTITION_SDCARD, allow_partition);
1309 if (allow_partition == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001310 gui_err("no_real_sdcard=This device does not have a real SD Card! Aborting!");
that3f7b1ac2014-12-30 11:30:13 +01001311 } else {
1312 if (!PartitionManager.Partition_SDCard())
1313 ret_val = 1; // failed
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001314 }
that3f7b1ac2014-12-30 11:30:13 +01001315 }
1316 operation_end(ret_val);
1317 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001318
that3f7b1ac2014-12-30 11:30:13 +01001319}
Dees_Troy51a0e822012-09-05 15:24:24 -04001320
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001321int GUIAction::installhtcdumlock(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001322{
1323 operation_start("Install HTC Dumlock");
1324 if (simulate) {
1325 simulate_progress_bar();
1326 } else
1327 TWFunc::install_htc_dumlock();
Dees_Troy51a0e822012-09-05 15:24:24 -04001328
that3f7b1ac2014-12-30 11:30:13 +01001329 operation_end(0);
1330 return 0;
1331}
Dees_Troy51a0e822012-09-05 15:24:24 -04001332
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001333int GUIAction::htcdumlockrestoreboot(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001334{
1335 operation_start("HTC Dumlock Restore Boot");
1336 if (simulate) {
1337 simulate_progress_bar();
1338 } else
1339 TWFunc::htc_dumlock_restore_original_boot();
Dees_Troy51a0e822012-09-05 15:24:24 -04001340
that3f7b1ac2014-12-30 11:30:13 +01001341 operation_end(0);
1342 return 0;
1343}
Dees_Troy51a0e822012-09-05 15:24:24 -04001344
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001345int GUIAction::htcdumlockreflashrecovery(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001346{
1347 operation_start("HTC Dumlock Reflash Recovery");
1348 if (simulate) {
1349 simulate_progress_bar();
1350 } else
1351 TWFunc::htc_dumlock_reflash_recovery_to_boot();
Dees_Troy51a0e822012-09-05 15:24:24 -04001352
that3f7b1ac2014-12-30 11:30:13 +01001353 operation_end(0);
1354 return 0;
1355}
Dees_Troy51a0e822012-09-05 15:24:24 -04001356
that3f7b1ac2014-12-30 11:30:13 +01001357int GUIAction::cmd(std::string arg)
1358{
1359 int op_status = 0;
1360
1361 operation_start("Command");
1362 LOGINFO("Running command: '%s'\n", arg.c_str());
1363 if (simulate) {
1364 simulate_progress_bar();
1365 } else {
1366 op_status = TWFunc::Exec_Cmd(arg);
1367 if (op_status != 0)
1368 op_status = 1;
1369 }
1370
1371 operation_end(op_status);
1372 return 0;
1373}
1374
1375int GUIAction::terminalcommand(std::string arg)
1376{
1377 int op_status = 0;
1378 string cmdpath, command;
1379
1380 DataManager::GetValue("tw_terminal_location", cmdpath);
1381 operation_start("CommandOutput");
1382 gui_print("%s # %s\n", cmdpath.c_str(), arg.c_str());
1383 if (simulate) {
1384 simulate_progress_bar();
1385 operation_end(op_status);
Matt Mower5aa29ab2015-02-25 23:50:55 -06001386 } else if (arg == "exit") {
1387 LOGINFO("Exiting terminal\n");
1388 operation_end(op_status);
1389 page("main");
that3f7b1ac2014-12-30 11:30:13 +01001390 } else {
1391 command = "cd \"" + cmdpath + "\" && " + arg + " 2>&1";;
1392 LOGINFO("Actual command is: '%s'\n", command.c_str());
that3f7b1ac2014-12-30 11:30:13 +01001393 DataManager::SetValue("tw_terminal_state", 1);
1394 DataManager::SetValue("tw_background_thread_running", 1);
thatc6085482015-01-09 22:12:43 +01001395 FILE* fp;
1396 char line[512];
1397
1398 fp = popen(command.c_str(), "r");
1399 if (fp == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001400 LOGERR("Error opening command to run (%s).\n", strerror(errno));
thatc6085482015-01-09 22:12:43 +01001401 } else {
Matt Mower23d8aae2017-01-06 14:30:33 -06001402 int fd = fileno(fp), has_data = 0, check = 0, keep_going = -1;
thatc6085482015-01-09 22:12:43 +01001403 struct timeval timeout;
1404 fd_set fdset;
1405
Matt Mowera8a89d12016-12-30 18:10:37 -06001406 while (keep_going)
thatc6085482015-01-09 22:12:43 +01001407 {
1408 FD_ZERO(&fdset);
1409 FD_SET(fd, &fdset);
1410 timeout.tv_sec = 0;
1411 timeout.tv_usec = 400000;
1412 has_data = select(fd+1, &fdset, NULL, NULL, &timeout);
1413 if (has_data == 0) {
1414 // Timeout reached
1415 DataManager::GetValue("tw_terminal_state", check);
1416 if (check == 0) {
1417 keep_going = 0;
1418 }
1419 } else if (has_data < 0) {
1420 // End of execution
1421 keep_going = 0;
1422 } else {
1423 // Try to read output
Matt Mowera8a89d12016-12-30 18:10:37 -06001424 if (fgets(line, sizeof(line), fp) != NULL)
thatc6085482015-01-09 22:12:43 +01001425 gui_print("%s", line); // Display output
1426 else
1427 keep_going = 0; // Done executing
1428 }
1429 }
1430 fclose(fp);
Dees_Troy51a0e822012-09-05 15:24:24 -04001431 }
thatc6085482015-01-09 22:12:43 +01001432 DataManager::SetValue("tw_operation_status", 0);
1433 DataManager::SetValue("tw_operation_state", 1);
1434 DataManager::SetValue("tw_terminal_state", 0);
1435 DataManager::SetValue("tw_background_thread_running", 0);
1436 DataManager::SetValue(TW_ACTION_BUSY, 0);
that3f7b1ac2014-12-30 11:30:13 +01001437 }
1438 return 0;
1439}
1440
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001441int GUIAction::killterminal(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001442{
that3f7b1ac2014-12-30 11:30:13 +01001443 LOGINFO("Sending kill command...\n");
1444 operation_start("KillCommand");
1445 DataManager::SetValue("tw_operation_status", 0);
1446 DataManager::SetValue("tw_operation_state", 1);
1447 DataManager::SetValue("tw_terminal_state", 0);
1448 DataManager::SetValue("tw_background_thread_running", 0);
1449 DataManager::SetValue(TW_ACTION_BUSY, 0);
1450 return 0;
1451}
1452
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001453int GUIAction::reinjecttwrp(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001454{
1455 int op_status = 0;
1456 operation_start("ReinjectTWRP");
Ethan Yonker74db1572015-10-28 12:44:49 -05001457 gui_msg("injecttwrp=Injecting TWRP into boot image...");
that3f7b1ac2014-12-30 11:30:13 +01001458 if (simulate) {
1459 simulate_progress_bar();
1460 } else {
1461 TWFunc::Exec_Cmd("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash");
Ethan Yonker74db1572015-10-28 12:44:49 -05001462 gui_msg("done=Done.");
that3f7b1ac2014-12-30 11:30:13 +01001463 }
1464
1465 operation_end(op_status);
1466 return 0;
1467}
1468
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001469int GUIAction::checkbackupname(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001470{
1471 int op_status = 0;
1472
1473 operation_start("CheckBackupName");
1474 if (simulate) {
1475 simulate_progress_bar();
1476 } else {
Ethan Yonker53796e72019-01-11 22:49:52 -06001477 string Backup_Name;
1478 DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
1479 op_status = PartitionManager.Check_Backup_Name(Backup_Name, true, true);
that3f7b1ac2014-12-30 11:30:13 +01001480 if (op_status != 0)
1481 op_status = 1;
1482 }
1483
1484 operation_end(op_status);
1485 return 0;
1486}
1487
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001488int GUIAction::decrypt(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001489{
1490 int op_status = 0;
1491
1492 operation_start("Decrypt");
1493 if (simulate) {
1494 simulate_progress_bar();
1495 } else {
1496 string Password;
1497 DataManager::GetValue("tw_crypto_password", Password);
1498 op_status = PartitionManager.Decrypt_Device(Password);
1499 if (op_status != 0)
1500 op_status = 1;
1501 else {
that3f7b1ac2014-12-30 11:30:13 +01001502
1503 DataManager::SetValue(TW_IS_ENCRYPTED, 0);
1504
Ethan Yonkercf50da52015-01-12 21:59:07 -06001505 int has_datamedia;
that3f7b1ac2014-12-30 11:30:13 +01001506
Ethan Yonkercf50da52015-01-12 21:59:07 -06001507 // Check for a custom theme and load it if exists
1508 DataManager::GetValue(TW_HAS_DATA_MEDIA, has_datamedia);
1509 if (has_datamedia != 0) {
1510 if (tw_get_default_metadata(DataManager::GetSettingsStoragePath().c_str()) != 0) {
Ethan Yonkerd9ff3c52015-01-21 21:51:20 -06001511 LOGINFO("Failed to get default contexts and file mode for storage files.\n");
Ethan Yonkercf50da52015-01-12 21:59:07 -06001512 } else {
1513 LOGINFO("Got default contexts and file mode for storage files.\n");
that3f7b1ac2014-12-30 11:30:13 +01001514 }
1515 }
Ethan Yonker66a19492015-12-10 10:19:45 -06001516 PartitionManager.Decrypt_Adopted();
that3f7b1ac2014-12-30 11:30:13 +01001517 }
1518 }
1519
1520 operation_end(op_status);
1521 return 0;
1522}
1523
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001524int GUIAction::adbsideload(std::string arg __unused)
thatcc8ddca2015-01-03 01:59:36 +01001525{
1526 operation_start("Sideload");
1527 if (simulate) {
1528 simulate_progress_bar();
1529 operation_end(0);
1530 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001531 gui_msg("start_sideload=Starting ADB sideload feature...");
thatc6085482015-01-09 22:12:43 +01001532 bool mtp_was_enabled = TWFunc::Toggle_MTP(false);
1533
1534 // wait for the adb connection
1535 int ret = apply_from_adb("/", &sideload_child_pid);
1536 DataManager::SetValue("tw_has_cancel", 0); // Remove cancel button from gui now that the zip install is going to start
1537
1538 if (ret != 0) {
1539 if (ret == -2)
Ethan Yonker74db1572015-10-28 12:44:49 -05001540 gui_msg("need_new_adb=You need adb 1.0.32 or newer to sideload to this device.");
thatc6085482015-01-09 22:12:43 +01001541 ret = 1; // failure
1542 } else {
1543 int wipe_cache = 0;
1544 int wipe_dalvik = 0;
1545 DataManager::GetValue("tw_wipe_dalvik", wipe_dalvik);
1546
1547 if (TWinstall_zip(FUSE_SIDELOAD_HOST_PATHNAME, &wipe_cache) == 0) {
1548 if (wipe_cache || DataManager::GetIntValue("tw_wipe_cache"))
1549 PartitionManager.Wipe_By_Path("/cache");
1550 if (wipe_dalvik)
1551 PartitionManager.Wipe_Dalvik_Cache();
1552 } else {
1553 ret = 1; // failure
1554 }
thatcc8ddca2015-01-03 01:59:36 +01001555 }
thatc6085482015-01-09 22:12:43 +01001556 if (sideload_child_pid) {
1557 LOGINFO("Signaling child sideload process to exit.\n");
1558 struct stat st;
1559 // Calling stat() on this magic filename signals the minadbd
1560 // subprocess to shut down.
1561 stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st);
1562 int status;
1563 LOGINFO("Waiting for child sideload process to exit.\n");
1564 waitpid(sideload_child_pid, &status, 0);
1565 }
Dees Troy28a85d22015-04-28 02:03:16 +00001566 property_set("ctl.start", "adbd");
thatc6085482015-01-09 22:12:43 +01001567 TWFunc::Toggle_MTP(mtp_was_enabled);
1568 reinject_after_flash();
1569 operation_end(ret);
thatcc8ddca2015-01-03 01:59:36 +01001570 }
that3f7b1ac2014-12-30 11:30:13 +01001571 return 0;
1572}
1573
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001574int GUIAction::adbsideloadcancel(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001575{
that3f7b1ac2014-12-30 11:30:13 +01001576 struct stat st;
1577 DataManager::SetValue("tw_has_cancel", 0); // Remove cancel button from gui
Ethan Yonker74db1572015-10-28 12:44:49 -05001578 gui_msg("cancel_sideload=Cancelling ADB sideload...");
thatcc8ddca2015-01-03 01:59:36 +01001579 LOGINFO("Signaling child sideload process to exit.\n");
1580 // Calling stat() on this magic filename signals the minadbd
1581 // subprocess to shut down.
1582 stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st);
1583 if (!sideload_child_pid) {
1584 LOGERR("Unable to get child ID\n");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001585 return 0;
1586 }
thatcc8ddca2015-01-03 01:59:36 +01001587 ::sleep(1);
1588 LOGINFO("Killing child sideload process.\n");
1589 kill(sideload_child_pid, SIGTERM);
1590 int status;
1591 LOGINFO("Waiting for child sideload process to exit.\n");
1592 waitpid(sideload_child_pid, &status, 0);
1593 sideload_child_pid = 0;
that3f7b1ac2014-12-30 11:30:13 +01001594 DataManager::SetValue("tw_page_done", "1"); // For OpenRecoveryScript support
1595 return 0;
1596}
1597
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001598int GUIAction::openrecoveryscript(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001599{
1600 operation_start("OpenRecoveryScript");
1601 if (simulate) {
1602 simulate_progress_bar();
Ethan Yonker24e7eb72015-01-03 16:13:06 -06001603 operation_end(0);
that3f7b1ac2014-12-30 11:30:13 +01001604 } else {
that10ae24f2015-12-26 20:53:51 +01001605 int op_status = OpenRecoveryScript::Run_OpenRecoveryScript_Action();
Ethan Yonkere1abe612015-06-09 11:09:32 -05001606 operation_end(op_status);
that3f7b1ac2014-12-30 11:30:13 +01001607 }
1608 return 0;
1609}
1610
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001611int GUIAction::installsu(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001612{
1613 int op_status = 0;
1614
1615 operation_start("Install SuperSU");
1616 if (simulate) {
1617 simulate_progress_bar();
1618 } else {
Ethan Yonkerfa67cbf2018-07-20 12:22:33 -05001619 LOGERR("Installing SuperSU was deprecated from TWRP.\n");
that3f7b1ac2014-12-30 11:30:13 +01001620 }
1621
1622 operation_end(op_status);
1623 return 0;
1624}
1625
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001626int GUIAction::fixsu(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001627{
1628 int op_status = 0;
1629
1630 operation_start("Fixing Superuser Permissions");
1631 if (simulate) {
1632 simulate_progress_bar();
1633 } else {
1634 LOGERR("Fixing su permissions was deprecated from TWRP.\n");
1635 LOGERR("4.3+ ROMs with SELinux will always lose su perms.\n");
1636 }
1637
1638 operation_end(op_status);
1639 return 0;
1640}
1641
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001642int GUIAction::decrypt_backup(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001643{
1644 int op_status = 0;
1645
1646 operation_start("Try Restore Decrypt");
1647 if (simulate) {
1648 simulate_progress_bar();
1649 } else {
1650 string Restore_Path, Filename, Password;
1651 DataManager::GetValue("tw_restore", Restore_Path);
1652 Restore_Path += "/";
1653 DataManager::GetValue("tw_restore_password", Password);
1654 TWFunc::SetPerformanceMode(true);
1655 if (TWFunc::Try_Decrypting_Backup(Restore_Path, Password))
1656 op_status = 0; // success
1657 else
1658 op_status = 1; // fail
1659 TWFunc::SetPerformanceMode(false);
1660 }
1661
1662 operation_end(op_status);
1663 return 0;
1664}
1665
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001666int GUIAction::repair(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001667{
1668 int op_status = 0;
1669
1670 operation_start("Repair Partition");
1671 if (simulate) {
1672 simulate_progress_bar();
1673 } else {
1674 string part_path;
1675 DataManager::GetValue("tw_partition_mount_point", part_path);
1676 if (PartitionManager.Repair_By_Path(part_path, true)) {
1677 op_status = 0; // success
1678 } else {
that3f7b1ac2014-12-30 11:30:13 +01001679 op_status = 1; // fail
1680 }
1681 }
1682
1683 operation_end(op_status);
1684 return 0;
1685}
1686
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001687int GUIAction::resize(std::string arg __unused)
Ethan Yonkera2719152015-05-28 09:44:41 -05001688{
1689 int op_status = 0;
1690
1691 operation_start("Resize Partition");
1692 if (simulate) {
1693 simulate_progress_bar();
1694 } else {
1695 string part_path;
1696 DataManager::GetValue("tw_partition_mount_point", part_path);
1697 if (PartitionManager.Resize_By_Path(part_path, true)) {
1698 op_status = 0; // success
1699 } else {
Ethan Yonkera2719152015-05-28 09:44:41 -05001700 op_status = 1; // fail
1701 }
1702 }
1703
1704 operation_end(op_status);
1705 return 0;
1706}
1707
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001708int GUIAction::changefilesystem(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001709{
1710 int op_status = 0;
1711
1712 operation_start("Change File System");
1713 if (simulate) {
1714 simulate_progress_bar();
1715 } else {
1716 string part_path, file_system;
1717 DataManager::GetValue("tw_partition_mount_point", part_path);
1718 DataManager::GetValue("tw_action_new_file_system", file_system);
1719 if (PartitionManager.Wipe_By_Path(part_path, file_system)) {
1720 op_status = 0; // success
1721 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001722 gui_err("change_fs_err=Error changing file system.");
that3f7b1ac2014-12-30 11:30:13 +01001723 op_status = 1; // fail
1724 }
1725 }
1726 PartitionManager.Update_System_Details();
1727 operation_end(op_status);
1728 return 0;
1729}
1730
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001731int GUIAction::startmtp(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001732{
1733 int op_status = 0;
1734
1735 operation_start("Start MTP");
1736 if (PartitionManager.Enable_MTP())
1737 op_status = 0; // success
1738 else
1739 op_status = 1; // fail
1740
1741 operation_end(op_status);
1742 return 0;
1743}
1744
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001745int GUIAction::stopmtp(std::string arg __unused)
that3f7b1ac2014-12-30 11:30:13 +01001746{
1747 int op_status = 0;
1748
1749 operation_start("Stop MTP");
1750 if (PartitionManager.Disable_MTP())
1751 op_status = 0; // success
1752 else
1753 op_status = 1; // fail
1754
1755 operation_end(op_status);
1756 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001757}
1758
Ethan Yonkerd0514ba2015-10-22 14:17:47 -05001759int GUIAction::flashimage(std::string arg __unused)
Ethan Yonker96af84a2015-01-05 14:58:36 -06001760{
1761 int op_status = 0;
1762
1763 operation_start("Flash Image");
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05001764 string path, filename;
1765 DataManager::GetValue("tw_zip_location", path);
1766 DataManager::GetValue("tw_file", filename);
Ethan Yonkere080c1f2016-09-19 13:50:25 -05001767 if (PartitionManager.Flash_Image(path, filename))
Ethan Yonker96af84a2015-01-05 14:58:36 -06001768 op_status = 0; // success
1769 else
1770 op_status = 1; // fail
1771
1772 operation_end(op_status);
1773 return 0;
1774}
1775
that10ae24f2015-12-26 20:53:51 +01001776int GUIAction::twcmd(std::string arg)
1777{
1778 operation_start("TWRP CLI Command");
1779 if (simulate)
1780 simulate_progress_bar();
1781 else
1782 OpenRecoveryScript::Run_CLI_Command(arg.c_str());
1783 operation_end(0);
1784 return 0;
1785}
1786
Dees_Troy51a0e822012-09-05 15:24:24 -04001787int GUIAction::getKeyByName(std::string key)
1788{
that8834a0f2016-01-05 23:29:30 +01001789 if (key == "home") return KEY_HOMEPAGE; // note: KEY_HOME is cursor movement (like KEY_END)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001790 else if (key == "menu") return KEY_MENU;
1791 else if (key == "back") return KEY_BACK;
1792 else if (key == "search") return KEY_SEARCH;
1793 else if (key == "voldown") return KEY_VOLUMEDOWN;
1794 else if (key == "volup") return KEY_VOLUMEUP;
1795 else if (key == "power") {
Dees_Troy51a0e822012-09-05 15:24:24 -04001796 int ret_val;
1797 DataManager::GetValue(TW_POWER_BUTTON, ret_val);
1798 if (!ret_val)
1799 return KEY_POWER;
1800 else
1801 return ret_val;
1802 }
1803
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001804 return atol(key.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -04001805}
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001806
1807int GUIAction::checkpartitionlifetimewrites(std::string arg)
1808{
1809 int op_status = 0;
1810 TWPartition* sys = PartitionManager.Find_Partition_By_Path(arg);
1811
1812 operation_start("Check Partition Lifetime Writes");
1813 if (sys) {
1814 if (sys->Check_Lifetime_Writes() != 0)
1815 DataManager::SetValue("tw_lifetime_writes", 1);
1816 else
1817 DataManager::SetValue("tw_lifetime_writes", 0);
1818 op_status = 0; // success
1819 } else {
1820 DataManager::SetValue("tw_lifetime_writes", 1);
1821 op_status = 1; // fail
1822 }
1823
1824 operation_end(op_status);
1825 return 0;
1826}
1827
1828int GUIAction::mountsystemtoggle(std::string arg)
1829{
1830 int op_status = 0;
Captain Throwback9d6feb52018-07-27 10:05:24 -04001831 bool remount_system = PartitionManager.Is_Mounted_By_Path(PartitionManager.Get_Android_Root_Path());
Ethan Yonker1673e3d2015-10-26 21:51:58 -05001832 bool remount_vendor = PartitionManager.Is_Mounted_By_Path("/vendor");
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001833
1834 operation_start("Toggle System Mount");
Captain Throwback9d6feb52018-07-27 10:05:24 -04001835 if (!PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), true)) {
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001836 op_status = 1; // fail
1837 } else {
Captain Throwback9d6feb52018-07-27 10:05:24 -04001838 TWPartition* Part = PartitionManager.Find_Partition_By_Path(PartitionManager.Get_Android_Root_Path());
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001839 if (Part) {
Ethan Yonkerd6966f42015-05-30 14:52:16 -05001840 if (arg == "0") {
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001841 DataManager::SetValue("tw_mount_system_ro", 0);
1842 Part->Change_Mount_Read_Only(false);
1843 } else {
1844 DataManager::SetValue("tw_mount_system_ro", 1);
1845 Part->Change_Mount_Read_Only(true);
1846 }
1847 if (remount_system) {
1848 Part->Mount(true);
1849 }
1850 op_status = 0; // success
1851 } else {
1852 op_status = 1; // fail
1853 }
Ethan Yonker1673e3d2015-10-26 21:51:58 -05001854 Part = PartitionManager.Find_Partition_By_Path("/vendor");
1855 if (Part) {
1856 if (arg == "0") {
1857 Part->Change_Mount_Read_Only(false);
1858 } else {
1859 Part->Change_Mount_Read_Only(true);
1860 }
1861 if (remount_vendor) {
1862 Part->Mount(true);
1863 }
1864 op_status = 0; // success
1865 } else {
1866 op_status = 1; // fail
1867 }
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001868 }
1869
1870 operation_end(op_status);
1871 return 0;
1872}
Ethan Yonker74db1572015-10-28 12:44:49 -05001873
1874int GUIAction::setlanguage(std::string arg __unused)
1875{
1876 int op_status = 0;
1877
1878 operation_start("Set Language");
1879 PageManager::LoadLanguage(DataManager::GetStrValue("tw_language"));
1880 PageManager::RequestReload();
1881 op_status = 0; // success
1882
1883 operation_end(op_status);
1884 return 0;
1885}
Ethan Yonker1b190162016-12-05 15:25:19 -06001886
Matt Mower9472ba12016-01-20 18:12:47 -06001887int GUIAction::togglebacklight(std::string arg __unused)
1888{
1889 blankTimer.toggleBlank();
1890 return 0;
1891}
1892
Ethan Yonker1b190162016-12-05 15:25:19 -06001893int GUIAction::setbootslot(std::string arg)
1894{
1895 operation_start("Set Boot Slot");
1896 if (!simulate)
Ethan Yonker1b190162016-12-05 15:25:19 -06001897 PartitionManager.Set_Active_Slot(arg);
Matt Mower029a82d2017-01-08 13:12:38 -06001898 else
Ethan Yonker1b190162016-12-05 15:25:19 -06001899 simulate_progress_bar();
1900 operation_end(0);
1901 return 0;
1902}
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -06001903
1904int GUIAction::checkforapp(std::string arg __unused)
1905{
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -06001906 operation_start("Check for TWRP App");
1907 if (!simulate)
1908 {
1909 string sdkverstr = TWFunc::System_Property_Get("ro.build.version.sdk");
1910 int sdkver = 0;
1911 if (!sdkverstr.empty()) {
1912 sdkver = atoi(sdkverstr.c_str());
1913 }
1914 if (sdkver <= 13) {
1915 if (sdkver == 0)
1916 LOGINFO("Unable to read sdk version from build prop\n");
1917 else
1918 LOGINFO("SDK version too low for TWRP app (%i < 14)\n", sdkver);
Ethan Yonker64c5c0a2017-03-06 12:42:54 -06001919 DataManager::SetValue("tw_app_install_status", 1); // 0 = no status, 1 = not installed, 2 = already installed or do not install
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -06001920 goto exit;
1921 }
Captain Throwback9d6feb52018-07-27 10:05:24 -04001922 if (PartitionManager.Mount_By_Path(PartitionManager.Get_Android_Root_Path(), false)) {
1923 string base_path = PartitionManager.Get_Android_Root_Path();
1924 if (TWFunc::Path_Exists(PartitionManager.Get_Android_Root_Path() + "/system"))
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -06001925 base_path += "/system"; // For devices with system as a root file system (e.g. Pixel)
1926 string install_path = base_path + "/priv-app";
1927 if (!TWFunc::Path_Exists(install_path))
1928 install_path = base_path + "/app";
1929 install_path += "/twrpapp";
1930 if (TWFunc::Path_Exists(install_path)) {
1931 LOGINFO("App found at '%s'\n", install_path.c_str());
Ethan Yonker64c5c0a2017-03-06 12:42:54 -06001932 DataManager::SetValue("tw_app_install_status", 2); // 0 = no status, 1 = not installed, 2 = already installed or do not install
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -06001933 goto exit;
1934 }
Ethan Yonker5e1a7f92017-01-18 16:44:54 -06001935 }
1936 if (PartitionManager.Mount_By_Path("/data", false)) {
Ethan Yonker5128d292017-02-04 19:52:56 -06001937 const char parent_path[] = "/data/app";
1938 const char app_prefix[] = "me.twrp.twrpapp-";
1939 DIR *d = opendir(parent_path);
1940 if (d) {
1941 struct dirent *p;
1942 while ((p = readdir(d))) {
1943 if (p->d_type != DT_DIR || strlen(p->d_name) < strlen(app_prefix) || strncmp(p->d_name, app_prefix, strlen(app_prefix)))
1944 continue;
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -06001945 closedir(d);
Ethan Yonker5128d292017-02-04 19:52:56 -06001946 LOGINFO("App found at '%s/%s'\n", parent_path, p->d_name);
Ethan Yonker64c5c0a2017-03-06 12:42:54 -06001947 DataManager::SetValue("tw_app_install_status", 2); // 0 = no status, 1 = not installed, 2 = already installed or do not install
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -06001948 goto exit;
1949 }
Ethan Yonker5128d292017-02-04 19:52:56 -06001950 closedir(d);
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -06001951 }
Ethan Yonker64c5c0a2017-03-06 12:42:54 -06001952 } else {
1953 LOGINFO("Data partition cannot be mounted during app check\n");
1954 DataManager::SetValue("tw_app_install_status", 2); // 0 = no status, 1 = not installed, 2 = already installed or do not install
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -06001955 }
1956 } else
1957 simulate_progress_bar();
1958 LOGINFO("App not installed\n");
1959 DataManager::SetValue("tw_app_install_status", 1); // 0 = no status, 1 = not installed, 2 = already installed
1960exit:
1961 operation_end(0);
1962 return 0;
1963}
1964
1965int GUIAction::installapp(std::string arg __unused)
1966{
1967 int op_status = 1;
1968 operation_start("Install TWRP App");
1969 if (!simulate)
1970 {
1971 if (DataManager::GetIntValue("tw_mount_system_ro") > 0 || DataManager::GetIntValue("tw_app_install_system") == 0) {
1972 if (PartitionManager.Mount_By_Path("/data", true)) {
1973 string install_path = "/data/app";
1974 string context = "u:object_r:apk_data_file:s0";
1975 if (!TWFunc::Path_Exists(install_path)) {
1976 if (mkdir(install_path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) {
1977 LOGERR("Error making %s directory: %s\n", install_path.c_str(), strerror(errno));
1978 goto exit;
1979 }
1980 if (chown(install_path.c_str(), 1000, 1000)) {
1981 LOGERR("chown %s error: %s\n", install_path.c_str(), strerror(errno));
1982 goto exit;
1983 }
Ethan Yonker4767caf2017-01-11 10:45:04 -06001984 if (setfilecon(install_path.c_str(), (security_context_t)context.c_str()) < 0) {
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -06001985 LOGERR("setfilecon %s error: %s\n", install_path.c_str(), strerror(errno));
1986 goto exit;
1987 }
1988 }
1989 install_path += "/me.twrp.twrpapp-1";
1990 if (mkdir(install_path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) {
1991 LOGERR("Error making %s directory: %s\n", install_path.c_str(), strerror(errno));
1992 goto exit;
1993 }
1994 if (chown(install_path.c_str(), 1000, 1000)) {
1995 LOGERR("chown %s error: %s\n", install_path.c_str(), strerror(errno));
1996 goto exit;
1997 }
Ethan Yonker4767caf2017-01-11 10:45:04 -06001998 if (setfilecon(install_path.c_str(), (security_context_t)context.c_str()) < 0) {
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -06001999 LOGERR("setfilecon %s error: %s\n", install_path.c_str(), strerror(errno));
2000 goto exit;
2001 }
2002 install_path += "/base.apk";
2003 if (TWFunc::copy_file("/sbin/me.twrp.twrpapp.apk", install_path, 0644)) {
2004 LOGERR("Error copying apk file\n");
2005 goto exit;
2006 }
2007 if (chown(install_path.c_str(), 1000, 1000)) {
2008 LOGERR("chown %s error: %s\n", install_path.c_str(), strerror(errno));
2009 goto exit;
2010 }
Ethan Yonker4767caf2017-01-11 10:45:04 -06002011 if (setfilecon(install_path.c_str(), (security_context_t)context.c_str()) < 0) {
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -06002012 LOGERR("setfilecon %s error: %s\n", install_path.c_str(), strerror(errno));
2013 goto exit;
2014 }
2015 sync();
2016 sync();
2017 }
2018 } else {
Captain Throwback9d6feb52018-07-27 10:05:24 -04002019 if (PartitionManager.Mount_By_Path(PartitionManager.Get_Android_Root_Path(), true)) {
2020 string base_path = PartitionManager.Get_Android_Root_Path();
2021 if (TWFunc::Path_Exists(PartitionManager.Get_Android_Root_Path() + "/system"))
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -06002022 base_path += "/system"; // For devices with system as a root file system (e.g. Pixel)
2023 string install_path = base_path + "/priv-app";
2024 string context = "u:object_r:system_file:s0";
2025 if (!TWFunc::Path_Exists(install_path))
2026 install_path = base_path + "/app";
2027 if (TWFunc::Path_Exists(install_path)) {
2028 install_path += "/twrpapp";
2029 LOGINFO("Installing app to '%s'\n", install_path.c_str());
2030 if (mkdir(install_path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0) {
Ethan Yonker4767caf2017-01-11 10:45:04 -06002031 if (setfilecon(install_path.c_str(), (security_context_t)context.c_str()) < 0) {
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -06002032 LOGERR("setfilecon %s error: %s\n", install_path.c_str(), strerror(errno));
2033 goto exit;
2034 }
2035 install_path += "/me.twrp.twrpapp.apk";
2036 if (TWFunc::copy_file("/sbin/me.twrp.twrpapp.apk", install_path, 0644)) {
2037 LOGERR("Error copying apk file\n");
2038 goto exit;
2039 }
Ethan Yonker4767caf2017-01-11 10:45:04 -06002040 if (setfilecon(install_path.c_str(), (security_context_t)context.c_str()) < 0) {
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -06002041 LOGERR("setfilecon %s error: %s\n", install_path.c_str(), strerror(errno));
2042 goto exit;
2043 }
2044 sync();
2045 sync();
Captain Throwback9d6feb52018-07-27 10:05:24 -04002046 PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), true);
Ethan Yonkerb4bff5e2016-12-16 07:47:58 -06002047 op_status = 0;
2048 } else {
2049 LOGERR("Error making app directory '%s': %s\n", strerror(errno));
2050 }
2051 }
2052 }
2053 }
2054 } else
2055 simulate_progress_bar();
2056exit:
2057 operation_end(0);
2058 return 0;
2059}
Ethan Yonker53796e72019-01-11 22:49:52 -06002060
2061int GUIAction::repackimage(std::string arg __unused)
2062{
2063 int op_status = 1;
2064 operation_start("Repack Image");
2065 if (!simulate)
2066 {
2067 std::string path = DataManager::GetStrValue("tw_filename");
2068 Repack_Options_struct Repack_Options;
2069 Repack_Options.Disable_Verity = false;
2070 Repack_Options.Disable_Force_Encrypt = false;
2071 Repack_Options.Backup_First = DataManager::GetIntValue("tw_repack_backup_first") != 0;
2072 if (DataManager::GetIntValue("tw_repack_kernel") == 1)
2073 Repack_Options.Type = REPLACE_KERNEL;
2074 else
2075 Repack_Options.Type = REPLACE_RAMDISK;
2076 if (!PartitionManager.Repack_Images(path, Repack_Options))
2077 goto exit;
2078 } else
2079 simulate_progress_bar();
2080 op_status = 0;
2081exit:
2082 operation_end(op_status);
2083 return 0;
2084}
2085
2086int GUIAction::fixabrecoverybootloop(std::string arg __unused)
2087{
2088 int op_status = 1;
2089 operation_start("Repack Image");
2090 if (!simulate)
2091 {
2092 if (!TWFunc::Path_Exists("/sbin/magiskboot")) {
2093 LOGERR("Image repacking tool not present in this TWRP build!");
2094 goto exit;
2095 }
2096 DataManager::SetProgress(0);
2097 TWPartition* part = PartitionManager.Find_Partition_By_Path("/boot");
2098 if (part)
2099 gui_msg(Msg("unpacking_image=Unpacking {1}...")(part->Display_Name));
2100 else {
2101 gui_msg(Msg(msg::kError, "unable_to_locate=Unable to locate {1}.")("/boot"));
2102 goto exit;
2103 }
2104 if (!PartitionManager.Prepare_Repack(part, REPACK_ORIG_DIR, DataManager::GetIntValue("tw_repack_backup_first") != 0, gui_lookup("repack", "Repack")))
2105 goto exit;
2106 DataManager::SetProgress(.25);
2107 gui_msg("fixing_recovery_loop_patch=Patching kernel...");
2108 std::string command = "cd " REPACK_ORIG_DIR " && /sbin/magiskboot --hexpatch kernel 77616E745F696E697472616D667300 736B69705F696E697472616D667300";
2109 if (TWFunc::Exec_Cmd(command) != 0) {
2110 gui_msg(Msg(msg::kError, "fix_recovery_loop_patch_error=Error patching kernel."));
2111 goto exit;
2112 }
2113 std::string header_path = REPACK_ORIG_DIR;
2114 header_path += "header";
2115 if (TWFunc::Path_Exists(header_path)) {
2116 command = "cd " REPACK_ORIG_DIR " && sed -i \"s|$(grep '^cmdline=' header | cut -d= -f2-)|$(grep '^cmdline=' header | cut -d= -f2- | sed -e 's/skip_override//' -e 's/ */ /g' -e 's/[ \t]*$//')|\" header";
2117 if (TWFunc::Exec_Cmd(command) != 0) {
2118 gui_msg(Msg(msg::kError, "fix_recovery_loop_patch_error=Error patching kernel."));
2119 goto exit;
2120 }
2121 }
2122 DataManager::SetProgress(.5);
2123 gui_msg(Msg("repacking_image=Repacking {1}...")(part->Display_Name));
2124 command = "cd " REPACK_ORIG_DIR " && /sbin/magiskboot --repack " REPACK_ORIG_DIR "boot.img";
2125 if (TWFunc::Exec_Cmd(command) != 0) {
2126 gui_msg(Msg(msg::kError, "repack_error=Error repacking image."));
2127 goto exit;
2128 }
2129 DataManager::SetProgress(.75);
2130 std::string path = REPACK_ORIG_DIR;
2131 std::string file = "new-boot.img";
2132 DataManager::SetValue("tw_flash_partition", "/boot;");
2133 if (!PartitionManager.Flash_Image(path, file)) {
2134 LOGINFO("Error flashing new image\n");
2135 goto exit;
2136 }
2137 DataManager::SetProgress(1);
2138 TWFunc::removeDir(REPACK_ORIG_DIR, false);
2139 } else
2140 simulate_progress_bar();
2141 op_status = 0;
2142exit:
2143 operation_end(op_status);
2144 return 0;
2145}