Merge "Simplified stats_event.c; exposed getter methods"
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 9b663be..460ddde 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -1167,7 +1167,7 @@
         std::string host;
         int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
         std::string error;
-        if (address.starts_with("vsock:")) {
+        if (address.starts_with("vsock:") || address.starts_with("localfilesystem:")) {
             serial = address;
         } else if (!android::base::ParseNetAddress(address, &host, &port, &serial, &error)) {
             SendFail(reply_fd, android::base::StringPrintf("couldn't parse '%s': %s",
diff --git a/adb/adb.h b/adb/adb.h
index c6cb06a..e7fcc91 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -200,7 +200,7 @@
 #define ADB_SUBCLASS 0x42
 #define ADB_PROTOCOL 0x1
 
-void local_init(int port);
+void local_init(const std::string& addr);
 bool local_connect(int port);
 int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* error);
 
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 0c5c28f..e5ffe4c 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -129,7 +129,7 @@
     }
 
     if (!getenv("ADB_EMU") || strcmp(getenv("ADB_EMU"), "0") != 0) {
-        local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
+        local_init(android::base::StringPrintf("tcp:%d", DEFAULT_ADB_LOCAL_TRANSPORT_PORT));
     }
 
     std::string error;
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index 7277cc8..3322574 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -32,11 +32,13 @@
 #include <sys/prctl.h>
 
 #include <memory>
+#include <vector>
 
 #include <android-base/logging.h>
 #include <android-base/macros.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 
 #if defined(__ANDROID__)
 #include <libminijail.h>
@@ -51,6 +53,7 @@
 #include "adb_auth.h"
 #include "adb_listeners.h"
 #include "adb_utils.h"
+#include "socket_spec.h"
 #include "transport.h"
 
 #include "mdns.h"
@@ -179,12 +182,26 @@
 }
 #endif
 
-static void setup_port(int port) {
-    LOG(INFO) << "adbd listening on port " << port;
-    local_init(port);
+static void setup_adb(const std::vector<std::string>& addrs) {
 #if defined(__ANDROID__)
+    // Get the first valid port from addrs and setup mDNS.
+    int port = -1;
+    std::string error;
+    for (const auto& addr : addrs) {
+        port = get_host_socket_spec_port(addr, &error);
+        if (port != -1) {
+            break;
+        }
+    }
+    if (port == -1) {
+        port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
+    }
     setup_mdns(port);
 #endif
+    for (const auto& addr : addrs) {
+        LOG(INFO) << "adbd listening on " << addr;
+        local_init(addr);
+    }
 }
 
 int adbd_main(int server_port) {
@@ -248,25 +265,38 @@
     // If one of these properties is set, also listen on that port.
     // If one of the properties isn't set and we couldn't listen on usb, listen
     // on the default port.
-    std::string prop_port = android::base::GetProperty("service.adb.tcp.port", "");
-    if (prop_port.empty()) {
-        prop_port = android::base::GetProperty("persist.adb.tcp.port", "");
-    }
+    std::vector<std::string> addrs;
+    std::string prop_addr = android::base::GetProperty("service.adb.listen_addrs", "");
+    if (prop_addr.empty()) {
+        std::string prop_port = android::base::GetProperty("service.adb.tcp.port", "");
+        if (prop_port.empty()) {
+            prop_port = android::base::GetProperty("persist.adb.tcp.port", "");
+        }
 
 #if !defined(__ANDROID__)
-    if (prop_port.empty() && getenv("ADBD_PORT")) {
-        prop_port = getenv("ADBD_PORT");
-    }
+        if (prop_port.empty() && getenv("ADBD_PORT")) {
+            prop_port = getenv("ADBD_PORT");
+        }
 #endif
 
-    int port;
-    if (sscanf(prop_port.c_str(), "%d", &port) == 1 && port > 0) {
-        D("using port=%d", port);
-        // Listen on TCP port specified by service.adb.tcp.port property.
-        setup_port(port);
-    } else if (!is_usb) {
-        // Listen on default port.
-        setup_port(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
+        int port;
+        if (sscanf(prop_port.c_str(), "%d", &port) == 1 && port > 0) {
+            D("using tcp port=%d", port);
+            // Listen on TCP and VSOCK port specified by service.adb.tcp.port property.
+            addrs.push_back(android::base::StringPrintf("tcp:%d", port));
+            addrs.push_back(android::base::StringPrintf("vsock:%d", port));
+            setup_adb(addrs);
+        } else if (!is_usb) {
+            // Listen on default port.
+            addrs.push_back(
+                    android::base::StringPrintf("tcp:%d", DEFAULT_ADB_LOCAL_TRANSPORT_PORT));
+            addrs.push_back(
+                    android::base::StringPrintf("vsock:%d", DEFAULT_ADB_LOCAL_TRANSPORT_PORT));
+            setup_adb(addrs);
+        }
+    } else {
+        addrs = android::base::Split(prop_addr, ",");
+        setup_adb(addrs);
     }
 
     D("adbd_main(): pre init_jdwp()");
diff --git a/adb/daemon/transport_qemu.cpp b/adb/daemon/transport_qemu.cpp
index aa760bc..901efee 100644
--- a/adb/daemon/transport_qemu.cpp
+++ b/adb/daemon/transport_qemu.cpp
@@ -18,6 +18,7 @@
 #include <qemu_pipe.h>
 
 #define TRACE_TAG TRANSPORT
+#include "socket_spec.h"
 #include "sysdeps.h"
 #include "transport.h"
 
@@ -55,7 +56,7 @@
  *   the transport registration is completed. That's why we need to send the
  *   'start' request after the transport is registered.
  */
-void qemu_socket_thread(int port) {
+void qemu_socket_thread(std::string_view addr) {
     /* 'accept' request to the adb QEMUD service. */
     static const char _accept_req[] = "accept";
     /* 'start' request to the adb QEMUD service. */
@@ -69,6 +70,12 @@
     adb_thread_setname("qemu socket");
     D("transport: qemu_socket_thread() starting");
 
+    std::string error;
+    int port = get_host_socket_spec_port(addr, &error);
+    if (port == -1) {
+        port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
+    }
+
     /* adb QEMUD service connection request. */
     snprintf(con_name, sizeof(con_name), "pipe:qemud:adb:%d", port);
 
@@ -78,7 +85,7 @@
         /* This could be an older version of the emulator, that doesn't
          * implement adb QEMUD service. Fall back to the old TCP way. */
         D("adb service is not available. Falling back to TCP socket.");
-        std::thread(server_socket_thread, tcp_listen_inaddr_any, port).detach();
+        std::thread(server_socket_thread, adb_listen, addr).detach();
         return;
     }
 
diff --git a/adb/fastdeploy/deploypatchgenerator/apk_archive.cpp b/adb/fastdeploy/deploypatchgenerator/apk_archive.cpp
index 3dc5e50..932d579 100644
--- a/adb/fastdeploy/deploypatchgenerator/apk_archive.cpp
+++ b/adb/fastdeploy/deploypatchgenerator/apk_archive.cpp
@@ -36,7 +36,7 @@
     FileRegion(borrowed_fd fd, off64_t offset, size_t length)
         : mapped_(android::base::MappedFile::FromOsHandle(adb_get_os_handle(fd), offset, length,
                                                           PROT_READ)) {
-        if (mapped_.data() != nullptr) {
+        if (mapped_ != nullptr) {
             return;
         }
 
@@ -50,14 +50,14 @@
         }
     }
 
-    const char* data() const { return mapped_.data() ? mapped_.data() : buffer_.data(); }
-    size_t size() const { return mapped_.data() ? mapped_.size() : buffer_.size(); }
+    const char* data() const { return mapped_ ? mapped_->data() : buffer_.data(); }
+    size_t size() const { return mapped_ ? mapped_->size() : buffer_.size(); }
 
   private:
     FileRegion() = default;
     DISALLOW_COPY_AND_ASSIGN(FileRegion);
 
-    android::base::MappedFile mapped_;
+    std::unique_ptr<android::base::MappedFile> mapped_;
     std::string buffer_;
 };
 }  // namespace
diff --git a/adb/socket_spec.cpp b/adb/socket_spec.cpp
index 9ce443e..d17036c 100644
--- a/adb/socket_spec.cpp
+++ b/adb/socket_spec.cpp
@@ -122,6 +122,41 @@
     return true;
 }
 
+int get_host_socket_spec_port(std::string_view spec, std::string* error) {
+    int port;
+    if (spec.starts_with("tcp:")) {
+        if (!parse_tcp_socket_spec(spec, nullptr, &port, nullptr, error)) {
+            return -1;
+        }
+    } else if (spec.starts_with("vsock:")) {
+#if ADB_LINUX
+        std::string spec_str(spec);
+        std::vector<std::string> fragments = android::base::Split(spec_str, ":");
+        if (fragments.size() != 2) {
+            *error = "given vsock server socket string was invalid";
+            return -1;
+        }
+        if (!android::base::ParseInt(fragments[1], &port)) {
+            *error = "could not parse vsock port";
+            errno = EINVAL;
+            return -1;
+        }
+        if (port < 0) {
+            *error = "vsock port was negative.";
+            errno = EINVAL;
+            return -1;
+        }
+#else   // ADB_LINUX
+        *error = "vsock is only supported on linux";
+        return -1;
+#endif  // ADB_LINUX
+    } else {
+        *error = "given socket spec string was invalid";
+        return -1;
+    }
+    return port;
+}
+
 static bool tcp_host_is_local(std::string_view hostname) {
     // FIXME
     return hostname.empty() || hostname == "localhost";
@@ -254,6 +289,14 @@
 
             fd->reset(network_local_client(&address[prefix.length()], it.second.socket_namespace,
                                            SOCK_STREAM, error));
+
+            if (fd->get() < 0) {
+                *error =
+                        android::base::StringPrintf("could not connect to %s address '%s'",
+                                                    it.first.c_str(), std::string(address).c_str());
+                return false;
+            }
+
             if (serial) {
                 *serial = address;
             }
@@ -275,7 +318,11 @@
         }
 
         int result;
+#if ADB_HOST
         if (hostname.empty() && gListenAll) {
+#else
+        if (hostname.empty()) {
+#endif
             result = network_inaddr_any_server(port, SOCK_STREAM, error);
         } else if (tcp_host_is_local(hostname)) {
             result = network_loopback_server(port, SOCK_STREAM, error, true);
diff --git a/adb/socket_spec.h b/adb/socket_spec.h
index 7cc2fac..94719c8 100644
--- a/adb/socket_spec.h
+++ b/adb/socket_spec.h
@@ -31,3 +31,5 @@
 
 bool parse_tcp_socket_spec(std::string_view spec, std::string* hostname, int* port,
                            std::string* serial, std::string* error);
+
+int get_host_socket_spec_port(std::string_view spec, std::string* error);
diff --git a/adb/socket_spec_test.cpp b/adb/socket_spec_test.cpp
index 3a2f60c..e9d5270 100644
--- a/adb/socket_spec_test.cpp
+++ b/adb/socket_spec_test.cpp
@@ -18,6 +18,10 @@
 
 #include <string>
 
+#include <unistd.h>
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
 #include <gtest/gtest.h>
 
 TEST(socket_spec, parse_tcp_socket_spec_just_port) {
@@ -88,3 +92,63 @@
     EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]:", &hostname, &port, &serial, &error));
     EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]:-1", &hostname, &port, &serial, &error));
 }
+
+TEST(socket_spec, get_host_socket_spec_port) {
+    std::string error;
+    EXPECT_EQ(5555, get_host_socket_spec_port("tcp:5555", &error));
+    EXPECT_EQ(5555, get_host_socket_spec_port("tcp:localhost:5555", &error));
+    EXPECT_EQ(5555, get_host_socket_spec_port("tcp:[::1]:5555", &error));
+    EXPECT_EQ(5555, get_host_socket_spec_port("vsock:5555", &error));
+}
+
+TEST(socket_spec, get_host_socket_spec_port_no_port) {
+    std::string error;
+    EXPECT_EQ(5555, get_host_socket_spec_port("tcp:localhost", &error));
+    EXPECT_EQ(-1, get_host_socket_spec_port("vsock:localhost", &error));
+}
+
+TEST(socket_spec, get_host_socket_spec_port_bad_ports) {
+    std::string error;
+    EXPECT_EQ(-1, get_host_socket_spec_port("tcp:65536", &error));
+    EXPECT_EQ(-1, get_host_socket_spec_port("tcp:-5", &error));
+    EXPECT_EQ(-1, get_host_socket_spec_port("vsock:-5", &error));
+    EXPECT_EQ(-1, get_host_socket_spec_port("vsock:5:5555", &error));
+}
+
+TEST(socket_spec, get_host_socket_spec_port_bad_string) {
+    std::string error;
+    EXPECT_EQ(-1, get_host_socket_spec_port("tcpz:5555", &error));
+    EXPECT_EQ(-1, get_host_socket_spec_port("vsockz:5555", &error));
+    EXPECT_EQ(-1, get_host_socket_spec_port("abcd:5555", &error));
+    EXPECT_EQ(-1, get_host_socket_spec_port("abcd", &error));
+}
+
+TEST(socket_spec, socket_spec_listen_connect_tcp) {
+    std::string error, serial;
+    int port;
+    unique_fd server_fd, client_fd;
+    EXPECT_FALSE(socket_spec_connect(&client_fd, "tcp:localhost:7777", &port, &serial, &error));
+    server_fd.reset(socket_spec_listen("tcp:7777", &error, &port));
+    EXPECT_NE(server_fd.get(), -1);
+    EXPECT_TRUE(socket_spec_connect(&client_fd, "tcp:localhost:7777", &port, &serial, &error));
+    EXPECT_NE(client_fd.get(), -1);
+}
+
+TEST(socket_spec, socket_spec_listen_connect_localfilesystem) {
+    std::string error, serial;
+    int port;
+    unique_fd server_fd, client_fd;
+    TemporaryDir sock_dir;
+
+    // Only run this test if the created directory is writable.
+    int result = access(sock_dir.path, W_OK);
+    if (result == 0) {
+        std::string sock_addr =
+                android::base::StringPrintf("localfilesystem:%s/af_unix_socket", sock_dir.path);
+        EXPECT_FALSE(socket_spec_connect(&client_fd, sock_addr, &port, &serial, &error));
+        server_fd.reset(socket_spec_listen(sock_addr, &error, &port));
+        EXPECT_NE(server_fd.get(), -1);
+        EXPECT_TRUE(socket_spec_connect(&client_fd, sock_addr, &port, &serial, &error));
+        EXPECT_NE(client_fd.get(), -1);
+    }
+}
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index 7d5bf17..423af67 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -625,7 +625,8 @@
         return true;
     };
 
-    static constexpr std::string_view prefixes[] = {"usb:", "product:", "model:", "device:"};
+    static constexpr std::string_view prefixes[] = {
+            "usb:", "product:", "model:", "device:", "localfilesystem:"};
     for (std::string_view prefix : prefixes) {
         if (command.starts_with(prefix)) {
             consume(prefix.size());
diff --git a/adb/transport.h b/adb/transport.h
index ea77117..569e8bb 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -424,11 +424,12 @@
 asocket* create_device_tracker(bool long_output);
 
 #if !ADB_HOST
-unique_fd tcp_listen_inaddr_any(int port, std::string* error);
-void server_socket_thread(std::function<unique_fd(int, std::string*)> listen_func, int port);
+unique_fd adb_listen(std::string_view addr, std::string* error);
+void server_socket_thread(std::function<unique_fd(std::string_view, std::string*)> listen_func,
+                          std::string_view addr);
 
 #if defined(__ANDROID__)
-void qemu_socket_thread(int port);
+void qemu_socket_thread(std::string_view addr);
 bool use_qemu_goldfish();
 #endif
 
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index b9f738d..c726186 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -85,22 +85,6 @@
     return local_connect_arbitrary_ports(port - 1, port, &dummy) == 0;
 }
 
-std::tuple<unique_fd, int, std::string> tcp_connect(const std::string& address,
-                                                    std::string* response) {
-    unique_fd fd;
-    int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
-    std::string serial;
-    std::string prefix_addr = address.starts_with("vsock:") ? address : "tcp:" + address;
-    if (socket_spec_connect(&fd, prefix_addr, &port, &serial, response)) {
-        close_on_exec(fd);
-        if (!set_tcp_keepalive(fd, 1)) {
-            D("warning: failed to configure TCP keepalives (%s)", strerror(errno));
-        }
-        return std::make_tuple(std::move(fd), port, serial);
-    }
-    return std::make_tuple(unique_fd(), 0, serial);
-}
-
 void connect_device(const std::string& address, std::string* response) {
     if (address.empty()) {
         *response = "empty address";
@@ -110,17 +94,25 @@
     D("connection requested to '%s'", address.c_str());
     unique_fd fd;
     int port;
-    std::string serial;
-    std::tie(fd, port, serial) = tcp_connect(address, response);
+    std::string serial, prefix_addr;
+
+    // If address does not match any socket type, it should default to TCP.
+    if (address.starts_with("vsock:") || address.starts_with("localfilesystem:")) {
+        prefix_addr = address;
+    } else {
+        prefix_addr = "tcp:" + address;
+    }
+
+    socket_spec_connect(&fd, prefix_addr, &port, &serial, response);
     if (fd.get() == -1) {
         return;
     }
-    auto reconnect = [address](atransport* t) {
+    auto reconnect = [prefix_addr](atransport* t) {
         std::string response;
         unique_fd fd;
         int port;
         std::string serial;
-        std::tie(fd, port, serial) = tcp_connect(address, &response);
+        socket_spec_connect(&fd, prefix_addr, &port, &serial, &response);
         if (fd == -1) {
             D("reconnect failed: %s", response.c_str());
             return ReconnectResult::Retry;
@@ -203,7 +195,7 @@
 std::mutex &retry_ports_lock = *new std::mutex;
 std::condition_variable &retry_ports_cond = *new std::condition_variable;
 
-static void client_socket_thread(int) {
+static void client_socket_thread(std::string_view) {
     adb_thread_setname("client_socket_thread");
     D("transport: client_socket_thread() starting");
     PollAllLocalPortsForEmulator();
@@ -248,7 +240,8 @@
 
 #else  // !ADB_HOST
 
-void server_socket_thread(std::function<unique_fd(int, std::string*)> listen_func, int port) {
+void server_socket_thread(std::function<unique_fd(std::string_view, std::string*)> listen_func,
+                          std::string_view addr) {
     adb_thread_setname("server socket");
 
     unique_fd serverfd;
@@ -256,7 +249,7 @@
 
     while (serverfd == -1) {
         errno = 0;
-        serverfd = listen_func(port, &error);
+        serverfd = listen_func(addr, &error);
         if (errno == EAFNOSUPPORT || errno == EINVAL || errno == EPROTONOSUPPORT) {
             D("unrecoverable error: '%s'", error.c_str());
             return;
@@ -276,7 +269,9 @@
             close_on_exec(fd.get());
             disable_tcp_nagle(fd.get());
             std::string serial = android::base::StringPrintf("host-%d", fd.get());
-            register_socket_transport(std::move(fd), std::move(serial), port, 1,
+            // We don't care about port value in "register_socket_transport" as it is used
+            // only from ADB_HOST. "server_socket_thread" is never called from ADB_HOST.
+            register_socket_transport(std::move(fd), std::move(serial), 0, 1,
                                       [](atransport*) { return ReconnectResult::Abort; });
         }
     }
@@ -285,38 +280,30 @@
 
 #endif
 
-unique_fd tcp_listen_inaddr_any(int port, std::string* error) {
-    return unique_fd{network_inaddr_any_server(port, SOCK_STREAM, error)};
-}
-
 #if !ADB_HOST
-static unique_fd vsock_listen(int port, std::string* error) {
-    return unique_fd{
-        socket_spec_listen(android::base::StringPrintf("vsock:%d", port), error, nullptr)
-    };
+unique_fd adb_listen(std::string_view addr, std::string* error) {
+    return unique_fd{socket_spec_listen(addr, error, nullptr)};
 }
 #endif
 
-void local_init(int port) {
+void local_init(const std::string& addr) {
 #if ADB_HOST
     D("transport: local client init");
-    std::thread(client_socket_thread, port).detach();
+    std::thread(client_socket_thread, addr).detach();
     adb_local_transport_max_port_env_override();
 #elif !defined(__ANDROID__)
     // Host adbd.
     D("transport: local server init");
-    std::thread(server_socket_thread, tcp_listen_inaddr_any, port).detach();
-    std::thread(server_socket_thread, vsock_listen, port).detach();
+    std::thread(server_socket_thread, adb_listen, addr).detach();
 #else
     D("transport: local server init");
     // For the adbd daemon in the system image we need to distinguish
     // between the device, and the emulator.
-    if (use_qemu_goldfish()) {
-        std::thread(qemu_socket_thread, port).detach();
+    if (addr.starts_with("tcp:") && use_qemu_goldfish()) {
+        std::thread(qemu_socket_thread, addr).detach();
     } else {
-        std::thread(server_socket_thread, tcp_listen_inaddr_any, port).detach();
+        std::thread(server_socket_thread, adb_listen, addr).detach();
     }
-    std::thread(server_socket_thread, vsock_listen, port).detach();
 #endif // !ADB_HOST
 }
 
diff --git a/base/include/android-base/mapped_file.h b/base/include/android-base/mapped_file.h
index 6a19f1b..8c37f43 100644
--- a/base/include/android-base/mapped_file.h
+++ b/base/include/android-base/mapped_file.h
@@ -53,7 +53,8 @@
   /**
    * Same thing, but using the raw OS file handle instead of a CRT wrapper.
    */
-  static MappedFile FromOsHandle(os_handle h, off64_t offset, size_t length, int prot);
+  static std::unique_ptr<MappedFile> FromOsHandle(os_handle h, off64_t offset, size_t length,
+                                                  int prot);
 
   /**
    * Removes the mapping.
@@ -69,10 +70,6 @@
   char* data() const { return base_ + offset_; }
   size_t size() const { return size_; }
 
-  bool isValid() const { return base_ != nullptr; }
-
-  explicit operator bool() const { return isValid(); }
-
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(MappedFile);
 
diff --git a/base/mapped_file.cpp b/base/mapped_file.cpp
index 862b73b..fff3453 100644
--- a/base/mapped_file.cpp
+++ b/base/mapped_file.cpp
@@ -38,15 +38,14 @@
 std::unique_ptr<MappedFile> MappedFile::FromFd(borrowed_fd fd, off64_t offset, size_t length,
                                                int prot) {
 #if defined(_WIN32)
-  auto file =
-      FromOsHandle(reinterpret_cast<HANDLE>(_get_osfhandle(fd.get())), offset, length, prot);
+  return FromOsHandle(reinterpret_cast<HANDLE>(_get_osfhandle(fd.get())), offset, length, prot);
 #else
-  auto file = FromOsHandle(fd.get(), offset, length, prot);
+  return FromOsHandle(fd.get(), offset, length, prot);
 #endif
-  return file ? std::make_unique<MappedFile>(std::move(file)) : std::unique_ptr<MappedFile>{};
 }
 
-MappedFile MappedFile::FromOsHandle(os_handle h, off64_t offset, size_t length, int prot) {
+std::unique_ptr<MappedFile> MappedFile::FromOsHandle(os_handle h, off64_t offset, size_t length,
+                                                     int prot) {
   static const off64_t page_size = InitPageSize();
   size_t slop = offset % page_size;
   off64_t file_offset = offset - slop;
@@ -59,28 +58,30 @@
     // http://b/119818070 "app crashes when reading asset of zero length".
     // Return a MappedFile that's only valid for reading the size.
     if (length == 0 && ::GetLastError() == ERROR_FILE_INVALID) {
-      return MappedFile{const_cast<char*>(kEmptyBuffer), 0, 0, nullptr};
+      return std::unique_ptr<MappedFile>(
+          new MappedFile(const_cast<char*>(kEmptyBuffer), 0, 0, nullptr));
     }
-    return MappedFile(nullptr, 0, 0, nullptr);
+    return nullptr;
   }
   void* base = MapViewOfFile(handle, (prot & PROT_WRITE) ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ, 0,
                              file_offset, file_length);
   if (base == nullptr) {
     CloseHandle(handle);
-    return MappedFile(nullptr, 0, 0, nullptr);
+    return nullptr;
   }
-  return MappedFile{static_cast<char*>(base), length, slop, handle};
+  return std::unique_ptr<MappedFile>(
+      new MappedFile(static_cast<char*>(base), length, slop, handle));
 #else
   void* base = mmap(nullptr, file_length, prot, MAP_SHARED, h, file_offset);
   if (base == MAP_FAILED) {
     // http://b/119818070 "app crashes when reading asset of zero length".
     // mmap fails with EINVAL for a zero length region.
     if (errno == EINVAL && length == 0) {
-      return MappedFile{const_cast<char*>(kEmptyBuffer), 0, 0};
+      return std::unique_ptr<MappedFile>(new MappedFile(const_cast<char*>(kEmptyBuffer), 0, 0));
     }
-    return MappedFile(nullptr, 0, 0);
+    return nullptr;
   }
-  return MappedFile{static_cast<char*>(base), length, slop};
+  return std::unique_ptr<MappedFile>(new MappedFile(static_cast<char*>(base), length, slop));
 #endif
 }
 
diff --git a/base/mapped_file_test.cpp b/base/mapped_file_test.cpp
index 3629108..d21703c 100644
--- a/base/mapped_file_test.cpp
+++ b/base/mapped_file_test.cpp
@@ -44,8 +44,6 @@
   ASSERT_TRUE(tf.fd != -1);
 
   auto m = android::base::MappedFile::FromFd(tf.fd, 4096, 0, PROT_READ);
-  ASSERT_NE(nullptr, m);
-  EXPECT_TRUE((bool)*m);
   EXPECT_EQ(0u, m->size());
   EXPECT_NE(nullptr, m->data());
 }
diff --git a/fs_mgr/libfiemap/fiemap_writer.cpp b/fs_mgr/libfiemap/fiemap_writer.cpp
index 961533e..b5794d3 100644
--- a/fs_mgr/libfiemap/fiemap_writer.cpp
+++ b/fs_mgr/libfiemap/fiemap_writer.cpp
@@ -386,43 +386,12 @@
     return true;
 }
 
-// Reserve space for the file on the file system and write it out to make sure the extents
-// don't come back unwritten. Return from this function with the kernel file offset set to 0.
-// If the filesystem is f2fs, then we also PIN the file on disk to make sure the blocks
-// aren't moved around.
-static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blocksz,
-                         uint64_t file_size, unsigned int fs_type,
-                         std::function<bool(uint64_t, uint64_t)> on_progress) {
-    switch (fs_type) {
-        case EXT4_SUPER_MAGIC:
-            break;
-        case F2FS_SUPER_MAGIC: {
-            bool supported;
-            if (!F2fsPinBeforeAllocate(file_fd, &supported)) {
-                return false;
-            }
-            if (supported && !PinFile(file_fd, file_path, fs_type)) {
-                return false;
-            }
-            break;
-        }
-        case MSDOS_SUPER_MAGIC:
-            // fallocate() is not supported, and not needed, since VFAT does not support holes.
-            // Instead we can perform a much faster allocation.
-            return FallocateFallback(file_fd, blocksz, file_size, file_path, on_progress);
-        default:
-            LOG(ERROR) << "Missing fallocate() support for file system " << fs_type;
-            return false;
-    }
-
-    if (fallocate(file_fd, FALLOC_FL_ZERO_RANGE, 0, file_size)) {
-        PLOG(ERROR) << "Failed to allocate space for file: " << file_path << " size: " << file_size;
-        return false;
-    }
-
-    // write zeroes in 'blocksz' byte increments until we reach file_size to make sure the data
-    // blocks are actually written to by the file system and thus getting rid of the holes in the
-    // file.
+// write zeroes in 'blocksz' byte increments until we reach file_size to make sure the data
+// blocks are actually written to by the file system and thus getting rid of the holes in the
+// file.
+static bool WriteZeroes(int file_fd, const std::string& file_path, size_t blocksz,
+                        uint64_t file_size,
+                        const std::function<bool(uint64_t, uint64_t)>& on_progress) {
     auto buffer = std::unique_ptr<void, decltype(&free)>(calloc(1, blocksz), free);
     if (buffer == nullptr) {
         LOG(ERROR) << "failed to allocate memory for writing file";
@@ -460,6 +429,50 @@
         PLOG(ERROR) << "Failed to reset offset at the beginning of : " << file_path;
         return false;
     }
+    return true;
+}
+
+// Reserve space for the file on the file system and write it out to make sure the extents
+// don't come back unwritten. Return from this function with the kernel file offset set to 0.
+// If the filesystem is f2fs, then we also PIN the file on disk to make sure the blocks
+// aren't moved around.
+static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blocksz,
+                         uint64_t file_size, unsigned int fs_type,
+                         std::function<bool(uint64_t, uint64_t)> on_progress) {
+    bool need_explicit_writes = true;
+    switch (fs_type) {
+        case EXT4_SUPER_MAGIC:
+            break;
+        case F2FS_SUPER_MAGIC: {
+            bool supported;
+            if (!F2fsPinBeforeAllocate(file_fd, &supported)) {
+                return false;
+            }
+            if (supported) {
+                if (!PinFile(file_fd, file_path, fs_type)) {
+                    return false;
+                }
+                need_explicit_writes = false;
+            }
+            break;
+        }
+        case MSDOS_SUPER_MAGIC:
+            // fallocate() is not supported, and not needed, since VFAT does not support holes.
+            // Instead we can perform a much faster allocation.
+            return FallocateFallback(file_fd, blocksz, file_size, file_path, on_progress);
+        default:
+            LOG(ERROR) << "Missing fallocate() support for file system " << fs_type;
+            return false;
+    }
+
+    if (fallocate(file_fd, 0, 0, file_size)) {
+        PLOG(ERROR) << "Failed to allocate space for file: " << file_path << " size: " << file_size;
+        return false;
+    }
+
+    if (need_explicit_writes && !WriteZeroes(file_fd, file_path, blocksz, file_size, on_progress)) {
+        return false;
+    }
 
     // flush all writes here ..
     if (fsync(file_fd)) {
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 4406696..7e7f393 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -1125,6 +1125,11 @@
     auto_slot_suffixing_ = true;
 }
 
+void MetadataBuilder::SetVirtualABDeviceFlag() {
+    RequireExpandedMetadataHeader();
+    header_.flags |= LP_HEADER_FLAG_VIRTUAL_AB_DEVICE;
+}
+
 bool MetadataBuilder::IsABDevice() {
     return !IPropertyFetcher::GetInstance()->GetProperty("ro.boot.slot_suffix", "").empty();
 }
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index 7a334fb..851f041 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -318,6 +318,8 @@
 
     // Set the LP_METADATA_AUTO_SLOT_SUFFIXING flag.
     void SetAutoSlotSuffixing();
+    // Set the LP_HEADER_FLAG_VIRTUAL_AB_DEVICE flag.
+    void SetVirtualABDeviceFlag();
 
     // If set, checks for slot suffixes will be ignored internally.
     void IgnoreSlotSuffixing();
diff --git a/fs_mgr/liblp/include/liblp/metadata_format.h b/fs_mgr/liblp/include/liblp/metadata_format.h
index 26cbf07..d3c9874 100644
--- a/fs_mgr/liblp/include/liblp/metadata_format.h
+++ b/fs_mgr/liblp/include/liblp/metadata_format.h
@@ -224,8 +224,6 @@
     /* 128: See LP_HEADER_FLAG_ constants for possible values. Header flags are
      * independent of the version number and intended to be informational only.
      * New flags can be added without bumping the version.
-     *
-     * (Note there are no flags currently defined.)
      */
     uint32_t flags;
 
@@ -233,6 +231,11 @@
     uint8_t reserved[124];
 } __attribute__((packed)) LpMetadataHeader;
 
+/* This device uses Virtual A/B. Note that on retrofit devices, the expanded
+ * header may not be present.
+ */
+#define LP_HEADER_FLAG_VIRTUAL_AB_DEVICE 0x1
+
 /* This struct defines a logical partition entry, similar to what would be
  * present in a GUID Partition Table.
  */
diff --git a/libziparchive/testdata/empty.zip b/libziparchive/testdata/empty.zip
new file mode 100644
index 0000000..15cb0ec
--- /dev/null
+++ b/libziparchive/testdata/empty.zip
Binary files differ
diff --git a/libziparchive/testdata/zero-size-cd.zip b/libziparchive/testdata/zero-size-cd.zip
new file mode 100644
index 0000000..b6c8cbe
--- /dev/null
+++ b/libziparchive/testdata/zero-size-cd.zip
Binary files differ
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index ef29188..68837cc 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -265,14 +265,10 @@
   ALOGV("+++ num_entries=%" PRIu32 " dir_size=%" PRIu32 " dir_offset=%" PRIu32, eocd->num_records,
         eocd->cd_size, eocd->cd_start_offset);
 
-  /*
-   * It all looks good.  Create a mapping for the CD, and set the fields
-   * in archive.
-   */
-
+  // It all looks good.  Create a mapping for the CD, and set the fields
+  // in archive.
   if (!archive->InitializeCentralDirectory(static_cast<off64_t>(eocd->cd_start_offset),
                                            static_cast<size_t>(eocd->cd_size))) {
-    ALOGE("Zip: failed to intialize central directory.\n");
     return kMmapFailed;
   }
 
@@ -354,7 +350,7 @@
   if (archive->hash_table == nullptr) {
     ALOGW("Zip: unable to allocate the %u-entry hash_table, entry size: %zu",
           archive->hash_table_size, sizeof(ZipStringOffset));
-    return -1;
+    return kAllocationFailed;
   }
 
   /*
@@ -365,24 +361,25 @@
   const uint8_t* ptr = cd_ptr;
   for (uint16_t i = 0; i < num_entries; i++) {
     if (ptr > cd_end - sizeof(CentralDirectoryRecord)) {
-      ALOGW("Zip: ran off the end (at %" PRIu16 ")", i);
+      ALOGW("Zip: ran off the end (item #%" PRIu16 ", %zu bytes of central directory)", i,
+            cd_length);
 #if defined(__ANDROID__)
       android_errorWriteLog(0x534e4554, "36392138");
 #endif
-      return -1;
+      return kInvalidFile;
     }
 
     const CentralDirectoryRecord* cdr = reinterpret_cast<const CentralDirectoryRecord*>(ptr);
     if (cdr->record_signature != CentralDirectoryRecord::kSignature) {
       ALOGW("Zip: missed a central dir sig (at %" PRIu16 ")", i);
-      return -1;
+      return kInvalidFile;
     }
 
     const off64_t local_header_offset = cdr->local_file_header_offset;
     if (local_header_offset >= archive->directory_offset) {
       ALOGW("Zip: bad LFH offset %" PRId64 " at entry %" PRIu16,
             static_cast<int64_t>(local_header_offset), i);
-      return -1;
+      return kInvalidFile;
     }
 
     const uint16_t file_name_length = cdr->file_name_length;
@@ -394,12 +391,12 @@
       ALOGW("Zip: file name for entry %" PRIu16
             " exceeds the central directory range, file_name_length: %" PRIu16 ", cd_length: %zu",
             i, file_name_length, cd_length);
-      return -1;
+      return kInvalidEntryName;
     }
     // Check that file name is valid UTF-8 and doesn't contain NUL (U+0000) characters.
     if (!IsValidEntryName(file_name, file_name_length)) {
       ALOGW("Zip: invalid file name at entry %" PRIu16, i);
-      return -1;
+      return kInvalidEntryName;
     }
 
     // Add the CDE filename to the hash table.
@@ -414,7 +411,7 @@
     ptr += sizeof(CentralDirectoryRecord) + file_name_length + extra_length + comment_length;
     if ((ptr - cd_ptr) > static_cast<int64_t>(cd_length)) {
       ALOGW("Zip: bad CD advance (%tu vs %zu) at entry %" PRIu16, ptr - cd_ptr, cd_length, i);
-      return -1;
+      return kInvalidFile;
     }
   }
 
@@ -422,7 +419,7 @@
   if (!archive->mapped_zip.ReadAtOffset(reinterpret_cast<uint8_t*>(&lfh_start_bytes),
                                         sizeof(uint32_t), 0)) {
     ALOGW("Zip: Unable to read header for entry at offset == 0.");
-    return -1;
+    return kInvalidFile;
   }
 
   if (lfh_start_bytes != LocalFileHeader::kSignature) {
@@ -430,7 +427,7 @@
 #if defined(__ANDROID__)
     android_errorWriteLog(0x534e4554, "64211847");
 #endif
-    return -1;
+    return kInvalidFile;
   }
 
   ALOGV("+++ zip good scan %" PRIu16 " entries", num_entries);
@@ -439,16 +436,8 @@
 }
 
 static int32_t OpenArchiveInternal(ZipArchive* archive, const char* debug_file_name) {
-  int32_t result = -1;
-  if ((result = MapCentralDirectory(debug_file_name, archive)) != 0) {
-    return result;
-  }
-
-  if ((result = ParseZipArchive(archive))) {
-    return result;
-  }
-
-  return 0;
+  int32_t result = MapCentralDirectory(debug_file_name, archive);
+  return result != 0 ? result : ParseZipArchive(archive);
 }
 
 int32_t OpenArchiveFd(int fd, const char* debug_file_name, ZipArchiveHandle* handle,
@@ -1185,7 +1174,7 @@
     return result;
   } else {
     if (base_ptr_ == nullptr) {
-      ALOGE("Zip: invalid file map\n");
+      ALOGE("Zip: invalid file map");
       return -1;
     }
     return static_cast<off64_t>(data_length_);
@@ -1196,12 +1185,12 @@
 bool MappedZipFile::ReadAtOffset(uint8_t* buf, size_t len, off64_t off) const {
   if (has_fd_) {
     if (!android::base::ReadFullyAtOffset(fd_, buf, len, off)) {
-      ALOGE("Zip: failed to read at offset %" PRId64 "\n", off);
+      ALOGE("Zip: failed to read at offset %" PRId64, off);
       return false;
     }
   } else {
     if (off < 0 || off > static_cast<off64_t>(data_length_)) {
-      ALOGE("Zip: invalid offset: %" PRId64 ", data length: %" PRId64 "\n", off, data_length_);
+      ALOGE("Zip: invalid offset: %" PRId64 ", data length: %" PRId64, off, data_length_);
       return false;
     }
     memcpy(buf, static_cast<const uint8_t*>(base_ptr_) + off, len);
@@ -1219,13 +1208,17 @@
   if (mapped_zip.HasFd()) {
     directory_map = android::base::MappedFile::FromFd(mapped_zip.GetFileDescriptor(),
                                                       cd_start_offset, cd_size, PROT_READ);
-    if (!directory_map) return false;
+    if (!directory_map) {
+      ALOGE("Zip: failed to map central directory (offset %" PRId64 ", size %zu): %s",
+            cd_start_offset, cd_size, strerror(errno));
+      return false;
+    }
 
     CHECK_EQ(directory_map->size(), cd_size);
     central_directory.Initialize(directory_map->data(), 0 /*offset*/, cd_size);
   } else {
     if (mapped_zip.GetBasePtr() == nullptr) {
-      ALOGE("Zip: Failed to map central directory, bad mapped_zip base pointer\n");
+      ALOGE("Zip: Failed to map central directory, bad mapped_zip base pointer");
       return false;
     }
     if (static_cast<off64_t>(cd_start_offset) + static_cast<off64_t>(cd_size) >
diff --git a/libziparchive/zip_archive_private.h b/libziparchive/zip_archive_private.h
index 60fdec0..1d05fc7 100644
--- a/libziparchive/zip_archive_private.h
+++ b/libziparchive/zip_archive_private.h
@@ -42,6 +42,7 @@
     "Invalid entry name",
     "I/O error",
     "File mapping failed",
+    "Allocation failed",
 };
 
 enum ErrorCodes : int32_t {
@@ -87,7 +88,10 @@
   // We were not able to mmap the central directory or entry contents.
   kMmapFailed = -12,
 
-  kLastErrorCode = kMmapFailed,
+  // An allocation failed.
+  kAllocationFailed = -13,
+
+  kLastErrorCode = kAllocationFailed,
 };
 
 class MappedZipFile {
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index 8781ab7..0916304 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -36,13 +36,9 @@
 
 static std::string test_data_dir = android::base::GetExecutableDirectory() + "/testdata";
 
-static const std::string kMissingZip = "missing.zip";
 static const std::string kValidZip = "valid.zip";
 static const std::string kLargeZip = "large.zip";
 static const std::string kBadCrcZip = "bad_crc.zip";
-static const std::string kCrashApk = "crash.apk";
-static const std::string kBadFilenameZip = "bad_filename.zip";
-static const std::string kUpdateZip = "dummy-update.zip";
 
 static const std::vector<uint8_t> kATxtContents{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'a',
                                                 'b', 'c', 'd', 'e', 'f', 'g', 'h', '\n'};
@@ -52,13 +48,6 @@
 
 static const std::vector<uint8_t> kBTxtContents{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '\n'};
 
-static const std::string kATxtName("a.txt");
-static const std::string kBTxtName("b.txt");
-static const std::string kNonexistentTxtName("nonexistent.txt");
-static const std::string kEmptyTxtName("empty.txt");
-static const std::string kLargeCompressTxtName("compress.txt");
-static const std::string kLargeUncompressTxtName("uncompress.txt");
-
 static int32_t OpenArchiveWrapper(const std::string& name, ZipArchiveHandle* handle) {
   const std::string abs_path = test_data_dir + "/" + name;
   return OpenArchive(abs_path.c_str(), handle);
@@ -69,19 +58,31 @@
   ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
   CloseArchive(handle);
 
-  ASSERT_EQ(-1, OpenArchiveWrapper(kBadFilenameZip, &handle));
+  ASSERT_EQ(kInvalidEntryName, OpenArchiveWrapper("bad_filename.zip", &handle));
   CloseArchive(handle);
 }
 
 TEST(ziparchive, OutOfBound) {
   ZipArchiveHandle handle;
-  ASSERT_EQ(-8, OpenArchiveWrapper(kCrashApk, &handle));
+  ASSERT_EQ(kInvalidOffset, OpenArchiveWrapper("crash.apk", &handle));
+  CloseArchive(handle);
+}
+
+TEST(ziparchive, EmptyArchive) {
+  ZipArchiveHandle handle;
+  ASSERT_EQ(kEmptyArchive, OpenArchiveWrapper("empty.zip", &handle));
+  CloseArchive(handle);
+}
+
+TEST(ziparchive, ZeroSizeCentralDirectory) {
+  ZipArchiveHandle handle;
+  ASSERT_EQ(kInvalidFile, OpenArchiveWrapper("zero-size-cd.zip", &handle));
   CloseArchive(handle);
 }
 
 TEST(ziparchive, OpenMissing) {
   ZipArchiveHandle handle;
-  ASSERT_NE(0, OpenArchiveWrapper(kMissingZip, &handle));
+  ASSERT_NE(0, OpenArchiveWrapper("missing.zip", &handle));
 
   // Confirm the file descriptor is not going to be mistaken for a valid one.
   ASSERT_EQ(-1, GetFileDescriptor(handle));
@@ -200,7 +201,7 @@
   ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
 
   ZipEntry data;
-  ASSERT_EQ(0, FindEntry(handle, kATxtName, &data));
+  ASSERT_EQ(0, FindEntry(handle, "a.txt", &data));
 
   // Known facts about a.txt, from zipinfo -v.
   ASSERT_EQ(63, data.offset);
@@ -211,7 +212,7 @@
   ASSERT_EQ(static_cast<uint32_t>(0x438a8005), data.mod_time);
 
   // An entry that doesn't exist. Should be a negative return code.
-  ASSERT_LT(FindEntry(handle, kNonexistentTxtName, &data), 0);
+  ASSERT_LT(FindEntry(handle, "this file does not exist", &data), 0);
 
   CloseArchive(handle);
 }
@@ -259,7 +260,7 @@
 
   // An entry that's deflated.
   ZipEntry data;
-  ASSERT_EQ(0, FindEntry(handle, kATxtName, &data));
+  ASSERT_EQ(0, FindEntry(handle, "a.txt", &data));
   const uint32_t a_size = data.uncompressed_length;
   ASSERT_EQ(a_size, kATxtContents.size());
   uint8_t* buffer = new uint8_t[a_size];
@@ -268,7 +269,7 @@
   delete[] buffer;
 
   // An entry that's stored.
-  ASSERT_EQ(0, FindEntry(handle, kBTxtName, &data));
+  ASSERT_EQ(0, FindEntry(handle, "b.txt", &data));
   const uint32_t b_size = data.uncompressed_length;
   ASSERT_EQ(b_size, kBTxtContents.size());
   buffer = new uint8_t[b_size];
@@ -323,7 +324,7 @@
   ASSERT_EQ(0, OpenArchiveFd(tmp_file.fd, "EmptyEntriesTest", &handle, false));
 
   ZipEntry entry;
-  ASSERT_EQ(0, FindEntry(handle, kEmptyTxtName, &entry));
+  ASSERT_EQ(0, FindEntry(handle, "empty.txt", &entry));
   ASSERT_EQ(static_cast<uint32_t>(0), entry.uncompressed_length);
   uint8_t buffer[1];
   ASSERT_EQ(0, ExtractToMemory(handle, &entry, buffer, 1));
@@ -403,7 +404,7 @@
   ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
 
   ZipEntry entry;
-  ASSERT_EQ(0, FindEntry(handle, kATxtName, &entry));
+  ASSERT_EQ(0, FindEntry(handle, "a.txt", &entry));
   ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, tmp_file.fd));
 
   // Assert that the first 8 bytes of the file haven't been clobbered.
@@ -425,7 +426,7 @@
 
 #if !defined(_WIN32)
 TEST(ziparchive, OpenFromMemory) {
-  const std::string zip_path = test_data_dir + "/" + kUpdateZip;
+  const std::string zip_path = test_data_dir + "/dummy-update.zip";
   android::base::unique_fd fd(open(zip_path.c_str(), O_RDONLY | O_BINARY));
   ASSERT_NE(-1, fd);
   struct stat sb;
@@ -510,27 +511,27 @@
 }
 
 TEST(ziparchive, StreamCompressed) {
-  ZipArchiveStreamTestUsingContents(kValidZip, kATxtName, kATxtContents, false);
+  ZipArchiveStreamTestUsingContents(kValidZip, "a.txt", kATxtContents, false);
 }
 
 TEST(ziparchive, StreamUncompressed) {
-  ZipArchiveStreamTestUsingContents(kValidZip, kBTxtName, kBTxtContents, false);
+  ZipArchiveStreamTestUsingContents(kValidZip, "b.txt", kBTxtContents, false);
 }
 
 TEST(ziparchive, StreamRawCompressed) {
-  ZipArchiveStreamTestUsingContents(kValidZip, kATxtName, kATxtContentsCompressed, true);
+  ZipArchiveStreamTestUsingContents(kValidZip, "a.txt", kATxtContentsCompressed, true);
 }
 
 TEST(ziparchive, StreamRawUncompressed) {
-  ZipArchiveStreamTestUsingContents(kValidZip, kBTxtName, kBTxtContents, true);
+  ZipArchiveStreamTestUsingContents(kValidZip, "b.txt", kBTxtContents, true);
 }
 
 TEST(ziparchive, StreamLargeCompressed) {
-  ZipArchiveStreamTestUsingMemory(kLargeZip, kLargeCompressTxtName);
+  ZipArchiveStreamTestUsingMemory(kLargeZip, "compress.txt");
 }
 
 TEST(ziparchive, StreamLargeUncompressed) {
-  ZipArchiveStreamTestUsingMemory(kLargeZip, kLargeUncompressTxtName);
+  ZipArchiveStreamTestUsingMemory(kLargeZip, "uncompress.txt");
 }
 
 TEST(ziparchive, StreamCompressedBadCrc) {
@@ -539,7 +540,7 @@
 
   ZipEntry entry;
   std::vector<uint8_t> read_data;
-  ZipArchiveStreamTest(handle, kATxtName, false, false, &entry, &read_data);
+  ZipArchiveStreamTest(handle, "a.txt", false, false, &entry, &read_data);
 
   CloseArchive(handle);
 }
@@ -550,7 +551,7 @@
 
   ZipEntry entry;
   std::vector<uint8_t> read_data;
-  ZipArchiveStreamTest(handle, kBTxtName, false, false, &entry, &read_data);
+  ZipArchiveStreamTest(handle, "b.txt", false, false, &entry, &read_data);
 
   CloseArchive(handle);
 }
@@ -647,7 +648,8 @@
 
   // Out of bounds.
   ASSERT_STREQ("Unknown return code", ErrorCodeString(1));
-  ASSERT_STREQ("Unknown return code", ErrorCodeString(-13));
+  ASSERT_STRNE("Unknown return code", ErrorCodeString(kLastErrorCode));
+  ASSERT_STREQ("Unknown return code", ErrorCodeString(kLastErrorCode - 1));
 
   ASSERT_STREQ("I/O error", ErrorCodeString(kIoError));
 }
@@ -698,7 +700,7 @@
   ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, &kZipFileWithBrokenLfhSignature[0],
                                         kZipFileWithBrokenLfhSignature.size()));
   ZipArchiveHandle handle;
-  ASSERT_EQ(-1, OpenArchiveFd(tmp_file.fd, "LeadingNonZipBytes", &handle, false));
+  ASSERT_EQ(kInvalidFile, OpenArchiveFd(tmp_file.fd, "LeadingNonZipBytes", &handle, false));
 }
 
 class VectorReader : public zip_archive::Reader {