Merge "If the pc is set to zero, the unwind is done."
diff --git a/adb/Android.mk b/adb/Android.mk
index 05b0284..2b6df70 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -133,7 +133,7 @@
 
 # Even though we're building a static library (and thus there's no link step for
 # this to take effect), this adds the includes to our path.
-LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase
+LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libqemu_pipe libbase
 
 LOCAL_WHOLE_STATIC_LIBRARIES := libadbd_usb
 
@@ -363,6 +363,7 @@
     libasyncio \
     libavb_user \
     libbase \
+    libqemu_pipe \
     libbootloader_message \
     libfs_mgr \
     libfec \
diff --git a/adb/adb.h b/adb/adb.h
index a4d233e..3651413 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -67,9 +67,8 @@
     uint32_t magic;       /* command ^ 0xffffffff             */
 };
 
-struct apacket
-{
-    apacket *next;
+struct apacket {
+    apacket* next;
 
     size_t len;
     char* ptr;
@@ -85,13 +84,11 @@
 ** this should be used to cleanup objects that depend on the
 ** transport (e.g. remote sockets, listeners, etc...)
 */
-struct  adisconnect
-{
-    void        (*func)(void*  opaque, atransport*  t);
-    void*         opaque;
+struct adisconnect {
+    void (*func)(void* opaque, atransport* t);
+    void* opaque;
 };
 
-
 // A transport object models the connection to a remote device or emulator there
 // is one transport per connected device/emulator. A "local transport" connects
 // through TCP (for the emulator), while a "usb transport" through USB (for real
@@ -121,15 +118,14 @@
     kCsUnauthorized,
 };
 
-
-void print_packet(const char *label, apacket *p);
+void print_packet(const char* label, apacket* p);
 
 // These use the system (v)fprintf, not the adb prefixed ones defined in sysdeps.h, so they
 // shouldn't be tagged with ADB_FORMAT_ARCHETYPE.
 void fatal(const char* fmt, ...) __attribute__((noreturn, format(__printf__, 1, 2)));
 void fatal_errno(const char* fmt, ...) __attribute__((noreturn, format(__printf__, 1, 2)));
 
-void handle_packet(apacket *p, atransport *t);
+void handle_packet(apacket* p, atransport* t);
 
 int launch_server(const std::string& socket_spec);
 int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply_fd);
@@ -138,7 +134,7 @@
 #if ADB_HOST
 int get_available_local_transport_index();
 #endif
-int  init_socket_transport(atransport *t, int s, int port, int local);
+int init_socket_transport(atransport* t, int s, int port, int local);
 void init_usb_transport(atransport* t, usb_handle* usb);
 
 std::string getEmulatorSerialString(int console_port);
@@ -153,77 +149,78 @@
 #endif
 
 #if !ADB_HOST
-int       init_jdwp(void);
-asocket*  create_jdwp_service_socket();
-asocket*  create_jdwp_tracker_service_socket();
-int       create_jdwp_connection_fd(int  jdwp_pid);
+int init_jdwp(void);
+asocket* create_jdwp_service_socket();
+asocket* create_jdwp_tracker_service_socket();
+int create_jdwp_connection_fd(int jdwp_pid);
 #endif
 
 int handle_forward_request(const char* service, TransportType type, const char* serial,
                            TransportId transport_id, int reply_fd);
 
 #if !ADB_HOST
-void framebuffer_service(int fd, void *cookie);
+void framebuffer_service(int fd, void* cookie);
 void set_verity_enabled_state_service(int fd, void* cookie);
 #endif
 
 /* packet allocator */
-apacket *get_apacket(void);
-void put_apacket(apacket *p);
+apacket* get_apacket(void);
+void put_apacket(apacket* p);
 
 // Define it if you want to dump packets.
 #define DEBUG_PACKETS 0
 
 #if !DEBUG_PACKETS
-#define print_packet(tag,p) do {} while (0)
+#define print_packet(tag, p) \
+    do {                     \
+    } while (0)
 #endif
 
 #if ADB_HOST_ON_TARGET
 /* adb and adbd are coexisting on the target, so use 5038 for adb
  * to avoid conflicting with adbd's usage of 5037
  */
-#  define DEFAULT_ADB_PORT 5038
+#define DEFAULT_ADB_PORT 5038
 #else
-#  define DEFAULT_ADB_PORT 5037
+#define DEFAULT_ADB_PORT 5037
 #endif
 
 #define DEFAULT_ADB_LOCAL_TRANSPORT_PORT 5555
 
-#define ADB_CLASS              0xff
-#define ADB_SUBCLASS           0x42
-#define ADB_PROTOCOL           0x1
-
+#define ADB_CLASS 0xff
+#define ADB_SUBCLASS 0x42
+#define ADB_PROTOCOL 0x1
 
 void local_init(int port);
 bool local_connect(int port);
-int  local_connect_arbitrary_ports(int console_port, int adb_port, std::string* error);
+int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* error);
 
-ConnectionState connection_state(atransport *t);
+ConnectionState connection_state(atransport* t);
 
 extern const char* adb_device_banner;
 
 #if !ADB_HOST
 extern int SHELL_EXIT_NOTIFY_FD;
-#endif // !ADB_HOST
+#endif  // !ADB_HOST
 
-#define CHUNK_SIZE (64*1024)
+#define CHUNK_SIZE (64 * 1024)
 
 #if !ADB_HOST
-#define USB_FFS_ADB_PATH  "/dev/usb-ffs/adb/"
-#define USB_FFS_ADB_EP(x) USB_FFS_ADB_PATH#x
+#define USB_FFS_ADB_PATH "/dev/usb-ffs/adb/"
+#define USB_FFS_ADB_EP(x) USB_FFS_ADB_PATH #x
 
-#define USB_FFS_ADB_EP0   USB_FFS_ADB_EP(ep0)
-#define USB_FFS_ADB_OUT   USB_FFS_ADB_EP(ep1)
-#define USB_FFS_ADB_IN    USB_FFS_ADB_EP(ep2)
+#define USB_FFS_ADB_EP0 USB_FFS_ADB_EP(ep0)
+#define USB_FFS_ADB_OUT USB_FFS_ADB_EP(ep1)
+#define USB_FFS_ADB_IN USB_FFS_ADB_EP(ep2)
 #endif
 
 int handle_host_request(const char* service, TransportType type, const char* serial,
                         TransportId transport_id, int reply_fd, asocket* s);
 
-void handle_online(atransport *t);
-void handle_offline(atransport *t);
+void handle_online(atransport* t);
+void handle_offline(atransport* t);
 
-void send_connect(atransport *t);
+void send_connect(atransport* t);
 
 void parse_banner(const std::string&, atransport* t);
 
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index 30cb29b..a142384 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -172,7 +172,7 @@
     auto pred = [](const std::unique_ptr<alistener>& listener) {
         return listener->local_name == "*smartsocket*";
     };
-    listener_list.erase(std::remove_if(listener_list.begin(), listener_list.end(), pred));
+    listener_list.remove_if(pred);
 }
 
 InstallStatus install_listener(const std::string& local_name, const char* connect_to,
diff --git a/adb/client/usb_linux.cpp b/adb/client/usb_linux.cpp
index a7df0ed..1f376a4 100644
--- a/adb/client/usb_linux.cpp
+++ b/adb/client/usb_linux.cpp
@@ -253,7 +253,7 @@
                             continue;
                         }
                             /* aproto 01 needs 0 termination */
