Merge "Restore fastboot delete-logical-partition command for VTS"
diff --git a/adb/Android.bp b/adb/Android.bp
index 139ee23..1b7a266 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -589,11 +589,9 @@
         "libcrypto_utils",
         "libcutils_sockets",
         "libdiagnose_usb",
-        "liblog",
         "libmdnssd",
         "libminijail",
         "libprotobuf-cpp-lite",
-        "libselinux",
         "libssl",
     ],
 
@@ -603,6 +601,8 @@
         "libadbd_auth",
         "libadbd_fs",
         "libcrypto",
+        "liblog",
+        "libselinux",
     ],
 
     target: {
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 1186060..7c7da08 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -194,8 +194,8 @@
         "     generate adb public/private key; private key stored in FILE,\n"
         "\n"
         "scripting:\n"
-        " wait-for[-TRANSPORT]-STATE\n"
-        "     wait for device to be in the given state\n"
+        " wait-for[-TRANSPORT]-STATE...\n"
+        "     wait for device to be in a given state\n"
         "     STATE: device, recovery, rescue, sideload, bootloader, or disconnect\n"
         "     TRANSPORT: usb, local, or any [default=any]\n"
         " get-state                print offline | bootloader | device\n"
@@ -1057,17 +1057,16 @@
 static bool wait_for_device(const char* service,
                             std::optional<std::chrono::milliseconds> timeout = std::nullopt) {
     std::vector<std::string> components = android::base::Split(service, "-");
-    if (components.size() < 3 || components.size() > 4) {
+    if (components.size() < 3) {
         fprintf(stderr, "adb: couldn't parse 'wait-for' command: %s\n", service);
         return false;
     }
 
-    TransportType t;
-    adb_get_transport(&t, nullptr, nullptr);
-
-    // Was the caller vague about what they'd like us to wait for?
-    // If so, check they weren't more specific in their choice of transport type.
-    if (components.size() == 3) {
+    // If the first thing after "wait-for-" wasn't a TRANSPORT, insert whatever
+    // the current transport implies.
+    if (components[2] != "usb" && components[2] != "local" && components[2] != "any") {
+        TransportType t;
+        adb_get_transport(&t, nullptr, nullptr);
         auto it = components.begin() + 2;
         if (t == kTransportUsb) {
             components.insert(it, "usb");
@@ -1076,23 +1075,9 @@
         } else {
             components.insert(it, "any");
         }
-    } else if (components[2] != "any" && components[2] != "local" && components[2] != "usb") {
-        fprintf(stderr, "adb: unknown type %s; expected 'any', 'local', or 'usb'\n",
-                components[2].c_str());
-        return false;
     }
 
-    if (components[3] != "any" && components[3] != "bootloader" && components[3] != "device" &&
-        components[3] != "recovery" && components[3] != "rescue" && components[3] != "sideload" &&
-        components[3] != "disconnect") {
-        fprintf(stderr,
-                "adb: unknown state %s; "
-                "expected 'any', 'bootloader', 'device', 'recovery', 'rescue', 'sideload', or "
-                "'disconnect'\n",
-                components[3].c_str());
-        return false;
-    }
-
+    // Stitch it back together and send it over...
     std::string cmd = format_host_command(android::base::Join(components, "-").c_str());
     if (timeout) {
         std::thread([timeout]() {
diff --git a/adb/client/file_sync_client.cpp b/adb/client/file_sync_client.cpp
index cc38926..04ad536 100644
--- a/adb/client/file_sync_client.cpp
+++ b/adb/client/file_sync_client.cpp
@@ -1097,14 +1097,14 @@
         }
     };
 
-    if (!sync_ls(sc, rpath.c_str(), callback)) {
+    if (!sync_ls(sc, rpath, callback)) {
         return false;
     }
 
     // Check each symlink we found to see whether it's a file or directory.
     for (copyinfo& link_ci : linklist) {
         struct stat st;
-        if (!sync_stat_fallback(sc, link_ci.rpath.c_str(), &st)) {
+        if (!sync_stat_fallback(sc, link_ci.rpath, &st)) {
             sc.Warning("stat failed for path %s: %s", link_ci.rpath.c_str(), strerror(errno));
             continue;
         }
diff --git a/adb/services.cpp b/adb/services.cpp
index 853d658..d87948c 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -95,56 +95,6 @@
 }
 
 #if ADB_HOST
-struct state_info {
-    TransportType transport_type;
-    std::string serial;
-    TransportId transport_id;
-    ConnectionState state;
-};
-
-static void wait_for_state(unique_fd fd, state_info* sinfo) {
-    D("wait_for_state %d", sinfo->state);
-
-    while (true) {
-        bool is_ambiguous = false;
-        std::string error = "unknown error";
-        const char* serial = sinfo->serial.length() ? sinfo->serial.c_str() : nullptr;
-        atransport* t = acquire_one_transport(sinfo->transport_type, serial, sinfo->transport_id,
-                                              &is_ambiguous, &error);
-        if (sinfo->state == kCsOffline) {
-            // wait-for-disconnect uses kCsOffline, we don't actually want to wait for 'offline'.
-            if (t == nullptr) {
-                SendOkay(fd);
-                break;
-            }
-        } else if (t != nullptr &&
-                   (sinfo->state == kCsAny || sinfo->state == t->GetConnectionState())) {
-            SendOkay(fd);
-            break;
-        }
-
-        if (!is_ambiguous) {
-            adb_pollfd pfd = {.fd = fd.get(), .events = POLLIN};
-            int rc = adb_poll(&pfd, 1, 100);
-            if (rc < 0) {
-                SendFail(fd, error);
-                break;
-            } else if (rc > 0 && (pfd.revents & POLLHUP) != 0) {
-                // The other end of the socket is closed, probably because the other side was
-                // terminated, bail out.
-                break;
-            }
-
-            // Try again...
-        } else {
-            SendFail(fd, error);
-            break;
-        }
-    }
-
-    D("wait_for_state is done");
-}
-
 void connect_emulator(const std::string& port_spec, std::string* response) {
     std::vector<std::string> pieces = android::base::Split(port_spec, ",");
     if (pieces.size() != 2) {
@@ -201,6 +151,80 @@
     adb_wifi_pair_device(host, password, response);
     SendProtocolString(fd.get(), response);
 }
+
+static void wait_service(unique_fd fd, std::string serial, TransportId transport_id,
+                         std::string spec) {
+    std::vector<std::string> components = android::base::Split(spec, "-");
+    if (components.size() < 2) {
+        SendFail(fd, "short wait-for-: " + spec);
+        return;
+    }
+
+    TransportType transport_type;
+    if (components[0] == "local") {
+        transport_type = kTransportLocal;
+    } else if (components[0] == "usb") {
+        transport_type = kTransportUsb;
+    } else if (components[0] == "any") {
+        transport_type = kTransportAny;
+    } else {
+        SendFail(fd, "bad wait-for- transport: " + spec);
+        return;
+    }
+
+    std::vector<ConnectionState> states;
+    for (size_t i = 1; i < components.size(); ++i) {
+        if (components[i] == "device") {
+            states.push_back(kCsDevice);
+        } else if (components[i] == "recovery") {
+            states.push_back(kCsRecovery);
+        } else if (components[i] == "rescue") {
+            states.push_back(kCsRescue);
+        } else if (components[i] == "sideload") {
+            states.push_back(kCsSideload);
+        } else if (components[i] == "bootloader") {
+            states.push_back(kCsBootloader);
+        } else if (components[i] == "any") {
+            states.push_back(kCsAny);
+        } else if (components[i] == "disconnect") {
+            states.push_back(kCsOffline);
+        } else {
+            SendFail(fd, "bad wait-for- state: " + spec);
+            return;
+        }
+    }
+
+    while (true) {
+        bool is_ambiguous = false;
+        std::string error = "unknown error";
+        atransport* t =
+                acquire_one_transport(transport_type, !serial.empty() ? serial.c_str() : nullptr,
+                                      transport_id, &is_ambiguous, &error);
+
+        for (const auto& state : states) {
+            // wait-for-disconnect uses kCsOffline, we don't actually want to wait for 'offline'.
+            if ((t == nullptr && state == kCsOffline) || (t != nullptr && state == kCsAny) ||
+                (t != nullptr && state == t->GetConnectionState())) {
+                SendOkay(fd);
+                return;
+            }
+        }
+
+        if (is_ambiguous) {
+            SendFail(fd, error);
+            return;
+        }
+
+        // Sleep before retrying.
+        adb_pollfd pfd = {.fd = fd.get(), .events = POLLIN};
+        if (adb_poll(&pfd, 1, 100) != 0) {
+            // The other end of the socket is closed, probably because the
+            // client terminated. Bail out.
+            SendFail(fd, error);
+            return;
+        }
+    }
+}
 #endif
 
 #if ADB_HOST
@@ -211,45 +235,10 @@
     } else if (name == "track-devices-l") {
         return create_device_tracker(true);
     } else if (android::base::ConsumePrefix(&name, "wait-for-")) {
-        std::shared_ptr<state_info> sinfo = std::make_shared<state_info>();
-        if (sinfo == nullptr) {
-            fprintf(stderr, "couldn't allocate state_info: %s", strerror(errno));
-            return nullptr;
-        }
-
-        sinfo->serial = serial;
-        sinfo->transport_id = transport_id;
-
-        if (android::base::ConsumePrefix(&name, "local")) {
-            sinfo->transport_type = kTransportLocal;
-        } else if (android::base::ConsumePrefix(&name, "usb")) {
-            sinfo->transport_type = kTransportUsb;
-        } else if (android::base::ConsumePrefix(&name, "any")) {
-            sinfo->transport_type = kTransportAny;
-        } else {
-            return nullptr;
-        }
-
-        if (name == "-device") {
-            sinfo->state = kCsDevice;
-        } else if (name == "-recovery") {
-            sinfo->state = kCsRecovery;
-        } else if (name == "-rescue") {
-            sinfo->state = kCsRescue;
-        } else if (name == "-sideload") {
-            sinfo->state = kCsSideload;
-        } else if (name == "-bootloader") {
-            sinfo->state = kCsBootloader;
-        } else if (name == "-any") {
-            sinfo->state = kCsAny;
-        } else if (name == "-disconnect") {
-            sinfo->state = kCsOffline;
-        } else {
-            return nullptr;
-        }
-
-        unique_fd fd = create_service_thread(
-                "wait", [sinfo](unique_fd fd) { wait_for_state(std::move(fd), sinfo.get()); });
+        std::string spec(name);
+        unique_fd fd =
+                create_service_thread("wait", std::bind(wait_service, std::placeholders::_1,
+                                                        std::string(serial), transport_id, spec));
         return create_local_socket(std::move(fd));
     } else if (android::base::ConsumePrefix(&name, "connect:")) {
         std::string host(name);
diff --git a/base/liblog_symbols.cpp b/base/liblog_symbols.cpp
index d5dfcd2..8d59179 100644
--- a/base/liblog_symbols.cpp
+++ b/base/liblog_symbols.cpp
@@ -16,14 +16,20 @@
 
 #include "liblog_symbols.h"
 
-#if defined(__ANDROID__) && !defined(NO_LIBLOG_DLSYM)
+#if defined(__ANDROID__)
+#if !defined(NO_LIBLOG_DLSYM) || defined(__ANDROID_APEX__)
+#define USE_DLSYM
+#endif
+#endif
+
+#ifdef USE_DLSYM
 #include <dlfcn.h>
 #endif
 
 namespace android {
 namespace base {
 
-#if defined(__ANDROID__) && !defined(NO_LIBLOG_DLSYM)
+#ifdef USE_DLSYM
 
 const std::optional<LibLogFunctions>& GetLibLogFunctions() {
   static std::optional<LibLogFunctions> liblog_functions = []() -> std::optional<LibLogFunctions> {
diff --git a/base/liblog_symbols.h b/base/liblog_symbols.h
index d3134e9..b4ab06a 100644
--- a/base/liblog_symbols.h
+++ b/base/liblog_symbols.h
@@ -36,8 +36,8 @@
   void (*__android_log_set_aborter)(__android_aborter_function aborter);
   void (*__android_log_call_aborter)(const char* abort_message);
   void (*__android_log_default_aborter)(const char* abort_message);
-  int (*__android_log_set_minimum_priority)(int priority);
-  int (*__android_log_get_minimum_priority)();
+  int32_t (*__android_log_set_minimum_priority)(int32_t priority);
+  int32_t (*__android_log_get_minimum_priority)();
   void (*__android_log_set_default_tag)(const char* tag);
 };
 
diff --git a/base/logging.cpp b/base/logging.cpp
index 9360a56..9a6e0fb 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -118,7 +118,7 @@
 }
 #endif
 
-static LogId log_id_tToLogId(int buffer_id) {
+static LogId log_id_tToLogId(int32_t buffer_id) {
   switch (buffer_id) {
     case LOG_ID_MAIN:
       return MAIN;
@@ -134,7 +134,7 @@
   }
 }
 
-static int LogIdTolog_id_t(LogId log_id) {
+static int32_t LogIdTolog_id_t(LogId log_id) {
   switch (log_id) {
     case MAIN:
       return LOG_ID_MAIN;
@@ -171,7 +171,7 @@
   }
 }
 
-static android_LogPriority LogSeverityToPriority(LogSeverity severity) {
+static int32_t LogSeverityToPriority(LogSeverity severity) {
   switch (severity) {
     case VERBOSE:
       return ANDROID_LOG_VERBOSE;
@@ -333,12 +333,12 @@
 void LogdLogger::operator()(LogId id, LogSeverity severity, const char* tag,
                             const char* file, unsigned int line,
                             const char* message) {
-  android_LogPriority priority = LogSeverityToPriority(severity);
+  int32_t priority = LogSeverityToPriority(severity);
   if (id == DEFAULT) {
     id = default_log_id_;
   }
 
-  int lg_id = LogIdTolog_id_t(id);
+  int32_t lg_id = LogIdTolog_id_t(id);
 
   char log_message_with_file[4068];  // LOGGER_ENTRY_MAX_PAYLOAD, not available in the NDK.
   if (priority == ANDROID_LOG_FATAL && file != nullptr) {
@@ -574,7 +574,7 @@
 void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity severity, const char* tag,
                          const char* message) {
   static auto& liblog_functions = GetLibLogFunctions();
-  auto priority = LogSeverityToPriority(severity);
+  int32_t priority = LogSeverityToPriority(severity);
   if (liblog_functions) {
     __android_logger_data logger_data = {
         sizeof(__android_logger_data), LOG_ID_DEFAULT, priority, tag, file, line};
@@ -608,7 +608,7 @@
   // we need to fall back to using gMinimumLogSeverity, since __android_log_is_loggable() will not
   // take into consideration the value from SetMinimumLogSeverity().
   if (liblog_functions) {
-    int priority = LogSeverityToPriority(severity);
+    int32_t priority = LogSeverityToPriority(severity);
     return __android_log_is_loggable(priority, tag, ANDROID_LOG_INFO);
   } else {
     return severity >= gMinimumLogSeverity;
@@ -618,7 +618,7 @@
 LogSeverity SetMinimumLogSeverity(LogSeverity new_severity) {
   static auto& liblog_functions = GetLibLogFunctions();
   if (liblog_functions) {
-    auto priority = LogSeverityToPriority(new_severity);
+    int32_t priority = LogSeverityToPriority(new_severity);
     return PriorityToLogSeverity(liblog_functions->__android_log_set_minimum_priority(priority));
   } else {
     LogSeverity old_severity = gMinimumLogSeverity;
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 0089989..c0c0e99 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1588,76 +1588,58 @@
     }
 }
 
-static std::string ResolveBlockDevice(const std::string& block_device) {
+static bool UnwindDmDeviceStack(const std::string& block_device,
+                                std::vector<std::string>* dm_stack) {
     if (!StartsWith(block_device, "/dev/block/")) {
         LWARNING << block_device << " is not a block device";
-        return block_device;
+        return false;
     }
-    std::string name = block_device.substr(5);
-    if (!StartsWith(name, "block/dm-")) {
-        // Not a dm-device, but might be a symlink. Optimistically try to readlink.
-        std::string result;
-        if (Readlink(block_device, &result)) {
-            return result;
-        } else if (errno == EINVAL) {
-            // After all, it wasn't a symlink.
-            return block_device;
-        } else {
-            LERROR << "Failed to readlink " << block_device;
-            return "";
-        }
-    }
-    // It's a dm-device, let's find what's inside!
-    std::string sys_dir = "/sys/" + name;
+    std::string current = block_device;
+    DeviceMapper& dm = DeviceMapper::Instance();
     while (true) {
-        std::string slaves_dir = sys_dir + "/slaves";
-        std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(slaves_dir.c_str()), closedir);
-        if (!dir) {
-            LERROR << "Failed to open " << slaves_dir;
-            return "";
+        dm_stack->push_back(current);
+        if (!dm.IsDmBlockDevice(current)) {
+            break;
         }
-        std::string sub_device_name = "";
-        for (auto entry = readdir(dir.get()); entry; entry = readdir(dir.get())) {
-            if (entry->d_type != DT_LNK) continue;
-            if (!sub_device_name.empty()) {
-                LERROR << "Too many slaves in " << slaves_dir;
-                return "";
-            }
-            sub_device_name = entry->d_name;
+        auto parent = dm.GetParentBlockDeviceByPath(current);
+        if (!parent) {
+            return false;
         }
-        if (sub_device_name.empty()) {
-            LERROR << "No slaves in " << slaves_dir;
-            return "";
-        }
-        if (!StartsWith(sub_device_name, "dm-")) {
-            // Not a dm-device! We can stop now.
-            return "/dev/block/" + sub_device_name;
-        }
-        // Still a dm-device, keep digging.
-        sys_dir = "/sys/block/" + sub_device_name;
+        current = *parent;
     }
+    return true;
 }
 
 FstabEntry* fs_mgr_get_mounted_entry_for_userdata(Fstab* fstab, const FstabEntry& mounted_entry) {
-    std::string resolved_block_device = ResolveBlockDevice(mounted_entry.blk_device);
-    if (resolved_block_device.empty()) {
+    if (mounted_entry.mount_point != "/data") {
+        LERROR << mounted_entry.mount_point << " is not /data";
         return nullptr;
     }
-    LINFO << "/data is mounted on " << resolved_block_device;
+    std::vector<std::string> dm_stack;
+    if (!UnwindDmDeviceStack(mounted_entry.blk_device, &dm_stack)) {
+        LERROR << "Failed to unwind dm-device stack for " << mounted_entry.blk_device;
+        return nullptr;
+    }
     for (auto& entry : *fstab) {
         if (entry.mount_point != "/data") {
             continue;
         }
         std::string block_device;
-        if (!Readlink(entry.blk_device, &block_device)) {
-            LWARNING << "Failed to readlink " << entry.blk_device;
+        if (entry.fs_mgr_flags.logical) {
+            if (!fs_mgr_update_logical_partition(&entry)) {
+                LERROR << "Failed to update logic partition " << entry.blk_device;
+                continue;
+            }
+            block_device = entry.blk_device;
+        } else if (!Readlink(entry.blk_device, &block_device)) {
+            PWARNING << "Failed to read link " << entry.blk_device;
             block_device = entry.blk_device;
         }
-        if (block_device == resolved_block_device) {
+        if (std::find(dm_stack.begin(), dm_stack.end(), block_device) != dm_stack.end()) {
             return &entry;
         }
     }
-    LERROR << "Didn't find entry that was used to mount /data";
+    LERROR << "Didn't find entry that was used to mount /data onto " << mounted_entry.blk_device;
     return nullptr;
 }
 
diff --git a/fs_mgr/libfiemap/Android.bp b/fs_mgr/libfiemap/Android.bp
index 2fd463c..ac589c7 100644
--- a/fs_mgr/libfiemap/Android.bp
+++ b/fs_mgr/libfiemap/Android.bp
@@ -45,6 +45,7 @@
     whole_static_libs: [
         "gsi_aidl_interface-cpp",
         "libgsi",
+        "libgsid",
     ],
     shared_libs: [
         "libbinder",
diff --git a/fs_mgr/libfiemap/binder.cpp b/fs_mgr/libfiemap/binder.cpp
index 5e29d4e..c8516ab 100644
--- a/fs_mgr/libfiemap/binder.cpp
+++ b/fs_mgr/libfiemap/binder.cpp
@@ -19,9 +19,9 @@
 #include <android-base/properties.h>
 #include <android/gsi/BnProgressCallback.h>
 #include <android/gsi/IGsiService.h>
-#include <binder/IServiceManager.h>
 #include <libfiemap/image_manager.h>
 #include <libgsi/libgsi.h>
+#include <libgsi/libgsid.h>
 
 namespace android {
 namespace fiemap {
@@ -224,19 +224,9 @@
     return false;
 }
 
-static sp<IGsiService> GetGsiService() {
-    auto sm = android::defaultServiceManager();
-    auto name = android::String16(kGsiServiceName);
-    android::sp<android::IBinder> res = sm->waitForService(name);
-    if (res) {
-        return android::interface_cast<IGsiService>(res);
-    }
-    return nullptr;
-}
-
 std::unique_ptr<IImageManager> IImageManager::Open(
         const std::string& dir, const std::chrono::milliseconds& /*timeout_ms*/) {
-    android::sp<IGsiService> service = GetGsiService();
+    android::sp<IGsiService> service = android::gsi::GetGsiService();
     android::sp<IImageService> manager;
 
     auto status = service->openImageService(dir, &manager);
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 68a81ed..957c26c 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -74,7 +74,8 @@
 
 static constexpr const std::string_view kCowGroupName = "cow";
 
-bool SourceCopyOperationIsClone(const chromeos_update_engine::InstallOperation& operation);
+bool OptimizeSourceCopyOperation(const chromeos_update_engine::InstallOperation& operation,
+                                 chromeos_update_engine::InstallOperation* optimized);
 
 enum class CreateResult : unsigned int {
     ERROR,
diff --git a/fs_mgr/libsnapshot/partition_cow_creator.cpp b/fs_mgr/libsnapshot/partition_cow_creator.cpp
index 61f5c0c..efdb59f 100644
--- a/fs_mgr/libsnapshot/partition_cow_creator.cpp
+++ b/fs_mgr/libsnapshot/partition_cow_creator.cpp
@@ -62,17 +62,68 @@
     return false;
 }
 
-bool SourceCopyOperationIsClone(const InstallOperation& operation) {
-    using ChromeOSExtent = chromeos_update_engine::Extent;
-    if (operation.src_extents().size() != operation.dst_extents().size()) {
+bool OptimizeSourceCopyOperation(const InstallOperation& operation, InstallOperation* optimized) {
+    if (operation.type() != InstallOperation::SOURCE_COPY) {
         return false;
     }
-    return std::equal(operation.src_extents().begin(), operation.src_extents().end(),
-                      operation.dst_extents().begin(),
-                      [](const ChromeOSExtent& src, const ChromeOSExtent& dst) {
-                          return src.start_block() == dst.start_block() &&
-                                 src.num_blocks() == dst.num_blocks();
-                      });
+
+    optimized->Clear();
+    optimized->set_type(InstallOperation::SOURCE_COPY);
+
+    const auto& src_extents = operation.src_extents();
+    const auto& dst_extents = operation.dst_extents();
+
+    // If input is empty, skip by returning an empty result.
+    if (src_extents.empty() && dst_extents.empty()) {
+        return true;
+    }
+
+    auto s_it = src_extents.begin();
+    auto d_it = dst_extents.begin();
+    uint64_t s_offset = 0;  // offset within *s_it
+    uint64_t d_offset = 0;  // offset within *d_it
+    bool is_optimized = false;
+
+    while (s_it != src_extents.end() || d_it != dst_extents.end()) {
+        if (s_it == src_extents.end() || d_it == dst_extents.end()) {
+            LOG(ERROR) << "number of blocks do not equal in src_extents and dst_extents";
+            return false;
+        }
+        if (s_it->num_blocks() <= s_offset || d_it->num_blocks() <= d_offset) {
+            LOG(ERROR) << "Offset goes out of bounds.";
+            return false;
+        }
+
+        // Check the next |step| blocks, where |step| is the min of remaining blocks in the current
+        // source extent and current destination extent.
+        auto s_step = s_it->num_blocks() - s_offset;
+        auto d_step = d_it->num_blocks() - d_offset;
+        auto step = std::min(s_step, d_step);
+
+        bool moved = s_it->start_block() + s_offset != d_it->start_block() + d_offset;
+        if (moved) {
+            // If the next |step| blocks are not copied to the same location, add them to result.
+            AppendExtent(optimized->mutable_src_extents(), s_it->start_block() + s_offset, step);
+            AppendExtent(optimized->mutable_dst_extents(), d_it->start_block() + d_offset, step);
+        } else {
+            // The next |step| blocks are optimized out.
+            is_optimized = true;
+        }
+
+        // Advance offsets by |step|, and go to the next non-empty extent if the current extent is
+        // depleted.
+        s_offset += step;
+        d_offset += step;
+        while (s_it != src_extents.end() && s_offset >= s_it->num_blocks()) {
+            ++s_it;
+            s_offset = 0;
+        }
+        while (d_it != dst_extents.end() && d_offset >= d_it->num_blocks()) {
+            ++d_it;
+            d_offset = 0;
+        }
+    }
+    return is_optimized;
 }
 
 void WriteExtent(DmSnapCowSizeCalculator* sc, const chromeos_update_engine::Extent& de,
@@ -101,12 +152,15 @@
     if (operations == nullptr) return sc.cow_size_bytes();
 
     for (const auto& iop : *operations) {
-        // Do not allocate space for operations that are going to be skipped
+        const InstallOperation* written_op = &iop;
+        InstallOperation buf;
+        // Do not allocate space for extents that are going to be skipped
         // during OTA application.
-        if (iop.type() == InstallOperation::SOURCE_COPY && SourceCopyOperationIsClone(iop))
-            continue;
+        if (iop.type() == InstallOperation::SOURCE_COPY && OptimizeSourceCopyOperation(iop, &buf)) {
+            written_op = &buf;
+        }
 
-        for (const auto& de : iop.dst_extents()) {
+        for (const auto& de : written_op->dst_extents()) {
             WriteExtent(&sc, de, sectors_per_block);
         }
     }
diff --git a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
index 9da3f05..526f874 100644
--- a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
+++ b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
@@ -12,6 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <optional>
+#include <tuple>
+
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <libdm/dm.h>
@@ -26,6 +29,13 @@
 
 using namespace android::fs_mgr;
 
+using chromeos_update_engine::InstallOperation;
+using UeExtent = chromeos_update_engine::Extent;
+using google::protobuf::RepeatedPtrField;
+using ::testing::Matches;
+using ::testing::Pointwise;
+using ::testing::Truly;
+
 namespace android {
 namespace snapshot {
 
@@ -213,5 +223,76 @@
     }
 }
 
+void BlocksToExtents(const std::vector<uint64_t>& blocks,
+                     google::protobuf::RepeatedPtrField<UeExtent>* extents) {
+    for (uint64_t block : blocks) {
+        AppendExtent(extents, block, 1);
+    }
+}
+
+template <typename T>
+std::vector<uint64_t> ExtentsToBlocks(const T& extents) {
+    std::vector<uint64_t> blocks;
+    for (const auto& extent : extents) {
+        for (uint64_t offset = 0; offset < extent.num_blocks(); ++offset) {
+            blocks.push_back(extent.start_block() + offset);
+        }
+    }
+    return blocks;
+}
+
+InstallOperation CreateCopyOp(const std::vector<uint64_t>& src_blocks,
+                              const std::vector<uint64_t>& dst_blocks) {
+    InstallOperation op;
+    op.set_type(InstallOperation::SOURCE_COPY);
+    BlocksToExtents(src_blocks, op.mutable_src_extents());
+    BlocksToExtents(dst_blocks, op.mutable_dst_extents());
+    return op;
+}
+
+// ExtentEqual(tuple<UeExtent, UeExtent>)
+MATCHER(ExtentEqual, "") {
+    auto&& [a, b] = arg;
+    return a.start_block() == b.start_block() && a.num_blocks() == b.num_blocks();
+}
+
+struct OptimizeOperationTestParam {
+    InstallOperation input;
+    std::optional<InstallOperation> expected_output;
+};
+
+class OptimizeOperationTest : public ::testing::TestWithParam<OptimizeOperationTestParam> {};
+TEST_P(OptimizeOperationTest, Test) {
+    InstallOperation actual_output;
+    EXPECT_EQ(GetParam().expected_output.has_value(),
+              OptimizeSourceCopyOperation(GetParam().input, &actual_output))
+            << "OptimizeSourceCopyOperation should "
+            << (GetParam().expected_output.has_value() ? "succeed" : "fail");
+    if (!GetParam().expected_output.has_value()) return;
+    EXPECT_THAT(actual_output.src_extents(),
+                Pointwise(ExtentEqual(), GetParam().expected_output->src_extents()));
+    EXPECT_THAT(actual_output.dst_extents(),
+                Pointwise(ExtentEqual(), GetParam().expected_output->dst_extents()));
+}
+
+std::vector<OptimizeOperationTestParam> GetOptimizeOperationTestParams() {
+    return {
+            {CreateCopyOp({}, {}), CreateCopyOp({}, {})},
+            {CreateCopyOp({1, 2, 4}, {1, 2, 4}), CreateCopyOp({}, {})},
+            {CreateCopyOp({1, 2, 3}, {4, 5, 6}), std::nullopt},
+            {CreateCopyOp({3, 2}, {1, 2}), CreateCopyOp({3}, {1})},
+            {CreateCopyOp({5, 6, 3, 4, 1, 2}, {1, 2, 3, 4, 5, 6}),
+             CreateCopyOp({5, 6, 1, 2}, {1, 2, 5, 6})},
+            {CreateCopyOp({1, 2, 3, 5, 5, 6}, {5, 6, 3, 4, 1, 2}),
+             CreateCopyOp({1, 2, 5, 5, 6}, {5, 6, 4, 1, 2})},
+            {CreateCopyOp({1, 2, 5, 6, 9, 10}, {1, 4, 5, 6, 7, 8}),
+             CreateCopyOp({2, 9, 10}, {4, 7, 8})},
+            {CreateCopyOp({2, 3, 3, 4, 4}, {1, 2, 3, 4, 5}), CreateCopyOp({2, 3, 4}, {1, 2, 5})},
+    };
+}
+
+INSTANTIATE_TEST_CASE_P(Snapshot, OptimizeOperationTest,
+                        ::testing::ValuesIn(GetOptimizeOperationTestParams()));
+
 }  // namespace snapshot
 }  // namespace android
diff --git a/fs_mgr/libsnapshot/utility.cpp b/fs_mgr/libsnapshot/utility.cpp
index 3318b33..d32b61e 100644
--- a/fs_mgr/libsnapshot/utility.cpp
+++ b/fs_mgr/libsnapshot/utility.cpp
@@ -34,6 +34,7 @@
 using android::fs_mgr::MetadataBuilder;
 using android::fs_mgr::Partition;
 using android::fs_mgr::ReadDefaultFstab;
+using google::protobuf::RepeatedPtrField;
 
 namespace android {
 namespace snapshot {
@@ -166,5 +167,20 @@
     return os << std::put_time(&now, "%Y%m%d-%H%M%S");
 }
 
+void AppendExtent(RepeatedPtrField<chromeos_update_engine::Extent>* extents, uint64_t start_block,
+                  uint64_t num_blocks) {
+    if (extents->size() > 0) {
+        auto last_extent = extents->rbegin();
+        auto next_block = last_extent->start_block() + last_extent->num_blocks();
+        if (start_block == next_block) {
+            last_extent->set_num_blocks(last_extent->num_blocks() + num_blocks);
+            return;
+        }
+    }
+    auto* new_extent = extents->Add();
+    new_extent->set_start_block(start_block);
+    new_extent->set_num_blocks(num_blocks);
+}
+
 }  // namespace snapshot
 }  // namespace android
diff --git a/fs_mgr/libsnapshot/utility.h b/fs_mgr/libsnapshot/utility.h
index 90ad0fe..e69bdad 100644
--- a/fs_mgr/libsnapshot/utility.h
+++ b/fs_mgr/libsnapshot/utility.h
@@ -125,5 +125,9 @@
 struct Now {};
 std::ostream& operator<<(std::ostream& os, const Now&);
 
+// Append to |extents|. Merged into the last element if possible.
+void AppendExtent(google::protobuf::RepeatedPtrField<chromeos_update_engine::Extent>* extents,
+                  uint64_t start_block, uint64_t num_blocks);
+
 }  // namespace snapshot
 }  // namespace android
diff --git a/init/Android.bp b/init/Android.bp
index 3bb08db..72a7bfe 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -81,6 +81,7 @@
         "-Wextra",
         "-Wno-unused-parameter",
         "-Werror",
+        "-Wthread-safety",
         "-DALLOW_FIRST_STAGE_CONSOLE=0",
         "-DALLOW_LOCAL_PROP_OVERRIDE=0",
         "-DALLOW_PERMISSIVE_SELINUX=0",
diff --git a/init/action_manager.cpp b/init/action_manager.cpp
index ebca762..b45f5cd 100644
--- a/init/action_manager.cpp
+++ b/init/action_manager.cpp
@@ -41,10 +41,12 @@
 }
 
 void ActionManager::QueueEventTrigger(const std::string& trigger) {
+    auto lock = std::lock_guard{event_queue_lock_};
     event_queue_.emplace(trigger);
 }
 
 void ActionManager::QueuePropertyChange(const std::string& name, const std::string& value) {
+    auto lock = std::lock_guard{event_queue_lock_};
     event_queue_.emplace(std::make_pair(name, value));
 }
 
@@ -53,6 +55,7 @@
 }
 
 void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
+    auto lock = std::lock_guard{event_queue_lock_};
     auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0, name,
                                            std::map<std::string, std::string>{});
     action->AddCommand(std::move(func), {name}, 0);
@@ -62,15 +65,18 @@
 }
 
 void ActionManager::ExecuteOneCommand() {
-    // Loop through the event queue until we have an action to execute
-    while (current_executing_actions_.empty() && !event_queue_.empty()) {
-        for (const auto& action : actions_) {
-            if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
-                           event_queue_.front())) {
-                current_executing_actions_.emplace(action.get());
+    {
+        auto lock = std::lock_guard{event_queue_lock_};
+        // Loop through the event queue until we have an action to execute
+        while (current_executing_actions_.empty() && !event_queue_.empty()) {
+            for (const auto& action : actions_) {
+                if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
+                               event_queue_.front())) {
+                    current_executing_actions_.emplace(action.get());
+                }
             }
+            event_queue_.pop();
         }
-        event_queue_.pop();
     }
 
     if (current_executing_actions_.empty()) {
@@ -103,6 +109,7 @@
 }
 
 bool ActionManager::HasMoreCommands() const {
+    auto lock = std::lock_guard{event_queue_lock_};
     return !current_executing_actions_.empty() || !event_queue_.empty();
 }
 
@@ -113,6 +120,7 @@
 }
 
 void ActionManager::ClearQueue() {
+    auto lock = std::lock_guard{event_queue_lock_};
     // We are shutting down so don't claim the oneshot builtin actions back
     current_executing_actions_ = {};
     event_queue_ = {};
diff --git a/init/action_manager.h b/init/action_manager.h
index a2b95ac..b6f93d9 100644
--- a/init/action_manager.h
+++ b/init/action_manager.h
@@ -16,9 +16,12 @@
 
 #pragma once
 
+#include <mutex>
 #include <string>
 #include <vector>
 
+#include <android-base/thread_annotations.h>
+
 #include "action.h"
 #include "builtins.h"
 
@@ -48,7 +51,9 @@
     void operator=(ActionManager const&) = delete;
 
     std::vector<std::unique_ptr<Action>> actions_;
-    std::queue<std::variant<EventTrigger, PropertyChange, BuiltinAction>> event_queue_;
+    std::queue<std::variant<EventTrigger, PropertyChange, BuiltinAction>> event_queue_
+            GUARDED_BY(event_queue_lock_);
+    mutable std::mutex event_queue_lock_;
     std::queue<const Action*> current_executing_actions_;
     std::size_t current_command_;
 };
diff --git a/init/init.cpp b/init/init.cpp
index a7518fc..b29dfa3 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -33,7 +33,9 @@
 #include <functional>
 #include <map>
 #include <memory>
+#include <mutex>
 #include <optional>
+#include <thread>
 #include <vector>
 
 #include <android-base/chrono_utils.h>
@@ -95,14 +97,155 @@
 static int signal_fd = -1;
 static int property_fd = -1;
 
-static std::unique_ptr<Timer> waiting_for_prop(nullptr);
-static std::string wait_prop_name;
-static std::string wait_prop_value;
-static std::string shutdown_command;
-static bool do_shutdown = false;
-
 static std::unique_ptr<Subcontext> subcontext;
 
+struct PendingControlMessage {
+    std::string message;
+    std::string name;
+    pid_t pid;
+    int fd;
+};
+static std::mutex pending_control_messages_lock;
+static std::queue<PendingControlMessage> pending_control_messages;
+
+// Init epolls various FDs to wait for various inputs.  It previously waited on property changes
+// with a blocking socket that contained the information related to the change, however, it was easy
+// to fill that socket and deadlock the system.  Now we use locks to handle the property changes
+// directly in the property thread, however we still must wake the epoll to inform init that there
+// is a change to process, so we use this FD.  It is non-blocking, since we do not care how many
+// times WakeEpoll() is called, only that the epoll will wake.
+static int wake_epoll_fd = -1;
+static void InstallInitNotifier(Epoll* epoll) {
+    int sockets[2];
+    if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, sockets) != 0) {
+        PLOG(FATAL) << "Failed to socketpair() between property_service and init";
+    }
+    int epoll_fd = sockets[0];
+    wake_epoll_fd = sockets[1];
+
+    auto drain_socket = [epoll_fd] {
+        char buf[512];
+        while (read(epoll_fd, buf, sizeof(buf)) > 0) {
+        }
+    };
+
+    if (auto result = epoll->RegisterHandler(epoll_fd, drain_socket); !result.ok()) {
+        LOG(FATAL) << result.error();
+    }
+}
+
+static void WakeEpoll() {
+    constexpr char value[] = "1";
+    write(wake_epoll_fd, value, sizeof(value));
+}
+
+static class PropWaiterState {
+  public:
+    bool StartWaiting(const char* name, const char* value) {
+        auto lock = std::lock_guard{lock_};
+        if (waiting_for_prop_) {
+            return false;
+        }
+        if (GetProperty(name, "") != value) {
+            // Current property value is not equal to expected value
+            wait_prop_name_ = name;
+            wait_prop_value_ = value;
+            waiting_for_prop_.reset(new Timer());
+        } else {
+            LOG(INFO) << "start_waiting_for_property(\"" << name << "\", \"" << value
+                      << "\"): already set";
+        }
+        return true;
+    }
+
+    void ResetWaitForProp() {
+        auto lock = std::lock_guard{lock_};
+        ResetWaitForPropLocked();
+    }
+
+    void CheckAndResetWait(const std::string& name, const std::string& value) {
+        auto lock = std::lock_guard{lock_};
+        // We always record how long init waited for ueventd to tell us cold boot finished.
+        // If we aren't waiting on this property, it means that ueventd finished before we even
+        // started to wait.
+        if (name == kColdBootDoneProp) {
+            auto time_waited = waiting_for_prop_ ? waiting_for_prop_->duration().count() : 0;
+            std::thread([time_waited] {
+                SetProperty("ro.boottime.init.cold_boot_wait", std::to_string(time_waited));
+            }).detach();
+        }
+
+        if (waiting_for_prop_) {
+            if (wait_prop_name_ == name && wait_prop_value_ == value) {
+                LOG(INFO) << "Wait for property '" << wait_prop_name_ << "=" << wait_prop_value_
+                          << "' took " << *waiting_for_prop_;
+                ResetWaitForPropLocked();
+                WakeEpoll();
+            }
+        }
+    }
+
+    // This is not thread safe because it releases the lock when it returns, so the waiting state
+    // may change.  However, we only use this function to prevent running commands in the main
+    // thread loop when we are waiting, so we do not care about false positives; only false
+    // negatives.  StartWaiting() and this function are always called from the same thread, so false
+    // negatives are not possible and therefore we're okay.
+    bool MightBeWaiting() {
+        auto lock = std::lock_guard{lock_};
+        return static_cast<bool>(waiting_for_prop_);
+    }
+
+  private:
+    void ResetWaitForPropLocked() {
+        wait_prop_name_.clear();
+        wait_prop_value_.clear();
+        waiting_for_prop_.reset();
+    }
+
+    std::mutex lock_;
+    std::unique_ptr<Timer> waiting_for_prop_{nullptr};
+    std::string wait_prop_name_;
+    std::string wait_prop_value_;
+
+} prop_waiter_state;
+
+bool start_waiting_for_property(const char* name, const char* value) {
+    return prop_waiter_state.StartWaiting(name, value);
+}
+
+void ResetWaitForProp() {
+    prop_waiter_state.ResetWaitForProp();
+}
+
+static class ShutdownState {
+  public:
+    void TriggerShutdown(const std::string& command) {
+        // We can't call HandlePowerctlMessage() directly in this function,
+        // because it modifies the contents of the action queue, which can cause the action queue
+        // to get into a bad state if this function is called from a command being executed by the
+        // action queue.  Instead we set this flag and ensure that shutdown happens before the next
+        // command is run in the main init loop.
+        auto lock = std::lock_guard{shutdown_command_lock_};
+        shutdown_command_ = command;
+        do_shutdown_ = true;
+        WakeEpoll();
+    }
+
+    std::optional<std::string> CheckShutdown() {
+        auto lock = std::lock_guard{shutdown_command_lock_};
+        if (do_shutdown_ && !IsShuttingDown()) {
+            do_shutdown_ = false;
+            return shutdown_command_;
+        }
+        return {};
+    }
+
+  private:
+    std::mutex shutdown_command_lock_;
+    std::string shutdown_command_;
+    bool do_shutdown_ = false;
+} shutdown_state;
+
 void DumpState() {
     ServiceList::GetInstance().DumpState();
     ActionManager::GetInstance().DumpState();
@@ -156,39 +299,7 @@
     }
 }
 
-bool start_waiting_for_property(const char* name, const char* value) {
-    if (waiting_for_prop) {
-        return false;
-    }
-    if (GetProperty(name, "") != value) {
-        // Current property value is not equal to expected value
-        wait_prop_name = name;
-        wait_prop_value = value;
-        waiting_for_prop.reset(new Timer());
-    } else {
-        LOG(INFO) << "start_waiting_for_property(\"" << name << "\", \"" << value
-                  << "\"): already set";
-    }
-    return true;
-}
-
-void ResetWaitForProp() {
-    wait_prop_name.clear();
-    wait_prop_value.clear();
-    waiting_for_prop.reset();
-}
-
-static void TriggerShutdown(const std::string& command) {
-    // We can't call HandlePowerctlMessage() directly in this function,
-    // because it modifies the contents of the action queue, which can cause the action queue
-    // to get into a bad state if this function is called from a command being executed by the
-    // action queue.  Instead we set this flag and ensure that shutdown happens before the next
-    // command is run in the main init loop.
-    shutdown_command = command;
-    do_shutdown = true;
-}
-
-void property_changed(const std::string& name, const std::string& value) {
+void PropertyChanged(const std::string& name, const std::string& value) {
     // If the property is sys.powerctl, we bypass the event queue and immediately handle it.
     // This is to ensure that init will always and immediately shutdown/reboot, regardless of
     // if there are other pending events to process or if init is waiting on an exec service or
@@ -196,26 +307,15 @@
     // In non-thermal-shutdown case, 'shutdown' trigger will be fired to let device specific
     // commands to be executed.
     if (name == "sys.powerctl") {
-        TriggerShutdown(value);
+        trigger_shutdown(value);
     }
 
-    if (property_triggers_enabled) ActionManager::GetInstance().QueuePropertyChange(name, value);
-
-    // We always record how long init waited for ueventd to tell us cold boot finished.
-    // If we aren't waiting on this property, it means that ueventd finished before we even started
-    // to wait.
-    if (name == kColdBootDoneProp) {
-        auto time_waited = waiting_for_prop ? waiting_for_prop->duration().count() : 0;
-        SetProperty("ro.boottime.init.cold_boot_wait", std::to_string(time_waited));
+    if (property_triggers_enabled) {
+        ActionManager::GetInstance().QueuePropertyChange(name, value);
+        WakeEpoll();
     }
 
-    if (waiting_for_prop) {
-        if (wait_prop_name == name && wait_prop_value == value) {
-            LOG(INFO) << "Wait for property '" << wait_prop_name << "=" << wait_prop_value
-                      << "' took " << *waiting_for_prop;
-            ResetWaitForProp();
-        }
-    }
+    prop_waiter_state.CheckAndResetWait(name, value);
 }
 
 static std::optional<boot_clock::time_point> HandleProcessActions() {
@@ -343,8 +443,46 @@
     return true;
 }
 
+bool QueueControlMessage(const std::string& message, const std::string& name, pid_t pid, int fd) {
+    auto lock = std::lock_guard{pending_control_messages_lock};
+    if (pending_control_messages.size() > 100) {
+        LOG(ERROR) << "Too many pending control messages, dropped '" << message << "' for '" << name
+                   << "' from pid: " << pid;
+        return false;
+    }
+    pending_control_messages.push({message, name, pid, fd});
+    WakeEpoll();
+    return true;
+}
+
+static void HandleControlMessages() {
+    auto lock = std::unique_lock{pending_control_messages_lock};
+    // Init historically would only execute handle one property message, including control messages
+    // in each iteration of its main loop.  We retain this behavior here to prevent starvation of
+    // other actions in the main loop.
+    if (!pending_control_messages.empty()) {
+        auto control_message = pending_control_messages.front();
+        pending_control_messages.pop();
+        lock.unlock();
+
+        bool success = HandleControlMessage(control_message.message, control_message.name,
+                                            control_message.pid);
+
+        uint32_t response = success ? PROP_SUCCESS : PROP_ERROR_HANDLE_CONTROL_MESSAGE;
+        if (control_message.fd != -1) {
+            TEMP_FAILURE_RETRY(send(control_message.fd, &response, sizeof(response), 0));
+            close(control_message.fd);
+        }
+        lock.lock();
+    }
+    // If we still have items to process, make sure we wake back up to do so.
+    if (!pending_control_messages.empty()) {
+        WakeEpoll();
+    }
+}
+
 static Result<void> wait_for_coldboot_done_action(const BuiltinArguments& args) {
-    if (!start_waiting_for_property(kColdBootDoneProp, "true")) {
+    if (!prop_waiter_state.StartWaiting(kColdBootDoneProp, "true")) {
         LOG(FATAL) << "Could not wait for '" << kColdBootDoneProp << "'";
     }
 
@@ -562,60 +700,6 @@
     }
 }
 
-void SendStopSendingMessagesMessage() {
-    auto init_message = InitMessage{};
-    init_message.set_stop_sending_messages(true);
-    if (auto result = SendMessage(property_fd, init_message); !result.ok()) {
-        LOG(ERROR) << "Failed to send 'stop sending messages' message: " << result.error();
-    }
-}
-
-void SendStartSendingMessagesMessage() {
-    auto init_message = InitMessage{};
-    init_message.set_start_sending_messages(true);
-    if (auto result = SendMessage(property_fd, init_message); !result.ok()) {
-        LOG(ERROR) << "Failed to send 'start sending messages' message: " << result.error();
-    }
-}
-
-static void HandlePropertyFd() {
-    auto message = ReadMessage(property_fd);
-    if (!message.ok()) {
-        LOG(ERROR) << "Could not read message from property service: " << message.error();
-        return;
-    }
-
-    auto property_message = PropertyMessage{};
-    if (!property_message.ParseFromString(*message)) {
-        LOG(ERROR) << "Could not parse message from property service";
-        return;
-    }
-
-    switch (property_message.msg_case()) {
-        case PropertyMessage::kControlMessage: {
-            auto& control_message = property_message.control_message();
-            bool success = HandleControlMessage(control_message.msg(), control_message.name(),
-                                                control_message.pid());
-
-            uint32_t response = success ? PROP_SUCCESS : PROP_ERROR_HANDLE_CONTROL_MESSAGE;
-            if (control_message.has_fd()) {
-                int fd = control_message.fd();
-                TEMP_FAILURE_RETRY(send(fd, &response, sizeof(response), 0));
-                close(fd);
-            }
-            break;
-        }
-        case PropertyMessage::kChangedMessage: {
-            auto& changed_message = property_message.changed_message();
-            property_changed(changed_message.name(), changed_message.value());
-            break;
-        }
-        default:
-            LOG(ERROR) << "Unknown message type from property service: "
-                       << property_message.msg_case();
-    }
-}
-
 int SecondStageMain(int argc, char** argv) {
     if (REBOOT_BOOTLOADER_ON_PANIC) {
         InstallRebootSignalHandlers();
@@ -623,7 +707,7 @@
 
     boot_clock::time_point start_time = boot_clock::now();
 
-    trigger_shutdown = TriggerShutdown;
+    trigger_shutdown = [](const std::string& command) { shutdown_state.TriggerShutdown(command); };
 
     SetStdioToDevNull(argv);
     InitKernelLogging(argv);
@@ -683,11 +767,8 @@
     }
 
     InstallSignalFdHandler(&epoll);
-
+    InstallInitNotifier(&epoll);
     StartPropertyService(&property_fd);
-    if (auto result = epoll.RegisterHandler(property_fd, HandlePropertyFd); !result.ok()) {
-        LOG(FATAL) << "Could not register epoll handler for property fd: " << result.error();
-    }
 
     // Make the time that init stages started available for bootstat to log.
     RecordStageBoottimes(start_time);
@@ -770,12 +851,12 @@
         // By default, sleep until something happens.
         auto epoll_timeout = std::optional<std::chrono::milliseconds>{};
 
-        if (do_shutdown && !IsShuttingDown()) {
-            do_shutdown = false;
-            HandlePowerctlMessage(shutdown_command);
+        auto shutdown_command = shutdown_state.CheckShutdown();
+        if (shutdown_command) {
+            HandlePowerctlMessage(*shutdown_command);
         }
 
-        if (!(waiting_for_prop || Service::is_exec_service_running())) {
+        if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) {
             am.ExecuteOneCommand();
         }
         if (!IsShuttingDown()) {
@@ -789,7 +870,7 @@
             }
         }
 
-        if (!(waiting_for_prop || Service::is_exec_service_running())) {
+        if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) {
             // If there's more work to do, wake up again immediately.
             if (am.HasMoreCommands()) epoll_timeout = 0ms;
         }
@@ -806,6 +887,7 @@
                 (*function)();
             }
         }
+        HandleControlMessages();
     }
 
     return 0;
diff --git a/init/init.h b/init/init.h
index 4bbca6f..27f64e2 100644
--- a/init/init.h
+++ b/init/init.h
@@ -38,8 +38,9 @@
 void ResetWaitForProp();
 
 void SendLoadPersistentPropertiesMessage();
-void SendStopSendingMessagesMessage();
-void SendStartSendingMessagesMessage();
+
+void PropertyChanged(const std::string& name, const std::string& value);
+bool QueueControlMessage(const std::string& message, const std::string& name, pid_t pid, int fd);
 
 int SecondStageMain(int argc, char** argv);
 
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 730bf6d..8206522 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -92,8 +92,11 @@
 static bool persistent_properties_loaded = false;
 
 static int property_set_fd = -1;
+static int from_init_socket = -1;
 static int init_socket = -1;
 static bool accept_messages = false;
+static std::mutex accept_messages_lock;
+static std::thread property_service_thread;
 
 static PropertyInfoAreaFile property_info_area;
 
@@ -115,6 +118,16 @@
     return 0;
 }
 
+void StartSendingMessages() {
+    auto lock = std::lock_guard{accept_messages_lock};
+    accept_messages = true;
+}
+
+void StopSendingMessages() {
+    auto lock = std::lock_guard{accept_messages_lock};
+    accept_messages = true;
+}
+
 bool CanReadProperty(const std::string& source_context, const std::string& name) {
     const char* target_context = nullptr;
     property_info_area->GetPropertyInfo(name.c_str(), &target_context, nullptr);
@@ -147,17 +160,6 @@
     return has_access;
 }
 
-static void SendPropertyChanged(const std::string& name, const std::string& value) {
-    auto property_msg = PropertyMessage{};
-    auto* changed_message = property_msg.mutable_changed_message();
-    changed_message->set_name(name);
-    changed_message->set_value(value);
-
-    if (auto result = SendMessage(init_socket, property_msg); !result.ok()) {
-        LOG(ERROR) << "Failed to send property changed message: " << result.error();
-    }
-}
-
 static uint32_t PropertySet(const std::string& name, const std::string& value, std::string* error) {
     size_t valuelen = value.size();
 
@@ -195,8 +197,9 @@
     }
     // If init hasn't started its main loop, then it won't be handling property changed messages
     // anyway, so there's no need to try to send them.
+    auto lock = std::lock_guard{accept_messages_lock};
     if (accept_messages) {
-        SendPropertyChanged(name, value);
+        PropertyChanged(name, value);
     }
     return PROP_SUCCESS;
 }
@@ -373,33 +376,24 @@
 
 static uint32_t SendControlMessage(const std::string& msg, const std::string& name, pid_t pid,
                                    SocketConnection* socket, std::string* error) {
+    auto lock = std::lock_guard{accept_messages_lock};
     if (!accept_messages) {
         *error = "Received control message after shutdown, ignoring";
         return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
     }
 
-    auto property_msg = PropertyMessage{};
-    auto* control_message = property_msg.mutable_control_message();
-    control_message->set_msg(msg);
-    control_message->set_name(name);
-    control_message->set_pid(pid);
-
     // We must release the fd before sending it to init, otherwise there will be a race with init.
     // If init calls close() before Release(), then fdsan will see the wrong tag and abort().
     int fd = -1;
     if (socket != nullptr && SelinuxGetVendorAndroidVersion() > __ANDROID_API_Q__) {
         fd = socket->Release();
-        control_message->set_fd(fd);
     }
 
-    if (auto result = SendMessage(init_socket, property_msg); !result.ok()) {
-        // We've already released the fd above, so if we fail to send the message to init, we need
-        // to manually free it here.
-        if (fd != -1) {
-            close(fd);
-        }
-        *error = "Failed to send control message: " + result.error().message();
-        return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
+    bool queue_success = QueueControlMessage(msg, name, pid, fd);
+    if (!queue_success && fd != -1) {
+        uint32_t response = PROP_ERROR_HANDLE_CONTROL_MESSAGE;
+        TEMP_FAILURE_RETRY(send(fd, &response, sizeof(response), 0));
+        close(fd);
     }
 
     return PROP_SUCCESS;
@@ -1110,14 +1104,6 @@
             persistent_properties_loaded = true;
             break;
         }
-        case InitMessage::kStopSendingMessages: {
-            accept_messages = false;
-            break;
-        }
-        case InitMessage::kStartSendingMessages: {
-            accept_messages = true;
-            break;
-        }
         default:
             LOG(ERROR) << "Unknown message type from init: " << init_message.msg_case();
     }
@@ -1157,9 +1143,9 @@
     if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sockets) != 0) {
         PLOG(FATAL) << "Failed to socketpair() between property_service and init";
     }
-    *epoll_socket = sockets[0];
+    *epoll_socket = from_init_socket = sockets[0];
     init_socket = sockets[1];
-    accept_messages = true;
+    StartSendingMessages();
 
     if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
                                    false, 0666, 0, 0, {});
@@ -1171,7 +1157,8 @@
 
     listen(property_set_fd, 8);
 
-    std::thread{PropertyServiceThread}.detach();
+    auto new_thread = std::thread{PropertyServiceThread};
+    property_service_thread.swap(new_thread);
 }
 
 }  // namespace init
diff --git a/init/property_service.h b/init/property_service.h
index 506d116..2d49a36 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -32,5 +32,8 @@
 void PropertyInit();
 void StartPropertyService(int* epoll_socket);
 
+void StartSendingMessages();
+void StopSendingMessages();
+
 }  // namespace init
 }  // namespace android
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 8d8bd8e..f006df3 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -59,6 +59,7 @@
 #include "builtin_arguments.h"
 #include "init.h"
 #include "mount_namespace.h"
+#include "property_service.h"
 #include "reboot_utils.h"
 #include "service.h"
 #include "service_list.h"
@@ -711,17 +712,12 @@
     for (const auto& s : ServiceList::GetInstance()) {
         s->UnSetExec();
     }
-    // We no longer process messages about properties changing coming from property service, so we
-    // need to tell property service to stop sending us these messages, otherwise it'll fill the
-    // buffers and block indefinitely, causing future property sets, including those that init makes
-    // during shutdown in Service::NotifyStateChange() to also block indefinitely.
-    SendStopSendingMessagesMessage();
 }
 
 static void LeaveShutdown() {
     LOG(INFO) << "Leaving shutdown mode";
     shutting_down = false;
-    SendStartSendingMessagesMessage();
+    StartSendingMessages();
 }
 
 static Result<void> UnmountAllApexes() {
@@ -981,6 +977,10 @@
         return;
     }
 
+    // We do not want to process any messages (queue'ing triggers, shutdown messages, control
+    // messages, etc) from properties during reboot.
+    StopSendingMessages();
+
     if (userspace_reboot) {
         HandleUserspaceReboot();
         return;
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index 57531c8..76caadc 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -97,6 +97,9 @@
         },
         android: {
             static_libs: ["libasync_safe"],
+            static: {
+                whole_static_libs: ["libasync_safe"],
+            },
         },
         vendor: {
             cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index c4e4f85..5805a4d 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -201,6 +201,8 @@
                                            CAP_MASK_LONG(CAP_SETGID),
                                               "system/bin/simpleperf_app_runner" },
     { 00755, AID_ROOT,      AID_ROOT,      0, "first_stage_ramdisk/system/bin/e2fsck" },
+    { 00755, AID_ROOT,      AID_ROOT,      0, "first_stage_ramdisk/system/bin/tune2fs" },
+    { 00755, AID_ROOT,      AID_ROOT,      0, "first_stage_ramdisk/system/bin/resize2fs" },
     // generic defaults
     { 00755, AID_ROOT,      AID_ROOT,      0, "bin/*" },
     { 00640, AID_ROOT,      AID_SHELL,     0, "fstab.*" },
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 50faa2a..0b98e1a 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -121,8 +121,12 @@
     logtags: ["event.logtags"],
     compile_multilib: "both",
     apex_available: [
-        "//apex_available:anyapex",
         "//apex_available:platform",
+        // liblog is exceptionally available to the runtime APEX
+        // because the dynamic linker has to use it statically.
+        // See b/151051671
+        "com.android.runtime",
+        // DO NOT add more apex names here
     ],
 }
 
diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h
index 15c7963..43a91ab 100644
--- a/liblog/include/android/log.h
+++ b/liblog/include/android/log.h
@@ -56,6 +56,7 @@
 
 #include <stdarg.h>
 #include <stddef.h>
+#include <stdint.h>
 #include <sys/cdefs.h>
 
 #if !defined(__BIONIC__) && !defined(__INTRODUCED_IN)
@@ -154,14 +155,11 @@
   /** The kernel log buffer. */
   LOG_ID_KERNEL = 7,
 
-  LOG_ID_MAX
-} log_id_t;
+  LOG_ID_MAX,
 
-/**
- * Let the logging function choose the best log target.
- * This is not part of the enum since adding either -1 or 0xFFFFFFFF forces the enum to be signed or
- * unsigned, which breaks unfortunately common arithmetic against LOG_ID_MIN and LOG_ID_MAX. */
-#define LOG_ID_DEFAULT (-1)
+  /** Let the logging function choose the best log target. */
+  LOG_ID_DEFAULT = 0x7FFFFFFF
+} log_id_t;
 
 /**
  * Writes the constant string `text` to the log buffer `id`,
@@ -188,11 +186,11 @@
  */
 struct __android_logger_data {
   size_t struct_size; /* Must be set to sizeof(__android_logger_data) and is used for versioning. */
-  int buffer_id;      /* log_id_t or -1 to represent 'default'. */
-  int priority;       /* android_LogPriority values. */
+  int32_t buffer_id;  /* log_id_t or -1 to represent 'default'. */
+  int32_t priority;   /* android_LogPriority values. */
   const char* tag;
   const char* file;  /* Optional file name, may be set to nullptr. */
-  unsigned int line; /* Optional line number, ignore if file is nullptr. */
+  uint32_t line;     /* Optional line number, ignore if file is nullptr. */
 };
 
 /**
@@ -206,7 +204,7 @@
  */
 typedef void (*__android_aborter_function)(const char* abort_message);
 
-#if __ANDROID_API__ >= 30 || !defined(__ANDROID__)
+#if !defined(__ANDROID__) || __ANDROID_API__ >= 30
 /**
  * Writes the log message specified with logger_data and msg to the log.  logger_data includes
  * additional file name and line number information that a logger may use.  logger_data is versioned
@@ -276,13 +274,13 @@
  *
  * This returns the previous set minimum priority, or ANDROID_LOG_DEFAULT if none was set.
  */
-int __android_log_set_minimum_priority(int priority) __INTRODUCED_IN(30);
+int32_t __android_log_set_minimum_priority(int32_t priority) __INTRODUCED_IN(30);
 
 /**
  * Gets the minimum priority that will be logged for this process.  If none has been set by a
  * previous __android_log_set_minimum_priority() call, this returns ANDROID_LOG_DEFAULT.
  */
-int __android_log_get_minimum_priority(void) __INTRODUCED_IN(30);
+int32_t __android_log_get_minimum_priority(void) __INTRODUCED_IN(30);
 
 /**
  * Sets the default tag if no tag is provided when writing a log message.  Defaults to
diff --git a/liblog/logger_name.cpp b/liblog/logger_name.cpp
index 7d676f4..e72290e 100644
--- a/liblog/logger_name.cpp
+++ b/liblog/logger_name.cpp
@@ -41,7 +41,10 @@
 }
 
 static_assert(std::is_same<std::underlying_type<log_id_t>::type, uint32_t>::value,
-              "log_id_t must be an unsigned int");
+              "log_id_t must be an uint32_t");
+
+static_assert(std::is_same<std::underlying_type<android_LogPriority>::type, uint32_t>::value,
+              "log_id_t must be an uint32_t");
 
 log_id_t android_name_to_log_id(const char* logName) {
   const char* b;
diff --git a/liblog/logger_write.cpp b/liblog/logger_write.cpp
index 0dbb94f..a8620a0 100644
--- a/liblog/logger_write.cpp
+++ b/liblog/logger_write.cpp
@@ -149,12 +149,12 @@
   GetDefaultTag().assign(tag, 0, LOGGER_ENTRY_MAX_PAYLOAD);
 }
 
-static std::atomic_int minimum_log_priority = ANDROID_LOG_DEFAULT;
-int __android_log_set_minimum_priority(int priority) {
+static std::atomic_int32_t minimum_log_priority = ANDROID_LOG_DEFAULT;
+int32_t __android_log_set_minimum_priority(int32_t priority) {
   return minimum_log_priority.exchange(priority, std::memory_order_relaxed);
 }
 
-int __android_log_get_minimum_priority() {
+int32_t __android_log_get_minimum_priority() {
   return minimum_log_priority;
 }
 
@@ -267,7 +267,7 @@
   static const char log_characters[] = "XXVDIWEF";
   static_assert(arraysize(log_characters) - 1 == ANDROID_LOG_SILENT,
                 "Mismatch in size of log_characters and values in android_LogPriority");
-  int priority =
+  int32_t priority =
       logger_data->priority > ANDROID_LOG_SILENT ? ANDROID_LOG_FATAL : logger_data->priority;
   char priority_char = log_characters[priority];
   uint64_t tid = GetThreadId();
diff --git a/libpixelflinger/Android.bp b/libpixelflinger/Android.bp
index 76d9444..45a32da 100644
--- a/libpixelflinger/Android.bp
+++ b/libpixelflinger/Android.bp
@@ -93,23 +93,5 @@
                 "arch-arm64/t32cb16blend.S",
             ],
         },
-        mips: {
-            mips32r6: {
-                srcs: [
-                    "codeflinger/MIPSAssembler.cpp",
-                    "codeflinger/mips_disassem.c",
-                    "arch-mips/t32cb16blend.S",
-                ],
-            },
-        },
-        mips64: {
-            srcs: [
-                "codeflinger/MIPSAssembler.cpp",
-                "codeflinger/MIPS64Assembler.cpp",
-                "codeflinger/mips64_disassem.c",
-                "arch-mips64/col32cb16blend.S",
-                "arch-mips64/t32cb16blend.S",
-            ],
-        },
     },
 }
diff --git a/libpixelflinger/arch-mips/col32cb16blend.S b/libpixelflinger/arch-mips/col32cb16blend.S
deleted file mode 100644
index 810294c..0000000
--- a/libpixelflinger/arch-mips/col32cb16blend.S
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
-** Copyright 2015, 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.
-*/
-
-       .macro pixel dreg src f sR sG sB shift
-
-#if __mips==32 && __mips_isa_rev>=2
-       /* extract red */
-       ext $t4,\src,\shift+11,5
-       mul $t4,$t4,\f
-
-       /* extract green */
-       ext $t5,\src,\shift+5,6
-       mul $t5,$t5,\f
-
-       /* extract blue */
-       ext $t6,\src,\shift,5
-       mul $t6,$t6,\f
-#else
-       /* extract red */
-       srl $t4,\src,\shift+11
-       andi $t4, 0x1f
-       mul $t4,$t4,\f
-
-       /* extract green */
-       srl $t5,\src,\shift+5
-       andi $t5, 0x3f
-       mul $t5,$t5,\f
-
-       /* extract blue */
-       srl $t6,\src,\shift
-       andi $t6, 0x1f
-       mul $t6,$t6,\f
-#endif
-
-       srl $t4,$t4,8
-       srl $t5,$t5,8
-       srl $t6,$t6,8
-       addu $t4,$t4,\sR
-       addu $t5,$t5,\sG
-       addu \dreg,$t6,\sB
-       sll $t4,$t4,11
-       sll $t5,$t5,5
-       or \dreg,\dreg,$t4
-       or \dreg,\dreg,$t5
-       andi \dreg, 0xffff
-       .endm
-
-       .text
-       .balign 4
-
-       .global scanline_col32cb16blend_mips
-       .ent    scanline_col32cb16blend_mips
-scanline_col32cb16blend_mips:
-
-       /* check if count is zero */
-       srl     $v0,$a1,24 /* sA */
-       beqz    $a2,done
-       li      $t4, 0x100
-       srl     $v1,$v0,7
-       addu    $v0,$v1,$v0
-       subu    $v0,$t4,$v0 /* f */
-#if __mips==32 && __mips_isa_rev>=2
-       ext     $a3,$a1,3,5 /* sR */
-       ext     $t0,$a1,10,6 /* sG */
-       ext     $t1,$a1,19,5 /* sB */
-#else
-       srl     $a3, $a1, 3
-       andi    $a3, 0x1f    /* sR */
-       srl     $t0, $a1, 10
-       andi    $t0, 0x3f    /* sG */
-       srl     $t1, $a1, 19
-       andi    $t1, 0x1f    /* sB */
-#endif
-
-       /* check if cnt is at least 4 */
-       addiu   $a2,$a2,-4
-       bltz    $a2,tail
-
-loop_4pixels:
-       lw      $t7,0($a0)
-       lw      $t8,4($a0)
-       addiu   $a0,$a0,8
-       addiu   $a2,$a2,-4
-       pixel   $t2 $t7 $v0 $a3 $t0 $t1 0
-       pixel   $t3 $t7 $v0 $a3 $t0 $t1 16
-#if __mips==32 && __mips_isa_rev>=2
-       ins     $t2,$t3,16,16
-#else
-       sll $t3, 16
-       or  $t2, $t2, $t3
-#endif
-       pixel   $t7 $t8 $v0 $a3 $t0 $t1 0
-       pixel   $t3 $t8 $v0 $a3 $t0 $t1 16
-#if __mips==32 && __mips_isa_rev>=2
-       ins     $t7,$t3,16,16
-#else
-       sll $t3, 16
-       or  $t7, $t7, $t3
-#endif
-       sw      $t2,-8($a0)
-       sw      $t7,-4($a0)
-       bgez    $a2, loop_4pixels
-
-tail:
-       /* the pixel count underran, restore it now */
-       addiu   $a2,$a2,4
-
-       /* handle the last 0..3 pixels */
-       beqz    $a2,done
-
-loop_1pixel:
-       lhu     $t7,0($a0)
-       addiu   $a0,$a0,2
-       addiu   $a2,$a2,-1
-       pixel   $t2 $t7 $v0 $a3 $t0 $t1 0
-       sh      $t2, -2($a0)
-       bnez    $a2,loop_1pixel
-
-done:
-       j       $ra
-       .end    scanline_col32cb16blend_mips
diff --git a/libpixelflinger/arch-mips/t32cb16blend.S b/libpixelflinger/arch-mips/t32cb16blend.S
deleted file mode 100644
index 1d2fb8f..0000000
--- a/libpixelflinger/arch-mips/t32cb16blend.S
+++ /dev/null
@@ -1,273 +0,0 @@
-/* libs/pixelflinger/t32cb16blend.S
-**
-** Copyright 2010, 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.
-*/
-
-#ifdef DEBUG
-#define DBG
-#else
-#define DBG #
-#endif
-
-/*
- * blend one of 2 16bpp RGB pixels held in dreg selected by shift
- * with the 32bpp ABGR pixel held in src and store the result in fb
- *
- * Assumes that the dreg data is little endian and that
- * the the second pixel (shift==16) will be merged into
- * the fb result
- *
- * Uses $t0,$t6,$t7,$t8
- */
-
-#if __mips==32 && __mips_isa_rev>=2
-    .macro pixel dreg src fb shift
-    /*
-     * sA = s >> 24
-     * f = 0x100 - (sA + (sA>>7))
-     */
-DBG .set    noat
-DBG rdhwr   $at,$2
-DBG .set    at
-
-    srl  $t7,\src,24
-    srl  $t6,$t7,7
-    addu $t7,$t6
-    li   $t6,0x100
-    subu $t7,$t6,$t7
-
-    /* red */
-    ext  $t8,\dreg,\shift+6+5,5         # dst[\shift:15..11]
-    mul  $t6,$t8,$t7
-    ext  $t0,\dreg,\shift+5,6           # start green extraction dst[\shift:10..5]
-    ext  $t8,\src,3,5               # src[7..3]
-    srl  $t6,8
-    addu $t8,$t6
-.if \shift!=0
-    sll  $t8,\shift+11
-    or   \fb,$t8
-.else
-    sll  \fb,$t8,11
-.endif
-
-    /* green */
-    mul  $t8,$t0,$t7
-    ext  $t0,\dreg,\shift,5         # start blue extraction dst[\shift:4..0]
-    ext  $t6,\src,2+8,6             # src[15..10]
-    srl  $t8,8
-    addu $t8,$t6
-
-    /* blue */
-    mul  $t0,$t0,$t7
-    sll  $t8, $t8, \shift+5
-    or   \fb, \fb, $t8
-    ext  $t6,\src,(3+8+8),5
-    srl  $t8,$t0,8
-    addu $t8,$t6
-    sll  $t8, $t8, \shift
-    or   \fb, \fb, $t8
-
-DBG .set    noat
-DBG rdhwr $t8,$2
-DBG subu  $t8,$at
-DBG sltu  $at,$t8,$v0
-DBG movn  $v0,$t8,$at
-DBG sgtu  $at,$t8,$v1
-DBG movn  $v1,$t8,$at
-DBG .set    at
-    .endm
-
-#else
-
-    .macro pixel dreg src fb shift
-    /*
-     * sA = s >> 24
-     * f = 0x100 - (sA + (sA>>7))
-     */
-DBG .set    push
-DBG .set    noat
-DBG .set    mips32r2
-DBG rdhwr   $at,$2
-DBG .set    pop
-
-    srl  $t7,\src,24
-    srl  $t6,$t7,7
-    addu $t7,$t6
-    li   $t6,0x100
-    subu $t7,$t6,$t7
-
-    /*
-     * red
-     * dR = (d >> (6 + 5)) & 0x1f;
-     * dR = (f*dR)>>8
-     * sR = (s >> (   3)) & 0x1f;
-     * sR += dR
-     * fb |= sR << 11
-     */
-    srl  $t8,\dreg,\shift+6+5
-.if \shift==0
-    and  $t8,0x1f
-.endif
-    mul  $t8,$t8,$t7
-    srl  $t6,\src,3
-    and  $t6,0x1f
-    srl  $t8,8
-    addu $t8,$t6
-.if \shift!=0
-    sll  $t8,\shift+11
-    or   \fb,$t8
-.else
-    sll  \fb,$t8,11
-.endif
-
-        /*
-     * green
-     * dG = (d >> 5) & 0x3f
-     * dG = (f*dG) >> 8
-     * sG = (s >> ( 8+2))&0x3F;
-     */
-    srl  $t8,\dreg,\shift+5
-    and  $t8,0x3f
-    mul  $t8,$t8,$t7
-    srl  $t6,\src,8+2
-    and  $t6,0x3f
-    srl  $t8,8
-    addu $t8,$t6
-    sll  $t8,\shift + 5
-    or   \fb,$t8
-
-    /* blue */
-.if \shift!=0
-    srl  $t8,\dreg,\shift
-    and  $t8,0x1f
-.else
-    and  $t8,\dreg,0x1f
-.endif
-    mul  $t8,$t8,$t7
-    srl  $t6,\src,(8+8+3)
-    and  $t6,0x1f
-    srl  $t8,8
-    addu $t8,$t6
-.if \shift!=0
-    sll  $t8,\shift
-.endif
-    or   \fb,$t8
-DBG .set    push
-DBG .set    noat
-DBG .set    mips32r2
-DBG rdhwr   $t8,$2
-DBG subu    $t8,$at
-DBG sltu    $at,$t8,$v0
-DBG movn    $v0,$t8,$at
-DBG sgtu    $at,$t8,$v1
-DBG movn    $v1,$t8,$at
-DBG .set    pop
-    .endm
-#endif
-
-    .text
-    .balign 4
-
-    .global scanline_t32cb16blend_mips
-    .ent    scanline_t32cb16blend_mips
-scanline_t32cb16blend_mips:
-DBG li    $v0,0xffffffff
-DBG li    $v1,0
-    /* Align the destination if necessary */
-    and   $t0,$a0,3
-    beqz  $t0,aligned
-
-    /* as long as there is at least one pixel */
-    beqz  $a2,done
-
-    lw    $t4,($a1)
-    addu  $a0,2
-    addu  $a1,4
-    beqz  $t4,1f
-    lhu   $t3,-2($a0)
-    pixel $t3,$t4,$t1,0
-    sh    $t1,-2($a0)
-1:  subu  $a2,1
-
-aligned:
-    /* Check to see if its worth unrolling the loop */
-    subu  $a2,4
-    bltz  $a2,tail
-
-    /* Process 4 pixels at a time */
-fourpixels:
-    /* 1st pair of pixels */
-    lw    $t4,0($a1)
-    lw    $t5,4($a1)
-    addu  $a0,8
-    addu  $a1,16
-
-    /* both are zero, skip this pair */
-    or    $t3,$t4,$t5
-    beqz  $t3,1f
-
-    /* load the destination */
-    lw    $t3,-8($a0)
-
-    pixel $t3,$t4,$t1,0
-    andi  $t1, 0xFFFF
-    pixel $t3,$t5,$t1,16
-    sw    $t1,-8($a0)
-
-1:
-    /* 2nd pair of pixels */
-    lw    $t4,-8($a1)
-    lw    $t5,-4($a1)
-
-    /* both are zero, skip this pair */
-    or    $t3,$t4,$t5
-    beqz  $t3,1f
-
-    /* load the destination */
-    lw    $t3,-4($a0)
-
-    pixel $t3,$t4,$t1,0
-    andi  $t1, 0xFFFF
-    pixel $t3,$t5,$t1,16
-    sw    $t1,-4($a0)
-
-1:  subu  $a2,4
-    bgtz  $a2,fourpixels
-
-tail:
-    /* the pixel count underran, restore it now */
-    addu  $a2,4
-
-    /* handle the last 0..3 pixels */
-    beqz  $a2,done
-onepixel:
-    lw    $t4,($a1)
-    addu  $a0,2
-    addu  $a1,4
-    beqz  $t4,1f
-    lhu   $t3,-2($a0)
-    pixel $t3,$t4,$t1,0
-    sh    $t1,-2($a0)
-1:  subu  $a2,1
-    bnez  $a2,onepixel
-done:
-DBG .set    push
-DBG .set    mips32r2
-DBG rdhwr   $a0,$3
-DBG mul     $v0,$a0
-DBG mul     $v1,$a0
-DBG .set    pop
-    j     $ra
-    .end    scanline_t32cb16blend_mips
diff --git a/libpixelflinger/arch-mips64/col32cb16blend.S b/libpixelflinger/arch-mips64/col32cb16blend.S
deleted file mode 100644
index 5baffb1..0000000
--- a/libpixelflinger/arch-mips64/col32cb16blend.S
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
-** Copyright 2015, 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.
-*/
-
-    .macro pixel dreg src f sR sG sB shift
-
-    /* extract red */
-.if \shift < 32
-    dext   $t0,\src,\shift+11,5
-.else
-    dextu  $t0,\src,\shift+11,5
-.endif
-    mul    $t0,$t0,\f
-
-    /* extract green */
-.if \shift < 32
-    dext   $t1,\src,\shift+5,6
-.else
-    dextu  $t1,\src,\shift+5,6
-.endif
-    mul    $t1,$t1,\f
-
-    /* extract blue */
-.if \shift < 32
-    dext   $t2,\src,\shift,5
-.else
-    dextu  $t2,\src,\shift,5
-.endif
-    mul    $t2,$t2,\f
-
-    srl    $t0,$t0,8
-    srl    $t1,$t1,8
-    srl    $t2,$t2,8
-    addu   $t0,$t0,\sR
-    addu   $t1,$t1,\sG
-    addu   \dreg,$t2,\sB
-    sll    $t0,$t0,11
-    sll    $t1,$t1,5
-    or     \dreg,\dreg,$t0
-    or     \dreg,\dreg,$t1
-    .endm
-
-    .text
-    .balign 4
-
-    .global scanline_col32cb16blend_mips64
-    .ent    scanline_col32cb16blend_mips64
-scanline_col32cb16blend_mips64:
-
-    /* check if count is zero */
-    srl     $v0,$a1,24 /* sA */
-    beqz    $a2,done
-    li      $t0, 0x100
-    srl     $v1,$v0,7
-    addu    $v0,$v1,$v0
-    subu    $v0,$t0,$v0 /* f */
-    ext     $a3,$a1,3,5 /* sR */
-    ext     $a4,$a1,10,6 /* sG */
-    ext     $a5,$a1,19,5 /* sB */
-
-    /* check if cnt is at least 4 */
-    addiu   $a2,$a2,-4
-    bltz    $a2,tail
-
-loop_4pixels:
-    ld      $t3,0($a0)
-    daddiu  $a0,$a0,8
-    addiu   $a2,$a2,-4
-    pixel   $a6 $t3 $v0 $a3 $a4 $a5 0
-    pixel   $a7 $t3 $v0 $a3 $a4 $a5 16
-    pixel   $t8 $t3 $v0 $a3 $a4 $a5 32
-    pixel   $t9 $t3 $v0 $a3 $a4 $a5 48
-    dins    $a6,$a7,16,16
-    dinsu   $a6,$t8,32,16
-    dinsu   $a6,$t9,48,16
-    sd      $a6,-8($a0)
-    bgez    $a2, loop_4pixels
-
-tail:
-    /* the pixel count underran, restore it now */
-    addiu   $a2,$a2,4
-
-    /* handle the last 0..3 pixels */
-    beqz    $a2,done
-
-loop_1pixel:
-    lhu     $t3,0($a0)
-    daddiu  $a0,$a0,2
-    addiu   $a2,$a2,-1
-    pixel   $a6 $t3 $v0 $a3 $a4 $a5 0
-    sh      $a6, -2($a0)
-    bnez    $a2,loop_1pixel
-
-done:
-    j       $ra
-    .end    scanline_col32cb16blend_mips64
diff --git a/libpixelflinger/arch-mips64/t32cb16blend.S b/libpixelflinger/arch-mips64/t32cb16blend.S
deleted file mode 100644
index 3cb5f93..0000000
--- a/libpixelflinger/arch-mips64/t32cb16blend.S
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
-** Copyright 2015, 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.
-*/
-
-#ifdef DEBUG
-#define DBG
-#else
-#define DBG #
-#endif
-
-/*
- * blend one of 2 16bpp RGB pixels held in dreg selected by shift
- * with the 32bpp ABGR pixel held in src and store the result in fb
- *
- * Assumes that the dreg data is little endian and that
- * the the second pixel (shift==16) will be merged into
- * the fb result
- *
- * Uses $a4,$t2,$t3,$t8
- */
-
-    .macro pixel dreg src fb shift
-    /*
-     * sA = s >> 24
-     * f = 0x100 - (sA + (sA>>7))
-     */
-    srl     $t3,\src,24
-    srl     $t2,$t3,7
-    addu    $t3,$t2
-    li      $t2,0x100
-    subu    $t3,$t2,$t3
-
-    /* red */
-    ext     $t8,\dreg,\shift+6+5,5                  # dst[\shift:15..11]
-    mul     $t2,$t8,$t3
-    ext     $a4,\dreg,\shift+5,6                    # start green extraction dst[\shift:10..5]
-    ext     $t8,\src,3,5                            # src[7..3]
-    srl     $t2,8
-    addu    $t8,$t2
-.if \shift!=0
-    sll     $t8,\shift+11                           # dst[\shift:15..11]
-    or      \fb,$t8
-.else
-    sll     \fb,$t8,11
-.endif
-
-    /* green */
-    mul     $t8,$a4,$t3
-    ext     $a4,\dreg,\shift,5                      # start blue extraction dst[\shift:4..0]
-    ext     $t2,\src,2+8,6                          # src[15..10]
-    srl     $t8,8
-    addu    $t8,$t2
-
-    /* blue */
-    mul     $a4,$a4,$t3
-    sll     $t8, $t8, \shift+5                  # finish green insertion dst[\shift:10..5]
-    or      \fb, \fb, $t8
-    ext     $t2,\src,(3+8+8),5
-    srl     $t8,$a4,8
-    addu    $t8,$t2
-    sll     $t8, $t8, \shift
-    or      \fb, \fb, $t8
-    .endm
-
-    .text
-    .balign 4
-
-    .global scanline_t32cb16blend_mips64
-    .ent    scanline_t32cb16blend_mips64
-scanline_t32cb16blend_mips64:
-    daddiu  $sp, $sp, -40
-DBG li      $v0,0xffffffff
-DBG li      $v1,0
-    /* Align the destination if necessary */
-    and     $a4,$a0,3
-    beqz    $a4,aligned
-
-    /* as long as there is at least one pixel */
-    beqz    $a2,done
-
-    lw      $t0,($a1)
-    daddu   $a0,2
-    daddu   $a1,4
-    beqz    $t0,1f
-    lhu     $a7,-2($a0)
-    pixel   $a7,$t0,$a5,0
-    sh      $a5,-2($a0)
-1:  subu    $a2,1
-
-aligned:
-    /* Check to see if its worth unrolling the loop */
-    subu    $a2,4
-    bltz    $a2,tail
-
-    /* Process 4 pixels at a time */
-fourpixels:
-    /* 1st pair of pixels */
-    lw      $t0,0($a1)
-    lw      $t1,4($a1)
-    daddu   $a0,8
-    daddu   $a1,16
-
-    /* both are zero, skip this pair */
-    or      $a7,$t0,$t1
-    beqz    $a7,1f
-
-    /* load the destination */
-    lw      $a7,-8($a0)
-
-    pixel   $a7,$t0,$a5,0
-    andi    $a5, 0xFFFF
-    pixel   $a7,$t1,$a5,16
-    sw      $a5,-8($a0)
-
-1:
-    /* 2nd pair of pixels */
-    lw      $t0,-8($a1)
-    lw      $t1,-4($a1)
-
-    /* both are zero, skip this pair */
-    or      $a7,$t0,$t1
-    beqz    $a7,1f
-
-    /* load the destination */
-    lw      $a7,-4($a0)
-
-    pixel   $a7,$t0,$a5,0
-    andi    $a5, 0xFFFF
-    pixel   $a7,$t1,$a5,16
-    sw      $a5,-4($a0)
-
-1:  subu    $a2,4
-    bgtz    $a2,fourpixels
-
-tail:
-    /* the pixel count underran, restore it now */
-    addu    $a2,4
-
-    /* handle the last 0..3 pixels */
-    beqz    $a2,done
-onepixel:
-    lw      $t0,($a1)
-    daddu   $a0,2
-    daddu   $a1,4
-    beqz    $t0,1f
-    lhu     $a7,-2($a0)
-    pixel   $a7,$t0,$a5,0
-    sh      $a5,-2($a0)
-1:  subu    $a2,1
-    bnez    $a2,onepixel
-done:
-DBG .set    push
-DBG .set    mips32r2
-DBG rdhwr   $a0,$3
-DBG mul     $v0,$a0
-DBG mul     $v1,$a0
-DBG .set    pop
-    daddiu  $sp, $sp, 40
-    j       $ra
-    .end    scanline_t32cb16blend_mips64
diff --git a/libpixelflinger/tests/arch-mips/Android.bp b/libpixelflinger/tests/arch-mips/Android.bp
deleted file mode 100644
index 2ca2721..0000000
--- a/libpixelflinger/tests/arch-mips/Android.bp
+++ /dev/null
@@ -1,11 +0,0 @@
-cc_defaults {
-    name: "pixelflinger-tests-mips",
-    defaults: ["pixelflinger-tests"],
-
-    enabled: false,
-    arch: {
-        mips: {
-            enabled: true,
-        },
-    },
-}
diff --git a/libpixelflinger/tests/arch-mips/col32cb16blend/Android.bp b/libpixelflinger/tests/arch-mips/col32cb16blend/Android.bp
deleted file mode 100644
index 45bfe29..0000000
--- a/libpixelflinger/tests/arch-mips/col32cb16blend/Android.bp
+++ /dev/null
@@ -1,6 +0,0 @@
-cc_test {
-    name: "test-pixelflinger-mips-col32cb16blend",
-    defaults: ["pixelflinger-tests-mips"],
-
-    srcs: ["col32cb16blend_test.c"],
-}
diff --git a/libpixelflinger/tests/arch-mips/col32cb16blend/col32cb16blend_test.c b/libpixelflinger/tests/arch-mips/col32cb16blend/col32cb16blend_test.c
deleted file mode 100644
index dd0e60f..0000000
--- a/libpixelflinger/tests/arch-mips/col32cb16blend/col32cb16blend_test.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-
-
-#define ARGB_8888_MAX   0xFFFFFFFF
-#define ARGB_8888_MIN   0x00000000
-#define RGB_565_MAX 0xFFFF
-#define RGB_565_MIN 0x0000
-
-struct test_t
-{
-    char name[256];
-    uint32_t src_color;
-    uint16_t dst_color;
-    size_t count;
-};
-
-struct test_t tests[] =
-{
-    {"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1},
-    {"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2},
-    {"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3},
-    {"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4},
-    {"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1},
-    {"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2},
-    {"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3},
-    {"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4},
-    {"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5},
-    {"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10}
-};
-
-void scanline_col32cb16blend_mips(uint16_t *dst, uint32_t src, size_t count);
-void scanline_col32cb16blend_c(uint16_t * dst, uint32_t src, size_t count)
-{
-    uint32_t srcAlpha = (src>>24);
-    uint32_t f = 0x100 - (srcAlpha + (srcAlpha>>7));
-
-    while (count--)
-    {
-        uint16_t d = *dst;
-        int dstR = (d>>11)&0x1f;
-        int dstG = (d>>5)&0x3f;
-        int dstB = (d)&0x1f;
-        int srcR = (src >> (   3))&0x1F;
-        int srcG = (src >> ( 8+2))&0x3F;
-        int srcB = (src >> (16+3))&0x1F;
-        srcR += (f*dstR)>>8;
-        srcG += (f*dstG)>>8;
-        srcB += (f*dstB)>>8;
-        *dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB);
-    }
-}
-
-void scanline_col32cb16blend_test()
-{
-    uint16_t dst_c[16], dst_asm[16];
-    uint32_t i, j;
-
-    for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i)
-    {
-        struct test_t test = tests[i];
-
-        printf("Testing - %s:",test.name);
-
-        memset(dst_c, 0, sizeof(dst_c));
-        memset(dst_asm, 0, sizeof(dst_asm));
-
-        for(j = 0; j < test.count; ++j)
-        {
-            dst_c[j]   = test.dst_color;
-            dst_asm[j] = test.dst_color;
-        }
-
-
-        scanline_col32cb16blend_c(dst_c, test.src_color, test.count);
-        scanline_col32cb16blend_mips(dst_asm, test.src_color, test.count);
-
-        if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0)
-            printf("Passed\n");
-        else
-            printf("Failed\n");
-
-        for(j = 0; j < test.count; ++j)
-        {
-            printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]);
-        }
-    }
-}
-
-int main()
-{
-    scanline_col32cb16blend_test();
-    return 0;
-}
diff --git a/libpixelflinger/tests/arch-mips/t32cb16blend/Android.bp b/libpixelflinger/tests/arch-mips/t32cb16blend/Android.bp
deleted file mode 100644
index 069e97c..0000000
--- a/libpixelflinger/tests/arch-mips/t32cb16blend/Android.bp
+++ /dev/null
@@ -1,6 +0,0 @@
-cc_test {
-    name: "test-pixelflinger-mips-t32cb16blend",
-    defaults: ["pixelflinger-tests-mips"],
-
-    srcs: ["t32cb16blend_test.c"],
-}
diff --git a/libpixelflinger/tests/arch-mips/t32cb16blend/t32cb16blend_test.c b/libpixelflinger/tests/arch-mips/t32cb16blend/t32cb16blend_test.c
deleted file mode 100644
index c6d6937..0000000
--- a/libpixelflinger/tests/arch-mips/t32cb16blend/t32cb16blend_test.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-
-#define ARGB_8888_MAX   0xFFFFFFFF
-#define ARGB_8888_MIN   0x00000000
-#define RGB_565_MAX     0xFFFF
-#define RGB_565_MIN     0x0000
-
-struct test_t
-{
-    char name[256];
-    uint32_t src_color;
-    uint16_t dst_color;
-    size_t count;
-};
-
-struct test_t tests[] =
-{
-    {"Count 0", 0, 0, 0},
-    {"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1},
-    {"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2},
-    {"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3},
-    {"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4},
-    {"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1},
-    {"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2},
-    {"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3},
-    {"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4},
-    {"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5},
-    {"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10}
-
-};
-
-void scanline_t32cb16blend_mips(uint16_t*, uint32_t*, size_t);
-void scanline_t32cb16blend_c(uint16_t * dst, uint32_t* src, size_t count)
-{
-    while (count--)
-    {
-        uint16_t d = *dst;
-        uint32_t s = *src++;
-        int dstR = (d>>11)&0x1f;
-        int dstG = (d>>5)&0x3f;
-        int dstB = (d)&0x1f;
-        int srcR = (s >> (   3))&0x1F;
-        int srcG = (s >> ( 8+2))&0x3F;
-        int srcB = (s >> (16+3))&0x1F;
-        int srcAlpha = (s>>24) & 0xFF;
-
-
-        int f = 0x100 - (srcAlpha + ((srcAlpha>>7) & 0x1));
-        srcR += (f*dstR)>>8;
-        srcG += (f*dstG)>>8;
-        srcB += (f*dstB)>>8;
-        // srcR = srcR > 0x1F? 0x1F: srcR;
-        // srcG = srcG > 0x3F? 0x3F: srcG;
-        // srcB = srcB > 0x1F? 0x1F: srcB;
-        *dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB);
-    }
-}
-
-void scanline_t32cb16blend_test()
-{
-    uint16_t dst_c[16], dst_asm[16];
-    uint32_t src[16];
-    uint32_t i;
-    uint32_t  j;
-
-    for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i)
-    {
-        struct test_t test = tests[i];
-
-        printf("Testing - %s:",test.name);
-
-        memset(dst_c, 0, sizeof(dst_c));
-        memset(dst_asm, 0, sizeof(dst_asm));
-
-        for(j = 0; j < test.count; ++j)
-        {
-            dst_c[j]   = test.dst_color;
-            dst_asm[j] = test.dst_color;
-            src[j] = test.src_color;
-        }
-
-        scanline_t32cb16blend_c(dst_c,src,test.count);
-        scanline_t32cb16blend_mips(dst_asm,src,test.count);
-
-
-        if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0)
-            printf("Passed\n");
-        else
-            printf("Failed\n");
-
-        for(j = 0; j < test.count; ++j)
-        {
-            printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]);
-        }
-    }
-}
-
-int main()
-{
-    scanline_t32cb16blend_test();
-    return 0;
-}
diff --git a/libpixelflinger/tests/arch-mips64/Android.bp b/libpixelflinger/tests/arch-mips64/Android.bp
deleted file mode 100644
index ba55d62..0000000
--- a/libpixelflinger/tests/arch-mips64/Android.bp
+++ /dev/null
@@ -1,11 +0,0 @@
-cc_defaults {
-    name: "pixelflinger-tests-mips64",
-    defaults: ["pixelflinger-tests"],
-
-    enabled: false,
-    arch: {
-        mips64: {
-            enabled: true,
-        },
-    },
-}
diff --git a/libpixelflinger/tests/arch-mips64/assembler/Android.bp b/libpixelflinger/tests/arch-mips64/assembler/Android.bp
deleted file mode 100644
index b672053..0000000
--- a/libpixelflinger/tests/arch-mips64/assembler/Android.bp
+++ /dev/null
@@ -1,9 +0,0 @@
-cc_test {
-    name: "test-pixelflinger-mips64-assembler-test",
-    defaults: ["pixelflinger-tests-mips64"],
-
-    srcs: [
-        "mips64_assembler_test.cpp",
-        "asm_mips_test_jacket.S",
-    ],
-}
diff --git a/libpixelflinger/tests/arch-mips64/assembler/asm_mips_test_jacket.S b/libpixelflinger/tests/arch-mips64/assembler/asm_mips_test_jacket.S
deleted file mode 100644
index 705ee9b..0000000
--- a/libpixelflinger/tests/arch-mips64/assembler/asm_mips_test_jacket.S
+++ /dev/null
@@ -1,93 +0,0 @@
-# /*
-#  * Copyright (C) 2015 The Android Open Source Project
-#  * All rights reserved.
-#  *
-#  * Redistribution and use in source and binary forms, with or without
-#  * modification, are permitted provided that the following conditions
-#  * are met:
-#  *  * Redistributions of source code must retain the above copyright
-#  *    notice, this list of conditions and the following disclaimer.
-#  *  * Redistributions in binary form must reproduce the above copyright
-#  *    notice, this list of conditions and the following disclaimer in
-#  *    the documentation and/or other materials provided with the
-#  *    distribution.
-#  *
-#  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-#  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-#  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-#  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-#  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-#  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-#  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-#  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-#  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-#  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-#  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-#  * SUCH DAMAGE.
-#  */
-
-    .text
-    .balign 8
-
-    .global asm_mips_test_jacket
-
-    # // Set the register
-    # // Calls the asm function
-    # // Reads the register values to output register
-
-    # // Parameters
-    # // a0 - Function to jump
-    # // a1 - register values array
-    # // a2 - flag values array
-asm_mips_test_jacket:
-    # // Save registers to stack
-    daddiu $sp, $sp, -96
-    sd  $s0, 64($sp)
-    sd  $s1, 72($sp)
-    sd  $s2, 80($sp)
-    sd  $ra, 88($sp)
-
-    move $s0, $a0
-    move $s1, $a1
-    move $s2, $a2
-
-    ld  $v0, 16($s1)
-    ld  $v1, 24($s1)
-    ld  $a0, 32($s1)
-    ld  $a1, 40($s1)
-    ld  $a2, 48($s1)
-    ld  $a3, 56($s1)
-    ld  $a4, 64($s1)
-    ld  $a5, 72($s1)
-    ld  $a6, 80($s1)
-    ld  $a7, 88($s1)
-    ld  $t0, 96($s1)
-    ld  $t1, 104($s1)
-    ld  $t2, 112($s1)
-    ld  $t3, 120($s1)
-
-    jal $s0
-
-    sd  $v0, 16($s1)
-    sd  $v1, 24($s1)
-    sd  $a0, 32($s1)
-    sd  $a1, 40($s1)
-    sd  $a2, 48($s1)
-    sd  $a3, 56($s1)
-    sd  $a4, 64($s1)
-    sd  $a5, 72($s1)
-    sd  $a6, 80($s1)
-    sd  $a7, 88($s1)
-    sd  $t0, 96($s1)
-    sd  $t1, 104($s1)
-    sd  $t2, 112($s1)
-    sd  $t3, 120($s1)
-
-    ld  $s0, 64($sp)
-    ld  $s1, 72($sp)
-    ld  $s2, 80($sp)
-    ld  $ra, 88($sp)
-
-    daddiu $sp, $sp, 96
-
-    j   $ra
diff --git a/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp b/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp
deleted file mode 100644
index 9fb0a28..0000000
--- a/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <errno.h>
-#define __STDC_FORMAT_MACROS
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include <android/log.h>
-#include <cutils/ashmem.h>
-
-#include "codeflinger/ARMAssemblerInterface.h"
-#include "codeflinger/MIPS64Assembler.h"
-
-using namespace android;
-
-#define TESTS_DATAOP_ENABLE             1
-#define TESTS_DATATRANSFER_ENABLE       1
-#define ASSEMBLY_SCRATCH_SIZE           4096
-
-void *instrMem;
-uint32_t  instrMemSize = 128 * 1024;
-char     dataMem[8192];
-
-typedef void (*asm_function_t)();
-extern "C" void asm_mips_test_jacket(asm_function_t function,
-                                     int64_t regs[], int32_t flags[]);
-
-#define MAX_32BIT (uint32_t)(((uint64_t)1 << 32) - 1)
-#define MAX_64BIT ((uint64_t)0xFFFFFFFFFFFFFFFF)
-const uint32_t NA = 0;
-const uint32_t NUM_REGS = 32;
-const uint32_t NUM_FLAGS = 16;
-
-enum instr_t
-{
-    INSTR_ADD,
-    INSTR_SUB,
-    INSTR_AND,
-    INSTR_ORR,
-    INSTR_RSB,
-    INSTR_BIC,
-    INSTR_CMP,
-    INSTR_MOV,
-    INSTR_MVN,
-    INSTR_MUL,
-    INSTR_MLA,
-    INSTR_SMULBB,
-    INSTR_SMULBT,
-    INSTR_SMULTB,
-    INSTR_SMULTT,
-    INSTR_SMULWB,
-    INSTR_SMULWT,
-    INSTR_SMLABB,
-    INSTR_UXTB16,
-    INSTR_UBFX,
-    INSTR_ADDR_ADD,
-    INSTR_ADDR_SUB,
-    INSTR_LDR,
-    INSTR_LDRB,
-    INSTR_LDRH,
-    INSTR_ADDR_LDR,
-    INSTR_LDM,
-    INSTR_STR,
-    INSTR_STRB,
-    INSTR_STRH,
-    INSTR_ADDR_STR,
-    INSTR_STM
-};
-
-enum shift_t
-{
-    SHIFT_LSL,
-    SHIFT_LSR,
-    SHIFT_ASR,
-    SHIFT_ROR,
-    SHIFT_NONE
-};
-
-enum offset_t
-{
-    REG_SCALE_OFFSET,
-    REG_OFFSET,
-    IMM8_OFFSET,
-    IMM12_OFFSET,
-    NO_OFFSET
-};
-
-enum cond_t
-{
-    EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV,
-    HS = CS,
-    LO = CC
-};
-
-const char * cc_code[] =
-{
-    "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC",
-    "HI", "LS","GE","LT", "GT", "LE", "AL", "NV"
-};
-
-struct condTest_t
-{
-    int     mode;
-    int32_t Rcond1;
-    int32_t Rcond2;
-    uint64_t Rcond1Value;
-    uint64_t Rcond2Value;
-};
-
-
-struct dataOpTest_t
-{
-    uint32_t   id;
-    instr_t    op;
-    condTest_t preCond;
-    cond_t     cond;
-    bool       setFlags;
-    uint64_t   RnValue;
-    uint64_t   RsValue;
-    bool       immediate;
-    uint32_t   immValue;
-    uint64_t   RmValue;
-    uint32_t   shiftMode;
-    uint32_t   shiftAmount;
-    uint64_t   RdValue;
-    bool       checkRd;
-    uint64_t   postRdValue;
-};
-
-struct dataTransferTest_t
-{
-    uint32_t id;
-    instr_t  op;
-    uint32_t preFlag;
-    cond_t   cond;
-    bool     setMem;
-    uint64_t memOffset;
-    uint64_t memValue;
-    uint64_t RnValue;
-    offset_t offsetType;
-    uint64_t RmValue;
-    uint32_t immValue;
-    bool     writeBack;
-    bool     preIndex;
-    bool     postIndex;
-    uint64_t RdValue;
-    uint64_t postRdValue;
-    uint64_t postRnValue;
-    bool     checkMem;
-    uint64_t postMemOffset;
-    uint32_t postMemLength;
-    uint64_t postMemValue;
-};
-
-
-dataOpTest_t dataOpTests [] =
-{
-     {0xA000,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT,NA,NA,NA,NA,1,0},
-     {0xA001,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT-1,NA,NA,NA,NA,1,MAX_64BIT},
-     {0xA002,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT,NA,NA,NA,1,0},
-     {0xA003,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT-1,NA,NA,NA,1,MAX_64BIT},
-     {0xA004,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL, 0,NA,1,0},
-     {0xA005,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0xFFFFFFFF80000001},
-     {0xA006,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,2},
-     {0xA007,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,2},
-     {0xA008,INSTR_ADD,{0,0,0,0,0},AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,1},
-     {0xA009,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_64BIT,SHIFT_ASR,31,NA,1,0},
-     {0xA010,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT,0,0,0,NA,1,1},
-     {0xA011,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT-1,0,0,0,NA,1,0},
-     {0xA012,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,0,0,NA,1,1},
-     {0xA013,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT-1,0,0,NA,1,0},
-     {0xA014,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,0,NA,1,1},
-     {0xA015,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0},
-     {0xA016,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,1},
-     {0xA017,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,1},
-     {0xA018,INSTR_AND,{0,0,0,0,0},AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,0},
-     {0xA019,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_ASR,31,NA,1,1},
-     {0xA020,INSTR_ORR,{0,0,0,0,0},AL,0,3,NA,1,MAX_32BIT,0,0,0,NA,1,MAX_64BIT},
-     {0xA021,INSTR_ORR,{0,0,0,0,0},AL,0,2,NA,1,MAX_32BIT-1,0,0,0,NA,1,MAX_64BIT-1},
-     {0xA022,INSTR_ORR,{0,0,0,0,0},AL,0,3,NA,0,0,MAX_32BIT,0,0,NA,1,MAX_64BIT},
-     {0xA023,INSTR_ORR,{0,0,0,0,0},AL,0,2,NA,0,0,MAX_32BIT-1,0,0,NA,1,MAX_64BIT-1},
-     {0xA024,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,0,NA,1,MAX_64BIT},
-     {0xA025,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0xFFFFFFFF80000001},
-     {0xA026,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,1},
-     {0xA027,INSTR_ORR,{0,0,0,0,0},AL,0,0,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,1},
-     {0xA028,INSTR_ORR,{0,0,0,0,0},AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,1},
-     {0xA029,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_64BIT,SHIFT_ASR,31,NA,1,MAX_64BIT},
-     {0xA030,INSTR_CMP,{0,0,0,0,0},AL,1,0x10000,NA,1,0x10000,0,0,0,NA,0,0},
-     {0xA031,INSTR_MUL,{0,0,0,0,0},AL,0,0,0x10000,0,0,0x10000,0,0,NA,1,0},
-     {0xA032,INSTR_MUL,{0,0,0,0,0},AL,0,0,0x1000,0,0,0x10000,0,0,NA,1,0x10000000},
-     {0xA033,INSTR_MUL,{0,0,0,0,0},AL,0,0,MAX_32BIT,0,0,1,0,0,NA,1,MAX_64BIT},
-     {0xA034,INSTR_MLA,{0,0,0,0,0},AL,0,0x10000,0x10000,0,0,0x10000,0,0,NA,1,0x10000},
-     {0xA035,INSTR_MLA,{0,0,0,0,0},AL,0,0x10000,0x1000,0,0,0x10000,0,0,NA,1,0x10010000},
-     {0xA036,INSTR_SUB,{1,R_v1,R_a6,2,4},MI,0,2,NA,0,NA,1,NA,NA,2,1,1},
-     {0xA037,INSTR_SUB,{2,R_v1,R_a6,2,0},MI,0,2,NA,0,NA,1,NA,NA,2,1,2},
-     {0xA038,INSTR_SUB,{1,R_v1,R_a6,4,2},GE,0,2,NA,1,1,NA,NA,NA,2,1,1},
-     {0xA039,INSTR_SUB,{1,R_a5,R_a6,2,7},GE,0,2,NA,1,1,NA,NA,NA,2,1,2},
-     {0xA040,INSTR_SUB,{1,R_a5,R_a6,1,1},HS,0,2,NA,1,1,NA,NA,NA,2,1,1},
-     {0xA041,INSTR_SUB,{1,R_a5,R_a6,0,1},HS,0,2,NA,1,1,NA,NA,NA,2,1,2},
-     {0xA042,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,1,1<< 16,0,0,0,NA,1,UINT64_C(1) -(1<<16)},
-     {0xA043,INSTR_SUB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,1,1,0,0,0,NA,1,MAX_64BIT-1},
-     {0xA044,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,1,1,0,0,0,NA,1,0},
-     {0xA045,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,1<<16,0,0,NA,1,UINT64_C(1) -(1<<16)},
-     {0xA046,INSTR_SUB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,0,NA,1,0,0,NA,1,MAX_64BIT-1},
-     {0xA047,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,0,0,NA,1,0},
-     {0xA048,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,SHIFT_LSL,16,NA,1,UINT64_C(1) -(1<<16)},
-     {0xA049,INSTR_SUB,{0,0,0,0,0},AL,0,0x80000001,NA,0,NA,MAX_32BIT,SHIFT_LSL,31,NA,1,1},
-     {0xA050,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,3,SHIFT_LSR,1,NA,1,0},
-     {0xA051,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT,SHIFT_LSR,31,NA,1,0},
-     {0xA052,INSTR_RSB,{1,R_a5,R_a6,4,1},GE,0,2,NA,1,0,NA,NA,NA,2,1,UINT64_C(-2)},
-     {0xA053,INSTR_RSB,{1,R_a5,R_a6,UINT64_C(-1),1},GE,0,2,NA,1,0,NA,NA,NA,2,1,2},
-     {0xA054,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,1,1<<16,NA,NA,NA,NA,1,(1<<16)-1},
-     {0xA055,INSTR_RSB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,1,1,NA,NA,NA,NA,1,UINT64_C(1)-MAX_64BIT},
-     {0xA056,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,1,1,NA,NA,NA,NA,1,0},
-     {0xA057,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,1<<16,0,0,NA,1,(1<<16)-1},
-     {0xA058,INSTR_RSB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,0,NA,1,0,0,NA,1,UINT64_C(1)-MAX_64BIT},
-     {0xA059,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,0,0,NA,1,0},
-     {0xA060,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,SHIFT_LSL,16,NA,1,(1<<16)-1},
-     {0xA061,INSTR_RSB,{0,0,0,0,0},AL,0,0x80000001,NA,0,NA,MAX_32BIT ,SHIFT_LSL,31,NA,1,UINT64_C(-1)},
-     {0xA062,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,3,SHIFT_LSR,1,NA,1,0},
-     {0xA063,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT,SHIFT_LSR,31,NA,1,0},
-     {0xA064,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,1,0x80000001,NA,NA,NA,NA,1,0xFFFFFFFF80000001},
-     {0xA065,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,0x80000001,0,0,NA,1,0xFFFFFFFF80000001},
-     {0xA066,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,NA,1,MAX_64BIT-1},
-     {0xA067,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0xFFFFFFFF80000000},
-     {0xA068,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,3,SHIFT_LSR,1,NA,1,1},
-     {0xA069,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,1},
-     {0xA070,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,3,SHIFT_ASR,1,NA,1,1},
-     {0xA071,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_64BIT ,SHIFT_ASR,31,NA,1,MAX_64BIT},
-     {0xA072,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,3,SHIFT_ROR,1,NA,1,0xFFFFFFFF80000001},
-     {0xA073,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,0x80000001,SHIFT_ROR,31,NA,1,3},
-     {0xA074,INSTR_MOV,{0,0,0,0,0},AL,1,NA,NA,0,0,MAX_64BIT -1,SHIFT_ASR,1,NA,1,MAX_64BIT},
-     {0xA075,INSTR_MOV,{0,0,0,0,0},AL,1,NA,NA,0,0,3,SHIFT_ASR,1,NA,1,1},
-     {0xA076,INSTR_MOV,{2,R_a5,R_a6,6,8},MI,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
-     {0xA077,INSTR_MOV,{2,R_a5,R_a6,UINT64_C(-4),UINT64_C(-8)},MI,0,NA,NA,0,0,0x80000001,0,0,2,1,0xFFFFFFFF80000001},
-     {0xA078,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),UINT64_C(-1)},LT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
-     {0xA079,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),1},LT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001},
-     {0xA080,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),UINT64_C(-5)},GE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,MAX_64BIT-1},
-     {0xA081,INSTR_MOV,{1,R_a5,R_a6,5,5},GE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,2,1,0xFFFFFFFF80000000},
-     {0xA082,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),1},GE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,2,1,2},
-     {0xA083,INSTR_MOV,{1,R_a5,R_a6,4,1},LE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,2},
-     {0xA084,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),UINT64_C(-1)},LE,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001},
-     {0xA085,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),1},LE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,2,1,0xFFFFFFFF80000000},
-     {0xA086,INSTR_MOV,{1,R_a5,R_a6,1,1},GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
-     {0xA087,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),UINT64_C(-3)},GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001},
-     {0xA088,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),0},GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
-     {0xA089,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),UINT64_C(-1)},GT,0,NA,NA,0,0,0x80000001,0,0,2,1,2},
-     {0xA090,INSTR_MOV,{1,R_a5,R_a6,6,1},GT,0,NA,NA,0,0,0x80000001,0,0,2,1,0xFFFFFFFF80000001},
-     {0xA091,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),1},GT,0,NA,NA,0,0,0x80000001,0,0,2,1,2},
-     {0xA092,INSTR_MOV,{1,R_a5,R_a6,1,1},GT,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,2},
-     {0xA093,INSTR_MOV,{1,R_a5,R_a6,4,1},GT,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,MAX_64BIT-1},
-     {0xA094,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),1},GT,0,NA,NA,0,0,MAX_32BIT ,SHIFT_LSL,1,2,1,2},
-     {0xA095,INSTR_MOV,{1,R_a5,R_a6,1,UINT64_C(-1)},HS,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
-     {0xA096,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),1},HS,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001},
-     {0xA097,INSTR_MVN,{1,R_a5,R_a6,1,4},HS,0,NA,NA,1,MAX_32BIT-1,NA,NA,NA,2,1,2},
-     {0xA098,INSTR_MVN,{1,R_a5,R_a6,UINT64_C(-1),1},HS,0,NA,NA,1,MAX_32BIT-1,NA,NA,NA,2,1,1},
-     {0xA099,INSTR_MVN,{0,0,0,0,0},AL,0,NA,NA,1,0,NA,NA,NA,2,1,MAX_64BIT},
-     {0xA100,INSTR_MVN,{0,0,0,0,0},AL,0,NA,NA,0,NA,MAX_32BIT-1,NA,0,2,1,1},
-     {0xA101,INSTR_MVN,{0,0,0,0,0},AL,0,NA,NA,0,NA,0x80000001,NA,0,2,1,0x7FFFFFFE},
-     {0xA102,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT,NA,NA,NA,NA,1,0},
-     {0xA103,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT-1,NA,NA,NA,NA,1,1},
-     {0xA104,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,0,0,NA,1,0},
-     {0xA105,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT-1,0,0,NA,1,1},
-     {0xA106,INSTR_BIC,{0,0,0,0,0},AL,0,0xF0,NA,0,0,3,SHIFT_ASR,1,NA,1,0xF0},
-     {0xA107,INSTR_BIC,{0,0,0,0,0},AL,0,0xF0,NA,0,0,MAX_64BIT,SHIFT_ASR,31,NA,1,0},
-     {0xA108,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFABCD0001,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
-     {0xA109,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFABCD0FFF,NA,NA,NA,1,0x00000FFF},
-     {0xA110,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
-     {0xA111,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,1},
-     {0xA112,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFABCD0001,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
-     {0xA113,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFABCD0FFF,NA,NA,NA,1,0x00000FFF},
-     {0xA114,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
-     {0xA115,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,1},
-     {0xA116,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
-     {0xA117,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF},
-     {0xA118,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
-     {0xA119,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,1},
-     {0xA120,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
-     {0xA121,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF},
-     {0xA122,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
-     {0xA123,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,1},
-     {0xA124,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFE},
-     {0xA125,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF},
-     {0xA126,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
-     {0xA127,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0},
-     {0xA128,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFE},
-     {0xA129,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF},
-     {0xA130,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
-     {0xA131,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0},
-     {0xA132,INSTR_SMLABB,{0,0,0,0,0},AL,0,1,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFABCD0001,NA,NA,NA,1,0},
-     {0xA133,INSTR_SMLABB,{0,0,0,0,0},AL,0,1,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFABCD0FFF,NA,NA,NA,1,0x00001000},
-     {0xA134,INSTR_SMLABB,{0,0,0,0,0},AL,0,0xFFFFFFFFFFFFFFFF,0xFFFFFFFFABCD0001,0,NA,0xABCDFFFF,NA,NA,NA,1,0xFFFFFFFFFFFFFFFE},
-     {0xA135,INSTR_SMLABB,{0,0,0,0,0},AL,0,0xFFFFFFFFFFFFFFFF,0xFFFFFFFFABCDFFFF,0,NA,0xABCDFFFF,NA,NA,NA,1,0},
-     {0xA136,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,0,NA,1,0x00CD0001},
-     {0xA137,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,1,NA,1,0x00AB00EF},
-     {0xA138,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,2,NA,1,0x000100CD},
-     {0xA139,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,3,NA,1,0x00EF00AB},
-     {0xA140,INSTR_ADDR_ADD,{0,0,0,0,0},AL,0,0xCFFFFFFFF,NA,0,NA,0x1,SHIFT_LSL,1,NA,1,0xD00000001},
-     {0xA141,INSTR_ADDR_ADD,{0,0,0,0,0},AL,0,0x01,NA,0,NA,0x1,SHIFT_LSL,2,NA,1,0x5},
-     {0xA142,INSTR_ADDR_ADD,{0,0,0,0,0},AL,0,0xCFFFFFFFF,NA,0,NA,0x1,NA,0,NA,1,0xD00000000},
-     {0xA143,INSTR_ADDR_SUB,{0,0,0,0,0},AL,0,0xD00000001,NA,0,NA,0x010000,SHIFT_LSR,15,NA,1,0xCFFFFFFFF},
-     {0xA144,INSTR_ADDR_SUB,{0,0,0,0,0},AL,0,0xCFFFFFFFF,NA,0,NA,0x020000,SHIFT_LSR,15,NA,1,0xCFFFFFFFB},
-     {0xA145,INSTR_ADDR_SUB,{0,0,0,0,0},AL,0,3,NA,0,NA,0x010000,SHIFT_LSR,15,NA,1,1},
-};
-
-dataTransferTest_t dataTransferTests [] =
-{
-    {0xB000,INSTR_LDR,AL,AL,1,24,0xABCDEF0123456789,0,REG_SCALE_OFFSET,24,NA,NA,NA,NA,NA,0x23456789,0,0,NA,NA,NA},
-    {0xB001,INSTR_LDR,AL,AL,1,0,0xABCDEF0123456789,0,IMM12_OFFSET,NA,4,1,0,1,NA,0x23456789,4,0,NA,NA,NA},
-    {0xB002,INSTR_LDR,AL,AL,1,0,0xABCDEF0123456789,0,NO_OFFSET,NA,NA,0,0,0,NA,0x23456789,0,0,NA,NA,NA},
-    {0xB003,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,0,REG_SCALE_OFFSET,4064,NA,NA,NA,NA,NA,0x89,0,0,NA,NA,NA},
-    {0xB004,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,0,0,1,0,NA,0x67,4065,0,NA,NA,NA},
-    {0xB005,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,1,0,1,0,NA,0x45,4065,0,NA,NA,NA},
-    {0xB006,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,2,0,1,0,NA,0x23,4065,0,NA,NA,NA},
-    {0xB007,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,1,1,0,1,NA,0x67,4066,0,NA,NA,NA},
-    {0xB008,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,0,NO_OFFSET,NA,NA,0,0,0,NA,0x89,0,0,NA,NA,NA},
-    {0xB009,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,0,IMM8_OFFSET,NA,2,1,0,1,NA,0x6789,2,0,NA,NA,NA},
-    {0xB010,INSTR_LDRH,AL,AL,1,4064,0xABCDEF0123456789,0,REG_OFFSET,4064,0,0,1,0,NA,0x6789,0,0,NA,NA,NA},
-    {0xB011,INSTR_LDRH,AL,AL,1,4064,0xABCDEF0123456789,0,REG_OFFSET,4066,0,0,1,0,NA,0x2345,0,0,NA,NA,NA},
-    {0xB012,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,0,NO_OFFSET,NA,0,0,0,0,NA,0x6789,0,0,NA,NA,NA},
-    {0xB013,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,2,NO_OFFSET,NA,0,0,0,0,NA,0x2345,2,0,NA,NA,NA},
-    {0xB014,INSTR_STR,AL,AL,1,2,0xDEADBEEFDEADBEEF,4,IMM12_OFFSET,NA,4,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,8,1,2,8,0xDEAD23456789BEEF},
-    {0xB015,INSTR_STR,AL,AL,1,2,0xDEADBEEFDEADBEEF,4,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4,1,2,8,0xDEAD23456789BEEF},
-    {0xB016,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,0,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDEAD89EF},
-    {0xB017,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,1,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDE89BEEF},
-    {0xB018,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,2,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEF89ADBEEF},
-    {0xB019,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,4,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,5,1,0,8,0xDEADBEEFDEAD89EF},
-    {0xB020,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDEAD89EF},
-    {0xB021,INSTR_STRH,AL,AL,1,4066,0xDEADBEEFDEADBEEF,4070,IMM8_OFFSET,NA,2,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,4072,1,4066,8,0xDEAD6789DEADBEEF},
-    {0xB022,INSTR_STRH,AL,AL,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEAD6789DEADBEEF},
-};
-
-
-void flushcache()
-{
-    const long base = long(instrMem);
-    const long curr = base + long(instrMemSize);
-    __builtin___clear_cache((char*)base, (char*)curr);
-}
-
-void dataOpTest(dataOpTest_t test, ArmToMips64Assembler *a64asm, uint32_t Rd = R_v1,
-                uint32_t Rn = R_t0, uint32_t Rm = R_t1, uint32_t Rs = R_t2)
-{
-    int64_t  regs[NUM_REGS] = {0};
-    int32_t  flags[NUM_FLAGS] = {0};
-    int64_t  savedRegs[NUM_REGS] = {0};
-    uint32_t i;
-    uint32_t op2;
-
-    for(i = 0; i < NUM_REGS; ++i)
-    {
-        regs[i] = i;
-    }
-
-    regs[Rd] = test.RdValue;
-    regs[Rn] = test.RnValue;
-    regs[Rs] = test.RsValue;
-    a64asm->reset();
-    if (test.preCond.mode) {
-        a64asm->set_condition(test.preCond.mode, test.preCond.Rcond1, test.preCond.Rcond2);
-        regs[test.preCond.Rcond1] = test.preCond.Rcond1Value;
-        regs[test.preCond.Rcond2] = test.preCond.Rcond2Value;
-    }
-    a64asm->prolog();
-    if(test.immediate == true)
-    {
-        op2 = a64asm->imm(test.immValue);
-    }
-    else if(test.immediate == false && test.shiftAmount == 0)
-    {
-        op2 = Rm;
-        regs[Rm] = (int64_t)((int32_t)(test.RmValue));
-    }
-    else
-    {
-        op2 = a64asm->reg_imm(Rm, test.shiftMode, test.shiftAmount);
-        regs[Rm] = (int64_t)((int32_t)(test.RmValue));
-    }
-    switch(test.op)
-    {
-    case INSTR_ADD: a64asm->ADD(test.cond, test.setFlags, Rd,Rn,op2); break;
-    case INSTR_SUB: a64asm->SUB(test.cond, test.setFlags, Rd,Rn,op2); break;
-    case INSTR_RSB: a64asm->RSB(test.cond, test.setFlags, Rd,Rn,op2); break;
-    case INSTR_AND: a64asm->AND(test.cond, test.setFlags, Rd,Rn,op2); break;
-    case INSTR_ORR: a64asm->ORR(test.cond, test.setFlags, Rd,Rn,op2); break;
-    case INSTR_BIC: a64asm->BIC(test.cond, test.setFlags, Rd,Rn,op2); break;
-    case INSTR_MUL: a64asm->MUL(test.cond, test.setFlags, Rd,Rm,Rs); break;
-    case INSTR_MLA: a64asm->MLA(test.cond, test.setFlags, Rd,Rm,Rs,Rn); break;
-    case INSTR_CMP: a64asm->CMP(test.cond, Rn,op2); break;
-    case INSTR_MOV: a64asm->MOV(test.cond, test.setFlags,Rd,op2); break;
-    case INSTR_MVN: a64asm->MVN(test.cond, test.setFlags,Rd,op2); break;
-    case INSTR_SMULBB:a64asm->SMULBB(test.cond, Rd,Rm,Rs); break;
-    case INSTR_SMULBT:a64asm->SMULBT(test.cond, Rd,Rm,Rs); break;
-    case INSTR_SMULTB:a64asm->SMULTB(test.cond, Rd,Rm,Rs); break;
-    case INSTR_SMULTT:a64asm->SMULTT(test.cond, Rd,Rm,Rs); break;
-    case INSTR_SMULWB:a64asm->SMULWB(test.cond, Rd,Rm,Rs); break;
-    case INSTR_SMULWT:a64asm->SMULWT(test.cond, Rd,Rm,Rs); break;
-    case INSTR_SMLABB:a64asm->SMLABB(test.cond, Rd,Rm,Rs,Rn); break;
-    case INSTR_UXTB16:a64asm->UXTB16(test.cond, Rd,Rm,test.shiftAmount); break;
-    case INSTR_ADDR_ADD: a64asm->ADDR_ADD(test.cond, test.setFlags, Rd,Rn,op2); break;
-    case INSTR_ADDR_SUB: a64asm->ADDR_SUB(test.cond, test.setFlags, Rd,Rn,op2); break;
-    default: printf("Error"); return;
-    }
-    a64asm->epilog(0);
-    a64asm->fix_branches();
-    flushcache();
-
-    asm_function_t asm_function = (asm_function_t)(instrMem);
-
-    for(i = 0; i < NUM_REGS; ++i)
-        savedRegs[i] = regs[i];
-
-    asm_mips_test_jacket(asm_function, regs, flags);
-
-    /* Check if all regs except Rd is same */
-    for(i = 0; i < NUM_REGS; ++i)
-    {
-        if((i == Rd) || i == 2) continue;
-        if(regs[i] != savedRegs[i])
-        {
-            printf("Test %x failed Reg(%d) tampered Expected(0x%" PRIx64 "),"
-                   "Actual(0x%" PRIx64 ") t\n", test.id, i, savedRegs[i],
-                   regs[i]);
-            exit(0);
-            return;
-        }
-    }
-
-    if(test.checkRd == 1 && regs[Rd] != test.postRdValue)
-    {
-        printf("Test %x failed, Expected(%" PRIx64 "), Actual(%" PRIx64 ")\n",
-               test.id, test.postRdValue, regs[Rd]);
-        exit(0);
-    }
-    else
-    {
-        printf("Test %x passed\n", test.id);
-    }
-}
-
-
-void dataTransferTest(dataTransferTest_t test, ARMAssemblerInterface *a64asm,
-                      uint32_t Rd = R_v1, uint32_t Rn = R_t0,uint32_t Rm = R_t1)
-{
-    int64_t regs[NUM_REGS] = {0};
-    int64_t savedRegs[NUM_REGS] = {0};
-    int32_t flags[NUM_FLAGS] = {0};
-    uint32_t i;
-    for(i = 0; i < NUM_REGS; ++i)
-    {
-        regs[i] = i;
-    }
-
-    uint32_t op2;
-
-    regs[Rd] = test.RdValue;
-    regs[Rn] = (uint64_t)(&dataMem[test.RnValue]);
-    regs[Rm] = test.RmValue;
-    flags[test.preFlag] = 1;
-
-    if(test.setMem == true)
-    {
-        unsigned char *mem = (unsigned char *)&dataMem[test.memOffset];
-        uint64_t value = test.memValue;
-        for(int j = 0; j < 8; ++j)
-        {
-            mem[j] = value & 0x00FF;
-            value >>= 8;
-        }
-    }
-    a64asm->reset();
-    a64asm->prolog();
-    if(test.offsetType == REG_SCALE_OFFSET)
-    {
-        op2 = a64asm->reg_scale_pre(Rm);
-    }
-    else if(test.offsetType == REG_OFFSET)
-    {
-        op2 = a64asm->reg_pre(Rm);
-    }
-    else if(test.offsetType == IMM12_OFFSET && test.preIndex == true)
-    {
-        op2 = a64asm->immed12_pre(test.immValue, test.writeBack);
-    }
-    else if(test.offsetType == IMM12_OFFSET && test.postIndex == true)
-    {
-        op2 = a64asm->immed12_post(test.immValue);
-    }
-    else if(test.offsetType == IMM8_OFFSET && test.preIndex == true)
-    {
-        op2 = a64asm->immed8_pre(test.immValue, test.writeBack);
-    }
-    else if(test.offsetType == IMM8_OFFSET && test.postIndex == true)
-    {
-        op2 = a64asm->immed8_post(test.immValue);
-    }
-    else if(test.offsetType == NO_OFFSET)
-    {
-        op2 = a64asm->__immed12_pre(0);
-    }
-    else
-    {
-        printf("Error - Unknown offset\n"); return;
-    }
-
-    switch(test.op)
-    {
-    case INSTR_LDR:  a64asm->LDR(test.cond, Rd,Rn,op2); break;
-    case INSTR_LDRB: a64asm->LDRB(test.cond, Rd,Rn,op2); break;
-    case INSTR_LDRH: a64asm->LDRH(test.cond, Rd,Rn,op2); break;
-    case INSTR_ADDR_LDR: a64asm->ADDR_LDR(test.cond, Rd,Rn,op2); break;
-    case INSTR_STR:  a64asm->STR(test.cond, Rd,Rn,op2); break;
-    case INSTR_STRB: a64asm->STRB(test.cond, Rd,Rn,op2); break;
-    case INSTR_STRH: a64asm->STRH(test.cond, Rd,Rn,op2); break;
-    case INSTR_ADDR_STR: a64asm->ADDR_STR(test.cond, Rd,Rn,op2); break;
-    default: printf("Error"); return;
-    }
-    a64asm->epilog(0);
-    flushcache();
-
-    asm_function_t asm_function = (asm_function_t)(instrMem);
-
-    for(i = 0; i < NUM_REGS; ++i)
-        savedRegs[i] = regs[i];
-
-    asm_mips_test_jacket(asm_function, regs, flags);
-
-    /* Check if all regs except Rd/Rn are same */
-    for(i = 0; i < NUM_REGS; ++i)
-    {
-        if(i == Rd || i == Rn || i == R_v0) continue;
-
-        if(regs[i] != savedRegs[i])
-        {
-            printf("Test %x failed Reg(%d) tampered"
-                   " Expected(0x%" PRIx64 "), Actual(0x%" PRIx64 ") t\n",
-                   test.id, i, savedRegs[i], regs[i]);
-            return;
-        }
-    }
-
-    if((uint64_t)regs[Rd] != test.postRdValue)
-    {
-        printf("Test %x failed, "
-               "Expected in Rd(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n",
-               test.id, test.postRdValue, regs[Rd]);
-    }
-    else if((uint64_t)regs[Rn] != (uint64_t)(&dataMem[test.postRnValue]))
-    {
-        printf("Test %x failed, "
-               "Expected in Rn(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n",
-               test.id, test.postRnValue, regs[Rn] - (uint64_t)dataMem);
-    }
-    else if(test.checkMem == true)
-    {
-        unsigned char *addr = (unsigned char *)&dataMem[test.postMemOffset];
-        uint64_t value;
-        value = 0;
-        for(uint32_t j = 0; j < test.postMemLength; ++j)
-            value = (value << 8) | addr[test.postMemLength-j-1];
-        if(value != test.postMemValue)
-        {
-            printf("Test %x failed, "
-                   "Expected in Mem(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n",
-                   test.id, test.postMemValue, value);
-        }
-        else
-        {
-            printf("Test %x passed\n", test.id);
-        }
-    }
-    else
-    {
-        printf("Test %x passed\n", test.id);
-    }
-}
-
-int main(void)
-{
-    uint32_t i;
-
-    /* Allocate memory to store instructions generated by ArmToArm64Assembler */
-    {
-        int fd = ashmem_create_region("code cache", instrMemSize);
-        if(fd < 0) {
-            printf("IF < 0\n");
-            printf("Creating code cache, ashmem_create_region "
-                                "failed with error '%s'", strerror(errno));
-        }
-        instrMem = mmap(NULL, instrMemSize,
-                                    PROT_READ | PROT_WRITE | PROT_EXEC,
-                                MAP_PRIVATE, fd, 0);
-    }
-
-    ArmToMips64Assembler a64asm(instrMem);
-
-    if(TESTS_DATAOP_ENABLE)
-    {
-        printf("Running data processing tests\n");
-        for(i = 0; i < sizeof(dataOpTests)/sizeof(dataOpTest_t); ++i) {
-            dataOpTest(dataOpTests[i], &a64asm);
-        }
-    }
-
-    if(TESTS_DATATRANSFER_ENABLE)
-    {
-        printf("Running data transfer tests\n");
-        for(i = 0; i < sizeof(dataTransferTests)/sizeof(dataTransferTest_t); ++i)
-            dataTransferTest(dataTransferTests[i], &a64asm);
-    }
-
-    return 0;
-}
diff --git a/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.bp b/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.bp
deleted file mode 100644
index bfc6ae9..0000000
--- a/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.bp
+++ /dev/null
@@ -1,6 +0,0 @@
-cc_test {
-    name: "test-pixelflinger-mips64-col32cb16blend",
-    defaults: ["pixelflinger-tests-mips64"],
-
-    srcs: ["col32cb16blend_test.c"],
-}
diff --git a/libpixelflinger/tests/arch-mips64/col32cb16blend/col32cb16blend_test.c b/libpixelflinger/tests/arch-mips64/col32cb16blend/col32cb16blend_test.c
deleted file mode 100644
index 066eab6..0000000
--- a/libpixelflinger/tests/arch-mips64/col32cb16blend/col32cb16blend_test.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-
-
-#define ARGB_8888_MAX   0xFFFFFFFF
-#define ARGB_8888_MIN   0x00000000
-#define RGB_565_MAX 0xFFFF
-#define RGB_565_MIN 0x0000
-
-struct test_t
-{
-    char name[256];
-    uint32_t src_color;
-    uint16_t dst_color;
-    size_t count;
-};
-
-struct test_t tests[] =
-{
-    {"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1},
-    {"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2},
-    {"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3},
-    {"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4},
-    {"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1},
-    {"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2},
-    {"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3},
-    {"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4},
-    {"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5},
-    {"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10}
-};
-
-void scanline_col32cb16blend_mips64(uint16_t *dst, uint32_t src, size_t count);
-void scanline_col32cb16blend_c(uint16_t * dst, uint32_t src, size_t count)
-{
-    uint32_t srcAlpha = (src>>24);
-    uint32_t f = 0x100 - (srcAlpha + (srcAlpha>>7));
-
-    while (count--)
-    {
-        uint16_t d = *dst;
-        int dstR = (d>>11)&0x1f;
-        int dstG = (d>>5)&0x3f;
-        int dstB = (d)&0x1f;
-        int srcR = (src >> (   3))&0x1F;
-        int srcG = (src >> ( 8+2))&0x3F;
-        int srcB = (src >> (16+3))&0x1F;
-        srcR += (f*dstR)>>8;
-        srcG += (f*dstG)>>8;
-        srcB += (f*dstB)>>8;
-        *dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB);
-    }
-}
-
-void scanline_col32cb16blend_test()
-{
-    uint16_t dst_c[16], dst_asm[16];
-    uint32_t i, j;
-
-    for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i)
-    {
-        struct test_t test = tests[i];
-
-        printf("Testing - %s:",test.name);
-
-        memset(dst_c, 0, sizeof(dst_c));
-        memset(dst_asm, 0, sizeof(dst_asm));
-
-        for(j = 0; j < test.count; ++j)
-        {
-            dst_c[j]   = test.dst_color;
-            dst_asm[j] = test.dst_color;
-        }
-
-
-        scanline_col32cb16blend_c(dst_c, test.src_color, test.count);
-        scanline_col32cb16blend_mips64(dst_asm, test.src_color, test.count);
-
-        if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0)
-            printf("Passed\n");
-        else
-            printf("Failed\n");
-
-        for(j = 0; j < test.count; ++j)
-        {
-            printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]);
-        }
-    }
-}
-
-int main()
-{
-    scanline_col32cb16blend_test();
-    return 0;
-}
diff --git a/libpixelflinger/tests/arch-mips64/disassembler/Android.bp b/libpixelflinger/tests/arch-mips64/disassembler/Android.bp
deleted file mode 100644
index 96bf9e9..0000000
--- a/libpixelflinger/tests/arch-mips64/disassembler/Android.bp
+++ /dev/null
@@ -1,6 +0,0 @@
-cc_test {
-    name: "test-pixelflinger-mips64-disassembler-test",
-    defaults: ["pixelflinger-tests-mips64"],
-
-    srcs: ["mips64_disassembler_test.cpp"],
-}
diff --git a/libpixelflinger/tests/arch-mips64/disassembler/mips64_disassembler_test.cpp b/libpixelflinger/tests/arch-mips64/disassembler/mips64_disassembler_test.cpp
deleted file mode 100644
index 22efa9f..0000000
--- a/libpixelflinger/tests/arch-mips64/disassembler/mips64_disassembler_test.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <stdio.h>
-#include <inttypes.h>
-#include <string.h>
-#include "../../../codeflinger/mips64_disassem.h"
-
-//typedef uint64_t db_addr_t;
-//db_addr_t mips_disassem(db_addr_t loc, char *di_buffer, int alt_format);
-
-struct test_table_entry_t
-{
-     uint32_t code;
-     const char *instr;
-};
-
-static test_table_entry_t test_table [] =
-{
-    { 0x00011020, "add\tv0,zero,at"     },
-    { 0x00832820, "add\ta1,a0,v1"       },
-    { 0x00c74020, "add\ta4,a2,a3"       },
-    { 0x012a5820, "add\ta7,a5,a6"       },
-    { 0x258dffff, "addiu\tt1,t0,-1"     },
-    { 0x25cf0004, "addiu\tt3,t2,4"      },
-    { 0x02119021, "addu\ts2,s0,s1"      },
-    { 0x0274a821, "addu\ts5,s3,s4"      },
-    { 0x02d7c024, "and\tt8,s6,s7"       },
-    { 0x333aff00, "andi\tk0,t9,0xff00"  },
-    { 0x3f7cffff, "aui\tgp,k1,-1"       },
-    { 0x3c1dffff, "lui\tsp,0xffff"      },
-    { 0x00e04051, "clo\ta4,a3"          },
-    { 0x01205050, "clz\ta6,a5"          },
-    { 0x016c682c, "dadd\tt1,a7,t0"      },
-    { 0x65cf0008, "daddiu\tt3,t2,8"     },
-    { 0x0211902d, "daddu\ts2,s0,s1"     },
-    { 0x7e741403, "dext\ts4,s3,16,3"    },
-    { 0x7eb6f801, "dextm\ts6,s5,0,64"   },
-    { 0x7ef87c02, "dextu\tt8,s7,48,16"  },
-    { 0x7f3a8207, "dins\tk0,t9,8,9"     },
-    { 0x7f7c0005, "dinsm\tgp,k1,0,33"   },
-    { 0x7fbe0806, "dinsu\ts8,sp,32,2"   },
-    { 0x03e1102e, "dsub\tv0,ra,at"      },
-    { 0x0064282f, "dsubu\ta1,v1,a0"     },
-    { 0x7cc77a00, "ext\ta3,a2,8,16"     },
-    { 0x7d09fc04, "ins\ta5,a4,16,16"    },
-    { 0x00200009, "jr\tat"              },
-    { 0x00201009, "jalr\tv0,at"         },
-    { 0x0020f809, "jalr\tat"            },
-    { 0x8082fff0, "lb\tv0,-16(a0)"      },
-    { 0x916c0008, "lbu\tt0,8(a7)"       },
-    { 0xdfa3ffe8, "ld\tv1,-24(sp)"      },
-    { 0x84850080, "lh\ta1,128(a0)"      },
-    { 0x94c7ff80, "lhu\ta3,-128(a2)"    },
-    { 0x8d09000c, "lw\ta5,12(a4)"       },
-    { 0x9d4bfff4, "lwu\ta7,-12(a6)"     },
-    { 0x00620898, "mul\tat,v1,v0"       },
-    { 0x006208d8, "muh\tat,v1,v0"       },
-    { 0x00620899, "mulu\tat,v1,v0"      },
-    { 0x006208d9, "muhu\tat,v1,v0"      },
-    { 0x00000000, "nop"                 },
-    { 0x02329827, "nor\ts3,s1,s2"       },
-    { 0x0295b025, "or\ts6,s4,s5"        },
-    { 0x36f0ff00, "ori\ts0,s7,0xff00"   },
-    { 0x7c03103b, "rdhwr\tv0,v1"        },
-    { 0x00242a02, "rotr\ta1,a0,8"       },
-    { 0x00c74046, "rotrv\ta4,a3,a2"     },
-    { 0xa12afff0, "sb\ta6,-16(a5)"      },
-    { 0xfd6c0100, "sd\tt0,256(a7)"      },
-    { 0x7c0d7420, "seb\tt2,t1"          },
-    { 0x7c0f8620, "seh\ts0,t3"          },
-    { 0x02329835, "seleqz\ts3,s1,s2"    },
-    { 0x0295b037, "selnez\ts6,s4,s5"    },
-    { 0xa6f84000, "sh\tt8,16384(s7)"    },
-    { 0x0019d100, "sll\tk0,t9,4"        },
-    { 0x037ce804, "sllv\tsp,gp,k1"      },
-    { 0x03df082a, "slt\tat,s8,ra"       },
-    { 0x28430007, "slti\tv1,v0,7"       },
-    { 0x2c850020, "sltiu\ta1,a0,32"     },
-    { 0x00c7402b, "sltu\ta4,a2,a3"      },
-    { 0x00095103, "sra\ta6,a5,4"        },
-    { 0x016c6807, "srav\tt1,t0,a7"      },
-    { 0x000e7a02, "srl\tt3,t2,8"        },
-    { 0x02119006, "srlv\ts2,s1,s0"      },
-    { 0x0274a822, "sub\ts5,s3,s4"       },
-    { 0x02d7c023, "subu\tt8,s6,s7"      },
-    { 0xaf3afffc, "sw\tk0,-4(t9)"       },
-    { 0x7c1be0a0, "wsbh\tgp,k1"         },
-    { 0x03bef826, "xor\tra,sp,s8"       },
-    { 0x3801ffff, "li\tat,0xffff"       },
-    { 0x3843ffff, "xori\tv1,v0,0xffff"  },
-};
-
-struct test_branches_table_entry_t
-{
-     uint32_t code;
-     const char *instr;
-     int16_t offset;
-};
-
-static test_branches_table_entry_t test_branches_table [] = {
-    { 0x1000ffff, "b\t", static_cast<int16_t>(0xffff)         },
-    { 0x13df0008, "beq\ts8,ra,", 0x8                          },
-    { 0x042100ff, "bgez\tat,", 0xff                           },
-    { 0x1c40ff00, "bgtz\tv0,", static_cast<int16_t>(0xff00)   },
-    { 0x18605555, "blez\tv1,", 0x5555                         },
-    { 0x0480aaaa, "bltz\ta0,", static_cast<int16_t>(0xaaaa)   },
-    { 0x14a68888, "bne\ta1,a2,", static_cast<int16_t>(0x8888) },
-};
-
-struct test_jump_table_entry_t
-{
-     uint32_t code;
-     const char *instr;
-     int32_t offset;
-};
-
-static test_jump_table_entry_t test_jump_table [] = {
-    { 0x0956ae66, "j\t", 0x156ae66          },
-    { 0x0d56ae66, "jal\t", 0x156ae66        },
-};
-
-int main()
-{
-    char instr[256];
-    uint32_t failed = 0;
-
-    for(uint32_t i = 0; i < sizeof(test_table)/sizeof(test_table_entry_t); ++i)
-    {
-        test_table_entry_t *test;
-        test = &test_table[i];
-        mips_disassem(&test->code, instr, 0);
-        if(strcmp(instr, test->instr) != 0)
-        {
-            printf("Test Failed \n"
-                   "Code     : 0x%0x\n"
-                   "Expected : %s\n"
-                   "Actual   : %s\n", test->code, test->instr, instr);
-            failed++;
-        }
-    }
-    for(uint32_t i = 0; i < sizeof(test_branches_table)/sizeof(test_branches_table_entry_t); ++i)
-    {
-        test_branches_table_entry_t *test;
-        test = &test_branches_table[i];
-        mips_disassem(&test->code, instr, 0);
-        //printf("DBG code address: %lx\n", (uint64_t)(&test->code));
-        uint64_t loc = (uint64_t)test + 4 + (test->offset << 2);
-        //printf("DBG loc: %lx\n", loc);
-        char temp[256], address[16];
-        strcpy(temp, test->instr);
-        sprintf(address, "0x%lx", loc);
-        strcat(temp, address);
-        if(strcmp(instr, temp) != 0)
-        {
-            printf("Test Failed \n"
-                   "Code     : 0x%0x\n"
-                   "Expected : %s\n"
-                   "Actual   : %s\n", test->code, temp, instr);
-            failed++;
-        }
-    }
-    for(uint32_t i = 0; i < sizeof(test_jump_table)/sizeof(test_jump_table_entry_t); ++i)
-    {
-        test_jump_table_entry_t *test;
-        test = &test_jump_table[i];
-        mips_disassem(&test->code, instr, 0);
-        //printf("DBG code address: %lx\n", (uint64_t)(&test->code));
-        uint64_t loc = ((uint64_t)test & 0xfffffffff0000000) | (test->offset << 2);
-        //printf("DBG loc: %lx\n", loc);
-        char temp[256], address[16];
-        strcpy(temp, test->instr);
-        sprintf(address, "0x%08lx", loc);
-        strcat(temp, address);
-        if(strcmp(instr, temp) != 0)
-        {
-            printf("Test Failed \n"
-                   "Code     : 0x%0x\n"
-                   "Expected : '%s'\n"
-                   "Actual   : '%s'\n", test->code, temp, instr);
-            failed++;
-        }
-    }
-    if(failed == 0)
-    {
-        printf("All tests PASSED\n");
-        return 0;
-    }
-    else
-    {
-        printf("%d tests FAILED\n", failed);
-        return -1;
-    }
-}
diff --git a/libstats/push_compat/Android.bp b/libstats/push_compat/Android.bp
index 465c05a..fcd8c83 100644
--- a/libstats/push_compat/Android.bp
+++ b/libstats/push_compat/Android.bp
@@ -35,6 +35,8 @@
     header_libs: ["libstatssocket_headers"],
     static_libs: [
         "libbase",
+    ],
+    shared_libs: [
         "liblog",
         "libutils",
     ],
diff --git a/rootdir/init.rc b/rootdir/init.rc
index fdc9d32..5ebffab 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -16,6 +16,11 @@
     # Disable sysrq from keyboard
     write /proc/sys/kernel/sysrq 0
 
+    # Android doesn't need kernel module autoloading, and it causes SELinux
+    # denials.  So disable it by setting modprobe to the empty string.  Note: to
+    # explicitly set a sysctl to an empty string, a trailing newline is needed.
+    write /proc/sys/kernel/modprobe \n
+
     # Set the security context of /adb_keys if present.
     restorecon /adb_keys