Add haptic feedback

Change-Id: I15d723f73c0b0bb4a40645d1c3f4c1c616f36998
diff --git a/data.cpp b/data.cpp
index c611e78..0d490a9 100644
--- a/data.cpp
+++ b/data.cpp
@@ -55,7 +55,7 @@
 	#include "twcommon.h"
 	#include "data.h"
 	#include "gui/pages.h"
-
+	#include "minuitwrp/minui.h"
 	void gui_notifyVarChange(const char *name, const char* value);
 }
 
@@ -583,6 +583,7 @@
 
 	mConstValues.insert(make_pair(TW_VERSION_VAR, TW_VERSION_STR));
 	mValues.insert(make_pair("tw_storage_path", make_pair("/", 1)));
+	mValues.insert(make_pair("tw_vibrate", make_pair("80", 1)));
 
 #ifdef TW_FORCE_CPUINFO_FOR_DEVICE_ID
 	printf("TW_FORCE_CPUINFO_FOR_DEVICE_ID := true\n");
@@ -1240,3 +1241,11 @@
 {
 	return DataManager::ReadSettingsFile();
 }
+void DataManager::Vibrate(const string varName)
+{
+	int vib_value = 0;
+	GetValue(varName, vib_value);
+	if (vib_value) {
+		vibrate(vib_value);
+	}
+}
diff --git a/data.hpp b/data.hpp
index 723cf9b..df57f23 100644
--- a/data.hpp
+++ b/data.hpp
@@ -55,6 +55,7 @@
 
 	static void DumpValues();
 	static void update_tz_environment_variables();
+	static void Vibrate(const string varName);
 	static void SetBackupFolder();
 	static void SetDefaultValues();
 	static void Output_Version(void); // Outputs the version to a file in the TWRP folder