-                        if (interface->bInterfaceProtocol == 0x01) {
+                        if (interface->bInterfaceProtocol == ADB_PROTOCOL) {
                             max_packet_size = ep1->wMaxPacketSize;
                             zero_mask = ep1->wMaxPacketSize - 1;
                         }
diff --git a/adb/client/usb_osx.cpp b/adb/client/usb_osx.cpp
index 4e1480f..2e999ee 100644
--- a/adb/client/usb_osx.cpp
+++ b/adb/client/usb_osx.cpp
@@ -174,7 +174,7 @@
         kr = (*iface)->GetInterfaceClass(iface, &if_class);
         kr = (*iface)->GetInterfaceSubClass(iface, &subclass);
         kr = (*iface)->GetInterfaceProtocol(iface, &protocol);
-        if(if_class != ADB_CLASS || subclass != ADB_SUBCLASS || protocol != ADB_PROTOCOL) {
+        if (!is_adb_interface(if_class, subclass, protocol)) {
             // Ignore non-ADB devices.
             LOG(DEBUG) << "Ignoring interface with incorrect class/subclass/protocol - " << if_class
                        << ", " << subclass << ", " << protocol;
diff --git a/adb/client/usb_windows.cpp b/adb/client/usb_windows.cpp
index 1620e6e..61981b1 100644
--- a/adb/client/usb_windows.cpp
+++ b/adb/client/usb_windows.cpp
@@ -18,8 +18,10 @@
 
 #include "sysdeps.h"
 
+// clang-format off
 #include <winsock2.h>  // winsock.h *must* be included before windows.h.
 #include <windows.h>
+// clang-format on
 #include <usb100.h>
 #include <winerror.h>
 
@@ -47,29 +49,29 @@
   ability to break a thread out of pipe IO.
 */
 struct usb_handle {
-  /// Previous entry in the list of opened usb handles
-  usb_handle *prev;
+    /// Previous entry in the list of opened usb handles
+    usb_handle* prev;
 
-  /// Next entry in the list of opened usb handles
-  usb_handle *next;
+    /// Next entry in the list of opened usb handles
+    usb_handle* next;
 
-  /// Handle to USB interface
-  ADBAPIHANDLE  adb_interface;
+    /// Handle to USB interface
+    ADBAPIHANDLE adb_interface;
 
-  /// Handle to USB read pipe (endpoint)
-  ADBAPIHANDLE  adb_read_pipe;
+    /// Handle to USB read pipe (endpoint)
+    ADBAPIHANDLE adb_read_pipe;
 
-  /// Handle to USB write pipe (endpoint)
-  ADBAPIHANDLE  adb_write_pipe;
+    /// Handle to USB write pipe (endpoint)
+    ADBAPIHANDLE adb_write_pipe;
 
-  /// Interface name
-  wchar_t*      interface_name;
+    /// Interface name
+    wchar_t* interface_name;
 
-  /// Maximum packet size.
-  unsigned max_packet_size;
+    /// Maximum packet size.
+    unsigned max_packet_size;
 
-  /// Mask for determining when to use zero length packets
-  unsigned zero_mask;
+    /// Mask for determining when to use zero length packets
+    unsigned zero_mask;
 };
 
 /// Class ID assigned to the device by androidusb.sys
@@ -77,8 +79,7 @@
 
 /// List of opened usb handles
 static usb_handle handle_list = {
-  .prev = &handle_list,
-  .next = &handle_list,
+    .prev = &handle_list, .next = &handle_list,
 };
 
 /// Locker for the list of opened usb handles
@@ -118,7 +119,7 @@
 int usb_write(usb_handle* handle, const void* data, int len);
 
 /// Reads data using the opened usb handle
-int usb_read(usb_handle *handle, void* data, int len);
+int usb_read(usb_handle* handle, void* data, int len);
 
 /// Cleans up opened usb handle
 void usb_cleanup_handle(usb_handle* handle);
@@ -130,401 +131,374 @@
 int usb_close(usb_handle* handle);
 
 int known_device_locked(const wchar_t* dev_name) {
-  usb_handle* usb;
+    usb_handle* usb;
 
-  if (NULL != dev_name) {
-    // Iterate through the list looking for the name match.
-    for(usb = handle_list.next; usb != &handle_list; usb = usb->next) {
-      // In Windows names are not case sensetive!
-      if((NULL != usb->interface_name) &&
-         (0 == wcsicmp(usb->interface_name, dev_name))) {
-        return 1;
-      }
+    if (NULL != dev_name) {
+        // Iterate through the list looking for the name match.
+        for (usb = handle_list.next; usb != &handle_list; usb = usb->next) {
+            // In Windows names are not case sensetive!
+            if ((NULL != usb->interface_name) && (0 == wcsicmp(usb->interface_name, dev_name))) {
+                return 1;
+            }
+        }
     }
-  }
 
-  return 0;
+    return 0;
 }
 
 int known_device(const wchar_t* dev_name) {
-  int ret = 0;
+    int ret = 0;
 
-  if (NULL != dev_name) {
-    std::lock_guard<std::mutex> lock(usb_lock);
-    ret = known_device_locked(dev_name);
-  }
+    if (NULL != dev_name) {
+        std::lock_guard<std::mutex> lock(usb_lock);
+        ret = known_device_locked(dev_name);
+    }
 
-  return ret;
+    return ret;
 }
 
 int register_new_device(usb_handle* handle) {
-  if (NULL == handle)
-    return 0;
+    if (NULL == handle) return 0;
 
-  std::lock_guard<std::mutex> lock(usb_lock);
+    std::lock_guard<std::mutex> lock(usb_lock);
 
-  // Check if device is already in the list
-  if (known_device_locked(handle->interface_name)) {
-    return 0;
-  }
+    // Check if device is already in the list
+    if (known_device_locked(handle->interface_name)) {
+        return 0;
+    }
 
-  // Not in the list. Add this handle to the list.
-  handle->next = &handle_list;
-  handle->prev = handle_list.prev;
-  handle->prev->next = handle;
-  handle->next->prev = handle;
+    // Not in the list. Add this handle to the list.
+    handle->next = &handle_list;
+    handle->prev = handle_list.prev;
+    handle->prev->next = handle;
+    handle->next->prev = handle;
 
-  return 1;
+    return 1;
 }
 
 void device_poll_thread() {
-  adb_thread_setname("Device Poll");
-  D("Created device thread");
+    adb_thread_setname("Device Poll");
+    D("Created device thread");
 
-  while (true) {
-    find_devices();
-    std::this_thread::sleep_for(1s);
-  }
+    while (true) {
+        find_devices();
+        std::this_thread::sleep_for(1s);
+    }
 }
 
-static LRESULT CALLBACK _power_window_proc(HWND hwnd, UINT uMsg, WPARAM wParam,
-                                           LPARAM lParam) {
-  switch (uMsg) {
-  case WM_POWERBROADCAST:
-    switch (wParam) {
-    case PBT_APMRESUMEAUTOMATIC:
-      // Resuming from sleep or hibernation, so kick all existing USB devices
-      // and then allow the device_poll_thread to redetect USB devices from
-      // scratch. If we don't do this, existing USB devices will never respond
-      // to us because they'll be waiting for the connect/auth handshake.
-      D("Received (WM_POWERBROADCAST, PBT_APMRESUMEAUTOMATIC) notification, "
-        "so kicking all USB devices\n");
-      kick_devices();
-      return TRUE;
+static LRESULT CALLBACK _power_window_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+    switch (uMsg) {
+        case WM_POWERBROADCAST:
+            switch (wParam) {
+                case PBT_APMRESUMEAUTOMATIC:
+                    // Resuming from sleep or hibernation, so kick all existing USB devices
+                    // and then allow the device_poll_thread to redetect USB devices from
+                    // scratch. If we don't do this, existing USB devices will never respond
+                    // to us because they'll be waiting for the connect/auth handshake.
+                    D("Received (WM_POWERBROADCAST, PBT_APMRESUMEAUTOMATIC) notification, "
+                      "so kicking all USB devices\n");
+                    kick_devices();
+                    return TRUE;
+            }
     }
-  }
-  return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+    return DefWindowProcW(hwnd, uMsg, wParam, lParam);
 }
 
 static void _power_notification_thread() {
-  // This uses a thread with its own window message pump to get power
-  // notifications. If adb runs from a non-interactive service account, this
-  // might not work (not sure). If that happens to not work, we could use
-  // heavyweight WMI APIs to get power notifications. But for the common case
-  // of a developer's interactive session, a window message pump is more
-  // appropriate.
-  D("Created power notification thread");
-  adb_thread_setname("Power Notifier");
+    // This uses a thread with its own window message pump to get power
+    // notifications. If adb runs from a non-interactive service account, this
+    // might not work (not sure). If that happens to not work, we could use
+    // heavyweight WMI APIs to get power notifications. But for the common case
+    // of a developer's interactive session, a window message pump is more
+    // appropriate.
+    D("Created power notification thread");
+    adb_thread_setname("Power Notifier");
 
-  // Window class names are process specific.
-  static const WCHAR kPowerNotificationWindowClassName[] =
-    L"PowerNotificationWindow";
+    // Window class names are process specific.
+    static const WCHAR kPowerNotificationWindowClassName[] = L"PowerNotificationWindow";
 
-  // Get the HINSTANCE corresponding to the module that _power_window_proc
-  // is in (the main module).
-  const HINSTANCE instance = GetModuleHandleW(NULL);
-  if (!instance) {
-    // This is such a common API call that this should never fail.
-    fatal("GetModuleHandleW failed: %s",
-          android::base::SystemErrorCodeToString(GetLastError()).c_str());
-  }
+    // Get the HINSTANCE corresponding to the module that _power_window_proc
+    // is in (the main module).
+    const HINSTANCE instance = GetModuleHandleW(NULL);
+    if (!instance) {
+        // This is such a common API call that this should never fail.
+        fatal("GetModuleHandleW failed: %s",
+              android::base::SystemErrorCodeToString(GetLastError()).c_str());
+    }
 
-  WNDCLASSEXW wndclass;
-  memset(&wndclass, 0, sizeof(wndclass));
-  wndclass.cbSize = sizeof(wndclass);
-  wndclass.lpfnWndProc = _power_window_proc;
-  wndclass.hInstance = instance;
-  wndclass.lpszClassName = kPowerNotificationWindowClassName;
-  if (!RegisterClassExW(&wndclass)) {
-    fatal("RegisterClassExW failed: %s",
-          android::base::SystemErrorCodeToString(GetLastError()).c_str());
-  }
+    WNDCLASSEXW wndclass;
+    memset(&wndclass, 0, sizeof(wndclass));
+    wndclass.cbSize = sizeof(wndclass);
+    wndclass.lpfnWndProc = _power_window_proc;
+    wndclass.hInstance = instance;
+    wndclass.lpszClassName = kPowerNotificationWindowClassName;
+    if (!RegisterClassExW(&wndclass)) {
+        fatal("RegisterClassExW failed: %s",
+              android::base::SystemErrorCodeToString(GetLastError()).c_str());
+    }
 
-  if (!CreateWindowExW(WS_EX_NOACTIVATE, kPowerNotificationWindowClassName,
-                       L"ADB Power Notification Window", WS_POPUP, 0, 0, 0, 0,
-                       NULL, NULL, instance, NULL)) {
-    fatal("CreateWindowExW failed: %s",
-          android::base::SystemErrorCodeToString(GetLastError()).c_str());
-  }
+    if (!CreateWindowExW(WS_EX_NOACTIVATE, kPowerNotificationWindowClassName,
+                         L"ADB Power Notification Window", WS_POPUP, 0, 0, 0, 0, NULL, NULL,
+                         instance, NULL)) {
+        fatal("CreateWindowExW failed: %s",
+              android::base::SystemErrorCodeToString(GetLastError()).c_str());
+    }
 
-  MSG msg;
-  while (GetMessageW(&msg, NULL, 0, 0)) {
-    TranslateMessage(&msg);
-    DispatchMessageW(&msg);
-  }
+    MSG msg;
+    while (GetMessageW(&msg, NULL, 0, 0)) {
+        TranslateMessage(&msg);
+        DispatchMessageW(&msg);
+    }
 
-  // GetMessageW() will return false if a quit message is posted. We don't
-  // do that, but it might be possible for that to occur when logging off or
-  // shutting down. Not a big deal since the whole process will be going away
-  // soon anyway.
-  D("Power notification thread exiting");
+    // GetMessageW() will return false if a quit message is posted. We don't
+    // do that, but it might be possible for that to occur when logging off or
+    // shutting down. Not a big deal since the whole process will be going away
+    // soon anyway.
+    D("Power notification thread exiting");
 }
 
 void usb_init() {
-  std::thread(device_poll_thread).detach();
-  std::thread(_power_notification_thread).detach();
+    std::thread(device_poll_thread).detach();
+    std::thread(_power_notification_thread).detach();
 }
 
 void usb_cleanup() {}
 
 usb_handle* do_usb_open(const wchar_t* interface_name) {
-  unsigned long name_len = 0;
+    unsigned long name_len = 0;
 
-  // Allocate our handle
-  usb_handle* ret = (usb_handle*)calloc(1, sizeof(usb_handle));
-  if (NULL == ret) {
-    D("Could not allocate %u bytes for usb_handle: %s", sizeof(usb_handle),
-      strerror(errno));
-    goto fail;
-  }
+    // Allocate our handle
+    usb_handle* ret = (usb_handle*)calloc(1, sizeof(usb_handle));
+    if (NULL == ret) {
+        D("Could not allocate %u bytes for usb_handle: %s", sizeof(usb_handle), strerror(errno));
+        goto fail;
+    }
 
-  // Set linkers back to the handle
-  ret->next = ret;
-  ret->prev = ret;
+    // Set linkers back to the handle
+    ret->next = ret;
+    ret->prev = ret;
 
-  // Create interface.
-  ret->adb_interface = AdbCreateInterfaceByName(interface_name);
-  if (NULL == ret->adb_interface) {
-    D("AdbCreateInterfaceByName failed: %s",
-      android::base::SystemErrorCodeToString(GetLastError()).c_str());
-    goto fail;
-  }
+    // Create interface.
+    ret->adb_interface = AdbCreateInterfaceByName(interface_name);
+    if (NULL == ret->adb_interface) {
+        D("AdbCreateInterfaceByName failed: %s",
+          android::base::SystemErrorCodeToString(GetLastError()).c_str());
+        goto fail;
+    }
 
-  // Open read pipe (endpoint)
-  ret->adb_read_pipe =
-    AdbOpenDefaultBulkReadEndpoint(ret->adb_interface,
-                                   AdbOpenAccessTypeReadWrite,
-                                   AdbOpenSharingModeReadWrite);
-  if (NULL == ret->adb_read_pipe) {
-    D("AdbOpenDefaultBulkReadEndpoint failed: %s",
-      android::base::SystemErrorCodeToString(GetLastError()).c_str());
-    goto fail;
-  }
+    // Open read pipe (endpoint)
+    ret->adb_read_pipe = AdbOpenDefaultBulkReadEndpoint(
+        ret->adb_interface, AdbOpenAccessTypeReadWrite, AdbOpenSharingModeReadWrite);
+    if (NULL == ret->adb_read_pipe) {
+        D("AdbOpenDefaultBulkReadEndpoint failed: %s",
+          android::base::SystemErrorCodeToString(GetLastError()).c_str());
+        goto fail;
+    }
 
-  // Open write pipe (endpoint)
-  ret->adb_write_pipe =
-    AdbOpenDefaultBulkWriteEndpoint(ret->adb_interface,
-                                    AdbOpenAccessTypeReadWrite,
-                                    AdbOpenSharingModeReadWrite);
-  if (NULL == ret->adb_write_pipe) {
-    D("AdbOpenDefaultBulkWriteEndpoint failed: %s",
-      android::base::SystemErrorCodeToString(GetLastError()).c_str());
-    goto fail;
-  }
+    // Open write pipe (endpoint)
+    ret->adb_write_pipe = AdbOpenDefaultBulkWriteEndpoint(
+        ret->adb_interface, AdbOpenAccessTypeReadWrite, AdbOpenSharingModeReadWrite);
+    if (NULL == ret->adb_write_pipe) {
+        D("AdbOpenDefaultBulkWriteEndpoint failed: %s",
+          android::base::SystemErrorCodeToString(GetLastError()).c_str());
+        goto fail;
+    }
 
-  // Save interface name
-  // First get expected name length
-  AdbGetInterfaceName(ret->adb_interface,
-                      NULL,
-                      &name_len,
-                      false);
-  if (0 == name_len) {
-    D("AdbGetInterfaceName returned name length of zero: %s",
-      android::base::SystemErrorCodeToString(GetLastError()).c_str());
-    goto fail;
-  }
+    // Save interface name
+    // First get expected name length
+    AdbGetInterfaceName(ret->adb_interface, NULL, &name_len, false);
+    if (0 == name_len) {
+        D("AdbGetInterfaceName returned name length of zero: %s",
+          android::base::SystemErrorCodeToString(GetLastError()).c_str());
+        goto fail;
+    }
 
-  ret->interface_name = (wchar_t*)malloc(name_len * sizeof(ret->interface_name[0]));
-  if (NULL == ret->interface_name) {
-    D("Could not allocate %lu characters for interface_name: %s", name_len, strerror(errno));
-    goto fail;
-  }
+    ret->interface_name = (wchar_t*)malloc(name_len * sizeof(ret->interface_name[0]));
+    if (NULL == ret->interface_name) {
+        D("Could not allocate %lu characters for interface_name: %s", name_len, strerror(errno));
+        goto fail;
+    }
 
-  // Now save the name
-  if (!AdbGetInterfaceName(ret->adb_interface,
-                           ret->interface_name,
-                           &name_len,
-                           false)) {
-    D("AdbGetInterfaceName failed: %s",
-      android::base::SystemErrorCodeToString(GetLastError()).c_str());
-    goto fail;
-  }
+    // Now save the name
+    if (!AdbGetInterfaceName(ret->adb_interface, ret->interface_name, &name_len, false)) {
+        D("AdbGetInterfaceName failed: %s",
+          android::base::SystemErrorCodeToString(GetLastError()).c_str());
+        goto fail;
+    }
 
-  // We're done at this point
-  return ret;
+    // We're done at this point
+    return ret;
 
 fail:
-  if (NULL != ret) {
-    usb_cleanup_handle(ret);
-    free(ret);
-  }
+    if (NULL != ret) {
+        usb_cleanup_handle(ret);
+        free(ret);
+    }
 
-  return NULL;
+    return NULL;
 }
 
 int usb_write(usb_handle* handle, const void* data, int len) {
-  unsigned long time_out = 5000;
-  unsigned long written = 0;
-  int err = 0;
+    unsigned long time_out = 5000;
+    unsigned long written = 0;
+    int err = 0;
 
-  D("usb_write %d", len);
-  if (NULL == handle) {
-    D("usb_write was passed NULL handle");
-    err = EINVAL;
-    goto fail;
-  }
-
-  // Perform write
-  if (!AdbWriteEndpointSync(handle->adb_write_pipe,
-                            (void*)data,
-                            (unsigned long)len,
-                            &written,
-                            time_out)) {
-    D("AdbWriteEndpointSync failed: %s",
-      android::base::SystemErrorCodeToString(GetLastError()).c_str());
-    err = EIO;
-    goto fail;
-  }
-
-  // Make sure that we've written what we were asked to write
-  D("usb_write got: %ld, expected: %d", written, len);
-  if (written != (unsigned long)len) {
-    // If this occurs, this code should be changed to repeatedly call
-    // AdbWriteEndpointSync() until all bytes are written.
-    D("AdbWriteEndpointSync was supposed to write %d, but only wrote %ld",
-      len, written);
-    err = EIO;
-    goto fail;
-  }
-
-  if (handle->zero_mask && (len & handle->zero_mask) == 0) {
-    // Send a zero length packet
-    if (!AdbWriteEndpointSync(handle->adb_write_pipe,
-                              (void*)data,
-                              0,
-                              &written,
-                              time_out)) {
-      D("AdbWriteEndpointSync of zero length packet failed: %s",
-        android::base::SystemErrorCodeToString(GetLastError()).c_str());
-      err = EIO;
-      goto fail;
+    D("usb_write %d", len);
+    if (NULL == handle) {
+        D("usb_write was passed NULL handle");
+        err = EINVAL;
+        goto fail;
     }
-  }
 
-  return 0;
+    // Perform write
+    if (!AdbWriteEndpointSync(handle->adb_write_pipe, (void*)data, (unsigned long)len, &written,
+                              time_out)) {
+        D("AdbWriteEndpointSync failed: %s",
+          android::base::SystemErrorCodeToString(GetLastError()).c_str());
+        err = EIO;
+        goto fail;
+    }
+
+    // Make sure that we've written what we were asked to write
+    D("usb_write got: %ld, expected: %d", written, len);
+    if (written != (unsigned long)len) {
+        // If this occurs, this code should be changed to repeatedly call
+        // AdbWriteEndpointSync() until all bytes are written.
+        D("AdbWriteEndpointSync was supposed to write %d, but only wrote %ld", len, written);
+        err = EIO;
+        goto fail;
+    }
+
+    if (handle->zero_mask && (len & handle->zero_mask) == 0) {
+        // Send a zero length packet
+        if (!AdbWriteEndpointSync(handle->adb_write_pipe, (void*)data, 0, &written, time_out)) {
+            D("AdbWriteEndpointSync of zero length packet failed: %s",
+              android::base::SystemErrorCodeToString(GetLastError()).c_str());
+            err = EIO;
+            goto fail;
+        }
+    }
+
+    return 0;
 
 fail:
-  // Any failure should cause us to kick the device instead of leaving it a
-  // zombie state with potential to hang.
-  if (NULL != handle) {
-    D("Kicking device due to error in usb_write");
-    usb_kick(handle);
-  }
+    // Any failure should cause us to kick the device instead of leaving it a
+    // zombie state with potential to hang.
+    if (NULL != handle) {
+        D("Kicking device due to error in usb_write");
+        usb_kick(handle);
+    }
 
-  D("usb_write failed");
-  errno = err;
-  return -1;
+    D("usb_write failed");
+    errno = err;
+    return -1;
 }
 
-int usb_read(usb_handle *handle, void* data, int len) {
-  unsigned long time_out = 0;
-  unsigned long read = 0;
-  int err = 0;
-  int orig_len = len;
+int usb_read(usb_handle* handle, void* data, int len) {
+    unsigned long time_out = 0;
+    unsigned long read = 0;
+    int err = 0;
+    int orig_len = len;
 
-  D("usb_read %d", len);
-  if (NULL == handle) {
-    D("usb_read was passed NULL handle");
-    err = EINVAL;
-    goto fail;
-  }
-
-  while (len == orig_len) {
-    if (!AdbReadEndpointSync(handle->adb_read_pipe, data, len, &read, time_out)) {
-      D("AdbReadEndpointSync failed: %s",
-        android::base::SystemErrorCodeToString(GetLastError()).c_str());
-      err = EIO;
-      goto fail;
+    D("usb_read %d", len);
+    if (NULL == handle) {
+        D("usb_read was passed NULL handle");
+        err = EINVAL;
+        goto fail;
     }
-    D("usb_read got: %ld, expected: %d", read, len);
 
-    data = (char*)data + read;
-    len -= read;
-  }
+    while (len == orig_len) {
+        if (!AdbReadEndpointSync(handle->adb_read_pipe, data, len, &read, time_out)) {
+            D("AdbReadEndpointSync failed: %s",
+              android::base::SystemErrorCodeToString(GetLastError()).c_str());
+            err = EIO;
+            goto fail;
+        }
+        D("usb_read got: %ld, expected: %d", read, len);
 
-  return orig_len - len;
+        data = (char*)data + read;
+        len -= read;
+    }
+
+    return orig_len - len;
 
 fail:
-  // Any failure should cause us to kick the device instead of leaving it a
-  // zombie state with potential to hang.
-  if (NULL != handle) {
-    D("Kicking device due to error in usb_read");
-    usb_kick(handle);
-  }
+    // Any failure should cause us to kick the device instead of leaving it a
+    // zombie state with potential to hang.
+    if (NULL != handle) {
+        D("Kicking device due to error in usb_read");
+        usb_kick(handle);
+    }
 
-  D("usb_read failed");
-  errno = err;
-  return -1;
+    D("usb_read failed");
+    errno = err;
+    return -1;
 }
 
 // Wrapper around AdbCloseHandle() that logs diagnostics.
 static void _adb_close_handle(ADBAPIHANDLE adb_handle) {
-  if (!AdbCloseHandle(adb_handle)) {
-    D("AdbCloseHandle(%p) failed: %s", adb_handle,
-      android::base::SystemErrorCodeToString(GetLastError()).c_str());
-  }
+    if (!AdbCloseHandle(adb_handle)) {
+        D("AdbCloseHandle(%p) failed: %s", adb_handle,
+          android::base::SystemErrorCodeToString(GetLastError()).c_str());
+    }
 }
 
 void usb_cleanup_handle(usb_handle* handle) {
-  D("usb_cleanup_handle");
-  if (NULL != handle) {
-    if (NULL != handle->interface_name)
-      free(handle->interface_name);
-    // AdbCloseHandle(pipe) will break any threads out of pending IO calls and
-    // wait until the pipe no longer uses the interface. Then we can
-    // AdbCloseHandle() the interface.
-    if (NULL != handle->adb_write_pipe)
-      _adb_close_handle(handle->adb_write_pipe);
-    if (NULL != handle->adb_read_pipe)
-      _adb_close_handle(handle->adb_read_pipe);
-    if (NULL != handle->adb_interface)
-      _adb_close_handle(handle->adb_interface);
+    D("usb_cleanup_handle");
+    if (NULL != handle) {
+        if (NULL != handle->interface_name) free(handle->interface_name);
+        // AdbCloseHandle(pipe) will break any threads out of pending IO calls and
+        // wait until the pipe no longer uses the interface. Then we can
+        // AdbCloseHandle() the interface.
+        if (NULL != handle->adb_write_pipe) _adb_close_handle(handle->adb_write_pipe);
+        if (NULL != handle->adb_read_pipe) _adb_close_handle(handle->adb_read_pipe);
+        if (NULL != handle->adb_interface) _adb_close_handle(handle->adb_interface);
 
-    handle->interface_name = NULL;
-    handle->adb_write_pipe = NULL;
-    handle->adb_read_pipe = NULL;
-    handle->adb_interface = NULL;
-  }
+        handle->interface_name = NULL;
+        handle->adb_write_pipe = NULL;
+        handle->adb_read_pipe = NULL;
+        handle->adb_interface = NULL;
+    }
 }
 
 static void usb_kick_locked(usb_handle* handle) {
-  // The reason the lock must be acquired before calling this function is in
-  // case multiple threads are trying to kick the same device at the same time.
-  usb_cleanup_handle(handle);
+    // The reason the lock must be acquired before calling this function is in
+    // case multiple threads are trying to kick the same device at the same time.
+    usb_cleanup_handle(handle);
 }
 
 void usb_kick(usb_handle* handle) {
-  D("usb_kick");
-  if (NULL != handle) {
-    std::lock_guard<std::mutex> lock(usb_lock);
-    usb_kick_locked(handle);
-  } else {
-    errno = EINVAL;
-  }
+    D("usb_kick");
+    if (NULL != handle) {
+        std::lock_guard<std::mutex> lock(usb_lock);
+        usb_kick_locked(handle);
+    } else {
+        errno = EINVAL;
+    }
 }
 
 int usb_close(usb_handle* handle) {
-  D("usb_close");
+    D("usb_close");
 
-  if (NULL != handle) {
-    // Remove handle from the list
-    {
-      std::lock_guard<std::mutex> lock(usb_lock);
+    if (NULL != handle) {
+        // Remove handle from the list
+        {
+            std::lock_guard<std::mutex> lock(usb_lock);
 
-      if ((handle->next != handle) && (handle->prev != handle)) {
-        handle->next->prev = handle->prev;
-        handle->prev->next = handle->next;
-        handle->prev = handle;
-        handle->next = handle;
-      }
+            if ((handle->next != handle) && (handle->prev != handle)) {
+                handle->next->prev = handle->prev;
+                handle->prev->next = handle->next;
+                handle->prev = handle;
+                handle->next = handle;
+            }
+        }
+
+        // Cleanup handle
+        usb_cleanup_handle(handle);
+        free(handle);
     }
 
-    // Cleanup handle
-    usb_cleanup_handle(handle);
-    free(handle);
-  }
-
-  return 0;
+    return 0;
 }
 
 size_t usb_get_max_packet_size(usb_handle* handle) {
@@ -532,131 +506,124 @@
 }
 
 int recognized_device(usb_handle* handle) {
-  if (NULL == handle)
-    return 0;
+    if (NULL == handle) return 0;
 
-  // Check vendor and product id first
-  USB_DEVICE_DESCRIPTOR device_desc;
+    // Check vendor and product id first
+    USB_DEVICE_DESCRIPTOR device_desc;
 
-  if (!AdbGetUsbDeviceDescriptor(handle->adb_interface,
-                                 &device_desc)) {
-    D("AdbGetUsbDeviceDescriptor failed: %s",
-      android::base::SystemErrorCodeToString(GetLastError()).c_str());
-    return 0;
-  }
+    if (!AdbGetUsbDeviceDescriptor(handle->adb_interface, &device_desc)) {
+        D("AdbGetUsbDeviceDescriptor failed: %s",
+          android::base::SystemErrorCodeToString(GetLastError()).c_str());
+        return 0;
+    }
 
-  // Then check interface properties
-  USB_INTERFACE_DESCRIPTOR interf_desc;
+    // Then check interface properties
+    USB_INTERFACE_DESCRIPTOR interf_desc;
 
-  if (!AdbGetUsbInterfaceDescriptor(handle->adb_interface,
-                                    &interf_desc)) {
-    D("AdbGetUsbInterfaceDescriptor failed: %s",
-      android::base::SystemErrorCodeToString(GetLastError()).c_str());
-    return 0;
-  }
+    if (!AdbGetUsbInterfaceDescriptor(handle->adb_interface, &interf_desc)) {
+        D("AdbGetUsbInterfaceDescriptor failed: %s",
+          android::base::SystemErrorCodeToString(GetLastError()).c_str());
+        return 0;
+    }
 
-  // Must have two endpoints
-  if (2 != interf_desc.bNumEndpoints) {
-    return 0;
-  }
+    // Must have two endpoints
+    if (2 != interf_desc.bNumEndpoints) {
+        return 0;
+    }
 
-  if (is_adb_interface(interf_desc.bInterfaceClass, interf_desc.bInterfaceSubClass,
-                       interf_desc.bInterfaceProtocol)) {
-    if (interf_desc.bInterfaceProtocol == 0x01) {
-      AdbEndpointInformation endpoint_info;
-      // assuming zero is a valid bulk endpoint ID
-      if (AdbGetEndpointInformation(handle->adb_interface, 0, &endpoint_info)) {
+    if (!is_adb_interface(interf_desc.bInterfaceClass, interf_desc.bInterfaceSubClass,
+                          interf_desc.bInterfaceProtocol)) {
+        return 0;
+    }
+
+    AdbEndpointInformation endpoint_info;
+    // assuming zero is a valid bulk endpoint ID
+    if (AdbGetEndpointInformation(handle->adb_interface, 0, &endpoint_info)) {
         handle->max_packet_size = endpoint_info.max_packet_size;
         handle->zero_mask = endpoint_info.max_packet_size - 1;
         D("device zero_mask: 0x%x", handle->zero_mask);
-      } else {
+    } else {
         D("AdbGetEndpointInformation failed: %s",
           android::base::SystemErrorCodeToString(GetLastError()).c_str());
-      }
     }
 
     return 1;
-  }
-
-  return 0;
 }
 
 void find_devices() {
-  usb_handle* handle = NULL;
-  char entry_buffer[2048];
-  AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]);
-  unsigned long entry_buffer_size = sizeof(entry_buffer);
+    usb_handle* handle = NULL;
+    char entry_buffer[2048];
+    AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]);
+    unsigned long entry_buffer_size = sizeof(entry_buffer);
 
-  // Enumerate all present and active interfaces.
-  ADBAPIHANDLE enum_handle =
-    AdbEnumInterfaces(usb_class_id, true, true, true);
+    // Enumerate all present and active interfaces.
+    ADBAPIHANDLE enum_handle = AdbEnumInterfaces(usb_class_id, true, true, true);
 
-  if (NULL == enum_handle) {
-    D("AdbEnumInterfaces failed: %s",
-      android::base::SystemErrorCodeToString(GetLastError()).c_str());
-    return;
-  }
-
-  while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) {
-    // Lets see if we already have this device in the list
-    if (!known_device(next_interface->device_name)) {
-      // This seems to be a new device. Open it!
-      handle = do_usb_open(next_interface->device_name);
-      if (NULL != handle) {
-        // Lets see if this interface (device) belongs to us
-        if (recognized_device(handle)) {
-          D("adding a new device %ls", next_interface->device_name);
-
-          // We don't request a wchar_t string from AdbGetSerialNumber() because of a bug in
-          // adb_winusb_interface.cpp:CopyMemory(buffer, ser_num->bString, bytes_written) where the
-          // last parameter should be (str_len * sizeof(wchar_t)). The bug reads 2 bytes past the
-          // end of a stack buffer in the best case, and in the unlikely case of a long serial
-          // number, it will read 2 bytes past the end of a heap allocation. This doesn't affect the
-          // resulting string, but we should avoid the bad reads in the first place.
-          char serial_number[512];
-          unsigned long serial_number_len = sizeof(serial_number);
-          if (AdbGetSerialNumber(handle->adb_interface,
-                                serial_number,
-                                &serial_number_len,
-                                true)) {
-            // Lets make sure that we don't duplicate this device
-            if (register_new_device(handle)) {
-              register_usb_transport(handle, serial_number, NULL, 1);
-            } else {
-              D("register_new_device failed for %ls", next_interface->device_name);
-              usb_cleanup_handle(handle);
-              free(handle);
-            }
-          } else {
-            D("cannot get serial number: %s",
-              android::base::SystemErrorCodeToString(GetLastError()).c_str());
-            usb_cleanup_handle(handle);
-            free(handle);
-          }
-        } else {
-          usb_cleanup_handle(handle);
-          free(handle);
-        }
-      }
+    if (NULL == enum_handle) {
+        D("AdbEnumInterfaces failed: %s",
+          android::base::SystemErrorCodeToString(GetLastError()).c_str());
+        return;
     }
 
-    entry_buffer_size = sizeof(entry_buffer);
-  }
+    while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) {
+        // Lets see if we already have this device in the list
+        if (!known_device(next_interface->device_name)) {
+            // This seems to be a new device. Open it!
+            handle = do_usb_open(next_interface->device_name);
+            if (NULL != handle) {
+                // Lets see if this interface (device) belongs to us
+                if (recognized_device(handle)) {
+                    D("adding a new device %ls", next_interface->device_name);
 
-  if (GetLastError() != ERROR_NO_MORE_ITEMS) {
-    // Only ERROR_NO_MORE_ITEMS is expected at the end of enumeration.
-    D("AdbNextInterface failed: %s",
-      android::base::SystemErrorCodeToString(GetLastError()).c_str());
-  }
+                    // We don't request a wchar_t string from AdbGetSerialNumber() because of a bug
+                    // in adb_winusb_interface.cpp:CopyMemory(buffer, ser_num->bString,
+                    // bytes_written) where the last parameter should be (str_len *
+                    // sizeof(wchar_t)). The bug reads 2 bytes past the end of a stack buffer in the
+                    // best case, and in the unlikely case of a long serial number, it will read 2
+                    // bytes past the end of a heap allocation. This doesn't affect the resulting
+                    // string, but we should avoid the bad reads in the first place.
+                    char serial_number[512];
+                    unsigned long serial_number_len = sizeof(serial_number);
+                    if (AdbGetSerialNumber(handle->adb_interface, serial_number, &serial_number_len,
+                                           true)) {
+                        // Lets make sure that we don't duplicate this device
+                        if (register_new_device(handle)) {
+                            register_usb_transport(handle, serial_number, NULL, 1);
+                        } else {
+                            D("register_new_device failed for %ls", next_interface->device_name);
+                            usb_cleanup_handle(handle);
+                            free(handle);
+                        }
+                    } else {
+                        D("cannot get serial number: %s",
+                          android::base::SystemErrorCodeToString(GetLastError()).c_str());
+                        usb_cleanup_handle(handle);
+                        free(handle);
+                    }
+                } else {
+                    usb_cleanup_handle(handle);
+                    free(handle);
+                }
+            }
+        }
 
-  _adb_close_handle(enum_handle);
+        entry_buffer_size = sizeof(entry_buffer);
+    }
+
+    if (GetLastError() != ERROR_NO_MORE_ITEMS) {
+        // Only ERROR_NO_MORE_ITEMS is expected at the end of enumeration.
+        D("AdbNextInterface failed: %s",
+          android::base::SystemErrorCodeToString(GetLastError()).c_str());
+    }
+
+    _adb_close_handle(enum_handle);
 }
 
 static void kick_devices() {
-  // Need to acquire lock to safely walk the list which might be modified
-  // by another thread.
-  std::lock_guard<std::mutex> lock(usb_lock);
-  for (usb_handle* usb = handle_list.next; usb != &handle_list; usb = usb->next) {
-    usb_kick_locked(usb);
-  }
+    // Need to acquire lock to safely walk the list which might be modified
+    // by another thread.
+    std::lock_guard<std::mutex> lock(usb_lock);
+    for (usb_handle* usb = handle_list.next; usb != &handle_list; usb = usb->next) {
+        usb_kick_locked(usb);
+    }
 }
diff --git a/adb/framebuffer_service.cpp b/adb/framebuffer_service.cpp
index 7baad8b..6c3a225 100644
--- a/adb/framebuffer_service.cpp
+++ b/adb/framebuffer_service.cpp
@@ -37,10 +37,11 @@
 */
 /* This version number defines the format of the fbinfo struct.
    It must match versioning in ddms where this data is consumed. */
-#define DDMS_RAWIMAGE_VERSION 1
+#define DDMS_RAWIMAGE_VERSION 2
 struct fbinfo {
     unsigned int version;
     unsigned int bpp;
+    unsigned int colorSpace;
     unsigned int size;
     unsigned int width;
     unsigned int height;
@@ -60,7 +61,7 @@
     unsigned int i, bsize;
     char buf[640];
     int fd_screencap;
-    int w, h, f;
+    int w, h, f, c;
     int fds[2];
     pid_t pid;
 
@@ -82,12 +83,14 @@
     adb_close(fds[1]);
     fd_screencap = fds[0];
 
-    /* read w, h & format */
+    /* read w, h, format & color space */
     if(!ReadFdExactly(fd_screencap, &w, 4)) goto done;
     if(!ReadFdExactly(fd_screencap, &h, 4)) goto done;
     if(!ReadFdExactly(fd_screencap, &f, 4)) goto done;
+    if(!ReadFdExactly(fd_screencap, &c, 4)) goto done;
 
     fbinfo.version = DDMS_RAWIMAGE_VERSION;
+    fbinfo.colorSpace = c;
     /* see hardware/hardware.h */
     switch (f) {
         case 1: /* RGBA_8888 */
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 6cedd92..9cd378c 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -288,7 +288,7 @@
 #define open    adb_open
 #define read    adb_read
 #define write   adb_write
-#include <system/qemu_pipe.h>
+#include <qemu_pipe.h>
 #undef open
 #undef read
 #undef write
diff --git a/base/logging.cpp b/base/logging.cpp
index 6357b4b..75078e5 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -80,7 +80,9 @@
 #if defined(__BIONIC__)
   return gettid();
 #elif defined(__APPLE__)
-  return syscall(SYS_thread_selfid);
+  uint64_t tid;
+  pthread_threadid_np(NULL, &tid);
+  return tid;
 #elif defined(__linux__)
   return syscall(__NR_gettid);
 #elif defined(_WIN32)
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 074f838..4b94f9c 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -738,6 +738,12 @@
     return false;
 }
 
+static bool should_use_metadata_encryption(const struct fstab_rec* rec) {
+    if (!(rec->fs_mgr_flags & (MF_FILEENCRYPTION | MF_FORCEFDEORFBE))) return false;
+    if (!(rec->fs_mgr_flags & MF_KEYDIRECTORY)) return false;
+    return true;
+}
+
 // Check to see if a mountable volume has encryption requirements
 static int handle_encryptable(const struct fstab_rec* rec)
 {
@@ -750,8 +756,14 @@
                      << " - allow continue unencrypted";
             return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
         }
+    } else if (should_use_metadata_encryption(rec)) {
+        if (umount(rec->mount_point) == 0) {
+            return FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION;
+        } else {
+            PERROR << "Could not umount " << rec->mount_point << " - fail since can't encrypt";
+            return FS_MGR_MNTALL_FAIL;
+        }
     } else if (rec->fs_mgr_flags & (MF_FILEENCRYPTION | MF_FORCEFDEORFBE)) {
-        // Deal with file level encryption
         LINFO << rec->mount_point << " is file encrypted";
         return FS_MGR_MNTALL_DEV_FILE_ENCRYPTED;
     } else if (fs_mgr_is_encryptable(rec)) {
@@ -873,7 +885,6 @@
             continue;
         }
 
-        /* mount(2) returned an error, handle the encryptable/formattable case */
         bool wiped = partition_wiped(fstab->recs[top_idx].blk_device);
         bool crypt_footer = false;
         if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
@@ -913,6 +924,8 @@
                 continue;
             }
         }
+
+        /* mount(2) returned an error, handle the encryptable/formattable case */
         if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
             fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) {
             if (wiped) {
@@ -938,6 +951,9 @@
                 }
             }
             encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
+        } else if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
+                   should_use_metadata_encryption(&fstab->recs[attempted_idx])) {
+            encryptable = FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED;
         } else {
             // fs_options might be null so we cannot use PERROR << directly.
             // Use StringPrintf to output "(null)" instead.
@@ -1220,48 +1236,46 @@
     return ret;
 }
 
