Merge "adb: add reboot-fastboot command"
diff --git a/adb/Android.bp b/adb/Android.bp
index 7f82ca6..a9ccc84 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -175,6 +175,12 @@
         "libdiagnose_usb",
         "libmdnssd",
         "libusb",
+        "libandroidfw",
+        "libziparchive",
+        "libz",
+        "libutils",
+        "liblog",
+        "libcutils",
     ],
 }
 
@@ -257,6 +263,12 @@
         "liblog",
         "libmdnssd",
         "libusb",
+        "libandroidfw",
+        "libziparchive",
+        "libz",
+        "libutils",
+        "liblog",
+        "libcutils",
     ],
 
     stl: "libc++_static",
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index f4a92e3..051ab73 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -21,6 +21,7 @@
 
 #include <algorithm>
 #include <list>
+#include <memory>
 
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
@@ -29,7 +30,6 @@
 
 #include "socket_spec.h"
 #include "sysdeps.h"
-#include "sysdeps/memory.h"
 #include "transport.h"
 
 // A listener is an entity which binds to a local port and, upon receiving a connection on that
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index 4cbc45a..d69dbef 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -14,31 +14,27 @@
  * limitations under the License.
  */
 
-#define TRACE_TAG ADB
+#include "adb_install.h"
 
 #include <stdio.h>
 #include <stdlib.h>
-
-#include "adb.h"
-#include "adb_client.h"
-#include "adb_install.h"
-#include "adb_utils.h"
-#include "client/file_sync_client.h"
-#include "commandline.h"
-#include "fastdeploy.h"
-#include "sysdeps.h"
-
+#include <unistd.h>
 #include <algorithm>
 #include <iostream>
 #include <string>
 #include <vector>
 
-#include <unistd.h>
-
-#include <android-base/file.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <android-base/test_utils.h>
+#include "adb.h"
+#include "adb_client.h"
+#include "adb_utils.h"
+#include "android-base/file.h"
+#include "android-base/stringprintf.h"
+#include "android-base/strings.h"
+#include "android-base/test_utils.h"
+#include "client/file_sync_client.h"
+#include "commandline.h"
+#include "fastdeploy.h"
+#include "sysdeps.h"
 
 static constexpr int kFastDeployMinApi = 24;
 
@@ -146,41 +142,16 @@
         TemporaryFile patchTmpFile;
 
         FILE* metadataFile = fopen(metadataTmpFile.path, "wb");
-        int metadata_len = extract_metadata(file, metadataFile);
+        extract_metadata(file, metadataFile);
         fclose(metadataFile);
 
-        int result = -1;
-        if (metadata_len <= 0) {
-            printf("failed to extract metadata %d\n", metadata_len);
-            return 1;
-        } else {
-            int create_patch_result = create_patch(file, metadataTmpFile.path, patchTmpFile.path);
-            if (create_patch_result != 0) {
-                printf("Patch creation failure, error code: %d\n", create_patch_result);
-                result = create_patch_result;
-                goto cleanup_streamed_apk;
-            } else {
-                std::vector<const char*> pm_args;
-                // pass all but 1st (command) and last (apk path) parameters through to pm for
-                // session creation
-                for (int i = 1; i < argc - 1; i++) {
-                    pm_args.push_back(argv[i]);
-                }
-                int apply_patch_result =
-                        install_patch(file, patchTmpFile.path, pm_args.size(), pm_args.data());
-                if (apply_patch_result != 0) {
-                    printf("Patch application failure, error code: %d\n", apply_patch_result);
-                    result = apply_patch_result;
-                    goto cleanup_streamed_apk;
-                }
-            }
-        }
-
-    cleanup_streamed_apk:
-        if (use_fastdeploy == true) {
-            delete_device_patch_file(file);
-        }
-        return result;
+        create_patch(file, metadataTmpFile.path, patchTmpFile.path);
+        // pass all but 1st (command) and last (apk path) parameters through to pm for
+        // session creation
+        std::vector<const char*> pm_args{argv + 1, argv + argc - 1};
+        install_patch(file, patchTmpFile.path, pm_args.size(), pm_args.data());
+        delete_device_patch_file(file);
+        return 0;
     } else {
         struct stat sb;
         if (stat(file, &sb) == -1) {
@@ -265,29 +236,11 @@
         TemporaryFile patchTmpFile;
 
         FILE* metadataFile = fopen(metadataTmpFile.path, "wb");
-        int metadata_len = extract_metadata(apk_file[0], metadataFile);
+        extract_metadata(apk_file[0], metadataFile);
         fclose(metadataFile);
 
-        if (metadata_len <= 0) {
-            printf("failed to extract metadata %d\n", metadata_len);
-            return 1;
-        } else {
-            int create_patch_result =
-                    create_patch(apk_file[0], metadataTmpFile.path, patchTmpFile.path);
-            if (create_patch_result != 0) {
-                printf("Patch creation failure, error code: %d\n", create_patch_result);
-                result = create_patch_result;
-                goto cleanup_apk;
-            } else {
-                int apply_patch_result =
-                        apply_patch_on_device(apk_file[0], patchTmpFile.path, apk_dest.c_str());
-                if (apply_patch_result != 0) {
-                    printf("Patch application failure, error code: %d\n", apply_patch_result);
-                    result = apply_patch_result;
-                    goto cleanup_apk;
-                }
-            }
-        }
+        create_patch(apk_file[0], metadataTmpFile.path, patchTmpFile.path);
+        apply_patch_on_device(apk_file[0], patchTmpFile.path, apk_dest.c_str());
     } else {
         if (!do_sync_push(apk_file, apk_dest.c_str(), false)) goto cleanup_apk;
     }
@@ -347,7 +300,6 @@
             use_localagent = true;
 #endif
         }
