Merge "Remove dead code."
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 8b6b2b5..3cd50ba 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -30,7 +30,9 @@
 #include <sys/time.h>
 #include <time.h>
 
+#include <chrono>
 #include <string>
+#include <thread>
 #include <vector>
 
 #include <android-base/errors.h>
@@ -51,6 +53,7 @@
 #include <sys/capability.h>
 #include <sys/mount.h>
 #include <android-base/properties.h>
+using namespace std::chrono_literals;
 #endif
 
 std::string adb_version() {
@@ -375,7 +378,7 @@
                     adbd_auth_verified(t);
                     t->failed_auth_attempts = 0;
                 } else {
-                    if (t->failed_auth_attempts++ > 256) adb_sleep_ms(1000);
+                    if (t->failed_auth_attempts++ > 256) std::this_thread::sleep_for(1s);
                     send_auth_request(t);
                 }
                 break;
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 919e1c1..0b1ba32 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -29,6 +29,7 @@
 #include <sys/types.h>
 
 #include <string>
+#include <thread>
 #include <vector>
 
 #include <android-base/stringprintf.h>
@@ -38,6 +39,7 @@
 #include "adb_io.h"
 #include "adb_utils.h"
 #include "socket_spec.h"
+#include "sysdeps/chrono.h"
 
 static TransportType __adb_transport = kTransportAny;
 static const char* __adb_serial = NULL;
@@ -188,8 +190,8 @@
         } else {
             fprintf(stdout,"* daemon started successfully *\n");
         }
-        /* give the server some time to start properly and detect devices */
-        adb_sleep_ms(3000);
+        // Give the server some time to start properly and detect devices.
+        std::this_thread::sleep_for(3s);
         // fall through to _adb_connect
     } else {
         // If a server is already running, check its version matches.
@@ -234,7 +236,7 @@
             }
 
             /* XXX can we better detect its death? */
-            adb_sleep_ms(2000);
+            std::this_thread::sleep_for(2s);
             goto start_server;
         }
     }
diff --git a/adb/adb_io.cpp b/adb/adb_io.cpp
index ae16834..ca8729e 100644
--- a/adb/adb_io.cpp
+++ b/adb/adb_io.cpp
@@ -20,6 +20,8 @@
 
 #include <unistd.h>
 
+#include <thread>
+
 #include <android-base/stringprintf.h>
 
 #include "adb.h"
@@ -104,7 +106,7 @@
         if (r == -1) {
             D("writex: fd=%d error %d: %s", fd, errno, strerror(errno));
             if (errno == EAGAIN) {
-                adb_sleep_ms(1); // just yield some cpu time
+                std::this_thread::yield();
                 continue;
             } else if (errno == EPIPE) {
                 D("writex: fd=%d disconnected", fd);
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index e15bcad..a064de2 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -33,6 +33,7 @@
 
 #include <memory>
 #include <string>
+#include <thread>
 #include <vector>
 
 #include <android-base/file.h>
@@ -59,6 +60,7 @@
 #include "file_sync_service.h"
 #include "services.h"
 #include "shell_service.h"
+#include "sysdeps/chrono.h"
 
 static int install_app(TransportType t, const char* serial, int argc, const char** argv);
 static int install_multiple_app(TransportType t, const char* serial, int argc, const char** argv);
@@ -1080,7 +1082,7 @@
 
     // Give adbd some time to kill itself and come back up.
     // We can't use wait-for-device because devices (e.g. adb over network) might not come back.
-    adb_sleep_ms(3000);
+    std::this_thread::sleep_for(3s);
     return true;
 }
 
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index 5e79b5e..f56f7f7 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -22,6 +22,7 @@
 #include <limits>
 #include <queue>
 #include <string>
+#include <thread>
 #include <vector>
 
 #include <unistd.h>
@@ -31,6 +32,7 @@
 #include "fdevent_test.h"
 #include "socket.h"
 #include "sysdeps.h"
+#include "sysdeps/chrono.h"
 
 struct ThreadArg {
     int first_read_fd;
@@ -44,7 +46,7 @@
     fdevent_loop();
 }
 
-const size_t SLEEP_FOR_FDEVENT_IN_MS = 100;
+constexpr auto SLEEP_FOR_FDEVENT = 100ms;
 
 TEST_F(LocalSocketTest, smoke) {
     // Join two socketpairs with a chain of intermediate socketpairs.
@@ -101,7 +103,7 @@
     ASSERT_EQ(0, adb_close(last[1]));
 
     // Wait until the local sockets are closed.
-    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
     TerminateThread(thread);
 }
@@ -154,12 +156,12 @@
     ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseWithPacketThreadFunc),
                                   &arg, &thread));
     // Wait until the fdevent_loop() starts.
-    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     ASSERT_EQ(0, adb_close(cause_close_fd[0]));
-    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
     ASSERT_EQ(0, adb_close(socket_fd[0]));
-    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
     TerminateThread(thread);
 }
@@ -179,9 +181,9 @@
     ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseWithPacketThreadFunc),
                                   &arg, &thread));
     // Wait until the fdevent_loop() starts.
-    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     ASSERT_EQ(0, adb_close(cause_close_fd[0]));
-    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
 
     // Verify if we can read successfully.
@@ -190,7 +192,7 @@
     ASSERT_EQ(true, ReadFdExactly(socket_fd[0], buf.data(), buf.size()));
     ASSERT_EQ(0, adb_close(socket_fd[0]));
 
-    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
     TerminateThread(thread);
 }
@@ -214,11 +216,11 @@
                                   &arg, &thread));
 
     // Wait until the fdevent_loop() starts.
-    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     EXPECT_EQ(2u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
     ASSERT_EQ(0, adb_close(socket_fd[0]));
 
-    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
     TerminateThread(thread);
 }
@@ -229,7 +231,7 @@
     std::string error;
     int fd = network_loopback_client(5038, SOCK_STREAM, &error);
     ASSERT_GE(fd, 0) << error;
-    adb_sleep_ms(200);
+    std::this_thread::sleep_for(200ms);
     ASSERT_EQ(0, adb_close(fd));
 }
 
@@ -265,13 +267,13 @@
                                   &arg, &thread));
 
     // Wait until the fdevent_loop() starts.
-    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
 
     // Wait until the client closes its socket.
     ASSERT_TRUE(adb_thread_join(client_thread));
 
-    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
     TerminateThread(thread);
 }
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index ad9b9fd..0489d09 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -248,11 +248,6 @@
 int unix_isatty(int fd);
 #define  isatty  ___xxx_isatty
 
-static __inline__ void  adb_sleep_ms( int  mseconds )
-{
-    Sleep( mseconds );
-}
-
 int network_loopback_client(int port, int type, std::string* error);
 int network_loopback_server(int port, int type, std::string* error);
 int network_inaddr_any_server(int port, int type, std::string* error);
@@ -766,11 +761,6 @@
 
 #define poll ___xxx_poll
 
-static __inline__ void  adb_sleep_ms( int  mseconds )
-{
-    usleep( mseconds*1000 );
-}
-
 static __inline__ int  adb_mkdir(const std::string& path, int mode)
 {
     return mkdir(path.c_str(), mode);
diff --git a/adb/sysdeps/chrono.h b/adb/sysdeps/chrono.h
new file mode 100644
index 0000000..c73a638
--- /dev/null
+++ b/adb/sysdeps/chrono.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <chrono>
+
+#if defined(_WIN32)
+// We don't have C++14 on Windows yet.
+// Reimplement std::chrono_literals ourselves until we do.
+
+// Silence the following warning (which gets promoted to an error):
+// error: literal operator suffixes not preceded by ‘_’ are reserved for future standardization
+#pragma GCC system_header
+
+constexpr std::chrono::seconds operator"" s(unsigned long long s) {
+    return std::chrono::seconds(s);
+}
+
+constexpr std::chrono::duration<long double> operator"" s(long double s) {
+    return std::chrono::duration<long double>(s);
+}
+
+constexpr std::chrono::milliseconds operator"" ms(unsigned long long ms) {
+    return std::chrono::milliseconds(ms);
+}
+
+constexpr std::chrono::duration<long double, std::milli> operator"" ms(long double ms) {
+    return std::chrono::duration<long double, std::milli>(ms);
+}
+#else
+using namespace std::chrono_literals;
+#endif
diff --git a/adb/sysdeps_test.cpp b/adb/sysdeps_test.cpp
index 9f77942..9007e75 100644
--- a/adb/sysdeps_test.cpp
+++ b/adb/sysdeps_test.cpp
@@ -16,14 +16,17 @@
 
 #include <gtest/gtest.h>
 #include <unistd.h>
+
 #include <atomic>
 #include <condition_variable>
+#include <thread>
 
 #include "adb_io.h"
 #include "sysdeps.h"
+#include "sysdeps/chrono.h"
 
 static void increment_atomic_int(void* c) {
-    sleep(1);
+    std::this_thread::sleep_for(1s);
     reinterpret_cast<std::atomic<int>*>(c)->fetch_add(1);
 }
 
@@ -34,7 +37,7 @@
         ASSERT_TRUE(adb_thread_create(increment_atomic_int, &counter));
     }
 