-/*
- * key_loc must be at least PROPERTY_VALUE_MAX bytes long
- *
- * real_blk_device must be at least PROPERTY_VALUE_MAX bytes long
- */
-int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_device, int size)
-{
-    int i = 0;
+struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab) {
+    int i;
 
     if (!fstab) {
-        return -1;
-    }
-    /* Initialize return values to null strings */
-    if (key_loc) {
-        *key_loc = '\0';
-    }
-    if (real_blk_device) {
-        *real_blk_device = '\0';
+        return NULL;
     }
 
     /* Look for the encryptable partition to find the data */
     for (i = 0; i < fstab->num_entries; i++) {
         /* Don't deal with vold managed enryptable partitions here */
-        if (fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) {
-            continue;
+        if (!(fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) &&
+            (fstab->recs[i].fs_mgr_flags &
+             (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE | MF_FILEENCRYPTION))) {
+            return &fstab->recs[i];
         }
-        if (!(fstab->recs[i].fs_mgr_flags
-              & (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE))) {
-            continue;
-        }
-
-        /* We found a match */
-        if (key_loc) {
-            strlcpy(key_loc, fstab->recs[i].key_loc, size);
-        }
-        if (real_blk_device) {
-            strlcpy(real_blk_device, fstab->recs[i].blk_device, size);
-        }
-        break;
     }
+    return NULL;
+}
 
-    return 0;
+/*
+ * key_loc must be at least PROPERTY_VALUE_MAX bytes long
+ *
+ * real_blk_device must be at least PROPERTY_VALUE_MAX bytes long
+ */
+void fs_mgr_get_crypt_info(struct fstab* fstab, char* key_loc, char* real_blk_device, size_t size) {
+    struct fstab_rec const* rec = fs_mgr_get_crypt_entry(fstab);
+    if (key_loc) {
+        if (rec) {
+            strlcpy(key_loc, rec->key_loc, size);
+        } else {
+            *key_loc = '\0';
+        }
+    }
+    if (real_blk_device) {
+        if (rec) {
+            strlcpy(real_blk_device, rec->blk_device, size);
+        } else {
+            *real_blk_device = '\0';
+        }
+    }
 }
 
 bool fs_mgr_load_verity_state(int* mode) {
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index bce245c..92c6ee8 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -33,6 +33,7 @@
 
 struct fs_mgr_flag_values {
     char *key_loc;
+    char* key_dir;
     char *verity_loc;
     long long part_length;
     char *label;
@@ -72,34 +73,35 @@
 };
 
 static struct flag_list fs_mgr_flags[] = {
-    { "wait",               MF_WAIT },
-    { "check",              MF_CHECK },
-    { "encryptable=",       MF_CRYPT },
-    { "forceencrypt=",      MF_FORCECRYPT },
-    { "fileencryption=",    MF_FILEENCRYPTION },
-    { "forcefdeorfbe=",     MF_FORCEFDEORFBE },
-    { "nonremovable",       MF_NONREMOVABLE },
-    { "voldmanaged=",       MF_VOLDMANAGED},
-    { "length=",            MF_LENGTH },
-    { "recoveryonly",       MF_RECOVERYONLY },
-    { "swapprio=",          MF_SWAPPRIO },
-    { "zramsize=",          MF_ZRAMSIZE },
-    { "max_comp_streams=",  MF_MAX_COMP_STREAMS },
-    { "verifyatboot",       MF_VERIFYATBOOT },
-    { "verify",             MF_VERIFY },
-    { "avb",                MF_AVB },
-    { "noemulatedsd",       MF_NOEMULATEDSD },
-    { "notrim",             MF_NOTRIM },
-    { "formattable",        MF_FORMATTABLE },
-    { "slotselect",         MF_SLOTSELECT },
-    { "nofail",             MF_NOFAIL },
-    { "latemount",          MF_LATEMOUNT },
-    { "reservedsize=",      MF_RESERVEDSIZE },
-    { "quota",              MF_QUOTA },
-    { "eraseblk=",          MF_ERASEBLKSIZE },
-    { "logicalblk=",        MF_LOGICALBLKSIZE },
-    { "defaults",           0 },
-    { 0,                    0 },
+    {"wait", MF_WAIT},
+    {"check", MF_CHECK},
+    {"encryptable=", MF_CRYPT},
+    {"forceencrypt=", MF_FORCECRYPT},
+    {"fileencryption=", MF_FILEENCRYPTION},
+    {"forcefdeorfbe=", MF_FORCEFDEORFBE},
+    {"keydirectory=", MF_KEYDIRECTORY},
+    {"nonremovable", MF_NONREMOVABLE},
+    {"voldmanaged=", MF_VOLDMANAGED},
+    {"length=", MF_LENGTH},
+    {"recoveryonly", MF_RECOVERYONLY},
+    {"swapprio=", MF_SWAPPRIO},
+    {"zramsize=", MF_ZRAMSIZE},
+    {"max_comp_streams=", MF_MAX_COMP_STREAMS},
+    {"verifyatboot", MF_VERIFYATBOOT},
+    {"verify", MF_VERIFY},
+    {"avb", MF_AVB},
+    {"noemulatedsd", MF_NOEMULATEDSD},
+    {"notrim", MF_NOTRIM},
+    {"formattable", MF_FORMATTABLE},
+    {"slotselect", MF_SLOTSELECT},
+    {"nofail", MF_NOFAIL},
+    {"latemount", MF_LATEMOUNT},
+    {"reservedsize=", MF_RESERVEDSIZE},
+    {"quota", MF_QUOTA},
+    {"eraseblk=", MF_ERASEBLKSIZE},
+    {"logicalblk=", MF_LOGICALBLKSIZE},
+    {"defaults", 0},
+    {0, 0},
 };
 
 #define EM_AES_256_XTS  1
@@ -268,6 +270,11 @@
                     } else {
                         flag_vals->file_names_mode = EM_AES_256_CTS;
                     }
+                } else if ((fl[i].flag == MF_KEYDIRECTORY) && flag_vals) {
+                    /* The metadata flag is followed by an = and the
+                     * directory for the keys.  Get it and return it.
+                     */
+                    flag_vals->key_dir = strdup(strchr(p, '=') + 1);
                 } else if ((fl[i].flag == MF_LENGTH) && flag_vals) {
                     /* The length flag is followed by an = and the
                      * size of the partition.  Get it and return it.
@@ -577,6 +584,7 @@
         fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
                                                     &flag_vals, NULL, 0);
         fstab->recs[cnt].key_loc = flag_vals.key_loc;
+        fstab->recs[cnt].key_dir = flag_vals.key_dir;
         fstab->recs[cnt].verity_loc = flag_vals.verity_loc;
         fstab->recs[cnt].length = flag_vals.part_length;
         fstab->recs[cnt].label = flag_vals.label;
@@ -736,6 +744,7 @@
         free(fstab->recs[i].fs_type);
         free(fstab->recs[i].fs_options);
         free(fstab->recs[i].key_loc);
+        free(fstab->recs[i].key_dir);
         free(fstab->recs[i].label);
     }
 
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index c3c87fa..724156d 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -109,6 +109,7 @@
 #define MF_ERASEBLKSIZE     0x800000
 #define MF_LOGICALBLKSIZE  0X1000000
 #define MF_AVB             0X2000000
+#define MF_KEYDIRECTORY 0X4000000
 
 #define DM_BUF_SIZE 4096
 
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 5c26c2e..653d8fa 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -51,6 +51,8 @@
 typedef void (*fs_mgr_verity_state_callback)(struct fstab_rec *fstab,
         const char *mount_point, int mode, int status);
 
+#define FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED 7
+#define FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION 6
 #define FS_MGR_MNTALL_DEV_FILE_ENCRYPTED 5
 #define FS_MGR_MNTALL_DEV_NEEDS_RECOVERY 4
 #define FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION 3
@@ -69,8 +71,8 @@
 int fs_mgr_do_mount_one(struct fstab_rec *rec);
 int fs_mgr_do_tmpfs_mount(const char *n_name);
 int fs_mgr_unmount_all(struct fstab *fstab);
-int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc,
-                          char *real_blk_device, int size);
+struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab);
+void fs_mgr_get_crypt_info(struct fstab* fstab, char* key_loc, char* real_blk_device, size_t size);
 bool fs_mgr_load_verity_state(int* mode);
 bool fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback);
 int fs_mgr_swapon_all(struct fstab *fstab);
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index bc2942d..94aacfd 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -43,6 +43,7 @@
     char* fs_options;
     int fs_mgr_flags;
     char* key_loc;
+    char* key_dir;
     char* verity_loc;
     long long length;
     char* label;
diff --git a/gatekeeperd/IGateKeeperService.cpp b/gatekeeperd/IGateKeeperService.cpp
index 95fbfd1..1c339f4 100644
--- a/gatekeeperd/IGateKeeperService.cpp
+++ b/gatekeeperd/IGateKeeperService.cpp
@@ -158,6 +158,12 @@
             reply->writeNoException();
             return NO_ERROR;
         }
+        case REPORT_DEVICE_SETUP_COMPLETE: {
+            CHECK_INTERFACE(IGateKeeperService, data, reply);
+            reportDeviceSetupComplete();
+            reply->writeNoException();
+            return NO_ERROR;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/gatekeeperd/IGateKeeperService.h b/gatekeeperd/IGateKeeperService.h
index f070486..2816efc 100644
--- a/gatekeeperd/IGateKeeperService.h
+++ b/gatekeeperd/IGateKeeperService.h
@@ -33,6 +33,7 @@
         VERIFY_CHALLENGE = IBinder::FIRST_CALL_TRANSACTION + 2,
         GET_SECURE_USER_ID = IBinder::FIRST_CALL_TRANSACTION + 3,
         CLEAR_SECURE_USER_ID = IBinder::FIRST_CALL_TRANSACTION + 4,
+        REPORT_DEVICE_SETUP_COMPLETE = IBinder::FIRST_CALL_TRANSACTION + 5,
     };
 
     enum {
@@ -95,6 +96,12 @@
      * Clears the secure user ID associated with the user.
      */
     virtual void clearSecureUserId(uint32_t uid) = 0;
+
+    /**
+     * Notifies gatekeeper that device setup has been completed and any potentially still existing
+     * state from before a factory reset can be cleaned up (if it has not been already).
+     */
+    virtual void reportDeviceSetupComplete() = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index 73dab9b..d581736 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -57,19 +57,13 @@
 class GateKeeperProxy : public BnGateKeeperService {
 public:
     GateKeeperProxy() {
+        clear_state_if_needed_done = false;
         hw_device = IGatekeeper::getService();
 
         if (hw_device == nullptr) {
             ALOGW("falling back to software GateKeeper");
             soft_device.reset(new SoftGateKeeperDevice());
         }
-
-        if (mark_cold_boot()) {
-            ALOGI("cold boot: clearing state");
-            if (hw_device != nullptr) {
-                hw_device->deleteAllUsers([](const GatekeeperResponse &){});
-            }
-        }
     }
 
     virtual ~GateKeeperProxy() {
@@ -87,6 +81,21 @@
         close(fd);
     }
 
+    void clear_state_if_needed() {
+        if (clear_state_if_needed_done) {
+            return;
+        }
+
+        if (mark_cold_boot()) {
+            ALOGI("cold boot: clearing state");
+            if (hw_device != nullptr) {
+                hw_device->deleteAllUsers([](const GatekeeperResponse &){});
+            }
+        }
+
+        clear_state_if_needed_done = true;
+    }
+
     bool mark_cold_boot() {
         const char *filename = ".coldboot";
         if (access(filename, F_OK) == -1) {
@@ -141,6 +150,10 @@
             return PERMISSION_DENIED;
         }
 
+        // Make sure to clear any state from before factory reset as soon as a credential is
+        // enrolled (which may happen during device setup).
+        clear_state_if_needed();
+
         // need a desired password to enroll
         if (desired_password_length == 0) return -EINVAL;
 
@@ -355,6 +368,18 @@
         }
     }
 
+    virtual void reportDeviceSetupComplete() {
+        IPCThreadState* ipc = IPCThreadState::self();
+        const int calling_pid = ipc->getCallingPid();
+        const int calling_uid = ipc->getCallingUid();
+        if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
+            ALOGE("%s: permission denied for [%d:%d]", __func__, calling_pid, calling_uid);
+            return;
+        }
+
+        clear_state_if_needed();
+    }
+
     virtual status_t dump(int fd, const Vector<String16> &) {
         IPCThreadState* ipc = IPCThreadState::self();
         const int pid = ipc->getCallingPid();
@@ -377,6 +402,8 @@
 private:
     sp<IGatekeeper> hw_device;
     std::unique_ptr<SoftGateKeeperDevice> soft_device;
+
+    bool clear_state_if_needed_done;
 };
 }// namespace android
 
diff --git a/healthd/Android.mk b/healthd/Android.mk
index 8b59964..6b14289 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -33,6 +33,30 @@
 
 include $(CLEAR_VARS)
 
+LOCAL_MODULE := libhealthd_draw
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+LOCAL_STATIC_LIBRARIES := \
+	libminui \
+	libbase
+LOCAL_SRC_FILES := healthd_draw.cpp
+
+ifneq ($(TARGET_HEALTHD_DRAW_SPLIT_SCREEN),)
+LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_SCREEN=$(TARGET_HEALTHD_DRAW_SPLIT_SCREEN)
+else
+LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_SCREEN=0
+endif
+
+ifneq ($(TARGET_HEALTHD_DRAW_SPLIT_OFFSET),)
+LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_OFFSET=$(TARGET_HEALTHD_DRAW_SPLIT_OFFSET)
+else
+LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_OFFSET=0
+endif
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
 LOCAL_CFLAGS := -Werror
 ifeq ($(strip $(BOARD_CHARGER_DISABLE_INIT_BLANK)),true)
 LOCAL_CFLAGS += -DCHARGER_DISABLE_INIT_BLANK
@@ -58,6 +82,7 @@
     libutils \
     libbase \
     libcutils \
+    libhealthd_draw \
     liblog \
     libm \
     libc \
@@ -101,6 +126,7 @@
 
 LOCAL_STATIC_LIBRARIES := \
     libhealthd_charger \
+    libhealthd_draw \
     libbatterymonitor \
     libbase \
     libutils \
diff --git a/healthd/healthd_draw.cpp b/healthd/healthd_draw.cpp
new file mode 100644
index 0000000..ea3d991
--- /dev/null
+++ b/healthd/healthd_draw.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2017 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 <android-base/stringprintf.h>
+#include <batteryservice/BatteryService.h>
+#include <cutils/klog.h>
+
+#include "healthd_draw.h"
+
+#define LOGE(x...) KLOG_ERROR("charger", x);
+#define LOGV(x...) KLOG_DEBUG("charger", x);
+
+HealthdDraw::HealthdDraw(animation* anim)
+  : kSplitScreen(HEALTHD_DRAW_SPLIT_SCREEN),
+    kSplitOffset(HEALTHD_DRAW_SPLIT_OFFSET) {
+  gr_init();
+  gr_font_size(gr_sys_font(), &char_width_, &char_height_);
+
+  screen_width_ = gr_fb_width() / (kSplitScreen ? 2 : 1);
+  screen_height_ = gr_fb_height();
+
+  int res;
+  if (!anim->text_clock.font_file.empty() &&
+      (res = gr_init_font(anim->text_clock.font_file.c_str(),
+                          &anim->text_clock.font)) < 0) {
+    LOGE("Could not load time font (%d)\n", res);
+  }
+  if (!anim->text_percent.font_file.empty() &&
+      (res = gr_init_font(anim->text_percent.font_file.c_str(),
+                          &anim->text_percent.font)) < 0) {
+    LOGE("Could not load percent font (%d)\n", res);
+  }
+}
+
+HealthdDraw::~HealthdDraw() {}
+
+void HealthdDraw::redraw_screen(const animation* batt_anim, GRSurface* surf_unknown) {
+  clear_screen();
+
+  /* try to display *something* */
+  if (batt_anim->cur_level < 0 || batt_anim->num_frames == 0)
+    draw_unknown(surf_unknown);
+  else
+    draw_battery(batt_anim);
+  gr_flip();
+}
+
+void HealthdDraw::blank_screen(bool blank) { gr_fb_blank(blank); }
+
+void HealthdDraw::clear_screen(void) {
+  gr_color(0, 0, 0, 255);
+  gr_clear();
+}
+
+int HealthdDraw::draw_surface_centered(GRSurface* surface) {
+  int w = gr_get_width(surface);
+  int h = gr_get_height(surface);
+  int x = (screen_width_ - w) / 2 + kSplitOffset;
+  int y = (screen_height_ - h) / 2;
+
+  LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y);
+  gr_blit(surface, 0, 0, w, h, x, y);
+  if (kSplitScreen) {
+    x += screen_width_ - 2 * kSplitOffset;
+    LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y);
+    gr_blit(surface, 0, 0, w, h, x, y);
+  }
+
+  return y + h;
+}
+
+int HealthdDraw::draw_text(const GRFont* font, int x, int y, const char* str) {
+  int str_len_px = gr_measure(font, str);
+
+  if (x < 0) x = (screen_width_ - str_len_px) / 2;
+  if (y < 0) y = (screen_height_ - char_height_) / 2;
+  gr_text(font, x + kSplitOffset, y, str, false /* bold */);
+  if (kSplitScreen)
+    gr_text(font, x - kSplitOffset + screen_width_, y, str, false /* bold */);
+
+  return y + char_height_;
+}
+
+void HealthdDraw::determine_xy(const animation::text_field& field,
+                               const int length, int* x, int* y) {
+  *x = field.pos_x;
+
+  int str_len_px = length * field.font->char_width;
+  if (field.pos_x == CENTER_VAL) {
+    *x = (screen_width_ - str_len_px) / 2;
+  } else if (field.pos_x >= 0) {
+    *x = field.pos_x;
+  } else {  // position from max edge
+    *x = screen_width_ + field.pos_x - str_len_px - kSplitOffset;
+  }
+
+  *y = field.pos_y;
+
+  if (field.pos_y == CENTER_VAL) {
+    *y = (screen_height_ - field.font->char_height) / 2;
+  } else if (field.pos_y >= 0) {
+    *y = field.pos_y;
+  } else {  // position from max edge
+    *y = screen_height_ + field.pos_y - field.font->char_height;
+  }
+}
+
+void HealthdDraw::draw_clock(const animation* anim) {
+  static constexpr char CLOCK_FORMAT[] = "%H:%M";
+  static constexpr int CLOCK_LENGTH = 6;
+
+  const animation::text_field& field = anim->text_clock;
+
+  if (field.font == nullptr || field.font->char_width == 0 ||
+      field.font->char_height == 0)
+    return;
+
+  time_t rawtime;
+  time(&rawtime);
+  tm* time_info = localtime(&rawtime);
+
+  char clock_str[CLOCK_LENGTH];
+  size_t length = strftime(clock_str, CLOCK_LENGTH, CLOCK_FORMAT, time_info);
+  if (length != CLOCK_LENGTH - 1) {
+    LOGE("Could not format time\n");
+    return;
+  }
+
+  int x, y;
+  determine_xy(field, length, &x, &y);
+
+  LOGV("drawing clock %s %d %d\n", clock_str, x, y);
+  gr_color(field.color_r, field.color_g, field.color_b, field.color_a);
+  draw_text(field.font, x, y, clock_str);
+}
+
+void HealthdDraw::draw_percent(const animation* anim) {
+  int cur_level = anim->cur_level;
+  if (anim->cur_status == BATTERY_STATUS_FULL) {
+    cur_level = 100;
+  }
+
+  if (cur_level <= 0) return;
+
+  const animation::text_field& field = anim->text_percent;
+  if (field.font == nullptr || field.font->char_width == 0 ||
+      field.font->char_height == 0) {
+    return;
+  }
+
+  std::string str = base::StringPrintf("%d%%", cur_level);
+
+  int x, y;
+  determine_xy(field, str.size(), &x, &y);
+
+  LOGV("drawing percent %s %d %d\n", str.c_str(), x, y);
+  gr_color(field.color_r, field.color_g, field.color_b, field.color_a);
+  draw_text(field.font, x, y, str.c_str());
+}
+
+void HealthdDraw::draw_battery(const animation* anim) {
+  const animation::frame& frame = anim->frames[anim->cur_frame];
+
+  if (anim->num_frames != 0) {
+    draw_surface_centered(frame.surface);
+    LOGV("drawing frame #%d min_cap=%d time=%d\n", anim->cur_frame,
+         frame.min_level, frame.disp_time);
+  }
+  draw_clock(anim);
+  draw_percent(anim);
+}
+
+void HealthdDraw::draw_unknown(GRSurface* surf_unknown) {
+  int y;
+  if (surf_unknown) {
+    draw_surface_centered(surf_unknown);
+  } else {
+    gr_color(0xa4, 0xc6, 0x39, 255);
+    y = draw_text(gr_sys_font(), -1, -1, "Charging!");
+    draw_text(gr_sys_font(), -1, y + 25, "?\?/100");
+  }
+}
diff --git a/healthd/healthd_draw.h b/healthd/healthd_draw.h
new file mode 100644
index 0000000..6a6ba76
--- /dev/null
+++ b/healthd/healthd_draw.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef HEALTHD_DRAW_H
+#define HEALTHD_DRAW_H
+
+#include <linux/input.h>
+#include <minui/minui.h>
+
+#include "animation.h"
+
+using namespace android;
+
+class HealthdDraw {
+ public:
+  // Configures font using given animation.
+  HealthdDraw(animation* anim);
+  virtual ~HealthdDraw();
+
+  // Redraws screen.
+  void redraw_screen(const animation* batt_anim, GRSurface* surf_unknown);
+
+  // Blanks screen if true, unblanks if false.
+  virtual void blank_screen(bool blank);
+
+ protected:
+  virtual void clear_screen();
+
+  // returns the last y-offset of where the surface ends.
+  virtual int draw_surface_centered(GRSurface* surface);
+  // Negative x or y coordinates center text.
+  virtual int draw_text(const GRFont* font, int x, int y, const char* str);
+
+  // Negative x or y coordinates position the text away from the opposite edge
+  // that positive ones do.
+  virtual void determine_xy(const animation::text_field& field,
+                            const int length, int* x, int* y);
+
+  // Draws battery animation, if it exists.
+  virtual void draw_battery(const animation* anim);
+  // Draws clock text, if animation contains text_field data.
+  virtual void draw_clock(const animation* anim);
+  // Draws battery percentage text if animation contains text_field data.
+  virtual void draw_percent(const animation* anim);
+  // Draws charger->surf_unknown or basic text.
+  virtual void draw_unknown(GRSurface* surf_unknown);
+
+  // Pixel sizes of characters for default font.
+  int char_width_;
+  int char_height_;
+
+  // Width and height of screen in pixels.
+  int screen_width_;
+  int screen_height_;
+
+  // Device screen is split vertically.
+  const bool kSplitScreen;
+  // Pixels to offset graphics towards center split.
+  const int kSplitOffset;
+};
+
+#endif  // HEALTHD_DRAW_H
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 032b214..4f77e7a 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2013 The Android Open Source Project
+ * Copyright (C) 2011-2017 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.
@@ -18,7 +18,6 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
-#include <linux/input.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -33,56 +32,54 @@
 
 #include <android-base/file.h>
 #include <android-base/macros.h>
-#include <android-base/stringprintf.h>
 
-#include <sys/socket.h>
 #include <linux/netlink.h>
+#include <sys/socket.h>
 
-#include <batteryservice/BatteryService.h>
 #include <cutils/klog.h>
 #include <cutils/misc.h>
-#include <cutils/uevent.h>
 #include <cutils/properties.h>
-#include <minui/minui.h>
+#include <cutils/uevent.h>
 #include <sys/reboot.h>
 
 #ifdef CHARGER_ENABLE_SUSPEND
 #include <suspend/autosuspend.h>
 #endif
 
-#include "animation.h"
 #include "AnimationParser.h"
+#include "healthd_draw.h"
 
 #include <healthd/healthd.h>
 
 using namespace android;
 
-char *locale;
+char* locale;
 
 #ifndef max
-#define max(a,b) ((a) > (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
 #endif
 
 #ifndef min
-#define min(a,b) ((a) < (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
 #endif
 
-#define ARRAY_SIZE(x)           (sizeof(x)/sizeof((x)[0]))
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 
-#define MSEC_PER_SEC            (1000LL)
-#define NSEC_PER_MSEC           (1000000LL)
+#define MSEC_PER_SEC (1000LL)
+#define NSEC_PER_MSEC (1000000LL)
 
-#define BATTERY_UNKNOWN_TIME    (2 * MSEC_PER_SEC)
-#define POWER_ON_KEY_TIME       (2 * MSEC_PER_SEC)
+#define BATTERY_UNKNOWN_TIME (2 * MSEC_PER_SEC)
+#define POWER_ON_KEY_TIME (2 * MSEC_PER_SEC)
 #define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC)
 
-#define LAST_KMSG_MAX_SZ        (32 * 1024)
+#define LAST_KMSG_MAX_SZ (32 * 1024)
 
-#define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0)
-#define LOGW(x...) do { KLOG_WARNING("charger", x); } while (0)
-#define LOGV(x...) do { KLOG_DEBUG("charger", x); } while (0)
+#define LOGE(x...) KLOG_ERROR("charger", x);
+#define LOGW(x...) KLOG_WARNING("charger", x);
+#define LOGV(x...) KLOG_DEBUG("charger", x);
 
-static constexpr const char* animation_desc_path = "/res/values/charger/animation.txt";
+static constexpr const char* animation_desc_path =
+    "/res/values/charger/animation.txt";
 
 struct key_state {
     bool pending;
@@ -97,34 +94,36 @@
     int64_t next_key_check;
     int64_t next_pwr_check;
 
-    struct key_state keys[KEY_MAX + 1];
+    key_state keys[KEY_MAX + 1];
 
-    struct animation *batt_anim;
+    animation* batt_anim;
     GRSurface* surf_unknown;
     int boot_min_cap;
 };
 