-        // TODO: --installlog <filename>
     }
 
     if (installMode == INSTALL_DEFAULT) {
diff --git a/adb/client/adb_install.h b/adb/client/adb_install.h
index e9410a9..5b6c4cb 100644
--- a/adb/client/adb_install.h
+++ b/adb/client/adb_install.h
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef ADB_INSTALL_H
-#define ADB_INSTALL_H
+#pragma once
 
-#include "fastdeploy.h"
+#include <string>
 
 int install_app(int argc, const char** argv);
 int install_multiple_app(int argc, const char** argv);
@@ -26,4 +25,3 @@
 int delete_device_file(const std::string& filename);
 int delete_host_file(const std::string& filename);
 
-#endif
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index ac02cbe..07b5747 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -63,7 +63,6 @@
 #include "services.h"
 #include "shell_protocol.h"
 #include "sysdeps/chrono.h"
-#include "sysdeps/memory.h"
 
 extern int gListenAll;
 
diff --git a/adb/client/fastdeploy.cpp b/adb/client/fastdeploy.cpp
index d3f35c8..183a1fa 100644
--- a/adb/client/fastdeploy.cpp
+++ b/adb/client/fastdeploy.cpp
@@ -14,15 +14,18 @@
  * limitations under the License.
  */
 
-#include <libgen.h>
+#include "fastdeploy.h"
+
 #include <algorithm>
 #include <array>
+#include <memory>
 
 #include "android-base/file.h"
 #include "android-base/strings.h"
+#include "androidfw/ResourceTypes.h"
+#include "androidfw/ZipFileRO.h"
 #include "client/file_sync_client.h"
 #include "commandline.h"
-#include "fastdeploy.h"
 #include "fastdeploycallbacks.h"
 #include "utils/String16.h"
 
@@ -138,60 +141,82 @@
     }
 }
 
