Make Loop::destroyAll() smarter.

Instead of blindly looping across 4096 possible devices, use
readdir() to only look at valid devices.  This speeds up destroyAll()
from 40ms to 0.7ms.

Add tracing information in several places.

Test: external/chromium-trace/systrace.py -b 128768 sched freq am pm ss core_services binder_driver -a system_server,installd,vold
Bug: 65634729, 65737446
Change-Id: If581de47fb55850c0fcd6e25bf33ed246e1b079d
diff --git a/Devmapper.cpp b/Devmapper.cpp
index ed498a3..2cbed86 100644
--- a/Devmapper.cpp
+++ b/Devmapper.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <fcntl.h>
@@ -34,6 +36,7 @@
 
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
+#include <utils/Trace.h>
 
 #include "Devmapper.h"
 
@@ -233,6 +236,7 @@
 }
 
 int Devmapper::destroyAll() {
+    ATRACE_NAME("Devmapper::destroyAll");
     char *buffer = (char *) malloc(1024 * 64);
     if (!buffer) {
         SLOGE("Error allocating memory (%s)", strerror(errno));
diff --git a/Loop.cpp b/Loop.cpp
index fc3909b..1eb9865 100644
--- a/Loop.cpp
+++ b/Loop.cpp
@@ -14,8 +14,11 @@
  * limitations under the License.
  */
 
+#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
+
 #include <stdio.h>
 #include <stdlib.h>
+#include <dirent.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
@@ -35,6 +38,7 @@
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
+#include <utils/Trace.h>
 
 #include "Loop.h"
 #include "VoldUtil.h"
@@ -262,9 +266,22 @@
 }
 
 int Loop::destroyAll() {
-    for (int i = 0; i < LOOP_MAX; i++) {
-        auto path = StringPrintf("/dev/block/loop%d", i);
+    ATRACE_NAME("Loop::destroyAll");
 
+    DIR* dir;
+    struct dirent* de;
+
+    std::string root = "/dev/block/";
+    if (!(dir = opendir(root.c_str()))) {
+        PLOG(ERROR) << "Failed to opendir";
+        return -1;
+    }
+
+    // Poke through all devices looking for loops
+    while ((de = readdir(dir))) {
+        if (strncmp(de->d_name, "loop", 4) != 0) continue;
+
+        auto path = root + de->d_name;
         unique_fd fd(open(path.c_str(), O_RDWR | O_CLOEXEC));
         if (fd.get() == -1) {
             if (errno != ENOENT) {
@@ -290,6 +307,8 @@
             LOG(VERBOSE) << "Found unmanaged loop device at " << path << " named " << id;
         }
     }
+
+    closedir(dir);
     return 0;
 }
 
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index 310610c..049f5ba 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
+
 #include "VoldNativeService.h"
 #include "VolumeManager.h"
 #include "BenchmarkTask.h"
@@ -32,6 +34,7 @@
 #include <android-base/strings.h>
 #include <fs_mgr.h>
 #include <private/android_filesystem_config.h>
+#include <utils/Trace.h>
 
 #ifndef LOG_TAG
 #define LOG_TAG "vold"
@@ -169,10 +172,12 @@
 }
 
 #define ACQUIRE_LOCK \
-    std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock());
+    std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock()); \
+    ATRACE_CALL();
 
 #define ACQUIRE_CRYPT_LOCK \
-    std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getCryptLock());
+    std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getCryptLock()); \
+    ATRACE_CALL();
 
 }  // namespace
 
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 70f71f9..e96b7ac 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
+
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -40,6 +42,7 @@
 #include <android-base/stringprintf.h>
 #include <cutils/fs.h>
 #include <cutils/log.h>
+#include <utils/Trace.h>
 
 #include <selinux/android.h>
 
@@ -94,6 +97,7 @@
 }
 
 int VolumeManager::updateVirtualDisk() {
+    ATRACE_NAME("VolumeManager::updateVirtualDisk");
     if (property_get_bool(kPropVirtualDisk, false)) {
         if (access(kPathVirtualDisk, F_OK) != 0) {
             Loop::createImageFile(kPathVirtualDisk, kSizeVirtualDisk / 512);
@@ -148,6 +152,8 @@
 }
 
 int VolumeManager::start() {
+    ATRACE_NAME("VolumeManager::start");
+
     // Always start from a clean slate by unmounting everything in
     // directories that we own, in case we crashed.
     unmountAll();
@@ -548,6 +554,7 @@
 
 int VolumeManager::unmountAll() {
     std::lock_guard<std::mutex> lock(mLock);
+    ATRACE_NAME("VolumeManager::unmountAll()");
 
     // First, try gracefully unmounting all known devices
     if (mInternalEmulated != nullptr) {
diff --git a/main.cpp b/main.cpp
index 37d02e7..f317f3d 100644
--- a/main.cpp
+++ b/main.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
+
 #include "model/Disk.h"
 #include "VolumeManager.h"
 #include "NetlinkManager.h"
@@ -25,6 +27,7 @@
 #include <android-base/stringprintf.h>
 #include <cutils/klog.h>
 #include <cutils/properties.h>
+#include <utils/Trace.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -51,6 +54,8 @@
     setenv("ANDROID_LOG_TAGS", "*:v", 1);
     android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
 
+    ATRACE_BEGIN("main");
+
     LOG(INFO) << "Vold 3.0 (the awakening) firing up";
 
     LOG(VERBOSE) << "Detected support for:"
@@ -93,10 +98,12 @@
         exit(1);
     }
 
+    ATRACE_BEGIN("VoldNativeService::start");
     if (android::vold::VoldNativeService::start() != android::OK) {
         LOG(ERROR) << "Unable to start VoldNativeService";
         exit(1);
     }
+    ATRACE_END();
 
     bool has_adoptable;
     bool has_quota;
@@ -105,10 +112,12 @@
         PLOG(ERROR) << "Error reading configuration... continuing anyways";
     }
 
+    ATRACE_BEGIN("NetlinkManager::start");
     if (nm->start()) {
         PLOG(ERROR) << "Unable to start NetlinkManager";
         exit(1);
     }
+    ATRACE_END();
 
     // This call should go after listeners are started to avoid
     // a deadlock between vold and init (see b/34278978 for details)
@@ -119,6 +128,9 @@
     // also the cold boot is needed in case we have flash drive
     // connected before Vold launched
     coldboot("/sys/block");
+
+    ATRACE_END();
+
     // Eventually we'll become the monitoring thread
     while(1) {
         pause();
@@ -188,6 +200,7 @@
 }
 
 static void coldboot(const char *path) {
+    ATRACE_NAME("coldboot");
     DIR *d = opendir(path);
     if(d) {
         do_coldboot(d, 0);
@@ -196,6 +209,8 @@
 }
 
 static int process_config(VolumeManager *vm, bool* has_adoptable, bool* has_quota) {
+    ATRACE_NAME("process_config");
+
     fstab = fs_mgr_read_fstab_default();
     if (!fstab) {
         PLOG(ERROR) << "Failed to open default fstab";