-    sleep(2);
+    std::this_thread::sleep_for(2s);
     ASSERT_EQ(100, counter.load());
 }
 
@@ -255,15 +258,15 @@
         ASSERT_FALSE(m.try_lock());
         m.lock();
         finished.store(true);
-        adb_sleep_ms(200);
+        std::this_thread::sleep_for(200ms);
         m.unlock();
     }, nullptr);
 
     ASSERT_FALSE(finished.load());
-    adb_sleep_ms(100);
+    std::this_thread::sleep_for(100ms);
     ASSERT_FALSE(finished.load());
     m.unlock();
-    adb_sleep_ms(100);
+    std::this_thread::sleep_for(100ms);
     m.lock();
     ASSERT_TRUE(finished.load());
     m.unlock();
@@ -279,13 +282,13 @@
     adb_thread_create([](void*) {
         ASSERT_FALSE(m.try_lock());
         m.lock();
-        adb_sleep_ms(500);
+        std::this_thread::sleep_for(500ms);
         m.unlock();
     }, nullptr);
 
-    adb_sleep_ms(100);
+    std::this_thread::sleep_for(100ms);
     m.unlock();
-    adb_sleep_ms(100);
+    std::this_thread::sleep_for(100ms);
     ASSERT_FALSE(m.try_lock());
     m.lock();
     m.unlock();
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index ba2b28d..c17f869 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -27,6 +27,7 @@
 
 #include <condition_variable>
 #include <mutex>
+#include <thread>
 #include <vector>
 
 #include <android-base/stringprintf.h>
@@ -39,6 +40,7 @@
 #include "adb.h"
 #include "adb_io.h"
 #include "adb_utils.h"
+#include "sysdeps/chrono.h"
 
 #if ADB_HOST
 
@@ -144,7 +146,7 @@
 
 // Retry the disconnected local port for 60 times, and sleep 1 second between two retries.
 constexpr uint32_t LOCAL_PORT_RETRY_COUNT = 60;
-constexpr uint32_t LOCAL_PORT_RETRY_INTERVAL_IN_MS = 1000;
+constexpr auto LOCAL_PORT_RETRY_INTERVAL = 1s;
 
 struct RetryPort {
     int port;
@@ -173,7 +175,7 @@
         // Sleep here instead of the end of loop, because if we immediately try to reconnect
         // the emulator just kicked, the adbd on the emulator may not have time to remove the
         // just kicked transport.
-        adb_sleep_ms(LOCAL_PORT_RETRY_INTERVAL_IN_MS);
+        std::this_thread::sleep_for(LOCAL_PORT_RETRY_INTERVAL);
 
         // Try connecting retry ports.
         std::vector<RetryPort> next_ports;
@@ -214,7 +216,7 @@
             serverfd = network_inaddr_any_server(port, SOCK_STREAM, &error);
             if(serverfd < 0) {
                 D("server: cannot bind socket yet: %s", error.c_str());
-                adb_sleep_ms(1000);
+                std::this_thread::sleep_for(1s);
                 continue;
             }
             close_on_exec(serverfd);
diff --git a/adb/usb_linux.cpp b/adb/usb_linux.cpp
index 3e5028d..e7f1338 100644
--- a/adb/usb_linux.cpp
+++ b/adb/usb_linux.cpp
@@ -38,6 +38,7 @@
 #include <list>
 #include <mutex>
 #include <string>
+#include <thread>
 
 #include <android-base/file.h>
 #include <android-base/stringprintf.h>
@@ -46,6 +47,7 @@
 #include "adb.h"
 #include "transport.h"
 
+using namespace std::chrono_literals;
 using namespace std::literals;
 
 /* usb scan debugging is waaaay too verbose */
@@ -577,7 +579,7 @@
         // TODO: Use inotify.
         find_usb_device("/dev/bus/usb", register_device);
         kick_disconnected_devices();
-        sleep(1);
+        std::this_thread::sleep_for(1s);
     }
 }
 
diff --git a/adb/usb_linux_client.cpp b/adb/usb_linux_client.cpp
index 6de10f5..1cc7f68 100644
--- a/adb/usb_linux_client.cpp
+++ b/adb/usb_linux_client.cpp
@@ -31,8 +31,10 @@
 
 #include <algorithm>
 #include <atomic>
+#include <chrono>
 #include <condition_variable>
 #include <mutex>
+#include <thread>
 
 #include <android-base/logging.h>
 #include <android-base/properties.h>
@@ -40,6 +42,8 @@
 #include "adb.h"
 #include "transport.h"
 
+using namespace std::chrono_literals;
+
 #define MAX_PACKET_SIZE_FS	64
 #define MAX_PACKET_SIZE_HS	512
 #define MAX_PACKET_SIZE_SS	1024
@@ -268,7 +272,7 @@
                 fd = unix_open("/dev/android", O_RDWR);
             }
             if (fd < 0) {
-                adb_sleep_ms(1000);
+                std::this_thread::sleep_for(1s);
             }
         } while (fd < 0);
         D("[ opening device succeeded ]");
@@ -476,7 +480,7 @@
             if (init_functionfs(usb)) {
                 break;
             }
-            adb_sleep_ms(1000);
+            std::this_thread::sleep_for(1s);
         }
         android::base::SetProperty("sys.usb.ffs.ready", "1");
 
diff --git a/adb/usb_osx.cpp b/adb/usb_osx.cpp
index 2ee2aae..e541f6e 100644
--- a/adb/usb_osx.cpp
+++ b/adb/usb_osx.cpp
@@ -30,8 +30,10 @@
 #include <stdio.h>
 
 #include <atomic>
+#include <chrono>
 #include <memory>
 #include <mutex>
+#include <thread>
 #include <vector>
 
 #include <android-base/logging.h>
@@ -40,6 +42,8 @@
 #include "adb.h"
 #include "transport.h"
 
+using namespace std::chrono_literals;
+
 struct usb_handle
 {
     UInt8 bulkIn;
@@ -411,7 +415,7 @@
         }
         // Signal the parent that we are running
         usb_inited_flag = true;
-        adb_sleep_ms(1000);
+        std::this_thread::sleep_for(1s);
     }
     VLOG(USB) << "RunLoopThread done";
 }
@@ -436,7 +440,7 @@
 
         // Wait for initialization to finish
         while (!usb_inited_flag) {
-            adb_sleep_ms(100);
+            std::this_thread::sleep_for(100ms);
         }
 
         initialized = true;
diff --git a/adb/usb_windows.cpp b/adb/usb_windows.cpp
index 755f07e..640e91e 100644
--- a/adb/usb_windows.cpp
+++ b/adb/usb_windows.cpp
@@ -28,12 +28,14 @@
 #include <stdlib.h>
 
 #include <mutex>
+#include <thread>
 
 #include <adb_api.h>
 
 #include <android-base/errors.h>
 
 #include "adb.h"