diff --git a/gui/action.cpp b/gui/action.cpp
index 5536c82..8539386 100644
--- a/gui/action.cpp
+++ b/gui/action.cpp
@@ -314,6 +314,7 @@
 
 void GUIAction::operation_start(const string operation_name)
 {
+	time(&Start);
 	DataManager::SetValue(TW_ACTION_BUSY, 1);
 	DataManager::SetValue("ui_progress", 0);
 	DataManager::SetValue("tw_operation", operation_name);
@@ -323,6 +324,7 @@
 
 void GUIAction::operation_end(const int operation_status, const int simulate)
 {
+	time_t Stop;
 	int simulate_fail;
 	DataManager::SetValue("ui_progress", 100);
 	if (simulate) {
@@ -344,6 +346,9 @@
 #ifndef TW_NO_SCREEN_TIMEOUT
 	blankTimer.resetTimerAndUnblank();
 #endif
+	time(&Stop);
+	if ((int) difftime(Stop, Start) > 10)
+		DataManager::Vibrate("tw_vibrate");
 }
 
 int GUIAction::doAction(Action action, int isThreaded /* = 0 */)
@@ -920,6 +925,7 @@
 					else {
 						operation_end(1, simulate);
 						return -1;
+
 					}
 					DataManager::SetValue(TW_BACKUP_NAME, "(Auto Generate)");
 				} else if (arg == "restore") {
diff --git a/gui/button.cpp b/gui/button.cpp
index be52c27..ca386be 100644
--- a/gui/button.cpp
+++ b/gui/button.cpp
@@ -30,6 +30,7 @@
 #include <time.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include "../data.hpp"
 
 #include <string>
 
@@ -280,6 +281,7 @@
 	} else {
 		if (last_state == 0) {
 			last_state = 1;
+			DataManager::Vibrate("tw_vibrate");
 			if (mButtonLabel != NULL)
 				mButtonLabel->isHighlighted = true;
 			if (mButtonImg != NULL)
diff --git a/gui/devices/1080x1920/res/ui.xml b/gui/devices/1080x1920/res/ui.xml
index beaf373..0f61fac 100644
--- a/gui/devices/1080x1920/res/ui.xml
+++ b/gui/devices/1080x1920/res/ui.xml
@@ -2456,7 +2456,16 @@
 			</object>
 
 			<object type="button">
-				<placement x="%col_center_x%" y="%row4_y%" />
+				<highlight color="%highlight_color%" />
+				<placement x="%col2_x%" y="%row4_y%" />
+				<font resource="font" color="%button_text_color%" />
+				<text>Vibration Duration</text>
+				<image resource="main_button" />
+				<action function="page">Vibrate</action>
+			</object>
+
+			<object type="button">
+				<placement x="%col_x%" y="%row4_y%" />
 				<font resource="font" color="%button_text_color%" />
 				<text>Restore Defaults</text>
 				<image resource="main_button" />
@@ -2663,6 +2672,36 @@
 			<object type="template" name="footer" />
 		</page>
 
+		<page name="Vibrate">
+			<object type="template" name="header" />
+
+			<object type="text" color="%text_color%">
+				<font resource="font" />
+				<placement x="%center_x%" y="%row1_header_y%" placement="5" />
+				<text>Vibration Settings :</text>
+			</object>
+
+			<object type="slidervalue">
+				<placement x="col1_x" y="%row4_text_y%" w="%slidervalue_w%" />
+				<font resource="font" color="%text_color%" />
+				<text>Vibration Value : </text>
+				<data variable="tw_vibrate" min="0" max="300" />
+				<colors line="%slidervalue_line_clr%" slider="%slidervalue_slider_clr%" />
+			</object>
+
+			<object type="action">
+				<touch key="home" />
+				<action function="page">main</action>
+			</object>
+
+			<object type="action">
+				<touch key="back" />
+				<action function="page">settings</action>
+			</object>
+
+			<object type="template" name="footer" />
+		</page>
+
 		<page name="advanced">
 			<object type="template" name="header" />
 
diff --git a/gui/keyboard.cpp b/gui/keyboard.cpp
index 95cdbf1..97a980a 100644
--- a/gui/keyboard.cpp
+++ b/gui/keyboard.cpp
@@ -30,6 +30,7 @@
 #include <time.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include "../data.hpp"
 
 #include <string>
 
@@ -388,6 +389,7 @@
 	switch (state)
 	{
 	case TOUCH_START:
+	DataManager::Vibrate("tw_vibrate");
 		if (GetSelection(x, y) == 0) {
 			startSelection = -1;
 			was_held = 0;
@@ -419,6 +421,7 @@
 			if (highlightRenderCount != 0)
 				mRendered = false;
 			highlightRenderCount = 0;
+			DataManager::Vibrate("tw_vibrate");
 			startSelection = 0;
 		}
 		break;
diff --git a/gui/objects.hpp b/gui/objects.hpp
index e7bb2a0..1053113 100644
--- a/gui/objects.hpp
+++ b/gui/objects.hpp
@@ -25,6 +25,7 @@
 #include <vector>
 #include <string>
 #include <map>
+#include <time.h>
 
 extern "C" {
 #ifdef HAVE_SELINUX
@@ -285,6 +286,7 @@
 	void operation_start(const string operation_name);
 	void operation_end(const int operation_status, const int simulate);
 	static void* command_thread(void *cookie);
+	time_t Start;
 };
 
 class GUIConsole : public RenderObject, public ActionObject
diff --git a/gui/slider.cpp b/gui/slider.cpp
index b46d156..3908b82 100644
--- a/gui/slider.cpp
+++ b/gui/slider.cpp
@@ -15,6 +15,7 @@
 #include <time.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include "../data.hpp"
 
 #include <string>
 
@@ -153,6 +154,7 @@
 		break;
 
 	case TOUCH_RELEASE:
+               DataManager::Vibrate("tw_button_vibrate");
 		if (!dragging)
 			return 0;
 
diff --git a/minuitwrp/events.c b/minuitwrp/events.c
index 73369a2..aecaf8f 100644
--- a/minuitwrp/events.c
+++ b/minuitwrp/events.c
@@ -106,6 +106,8 @@
     int fd;
     int ret;
 
+    if (timeout_ms > 10000) timeout_ms = 1000;
+
     fd = open(VIBRATOR_TIMEOUT_FILE, O_WRONLY);
     if (fd < 0)
         return -1;
diff --git a/minuitwrp/minui.h b/minuitwrp/minui.h
index 03e15bb..5f02d4a 100644
--- a/minuitwrp/minui.h
+++ b/minuitwrp/minui.h
@@ -70,4 +70,6 @@
 void ev_dispatch(void);
 int ev_get_input(int fd, short revents, struct input_event *ev);
 
+int vibrate(int timeout_ms);
+
 #endif