partitionmanager: support delayed adopted storage mount

* On some devices, the external mmc driver will only load the card after
  a certain delay. The original code will break and fail to mount any
  adopted storage in this case.

* Add a special fstab flag to allow the partitionmanager to retry after
  a delay.

Change-Id: I219978850ff3ba7ad9dc7ca96fc30634c9574164
diff --git a/partition.cpp b/partition.cpp
index e609f54..7755b46 100755
--- a/partition.cpp
+++ b/partition.cpp
@@ -160,6 +160,7 @@
 	TWFLAG_RESIZE,
 	TWFLAG_KEYDIRECTORY,
 	TWFLAG_WRAPPEDKEY,
+	TWFLAG_ADOPTED_MOUNT_DELAY,
 };
 
 /* Flags without a trailing '=' are considered dual format flags and can be
@@ -204,6 +205,7 @@
 	{ "resize",                 TWFLAG_RESIZE },
 	{ "keydirectory=",          TWFLAG_KEYDIRECTORY },
 	{ "wrappedkey",             TWFLAG_WRAPPEDKEY },
+	{ "adopted_mount_delay=",   TWFLAG_ADOPTED_MOUNT_DELAY },
 	{ 0,                        0 },
 };
 
@@ -268,6 +270,7 @@
 	SlotSelect = false;
 	Key_Directory = "";
 	Is_Super = false;
+	Adopted_Mount_Delay = 0;
 }
 
 TWPartition::~TWPartition(void) {
@@ -1006,6 +1009,9 @@
 		case TWFLAG_ALTDEVICE:
 			Alternate_Block_Device = str;
 			break;
+		case TWFLAG_ADOPTED_MOUNT_DELAY:
+			Adopted_Mount_Delay = atoi(str);
+			break;
 		case TWFLAG_KEYDIRECTORY:
 			Key_Directory = str;
 			break;
diff --git a/partitionmanager.cpp b/partitionmanager.cpp
index 8973782..857ed99 100755
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -2959,6 +2959,16 @@
 	}
 	std::vector<TWPartition*>::iterator adopt;
 	for (adopt = Partitions.begin(); adopt != Partitions.end(); adopt++) {
+		if ((*adopt)->Removable && !(*adopt)->Is_Present && (*adopt)->Adopted_Mount_Delay > 0) {
+			// On some devices, the external mmc driver takes some time
+			// to recognize the card, in which case the "actual block device"
+			// would not have been found yet. We wait the specified delay
+			// and then try again.
+			LOGINFO("Sleeping %d seconds for adopted storage.\n", (*adopt)->Adopted_Mount_Delay);
+			sleep((*adopt)->Adopted_Mount_Delay);
+			(*adopt)->Find_Actual_Block_Device();
+		}
+
 		if ((*adopt)->Removable && (*adopt)->Is_Present) {
 			if ((*adopt)->Decrypt_Adopted() == 0) {
 				ret = true;
diff --git a/partitions.hpp b/partitions.hpp
index 9c2b65f..49ebf60 100755
--- a/partitions.hpp
+++ b/partitions.hpp
@@ -168,6 +168,7 @@
 	string Crypto_Key_Location;                                               // Location of the crypto key used for decrypting encrypted data partitions
 	unsigned int MTP_Storage_ID;
 	string Adopted_GUID;
+	unsigned int Adopted_Mount_Delay;
 
 protected:
 	bool Has_Data_Media;                                                      // Indicates presence of /data/media, may affect wiping and backup methods