-static const struct animation BASE_ANIMATION = {
-    .text_clock = {
-        .pos_x = 0,
-        .pos_y = 0,
+static const animation BASE_ANIMATION = {
+    .text_clock =
+        {
+            .pos_x = 0,
+            .pos_y = 0,
 
-        .color_r = 255,
-        .color_g = 255,
-        .color_b = 255,
-        .color_a = 255,
+            .color_r = 255,
+            .color_g = 255,
+            .color_b = 255,
+            .color_a = 255,
 
-        .font = nullptr,
-    },
-    .text_percent = {
-        .pos_x = 0,
-        .pos_y = 0,
+            .font = nullptr,
+        },
+    .text_percent =
+        {
+            .pos_x = 0,
+            .pos_y = 0,
 
-        .color_r = 255,
-        .color_g = 255,
-        .color_b = 255,
-        .color_a = 255,
-    },
+            .color_r = 255,
+            .color_g = 255,
+            .color_b = 255,
+            .color_a = 255,
+        },
 
     .run = false,
 
@@ -140,8 +139,7 @@
     .cur_status = BATTERY_STATUS_UNKNOWN,
 };
 
-
-static struct animation::frame default_animation_frames[] = {
+static animation::frame default_animation_frames[] = {
     {
         .disp_time = 750,
         .min_level = 0,
@@ -180,35 +178,25 @@
     },
 };
 
-static struct animation battery_animation = BASE_ANIMATION;
+static animation battery_animation = BASE_ANIMATION;
 
-static struct charger charger_state;
-static struct healthd_config *healthd_config;
-static struct android::BatteryProperties *batt_prop;
-static int char_width;
-static int char_height;
-static bool minui_inited;
+static charger charger_state;
+static healthd_config* healthd_config;
+static android::BatteryProperties* batt_prop;
+static std::unique_ptr<HealthdDraw> healthd_draw;
 
 /* current time in milliseconds */
-static int64_t curr_time_ms(void)
-{
-    struct timespec tm;
+static int64_t curr_time_ms() {
+    timespec tm;
     clock_gettime(CLOCK_MONOTONIC, &tm);
     return tm.tv_sec * MSEC_PER_SEC + (tm.tv_nsec / NSEC_PER_MSEC);
 }
 
-static void clear_screen(void)
-{
-    gr_color(0, 0, 0, 255);
-    gr_clear();
-}
-
 #define MAX_KLOG_WRITE_BUF_SZ 256
 
-static void dump_last_kmsg(void)
-{
-    char *buf;
-    char *ptr;
+static void dump_last_kmsg(void) {
+    char* buf;
+    char* ptr;
     unsigned sz = 0;
     int len;
 
@@ -238,11 +226,10 @@
     while (len > 0) {
         int cnt = min(len, MAX_KLOG_WRITE_BUF_SZ);
         char yoink;
-        char *nl;
+        char* nl;
 
-        nl = (char *)memrchr(ptr, '\n', cnt - 1);
-        if (nl)
-            cnt = nl - ptr + 1;
+        nl = (char*)memrchr(ptr, '\n', cnt - 1);
+        if (nl) cnt = nl - ptr + 1;
 
         yoink = ptr[cnt];
         ptr[cnt] = '\0';
@@ -262,241 +249,59 @@
 }
 
 #ifdef CHARGER_ENABLE_SUSPEND
-static int request_suspend(bool enable)
-{
+static int request_suspend(bool enable) {
     if (enable)
         return autosuspend_enable();
     else
         return autosuspend_disable();
 }
 #else
-static int request_suspend(bool /*enable*/)
-{
+static int request_suspend(bool /*enable*/) {
     return 0;
 }
 #endif
 
-static int draw_text(const char *str, int x, int y)
-{
-    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(gr_sys_font(), x, y, str, 0);
-
-    return y + char_height;
-}
-
-static void android_green(void)
-{
-    gr_color(0xa4, 0xc6, 0x39, 255);
-}
-
-// Negative x or y coordinates position the text away from the opposite edge that positive ones do.
-void determine_xy(const animation::text_field& field, const int length, int* x, int* y)
-{
-    *x = field.pos_x;
-    *y = field.pos_y;
-
-    int str_len_px = length * field.font->char_width;
-    if (field.pos_x == CENTER_VAL) {
-        *x = (gr_fb_width() - str_len_px) / 2;
-    } else if (field.pos_x >= 0) {
-        *x = field.pos_x;
-    } else {  // position from max edge
-        *x = gr_fb_width() + field.pos_x - str_len_px;
-    }
-
-    if (field.pos_y == CENTER_VAL) {
-        *y = (gr_fb_height() - field.font->char_height) / 2;
-    } else if (field.pos_y >= 0) {
-        *y = field.pos_y;
-    } else {  // position from max edge
-        *y = gr_fb_height() + field.pos_y - field.font->char_height;
-    }
-}
-
-static void draw_clock(const animation& anim)
-{
-    static constexpr char CLOCK_FORMAT[] = "%H:%M";
-    static constexpr int CLOCK_LENGTH = 6;
-
-    const animation::text_field& field = anim.text_clock;
-
-    if (field.font == nullptr || field.font->char_width == 0 || field.font->char_height == 0) return;
-
-    time_t rawtime;
-    time(&rawtime);
-    struct tm* time_info = localtime(&rawtime);
-
-    char clock_str[CLOCK_LENGTH];
-    size_t length = strftime(clock_str, CLOCK_LENGTH, CLOCK_FORMAT, time_info);
-    if (length != CLOCK_LENGTH - 1) {
-        LOGE("Could not format time\n");
-        return;
-    }
-
-    int x, y;
-    determine_xy(field, length, &x, &y);
-
-    LOGV("drawing clock %s %d %d\n", clock_str, x, y);
-    gr_color(field.color_r, field.color_g, field.color_b, field.color_a);
-    gr_text(field.font, x, y, clock_str, false);
-}
-
-static void draw_percent(const animation& anim)
-{
-    int cur_level = anim.cur_level;
-    if (anim.cur_status == BATTERY_STATUS_FULL) {
-        cur_level = 100;
-    }
-
-    if (cur_level <= 0) return;
-
-    const animation::text_field& field = anim.text_percent;
-    if (field.font == nullptr || field.font->char_width == 0 || field.font->char_height == 0) {
-        return;
-    }
-
-    std::string str = base::StringPrintf("%d%%", cur_level);
-
-    int x, y;
-    determine_xy(field, str.size(), &x, &y);
-
-    LOGV("drawing percent %s %d %d\n", str.c_str(), x, y);
-    gr_color(field.color_r, field.color_g, field.color_b, field.color_a);
-    gr_text(field.font, x, y, str.c_str(), false);
-}
-
-/* returns the last y-offset of where the surface ends */
-static int draw_surface_centered(GRSurface* surface)
-{
-    int w;
-    int h;
-    int x;
-    int y;
-
-    w = gr_get_width(surface);
-    h = gr_get_height(surface);
-    x = (gr_fb_width() - w) / 2 ;
-    y = (gr_fb_height() - h) / 2 ;
-
-    LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y);
-    gr_blit(surface, 0, 0, w, h, x, y);
-    return y + h;
-}
-
-static void draw_unknown(struct charger *charger)
-{
-    int y;
-    if (charger->surf_unknown) {
-        draw_surface_centered(charger->surf_unknown);
-    } else {
-        android_green();
-        y = draw_text("Charging!", -1, -1);
-        draw_text("?\?/100", -1, y + 25);
-    }
-}
-
-static void draw_battery(const struct charger* charger)
-{
-    const struct animation& anim = *charger->batt_anim;
-    const struct animation::frame& frame = anim.frames[anim.cur_frame];
-
-    if (anim.num_frames != 0) {
-        draw_surface_centered(frame.surface);
-        LOGV("drawing frame #%d min_cap=%d time=%d\n",
-             anim.cur_frame, frame.min_level,
-             frame.disp_time);
-    }
-    draw_clock(anim);
-    draw_percent(anim);
-}
-
-static void redraw_screen(struct charger *charger)
-{
-    struct animation *batt_anim = charger->batt_anim;
-
-    clear_screen();
-
-    /* try to display *something* */
-    if (batt_anim->cur_level < 0 || batt_anim->num_frames == 0)
-        draw_unknown(charger);
-    else
-        draw_battery(charger);
-    gr_flip();
-}
-
-static void kick_animation(struct animation *anim)
-{
+static void kick_animation(animation* anim) {
     anim->run = true;
 }
 
-static void reset_animation(struct animation *anim)
-{
+static void reset_animation(animation* anim) {
     anim->cur_cycle = 0;
     anim->cur_frame = 0;
     anim->run = false;
 }
 
-static void init_status_display(struct animation* anim)
-{
-    int res;
-
-    if (!anim->text_clock.font_file.empty()) {
-        if ((res =
-                gr_init_font(anim->text_clock.font_file.c_str(), &anim->text_clock.font)) < 0) {
-            LOGE("Could not load time font (%d)\n", res);
-        }
-    }
-
-    if (!anim->text_percent.font_file.empty()) {
-        if ((res =
-                gr_init_font(anim->text_percent.font_file.c_str(), &anim->text_percent.font)) < 0) {
-            LOGE("Could not load percent font (%d)\n", res);
-        }
-    }
-}
-
-static void update_screen_state(struct charger *charger, int64_t now)
-{
-    struct animation *batt_anim = charger->batt_anim;
+static void update_screen_state(charger* charger, int64_t now) {
+    animation* batt_anim = charger->batt_anim;
     int disp_time;
 
     if (!batt_anim->run || now < charger->next_screen_transition) return;
 
-    if (!minui_inited) {
+    if (healthd_draw == nullptr) {
         if (healthd_config && healthd_config->screen_on) {
             if (!healthd_config->screen_on(batt_prop)) {
                 LOGV("[%" PRId64 "] leave screen off\n", now);
                 batt_anim->run = false;
                 charger->next_screen_transition = -1;
-                if (charger->charger_connected)
-                    request_suspend(true);
+                if (charger->charger_connected) request_suspend(true);
                 return;
             }
         }
 
-        gr_init();
-        gr_font_size(gr_sys_font(), &char_width, &char_height);
-        init_status_display(batt_anim);
+        healthd_draw.reset(new HealthdDraw(batt_anim));
 
 #ifndef CHARGER_DISABLE_INIT_BLANK
-        gr_fb_blank(true);
+        healthd_draw->blank_screen(true);
 #endif
-        minui_inited = true;
     }
 
     /* animation is over, blank screen and leave */
     if (batt_anim->num_cycles > 0 && batt_anim->cur_cycle == batt_anim->num_cycles) {
         reset_animation(batt_anim);
         charger->next_screen_transition = -1;
-        gr_fb_blank(true);
+        healthd_draw->blank_screen(true);
         LOGV("[%" PRId64 "] animation done\n", now);
-        if (charger->charger_connected)
-            request_suspend(true);
+        if (charger->charger_connected) request_suspend(true);
         return;
     }
 
@@ -504,7 +309,6 @@
 
     /* animation starting, set up the animation */
     if (batt_anim->cur_frame == 0) {
-
         LOGV("[%" PRId64 "] animation starting\n", now);
         if (batt_prop) {
             batt_anim->cur_level = batt_prop->batteryLevel;
@@ -521,17 +325,16 @@
 
                 // repeat the first frame first_frame_repeats times
                 disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time *
-                    batt_anim->first_frame_repeats;
+                            batt_anim->first_frame_repeats;
             }
         }
     }
 
     /* unblank the screen  on first cycle */
-    if (batt_anim->cur_cycle == 0)
-        gr_fb_blank(false);
+    if (batt_anim->cur_cycle == 0) healthd_draw->blank_screen(false);
 
     /* draw the new frame (@ cur_frame) */
-    redraw_screen(charger);
+    healthd_draw->redraw_screen(charger->batt_anim, charger->surf_unknown);
 
     /* if we don't have anim frames, we only have one image, so just bump
      * the cycle counter and exit
@@ -575,22 +378,18 @@
     }
 }
 
-static int set_key_callback(struct charger *charger, int code, int value)
-{
+static int set_key_callback(charger* charger, int code, int value) {
     int64_t now = curr_time_ms();
     int down = !!value;
 
-    if (code > KEY_MAX)
-        return -1;
+    if (code > KEY_MAX) return -1;
 
     /* ignore events that don't modify our state */
-    if (charger->keys[code].down == down)
-        return 0;
+    if (charger->keys[code].down == down) return 0;
 
     /* only record the down even timestamp, as the amount
      * of time the key spent not being pressed is not useful */
-    if (down)
-        charger->keys[code].timestamp = now;
+    if (down) charger->keys[code].timestamp = now;
     charger->keys[code].down = down;
     charger->keys[code].pending = true;
     if (down) {
@@ -599,34 +398,27 @@
         int64_t duration = now - charger->keys[code].timestamp;
         int64_t secs = duration / 1000;
         int64_t msecs = duration - secs * 1000;
-        LOGV("[%" PRId64 "] key[%d] up (was down for %" PRId64 ".%" PRId64 "sec)\n",
-             now, code, secs, msecs);
+        LOGV("[%" PRId64 "] key[%d] up (was down for %" PRId64 ".%" PRId64 "sec)\n", now, code,
+             secs, msecs);
     }
 
     return 0;
 }
 
-static void update_input_state(struct charger *charger,
-                               struct input_event *ev)
-{
-    if (ev->type != EV_KEY)
-        return;
+static void update_input_state(charger* charger, input_event* ev) {
+    if (ev->type != EV_KEY) return;
     set_key_callback(charger, ev->code, ev->value);
 }
 
-static void set_next_key_check(struct charger *charger,
-                               struct key_state *key,
-                               int64_t timeout)
-{
+static void set_next_key_check(charger* charger, key_state* key, int64_t timeout) {
     int64_t then = key->timestamp + timeout;
 
     if (charger->next_key_check == -1 || then < charger->next_key_check)
         charger->next_key_check = then;
 }
 
-static void process_key(struct charger *charger, int code, int64_t now)
-{
-    struct key_state *key = &charger->keys[code];
+static void process_key(charger* charger, int code, int64_t now) {
+    key_state* key = &charger->keys[code];
 
     if (code == KEY_POWER) {
         if (key->down) {
@@ -643,8 +435,10 @@
                         LOGW("[%" PRId64 "] rebooting\n", now);
                         reboot(RB_AUTOBOOT);
                     } else {
-                        LOGV("[%" PRId64 "] ignore power-button press, battery level "
-                            "less than minimum\n", now);
+                        LOGV("[%" PRId64
+                             "] ignore power-button press, battery level "
+                             "less than minimum\n",
+                             now);
                     }
                 }
             } else {
@@ -653,9 +447,9 @@
                  */
                 set_next_key_check(charger, key, POWER_ON_KEY_TIME);
 
-               /* Turn on the display and kick animation on power-key press
-                * rather than on key release
-                */
+                /* Turn on the display and kick animation on power-key press
+                 * rather than on key release
+                 */
                 kick_animation(charger->batt_anim);
                 request_suspend(false);
             }
@@ -670,21 +464,17 @@
     key->pending = false;
 }
 
-static void handle_input_state(struct charger *charger, int64_t now)
-{
+static void handle_input_state(charger* charger, int64_t now) {
     process_key(charger, KEY_POWER, now);
 
     if (charger->next_key_check != -1 && now > charger->next_key_check)
         charger->next_key_check = -1;
 }
 
-static void handle_power_supply_state(struct charger *charger, int64_t now)
-{
-    if (!charger->have_battery_state)
-        return;
+static void handle_power_supply_state(charger* charger, int64_t now) {
+    if (!charger->have_battery_state) return;
 
     if (!charger->charger_connected) {
-
         /* Last cycle would have stopped at the extreme top of battery-icon
          * Need to show the correct level corresponding to capacity.
          */
@@ -710,9 +500,8 @@
     }
 }
 
-void healthd_mode_charger_heartbeat()
-{
-    struct charger *charger = &charger_state;
+void healthd_mode_charger_heartbeat() {
+    charger* charger = &charger_state;
     int64_t now = curr_time_ms();
 
     handle_input_state(charger, now);
@@ -724,14 +513,11 @@
     update_screen_state(charger, now);
 }
 
-void healthd_mode_charger_battery_update(
-    struct android::BatteryProperties *props)
-{
-    struct charger *charger = &charger_state;
+void healthd_mode_charger_battery_update(android::BatteryProperties* props) {
+    charger* charger = &charger_state;
 
     charger->charger_connected =
-        props->chargerAcOnline || props->chargerUsbOnline ||
-        props->chargerWirelessOnline;
+        props->chargerAcOnline || props->chargerUsbOnline || props->chargerWirelessOnline;
 
     if (!charger->have_battery_state) {
         charger->have_battery_state = true;
@@ -742,19 +528,16 @@
     batt_prop = props;
 }
 
-int healthd_mode_charger_preparetowait(void)
-{
-    struct charger *charger = &charger_state;
+int healthd_mode_charger_preparetowait(void) {
+    charger* charger = &charger_state;
     int64_t now = curr_time_ms();
     int64_t next_event = INT64_MAX;
     int64_t timeout;
 
-    LOGV("[%" PRId64 "] next screen: %" PRId64 " next key: %" PRId64 " next pwr: %" PRId64 "\n", now,
-         charger->next_screen_transition, charger->next_key_check,
-         charger->next_pwr_check);
+    LOGV("[%" PRId64 "] next screen: %" PRId64 " next key: %" PRId64 " next pwr: %" PRId64 "\n",
+         now, charger->next_screen_transition, charger->next_key_check, charger->next_pwr_check);
 
-    if (charger->next_screen_transition != -1)
-        next_event = charger->next_screen_transition;
+    if (charger->next_screen_transition != -1) next_event = charger->next_screen_transition;
     if (charger->next_key_check != -1 && charger->next_key_check < next_event)
         next_event = charger->next_key_check;
     if (charger->next_pwr_check != -1 && charger->next_pwr_check < next_event)
@@ -765,32 +548,27 @@
     else
         timeout = -1;
 
-   return (int)timeout;
+    return (int)timeout;
 }
 
-static int input_callback(struct charger *charger, int fd, unsigned int epevents)
-{
-    struct input_event ev;
+static int input_callback(charger* charger, int fd, unsigned int epevents) {
+    input_event ev;
     int ret;
 
     ret = ev_get_input(fd, epevents, &ev);
-    if (ret)
-        return -1;
+    if (ret) return -1;
     update_input_state(charger, &ev);
     return 0;
 }
 
-static void charger_event_handler(uint32_t /*epevents*/)
-{
+static void charger_event_handler(uint32_t /*epevents*/) {
     int ret;
 
     ret = ev_wait(-1);
-    if (!ret)
-        ev_dispatch();
+    if (!ret) ev_dispatch();
 }
 
-animation* init_animation()
-{
+animation* init_animation() {
     bool parse_success;
 
     std::string content;
@@ -813,32 +591,29 @@
     }
 
     LOGV("Animation Description:\n");
-    LOGV("  animation: %d %d '%s' (%d)\n",
-        battery_animation.num_cycles, battery_animation.first_frame_repeats,
-        battery_animation.animation_file.c_str(), battery_animation.num_frames);
+    LOGV("  animation: %d %d '%s' (%d)\n", battery_animation.num_cycles,
+         battery_animation.first_frame_repeats, battery_animation.animation_file.c_str(),
+         battery_animation.num_frames);
     LOGV("  fail_file: '%s'\n", battery_animation.fail_file.c_str());
-    LOGV("  clock: %d %d %d %d %d %d '%s'\n",
-        battery_animation.text_clock.pos_x, battery_animation.text_clock.pos_y,
-        battery_animation.text_clock.color_r, battery_animation.text_clock.color_g,
-        battery_animation.text_clock.color_b, battery_animation.text_clock.color_a,
-        battery_animation.text_clock.font_file.c_str());
-    LOGV("  percent: %d %d %d %d %d %d '%s'\n",
-        battery_animation.text_percent.pos_x, battery_animation.text_percent.pos_y,
-        battery_animation.text_percent.color_r, battery_animation.text_percent.color_g,
-        battery_animation.text_percent.color_b, battery_animation.text_percent.color_a,
-        battery_animation.text_percent.font_file.c_str());
+    LOGV("  clock: %d %d %d %d %d %d '%s'\n", battery_animation.text_clock.pos_x,
+         battery_animation.text_clock.pos_y, battery_animation.text_clock.color_r,
+         battery_animation.text_clock.color_g, battery_animation.text_clock.color_b,
+         battery_animation.text_clock.color_a, battery_animation.text_clock.font_file.c_str());
+    LOGV("  percent: %d %d %d %d %d %d '%s'\n", battery_animation.text_percent.pos_x,
+         battery_animation.text_percent.pos_y, battery_animation.text_percent.color_r,
+         battery_animation.text_percent.color_g, battery_animation.text_percent.color_b,
+         battery_animation.text_percent.color_a, battery_animation.text_percent.font_file.c_str());
     for (int i = 0; i < battery_animation.num_frames; i++) {
         LOGV("  frame %.2d: %d %d %d\n", i, battery_animation.frames[i].disp_time,
-            battery_animation.frames[i].min_level, battery_animation.frames[i].max_level);
+             battery_animation.frames[i].min_level, battery_animation.frames[i].max_level);
     }
 
     return &battery_animation;
 }
 
-void healthd_mode_charger_init(struct healthd_config* config)
-{
+void healthd_mode_charger_init(struct healthd_config* config) {
     int ret;
-    struct charger *charger = &charger_state;
+    charger* charger = &charger_state;
     int i;
     int epollfd;
 
@@ -846,14 +621,13 @@
 
     LOGW("--------------- STARTING CHARGER MODE ---------------\n");
 
-    ret = ev_init(std::bind(&input_callback, charger, std::placeholders::_1,
-                            std::placeholders::_2));
+    ret = ev_init(std::bind(&input_callback, charger, std::placeholders::_1, std::placeholders::_2));
     if (!ret) {
         epollfd = ev_get_epollfd();
         healthd_register_event(epollfd, charger_event_handler, EVENT_WAKEUP_FD);
     }
 
-    struct animation* anim = init_animation();
+    animation* anim = init_animation();
     charger->batt_anim = anim;
 
     ret = res_create_display_surface(anim->fail_file.c_str(), &charger->surf_unknown);
@@ -870,15 +644,15 @@
     int scale_count;
     int scale_fps;  // Not in use (charger/battery_scale doesn't have FPS text
                     // chunk). We are using hard-coded frame.disp_time instead.
-    ret = res_create_multi_display_surface(anim->animation_file.c_str(),
-        &scale_count, &scale_fps, &scale_frames);
+    ret = res_create_multi_display_surface(anim->animation_file.c_str(), &scale_count, &scale_fps,
+                                           &scale_frames);
     if (ret < 0) {
         LOGE("Cannot load battery_scale image\n");
         anim->num_frames = 0;
         anim->num_cycles = 1;
     } else if (scale_count != anim->num_frames) {
-        LOGE("battery_scale image has unexpected frame count (%d, expected %d)\n",
-             scale_count, anim->num_frames);
+        LOGE("battery_scale image has unexpected frame count (%d, expected %d)\n", scale_count,
+             anim->num_frames);
         anim->num_frames = 0;
         anim->num_cycles = 1;
     } else {
@@ -886,8 +660,8 @@
             anim->frames[i].surface = scale_frames[i];
         }
     }
-    ev_sync_key_state(std::bind(&set_key_callback, charger, std::placeholders::_1,
-                                std::placeholders::_2));
+    ev_sync_key_state(
+        std::bind(&set_key_callback, charger, std::placeholders::_1, std::placeholders::_2));
 
     charger->next_screen_transition = -1;
     charger->next_key_check = -1;
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 20f1450..950a551 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -506,6 +506,25 @@
         // do anything different from the nonencrypted case.
         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
         return Success();
+    } else if (code == FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED) {
+        if (e4crypt_install_keyring()) {
+            return Error() << "e4crypt_install_keyring() failed";
+        }
+        property_set("ro.crypto.state", "encrypted");
+        property_set("ro.crypto.type", "file");
+
+        // defaultcrypto detects file/block encryption. init flow is same for each.
+        ActionManager::GetInstance().QueueEventTrigger("defaultcrypto");
+        return Success();
+    } else if (code == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
+        if (e4crypt_install_keyring()) {
+            return Error() << "e4crypt_install_keyring() failed";
+        }
+        property_set("ro.crypto.type", "file");
+
+        // encrypt detects file/block encryption. init flow is same for each.
+        ActionManager::GetInstance().QueueEventTrigger("encrypt");
+        return Success();
     } else if (code > 0) {
         Error() << "fs_mgr_mount_all() returned unexpected error " << code;
     }
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 1a44fe3..3cf3ab9 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -521,7 +521,7 @@
     }
 }
 
-static void load_properties_from_file(const char *, const char *);
+static bool load_properties_from_file(const char *, const char *);
 
 /*
  * Filter is used to decide which properties to load: NULL loads all keys,
@@ -585,17 +585,18 @@
 
 // Filter is used to decide which properties to load: NULL loads all keys,
 // "ro.foo.*" is a prefix match, and "ro.foo.bar" is an exact match.
-static void load_properties_from_file(const char* filename, const char* filter) {
+static bool load_properties_from_file(const char* filename, const char* filter) {
     Timer t;
     auto file_contents = ReadFile(filename);
     if (!file_contents) {
         PLOG(WARNING) << "Couldn't load property file '" << filename
                       << "': " << file_contents.error();
-        return;
+        return false;
     }
     file_contents->push_back('\n');
     load_properties(file_contents->data(), filter);
     LOG(VERBOSE) << "(Loading properties from " << filename << " took " << t << ".)";
+    return true;
 }
 
 // persist.sys.usb.config values can't be combined on build-time when property
@@ -615,7 +616,13 @@
 }
 
 void property_load_boot_defaults() {
-    load_properties_from_file("/default.prop", NULL);
+    if (!load_properties_from_file("/system/etc/prop.default", NULL)) {
+        // Try recovery path
+        if (!load_properties_from_file("/prop.default", NULL)) {
+            // Try legacy path
+            load_properties_from_file("/default.prop", NULL);
+        }
+    }
     load_properties_from_file("/odm/default.prop", NULL);
     load_properties_from_file("/vendor/default.prop", NULL);
 
diff --git a/init/reboot.cpp b/init/reboot.cpp
index b17dbaf..21086dc 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -280,16 +280,16 @@
         }
         bool unmount_done = true;
         if (emulated_devices.size() > 0) {
-            unmount_done = std::all_of(emulated_devices.begin(), emulated_devices.end(),
-                                       [](auto& entry) { return entry.Umount(false); });
+            for (auto& entry : emulated_devices) {
+                if (!entry.Umount(false)) unmount_done = false;
+            }
             if (unmount_done) {
                 sync();
             }
         }
-        unmount_done =
-            std::all_of(block_devices.begin(), block_devices.end(),
-                        [&timeout](auto& entry) { return entry.Umount(timeout == 0ms); }) &&
-            unmount_done;
+        for (auto& entry : block_devices) {
+            if (!entry.Umount(timeout == 0ms)) unmount_done = false;
+        }
         if (unmount_done) {
             return UMOUNT_STAT_SUCCESS;
         }
diff --git a/init/selinux.cpp b/init/selinux.cpp
index c4b01e6..331fad6 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -115,7 +115,7 @@
         // fork succeeded -- this is executing in the child process
 
         // Close the pipe FD not used by this process
-        TEMP_FAILURE_RETRY(close(pipe_fds[0]));
+        close(pipe_fds[0]);
 
         // Redirect stderr to the pipe FD provided by the parent
         if (TEMP_FAILURE_RETRY(dup2(pipe_fds[1], STDERR_FILENO)) == -1) {
@@ -123,7 +123,7 @@
             _exit(127);
             return false;
         }
-        TEMP_FAILURE_RETRY(close(pipe_fds[1]));
+        close(pipe_fds[1]);
 
         if (execv(filename, argv) == -1) {
             PLOG(ERROR) << "Failed to execve " << filename;
@@ -137,7 +137,7 @@
         // fork succeeded -- this is executing in the original/parent process
 
         // Close the pipe FD not used by this process
-        TEMP_FAILURE_RETRY(close(pipe_fds[1]));
+        close(pipe_fds[1]);
 
         // Log the redirected output of the child process.
         // It's unfortunate that there's no standard way to obtain an istream for a file descriptor.
@@ -148,7 +148,7 @@
         if (!android::base::ReadFdToString(child_out_fd, &child_output)) {
             PLOG(ERROR) << "Failed to capture full output of " << filename;
         }
-        TEMP_FAILURE_RETRY(close(child_out_fd));
+        close(child_out_fd);
         if (!child_output.empty()) {
             // Log captured output, line by line, because LOG expects to be invoked for each line
             std::istringstream in(child_output);
diff --git a/libappfuse/FuseBridgeLoop.cc b/libappfuse/FuseBridgeLoop.cc
index 3f47066..0792307 100644
--- a/libappfuse/FuseBridgeLoop.cc
+++ b/libappfuse/FuseBridgeLoop.cc
@@ -57,6 +57,12 @@
             return;
     }
 }
+
+void LogResponseError(const std::string& message, const FuseResponse& response) {
+    LOG(ERROR) << message << ": header.len=" << response.header.len
+               << " header.error=" << response.header.error
+               << " header.unique=" << response.header.unique;
+}
 }
 
 class FuseBridgeEntry {
@@ -135,6 +141,7 @@
         }
 
         if (!buffer_.response.Write(device_fd_)) {
+            LogResponseError("Failed to write a reply from proxy to device", buffer_.response);
             return FuseBridgeState::kClosing;
         }
 
@@ -200,6 +207,7 @@
         }
 
         if (!buffer_.response.Write(device_fd_)) {
+            LogResponseError("Failed to write a response to device", buffer_.response);
             return FuseBridgeState::kClosing;
         }
 
@@ -215,6 +223,11 @@
             case ResultOrAgain::kSuccess:
                 return FuseBridgeState::kWaitToReadEither;
             case ResultOrAgain::kFailure:
+                LOG(ERROR) << "Failed to write a request to proxy:"
+                           << " header.len=" << buffer_.request.header.len
+                           << " header.opcode=" << buffer_.request.header.opcode
+                           << " header.unique=" << buffer_.request.header.unique
+                           << " header.nodeid=" << buffer_.request.header.nodeid;
                 return FuseBridgeState::kClosing;
             case ResultOrAgain::kAgain:
                 return FuseBridgeState::kWaitToWriteProxy;
diff --git a/libappfuse/FuseBuffer.cc b/libappfuse/FuseBuffer.cc
index 653e96b..1eab46c 100644
--- a/libappfuse/FuseBuffer.cc
+++ b/libappfuse/FuseBuffer.cc
@@ -115,7 +115,10 @@
                 case EAGAIN:
                     return ResultOrAgain::kAgain;
                 default:
-                    PLOG(ERROR) << "Failed to write a FUSE message";
+                    PLOG(ERROR) << "Failed to write a FUSE message: "
+                                << "fd=" << fd << " "
+                                << "sockflag=" << sockflag << " "
+                                << "data=" << data;
                     return ResultOrAgain::kFailure;
             }
         }
@@ -248,7 +251,9 @@
 void FuseBuffer::HandleNotImpl() {
   LOG(VERBOSE) << "NOTIMPL op=" << request.header.opcode << " uniq="
       << request.header.unique << " nid=" << request.header.nodeid;
-  const uint64_t unique = request.header.unique;
+  // Add volatile as a workaround for compiler issue which removes the temporary
+  // variable.
+  const volatile uint64_t unique = request.header.unique;
   response.Reset(0, -ENOSYS, unique);
 }
 
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp
index 73bfdec..4c0c1a8 100644
--- a/libbacktrace/UnwindStack.cpp
+++ b/libbacktrace/UnwindStack.cpp
@@ -43,30 +43,8 @@
 #include "UnwindStack.h"
 #include "UnwindStackMap.h"
 
-static std::string GetFunctionName(BacktraceMap* back_map, uintptr_t pc, uintptr_t* offset) {
-  *offset = 0;
-  unwindstack::Maps* maps = reinterpret_cast<UnwindStackMap*>(back_map)->stack_maps();
-
-  // Get the map for this
-  unwindstack::MapInfo* map_info = maps->Find(pc);
-  if (map_info == nullptr || map_info->flags & PROT_DEVICE_MAP) {
-    return "";
-  }
-
-  UnwindStackMap* stack_map = reinterpret_cast<UnwindStackMap*>(back_map);
-  unwindstack::Elf* elf = map_info->GetElf(stack_map->process_memory(), true);
-
-  std::string name;
-  uint64_t func_offset;
-  if (!elf->GetFunctionName(elf->GetRelPc(pc, map_info), &name, &func_offset)) {
-    return "";
-  }
-  *offset = func_offset;
-  return name;
-}
-
-static bool Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
-                   std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames) {
+bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
+                       std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames) {
   static std::set<std::string> skip_names{"libunwindstack.so", "libbacktrace.so"};
   UnwindStackMap* stack_map = reinterpret_cast<UnwindStackMap*>(back_map);
   auto process_memory = stack_map->process_memory();
@@ -110,7 +88,7 @@
     : BacktraceCurrent(pid, tid, map) {}
 
 std::string UnwindStackCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
-  return ::GetFunctionName(GetMap(), pc, offset);
+  return GetMap()->GetFunctionName(pc, offset);
 }
 
 bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) {
@@ -126,14 +104,14 @@
   }
 
   error_ = BACKTRACE_UNWIND_NO_ERROR;
-  return ::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames);
+  return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames);
 }
 
 UnwindStackPtrace::UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map)
     : BacktracePtrace(pid, tid, map) {}
 
 std::string UnwindStackPtrace::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
-  return ::GetFunctionName(GetMap(), pc, offset);
+  return GetMap()->GetFunctionName(pc, offset);
 }
 
 bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, ucontext_t* context) {
@@ -146,5 +124,5 @@
   }
 
   error_ = BACKTRACE_UNWIND_NO_ERROR;
-  return ::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames);
+  return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames);
 }
diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp
index d4a2444..e7e5e4c 100644
--- a/libbacktrace/UnwindStackMap.cpp
+++ b/libbacktrace/UnwindStackMap.cpp
@@ -75,6 +75,31 @@
   map->load_bias = elf->GetLoadBias();
 }
 
+std::string UnwindStackMap::GetFunctionName(uintptr_t pc, uintptr_t* offset) {
+  *offset = 0;
+  unwindstack::Maps* maps = stack_maps();
+
+  // Get the map for this
+  unwindstack::MapInfo* map_info = maps->Find(pc);
+  if (map_info == nullptr || map_info->flags & PROT_DEVICE_MAP) {
+    return "";
+  }
+
+  unwindstack::Elf* elf = map_info->GetElf(process_memory(), true);
+
+  std::string name;
+  uint64_t func_offset;
+  if (!elf->GetFunctionName(elf->GetRelPc(pc, map_info), &name, &func_offset)) {
+    return "";
+  }
+  *offset = func_offset;
+  return name;
+}
+
+std::shared_ptr<unwindstack::Memory> UnwindStackMap::GetProcessMemory() {
+  return process_memory_;
+}
+
 //-------------------------------------------------------------------------
 // BacktraceMap create function.
 //-------------------------------------------------------------------------
diff --git a/libbacktrace/UnwindStackMap.h b/libbacktrace/UnwindStackMap.h
index b93b340..bc432e7 100644
--- a/libbacktrace/UnwindStackMap.h
+++ b/libbacktrace/UnwindStackMap.h
@@ -34,6 +34,9 @@
 
   void FillIn(uintptr_t addr, backtrace_map_t* map) override;
 
+  virtual std::string GetFunctionName(uintptr_t pc, uintptr_t* offset) override;
+  virtual std::shared_ptr<unwindstack::Memory> GetProcessMemory() override final;
+
   unwindstack::Maps* stack_maps() { return stack_maps_.get(); }
 
   const std::shared_ptr<unwindstack::Memory>& process_memory() { return process_memory_; }
diff --git a/libbacktrace/include/backtrace/Backtrace.h b/libbacktrace/include/backtrace/Backtrace.h
index 289fd0c..274c64b 100644
--- a/libbacktrace/include/backtrace/Backtrace.h
+++ b/libbacktrace/include/backtrace/Backtrace.h
@@ -77,6 +77,10 @@
   const uint8_t* data;
 };
 
+namespace unwindstack {
+class Regs;
+}
+
 class Backtrace {
 public:
   // Create the correct Backtrace object based on what is to be unwound.
@@ -106,6 +110,9 @@
   // Get the current stack trace and store in the backtrace_ structure.
   virtual bool Unwind(size_t num_ignore_frames, ucontext_t* context = NULL) = 0;
 
+  static bool Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
+                     std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames);
+
   // Get the function name and offset into the function given the pc.
   // If the string is empty, then no valid function name was found,
   // or the pc is not in any valid map.
diff --git a/libbacktrace/include/backtrace/BacktraceMap.h b/libbacktrace/include/backtrace/BacktraceMap.h
index 6cf8b3f..e176c78 100644
--- a/libbacktrace/include/backtrace/BacktraceMap.h
+++ b/libbacktrace/include/backtrace/BacktraceMap.h
@@ -46,6 +46,10 @@
   std::string name;
 };
 
+namespace unwindstack {
+class Memory;
+}
+
 class BacktraceMap {
 public:
   // If uncached is true, then parse the current process map as of the call.
@@ -62,6 +66,10 @@
   // Fill in the map data structure for the given address.
   virtual void FillIn(uintptr_t addr, backtrace_map_t* map);
 
+  // Only supported with the new unwinder.
+  virtual std::string GetFunctionName(uintptr_t /*pc*/, uintptr_t* /*offset*/) { return ""; }
+  virtual std::shared_ptr<unwindstack::Memory> GetProcessMemory() { return nullptr; }
+
   // The flags returned are the same flags as used by the mmap call.
   // The values are PROT_*.
   int GetFlags(uintptr_t pc) {
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index d54eeae..7603ffc 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -132,7 +132,8 @@
     { 00640, AID_ROOT,      AID_SHELL,     0, "data/nativetest64/tests.txt" },
     { 00750, AID_ROOT,      AID_SHELL,     0, "data/nativetest/*" },
     { 00750, AID_ROOT,      AID_SHELL,     0, "data/nativetest64/*" },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "default.prop" },
+    { 00600, AID_ROOT,      AID_ROOT,      0, "default.prop" }, // legacy
+    { 00600, AID_ROOT,      AID_ROOT,      0, "system/etc/prop.default" },
     { 00600, AID_ROOT,      AID_ROOT,      0, "odm/build.prop" },
     { 00600, AID_ROOT,      AID_ROOT,      0, "odm/default.prop" },
     { 00444, AID_ROOT,      AID_ROOT,      0, odm_conf_dir + 1 },
diff --git a/libcutils/include/cutils/native_handle.h b/libcutils/include/cutils/native_handle.h
index 55754b5..10f5bc0 100644
--- a/libcutils/include/cutils/native_handle.h
+++ b/libcutils/include/cutils/native_handle.h
@@ -43,6 +43,8 @@
 #endif
 } native_handle_t;
 
+typedef const native_handle_t* buffer_handle_t;
+
 /*
  * native_handle_close
  * 
diff --git a/libcutils/include/cutils/sched_policy.h b/libcutils/include/cutils/sched_policy.h
index cf8f5c3..4c1113b 100644
--- a/libcutils/include/cutils/sched_policy.h
+++ b/libcutils/include/cutils/sched_policy.h
@@ -47,6 +47,7 @@
     SP_AUDIO_APP  = 3,
     SP_AUDIO_SYS  = 4,
     SP_TOP_APP    = 5,
+    SP_RT_APP     = 6,
     SP_CNT,
     SP_MAX        = SP_CNT - 1,
     SP_SYSTEM_DEFAULT = SP_FOREGROUND,
diff --git a/libcutils/sched_policy.cpp b/libcutils/sched_policy.cpp
index f733e90..b00fa85 100644
--- a/libcutils/sched_policy.cpp
+++ b/libcutils/sched_policy.cpp
@@ -63,6 +63,7 @@
 static int bg_schedboost_fd = -1;
 static int fg_schedboost_fd = -1;
 static int ta_schedboost_fd = -1;
+static int rt_schedboost_fd = -1;
 
 /* Add tid to the scheduling group defined by the policy */
 static int add_tid_to_cgroup(int tid, int fd)
@@ -159,6 +160,8 @@
                 fg_schedboost_fd = open(filename, O_WRONLY | O_CLOEXEC);
                 filename = "/dev/stune/background/tasks";
                 bg_schedboost_fd = open(filename, O_WRONLY | O_CLOEXEC);
+                filename = "/dev/stune/rt/tasks";
+                rt_schedboost_fd = open(filename, O_WRONLY | O_CLOEXEC);
             }
         }
     }
@@ -394,6 +397,9 @@
     case SP_SYSTEM:
         SLOGD("/// tid %d (%s)", tid, thread_name);
         break;
+    case SP_RT_APP:
+	SLOGD("RT  tid %d (%s)", tid, thread_name);
+	break;
     default:
         SLOGD("??? tid %d (%s)", tid, thread_name);
         break;
@@ -414,6 +420,9 @@
         case SP_TOP_APP:
             boost_fd = ta_schedboost_fd;
             break;
+        case SP_RT_APP:
+	    boost_fd = rt_schedboost_fd;
+	    break;
         default:
             boost_fd = -1;
             break;
@@ -458,6 +467,7 @@
        [SP_AUDIO_APP]  = "aa",
        [SP_AUDIO_SYS]  = "as",
        [SP_TOP_APP]    = "ta",
+       [SP_RT_APP]    = "rt",
     };
     if ((policy < SP_CNT) && (strings[policy] != NULL))
         return strings[policy];
diff --git a/libcutils/threads.c b/libcutils/threads.c
index 036f8c5..4bae39e 100644
--- a/libcutils/threads.c
+++ b/libcutils/threads.c
@@ -35,7 +35,9 @@
 #ifndef __ANDROID__
 pid_t gettid() {
 #if defined(__APPLE__)
-  return syscall(SYS_thread_selfid);
+  uint64_t tid;
+  pthread_threadid_np(NULL, &tid);
+  return tid;
 #elif defined(__linux__)
   return syscall(__NR_gettid);
 #elif defined(_WIN32)
diff --git a/libsuspend/autosuspend_wakeup_count.c b/libsuspend/autosuspend_wakeup_count.c
index 4dedf7f..2da204a 100644
--- a/libsuspend/autosuspend_wakeup_count.c
+++ b/libsuspend/autosuspend_wakeup_count.c
@@ -24,6 +24,7 @@
 #include <stddef.h>
 #include <stdbool.h>
 #include <string.h>
+#include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -35,12 +36,24 @@
 #define SYS_POWER_STATE "/sys/power/state"
 #define SYS_POWER_WAKEUP_COUNT "/sys/power/wakeup_count"
 
+#define BASE_SLEEP_TIME 100000
+
 static int state_fd;
 static int wakeup_count_fd;
 static pthread_t suspend_thread;
 static sem_t suspend_lockout;
 static const char *sleep_state = "mem";
 static void (*wakeup_func)(bool success) = NULL;
+static int sleep_time = BASE_SLEEP_TIME;
+
+static void update_sleep_time(bool success) {
+    if (success) {
+        sleep_time = BASE_SLEEP_TIME;
+        return;
+    }
+    // double sleep time after each failure up to one minute
+    sleep_time = MIN(sleep_time * 2, 60000000);
+}
 
 static void *suspend_thread_func(void *arg __attribute__((unused)))
 {
@@ -48,10 +61,12 @@
     char wakeup_count[20];
     int wakeup_count_len;
     int ret;
-    bool success;
+    bool success = true;
 
     while (1) {
-        usleep(100000);
+        update_sleep_time(success);
+        usleep(sleep_time);
+        success = false;
         ALOGV("%s: read wakeup_count\n", __func__);
         lseek(wakeup_count_fd, 0, SEEK_SET);
         wakeup_count_len = TEMP_FAILURE_RETRY(read(wakeup_count_fd, wakeup_count,
@@ -75,7 +90,6 @@
             continue;
         }
 
-        success = true;
         ALOGV("%s: write %*s to wakeup_count\n", __func__, wakeup_count_len, wakeup_count);
         ret = TEMP_FAILURE_RETRY(write(wakeup_count_fd, wakeup_count, wakeup_count_len));
         if (ret < 0) {
@@ -84,8 +98,8 @@
         } else {
             ALOGV("%s: write %s to %s\n", __func__, sleep_state, SYS_POWER_STATE);
             ret = TEMP_FAILURE_RETRY(write(state_fd, sleep_state, strlen(sleep_state)));
-            if (ret < 0) {
-                success = false;
+            if (ret >= 0) {
+                success = true;
             }
             void (*func)(bool success) = wakeup_func;
             if (func != NULL) {
diff --git a/libsystem/include/system/qemu_pipe.h b/libsystem/include/system/qemu_pipe.h
deleted file mode 100644
index af25079..0000000
--- a/libsystem/include/system/qemu_pipe.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-#ifndef ANDROID_INCLUDE_SYSTEM_QEMU_PIPE_H
-#define ANDROID_INCLUDE_SYSTEM_QEMU_PIPE_H
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-
-// Define QEMU_PIPE_DEBUG if you want to print error messages when an error
-// occurs during pipe operations. The macro should simply take a printf-style
-// formatting string followed by optional arguments.
-#ifndef QEMU_PIPE_DEBUG
-#  define  QEMU_PIPE_DEBUG(...)   (void)0
-#endif
-
-// Try to open a new Qemu fast-pipe. This function returns a file descriptor
-// that can be used to communicate with a named service managed by the
-// emulator.
-//
-// This file descriptor can be used as a standard pipe/socket descriptor.
-//
-// 'pipeName' is the name of the emulator service you want to connect to,
-// and must begin with 'pipe:' (e.g. 'pipe:camera' or 'pipe:opengles').
-//
-// On success, return a valid file descriptor, or -1/errno on failure. E.g.:
-//
-// EINVAL  -> unknown/unsupported pipeName
-// ENOSYS  -> fast pipes not available in this system.
-//
-// ENOSYS should never happen, except if you're trying to run within a
-// misconfigured emulator.
-//
-// You should be able to open several pipes to the same pipe service,
-// except for a few special cases (e.g. GSM modem), where EBUSY will be
-// returned if more than one client tries to connect to it.
-static __inline__ int qemu_pipe_open(const char* pipeName) {
-    // Sanity check.
-    if (!pipeName || memcmp(pipeName, "pipe:", 5) != 0) {
-        errno = EINVAL;
-        return -1;
-    }
-
-    int fd = TEMP_FAILURE_RETRY(open("/dev/qemu_pipe", O_RDWR));
-    if (fd < 0) {
-        QEMU_PIPE_DEBUG("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__,
-                        strerror(errno));
-        return -1;
-    }
-
-    // Write the pipe name, *including* the trailing zero which is necessary.
-    size_t pipeNameLen = strlen(pipeName);
-    ssize_t ret = TEMP_FAILURE_RETRY(write(fd, pipeName, pipeNameLen + 1U));
-    if (ret != (ssize_t)pipeNameLen + 1) {
-        QEMU_PIPE_DEBUG("%s: Could not connect to %s pipe service: %s",
-                        __FUNCTION__, pipeName, strerror(errno));
-        if (ret == 0) {
-            errno = ECONNRESET;
-        } else if (ret > 0) {
-            errno = EINVAL;
-        }
-        return -1;
-    }
-    return fd;
-}
-
-// Send a framed message |buff| of |len| bytes through the |fd| descriptor.
-// This really adds a 4-hexchar prefix describing the payload size.
-// Returns 0 on success, and -1 on error.
-static int __inline__ qemu_pipe_frame_send(int fd,
-                                           const void* buff,
-                                           size_t len) {
-    char header[5];
-    snprintf(header, sizeof(header), "%04zx", len);
-    ssize_t ret = TEMP_FAILURE_RETRY(write(fd, header, 4));
-    if (ret != 4) {
-        QEMU_PIPE_DEBUG("Can't write qemud frame header: %s", strerror(errno));
-        return -1;
-    }
-    ret = TEMP_FAILURE_RETRY(write(fd, buff, len));
-    if (ret != (ssize_t)len) {
-        QEMU_PIPE_DEBUG("Can't write qemud frame payload: %s", strerror(errno));
-        return -1;
-    }
-    return 0;
-}
-
-// Read a frame message from |fd|, and store it into |buff| of |len| bytes.
-// If the framed message is larger than |len|, then this returns -1 and the
-// content is lost. Otherwise, this returns the size of the message. NOTE:
-// empty messages are possible in a framed wire protocol and do not mean
-// end-of-stream.
-static int __inline__ qemu_pipe_frame_recv(int fd, void* buff, size_t len) {
-    char header[5];
-    ssize_t ret = TEMP_FAILURE_RETRY(read(fd, header, 4));
-    if (ret != 4) {
-        QEMU_PIPE_DEBUG("Can't read qemud frame header: %s", strerror(errno));
-        return -1;
-    }
-    header[4] = '\0';
-    size_t size;
-    if (sscanf(header, "%04zx", &size) != 1) {
-        QEMU_PIPE_DEBUG("Malformed qemud frame header: [%.*s]", 4, header);
-        return -1;
-    }
-    if (size > len) {
-        QEMU_PIPE_DEBUG("Oversized qemud frame (% bytes, expected <= %)", size,
-                        len);
-        return -1;
-    }
-    ret = TEMP_FAILURE_RETRY(read(fd, buff, size));
-    if (ret != (ssize_t)size) {
-        QEMU_PIPE_DEBUG("Could not read qemud frame payload: %s",
-                        strerror(errno));
-        return -1;
-    }
-    return size;
-}
-
-#endif /* ANDROID_INCLUDE_HARDWARE_QEMUD_PIPE_H */
diff --git a/libsystem/include/system/window-deprecated.h b/libsystem/include/system/window-deprecated.h
deleted file mode 100644
index e836aea..0000000
--- a/libsystem/include/system/window-deprecated.h
+++ /dev/null
@@ -1,1114 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-/**************************************************************************************************
- **************************************************************************************************
- ****                                                                                          ****
- ****  DEPRECATED                                                                              ****
- ****                                                                                          ****
- ****  THIS FILE EXISTS ONLY FOR BACKWARD SOURCE COMPATIBILITY.                                ****
- ****                                                                                          ****
- ****  DO NOT ADD TO THIS FILE.                                                                ****
- ****                                                                                          ****
- ****  Driver implementors (vendors) should use vndk/window.h                                  ****
- ****  (frameworks/native/libs/nativewindow/include/vndk/window.h)                             ****
- ****                                                                                          ****
- ****  Internal definition can be found here:                                                  ****
- ****  frameworks/native/libs/nativewindow/include/system/window.h                             ****
- ****                                                                                          ****
- **************************************************************************************************
- **************************************************************************************************/
-
-#pragma once
-
-#include <cutils/native_handle.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/cdefs.h>
-#include <system/graphics.h>
-#include <unistd.h>
-#include <stdbool.h>
-
-#ifndef __UNUSED
-#define __UNUSED __attribute__((__unused__))
-#endif
-#ifndef __deprecated
-#define __deprecated __attribute__((__deprecated__))
-#endif
-
-__BEGIN_DECLS
-
-/*****************************************************************************/
-
-#ifdef __cplusplus
-#define ANDROID_NATIVE_UNSIGNED_CAST(x) static_cast<unsigned int>(x)
-#else
-#define ANDROID_NATIVE_UNSIGNED_CAST(x) ((unsigned int)(x))
-#endif
-
-#define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d) \
-    ((ANDROID_NATIVE_UNSIGNED_CAST(a) << 24) | \
-     (ANDROID_NATIVE_UNSIGNED_CAST(b) << 16) | \
-     (ANDROID_NATIVE_UNSIGNED_CAST(c) << 8) | \
-     (ANDROID_NATIVE_UNSIGNED_CAST(d)))
-
-#define ANDROID_NATIVE_WINDOW_MAGIC \
-    ANDROID_NATIVE_MAKE_CONSTANT('_','w','n','d')
-
-#define ANDROID_NATIVE_BUFFER_MAGIC \
-    ANDROID_NATIVE_MAKE_CONSTANT('_','b','f','r')
-
-// ---------------------------------------------------------------------------
-
-// This #define may be used to conditionally compile device-specific code to
-// support either the prior ANativeWindow interface, which did not pass libsync
-// fences around, or the new interface that does.  This #define is only present
-// when the ANativeWindow interface does include libsync support.
-#define ANDROID_NATIVE_WINDOW_HAS_SYNC 1
-
-// ---------------------------------------------------------------------------
-
-typedef const native_handle_t* buffer_handle_t;
-
-// ---------------------------------------------------------------------------
-
-typedef struct android_native_rect_t
-{
-    int32_t left;
-    int32_t top;
-    int32_t right;
-    int32_t bottom;
-} android_native_rect_t;
-
-// ---------------------------------------------------------------------------
-
-typedef struct android_native_base_t
-{
-    /* a magic value defined by the actual EGL native type */
-    int magic;
-
-    /* the sizeof() of the actual EGL native type */
-    int version;
-
-    void* reserved[4];
-
-    /* reference-counting interface */
-    void (*incRef)(struct android_native_base_t* base);
-    void (*decRef)(struct android_native_base_t* base);
-} android_native_base_t;
-
-typedef struct ANativeWindowBuffer
-{
-#ifdef __cplusplus
-    ANativeWindowBuffer() {
-        common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
-        common.version = sizeof(ANativeWindowBuffer);
-        memset(common.reserved, 0, sizeof(common.reserved));
-    }
-
-    // Implement the methods that sp<ANativeWindowBuffer> expects so that it
-    // can be used to automatically refcount ANativeWindowBuffer's.
-    void incStrong(const void* /*id*/) const {
-        common.incRef(const_cast<android_native_base_t*>(&common));
-    }
-    void decStrong(const void* /*id*/) const {
-        common.decRef(const_cast<android_native_base_t*>(&common));
-    }
-#endif
-
-    struct android_native_base_t common;
-
-    int width;
-    int height;
-    int stride;
-    int format;
-    int usage;
-    uintptr_t layerCount;
-
-    void* reserved[1];
-
-    buffer_handle_t handle;
-
-    void* reserved_proc[8];
-} ANativeWindowBuffer_t;
-
-// Old typedef for backwards compatibility.
-typedef ANativeWindowBuffer_t android_native_buffer_t;
-
-// ---------------------------------------------------------------------------
-
-/* attributes queriable with query() */
-enum {
-    NATIVE_WINDOW_WIDTH     = 0,
-    NATIVE_WINDOW_HEIGHT    = 1,
-    NATIVE_WINDOW_FORMAT    = 2,
-
-    /* The minimum number of buffers that must remain un-dequeued after a buffer
-     * has been queued.  This value applies only if set_buffer_count was used to
-     * override the number of buffers and if a buffer has since been queued.
-     * Users of the set_buffer_count ANativeWindow method should query this
-     * value before calling set_buffer_count.  If it is necessary to have N
-     * buffers simultaneously dequeued as part of the steady-state operation,
-     * and this query returns M then N+M buffers should be requested via
-     * native_window_set_buffer_count.
-     *
-     * Note that this value does NOT apply until a single buffer has been
-     * queued.  In particular this means that it is possible to:
-     *
-     * 1. Query M = min undequeued buffers
-     * 2. Set the buffer count to N + M
-     * 3. Dequeue all N + M buffers
-     * 4. Cancel M buffers
-     * 5. Queue, dequeue, queue, dequeue, ad infinitum
-     */
-    NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS = 3,
-
-    /* Check whether queueBuffer operations on the ANativeWindow send the buffer
-     * to the window compositor.  The query sets the returned 'value' argument
-     * to 1 if the ANativeWindow DOES send queued buffers directly to the window
-     * compositor and 0 if the buffers do not go directly to the window
-     * compositor.
-     *
-     * This can be used to determine whether protected buffer content should be
-     * sent to the ANativeWindow.  Note, however, that a result of 1 does NOT
-     * indicate that queued buffers will be protected from applications or users
-     * capturing their contents.  If that behavior is desired then some other
-     * mechanism (e.g. the GRALLOC_USAGE_PROTECTED flag) should be used in
-     * conjunction with this query.
-     */
-    NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER = 4,
-
-    /* Get the concrete type of a ANativeWindow.  See below for the list of
-     * possible return values.
-     *
-     * This query should not be used outside the Android framework and will
-     * likely be removed in the near future.
-     */
-    NATIVE_WINDOW_CONCRETE_TYPE = 5,
-
-
-    /*
-     * Default width and height of ANativeWindow buffers, these are the
-     * dimensions of the window buffers irrespective of the
-     * NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS call and match the native window
-     * size unless overridden by NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS.
-     */
-    NATIVE_WINDOW_DEFAULT_WIDTH = 6,
-    NATIVE_WINDOW_DEFAULT_HEIGHT = 7,
-
-    /*
-     * transformation that will most-likely be applied to buffers. This is only
-     * a hint, the actual transformation applied might be different.
-     *
-     * INTENDED USE:
-     *
-     * The transform hint can be used by a producer, for instance the GLES
-     * driver, to pre-rotate the rendering such that the final transformation
-     * in the composer is identity. This can be very useful when used in
-     * conjunction with the h/w composer HAL, in situations where it
-     * cannot handle arbitrary rotations.
-     *
-     * 1. Before dequeuing a buffer, the GL driver (or any other ANW client)
-     *    queries the ANW for NATIVE_WINDOW_TRANSFORM_HINT.
-     *
-     * 2. The GL driver overrides the width and height of the ANW to
-     *    account for NATIVE_WINDOW_TRANSFORM_HINT. This is done by querying
-     *    NATIVE_WINDOW_DEFAULT_{WIDTH | HEIGHT}, swapping the dimensions
-     *    according to NATIVE_WINDOW_TRANSFORM_HINT and calling
-     *    native_window_set_buffers_dimensions().
-     *
-     * 3. The GL driver dequeues a buffer of the new pre-rotated size.
-     *
-     * 4. The GL driver renders to the buffer such that the image is
-     *    already transformed, that is applying NATIVE_WINDOW_TRANSFORM_HINT
-     *    to the rendering.
-     *
-     * 5. The GL driver calls native_window_set_transform to apply
-     *    inverse transformation to the buffer it just rendered.
-     *    In order to do this, the GL driver needs
-     *    to calculate the inverse of NATIVE_WINDOW_TRANSFORM_HINT, this is
-     *    done easily:
-     *
-     *        int hintTransform, inverseTransform;
-     *        query(..., NATIVE_WINDOW_TRANSFORM_HINT, &hintTransform);
-     *        inverseTransform = hintTransform;
-     *        if (hintTransform & HAL_TRANSFORM_ROT_90)
-     *            inverseTransform ^= HAL_TRANSFORM_ROT_180;
-     *
-     *
-     * 6. The GL driver queues the pre-transformed buffer.
-     *
-     * 7. The composer combines the buffer transform with the display
-     *    transform.  If the buffer transform happens to cancel out the
-     *    display transform then no rotation is needed.
-     *
-     */
-    NATIVE_WINDOW_TRANSFORM_HINT = 8,
-
-    /*
-     * Boolean that indicates whether the consumer is running more than
-     * one buffer behind the producer.
-     */
-    NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND = 9,
-
-    /*
-     * The consumer gralloc usage bits currently set by the consumer.
-     * The values are defined in hardware/libhardware/include/gralloc.h.
-     */
-    NATIVE_WINDOW_CONSUMER_USAGE_BITS = 10,
-
-    /**
-     * Transformation that will by applied to buffers by the hwcomposer.
-     * This must not be set or checked by producer endpoints, and will
-     * disable the transform hint set in SurfaceFlinger (see
-     * NATIVE_WINDOW_TRANSFORM_HINT).
-     *
-     * INTENDED USE:
-     * Temporary - Please do not use this.  This is intended only to be used
-     * by the camera's LEGACY mode.
-     *
-     * In situations where a SurfaceFlinger client wishes to set a transform
-     * that is not visible to the producer, and will always be applied in the
-     * hardware composer, the client can set this flag with
-     * native_window_set_buffers_sticky_transform.  This can be used to rotate
-     * and flip buffers consumed by hardware composer without actually changing
-     * the aspect ratio of the buffers produced.
-     */
-    NATIVE_WINDOW_STICKY_TRANSFORM = 11,
-
-    /**
-     * The default data space for the buffers as set by the consumer.
-     * The values are defined in graphics.h.
-     */
-    NATIVE_WINDOW_DEFAULT_DATASPACE = 12,
-
-    /*
-     * Returns the age of the contents of the most recently dequeued buffer as
-     * the number of frames that have elapsed since it was last queued. For
-     * example, if the window is double-buffered, the age of any given buffer in
-     * steady state will be 2. If the dequeued buffer has never been queued, its
-     * age will be 0.
-     */
-    NATIVE_WINDOW_BUFFER_AGE = 13,
-
-    /*
-     * Returns the duration of the last dequeueBuffer call in microseconds
-     */
-    NATIVE_WINDOW_LAST_DEQUEUE_DURATION = 14,
-
-    /*
-     * Returns the duration of the last queueBuffer call in microseconds
-     */
-    NATIVE_WINDOW_LAST_QUEUE_DURATION = 15,
-
-    /*
-     * Returns the number of image layers that the ANativeWindow buffer
-     * contains. By default this is 1, unless a buffer is explicitly allocated
-     * to contain multiple layers.
-     */
-    NATIVE_WINDOW_LAYER_COUNT = 16,
-
-    /*
-     * Returns 1 if the native window is valid, 0 otherwise. native window is valid
-     * if it is safe (i.e. no crash will occur) to call any method on it.
-     */
-    NATIVE_WINDOW_IS_VALID = 17,
-
-    /*
-     * Returns 1 if NATIVE_WINDOW_GET_FRAME_TIMESTAMPS will return display
-     * present info, 0 if it won't.
-     */
-    NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT = 18,
-
-    /*
-     * The consumer end is capable of handling protected buffers, i.e. buffer
-     * with GRALLOC_USAGE_PROTECTED usage bits on.
-     */
-    NATIVE_WINDOW_CONSUMER_IS_PROTECTED = 19,
-};
-
-/* Valid operations for the (*perform)() hook.
- *
- * Values marked as 'deprecated' are supported, but have been superceded by
- * other functionality.
- *
- * Values marked as 'private' should be considered private to the framework.
- * HAL implementation code with access to an ANativeWindow should not use these,
- * as it may not interact properly with the framework's use of the
- * ANativeWindow.
- */
-enum {
-// clang-format off
-    NATIVE_WINDOW_SET_USAGE                 =  0,
-    NATIVE_WINDOW_CONNECT                   =  1,   /* deprecated */
-    NATIVE_WINDOW_DISCONNECT                =  2,   /* deprecated */
-    NATIVE_WINDOW_SET_CROP                  =  3,   /* private */
-    NATIVE_WINDOW_SET_BUFFER_COUNT          =  4,
-    NATIVE_WINDOW_SET_BUFFERS_GEOMETRY      =  5,   /* deprecated */
-    NATIVE_WINDOW_SET_BUFFERS_TRANSFORM     =  6,
-    NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP     =  7,
-    NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS    =  8,
-    NATIVE_WINDOW_SET_BUFFERS_FORMAT        =  9,
-    NATIVE_WINDOW_SET_SCALING_MODE          = 10,   /* private */
-    NATIVE_WINDOW_LOCK                      = 11,   /* private */
-    NATIVE_WINDOW_UNLOCK_AND_POST           = 12,   /* private */
-    NATIVE_WINDOW_API_CONNECT               = 13,   /* private */
-    NATIVE_WINDOW_API_DISCONNECT            = 14,   /* private */
-    NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS = 15, /* private */
-    NATIVE_WINDOW_SET_POST_TRANSFORM_CROP   = 16,   /* private */
-    NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM = 17,/* private */
-    NATIVE_WINDOW_SET_SIDEBAND_STREAM       = 18,
-    NATIVE_WINDOW_SET_BUFFERS_DATASPACE     = 19,
-    NATIVE_WINDOW_SET_SURFACE_DAMAGE        = 20,   /* private */
-    NATIVE_WINDOW_SET_SHARED_BUFFER_MODE    = 21,
-    NATIVE_WINDOW_SET_AUTO_REFRESH          = 22,
-    NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION= 23,
-    NATIVE_WINDOW_GET_NEXT_FRAME_ID         = 24,
-    NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS   = 25,
-    NATIVE_WINDOW_GET_COMPOSITOR_TIMING     = 26,
-    NATIVE_WINDOW_GET_FRAME_TIMESTAMPS      = 27,
-    NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT    = 28,
-    NATIVE_WINDOW_GET_HDR_SUPPORT           = 29,
-// clang-format on
-};
-
-/* parameter for NATIVE_WINDOW_[API_][DIS]CONNECT */
-enum {
-    /* Buffers will be queued by EGL via eglSwapBuffers after being filled using
-     * OpenGL ES.
-     */
-    NATIVE_WINDOW_API_EGL = 1,
-
-    /* Buffers will be queued after being filled using the CPU
-     */
-    NATIVE_WINDOW_API_CPU = 2,
-
-    /* Buffers will be queued by Stagefright after being filled by a video
-     * decoder.  The video decoder can either be a software or hardware decoder.
-     */
-    NATIVE_WINDOW_API_MEDIA = 3,
-
-    /* Buffers will be queued by the the camera HAL.
-     */
-    NATIVE_WINDOW_API_CAMERA = 4,
-};
-
-/* parameter for NATIVE_WINDOW_SET_BUFFERS_TRANSFORM */
-enum {
-    /* flip source image horizontally */
-    NATIVE_WINDOW_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H ,
-    /* flip source image vertically */
-    NATIVE_WINDOW_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V,
-    /* rotate source image 90 degrees clock-wise, and is applied after TRANSFORM_FLIP_{H|V} */
-    NATIVE_WINDOW_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,
-    /* rotate source image 180 degrees */
-    NATIVE_WINDOW_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,
-    /* rotate source image 270 degrees clock-wise */
-    NATIVE_WINDOW_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,
-    /* transforms source by the inverse transform of the screen it is displayed onto. This
-     * transform is applied last */
-    NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY = 0x08
-};
-
-/* parameter for NATIVE_WINDOW_SET_SCALING_MODE
- * keep in sync with Surface.java in frameworks/base */
-enum {
-    /* the window content is not updated (frozen) until a buffer of
-     * the window size is received (enqueued)
-     */
-    NATIVE_WINDOW_SCALING_MODE_FREEZE           = 0,
-    /* the buffer is scaled in both dimensions to match the window size */
-    NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW  = 1,
-    /* the buffer is scaled uniformly such that the smaller dimension
-     * of the buffer matches the window size (cropping in the process)
-     */
-    NATIVE_WINDOW_SCALING_MODE_SCALE_CROP       = 2,
-    /* the window is clipped to the size of the buffer's crop rectangle; pixels
-     * outside the crop rectangle are treated as if they are completely
-     * transparent.
-     */
-    NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP    = 3,
-};
-
-/* values returned by the NATIVE_WINDOW_CONCRETE_TYPE query */
-enum {
-    NATIVE_WINDOW_FRAMEBUFFER               = 0, /* FramebufferNativeWindow */
-    NATIVE_WINDOW_SURFACE                   = 1, /* Surface */
-};
-
-/* parameter for NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
- *
- * Special timestamp value to indicate that timestamps should be auto-generated
- * by the native window when queueBuffer is called.  This is equal to INT64_MIN,
- * defined directly to avoid problems with C99/C++ inclusion of stdint.h.
- */
-static const int64_t NATIVE_WINDOW_TIMESTAMP_AUTO = (-9223372036854775807LL-1);
-
-/* parameter for NATIVE_WINDOW_GET_FRAME_TIMESTAMPS
- *
- * Special timestamp value to indicate the timestamps aren't yet known or
- * that they are invalid.
- */
-static const int64_t NATIVE_WINDOW_TIMESTAMP_PENDING = -2;
-static const int64_t NATIVE_WINDOW_TIMESTAMP_INVALID = -1;
-
-struct ANativeWindow
-{
-#ifdef __cplusplus
-    ANativeWindow()
-        : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)
-    {
-        common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
-        common.version = sizeof(ANativeWindow);
-        memset(common.reserved, 0, sizeof(common.reserved));
-    }
-
-    /* Implement the methods that sp<ANativeWindow> expects so that it
-       can be used to automatically refcount ANativeWindow's. */
-    void incStrong(const void* /*id*/) const {
-        common.incRef(const_cast<android_native_base_t*>(&common));
-    }
-    void decStrong(const void* /*id*/) const {
-        common.decRef(const_cast<android_native_base_t*>(&common));
-    }
-#endif
-
-    struct android_native_base_t common;
-
-    /* flags describing some attributes of this surface or its updater */
-    const uint32_t flags;
-
-    /* min swap interval supported by this updated */
-    const int   minSwapInterval;
-
-    /* max swap interval supported by this updated */
-    const int   maxSwapInterval;
-
-    /* horizontal and vertical resolution in DPI */
-    const float xdpi;
-    const float ydpi;
-
-    /* Some storage reserved for the OEM's driver. */
-    intptr_t    oem[4];
-
-    /*
-     * Set the swap interval for this surface.
-     *
-     * Returns 0 on success or -errno on error.
-     */
-    int     (*setSwapInterval)(struct ANativeWindow* window,
-                int interval);
-
-    /*
-     * Hook called by EGL to acquire a buffer. After this call, the buffer
-     * is not locked, so its content cannot be modified. This call may block if
-     * no buffers are available.
-     *
-     * The window holds a reference to the buffer between dequeueBuffer and
-     * either queueBuffer or cancelBuffer, so clients only need their own
-     * reference if they might use the buffer after queueing or canceling it.
-     * Holding a reference to a buffer after queueing or canceling it is only
-     * allowed if a specific buffer count has been set.
-     *
-     * Returns 0 on success or -errno on error.
-     *
-     * XXX: This function is deprecated.  It will continue to work for some
-     * time for binary compatibility, but the new dequeueBuffer function that
-     * outputs a fence file descriptor should be used in its place.
-     */
-    int     (*dequeueBuffer_DEPRECATED)(struct ANativeWindow* window,
-                struct ANativeWindowBuffer** buffer);
-
-    /*
-     * hook called by EGL to lock a buffer. This MUST be called before modifying
-     * the content of a buffer. The buffer must have been acquired with
-     * dequeueBuffer first.
-     *
-     * Returns 0 on success or -errno on error.
-     *
-     * XXX: This function is deprecated.  It will continue to work for some
-     * time for binary compatibility, but it is essentially a no-op, and calls
-     * to it should be removed.
-     */
-    int     (*lockBuffer_DEPRECATED)(struct ANativeWindow* window,
-                struct ANativeWindowBuffer* buffer);
-
-    /*
-     * Hook called by EGL when modifications to the render buffer are done.
-     * This unlocks and post the buffer.
-     *
-     * The window holds a reference to the buffer between dequeueBuffer and
-     * either queueBuffer or cancelBuffer, so clients only need their own
-     * reference if they might use the buffer after queueing or canceling it.
-     * Holding a reference to a buffer after queueing or canceling it is only
-     * allowed if a specific buffer count has been set.
-     *
-     * Buffers MUST be queued in the same order than they were dequeued.
-     *
-     * Returns 0 on success or -errno on error.
-     *
-     * XXX: This function is deprecated.  It will continue to work for some
-     * time for binary compatibility, but the new queueBuffer function that
-     * takes a fence file descriptor should be used in its place (pass a value
-     * of -1 for the fence file descriptor if there is no valid one to pass).
-     */
-    int     (*queueBuffer_DEPRECATED)(struct ANativeWindow* window,
-                struct ANativeWindowBuffer* buffer);
-
-    /*
-     * hook used to retrieve information about the native window.
-     *
-     * Returns 0 on success or -errno on error.
-     */
-    int     (*query)(const struct ANativeWindow* window,
-                int what, int* value);
-
-    /*
-     * hook used to perform various operations on the surface.
-     * (*perform)() is a generic mechanism to add functionality to
-     * ANativeWindow while keeping backward binary compatibility.
-     *
-     * DO NOT CALL THIS HOOK DIRECTLY.  Instead, use the helper functions
-     * defined below.
-     *
-     * (*perform)() returns -ENOENT if the 'what' parameter is not supported
-     * by the surface's implementation.
-     *
-     * See above for a list of valid operations, such as
-     * NATIVE_WINDOW_SET_USAGE or NATIVE_WINDOW_CONNECT
-     */
-    int     (*perform)(struct ANativeWindow* window,
-                int operation, ... );
-
-    /*
-     * Hook used to cancel a buffer that has been dequeued.
-     * No synchronization is performed between dequeue() and cancel(), so
-     * either external synchronization is needed, or these functions must be
-     * called from the same thread.
-     *
-     * The window holds a reference to the buffer between dequeueBuffer and
-     * either queueBuffer or cancelBuffer, so clients only need their own
-     * reference if they might use the buffer after queueing or canceling it.
-     * Holding a reference to a buffer after queueing or canceling it is only
-     * allowed if a specific buffer count has been set.
-     *
-     * XXX: This function is deprecated.  It will continue to work for some
-     * time for binary compatibility, but the new cancelBuffer function that
-     * takes a fence file descriptor should be used in its place (pass a value
-     * of -1 for the fence file descriptor if there is no valid one to pass).
-     */
-    int     (*cancelBuffer_DEPRECATED)(struct ANativeWindow* window,
-                struct ANativeWindowBuffer* buffer);
-
-    /*
-     * Hook called by EGL to acquire a buffer. This call may block if no
-     * buffers are available.
-     *
-     * The window holds a reference to the buffer between dequeueBuffer and
-     * either queueBuffer or cancelBuffer, so clients only need their own
-     * reference if they might use the buffer after queueing or canceling it.
-     * Holding a reference to a buffer after queueing or canceling it is only
-     * allowed if a specific buffer count has been set.
-     *
-     * The libsync fence file descriptor returned in the int pointed to by the
-     * fenceFd argument will refer to the fence that must signal before the
-     * dequeued buffer may be written to.  A value of -1 indicates that the
-     * caller may access the buffer immediately without waiting on a fence.  If
-     * a valid file descriptor is returned (i.e. any value except -1) then the
-     * caller is responsible for closing the file descriptor.
-     *
-     * Returns 0 on success or -errno on error.
-     */
-    int     (*dequeueBuffer)(struct ANativeWindow* window,
-                struct ANativeWindowBuffer** buffer, int* fenceFd);
-
-    /*
-     * Hook called by EGL when modifications to the render buffer are done.
-     * This unlocks and post the buffer.
-     *
-     * The window holds a reference to the buffer between dequeueBuffer and
-     * either queueBuffer or cancelBuffer, so clients only need their own
-     * reference if they might use the buffer after queueing or canceling it.
-     * Holding a reference to a buffer after queueing or canceling it is only
-     * allowed if a specific buffer count has been set.
-     *
-     * The fenceFd argument specifies a libsync fence file descriptor for a
-     * fence that must signal before the buffer can be accessed.  If the buffer
-     * can be accessed immediately then a value of -1 should be used.  The
-     * caller must not use the file descriptor after it is passed to
-     * queueBuffer, and the ANativeWindow implementation is responsible for
-     * closing it.
-     *
-     * Returns 0 on success or -errno on error.
-     */
-    int     (*queueBuffer)(struct ANativeWindow* window,
-                struct ANativeWindowBuffer* buffer, int fenceFd);
-
-    /*
-     * Hook used to cancel a buffer that has been dequeued.
-     * No synchronization is performed between dequeue() and cancel(), so
-     * either external synchronization is needed, or these functions must be
-     * called from the same thread.
-     *
-     * The window holds a reference to the buffer between dequeueBuffer and
-     * either queueBuffer or cancelBuffer, so clients only need their own
-     * reference if they might use the buffer after queueing or canceling it.
-     * Holding a reference to a buffer after queueing or canceling it is only
-     * allowed if a specific buffer count has been set.
-     *
-     * The fenceFd argument specifies a libsync fence file decsriptor for a
-     * fence that must signal before the buffer can be accessed.  If the buffer
-     * can be accessed immediately then a value of -1 should be used.
-     *
-     * Note that if the client has not waited on the fence that was returned
-     * from dequeueBuffer, that same fence should be passed to cancelBuffer to
-     * ensure that future uses of the buffer are preceded by a wait on that
-     * fence.  The caller must not use the file descriptor after it is passed
-     * to cancelBuffer, and the ANativeWindow implementation is responsible for
-     * closing it.
-     *
-     * Returns 0 on success or -errno on error.
-     */
-    int     (*cancelBuffer)(struct ANativeWindow* window,
-                struct ANativeWindowBuffer* buffer, int fenceFd);
-};
-
- /* Backwards compatibility: use ANativeWindow (struct ANativeWindow in C).
-  * android_native_window_t is deprecated.
-  */
-typedef struct ANativeWindow ANativeWindow;
-typedef struct ANativeWindow android_native_window_t __deprecated;
-
-/*
- *  native_window_set_usage(..., usage)
- *  Sets the intended usage flags for the next buffers
- *  acquired with (*lockBuffer)() and on.
- *  By default (if this function is never called), a usage of
- *      GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE
- *  is assumed.
- *  Calling this function will usually cause following buffers to be
- *  reallocated.
- */
-
-static inline int native_window_set_usage(
-        struct ANativeWindow* window, int usage)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage);
-}
-
-/* deprecated. Always returns 0. Don't call. */
-static inline int native_window_connect(
-        struct ANativeWindow* window __UNUSED, int api __UNUSED) __deprecated;
-
-static inline int native_window_connect(
-        struct ANativeWindow* window __UNUSED, int api __UNUSED) {
-    return 0;
-}
-
-/* deprecated. Always returns 0. Don't call. */
-static inline int native_window_disconnect(
-        struct ANativeWindow* window __UNUSED, int api __UNUSED) __deprecated;
-
-static inline int native_window_disconnect(
-        struct ANativeWindow* window __UNUSED, int api __UNUSED) {
-    return 0;
-}
-
-/*
- * native_window_set_crop(..., crop)
- * Sets which region of the next queued buffers needs to be considered.
- * Depending on the scaling mode, a buffer's crop region is scaled and/or
- * cropped to match the surface's size.  This function sets the crop in
- * pre-transformed buffer pixel coordinates.
- *
- * The specified crop region applies to all buffers queued after it is called.
- *
- * If 'crop' is NULL, subsequently queued buffers won't be cropped.
- *
- * An error is returned if for instance the crop region is invalid, out of the
- * buffer's bound or if the window is invalid.
- */
-static inline int native_window_set_crop(
-        struct ANativeWindow* window,
-        android_native_rect_t const * crop)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_CROP, crop);
-}
-
-/*
- * native_window_set_post_transform_crop(..., crop)
- * Sets which region of the next queued buffers needs to be considered.
- * Depending on the scaling mode, a buffer's crop region is scaled and/or
- * cropped to match the surface's size.  This function sets the crop in
- * post-transformed pixel coordinates.
- *
- * The specified crop region applies to all buffers queued after it is called.
- *
- * If 'crop' is NULL, subsequently queued buffers won't be cropped.
- *
- * An error is returned if for instance the crop region is invalid, out of the
- * buffer's bound or if the window is invalid.
- */
-static inline int native_window_set_post_transform_crop(
-        struct ANativeWindow* window,
-        android_native_rect_t const * crop)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_POST_TRANSFORM_CROP, crop);
-}
-
-/*
- * native_window_set_active_rect(..., active_rect)
- *
- * This function is deprecated and will be removed soon.  For now it simply
- * sets the post-transform crop for compatibility while multi-project commits
- * get checked.
- */
-static inline int native_window_set_active_rect(
-        struct ANativeWindow* window,
-        android_native_rect_t const * active_rect) __deprecated;
-
-static inline int native_window_set_active_rect(
-        struct ANativeWindow* window,
-        android_native_rect_t const * active_rect)
-{
-    return native_window_set_post_transform_crop(window, active_rect);
-}
-
-/*
- * native_window_set_buffer_count(..., count)
- * Sets the number of buffers associated with this native window.
- */
-static inline int native_window_set_buffer_count(
-        struct ANativeWindow* window,
-        size_t bufferCount)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_BUFFER_COUNT, bufferCount);
-}
-
-/*
- * native_window_set_buffers_geometry(..., int w, int h, int format)
- * All buffers dequeued after this call will have the dimensions and format
- * specified.  A successful call to this function has the same effect as calling
- * native_window_set_buffers_size and native_window_set_buffers_format.
- *
- * XXX: This function is deprecated.  The native_window_set_buffers_dimensions
- * and native_window_set_buffers_format functions should be used instead.
- */
-static inline int native_window_set_buffers_geometry(
-        struct ANativeWindow* window,
-        int w, int h, int format) __deprecated;
-
-static inline int native_window_set_buffers_geometry(
-        struct ANativeWindow* window,
-        int w, int h, int format)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
-            w, h, format);
-}
-
-/*
- * native_window_set_buffers_dimensions(..., int w, int h)
- * All buffers dequeued after this call will have the dimensions specified.
- * In particular, all buffers will have a fixed-size, independent from the
- * native-window size. They will be scaled according to the scaling mode
- * (see native_window_set_scaling_mode) upon window composition.
- *
- * If w and h are 0, the normal behavior is restored. That is, dequeued buffers
- * following this call will be sized to match the window's size.
- *
- * Calling this function will reset the window crop to a NULL value, which
- * disables cropping of the buffers.
- */
-static inline int native_window_set_buffers_dimensions(
-        struct ANativeWindow* window,
-        int w, int h)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS,
-            w, h);
-}
-
-/*
- * native_window_set_buffers_user_dimensions(..., int w, int h)
- *
- * Sets the user buffer size for the window, which overrides the
- * window's size.  All buffers dequeued after this call will have the
- * dimensions specified unless overridden by
- * native_window_set_buffers_dimensions.  All buffers will have a
- * fixed-size, independent from the native-window size. They will be
- * scaled according to the scaling mode (see
- * native_window_set_scaling_mode) upon window composition.
- *
- * If w and h are 0, the normal behavior is restored. That is, the
- * default buffer size will match the windows's size.
- *
- * Calling this function will reset the window crop to a NULL value, which
- * disables cropping of the buffers.
- */
-static inline int native_window_set_buffers_user_dimensions(
-        struct ANativeWindow* window,
-        int w, int h)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS,
-            w, h);
-}
-
-/*
- * native_window_set_buffers_format(..., int format)
- * All buffers dequeued after this call will have the format specified.
- *
- * If the specified format is 0, the default buffer format will be used.
- */
-static inline int native_window_set_buffers_format(
-        struct ANativeWindow* window,
-        int format)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_FORMAT, format);
-}
-
-/*
- * native_window_set_buffers_data_space(..., int dataSpace)
- * All buffers queued after this call will be associated with the dataSpace
- * parameter specified.
- *
- * dataSpace specifies additional information about the buffer that's dependent
- * on the buffer format and the endpoints. For example, it can be used to convey
- * the color space of the image data in the buffer, or it can be used to
- * indicate that the buffers contain depth measurement data instead of color
- * images.  The default dataSpace is 0, HAL_DATASPACE_UNKNOWN, unless it has been
- * overridden by the consumer.
- */
-static inline int native_window_set_buffers_data_space(
-        struct ANativeWindow* window,
-        android_dataspace_t dataSpace)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_DATASPACE,
-            dataSpace);
-}
-
-/*
- * native_window_set_buffers_transform(..., int transform)
- * All buffers queued after this call will be displayed transformed according
- * to the transform parameter specified.
- */
-static inline int native_window_set_buffers_transform(
-        struct ANativeWindow* window,
-        int transform)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_TRANSFORM,
-            transform);
-}
-
-/*
- * native_window_set_buffers_sticky_transform(..., int transform)
- * All buffers queued after this call will be displayed transformed according
- * to the transform parameter specified applied on top of the regular buffer
- * transform.  Setting this transform will disable the transform hint.
- *
- * Temporary - This is only intended to be used by the LEGACY camera mode, do
- *   not use this for anything else.
- */
-static inline int native_window_set_buffers_sticky_transform(
-        struct ANativeWindow* window,
-        int transform)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM,
-            transform);
-}
-
-/*
- * native_window_set_buffers_timestamp(..., int64_t timestamp)
- * All buffers queued after this call will be associated with the timestamp
- * parameter specified. If the timestamp is set to NATIVE_WINDOW_TIMESTAMP_AUTO
- * (the default), timestamps will be generated automatically when queueBuffer is
- * called. The timestamp is measured in nanoseconds, and is normally monotonically
- * increasing. The timestamp should be unaffected by time-of-day adjustments,
- * and for a camera should be strictly monotonic but for a media player may be
- * reset when the position is set.
- */
-static inline int native_window_set_buffers_timestamp(
-        struct ANativeWindow* window,
-        int64_t timestamp)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP,
-            timestamp);
-}
-
-/*
- * native_window_set_scaling_mode(..., int mode)
- * All buffers queued after this call will be associated with the scaling mode
- * specified.
- */
-static inline int native_window_set_scaling_mode(
-        struct ANativeWindow* window,
-        int mode)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_SCALING_MODE,
-            mode);
-}
-
-/*
- * native_window_api_connect(..., int api)
- * connects an API to this window. only one API can be connected at a time.
- * Returns -EINVAL if for some reason the window cannot be connected, which
- * can happen if it's connected to some other API.
- */
-static inline int native_window_api_connect(
-        struct ANativeWindow* window, int api)
-{
-    return window->perform(window, NATIVE_WINDOW_API_CONNECT, api);
-}
-
-/*
- * native_window_api_disconnect(..., int api)
- * disconnect the API from this window.
- * An error is returned if for instance the window wasn't connected in the
- * first place.
- */
-static inline int native_window_api_disconnect(
-        struct ANativeWindow* window, int api)
-{
-    return window->perform(window, NATIVE_WINDOW_API_DISCONNECT, api);
-}
-
-/*
- * native_window_dequeue_buffer_and_wait(...)
- * Dequeue a buffer and wait on the fence associated with that buffer.  The
- * buffer may safely be accessed immediately upon this function returning.  An
- * error is returned if either of the dequeue or the wait operations fail.
- */
-static inline int native_window_dequeue_buffer_and_wait(ANativeWindow *anw,
-        struct ANativeWindowBuffer** anb) {
-    return anw->dequeueBuffer_DEPRECATED(anw, anb);
-}
-
-/*
- * native_window_set_sideband_stream(..., native_handle_t*)
- * Attach a sideband buffer stream to a native window.
- */
-static inline int native_window_set_sideband_stream(
-        struct ANativeWindow* window,
-        native_handle_t* sidebandHandle)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_SIDEBAND_STREAM,
-            sidebandHandle);
-}
-
-/*
- * native_window_set_surface_damage(..., android_native_rect_t* rects, int numRects)
- * Set the surface damage (i.e., the region of the surface that has changed
- * since the previous frame). The damage set by this call will be reset (to the
- * default of full-surface damage) after calling queue, so this must be called
- * prior to every frame with damage that does not cover the whole surface if the
- * caller desires downstream consumers to use this optimization.
- *
- * The damage region is specified as an array of rectangles, with the important
- * caveat that the origin of the surface is considered to be the bottom-left
- * corner, as in OpenGL ES.
- *
- * If numRects is set to 0, rects may be NULL, and the surface damage will be
- * set to the full surface (the same as if this function had not been called for
- * this frame).
- */
-static inline int native_window_set_surface_damage(
-        struct ANativeWindow* window,
-        const android_native_rect_t* rects, size_t numRects)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_SURFACE_DAMAGE,
-            rects, numRects);
-}
-
-/*
- * native_window_set_shared_buffer_mode(..., bool sharedBufferMode)
- * Enable/disable shared buffer mode
- */
-static inline int native_window_set_shared_buffer_mode(
-        struct ANativeWindow* window,
-        bool sharedBufferMode)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_SHARED_BUFFER_MODE,
-            sharedBufferMode);
-}
-
-/*
- * native_window_set_auto_refresh(..., autoRefresh)
- * Enable/disable auto refresh when in shared buffer mode
- */
-static inline int native_window_set_auto_refresh(
-        struct ANativeWindow* window,
-        bool autoRefresh)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_AUTO_REFRESH, autoRefresh);
-}
-
-static inline int native_window_get_refresh_cycle_duration(
-        struct ANativeWindow* window,
-        int64_t* outRefreshDuration)
-{
-    return window->perform(window, NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION,
-            outRefreshDuration);
-}
-
-static inline int native_window_get_next_frame_id(
-        struct ANativeWindow* window, uint64_t* frameId)
-{
-    return window->perform(window, NATIVE_WINDOW_GET_NEXT_FRAME_ID, frameId);
-}
-
-static inline int native_window_enable_frame_timestamps(
-        struct ANativeWindow* window, bool enable)
-{
-    return window->perform(window, NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS,
-            enable);
-}
-
-static inline int native_window_get_compositor_timing(
-        struct ANativeWindow* window,
-        int64_t* compositeDeadline, int64_t* compositeInterval,
-        int64_t* compositeToPresentLatency)
-{
-    return window->perform(window, NATIVE_WINDOW_GET_COMPOSITOR_TIMING,
-            compositeDeadline, compositeInterval, compositeToPresentLatency);
-}
-
-static inline int native_window_get_frame_timestamps(
-        struct ANativeWindow* window, uint64_t frameId,
-        int64_t* outRequestedPresentTime, int64_t* outAcquireTime,
-        int64_t* outLatchTime, int64_t* outFirstRefreshStartTime,
-        int64_t* outLastRefreshStartTime, int64_t* outGpuCompositionDoneTime,
-        int64_t* outDisplayPresentTime, int64_t* outDequeueReadyTime,
-        int64_t* outReleaseTime)
-{
-    return window->perform(window, NATIVE_WINDOW_GET_FRAME_TIMESTAMPS,
-            frameId, outRequestedPresentTime, outAcquireTime, outLatchTime,
-            outFirstRefreshStartTime, outLastRefreshStartTime,
-            outGpuCompositionDoneTime, outDisplayPresentTime,
-            outDequeueReadyTime, outReleaseTime);
-}
-
-static inline int native_window_get_wide_color_support(
-    struct ANativeWindow* window, bool* outSupport) {
-  return window->perform(window, NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT,
-                         outSupport);
-}
-
-static inline int native_window_get_hdr_support(struct ANativeWindow* window,
-                                                bool* outSupport) {
-  return window->perform(window, NATIVE_WINDOW_GET_HDR_SUPPORT, outSupport);
-}
-
-__END_DECLS
diff --git a/libsystem/include/system/window.h b/libsystem/include/system/window.h
deleted file mode 100644
index efa10d6..0000000
--- a/libsystem/include/system/window.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#ifndef SYSTEM_CORE_INCLUDE_ANDROID_WINDOW_H
-#define SYSTEM_CORE_INCLUDE_ANDROID_WINDOW_H
-
-#include <system/window-deprecated.h>
-
-#endif /* SYSTEM_CORE_INCLUDE_ANDROID_WINDOW_H */
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index f40086e..e687a68 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -122,6 +122,7 @@
         "tests/MemoryRangeTest.cpp",
         "tests/MemoryRemoteTest.cpp",
         "tests/MemoryTest.cpp",
