blob: 3e19a6132048f487611ba5f21d558f8c2e807c74 [file] [log] [blame]
Dees_Troy51a0e822012-09-05 15:24:24 -04001// image.cpp - GUIImage object
2
3#include <stdarg.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <fcntl.h>
8#include <sys/stat.h>
9#include <sys/time.h>
10#include <sys/mman.h>
11#include <sys/types.h>
12#include <sys/ioctl.h>
13#include <linux/input.h>
14#include <time.h>
15#include <unistd.h>
16#include <stdlib.h>
Dees_Troy657c3092012-09-10 20:32:10 -040017#include <sys/wait.h>
Dees_Troy51a0e822012-09-05 15:24:24 -040018
19#include <string>
20#include <sstream>
21#include "../partitions.hpp"
22
23extern "C" {
24#include "../common.h"
25#include "../roots.h"
26#include "../tw_reboot.h"
27#include "../minuitwrp/minui.h"
28#include "../recovery_ui.h"
Dees_Troy5bf43922012-09-07 16:07:55 -040029#include "../extra-functions.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040030#include "../variables.h"
31
Dees_Troy51a0e822012-09-05 15:24:24 -040032void fix_perms();
33void wipe_dalvik_cache(void);
34int check_backup_name(int show_error);
35void wipe_battery_stats(void);
36void wipe_rotate_data(void);
37int usb_storage_enable(void);
38int usb_storage_disable(void);
39int __system(const char *command);
40FILE * __popen(const char *program, const char *type);
41int __pclose(FILE *iop);
42void run_script(const char *str1, const char *str2, const char *str3, const char *str4, const char *str5, const char *str6, const char *str7, int request_confirm);
43void update_tz_environment_variables();
44void install_htc_dumlock(void);
45void htc_dumlock_restore_original_boot(void);
46void htc_dumlock_reflash_recovery_to_boot(void);
47int check_for_script_file(void);
48int gui_console_only();
49int run_script_file(void);
50int gui_start();
51};
52
53#include "rapidxml.hpp"
54#include "objects.hpp"
55
Dees_Troy51a0e822012-09-05 15:24:24 -040056void curtainClose(void);
57
58GUIAction::GUIAction(xml_node<>* node)
59 : Conditional(node)
60{
61 xml_node<>* child;
62 xml_node<>* actions;
63 xml_attribute<>* attr;
64
65 mKey = 0;
66
67 if (!node) return;
68
69 // First, get the action
70 actions = node->first_node("actions");
71 if (actions) child = actions->first_node("action");
72 else child = node->first_node("action");
73
74 if (!child) return;
75
76 while (child)
77 {
78 Action action;
79
80 attr = child->first_attribute("function");
81 if (!attr) return;
82
83 action.mFunction = attr->value();
84 action.mArg = child->value();
85 mActions.push_back(action);
86
87 child = child->next_sibling("action");
88 }
89
90 // Now, let's get either the key or region
91 child = node->first_node("touch");
92 if (child)
93 {
94 attr = child->first_attribute("key");
95 if (attr)
96 {
97 std::string key = attr->value();
98
99 mKey = getKeyByName(key);
100 }
101 else
102 {
103 attr = child->first_attribute("x");
104 if (!attr) return;
105 mActionX = atol(attr->value());
106 attr = child->first_attribute("y");
107 if (!attr) return;
108 mActionY = atol(attr->value());
109 attr = child->first_attribute("w");
110 if (!attr) return;
111 mActionW = atol(attr->value());
112 attr = child->first_attribute("h");
113 if (!attr) return;
114 mActionH = atol(attr->value());
115 }
116 }
117}
118
119int GUIAction::NotifyTouch(TOUCH_STATE state, int x, int y)
120{
121 if (state == TOUCH_RELEASE)
122 doActions();
123
124 return 0;
125}
126
127int GUIAction::NotifyKey(int key)
128{
129 if (!mKey || key != mKey)
130 return 1;
131
132 doActions();
133 return 0;
134}
135
136int GUIAction::NotifyVarChange(std::string varName, std::string value)
137{
138 if (varName.empty() && !isConditionValid() && !mKey && !mActionW)
139 doActions();
140
141 // This handles notifying the condition system of page start
142 if (varName.empty() && isConditionValid())
143 NotifyPageSet();
144
145 if ((varName.empty() || IsConditionVariable(varName)) && isConditionValid() && isConditionTrue())
146 doActions();
147
148 return 0;
149}
150
151void GUIAction::simulate_progress_bar(void)
152{
153 ui_print("Simulating actions...\n");
154 for (int i = 0; i < 5; i++)
155 {
156 usleep(500000);
157 DataManager::SetValue("ui_progress", i * 20);
158 }
159}
160
Dees_Troy657c3092012-09-10 20:32:10 -0400161int GUIAction::flash_zip(std::string filename, std::string pageName, const int simulate, int* wipe_cache)
Dees_Troy51a0e822012-09-05 15:24:24 -0400162{
163 int ret_val = 0;
164
165 DataManager::SetValue("ui_progress", 0);
166
167 if (filename.empty())
168 {
169 LOGE("No file specified.\n");
170 return -1;
171 }
172
173 // We're going to jump to this page first, like a loading page
174 gui_changePage(pageName);
175
176 int fd = -1;
177 ZipArchive zip;
178
Dees_Troy657c3092012-09-10 20:32:10 -0400179 if (!PartitionManager.Mount_By_Path(filename, true))
180 return -1;
181
182 if (mzOpenZipArchive(filename.c_str(), &zip))
Dees_Troy51a0e822012-09-05 15:24:24 -0400183 {
184 LOGE("Unable to open zip file.\n");
185 return -1;
186 }
187
188 // Check the zip to see if it has a custom installer theme
189 const ZipEntry* twrp = mzFindZipEntry(&zip, "META-INF/teamwin/twrp.zip");
190 if (twrp != NULL)
191 {
192 unlink("/tmp/twrp.zip");
193 fd = creat("/tmp/twrp.zip", 0666);
194 }
195 if (fd >= 0 && twrp != NULL &&
196 mzExtractZipEntryToFile(&zip, twrp, fd) &&
197 !PageManager::LoadPackage("install", "/tmp/twrp.zip", "main"))
198 {
199 mzCloseZipArchive(&zip);
Dees_Troy657c3092012-09-10 20:32:10 -0400200 PageManager::SelectPackage("install");
Dees_Troy51a0e822012-09-05 15:24:24 -0400201 gui_changePage("main");
202 }
203 else
204 {
205 // In this case, we just use the default page
206 mzCloseZipArchive(&zip);
Dees_Troy657c3092012-09-10 20:32:10 -0400207 gui_changePage(pageName);
Dees_Troy51a0e822012-09-05 15:24:24 -0400208 }
209 if (fd >= 0)
210 close(fd);
211
212 if (simulate) {
213 simulate_progress_bar();
214 } else {
Dees_Troy657c3092012-09-10 20:32:10 -0400215 ret_val = TWinstall_zip(filename.c_str(), wipe_cache);
Dees_Troy51a0e822012-09-05 15:24:24 -0400216
217 // Now, check if we need to ensure TWRP remains installed...
218 struct stat st;
219 if (stat("/sbin/installTwrp", &st) == 0)
220 {
221 DataManager::SetValue("tw_operation", "Configuring TWRP");
222 DataManager::SetValue("tw_partition", "");
223 ui_print("Configuring TWRP...\n");
224 if (__system("/sbin/installTwrp reinstall") < 0)
225 {
226 ui_print("Unable to configure TWRP with this kernel.\n");
227 }
228 }
229 }
230
231 // Done
232 DataManager::SetValue("ui_progress", 100);
233 DataManager::SetValue("ui_progress", 0);
234 return ret_val;
235}
236
237int GUIAction::doActions()
238{
239 if (mActions.size() < 1) return -1;
240 if (mActions.size() == 1)
241 return doAction(mActions.at(0), 0);
242
243 // For multi-action, we always use a thread
244 pthread_t t;
245 pthread_create(&t, NULL, thread_start, this);
246
247 return 0;
248}
249
250void* GUIAction::thread_start(void *cookie)
251{
252 GUIAction* ourThis = (GUIAction*) cookie;
253
254 DataManager::SetValue(TW_ACTION_BUSY, 1);
255
256 if (ourThis->mActions.size() > 1)
257 {
258 std::vector<Action>::iterator iter;
259 for (iter = ourThis->mActions.begin(); iter != ourThis->mActions.end(); iter++)
260 ourThis->doAction(*iter, 1);
261 }
262 else
263 {
264 ourThis->doAction(ourThis->mActions.at(0), 1);
265 }
266 int check = 0;
267 DataManager::GetValue("tw_background_thread_running", check);
268 if (check == 0)
269 DataManager::SetValue(TW_ACTION_BUSY, 0);
270 return NULL;
271}
272
273void GUIAction::operation_start(const string operation_name)
274{
275 DataManager::SetValue(TW_ACTION_BUSY, 1);
276 DataManager::SetValue("ui_progress", 0);
277 DataManager::SetValue("tw_operation", operation_name);
278 DataManager::SetValue("tw_operation_status", 0);
279 DataManager::SetValue("tw_operation_state", 0);
280}
281
282void GUIAction::operation_end(const int operation_status, const int simulate)
283{
284 int simulate_fail;
285
286 DataManager::SetValue("ui_progress", 100);
287 if (simulate) {
288 DataManager::GetValue(TW_SIMULATE_FAIL, simulate_fail);
289 if (simulate_fail != 0)
290 DataManager::SetValue("tw_operation_status", 1);
291 else
292 DataManager::SetValue("tw_operation_status", 0);
293 } else {
294 if (operation_status != 0)
295 DataManager::SetValue("tw_operation_status", 1);
296 else
297 DataManager::SetValue("tw_operation_status", 0);
298 }
299 DataManager::SetValue("tw_operation_state", 1);
300 DataManager::SetValue(TW_ACTION_BUSY, 0);
301}
302
303int GUIAction::doAction(Action action, int isThreaded /* = 0 */)
304{
305 static string zip_queue[10];
306 static int zip_queue_index;
307 static pthread_t terminal_command;
308 int simulate;
309
310 std::string arg = gui_parse_text(action.mArg);
311
312 std::string function = gui_parse_text(action.mFunction);
313
314 DataManager::GetValue(TW_SIMULATE_ACTIONS, simulate);
315
316 if (function == "reboot")
317 {
318 //curtainClose(); this sometimes causes a crash
319
320 sync();
321
322 if (arg == "recovery")
323 tw_reboot(rb_recovery);
324 else if (arg == "poweroff")
325 tw_reboot(rb_poweroff);
326 else if (arg == "bootloader")
327 tw_reboot(rb_bootloader);
328 else if (arg == "download")
329 tw_reboot(rb_download);
330 else
331 tw_reboot(rb_system);
332
333 // This should never occur
334 return -1;
335 }
336 if (function == "home")
337 {
338 PageManager::SelectPackage("TWRP");
339 gui_changePage("main");
340 return 0;
341 }
342
343 if (function == "key")
344 {
345 PageManager::NotifyKey(getKeyByName(arg));
346 return 0;
347 }
348
349 if (function == "page") {
350 std::string page_name = gui_parse_text(arg);
351 return gui_changePage(page_name);
352 }
353
354 if (function == "reload") {
355 int check = 0, ret_val = 0;
356 std::string theme_path;
357
358 operation_start("Reload Theme");
359 theme_path = DataManager::GetSettingsStoragePath();
Dees_Troy5bf43922012-09-07 16:07:55 -0400360 if (PartitionManager.Mount_By_Path(theme_path.c_str(), 1) < 0) {
Dees_Troy51a0e822012-09-05 15:24:24 -0400361 LOGE("Unable to mount %s during reload function startup.\n", theme_path.c_str());
362 check = 1;
363 }
364
365 theme_path += "/TWRP/theme/ui.zip";
366 if (check != 0 || PageManager::ReloadPackage("TWRP", theme_path) != 0)
367 {
368 // Loading the custom theme failed - try loading the stock theme
369 LOGI("Attempting to reload stock theme...\n");
370 if (PageManager::ReloadPackage("TWRP", "/res/ui.xml"))
371 {
372 LOGE("Failed to load base packages.\n");
373 ret_val = 1;
374 }
375 }
376 operation_end(ret_val, simulate);
377 }
378
379 if (function == "readBackup")
380 {
381 string Restore_Name;
382 DataManager::GetValue("tw_restore", Restore_Name);
Dees_Troy5bf43922012-09-07 16:07:55 -0400383 PartitionManager.Set_Restore_Files(Restore_Name);
Dees_Troy51a0e822012-09-05 15:24:24 -0400384 return 0;
385 }
386
387 if (function == "set")
388 {
389 if (arg.find('=') != string::npos)
390 {
391 string varName = arg.substr(0, arg.find('='));
392 string value = arg.substr(arg.find('=') + 1, string::npos);
393
394 DataManager::GetValue(value, value);
395 DataManager::SetValue(varName, value);
396 }
397 else
398 DataManager::SetValue(arg, "1");
399 return 0;
400 }
401 if (function == "clear")
402 {
403 DataManager::SetValue(arg, "0");
404 return 0;
405 }
406
407 if (function == "mount")
408 {
409 if (arg == "usb")
410 {
411 DataManager::SetValue(TW_ACTION_BUSY, 1);
412 if (!simulate)
413 usb_storage_enable();
414 else
415 ui_print("Simulating actions...\n");
416 }
417 else if (!simulate)
418 {
419 string cmd;
420 if (arg == "EXTERNAL")
Dees_Troy51127312012-09-08 13:08:49 -0400421 PartitionManager.Mount_By_Path(DataManager::GetStrValue(TW_EXTERNAL_MOUNT), true);
Dees_Troy51a0e822012-09-05 15:24:24 -0400422 else if (arg == "INTERNAL")
Dees_Troy51127312012-09-08 13:08:49 -0400423 PartitionManager.Mount_By_Path(DataManager::GetStrValue(TW_INTERNAL_MOUNT), true);
Dees_Troy51a0e822012-09-05 15:24:24 -0400424 else
Dees_Troy51127312012-09-08 13:08:49 -0400425 PartitionManager.Mount_By_Path(arg, true);
Dees_Troy51a0e822012-09-05 15:24:24 -0400426 } else
427 ui_print("Simulating actions...\n");
428 return 0;
429 }
430
431 if (function == "umount" || function == "unmount")
432 {
433 if (arg == "usb")
434 {
435 if (!simulate)
436 usb_storage_disable();
437 else
438 ui_print("Simulating actions...\n");
439 DataManager::SetValue(TW_ACTION_BUSY, 0);
440 }
441 else if (!simulate)
442 {
443 string cmd;
444 if (arg == "EXTERNAL")
Dees_Troy51127312012-09-08 13:08:49 -0400445 PartitionManager.UnMount_By_Path(DataManager::GetStrValue(TW_EXTERNAL_MOUNT), true);
Dees_Troy51a0e822012-09-05 15:24:24 -0400446 else if (arg == "INTERNAL")
Dees_Troy51127312012-09-08 13:08:49 -0400447 PartitionManager.UnMount_By_Path(DataManager::GetStrValue(TW_INTERNAL_MOUNT), true);
Dees_Troy51a0e822012-09-05 15:24:24 -0400448 else
Dees_Troy51127312012-09-08 13:08:49 -0400449 PartitionManager.UnMount_By_Path(arg, true);
Dees_Troy51a0e822012-09-05 15:24:24 -0400450 } else
451 ui_print("Simulating actions...\n");
452 return 0;
453 }
454
455 if (function == "restoredefaultsettings")
456 {
457 operation_start("Restore Defaults");
458 if (simulate) // Simulated so that people don't accidently wipe out the "simulation is on" setting
459 ui_print("Simulating actions...\n");
460 else {
461 DataManager::ResetDefaults();
Dees_Troy5bf43922012-09-07 16:07:55 -0400462 PartitionManager.Update_System_Details();
463 PartitionManager.Mount_Current_Storage(true);
Dees_Troy51a0e822012-09-05 15:24:24 -0400464 }
465 operation_end(0, simulate);
466 }
467
468 if (function == "copylog")
469 {
470 operation_start("Copy Log");
471 if (!simulate)
472 {
473 char command[255];
474
Dees_Troy5bf43922012-09-07 16:07:55 -0400475 PartitionManager.Mount_Current_Storage(true);
Dees_Troy51a0e822012-09-05 15:24:24 -0400476 sprintf(command, "cp /tmp/recovery.log %s", DataManager::GetCurrentStoragePath().c_str());
477 __system(command);
478 sync();
479 ui_print("Copied recovery log to %s.\n", DataManager::GetCurrentStoragePath().c_str());
480 } else
481 simulate_progress_bar();
482 operation_end(0, simulate);
483 return 0;
484 }
485
486 if (function == "compute" || function == "addsubtract")
487 {
488 if (arg.find("+") != string::npos)
489 {
490 string varName = arg.substr(0, arg.find('+'));
491 string string_to_add = arg.substr(arg.find('+') + 1, string::npos);
492 int amount_to_add = atoi(string_to_add.c_str());
493 int value;
494
495 DataManager::GetValue(varName, value);
496 DataManager::SetValue(varName, value + amount_to_add);
497 return 0;
498 }
499 if (arg.find("-") != string::npos)
500 {
501 string varName = arg.substr(0, arg.find('-'));
502 string string_to_subtract = arg.substr(arg.find('-') + 1, string::npos);
503 int amount_to_subtract = atoi(string_to_subtract.c_str());
504 int value;
505
506 DataManager::GetValue(varName, value);
507 value -= amount_to_subtract;
508 if (value <= 0)
509 value = 0;
510 DataManager::SetValue(varName, value);
511 return 0;
512 }
513 }
514
515 if (function == "setguitimezone")
516 {
517 string SelectedZone;
518 DataManager::GetValue(TW_TIME_ZONE_GUISEL, SelectedZone); // read the selected time zone into SelectedZone
519 string Zone = SelectedZone.substr(0, SelectedZone.find(';')); // parse to get time zone
520 string DSTZone = SelectedZone.substr(SelectedZone.find(';') + 1, string::npos); // parse to get DST component
521
522 int dst;
523 DataManager::GetValue(TW_TIME_ZONE_GUIDST, dst); // check wether user chose to use DST
524
525 string offset;
526 DataManager::GetValue(TW_TIME_ZONE_GUIOFFSET, offset); // pull in offset
527
528 string NewTimeZone = Zone;
529 if (offset != "0")
530 NewTimeZone += ":" + offset;
531
532 if (dst != 0)
533 NewTimeZone += DSTZone;
534
535 DataManager::SetValue(TW_TIME_ZONE_VAR, NewTimeZone);
536 update_tz_environment_variables();
537 return 0;
538 }
539
540 if (function == "togglestorage") {
541 if (arg == "internal") {
542 DataManager::SetValue(TW_USE_EXTERNAL_STORAGE, 0);
543 } else if (arg == "external") {
544 DataManager::SetValue(TW_USE_EXTERNAL_STORAGE, 1);
545 }
Dees_Troy51127312012-09-08 13:08:49 -0400546 if (PartitionManager.Mount_Current_Storage(true)) {
Dees_Troy51a0e822012-09-05 15:24:24 -0400547 if (arg == "internal") {
548 // Save the current zip location to the external variable
549 DataManager::SetValue(TW_ZIP_EXTERNAL_VAR, DataManager::GetStrValue(TW_ZIP_LOCATION_VAR));
550 // Change the current zip location to the internal variable
551 DataManager::SetValue(TW_ZIP_LOCATION_VAR, DataManager::GetStrValue(TW_ZIP_INTERNAL_VAR));
552 } else if (arg == "external") {
553 // Save the current zip location to the internal variable
554 DataManager::SetValue(TW_ZIP_INTERNAL_VAR, DataManager::GetStrValue(TW_ZIP_LOCATION_VAR));
555 // Change the current zip location to the external variable
556 DataManager::SetValue(TW_ZIP_LOCATION_VAR, DataManager::GetStrValue(TW_ZIP_EXTERNAL_VAR));
557 }
558 } else {
559 // We weren't able to toggle for some reason, restore original setting
560 if (arg == "internal") {
561 DataManager::SetValue(TW_USE_EXTERNAL_STORAGE, 1);
562 } else if (arg == "external") {
563 DataManager::SetValue(TW_USE_EXTERNAL_STORAGE, 0);
564 }
565 }
566 return 0;
567 }
568
569 if (function == "overlay")
570 return gui_changeOverlay(arg);
571
572 if (function == "queuezip")
573 {
574 if (zip_queue_index >= 10) {
575 ui_print("Maximum zip queue reached!\n");
576 return 0;
577 }
578 DataManager::GetValue("tw_filename", zip_queue[zip_queue_index]);
579 if (strlen(zip_queue[zip_queue_index].c_str()) > 0) {
580 zip_queue_index++;
581 DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
582 }
583 return 0;
584 }
585
586 if (function == "cancelzip")
587 {
588 if (zip_queue_index <= 0) {
589 ui_print("Minimum zip queue reached!\n");
590 return 0;
591 } else {
592 zip_queue_index--;
593 DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
594 }
595 return 0;
596 }
597
598 if (function == "queueclear")
599 {
600 zip_queue_index = 0;
601 DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
602 return 0;
603 }
604
605 if (function == "sleep")
606 {
607 operation_start("Sleep");
608 usleep(atoi(arg.c_str()));
609 operation_end(0, simulate);
610 return 0;
611 }
612
613 if (isThreaded)
614 {
615 if (function == "fileexists")
616 {
617 struct stat st;
618 string newpath = arg + "/.";
619
620 operation_start("FileExists");
621 if (stat(arg.c_str(), &st) == 0 || stat(newpath.c_str(), &st) == 0)
622 operation_end(0, simulate);
623 else
624 operation_end(1, simulate);
625 }
626
627 if (function == "flash")
628 {
Dees_Troy657c3092012-09-10 20:32:10 -0400629 int i, ret_val = 0, wipe_cache = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400630
631 for (i=0; i<zip_queue_index; i++) {
632 operation_start("Flashing");
633 DataManager::SetValue("tw_filename", zip_queue[i]);
634 DataManager::SetValue(TW_ZIP_INDEX, (i + 1));
635
Dees_Troy657c3092012-09-10 20:32:10 -0400636 ret_val = flash_zip(zip_queue[i], arg, simulate, &wipe_cache);
Dees_Troy51a0e822012-09-05 15:24:24 -0400637 if (ret_val != 0) {
638 ui_print("Error flashing zip '%s'\n", zip_queue[i].c_str());
639 i = 10; // Error flashing zip - exit queue
640 ret_val = 1;
641 }
642 }
643 zip_queue_index = 0;
644 DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
645
Dees_Troy657c3092012-09-10 20:32:10 -0400646 if (wipe_cache)
647 PartitionManager.Wipe_By_Path("/cache");
648
Dees_Troy51a0e822012-09-05 15:24:24 -0400649 if (DataManager::GetIntValue(TW_HAS_INJECTTWRP) == 1 && DataManager::GetIntValue(TW_INJECT_AFTER_ZIP) == 1) {
650 operation_start("ReinjectTWRP");
651 ui_print("Injecting TWRP into boot image...\n");
652 if (simulate) {
653 simulate_progress_bar();
654 } else {
655 __system("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash");
656 ui_print("TWRP injection complete.\n");
657 }
658 }
659 operation_end(ret_val, simulate);
660 return 0;
661 }
662 if (function == "wipe")
663 {
664 operation_start("Format");
665 DataManager::SetValue("tw_partition", arg);
666
667 int ret_val = 0;
668
669 if (simulate) {
670 simulate_progress_bar();
671 } else {
672 if (arg == "data")
Dees_Troy5bf43922012-09-07 16:07:55 -0400673 PartitionManager.Factory_Reset();
Dees_Troy51a0e822012-09-05 15:24:24 -0400674 else if (arg == "battery")
675 wipe_battery_stats();
676 else if (arg == "rotate")
677 wipe_rotate_data();
678 else if (arg == "dalvik")
679 wipe_dalvik_cache();
680 else if (arg == "DATAMEDIA") {
681 LOGE("TODO: Implement formatting of datamedia device!\n");
682 ret_val = 1; //format_data_media();
683 int has_datamedia, dual_storage;
684
685 DataManager::GetValue(TW_HAS_DATA_MEDIA, has_datamedia);
686 DataManager::GetValue(TW_HAS_DUAL_STORAGE, dual_storage);
687 if (has_datamedia && !dual_storage) {
688 system("umount /sdcard");
689 system("mount /data/media /sdcard");
690 }
691 } else if (arg == "INTERNAL") {
692 int has_datamedia, dual_storage;
693
694 DataManager::GetValue(TW_HAS_DATA_MEDIA, has_datamedia);
695 if (has_datamedia) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400696 PartitionManager.Mount_By_Path("/data", 1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400697 __system("rm -rf /data/media");
698 __system("cd /data && mkdir media && chmod 775 media");
699 DataManager::GetValue(TW_HAS_DUAL_STORAGE, dual_storage);
700 if (!dual_storage) {
701 system("umount /sdcard");
702 system("mount /data/media /sdcard");
703 }
704 } else {
705 ret_val = 0;
706 LOGE("Wipe not implemented yet!\n");
707 }
708 } else if (arg == "EXTERNAL") {
709 ret_val = 0;
710 LOGE("Wipe not implemented yet!\n");
711 } else
Dees_Troy5bf43922012-09-07 16:07:55 -0400712 PartitionManager.Wipe_By_Path(arg);
Dees_Troy51a0e822012-09-05 15:24:24 -0400713
714 if (arg == "/sdcard") {
Dees_Troy5bf43922012-09-07 16:07:55 -0400715 PartitionManager.Mount_By_Path("/sdcard", 1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400716 mkdir("/sdcard/TWRP", 0777);
717 DataManager::Flush();
718 }
719 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400720 PartitionManager.Update_System_Details();
Dees_Troy51a0e822012-09-05 15:24:24 -0400721 if (ret_val != 0)
722 ret_val = 1;
723 operation_end(ret_val, simulate);
724 return 0;
725 }
726 if (function == "refreshsizes")
727 {
728 operation_start("Refreshing Sizes");
729 if (simulate) {
730 simulate_progress_bar();
731 } else
Dees_Troy5bf43922012-09-07 16:07:55 -0400732 PartitionManager.Update_System_Details();
Dees_Troy51a0e822012-09-05 15:24:24 -0400733 operation_end(0, simulate);
734 }
735 if (function == "nandroid")
736 {
737 operation_start("Nandroid");
738
739 if (simulate) {
740 DataManager::SetValue("tw_partition", "Simulation");
741 simulate_progress_bar();
742 } else {
743 if (arg == "backup") {
744 string Backup_Name;
745 DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
746 if (Backup_Name == "(Current Date)" || Backup_Name == "0" || Backup_Name == "(" || check_backup_name(1))
Dees_Troy5bf43922012-09-07 16:07:55 -0400747 PartitionManager.Run_Backup(Backup_Name);
Dees_Troy51a0e822012-09-05 15:24:24 -0400748 else
749 return -1;
750 DataManager::SetValue(TW_BACKUP_NAME, "(Current Date)");
751 } else if (arg == "restore") {
752 string Restore_Name;
753 DataManager::GetValue("tw_restore", Restore_Name);
Dees_Troy5bf43922012-09-07 16:07:55 -0400754 PartitionManager.Run_Restore(Restore_Name);
Dees_Troy51a0e822012-09-05 15:24:24 -0400755 } else {
756 operation_end(1, simulate);
757 return -1;
758 }
759 }
760 operation_end(0, simulate);
761 return 0;
762 }
763 if (function == "fixpermissions")
764 {
765 operation_start("Fix Permissions");
766 LOGI("fix permissions started!\n");
767 if (simulate) {
768 simulate_progress_bar();
769 } else
770 fix_perms();
771
772 LOGI("fix permissions DONE!\n");
773 operation_end(0, simulate);
774 return 0;
775 }
776 if (function == "dd")
777 {
778 operation_start("imaging");
779
780 if (simulate) {
781 simulate_progress_bar();
782 } else {
783 char cmd[512];
784 sprintf(cmd, "dd %s", arg.c_str());
785 __system(cmd);
786 }
787 operation_end(0, simulate);
788 return 0;
789 }
790 if (function == "partitionsd")
791 {
792 operation_start("Partition SD Card");
793
794 if (simulate) {
795 simulate_progress_bar();
796 } else {
797 int allow_partition;
798 DataManager::GetValue(TW_ALLOW_PARTITION_SDCARD, allow_partition);
799 if (allow_partition == 0) {
800 ui_print("This device does not have a real SD Card!\nAborting!\n");
801 } else {
802 // Below seen in Koush's recovery
803 char sddevice[256];
804 char mkdir_path[255];
805 Volume *vol = volume_for_path("/sdcard");
806 strcpy(sddevice, vol->device);
807 // Just need block not whole partition
808 sddevice[strlen("/dev/block/mmcblkX")] = NULL;
809
810 char es[64];
811 std::string ext_format, sd_path;
812 int ext, swap;
813 DataManager::GetValue("tw_sdext_size", ext);
814 DataManager::GetValue("tw_swap_size", swap);
815 DataManager::GetValue("tw_sdpart_file_system", ext_format);
816 sprintf(es, "/sbin/sdparted -es %dM -ss %dM -efs ext3 -s > /cache/part.log",ext,swap);
817 LOGI("\nrunning script: %s\n", es);
818 run_script("\nContinue partitioning?",
819 "\nPartitioning sdcard : ",
820 es,
821 "\nunable to execute parted!\n(%s)\n",
822 "\nOops... something went wrong!\nPlease check the recovery log!\n",
823 "\nPartitioning complete!\n\n",
824 "\nPartitioning aborted!\n\n", 0);
825
826 // recreate TWRP folder and rewrite settings - these will be gone after sdcard is partitioned
827#ifdef TW_EXTERNAL_STORAGE_PATH
Dees_Troy5bf43922012-09-07 16:07:55 -0400828 PartitionManager.Mount_By_Path(EXPAND(TW_EXTERNAL_STORAGE_PATH), 1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400829 DataManager::GetValue(TW_EXTERNAL_PATH, sd_path);
830 memset(mkdir_path, 0, sizeof(mkdir_path));
831 sprintf(mkdir_path, "%s/TWRP", sd_path.c_str());
832#else
Dees_Troy5bf43922012-09-07 16:07:55 -0400833 PartitionManager.Mount_By_Path("/sdcard", 1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400834 strcpy(mkdir_path, "/sdcard/TWRP");
835#endif
836 mkdir(mkdir_path, 0777);
837 DataManager::Flush();
838#ifdef TW_EXTERNAL_STORAGE_PATH
839 DataManager::SetValue(TW_ZIP_EXTERNAL_VAR, EXPAND(TW_EXTERNAL_STORAGE_PATH));
840 if (DataManager::GetIntValue(TW_USE_EXTERNAL_STORAGE) == 1)
841 DataManager::SetValue(TW_ZIP_LOCATION_VAR, EXPAND(TW_EXTERNAL_STORAGE_PATH));
842#else
843 DataManager::SetValue(TW_ZIP_EXTERNAL_VAR, "/sdcard");
844 if (DataManager::GetIntValue(TW_USE_EXTERNAL_STORAGE) == 1)
845 DataManager::SetValue(TW_ZIP_LOCATION_VAR, "/sdcard");
846#endif
847 // This is sometimes needed to make a healthy ext4 partition
848 if (ext > 0 && strcmp(ext_format.c_str(), "ext4") == 0) {
849 char command[256];
850 LOGE("Fix this format command!\n");
851 //sprintf(command, "mke2fs -t ext4 -m 0 %s", sde.blk);
852 ui_print("Formatting sd-ext as ext4...\n");
853 LOGI("Formatting sd-ext after partitioning, command: '%s'\n", command);
854 __system(command);
855 ui_print("DONE\n");
856 }
857
Dees_Troy5bf43922012-09-07 16:07:55 -0400858 PartitionManager.Update_System_Details();
Dees_Troy51a0e822012-09-05 15:24:24 -0400859 }
860 }
861 operation_end(0, simulate);
862 return 0;
863 }
864 if (function == "installhtcdumlock")
865 {
866 operation_start("Install HTC Dumlock");
867 if (simulate) {
868 simulate_progress_bar();
869 } else
870 install_htc_dumlock();
871
872 operation_end(0, simulate);
873 return 0;
874 }
875 if (function == "htcdumlockrestoreboot")
876 {
877 operation_start("HTC Dumlock Restore Boot");
878 if (simulate) {
879 simulate_progress_bar();
880 } else
881 htc_dumlock_restore_original_boot();
882
883 operation_end(0, simulate);
884 return 0;
885 }
886 if (function == "htcdumlockreflashrecovery")
887 {
888 operation_start("HTC Dumlock Reflash Recovery");
889 if (simulate) {
890 simulate_progress_bar();
891 } else
892 htc_dumlock_reflash_recovery_to_boot();
893
894 operation_end(0, simulate);
895 return 0;
896 }
897 if (function == "cmd")
898 {
899 int op_status = 0;
900
901 operation_start("Command");
902 LOGI("Running command: '%s'\n", arg.c_str());
903 if (simulate) {
904 simulate_progress_bar();
905 } else {
906 op_status = __system(arg.c_str());
907 if (op_status != 0)
908 op_status = 1;
909 }
910
911 operation_end(op_status, simulate);
912 return 0;
913 }
914 if (function == "terminalcommand")
915 {
916 int op_status = 0;
917 string cmdpath, command;
918
919 DataManager::GetValue("tw_terminal_location", cmdpath);
920 operation_start("CommandOutput");
921 ui_print("%s # %s\n", cmdpath.c_str(), arg.c_str());
922 if (simulate) {
923 simulate_progress_bar();
924 operation_end(op_status, simulate);
925 } else {
926 command = "cd \"";
927 command += cmdpath;
928 command += "\" && ";
929 command += arg;
930 LOGI("Actual command is: '%s'\n", command.c_str());
931 DataManager::SetValue("tw_terminal_command_thread", command);
932 DataManager::SetValue("tw_terminal_state", 1);
933 DataManager::SetValue("tw_background_thread_running", 1);
934 op_status = pthread_create(&terminal_command, NULL, command_thread, NULL);
935 if (op_status != 0) {
936 LOGE("Error starting terminal command thread, %i.\n", op_status);
937 DataManager::SetValue("tw_terminal_state", 0);
938 DataManager::SetValue("tw_background_thread_running", 0);
939 operation_end(1, simulate);
940 }
941 }
942 return 0;
943 }
944 if (function == "killterminal")
945 {
946 int op_status = 0;
947
948 LOGI("Sending kill command...\n");
949 operation_start("KillCommand");
950 DataManager::SetValue("tw_operation_status", 0);
951 DataManager::SetValue("tw_operation_state", 1);
952 DataManager::SetValue("tw_terminal_state", 0);
953 DataManager::SetValue("tw_background_thread_running", 0);
954 DataManager::SetValue(TW_ACTION_BUSY, 0);
955 return 0;
956 }
957 if (function == "reinjecttwrp")
958 {
959 int op_status = 0;
960
961 operation_start("ReinjectTWRP");
962 ui_print("Injecting TWRP into boot image...\n");
963 if (simulate) {
964 simulate_progress_bar();
965 } else {
966 __system("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash");
967 ui_print("TWRP injection complete.\n");
968 }
969
970 operation_end(op_status, simulate);
971 return 0;
972 }
973 if (function == "checkbackupname")
974 {
975 int op_status = 0;
976
977 operation_start("CheckBackupName");
978 if (simulate) {
979 simulate_progress_bar();
980 } else {
981 op_status = check_backup_name(1);
982 if (op_status != 0)
983 op_status = 1;
984 }
985
986 operation_end(op_status, simulate);
987 return 0;
988 }
989 if (function == "decrypt")
990 {
991 int op_status = 0;
992
993 operation_start("Decrypt");
994 if (simulate) {
995 simulate_progress_bar();
996 } else {
997 string Password;
998 DataManager::GetValue("tw_crypto_password", Password);
Dees_Troy5bf43922012-09-07 16:07:55 -0400999 op_status = PartitionManager.Decrypt_Device(Password);
Dees_Troy51a0e822012-09-05 15:24:24 -04001000 if (op_status != 0)
1001 op_status = 1;
1002 else {
1003 int load_theme = 1;
1004
1005 DataManager::SetValue(TW_IS_ENCRYPTED, 0);
1006 DataManager::ReadSettingsFile();
Dees_Troy7d15c252012-09-05 20:47:21 -04001007LOGE("TODO: Implement ORS support\n");
1008 if (0/*check_for_script_file()*/) {
Dees_Troy51a0e822012-09-05 15:24:24 -04001009 ui_print("Processing OpenRecoveryScript file...\n");
Dees_Troy7d15c252012-09-05 20:47:21 -04001010 if (/*run_script_file() ==*/ 0) {
Dees_Troy51a0e822012-09-05 15:24:24 -04001011 usleep(2000000); // Sleep for 2 seconds before rebooting
1012 tw_reboot(rb_system);
1013 load_theme = 0;
1014 }
1015 }
1016
1017 if (load_theme) {
1018 int has_datamedia;
1019
1020 // Check for a custom theme and load it if exists
1021 DataManager::GetValue(TW_HAS_DATA_MEDIA, has_datamedia);
1022 if (has_datamedia != 0) {
1023 struct stat st;
1024 int check = 0;
1025 std::string theme_path;
1026
1027 theme_path = DataManager::GetSettingsStoragePath();
Dees_Troy5bf43922012-09-07 16:07:55 -04001028 if (PartitionManager.Mount_By_Path(theme_path.c_str(), 1) < 0) {
Dees_Troy51a0e822012-09-05 15:24:24 -04001029 LOGE("Unable to mount %s during reload function startup.\n", theme_path.c_str());
1030 check = 1;
1031 }
1032
1033 theme_path += "/TWRP/theme/ui.zip";
1034 if (check == 0 && stat(theme_path.c_str(), &st) == 0) {
1035 if (PageManager::ReloadPackage("TWRP", theme_path) != 0)
1036 {
1037 // Loading the custom theme failed - try loading the stock theme
1038 LOGI("Attempting to reload stock theme...\n");
1039 if (PageManager::ReloadPackage("TWRP", "/res/ui.xml"))
1040 {
1041 LOGE("Failed to load base packages.\n");
1042 }
1043 }
1044 }
1045 }
1046 }
1047 }
1048 }
1049
1050 operation_end(op_status, simulate);
1051 return 0;
1052 }
1053 }
1054 else
1055 {
1056 pthread_t t;
1057 pthread_create(&t, NULL, thread_start, this);
1058 return 0;
1059 }
1060 return -1;
1061}
1062
1063int GUIAction::getKeyByName(std::string key)
1064{
1065 if (key == "home") return KEY_HOME;
1066 else if (key == "menu") return KEY_MENU;
1067 else if (key == "back") return KEY_BACK;
1068 else if (key == "search") return KEY_SEARCH;
1069 else if (key == "voldown") return KEY_VOLUMEDOWN;
1070 else if (key == "volup") return KEY_VOLUMEUP;
1071 else if (key == "power") {
1072 int ret_val;
1073 DataManager::GetValue(TW_POWER_BUTTON, ret_val);
1074 if (!ret_val)
1075 return KEY_POWER;
1076 else
1077 return ret_val;
1078 }
1079
1080 return atol(key.c_str());
1081}
1082
1083void* GUIAction::command_thread(void *cookie)
1084{
1085 string command;
1086 FILE* fp;
1087 char line[512];
1088
1089 DataManager::GetValue("tw_terminal_command_thread", command);
1090 fp = __popen(command.c_str(), "r");
1091 if (fp == NULL) {
1092 LOGE("Error opening command to run.\n");
1093 } else {
1094 int fd = fileno(fp), has_data = 0, check = 0, keep_going = -1, bytes_read = 0;
1095 struct timeval timeout;
1096 fd_set fdset;
1097
1098 while(keep_going)
1099 {
1100 FD_ZERO(&fdset);
1101 FD_SET(fd, &fdset);
1102 timeout.tv_sec = 0;
1103 timeout.tv_usec = 400000;
1104 has_data = select(fd+1, &fdset, NULL, NULL, &timeout);
1105 if (has_data == 0) {
1106 // Timeout reached
1107 DataManager::GetValue("tw_terminal_state", check);
1108 if (check == 0) {
1109 keep_going = 0;
1110 }
1111 } else if (has_data < 0) {
1112 // End of execution
1113 keep_going = 0;
1114 } else {
1115 // Try to read output
1116 bytes_read = read(fd, line, sizeof(line));
1117 if (bytes_read > 0)
1118 ui_print("%s", line); // Display output
1119 else
1120 keep_going = 0; // Done executing
1121 }
1122 }
1123 fclose(fp);
1124 }
1125 DataManager::SetValue("tw_operation_status", 0);
1126 DataManager::SetValue("tw_operation_state", 1);
1127 DataManager::SetValue("tw_terminal_state", 0);
1128 DataManager::SetValue("tw_background_thread_running", 0);
1129 DataManager::SetValue(TW_ACTION_BUSY, 0);
1130 return NULL;
1131}