+#include "sysdeps/chrono.h"
 #include "transport.h"
 
 /** Structure usb_handle describes our connection to the usb device via
@@ -176,9 +178,9 @@
   adb_thread_setname("Device Poll");
   D("Created device thread");
 
-  while(1) {
+  while (true) {
     find_devices();
-    adb_sleep_ms(1000);
+    std::this_thread::sleep_for(1s);
   }
 }
 
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 612885b..857bcb2 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -257,13 +257,13 @@
 
 static int draw_text(const char *str, int x, int y)
 {
-    int str_len_px = gr_measure(str);
+    int str_len_px = gr_measure(gr_sys_font(), str);
 
     if (x < 0)
         x = (gr_fb_width() - str_len_px) / 2;
     if (y < 0)
         y = (gr_fb_height() - char_height) / 2;
-    gr_text(x, y, str, 0);
+    gr_text(gr_sys_font(), x, y, str, 0);
 
     return y + char_height;
 }
@@ -364,7 +364,7 @@
         }
 
         gr_init();
-        gr_font_size(&char_width, &char_height);
+        gr_font_size(gr_sys_font(), &char_width, &char_height);
 
 #ifndef CHARGER_DISABLE_INIT_BLANK
         gr_fb_blank(true);
diff --git a/include/cutils/files.h b/include/cutils/android_get_control_file.h
similarity index 87%
rename from include/cutils/files.h
rename to include/cutils/android_get_control_file.h
index 0210e30..ed8fbf8 100644
--- a/include/cutils/files.h
+++ b/include/cutils/android_get_control_file.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef __CUTILS_FILES_H
-#define __CUTILS_FILES_H
+#ifndef __CUTILS_ANDROID_GET_CONTROL_FILE_H
+#define __CUTILS_ANDROID_GET_CONTROL_FILE_H
 
 #define ANDROID_FILE_ENV_PREFIX "ANDROID_FILE_"
 
@@ -34,4 +34,4 @@
 }
 #endif
 
-#endif /* __CUTILS_FILES_H */
+#endif /* __CUTILS_ANDROID_GET_CONTROL_FILE_H */
diff --git a/include/cutils/sockets.h b/include/cutils/sockets.h
index 4626e7a..d724dd6 100644
--- a/include/cutils/sockets.h
+++ b/include/cutils/sockets.h
@@ -35,6 +35,7 @@
 #else
 
 #include <sys/socket.h>
+#include <netinet/in.h>
 
 typedef int cutils_socket_t;
 #define INVALID_SOCKET (-1)
diff --git a/include/ziparchive/zip_archive.h b/include/ziparchive/zip_archive.h
index fc845a4..54946fc 100644
--- a/include/ziparchive/zip_archive.h
+++ b/include/ziparchive/zip_archive.h
@@ -195,7 +195,8 @@
  * Uncompress and write an entry to an open file identified by |fd|.
  * |entry->uncompressed_length| bytes will be written to the file at
  * its current offset, and the file will be truncated at the end of
- * the uncompressed data.
+ * the uncompressed data (no truncation if |fd| references a block
+ * device).
  *
  * Returns 0 on success and negative values on failure.
  */
diff --git a/init/action.cpp b/init/action.cpp
index ccc18cf..0ea7e14 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.";
     }
 }
 