-static std::string get_aapt2_path() {
-    if (g_use_localagent) {
-        // This should never happen on a Windows machine
-        const char* host_out = getenv("ANDROID_HOST_OUT");
-        if (host_out == nullptr) {
-            fatal("Could not locate aapt2 because $ANDROID_HOST_OUT is not defined");
-        }
-        return android::base::StringPrintf("%s/bin/aapt2", host_out);
+static std::string get_string_from_utf16(const char16_t* input, int input_len) {
+    ssize_t utf8_length = utf16_to_utf8_length(input, input_len);
+    if (utf8_length <= 0) {
+        return {};
     }
-
-    std::string adb_dir = android::base::GetExecutableDirectory();
-    if (adb_dir.empty()) {
-        fatal("Could not locate aapt2");
-    }
-    return adb_dir + "/aapt2";
+    std::string utf8;
+    utf8.resize(utf8_length);
+    utf16_to_utf8(input, input_len, &*utf8.begin(), utf8_length + 1);
+    return utf8;
 }
 
-static int system_capture(const char* cmd, std::string& output) {
-    FILE* pipe = popen(cmd, "re");
-    int fd = -1;
-
-    if (pipe != nullptr) {
-        fd = fileno(pipe);
-    }
-
-    if (fd == -1) {
-        fatal_errno("Could not create pipe for process '%s'", cmd);
-    }
-
-    if (!android::base::ReadFdToString(fd, &output)) {
-        fatal_errno("Error reading from process '%s'", cmd);
-    }
-
-    return pclose(pipe);
-}
-
-// output is required to point to a valid output string (non-null)
 static std::string get_packagename_from_apk(const char* apkPath) {
-    const char* kAapt2DumpNameCommandPattern = R"(%s dump packagename "%s")";
-    std::string aapt2_path_string = get_aapt2_path();
-    std::string getPackagenameCommand = android::base::StringPrintf(
-            kAapt2DumpNameCommandPattern, aapt2_path_string.c_str(), apkPath);
-
-    std::string package_name;
-    int exit_code = system_capture(getPackagenameCommand.c_str(), package_name);
-    if (exit_code != 0) {
-        fatal("Error executing '%s' exitcode: %d", getPackagenameCommand.c_str(), exit_code);
+    std::unique_ptr<android::ZipFileRO> zipFile(android::ZipFileRO::open(apkPath));
+    if (zipFile == nullptr) {
+        fatal("Could not open %s", apkPath);
     }
-
-    // strip any line end characters from the output
-    return android::base::Trim(package_name);
+    android::ZipEntryRO entry = zipFile->findEntryByName("AndroidManifest.xml");
+    if (entry == nullptr) {
+        fatal("Could not find AndroidManifest.xml inside %s", apkPath);
+    }
+    uint32_t manifest_len = 0;
+    if (!zipFile->getEntryInfo(entry, NULL, &manifest_len, NULL, NULL, NULL, NULL)) {
+        fatal("Could not read AndroidManifest.xml inside %s", apkPath);
+    }
+    std::vector<char> manifest_data(manifest_len);
+    if (!zipFile->uncompressEntry(entry, manifest_data.data(), manifest_len)) {
+        fatal("Could not uncompress AndroidManifest.xml inside %s", apkPath);
+    }
+    android::ResXMLTree tree;
+    android::status_t setto_status = tree.setTo(manifest_data.data(), manifest_len, true);
+    if (setto_status != android::OK) {
+        fatal("Could not parse AndroidManifest.xml inside %s", apkPath);
+    }
+    android::ResXMLParser::event_code_t code;
+    while ((code = tree.next()) != android::ResXMLParser::BAD_DOCUMENT &&
+           code != android::ResXMLParser::END_DOCUMENT) {
+        switch (code) {
+            case android::ResXMLParser::START_TAG: {
+                size_t element_name_length;
+                const char16_t* element_name = tree.getElementName(&element_name_length);
+                if (element_name == nullptr) {
+                    continue;
+                }
+                std::u16string element_name_string(element_name, element_name_length);
+                if (element_name_string == u"manifest") {
+                    for (size_t i = 0; i < tree.getAttributeCount(); i++) {
+                        size_t attribute_name_length;
+                        const char16_t* attribute_name_text =
+                                tree.getAttributeName(i, &attribute_name_length);
+                        if (attribute_name_text == nullptr) {
+                            continue;
+                        }
+                        std::u16string attribute_name_string(attribute_name_text,
+                                                             attribute_name_length);
+                        if (attribute_name_string == u"package") {
+                            size_t attribute_value_length;
+                            const char16_t* attribute_value_text =
+                                    tree.getAttributeStringValue(i, &attribute_value_length);
+                            if (attribute_value_text == nullptr) {
+                                continue;
+                            }
+                            return get_string_from_utf16(attribute_value_text,
+                                                         attribute_value_length);
+                        }
+                    }
+                }
+                break;
+            }
+            default:
+                break;
+        }
+    }
+    fatal("Could not find package name tag in AndroidManifest.xml inside %s", apkPath);
 }
 
-int extract_metadata(const char* apkPath, FILE* outputFp) {
+void extract_metadata(const char* apkPath, FILE* outputFp) {
     std::string packageName = get_packagename_from_apk(apkPath);
     const char* kAgentExtractCommandPattern = "/data/local/tmp/deployagent extract %s";
     std::string extractCommand =
@@ -200,13 +225,10 @@
     std::vector<char> extractErrorBuffer;
     int statusCode;
     DeployAgentFileCallback cb(outputFp, &extractErrorBuffer, &statusCode);
-    int ret = send_shell_command(extractCommand, false, &cb);
-
-    if (ret == 0) {
-        return cb.getBytesWritten();
+    int returnCode = send_shell_command(extractCommand, false, &cb);
+    if (returnCode != 0) {
+        fatal("Executing %s returned %d\n", extractCommand.c_str(), returnCode);
     }
-
-    return ret;
 }
 
 static std::string get_patch_generator_command() {
@@ -229,11 +251,14 @@
                                        adb_dir.c_str());
 }
 
-int create_patch(const char* apkPath, const char* metadataPath, const char* patchPath) {
+void create_patch(const char* apkPath, const char* metadataPath, const char* patchPath) {
     std::string generatePatchCommand = android::base::StringPrintf(
             R"(%s "%s" "%s" > "%s")", get_patch_generator_command().c_str(), apkPath, metadataPath,
             patchPath);
-    return system(generatePatchCommand.c_str());
+    int returnCode = system(generatePatchCommand.c_str());
+    if (returnCode != 0) {
+        fatal("Executing %s returned %d\n", generatePatchCommand.c_str(), returnCode);
+    }
 }
 
 std::string get_patch_path(const char* apkPath) {
@@ -243,36 +268,38 @@
     return patchDevicePath;
 }
 
-int apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath) {
+void apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath) {
     const std::string kAgentApplyCommandPattern = "/data/local/tmp/deployagent apply %s %s -o %s";
     std::string packageName = get_packagename_from_apk(apkPath);
     std::string patchDevicePath = get_patch_path(apkPath);
 
     std::vector<const char*> srcs = {patchPath};
     bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
-
     if (!push_ok) {
-        return -1;
+        fatal("Error pushing %s to %s returned\n", patchPath, patchDevicePath.c_str());
     }
 
     std::string applyPatchCommand =
             android::base::StringPrintf(kAgentApplyCommandPattern.c_str(), packageName.c_str(),
                                         patchDevicePath.c_str(), outputPath);
 
-    return send_shell_command(applyPatchCommand);
+    int returnCode = send_shell_command(applyPatchCommand);
+    if (returnCode != 0) {
+        fatal("Executing %s returned %d\n", applyPatchCommand.c_str(), returnCode);
+    }
 }
 
-int install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv) {
+void install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv) {
     const std::string kAgentApplyCommandPattern = "/data/local/tmp/deployagent apply %s %s -pm %s";
     std::string packageName = get_packagename_from_apk(apkPath);
-    std::vector<const char*> srcs;
+
     std::string patchDevicePath =
             android::base::StringPrintf("%s%s.patch", kDeviceAgentPath, packageName.c_str());
-    srcs.push_back(patchPath);
-    bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
 
+    std::vector<const char*> srcs{patchPath};
+    bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
     if (!push_ok) {
-        return -1;
+        fatal("Error pushing %s to %s returned\n", patchPath, patchDevicePath.c_str());
     }
 
     std::vector<unsigned char> applyOutputBuffer;
@@ -287,5 +314,8 @@
     std::string applyPatchCommand =
             android::base::StringPrintf(kAgentApplyCommandPattern.c_str(), packageName.c_str(),
                                         patchDevicePath.c_str(), argsString.c_str());
-    return send_shell_command(applyPatchCommand);
+    int returnCode = send_shell_command(applyPatchCommand);
+    if (returnCode != 0) {
+        fatal("Executing %s returned %d\n", applyPatchCommand.c_str(), returnCode);
+    }
 }
diff --git a/adb/client/fastdeploy.h b/adb/client/fastdeploy.h
index e5e7663..a6b10d3 100644
--- a/adb/client/fastdeploy.h
+++ b/adb/client/fastdeploy.h
@@ -16,7 +16,7 @@
 
 #pragma once
 
-#include "adb.h"
+#include <string>
 
 enum FastDeploy_AgentUpdateStrategy {
     FastDeploy_AgentUpdateAlways,
@@ -27,8 +27,8 @@
 void fastdeploy_set_local_agent(bool use_localagent);
 int get_device_api_level();
 void update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy);
-int extract_metadata(const char* apkPath, FILE* outputFp);
-int create_patch(const char* apkPath, const char* metadataPath, const char* patchPath);
-int apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath);
-int install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv);
+void extract_metadata(const char* apkPath, FILE* outputFp);
+void create_patch(const char* apkPath, const char* metadataPath, const char* patchPath);
+void apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath);
+void install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv);
 std::string get_patch_path(const char* apkPath);
