Merge "Remove workaround for libart greylist." into nyc-dev
diff --git a/adb/adb.cpp b/adb/adb.cpp
index cb54d04..e0c0503 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -1134,6 +1134,13 @@
         /* we don't even need to send a reply */
         return 0;
     }
+
+    if (!strcmp(service, "reconnect")) {
+        if (s->transport != nullptr) {
+            kick_transport(s->transport);
+        }
+        return SendOkay(reply_fd, "done");
+    }
 #endif // ADB_HOST
 
     int ret = handle_forward_request(service, type, serial, reply_fd);
diff --git a/adb/adb.h b/adb/adb.h
index 59644d4..ea20800 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -50,7 +50,7 @@
 std::string adb_version();
 
 // Increment this when we want to force users to start a new adb server.
-#define ADB_SERVER_VERSION 35
+#define ADB_SERVER_VERSION 36
 
 class atransport;
 struct usb_handle;
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index d29c08e..a27dd47 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -158,7 +158,8 @@
         }
     }
 
-    if (memcmp(&service[0],"host",4) != 0 && switch_socket_transport(fd, error)) {
+    if ((memcmp(&service[0],"host",4) != 0 || service == "host:reconnect") &&
+        switch_socket_transport(fd, error)) {
         return -1;
     }
 
@@ -168,9 +169,11 @@
         return -1;
     }
 
-    if (!adb_status(fd, error)) {
-        adb_close(fd);
-        return -1;
+    if (service != "reconnect") {
+        if (!adb_status(fd, error)) {
+            adb_close(fd);
+            return -1;
+        }
     }
 
     D("_adb_connect: return fd %d", fd);
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index b828c41..0c5be84 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -242,6 +242,9 @@
         "  - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
         "    is updated.\n"
         "\n"
+        "internal debugging:\n"
+        "  adb reconnect                  Kick current connection from host side and make it reconnect.\n"
+        "  adb reconnect device           Kick current connection from device side and make it reconnect.\n"
         "environment variables:\n"
         "  ADB_TRACE                    - Print debug information. A comma separated list of the following values\n"
         "                                 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
@@ -1934,6 +1937,14 @@
             }
         }
         return 0;
+    } else if (!strcmp(argv[0], "reconnect")) {
+        if (argc == 1) {
+            return adb_query_command("host:reconnect");
+        } else if (argc == 2 && !strcmp(argv[1], "device")) {
+            std::string err;
+            adb_connect("reconnect", &err);
+            return 0;
+        }
     }
 
     usage();
diff --git a/adb/services.cpp b/adb/services.cpp
index 67e8e41..3b212e9 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -184,6 +184,13 @@
     adb_close(fd);
 }
 