+        "tests/RegsIterateTest.cpp",
         "tests/RegsStepIfSignalHandlerTest.cpp",
         "tests/RegsTest.cpp",
         "tests/SymbolsTest.cpp",
diff --git a/libunwindstack/Regs.cpp b/libunwindstack/Regs.cpp
index cf71e39..36b8e25 100644
--- a/libunwindstack/Regs.cpp
+++ b/libunwindstack/Regs.cpp
@@ -80,6 +80,25 @@
   return true;
 }
 
+void RegsArm::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
+  fn("r0", regs_[ARM_REG_R0]);
+  fn("r1", regs_[ARM_REG_R1]);
+  fn("r2", regs_[ARM_REG_R2]);
+  fn("r3", regs_[ARM_REG_R3]);
+  fn("r4", regs_[ARM_REG_R4]);
+  fn("r5", regs_[ARM_REG_R5]);
+  fn("r6", regs_[ARM_REG_R6]);
+  fn("r7", regs_[ARM_REG_R7]);
+  fn("r8", regs_[ARM_REG_R8]);
+  fn("r9", regs_[ARM_REG_R9]);
+  fn("r10", regs_[ARM_REG_R10]);
+  fn("r11", regs_[ARM_REG_R11]);
+  fn("ip", regs_[ARM_REG_R12]);
+  fn("sp", regs_[ARM_REG_SP]);
+  fn("lr", regs_[ARM_REG_LR]);
+  fn("pc", regs_[ARM_REG_PC]);
+}
+
 RegsArm64::RegsArm64()
     : RegsImpl<uint64_t>(ARM64_REG_LAST, ARM64_REG_SP, Location(LOCATION_REGISTER, ARM64_REG_LR)) {}
 