@@ -152,6 +157,11 @@
 bool Action::InitTriggers(const std::vector<std::string>& args, std::string* err) {
     const static std::string prop_str("property:");
     for (std::size_t i = 0; i < args.size(); ++i) {
+        if (args[i].empty()) {
+            *err = "empty trigger is not valid";
+            return false;
+        }
+
         if (i % 2) {
             if (args[i] != "&&") {
                 *err = "&& is the only symbol allowed to concatenate actions";
@@ -181,7 +191,11 @@
 bool Action::InitSingleTrigger(const std::string& trigger) {
     std::vector<std::string> name_vector{trigger};
     std::string err;
-    return InitTriggers(name_vector, &err);
+    bool ret = InitTriggers(name_vector, &err);
+    if (!ret) {
+        LOG(ERROR) << "InitSingleTrigger failed due to: " << err;
+    }
+    return ret;
 }
 
 // This function checks that all property triggers are satisfied, that is
@@ -247,9 +261,7 @@
         result += event_trigger_;
         result += ' ';
     }
-    if (!result.empty()) {
-        result.pop_back();
-    }
+    result.pop_back();
     return result;
 }
 
diff --git a/init/builtins.cpp b/init/builtins.cpp
index ebdc8c9..6d58754 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -40,6 +40,7 @@
 
 #include <thread>
 
+#include <selinux/android.h>
 #include <selinux/selinux.h>
 #include <selinux/label.h>
 
@@ -589,9 +590,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;
@@ -904,21 +905,49 @@
 static int do_restorecon(const std::vector<std::string>& args) {
     int ret = 0;
 
-    for (auto it = std::next(args.begin()); it != args.end(); ++it) {
-        if (restorecon(it->c_str()) < 0)
-            ret = -errno;
+    struct flag_type {const char* name; int value;};
+    static const flag_type flags[] = {
+        {"--recursive", SELINUX_ANDROID_RESTORECON_RECURSE},
+        {"--skip-ce", SELINUX_ANDROID_RESTORECON_SKIPCE},
+        {"--cross-filesystems", SELINUX_ANDROID_RESTORECON_CROSS_FILESYSTEMS},
+        {0, 0}
+    };
+
+    int flag = 0;
+
+    bool in_flags = true;
+    for (size_t i = 1; i < args.size(); ++i) {
+        if (android::base::StartsWith(args[i], "--")) {
+            if (!in_flags) {
+                LOG(ERROR) << "restorecon - flags must precede paths";
+                return -1;
+            }
+            bool found = false;
+            for (size_t j = 0; flags[j].name; ++j) {
+                if (args[i] == flags[j].name) {
+                    flag |= flags[j].value;
+                    found = true;
+                    break;
+                }
+            }
+            if (!found) {
+                LOG(ERROR) << "restorecon - bad flag " << args[i];
+                return -1;
+            }
+        } else {
+            in_flags = false;
+            if (restorecon(args[i].c_str(), flag) < 0) {
+                ret = -errno;
+            }
+        }
     }
     return ret;
 }
 
 static int do_restorecon_recursive(const std::vector<std::string>& args) {
-    int ret = 0;
-
-    for (auto it = std::next(args.begin()); it != args.end(); ++it) {
-        if (restorecon_recursive(it->c_str()) < 0)
-            ret = -errno;
-    }
-    return ret;
+    std::vector<std::string> non_const_args(args);
+    non_const_args.insert(std::next(non_const_args.begin()), "--recursive");
+    return do_restorecon(non_const_args);
 }
 
 static int do_loglevel(const std::vector<std::string>& args) {
diff --git a/init/descriptors.cpp b/init/descriptors.cpp
index 10aae88..429a76e 100644
--- a/init/descriptors.cpp
+++ b/init/descriptors.cpp
@@ -23,7 +23,7 @@
 #include <unistd.h>
 
 #include <android-base/stringprintf.h>
-#include <cutils/files.h>
+#include <cutils/android_get_control_file.h>
 #include <cutils/sockets.h>
 
 #include "init.h"
diff --git a/init/devices.cpp b/init/devices.cpp
index 5098fb3..2db24b7 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -111,13 +111,18 @@
         return -ENOMEM;
 
     node->dp.name = strdup(name);
-    if (!node->dp.name)
+    if (!node->dp.name) {
+        free(node);
         return -ENOMEM;
+    }
 
     if (attr) {
         node->dp.attr = strdup(attr);
-        if (!node->dp.attr)
+        if (!node->dp.attr) {
+            free(node->dp.name);
+            free(node);
             return -ENOMEM;
+        }
     }
 
     node->dp.perm = perm;
@@ -185,7 +190,7 @@
 
     if (access(path.c_str(), F_OK) == 0) {
         LOG(VERBOSE) << "restorecon_recursive: " << path;
-        restorecon_recursive(path.c_str());
+        restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE);
     }
 }
 
diff --git a/init/init.cpp b/init/init.cpp
index cbd46bf..4efcc34 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -657,8 +657,8 @@
     restorecon("/dev/socket");
     restorecon("/dev/__properties__");
     restorecon("/property_contexts");
-    restorecon_recursive("/sys");
-    restorecon_recursive("/dev/block");
+    restorecon("/sys", SELINUX_ANDROID_RESTORECON_RECURSE);
+    restorecon("/dev/block", SELINUX_ANDROID_RESTORECON_RECURSE);
     restorecon("/dev/device-mapper");
 
     epoll_fd = epoll_create1(EPOLL_CLOEXEC);
diff --git a/init/property_service.cpp b/init/property_service.cpp
index e7176c6..e198297 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -42,6 +42,7 @@
 #include <netinet/in.h>
 #include <sys/mman.h>
 
+#include <selinux/android.h>
 #include <selinux/selinux.h>
 #include <selinux/label.h>
 
@@ -175,7 +176,7 @@
     if (valuelen >= PROP_VALUE_MAX) return -1;
 
     if (strcmp("selinux.restorecon_recursive", name) == 0 && valuelen > 0) {
-        if (restorecon_recursive(value) != 0) {
+        if (restorecon(value, SELINUX_ANDROID_RESTORECON_RECURSE) != 0) {
             LOG(ERROR) << "Failed to restorecon_recursive " << value;
         }
     }
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index e7794ec..361b925 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -95,7 +95,6 @@
     int prefix = 0;
     int wildcard = 0;
     char *endptr;
-    char *tmp = 0;
 
     if (nargs == 0)
         return;
@@ -129,14 +128,12 @@
     perm = strtol(args[1], &endptr, 8);
     if (!endptr || *endptr != '\0') {
         LOG(ERROR) << "invalid mode '" << args[1] << "'";
-        free(tmp);
         return;
     }
 
     struct passwd* pwd = getpwnam(args[2]);
     if (!pwd) {
         LOG(ERROR) << "invalid uid '" << args[2] << "'";
-        free(tmp);
         return;
     }
     uid = pwd->pw_uid;
@@ -144,11 +141,17 @@
     struct group* grp = getgrnam(args[3]);
     if (!grp) {
         LOG(ERROR) << "invalid gid '" << args[3] << "'";
-        free(tmp);
         return;
     }
     gid = grp->gr_gid;
 
-    add_dev_perms(name, attr, perm, uid, gid, prefix, wildcard);
-    free(tmp);
+    if (add_dev_perms(name, attr, perm, uid, gid, prefix, wildcard) != 0) {
+        PLOG(ERROR) << "add_dev_perms(name=" << name <<
+                       ", attr=" << attr <<
+                       ", perm=" << std::oct << perm << std::dec <<
+                       ", uid=" << uid << ", gid=" << gid <<
+                       ", prefix=" << prefix << ", wildcard=" << wildcard <<
+                       ")";
+        return;
+    }
 }
diff --git a/init/util.cpp b/init/util.cpp
index cb5a094..5205ea0 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -369,14 +369,9 @@
     return rc;
 }
 
-int restorecon(const char* pathname)
+int restorecon(const char* pathname, int flags)
 {
-    return selinux_android_restorecon(pathname, 0);
-}
-
-int restorecon_recursive(const char* pathname)
-{
-    return selinux_android_restorecon(pathname, SELINUX_ANDROID_RESTORECON_RECURSE);
+    return selinux_android_restorecon(pathname, flags);
 }
 
 /*
diff --git a/init/util.h b/init/util.h
index dccec04..d56da39 100644
--- a/init/util.h
+++ b/init/util.h
@@ -68,8 +68,7 @@
 void import_kernel_cmdline(bool in_qemu,
                            const std::function<void(const std::string&, const std::string&, bool)>&);
 int make_dir(const char *path, mode_t mode);
-int restorecon(const char *pathname);
-int restorecon_recursive(const char *pathname);
+int restorecon(const char *pathname, int flags = 0);
 std::string bytes_to_hex(const uint8_t *bytes, size_t bytes_len);
 bool is_dir(const char* pathname);
 bool expand_props(const std::string& src, std::string* dst);
diff --git a/init/util_test.cpp b/init/util_test.cpp
index 6ecbf90..e9f164d 100644
--- a/init/util_test.cpp
+++ b/init/util_test.cpp
@@ -16,6 +16,7 @@
 
 #include "util.h"
 
+#include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdlib.h>
@@ -23,7 +24,9 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <cutils/files.h>
+#include <android-base/stringprintf.h>
+#include <android-base/test_utils.h>
+#include <cutils/android_get_control_file.h>
 #include <gtest/gtest.h>
 #include <selinux/android.h>
 
@@ -55,45 +58,48 @@
 TEST(util, create_file) {
   if (!sehandle) sehandle = selinux_android_file_context_handle();
 
-  static const char path[] = "/data/local/tmp/util.create_file.test";
-  static const char key[] = ANDROID_FILE_ENV_PREFIX "_data_local_tmp_util_create_file_test";
-  EXPECT_EQ(unsetenv(key), 0);
-  unlink(path);
+  TemporaryFile tf;
+  close(tf.fd);
+  EXPECT_GE(unlink(tf.path), 0);
 
-  int fd;
+  std::string key(ANDROID_FILE_ENV_PREFIX);
+  key += tf.path;
+
+  std::for_each(key.begin(), key.end(), [] (char& c) { c = isalnum(c) ? c : '_'; });
+
+  EXPECT_EQ(unsetenv(key.c_str()), 0);
+
   uid_t uid = decode_uid("logd");
   gid_t gid = decode_uid("system");
   mode_t perms = S_IRWXU | S_IWGRP | S_IRGRP | S_IROTH;
   static const char context[] = "u:object_r:misc_logd_file:s0";
-  EXPECT_GE(fd = create_file(path, O_RDWR | O_CREAT, perms, uid, gid, context), 0);
-  if (fd < 0) return;
+  EXPECT_GE(tf.fd = create_file(tf.path, O_RDWR | O_CREAT, perms, uid, gid, context), 0);
+  if (tf.fd < 0) return;
   static const char hello[] = "hello world\n";
   static const ssize_t len = strlen(hello);
-  EXPECT_EQ(write(fd, hello, len), len);
-  char buffer[sizeof(hello)];
+  EXPECT_EQ(write(tf.fd, hello, len), len);
+  char buffer[sizeof(hello) + 1];
   memset(buffer, 0, sizeof(buffer));
-  EXPECT_GE(lseek(fd, 0, SEEK_SET), 0);
-  EXPECT_EQ(read(fd, buffer, sizeof(buffer)), len);
-  EXPECT_EQ(strcmp(hello, buffer), 0);
-  char val[32];
-  snprintf(val, sizeof(val), "%d", fd);
-  EXPECT_EQ(android_get_control_file(path), -1);
-  setenv(key, val, true);
-  EXPECT_EQ(android_get_control_file(path), fd);
-  close(fd);
-  EXPECT_EQ(android_get_control_file(path), -1);
-  EXPECT_EQ(unsetenv(key), 0);
+  EXPECT_GE(lseek(tf.fd, 0, SEEK_SET), 0);
+  EXPECT_EQ(read(tf.fd, buffer, sizeof(buffer)), len);
+  EXPECT_EQ(std::string(hello), buffer);
+  EXPECT_EQ(android_get_control_file(tf.path), -1);
+  EXPECT_EQ(setenv(key.c_str(), android::base::StringPrintf("%d", tf.fd).c_str(), true), 0);
+  EXPECT_EQ(android_get_control_file(tf.path), tf.fd);
+  close(tf.fd);
+  EXPECT_EQ(android_get_control_file(tf.path), -1);
+  EXPECT_EQ(unsetenv(key.c_str()), 0);
   struct stat st;
-  EXPECT_EQ(stat(path, &st), 0);
+  EXPECT_EQ(stat(tf.path, &st), 0);
   EXPECT_EQ(st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO), perms);
   EXPECT_EQ(st.st_uid, uid);
   EXPECT_EQ(st.st_gid, gid);
   security_context_t con;
-  EXPECT_GE(getfilecon(path, &con), 0);
+  EXPECT_GE(getfilecon(tf.path, &con), 0);
   EXPECT_NE(con, static_cast<security_context_t>(NULL));
   if (con) {
     EXPECT_EQ(context, std::string(con));
   }
   freecon(con);
-  EXPECT_EQ(unlink(path), 0);
+  EXPECT_EQ(unlink(tf.path), 0);
 }
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/FuseBuffer.cc b/libappfuse/FuseBuffer.cc
index 74fe756..3ade31c 100644
--- a/libappfuse/FuseBuffer.cc
+++ b/libappfuse/FuseBuffer.cc
@@ -118,23 +118,18 @@
     return;
   }
 
-  // We limit ourselves to 15 because we don't handle BATCH_FORGET yet
-  size_t response_size = sizeof(fuse_init_out);
+  // We limit ourselves to minor=15 because we don't handle BATCH_FORGET yet.
+  // Thus we need to use FUSE_COMPAT_22_INIT_OUT_SIZE.
 #if defined(FUSE_COMPAT_22_INIT_OUT_SIZE)
   // FUSE_KERNEL_VERSION >= 23.
-
-  // If the kernel only works on minor revs older than or equal to 22,
-  // then use the older structure size since this code only uses the 7.22
-  // version of the structure.
-  if (minor <= 22) {
-    response_size = FUSE_COMPAT_22_INIT_OUT_SIZE;
-  }
+  const size_t response_size = FUSE_COMPAT_22_INIT_OUT_SIZE;
+#else
+  const size_t response_size = sizeof(fuse_init_out);
 #endif
 
   response.Reset(response_size, kFuseSuccess, unique);
   fuse_init_out* const out = &response.init_out;
   out->major = FUSE_KERNEL_VERSION;
-  // We limit ourselves to 15 because we don't handle BATCH_FORGET yet.
   out->minor = std::min(minor, 15u);
   out->max_readahead = max_readahead;
   out->flags = FUSE_ATOMIC_O_TRUNC | FUSE_BIG_WRITES;
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
diff --git a/libappfuse/tests/FuseBufferTest.cc b/libappfuse/tests/FuseBufferTest.cc
index 17f1306..c822135 100644
--- a/libappfuse/tests/FuseBufferTest.cc
+++ b/libappfuse/tests/FuseBufferTest.cc
@@ -164,7 +164,7 @@
 
   buffer.HandleInit();
 
-  ASSERT_EQ(sizeof(fuse_out_header) + sizeof(fuse_init_out),
+  ASSERT_EQ(sizeof(fuse_out_header) + FUSE_COMPAT_22_INIT_OUT_SIZE,
             buffer.response.header.len);
   EXPECT_EQ(kFuseSuccess, buffer.response.header.error);
   EXPECT_EQ(static_cast<unsigned int>(FUSE_KERNEL_VERSION),
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index f7b497d..39f8aba 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -18,6 +18,7 @@
 // they correspond to features not used by our host development tools
 // which are also hard or even impossible to port to native Win32
 libcutils_nonwindows_sources = [
+    "android_get_control_file.cpp",
     "fs.c",
     "multiuser.c",
     "socket_inaddr_any_server_unix.c",
@@ -34,7 +35,6 @@
     host_supported: true,
     srcs: [
         "config_utils.c",
-        "files.cpp",
         "fs_config.c",
         "canned_fs_config.c",
         "hashmap.c",
diff --git a/include/cutils/files.h b/libcutils/android_get_control_env.h
similarity index 63%
copy from include/cutils/files.h
copy to libcutils/android_get_control_env.h
index 0210e30..638c831 100644
--- a/include/cutils/files.h
+++ b/libcutils/android_get_control_env.h
@@ -14,24 +14,20 @@
  * limitations under the License.
  */
 
-#ifndef __CUTILS_FILES_H
-#define __CUTILS_FILES_H
+#ifndef __CUTILS_ANDROID_GET_CONTROL_ENV_H
+#define __CUTILS_ANDROID_GET_CONTROL_ENV_H
 
-#define ANDROID_FILE_ENV_PREFIX "ANDROID_FILE_"
+/* To declare library function hidden and internal */
+#define LIBCUTILS_HIDDEN __attribute__((visibility("hidden")))
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/*
- * android_get_control_file - simple helper function to get the file
- * descriptor of our init-managed file. `path' is the filename path as
- * given in init.rc. Returns -1 on error.
- */
-int android_get_control_file(const char* path);
-
+LIBCUTILS_HIDDEN int __android_get_control_from_env(const char* prefix,
+                                                    const char* name);
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* __CUTILS_FILES_H */
+#endif /* __CUTILS_ANDROID_GET_CONTROL_ENV_H */
diff --git a/libcutils/files.cpp b/libcutils/android_get_control_file.cpp
similarity index 74%
rename from libcutils/files.cpp
rename to libcutils/android_get_control_file.cpp
index bf15b42..780d9f1 100644
--- a/libcutils/files.cpp
+++ b/libcutils/android_get_control_file.cpp
@@ -25,11 +25,6 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-
-// This file contains files implementation that can be shared between
-// platforms as long as the correct headers are included.
-#define _GNU_SOURCE 1 // for asprintf
-
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -41,17 +36,20 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <cutils/files.h>
+#include <cutils/android_get_control_file.h>
 
-#ifndef TEMP_FAILURE_RETRY // _WIN32 does not define
-#define TEMP_FAILURE_RETRY(exp) (exp)
+#include "android_get_control_env.h"
+
+#ifndef TEMP_FAILURE_RETRY
+#define TEMP_FAILURE_RETRY(exp) (exp) // KISS implementation
 #endif
 
-int android_get_control_file(const char* path) {
-    if (!path) return -1;
+LIBCUTILS_HIDDEN int __android_get_control_from_env(const char* prefix,
+                                                    const char* name) {
+    if (!prefix || !name) return -1;
 
     char *key = NULL;
-    if (asprintf(&key, ANDROID_FILE_ENV_PREFIX "%s", path) < 0) return -1;
+    if (asprintf(&key, "%s%s", prefix, name) < 0) return -1;
     if (!key) return -1;
 
     char *cp = key;
@@ -70,29 +68,33 @@
 
     // validity checking
     if ((fd < 0) || (fd > INT_MAX)) return -1;
-#if defined(_SC_OPEN_MAX)
-    if (fd >= sysconf(_SC_OPEN_MAX)) return -1;
-#elif defined(OPEN_MAX)
-    if (fd >= OPEN_MAX) return -1;
-#elif defined(_POSIX_OPEN_MAX)
-    if (fd >= _POSIX_OPEN_MAX) return -1;
-#endif
 
-#if defined(F_GETFD)
+    // Since we are inheriting an fd, it could legitimately exceed _SC_OPEN_MAX
+
+    // Still open?
+#if defined(F_GETFD) // Lowest overhead
     if (TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD)) < 0) return -1;
-#elif defined(F_GETFL)
+#elif defined(F_GETFL) // Alternate lowest overhead
     if (TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL)) < 0) return -1;