diff --git a/adb/fdevent_test.cpp b/adb/fdevent_test.cpp
index 0cb2439..816134f 100644
--- a/adb/fdevent_test.cpp
+++ b/adb/fdevent_test.cpp
@@ -19,6 +19,7 @@
 #include <gtest/gtest.h>
 
 #include <limits>
+#include <memory>
 #include <queue>
 #include <string>
 #include <thread>
@@ -26,7 +27,6 @@
 
 #include "adb_io.h"
 #include "fdevent_test.h"
-#include "sysdeps/memory.h"
 
 class FdHandler {
   public:
diff --git a/adb/sysdeps/errno.cpp b/adb/sysdeps/errno.cpp
index 6869947..9a37ea2 100644
--- a/adb/sysdeps/errno.cpp
+++ b/adb/sysdeps/errno.cpp
@@ -24,10 +24,6 @@
 
 #include "adb.h"
 
-#if defined(_WIN32)
-#define ETXTBSY EBUSY
-#endif
-
 // Use the linux asm-generic values for errno (which are used on all android archs but mips).
 #define ERRNO_VALUES()             \
     ERRNO_VALUE(EACCES, 13);       \
diff --git a/adb/sysdeps/memory.h b/adb/sysdeps/memory.h
deleted file mode 100644
index 4108aff..0000000
--- a/adb/sysdeps/memory.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#pragma once
-
-/*
- * Copyright (C) 2018 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 <memory>
-#include <type_traits>
-
-#if defined(_WIN32)
-// We don't have C++14 on Windows yet.
-// Reimplement std::make_unique ourselves until we do.
-
-namespace internal {
-
-template <typename T>
-struct array_known_bounds;
-
-template <typename T>
-struct array_known_bounds<T[]> {
-    constexpr static bool value = false;
-};
-
-template <typename T, size_t N>
-struct array_known_bounds<T[N]> {
-    constexpr static bool value = true;
-};
-
-}  // namespace internal
-
-namespace std {
-
-template <typename T, typename... Args>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type make_unique(
-    Args&&... args) {
-    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
-}
-
-template <typename T>
-typename std::enable_if<std::is_array<T>::value && !internal::array_known_bounds<T>::value,
-                        std::unique_ptr<T>>::type
-make_unique(std::size_t size) {
-    return std::unique_ptr<T>(new typename std::remove_extent<T>::type[size]());
-}
-
-template <typename T, typename... Args>
-typename std::enable_if<std::is_array<T>::value && internal::array_known_bounds<T>::value,
-                        std::unique_ptr<T>>::type
-make_unique(Args&&... args) = delete;
-
-}  // namespace std
-
-#endif
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 8784757..0a08fbb 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -94,6 +94,10 @@
     _fh_socket_writev,
 };
 
+#if defined(assert)
+#undef assert
+#endif
+
 #define assert(cond)                                                                       \
     do {                                                                                   \
         if (!(cond)) fatal("assertion failed '%s' on %s:%d\n", #cond, __FILE__, __LINE__); \
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 95df490..cabd279 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -17,7 +17,6 @@
 #define TRACE_TAG TRANSPORT
 
 #include "sysdeps.h"
-#include "sysdeps/memory.h"
 
 #include "transport.h"
 
@@ -32,6 +31,7 @@
 #include <algorithm>
 #include <deque>
 #include <list>
+#include <memory>
 #include <mutex>
 #include <set>
 #include <thread>
diff --git a/adb/transport_fd.cpp b/adb/transport_fd.cpp
index 85f3c52..ec61279 100644
--- a/adb/transport_fd.cpp
+++ b/adb/transport_fd.cpp
@@ -17,6 +17,7 @@
 #include <stdint.h>
 
 #include <deque>
+#include <memory>
 #include <mutex>
 #include <string>
 #include <thread>
@@ -28,7 +29,6 @@
 #include "adb_unique_fd.h"
 #include "adb_utils.h"
 #include "sysdeps.h"
-#include "sysdeps/memory.h"
 #include "transport.h"
 #include "types.h"
 
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 8353d89..dc87ac7 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -26,6 +26,7 @@
 #include <sys/types.h>
 
 #include <condition_variable>
+#include <memory>
 #include <mutex>
 #include <thread>
 #include <unordered_map>
@@ -45,7 +46,6 @@
 #include "adb_unique_fd.h"
 #include "adb_utils.h"
 #include "sysdeps/chrono.h"
-#include "sysdeps/memory.h"
 
 #if ADB_HOST
 
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index 602970c..c471bf9 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -16,8 +16,9 @@
 
 #define TRACE_TAG TRANSPORT
 
+#include <memory>
+
 #include "sysdeps.h"
-#include "sysdeps/memory.h"
 #include "transport.h"
 
 #include <stdio.h>
diff --git a/adb/types.h b/adb/types.h
index 1f7008e..0c71c3a 100644
--- a/adb/types.h
+++ b/adb/types.h
@@ -25,7 +25,6 @@
 
 #include <android-base/logging.h>
 
-#include "sysdeps/memory.h"
 #include "sysdeps/uio.h"
 
 // Essentially std::vector<char>, except without zero initialization or reallocation.
diff --git a/adb/types_test.cpp b/adb/types_test.cpp
index 31ab90a..1fbd2ca 100644
--- a/adb/types_test.cpp
+++ b/adb/types_test.cpp
@@ -16,7 +16,7 @@
 
 #include <gtest/gtest.h>
 
-#include "sysdeps/memory.h"
+#include <memory>
 #include "types.h"
 
 static std::unique_ptr<IOVector::block_type> create_block(const std::string& string) {
diff --git a/base/include/android-base/utf8.h b/base/include/android-base/utf8.h
index 4b91623..1a414ec 100644
--- a/base/include/android-base/utf8.h
+++ b/base/include/android-base/utf8.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #ifdef _WIN32
+#include <sys/types.h>
 #include <string>
 #else
 // Bring in prototypes for standard APIs so that we can import them into the utf8 namespace.
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index d5ea6db..6e45133 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -237,7 +237,13 @@
     CommandResult ret;
     auto cb = [&ret](CommandResult result) { ret = result; };
     auto result = boot_control_hal->setActiveBootSlot(slot, cb);
-    if (result.isOk() && ret.success) return device->WriteStatus(FastbootResult::OKAY, "");
+    if (result.isOk() && ret.success) {
+        // Save as slot suffix to match the suffix format as returned from
+        // the boot control HAL.
+        auto current_slot = "_" + args[1];
+        device->set_active_slot(current_slot);
+        return device->WriteStatus(FastbootResult::OKAY, "");
+    }
     return device->WriteStatus(FastbootResult::FAIL, "Unable to set slot");
 }
 
diff --git a/fastboot/device/fastboot_device.cpp b/fastboot/device/fastboot_device.cpp
index b843c05..6cb4892 100644
--- a/fastboot/device/fastboot_device.cpp
+++ b/fastboot/device/fastboot_device.cpp
@@ -57,7 +57,8 @@
       transport_(std::make_unique<ClientUsbTransport>()),
       boot_control_hal_(IBootControl::getService()),
       health_hal_(get_health_service()),
-      fastboot_hal_(IFastboot::getService()) {}
+      fastboot_hal_(IFastboot::getService()),
+      active_slot_("") {}
 
 FastbootDevice::~FastbootDevice() {
     CloseDevice();
@@ -68,6 +69,11 @@
 }
 
 std::string FastbootDevice::GetCurrentSlot() {
+    // Check if a set_active ccommand was issued earlier since the boot control HAL
+    // returns the slot that is currently booted into.
+    if (!active_slot_.empty()) {
+        return active_slot_;
+    }
     // Non-A/B devices must not have boot control HALs.
     if (!boot_control_hal_) {
         return "";
diff --git a/fastboot/device/fastboot_device.h b/fastboot/device/fastboot_device.h
index 2eb7177..091aadf 100644
--- a/fastboot/device/fastboot_device.h
+++ b/fastboot/device/fastboot_device.h
@@ -56,6 +56,8 @@
     }
     android::sp<android::hardware::health::V2_0::IHealth> health_hal() { return health_hal_; }
 
+    void set_active_slot(const std::string& active_slot) { active_slot_ = active_slot; }
+
   private:
     const std::unordered_map<std::string, CommandHandler> kCommandMap;
 
@@ -64,4 +66,5 @@
     android::sp<android::hardware::health::V2_0::IHealth> health_hal_;
     android::sp<android::hardware::fastboot::V1_0::IFastboot> fastboot_hal_;
     std::vector<char> download_data_;
+    std::string active_slot_;
 };
diff --git a/fastboot/device/flashing.cpp b/fastboot/device/flashing.cpp
index 4fc3d1d..2347496 100644
--- a/fastboot/device/flashing.cpp
+++ b/fastboot/device/flashing.cpp
@@ -72,7 +72,7 @@
 }
 
 int FlashSparseData(int fd, std::vector<char>& downloaded_data) {
-    struct sparse_file* file = sparse_file_import_buf(downloaded_data.data(), true, true);
+    struct sparse_file* file = sparse_file_import_buf(downloaded_data.data(), true, false);
     if (!file) {
         return -ENOENT;
     }
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 3226010..a6ef35b 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1546,8 +1546,6 @@
 
     DeviceMapper& dm = DeviceMapper::Instance();
 
-    bool system_root = android::base::GetProperty("ro.build.system_root_image", "") == "true";
-
     for (int i = 0; i < fstab->num_entries; i++) {
         auto fsrec = &fstab->recs[i];
         if (!fs_mgr_is_verified(fsrec) && !fs_mgr_is_avb(fsrec)) {
@@ -1555,7 +1553,7 @@
         }
 
         std::string mount_point;
-        if (system_root && !strcmp(fsrec->mount_point, "/")) {
+        if (!strcmp(fsrec->mount_point, "/")) {
             // In AVB, the dm device name is vroot instead of system.
             mount_point = fs_mgr_is_avb(fsrec) ? "vroot" : "system";
         } else {
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 35f8be8..ff7a75c 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -167,25 +167,9 @@
            candidate + kUpperName + ",workdir=" + candidate + kWorkName;
 }
 
-bool fs_mgr_system_root_image(const fstab* fstab) {
-    if (!fstab) {  // can not happen?
-        // This will return empty on init first_stage_mount,
-        // hence why we prefer checking the fstab instead.
-        return android::base::GetBoolProperty("ro.build.system_root_image", false);
-    }
-    for (auto i = 0; i < fstab->num_entries; i++) {
-        const auto fsrec = &fstab->recs[i];
-        auto fsrec_mount_point = fsrec->mount_point;
-        if (!fsrec_mount_point) continue;
-        if ("/system"s == fsrec_mount_point) return false;
-    }
-    return true;
-}
-
-const char* fs_mgr_mount_point(const fstab* fstab, const char* mount_point) {
+const char* fs_mgr_mount_point(const char* mount_point) {
     if (!mount_point) return mount_point;
     if ("/"s != mount_point) return mount_point;
-    if (!fs_mgr_system_root_image(fstab)) return mount_point;
     return "/system";
 }
 
@@ -533,7 +517,7 @@
     for (auto i = 0; i < fstab->num_entries; i++) {
         const auto fsrec = &fstab->recs[i];
         if (!fs_mgr_wants_overlayfs(fsrec)) continue;
-        std::string new_mount_point(fs_mgr_mount_point(fstab, fsrec->mount_point));
+        std::string new_mount_point(fs_mgr_mount_point(fsrec->mount_point));
         if (mount_point && (new_mount_point != mount_point)) continue;
         if (std::find(verity.begin(), verity.end(), android::base::Basename(new_mount_point)) !=
             verity.end()) {
@@ -776,7 +760,7 @@
     std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
                                                                fs_mgr_free_fstab);
     if (!fstab) return ret;
-    auto mounts = fs_mgr_candidate_list(fstab.get(), fs_mgr_mount_point(fstab.get(), mount_point));
+    auto mounts = fs_mgr_candidate_list(fstab.get(), fs_mgr_mount_point(mount_point));
     if (mounts.empty()) return ret;
 
     std::string dir;
@@ -811,10 +795,7 @@
 // If something is altered, set *change.
 bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) {
     if (change) *change = false;
-    mount_point = fs_mgr_mount_point(std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>(
-                                             fs_mgr_read_fstab_default(), fs_mgr_free_fstab)
-                                             .get(),
-                                     mount_point);
+    mount_point = fs_mgr_mount_point(mount_point);
     auto ret = true;
     for (const auto& overlay_mount_point : kOverlayMountPoints) {
         ret &= fs_mgr_overlayfs_teardown_one(overlay_mount_point, mount_point ?: "", change);
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 17d34e1..7da2526 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -1018,7 +1018,11 @@
         if (siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) {
             if (e4crypt_is_native()) {
                 LOG(ERROR) << "Rebooting into recovery, reason: " << reboot_reason;
-                reboot_into_recovery({"--prompt_and_wipe_data", "--reason="s + reboot_reason});
+                if (auto result = reboot_into_recovery(
+                            {"--prompt_and_wipe_data", "--reason="s + reboot_reason});
+                    !result) {
+                    LOG(FATAL) << "Could not reboot into recovery: " << result.error();
+                }
             } else {
                 LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason;
             }
diff --git a/init/keychords.cpp b/init/keychords.cpp
index b8c1cfd..f5ac44f 100644
--- a/init/keychords.cpp
+++ b/init/keychords.cpp
@@ -41,7 +41,7 @@
 
 Keychords::~Keychords() noexcept {
     if (inotify_fd_ >= 0) {
-        epoll_->UnregisterHandler(inotify_fd_);
+        epoll_->UnregisterHandler(inotify_fd_).IgnoreError();
         ::close(inotify_fd_);
     }
     while (!registration_.empty()) GeteventCloseDevice(registration_.begin()->first);
@@ -186,7 +186,11 @@
         current_ |= mask & available & set;
         LambdaCheck();
     }
-    epoll_->RegisterHandler(fd, [this, fd]() { this->LambdaHandler(fd); });
+    if (auto result = epoll_->RegisterHandler(fd, [this, fd]() { this->LambdaHandler(fd); });
+        !result) {
+        LOG(WARNING) << "Could not register keychord epoll handler: " << result.error();
+        return false;
+    }
     return true;
 }
 
@@ -208,7 +212,7 @@
     auto it = registration_.find(device);
     if (it == registration_.end()) return;
     auto fd = (*it).second;
-    epoll_->UnregisterHandler(fd);
+    epoll_->UnregisterHandler(fd).IgnoreError();
     registration_.erase(it);
     ::close(fd);
 }
@@ -266,7 +270,11 @@
     }
 
     if (inotify_fd_ >= 0) {
-        epoll_->RegisterHandler(inotify_fd_, [this]() { this->InotifyHandler(); });
+        if (auto result =
+                    epoll_->RegisterHandler(inotify_fd_, [this]() { this->InotifyHandler(); });
+            !result) {
+            LOG(WARNING) << "Could not register keychord epoll handler: " << result.error();
+        }
     }
 }
 
diff --git a/init/keychords_test.cpp b/init/keychords_test.cpp
index a3baeb1..e5a6fd3 100644
--- a/init/keychords_test.cpp
+++ b/init/keychords_test.cpp
@@ -213,7 +213,7 @@
 }
 
 void TestFrame::RelaxForMs(std::chrono::milliseconds wait) {
-    epoll_.Wait(wait);
+    epoll_.Wait(wait).IgnoreError();
 }
 
 void TestFrame::SetChord(int key, bool value) {
diff --git a/init/reboot.cpp b/init/reboot.cpp
index d476336..a145797 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -142,7 +142,9 @@
         LOG(WARNING) << "cannot find blank_screen in TurnOffBacklight";
         return;
     }
-    service->Start();
+    if (auto result = service->Start(); !result) {
+        LOG(WARNING) << "Could not start blank_screen service: " << result.error();
+    }
 }
 
 static void ShutdownVold() {
diff --git a/init/result.h b/init/result.h
index fc03962..0e3fd3d 100644
--- a/init/result.h
+++ b/init/result.h
@@ -151,7 +151,7 @@
 }
 
 template <typename T>
-class Result {
+class [[nodiscard]] Result {
   public:
     Result() {}
 
@@ -170,6 +170,8 @@
         : contents_(std::in_place_index_t<1>(), std::move(result_error.error_string),
                     result_error.error_errno) {}
 
+    void IgnoreError() const {}
+
     bool has_value() const { return contents_.index() == 0; }
 
     T& value() & { return std::get<0>(contents_); }
diff --git a/init/subcontext_benchmark.cpp b/init/subcontext_benchmark.cpp
index 6307993..eae03e3 100644
--- a/init/subcontext_benchmark.cpp
+++ b/init/subcontext_benchmark.cpp
@@ -39,7 +39,7 @@
     free(context);
 
     while (state.KeepRunning()) {
-        subcontext.Execute(std::vector<std::string>{"return_success"});
+        subcontext.Execute(std::vector<std::string>{"return_success"}).IgnoreError();
     }
 
     if (subcontext.pid() > 0) {
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 24ea7aa..9dc2699 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -374,6 +374,7 @@
                     continue;
                 if (!if_indextoname(* (int *) RTA_DATA(rta), dev))
                     return false;
+                continue;
             default:
                 continue;
         }
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index fd3f602..3308adf 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -23,11 +23,21 @@
         "-D_FILE_OFFSET_BITS=64",
     ],
     cppflags: [
-        "-Wold-style-cast",
         // Incorrectly warns when C++11 empty brace {} initializer is used.
         // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61489
         "-Wno-missing-field-initializers",
     ],
+
+    // Enable -Wold-style-cast only for non-Windows targets.  _islower_l,
+    // _isupper_l etc. in MinGW locale_win32.h (included from
+    // libcxx/include/__locale) has an old-style-cast.
+    target: {
+        not_windows: {
+            cppflags: [
+                "-Wold-style-cast",
+            ],
+        },
+    },
 }
 
 cc_defaults {
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 1980dc6..8b68dca 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -822,7 +822,7 @@
 }
 
 #ifdef LMKD_LOG_STATS
-static void memory_stat_parse_line(char *line, struct memory_stat *mem_st) {
+static void memory_stat_parse_line(char* line, struct memory_stat* mem_st) {
     char key[LINE_MAX + 1];
     int64_t value;
 
@@ -844,17 +844,10 @@
         mem_st->swap_in_bytes = value;
 }
 
-static int memory_stat_parse(struct memory_stat *mem_st,  int pid, uid_t uid) {
+static int memory_stat_from_cgroup(struct memory_stat* mem_st, int pid, uid_t uid) {
     FILE *fp;
     char buf[PATH_MAX];
 
-    /*
-     * Per-application memory.stat files are available only when
-     * per-application memcgs are enabled.
-     */
-    if (!per_app_memcg)
-        return -1;
-
     snprintf(buf, sizeof(buf), MEMCG_PROCESS_MEMORY_STAT_PATH, uid, pid);
 
     fp = fopen(buf, "r");
@@ -864,13 +857,50 @@
         return -1;
     }
 