@@ -112,6 +131,42 @@
   return true;
 }
 
+void RegsArm64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
+  fn("x0", regs_[ARM64_REG_R0]);
+  fn("x1", regs_[ARM64_REG_R1]);
+  fn("x2", regs_[ARM64_REG_R2]);
+  fn("x3", regs_[ARM64_REG_R3]);
+  fn("x4", regs_[ARM64_REG_R4]);
+  fn("x5", regs_[ARM64_REG_R5]);
+  fn("x6", regs_[ARM64_REG_R6]);
+  fn("x7", regs_[ARM64_REG_R7]);
+  fn("x8", regs_[ARM64_REG_R8]);
+  fn("x9", regs_[ARM64_REG_R9]);
+  fn("x10", regs_[ARM64_REG_R10]);
+  fn("x11", regs_[ARM64_REG_R11]);
+  fn("x12", regs_[ARM64_REG_R12]);
+  fn("x13", regs_[ARM64_REG_R13]);
+  fn("x14", regs_[ARM64_REG_R14]);
+  fn("x15", regs_[ARM64_REG_R15]);
+  fn("x16", regs_[ARM64_REG_R16]);
+  fn("x17", regs_[ARM64_REG_R17]);
+  fn("x18", regs_[ARM64_REG_R18]);
+  fn("x19", regs_[ARM64_REG_R19]);
+  fn("x20", regs_[ARM64_REG_R20]);
+  fn("x21", regs_[ARM64_REG_R21]);
+  fn("x22", regs_[ARM64_REG_R22]);
+  fn("x23", regs_[ARM64_REG_R23]);
+  fn("x24", regs_[ARM64_REG_R24]);
+  fn("x25", regs_[ARM64_REG_R25]);
+  fn("x26", regs_[ARM64_REG_R26]);
+  fn("x27", regs_[ARM64_REG_R27]);
+  fn("x28", regs_[ARM64_REG_R28]);
+  fn("x29", regs_[ARM64_REG_R29]);
+  fn("sp", regs_[ARM64_REG_SP]);
+  fn("lr", regs_[ARM64_REG_LR]);
+  fn("pc", regs_[ARM64_REG_PC]);
+}
+
 RegsX86::RegsX86()
     : RegsImpl<uint32_t>(X86_REG_LAST, X86_REG_SP, Location(LOCATION_SP_OFFSET, -4)) {}
 