-#else
+#else // Hail Mary pass
     struct stat s;
     if (TEMP_FAILURE_RETRY(fstat(fd, &s)) < 0) return -1;
 #endif
 
+    return static_cast<int>(fd);
+}
+
+int android_get_control_file(const char* path) {
+    int fd = __android_get_control_from_env(ANDROID_FILE_ENV_PREFIX, path);
+
 #if defined(__linux__)
+    // Find file path from /proc and make sure it is correct
     char *proc = NULL;
-    if (asprintf(&proc, "/proc/self/fd/%ld", fd) < 0) return -1;
+    if (asprintf(&proc, "/proc/self/fd/%d", fd) < 0) return -1;
     if (!proc) return -1;
 
     size_t len = strlen(path);
+    // readlink() does not guarantee a nul byte, len+2 so we catch truncation.
     char *buf = static_cast<char *>(calloc(1, len + 2));
     if (!buf) {
         free(proc);
@@ -104,8 +106,8 @@
     free(buf);
     if (ret < 0) return -1;
     if (cmp != 0) return -1;
+    // It is what we think it is
 #endif
 
-    // It is what we think it is
-    return static_cast<int>(fd);
+    return fd;
 }
diff --git a/libcutils/klog.cpp b/libcutils/klog.cpp
index 9d823cf..4bad28a 100644
--- a/libcutils/klog.cpp
+++ b/libcutils/klog.cpp
@@ -24,7 +24,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <cutils/files.h>
+#include <cutils/android_get_control_file.h>
 #include <cutils/klog.h>
 
 static int klog_level = KLOG_DEFAULT_LEVEL;
diff --git a/libcutils/sockets.cpp b/libcutils/sockets.cpp
index 63761a2..23a447b 100644
--- a/libcutils/sockets.cpp
+++ b/libcutils/sockets.cpp
@@ -28,33 +28,9 @@
 
 // This file contains socket implementation that can be shared between
 // platforms as long as the correct headers are included.
-#define _GNU_SOURCE 1 // For asprintf
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#if !defined(_WIN32)
-#include <netinet/in.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#if !defined(_WIN32)
-#include <sys/un.h>
-#endif
-#include <unistd.h>
-
-#include <string>
 
 #include <cutils/sockets.h>
 
-#ifndef TEMP_FAILURE_RETRY // _WIN32 does not define
-#define TEMP_FAILURE_RETRY(exp) (exp)
-#endif
-
 int socket_get_local_port(cutils_socket_t sock) {
     sockaddr_storage addr;
     socklen_t addr_size = sizeof(addr);
@@ -65,58 +41,3 @@
     }
     return -1;
 }
