Clean up ASEC unmounting on physical storage.

When physical devices are unsafely removed, unmountAllAsecsInDir()
fails to find any ASECs, and leaves them all mounted, preventing the
rest of volume from going down.

Now we examine all ASEC containers, and remove when on external
storage, or when the storage media is no longer found.

Bug: 11175082
Change-Id: Iffa38ea43f7e5ad78b598374ebeb60a8727d99fd
diff --git a/DirectVolume.cpp b/DirectVolume.cpp
index 4e0d621..960eef6 100644
--- a/DirectVolume.cpp
+++ b/DirectVolume.cpp
@@ -321,15 +321,16 @@
          * Yikes, our mounted partition is going away!
          */
 
+        bool providesAsec = (getFlags() & VOL_PROVIDES_ASEC) != 0;
+        if (providesAsec && mVm->cleanupAsec(this, true)) {
+            SLOGE("Failed to cleanup ASEC - unmount will probably fail!");
+        }
+
         snprintf(msg, sizeof(msg), "Volume %s %s bad removal (%d:%d)",
                  getLabel(), getFuseMountpoint(), major, minor);
         mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,
                                              msg, false);
 
-	if (mVm->cleanupAsec(this, true)) {
-            SLOGE("Failed to cleanup ASEC - unmount will probably fail!");
-        }
-
         if (Volume::unmountVol(true, false)) {
             SLOGE("Failed to unmount volume on bad removal (%s)", 
                  strerror(errno));
diff --git a/DirectVolume.h b/DirectVolume.h
index 337c72d..7be133f 100644
--- a/DirectVolume.h
+++ b/DirectVolume.h
@@ -42,7 +42,6 @@
     int            mDiskNumParts;
     unsigned int   mPendingPartMap;
     int            mIsDecrypted;
-    int            mFlags;
 
 public:
     DirectVolume(VolumeManager *vm, const fstab_rec* rec, int flags);
@@ -65,7 +64,6 @@
     int updateDeviceInfo(char *new_path, int new_major, int new_minor);
     virtual void revertDeviceInfo(void);
     int isDecrypted() { return mIsDecrypted; }
-    int getFlags() { return mFlags; }
 
 private:
     void handleDiskAdded(const char *devpath, NetlinkEvent *evt);
diff --git a/Volume.cpp b/Volume.cpp
index cbec5d4..21b66b1 100644
--- a/Volume.cpp
+++ b/Volume.cpp
@@ -72,6 +72,7 @@
  * Path to internal storage where *only* root can access ASEC image files
  */
 const char *Volume::SEC_ASECDIR_INT   = "/data/app-asec";
+
 /*
  * Path to where secure containers are mounted
  */
@@ -480,6 +481,7 @@
     }
 
     if (fs_prepare_dir(secure_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) != 0) {
+        SLOGW("fs_prepare_dir failed: %s", strerror(errno));
         return -1;
     }
 
@@ -662,7 +664,7 @@
     char line[1024];
     char value[128];
     if (fgets(line, sizeof(line), fp) != NULL) {
-        ALOGD("blkid reported: %s", line);
+        ALOGD("blkid identified as %s", line);
 
         char* start = strstr(line, "UUID=") + 5;
         if (sscanf(start, "\"%127[^\"]\"", value) == 1) {
@@ -678,6 +680,7 @@
             setUserLabel(NULL);
         }
     } else {
+        ALOGW("blkid failed to identify %s", devicePath);
         res = -1;
     }
 
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 950138c..2a9cd20 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -1549,28 +1549,49 @@
 }
 
 int VolumeManager::cleanupAsec(Volume *v, bool force) {
-    int rc = unmountAllAsecsInDir(Volume::SEC_ASECDIR_EXT);
+    int rc = 0;
 
-    AsecIdCollection toUnmount;
-    // Find the remaining OBB files that are on external storage.
+    char asecFileName[255];
+
+    AsecIdCollection removeAsec;
+    AsecIdCollection removeObb;
+
     for (AsecIdCollection::iterator it = mActiveContainers->begin(); it != mActiveContainers->end();
             ++it) {
         ContainerData* cd = *it;
 
         if (cd->type == ASEC) {
-            // nothing
+            if (findAsec(cd->id, asecFileName, sizeof(asecFileName))) {
+                SLOGE("Couldn't find ASEC %s; cleaning up", cd->id);
+                removeAsec.push_back(cd);
+            } else {
+                SLOGD("Found ASEC at path %s", asecFileName);
+                if (!strncmp(asecFileName, Volume::SEC_ASECDIR_EXT,
+                        strlen(Volume::SEC_ASECDIR_EXT))) {
+                    removeAsec.push_back(cd);
+                }
+            }
         } else if (cd->type == OBB) {
             if (v == getVolumeForFile(cd->id)) {
-                toUnmount.push_back(cd);
+                removeObb.push_back(cd);
             }
         } else {
             SLOGE("Unknown container type %d!", cd->type);
         }
     }
 
-    for (AsecIdCollection::iterator it = toUnmount.begin(); it != toUnmount.end(); ++it) {
+    for (AsecIdCollection::iterator it = removeAsec.begin(); it != removeAsec.end(); ++it) {
         ContainerData *cd = *it;
-        SLOGI("Unmounting ASEC %s (dependant on %s)", cd->id, v->getFuseMountpoint());
+        SLOGI("Unmounting ASEC %s (dependent on %s)", cd->id, v->getLabel());
+        if (unmountAsec(cd->id, force)) {
+            SLOGE("Failed to unmount ASEC %s (%s)", cd->id, strerror(errno));
+            rc = -1;
+        }
+    }
+
+    for (AsecIdCollection::iterator it = removeObb.begin(); it != removeObb.end(); ++it) {
+        ContainerData *cd = *it;
+        SLOGI("Unmounting OBB %s (dependent on %s)", cd->id, v->getLabel());
         if (unmountObb(cd->id, force)) {
             SLOGE("Failed to unmount OBB %s (%s)", cd->id, strerror(errno));
             rc = -1;