@@ -146,6 +201,18 @@
   return true;
 }
 
+void RegsX86::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
+  fn("eax", regs_[X86_REG_EAX]);
+  fn("ebx", regs_[X86_REG_EBX]);
+  fn("ecx", regs_[X86_REG_ECX]);
+  fn("edx", regs_[X86_REG_EDX]);
+  fn("ebp", regs_[X86_REG_EBP]);
+  fn("edi", regs_[X86_REG_EDI]);
+  fn("esi", regs_[X86_REG_ESI]);
+  fn("esp", regs_[X86_REG_ESP]);
+  fn("eip", regs_[X86_REG_EIP]);
+}
+
 RegsX86_64::RegsX86_64()
     : RegsImpl<uint64_t>(X86_64_REG_LAST, X86_64_REG_SP, Location(LOCATION_SP_OFFSET, -8)) {}
 
@@ -181,6 +248,26 @@
   return true;
 }
 
+void RegsX86_64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
+  fn("rax", regs_[X86_64_REG_RAX]);
+  fn("rbx", regs_[X86_64_REG_RBX]);
+  fn("rcx", regs_[X86_64_REG_RCX]);
+  fn("rdx", regs_[X86_64_REG_RDX]);
+  fn("r8", regs_[X86_64_REG_R8]);
+  fn("r9", regs_[X86_64_REG_R9]);
+  fn("r10", regs_[X86_64_REG_R10]);
+  fn("r11", regs_[X86_64_REG_R11]);
+  fn("r12", regs_[X86_64_REG_R12]);
+  fn("r13", regs_[X86_64_REG_R13]);
+  fn("r14", regs_[X86_64_REG_R14]);
+  fn("r15", regs_[X86_64_REG_R15]);
+  fn("rdi", regs_[X86_64_REG_RDI]);
+  fn("rsi", regs_[X86_64_REG_RSI]);
+  fn("rbp", regs_[X86_64_REG_RBP]);
+  fn("rsp", regs_[X86_64_REG_RSP]);
+  fn("rip", regs_[X86_64_REG_RIP]);
+}
+
 static Regs* ReadArm(void* remote_data) {
   arm_user_regs* user = reinterpret_cast<arm_user_regs*>(remote_data);
 
diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h
index 9d3150b..6576e4c 100644
--- a/libunwindstack/include/unwindstack/Regs.h
+++ b/libunwindstack/include/unwindstack/Regs.h
@@ -19,6 +19,8 @@
 
 #include <stdint.h>
 
+#include <functional>
+#include <string>
 #include <vector>
 
 namespace unwindstack {
@@ -63,6 +65,8 @@
 
   virtual bool SetPcFromReturnAddress(Memory* process_memory) = 0;
 
+  virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) = 0;
+
   uint16_t sp_reg() { return sp_reg_; }
   uint16_t total_regs() { return total_regs_; }
 
@@ -94,6 +98,12 @@
 
   void* RawData() override { return regs_.data(); }
 
+  virtual void IterateRegisters(std::function<void(const char*, uint64_t)> fn) override {
+    for (size_t i = 0; i < regs_.size(); ++i) {
+      fn(std::to_string(i).c_str(), regs_[i]);
+    }
+  }
+
  protected:
   AddressType pc_;
   AddressType sp_;
@@ -114,6 +124,8 @@
   bool SetPcFromReturnAddress(Memory* process_memory) override;
 
   bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
+
+  virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
 };
 
 class RegsArm64 : public RegsImpl<uint64_t> {
@@ -130,6 +142,8 @@
   bool SetPcFromReturnAddress(Memory* process_memory) override;
 
   bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
+
+  virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
 };
 
 class RegsX86 : public RegsImpl<uint32_t> {
@@ -148,6 +162,8 @@
   bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
 
   void SetFromUcontext(x86_ucontext_t* ucontext);
+
+  virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
 };
 
 class RegsX86_64 : public RegsImpl<uint64_t> {
@@ -166,6 +182,8 @@
   bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
 
   void SetFromUcontext(x86_64_ucontext_t* ucontext);
+
+  virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
 };
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/RegsFake.h b/libunwindstack/tests/RegsFake.h
index efcd029..fedaf87 100644
--- a/libunwindstack/tests/RegsFake.h
+++ b/libunwindstack/tests/RegsFake.h
@@ -42,6 +42,8 @@
     return true;
   }
 
+  void IterateRegisters(std::function<void(const char*, uint64_t)>) override {}
+
   uint64_t GetAdjustedPc(uint64_t rel_pc, Elf*) override { return rel_pc - 2; }
 
   bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