-
-int android_get_control_socket(const char* name) {
-    char *key = NULL;
-    if (asprintf(&key, ANDROID_SOCKET_ENV_PREFIX "%s", name) < 0) return -1;
-    if (!key) return -1;
-
-    char *cp = key;
-    while (*cp) {
-        if (!isalnum(*cp)) *cp = '_';
-        ++cp;
-    }
-
-    const char* val = getenv(key);
-    free(key);
-    if (!val) return -1;
-
-    errno = 0;
-    long fd = strtol(val, NULL, 10);
-    if (errno) return -1;
-
-    // validity checking
-    if ((fd < 0) || (fd > INT_MAX)) return -1;
-#if defined(_SC_OPEN_MAX)
-    if (fd >= sysconf(_SC_OPEN_MAX)) return -1;
-#elif defined(OPEN_MAX)
-    if (fd >= OPEN_MAX) return -1;
-#elif defined(_POSIX_OPEN_MAX)
-    if (fd >= _POSIX_OPEN_MAX) return -1;
-#endif
-
-#if defined(F_GETFD)
-    if (TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD)) < 0) return -1;
-#elif defined(F_GETFL)
-    if (TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL)) < 0) return -1;
-#else
-    struct stat s;
-    if (TEMP_FAILURE_RETRY(fstat(fd, &s)) < 0) return -1;
-#endif
-
-#if !defined(_WIN32)
-    struct sockaddr_un addr;
-    socklen_t addrlen = sizeof(addr);
-    int ret = TEMP_FAILURE_RETRY(getsockname(fd, (struct sockaddr *)&addr, &addrlen));
-    if (ret < 0) return -1;
-    char *path = NULL;
-    if (asprintf(&path, ANDROID_SOCKET_DIR"/%s", name) < 0) return -1;
-    if (!path) return -1;
-    int cmp = strcmp(addr.sun_path, path);
-    free(path);
-    if (cmp != 0) return -1;
-#endif
-
-    // It is what we think it is
-    return static_cast<int>(fd);
-}
diff --git a/libcutils/sockets_unix.cpp b/libcutils/sockets_unix.cpp
index 3545403..5a14a5c 100644
--- a/libcutils/sockets_unix.cpp
+++ b/libcutils/sockets_unix.cpp
@@ -16,13 +16,25 @@
 
 #define LOG_TAG "socket-unix"
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
 #include <sys/uio.h>
+#include <sys/un.h>
 #include <time.h>
 #include <unistd.h>
 
 #include <android/log.h>
+#include <cutils/android_get_control_file.h>
 #include <cutils/sockets.h>
 
+#include "android_get_control_env.h"
+
+#ifndef TEMP_FAILURE_RETRY
+#define TEMP_FAILURE_RETRY(exp) (exp) // KISS implementation
+#endif
+
 #if defined(__ANDROID__)
 /* For the socket trust (credentials) check */
 #include <private/android_filesystem_config.h>
@@ -80,3 +92,24 @@
 
     return writev(sock, iovec_buffers, num_buffers);
 }
+
+int android_get_control_socket(const char* name) {
+    int fd = __android_get_control_from_env(ANDROID_SOCKET_ENV_PREFIX, name);
+
+    if (fd < 0) return fd;
+
+    // Compare to UNIX domain socket name, must match!
+    struct sockaddr_un addr;
+    socklen_t addrlen = sizeof(addr);
+    int ret = TEMP_FAILURE_RETRY(getsockname(fd, (struct sockaddr *)&addr, &addrlen));
+    if (ret < 0) return -1;
+    char *path = NULL;
+    if (asprintf(&path, ANDROID_SOCKET_DIR "/%s", name) < 0) return -1;
+    if (!path) return -1;
+    int cmp = strcmp(addr.sun_path, path);
+    free(path);
+    if (cmp != 0) return -1;
+
+    // It is what we think it is
+    return fd;
+}
diff --git a/libcutils/sockets_windows.cpp b/libcutils/sockets_windows.cpp
index ed6b1a7..3064c70 100644
--- a/libcutils/sockets_windows.cpp
+++ b/libcutils/sockets_windows.cpp
@@ -84,3 +84,7 @@
 
     return -1;
 }
+
+int android_get_control_socket(const char* name) {
+    return -1;
+}
diff --git a/libcutils/tests/Android.bp b/libcutils/tests/Android.bp
index bd35412..72e2eac 100644
--- a/libcutils/tests/Android.bp
+++ b/libcutils/tests/Android.bp
@@ -14,7 +14,7 @@
 
 cc_defaults {
     name: "libcutils_test_default",
-    srcs: ["sockets_test.cpp", "files_test.cpp"],
+    srcs: ["sockets_test.cpp"],
 
     target: {
         android: {
@@ -28,7 +28,11 @@
         },
 
         not_windows: {
-            srcs: ["test_str_parms.cpp"],
+            srcs: [
+                "test_str_parms.cpp",
+                "android_get_control_socket_test.cpp",
+                "android_get_control_file_test.cpp"
+            ],
         },
     },
 
diff --git a/libcutils/tests/android_get_control_file_test.cpp b/libcutils/tests/android_get_control_file_test.cpp
new file mode 100644
index 0000000..6c6fd2a
--- /dev/null
+++ b/libcutils/tests/android_get_control_file_test.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include <string>
+
+#include <android-base/stringprintf.h>
+#include <android-base/test_utils.h>
+#include <cutils/android_get_control_file.h>
+#include <gtest/gtest.h>
+
+TEST(FilesTest, android_get_control_file) {
+    TemporaryFile tf;
+    ASSERT_GE(tf.fd, 0);
+
+    std::string key(ANDROID_FILE_ENV_PREFIX);
+    key += tf.path;
+
+    std::for_each(key.begin(), key.end(), [] (char& c) { c = isalnum(c) ? c : '_'; });
+
+    EXPECT_EQ(unsetenv(key.c_str()), 0);
+    EXPECT_EQ(android_get_control_file(tf.path), -1);
+
+    EXPECT_EQ(setenv(key.c_str(), android::base::StringPrintf("%d", tf.fd).c_str(), true), 0);
+
+    EXPECT_EQ(android_get_control_file(tf.path), tf.fd);
+    close(tf.fd);
+    EXPECT_EQ(android_get_control_file(tf.path), -1);
+    EXPECT_EQ(unsetenv(key.c_str()), 0);
+    EXPECT_EQ(android_get_control_file(tf.path), -1);
+}
diff --git a/libcutils/tests/android_get_control_socket_test.cpp b/libcutils/tests/android_get_control_socket_test.cpp
new file mode 100644
index 0000000..e586748
--- /dev/null
+++ b/libcutils/tests/android_get_control_socket_test.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <time.h>
+
+#include <cutils/sockets.h>
+#include <gtest/gtest.h>
+
+#ifndef SOCK_NONBLOCK
+#define SOCK_NONBLOCK 0
+#endif
+
+#ifndef SOCK_CLOEXEC
+#define SOCK_CLOEXEC 0
+#endif
+
+TEST(SocketsTest, android_get_control_socket) {
+    static const char key[] = ANDROID_SOCKET_ENV_PREFIX "SocketsTest_android_get_control_socket";
+    static const char* name = key + strlen(ANDROID_SOCKET_ENV_PREFIX);
+
+    EXPECT_EQ(unsetenv(key), 0);
+    EXPECT_EQ(android_get_control_socket(name), -1);
+
+    int fd;
+    ASSERT_GE(fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0), 0);
+#ifdef F_GETFL
+    int flags;
+    ASSERT_GE(flags = fcntl(fd, F_GETFL), 0);
+    ASSERT_GE(fcntl(fd, F_SETFL, flags | O_NONBLOCK), 0);
+#endif
+    EXPECT_EQ(android_get_control_socket(name), -1);
+
+    struct sockaddr_un addr;
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_family = AF_UNIX;
+    snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s", name);
+    unlink(addr.sun_path);
+
+    EXPECT_EQ(bind(fd, (struct sockaddr*)&addr, sizeof(addr)), 0);
+    EXPECT_EQ(android_get_control_socket(name), -1);
+
+    char val[32];
+    snprintf(val, sizeof(val), "%d", fd);
+    EXPECT_EQ(setenv(key, val, true), 0);
+
+    EXPECT_EQ(android_get_control_socket(name), fd);
+    socket_close(fd);
+    EXPECT_EQ(android_get_control_socket(name), -1);
+    EXPECT_EQ(unlink(addr.sun_path), 0);
+    EXPECT_EQ(android_get_control_socket(name), -1);
+    EXPECT_EQ(unsetenv(key), 0);
+    EXPECT_EQ(android_get_control_socket(name), -1);
+}
diff --git a/libcutils/tests/files_test.cpp b/libcutils/tests/files_test.cpp
deleted file mode 100644
index 1a7d673..0000000
--- a/libcutils/tests/files_test.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <time.h>
-
-#include <cutils/files.h>
-#include <gtest/gtest.h>
-
-TEST(FilesTest, android_get_control_file) {
-    static const char key[] = ANDROID_FILE_ENV_PREFIX "_dev_kmsg";
-    static const char name[] = "/dev/kmsg";
-
-    EXPECT_EQ(unsetenv(key), 0);
-    EXPECT_EQ(android_get_control_file(name), -1);
-
-    int fd;
-    ASSERT_GE(fd = open(name, O_RDONLY | O_CLOEXEC), 0);
-    EXPECT_EQ(android_get_control_file(name), -1);
-
-    char val[32];
-    snprintf(val, sizeof(val), "%d", fd);
-    EXPECT_EQ(setenv(key, val, true), 0);
-
-    EXPECT_EQ(android_get_control_file(name), fd);
-    close(fd);
-    EXPECT_EQ(android_get_control_file(name), -1);
-    EXPECT_EQ(unsetenv(key), 0);
-    EXPECT_EQ(android_get_control_file(name), -1);
-}
diff --git a/libcutils/tests/sockets_test.cpp b/libcutils/tests/sockets_test.cpp
index adfbf4a..0441fb6 100644
--- a/libcutils/tests/sockets_test.cpp
+++ b/libcutils/tests/sockets_test.cpp
@@ -18,11 +18,9 @@
 // IPv6 capabilities. These tests assume that no UDP packets are lost, which
 // should be the case for loopback communication, but is not guaranteed.
 