-    while (fgets(buf, PAGE_SIZE, fp) != NULL ) {
+    while (fgets(buf, PAGE_SIZE, fp) != NULL) {
         memory_stat_parse_line(buf, mem_st);
     }
     fclose(fp);
 
     return 0;
 }
+
+static int memory_stat_from_procfs(struct memory_stat* mem_st, int pid) {
+    char path[PATH_MAX];
+    char buffer[PROC_STAT_BUFFER_SIZE];
+    int fd, ret;
+
+    snprintf(path, sizeof(path), PROC_STAT_FILE_PATH, pid);
+    if ((fd = open(path, O_RDONLY | O_CLOEXEC)) < 0) {
+        ALOGE("%s open failed: %s", path, strerror(errno));
+        return -1;
+    }
+
+    ret = read(fd, buffer, sizeof(buffer));
+    if (ret < 0) {
+        ALOGE("%s read failed: %s", path, strerror(errno));
+        close(fd);
+        return -1;
+    }
+    close(fd);
+
+    // field 10 is pgfault
+    // field 12 is pgmajfault
+    // field 24 is rss_in_pages
+    int64_t pgfault = 0, pgmajfault = 0, rss_in_pages = 0;
+    if (sscanf(buffer,
+               "%*u %*s %*s %*d %*d %*d %*d %*d %*d %" SCNd64 " %*d "
+               "%" SCNd64 " %*d %*u %*u %*d %*d %*d %*d %*d %*d "
+               "%*d %*d %" SCNd64 "",
+               &pgfault, &pgmajfault, &rss_in_pages) != 3) {
+        return -1;
+    }
+    mem_st->pgfault = pgfault;
+    mem_st->pgmajfault = pgmajfault;
+    mem_st->rss_in_bytes = (rss_in_pages * PAGE_SIZE);
+
+    return 0;
+}
 #endif
 
 /* /prop/zoneinfo parsing routines */