diff --git a/libunwindstack/tests/RegsIterateTest.cpp b/libunwindstack/tests/RegsIterateTest.cpp
new file mode 100644
index 0000000..c8d1d98
--- /dev/null
+++ b/libunwindstack/tests/RegsIterateTest.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2017 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 <stdint.h>
+
+#include <utility>
+#include <type_traits>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/ElfInterface.h>
+#include <unwindstack/MapInfo.h>
+#include <unwindstack/Regs.h>
+
+#include "Machine.h"
+
+namespace unwindstack {
+
+struct Register {
+  std::string expected_name;
+  uint64_t offset;
+
+  bool operator==(const Register& rhs) const {
+    return std::tie(expected_name, offset) == std::tie(rhs.expected_name, rhs.offset);
+  }
+};
+
+template<typename T>
+class RegsIterateTest : public ::testing::Test {
+};
+
+template<typename RegsType>
+std::vector<Register> ExpectedRegisters();
+
+template<>
+std::vector<Register> ExpectedRegisters<RegsArm>() {
+  std::vector<Register> result;
+  result.push_back({"r0", ARM_REG_R0});
+  result.push_back({"r1", ARM_REG_R1});
+  result.push_back({"r2", ARM_REG_R2});
+  result.push_back({"r3", ARM_REG_R3});
+  result.push_back({"r4", ARM_REG_R4});
+  result.push_back({"r5", ARM_REG_R5});
+  result.push_back({"r6", ARM_REG_R6});
+  result.push_back({"r7", ARM_REG_R7});
+  result.push_back({"r8", ARM_REG_R8});
+  result.push_back({"r9", ARM_REG_R9});
+  result.push_back({"r10", ARM_REG_R10});
+  result.push_back({"r11", ARM_REG_R11});
+  result.push_back({"ip", ARM_REG_R12});
+  result.push_back({"sp", ARM_REG_SP});
+  result.push_back({"lr", ARM_REG_LR});
+  result.push_back({"pc", ARM_REG_PC});
+  return result;
+}
+
+template<>
+std::vector<Register> ExpectedRegisters<RegsArm64>() {
+  std::vector<Register> result;
+  result.push_back({"x0", ARM64_REG_R0});
+  result.push_back({"x1", ARM64_REG_R1});
+  result.push_back({"x2", ARM64_REG_R2});
+  result.push_back({"x3", ARM64_REG_R3});
+  result.push_back({"x4", ARM64_REG_R4});
+  result.push_back({"x5", ARM64_REG_R5});
+  result.push_back({"x6", ARM64_REG_R6});
+  result.push_back({"x7", ARM64_REG_R7});
+  result.push_back({"x8", ARM64_REG_R8});
+  result.push_back({"x9", ARM64_REG_R9});
+  result.push_back({"x10", ARM64_REG_R10});
+  result.push_back({"x11", ARM64_REG_R11});
+  result.push_back({"x12", ARM64_REG_R12});
+  result.push_back({"x13", ARM64_REG_R13});
+  result.push_back({"x14", ARM64_REG_R14});
+  result.push_back({"x15", ARM64_REG_R15});
+  result.push_back({"x16", ARM64_REG_R16});
+  result.push_back({"x17", ARM64_REG_R17});
+  result.push_back({"x18", ARM64_REG_R18});
+  result.push_back({"x19", ARM64_REG_R19});
+  result.push_back({"x20", ARM64_REG_R20});
+  result.push_back({"x21", ARM64_REG_R21});
+  result.push_back({"x22", ARM64_REG_R22});
+  result.push_back({"x23", ARM64_REG_R23});
+  result.push_back({"x24", ARM64_REG_R24});
+  result.push_back({"x25", ARM64_REG_R25});
+  result.push_back({"x26", ARM64_REG_R26});
+  result.push_back({"x27", ARM64_REG_R27});
+  result.push_back({"x28", ARM64_REG_R28});
+  result.push_back({"x29", ARM64_REG_R29});
+  result.push_back({"sp", ARM64_REG_SP});
+  result.push_back({"lr", ARM64_REG_LR});
+  result.push_back({"pc", ARM64_REG_PC});
+  return result;
+}
+
+template<>
+std::vector<Register> ExpectedRegisters<RegsX86>() {
+  std::vector<Register> result;
+  result.push_back({"eax", X86_REG_EAX});
+  result.push_back({"ebx", X86_REG_EBX});
+  result.push_back({"ecx", X86_REG_ECX});
+  result.push_back({"edx", X86_REG_EDX});
+  result.push_back({"ebp", X86_REG_EBP});
+  result.push_back({"edi", X86_REG_EDI});
+  result.push_back({"esi", X86_REG_ESI});
+  result.push_back({"esp", X86_REG_ESP});
+  result.push_back({"eip", X86_REG_EIP});
+  return result;
+}
+
+template<>
+std::vector<Register> ExpectedRegisters<RegsX86_64>() {
+  std::vector<Register> result;
+  result.push_back({"rax", X86_64_REG_RAX});
+  result.push_back({"rbx", X86_64_REG_RBX});
+  result.push_back({"rcx", X86_64_REG_RCX});
+  result.push_back({"rdx", X86_64_REG_RDX});
+  result.push_back({"r8", X86_64_REG_R8});
+  result.push_back({"r9", X86_64_REG_R9});
+  result.push_back({"r10", X86_64_REG_R10});
+  result.push_back({"r11", X86_64_REG_R11});
+  result.push_back({"r12", X86_64_REG_R12});
+  result.push_back({"r13", X86_64_REG_R13});
+  result.push_back({"r14", X86_64_REG_R14});
+  result.push_back({"r15", X86_64_REG_R15});
+  result.push_back({"rdi", X86_64_REG_RDI});
+  result.push_back({"rsi", X86_64_REG_RSI});
+  result.push_back({"rbp", X86_64_REG_RBP});
+  result.push_back({"rsp", X86_64_REG_RSP});
+  result.push_back({"rip", X86_64_REG_RIP});
+  return result;
+}
+
+using RegTypes = ::testing::Types<RegsArm, RegsArm64, RegsX86, RegsX86_64>;
+TYPED_TEST_CASE(RegsIterateTest, RegTypes);
+
+TYPED_TEST(RegsIterateTest, iterate) {
+  std::vector<Register> expected = ExpectedRegisters<TypeParam>();
+  TypeParam regs;
+  for (const auto& reg : expected) {
+    regs[reg.offset] = reg.offset;
+  }
+
+  std::vector<Register> actual;
+  regs.IterateRegisters([&actual](const char* name, uint64_t value) {
+    actual.push_back({name, value});
+  });
+
+  ASSERT_EQ(expected, actual);
+}
+
+}  // namespace unwindstack
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 3589e6f..b70845b 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -84,6 +84,10 @@
         "libutils_headers",
     ],
 
+    shared_libs: [
+        "liblog",
+    ],
+
     arch: {
         mips: {
             cflags: ["-DALIGN_DOUBLE"],
@@ -102,7 +106,6 @@
                 "libbacktrace",
                 "libcutils",
                 "libdl",
-                "liblog",
                 "libvndksupport",
             ],
 
diff --git a/libutils/Unicode.cpp b/libutils/Unicode.cpp
index 5fd9155..e7520a8 100644
--- a/libutils/Unicode.cpp
+++ b/libutils/Unicode.cpp
@@ -297,23 +297,22 @@
 
 char16_t* strstr16(const char16_t* src, const char16_t* target)
 {
-    const char16_t needle = *target++;
-    const size_t target_len = strlen16(target);
-    if (needle != '\0') {
-      do {
+    const char16_t needle = *target;
+    if (needle == '\0') return (char16_t*)src;
+
+    const size_t target_len = strlen16(++target);
+    do {
         do {
-          if (*src == '\0') {
-            return nullptr;
-          }
+            if (*src == '\0') {
+                return nullptr;
+            }
         } while (*src++ != needle);
-      } while (strncmp16(src, target, target_len) != 0);
-      src--;
-    }
+    } while (strncmp16(src, target, target_len) != 0);
+    src--;
 
     return (char16_t*)src;
 }
 
-
 int strzcmp16(const char16_t *s1, size_t n1, const char16_t *s2, size_t n2)
 {
     const char16_t* e1 = s1+n1;
diff --git a/libutils/tests/Unicode_test.cpp b/libutils/tests/Unicode_test.cpp
index d23e43a..b92eef8 100644
--- a/libutils/tests/Unicode_test.cpp
+++ b/libutils/tests/Unicode_test.cpp
@@ -15,7 +15,11 @@
  */
 
 #define LOG_TAG "Unicode_test"
-#include <utils/Log.h>
+
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include <log/log.h>
 #include <utils/Unicode.h>
 
 #include <gtest/gtest.h>
@@ -119,6 +123,31 @@
             << "should return the original pointer";
 }
 
+TEST_F(UnicodeTest, strstr16EmptyTarget_bug) {
+    // In the original code when target is an empty string strlen16() would
+    // start reading the memory until a "terminating null" (that is, zero)
+    // character is found.   This happens because "*target++" in the original
+    // code would increment the pointer beyond the actual string.
+    void* memptr;
+    const size_t alignment = sysconf(_SC_PAGESIZE);
+    const size_t size = 2 * alignment;
+    ASSERT_EQ(posix_memalign(&memptr, alignment, size), 0);
+    // Fill allocated memory.
+    memset(memptr, 'A', size);
+    // Create a pointer to an "empty" string on the first page.
+    char16_t* const emptyString = (char16_t* const)((char*)memptr + alignment - 4);
+    *emptyString = (char16_t)0;
+    // Protect the second page to show that strstr16() violates that.
+    ASSERT_EQ(mprotect((char*)memptr + alignment, alignment, PROT_NONE), 0);
+    // Test strstr16(): when bug is present a segmentation fault is raised.
+    ASSERT_EQ(strstr16((char16_t*)memptr, emptyString), (char16_t*)memptr)
+        << "should not read beyond the first char16_t.";
+    // Reset protection of the second page
+    ASSERT_EQ(mprotect((char*)memptr + alignment, alignment, PROT_READ | PROT_WRITE), 0);
+    // Free allocated memory.
+    free(memptr);
+}
+
 TEST_F(UnicodeTest, strstr16SameString) {
     const char16_t* result = strstr16(kSearchString, kSearchString);
     EXPECT_EQ(kSearchString, result)
diff --git a/libvndksupport/linker.c b/libvndksupport/linker.c
index 289f153..696e978 100644
--- a/libvndksupport/linker.c
+++ b/libvndksupport/linker.c
@@ -31,7 +31,9 @@
         };
         void* handle = android_dlopen_ext(name, flag, &dlextinfo);
         if (!handle) {
-            ALOGE("Could not load %s from sphal namespace: %s.", name, dlerror());
+            ALOGE(
+                "Could not load %s from sphal namespace: %s. ",
+                name, dlerror());
         }
         return handle;
     } else {
@@ -43,4 +45,6 @@
     }
 }
 
-int android_unload_sphal_library(void* handle) { return dlclose(handle); }
+int android_unload_sphal_library(void* handle) {
+    return dlclose(handle);
+}
diff --git a/logd/LogTags.cpp b/logd/LogTags.cpp
index fcd45bd..ff7e762 100644
--- a/logd/LogTags.cpp
+++ b/logd/LogTags.cpp
@@ -105,7 +105,7 @@
                 android::base::WriteStringToFd(
                     formatEntry_locked(it.first, AID_ROOT), fd);
             }
-            TEMP_FAILURE_RETRY(close(fd));
+            close(fd);
         }
     }
 
@@ -601,7 +601,7 @@
 
     std::string ret = formatEntry_locked(tag, uid, false);
     android::base::WriteStringToFd(ret, fd);
-    TEMP_FAILURE_RETRY(close(fd));
+    close(fd);
 
     size_t size = 0;
     file2watermark_const_iterator iwater;
@@ -625,7 +625,7 @@
 
     std::string ret = formatEntry_locked(tag, uid, false);
     android::base::WriteStringToFd(ret, fd);
-    TEMP_FAILURE_RETRY(close(fd));
+    close(fd);
 
     size_t size = 0;
     file2watermark_const_iterator iwater;
diff --git a/logd/tests/AndroidTest.xml b/logd/tests/AndroidTest.xml
index b16bdfd..8704611 100644
--- a/logd/tests/AndroidTest.xml
+++ b/logd/tests/AndroidTest.xml
@@ -14,6 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Logging Daemon test cases">
+    <option name="config-descriptor:metadata" key="component" value="systems" />
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
         <option name="cleanup" value="true" />
         <option name="push" value="CtsLogdTestCases->/data/local/tmp/CtsLogdTestCases" />
diff --git a/qemu_pipe/Android.bp b/qemu_pipe/Android.bp
new file mode 100644
index 0000000..93c347b
--- /dev/null
+++ b/qemu_pipe/Android.bp
@@ -0,0 +1,14 @@
+// Copyright 2011 The Android Open Source Project
+
+cc_library_static {
+    name: "libqemu_pipe",
+    vendor_available: true,
+    sanitize: {
+        misc_undefined: ["integer"],
+    },
+    srcs: ["qemu_pipe.cpp"],
+    local_include_dirs: ["include"],
+    static_libs: ["libbase"],
+    export_include_dirs: ["include"],
+    cflags: ["-Werror"],
+}
diff --git a/qemu_pipe/include/qemu_pipe.h b/qemu_pipe/include/qemu_pipe.h
new file mode 100644
index 0000000..0987498
--- /dev/null
+++ b/qemu_pipe/include/qemu_pipe.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+#ifndef ANDROID_CORE_INCLUDE_QEMU_PIPE_H
+#define ANDROID_CORE_INCLUDE_QEMU_PIPE_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+// Try to open a new Qemu fast-pipe. This function returns a file descriptor
+// that can be used to communicate with a named service managed by the
+// emulator.
+//
+// This file descriptor can be used as a standard pipe/socket descriptor.
+//
+// 'pipeName' is the name of the emulator service you want to connect to,
+// and should begin with 'pipe:' (e.g. 'pipe:camera' or 'pipe:opengles').
+// For backward compatibility, the 'pipe:' prefix can be omitted, and in
+// that case, qemu_pipe_open will add it for you.
+
+// On success, return a valid file descriptor, or -1/errno on failure. E.g.:
+//
+// EINVAL  -> unknown/unsupported pipeName
+// ENOSYS  -> fast pipes not available in this system.
+//
+// ENOSYS should never happen, except if you're trying to run within a
+// misconfigured emulator.
+//
+// You should be able to open several pipes to the same pipe service,
+// except for a few special cases (e.g. GSM modem), where EBUSY will be
+// returned if more than one client tries to connect to it.
+int qemu_pipe_open(const char* pipeName);
+
+// Send a framed message |buff| of |len| bytes through the |fd| descriptor.
+// This really adds a 4-hexchar prefix describing the payload size.
+// Returns 0 on success, and -1 on error.
+int qemu_pipe_frame_send(int fd, const void* buff, size_t len);
+
+// Read a frame message from |fd|, and store it into |buff| of |len| bytes.
+// If the framed message is larger than |len|, then this returns -1 and the
+// content is lost. Otherwise, this returns the size of the message. NOTE:
+// empty messages are possible in a framed wire protocol and do not mean
+// end-of-stream.
+int qemu_pipe_frame_recv(int fd, void* buff, size_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ANDROID_CORE_INCLUDE_QEMU_PIPE_H */
diff --git a/qemu_pipe/qemu_pipe.cpp b/qemu_pipe/qemu_pipe.cpp
new file mode 100644
index 0000000..beeccb0
--- /dev/null
+++ b/qemu_pipe/qemu_pipe.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2011 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 "qemu_pipe.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include <android-base/file.h>
+
+using android::base::ReadFully;
+using android::base::WriteFully;
+
+// Define QEMU_PIPE_DEBUG if you want to print error messages when an error
+// occurs during pipe operations. The macro should simply take a printf-style
+// formatting string followed by optional arguments.
+#ifndef QEMU_PIPE_DEBUG
+#  define  QEMU_PIPE_DEBUG(...)   (void)0
+#endif
+
+int qemu_pipe_open(const char* pipeName) {
+    // Sanity check.
+    if (!pipeName) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    int fd = TEMP_FAILURE_RETRY(open("/dev/qemu_pipe", O_RDWR));
+    if (fd < 0) {
+        QEMU_PIPE_DEBUG("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__,
+                        strerror(errno));
+        return -1;
+    }
+
+    // Write the pipe name, *including* the trailing zero which is necessary.
+    size_t pipeNameLen = strlen(pipeName);
+    if (WriteFully(fd, pipeName, pipeNameLen + 1U)) {
+        return fd;
+    }
+
+    // now, add 'pipe:' prefix and try again
+    // Note: host side will wait for the trailing '\0' to start
+    // service lookup.
+    const char pipe_prefix[] = "pipe:";
+    if (WriteFully(fd, pipe_prefix, strlen(pipe_prefix)) &&
+            WriteFully(fd, pipeName, pipeNameLen + 1U)) {
+        return fd;
+    }
+    QEMU_PIPE_DEBUG("%s: Could not write to %s pipe service: %s",
+            __FUNCTION__, pipeName, strerror(errno));
+    close(fd);
+    return -1;
+}
+
+int qemu_pipe_frame_send(int fd, const void* buff, size_t len) {
+    char header[5];
+    snprintf(header, sizeof(header), "%04zx", len);
+    if (!WriteFully(fd, header, 4)) {
+        QEMU_PIPE_DEBUG("Can't write qemud frame header: %s", strerror(errno));
+        return -1;
+    }
+    if (!WriteFully(fd, buff, len)) {
+        QEMU_PIPE_DEBUG("Can't write qemud frame payload: %s", strerror(errno));
+        return -1;
+    }
+    return 0;
+}
+
+int qemu_pipe_frame_recv(int fd, void* buff, size_t len) {
+    char header[5];
+    if (!ReadFully(fd, header, 4)) {
+        QEMU_PIPE_DEBUG("Can't read qemud frame header: %s", strerror(errno));
+        return -1;
+    }
+    header[4] = '\0';
+    size_t size;
+    if (sscanf(header, "%04zx", &size) != 1) {
+        QEMU_PIPE_DEBUG("Malformed qemud frame header: [%.*s]", 4, header);
+        return -1;
+    }
+    if (size > len) {
+        QEMU_PIPE_DEBUG("Oversized qemud frame (% bytes, expected <= %)", size,
+                        len);
+        return -1;
+    }
+    if (!ReadFully(fd, buff, size)) {
+        QEMU_PIPE_DEBUG("Could not read qemud frame payload: %s",
+                        strerror(errno));
+        return -1;
+    }
+    return size;
+}
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index fd46251..21f24f2 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -101,6 +101,21 @@
   $(foreach binary, $(SANITIZE_ASAN_OPTIONS_FOR), $(eval $(call create-asan-options-module,$(binary))))
 endif
 
+# ASAN extration.
+ASAN_EXTRACT_FILES :=
+ifeq ($(SANITIZE_TARGET_SYSTEM),true)
+include $(CLEAR_VARS)
+LOCAL_MODULE:= asan_extract
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_SRC_FILES := asan_extract.sh
+LOCAL_INIT_RC := asan_extract.rc
+# We need bzip2 on device for extraction.
+LOCAL_REQUIRED_MODULES := bzip2
+include $(BUILD_PREBUILT)
+ASAN_EXTRACT_FILES := asan_extract
+endif
+
 endif
 
 #######################################
@@ -114,7 +129,7 @@
 EXPORT_GLOBAL_ASAN_OPTIONS :=
 ifneq ($(filter address,$(SANITIZE_TARGET)),)
   EXPORT_GLOBAL_ASAN_OPTIONS := export ASAN_OPTIONS include=/system/asan.options
-  LOCAL_REQUIRED_MODULES := asan.options $(ASAN_OPTIONS_FILES)
+  LOCAL_REQUIRED_MODULES := asan.options $(ASAN_OPTIONS_FILES) $(ASAN_EXTRACT_FILES)
 endif
 
 EXPORT_GLOBAL_GCOV_OPTIONS :=
diff --git a/rootdir/asan_extract.rc b/rootdir/asan_extract.rc
new file mode 100644
index 0000000..4aea6a3
--- /dev/null
+++ b/rootdir/asan_extract.rc
@@ -0,0 +1,3 @@
+# When /data is available, look for /system/asan.tar.gz and potentially extract.
+on post-fs-data
+    exec - system system -- /system/bin/asan_extract
diff --git a/rootdir/asan_extract.sh b/rootdir/asan_extract.sh
new file mode 100644
index 0000000..2d72320
--- /dev/null
+++ b/rootdir/asan_extract.sh
@@ -0,0 +1,95 @@
+#!/system/bin/sh
+
+#
+# Copyright (C) 2017 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.
+#
+
+# This script will extract ASAN libraries from /system/asan.tar.gz to /data and then reboot.
+
+# TODO:
+#   * Timestamp or something to know when to run this again. Right now take the existence of
+#     /data/lib as we're already done.
+#   * Need to distinguish pre- from post-decryption for FDE.
+
+SRC=/system/asan.tar.bz2
+MD5_FILE=/data/asan.md5sum
+ASAN_DIR=/data/asan
+# Minimum /data size in blocks. Arbitrarily 512M.
+MIN_DATA_SIZE=131072
+
+# Checks for FDE pre-decrypt state.
+
+VOLD_STATUS=$(getprop vold.decrypt)
+if [ "$VOLD_STATUS" = "trigger_restart_min_framework" ] ; then
+  log -p i -t asan_install "Pre-decrypt FDE detected (by vold property)!"
+  exit 1
+fi
+
+STATFS_BLOCKS=$(stat -f -c '%b' /data)
+if [ "$STATFS_BLOCKS" -le "$MIN_DATA_SIZE" ] ; then
+  log -p i -t asan_install "Pre-decrypt FDE detected (by /data size)!"
+  exit 1
+fi
+
+# Check for ASAN source.
+
+if ! test -f $SRC ; then
+  log -p i -t asan_install "Did not find $SRC!"
+  exit 1
+fi
+
+log -p i -t asan_install "Found $SRC, checking whether we need to apply it."
+
+# Checksum check.
+
+ASAN_TAR_MD5=$(md5sum $SRC)
+if test -f $MD5_FILE ; then
+  INSTALLED_MD5=$(cat $MD5_FILE)
+  if [ "x$ASAN_TAR_MD5" = "x$INSTALLED_MD5" ] ; then
+    log -p i -t asan_install "Checksums match, nothing to be done here."
+    exit 0
+  fi
+fi
+
+# Actually apply the source.
+
+# Just clean up, helps with restorecon.
+rm -rf $ASAN_DIR
+
+log -p i -t asan_install "Untarring $SRC..."
+
+# Unzip from /system/asan.tar.gz into data. Need to pipe as gunzip is not on device.
+bzip2 -c -d $SRC | tar -x -f - --no-same-owner -C / || exit 1
+
+# Cannot log here, log would run with system_data_file.
+
+# Set correct permission bits.
+chmod -R 744 $ASAN_DIR
+cd $ASAN_DIR ; find . -type d -exec chmod 755 {} \;
+
+restorecon -R -F $ASAN_DIR/*/lib*
+
+log -p i -t asan_install "Fixed selinux labels..."
+
+
+# Now write down our checksum to mark the extraction complete.
+echo "$ASAN_TAR_MD5" > $MD5_FILE
+
+# We want to reboot now. It seems it is not possible to run "reboot" here, the device will
+# just be stuck.
+
+log -p i -t asan_install "Signaling init to reboot..."
+
+setprop sys.powerctl reboot
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index ce354f2..b4a0158 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -88,7 +88,7 @@
 namespace.rs.asan.permitted.paths = /data/asan/vendor/${LIB}:/vendor/${LIB}:/data
 
 namespace.rs.links = default,vndk
-namespace.rs.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so:libmediandk.so:libui.so:libvndksupport.so
+namespace.rs.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so:libmediandk.so:libvndksupport.so
 namespace.rs.link.vndk.shared_libs = android.hardware.renderscript@1.0.so:android.hardware.graphics.allocator@2.0.so:android.hardware.graphics.mapper@2.0.so:android.hardware.graphics.common@1.0.so:android.hidl.memory@1.0.so:libhwbinder.so:libbase.so:libcutils.so:libhardware.so:libhidlbase.so:libhidlmemory.so:libhidltransport.so:libion.so:libutils.so:libc++.so
 
 ###############################################################################
diff --git a/rootdir/init.rc b/rootdir/init.rc
index d503ffe..917e99d 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -61,18 +61,22 @@
     mkdir /dev/stune/foreground
     mkdir /dev/stune/background
     mkdir /dev/stune/top-app
+    mkdir /dev/stune/rt
     chown system system /dev/stune
     chown system system /dev/stune/foreground
     chown system system /dev/stune/background
     chown system system /dev/stune/top-app
+    chown system system /dev/stune/rt
     chown system system /dev/stune/tasks
     chown system system /dev/stune/foreground/tasks
     chown system system /dev/stune/background/tasks
     chown system system /dev/stune/top-app/tasks
+    chown system system /dev/stune/rt/tasks
     chmod 0664 /dev/stune/tasks
     chmod 0664 /dev/stune/foreground/tasks
     chmod 0664 /dev/stune/background/tasks
     chmod 0664 /dev/stune/top-app/tasks
+    chmod 0664 /dev/stune/rt/tasks
 
     # Mount staging areas for devices managed by vold
     # See storage config details at http://source.android.com/tech/storage/
diff --git a/trusty/keymaster/trusty_keymaster_device.cpp b/trusty/keymaster/trusty_keymaster_device.cpp
index 55a03bd..b8c2032 100644
--- a/trusty/keymaster/trusty_keymaster_device.cpp
+++ b/trusty/keymaster/trusty_keymaster_device.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "TrustyKeymaster"
 
 #include <assert.h>
+#include <errno.h>
 #include <openssl/evp.h>
 #include <openssl/x509.h>
 #include <stddef.h>