-#include <stdio.h>
-#include <stdlib.h>
+#include <string.h>
 #include <sys/socket.h>
 #include <sys/types.h>
-#include <sys/un.h>
 #include <time.h>
 
 #include <cutils/sockets.h>
@@ -189,49 +187,3 @@
 TEST(SocketsTest, TestSocketSendBuffersFailure) {
     EXPECT_EQ(-1, socket_send_buffers(INVALID_SOCKET, nullptr, 0));
 }
-
-#ifndef SOCK_NONBLOCK
-#define SOCK_NONBLOCK 0
-#endif
-
-#ifndef SOCK_CLOEXEC
-#define SOCK_CLOEXEC 0
-#endif
-
-TEST(SocketsTest, android_get_control_socket) {
-    static const char key[] = ANDROID_SOCKET_ENV_PREFIX "SocketsTest_android_get_control_socket";
-    static const char* name = key + strlen(ANDROID_SOCKET_ENV_PREFIX);
-
-    EXPECT_EQ(unsetenv(key), 0);
-    EXPECT_EQ(android_get_control_socket(name), -1);
-
-    int fd;
-    ASSERT_GE(fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0), 0);
-#ifdef F_GETFL
-    int flags;
-    ASSERT_GE(flags = fcntl(fd, F_GETFL), 0);
-    ASSERT_GE(fcntl(fd, F_SETFL, flags | O_NONBLOCK), 0);
-#endif
-    EXPECT_EQ(android_get_control_socket(name), -1);
-
-    struct sockaddr_un addr;
-    memset(&addr, 0, sizeof(addr));
-    addr.sun_family = AF_UNIX;
-    snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s", name);
-    unlink(addr.sun_path);
-
-    EXPECT_EQ(bind(fd, (struct sockaddr*)&addr, sizeof(addr)), 0);
-    EXPECT_EQ(android_get_control_socket(name), -1);
-
-    char val[32];
-    snprintf(val, sizeof(val), "%d", fd);
-    EXPECT_EQ(setenv(key, val, true), 0);
-
-    EXPECT_EQ(android_get_control_socket(name), fd);
-    socket_close(fd);
-    EXPECT_EQ(android_get_control_socket(name), -1);
-    EXPECT_EQ(unlink(addr.sun_path), 0);
-    EXPECT_EQ(android_get_control_socket(name), -1);
-    EXPECT_EQ(unsetenv(key), 0);
-    EXPECT_EQ(android_get_control_socket(name), -1);
-}
diff --git a/liblog/logprint.c b/liblog/logprint.c
index fb942a1..da80e36 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -632,8 +632,8 @@
     size_t len;
     int64_t lval;
 
-    if (eventDataLen < 1)
-        return -1;
+    if (eventDataLen < 1) return -1;
+
     type = *eventData++;
     eventDataLen--;
 