@@ -1125,7 +1155,11 @@
 
 #ifdef LMKD_LOG_STATS
     if (enable_stats_log) {
-        memory_stat_parse_result = memory_stat_parse(&mem_st, pid, uid);
+        if (per_app_memcg) {
+            memory_stat_parse_result = memory_stat_from_cgroup(&mem_st, pid, uid);
+        } else {
+            memory_stat_parse_result = memory_stat_from_procfs(&mem_st, pid);
+        }
     }
 #endif
 
@@ -1148,6 +1182,9 @@
             stats_write_lmk_kill_occurred(log_ctx, LMK_KILL_OCCURRED, uid, taskname,
                     procp->oomadj, mem_st.pgfault, mem_st.pgmajfault, mem_st.rss_in_bytes,
                     mem_st.cache_in_bytes, mem_st.swap_in_bytes);
+        } else if (enable_stats_log) {
+            stats_write_lmk_kill_occurred(log_ctx, LMK_KILL_OCCURRED, uid, taskname, procp->oomadj,
+                                          -1, -1, tasksize * BYTES_IN_KILOBYTE, -1, -1);
         }
 #endif
         return tasksize;
diff --git a/lmkd/statslog.h b/lmkd/statslog.h
index edebb19..8458480 100644
--- a/lmkd/statslog.h
+++ b/lmkd/statslog.h
@@ -67,6 +67,9 @@
 };
 
 #define MEMCG_PROCESS_MEMORY_STAT_PATH "/dev/memcg/apps/uid_%u/pid_%u/memory.stat"
+#define PROC_STAT_FILE_PATH "/proc/%d/stat"
+#define PROC_STAT_BUFFER_SIZE 1024
+#define BYTES_IN_KILOBYTE 1024
 
 /**
  * Logs the change in LMKD state which is used as start/stop boundaries for logging