Merge "Revert :Force sync files written by minzip" into android-6.0
diff --git a/Android.mk b/Android.mk
index 1fc8c53..9dc31a5 100644
--- a/Android.mk
+++ b/Android.mk
@@ -344,7 +344,8 @@
     dosfsck \
     dosfslabel \
     fsck_msdos_symlink \
-    mkdosfs
+    mkdosfs \
+    permissive.sh
 
 ifneq ($(TARGET_ARCH), arm64)
     ifneq ($(TARGET_ARCH), x86_64)
diff --git a/etc/init.rc b/etc/init.rc
index 3cf5d4c..f0af6be 100644
--- a/etc/init.rc
+++ b/etc/init.rc
@@ -2,6 +2,13 @@
 import /init.recovery.${ro.hardware}.rc
 
 on early-init
+    # Apply strict SELinux checking of PROT_EXEC on mmap/mprotect calls.
+    write /sys/fs/selinux/checkreqprot 0
+
+    # Set the security context for the init process.
+    # This should occur before anything else (e.g. ueventd) is started.
+    setcon u:r:init:s0
+
     start ueventd
     start healthd
 
diff --git a/gui/Android.mk b/gui/Android.mk
index 1d0d134..6633e9a 100644
--- a/gui/Android.mk
+++ b/gui/Android.mk
@@ -27,7 +27,8 @@
     partitionlist.cpp \
     mousecursor.cpp \
     scrolllist.cpp \
-    patternpassword.cpp
+    patternpassword.cpp \
+    textbox.cpp
 
 ifneq ($(TWRP_CUSTOM_KEYBOARD),)
     LOCAL_SRC_FILES += $(TWRP_CUSTOM_KEYBOARD)
diff --git a/gui/console.cpp b/gui/console.cpp
index 47caadb..6b38d61 100644
--- a/gui/console.cpp
+++ b/gui/console.cpp
@@ -158,39 +158,9 @@
 	return 0;
 }
 
-bool GUIConsole::AddLines()
-{
-	if (mLastCount == gConsole.size())
-		return false; // nothing to add
-
-	size_t prevCount = mLastCount;
-	mLastCount = gConsole.size();
-
-	// Due to word wrap, figure out what / how the newly added text needs to be added to the render vector that is word wrapped
-	// Note, that multiple consoles on different GUI pages may be different widths or use different fonts, so the word wrapping
-	// may different in different console windows
-	for (size_t i = prevCount; i < mLastCount; i++) {
-		string curr_line = gConsole[i];
-		string curr_color = gConsoleColor[i];
-		for(;;) {
-			size_t line_char_width = gr_maxExW(curr_line.c_str(), mFont->GetResource(), mRenderW);
-			if (line_char_width < curr_line.size()) {
-				rConsole.push_back(curr_line.substr(0, line_char_width));
-				rConsoleColor.push_back(curr_color);
-				curr_line = curr_line.substr(line_char_width);
-			} else {
-				rConsole.push_back(curr_line);
-				rConsoleColor.push_back(curr_color);
-				break;
-			}
-		}
-	}
-	return true;
-}
-
 int GUIConsole::RenderConsole(void)
 {
-	AddLines();
+	AddLines(&gConsole, &gConsoleColor, &mLastCount, &rConsole, &rConsoleColor);
 	GUIScrollList::Render();
 
 	// if last line is fully visible, keep tracking the last line when new lines are added
@@ -241,7 +211,7 @@
 		scrollToEnd = true;
 	}
 
