Merge "libcutils: move cutils/files.h to cutils/android_get_control_file.h"
diff --git a/init/action.cpp b/init/action.cpp
index ccc18cf..acbb12e 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -105,7 +105,10 @@
 }
 
 void Action::ExecuteOneCommand(std::size_t command) const {
-    ExecuteCommand(commands_[command]);
+    // We need a copy here since some Command execution may result in
+    // changing commands_ vector by importing .rc files through parser
+    Command cmd = commands_[command];
+    ExecuteCommand(cmd);
 }
 
 void Action::ExecuteAllCommands() const {
@@ -118,14 +121,16 @@
     Timer t;
     int result = command.InvokeFunc();
 
-    // TODO: this should probably be changed to "if (failed || took a long time)"...
-    if (android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
+    double duration_ms = t.duration() * 1000;
+    // Any action longer than 50ms will be warned to user as slow operation
+    if (duration_ms > 50.0 ||
+        android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
         std::string trigger_name = BuildTriggersString();
         std::string cmd_str = command.BuildCommandString();
         std::string source = command.BuildSourceString();
 
         LOG(INFO) << "Command '" << cmd_str << "' action=" << trigger_name << source
-                  << " returned " << result << " took " << t.duration() << "s";
+                  << " returned " << result << " took " << duration_ms << "ms.";
     }
 }
 
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 08b591b..8042bfd 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -589,9 +589,9 @@
 
     for (na = args.size() - 1; na > 1; --na) {
         if (args[na] == "--early") {
-             path_arg_end = na;
-             queue_event = false;
-             mount_mode = MOUNT_MODE_EARLY;
+            path_arg_end = na;
+            queue_event = false;
+            mount_mode = MOUNT_MODE_EARLY;
         } else if (args[na] == "--late") {
             path_arg_end = na;
             import_rc = false;
diff --git a/libappfuse/FuseBridgeLoop.cc b/libappfuse/FuseBridgeLoop.cc
index acb963c..2386bf8 100644
--- a/libappfuse/FuseBridgeLoop.cc
+++ b/libappfuse/FuseBridgeLoop.cc
@@ -20,12 +20,14 @@
 #include <android-base/unique_fd.h>
 
 namespace android {
+namespace fuse {
 
-bool FuseBridgeLoop::Start(
-    int raw_dev_fd, int raw_proxy_fd, FuseBridgeLoop::Callback* callback) {
+bool StartFuseBridgeLoop(
+    int raw_dev_fd, int raw_proxy_fd, FuseBridgeLoopCallback* callback) {
   base::unique_fd dev_fd(raw_dev_fd);
   base::unique_fd proxy_fd(raw_proxy_fd);
-  fuse::FuseBuffer buffer;
+  FuseBuffer buffer;
+  size_t open_count = 0;
 
   LOG(DEBUG) << "Start fuse loop.";
   while (true) {
@@ -71,18 +73,29 @@
       return false;
     }
 
-    if (opcode == FUSE_INIT) {
-      callback->OnMount();
+    switch (opcode) {
+      case FUSE_INIT:
+        callback->OnMount();
+        break;
+      case FUSE_OPEN:
+        if (buffer.response.header.error == fuse::kFuseSuccess) {
+          open_count++;
+        }
+        break;
+      case FUSE_RELEASE:
+        if (open_count != 0) {
+            open_count--;
+        } else {
+            LOG(WARNING) << "Unexpected FUSE_RELEASE before opening a file.";
+            break;
+        }
+        if (open_count == 0) {
+          return true;
+        }
+        break;
     }
   }
 }
 
-namespace fuse {
-
-bool StartFuseBridgeLoop(
-    int raw_dev_fd, int raw_proxy_fd, FuseBridgeLoopCallback* callback) {
-  return FuseBridgeLoop().Start(raw_dev_fd, raw_proxy_fd, callback);
-}
-
 }  // namespace fuse
 }  // namespace android
diff --git a/libappfuse/include/libappfuse/FuseBridgeLoop.h b/libappfuse/include/libappfuse/FuseBridgeLoop.h
index 38043bc..1f71cf2 100644
--- a/libappfuse/include/libappfuse/FuseBridgeLoop.h
+++ b/libappfuse/include/libappfuse/FuseBridgeLoop.h
@@ -20,23 +20,14 @@
 #include "libappfuse/FuseBuffer.h"
 
 namespace android {
-
-// TODO: Remove the class after switching to StartFuseBridgeLoop in the
-// framework code.
-class FuseBridgeLoop final {
- public:
-  class Callback {
-   public:
-    virtual void OnMount() = 0;
-    virtual ~Callback() = default;
-  };
-
-  bool Start(int dev_fd, int proxy_fd, Callback* callback);
-};
-
 namespace fuse {
 
-class FuseBridgeLoopCallback : public FuseBridgeLoop::Callback {};
+class FuseBridgeLoopCallback {
+ public:
+  virtual void OnMount() = 0;
+  virtual ~FuseBridgeLoopCallback() = default;
+};
+
 bool StartFuseBridgeLoop(
     int dev_fd, int proxy_fd, FuseBridgeLoopCallback* callback);
 
diff --git a/libappfuse/tests/FuseBridgeLoopTest.cc b/libappfuse/tests/FuseBridgeLoopTest.cc
index bd503eb..e74d9e7 100644
--- a/libappfuse/tests/FuseBridgeLoopTest.cc
+++ b/libappfuse/tests/FuseBridgeLoopTest.cc
@@ -200,11 +200,16 @@
 TEST_F(FuseBridgeLoopTest, Proxy) {
   CheckProxy(FUSE_LOOKUP);
   CheckProxy(FUSE_GETATTR);
-  CheckProxy(FUSE_OPEN);
   CheckProxy(FUSE_READ);
   CheckProxy(FUSE_WRITE);
-  CheckProxy(FUSE_RELEASE);
   CheckProxy(FUSE_FSYNC);
+
+  // Invoke FUSE_OPEN and FUSE_RELEASE at last as the loop will exit when all files are closed.
+  CheckProxy(FUSE_OPEN);
+  CheckProxy(FUSE_RELEASE);
+
+  // Ensure the loop exits.
+  Close();
 }
 
 }  // namespace fuse