@@ -729,8 +729,7 @@
         {
             int32_t ival;
 
-            if (eventDataLen < 4)
-                return -1;
+            if (eventDataLen < 4) return -1;
             ival = get4LE(eventData);
             eventData += 4;
             eventDataLen -= 4;
@@ -740,8 +739,7 @@
         goto pr_lval;
     case EVENT_TYPE_LONG:
         /* 64-bit signed long */
-        if (eventDataLen < 8)
-            return -1;
+        if (eventDataLen < 8) return -1;
         lval = get8LE(eventData);
         eventData += 8;
         eventDataLen -= 8;
@@ -761,8 +759,7 @@
             uint32_t ival;
             float fval;
 
-            if (eventDataLen < 4)
-                return -1;
+            if (eventDataLen < 4) return -1;
             ival = get4LE(eventData);
             fval = *(float*)&ival;
             eventData += 4;
@@ -783,14 +780,12 @@
         {
             unsigned int strLen;
 
-            if (eventDataLen < 4)
-                return -1;
+            if (eventDataLen < 4) return -1;
             strLen = get4LE(eventData);
             eventData += 4;
             eventDataLen -= 4;
 
-            if (eventDataLen < strLen)
-                return -1;
+            if (eventDataLen < strLen) return -1;
 
             if (cp && (strLen == 0)) {
                 /* reset the format if no content */
@@ -818,41 +813,32 @@
             unsigned char count;
             int i;
 
-            if (eventDataLen < 1)
-                return -1;
+            if (eventDataLen < 1) return -1;
 
             count = *eventData++;
             eventDataLen--;
 
-            if (outBufLen > 0) {
-                *outBuf++ = '[';
-                outBufLen--;
-            } else {
-                goto no_room;
-            }
+            if (outBufLen <= 0) goto no_room;
+
+            *outBuf++ = '[';
+            outBufLen--;
 
             for (i = 0; i < count; i++) {
                 result = android_log_printBinaryEvent(&eventData, &eventDataLen,
                         &outBuf, &outBufLen, fmtStr, fmtLen);
-                if (result != 0)
-                    goto bail;
+                if (result != 0) goto bail;
 
-                if (i < count-1) {
-                    if (outBufLen > 0) {
-                        *outBuf++ = ',';
-                        outBufLen--;
-                    } else {
-                        goto no_room;
-                    }
+                if (i < (count - 1)) {
+                    if (outBufLen <= 0) goto no_room;
+                    *outBuf++ = ',';
+                    outBufLen--;
                 }
             }
 
-            if (outBufLen > 0) {
-                *outBuf++ = ']';
-                outBufLen--;
-            } else {
-                goto no_room;
-            }
+            if (outBufLen <= 0) goto no_room;
+
+            *outBuf++ = ']';
+            outBufLen--;
         }
         break;
     default:
@@ -997,8 +983,7 @@
         }
     }
     inCount = buf->len;
-    if (inCount < 4)
-        return -1;
+    if (inCount < 4) return -1;
     tagIndex = get4LE(eventData);
     eventData += 4;
     inCount -= 4;
@@ -1031,16 +1016,20 @@
     /*
      * Format the event log data into the buffer.
      */
-    char* outBuf = messageBuf;
-    size_t outRemaining = messageBufLen - 1; /* leave one for nul byte */
-    int result;
     const char* fmtStr = NULL;
     size_t fmtLen = 0;
     if (descriptive_output && map) {
         fmtStr = android_lookupEventFormat_len(map, &fmtLen, tagIndex);
     }
-    result = android_log_printBinaryEvent(&eventData, &inCount, &outBuf,
-                &outRemaining, &fmtStr, &fmtLen);
+
+    char* outBuf = messageBuf;
+    size_t outRemaining = messageBufLen - 1; /* leave one for nul byte */
+    int result = 0;
+
+    if ((inCount > 0) || fmtLen) {
+        result = android_log_printBinaryEvent(&eventData, &inCount, &outBuf,
+                                              &outRemaining, &fmtStr, &fmtLen);
+    }
     if ((result == 1) && fmtStr) {
         /* We overflowed :-(, let's repaint the line w/o format dressings */
         eventData = (const unsigned char*)buf->msg;
@@ -1055,18 +1044,18 @@
     }
     if (result < 0) {
         fprintf(stderr, "Binary log entry conversion failed\n");
-        return -1;
-    } else if (result == 1) {
-        if (outBuf > messageBuf) {
-            /* leave an indicator */
-            *(outBuf-1) = '!';
-        } else {
-            /* no room to output anything at all */
-            *outBuf++ = '!';
-            outRemaining--;
+    }
+    if (result) {
+        if (!outRemaining) {
+            /* make space to leave an indicator */
+            --outBuf;
+            ++outRemaining;
         }
-        /* pretend we ate all the data */
+        *outBuf++ = (result < 0) ? '!' : '^'; /* Error or Truncation? */
+        outRemaining--;
+        /* pretend we ate all the data to prevent log stutter */
         inCount = 0;
+        if (result > 0) result = 0;
     }
 
     /* eat the silly terminating '\n' */
@@ -1090,7 +1079,7 @@
 
     entry->message = messageBuf;
 
-    return 0;
+    return result;
 }
 
 /*
@@ -1802,8 +1791,7 @@
     outBuffer = android_log_formatLogLine(p_format, defaultBuffer,
             sizeof(defaultBuffer), entry, &totalLen);
 
-    if (!outBuffer)
-        return -1;
+    if (!outBuffer) return -1;
 
     do {
         ret = write(fd, outBuffer, totalLen);
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 9c09523..70c7a48 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -328,6 +328,9 @@
             EXPECT_TRUE(NULL != logformat);
             AndroidLogEntry entry;
             char msgBuf[1024];
+            if (length != total) {
+                fprintf(stderr, "Expect \"Binary log entry conversion failed\"\n");
+            }
             int processBinaryLogBuffer = android_log_processBinaryLogBuffer(
                 &log_msg.entry_v1, &entry, NULL, msgBuf, sizeof(msgBuf));
             EXPECT_EQ((length == total) ? 0 : -1, processBinaryLogBuffer);
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index d36cc3f..e6e0276 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -781,7 +781,8 @@
   // Creates a FileWriter for |fd| and prepare to write |entry| to it,
   // guaranteeing that the file descriptor is valid and that there's enough
   // space on the volume to write out the entry completely and that the file
-  // is truncated to the correct length.
+  // is truncated to the correct length (no truncation if |fd| references a
+  // block device).
   //
   // Returns a valid FileWriter on success, |nullptr| if an error occurred.
   static std::unique_ptr<FileWriter> Create(int fd, const ZipEntry* entry) {
@@ -814,13 +815,22 @@
     }
 #endif  // __linux__
 
-    result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
-    if (result == -1) {
-      ALOGW("Zip: unable to truncate file to %" PRId64 ": %s",
-            static_cast<int64_t>(declared_length + current_offset), strerror(errno));
+    struct stat sb;
+    if (fstat(fd, &sb) == -1) {
+      ALOGW("Zip: unable to fstat file: %s", strerror(errno));
       return std::unique_ptr<FileWriter>(nullptr);
     }
 
+    // Block device doesn't support ftruncate(2).
+    if (!S_ISBLK(sb.st_mode)) {
+      result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
+      if (result == -1) {
+        ALOGW("Zip: unable to truncate file to %" PRId64 ": %s",
+              static_cast<int64_t>(declared_length + current_offset), strerror(errno));
+        return std::unique_ptr<FileWriter>(nullptr);
+      }
+    }
+
     return std::unique_ptr<FileWriter>(new FileWriter(fd, declared_length));
   }
 
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index d0c693d..41f2280 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -81,6 +81,7 @@
 static size_t g_maxCount;
 static size_t g_printCount;
 static bool g_printItAnyways;
+static bool g_debug;
 
 enum helpType {
     HELP_FALSE,
@@ -188,7 +189,7 @@
     } else {
         err = android_log_processLogBuffer(&buf->entry_v1, &entry);
     }
-    if (err < 0) {
+    if ((err < 0) && !g_debug) {
         goto error;
     }
 
@@ -619,6 +620,7 @@
         int option_index = 0;
         // list of long-argument only strings for later comparison
         static const char pid_str[] = "pid";
+        static const char debug_str[] = "debug";
         static const char id_str[] = "id";
         static const char wrap_str[] = "wrap";
         static const char print_str[] = "print";
@@ -627,6 +629,7 @@
           { "buffer",        required_argument, NULL,   'b' },
           { "buffer-size",   optional_argument, NULL,   'g' },
           { "clear",         no_argument,       NULL,   'c' },
+          { debug_str,       no_argument,       NULL,   0 },
           { "dividers",      no_argument,       NULL,   'D' },
           { "file",          required_argument, NULL,   'f' },
           { "format",        required_argument, NULL,   'v' },
@@ -691,6 +694,10 @@
                     g_printItAnyways = true;
                     break;
                 }
+                if (long_options[option_index].name == debug_str) {
+                    g_debug = true;
+                    break;
+                }
                 if (long_options[option_index].name == id_str) {
                     setId = optarg && optarg[0] ? optarg : NULL;
                     break;
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index 18067dc..8d7c04e 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -1255,19 +1255,25 @@
     va_end(ap);
 
     char *str = NULL;
-    asprintf(&str, "I/%s ( %%d): %s%%c", tag, buffer);
+    asprintf(&str, "I/%s ( %%d):%%c%s%%c", tag, buffer);
     std::string expect(str);
     free(str);
 
     int count = 0;
     pid_t pid = getpid();
     std::string lastMatch;
+    int maxMatch = 1;
     while (fgets(buffer, sizeof(buffer), fp)) {
+        char space;
         char newline;
         int p;
-        int ret = sscanf(buffer, expect.c_str(), &p, &newline);
-        if ((2 == ret) && (p == pid) && (newline == '\n')) ++count;
-        else if ((1 == ret) && (p == pid) && (count == 0)) lastMatch = buffer;
+        int ret = sscanf(buffer, expect.c_str(), &p, &space, &newline);
+        if ((ret == 3) && (p == pid) && (space == ' ') && (newline == '\n')) {
+            ++count;
+        } else if ((ret >= maxMatch) && (p == pid) && (count == 0)) {
+            lastMatch = buffer;
+            maxMatch = ret;
+        }
     }
 
     pclose(fp);
@@ -1395,4 +1401,10 @@
         }
     }
 
+    {
+        static const struct tag sync = { 27501, "notification_panel_hidden" };
+        android_log_event_context ctx(sync.tagNo);
+        ctx.write();
+        EXPECT_TRUE(End_to_End(sync.tagStr, ""));
+    }
 }
diff --git a/logd/main.cpp b/logd/main.cpp
index d698976..7550c41 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -37,9 +37,9 @@
 #include <memory>
 
 #include <android-base/macros.h>
+#include <cutils/android_get_control_file.h>
 #include <cutils/properties.h>
 #include <cutils/sched_policy.h>
-#include <cutils/files.h>
 #include <cutils/sockets.h>
 #include <log/event_tag_map.h>
 #include <packagelistparser/packagelistparser.h>
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 4e766bb..fb53178 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -293,11 +293,8 @@
     mount none /mnt/runtime/default /storage slave bind rec
 
     # Make sure /sys/kernel/debug (if present) is labeled properly
-    restorecon_recursive /sys/kernel/debug
-
-    # On systems with tracefs, tracing is a separate mount, so make sure
-    # it too is correctly labeled
-    restorecon_recursive /sys/kernel/debug/tracing
+    # Note that tracefs may be mounted under debug, so we need to cross filesystems
+    restorecon --recursive --cross-filesystems /sys/kernel/debug
 
     # We chown/chmod /cache again so because mount is run as root + defaults
     chown system cache /cache
@@ -462,7 +459,7 @@
     init_user0
 
     # Set SELinux security contexts on upgrade or policy update.
-    restorecon_recursive /data
+    restorecon --recursive --skip-ce /data
 
     # Check any timezone data in /data is newer than the copy in /system, delete if not.
     exec - system system -- /system/bin/tzdatacheck /system/usr/share/zoneinfo /data/misc/zoneinfo
diff --git a/sdcard/fuse.cpp b/sdcard/fuse.cpp
index d4c51fd..9393846 100644
--- a/sdcard/fuse.cpp
+++ b/sdcard/fuse.cpp
@@ -1262,12 +1262,9 @@
 #if defined(FUSE_COMPAT_22_INIT_OUT_SIZE)
     /* FUSE_KERNEL_VERSION >= 23. */
 
-    /* If the kernel only works on minor revs older than or equal to 22,
-     * then use the older structure size since this code only uses the 7.22
-     * version of the structure. */
-    if (req->minor <= 22) {
-        fuse_struct_size = FUSE_COMPAT_22_INIT_OUT_SIZE;
-    }
+    /* Since we return minor version 15, the kernel does not accept the latest
+     * fuse_init_out size. We need to use FUSE_COMPAT_22_INIT_OUT_SIZE always.*/
+    fuse_struct_size = FUSE_COMPAT_22_INIT_OUT_SIZE;
 #endif
 
     out.major = FUSE_KERNEL_VERSION;
diff --git a/toolbox/newfs_msdos.c b/toolbox/newfs_msdos.c
index 27ea9e8..d7047e2 100644
--- a/toolbox/newfs_msdos.c
+++ b/toolbox/newfs_msdos.c
@@ -741,6 +741,7 @@
                 exit(1);
             }
         }
+        free(img);
     }
     return 0;
 }