Merge "Reset failed decryption count on successful decryptions" into lmp-dev
diff --git a/cryptfs.c b/cryptfs.c
index 01dfec3..ec565c8 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -40,6 +40,7 @@
 #include <ext4.h>
 #include <linux/kdev_t.h>
 #include <fs_mgr.h>
+#include <time.h>
 #include "cryptfs.h"
 #define LOG_TAG "Cryptfs"
 #include "cutils/log.h"
@@ -1426,26 +1427,38 @@
     return encrypt_master_key(passwd, salt, key_buf, master_key, crypt_ftr);
 }
 
-static int wait_and_unmount(char *mountpoint)
+static int wait_and_unmount(char *mountpoint, bool kill)
 {
     int i, err, rc;
 #define WAIT_UNMOUNT_COUNT 20
 
     /*  Now umount the tmpfs filesystem */
     for (i=0; i<WAIT_UNMOUNT_COUNT; i++) {
-        if (umount(mountpoint)) {
-            if (errno == EINVAL) {
-                /* EINVAL is returned if the directory is not a mountpoint,
-                 * i.e. there is no filesystem mounted there.  So just get out.
-                 */
-                break;
-            }
-            err = errno;
-            sleep(1);
-            i++;
-        } else {
-          break;
+        if (umount(mountpoint) == 0) {
+            break;
         }
+
+        if (errno == EINVAL) {
+            /* EINVAL is returned if the directory is not a mountpoint,
+             * i.e. there is no filesystem mounted there.  So just get out.
+             */
+            break;
+        }
+
+        err = errno;
+
+        /* If allowed, be increasingly aggressive before the last two retries */
+        if (kill) {
+            if (i == (WAIT_UNMOUNT_COUNT - 3)) {
+                SLOGW("sending SIGHUP to processes with open files\n");
+                vold_killProcessesWithOpenFiles(mountpoint, 1);
+            } else if (i == (WAIT_UNMOUNT_COUNT - 2)) {
+                SLOGW("sending SIGKILL to processes with open files\n");
+                vold_killProcessesWithOpenFiles(mountpoint, 2);
+            }
+        }
+
+        sleep(1);
     }
 
     if (i < WAIT_UNMOUNT_COUNT) {
@@ -1587,7 +1600,7 @@
         return -1;
     }
 
-    if (! (rc = wait_and_unmount(DATA_MNT_POINT)) ) {
+    if (! (rc = wait_and_unmount(DATA_MNT_POINT, true)) ) {
         /* If ro.crypto.readonly is set to 1, mount the decrypted
          * filesystem readonly.  This is used when /data is mounted by
          * recovery mode.
@@ -2130,21 +2143,26 @@
     }
 
     if (data->cur_pct >= 5) {
-        double elapsed_time = difftime(time(NULL), data->time_started);
-        off64_t remaining_blocks = data->tot_used_blocks
-                                   - data->used_blocks_already_done;
-        int remaining_time = (int)(elapsed_time * remaining_blocks
-                                   / data->used_blocks_already_done);
+        struct timespec time_now;
+        if (clock_gettime(CLOCK_MONOTONIC, &time_now)) {
+            SLOGW("Error getting time");
+        } else {
+            double elapsed_time = difftime(time_now.tv_sec, data->time_started);
+            off64_t remaining_blocks = data->tot_used_blocks
+                                       - data->used_blocks_already_done;
+            int remaining_time = (int)(elapsed_time * remaining_blocks
+                                       / data->used_blocks_already_done);
 
-        // Change time only if not yet set, lower, or a lot higher for
-        // best user experience
-        if (data->remaining_time == -1
-            || remaining_time < data->remaining_time
-            || remaining_time > data->remaining_time + 60) {
-            char buf[8];
-            snprintf(buf, sizeof(buf), "%d", remaining_time);
-            property_set("vold.encrypt_time_remaining", buf);
-            data->remaining_time = remaining_time;
+            // Change time only if not yet set, lower, or a lot higher for
+            // best user experience
+            if (data->remaining_time == -1
+                || remaining_time < data->remaining_time
+                || remaining_time > data->remaining_time + 60) {
+                char buf[8];
+                snprintf(buf, sizeof(buf), "%d", remaining_time);
+                property_set("vold.encrypt_time_remaining", buf);
+                data->remaining_time = remaining_time;
+            }
         }
     }
 }
@@ -2352,7 +2370,13 @@
 
     data.one_pct = data.tot_used_blocks / 100;
     data.cur_pct = 0;
-    data.time_started = time(NULL);
+
+    struct timespec time_started = {0};
+    if (clock_gettime(CLOCK_MONOTONIC, &time_started)) {
+        SLOGW("Error getting time at start");
+        // Note - continue anyway - we'll run with 0
+    }
+    data.time_started = time_started.tv_sec;
     data.remaining_time = -1;
 
     rc = encrypt_groups(&data);
@@ -2877,13 +2901,13 @@
          * above, so just unmount it now.  We must do this _AFTER_ killing the framework,
          * unlike the case for vold managed devices above.
          */
-        if (wait_and_unmount(sd_mnt_point)) {
+        if (wait_and_unmount(sd_mnt_point, false)) {
             goto error_shutting_down;
         }
     }
 
     /* Now unmount the /data partition. */
-    if (wait_and_unmount(DATA_MNT_POINT)) {
+    if (wait_and_unmount(DATA_MNT_POINT, false)) {
         if (allow_reboot) {
             goto error_shutting_down;
         } else {