-	if (AddLines()) {
+	if (AddLines(&gConsole, &gConsoleColor, &mLastCount, &rConsole, &rConsoleColor)) {
 		// someone added new text
 		// at least the scrollbar must be updated, even if the new lines are currently not visible
 		mUpdate = 1;
diff --git a/gui/devices/landscape/res/landscape.xml b/gui/devices/landscape/res/landscape.xml
index 57406d9..ec6f88e 100644
--- a/gui/devices/landscape/res/landscape.xml
+++ b/gui/devices/landscape/res/landscape.xml
@@ -2488,7 +2488,7 @@
 			</object>
 
 			<object type="button">
-				<placement x="%slidervalue_x%" y="%row3_text_y%" />
+				<placement x="%slidervalue_x%" y="%row3_text_y%" textplacement="6" />
 				<condition var1="tw_screen_timeout_secs" op="=" var2="0" />
 				<condition var1="tw_no_screen_timeout" op="!=" var2="1" />
 				<text>Enable screen timeout.</text>
@@ -2497,7 +2497,7 @@
 			</object>
 
 			<object type="button">
-				<placement x="%slidervalue_x%" y="%row3_text_y%" />
+				<placement x="%slidervalue_x%" y="%row3_text_y%" textplacement="6" />
 				<condition var1="tw_screen_timeout_secs" op="!=" var2="0" />
 				<condition var1="tw_no_screen_timeout" op="!=" var2="1" />
 				<text>Enable screen timeout.</text>
diff --git a/gui/devices/portrait/res/portrait.xml b/gui/devices/portrait/res/portrait.xml
index db54e55..9c23067 100644
--- a/gui/devices/portrait/res/portrait.xml
+++ b/gui/devices/portrait/res/portrait.xml
@@ -2512,7 +2512,7 @@
 			</object>
 
 			<object type="button">
-				<placement x="%col1_x%" y="%row2_text_y%" />
+				<placement x="%col1_x%" y="%row2_text_y%" textplacement="6" />
 				<font resource="font" color="%text_color%" />
 				<condition var1="tw_screen_timeout_secs" op="=" var2="0" />
 				<condition var1="tw_no_screen_timeout" op="!=" var2="1" />
@@ -2522,7 +2522,7 @@
 			</object>
 
 			<object type="button">
-				<placement x="%col1_x%" y="%row2_text_y%" />
+				<placement x="%col1_x%" y="%row2_text_y%" textplacement="6" />
 				<font resource="font" color="%text_color%" />
 				<condition var1="tw_screen_timeout_secs" op="!=" var2="0" />
 				<condition var1="tw_no_screen_timeout" op="!=" var2="1" />
diff --git a/gui/devices/watch/res/watch.xml b/gui/devices/watch/res/watch.xml
index 00780d0..3adf164 100644
--- a/gui/devices/watch/res/watch.xml
+++ b/gui/devices/watch/res/watch.xml
@@ -2511,7 +2511,7 @@
 			</object>
 
 			<object type="button">
-				<placement x="%col1_x%" y="%row2_text_y%" />
+				<placement x="%col1_x%" y="%row2_text_y%" textplacement="6" />
 				<font resource="font" color="%text_color%" />
 				<condition var1="tw_screen_timeout_secs" op="=" var2="0" />
 				<condition var1="tw_no_screen_timeout" op="!=" var2="1" />
@@ -2521,7 +2521,7 @@
 			</object>
 
 			<object type="button">
-				<placement x="%col1_x%" y="%row2_text_y%" />
+				<placement x="%col1_x%" y="%row2_text_y%" textplacement="6" />
 				<font resource="font" color="%text_color%" />
 				<condition var1="tw_screen_timeout_secs" op="!=" var2="0" />
 				<condition var1="tw_no_screen_timeout" op="!=" var2="1" />
diff --git a/gui/objects.hpp b/gui/objects.hpp
index 73d8717..3d217c4 100644
--- a/gui/objects.hpp
+++ b/gui/objects.hpp
@@ -545,6 +545,7 @@
 	int lastY, last2Y; // last 2 touch locations, used for tracking kinetic scroll speed
 	int fastScroll; // indicates that the inital touch was inside the fastscroll region - makes for easier fast scrolling as the touches don't have to stay within the fast scroll region and you drag your finger
 	int mUpdate; // indicates that a change took place and we need to re-render
+	bool AddLines(std::vector<std::string>* origText, std::vector<std::string>* origColor, size_t* lastCount, std::vector<std::string>* rText, std::vector<std::string>* rColor);
 };
 
 class GUIFileSelector : public GUIScrollList
@@ -680,6 +681,33 @@
 	bool updateList;
 };
 
+class GUITextBox : public GUIScrollList
+{
+public:
+	GUITextBox(xml_node<>* node);
+
+public:
+	// Update - Update any UI component animations (called <= 30 FPS)
+	//  Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
+	virtual int Update(void);
+
+	// NotifyVarChange - Notify of a variable change
+	virtual int NotifyVarChange(const std::string& varName, const std::string& value);
+
+	// ScrollList interface
+	virtual size_t GetItemCount();
+	virtual void RenderItem(size_t itemindex, int yPos, bool selected);
+	virtual void NotifySelect(size_t item_selected);
+protected:
+
+	size_t mLastCount;
+	bool mIsStatic;
+	std::vector<std::string> mLastValue; // Parsed text - parsed for variables but not word wrapped
+	std::vector<std::string> mText;      // Original text - not parsed for variables and not word wrapped
+	std::vector<std::string> rText;      // Rendered text - what we actually see
+
+};
+
 class GUIConsole : public GUIScrollList
 {
 public:
@@ -725,7 +753,6 @@
 	std::vector<std::string> rConsoleColor;
 
 protected:
-	bool AddLines();
 	int RenderSlideout(void);
 	int RenderConsole(void);
 };
diff --git a/gui/pages.cpp b/gui/pages.cpp
index 9bff289..3abd287 100644
--- a/gui/pages.cpp
+++ b/gui/pages.cpp
@@ -444,6 +444,13 @@
 			mRenders.push_back(element);
 			mActions.push_back(element);
 		}
+		else if (type == "textbox")
+		{
+			GUITextBox* element = new GUITextBox(child);
+			mObjects.push_back(element);
+			mRenders.push_back(element);
+			mActions.push_back(element);
+		}
 		else if (type == "template")
 		{
 			if (!templates || !child->first_attribute("name"))
diff --git a/gui/scrolllist.cpp b/gui/scrolllist.cpp
index a033205..d857e06 100644
--- a/gui/scrolllist.cpp
+++ b/gui/scrolllist.cpp
@@ -607,3 +607,43 @@
 		mUpdate = 1;
 	}
 }