+static void reconnect_service(int fd, void* arg) {
+    WriteFdExactly(fd, "done");
+    adb_close(fd);
+    atransport* t = static_cast<atransport*>(arg);
+    kick_transport(t);
+}
+
 int reverse_service(const char* command) {
     int s[2];
     if (adb_socketpair(s)) {
@@ -345,6 +352,8 @@
         ret = create_service_thread(set_verity_enabled_state_service, (void*)0);
     } else if(!strncmp(name, "enable-verity:", 15)) {
         ret = create_service_thread(set_verity_enabled_state_service, (void*)1);
+    } else if (!strcmp(name, "reconnect")) {
+        ret = create_service_thread(reconnect_service, const_cast<atransport*>(transport));
 #endif
     }
     if (ret >= 0) {
diff --git a/adb/sysdeps_test.cpp b/adb/sysdeps_test.cpp
index 78efea8..f0c334e 100644
--- a/adb/sysdeps_test.cpp
+++ b/adb/sysdeps_test.cpp
@@ -215,3 +215,32 @@
     // Linux returns POLLIN | POLLHUP, Windows returns just POLLHUP.
     EXPECT_EQ(POLLHUP, pfd.revents & POLLHUP);
 }
+
+TEST_F(sysdeps_poll, fd_count) {
+    // https://code.google.com/p/android/issues/detail?id=12141
+    static constexpr int num_sockets = 512;
+    std::vector<int> sockets;
+    std::vector<adb_pollfd> pfds;
+    sockets.resize(num_sockets * 2);
+    for (int32_t i = 0; i < num_sockets; ++i) {
+        ASSERT_EQ(0, adb_socketpair(&sockets[i * 2])) << strerror(errno);
+        ASSERT_TRUE(WriteFdExactly(sockets[i * 2], &i, sizeof(i)));
+        adb_pollfd pfd;
+        pfd.events = POLLIN;
+        pfd.fd = sockets[i * 2 + 1];
+        pfds.push_back(pfd);
+    }
+
+    ASSERT_EQ(num_sockets, adb_poll(pfds.data(), pfds.size(), 0));
+    for (int i = 0; i < num_sockets; ++i) {
+        ASSERT_NE(0, pfds[i].revents & POLLIN);
+
+        int32_t buf[2] = { -1, -1 };
+        ASSERT_EQ(adb_read(pfds[i].fd, buf, sizeof(buf)), static_cast<ssize_t>(sizeof(int32_t)));
+        ASSERT_EQ(i, buf[0]);
+    }
+
+    for (int fd : sockets) {
+        adb_close(fd);
+    }
+}
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index a2f34fb..bc09fdc 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -191,7 +191,7 @@
 #define  fh_socket  u.socket
 
 #define  WIN32_FH_BASE    2048
-#define  WIN32_MAX_FHS    128
+#define  WIN32_MAX_FHS    2048
 
 static adb_mutex_t   _win32_lock;
 static  FHRec        _win32_fhs[ WIN32_MAX_FHS ];
diff --git a/adb/transport.cpp b/adb/transport.cpp
index f86a222..413b362 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -305,7 +305,11 @@
 
 void kick_transport(atransport* t) {
     adb_mutex_lock(&transport_lock);
-    kick_transport_locked(t);
+    // As kick_transport() can be called from threads without guarantee that t is valid,
+    // check if the transport is in transport_list first.
+    if (std::find(transport_list.begin(), transport_list.end(), t) != transport_list.end()) {
+        kick_transport_locked(t);
+    }
     adb_mutex_unlock(&transport_lock);
 }
 
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 12f507a..7f0e5bb 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -25,9 +25,11 @@
 #include <sys/poll.h>
 #include <sys/prctl.h>
 #include <sys/ptrace.h>
+#include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <sys/un.h>
 #include <time.h>
 
 #include <set>
@@ -36,6 +38,7 @@
 
 #include <log/logger.h>
 
+#include <android-base/unique_fd.h>
 #include <cutils/debugger.h>
 #include <cutils/properties.h>
 #include <cutils/sockets.h>
@@ -248,6 +251,43 @@
   return 0;
 }
 
+static int activity_manager_connect() {
+  android::base::unique_fd amfd(socket(PF_UNIX, SOCK_STREAM, 0));
+  if (amfd.get() < -1) {
+    ALOGE("debuggerd: Unable to connect to activity manager (socket failed: %s)", strerror(errno));
+    return -1;
+  }
+
+  struct sockaddr_un address;
+  memset(&address, 0, sizeof(address));
+  address.sun_family = AF_UNIX;
+  // The path used here must match the value defined in NativeCrashListener.java.
+  strncpy(address.sun_path, "/data/system/ndebugsocket", sizeof(address.sun_path));
+  if (TEMP_FAILURE_RETRY(connect(amfd.get(), reinterpret_cast<struct sockaddr*>(&address),
+                                 sizeof(address))) == -1) {
+    ALOGE("debuggerd: Unable to connect to activity manager (connect failed: %s)", strerror(errno));
+    return -1;
+  }
+
+  struct timeval tv;
+  memset(&tv, 0, sizeof(tv));
+  tv.tv_sec = 1;  // tight leash
+  if (setsockopt(amfd.get(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) {
+    ALOGE("debuggerd: Unable to connect to activity manager (setsockopt SO_SNDTIMEO failed: %s)",
+          strerror(errno));
+    return -1;
+  }
+
+  tv.tv_sec = 3;  // 3 seconds on handshake read
+  if (setsockopt(amfd.get(), SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
+    ALOGE("debuggerd: Unable to connect to activity manager (setsockopt SO_RCVTIMEO failed: %s)",
+          strerror(errno));
+    return -1;
+  }
+
+  return amfd.release();
+}
+
 static bool should_attach_gdb(const debugger_request_t& request) {
   if (request.action == DEBUGGER_ACTION_CRASH) {
     return property_get_bool("debug.debuggerd.wait_for_gdb", false);
@@ -375,7 +415,7 @@
 
 static bool perform_dump(const debugger_request_t& request, int fd, int tombstone_fd,
                          BacktraceMap* backtrace_map, const std::set<pid_t>& siblings,
-                         int* crash_signal) {
+                         int* crash_signal, int amfd) {
   if (TEMP_FAILURE_RETRY(write(fd, "\0", 1)) != 1) {
     ALOGE("debuggerd: failed to respond to client: %s\n", strerror(errno));
     return false;
@@ -393,7 +433,7 @@
         if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
           ALOGV("debuggerd: stopped -- dumping to tombstone");
           engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings, signal,
-                            request.original_si_code, request.abort_msg_address);
+                            request.original_si_code, request.abort_msg_address, amfd);
         } else if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE) {
           ALOGV("debuggerd: stopped -- dumping to fd");
           dump_backtrace(fd, -1, backtrace_map, request.pid, request.tid, siblings);
@@ -420,7 +460,7 @@
         ALOGV("stopped -- fatal signal\n");
         *crash_signal = signal;
         engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings, signal,
-                          request.original_si_code, request.abort_msg_address);
+                          request.original_si_code, request.abort_msg_address, amfd);
         break;
 
       default:
@@ -506,6 +546,12 @@
   // Generate the backtrace map before dropping privileges.
   std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(request.pid));
 
+  int amfd = -1;
+  if (request.action == DEBUGGER_ACTION_CRASH) {
+    // Connect to the activity manager before dropping privileges.
+    amfd = activity_manager_connect();
+  }
+
   bool succeeded = false;
 
   // Now that we've done everything that requires privileges, we can drop them.
@@ -515,7 +561,8 @@
   }
 
   int crash_signal = SIGKILL;
