apex: only mount required apex files

Since recent kernels seem to limit the number of loopback
devices to 7, we now just mount the required apex files in TWRP.

To mount additional apex files specify TW_ADDITIONAL_APEX_FILES
in your BoardConfig, for example:
TW_ADDITIONAL_APEX_FILES := "apex1 apex2"

To disable Apex in your builds use:
TW_EXLUCDE_APEX := true
Change-Id: Ib55529a4dc17ce2b737b01b86100dca3dc75e6c9

Change-Id: I3b4dfbb164838ffb126016b0d862f67d3f170bf3
diff --git a/twrpApex.cpp b/twrpApex.cpp
index 52dd9e5..45e3e30 100755
--- a/twrpApex.cpp
+++ b/twrpApex.cpp
@@ -1,21 +1,44 @@
 #include "twrpApex.hpp"
 #include "twrp-functions.hpp"
+#include "common.h"
 
 namespace fs = std::filesystem;
 
 bool twrpApex::loadApexImages() {
 	std::vector<std::string> apexFiles;
+	std::vector<std::string> checkApexFlatFiles;
+#ifdef TW_ADDITIONAL_APEX_FILES
+	char* additionalFiles = strdup(EXPAND(TW_ADDITIONAL_APEX_FILES));
+	char* additionalApexFiles = std::strtok(additionalFiles, " ");
+#endif
+
+	apexFiles.push_back(APEX_DIR "/com.android.apex.cts.shim.apex");
+	apexFiles.push_back(APEX_DIR "/com.google.android.tzdata2.apex");
+	apexFiles.push_back(APEX_DIR "/com.android.tzdata.apex");
+	apexFiles.push_back(APEX_DIR "/com.android.art.release.apex");
+	apexFiles.push_back(APEX_DIR "/com.google.android.media.swcodec.apex");
+	apexFiles.push_back(APEX_DIR "/com.android.media.swcodec.apex");
+
+#ifdef TW_ADDITIONAL_APEX_FILES
+	while(additionalApexFiles) {
+		std::stringstream apexFile;
+		apexFile << APEX_DIR << "/" << additionalApexFiles;
+		apexFiles.push_back(apexFile.str());
+		additionalApexFiles = std::strtok(nullptr, " ");
+	}
+#endif
+
 	if (access(APEX_DIR, F_OK) != 0) {
 		LOGERR("Unable to open %s\n", APEX_DIR);
 		return false;
 	}
 	for (const auto& entry : fs::directory_iterator(APEX_DIR)) {
 	   if (entry.is_regular_file()) {
-		   apexFiles.push_back(entry.path().string());
+		   checkApexFlatFiles.push_back(entry.path().string());
 	   }
 	}
 
-	if (apexFiles.size() == 0) {
+	if (checkApexFlatFiles.size() == 0) {
 		// flattened apex directory
 		LOGINFO("Bind mounting flattened apex directory\n");
 		if (mount(APEX_DIR, APEX_BASE, "", MS_BIND, NULL) < 0) {
@@ -36,9 +59,8 @@
 	ZipArchiveHandle handle;
 	int32_t ret = OpenArchive(file.c_str(), &handle);
 	if (ret != 0) {
-		LOGERR("unable to open zip archive %s\n", file.c_str());
-		CloseArchive(handle);
-		return nullptr;
+		LOGINFO("unable to open zip archive %s. Reason: %s\n", file.c_str(), strerror(errno));
+		return std::string();
 	}
 
 	ZipEntry entry;
@@ -47,7 +69,7 @@
 	if (ret != 0) {
 		LOGERR("unable to find %s in zip\n", APEX_PAYLOAD);
 		CloseArchive(handle);
-		return nullptr;
+		return std::string();
 	}
 
 	std::string baseFile = basename(file.c_str());
@@ -59,7 +81,7 @@
 		LOGERR("unable to extract %s\n", path.c_str());
 		close(fd);
 		CloseArchive(handle);
-		return nullptr;
+		return std::string();
 	}
 
 	CloseArchive(handle);
@@ -87,6 +109,10 @@
 			}
 		}
 		std::string fileToMount = unzipImage(apexFile);
+		if (fileToMount.empty()) {
+			LOGINFO("Skipping non-existent apex file: %s\n", apexFile.c_str());
+			continue;
+		}
 		bool load_result = loadApexImage(fileToMount, device_no);
 		if (!load_result) {
 			return false;
@@ -114,7 +140,8 @@
 	}
 
 	if (ioctl(loop_fd, LOOP_SET_FD, fd) < 0) {
-		LOGERR("failed to mount %s to loop device %s\n", fileToMount.c_str(), loop_device.c_str());
+		LOGERR("failed to mount %s to loop device %s. Reason: %s\n", fileToMount.c_str(), loop_device.c_str(), 
+			strerror(errno));
 		close(fd);
 		close(loop_fd);
 		return false;