+
+bool GUIScrollList::AddLines(std::vector<std::string>* origText, std::vector<std::string>* origColor, size_t* lastCount, std::vector<std::string>* rText, std::vector<std::string>* rColor)
+{
+	if (*lastCount == origText->size())
+		return false; // nothing to add
+
+	size_t prevCount = *lastCount;
+	*lastCount = origText->size();
+
+	// Due to word wrap, figure out what / how the newly added text needs to be added to the render vector that is word wrapped
+	// Note, that multiple consoles on different GUI pages may be different widths or use different fonts, so the word wrapping
+	// may different in different console windows
+	for (size_t i = prevCount; i < *lastCount; i++) {
+		string curr_line = origText->at(i);
+		string curr_color;
+		if (origColor)
+			curr_color = origColor->at(i);
+		for(;;) {
+			size_t line_char_width = gr_ttf_maxExW(curr_line.c_str(), mFont->GetResource(), mRenderW);
+			if (line_char_width < curr_line.size()) {
+				//string left = curr_line.substr(0, line_char_width);
+				size_t wrap_pos = curr_line.find_last_of(" ,./:-_;", line_char_width - 1);
+				if (wrap_pos == string::npos)
+					wrap_pos = line_char_width;
+				else if (wrap_pos < line_char_width - 1)
+					wrap_pos++;
+				rText->push_back(curr_line.substr(0, wrap_pos));
+				if (origColor)
+					rColor->push_back(curr_color);
+				curr_line = curr_line.substr(wrap_pos);
+			} else {
+				rText->push_back(curr_line);
+				if (origColor)
+					rColor->push_back(curr_color);
+				break;
+			}
+		}
+	}
+	return true;
+}
diff --git a/gui/textbox.cpp b/gui/textbox.cpp
new file mode 100644
index 0000000..277297f
--- /dev/null
+++ b/gui/textbox.cpp
@@ -0,0 +1,120 @@
+/*
+        Copyright 2015 bigbiff/Dees_Troy/_that TeamWin
+        This file is part of TWRP/TeamWin Recovery Project.
+
+        TWRP is free software: you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation, either version 3 of the License, or
+        (at your option) any later version.
+
+        TWRP is distributed in the hope that it will be useful,
+        but WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+        GNU General Public License for more details.
+
+        You should have received a copy of the GNU General Public License
+        along with TWRP.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+// textbox.cpp - GUITextBox object
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+GUITextBox::GUITextBox(xml_node<>* node) : GUIScrollList(node)
+{
+	xml_node<>* child;
+
+	mLastCount = 0;
+	mIsStatic = true;
+
+	allowSelection = false;	// textbox doesn't support list item selections
+
+	child = FindNode(node, "color");
+	if (child)
+	{
+		mFontColor = LoadAttrColor(child, "foreground", mFontColor);
+		mBackgroundColor = LoadAttrColor(child, "background", mBackgroundColor);
+		//mScrollColor = LoadAttrColor(child, "scroll", mScrollColor);
+	}
+	child = FindNode(node, "text");
+	while (child) {
+		string txt = child->value();
+		mText.push_back(txt);
+		string lookup = gui_parse_text(txt);
+		if (lookup != txt)
+			mIsStatic = false;
+		mLastValue.push_back(lookup);
+		child = child->next_sibling("text");
+	}
+}
+
+int GUITextBox::Update(void)
+{
+	if (AddLines(&mLastValue, NULL, &mLastCount, &rText, NULL)) {
+		// someone added new text
+		// at least the scrollbar must be updated, even if the new lines are currently not visible
+		mUpdate = 1;
+	}
+
+	GUIScrollList::Update();
+
+	if (mUpdate) {
+		mUpdate = 0;
+		if (Render() == 0)
+			return 2;
+	}
+	return 0;
+}
+
+size_t GUITextBox::GetItemCount()
+{
+	return rText.size();
+}
+
+void GUITextBox::RenderItem(size_t itemindex, int yPos, bool selected __unused)
+{
+	// Set the color for the font
+	gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, mFontColor.alpha);
+
+	// render text
+	const char* text = rText[itemindex].c_str();
+	gr_textEx(mRenderX, yPos, text, mFont->GetResource());
+}
+
+void GUITextBox::NotifySelect(size_t item_selected __unused)
+{
+	// do nothing - textbox ignores selections
+}
+
+int GUITextBox::NotifyVarChange(const std::string& varName, const std::string& value)
+{
+	GUIScrollList::NotifyVarChange(varName, value);
+
+	if(!isConditionTrue() || mIsStatic)
+		return 0;
+
+	// Check to see if the variable exists in mText
+	for (size_t i = 0; i < mText.size(); i++) {
+		string lookup = gui_parse_text(mText.at(i));
+		if (lookup != mText.at(i)) {
+			mLastValue.at(i) = lookup;
+			mUpdate = 1;
+			// There are ways to improve efficiency here, but I am not
+			// sure if we will even use this feature in the stock theme
+			// at all except for language translation. If we start using
+			// variables in textboxes in the stock theme, we can circle
+			// back and make improvements here.
+			mLastCount = 0;
+			rText.clear();
+		}
+	}
+	return 0;
+}