-  succeeded = perform_dump(request, fd, tombstone_fd, backtrace_map.get(), siblings, &crash_signal);
+  succeeded = perform_dump(request, fd, tombstone_fd, backtrace_map.get(), siblings,
+                           &crash_signal, amfd);
   if (succeeded) {
     if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
       if (!tombstone_path.empty()) {
@@ -559,6 +606,8 @@
     uninit_getevent();
   }
 
+  close(amfd);
+
   exit(!succeeded);
 }
 
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index 7cf2ffc..d802c8c 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -28,9 +28,7 @@
 #include <string.h>
 #include <time.h>
 #include <sys/ptrace.h>
-#include <sys/socket.h>
 #include <sys/stat.h>
-#include <sys/un.h>
 
 #include <memory>
 #include <string>
@@ -59,9 +57,6 @@
 #define TOMBSTONE_DIR   "/data/tombstones"
 #define TOMBSTONE_TEMPLATE (TOMBSTONE_DIR"/tombstone_%02d")
 
-// Must match the path defined in NativeCrashListener.java
-#define NCRASH_SOCKET_PATH "/data/system/ndebugsocket"
-
 static bool signal_has_si_addr(int sig) {
   switch (sig) {
     case SIGBUS:
@@ -711,39 +706,9 @@
   return fd;
 }
 
-static int activity_manager_connect() {
-  int amfd = socket(PF_UNIX, SOCK_STREAM, 0);
-  if (amfd >= 0) {
-    struct sockaddr_un address;
-    int err;
-
-    memset(&address, 0, sizeof(address));
-    address.sun_family = AF_UNIX;
-    strncpy(address.sun_path, NCRASH_SOCKET_PATH, sizeof(address.sun_path));
-    err = TEMP_FAILURE_RETRY(connect(
-        amfd, reinterpret_cast<struct sockaddr*>(&address), sizeof(address)));
-    if (!err) {
-      struct timeval tv;
-      memset(&tv, 0, sizeof(tv));
-      tv.tv_sec = 1;  // tight leash
-      err = setsockopt(amfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
-      if (!err) {
-        tv.tv_sec = 3;  // 3 seconds on handshake read
-        err = setsockopt(amfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
-      }
-    }
-    if (err) {
-      close(amfd);
-      amfd = -1;
-    }
-  }
-
-  return amfd;
-}
-
 void engrave_tombstone(int tombstone_fd, BacktraceMap* map, pid_t pid, pid_t tid,
                        const std::set<pid_t>& siblings, int signal, int original_si_code,
-                       uintptr_t abort_msg_address) {
+                       uintptr_t abort_msg_address, int amfd) {
   log_t log;
   log.current_tid = tid;
   log.crashed_tid = tid;
@@ -756,10 +721,6 @@
   log.tfd = tombstone_fd;
   // Preserve amfd since it can be modified through the calls below without
   // being closed.
-  int amfd = activity_manager_connect();
   log.amfd = amfd;
   dump_crash(&log, map, pid, tid, siblings, signal, original_si_code, abort_msg_address);
-
-  // This file descriptor can be -1, any error is ignored.
-  close(amfd);
 }
diff --git a/debuggerd/tombstone.h b/debuggerd/tombstone.h
index 2b8b8be..7f3eebe 100644
--- a/debuggerd/tombstone.h
+++ b/debuggerd/tombstone.h
@@ -34,6 +34,6 @@
 /* Creates a tombstone file and writes the crash dump to it. */
 void engrave_tombstone(int tombstone_fd, BacktraceMap* map, pid_t pid, pid_t tid,
                        const std::set<pid_t>& siblings, int signal, int original_si_code,
-                       uintptr_t abort_msg_address);
+                       uintptr_t abort_msg_address, int amfd);
 
 #endif // _DEBUGGERD_TOMBSTONE_H
diff --git a/gatekeeperd/gatekeeperd.rc b/gatekeeperd/gatekeeperd.rc
index 3f1b92d..8b126d5 100644
--- a/gatekeeperd/gatekeeperd.rc
+++ b/gatekeeperd/gatekeeperd.rc
@@ -1,3 +1,4 @@
 service gatekeeperd /system/bin/gatekeeperd /data/misc/gatekeeper
     class late_start
     user system
+    writepid /dev/cpuset/system-background/tasks
diff --git a/init/builtins.cpp b/init/builtins.cpp
index c8780bb..b77f9ad 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -537,11 +537,11 @@
     import_late(args, 2);
 
     if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {
-        property_set("vold.decrypt", "trigger_encryption");
+        ActionManager::GetInstance().QueueEventTrigger("encrypt");
     } else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {
         property_set("ro.crypto.state", "encrypted");
         property_set("ro.crypto.type", "block");
-        property_set("vold.decrypt", "trigger_default_encryption");
+        ActionManager::GetInstance().QueueEventTrigger("defaultcrypto");
     } else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
         property_set("ro.crypto.state", "unencrypted");
         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
diff --git a/liblog/log_is_loggable.c b/liblog/log_is_loggable.c
index 79a5670..bd8d5af 100644
--- a/liblog/log_is_loggable.c
+++ b/liblog/log_is_loggable.c
@@ -63,7 +63,6 @@
 
 static void refresh_cache(struct cache *cache, const char *key)
 {
-    uint32_t serial;
     char buf[PROP_VALUE_MAX];
 
     if (!cache->pinfo) {
@@ -71,13 +70,8 @@
         if (!cache->pinfo) {
             return;
         }
-        cache->serial = -1;
     }
-    serial = __system_property_serial(cache->pinfo);
-    if (serial == cache->serial) {
-        return;
-    }
-    cache->serial = serial;
+    cache->serial = __system_property_serial(cache->pinfo);
     __system_property_read(cache->pinfo, 0, buf);
     switch(buf[0]) {
     case 't': case 'T':
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 329898f..6aa4fb7 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -1277,7 +1277,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_FALSE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_FALSE(__android_log_is_loggable(
                         levels[i].level, tag, levels[j].level));
                 }
@@ -1286,7 +1286,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_TRUE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_TRUE(__android_log_is_loggable(
                         levels[i].level, tag, levels[j].level));
                 }
@@ -1318,7 +1318,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_FALSE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_FALSE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1327,7 +1327,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_TRUE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_TRUE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1347,7 +1347,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_FALSE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_FALSE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1356,7 +1356,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_TRUE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_TRUE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1378,7 +1378,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_FALSE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_FALSE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1387,7 +1387,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_TRUE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_TRUE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1407,7 +1407,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_FALSE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_FALSE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1416,7 +1416,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_TRUE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_TRUE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1452,7 +1452,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_FALSE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_FALSE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1461,7 +1461,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_TRUE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_TRUE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1481,7 +1481,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_FALSE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_FALSE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1490,7 +1490,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_TRUE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_TRUE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index 921a461..dfcca12 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -153,23 +153,29 @@
         return;
     }
 
-    FILE *fp;
+    int tries = 3; // in case run too soon after system start or buffer clear
+    int count;
 
-    ASSERT_TRUE(NULL != (fp = popen(
-      "logcat -v long -v America/Los_Angeles -b all -t 3 2>/dev/null",
-      "r")));
+    do {
+        FILE *fp;
 
-    char buffer[5120];
+        ASSERT_TRUE(NULL != (fp = popen(
+          "logcat -v long -v America/Los_Angeles -b all -t 3 2>/dev/null",
+          "r")));
 
-    int count = 0;
+        char buffer[5120];
 
-    while (fgetLongTime(buffer, sizeof(buffer), fp)) {
-        if (strstr(buffer, " -0700") || strstr(buffer, " -0800")) {
-            ++count;
+        count = 0;
+
+        while (fgetLongTime(buffer, sizeof(buffer), fp)) {
+            if (strstr(buffer, " -0700") || strstr(buffer, " -0800")) {
+                ++count;
+            }
         }
-    }
 
-    pclose(fp);
+        pclose(fp);
+
+    } while ((count < 3) && --tries && (sleep(1), true));
 
     ASSERT_EQ(3, count);
 }
@@ -196,84 +202,47 @@
     ASSERT_EQ(0, count);
 }
 
+void do_tail(int num) {
+    int tries = 3; // in case run too soon after system start or buffer clear
+    int count;
+
+    do {
+        char buffer[5120];
+
+        snprintf(buffer, sizeof(buffer),
+          "logcat -v long -b radio -b events -b system -b main -t %d 2>/dev/null",
+          num);
+
+        FILE *fp;
+        ASSERT_TRUE(NULL != (fp = popen(buffer, "r")));
+
+        count = 0;
+
+        while (fgetLongTime(buffer, sizeof(buffer), fp)) {
+            ++count;
+        }
+
+        pclose(fp);
+
+    } while ((count < num) && --tries && (sleep(1), true));
+
+    ASSERT_EQ(num, count);
+}
+
 TEST(logcat, tail_3) {
-    FILE *fp;
-
-    ASSERT_TRUE(NULL != (fp = popen(
-      "logcat -v long -b radio -b events -b system -b main -t 3 2>/dev/null",
-      "r")));
-
-    char buffer[5120];
-
-    int count = 0;
-
-    while (fgetLongTime(buffer, sizeof(buffer), fp)) {
-        ++count;
-    }
-
-    pclose(fp);
-
-    ASSERT_EQ(3, count);
+    do_tail(3);
 }
 
 TEST(logcat, tail_10) {
-    FILE *fp;
-
-    ASSERT_TRUE(NULL != (fp = popen(
-      "logcat -v long -b radio -b events -b system -b main -t 10 2>/dev/null",
-      "r")));
-
-    char buffer[5120];
-
-    int count = 0;
-
-    while (fgetLongTime(buffer, sizeof(buffer), fp)) {
-        ++count;
-    }
-
-    pclose(fp);
-
-    ASSERT_EQ(10, count);
+    do_tail(10);
 }
 
 TEST(logcat, tail_100) {
-    FILE *fp;
-
-    ASSERT_TRUE(NULL != (fp = popen(
-      "logcat -v long -b radio -b events -b system -b main -t 100 2>/dev/null",
-      "r")));
-
-    char buffer[5120];
-
-    int count = 0;
-
-    while (fgetLongTime(buffer, sizeof(buffer), fp)) {
-        ++count;
-    }
-
-    pclose(fp);
-
-    ASSERT_EQ(100, count);
+    do_tail(100);
 }
 
 TEST(logcat, tail_1000) {
-    FILE *fp;
-
-    ASSERT_TRUE(NULL != (fp = popen(
-      "logcat -v long -b radio -b events -b system -b main -t 1000 2>/dev/null",
-      "r")));
-
-    char buffer[5120];
-
-    int count = 0;
-
-    while (fgetLongTime(buffer, sizeof(buffer), fp)) {
-        ++count;
-    }
-
-    pclose(fp);
-
-    ASSERT_EQ(1000, count);
+    do_tail(1000);
 }
 
 TEST(logcat, tail_time) {
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 3e2f0a5..f505faf 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -427,6 +427,7 @@
 
     mkdir /data/system 0775 system system
     mkdir /data/system/heapdump 0700 system system
+    mkdir /data/system/users 0775 system system
 
     mkdir /data/system_de 0770 system system
     mkdir /data/system_ce 0770 system system
@@ -556,13 +557,6 @@
     class_start main
     class_start late_start
 
-on property:vold.decrypt=trigger_default_encryption
-    start defaultcrypto
-
-on property:vold.decrypt=trigger_encryption
-    start surfaceflinger
-    start encrypt
-
 on property:sys.init_log_level=*
     loglevel ${sys.init_log_level}