Snap for 6439596 from af8f6cf3aba3398b36117dd3acce6f5a3c0610c6 to qt-aml-tzdata-release

Change-Id: I853bc427c872c044202800e8bb558018278291ed
diff --git a/Android.bp b/Android.bp
index 9829c7f..de9ea86 100644
--- a/Android.bp
+++ b/Android.bp
@@ -7,7 +7,6 @@
 }
 
 subdirs = [
-    "adbd_auth",
     "cmds/*",
     "headers",
     "libs/*",
@@ -21,25 +20,3 @@
     vendor: true,
     export_include_dirs: ["include_sensor"],
 }
-
-filegroup {
-    name: "framework_native_aidl_binder",
-    srcs: ["aidl/binder/**/*.aidl"],
-    path: "aidl/binder",
-    visibility: ["//frameworks/native"],
-}
-
-filegroup {
-    name: "framework_native_aidl_gui",
-    srcs: ["aidl/gui/**/*.aidl"],
-    path: "aidl/gui",
-    visibility: ["//frameworks/native"],
-}
-
-filegroup {
-    name: "framework_native_aidl",
-    srcs: [
-        ":framework_native_aidl_binder",
-        ":framework_native_aidl_gui",
-    ],
-}
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 4f7cdf3..1a932c3 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -4,16 +4,13 @@
 [Builtin Hooks Options]
 # Only turn on clang-format check for the following subfolders.
 clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
-               include/input/
                libs/binder/ndk/
                libs/graphicsenv/
                libs/gui/
-               libs/input/
                libs/renderengine/
                libs/ui/
                libs/vr/
                services/bufferhub/
-               services/inputflinger/
                services/surfaceflinger/
                services/vr/
 
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index e7d0ad0..cc2a6f7 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -10,7 +10,9 @@
 
     shared_libs: [
         "libbinder",
+        "libhwbinder",
         "libhidlbase",
+        "libhidltransport",
         "liblog",
         "libutils",
         "libcutils",
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 5186ad3..1429bc8 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -1468,11 +1468,10 @@
 
     // Reset the trace buffer size to 1.
     if (traceStop) {
+        cleanUpVendorTracing();
         cleanUpUserspaceTracing();
-        if (!onlyUserspace) {
-            cleanUpVendorTracing();
+        if (!onlyUserspace)
             cleanUpKernelTracing();
-        }
     }
 
     return g_traceAborted ? 1 : 0;
diff --git a/cmds/bugreport/bugreport.cpp b/cmds/bugreport/bugreport.cpp
index 840ae47..917c813 100644
--- a/cmds/bugreport/bugreport.cpp
+++ b/cmds/bugreport/bugreport.cpp
@@ -37,7 +37,7 @@
   property_set("ctl.start", "dumpstate");
 
   // Socket will not be available until service starts.
-  int s = -1;
+  int s;
   for (int i = 0; i < 20; i++) {
     s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED,
                             SOCK_STREAM);
diff --git a/cmds/bugreportz/main.cpp b/cmds/bugreportz/main.cpp
index 40346be..74a95b0 100644
--- a/cmds/bugreportz/main.cpp
+++ b/cmds/bugreportz/main.cpp
@@ -72,7 +72,7 @@
     property_set("ctl.start", "dumpstatez");
 
     // Socket will not be available until service starts.
-    int s = -1;
+    int s;
     for (int i = 0; i < 20; i++) {
         s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
         if (s >= 0) break;
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 09aee89..ee32cb4 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -86,13 +86,15 @@
         "libdumpstateaidl",
         "libdumpstateutil",
         "libdumputils",
-        "libhardware_legacy",
         "libhidlbase",
+        "libhidltransport",
         "liblog",
         "libutils",
     ],
     srcs: [
+        "DumpstateSectionReporter.cpp",
         "DumpstateService.cpp",
+        "utils.cpp",
     ],
     static_libs: [
         "libincidentcompanion",
@@ -118,11 +120,10 @@
         "kill",
         "librank",
         "logcat",
-        "lpdump",
-        "lpdumpd",
         "lsmod",
         "lsof",
         "netstat",
+        "parse_radio_log",
         "printenv",
         "procrank",
         "screencap",
@@ -145,12 +146,6 @@
         "tests/dumpstate_test.cpp",
     ],
     static_libs: ["libgmock"],
-    test_config: "dumpstate_test.xml",
-    data: [
-        ":dumpstate_test_fixture",
-        "tests/testdata/**/*",
-    ],
-    test_suites: ["device-tests"],
 }
 
 cc_test {
diff --git a/cmds/dumpstate/DumpstateInternal.cpp b/cmds/dumpstate/DumpstateInternal.cpp
index bbc724c..33e35f7 100644
--- a/cmds/dumpstate/DumpstateInternal.cpp
+++ b/cmds/dumpstate/DumpstateInternal.cpp
@@ -68,8 +68,7 @@
     }
 
     static const std::vector<std::string> group_names{
-        "log", "sdcard_r", "sdcard_rw", "mount", "inet", "net_bw_stats",
-            "readproc", "bluetooth", "wakelock"};
+        "log", "sdcard_r", "sdcard_rw", "mount", "inet", "net_bw_stats", "readproc", "bluetooth"};
     std::vector<gid_t> groups(group_names.size(), 0);
     for (size_t i = 0; i < group_names.size(); ++i) {
         grp = getgrnam(group_names[i].c_str());
@@ -117,11 +116,6 @@
         capdata[cap_syslog_index].effective |= cap_syslog_mask;
     }
 
-    const uint32_t cap_block_suspend_mask = CAP_TO_MASK(CAP_BLOCK_SUSPEND);
-    const uint32_t cap_block_suspend_index = CAP_TO_INDEX(CAP_BLOCK_SUSPEND);
-    capdata[cap_block_suspend_index].permitted |= cap_block_suspend_mask;
-    capdata[cap_block_suspend_index].effective |= cap_block_suspend_mask;
-
     if (capset(&capheader, &capdata[0]) != 0) {
         MYLOGE("capset({%#x, %#x}) failed: %s\n", capdata[0].effective,
                capdata[1].effective, strerror(errno));
diff --git a/cmds/dumpstate/DumpstateSectionReporter.cpp b/cmds/dumpstate/DumpstateSectionReporter.cpp
new file mode 100644
index 0000000..f814bde
--- /dev/null
+++ b/cmds/dumpstate/DumpstateSectionReporter.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "dumpstate"
+
+#include "DumpstateSectionReporter.h"
+
+namespace android {
+namespace os {
+namespace dumpstate {
+
+DumpstateSectionReporter::DumpstateSectionReporter(const std::string& title,
+                                                   sp<android::os::IDumpstateListener> listener,
+                                                   bool sendReport)
+    : title_(title), listener_(listener), sendReport_(sendReport), status_(OK), size_(-1) {
+    started_ = std::chrono::steady_clock::now();
+}
+
+DumpstateSectionReporter::~DumpstateSectionReporter() {
+    if ((listener_ != nullptr) && (sendReport_)) {
+        auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
+            std::chrono::steady_clock::now() - started_);
+        listener_->onSectionComplete(title_, status_, size_, (int32_t)elapsed.count());
+    }
+}
+
+}  // namespace dumpstate
+}  // namespace os
+}  // namespace android
diff --git a/cmds/dumpstate/DumpstateSectionReporter.h b/cmds/dumpstate/DumpstateSectionReporter.h
new file mode 100644
index 0000000..e971de8
--- /dev/null
+++ b/cmds/dumpstate/DumpstateSectionReporter.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_OS_DUMPSTATESECTIONREPORTER_H_
+#define ANDROID_OS_DUMPSTATESECTIONREPORTER_H_
+
+#include <android/os/IDumpstateListener.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace os {
+namespace dumpstate {
+
+
+/*
+ * Helper class used to report per section details to a listener.
+ *
+ * Typical usage:
+ *
+ *    DumpstateSectionReporter sectionReporter(title, listener, sendReport);
+ *    sectionReporter.setSize(5000);
+ *
+ */
+class DumpstateSectionReporter {
+  public:
+    DumpstateSectionReporter(const std::string& title, sp<android::os::IDumpstateListener> listener,
+                             bool sendReport);
+
+    ~DumpstateSectionReporter();
+
+    void setStatus(status_t status) {
+        status_ = status;
+    }
+
+    void setSize(int size) {
+        size_ = size;
+    }
+
+  private:
+    std::string title_;
+    android::sp<android::os::IDumpstateListener> listener_;
+    bool sendReport_;
+    status_t status_;
+    int size_;
+    std::chrono::time_point<std::chrono::steady_clock> started_;
+};
+
+}  // namespace dumpstate
+}  // namespace os
+}  // namespace android
+
+#endif  // ANDROID_OS_DUMPSTATESECTIONREPORTER_H_
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index f98df99..ddae9ea 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -151,15 +151,15 @@
         signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
     }
 
-    std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
-    options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_fd,
-                        screenshot_fd);
-
-    if (bugreport_fd.get() == -1 || (options->do_fb && screenshot_fd.get() == -1)) {
+    if (bugreport_fd.get() == -1 || screenshot_fd.get() == -1) {
+        // TODO(b/111441001): screenshot fd should be optional
         MYLOGE("Invalid filedescriptor");
         signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
     }
 
+    std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
+    options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_fd,
+                        screenshot_fd);
 
     ds_ = &(Dumpstate::GetInstance());
     ds_->SetOptions(std::move(options));
@@ -200,7 +200,8 @@
     dprintf(fd, "id: %d\n", ds_->id_);
     dprintf(fd, "pid: %d\n", ds_->pid_);
     dprintf(fd, "update_progress: %s\n", ds_->options_->do_progress_updates ? "true" : "false");
-    dprintf(fd, "last_percent_progress: %d\n", ds_->last_reported_percent_progress_);
+    dprintf(fd, "update_progress_threshold: %d\n", ds_->update_progress_threshold_);
+    dprintf(fd, "last_updated_progress: %d\n", ds_->last_updated_progress_);
     dprintf(fd, "progress:\n");
     ds_->progress_->Dump(fd, "  ");
     dprintf(fd, "args: %s\n", ds_->options_->args.c_str());
diff --git a/cmds/dumpstate/DumpstateUtil.cpp b/cmds/dumpstate/DumpstateUtil.cpp
index 4b69607..97c8ae2 100644
--- a/cmds/dumpstate/DumpstateUtil.cpp
+++ b/cmds/dumpstate/DumpstateUtil.cpp
@@ -378,6 +378,34 @@
     return status;
 }
 
+int GetPidByName(const std::string& ps_name) {
+    DIR* proc_dir;
+    struct dirent* ps;
+    unsigned int pid;
+    std::string cmdline;
+
+    if (!(proc_dir = opendir("/proc"))) {
+        MYLOGE("Can't open /proc\n");
+        return -1;
+    }
+
+    while ((ps = readdir(proc_dir))) {
+        if (!(pid = atoi(ps->d_name))) {
+            continue;
+        }
+        android::base::ReadFileToString("/proc/" + std::string(ps->d_name) + "/cmdline", &cmdline);
+        if (cmdline.find(ps_name) == std::string::npos) {
+            continue;
+        } else {
+            closedir(proc_dir);
+            return pid;
+        }
+    }
+    MYLOGE("can't find the pid\n");
+    closedir(proc_dir);
+    return -1;
+}
+
 }  // namespace dumpstate
 }  // namespace os
 }  // namespace android
diff --git a/cmds/dumpstate/DumpstateUtil.h b/cmds/dumpstate/DumpstateUtil.h
index b7ac25c..d75b08c 100644
--- a/cmds/dumpstate/DumpstateUtil.h
+++ b/cmds/dumpstate/DumpstateUtil.h
@@ -205,6 +205,12 @@
  */
 int DumpFileToFd(int fd, const std::string& title, const std::string& path);
 
+/*
+ * Finds the process id by process name.
+ * |ps_name| the process name we want to search for
+ */
+int GetPidByName(const std::string& ps_name);
+
 }  // namespace dumpstate
 }  // namespace os
 }  // namespace android
diff --git a/cmds/dumpstate/TEST_MAPPING b/cmds/dumpstate/TEST_MAPPING
deleted file mode 100644
index 083944f..0000000
--- a/cmds/dumpstate/TEST_MAPPING
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "presubmit": [
-    {
-      "name": "dumpstate_test"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index cb2d8b8..347856d 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -73,7 +73,7 @@
      * @param callingUid UID of the original application that requested the report.
      * @param callingPackage package of the original application that requested the report.
      * @param bugreportFd the file to which the zipped bugreport should be written
-     * @param screenshotFd the file to which screenshot should be written
+     * @param screenshotFd the file to which screenshot should be written; optional
      * @param bugreportMode the mode that specifies other run time options; must be one of above
      * @param listener callback for updates; optional
      */
diff --git a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
index e486460..ea1e467 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
@@ -61,4 +61,21 @@
      * Called when taking bugreport finishes successfully.
      */
     void onFinished();
+
+    // TODO(b/111441001): Remove old methods when not used anymore.
+    void onProgressUpdated(int progress);
+    void onMaxProgressUpdated(int maxProgress);
+
+    /**
+     * Called after every section is complete.
+     *
+     * @param  name          section name
+     * @param  status        values from status_t
+     *                       {@code OK} section completed successfully
+     *                       {@code TIMEOUT} dump timed out
+     *                       {@code != OK} error
+     * @param  size          size in bytes, may be invalid if status != OK
+     * @param  durationMs    duration in ms
+     */
+    void onSectionComplete(@utf8InCpp String name, int status, int size, int durationMs);
 }
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index c5bfb42..5de4077 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -22,8 +22,6 @@
 #include <inttypes.h>
 #include <libgen.h>
 #include <limits.h>
-#include <math.h>
-#include <poll.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -34,22 +32,13 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/wait.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <string.h>
-#include <sys/capability.h>
-#include <sys/inotify.h>
-#include <sys/klog.h>
-#include <time.h>
 #include <unistd.h>
 
 #include <chrono>
-#include <cmath>
 #include <fstream>
 #include <functional>
 #include <future>
 #include <memory>
-#include <numeric>
 #include <regex>
 #include <set>
 #include <string>
@@ -69,19 +58,17 @@
 #include <binder/IServiceManager.h>
 #include <cutils/native_handle.h>
 #include <cutils/properties.h>
-#include <cutils/sockets.h>
 #include <debuggerd/client.h>
 #include <dumpsys.h>
 #include <dumputils/dump_utils.h>
-#include <hardware_legacy/power.h>
 #include <hidl/ServiceManagement.h>
-#include <log/log.h>
 #include <openssl/sha.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
 #include <serviceutils/PriorityDumper.h>
 #include <utils/StrongPointer.h>
 #include "DumpstateInternal.h"
+#include "DumpstateSectionReporter.h"
 #include "DumpstateService.h"
 #include "dumpstate.h"
 
@@ -106,29 +93,10 @@
 using android::os::IDumpstateListener;
 using android::os::dumpstate::CommandOptions;
 using android::os::dumpstate::DumpFileToFd;
+using android::os::dumpstate::DumpstateSectionReporter;
+using android::os::dumpstate::GetPidByName;
 using android::os::dumpstate::PropertiesHelper;
 
-// Keep in sync with
-// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
-static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
-
-/* Most simple commands have 10 as timeout, so 5 is a good estimate */
-static const int32_t WEIGHT_FILE = 5;
-
-// TODO: temporary variables and functions used during C++ refactoring
-static Dumpstate& ds = Dumpstate::GetInstance();
-static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
-                      const CommandOptions& options = CommandOptions::DEFAULT,
-                      bool verbose_duration = false) {
-    return ds.RunCommand(title, full_command, options, verbose_duration);
-}
-
-// Reasonable value for max stats.
-static const int STATS_MAX_N_RUNS = 1000;
-static const long STATS_MAX_AVERAGE = 100000;
-
-CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
-
 typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
 
 /* read before root is shed */
@@ -154,7 +122,6 @@
 #define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
 #define WLUTIL "/vendor/xbin/wlutil"
 #define WMTRACE_DATA_DIR "/data/misc/wmtrace"
-#define OTA_METADATA_DIR "/metadata/ota"
 
 // TODO(narayan): Since this information has to be kept in sync
 // with tombstoned, we should just put it in a common header.
@@ -166,6 +133,7 @@
 static const std::string ANR_FILE_PREFIX = "anr_";
 
 // TODO: temporary variables and functions used during C++ refactoring
+static Dumpstate& ds = Dumpstate::GetInstance();
 
 #define RETURN_IF_USER_DENIED_CONSENT()                                                        \
     if (ds.IsUserConsentDenied()) {                                                            \
@@ -180,8 +148,6 @@
     func_ptr(__VA_ARGS__);                                  \
     RETURN_IF_USER_DENIED_CONSENT();
 
-static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
-
 namespace android {
 namespace os {
 namespace {
@@ -254,7 +220,7 @@
         MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
         return 0L;
     }
-    MYLOGD("Module metadata package name: %s\n", package_name.c_str());
+    MYLOGD("Module metadata package name: %s", package_name.c_str());
     int64_t version_code;
     status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
                                                        &version_code);
@@ -269,6 +235,10 @@
 }  // namespace os
 }  // namespace android
 
+static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
+                      const CommandOptions& options = CommandOptions::DEFAULT) {
+    return ds.RunCommand(title, fullCommand, options);
+}
 static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
                        const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
                        long dumpsysTimeoutMs = 0) {
@@ -301,10 +271,12 @@
  * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
  * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
  * is set, the vector only contains files that were written in the last 30 minutes.
+ * If |limit_by_count| is set, the vector only contains the ten latest files.
  */
 static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
                                         const std::string& file_prefix,
-                                        bool limit_by_mtime) {
+                                        bool limit_by_mtime,
+                                        bool limit_by_count = true) {
     const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
 
     std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
@@ -348,6 +320,15 @@
         dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
     }
 
+    // Sort in descending modification time so that we only keep the newest
+    // reports if |limit_by_count| is true.
+    std::sort(dump_data.begin(), dump_data.end(),
+              [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; });
+
+    if (limit_by_count && dump_data.size() > 10) {
+        dump_data.erase(dump_data.begin() + 10, dump_data.end());
+    }
+
     return dump_data;
 }
 
@@ -440,6 +421,108 @@
     closedir(d);
 }
 
+
+
+// dump anrd's trace and add to the zip file.
+// 1. check if anrd is running on this device.
+// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
+// 3. wait until the trace generation completes and add to the zip file.
+static bool dump_anrd_trace() {
+    unsigned int pid;
+    char buf[50], path[PATH_MAX];
+    struct dirent *trace;
+    struct stat st;
+    DIR *trace_dir;
+    int retry = 5;
+    long max_ctime = 0, old_mtime;
+    long long cur_size = 0;
+    const char *trace_path = "/data/misc/anrd/";
+
+    if (!ds.IsZipping()) {
+        MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
+        return false;
+    }
+
+    // find anrd's pid if it is running.
+    pid = GetPidByName("/system/bin/anrd");
+
+    if (pid > 0) {
+        if (stat(trace_path, &st) == 0) {
+            old_mtime = st.st_mtime;
+        } else {
+            MYLOGE("Failed to find: %s\n", trace_path);
+            return false;
+        }
+
+        // send SIGUSR1 to the anrd to generate a trace.
+        sprintf(buf, "%u", pid);
+        if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
+                       CommandOptions::WithTimeout(1).Build())) {
+            MYLOGE("anrd signal timed out. Please manually collect trace\n");
+            return false;
+        }
+
+        while (retry-- > 0 && old_mtime == st.st_mtime) {
+            sleep(1);
+            stat(trace_path, &st);
+        }
+
+        if (retry < 0 && old_mtime == st.st_mtime) {
+            MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
+            return false;
+        }
+
+        // identify the trace file by its creation time.
+        if (!(trace_dir = opendir(trace_path))) {
+            MYLOGE("Can't open trace file under %s\n", trace_path);
+        }
+        while ((trace = readdir(trace_dir))) {
+            if (strcmp(trace->d_name, ".") == 0
+                    || strcmp(trace->d_name, "..") == 0) {
+                continue;
+            }
+            sprintf(path, "%s%s", trace_path, trace->d_name);
+            if (stat(path, &st) == 0) {
+                if (st.st_ctime > max_ctime) {
+                    max_ctime = st.st_ctime;
+                    sprintf(buf, "%s", trace->d_name);
+                }
+            }
+        }
+        closedir(trace_dir);
+
+        // Wait until the dump completes by checking the size of the trace.
+        if (max_ctime > 0) {
+            sprintf(path, "%s%s", trace_path, buf);
+            while(true) {
+                sleep(1);
+                if (stat(path, &st) == 0) {
+                    if (st.st_size == cur_size) {
+                        break;
+                    } else if (st.st_size > cur_size) {
+                        cur_size = st.st_size;
+                    } else {
+                        return false;
+                    }
+                } else {
+                    MYLOGE("Cant stat() %s anymore\n", path);
+                    return false;
+                }
+            }
+            // Add to the zip file.
+            if (!ds.AddZipEntry("anrd_trace.txt", path)) {
+                MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
+            } else {
+                android::os::UnlinkAndLogOnError(path);
+                return true;
+            }
+        } else {
+            MYLOGE("Can't stats any trace file under %s\n", trace_path);
+        }
+    }
+    return false;
+}
+
 static bool skip_not_stat(const char *path) {
     static const char stat[] = "/stat";
     size_t len = strlen(path);
@@ -877,17 +960,6 @@
         CommandOptions::WithTimeoutInMs(timeout_ms).Build());
 }
 
-static void DoSystemLogcat(time_t since) {
-    char since_str[80];
-    strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
-
-    unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
-    RunCommand("SYSTEM LOG",
-               {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
-                since_str},
-               CommandOptions::WithTimeoutInMs(timeout_ms).Build());
-}
-
 static void DoLogcat() {
     unsigned long timeout_ms;
     // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
@@ -900,17 +972,17 @@
     RunCommand(
         "EVENT LOG",
         {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
-        CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
+        CommandOptions::WithTimeoutInMs(timeout_ms).Build());
     timeout_ms = logcat_timeout({"stats"});
     RunCommand(
         "STATS LOG",
         {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
-        CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
+        CommandOptions::WithTimeoutInMs(timeout_ms).Build());
     timeout_ms = logcat_timeout({"radio"});
     RunCommand(
         "RADIO LOG",
         {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
-        CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
+        CommandOptions::WithTimeoutInMs(timeout_ms).Build());
 
     RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
 
@@ -919,31 +991,6 @@
                                "-v", "uid", "-d", "*:v"});
 }
 
-static void DumpIncidentReport() {
-    if (!ds.IsZipping()) {
-        MYLOGD("Not dumping incident report because it's not a zipped bugreport\n");
-        return;
-    }
-    DurationReporter duration_reporter("INCIDENT REPORT");
-    const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
-    auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
-                O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
-                S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
-    if (fd < 0) {
-        MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
-        return;
-    }
-    RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(120).Build());
-    bool empty = 0 == lseek(fd, 0, SEEK_END);
-    if (!empty) {
-        // Use a different name from "incident.proto"
-        // /proto/incident.proto is reserved for incident service dump
-        // i.e. metadata for debugging.
-        ds.AddZipEntry(kProtoPath + "incident_report" + kProtoExt, path);
-    }
-    unlink(path.c_str());
-}
-
 static void DumpIpTablesAsRoot() {
     RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
     RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
@@ -955,15 +1002,6 @@
     RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
 }
 
-static void DumpDynamicPartitionInfo() {
-    if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
-        return;
-    }
-
-    RunCommand("LPDUMP", {"lpdump", "--all"});
-    RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
-}
-
 static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
     MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
            anr_traces_dir.c_str());
@@ -1083,17 +1121,20 @@
         RETURN_IF_USER_DENIED_CONSENT();
         std::string path(title);
         path.append(" - ").append(String8(service).c_str());
+        DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
         size_t bytes_written = 0;
-        status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
+        status_t status = dumpsys.startDumpThread(service, args);
         if (status == OK) {
             dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
             std::chrono::duration<double> elapsed_seconds;
             status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
                                        /* as_proto = */ false, elapsed_seconds, bytes_written);
+            section_reporter.setSize(bytes_written);
             dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
             bool dump_complete = (status == OK);
             dumpsys.stopDumpThread(dump_complete);
         }
+        section_reporter.setStatus(status);
 
         auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
             std::chrono::steady_clock::now() - start);
@@ -1156,7 +1197,8 @@
             path.append("_HIGH");
         }
         path.append(kProtoExt);
-        status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
+        DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
+        status_t status = dumpsys.startDumpThread(service, args);
         if (status == OK) {
             status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
             bool dumpTerminated = (status == OK);
@@ -1164,6 +1206,8 @@
         }
         ZipWriter::FileEntry file_entry;
         ds.zip_writer_->GetLastEntry(&file_entry);
+        section_reporter.setSize(file_entry.compressed_size);
+        section_reporter.setStatus(status);
 
         auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
             std::chrono::steady_clock::now() - start);
@@ -1270,45 +1314,6 @@
     }
 }
 
-static void DumpExternalFragmentationInfo() {
-    struct stat st;
-    if (stat("/proc/buddyinfo", &st) != 0) {
-        MYLOGE("Unable to dump external fragmentation info\n");
-        return;
-    }
-
-    printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
-    std::ifstream ifs("/proc/buddyinfo");
-    auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
-    for (std::string line; std::getline(ifs, line);) {
-        std::smatch match_results;
-        if (std::regex_match(line, match_results, unusable_index_regex)) {
-            std::stringstream free_pages(std::string{match_results[3]});
-            std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
-                                                  std::istream_iterator<int>());
-
-            int total_free_pages = 0;
-            for (size_t i = 0; i < free_pages_per_order.size(); i++) {
-                total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
-            }
-
-            printf("Node %s, zone %8s", match_results[1].str().c_str(),
-                   match_results[2].str().c_str());
-
-            int usable_free_pages = total_free_pages;
-            for (size_t i = 0; i < free_pages_per_order.size(); i++) {
-                auto unusable_index = (total_free_pages - usable_free_pages) /
-                        static_cast<double>(total_free_pages);
-                printf(" %5.3f", unusable_index);
-                usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
-            }
-
-            printf("\n");
-        }
-    }
-    printf("\n");
-}
-
 // Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
 // via the consent they are shown. Ignores other errors that occur while running various
 // commands. The consent checking is currently done around long running tasks, which happen to
@@ -1322,6 +1327,7 @@
     dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
     RunCommand("UPTIME", {"uptime"});
     DumpBlockStatFiles();
+    dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
     DumpFile("MEMORY INFO", "/proc/meminfo");
     RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
                             "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
@@ -1334,10 +1340,11 @@
     DumpFile("ZONEINFO", "/proc/zoneinfo");
     DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
     DumpFile("BUDDYINFO", "/proc/buddyinfo");
-    DumpExternalFragmentationInfo();
+    DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
 
     DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
     DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
+    DumpFile("KERNEL SYNC", "/d/sync");
 
     RunCommand("PROCESSES AND THREADS",
                {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
@@ -1373,11 +1380,13 @@
     /* Dump Bluetooth HCI logs */
     ds.AddDir("/data/misc/bluetooth/logs", true);
 
-    if (ds.options_->do_fb && !ds.do_early_screenshot_) {
+    if (!ds.do_early_screenshot_) {
         MYLOGI("taking late screenshot\n");
         ds.TakeScreenshot();
     }
 
+    DoLogcat();
+
     AddAnrTraceFiles();
 
     // NOTE: tombstones are always added as separate entries in the zip archive
@@ -1410,6 +1419,8 @@
 
     RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
 
+    RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
+
     /* Binder state is expensive to look at as it uses a lot of memory. */
     DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
     DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
@@ -1417,6 +1428,7 @@
     DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
     DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
 
+    RunDumpsys("WINSCOPE TRACE", {"window", "trace"});
     /* Add window and surface trace files. */
     if (!PropertiesHelper::IsUserBuild()) {
         ds.AddDir(WMTRACE_DATA_DIR, false);
@@ -1515,9 +1527,6 @@
     printf("========================================================\n");
     // This differs from the usual dumpsys stats, which is the stats report data.
     RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
-
-    RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpIncidentReport);
-
     return Dumpstate::RunStatus::OK;
 }
 
@@ -1530,16 +1539,13 @@
  * with the caller.
  */
 static Dumpstate::RunStatus DumpstateDefault() {
+    // Try to dump anrd trace if the daemon is running.
+    dump_anrd_trace();
+
     // Invoking the following dumpsys calls before DumpTraces() to try and
     // keep the system stats as close to its initial state as possible.
     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysCritical);
 
-    // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
-    // buffer.
-    DoLogcat();
-    // Capture timestamp after first logcat to use in next logcat
-    time_t logcat_ts = time(nullptr);
-
     /* collect stack traces from Dalvik and native processes (needs root) */
     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpTraces, &dump_traces_path);
 
@@ -1557,8 +1563,6 @@
     }
     add_mountinfo();
     DumpIpTablesAsRoot();
-    DumpDynamicPartitionInfo();
-    ds.AddDir(OTA_METADATA_DIR, true);
 
     // Capture any IPSec policies in play. No keys are exposed here.
     RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
@@ -1578,19 +1582,12 @@
         RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
     }
 
-    DumpFile("PSI cpu", "/proc/pressure/cpu");
-    DumpFile("PSI memory", "/proc/pressure/memory");
-    DumpFile("PSI io", "/proc/pressure/io");
-
     if (!DropRootUser()) {
         return Dumpstate::RunStatus::ERROR;
     }
 
     RETURN_IF_USER_DENIED_CONSENT();
-    Dumpstate::RunStatus status = dumpstate();
-    // Capture logcat since the last time we did it.
-    DoSystemLogcat(logcat_ts);
-    return status;
+    return dumpstate();
 }
 
 // This method collects common dumpsys for telephony and wifi
@@ -1907,21 +1904,22 @@
 
 static void ShowUsage() {
     fprintf(stderr,
-            "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-d] [-p] "
+            "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
             "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
             "  -h: display this help message\n"
             "  -b: play sound file instead of vibrate, at beginning of job\n"
             "  -e: play sound file instead of vibrate, at end of job\n"
-            "  -d: append date to filename\n"
-            "  -p: capture screenshot to filename.png\n"
-            "  -z: generate zipped file\n"
+            "  -o: write to file (instead of stdout)\n"
+            "  -d: append date to filename (requires -o)\n"
+            "  -p: capture screenshot to filename.png (requires -o)\n"
+            "  -z: generate zipped file (requires -o)\n"
             "  -s: write output to control socket (for init)\n"
-            "  -S: write file location to control socket (for init; requires -z)\n"
+            "  -S: write file location to control socket (for init; requires -o and -z)\n"
             "  -q: disable vibrate\n"
-            "  -B: send broadcast when finished\n"
+            "  -B: send broadcast when finished (requires -o)\n"
             "  -P: send broadcast when started and update system properties on "
-            "progress (requires -B)\n"
-            "  -R: take bugreport in remote mode (requires -z, -d and -B, "
+            "progress (requires -o and -B)\n"
+            "  -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
             "shouldn't be used with -P)\n"
             "  -w: start binder service and make it wait for a call to startBugreport\n"
             "  -v: prints the dumpstate header and exit\n");
@@ -2033,7 +2031,7 @@
 
 static void Vibrate(int duration_ms) {
     // clang-format off
-    RunCommand("", {"cmd", "vibrator", "vibrate", "-f", std::to_string(duration_ms), "dumpstate"},
+    RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
                CommandOptions::WithTimeout(10)
                    .Log("Vibrate: '%s'\n")
                    .Always()
@@ -2405,6 +2403,7 @@
         }
     }
 
+    // TODO: use helper function to convert argv into a string
     for (int i = 0; i < argc; i++) {
         args += argv[i];
         if (i < argc - 1) {
@@ -2555,13 +2554,6 @@
 
     MYLOGI("begin\n");
 
-    if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
-        MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
-    } else {
-        // Wake lock will be released automatically on process death
-        MYLOGD("Wake lock acquired.\n");
-    }
-
     register_sig_handler();
 
     // TODO(b/111441001): maybe skip if already started?
@@ -2635,8 +2627,13 @@
     }
 
     if (options_->do_fb && do_early_screenshot_) {
-        MYLOGI("taking early screenshot\n");
-        TakeScreenshot();
+        if (screenshot_path_.empty()) {
+            // should not have happened
+            MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
+        } else {
+            MYLOGI("taking early screenshot\n");
+            TakeScreenshot();
+        }
     }
 
     if (options_->do_zip_file && zip_file != nullptr) {
@@ -2692,7 +2689,7 @@
         // Dump state for the default case. This also drops root.
         RunStatus s = DumpstateDefault();
         if (s != RunStatus::OK) {
-            if (s == RunStatus::USER_CONSENT_DENIED) {
+            if (s == RunStatus::USER_CONSENT_TIMED_OUT) {
                 HandleUserConsentDenied();
             }
             return s;
@@ -2888,833 +2885,3 @@
             exit(2);
     }
 }
-
-// TODO(111441001): Default DumpOptions to sensible values.
-Dumpstate::Dumpstate(const std::string& version)
-    : pid_(getpid()),
-      options_(new Dumpstate::DumpOptions()),
-      last_reported_percent_progress_(0),
-      version_(version),
-      now_(time(nullptr)) {
-}
-
-Dumpstate& Dumpstate::GetInstance() {
-    static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
-    return singleton_;
-}
-
-DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose)
-    : title_(title), logcat_only_(logcat_only), verbose_(verbose) {
-    if (!title_.empty()) {
-        started_ = Nanotime();
-    }
-}
-
-DurationReporter::~DurationReporter() {
-    if (!title_.empty()) {
-        float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
-        if (elapsed < .5f && !verbose_) {
-            return;
-        }
-        MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
-        if (logcat_only_) {
-            return;
-        }
-        // Use "Yoda grammar" to make it easier to grep|sort sections.
-        printf("------ %.3fs was the duration of '%s' ------\n", elapsed, title_.c_str());
-    }
-}
-
-const int32_t Progress::kDefaultMax = 5000;
-
-Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
-}
-
-Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
-    : Progress(initial_max, growth_factor, "") {
-    progress_ = progress;
-}
-
-Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
-    : initial_max_(initial_max),
-      progress_(0),
-      max_(initial_max),
-      growth_factor_(growth_factor),
-      n_runs_(0),
-      average_max_(0),
-      path_(path) {
-    if (!path_.empty()) {
-        Load();
-    }
-}
-
-void Progress::Load() {
-    MYLOGD("Loading stats from %s\n", path_.c_str());
-    std::string content;
-    if (!android::base::ReadFileToString(path_, &content)) {
-        MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
-        return;
-    }
-    if (content.empty()) {
-        MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
-        return;
-    }
-    std::vector<std::string> lines = android::base::Split(content, "\n");
-
-    if (lines.size() < 1) {
-        MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
-               (int)lines.size(), max_);
-        return;
-    }
-    char* ptr;
-    n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
-    average_max_ = strtol(ptr, nullptr, 10);
-    if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
-        average_max_ > STATS_MAX_AVERAGE) {
-        MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
-        initial_max_ = Progress::kDefaultMax;
-    } else {
-        initial_max_ = average_max_;
-    }
-    max_ = initial_max_;
-
-    MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
-}
-
-void Progress::Save() {
-    int32_t total = n_runs_ * average_max_ + progress_;
-    int32_t runs = n_runs_ + 1;
-    int32_t average = floor(((float)total) / runs);
-    MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
-           path_.c_str());
-    if (path_.empty()) {
-        return;
-    }
-
-    std::string content = android::base::StringPrintf("%d %d\n", runs, average);
-    if (!android::base::WriteStringToFile(content, path_)) {
-        MYLOGE("Could not save stats on %s\n", path_.c_str());
-    }
-}
-
-int32_t Progress::Get() const {
-    return progress_;
-}
-
-bool Progress::Inc(int32_t delta_sec) {
-    bool changed = false;
-    if (delta_sec >= 0) {
-        progress_ += delta_sec;
-        if (progress_ > max_) {
-            int32_t old_max = max_;
-            max_ = floor((float)progress_ * growth_factor_);
-            MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
-            changed = true;
-        }
-    }
-    return changed;
-}
-
-int32_t Progress::GetMax() const {
-    return max_;
-}
-
-int32_t Progress::GetInitialMax() const {
-    return initial_max_;
-}
-
-void Progress::Dump(int fd, const std::string& prefix) const {
-    const char* pr = prefix.c_str();
-    dprintf(fd, "%sprogress: %d\n", pr, progress_);
-    dprintf(fd, "%smax: %d\n", pr, max_);
-    dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
-    dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
-    dprintf(fd, "%spath: %s\n", pr, path_.c_str());
-    dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
-    dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
-}
-
-bool Dumpstate::IsZipping() const {
-    return zip_writer_ != nullptr;
-}
-
-std::string Dumpstate::GetPath(const std::string& suffix) const {
-    return GetPath(bugreport_internal_dir_, suffix);
-}
-
-std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
-    return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
-                                       name_.c_str(), suffix.c_str());
-}
-
-void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
-    progress_ = std::move(progress);
-}
-
-void for_each_userid(void (*func)(int), const char *header) {
-    std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
-                                                                    "for_each_userid(%s)", header);
-    DurationReporter duration_reporter(title);
-    if (PropertiesHelper::IsDryRun()) return;
-
-    DIR *d;
-    struct dirent *de;
-
-    if (header) printf("\n------ %s ------\n", header);
-    func(0);
-
-    if (!(d = opendir("/data/system/users"))) {
-        printf("Failed to open /data/system/users (%s)\n", strerror(errno));
-        return;
-    }
-
-    while ((de = readdir(d))) {
-        int userid;
-        if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
-            continue;
-        }
-        func(userid);
-    }
-
-    closedir(d);
-}
-
-static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
-    DIR *d;
-    struct dirent *de;
-
-    if (!(d = opendir("/proc"))) {
-        printf("Failed to open /proc (%s)\n", strerror(errno));
-        return;
-    }
-
-    if (header) printf("\n------ %s ------\n", header);
-    while ((de = readdir(d))) {
-        if (ds.IsUserConsentDenied()) {
-            MYLOGE(
-                "Returning early because user denied consent to share bugreport with calling app.");
-            closedir(d);
-            return;
-        }
-        int pid;
-        int fd;
-        char cmdpath[255];
-        char cmdline[255];
-
-        if (!(pid = atoi(de->d_name))) {
-            continue;
-        }
-
-        memset(cmdline, 0, sizeof(cmdline));
-
-        snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
-        if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
-            TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
-            close(fd);
-            if (cmdline[0]) {
-                helper(pid, cmdline, arg);
-                continue;
-            }
-        }
-
-        // if no cmdline, a kernel thread has comm
-        snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
-        if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
-            TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
-            close(fd);
-            if (cmdline[1]) {
-                cmdline[0] = '[';
-                size_t len = strcspn(cmdline, "\f\b\r\n");
-                cmdline[len] = ']';
-                cmdline[len+1] = '\0';
-            }
-        }
-        if (!cmdline[0]) {
-            strcpy(cmdline, "N/A");
-        }
-        helper(pid, cmdline, arg);
-    }
-
-    closedir(d);
-}
-
-static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
-    for_each_pid_func *func = (for_each_pid_func*) arg;
-    func(pid, cmdline);
-}
-
-void for_each_pid(for_each_pid_func func, const char *header) {
-    std::string title = header == nullptr ? "for_each_pid"
-                                          : android::base::StringPrintf("for_each_pid(%s)", header);
-    DurationReporter duration_reporter(title);
-    if (PropertiesHelper::IsDryRun()) return;
-
-    __for_each_pid(for_each_pid_helper, header, (void *) func);
-}
-
-static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
-    DIR *d;
-    struct dirent *de;
-    char taskpath[255];
-    for_each_tid_func *func = (for_each_tid_func *) arg;
-
-    snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
-
-    if (!(d = opendir(taskpath))) {
-        printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
-        return;
-    }
-
-    func(pid, pid, cmdline);
-
-    while ((de = readdir(d))) {
-        if (ds.IsUserConsentDenied()) {
-            MYLOGE(
-                "Returning early because user denied consent to share bugreport with calling app.");
-            closedir(d);
-            return;
-        }
-        int tid;
-        int fd;
-        char commpath[255];
-        char comm[255];
-
-        if (!(tid = atoi(de->d_name))) {
-            continue;
-        }
-
-        if (tid == pid)
-            continue;
-
-        snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
-        memset(comm, 0, sizeof(comm));
-        if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
-            strcpy(comm, "N/A");
-        } else {
-            char *c;
-            TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
-            close(fd);
-
-            c = strrchr(comm, '\n');
-            if (c) {
-                *c = '\0';
-            }
-        }
-        func(pid, tid, comm);
-    }
-
-    closedir(d);
-}
-
-void for_each_tid(for_each_tid_func func, const char *header) {
-    std::string title = header == nullptr ? "for_each_tid"
-                                          : android::base::StringPrintf("for_each_tid(%s)", header);
-    DurationReporter duration_reporter(title);
-
-    if (PropertiesHelper::IsDryRun()) return;
-
-    __for_each_pid(for_each_tid_helper, header, (void *) func);
-}
-
-void show_wchan(int pid, int tid, const char *name) {
-    if (PropertiesHelper::IsDryRun()) return;
-
-    char path[255];
-    char buffer[255];
-    int fd, ret, save_errno;
-    char name_buffer[255];
-
-    memset(buffer, 0, sizeof(buffer));
-
-    snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
-    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
-        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
-        return;
-    }
-
-    ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
-    save_errno = errno;
-    close(fd);
-
-    if (ret < 0) {
-        printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
-        return;
-    }
-
-    snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
-             pid == tid ? 0 : 3, "", name);
-
-    printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
-
-    return;
-}
-
-// print time in centiseconds
-static void snprcent(char *buffer, size_t len, size_t spc,
-                     unsigned long long time) {
-    static long hz; // cache discovered hz
-
-    if (hz <= 0) {
-        hz = sysconf(_SC_CLK_TCK);
-        if (hz <= 0) {
-            hz = 1000;
-        }
-    }
-
-    // convert to centiseconds
-    time = (time * 100 + (hz / 2)) / hz;
-
-    char str[16];
-
-    snprintf(str, sizeof(str), " %llu.%02u",
-             time / 100, (unsigned)(time % 100));
-    size_t offset = strlen(buffer);
-    snprintf(buffer + offset, (len > offset) ? len - offset : 0,
-             "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
-}
-
-// print permille as a percent
-static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
-    char str[16];
-
-    snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
-    size_t offset = strlen(buffer);
-    snprintf(buffer + offset, (len > offset) ? len - offset : 0,
-             "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
-}
-
-void show_showtime(int pid, const char *name) {
-    if (PropertiesHelper::IsDryRun()) return;
-
-    char path[255];
-    char buffer[1023];
-    int fd, ret, save_errno;
-
-    memset(buffer, 0, sizeof(buffer));
-
-    snprintf(path, sizeof(path), "/proc/%d/stat", pid);
-    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
-        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
-        return;
-    }
-
-    ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
-    save_errno = errno;
-    close(fd);
-
-    if (ret < 0) {
-        printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
-        return;
-    }
-
-    // field 14 is utime
-    // field 15 is stime
-    // field 42 is iotime
-    unsigned long long utime = 0, stime = 0, iotime = 0;
-    if (sscanf(buffer,
-               "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
-               "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
-               "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
-               "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
-               &utime, &stime, &iotime) != 3) {
-        return;
-    }
-
-    unsigned long long total = utime + stime;
-    if (!total) {
-        return;
-    }
-
-    unsigned permille = (iotime * 1000 + (total / 2)) / total;
-    if (permille > 1000) {
-        permille = 1000;
-    }
-
-    // try to beautify and stabilize columns at <80 characters
-    snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
-    if ((name[0] != '[') || utime) {
-        snprcent(buffer, sizeof(buffer), 57, utime);
-    }
-    snprcent(buffer, sizeof(buffer), 65, stime);
-    if ((name[0] != '[') || iotime) {
-        snprcent(buffer, sizeof(buffer), 73, iotime);
-    }
-    if (iotime) {
-        snprdec(buffer, sizeof(buffer), 79, permille);
-    }
-    puts(buffer);  // adds a trailing newline
-
-    return;
-}
-
-void do_dmesg() {
-    const char *title = "KERNEL LOG (dmesg)";
-    DurationReporter duration_reporter(title);
-    printf("------ %s ------\n", title);
-
-    if (PropertiesHelper::IsDryRun()) return;
-
-    /* Get size of kernel buffer */
-    int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
-    if (size <= 0) {
-        printf("Unexpected klogctl return value: %d\n\n", size);
-        return;
-    }
-    char *buf = (char *) malloc(size + 1);
-    if (buf == nullptr) {
-        printf("memory allocation failed\n\n");
-        return;
-    }
-    int retval = klogctl(KLOG_READ_ALL, buf, size);
-    if (retval < 0) {
-        printf("klogctl failure\n\n");
-        free(buf);
-        return;
-    }
-    buf[retval] = '\0';
-    printf("%s\n\n", buf);
-    free(buf);
-    return;
-}
-
-void do_showmap(int pid, const char *name) {
-    char title[255];
-    char arg[255];
-
-    snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
-    snprintf(arg, sizeof(arg), "%d", pid);
-    RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
-}
-
-int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
-    DurationReporter duration_reporter(title);
-
-    int status = DumpFileToFd(STDOUT_FILENO, title, path);
-
-    UpdateProgress(WEIGHT_FILE);
-
-    return status;
-}
-
-int read_file_as_long(const char *path, long int *output) {
-    int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
-    if (fd < 0) {
-        int err = errno;
-        MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
-        return -1;
-    }
-    char buffer[50];
-    ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
-    if (bytes_read == -1) {
-        MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
-        return -2;
-    }
-    if (bytes_read == 0) {
-        MYLOGE("File %s is empty\n", path);
-        return -3;
-    }
-    *output = atoi(buffer);
-    return 0;
-}
-
-/* calls skip to gate calling dump_from_fd recursively
- * in the specified directory. dump_from_fd defaults to
- * dump_file_from_fd above when set to NULL. skip defaults
- * to false when set to NULL. dump_from_fd will always be
- * called with title NULL.
- */
-int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
-               int (*dump_from_fd)(const char* title, const char* path, int fd)) {
-    DurationReporter duration_reporter(title);
-    DIR *dirp;
-    struct dirent *d;
-    char *newpath = nullptr;
-    const char *slash = "/";
-    int retval = 0;
-
-    if (!title.empty()) {
-        printf("------ %s (%s) ------\n", title.c_str(), dir);
-    }
-    if (PropertiesHelper::IsDryRun()) return 0;
-
-    if (dir[strlen(dir) - 1] == '/') {
-        ++slash;
-    }
-    dirp = opendir(dir);
-    if (dirp == nullptr) {
-        retval = -errno;
-        MYLOGE("%s: %s\n", dir, strerror(errno));
-        return retval;
-    }
-
-    if (!dump_from_fd) {
-        dump_from_fd = dump_file_from_fd;
-    }
-    for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
-        if ((d->d_name[0] == '.')
-         && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
-          || (d->d_name[1] == '\0'))) {
-            continue;
-        }
-        asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
-                 (d->d_type == DT_DIR) ? "/" : "");
-        if (!newpath) {
-            retval = -errno;
-            continue;
-        }
-        if (skip && (*skip)(newpath)) {
-            continue;
-        }
-        if (d->d_type == DT_DIR) {
-            int ret = dump_files("", newpath, skip, dump_from_fd);
-            if (ret < 0) {
-                retval = ret;
-            }
-            continue;
-        }
-        android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
-        if (fd.get() < 0) {
-            retval = -1;
-            printf("*** %s: %s\n", newpath, strerror(errno));
-            continue;
-        }
-        (*dump_from_fd)(nullptr, newpath, fd.get());
-    }
-    closedir(dirp);
-    if (!title.empty()) {
-        printf("\n");
-    }
-    return retval;
-}
-
-/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
- * it's possible to avoid issues where opening the file itself can get
- * stuck.
- */
-int dump_file_from_fd(const char *title, const char *path, int fd) {
-    if (PropertiesHelper::IsDryRun()) return 0;
-
-    int flags = fcntl(fd, F_GETFL);
-    if (flags == -1) {
-        printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
-        return -1;
-    } else if (!(flags & O_NONBLOCK)) {
-        printf("*** %s: fd must have O_NONBLOCK set.\n", path);
-        return -1;
-    }
-    return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
-}
-
-int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
-                          const CommandOptions& options, bool verbose_duration) {
-    DurationReporter duration_reporter(title, false /* logcat_only */, verbose_duration);
-
-    int status = RunCommandToFd(STDOUT_FILENO, title, full_command, options);
-
-    /* TODO: for now we're simplifying the progress calculation by using the
-     * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
-     * where its weight should be much higher proportionally to its timeout.
-     * Ideally, it should use a options.EstimatedDuration() instead...*/
-    UpdateProgress(options.Timeout());
-
-    return status;
-}
-
-void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
-                           const CommandOptions& options, long dumpsysTimeoutMs) {
-    long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
-    std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
-    dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
-    RunCommand(title, dumpsys, options);
-}
-
-int open_socket(const char *service) {
-    int s = android_get_control_socket(service);
-    if (s < 0) {
-        MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
-        return -1;
-    }
-    fcntl(s, F_SETFD, FD_CLOEXEC);
-
-    // Set backlog to 0 to make sure that queue size will be minimum.
-    // In Linux, because the minimum queue will be 1, connect() will be blocked
-    // if the other clients already called connect() and the connection request was not accepted.
-    if (listen(s, 0) < 0) {
-        MYLOGE("listen(control socket): %s\n", strerror(errno));
-        return -1;
-    }
-
-    struct sockaddr addr;
-    socklen_t alen = sizeof(addr);
-    int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
-
-    // Close socket just after accept(), to make sure that connect() by client will get error
-    // when the socket is used by the other services.
-    // There is still a race condition possibility between accept and close, but there is no way
-    // to close-on-accept atomically.
-    // See detail; b/123306389#comment25
-    close(s);
-
-    if (fd < 0) {
-        MYLOGE("accept(control socket): %s\n", strerror(errno));
-        return -1;
-    }
-
-    return fd;
-}
-
-/* redirect output to a service control socket */
-bool redirect_to_socket(FILE* redirect, const char* service) {
-    int fd = open_socket(service);
-    if (fd == -1) {
-        return false;
-    }
-    fflush(redirect);
-    // TODO: handle dup2 failure
-    TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
-    close(fd);
-    return true;
-}
-
-// TODO: should call is_valid_output_file and/or be merged into it.
-void create_parent_dirs(const char *path) {
-    char *chp = const_cast<char *> (path);
-
-    /* skip initial slash */
-    if (chp[0] == '/')
-        chp++;
-
-    /* create leading directories, if necessary */
-    struct stat dir_stat;
-    while (chp && chp[0]) {
-        chp = strchr(chp, '/');
-        if (chp) {
-            *chp = 0;
-            if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
-                MYLOGI("Creating directory %s\n", path);
-                if (mkdir(path, 0770)) { /* drwxrwx--- */
-                    MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
-                } else if (chown(path, AID_SHELL, AID_SHELL)) {
-                    MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
-                }
-            }
-            *chp++ = '/';
-        }
-    }
-}
-
-bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
-    create_parent_dirs(path);
-
-    int fd = TEMP_FAILURE_RETRY(open(path,
-                                     O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
-                                     S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
-    if (fd < 0) {
-        MYLOGE("%s: %s\n", path, strerror(errno));
-        return false;
-    }
-
-    TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
-    close(fd);
-    return true;
-}
-
-bool redirect_to_file(FILE* redirect, char* path) {
-    return _redirect_to_file(redirect, path, O_TRUNC);
-}
-
-bool redirect_to_existing_file(FILE* redirect, char* path) {
-    return _redirect_to_file(redirect, path, O_APPEND);
-}
-
-void dump_route_tables() {
-    DurationReporter duration_reporter("DUMP ROUTE TABLES");
-    if (PropertiesHelper::IsDryRun()) return;
-    const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
-    ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
-    FILE* fp = fopen(RT_TABLES_PATH, "re");
-    if (!fp) {
-        printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
-        return;
-    }
-    char table[16];
-    // Each line has an integer (the table number), a space, and a string (the table name). We only
-    // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
-    // Add a fixed max limit so this doesn't go awry.
-    for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
-        RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
-        RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
-    }
-    fclose(fp);
-}
-
-// TODO: make this function thread safe if sections are generated in parallel.
-void Dumpstate::UpdateProgress(int32_t delta_sec) {
-    if (progress_ == nullptr) {
-        MYLOGE("UpdateProgress: progress_ not set\n");
-        return;
-    }
-
-    // Always update progess so stats can be tuned...
-    progress_->Inc(delta_sec);
-
-    // ...but only notifiy listeners when necessary.
-    if (!options_->do_progress_updates) return;
-
-    int progress = progress_->Get();
-    int max = progress_->GetMax();
-    int percent = 100 * progress / max;
-
-    if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
-        return;
-    }
-    last_reported_percent_progress_ = percent;
-
-    if (control_socket_fd_ >= 0) {
-        dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
-        fsync(control_socket_fd_);
-    }
-
-    if (listener_ != nullptr) {
-        if (percent % 5 == 0) {
-            // We don't want to spam logcat, so only log multiples of 5.
-            MYLOGD("Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(), progress, max,
-                   percent);
-        } else {
-            // stderr is ignored on normal invocations, but useful when calling
-            // /system/bin/dumpstate directly for debuggging.
-            fprintf(stderr, "Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(),
-                    progress, max, percent);
-        }
-
-        listener_->onProgress(percent);
-    }
-}
-
-void Dumpstate::TakeScreenshot(const std::string& path) {
-    const std::string& real_path = path.empty() ? screenshot_path_ : path;
-    int status =
-        RunCommand("", {"/system/bin/screencap", "-p", real_path},
-                   CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
-    if (status == 0) {
-        MYLOGD("Screenshot saved on %s\n", real_path.c_str());
-    } else {
-        MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
-    }
-}
-
-bool is_dir(const char* pathname) {
-    struct stat info;
-    if (stat(pathname, &info) == -1) {
-        return false;
-    }
-    return S_ISDIR(info.st_mode);
-}
-
-time_t get_mtime(int fd, time_t default_mtime) {
-    struct stat info;
-    if (fstat(fd, &info) == -1) {
-        return default_mtime;
-    }
-    return info.st_mtime;
-}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 82bf821..d02ec75 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -73,15 +73,13 @@
  */
 class DurationReporter {
   public:
-    explicit DurationReporter(const std::string& title, bool logcat_only = false,
-                              bool verbose = false);
+    explicit DurationReporter(const std::string& title, bool logcat_only = false);
 
     ~DurationReporter();
 
   private:
     std::string title_;
     bool logcat_only_;
-    bool verbose_;
     uint64_t started_;
 
     DISALLOW_COPY_AND_ASSIGN(DurationReporter);
@@ -226,8 +224,7 @@
      */
     int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
                    const android::os::dumpstate::CommandOptions& options =
-                       android::os::dumpstate::CommandOptions::DEFAULT,
-                   bool verbose_duration = false);
+                       android::os::dumpstate::CommandOptions::DEFAULT);
 
     /*
      * Runs `dumpsys` with the given arguments, automatically setting its timeout
@@ -403,8 +400,12 @@
     // Runtime options.
     std::unique_ptr<DumpOptions> options_;
 
-    // Last progress that was sent to the listener [0-100].
-    int last_reported_percent_progress_ = 0;
+    // How frequently the progess should be updated;the listener will only be notificated when the
+    // delta from the previous update is more than the threshold.
+    int32_t update_progress_threshold_ = 100;
+
+    // Last progress that triggered a listener updated
+    int32_t last_updated_progress_;
 
     // Whether it should take an screenshot earlier in the process.
     bool do_early_screenshot_ = false;
@@ -440,7 +441,8 @@
     // Full path of the bugreport file, be it zip or text, inside bugreport_internal_dir_.
     std::string path_;
 
-    // Full path of the file containing the screenshot (when requested).
+    // TODO: If temporary this should be removed at the end.
+    // Full path of the temporary file containing the screenshot (when requested).
     std::string screenshot_path_;
 
     // Pointer to the zipped file.
@@ -584,6 +586,9 @@
 /** Gets the last modification time of a file, or default time if file is not found. */
 time_t get_mtime(int fd, time_t default_mtime);
 
+/* Dumps eMMC Extended CSD data. */
+void dump_emmc_ecsd(const char *ext_csd_path);
+
 /** Gets command-line arguments. */
 void format_args(int argc, const char *argv[], std::string *args);
 
diff --git a/cmds/dumpstate/dumpstate_test.xml b/cmds/dumpstate/dumpstate_test.xml
deleted file mode 100644
index e4e4a30..0000000
--- a/cmds/dumpstate/dumpstate_test.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 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.
--->
-<configuration description="Config for dumpstate_test">
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
-        <option name="cleanup" value="true" />
-        <option name="push" value="dumpstate_test->/data/local/tmp/dumpstate_test" />
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
-    <option name="test-suite-tag" value="apct" />
-    <test class="com.android.tradefed.testtype.GTest" >
-        <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="file-exclusion-filter-regex" value=".*/dumpstate_test_fixture" />
-        <option name="file-exclusion-filter-regex" value=".*/tests/.*" />
-        <option name="module-name" value="dumpstate_test" />
-    </test>
-</configuration>
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index 7e6f6f5..fc3642c 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -14,21 +14,20 @@
  * limitations under the License.
  */
 
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <fcntl.h>
+#include <libgen.h>
+
 #include <android-base/file.h>
 #include <android/os/BnDumpstate.h>
 #include <android/os/BnDumpstateListener.h>
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
 #include <cutils/properties.h>
-#include <fcntl.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <libgen.h>
 #include <ziparchive/zip_archive.h>
 
-#include <fstream>
-#include <regex>
-
 #include "dumpstate.h"
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
@@ -45,11 +44,6 @@
 
 namespace {
 
-struct SectionInfo {
-    std::string name;
-    int32_t size_bytes;
-};
-
 sp<IDumpstate> GetDumpstateService() {
     return android::interface_cast<IDumpstate>(
         android::defaultServiceManager()->getService(String16("dumpstate")));
@@ -61,80 +55,15 @@
                                    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
 }
 
-void GetEntry(const ZipArchiveHandle archive, const std::string_view entry_name, ZipEntry* data) {
-    int32_t e = FindEntry(archive, entry_name, data);
-    EXPECT_EQ(e, 0) << ErrorCodeString(e) << " entry name: " << entry_name;
-}
-
-// Extracts the main bugreport txt from the given archive and writes into output_fd.
-void ExtractBugreport(const ZipArchiveHandle* handle, int output_fd) {
-    // Read contents of main_entry.txt which is a single line indicating the name of the zip entry
-    // that contains the main bugreport txt.
-    ZipEntry main_entry;
-    GetEntry(*handle, "main_entry.txt", &main_entry);
-    std::string bugreport_txt_name;
-    bugreport_txt_name.resize(main_entry.uncompressed_length);
-    ExtractToMemory(*handle, &main_entry, reinterpret_cast<uint8_t*>(bugreport_txt_name.data()),
-                    main_entry.uncompressed_length);
-
-    // Read the main bugreport txt and extract to output_fd.
-    ZipEntry entry;
-    GetEntry(*handle, bugreport_txt_name, &entry);
-    ExtractEntryToFile(*handle, &entry, output_fd);
-}
-
-bool IsSectionStart(const std::string& line, std::string* section_name) {
-    static const std::regex kSectionStart = std::regex{"DUMP OF SERVICE (.*):"};
-    std::smatch match;
-    if (std::regex_match(line, match, kSectionStart)) {
-        *section_name = match.str(1);
-        return true;
-    }
-    return false;
-}
-
-bool IsSectionEnd(const std::string& line) {
-    // Not all lines that contain "was the duration of" is a section end, but all section ends do
-    // contain "was the duration of". The disambiguation can be done by the caller.
-    return (line.find("was the duration of") != std::string::npos);
-}
-
-// Extracts the zipped bugreport and identifies the sections.
-void ParseSections(const std::string& zip_path, std::vector<SectionInfo>* sections) {
-    // Open the archive
-    ZipArchiveHandle handle;
-    ASSERT_EQ(OpenArchive(zip_path.c_str(), &handle), 0);
-
-    // Extract the main entry to a temp file
-    TemporaryFile tmp_binary;
-    ASSERT_NE(-1, tmp_binary.fd);
-    ExtractBugreport(&handle, tmp_binary.fd);
-
-    // Read line by line and identify sections
-    std::ifstream ifs(tmp_binary.path, std::ifstream::in);
-    std::string line;
-    int section_bytes = 0;
-    std::string current_section_name;
-    while (std::getline(ifs, line)) {
-        std::string section_name;
-        if (IsSectionStart(line, &section_name)) {
-            section_bytes = 0;
-            current_section_name = section_name;
-        } else if (IsSectionEnd(line)) {
-            if (!current_section_name.empty()) {
-                sections->push_back({current_section_name, section_bytes});
-            }
-            current_section_name = "";
-        } else if (!current_section_name.empty()) {
-            section_bytes += line.length();
-        }
-    }
-
-    CloseArchive(handle);
-}
-
 }  // namespace
 
+struct SectionInfo {
+    std::string name;
+    status_t status;
+    int32_t size_bytes;
+    int32_t duration_ms;
+};
+
 /**
  * Listens to bugreport progress and updates the user by writing the progress to STDOUT. All the
  * section details generated by dumpstate are added to a vector to be used by Tests later.
@@ -167,6 +96,26 @@
         return binder::Status::ok();
     }
 
+    binder::Status onProgressUpdated(int32_t progress) override {
+        dprintf(out_fd_, "\rIn progress %d/%d", progress, max_progress_);
+        return binder::Status::ok();
+    }
+
+    binder::Status onMaxProgressUpdated(int32_t max_progress) override {
+        std::lock_guard<std::mutex> lock(lock_);
+        max_progress_ = max_progress;
+        return binder::Status::ok();
+    }
+
+    binder::Status onSectionComplete(const ::std::string& name, int32_t status, int32_t size_bytes,
+                                     int32_t duration_ms) override {
+        std::lock_guard<std::mutex> lock(lock_);
+        if (sections_.get() != nullptr) {
+            sections_->push_back({name, status, size_bytes, duration_ms});
+        }
+        return binder::Status::ok();
+    }
+
     bool getIsFinished() {
         std::lock_guard<std::mutex> lock(lock_);
         return is_finished_;
@@ -179,6 +128,7 @@
 
   private:
     int out_fd_;
+    int max_progress_ = 5000;
     int error_code_ = -1;
     bool is_finished_ = false;
     std::shared_ptr<std::vector<SectionInfo>> sections_;
@@ -216,8 +166,8 @@
         duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
     }
 
-    static const std::string getZipFilePath() {
-        return ds.GetPath(".zip");
+    static const char* getZipFilePath() {
+        return ds.GetPath(".zip").c_str();
     }
 };
 std::shared_ptr<std::vector<SectionInfo>> ZippedBugreportGenerationTest::sections =
@@ -226,12 +176,12 @@
 std::chrono::milliseconds ZippedBugreportGenerationTest::duration = 0s;
 
 TEST_F(ZippedBugreportGenerationTest, IsGeneratedWithoutErrors) {
-    EXPECT_EQ(access(getZipFilePath().c_str(), F_OK), 0);
+    EXPECT_EQ(access(getZipFilePath(), F_OK), 0);
 }
 
 TEST_F(ZippedBugreportGenerationTest, Is3MBto30MBinSize) {
     struct stat st;
-    EXPECT_EQ(stat(getZipFilePath().c_str(), &st), 0);
+    EXPECT_EQ(stat(getZipFilePath(), &st), 0);
     EXPECT_GE(st.st_size, 3000000 /* 3MB */);
     EXPECT_LE(st.st_size, 30000000 /* 30MB */);
 }
@@ -250,7 +200,7 @@
   public:
     ZipArchiveHandle handle;
     void SetUp() {
-        ASSERT_EQ(OpenArchive(ZippedBugreportGenerationTest::getZipFilePath().c_str(), &handle), 0);
+        ASSERT_EQ(OpenArchive(ZippedBugreportGenerationTest::getZipFilePath(), &handle), 0);
     }
     void TearDown() {
         CloseArchive(handle);
@@ -258,30 +208,29 @@
 
     void FileExists(const char* filename, uint32_t minsize, uint32_t maxsize) {
         ZipEntry entry;
-        GetEntry(handle, filename, &entry);
+        EXPECT_EQ(FindEntry(handle, ZipString(filename), &entry), 0);
         EXPECT_GT(entry.uncompressed_length, minsize);
         EXPECT_LT(entry.uncompressed_length, maxsize);
     }
 };
 
 TEST_F(ZippedBugReportContentsTest, ContainsMainEntry) {
-    ZipEntry main_entry;
+    ZipEntry mainEntryLoc;
     // contains main entry name file
-    GetEntry(handle, "main_entry.txt", &main_entry);
+    EXPECT_EQ(FindEntry(handle, ZipString("main_entry.txt"), &mainEntryLoc), 0);
 
-    std::string bugreport_txt_name;
-    bugreport_txt_name.resize(main_entry.uncompressed_length);
-    ExtractToMemory(handle, &main_entry, reinterpret_cast<uint8_t*>(bugreport_txt_name.data()),
-                    main_entry.uncompressed_length);
+    char* buf = new char[mainEntryLoc.uncompressed_length];
+    ExtractToMemory(handle, &mainEntryLoc, (uint8_t*)buf, mainEntryLoc.uncompressed_length);
+    delete[] buf;
 
     // contains main entry file
-    FileExists(bugreport_txt_name.c_str(), 1000000U, 50000000U);
+    FileExists(buf, 1000000U, 50000000U);
 }
 
 TEST_F(ZippedBugReportContentsTest, ContainsVersion) {
     ZipEntry entry;
     // contains main entry name file
-    GetEntry(handle, "version.txt", &entry);
+    EXPECT_EQ(FindEntry(handle, ZipString("version.txt"), &entry), 0);
 
     char* buf = new char[entry.uncompressed_length + 1];
     ExtractToMemory(handle, &entry, (uint8_t*)buf, entry.uncompressed_length);
@@ -295,10 +244,6 @@
     FileExists("dumpstate_board.txt", 100000U, 1000000U);
 }
 
-TEST_F(ZippedBugReportContentsTest, ContainsProtoFile) {
-    FileExists("proto/activity.proto", 100000U, 1000000U);
-}
-
 // Spot check on some files pulled from the file system
 TEST_F(ZippedBugReportContentsTest, ContainsSomeFileSystemFiles) {
     // FS/proc/*/mountinfo size > 0
@@ -313,11 +258,6 @@
  */
 class BugreportSectionTest : public Test {
   public:
-    static void SetUpTestCase() {
-        ParseSections(ZippedBugreportGenerationTest::getZipFilePath().c_str(),
-                      ZippedBugreportGenerationTest::sections.get());
-    }
-
     int numMatches(const std::string& substring) {
         int matches = 0;
         for (auto const& section : *ZippedBugreportGenerationTest::sections) {
@@ -327,11 +267,10 @@
         }
         return matches;
     }
-
     void SectionExists(const std::string& sectionName, int minsize) {
         for (auto const& section : *ZippedBugreportGenerationTest::sections) {
             if (sectionName == section.name) {
-                EXPECT_GE(section.size_bytes, minsize) << " for section:" << sectionName;
+                EXPECT_GE(section.size_bytes, minsize);
                 return;
             }
         }
@@ -339,59 +278,71 @@
     }
 };
 
+// Test all sections are generated without timeouts or errors
+TEST_F(BugreportSectionTest, GeneratedWithoutErrors) {
+    for (auto const& section : *ZippedBugreportGenerationTest::sections) {
+        EXPECT_EQ(section.status, 0) << section.name << " failed with status " << section.status;
+    }
+}
+
 TEST_F(BugreportSectionTest, Atleast3CriticalDumpsysSectionsGenerated) {
-    int numSections = numMatches("CRITICAL");
+    int numSections = numMatches("DUMPSYS CRITICAL");
     EXPECT_GE(numSections, 3);
 }
 
 TEST_F(BugreportSectionTest, Atleast2HighDumpsysSectionsGenerated) {
-    int numSections = numMatches("HIGH");
+    int numSections = numMatches("DUMPSYS HIGH");
     EXPECT_GE(numSections, 2);
 }
 
 TEST_F(BugreportSectionTest, Atleast50NormalDumpsysSectionsGenerated) {
-    int allSections = ZippedBugreportGenerationTest::sections->size();
-    int criticalSections = numMatches("CRITICAL");
-    int highSections = numMatches("HIGH");
+    int allSections = numMatches("DUMPSYS");
+    int criticalSections = numMatches("DUMPSYS CRITICAL");
+    int highSections = numMatches("DUMPSYS HIGH");
     int normalSections = allSections - criticalSections - highSections;
 
     EXPECT_GE(normalSections, 50) << "Total sections less than 50 (Critical:" << criticalSections
                                   << "High:" << highSections << "Normal:" << normalSections << ")";
 }
 
+TEST_F(BugreportSectionTest, Atleast1ProtoDumpsysSectionGenerated) {
+    int numSections = numMatches("proto/");
+    EXPECT_GE(numSections, 1);
+}
+
 // Test if some critical sections are being generated.
 TEST_F(BugreportSectionTest, CriticalSurfaceFlingerSectionGenerated) {
-    SectionExists("CRITICAL SurfaceFlinger", /* bytes= */ 10000);
+    SectionExists("DUMPSYS CRITICAL - SurfaceFlinger", /* bytes= */ 10000);
 }
 
 TEST_F(BugreportSectionTest, ActivitySectionsGenerated) {
-    SectionExists("CRITICAL activity", /* bytes= */ 5000);
-    SectionExists("activity", /* bytes= */ 10000);
+    SectionExists("DUMPSYS CRITICAL - activity", /* bytes= */ 5000);
+    SectionExists("DUMPSYS - activity", /* bytes= */ 10000);
 }
 
 TEST_F(BugreportSectionTest, CpuinfoSectionGenerated) {
-    SectionExists("CRITICAL cpuinfo", /* bytes= */ 1000);
+    SectionExists("DUMPSYS CRITICAL - cpuinfo", /* bytes= */ 1000);
 }
 
 TEST_F(BugreportSectionTest, WindowSectionGenerated) {
-    SectionExists("CRITICAL window", /* bytes= */ 20000);
+    SectionExists("DUMPSYS CRITICAL - window", /* bytes= */ 20000);
 }
 
 TEST_F(BugreportSectionTest, ConnectivitySectionsGenerated) {
-    SectionExists("HIGH connectivity", /* bytes= */ 3000);
-    SectionExists("connectivity", /* bytes= */ 5000);
+    SectionExists("DUMPSYS HIGH - connectivity", /* bytes= */ 5000);
+    SectionExists("DUMPSYS - connectivity", /* bytes= */ 5000);
 }
 
 TEST_F(BugreportSectionTest, MeminfoSectionGenerated) {
-    SectionExists("HIGH meminfo", /* bytes= */ 100000);
+    SectionExists("DUMPSYS HIGH - meminfo", /* bytes= */ 100000);
 }
 
 TEST_F(BugreportSectionTest, BatteryStatsSectionGenerated) {
-    SectionExists("batterystats", /* bytes= */ 1000);
+    SectionExists("DUMPSYS - batterystats", /* bytes= */ 1000);
 }
 
 TEST_F(BugreportSectionTest, WifiSectionGenerated) {
-    SectionExists("wifi", /* bytes= */ 100000);
+    SectionExists("DUMPSYS - wifi", /* bytes= */ 100000);
 }
 
 class DumpstateBinderTest : public Test {
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index cff1d43..71d15f4 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -62,6 +62,10 @@
     MOCK_METHOD1(onProgress, binder::Status(int32_t progress));
     MOCK_METHOD1(onError, binder::Status(int32_t error_code));
     MOCK_METHOD0(onFinished, binder::Status());
+    MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress));
+    MOCK_METHOD1(onMaxProgressUpdated, binder::Status(int32_t max_progress));
+    MOCK_METHOD4(onSectionComplete, binder::Status(const ::std::string& name, int32_t status,
+                                                   int32_t size, int32_t durationMs));
 
   protected:
     MOCK_METHOD0(onAsBinder, IBinder*());
@@ -101,8 +105,9 @@
 
   protected:
     const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str());
-    const std::string kTestDataPath = kTestPath + "/tests/testdata/";
-    const std::string kSimpleCommand = kTestPath + "/dumpstate_test_fixture";
+    const std::string kFixturesPath = kTestPath + "/../dumpstate_test_fixture/";
+    const std::string kTestDataPath = kFixturesPath + "tests/testdata/";
+    const std::string kSimpleCommand = kFixturesPath + "dumpstate_test_fixture";
     const std::string kEchoCommand = "/system/bin/echo";
 
     /*
@@ -586,6 +591,7 @@
         SetDryRun(false);
         SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)"));
         ds.progress_.reset(new Progress());
+        ds.update_progress_threshold_ = 0;
         ds.options_.reset(new Dumpstate::DumpOptions());
     }
 
@@ -610,9 +616,10 @@
         return status;
     }
 
-    void SetProgress(long progress, long initial_max) {
-        ds.last_reported_percent_progress_ = 0;
+    void SetProgress(long progress, long initial_max, long threshold = 0) {
         ds.options_->do_progress_updates = true;
+        ds.update_progress_threshold_ = threshold;
+        ds.last_updated_progress_ = 0;
         ds.progress_.reset(new Progress(initial_max, progress, 1.2));
     }
 
@@ -657,8 +664,7 @@
 TEST_F(DumpstateTest, RunCommandWithTitle) {
     EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
     EXPECT_THAT(err, StrEq("stderr\n"));
-    // The duration may not get output, depending on how long it takes,
-    // so we just check the prefix.
+    // We don't know the exact duration, so we check the prefix and suffix
     EXPECT_THAT(out,
                 StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
 }
@@ -693,8 +699,7 @@
 TEST_F(DumpstateTest, RunCommandDryRun) {
     SetDryRun(true);
     EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
-    // The duration may not get output, depending on how long it takes,
-    // so we just check the prefix.
+    // We don't know the exact duration, so we check the prefix and suffix
     EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand +
                                 ") ------\n\t(skipped on dry run)\n"));
     EXPECT_THAT(err, IsEmpty());
@@ -790,36 +795,73 @@
     ds.listener_name_ = "FoxMulder";
     SetProgress(0, 30);
 
+    EXPECT_CALL(*listener, onProgressUpdated(20));
     EXPECT_CALL(*listener, onProgress(66));  // 20/30 %
     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
     std::string progress_message = GetProgressMessage(ds.listener_name_, 20, 30);
     EXPECT_THAT(out, StrEq("stdout\n"));
     EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
 
-    EXPECT_CALL(*listener, onProgress(80));  // 24/30 %
-    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
-    progress_message = GetProgressMessage(ds.listener_name_, 24, 30);
+    EXPECT_CALL(*listener, onProgressUpdated(30));
+    EXPECT_CALL(*listener, onProgress(100));  // 35/35 %
+    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Build()));
+    progress_message = GetProgressMessage(ds.listener_name_, 30, 30);
+    EXPECT_THAT(out, StrEq("stdout\n"));
+    EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
+
+    // Run a command that will increase maximum timeout.
+    EXPECT_CALL(*listener, onProgressUpdated(31));
+    EXPECT_CALL(*listener, onMaxProgressUpdated(37));
+    EXPECT_CALL(*listener, onProgress(83));  // 31/37 %
+    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
+    progress_message = GetProgressMessage(ds.listener_name_, 31, 37, 30);  // 20% increase
     EXPECT_THAT(out, StrEq("stdout\n"));
     EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
 
     // Make sure command ran while in dry_run is counted.
     SetDryRun(true);
-    EXPECT_CALL(*listener, onProgress(90));  // 27/30 %
-    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
-    progress_message = GetProgressMessage(ds.listener_name_, 27, 30);
+    EXPECT_CALL(*listener, onProgressUpdated(35));
+    EXPECT_CALL(*listener, onProgress(94));  // 35/37 %
+    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
+    progress_message = GetProgressMessage(ds.listener_name_, 35, 37);
     EXPECT_THAT(out, IsEmpty());
     EXPECT_THAT(err, StrEq(progress_message));
 
-    SetDryRun(false);
-    EXPECT_CALL(*listener, onProgress(96));  // 29/30 %
-    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(2).Build()));
-    progress_message = GetProgressMessage(ds.listener_name_, 29, 30);
+    ds.listener_.clear();
+}
+
+TEST_F(DumpstateTest, RunCommandProgressIgnoreThreshold) {
+    sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
+    ds.listener_ = listener;
+    ds.listener_name_ = "FoxMulder";
+    SetProgress(0, 8, 5);  // 8 max, 5 threshold
+
+    // First update should always be sent.
+    EXPECT_CALL(*listener, onProgressUpdated(1));
+    EXPECT_CALL(*listener, onProgress(12));  // 1/12 %
+    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
+    std::string progress_message = GetProgressMessage(ds.listener_name_, 1, 8);
     EXPECT_THAT(out, StrEq("stdout\n"));
     EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
 
-    EXPECT_CALL(*listener, onProgress(100));  // 30/30 %
+    // Fourth update should be ignored because it's between the threshold (5 -1 = 4 < 5).
+    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
+    EXPECT_THAT(out, StrEq("stdout\n"));
+    EXPECT_THAT(err, StrEq("stderr\n"));
+
+    // Third update should be sent because it reaches threshold (6 - 1 = 5).
+    EXPECT_CALL(*listener, onProgressUpdated(6));
+    EXPECT_CALL(*listener, onProgress(75));  // 6/8 %
     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
-    progress_message = GetProgressMessage(ds.listener_name_, 30, 30);
+    progress_message = GetProgressMessage(ds.listener_name_, 6, 8);
+    EXPECT_THAT(out, StrEq("stdout\n"));
+    EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
+
+    // Fourth update should be ignored because it's between the threshold (9 - 6 = 3 < 5).
+    // But max update should be sent.
+    EXPECT_CALL(*listener, onMaxProgressUpdated(10));  // 9 * 120% = 10.8 = 10
+    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
+    progress_message = GetProgressMessage(ds.listener_name_, 9, 10, 8, false);
     EXPECT_THAT(out, StrEq("stdout\n"));
     EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
 
@@ -995,8 +1037,7 @@
 TEST_F(DumpstateTest, DumpFileNotFoundWithTitle) {
     EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
     EXPECT_THAT(err, IsEmpty());
-    // The duration may not get output, depending on how long it takes,
-    // so we just check the prefix.
+    // We don't know the exact duration, so we check the prefix and suffix
     EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No "
                                 "such file or directory\n"));
 }
@@ -1047,6 +1088,7 @@
     ds.listener_name_ = "FoxMulder";
     SetProgress(0, 30);
 
+    EXPECT_CALL(*listener, onProgressUpdated(5));
     EXPECT_CALL(*listener, onProgress(16));  // 5/30 %
     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
 
@@ -1362,6 +1404,14 @@
         return status;
     }
 
+    // Find out the pid of the process_name
+    int FindPidOfProcess(const std::string& process_name) {
+        CaptureStderr();
+        int status = GetPidByName(process_name);
+        err = GetCapturedStderr();
+        return status;
+    }
+
     int fd;
 
     // 'fd` output and `stderr` from the last command ran.
@@ -1711,6 +1761,18 @@
     EXPECT_THAT(out, EndsWith("skipped on dry run\n"));
 }
 
+TEST_F(DumpstateUtilTest, FindingPidWithExistingProcess) {
+    // init process always has pid 1.
+    EXPECT_EQ(1, FindPidOfProcess("init"));
+    EXPECT_THAT(err, IsEmpty());
+}
+
+TEST_F(DumpstateUtilTest, FindingPidWithNotExistingProcess) {
+    // find the process with abnormal name.
+    EXPECT_EQ(-1, FindPidOfProcess("abcdef12345-543"));
+    EXPECT_THAT(err, StrEq("can't find the pid\n"));
+}
+
 }  // namespace dumpstate
 }  // namespace os
 }  // namespace android
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
new file mode 100644
index 0000000..0bb80dc
--- /dev/null
+++ b/cmds/dumpstate/utils.cpp
@@ -0,0 +1,1012 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#define LOG_TAG "dumpstate"
+
+#include "dumpstate.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <math.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/capability.h>
+#include <sys/inotify.h>
+#include <sys/klog.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+#include <log/log.h>
+#include <private/android_filesystem_config.h>
+
+#include "DumpstateInternal.h"
+
+// TODO: remove once moved to namespace
+using android::os::dumpstate::CommandOptions;
+using android::os::dumpstate::DumpFileToFd;
+using android::os::dumpstate::PropertiesHelper;
+
+// Keep in sync with
+// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
+static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
+
+/* Most simple commands have 10 as timeout, so 5 is a good estimate */
+static const int32_t WEIGHT_FILE = 5;
+
+// TODO: temporary variables and functions used during C++ refactoring
+static Dumpstate& ds = Dumpstate::GetInstance();
+static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
+                      const CommandOptions& options = CommandOptions::DEFAULT) {
+    return ds.RunCommand(title, full_command, options);
+}
+
+// Reasonable value for max stats.
+static const int STATS_MAX_N_RUNS = 1000;
+static const long STATS_MAX_AVERAGE = 100000;
+
+CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
+
+// TODO(111441001): Default DumpOptions to sensible values.
+Dumpstate::Dumpstate(const std::string& version)
+    : pid_(getpid()),
+      options_(new Dumpstate::DumpOptions()),
+      version_(version),
+      now_(time(nullptr)) {
+}
+
+Dumpstate& Dumpstate::GetInstance() {
+    static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
+    return singleton_;
+}
+
+DurationReporter::DurationReporter(const std::string& title, bool logcat_only)
+    : title_(title), logcat_only_(logcat_only) {
+    if (!title_.empty()) {
+        started_ = Nanotime();
+    }
+}
+
+DurationReporter::~DurationReporter() {
+    if (!title_.empty()) {
+        float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
+        if (elapsed < .5f) {
+            return;
+        }
+        MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
+        if (logcat_only_) {
+            return;
+        }
+        // Use "Yoda grammar" to make it easier to grep|sort sections.
+        printf("------ %.3fs was the duration of '%s' ------\n", elapsed, title_.c_str());
+    }
+}
+
+const int32_t Progress::kDefaultMax = 5000;
+
+Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
+}
+
+Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
+    : Progress(initial_max, growth_factor, "") {
+    progress_ = progress;
+}
+
+Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
+    : initial_max_(initial_max),
+      progress_(0),
+      max_(initial_max),
+      growth_factor_(growth_factor),
+      n_runs_(0),
+      average_max_(0),
+      path_(path) {
+    if (!path_.empty()) {
+        Load();
+    }
+}
+
+void Progress::Load() {
+    MYLOGD("Loading stats from %s\n", path_.c_str());
+    std::string content;
+    if (!android::base::ReadFileToString(path_, &content)) {
+        MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
+        return;
+    }
+    if (content.empty()) {
+        MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
+        return;
+    }
+    std::vector<std::string> lines = android::base::Split(content, "\n");
+
+    if (lines.size() < 1) {
+        MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
+               (int)lines.size(), max_);
+        return;
+    }
+    char* ptr;
+    n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
+    average_max_ = strtol(ptr, nullptr, 10);
+    if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
+        average_max_ > STATS_MAX_AVERAGE) {
+        MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
+        initial_max_ = Progress::kDefaultMax;
+    } else {
+        initial_max_ = average_max_;
+    }
+    max_ = initial_max_;
+
+    MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
+}
+
+void Progress::Save() {
+    int32_t total = n_runs_ * average_max_ + progress_;
+    int32_t runs = n_runs_ + 1;
+    int32_t average = floor(((float)total) / runs);
+    MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
+           path_.c_str());
+    if (path_.empty()) {
+        return;
+    }
+
+    std::string content = android::base::StringPrintf("%d %d\n", runs, average);
+    if (!android::base::WriteStringToFile(content, path_)) {
+        MYLOGE("Could not save stats on %s\n", path_.c_str());
+    }
+}
+
+int32_t Progress::Get() const {
+    return progress_;
+}
+
+bool Progress::Inc(int32_t delta_sec) {
+    bool changed = false;
+    if (delta_sec >= 0) {
+        progress_ += delta_sec;
+        if (progress_ > max_) {
+            int32_t old_max = max_;
+            max_ = floor((float)progress_ * growth_factor_);
+            MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
+            changed = true;
+        }
+    }
+    return changed;
+}
+
+int32_t Progress::GetMax() const {
+    return max_;
+}
+
+int32_t Progress::GetInitialMax() const {
+    return initial_max_;
+}
+
+void Progress::Dump(int fd, const std::string& prefix) const {
+    const char* pr = prefix.c_str();
+    dprintf(fd, "%sprogress: %d\n", pr, progress_);
+    dprintf(fd, "%smax: %d\n", pr, max_);
+    dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
+    dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
+    dprintf(fd, "%spath: %s\n", pr, path_.c_str());
+    dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
+    dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
+}
+
+bool Dumpstate::IsZipping() const {
+    return zip_writer_ != nullptr;
+}
+
+std::string Dumpstate::GetPath(const std::string& suffix) const {
+    return GetPath(bugreport_internal_dir_, suffix);
+}
+
+std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
+    return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
+                                       name_.c_str(), suffix.c_str());
+}
+
+void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
+    progress_ = std::move(progress);
+}
+
+void for_each_userid(void (*func)(int), const char *header) {
+    std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
+                                                                    "for_each_userid(%s)", header);
+    DurationReporter duration_reporter(title);
+    if (PropertiesHelper::IsDryRun()) return;
+
+    DIR *d;
+    struct dirent *de;
+
+    if (header) printf("\n------ %s ------\n", header);
+    func(0);
+
+    if (!(d = opendir("/data/system/users"))) {
+        printf("Failed to open /data/system/users (%s)\n", strerror(errno));
+        return;
+    }
+
+    while ((de = readdir(d))) {
+        int userid;
+        if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
+            continue;
+        }
+        func(userid);
+    }
+
+    closedir(d);
+}
+
+static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
+    DIR *d;
+    struct dirent *de;
+
+    if (!(d = opendir("/proc"))) {
+        printf("Failed to open /proc (%s)\n", strerror(errno));
+        return;
+    }
+
+    if (header) printf("\n------ %s ------\n", header);
+    while ((de = readdir(d))) {
+        if (ds.IsUserConsentDenied()) {
+            MYLOGE(
+                "Returning early because user denied consent to share bugreport with calling app.");
+            closedir(d);
+            return;
+        }
+        int pid;
+        int fd;
+        char cmdpath[255];
+        char cmdline[255];
+
+        if (!(pid = atoi(de->d_name))) {
+            continue;
+        }
+
+        memset(cmdline, 0, sizeof(cmdline));
+
+        snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
+        if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
+            TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
+            close(fd);
+            if (cmdline[0]) {
+                helper(pid, cmdline, arg);
+                continue;
+            }
+        }
+
+        // if no cmdline, a kernel thread has comm
+        snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
+        if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
+            TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
+            close(fd);
+            if (cmdline[1]) {
+                cmdline[0] = '[';
+                size_t len = strcspn(cmdline, "\f\b\r\n");
+                cmdline[len] = ']';
+                cmdline[len+1] = '\0';
+            }
+        }
+        if (!cmdline[0]) {
+            strcpy(cmdline, "N/A");
+        }
+        helper(pid, cmdline, arg);
+    }
+
+    closedir(d);
+}
+
+static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
+    for_each_pid_func *func = (for_each_pid_func*) arg;
+    func(pid, cmdline);
+}
+
+void for_each_pid(for_each_pid_func func, const char *header) {
+    std::string title = header == nullptr ? "for_each_pid"
+                                          : android::base::StringPrintf("for_each_pid(%s)", header);
+    DurationReporter duration_reporter(title);
+    if (PropertiesHelper::IsDryRun()) return;
+
+    __for_each_pid(for_each_pid_helper, header, (void *) func);
+}
+
+static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
+    DIR *d;
+    struct dirent *de;
+    char taskpath[255];
+    for_each_tid_func *func = (for_each_tid_func *) arg;
+
+    snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
+
+    if (!(d = opendir(taskpath))) {
+        printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
+        return;
+    }
+
+    func(pid, pid, cmdline);
+
+    while ((de = readdir(d))) {
+        if (ds.IsUserConsentDenied()) {
+            MYLOGE(
+                "Returning early because user denied consent to share bugreport with calling app.");
+            closedir(d);
+            return;
+        }
+        int tid;
+        int fd;
+        char commpath[255];
+        char comm[255];
+
+        if (!(tid = atoi(de->d_name))) {
+            continue;
+        }
+
+        if (tid == pid)
+            continue;
+
+        snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
+        memset(comm, 0, sizeof(comm));
+        if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
+            strcpy(comm, "N/A");
+        } else {
+            char *c;
+            TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
+            close(fd);
+
+            c = strrchr(comm, '\n');
+            if (c) {
+                *c = '\0';
+            }
+        }
+        func(pid, tid, comm);
+    }
+
+    closedir(d);
+}
+
+void for_each_tid(for_each_tid_func func, const char *header) {
+    std::string title = header == nullptr ? "for_each_tid"
+                                          : android::base::StringPrintf("for_each_tid(%s)", header);
+    DurationReporter duration_reporter(title);
+
+    if (PropertiesHelper::IsDryRun()) return;
+
+    __for_each_pid(for_each_tid_helper, header, (void *) func);
+}
+
+void show_wchan(int pid, int tid, const char *name) {
+    if (PropertiesHelper::IsDryRun()) return;
+
+    char path[255];
+    char buffer[255];
+    int fd, ret, save_errno;
+    char name_buffer[255];
+
+    memset(buffer, 0, sizeof(buffer));
+
+    snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
+    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
+        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
+        return;
+    }
+
+    ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+    save_errno = errno;
+    close(fd);
+
+    if (ret < 0) {
+        printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
+        return;
+    }
+
+    snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
+             pid == tid ? 0 : 3, "", name);
+
+    printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
+
+    return;
+}
+
+// print time in centiseconds
+static void snprcent(char *buffer, size_t len, size_t spc,
+                     unsigned long long time) {
+    static long hz; // cache discovered hz
+
+    if (hz <= 0) {
+        hz = sysconf(_SC_CLK_TCK);
+        if (hz <= 0) {
+            hz = 1000;
+        }
+    }
+
+    // convert to centiseconds
+    time = (time * 100 + (hz / 2)) / hz;
+
+    char str[16];
+
+    snprintf(str, sizeof(str), " %llu.%02u",
+             time / 100, (unsigned)(time % 100));
+    size_t offset = strlen(buffer);
+    snprintf(buffer + offset, (len > offset) ? len - offset : 0,
+             "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
+}
+
+// print permille as a percent
+static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
+    char str[16];
+
+    snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
+    size_t offset = strlen(buffer);
+    snprintf(buffer + offset, (len > offset) ? len - offset : 0,
+             "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
+}
+
+void show_showtime(int pid, const char *name) {
+    if (PropertiesHelper::IsDryRun()) return;
+
+    char path[255];
+    char buffer[1023];
+    int fd, ret, save_errno;
+
+    memset(buffer, 0, sizeof(buffer));
+
+    snprintf(path, sizeof(path), "/proc/%d/stat", pid);
+    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
+        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
+        return;
+    }
+
+    ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+    save_errno = errno;
+    close(fd);
+
+    if (ret < 0) {
+        printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
+        return;
+    }
+
+    // field 14 is utime
+    // field 15 is stime
+    // field 42 is iotime
+    unsigned long long utime = 0, stime = 0, iotime = 0;
+    if (sscanf(buffer,
+               "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
+               "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
+               "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
+               "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
+               &utime, &stime, &iotime) != 3) {
+        return;
+    }
+
+    unsigned long long total = utime + stime;
+    if (!total) {
+        return;
+    }
+
+    unsigned permille = (iotime * 1000 + (total / 2)) / total;
+    if (permille > 1000) {
+        permille = 1000;
+    }
+
+    // try to beautify and stabilize columns at <80 characters
+    snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
+    if ((name[0] != '[') || utime) {
+        snprcent(buffer, sizeof(buffer), 57, utime);
+    }
+    snprcent(buffer, sizeof(buffer), 65, stime);
+    if ((name[0] != '[') || iotime) {
+        snprcent(buffer, sizeof(buffer), 73, iotime);
+    }
+    if (iotime) {
+        snprdec(buffer, sizeof(buffer), 79, permille);
+    }
+    puts(buffer);  // adds a trailing newline
+
+    return;
+}
+
+void do_dmesg() {
+    const char *title = "KERNEL LOG (dmesg)";
+    DurationReporter duration_reporter(title);
+    printf("------ %s ------\n", title);
+
+    if (PropertiesHelper::IsDryRun()) return;
+
+    /* Get size of kernel buffer */
+    int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
+    if (size <= 0) {
+        printf("Unexpected klogctl return value: %d\n\n", size);
+        return;
+    }
+    char *buf = (char *) malloc(size + 1);
+    if (buf == nullptr) {
+        printf("memory allocation failed\n\n");
+        return;
+    }
+    int retval = klogctl(KLOG_READ_ALL, buf, size);
+    if (retval < 0) {
+        printf("klogctl failure\n\n");
+        free(buf);
+        return;
+    }
+    buf[retval] = '\0';
+    printf("%s\n\n", buf);
+    free(buf);
+    return;
+}
+
+void do_showmap(int pid, const char *name) {
+    char title[255];
+    char arg[255];
+
+    snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
+    snprintf(arg, sizeof(arg), "%d", pid);
+    RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
+}
+
+int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
+    DurationReporter duration_reporter(title);
+
+    int status = DumpFileToFd(STDOUT_FILENO, title, path);
+
+    UpdateProgress(WEIGHT_FILE);
+
+    return status;
+}
+
+int read_file_as_long(const char *path, long int *output) {
+    int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
+    if (fd < 0) {
+        int err = errno;
+        MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
+        return -1;
+    }
+    char buffer[50];
+    ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+    if (bytes_read == -1) {
+        MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
+        return -2;
+    }
+    if (bytes_read == 0) {
+        MYLOGE("File %s is empty\n", path);
+        return -3;
+    }
+    *output = atoi(buffer);
+    return 0;
+}
+
+/* calls skip to gate calling dump_from_fd recursively
+ * in the specified directory. dump_from_fd defaults to
+ * dump_file_from_fd above when set to NULL. skip defaults
+ * to false when set to NULL. dump_from_fd will always be
+ * called with title NULL.
+ */
+int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
+               int (*dump_from_fd)(const char* title, const char* path, int fd)) {
+    DurationReporter duration_reporter(title);
+    DIR *dirp;
+    struct dirent *d;
+    char *newpath = nullptr;
+    const char *slash = "/";
+    int retval = 0;
+
+    if (!title.empty()) {
+        printf("------ %s (%s) ------\n", title.c_str(), dir);
+    }
+    if (PropertiesHelper::IsDryRun()) return 0;
+
+    if (dir[strlen(dir) - 1] == '/') {
+        ++slash;
+    }
+    dirp = opendir(dir);
+    if (dirp == nullptr) {
+        retval = -errno;
+        MYLOGE("%s: %s\n", dir, strerror(errno));
+        return retval;
+    }
+
+    if (!dump_from_fd) {
+        dump_from_fd = dump_file_from_fd;
+    }
+    for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
+        if ((d->d_name[0] == '.')
+         && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
+          || (d->d_name[1] == '\0'))) {
+            continue;
+        }
+        asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
+                 (d->d_type == DT_DIR) ? "/" : "");
+        if (!newpath) {
+            retval = -errno;
+            continue;
+        }
+        if (skip && (*skip)(newpath)) {
+            continue;
+        }
+        if (d->d_type == DT_DIR) {
+            int ret = dump_files("", newpath, skip, dump_from_fd);
+            if (ret < 0) {
+                retval = ret;
+            }
+            continue;
+        }
+        android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
+        if (fd.get() < 0) {
+            retval = -1;
+            printf("*** %s: %s\n", newpath, strerror(errno));
+            continue;
+        }
+        (*dump_from_fd)(nullptr, newpath, fd.get());
+    }
+    closedir(dirp);
+    if (!title.empty()) {
+        printf("\n");
+    }
+    return retval;
+}
+
+/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
+ * it's possible to avoid issues where opening the file itself can get
+ * stuck.
+ */
+int dump_file_from_fd(const char *title, const char *path, int fd) {
+    if (PropertiesHelper::IsDryRun()) return 0;
+
+    int flags = fcntl(fd, F_GETFL);
+    if (flags == -1) {
+        printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
+        return -1;
+    } else if (!(flags & O_NONBLOCK)) {
+        printf("*** %s: fd must have O_NONBLOCK set.\n", path);
+        return -1;
+    }
+    return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
+}
+
+int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
+                          const CommandOptions& options) {
+    DurationReporter duration_reporter(title);
+
+    int status = RunCommandToFd(STDOUT_FILENO, title, full_command, options);
+
+    /* TODO: for now we're simplifying the progress calculation by using the
+     * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
+     * where its weight should be much higher proportionally to its timeout.
+     * Ideally, it should use a options.EstimatedDuration() instead...*/
+    UpdateProgress(options.Timeout());
+
+    return status;
+}
+
+void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
+                           const CommandOptions& options, long dumpsysTimeoutMs) {
+    long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
+    std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
+    dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
+    RunCommand(title, dumpsys, options);
+}
+
+int open_socket(const char *service) {
+    int s = android_get_control_socket(service);
+    if (s < 0) {
+        MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
+        return -1;
+    }
+    fcntl(s, F_SETFD, FD_CLOEXEC);
+    if (listen(s, 4) < 0) {
+        MYLOGE("listen(control socket): %s\n", strerror(errno));
+        return -1;
+    }
+
+    struct sockaddr addr;
+    socklen_t alen = sizeof(addr);
+    int fd = accept(s, &addr, &alen);
+    if (fd < 0) {
+        MYLOGE("accept(control socket): %s\n", strerror(errno));
+        return -1;
+    }
+
+    return fd;
+}
+
+/* redirect output to a service control socket */
+bool redirect_to_socket(FILE* redirect, const char* service) {
+    int fd = open_socket(service);
+    if (fd == -1) {
+        return false;
+    }
+    fflush(redirect);
+    // TODO: handle dup2 failure
+    TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
+    close(fd);
+    return true;
+}
+
+// TODO: should call is_valid_output_file and/or be merged into it.
+void create_parent_dirs(const char *path) {
+    char *chp = const_cast<char *> (path);
+
+    /* skip initial slash */
+    if (chp[0] == '/')
+        chp++;
+
+    /* create leading directories, if necessary */
+    struct stat dir_stat;
+    while (chp && chp[0]) {
+        chp = strchr(chp, '/');
+        if (chp) {
+            *chp = 0;
+            if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
+                MYLOGI("Creating directory %s\n", path);
+                if (mkdir(path, 0770)) { /* drwxrwx--- */
+                    MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
+                } else if (chown(path, AID_SHELL, AID_SHELL)) {
+                    MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
+                }
+            }
+            *chp++ = '/';
+        }
+    }
+}
+
+bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
+    create_parent_dirs(path);
+
+    int fd = TEMP_FAILURE_RETRY(open(path,
+                                     O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
+                                     S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
+    if (fd < 0) {
+        MYLOGE("%s: %s\n", path, strerror(errno));
+        return false;
+    }
+
+    TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
+    close(fd);
+    return true;
+}
+
+bool redirect_to_file(FILE* redirect, char* path) {
+    return _redirect_to_file(redirect, path, O_TRUNC);
+}
+
+bool redirect_to_existing_file(FILE* redirect, char* path) {
+    return _redirect_to_file(redirect, path, O_APPEND);
+}
+
+void dump_route_tables() {
+    DurationReporter duration_reporter("DUMP ROUTE TABLES");
+    if (PropertiesHelper::IsDryRun()) return;
+    const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
+    ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
+    FILE* fp = fopen(RT_TABLES_PATH, "re");
+    if (!fp) {
+        printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
+        return;
+    }
+    char table[16];
+    // Each line has an integer (the table number), a space, and a string (the table name). We only
+    // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
+    // Add a fixed max limit so this doesn't go awry.
+    for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
+        RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
+        RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
+    }
+    fclose(fp);
+}
+
+// TODO: make this function thread safe if sections are generated in parallel.
+void Dumpstate::UpdateProgress(int32_t delta_sec) {
+    if (progress_ == nullptr) {
+        MYLOGE("UpdateProgress: progress_ not set\n");
+        return;
+    }
+
+    // Always update progess so stats can be tuned...
+    bool max_changed = progress_->Inc(delta_sec);
+
+    // ...but only notifiy listeners when necessary.
+    if (!options_->do_progress_updates) return;
+
+    int progress = progress_->Get();
+    int max = progress_->GetMax();
+
+    // adjusts max on the fly
+    if (max_changed && listener_ != nullptr) {
+        listener_->onMaxProgressUpdated(max);
+    }
+
+    int32_t last_update_delta = progress - last_updated_progress_;
+    if (last_updated_progress_ > 0 && last_update_delta < update_progress_threshold_) {
+        return;
+    }
+    last_updated_progress_ = progress;
+
+    if (control_socket_fd_ >= 0) {
+        dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
+        fsync(control_socket_fd_);
+    }
+
+    int percent = 100 * progress / max;
+    if (listener_ != nullptr) {
+        if (percent % 5 == 0) {
+            // We don't want to spam logcat, so only log multiples of 5.
+            MYLOGD("Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(), progress, max,
+                   percent);
+        } else {
+            // stderr is ignored on normal invocations, but useful when calling
+            // /system/bin/dumpstate directly for debuggging.
+            fprintf(stderr, "Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(),
+                    progress, max, percent);
+        }
+        // TODO(b/111441001): Remove in favor of onProgress
+        listener_->onProgressUpdated(progress);
+
+        listener_->onProgress(percent);
+    }
+}
+
+void Dumpstate::TakeScreenshot(const std::string& path) {
+    const std::string& real_path = path.empty() ? screenshot_path_ : path;
+    int status =
+        RunCommand("", {"/system/bin/screencap", "-p", real_path},
+                   CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
+    if (status == 0) {
+        MYLOGD("Screenshot saved on %s\n", real_path.c_str());
+    } else {
+        MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
+    }
+}
+
+bool is_dir(const char* pathname) {
+    struct stat info;
+    if (stat(pathname, &info) == -1) {
+        return false;
+    }
+    return S_ISDIR(info.st_mode);
+}
+
+time_t get_mtime(int fd, time_t default_mtime) {
+    struct stat info;
+    if (fstat(fd, &info) == -1) {
+        return default_mtime;
+    }
+    return info.st_mtime;
+}
+
+void dump_emmc_ecsd(const char *ext_csd_path) {
+    // List of interesting offsets
+    struct hex {
+        char str[2];
+    };
+    static const size_t EXT_CSD_REV = 192 * sizeof(hex);
+    static const size_t EXT_PRE_EOL_INFO = 267 * sizeof(hex);
+    static const size_t EXT_DEVICE_LIFE_TIME_EST_TYP_A = 268 * sizeof(hex);
+    static const size_t EXT_DEVICE_LIFE_TIME_EST_TYP_B = 269 * sizeof(hex);
+
+    std::string buffer;
+    if (!android::base::ReadFileToString(ext_csd_path, &buffer)) {
+        return;
+    }
+
+    printf("------ %s Extended CSD ------\n", ext_csd_path);
+
+    if (buffer.length() < (EXT_CSD_REV + sizeof(hex))) {
+        printf("*** %s: truncated content %zu\n\n", ext_csd_path, buffer.length());
+        return;
+    }
+
+    int ext_csd_rev = 0;
+    std::string sub = buffer.substr(EXT_CSD_REV, sizeof(hex));
+    if (sscanf(sub.c_str(), "%2x", &ext_csd_rev) != 1) {
+        printf("*** %s: EXT_CSD_REV parse error \"%s\"\n\n", ext_csd_path, sub.c_str());
+        return;
+    }
+
+    static const char *ver_str[] = {
+        "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0"
+    };
+    printf("rev 1.%d (MMC %s)\n", ext_csd_rev,
+           (ext_csd_rev < (int)(sizeof(ver_str) / sizeof(ver_str[0]))) ? ver_str[ext_csd_rev]
+                                                                       : "Unknown");
+    if (ext_csd_rev < 7) {
+        printf("\n");
+        return;
+    }
+
+    if (buffer.length() < (EXT_PRE_EOL_INFO + sizeof(hex))) {
+        printf("*** %s: truncated content %zu\n\n", ext_csd_path, buffer.length());
+        return;
+    }
+
+    int ext_pre_eol_info = 0;
+    sub = buffer.substr(EXT_PRE_EOL_INFO, sizeof(hex));
+    if (sscanf(sub.c_str(), "%2x", &ext_pre_eol_info) != 1) {
+        printf("*** %s: PRE_EOL_INFO parse error \"%s\"\n\n", ext_csd_path, sub.c_str());
+        return;
+    }
+
+    static const char *eol_str[] = {
+        "Undefined",
+        "Normal",
+        "Warning (consumed 80% of reserve)",
+        "Urgent (consumed 90% of reserve)"
+    };
+    printf(
+        "PRE_EOL_INFO %d (MMC %s)\n", ext_pre_eol_info,
+        eol_str[(ext_pre_eol_info < (int)(sizeof(eol_str) / sizeof(eol_str[0]))) ? ext_pre_eol_info
+                                                                                 : 0]);
+
+    for (size_t lifetime = EXT_DEVICE_LIFE_TIME_EST_TYP_A;
+            lifetime <= EXT_DEVICE_LIFE_TIME_EST_TYP_B;
+            lifetime += sizeof(hex)) {
+        int ext_device_life_time_est;
+        static const char *est_str[] = {
+            "Undefined",
+            "0-10% of device lifetime used",
+            "10-20% of device lifetime used",
+            "20-30% of device lifetime used",
+            "30-40% of device lifetime used",
+            "40-50% of device lifetime used",
+            "50-60% of device lifetime used",
+            "60-70% of device lifetime used",
+            "70-80% of device lifetime used",
+            "80-90% of device lifetime used",
+            "90-100% of device lifetime used",
+            "Exceeded the maximum estimated device lifetime",
+        };
+
+        if (buffer.length() < (lifetime + sizeof(hex))) {
+            printf("*** %s: truncated content %zu\n", ext_csd_path, buffer.length());
+            break;
+        }
+
+        ext_device_life_time_est = 0;
+        sub = buffer.substr(lifetime, sizeof(hex));
+        if (sscanf(sub.c_str(), "%2x", &ext_device_life_time_est) != 1) {
+            printf("*** %s: DEVICE_LIFE_TIME_EST_TYP_%c parse error \"%s\"\n", ext_csd_path,
+                   (unsigned)((lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) / sizeof(hex)) + 'A',
+                   sub.c_str());
+            continue;
+        }
+        printf("DEVICE_LIFE_TIME_EST_TYP_%c %d (MMC %s)\n",
+               (unsigned)((lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) / sizeof(hex)) + 'A',
+               ext_device_life_time_est,
+               est_str[(ext_device_life_time_est < (int)(sizeof(est_str) / sizeof(est_str[0])))
+                           ? ext_device_life_time_est
+                           : 0]);
+    }
+
+    printf("\n");
+}
diff --git a/cmds/dumpsys/TEST_MAPPING b/cmds/dumpsys/TEST_MAPPING
deleted file mode 100644
index dc88ada..0000000
--- a/cmds/dumpsys/TEST_MAPPING
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "presubmit": [
-    {
-      // small test which assumes the output format of dumpsys, however
-      // there are many other parts of Android that expect the output
-      // to be a specific way (see b/141728094)
-      "name": "timezone_data_e2e_tests"
-    },
-    {
-      "name": "dumpsys_test"
-    }
-  ]
-}
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index abdf168..4811927 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -59,13 +59,12 @@
             "usage: dumpsys\n"
             "         To dump all services.\n"
             "or:\n"
-            "       dumpsys [-t TIMEOUT] [--priority LEVEL] [--pid] [--help | -l | --skip SERVICES "
-            "| SERVICE [ARGS]]\n"
+            "       dumpsys [-t TIMEOUT] [--priority LEVEL] [--help | -l | --skip SERVICES | "
+            "SERVICE [ARGS]]\n"
             "         --help: shows this help\n"
             "         -l: only list services, do not dump them\n"
             "         -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n"
             "         -T TIMEOUT_MS: TIMEOUT to use in milliseconds instead of default 10 seconds\n"
-            "         --pid: dump PID instead of usual dump\n"
             "         --proto: filter services that support dumping data in proto format. Dumps\n"
             "               will be in proto format.\n"
             "         --priority LEVEL: filter services based on specified priority\n"
@@ -121,11 +120,9 @@
     bool showListOnly = false;
     bool skipServices = false;
     bool asProto = false;
-    Type type = Type::DUMP;
     int timeoutArgMs = 10000;
     int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL;
-    static struct option longOptions[] = {{"pid", no_argument, 0, 0},
-                                          {"priority", required_argument, 0, 0},
+    static struct option longOptions[] = {{"priority", required_argument, 0, 0},
                                           {"proto", no_argument, 0, 0},
                                           {"skip", no_argument, 0, 0},
                                           {"help", no_argument, 0, 0},
@@ -160,8 +157,6 @@
                     usage();
                     return -1;
                 }
-            } else if (!strcmp(longOptions[optionIndex].name, "pid")) {
-                type = Type::PID;
             }
             break;
 
@@ -206,13 +201,7 @@
             if (i == optind) {
                 services.add(String16(argv[i]));
             } else {
-                const String16 arg(argv[i]);
-                args.add(arg);
-                // For backward compatible, if the proto argument is passed to the service, the
-                // dump request is also considered to use proto.
-                if (!asProto && !arg.compare(String16(PriorityDumper::PROTO_ARG))) {
-                    asProto = true;
-                }
+                args.add(String16(argv[i]));
             }
         }
     }
@@ -251,7 +240,7 @@
         const String16& serviceName = services[i];
         if (IsSkipped(skippedServices, serviceName)) continue;
 
-        if (startDumpThread(type, serviceName, args) == OK) {
+        if (startDumpThread(serviceName, args) == OK) {
             bool addSeparator = (N > 1);
             if (addSeparator) {
                 writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags);
@@ -318,18 +307,7 @@
     }
 }
 
-static status_t dumpPidToFd(const sp<IBinder>& service, const unique_fd& fd) {
-     pid_t pid;
-     status_t status = service->getDebugPid(&pid);
-     if (status != OK) {
-         return status;
-     }
-     WriteStringToFd(std::to_string(pid) + "\n", fd.get());
-     return OK;
-}
-
-status_t Dumpsys::startDumpThread(Type type, const String16& serviceName,
-                                  const Vector<String16>& args) {
+status_t Dumpsys::startDumpThread(const String16& serviceName, const Vector<String16>& args) {
     sp<IBinder> service = sm_->checkService(serviceName);
     if (service == nullptr) {
         aerr << "Can't find service: " << serviceName << endl;
@@ -349,22 +327,16 @@
 
     // dump blocks until completion, so spawn a thread..
     activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable {
-        status_t err = 0;
+        int err = service->dump(remote_end.get(), args);
 
-        switch (type) {
-        case Type::DUMP:
-            err = service->dump(remote_end.get(), args);
-            break;
-        case Type::PID:
-            err = dumpPidToFd(service, remote_end);
-            break;
-        default:
-            aerr << "Unknown dump type" << static_cast<int>(type) << endl;
-            return;
-        }
+        // It'd be nice to be able to close the remote end of the socketpair before the dump
+        // call returns, to terminate our reads if the other end closes their copy of the
+        // file descriptor, but then hangs for some reason. There doesn't seem to be a good
+        // way to do this, though.
+        remote_end.reset();
 
-        if (err != OK) {
-            aerr << "Error dumping service info status_t: (" << err << ") "
+        if (err != 0) {
+            aerr << "Error dumping service info: (" << strerror(err) << ") "
                  << serviceName << endl;
         }
     });
diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h
index 929c55c..c48a1e9 100644
--- a/cmds/dumpsys/dumpsys.h
+++ b/cmds/dumpsys/dumpsys.h
@@ -51,11 +51,6 @@
      */
     static void setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags);
 
-    enum class Type {
-        DUMP,  // dump using `dump` function
-        PID,   // dump pid of server only
-    };
-
     /**
      * Starts a thread to connect to a service and get its dump output. The thread redirects
      * the output to a pipe. Thread must be stopped by a subsequent callto {@code
@@ -66,8 +61,7 @@
      *         {@code NAME_NOT_FOUND} service could not be found.
      *         {@code != OK} error
      */
-    status_t startDumpThread(Type type, const String16& serviceName,
-                             const Vector<String16>& args);
+    status_t startDumpThread(const String16& serviceName, const Vector<String16>& args);
 
     /**
      * Writes a section header to a file descriptor.
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index b9395ba..3ada153 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -53,8 +53,7 @@
     MOCK_CONST_METHOD1(checkService, sp<IBinder>(const String16&));
     MOCK_METHOD4(addService, status_t(const String16&, const sp<IBinder>&, bool, int));
     MOCK_METHOD1(listServices, Vector<String16>(int));
-    MOCK_METHOD1(waitForService, sp<IBinder>(const String16&));
-    MOCK_METHOD1(isDeclared, bool(const String16&));
+
   protected:
     MOCK_METHOD0(onAsBinder, IBinder*());
 };
@@ -195,7 +194,7 @@
         CaptureStdout();
         CaptureStderr();
         dump_.setServiceArgs(args, supportsProto, priorityFlags);
-        status_t status = dump_.startDumpThread(Dumpsys::Type::DUMP, serviceName, args);
+        status_t status = dump_.startDumpThread(serviceName, args);
         EXPECT_THAT(status, Eq(0));
         status = dump_.writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(500), false,
                                  elapsedDuration, bytesWritten);
@@ -540,27 +539,6 @@
     AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH);
 }
 
-// Tests 'dumpsys --pid'
-TEST_F(DumpsysTest, ListAllServicesWithPid) {
-    ExpectListServices({"Locksmith", "Valet"});
-    ExpectCheckService("Locksmith");
-    ExpectCheckService("Valet");
-
-    CallMain({"--pid"});
-
-    AssertRunningServices({"Locksmith", "Valet"});
-    AssertOutputContains(std::to_string(getpid()));
-}
-
-// Tests 'dumpsys --pid service_name'
-TEST_F(DumpsysTest, ListServiceWithPid) {
-    ExpectCheckService("Locksmith");
-
-    CallMain({"--pid", "Locksmith"});
-
-    AssertOutput(std::to_string(getpid()) + "\n");
-}
-
 TEST_F(DumpsysTest, GetBytesWritten) {
     const char* serviceName = "service2";
     const char* dumpContents = "dump1";
@@ -585,4 +563,4 @@
         dump_.writeDump(STDOUT_FILENO, String16("service"), std::chrono::milliseconds(500),
                         /* as_proto = */ false, elapsedDuration, bytesWritten);
     EXPECT_THAT(status, Eq(INVALID_OPERATION));
-}
+}
\ No newline at end of file
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
deleted file mode 100644
index 40b8dc7..0000000
--- a/cmds/idlcli/Android.bp
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (C) 2019 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.
-
-cc_defaults {
-    name: "idlcli-defaults",
-    shared_libs: [
-        "android.hardware.vibrator@1.0",
-        "android.hardware.vibrator@1.1",
-        "android.hardware.vibrator@1.2",
-        "android.hardware.vibrator@1.3",
-        "libbase",
-        "libhidlbase",
-        "liblog",
-        "libutils",
-    ],
-    cflags: [
-        "-DLOG_TAG=\"idlcli\"",
-    ],
-}
-
-cc_library {
-    name: "libidlcli",
-    defaults: ["idlcli-defaults"],
-    srcs: [
-        "CommandVibrator.cpp",
-        "vibrator/CommandOff.cpp",
-        "vibrator/CommandOn.cpp",
-        "vibrator/CommandPerform.cpp",
-        "vibrator/CommandSetAmplitude.cpp",
-        "vibrator/CommandSetExternalControl.cpp",
-        "vibrator/CommandSupportsAmplitudeControl.cpp",
-        "vibrator/CommandSupportsExternalControl.cpp",
-    ],
-    visibility: [":__subpackages__"],
-}
-
-cc_binary {
-    name: "idlcli",
-    defaults: ["idlcli-defaults"],
-    srcs: ["main.cpp"],
-    whole_static_libs: ["libidlcli"],
-}
diff --git a/cmds/idlcli/CommandVibrator.cpp b/cmds/idlcli/CommandVibrator.cpp
deleted file mode 100644
index a7a70c3..0000000
--- a/cmds/idlcli/CommandVibrator.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "utils.h"
-
-namespace android {
-namespace idlcli {
-
-class IdlCli;
-
-class CommandVibrator : public CommandWithSubcommands<CommandVibrator> {
-    std::string getDescription() const override { return "Invoke Vibrator HIDL APIs."; }
-
-    std::string getUsageSummary() const override { return "<api> [arguments]"; }
-
-    UsageDetails getUsageDetails() const override {
-        UsageDetails details{
-                {"<api>", CommandRegistry<CommandVibrator>::List()},
-        };
-        return details;
-    }
-};
-
-static const auto Command = CommandRegistry<IdlCli>::Register<CommandVibrator>("vibrator");
-
-} // namespace idlcli
-} // namespace android
diff --git a/cmds/idlcli/IdlCli.h b/cmds/idlcli/IdlCli.h
deleted file mode 100644
index dd84304..0000000
--- a/cmds/idlcli/IdlCli.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef FRAMEWORK_NATIVE_CMDS_IDLCLI_IDLCLI_H_
-#define FRAMEWORK_NATIVE_CMDS_IDLCLI_IDLCLI_H_
-
-#include "utils.h"
-
-namespace android {
-namespace idlcli {
-
-class IdlCli : public CommandWithSubcommands<IdlCli> {
-    std::string getDescription() const override { return "Invoke IDL APIs."; }
-
-    std::string getUsageSummary() const override { return "<idl> [arguments]"; }
-
-    UsageDetails getUsageDetails() const override {
-        UsageDetails details{
-                {"<idl>", CommandRegistry<IdlCli>::List()},
-        };
-        return details;
-    }
-};
-
-} // namespace idlcli
-} // namespace android
-
-#endif // FRAMEWORK_NATIVE_CMDS_IDLCLI_IDLCLI_H_
diff --git a/cmds/idlcli/main.cpp b/cmds/idlcli/main.cpp
deleted file mode 100644
index 9ed9d82..0000000
--- a/cmds/idlcli/main.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "IdlCli.h"
-#include "utils.h"
-
-int main(const int argc, const char* const argv[]) {
-    using namespace ::android::idlcli;
-    return IdlCli{}.main(Args{argc, argv});
-}
diff --git a/cmds/idlcli/utils.h b/cmds/idlcli/utils.h
deleted file mode 100644
index a8e5954..0000000
--- a/cmds/idlcli/utils.h
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef FRAMEWORK_NATIVE_CMDS_IDLCLI_UTILS_H_
-#define FRAMEWORK_NATIVE_CMDS_IDLCLI_UTILS_H_
-
-#include <hidl/HidlSupport.h>
-
-#include <iomanip>
-#include <iostream>
-#include <map>
-#include <sstream>
-#include <string>
-#include <vector>
-
-namespace android {
-namespace idlcli {
-
-namespace overrides {
-
-namespace details {
-
-template <typename T>
-inline std::istream &operator>>(std::istream &stream, T &out) {
-    auto pos = stream.tellg();
-    auto tmp = +out;
-    auto min = +std::numeric_limits<T>::min();
-    auto max = +std::numeric_limits<T>::max();
-    stream >> tmp;
-    if (!stream) {
-        return stream;
-    }
-    if (tmp < min || tmp > max) {
-        stream.seekg(pos);
-        stream.setstate(std::ios_base::failbit);
-        return stream;
-    }
-    out = tmp;
-    return stream;
-}
-
-} // namespace details
-
-// override for default behavior of treating as a character
-inline std::istream &operator>>(std::istream &stream, int8_t &out) {
-    return details::operator>>(stream, out);
-}
-
-// override for default behavior of treating as a character
-inline std::istream &operator>>(std::istream &stream, uint8_t &out) {
-    return details::operator>>(stream, out);
-}
-
-} // namespace overrides
-
-template <typename T, typename R = hardware::hidl_enum_range<T>>
-inline std::istream &operator>>(std::istream &stream, T &out) {
-    using overrides::operator>>;
-    auto validRange = R();
-    auto pos = stream.tellg();
-    std::underlying_type_t<T> in;
-    T tmp;
-    stream >> in;
-    if (!stream) {
-        return stream;
-    }
-    tmp = static_cast<T>(in);
-    if (tmp < *validRange.begin() || tmp > *std::prev(validRange.end())) {
-        stream.seekg(pos);
-        stream.setstate(std::ios_base::failbit);
-        return stream;
-    }
-    out = tmp;
-    return stream;
-}
-
-enum Status : unsigned int {
-    OK,
-    USAGE,
-    UNAVAILABLE,
-    ERROR,
-};
-
-class Args {
-public:
-    Args(const int argc, const char *const argv[]) {
-        for (int argi = 0; argi < argc; argi++) {
-            mArgs.emplace_back(std::string_view(argv[argi]));
-        }
-    }
-
-    template <typename T = std::string>
-    std::optional<T> get() {
-        return get<T>(false);
-    }
-
-    template <typename T = std::string>
-    std::optional<T> pop() {
-        return get<T>(true);
-    }
-
-    bool empty() { return mArgs.empty(); }
-
-private:
-    template <typename T>
-    std::optional<T> get(bool erase) {
-        using idlcli::operator>>;
-        using overrides::operator>>;
-        T retValue;
-
-        if (mArgs.empty()) {
-            return {};
-        }
-
-        std::stringstream stream{std::string{mArgs.front()}};
-        stream >> std::setbase(0) >> retValue;
-        if (!stream || !stream.eof()) {
-            return {};
-        }
-
-        if (erase) {
-            mArgs.erase(mArgs.begin());
-        }
-
-        return retValue;
-    }
-
-    std::vector<std::string_view> mArgs;
-};
-
-class Command {
-protected:
-    struct Usage {
-        std::string name;
-        std::vector<std::string> details;
-    };
-    using UsageDetails = std::vector<Usage>;
-
-public:
-    virtual ~Command() = default;
-
-    Status main(Args &&args) {
-        Status status = doArgsAndMain(std::move(args));
-        if (status == USAGE) {
-            printUsage();
-            return ERROR;
-        }
-        if (status == UNAVAILABLE) {
-            std::cerr << "The requested operation is unavailable." << std::endl;
-            return ERROR;
-        }
-        return status;
-    }
-
-private:
-    virtual std::string getDescription() const = 0;
-    virtual std::string getUsageSummary() const = 0;
-    virtual UsageDetails getUsageDetails() const = 0;
-    virtual Status doArgs(Args &args) = 0;
-    virtual Status doMain(Args &&args) = 0;
-
-    void printUsage() const {
-        std::cerr << "Description:\n  " << getDescription() << std::endl;
-        std::cerr << "Usage:\n  " << mName << " " << getUsageSummary() << std::endl;
-
-        std::cerr << "Details:" << std::endl;
-        size_t entryNameWidth = 0;
-        for (auto &entry : getUsageDetails()) {
-            entryNameWidth = std::max(entryNameWidth, entry.name.length());
-        }
-        for (auto &entry : getUsageDetails()) {
-            auto prefix = entry.name;
-            for (auto &line : entry.details) {
-                std::cerr << "  " << std::left << std::setw(entryNameWidth + 8) << prefix << line
-                          << std::endl;
-                prefix = "";
-            }
-        }
-    }
-
-    Status doArgsAndMain(Args &&args) {
-        Status status;
-        mName = *args.pop();
-        if ((status = doArgs(args)) != OK) {
-            return status;
-        }
-        if ((status = doMain(std::move(args))) != OK) {
-            return status;
-        }
-        return OK;
-    }
-
-protected:
-    std::string mName;
-};
-
-template <typename T>
-class CommandRegistry {
-private:
-    using CommandCreator = std::function<std::unique_ptr<Command>()>;
-
-public:
-    template <typename U>
-    static CommandCreator Register(const std::string name) {
-        Instance()->mCommands[name] = [] { return std::make_unique<U>(); };
-        return Instance()->mCommands[name];
-    }
-
-    static std::unique_ptr<Command> Create(const std::string name) {
-        auto it = Instance()->mCommands.find(name);
-        if (it == Instance()->mCommands.end()) {
-            return nullptr;
-        }
-        return it->second();
-    }
-
-    static auto List() {
-        std::vector<std::string> list;
-        for (auto &it : Instance()->mCommands) {
-            list.push_back(it.first);
-        }
-        std::sort(list.begin(), list.end());
-        return list;
-    }
-
-private:
-    static CommandRegistry *Instance() {
-        static CommandRegistry sRegistry;
-        return &sRegistry;
-    }
-
-private:
-    std::map<const std::string, CommandCreator> mCommands;
-};
-
-template <typename T>
-class CommandWithSubcommands : public Command {
-private:
-    Status doArgs(Args &args) override {
-        mCommand = CommandRegistry<T>::Create(*args.get());
-        if (!mCommand) {
-            std::cerr << "Invalid Command!" << std::endl;
-            return USAGE;
-        }
-        return OK;
-    }
-
-    Status doMain(Args &&args) override { return mCommand->main(std::move(args)); }
-
-protected:
-    std::unique_ptr<Command> mCommand;
-};
-
-} // namespace idlcli
-} // namespace android
-
-#endif // FRAMEWORK_NATIVE_CMDS_IDLCLI_UTILS_H_
diff --git a/cmds/idlcli/vibrator.h b/cmds/idlcli/vibrator.h
deleted file mode 100644
index bcb207b..0000000
--- a/cmds/idlcli/vibrator.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
-#define FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
-
-#include <android/hardware/vibrator/1.3/IVibrator.h>
-
-#include "utils.h"
-
-#include "log/log.h"
-
-namespace android {
-
-using hardware::Return;
-
-static constexpr int NUM_TRIES = 2;
-
-// Creates a Return<R> with STATUS::EX_NULL_POINTER.
-template <class R>
-inline Return<R> NullptrStatus() {
-    using ::android::hardware::Status;
-    return Return<R>{Status::fromExceptionCode(Status::EX_NULL_POINTER)};
-}
-
-template <typename I>
-class HalWrapper {
-public:
-    static std::unique_ptr<HalWrapper> Create() {
-        // Assume that if getService returns a nullptr, HAL is not available on the
-        // device.
-        auto hal = I::getService();
-        return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr;
-    }
-
-    template <class R, class... Args0, class... Args1>
-    Return<R> call(Return<R> (I::*fn)(Args0...), Args1&&... args1) {
-        return (*mHal.*fn)(std::forward<Args1>(args1)...);
-    }
-
-private:
-    HalWrapper(sp<I>&& hal) : mHal(std::move(hal)) {}
-
-private:
-    sp<I> mHal;
-};
-
-template <typename I>
-static auto getHal() {
-    static auto sHalWrapper = HalWrapper<I>::Create();
-    return sHalWrapper.get();
-}
-
-template <class R, class I, class... Args0, class... Args1>
-Return<R> halCall(Return<R> (I::*fn)(Args0...), Args1&&... args1) {
-    auto hal = getHal<I>();
-    return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>();
-}
-
-namespace idlcli {
-namespace vibrator {
-
-namespace V1_0 = ::android::hardware::vibrator::V1_0;
-namespace V1_1 = ::android::hardware::vibrator::V1_1;
-namespace V1_2 = ::android::hardware::vibrator::V1_2;
-namespace V1_3 = ::android::hardware::vibrator::V1_3;
-
-} // namespace vibrator
-} // namespace idlcli
-
-} // namespace android
-
-#endif // FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
diff --git a/cmds/idlcli/vibrator/CommandOff.cpp b/cmds/idlcli/vibrator/CommandOff.cpp
deleted file mode 100644
index a674f01..0000000
--- a/cmds/idlcli/vibrator/CommandOff.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "utils.h"
-#include "vibrator.h"
-
-namespace android {
-namespace idlcli {
-
-class CommandVibrator;
-
-namespace vibrator {
-
-class CommandOff : public Command {
-    std::string getDescription() const override { return "Turn off vibrator."; }
-
-    std::string getUsageSummary() const override { return ""; }
-
-    UsageDetails getUsageDetails() const override {
-        UsageDetails details{};
-        return details;
-    }
-
-    Status doArgs(Args &args) override {
-        if (!args.empty()) {
-            std::cerr << "Unexpected Arguments!" << std::endl;
-            return USAGE;
-        }
-        return OK;
-    }
-
-    Status doMain(Args && /*args*/) override {
-        auto ret = halCall(&V1_0::IVibrator::off);
-
-        if (!ret.isOk()) {
-            return UNAVAILABLE;
-        }
-
-        std::cout << "Status: " << toString(ret) << std::endl;
-
-        return ret == V1_0::Status::OK ? OK : ERROR;
-    }
-};
-
-static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandOff>("off");
-
-} // namespace vibrator
-} // namespace idlcli
-} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandOn.cpp b/cmds/idlcli/vibrator/CommandOn.cpp
deleted file mode 100644
index 2164b7d..0000000
--- a/cmds/idlcli/vibrator/CommandOn.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "utils.h"
-#include "vibrator.h"
-
-namespace android {
-namespace idlcli {
-
-class CommandVibrator;
-
-namespace vibrator {
-
-class CommandOn : public Command {
-    std::string getDescription() const override { return "Turn on vibrator."; }
-
-    std::string getUsageSummary() const override { return "<duration>"; }
-
-    UsageDetails getUsageDetails() const override {
-        UsageDetails details{
-                {"<duration>", {"In milliseconds."}},
-        };
-        return details;
-    }
-
-    Status doArgs(Args &args) override {
-        if (auto duration = args.pop<decltype(mDuration)>()) {
-            mDuration = *duration;
-        } else {
-            std::cerr << "Missing or Invalid Duration!" << std::endl;
-            return USAGE;
-        }
-        if (!args.empty()) {
-            std::cerr << "Unexpected Arguments!" << std::endl;
-            return USAGE;
-        }
-        return OK;
-    }
-
-    Status doMain(Args && /*args*/) override {
-        auto ret = halCall(&V1_0::IVibrator::on, mDuration);
-
-        if (!ret.isOk()) {
-            return UNAVAILABLE;
-        }
-
-        std::cout << "Status: " << toString(ret) << std::endl;
-
-        return ret == V1_0::Status::OK ? OK : ERROR;
-    }
-
-    uint32_t mDuration;
-};
-
-static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandOn>("on");
-
-} // namespace vibrator
-} // namespace idlcli
-} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandPerform.cpp b/cmds/idlcli/vibrator/CommandPerform.cpp
deleted file mode 100644
index 688cbd8..0000000
--- a/cmds/idlcli/vibrator/CommandPerform.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "utils.h"
-#include "vibrator.h"
-
-namespace android {
-namespace idlcli {
-
-class CommandVibrator;
-
-namespace vibrator {
-
-using V1_0::EffectStrength;
-using V1_3::Effect;
-
-class CommandPerform : public Command {
-    std::string getDescription() const override { return "Perform vibration effect."; }
-
-    std::string getUsageSummary() const override { return "<effect> <strength>"; }
-
-    UsageDetails getUsageDetails() const override {
-        UsageDetails details{
-                {"<effect>", {"Effect ID."}},
-                {"<strength>", {"0-2."}},
-        };
-        return details;
-    }
-
-    Status doArgs(Args &args) override {
-        if (auto effect = args.pop<decltype(mEffect)>()) {
-            mEffect = *effect;
-            std::cout << "Effect: " << toString(mEffect) << std::endl;
-        } else {
-            std::cerr << "Missing or Invalid Effect!" << std::endl;
-            return USAGE;
-        }
-        if (auto strength = args.pop<decltype(mStrength)>()) {
-            mStrength = *strength;
-            std::cout << "Strength: " << toString(mStrength) << std::endl;
-        } else {
-            std::cerr << "Missing or Invalid Strength!" << std::endl;
-            return USAGE;
-        }
-        if (!args.empty()) {
-            std::cerr << "Unexpected Arguments!" << std::endl;
-            return USAGE;
-        }
-        return OK;
-    }
-
-    Status doMain(Args && /*args*/) override {
-        Return<void> ret;
-        V1_0::Status status;
-        uint32_t lengthMs;
-        auto callback = [&status, &lengthMs](V1_0::Status retStatus, uint32_t retLengthMs) {
-            status = retStatus;
-            lengthMs = retLengthMs;
-        };
-
-        if (auto hal = getHal<V1_3::IVibrator>()) {
-            ret = hal->call(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(mEffect),
-                            mStrength, callback);
-        } else if (auto hal = getHal<V1_2::IVibrator>()) {
-            ret = hal->call(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(mEffect),
-                            mStrength, callback);
-        } else if (auto hal = getHal<V1_1::IVibrator>()) {
-            ret = hal->call(&V1_1::IVibrator::perform_1_1, static_cast<V1_1::Effect_1_1>(mEffect),
-                            mStrength, callback);
-        } else if (auto hal = getHal<V1_0::IVibrator>()) {
-            ret = hal->call(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(mEffect),
-                            mStrength, callback);
-        } else {
-            ret = NullptrStatus<void>();
-        }
-
-        if (!ret.isOk()) {
-            return UNAVAILABLE;
-        }
-
-        std::cout << "Status: " << toString(status) << std::endl;
-        std::cout << "Length: " << lengthMs << std::endl;
-
-        return status == V1_0::Status::OK ? OK : ERROR;
-    }
-
-    Effect mEffect;
-    EffectStrength mStrength;
-};
-
-static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandPerform>("perform");
-
-} // namespace vibrator
-} // namespace idlcli
-} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandSetAmplitude.cpp b/cmds/idlcli/vibrator/CommandSetAmplitude.cpp
deleted file mode 100644
index 38a1dc2..0000000
--- a/cmds/idlcli/vibrator/CommandSetAmplitude.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "utils.h"
-#include "vibrator.h"
-
-namespace android {
-namespace idlcli {
-
-class CommandVibrator;
-
-namespace vibrator {
-
-class CommandSetAmplitude : public Command {
-    std::string getDescription() const override { return "Set vibration amplitude."; }
-
-    std::string getUsageSummary() const override { return "<amplitude>"; }
-
-    UsageDetails getUsageDetails() const override {
-        UsageDetails details{
-                {"<amplitude>", {"1-255."}},
-        };
-        return details;
-    }
-
-    Status doArgs(Args &args) override {
-        if (auto amplitude = args.pop<decltype(mAmplitude)>()) {
-            mAmplitude = *amplitude;
-        } else {
-            std::cerr << "Missing or Invalid Amplitude!" << std::endl;
-            return USAGE;
-        }
-        if (!args.empty()) {
-            std::cerr << "Unexpected Arguments!" << std::endl;
-            return USAGE;
-        }
-        return OK;
-    }
-
-    Status doMain(Args && /*args*/) override {
-        auto ret = halCall(&V1_0::IVibrator::setAmplitude, mAmplitude);
-
-        if (!ret.isOk()) {
-            return UNAVAILABLE;
-        }
-
-        std::cout << "Status: " << toString(ret) << std::endl;
-
-        return ret == V1_0::Status::OK ? OK : ERROR;
-    }
-
-    uint8_t mAmplitude;
-};
-
-static const auto Command =
-        CommandRegistry<CommandVibrator>::Register<CommandSetAmplitude>("setAmplitude");
-
-} // namespace vibrator
-} // namespace idlcli
-} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandSetExternalControl.cpp b/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
deleted file mode 100644
index 5fb1fac..0000000
--- a/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "utils.h"
-#include "vibrator.h"
-
-namespace android {
-namespace idlcli {
-
-class CommandVibrator;
-
-namespace vibrator {
-
-class CommandSetExternalControl : public Command {
-    std::string getDescription() const override {
-        return "Enable/disable vibration external control.";
-    }
-
-    std::string getUsageSummary() const override { return "<enable>"; }
-
-    UsageDetails getUsageDetails() const override {
-        UsageDetails details{
-                {"<enable>", {"0/1."}},
-        };
-        return details;
-    }
-
-    Status doArgs(Args &args) override {
-        if (auto enable = args.pop<decltype(mEnable)>()) {
-            mEnable = *enable;
-        } else {
-            std::cerr << "Missing Enable!" << std::endl;
-            return USAGE;
-        }
-        return OK;
-    }
-
-    Status doMain(Args && /*args*/) override {
-        auto ret = halCall(&V1_3::IVibrator::setExternalControl, mEnable);
-
-        if (!ret.isOk()) {
-            return UNAVAILABLE;
-        }
-
-        std::cout << "Status: " << toString(ret) << std::endl;
-
-        return ret == V1_0::Status::OK ? OK : ERROR;
-    }
-
-    bool mEnable;
-};
-
-static const auto Command =
-        CommandRegistry<CommandVibrator>::Register<CommandSetExternalControl>("setExternalControl");
-
-} // namespace vibrator
-} // namespace idlcli
-} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp b/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp
deleted file mode 100644
index cdc529a..0000000
--- a/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "utils.h"
-#include "vibrator.h"
-
-namespace android {
-namespace idlcli {
-
-class CommandVibrator;
-
-namespace vibrator {
-
-class CommandSupportsAmplitudeControl : public Command {
-    std::string getDescription() const override { return "Check support for amplitude control."; }
-
-    std::string getUsageSummary() const override { return ""; }
-
-    UsageDetails getUsageDetails() const override {
-        UsageDetails details{};
-        return details;
-    }
-
-    Status doArgs(Args &args) override {
-        if (!args.empty()) {
-            std::cerr << "Unexpected Arguments!" << std::endl;
-            return USAGE;
-        }
-        return OK;
-    }
-
-    Status doMain(Args && /*args*/) override {
-        auto ret = halCall(&V1_0::IVibrator::supportsAmplitudeControl);
-
-        if (!ret.isOk()) {
-            return UNAVAILABLE;
-        }
-
-        std::cout << "Result: " << std::boolalpha << ret << std::endl;
-
-        return OK;
-    }
-};
-
-static const auto Command =
-        CommandRegistry<CommandVibrator>::Register<CommandSupportsAmplitudeControl>(
-                "supportsAmplitudeControl");
-
-} // namespace vibrator
-} // namespace idlcli
-} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp b/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp
deleted file mode 100644
index ed15d76..0000000
--- a/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "utils.h"
-#include "vibrator.h"
-
-namespace android {
-namespace idlcli {
-
-class CommandVibrator;
-
-namespace vibrator {
-
-class CommandSupportsExternalControl : public Command {
-    std::string getDescription() const override { return "Check support for external control."; }
-
-    std::string getUsageSummary() const override { return ""; }
-
-    UsageDetails getUsageDetails() const override {
-        UsageDetails details{};
-        return details;
-    }
-
-    Status doArgs(Args &args) override {
-        if (!args.empty()) {
-            std::cerr << "Unexpected Arguments!" << std::endl;
-            return USAGE;
-        }
-        return OK;
-    }
-
-    Status doMain(Args && /*args*/) override {
-        auto ret = halCall(&V1_3::IVibrator::supportsExternalControl);
-
-        if (!ret.isOk()) {
-            return UNAVAILABLE;
-        }
-
-        std::cout << "Result: " << std::boolalpha << ret << std::endl;
-
-        return OK;
-    }
-};
-
-static const auto Command =
-        CommandRegistry<CommandVibrator>::Register<CommandSupportsExternalControl>(
-                "supportsExternalControl");
-
-} // namespace vibrator
-} // namespace idlcli
-} // namespace android
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 75dec37..c80ae3b 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -138,7 +138,6 @@
 
 cc_binary {
     name: "otapreopt_chroot",
-    defaults: ["libapexd-deps"],
     cflags: [
         "-Wall",
         "-Werror",
@@ -151,11 +150,20 @@
     ],
     shared_libs: [
         "libbase",
+        "libbinder",
         "liblog",
+        "libprotobuf-cpp-full",
+        "libselinux",
         "libutils",
+        "libziparchive",
     ],
     static_libs: [
+        "libapex",
         "libapexd",
+        "lib_apex_manifest_proto",
+        "libavb",
+        "libdm",
+        "libvold_binder",
     ],
 }
 
@@ -164,7 +172,6 @@
     srcs: [
         "binder/android/os/IInstalld.aidl",
     ],
-    path: "binder",
 }
 
 //
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 4026f29..3472727 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -832,7 +832,7 @@
     };
 
     LOG(DEBUG) << "Copying " << from << " to " << to;
-    return logwrap_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, LOG_ALOG, false, nullptr);
+    return android_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, true);
 }
 
 binder::Status InstalldNativeService::snapshotAppData(
@@ -2107,15 +2107,10 @@
     CHECK_ARGUMENT_PATH(dexMetadataPath);
     std::lock_guard<std::recursive_mutex> lock(mLock);
 
-    const char* oat_dir = getCStr(outputPath);
-    const char* instruction_set = instructionSet.c_str();
-    if (oat_dir != nullptr && !createOatDir(oat_dir, instruction_set).isOk()) {
-        // Can't create oat dir - let dexopt use cache dir.
-        oat_dir = nullptr;
-    }
-
     const char* apk_path = apkPath.c_str();
     const char* pkgname = getCStr(packageName, "*");
+    const char* instruction_set = instructionSet.c_str();
+    const char* oat_dir = getCStr(outputPath);
     const char* compiler_filter = compilerFilter.c_str();
     const char* volume_uuid = getCStr(uuid);
     const char* class_loader_context = getCStr(classLoaderContext);
@@ -2141,26 +2136,6 @@
     return *_aidl_return ? ok() : error("viewcompiler failed");
 }
 
-binder::Status InstalldNativeService::markBootComplete(const std::string& instructionSet) {
-    ENFORCE_UID(AID_SYSTEM);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
-
-    const char* instruction_set = instructionSet.c_str();
-
-    char boot_marker_path[PKG_PATH_MAX];
-    sprintf(boot_marker_path,
-          "%s/%s/%s/.booting",
-          android_data_dir.c_str(),
-          DALVIK_CACHE,
-          instruction_set);
-
-    ALOGV("mark_boot_complete : %s", boot_marker_path);
-    if (unlink(boot_marker_path) != 0) {
-        return error(StringPrintf("Failed to unlink %s", boot_marker_path));
-    }
-    return ok();
-}
-
 binder::Status InstalldNativeService::linkNativeLibraryDirectory(
         const std::unique_ptr<std::string>& uuid, const std::string& packageName,
         const std::string& nativeLibPath32, int32_t userId) {
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 2b7bf33..eba966d 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -123,7 +123,6 @@
             int32_t uid);
     binder::Status removeIdmap(const std::string& overlayApkPath);
     binder::Status rmPackageDir(const std::string& packageDir);
-    binder::Status markBootComplete(const std::string& instructionSet);
     binder::Status freeCache(const std::unique_ptr<std::string>& uuid, int64_t targetFreeBytes,
             int64_t cacheReservedBytes, int32_t flags);
     binder::Status linkNativeLibraryDirectory(const std::unique_ptr<std::string>& uuid,
diff --git a/cmds/installd/OWNERS b/cmds/installd/OWNERS
index 9a21104..5673918 100644
--- a/cmds/installd/OWNERS
+++ b/cmds/installd/OWNERS
@@ -4,9 +4,7 @@
 calin@google.com
 jsharkey@android.com
 maco@google.com
-mast@google.com
 mathieuc@google.com
 narayan@google.com
 ngeoffray@google.com
-rpl@google.com
 toddke@google.com
diff --git a/cmds/installd/art_helper/Android.bp b/cmds/installd/art_helper/Android.bp
new file mode 100644
index 0000000..c47dd72
--- /dev/null
+++ b/cmds/installd/art_helper/Android.bp
@@ -0,0 +1,12 @@
+// Inherit image values.
+art_global_defaults {
+    name: "libartimagevalues_defaults",
+}
+
+cc_library_static {
+    name: "libartimagevalues",
+    defaults: ["libartimagevalues_defaults"],
+    srcs: ["art_image_values.cpp"],
+    export_include_dirs: ["."],
+    cflags: ["-Wconversion"],
+}
diff --git a/cmds/installd/art_helper/art_image_values.cpp b/cmds/installd/art_helper/art_image_values.cpp
new file mode 100644
index 0000000..a139049
--- /dev/null
+++ b/cmds/installd/art_helper/art_image_values.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "art_image_values.h"
+
+namespace android {
+namespace installd {
+namespace art {
+
+uint32_t GetImageBaseAddress() {
+    return ART_BASE_ADDRESS;
+}
+int32_t GetImageMinBaseAddressDelta() {
+    return ART_BASE_ADDRESS_MIN_DELTA;
+}
+int32_t GetImageMaxBaseAddressDelta() {
+    return ART_BASE_ADDRESS_MAX_DELTA;
+}
+
+static_assert(ART_BASE_ADDRESS_MIN_DELTA < ART_BASE_ADDRESS_MAX_DELTA, "Inconsistent setup");
+
+}  // namespace art
+}  // namespace installd
+}  // namespace android
diff --git a/cmds/installd/art_helper/art_image_values.h b/cmds/installd/art_helper/art_image_values.h
new file mode 100644
index 0000000..20c44c9
--- /dev/null
+++ b/cmds/installd/art_helper/art_image_values.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H
+#define FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H
+
+#include <cstdint>
+
+namespace android {
+namespace installd {
+namespace art {
+
+uint32_t GetImageBaseAddress();
+int32_t GetImageMinBaseAddressDelta();
+int32_t GetImageMaxBaseAddressDelta();
+
+}  // namespace art
+}  // namespace installd
+}  // namespace android
+
+#endif  // FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 26e9984..b795c02 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -75,7 +75,6 @@
     void idmap(@utf8InCpp String targetApkPath, @utf8InCpp String overlayApkPath, int uid);
     void removeIdmap(@utf8InCpp String overlayApkPath);
     void rmPackageDir(@utf8InCpp String packageDir);
-    void markBootComplete(@utf8InCpp String instructionSet);
     void freeCache(@nullable @utf8InCpp String uuid, long targetFreeBytes,
             long cacheReservedBytes, int flags);
     void linkNativeLibraryDirectory(@nullable @utf8InCpp String uuid,
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 838d11d..5fb13a5 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -303,9 +303,6 @@
 // Location of the apex image.
 static const char* kApexImage = "/system/framework/apex.art";
 
-// Phenotype property name for enabling profiling the boot class path.
-static const char* PROFILE_BOOT_CLASS_PATH = "profilebootclasspath";
-
 class RunDex2Oat : public ExecVHelper {
   public:
     RunDex2Oat(int zip_fd,
@@ -339,6 +336,10 @@
                 ? "dalvik.vm.dex2oat-threads"
                 : "dalvik.vm.boot-dex2oat-threads";
         std::string dex2oat_threads_arg = MapPropertyToArg(threads_property, "-j%s");
+        const char* cpu_set_property = post_bootcomplete
+                ? "dalvik.vm.dex2oat-cpu-set"
+                : "dalvik.vm.boot-dex2oat-cpu-set";
+        std::string dex2oat_cpu_set_arg = MapPropertyToArg(cpu_set_property, "--cpu-set=%s");
 
         std::string bootclasspath;
         char* dex2oat_bootclasspath = getenv("DEX2OATBOOTCLASSPATH");
@@ -405,15 +406,7 @@
             server_configurable_flags::GetServerConfigurableFlag(RUNTIME_NATIVE_BOOT_NAMESPACE,
                                                                  ENABLE_APEX_IMAGE,
                                                                  /*default_value=*/ "");
-
-        std::string profile_boot_class_path = GetProperty("dalvik.vm.profilebootclasspath", "");
-        profile_boot_class_path =
-            server_configurable_flags::GetServerConfigurableFlag(
-                RUNTIME_NATIVE_BOOT_NAMESPACE,
-                PROFILE_BOOT_CLASS_PATH,
-                /*default_value=*/ profile_boot_class_path);
-
-        if (use_apex_image == "true" || profile_boot_class_path == "true") {
+        if (use_apex_image == "true") {
           boot_image = StringPrintf("-Ximage:%s", kApexImage);
         } else {
           boot_image = MapPropertyToArg("dalvik.vm.boot-image", "-Ximage:%s");
@@ -518,6 +511,7 @@
         AddArg(image_block_size_arg);
         AddArg(dex2oat_compiler_filter_arg);
         AddArg(dex2oat_threads_arg);
+        AddArg(dex2oat_cpu_set_arg);
         AddArg(dex2oat_swap_fd);
         AddArg(dex2oat_image_fd);
 
@@ -720,7 +714,8 @@
                   const unique_fd& reference_profile_fd,
                   const std::vector<unique_fd>& apk_fds,
                   const std::vector<std::string>& dex_locations,
-                  bool copy_and_update) {
+                  bool copy_and_update,
+                  bool store_aggregation_counters) {
 
         // TODO(calin): Assume for now we run in the bg compile job (which is in
         // most of the invocation). With the current data flow, is not very easy or
@@ -752,6 +747,10 @@
             AddArg("--copy-and-update-profile-key");
         }
 
+        if (store_aggregation_counters) {
+            AddArg("--store-aggregation-counters");
+        }
+
         // Do not add after dex2oat_flags, they should override others for debugging.
         PrepareArgs(profman_bin);
     }
@@ -759,12 +758,14 @@
     void SetupMerge(const std::vector<unique_fd>& profiles_fd,
                     const unique_fd& reference_profile_fd,
                     const std::vector<unique_fd>& apk_fds = std::vector<unique_fd>(),
-                    const std::vector<std::string>& dex_locations = std::vector<std::string>()) {
+                    const std::vector<std::string>& dex_locations = std::vector<std::string>(),
+                    bool store_aggregation_counters = false) {
         SetupArgs(profiles_fd,
                   reference_profile_fd,
                   apk_fds,
                   dex_locations,
-                  /*copy_and_update=*/false);
+                  /*copy_and_update=*/false,
+                  store_aggregation_counters);
     }
 
     void SetupCopyAndUpdate(unique_fd&& profile_fd,
@@ -781,7 +782,8 @@
                   reference_profile_fd_,
                   apk_fds_,
                   dex_locations,
-                  /*copy_and_update=*/true);
+                  /*copy_and_update=*/true,
+                  /*store_aggregation_counters=*/false);
     }
 
     void SetupDump(const std::vector<unique_fd>& profiles_fd,
@@ -795,7 +797,8 @@
                   reference_profile_fd,
                   apk_fds,
                   dex_locations,
-                  /*copy_and_update=*/false);
+                  /*copy_and_update=*/false,
+                  /*store_aggregation_counters=*/false);
     }
 
     void Exec() {
@@ -2119,20 +2122,14 @@
     // Create a swap file if necessary.
     unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path);
 
-    // Open the reference profile if needed.
-    Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile(
-            pkgname, dex_path, profile_name, profile_guided, is_public, uid, is_secondary_dex);
-
-    if (reference_profile_fd.get() == -1) {
-        // We don't create an app image without reference profile since there is no speedup from
-        // loading it in that case and instead will be a small overhead.
-        generate_app_image = false;
-    }
-
     // Create the app image file if needed.
     Dex2oatFileWrapper image_fd = maybe_open_app_image(
             out_oat_path, generate_app_image, is_public, uid, is_secondary_dex);
 
+    // Open the reference profile if needed.
+    Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile(
+            pkgname, dex_path, profile_name, profile_guided, is_public, uid, is_secondary_dex);
+
     unique_fd dex_metadata_fd;
     if (dex_metadata_path != nullptr) {
         dex_metadata_fd.reset(TEMP_FAILURE_RETRY(open(dex_metadata_path, O_RDONLY | O_NOFOLLOW)));
@@ -2830,7 +2827,8 @@
         args.SetupMerge(profiles_fd,
                         snapshot_fd,
                         apk_fds,
-                        dex_locations);
+                        dex_locations,
+                        /*store_aggregation_counters=*/true);
         pid_t pid = fork();
         if (pid == 0) {
             /* child -- drop privileges before continuing */
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index ef739ba..a8c48c5 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -32,15 +32,15 @@
 static constexpr int DEX2OAT_FOR_BOOT_IMAGE      = 2;
 static constexpr int DEX2OAT_FOR_FILTER          = 3;
 
-#define ANDROID_ART_APEX_BIN "/apex/com.android.art/bin"
+#define ANDROID_RUNTIME_APEX_BIN "/apex/com.android.runtime/bin"
 // Location of binaries in the Android Runtime APEX.
-static constexpr const char* kDex2oatPath = ANDROID_ART_APEX_BIN "/dex2oat";
-static constexpr const char* kDex2oatDebugPath = ANDROID_ART_APEX_BIN "/dex2oatd";
-static constexpr const char* kProfmanPath = ANDROID_ART_APEX_BIN "/profman";
-static constexpr const char* kProfmanDebugPath = ANDROID_ART_APEX_BIN "/profmand";
-static constexpr const char* kDexoptanalyzerPath = ANDROID_ART_APEX_BIN "/dexoptanalyzer";
-static constexpr const char* kDexoptanalyzerDebugPath = ANDROID_ART_APEX_BIN "/dexoptanalyzerd";
-#undef ANDROID_ART_APEX_BIN
+static constexpr const char* kDex2oatPath = ANDROID_RUNTIME_APEX_BIN "/dex2oat";
+static constexpr const char* kDex2oatDebugPath = ANDROID_RUNTIME_APEX_BIN "/dex2oatd";
+static constexpr const char* kProfmanPath = ANDROID_RUNTIME_APEX_BIN "/profman";
+static constexpr const char* kProfmanDebugPath = ANDROID_RUNTIME_APEX_BIN "/profmand";
+static constexpr const char* kDexoptanalyzerPath = ANDROID_RUNTIME_APEX_BIN "/dexoptanalyzer";
+static constexpr const char* kDexoptanalyzerDebugPath = ANDROID_RUNTIME_APEX_BIN "/dexoptanalyzerd";
+#undef ANDROID_RUNTIME_APEX_BIN
 
 // Clear the reference profile identified by the given profile name.
 bool clear_primary_reference_profile(const std::string& pkgname, const std::string& profile_name);
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index b5bc28c..673ff0d 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -74,7 +74,7 @@
 
     // Read current filesystem layout version to handle upgrade paths
     char version_path[PATH_MAX];
-    snprintf(version_path, PATH_MAX, "%smisc/installd/layout_version", android_data_dir.c_str());
+    snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.c_str());
 
     int oldVersion;
     if (fs_read_atomic_int(version_path, &oldVersion) == -1) {
diff --git a/cmds/installd/migrate_legacy_obb_data.sh b/cmds/installd/migrate_legacy_obb_data.sh
index 0e6d7b9..1075688 100644
--- a/cmds/installd/migrate_legacy_obb_data.sh
+++ b/cmds/installd/migrate_legacy_obb_data.sh
@@ -15,17 +15,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-rm -rf /data/media/Android/obb/test_probe
-mkdir -p /data/media/Android/obb/
-touch /data/media/Android/obb/test_probe
+rm -rf /sdcard/Android/obb/test_probe
+mkdir -p /sdcard/Android/obb/
+touch /sdcard/Android/obb/test_probe
 if ! test -f /data/media/0/Android/obb/test_probe ; then
   log -p i -t migrate_legacy_obb_data "No support for 'unshared_obb'. Not migrating"
-  rm -rf /data/media/Android/obb/test_probe
+  rm -rf /sdcard/Android/obb/test_probe
   exit 0
 fi
 
 # Delete the test file, and remove the obb folder if it is empty
-rm -rf /data/media/Android/obb/test_probe
+rm -rf /sdcard/Android/obb/test_probe
 rmdir /data/media/obb
 
 if ! test -d /data/media/obb ; then
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index db36ce3..9bc5fc8 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -445,11 +445,9 @@
         }
         cmd.push_back(StringPrintf("--oat-file=%s", oat_path.c_str()));
 
-        int32_t base_offset = ChooseRelocationOffsetDelta(
-                art::imagevalues::GetImageMinBaseAddressDelta(),
-                art::imagevalues::GetImageMaxBaseAddressDelta());
-        cmd.push_back(StringPrintf("--base=0x%x",
-                art::imagevalues::GetImageBaseAddress() + base_offset));
+        int32_t base_offset = ChooseRelocationOffsetDelta(art::GetImageMinBaseAddressDelta(),
+                                                          art::GetImageMaxBaseAddressDelta());
+        cmd.push_back(StringPrintf("--base=0x%x", art::GetImageBaseAddress() + base_offset));
 
         cmd.push_back(StringPrintf("--instruction-set=%s", isa));
 
@@ -466,7 +464,7 @@
                 "--compiler-filter=",
                 false,
                 cmd);
-        cmd.push_back("--profile-file=/system/etc/boot-image.prof");
+        cmd.push_back("--image-classes=/system/etc/preloaded-classes");
         // TODO: Compiled-classes.
         const std::string* extra_opts =
                 system_properties_.GetProperty("dalvik.vm.image-dex2oat-flags");
@@ -480,6 +478,10 @@
                 "-j",
                 false,
                 cmd);
+        AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-cpu-set",
+                "--cpu-set=",
+                false,
+                cmd);
         AddCompilerOptionFromSystemProperty(
                 StringPrintf("dalvik.vm.isa.%s.variant", isa).c_str(),
                 "--instruction-set-variant=",
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 3ff9d11..2e2cc18 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -64,18 +64,16 @@
     // system/apex/apexd/apexd_main.cpp.
     //
     // Only scan the APEX directory under /system (within the chroot dir).
-    // Cast call to void to suppress warn_unused_result.
-    static_cast<void>(apex::scanPackagesDirAndActivate(apex::kApexPackageSystemDir));
+    apex::scanPackagesDirAndActivate(apex::kApexPackageSystemDir);
     return apex::getActivePackages();
 }
 
 static void DeactivateApexPackages(const std::vector<apex::ApexFile>& active_packages) {
     for (const apex::ApexFile& apex_file : active_packages) {
         const std::string& package_path = apex_file.GetPath();
-        base::Result<void> status = apex::deactivatePackage(package_path);
-        if (!status) {
-            LOG(ERROR) << "Failed to deactivate " << package_path << ": "
-                       << status.error();
+        apex::Status status = apex::deactivatePackage(package_path);
+        if (!status.Ok()) {
+            LOG(ERROR) << "Failed to deactivate " << package_path << ": " << status.ErrorMessage();
         }
     }
 }
@@ -233,21 +231,9 @@
     }
 
     // Try to mount APEX packages in "/apex" in the chroot dir. We need at least
-    // the ART APEX, as it is required by otapreopt to run dex2oat.
+    // the Android Runtime APEX, as it is required by otapreopt to run dex2oat.
     std::vector<apex::ApexFile> active_packages = ActivateApexPackages();
 
-    // Check that an ART APEX has been activated; clean up and exit
-    // early otherwise.
-    if (std::none_of(active_packages.begin(),
-                     active_packages.end(),
-                     [](const apex::ApexFile& package){
-                         return package.GetManifest().name() == "com.android.art";
-                     })) {
-        LOG(FATAL_WITHOUT_ABORT) << "No activated com.android.art APEX package.";
-        DeactivateApexPackages(active_packages);
-        exit(217);
-    }
-
     // Now go on and run otapreopt.
 
     // Incoming:  cmd + status-fd + target-slot + cmd...      | Incoming | = argc
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index bd45005..aa79fdc 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -89,8 +89,6 @@
         "libinstalld",
         "liblog",
         "liblogwrap",
-        "libziparchive",
-        "libz",
     ],
     test_config: "installd_dexopt_test.xml",
 }
diff --git a/cmds/installd/tests/installd_cache_test.cpp b/cmds/installd/tests/installd_cache_test.cpp
index 5a5cb53..db09070 100644
--- a/cmds/installd/tests/installd_cache_test.cpp
+++ b/cmds/installd/tests/installd_cache_test.cpp
@@ -67,29 +67,29 @@
 }
 
 static void mkdir(const char* path) {
-    const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path);
-    ::mkdir(fullPath.c_str(), 0755);
+    const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
+    ::mkdir(fullPath, 0755);
 }
 
 static void touch(const char* path, int len, int time) {
-    const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path);
-    int fd = ::open(fullPath.c_str(), O_RDWR | O_CREAT, 0644);
+    const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
+    int fd = ::open(fullPath, O_RDWR | O_CREAT, 0644);
     ::fallocate(fd, 0, 0, len);
     ::close(fd);
     struct utimbuf times;
     times.actime = times.modtime = std::time(0) + time;
-    ::utime(fullPath.c_str(), &times);
+    ::utime(fullPath, &times);
 }
 
 static int exists(const char* path) {
-    const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path);
-    return ::access(fullPath.c_str(), F_OK);
+    const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
+    return ::access(fullPath, F_OK);
 }
 
 static int64_t size(const char* path) {
-    const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path);
+    const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
     struct stat buf;
-    if (!stat(fullPath.c_str(), &buf)) {
+    if (!stat(fullPath, &buf)) {
         return buf.st_size;
     } else {
         return -1;
@@ -107,8 +107,8 @@
 }
 
 static void setxattr(const char* path, const char* key) {
-    const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path);
-    ::setxattr(fullPath.c_str(), key, "", 0, 0);
+    const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
+    ::setxattr(fullPath, key, "", 0, 0);
 }
 
 class CacheTest : public testing::Test {
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 0212bc5..fa2b0d9 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -41,7 +41,6 @@
 #include "globals.h"
 #include "tests/test_utils.h"
 #include "utils.h"
-#include "ziparchive/zip_writer.h"
 
 using android::base::ReadFully;
 using android::base::unique_fd;
@@ -196,7 +195,6 @@
     std::unique_ptr<std::string> volume_uuid_;
     std::string package_name_;
     std::string apk_path_;
-    std::string empty_dm_file_;
     std::string app_apk_dir_;
     std::string app_private_dir_ce_;
     std::string app_private_dir_de_;
@@ -241,14 +239,18 @@
     }
 
     ::testing::AssertionResult create_mock_app() {
+        // Create the oat dir.
+        app_oat_dir_ = app_apk_dir_ + "/oat";
         // For debug mode, the directory might already exist. Avoid erroring out.
         if (mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755) != 0 && !kDebug) {
             return ::testing::AssertionFailure() << "Could not create app dir " << app_apk_dir_
                                                  << " : " << strerror(errno);
         }
-
-        // Initialize the oat dir path.
-        app_oat_dir_ = app_apk_dir_ + "/oat";
+        binder::Status status = service_->createOatDir(app_oat_dir_, kRuntimeIsa);
+        if (!status.isOk()) {
+            return ::testing::AssertionFailure() << "Could not create oat dir: "
+                                                 << status.toString8().c_str();
+        }
 
         // Copy the primary apk.
         apk_path_ = app_apk_dir_ + "/base.jar";
@@ -258,28 +260,8 @@
                                                  << " : " << error_msg;
         }
 
-        // Create an empty dm file.
-        empty_dm_file_ = apk_path_ + ".dm";
-        {
-            int fd = open(empty_dm_file_.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
-            if (fd < 0) {
-                return ::testing::AssertionFailure() << "Could not open " << empty_dm_file_;
-            }
-            FILE* file = fdopen(fd, "wb");
-            if (file == nullptr) {
-                return ::testing::AssertionFailure() << "Null file for " << empty_dm_file_
-                         << " fd=" << fd;
-            }
-            ZipWriter writer(file);
-            // Add vdex to zip.
-            writer.StartEntry("primary.prof", ZipWriter::kCompress);
-            writer.FinishEntry();
-            writer.Finish();
-            fclose(file);
-          }
-
         // Create the app user data.
-        binder::Status status = service_->createAppData(
+        status = service_->createAppData(
                 volume_uuid_,
                 package_name_,
                 kTestUserId,
@@ -497,7 +479,7 @@
         bool prof_result;
         ASSERT_BINDER_SUCCESS(service_->prepareAppProfile(
                 package_name_, kTestUserId, kTestAppId, *profile_name_ptr, apk_path_,
-                dm_path_ptr, &prof_result));
+                /*dex_metadata*/ nullptr, &prof_result));
         ASSERT_TRUE(prof_result);
 
         binder::Status result = service_->dexopt(apk_path_,
@@ -643,16 +625,6 @@
                         DEX2OAT_FROM_SCRATCH);
 }
 
-TEST_F(DexoptTest, DexoptPrimaryPublicCreateOatDir) {
-    LOG(INFO) << "DexoptPrimaryPublic";
-    ASSERT_BINDER_SUCCESS(service_->createOatDir(app_oat_dir_, kRuntimeIsa));
-    CompilePrimaryDexOk("verify",
-                        DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
-                        app_oat_dir_.c_str(),
-                        kTestAppGid,
-                        DEX2OAT_FROM_SCRATCH);
-}
-
 TEST_F(DexoptTest, DexoptPrimaryFailedInvalidFilter) {
     LOG(INFO) << "DexoptPrimaryFailedInvalidFilter";
     binder::Status status;
@@ -673,9 +645,7 @@
                         DEXOPT_BOOTCOMPLETE | DEXOPT_PROFILE_GUIDED | DEXOPT_GENERATE_APP_IMAGE,
                         app_oat_dir_.c_str(),
                         kTestAppGid,
-                        DEX2OAT_FROM_SCRATCH,
-                        /*binder_result=*/nullptr,
-                        empty_dm_file_.c_str());
+                        DEX2OAT_FROM_SCRATCH);
 }
 
 TEST_F(DexoptTest, DexoptPrimaryProfilePublic) {
@@ -685,9 +655,7 @@
                                 DEXOPT_GENERATE_APP_IMAGE,
                         app_oat_dir_.c_str(),
                         kTestAppGid,
-                        DEX2OAT_FROM_SCRATCH,
-                        /*binder_result=*/nullptr,
-                        empty_dm_file_.c_str());
+                        DEX2OAT_FROM_SCRATCH);
 }
 
 TEST_F(DexoptTest, DexoptPrimaryBackgroundOk) {
@@ -697,9 +665,7 @@
                                 DEXOPT_GENERATE_APP_IMAGE,
                         app_oat_dir_.c_str(),
                         kTestAppGid,
-                        DEX2OAT_FROM_SCRATCH,
-                        /*binder_result=*/nullptr,
-                        empty_dm_file_.c_str());
+                        DEX2OAT_FROM_SCRATCH);
 }
 
 TEST_F(DexoptTest, ResolveStartupConstStrings) {
@@ -718,9 +684,7 @@
                                 DEXOPT_GENERATE_APP_IMAGE,
                         app_oat_dir_.c_str(),
                         kTestAppGid,
-                        DEX2OAT_FROM_SCRATCH,
-                        /*binder_result=*/nullptr,
-                        empty_dm_file_.c_str());
+                        DEX2OAT_FROM_SCRATCH);
     run_cmd_and_process_output(
             "oatdump --header-only --oat-file=" + odex,
             [&](const std::string& line) {
@@ -737,9 +701,7 @@
                                 DEXOPT_GENERATE_APP_IMAGE,
                         app_oat_dir_.c_str(),
                         kTestAppGid,
-                        DEX2OAT_FROM_SCRATCH,
-                        /*binder_result=*/nullptr,
-                        empty_dm_file_.c_str());
+                        DEX2OAT_FROM_SCRATCH);
     run_cmd_and_process_output(
             "oatdump --header-only --oat-file=" + odex,
             [&](const std::string& line) {
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index 5afae4b..93d878b 100644
--- a/cmds/lshal/Android.bp
+++ b/cmds/lshal/Android.bp
@@ -12,13 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-cc_library_static {
+cc_library_shared {
     name: "liblshal",
     shared_libs: [
         "libbase",
         "libcutils",
         "libutils",
         "libhidlbase",
+        "libhidltransport",
         "libhidl-gen-hash",
         "libhidl-gen-utils",
         "libvintf",
@@ -35,7 +36,6 @@
         "TableEntry.cpp",
         "TextTable.cpp",
         "utils.cpp",
-        "WaitCommand.cpp",
     ],
     cflags: [
         "-Wall",
@@ -47,15 +47,13 @@
     name: "lshal_defaults",
     shared_libs: [
         "libbase",
-        "libcutils",
-        "libutils",
         "libhidlbase",
-        "libhidl-gen-hash",
         "libhidl-gen-utils",
-        "libvintf",
+        "libhidltransport",
+        "liblshal",
+        "libutils",
     ],
     static_libs: [
-        "liblshal",
         "libprocpartition",
     ],
     cflags: ["-Wall", "-Werror"],
@@ -71,16 +69,14 @@
 
 cc_test {
     name: "lshal_test",
-    test_suites: ["device-tests"],
     defaults: ["lshal_defaults"],
     gtest: true,
     static_libs: [
-        "android.hardware.tests.baz@1.0",
-        "libgmock",
+        "libgmock"
     ],
     shared_libs: [
-        "libhidlbase",
         "libvintf",
+        "android.hardware.tests.baz@1.0"
     ],
     srcs: [
         "test.cpp"
diff --git a/cmds/lshal/Command.h b/cmds/lshal/Command.h
index 84809d9..e19e3f7 100644
--- a/cmds/lshal/Command.h
+++ b/cmds/lshal/Command.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_COMMAND_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_COMMAND_H_
 
 #include "utils.h"
 
@@ -47,3 +48,5 @@
 
 }  // namespace lshal
 }  // namespace android
+
+#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp
index af22ac9..0952db6 100644
--- a/cmds/lshal/DebugCommand.cpp
+++ b/cmds/lshal/DebugCommand.cpp
@@ -79,7 +79,7 @@
             "    lshal debug [-E] <interface> [options [options [...]]] \n"
             "        Print debug information of a specified interface.\n"
             "        -E: excludes debug output if HAL is actually a subclass.\n"
-            "        <interface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n"
+            "        <inteface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n"
             "            If instance name is missing `default` is used.\n"
             "        options: space separated options to IBase::debug.\n";
 
@@ -88,3 +88,4 @@
 
 }  // namespace lshal
 }  // namespace android
+
diff --git a/cmds/lshal/DebugCommand.h b/cmds/lshal/DebugCommand.h
index cd57e31..3c3f56f 100644
--- a/cmds/lshal/DebugCommand.h
+++ b/cmds/lshal/DebugCommand.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_
 
 #include <string>
 
@@ -52,3 +53,5 @@
 
 }  // namespace lshal
 }  // namespace android
+
+#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_
diff --git a/cmds/lshal/HelpCommand.h b/cmds/lshal/HelpCommand.h
index bfa8500..da0cba6 100644
--- a/cmds/lshal/HelpCommand.h
+++ b/cmds/lshal/HelpCommand.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_HELP_COMMAND_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_HELP_COMMAND_H_
 
 #include <string>
 
@@ -43,3 +44,5 @@
 
 }  // namespace lshal
 }  // namespace android
+
+#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_HELP_COMMAND_H_
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index a7ccf64..c706d91 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -163,11 +163,11 @@
 VintfInfo getVintfInfo(const std::shared_ptr<const ObjectType>& object,
                        const FqInstance& fqInstance, vintf::TransportArch ta, VintfInfo value) {
     bool found = false;
-    (void)object->forEachHidlInstanceOfVersion(fqInstance.getPackage(), fqInstance.getVersion(),
-                                               [&](const auto& instance) {
-                                                   found = match(instance, fqInstance, ta);
-                                                   return !found; // continue if not found
-                                               });
+    (void)object->forEachInstanceOfVersion(fqInstance.getPackage(), fqInstance.getVersion(),
+                                           [&](const auto& instance) {
+                                               found = match(instance, fqInstance, ta);
+                                               return !found; // continue if not found
+                                           });
     return found ? value : VINTF_INFO_EMPTY;
 }
 
@@ -453,7 +453,7 @@
     }
 
     bool found = false;
-    (void)manifest->forEachHidlInstanceOfVersion(package, version, [&found](const auto&) {
+    (void)manifest->forEachInstanceOfVersion(package, version, [&found](const auto&) {
         found = true;
         return false; // break
     });
@@ -797,9 +797,9 @@
 
         std::map<std::string, TableEntry> entries;
 
-        manifest->forEachHidlInstance([&] (const vintf::ManifestInstance& manifestInstance) {
+        manifest->forEachInstance([&] (const vintf::ManifestInstance& manifestInstance) {
             TableEntry entry{
-                .interfaceName = manifestInstance.description(),
+                .interfaceName = manifestInstance.getFqInstance().string(),
                 .transport = manifestInstance.transport(),
                 .arch = manifestInstance.arch(),
                 // TODO(b/71555570): Device manifest does not distinguish HALs from vendor or ODM.
@@ -975,8 +975,7 @@
        "    - DM: if the HAL is in the device manifest\n"
        "    - DC: if the HAL is in the device compatibility matrix\n"
        "    - FM: if the HAL is in the framework manifest\n"
-       "    - FC: if the HAL is in the framework compatibility matrix\n"
-       "    - X: if the HAL is in none of the above lists"});
+       "    - FC: if the HAL is in the framework compatibility matrix"});
     mOptions.push_back({'S', "service-status", no_argument, v++, [](ListCommand* thiz, const char*) {
         thiz->mSelectedColumns.push_back(TableColumnType::SERVICE_STATUS);
         return OK;
diff --git a/cmds/lshal/ListCommand.h b/cmds/lshal/ListCommand.h
index b3ed23d..85195fc 100644
--- a/cmds/lshal/ListCommand.h
+++ b/cmds/lshal/ListCommand.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
 
 #include <getopt.h>
 #include <stdint.h>
@@ -205,3 +206,5 @@
 
 }  // namespace lshal
 }  // namespace android
+
+#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 132b31e..8c83457 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -26,9 +26,7 @@
 #include <hidl/HidlTransportUtils.h>
 
 #include "DebugCommand.h"
-#include "HelpCommand.h"
 #include "ListCommand.h"
-#include "WaitCommand.h"
 #include "PipeRelay.h"
 
 namespace android {
@@ -51,7 +49,6 @@
     mRegisteredCommands.push_back({std::make_unique<ListCommand>(*this)});
     mRegisteredCommands.push_back({std::make_unique<DebugCommand>(*this)});
     mRegisteredCommands.push_back({std::make_unique<HelpCommand>(*this)});
-    mRegisteredCommands.push_back({std::make_unique<WaitCommand>(*this)});
 }
 
 void Lshal::forEachCommand(const std::function<void(const Command* c)>& f) const {
diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h
index 830bd87..9457f1e 100644
--- a/cmds/lshal/Lshal.h
+++ b/cmds/lshal/Lshal.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_
 
 #include <iostream>
 #include <string>
@@ -24,6 +25,7 @@
 #include <utils/StrongPointer.h>
 
 #include "Command.h"
+#include "HelpCommand.h"
 #include "NullableOStream.h"
 #include "utils.h"
 
@@ -74,3 +76,5 @@
 
 }  // namespace lshal
 }  // namespace android
+
+#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_
diff --git a/cmds/lshal/NullableOStream.h b/cmds/lshal/NullableOStream.h
index 7cffcf8..737d3a2 100644
--- a/cmds/lshal/NullableOStream.h
+++ b/cmds/lshal/NullableOStream.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_NULLABLE_O_STREAM_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_NULLABLE_O_STREAM_H_
 
 #include <iostream>
 
@@ -68,3 +69,5 @@
 
 }  // namespace lshal
 }  // namespace android
+
+#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_NULLABLE_O_STREAM_H_
diff --git a/cmds/lshal/PipeRelay.h b/cmds/lshal/PipeRelay.h
index 835016041..8dc3093 100644
--- a/cmds/lshal/PipeRelay.h
+++ b/cmds/lshal/PipeRelay.h
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef FRAMEWORKS_NATIVE_CMDS_LSHAL_PIPE_RELAY_H_
+
+#define FRAMEWORKS_NATIVE_CMDS_LSHAL_PIPE_RELAY_H_
 
 #include <android-base/macros.h>
 #include <ostream>
@@ -51,3 +53,6 @@
 
 }  // namespace lshal
 }  // namespace android
+
+#endif  // FRAMEWORKS_NATIVE_CMDS_LSHAL_PIPE_RELAY_H_
+
diff --git a/cmds/lshal/TEST_MAPPING b/cmds/lshal/TEST_MAPPING
deleted file mode 100644
index 0320624..0000000
--- a/cmds/lshal/TEST_MAPPING
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "presubmit": [
-    {
-      "name": "lshal_test"
-    }
-  ]
-}
-
diff --git a/cmds/lshal/TableEntry.h b/cmds/lshal/TableEntry.h
index 0ff0c96..601b7e2 100644
--- a/cmds/lshal/TableEntry.h
+++ b/cmds/lshal/TableEntry.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_
 
 #include <stdint.h>
 
@@ -156,3 +157,5 @@
 
 }  // namespace lshal
 }  // namespace android
+
+#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_
diff --git a/cmds/lshal/TextTable.h b/cmds/lshal/TextTable.h
index be41a08..301b4bd 100644
--- a/cmds/lshal/TextTable.h
+++ b/cmds/lshal/TextTable.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_TEXT_TABLE_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_TEXT_TABLE_H_
 
 #include <iostream>
 #include <string>
@@ -79,3 +80,5 @@
 
 } // namespace lshal
 } // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_TEXT_TABLE_H_
diff --git a/cmds/lshal/Timeout.h b/cmds/lshal/Timeout.h
index e8d22d9..46d8177 100644
--- a/cmds/lshal/Timeout.h
+++ b/cmds/lshal/Timeout.h
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#pragma once
-
 #include <condition_variable>
 #include <chrono>
 #include <functional>
diff --git a/cmds/lshal/WaitCommand.cpp b/cmds/lshal/WaitCommand.cpp
deleted file mode 100644
index 65b41b9..0000000
--- a/cmds/lshal/WaitCommand.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "WaitCommand.h"
-
-#include "Lshal.h"
-
-#include <hidl/ServiceManagement.h>
-#include <hidl-util/FQName.h>
-
-namespace android {
-namespace lshal {
-
-std::string WaitCommand::getName() const {
-    return "wait";
-}
-
-std::string WaitCommand::getSimpleDescription() const {
-    return "Wait for HAL to start if it is not already started.";
-}
-
-Status WaitCommand::parseArgs(const Arg &arg) {
-    if (optind + 1 != arg.argc) {
-        return USAGE;
-    }
-
-    mInterfaceName = arg.argv[optind];
-    ++optind;
-    return OK;
-}
-
-Status WaitCommand::main(const Arg &arg) {
-    Status status = parseArgs(arg);
-    if (status != OK) {
-        return status;
-    }
-
-    auto [interface, instance] = splitFirst(mInterfaceName, '/');
-    instance = instance.empty() ? "default" : instance;
-
-    FQName fqName;
-    if (!FQName::parse(interface, &fqName) || fqName.isIdentifier() || !fqName.isFullyQualified()) {
-        mLshal.err() << "Invalid fully-qualified name '" << interface << "'\n\n";
-        return USAGE;
-    }
-
-    using android::hidl::manager::V1_0::IServiceManager;
-
-    using android::hardware::details::getRawServiceInternal;
-    auto service = getRawServiceInternal(interface, instance, true /*retry*/, false /*getStub*/);
-
-    if (service == nullptr) {
-        mLshal.err() << "Service not found (missing permissions or not in VINTF manifest?).\n";
-        return NO_INTERFACE;
-    }
-
-    return OK;
-}
-
-void WaitCommand::usage() const {
-    static const std::string debug =
-            "wait:\n"
-            "    lshal wait <interface/instance> \n"
-            "        For a HAL that is on the device, wait for the HAL to start.\n"
-            "        This will not start a HAL unless it is configured as a lazy HAL.\n"
-            "        <interface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n"
-            "            If instance name is missing `default` is used.\n";
-
-    mLshal.err() << debug;
-}
-
-}  // namespace lshal
-}  // namespace android
-
diff --git a/cmds/lshal/WaitCommand.h b/cmds/lshal/WaitCommand.h
deleted file mode 100644
index c9f67c2..0000000
--- a/cmds/lshal/WaitCommand.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <string>
-
-#include <android-base/macros.h>
-
-#include "Command.h"
-#include "utils.h"
-
-namespace android {
-namespace lshal {
-
-class Lshal;
-
-class WaitCommand : public Command {
-public:
-    explicit WaitCommand(Lshal &lshal) : Command(lshal) {}
-    ~WaitCommand() = default;
-    Status main(const Arg &arg) override;
-    void usage() const override;
-    std::string getSimpleDescription() const override;
-    std::string getName() const override;
-private:
-    Status parseArgs(const Arg &arg);
-
-    std::string mInterfaceName;
-
-    DISALLOW_COPY_AND_ASSIGN(WaitCommand);
-};
-
-
-}  // namespace lshal
-}  // namespace android
diff --git a/cmds/lshal/libprocpartition/include/procpartition/procpartition.h b/cmds/lshal/libprocpartition/include/procpartition/procpartition.h
index ca1e690..7e86432 100644
--- a/cmds/lshal/libprocpartition/include/procpartition/procpartition.h
+++ b/cmds/lshal/libprocpartition/include/procpartition/procpartition.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_PROCPARTITION_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_PROCPARTITION_H_
 
 #include <sys/types.h>
 
@@ -43,3 +44,5 @@
 
 }  // namespace procpartition
 }  // namespace android
+
+#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_PROCPARTITION_H_
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index 3d550ba..fc8d58b 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -452,7 +452,7 @@
 }
 
 TEST_F(ListTest, DumpVintf) {
-    const std::string expected = "<manifest version=\"2.0\" type=\"device\">\n"
+    const std::string expected = "<manifest version=\"1.0\" type=\"device\">\n"
                                  "    <hal format=\"hidl\">\n"
                                  "        <name>a.h.foo1</name>\n"
                                  "        <transport>hwbinder</transport>\n"
@@ -493,19 +493,19 @@
 TEST_F(ListTest, DumpDefault) {
     const std::string expected =
         "[fake description 0]\n"
-        "VINTF R Interface            Thread Use Server Clients\n"
-        "X     N a.h.foo1@1.0::IFoo/1 11/21      1      2 4\n"
-        "X     Y a.h.foo2@2.0::IFoo/2 12/22      2      3 5\n"
+        "R Interface            Thread Use Server Clients\n"
+        "N a.h.foo1@1.0::IFoo/1 11/21      1      2 4\n"
+        "Y a.h.foo2@2.0::IFoo/2 12/22      2      3 5\n"
         "\n"
         "[fake description 1]\n"
-        "VINTF R Interface            Thread Use Server Clients\n"
-        "X     ? a.h.foo3@3.0::IFoo/3 N/A        N/A    4 6\n"
-        "X     ? a.h.foo4@4.0::IFoo/4 N/A        N/A    5 7\n"
+        "R Interface            Thread Use Server Clients\n"
+        "? a.h.foo3@3.0::IFoo/3 N/A        N/A    4 6\n"
+        "? a.h.foo4@4.0::IFoo/4 N/A        N/A    5 7\n"
         "\n"
         "[fake description 2]\n"
-        "VINTF R Interface            Thread Use Server Clients\n"
-        "X     ? a.h.foo5@5.0::IFoo/5 N/A        N/A    6 8\n"
-        "X     ? a.h.foo6@6.0::IFoo/6 N/A        N/A    7 9\n"
+        "R Interface            Thread Use Server Clients\n"
+        "? a.h.foo5@5.0::IFoo/5 N/A        N/A    6 8\n"
+        "? a.h.foo6@6.0::IFoo/6 N/A        N/A    7 9\n"
         "\n";
 
     optind = 1; // mimic Lshal::parseArg()
diff --git a/cmds/lshal/utils.h b/cmds/lshal/utils.h
index 04f5272..240155e 100644
--- a/cmds/lshal/utils.h
+++ b/cmds/lshal/utils.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_UTILS_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_UTILS_H_
 
 #include <iomanip>
 #include <iostream>
@@ -87,3 +88,5 @@
 
 }  // namespace lshal
 }  // namespace android
+
+#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_UTILS_H_
diff --git a/cmds/service/Android.bp b/cmds/service/Android.bp
index a5b1ac5..9513ec1 100644
--- a/cmds/service/Android.bp
+++ b/cmds/service/Android.bp
@@ -4,7 +4,6 @@
     srcs: ["service.cpp"],
 
     shared_libs: [
-        "libcutils",
         "libutils",
         "libbinder",
     ],
@@ -23,7 +22,6 @@
     srcs: ["service.cpp"],
 
     shared_libs: [
-        "libcutils",
         "libutils",
         "libbinder",
     ],
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
index 18b6b58..d5dc6b7 100644
--- a/cmds/service/service.cpp
+++ b/cmds/service/service.cpp
@@ -18,18 +18,13 @@
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
 #include <binder/TextOutput.h>
-#include <cutils/ashmem.h>
 
 #include <getopt.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
-#include <sys/mman.h>
 #include <sys/time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 
 using namespace android;
 
@@ -75,7 +70,7 @@
 {
     bool wantsUsage = false;
     int result = 0;
-
+    
     while (1) {
         int ic = getopt(argc, argv, "h?");
         if (ic < 0)
@@ -102,7 +97,7 @@
         aerr << "service: Unable to get default service manager!" << endl;
         return 20;
     }
-
+    
     if (optind >= argc) {
         wantsUsage = true;
     } else if (!wantsUsage) {
@@ -124,8 +119,8 @@
             for (unsigned i = 0; i < services.size(); i++) {
                 String16 name = services[i];
                 sp<IBinder> service = sm->checkService(name);
-                aout << i
-                     << "\t" << good_old_string(name)
+                aout << i 
+                     << "\t" << good_old_string(name) 
                      << ": [" << good_old_string(get_interface_name(service)) << "]"
                      << endl;
             }
@@ -192,120 +187,69 @@
                         } else if (strcmp(argv[optind], "null") == 0) {
                             optind++;
                             data.writeStrongBinder(nullptr);
-                        } else if (strcmp(argv[optind], "fd") == 0) {
-                            optind++;
-                            if (optind >= argc) {
-                                aerr << "service: no path supplied for 'fd'" << endl;
-                                wantsUsage = true;
-                                result = 10;
-                                break;
-                            }
-                            const char *path = argv[optind++];
-                            int fd = open(path, O_RDONLY);
-                            if (fd < 0) {
-                                aerr << "service: could not open '" << path << "'" << endl;
-                                wantsUsage = true;
-                                result = 10;
-                                break;
-                            }
-                            data.writeFileDescriptor(fd, true /* take ownership */);
-                        } else if (strcmp(argv[optind], "afd") == 0) {
-                            optind++;
-                            if (optind >= argc) {
-                                aerr << "service: no path supplied for 'afd'" << endl;
-                                wantsUsage = true;
-                                result = 10;
-                                break;
-                            }
-                            const char *path = argv[optind++];
-                            int fd = open(path, O_RDONLY);
-                            struct stat statbuf;
-                            if (fd < 0 || fstat(fd, &statbuf) != 0) {
-                                aerr << "service: could not open or stat '" << path << "'" << endl;
-                                wantsUsage = true;
-                                result = 10;
-                                break;
-                            }
-                            int afd = ashmem_create_region("test", statbuf.st_size);
-                            void* ptr = mmap(NULL, statbuf.st_size,
-                                   PROT_READ | PROT_WRITE, MAP_SHARED, afd, 0);
-                            read(fd, ptr, statbuf.st_size);
-                            close(fd);
-                            data.writeFileDescriptor(afd, true /* take ownership */);
-                        } else if (strcmp(argv[optind], "nfd") == 0) {
-                            optind++;
-                            if (optind >= argc) {
-                                aerr << "service: no file descriptor supplied for 'nfd'" << endl;
-                                wantsUsage = true;
-                                result = 10;
-                                break;
-                            }
-                            data.writeFileDescriptor(
-                                    atoi(argv[optind++]), true /* take ownership */);
-
                         } else if (strcmp(argv[optind], "intent") == 0) {
-
-                            char* action = nullptr;
-                            char* dataArg = nullptr;
-                            char* type = nullptr;
-                            int launchFlags = 0;
-                            char* component = nullptr;
-                            int categoryCount = 0;
-                            char* categories[16];
-
-                            char* context1 = nullptr;
-
+                        	
+                        	char* action = nullptr;
+                        	char* dataArg = nullptr;
+                        	char* type = nullptr;
+                        	int launchFlags = 0;
+                        	char* component = nullptr;
+                        	int categoryCount = 0;
+                        	char* categories[16];
+                        	
+                        	char* context1 = nullptr;
+                        	
                             optind++;
-
-                            while (optind < argc)
-                            {
-                                char* key = strtok_r(argv[optind], "=", &context1);
-                                char* value = strtok_r(nullptr, "=", &context1);
-
+                            
+                        	while (optind < argc)
+                        	{
+                        		char* key = strtok_r(argv[optind], "=", &context1);
+                        		char* value = strtok_r(nullptr, "=", &context1);
+                                
                                 // we have reached the end of the XXX=XXX args.
                                 if (key == nullptr) break;
-
-                                if (strcmp(key, "action") == 0)
-                                {
-                                    action = value;
-                                }
-                                else if (strcmp(key, "data") == 0)
-                                {
-                                    dataArg = value;
-                                }
-                                else if (strcmp(key, "type") == 0)
-                                {
-                                    type = value;
-                                }
-                                else if (strcmp(key, "launchFlags") == 0)
-                                {
-                                    launchFlags = atoi(value);
-                                }
-                                else if (strcmp(key, "component") == 0)
-                                {
-                                    component = value;
-                                }
-                                else if (strcmp(key, "categories") == 0)
-                                {
-                                    char* context2 = nullptr;
-                                    categories[categoryCount] = strtok_r(value, ",", &context2);
-
-                                    while (categories[categoryCount] != nullptr)
-                                    {
-                                        categoryCount++;
-                                        categories[categoryCount] = strtok_r(nullptr, ",", &context2);
-                                    }
-                                }
-
+                        		
+                        		if (strcmp(key, "action") == 0)
+                        		{
+                        			action = value;
+                        		}
+                        		else if (strcmp(key, "data") == 0)
+                        		{
+                        			dataArg = value;
+                        		}
+                        		else if (strcmp(key, "type") == 0)
+                        		{
+                        			type = value;
+                        		}
+                        		else if (strcmp(key, "launchFlags") == 0)
+                        		{
+                        			launchFlags = atoi(value);
+                        		}
+                        		else if (strcmp(key, "component") == 0)
+                        		{
+                        			component = value;
+                        		}
+                        		else if (strcmp(key, "categories") == 0)
+                        		{
+                        			char* context2 = nullptr;
+                        			categories[categoryCount] = strtok_r(value, ",", &context2);
+                        			
+                        			while (categories[categoryCount] != nullptr)
+                        			{
+                        				categoryCount++;
+                        				categories[categoryCount] = strtok_r(nullptr, ",", &context2);
+                        			}
+                        		}
+                                
                                 optind++;
-                            }
-
+                        	} 
+                        	
                             writeString16(data, action);
                             writeString16(data, dataArg);
                             writeString16(data, type);
-                            data.writeInt32(launchFlags);
+                       		data.writeInt32(launchFlags);
                             writeString16(data, component);
-
+                        	
                             if (categoryCount > 0)
                             {
                                 data.writeInt32(categoryCount);
@@ -317,10 +261,10 @@
                             else
                             {
                                 data.writeInt32(0);
-                            }
-
+                            }                            
+  
                             // for now just set the extra field to be null.
-                            data.writeInt32(-1);
+                       		data.writeInt32(-1);
                         } else {
                             aerr << "service: unknown option " << argv[optind] << endl;
                             wantsUsage = true;
@@ -328,7 +272,7 @@
                             break;
                         }
                     }
-
+                    
                     service->transact(code, data, &reply);
                     aout << "Result: " << reply << endl;
                 } else {
@@ -351,29 +295,23 @@
             result = 10;
         }
     }
-
+    
     if (wantsUsage) {
         aout << "Usage: service [-h|-?]\n"
                 "       service list\n"
                 "       service check SERVICE\n"
-                "       service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR | null"
-                " | fd f | nfd n | afd f ] ...\n"
+                "       service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR ] ...\n"
                 "Options:\n"
                 "   i32: Write the 32-bit integer N into the send parcel.\n"
                 "   i64: Write the 64-bit integer N into the send parcel.\n"
                 "   f:   Write the 32-bit single-precision number N into the send parcel.\n"
                 "   d:   Write the 64-bit double-precision number N into the send parcel.\n"
-                "   s16: Write the UTF-16 string STR into the send parcel.\n"
-                "  null: Write a null binder into the send parcel.\n"
-                "    fd: Write a file descriptor for the file f to the send parcel.\n"
-                "   nfd: Write file descriptor n to the send parcel.\n"
-                "   afd: Write an ashmem file descriptor for a region containing the data from"
-                " file f to the send parcel.\n";
+                "   s16: Write the UTF-16 string STR into the send parcel.\n";
 //                "   intent: Write and Intent int the send parcel. ARGS can be\n"
 //                "       action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
         return result;
     }
-
+    
     return result;
 }
 
diff --git a/cmds/servicemanager/Access.cpp b/cmds/servicemanager/Access.cpp
deleted file mode 100644
index b7e520f..0000000
--- a/cmds/servicemanager/Access.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Access.h"
-
-#include <android-base/logging.h>
-#include <binder/IPCThreadState.h>
-#include <log/log_safetynet.h>
-#include <selinux/android.h>
-#include <selinux/avc.h>
-
-namespace android {
-
-#ifdef VENDORSERVICEMANAGER
-constexpr bool kIsVendor = true;
-#else
-constexpr bool kIsVendor = false;
-#endif
-
-static std::string getPidcon(pid_t pid) {
-    android_errorWriteLog(0x534e4554, "121035042");
-
-    char* lookup = nullptr;
-    if (getpidcon(pid, &lookup) < 0) {
-        LOG(ERROR) << "SELinux: getpidcon(pid=" << pid << ") failed to retrieve pid context";
-        return "";
-    }
-    std::string result = lookup;
-    freecon(lookup);
-    return result;
-}
-
-static struct selabel_handle* getSehandle() {
-    static struct selabel_handle* gSehandle = nullptr;
-
-    if (gSehandle != nullptr && selinux_status_updated()) {
-        selabel_close(gSehandle);
-        gSehandle = nullptr;
-    }
-
-    if (gSehandle == nullptr) {
-        gSehandle = kIsVendor
-            ? selinux_android_vendor_service_context_handle()
-            : selinux_android_service_context_handle();
-    }
-
-    CHECK(gSehandle != nullptr);
-    return gSehandle;
-}
-
-struct AuditCallbackData {
-    const Access::CallingContext* context;
-    const std::string* tname;
-};
-
-static int auditCallback(void *data, security_class_t /*cls*/, char *buf, size_t len) {
-    const AuditCallbackData* ad = reinterpret_cast<AuditCallbackData*>(data);
-
-    if (!ad) {
-        LOG(ERROR) << "No service manager audit data";
-        return 0;
-    }
-
-    snprintf(buf, len, "pid=%d uid=%d name=%s", ad->context->debugPid, ad->context->uid,
-        ad->tname->c_str());
-    return 0;
-}
-
-Access::Access() {
-    union selinux_callback cb;
-
-    cb.func_audit = auditCallback;
-    selinux_set_callback(SELINUX_CB_AUDIT, cb);
-
-    cb.func_log = kIsVendor ? selinux_vendor_log_callback : selinux_log_callback;
-    selinux_set_callback(SELINUX_CB_LOG, cb);
-
-    CHECK(selinux_status_open(true /*fallback*/) >= 0);
-
-    CHECK(getcon(&mThisProcessContext) == 0);
-}
-
-Access::~Access() {
-    freecon(mThisProcessContext);
-}
-
-Access::CallingContext Access::getCallingContext() {
-    IPCThreadState* ipc = IPCThreadState::self();
-
-    const char* callingSid = ipc->getCallingSid();
-    pid_t callingPid = ipc->getCallingPid();
-
-    return CallingContext {
-        .debugPid = callingPid,
-        .uid = ipc->getCallingUid(),
-        .sid = callingSid ? std::string(callingSid) : getPidcon(callingPid),
-    };
-}
-
-bool Access::canFind(const CallingContext& ctx,const std::string& name) {
-    return actionAllowedFromLookup(ctx, name, "find");
-}
-
-bool Access::canAdd(const CallingContext& ctx, const std::string& name) {
-    return actionAllowedFromLookup(ctx, name, "add");
-}
-
-bool Access::canList(const CallingContext& ctx) {
-    return actionAllowed(ctx, mThisProcessContext, "list", "service_manager");
-}
-
-bool Access::actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm,
-        const std::string& tname) {
-    const char* tclass = "service_manager";
-
-    AuditCallbackData data = {
-        .context = &sctx,
-        .tname = &tname,
-    };
-
-    return 0 == selinux_check_access(sctx.sid.c_str(), tctx, tclass, perm,
-        reinterpret_cast<void*>(&data));
-}
-
-bool Access::actionAllowedFromLookup(const CallingContext& sctx, const std::string& name, const char *perm) {
-    char *tctx = nullptr;
-    if (selabel_lookup(getSehandle(), &tctx, name.c_str(), SELABEL_CTX_ANDROID_SERVICE) != 0) {
-        LOG(ERROR) << "SELinux: No match for " << name << " in service_contexts.\n";
-        return false;
-    }
-
-    bool allowed = actionAllowed(sctx, tctx, perm, name);
-    freecon(tctx);
-    return allowed;
-}
-
-}  // android
diff --git a/cmds/servicemanager/Access.h b/cmds/servicemanager/Access.h
deleted file mode 100644
index 77c2cd4..0000000
--- a/cmds/servicemanager/Access.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <string>
-#include <sys/types.h>
-
-namespace android {
-
-// singleton
-class Access {
-public:
-    Access();
-    virtual ~Access();
-
-    Access(const Access&) = delete;
-    Access& operator=(const Access&) = delete;
-    Access(Access&&) = delete;
-    Access& operator=(Access&&) = delete;
-
-    struct CallingContext {
-        pid_t debugPid;
-        uid_t uid;
-        std::string sid;
-    };
-
-    virtual CallingContext getCallingContext();
-
-    virtual bool canFind(const CallingContext& ctx, const std::string& name);
-    virtual bool canAdd(const CallingContext& ctx, const std::string& name);
-    virtual bool canList(const CallingContext& ctx);
-
-private:
-    bool actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm,
-            const std::string& tname);
-    bool actionAllowedFromLookup(const CallingContext& sctx, const std::string& name,
-            const char *perm);
-
-    char* mThisProcessContext = nullptr;
-};
-
-};
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 7277e85..428561b 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -1,58 +1,51 @@
 cc_defaults {
-    name: "servicemanager_defaults",
+    name: "servicemanager_flags",
 
     cflags: [
         "-Wall",
         "-Wextra",
         "-Werror",
     ],
-
-    srcs: [
-        "Access.cpp",
-        "ServiceManager.cpp",
-    ],
-
-    shared_libs: [
-        "libbase",
-        "libbinder", // also contains servicemanager_interface
-        "libvintf",
-        "libcutils",
-        "liblog",
-        "libutils",
-        "libselinux",
-    ],
-
-    target: {
-        vendor: {
-            exclude_shared_libs: ["libvintf"],
+    product_variables: {
+        binder32bit: {
+            cflags: ["-DBINDER_IPC_32BIT=1"],
         },
     },
+
+    shared_libs: ["liblog"],
+}
+
+cc_binary {
+    name: "bctest",
+    defaults: ["servicemanager_flags"],
+    srcs: [
+        "bctest.c",
+        "binder.c",
+    ],
 }
 
 cc_binary {
     name: "servicemanager",
-    defaults: ["servicemanager_defaults"],
+    defaults: ["servicemanager_flags"],
+    srcs: [
+        "service_manager.c",
+        "binder.c",
+    ],
+    shared_libs: ["libcutils", "libselinux"],
     init_rc: ["servicemanager.rc"],
-    srcs: ["main.cpp"],
 }
 
 cc_binary {
     name: "vndservicemanager",
-    defaults: ["servicemanager_defaults"],
-    init_rc: ["vndservicemanager.rc"],
+    defaults: ["servicemanager_flags"],
     vendor: true,
+    srcs: [
+        "service_manager.c",
+        "binder.c",
+    ],
     cflags: [
         "-DVENDORSERVICEMANAGER=1",
     ],
-    srcs: ["main.cpp"],
-}
-
-cc_test {
-    name: "servicemanager_test",
-    test_suites: ["device-tests"],
-    defaults: ["servicemanager_defaults"],
-    srcs: [
-        "test_sm.cpp",
-    ],
-    static_libs: ["libgmock"],
+    shared_libs: ["libcutils", "libselinux"],
+    init_rc: ["vndservicemanager.rc"],
 }
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
deleted file mode 100644
index 861401c..0000000
--- a/cmds/servicemanager/ServiceManager.cpp
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "ServiceManager.h"
-
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <binder/Stability.h>
-#include <cutils/android_filesystem_config.h>
-#include <cutils/multiuser.h>
-#include <thread>
-
-#ifndef VENDORSERVICEMANAGER
-#include <vintf/VintfObject.h>
-#include <vintf/constants.h>
-#endif  // !VENDORSERVICEMANAGER
-
-using ::android::binder::Status;
-using ::android::internal::Stability;
-
-namespace android {
-
-#ifndef VENDORSERVICEMANAGER
-static bool isVintfDeclared(const std::string& name) {
-    size_t firstSlash = name.find('/');
-    size_t lastDot = name.rfind('.', firstSlash);
-    if (firstSlash == std::string::npos || lastDot == std::string::npos) {
-        LOG(ERROR) << "VINTF HALs require names in the format type/instance (e.g. "
-                   << "some.package.foo.IFoo/default) but got: " << name;
-        return false;
-    }
-    const std::string package = name.substr(0, lastDot);
-    const std::string iface = name.substr(lastDot+1, firstSlash-lastDot-1);
-    const std::string instance = name.substr(firstSlash+1);
-
-    for (const auto& manifest : {
-            vintf::VintfObject::GetDeviceHalManifest(),
-            vintf::VintfObject::GetFrameworkHalManifest()
-        }) {
-        if (manifest != nullptr && manifest->hasAidlInstance(package, iface, instance)) {
-            return true;
-        }
-    }
-    LOG(ERROR) << "Could not find " << package << "." << iface << "/" << instance
-               << " in the VINTF manifest.";
-    return false;
-}
-
-static bool meetsDeclarationRequirements(const sp<IBinder>& binder, const std::string& name) {
-    if (!Stability::requiresVintfDeclaration(binder)) {
-        return true;
-    }
-
-    return isVintfDeclared(name);
-}
-#endif  // !VENDORSERVICEMANAGER
-
-ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access)) {}
-ServiceManager::~ServiceManager() {
-    // this should only happen in tests
-
-    for (const auto& [name, callbacks] : mNameToCallback) {
-        CHECK(!callbacks.empty()) << name;
-        for (const auto& callback : callbacks) {
-            CHECK(callback != nullptr) << name;
-        }
-    }
-
-    for (const auto& [name, service] : mNameToService) {
-        CHECK(service.binder != nullptr) << name;
-    }
-}
-
-Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) {
-    *outBinder = tryGetService(name, true);
-    // returns ok regardless of result for legacy reasons
-    return Status::ok();
-}
-
-Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) {
-    *outBinder = tryGetService(name, false);
-    // returns ok regardless of result for legacy reasons
-    return Status::ok();
-}
-
-sp<IBinder> ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) {
-    auto ctx = mAccess->getCallingContext();
-
-    sp<IBinder> out;
-    if (auto it = mNameToService.find(name); it != mNameToService.end()) {
-        const Service& service = it->second;
-
-        if (!service.allowIsolated) {
-            uid_t appid = multiuser_get_app_id(ctx.uid);
-            bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END;
-
-            if (isIsolated) {
-                return nullptr;
-            }
-        }
-        out = service.binder;
-    }
-
-    if (!mAccess->canFind(ctx, name)) {
-        return nullptr;
-    }
-
-    if (!out && startIfNotFound) {
-        tryStartService(name);
-    }
-
-    return out;
-}
-
-bool isValidServiceName(const std::string& name) {
-    if (name.size() == 0) return false;
-    if (name.size() > 127) return false;
-
-    for (char c : name) {
-        if (c == '_' || c == '-' || c == '.' || c == '/') continue;
-        if (c >= 'a' && c <= 'z') continue;
-        if (c >= 'A' && c <= 'Z') continue;
-        if (c >= '0' && c <= '9') continue;
-        return false;
-    }
-
-    return true;
-}
-
-Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
-    auto ctx = mAccess->getCallingContext();
-
-    // apps cannot add services
-    if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
-        return Status::fromExceptionCode(Status::EX_SECURITY);
-    }
-
-    if (!mAccess->canAdd(ctx, name)) {
-        return Status::fromExceptionCode(Status::EX_SECURITY);
-    }
-
-    if (binder == nullptr) {
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
-    }
-
-    if (!isValidServiceName(name)) {
-        LOG(ERROR) << "Invalid service name: " << name;
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
-    }
-
-#ifndef VENDORSERVICEMANAGER
-    if (!meetsDeclarationRequirements(binder, name)) {
-        // already logged
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
-    }
-#endif  // !VENDORSERVICEMANAGER
-
-    // implicitly unlinked when the binder is removed
-    if (binder->remoteBinder() != nullptr && binder->linkToDeath(this) != OK) {
-        LOG(ERROR) << "Could not linkToDeath when adding " << name;
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
-    }
-
-    mNameToService[name] = Service {
-        .binder = binder,
-        .allowIsolated = allowIsolated,
-        .dumpPriority = dumpPriority,
-    };
-
-    auto it = mNameToCallback.find(name);
-    if (it != mNameToCallback.end()) {
-        for (const sp<IServiceCallback>& cb : it->second) {
-            // permission checked in registerForNotifications
-            cb->onRegistration(name, binder);
-        }
-    }
-
-    return Status::ok();
-}
-
-Status ServiceManager::listServices(int32_t dumpPriority, std::vector<std::string>* outList) {
-    if (!mAccess->canList(mAccess->getCallingContext())) {
-        return Status::fromExceptionCode(Status::EX_SECURITY);
-    }
-
-    size_t toReserve = 0;
-    for (auto const& [name, service] : mNameToService) {
-        (void) name;
-
-        if (service.dumpPriority & dumpPriority) ++toReserve;
-    }
-
-    CHECK(outList->empty());
-
-    outList->reserve(toReserve);
-    for (auto const& [name, service] : mNameToService) {
-        (void) service;
-
-        if (service.dumpPriority & dumpPriority) {
-            outList->push_back(name);
-        }
-    }
-
-    return Status::ok();
-}
-
-Status ServiceManager::registerForNotifications(
-        const std::string& name, const sp<IServiceCallback>& callback) {
-    auto ctx = mAccess->getCallingContext();
-
-    if (!mAccess->canFind(ctx, name)) {
-        return Status::fromExceptionCode(Status::EX_SECURITY);
-    }
-
-    if (!isValidServiceName(name)) {
-        LOG(ERROR) << "Invalid service name: " << name;
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
-    }
-
-    if (callback == nullptr) {
-        return Status::fromExceptionCode(Status::EX_NULL_POINTER);
-    }
-
-    if (OK != IInterface::asBinder(callback)->linkToDeath(this)) {
-        LOG(ERROR) << "Could not linkToDeath when adding " << name;
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
-    }
-
-    mNameToCallback[name].push_back(callback);
-
-    if (auto it = mNameToService.find(name); it != mNameToService.end()) {
-        const sp<IBinder>& binder = it->second.binder;
-
-        // never null if an entry exists
-        CHECK(binder != nullptr) << name;
-        callback->onRegistration(name, binder);
-    }
-
-    return Status::ok();
-}
-Status ServiceManager::unregisterForNotifications(
-        const std::string& name, const sp<IServiceCallback>& callback) {
-    auto ctx = mAccess->getCallingContext();
-
-    if (!mAccess->canFind(ctx, name)) {
-        return Status::fromExceptionCode(Status::EX_SECURITY);
-    }
-
-    bool found = false;
-
-    auto it = mNameToCallback.find(name);
-    if (it != mNameToCallback.end()) {
-        removeCallback(IInterface::asBinder(callback), &it, &found);
-    }
-
-    if (!found) {
-        LOG(ERROR) << "Trying to unregister callback, but none exists " << name;
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
-    }
-
-    return Status::ok();
-}
-
-Status ServiceManager::isDeclared(const std::string& name, bool* outReturn) {
-    auto ctx = mAccess->getCallingContext();
-
-    if (!mAccess->canFind(ctx, name)) {
-        return Status::fromExceptionCode(Status::EX_SECURITY);
-    }
-
-    *outReturn = false;
-
-#ifndef VENDORSERVICEMANAGER
-    *outReturn = isVintfDeclared(name);
-#endif
-    return Status::ok();
-}
-
-void ServiceManager::removeCallback(const wp<IBinder>& who,
-                                    CallbackMap::iterator* it,
-                                    bool* found) {
-    std::vector<sp<IServiceCallback>>& listeners = (*it)->second;
-
-    for (auto lit = listeners.begin(); lit != listeners.end();) {
-        if (IInterface::asBinder(*lit) == who) {
-            if(found) *found = true;
-            lit = listeners.erase(lit);
-        } else {
-            ++lit;
-        }
-    }
-
-    if (listeners.empty()) {
-        *it = mNameToCallback.erase(*it);
-    } else {
-        it++;
-    }
-}
-
-void ServiceManager::binderDied(const wp<IBinder>& who) {
-    for (auto it = mNameToService.begin(); it != mNameToService.end();) {
-        if (who == it->second.binder) {
-            it = mNameToService.erase(it);
-        } else {
-            ++it;
-        }
-    }
-
-    for (auto it = mNameToCallback.begin(); it != mNameToCallback.end();) {
-        removeCallback(who, &it, nullptr /*found*/);
-    }
-}
-
-void ServiceManager::tryStartService(const std::string& name) {
-    ALOGI("Since '%s' could not be found, trying to start it as a lazy AIDL service",
-          name.c_str());
-
-    std::thread([=] {
-        (void)base::SetProperty("ctl.interface_start", "aidl/" + name);
-    }).detach();
-}
-
-}  // namespace android
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
deleted file mode 100644
index 7dcdaa4..0000000
--- a/cmds/servicemanager/ServiceManager.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <android/os/BnServiceManager.h>
-#include <android/os/IServiceCallback.h>
-
-#include "Access.h"
-
-namespace android {
-
-using os::IServiceCallback;
-
-class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient {
-public:
-    ServiceManager(std::unique_ptr<Access>&& access);
-    ~ServiceManager();
-
-    // getService will try to start any services it cannot find
-    binder::Status getService(const std::string& name, sp<IBinder>* outBinder) override;
-    binder::Status checkService(const std::string& name, sp<IBinder>* outBinder) override;
-    binder::Status addService(const std::string& name, const sp<IBinder>& binder,
-                              bool allowIsolated, int32_t dumpPriority) override;
-    binder::Status listServices(int32_t dumpPriority, std::vector<std::string>* outList) override;
-    binder::Status registerForNotifications(const std::string& name,
-                                            const sp<IServiceCallback>& callback) override;
-    binder::Status unregisterForNotifications(const std::string& name,
-                                              const sp<IServiceCallback>& callback) override;
-    binder::Status isDeclared(const std::string& name, bool* outReturn) override;
-
-    void binderDied(const wp<IBinder>& who) override;
-
-protected:
-    virtual void tryStartService(const std::string& name);
-
-private:
-    struct Service {
-        sp<IBinder> binder; // not null
-        bool allowIsolated;
-        int32_t dumpPriority;
-    };
-
-    using CallbackMap = std::map<std::string, std::vector<sp<IServiceCallback>>>;
-    using ServiceMap = std::map<std::string, Service>;
-
-    // removes a callback from mNameToCallback, removing it if the vector is empty
-    // this updates iterator to the next location
-    void removeCallback(const wp<IBinder>& who,
-                        CallbackMap::iterator* it,
-                        bool* found);
-    sp<IBinder> tryGetService(const std::string& name, bool startIfNotFound);
-
-    CallbackMap mNameToCallback;
-    ServiceMap mNameToService;
-
-    std::unique_ptr<Access> mAccess;
-};
-
-}  // namespace android
diff --git a/cmds/servicemanager/TEST_MAPPING b/cmds/servicemanager/TEST_MAPPING
deleted file mode 100644
index 739740a..0000000
--- a/cmds/servicemanager/TEST_MAPPING
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "presubmit": [
-    {
-      "name": "servicemanager_test"
-    }
-  ],
-  "imports": [
-    {
-      "path": "frameworks/native/libs/binder"
-    }
-  ]
-}
diff --git a/cmds/servicemanager/bctest.c b/cmds/servicemanager/bctest.c
new file mode 100644
index 0000000..354df67
--- /dev/null
+++ b/cmds/servicemanager/bctest.c
@@ -0,0 +1,107 @@
+/* Copyright 2008 The Android Open Source Project
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "binder.h"
+
+uint32_t svcmgr_lookup(struct binder_state *bs, uint32_t target, const char *name)
+{
+    uint32_t handle;
+    unsigned iodata[512/4];
+    struct binder_io msg, reply;
+
+    bio_init(&msg, iodata, sizeof(iodata), 4);
+    bio_put_uint32(&msg, 0);  // strict mode header
+    bio_put_string16_x(&msg, SVC_MGR_NAME);
+    bio_put_string16_x(&msg, name);
+
+    if (binder_call(bs, &msg, &reply, target, SVC_MGR_CHECK_SERVICE))
+        return 0;
+
+    handle = bio_get_ref(&reply);
+
+    if (handle)
+        binder_acquire(bs, handle);
+
+    binder_done(bs, &msg, &reply);
+
+    return handle;
+}
+
+int svcmgr_publish(struct binder_state *bs, uint32_t target, const char *name, void *ptr)
+{
+    int status;
+    unsigned iodata[512/4];
+    struct binder_io msg, reply;
+
+    bio_init(&msg, iodata, sizeof(iodata), 4);
+    bio_put_uint32(&msg, 0);  // strict mode header
+    bio_put_string16_x(&msg, SVC_MGR_NAME);
+    bio_put_string16_x(&msg, name);
+    bio_put_obj(&msg, ptr);
+
+    if (binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE))
+        return -1;
+
+    status = bio_get_uint32(&reply);
+
+    binder_done(bs, &msg, &reply);
+
+    return status;
+}
+
+unsigned token;
+
+int main(int argc, char **argv)
+{
+    struct binder_state *bs;
+    uint32_t svcmgr = BINDER_SERVICE_MANAGER;
+    uint32_t handle;
+
+    bs = binder_open("/dev/binder", 128*1024);
+    if (!bs) {
+        fprintf(stderr, "failed to open binder driver\n");
+        return -1;
+    }
+
+    argc--;
+    argv++;
+    while (argc > 0) {
+        if (!strcmp(argv[0],"alt")) {
+            handle = svcmgr_lookup(bs, svcmgr, "alt_svc_mgr");
+            if (!handle) {
+                fprintf(stderr,"cannot find alt_svc_mgr\n");
+                return -1;
+            }
+            svcmgr = handle;
+            fprintf(stderr,"svcmgr is via %x\n", handle);
+        } else if (!strcmp(argv[0],"lookup")) {
+            if (argc < 2) {
+                fprintf(stderr,"argument required\n");
+                return -1;
+            }
+            handle = svcmgr_lookup(bs, svcmgr, argv[1]);
+            fprintf(stderr,"lookup(%s) = %x\n", argv[1], handle);
+            argc--;
+            argv++;
+        } else if (!strcmp(argv[0],"publish")) {
+            if (argc < 2) {
+                fprintf(stderr,"argument required\n");
+                return -1;
+            }
+            svcmgr_publish(bs, svcmgr, argv[1], &token);
+            argc--;
+            argv++;
+        } else {
+            fprintf(stderr,"unknown command %s\n", argv[0]);
+            return -1;
+        }
+        argc--;
+        argv++;
+    }
+    return 0;
+}
diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c
new file mode 100644
index 0000000..cf3b172
--- /dev/null
+++ b/cmds/servicemanager/binder.c
@@ -0,0 +1,682 @@
+/* Copyright 2008 The Android Open Source Project
+ */
+
+#define LOG_TAG "Binder"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include <log/log.h>
+
+#include "binder.h"
+
+#define MAX_BIO_SIZE (1 << 30)
+
+#define TRACE 0
+
+void bio_init_from_txn(struct binder_io *io, struct binder_transaction_data *txn);
+
+#if TRACE
+void hexdump(void *_data, size_t len)
+{
+    unsigned char *data = _data;
+    size_t count;
+
+    for (count = 0; count < len; count++) {
+        if ((count & 15) == 0)
+            fprintf(stderr,"%04zu:", count);
+        fprintf(stderr," %02x %c", *data,
+                (*data < 32) || (*data > 126) ? '.' : *data);
+        data++;
+        if ((count & 15) == 15)
+            fprintf(stderr,"\n");
+    }
+    if ((count & 15) != 0)
+        fprintf(stderr,"\n");
+}
+
+void binder_dump_txn(struct binder_transaction_data *txn)
+{
+    struct flat_binder_object *obj;
+    binder_size_t *offs = (binder_size_t *)(uintptr_t)txn->data.ptr.offsets;
+    size_t count = txn->offsets_size / sizeof(binder_size_t);
+
+    fprintf(stderr,"  target %016"PRIx64"  cookie %016"PRIx64"  code %08x  flags %08x\n",
+            (uint64_t)txn->target.ptr, (uint64_t)txn->cookie, txn->code, txn->flags);
+    fprintf(stderr,"  pid %8d  uid %8d  data %"PRIu64"  offs %"PRIu64"\n",
+            txn->sender_pid, txn->sender_euid, (uint64_t)txn->data_size, (uint64_t)txn->offsets_size);
+    hexdump((void *)(uintptr_t)txn->data.ptr.buffer, txn->data_size);
+    while (count--) {
+        obj = (struct flat_binder_object *) (((char*)(uintptr_t)txn->data.ptr.buffer) + *offs++);
+        fprintf(stderr,"  - type %08x  flags %08x  ptr %016"PRIx64"  cookie %016"PRIx64"\n",
+                obj->type, obj->flags, (uint64_t)obj->binder, (uint64_t)obj->cookie);
+    }
+}
+
+#define NAME(n) case n: return #n
+const char *cmd_name(uint32_t cmd)
+{
+    switch(cmd) {
+        NAME(BR_NOOP);
+        NAME(BR_TRANSACTION_COMPLETE);
+        NAME(BR_INCREFS);
+        NAME(BR_ACQUIRE);
+        NAME(BR_RELEASE);
+        NAME(BR_DECREFS);
+        NAME(BR_TRANSACTION);
+        NAME(BR_REPLY);
+        NAME(BR_FAILED_REPLY);
+        NAME(BR_DEAD_REPLY);
+        NAME(BR_DEAD_BINDER);
+    default: return "???";
+    }
+}
+#else
+#define hexdump(a,b) do{} while (0)
+#define binder_dump_txn(txn)  do{} while (0)
+#endif
+
+#define BIO_F_SHARED    0x01  /* needs to be buffer freed */
+#define BIO_F_OVERFLOW  0x02  /* ran out of space */
+#define BIO_F_IOERROR   0x04
+#define BIO_F_MALLOCED  0x08  /* needs to be free()'d */
+
+struct binder_state
+{
+    int fd;
+    void *mapped;
+    size_t mapsize;
+};
+
+struct binder_state *binder_open(const char* driver, size_t mapsize)
+{
+    struct binder_state *bs;
+    struct binder_version vers;
+
+    bs = malloc(sizeof(*bs));
+    if (!bs) {
+        errno = ENOMEM;
+        return NULL;
+    }
+
+    bs->fd = open(driver, O_RDWR | O_CLOEXEC);
+    if (bs->fd < 0) {
+        fprintf(stderr,"binder: cannot open %s (%s)\n",
+                driver, strerror(errno));
+        goto fail_open;
+    }
+
+    if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
+        (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
+        fprintf(stderr,
+                "binder: kernel driver version (%d) differs from user space version (%d)\n",
+                vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
+        goto fail_open;
+    }
+
+    bs->mapsize = mapsize;
+    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
+    if (bs->mapped == MAP_FAILED) {
+        fprintf(stderr,"binder: cannot map device (%s)\n",
+                strerror(errno));
+        goto fail_map;
+    }
+
+    return bs;
+
+fail_map:
+    close(bs->fd);
+fail_open:
+    free(bs);
+    return NULL;
+}
+
+void binder_close(struct binder_state *bs)
+{
+    munmap(bs->mapped, bs->mapsize);
+    close(bs->fd);
+    free(bs);
+}
+
+int binder_become_context_manager(struct binder_state *bs)
+{
+    struct flat_binder_object obj;
+    memset(&obj, 0, sizeof(obj));
+    obj.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
+
+    int result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR_EXT, &obj);
+
+    // fallback to original method
+    if (result != 0) {
+        android_errorWriteLog(0x534e4554, "121035042");
+
+        result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
+    }
+    return result;
+}
+
+int binder_write(struct binder_state *bs, void *data, size_t len)
+{
+    struct binder_write_read bwr;
+    int res;
+
+    bwr.write_size = len;
+    bwr.write_consumed = 0;
+    bwr.write_buffer = (uintptr_t) data;
+    bwr.read_size = 0;
+    bwr.read_consumed = 0;
+    bwr.read_buffer = 0;
+    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
+    if (res < 0) {
+        fprintf(stderr,"binder_write: ioctl failed (%s)\n",
+                strerror(errno));
+    }
+    return res;
+}
+
+void binder_free_buffer(struct binder_state *bs,
+                        binder_uintptr_t buffer_to_free)
+{
+    struct {
+        uint32_t cmd_free;
+        binder_uintptr_t buffer;
+    } __attribute__((packed)) data;
+    data.cmd_free = BC_FREE_BUFFER;
+    data.buffer = buffer_to_free;
+    binder_write(bs, &data, sizeof(data));
+}
+
+void binder_send_reply(struct binder_state *bs,
+                       struct binder_io *reply,
+                       binder_uintptr_t buffer_to_free,
+                       int status)
+{
+    struct {
+        uint32_t cmd_free;
+        binder_uintptr_t buffer;
+        uint32_t cmd_reply;
+        struct binder_transaction_data txn;
+    } __attribute__((packed)) data;
+
+    data.cmd_free = BC_FREE_BUFFER;
+    data.buffer = buffer_to_free;
+    data.cmd_reply = BC_REPLY;
+    data.txn.target.ptr = 0;
+    data.txn.cookie = 0;
+    data.txn.code = 0;
+    if (status) {
+        data.txn.flags = TF_STATUS_CODE;
+        data.txn.data_size = sizeof(int);
+        data.txn.offsets_size = 0;
+        data.txn.data.ptr.buffer = (uintptr_t)&status;
+        data.txn.data.ptr.offsets = 0;
+    } else {
+        data.txn.flags = 0;
+        data.txn.data_size = reply->data - reply->data0;
+        data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0);
+        data.txn.data.ptr.buffer = (uintptr_t)reply->data0;
+        data.txn.data.ptr.offsets = (uintptr_t)reply->offs0;
+    }
+    binder_write(bs, &data, sizeof(data));
+}
+
+int binder_parse(struct binder_state *bs, struct binder_io *bio,
+                 uintptr_t ptr, size_t size, binder_handler func)
+{
+    int r = 1;
+    uintptr_t end = ptr + (uintptr_t) size;
+
+    while (ptr < end) {
+        uint32_t cmd = *(uint32_t *) ptr;
+        ptr += sizeof(uint32_t);
+#if TRACE
+        fprintf(stderr,"%s:\n", cmd_name(cmd));
+#endif
+        switch(cmd) {
+        case BR_NOOP:
+            break;
+        case BR_TRANSACTION_COMPLETE:
+            break;
+        case BR_INCREFS:
+        case BR_ACQUIRE:
+        case BR_RELEASE:
+        case BR_DECREFS:
+#if TRACE
+            fprintf(stderr,"  %p, %p\n", (void *)ptr, (void *)(ptr + sizeof(void *)));
+#endif
+            ptr += sizeof(struct binder_ptr_cookie);
+            break;
+        case BR_TRANSACTION_SEC_CTX:
+        case BR_TRANSACTION: {
+            struct binder_transaction_data_secctx txn;
+            if (cmd == BR_TRANSACTION_SEC_CTX) {
+                if ((end - ptr) < sizeof(struct binder_transaction_data_secctx)) {
+                    ALOGE("parse: txn too small (binder_transaction_data_secctx)!\n");
+                    return -1;
+                }
+                memcpy(&txn, (void*) ptr, sizeof(struct binder_transaction_data_secctx));
+                ptr += sizeof(struct binder_transaction_data_secctx);
+            } else /* BR_TRANSACTION */ {
+                if ((end - ptr) < sizeof(struct binder_transaction_data)) {
+                    ALOGE("parse: txn too small (binder_transaction_data)!\n");
+                    return -1;
+                }
+                memcpy(&txn.transaction_data, (void*) ptr, sizeof(struct binder_transaction_data));
+                ptr += sizeof(struct binder_transaction_data);
+
+                txn.secctx = 0;
+            }
+
+            binder_dump_txn(&txn.transaction_data);
+            if (func) {
+                unsigned rdata[256/4];
+                struct binder_io msg;
+                struct binder_io reply;
+                int res;
+
+                bio_init(&reply, rdata, sizeof(rdata), 4);
+                bio_init_from_txn(&msg, &txn.transaction_data);
+                res = func(bs, &txn, &msg, &reply);
+                if (txn.transaction_data.flags & TF_ONE_WAY) {
+                    binder_free_buffer(bs, txn.transaction_data.data.ptr.buffer);
+                } else {
+                    binder_send_reply(bs, &reply, txn.transaction_data.data.ptr.buffer, res);
+                }
+            }
+            break;
+        }
+        case BR_REPLY: {
+            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
+            if ((end - ptr) < sizeof(*txn)) {
+                ALOGE("parse: reply too small!\n");
+                return -1;
+            }
+            binder_dump_txn(txn);
+            if (bio) {
+                bio_init_from_txn(bio, txn);
+                bio = 0;
+            } else {
+                /* todo FREE BUFFER */
+            }
+            ptr += sizeof(*txn);
+            r = 0;
+            break;
+        }
+        case BR_DEAD_BINDER: {
+            struct binder_death *death = (struct binder_death *)(uintptr_t) *(binder_uintptr_t *)ptr;
+            ptr += sizeof(binder_uintptr_t);
+            death->func(bs, death->ptr);
+            break;
+        }
+        case BR_FAILED_REPLY:
+            r = -1;
+            break;
+        case BR_DEAD_REPLY:
+            r = -1;
+            break;
+        default:
+            ALOGE("parse: OOPS %d\n", cmd);
+            return -1;
+        }
+    }
+
+    return r;
+}
+
+void binder_acquire(struct binder_state *bs, uint32_t target)
+{
+    uint32_t cmd[2];
+    cmd[0] = BC_ACQUIRE;
+    cmd[1] = target;
+    binder_write(bs, cmd, sizeof(cmd));
+}
+
+void binder_release(struct binder_state *bs, uint32_t target)
+{
+    uint32_t cmd[2];
+    cmd[0] = BC_RELEASE;
+    cmd[1] = target;
+    binder_write(bs, cmd, sizeof(cmd));
+}
+
+void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death)
+{
+    struct {
+        uint32_t cmd;
+        struct binder_handle_cookie payload;
+    } __attribute__((packed)) data;
+
+    data.cmd = BC_REQUEST_DEATH_NOTIFICATION;
+    data.payload.handle = target;
+    data.payload.cookie = (uintptr_t) death;
+    binder_write(bs, &data, sizeof(data));
+}
+
+int binder_call(struct binder_state *bs,
+                struct binder_io *msg, struct binder_io *reply,
+                uint32_t target, uint32_t code)
+{
+    int res;
+    struct binder_write_read bwr;
+    struct {
+        uint32_t cmd;
+        struct binder_transaction_data txn;
+    } __attribute__((packed)) writebuf;
+    unsigned readbuf[32];
+
+    if (msg->flags & BIO_F_OVERFLOW) {
+        fprintf(stderr,"binder: txn buffer overflow\n");
+        goto fail;
+    }
+
+    writebuf.cmd = BC_TRANSACTION;
+    writebuf.txn.target.handle = target;
+    writebuf.txn.code = code;
+    writebuf.txn.flags = 0;
+    writebuf.txn.data_size = msg->data - msg->data0;
+    writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0);
+    writebuf.txn.data.ptr.buffer = (uintptr_t)msg->data0;
+    writebuf.txn.data.ptr.offsets = (uintptr_t)msg->offs0;
+
+    bwr.write_size = sizeof(writebuf);
+    bwr.write_consumed = 0;
+    bwr.write_buffer = (uintptr_t) &writebuf;
+
+    hexdump(msg->data0, msg->data - msg->data0);
+    for (;;) {
+        bwr.read_size = sizeof(readbuf);
+        bwr.read_consumed = 0;
+        bwr.read_buffer = (uintptr_t) readbuf;
+
+        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
+
+        if (res < 0) {
+            fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
+            goto fail;
+        }
+
+        res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0);
+        if (res == 0) return 0;
+        if (res < 0) goto fail;
+    }
+
+fail:
+    memset(reply, 0, sizeof(*reply));
+    reply->flags |= BIO_F_IOERROR;
+    return -1;
+}
+
+void binder_loop(struct binder_state *bs, binder_handler func)
+{
+    int res;
+    struct binder_write_read bwr;
+    uint32_t readbuf[32];
+
+    bwr.write_size = 0;
+    bwr.write_consumed = 0;
+    bwr.write_buffer = 0;
+
+    readbuf[0] = BC_ENTER_LOOPER;
+    binder_write(bs, readbuf, sizeof(uint32_t));
+
+    for (;;) {
+        bwr.read_size = sizeof(readbuf);
+        bwr.read_consumed = 0;
+        bwr.read_buffer = (uintptr_t) readbuf;
+
+        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
+
+        if (res < 0) {
+            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
+            break;
+        }
+
+        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
+        if (res == 0) {
+            ALOGE("binder_loop: unexpected reply?!\n");
+            break;
+        }
+        if (res < 0) {
+            ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
+            break;
+        }
+    }
+}
+
+void bio_init_from_txn(struct binder_io *bio, struct binder_transaction_data *txn)
+{
+    bio->data = bio->data0 = (char *)(intptr_t)txn->data.ptr.buffer;
+    bio->offs = bio->offs0 = (binder_size_t *)(intptr_t)txn->data.ptr.offsets;
+    bio->data_avail = txn->data_size;
+    bio->offs_avail = txn->offsets_size / sizeof(size_t);
+    bio->flags = BIO_F_SHARED;
+}
+
+void bio_init(struct binder_io *bio, void *data,
+              size_t maxdata, size_t maxoffs)
+{
+    size_t n = maxoffs * sizeof(size_t);
+
+    if (n > maxdata) {
+        bio->flags = BIO_F_OVERFLOW;
+        bio->data_avail = 0;
+        bio->offs_avail = 0;
+        return;
+    }
+
+    bio->data = bio->data0 = (char *) data + n;
+    bio->offs = bio->offs0 = data;
+    bio->data_avail = maxdata - n;
+    bio->offs_avail = maxoffs;
+    bio->flags = 0;
+}
+
+static void *bio_alloc(struct binder_io *bio, size_t size)
+{
+    size = (size + 3) & (~3);
+    if (size > bio->data_avail) {
+        bio->flags |= BIO_F_OVERFLOW;
+        return NULL;
+    } else {
+        void *ptr = bio->data;
+        bio->data += size;
+        bio->data_avail -= size;
+        return ptr;
+    }
+}
+
+void binder_done(struct binder_state *bs,
+                 __unused struct binder_io *msg,
+                 struct binder_io *reply)
+{
+    struct {
+        uint32_t cmd;
+        uintptr_t buffer;
+    } __attribute__((packed)) data;
+
+    if (reply->flags & BIO_F_SHARED) {
+        data.cmd = BC_FREE_BUFFER;
+        data.buffer = (uintptr_t) reply->data0;
+        binder_write(bs, &data, sizeof(data));
+        reply->flags = 0;
+    }
+}
+
+static struct flat_binder_object *bio_alloc_obj(struct binder_io *bio)
+{
+    struct flat_binder_object *obj;
+
+    obj = bio_alloc(bio, sizeof(*obj));
+
+    if (obj && bio->offs_avail) {
+        bio->offs_avail--;
+        *bio->offs++ = ((char*) obj) - ((char*) bio->data0);
+        return obj;
+    }
+
+    bio->flags |= BIO_F_OVERFLOW;
+    return NULL;
+}
+
+void bio_put_uint32(struct binder_io *bio, uint32_t n)
+{
+    uint32_t *ptr = bio_alloc(bio, sizeof(n));
+    if (ptr)
+        *ptr = n;
+}
+
+void bio_put_obj(struct binder_io *bio, void *ptr)
+{
+    struct flat_binder_object *obj;
+
+    obj = bio_alloc_obj(bio);
+    if (!obj)
+        return;
+
+    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+    obj->hdr.type = BINDER_TYPE_BINDER;
+    obj->binder = (uintptr_t)ptr;
+    obj->cookie = 0;
+}
+
+void bio_put_ref(struct binder_io *bio, uint32_t handle)
+{
+    struct flat_binder_object *obj;
+
+    if (handle)
+        obj = bio_alloc_obj(bio);
+    else
+        obj = bio_alloc(bio, sizeof(*obj));
+
+    if (!obj)
+        return;
+
+    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+    obj->hdr.type = BINDER_TYPE_HANDLE;
+    obj->handle = handle;
+    obj->cookie = 0;
+}
+
+void bio_put_string16(struct binder_io *bio, const uint16_t *str)
+{
+    size_t len;
+    uint16_t *ptr;
+
+    if (!str) {
+        bio_put_uint32(bio, 0xffffffff);
+        return;
+    }
+
+    len = 0;
+    while (str[len]) len++;
+
+    if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
+        bio_put_uint32(bio, 0xffffffff);
+        return;
+    }
+
+    /* Note: The payload will carry 32bit size instead of size_t */
+    bio_put_uint32(bio, (uint32_t) len);
+    len = (len + 1) * sizeof(uint16_t);
+    ptr = bio_alloc(bio, len);
+    if (ptr)
+        memcpy(ptr, str, len);
+}
+
+void bio_put_string16_x(struct binder_io *bio, const char *_str)
+{
+    unsigned char *str = (unsigned char*) _str;
+    size_t len;
+    uint16_t *ptr;
+
+    if (!str) {
+        bio_put_uint32(bio, 0xffffffff);
+        return;
+    }
+
+    len = strlen(_str);
+
+    if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
+        bio_put_uint32(bio, 0xffffffff);
+        return;
+    }
+
+    /* Note: The payload will carry 32bit size instead of size_t */
+    bio_put_uint32(bio, len);
+    ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t));
+    if (!ptr)
+        return;
+
+    while (*str)
+        *ptr++ = *str++;
+    *ptr++ = 0;
+}
+
+static void *bio_get(struct binder_io *bio, size_t size)
+{
+    size = (size + 3) & (~3);
+
+    if (bio->data_avail < size){
+        bio->data_avail = 0;
+        bio->flags |= BIO_F_OVERFLOW;
+        return NULL;
+    }  else {
+        void *ptr = bio->data;
+        bio->data += size;
+        bio->data_avail -= size;
+        return ptr;
+    }
+}
+
+uint32_t bio_get_uint32(struct binder_io *bio)
+{
+    uint32_t *ptr = bio_get(bio, sizeof(*ptr));
+    return ptr ? *ptr : 0;
+}
+
+uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz)
+{
+    size_t len;
+
+    /* Note: The payload will carry 32bit size instead of size_t */
+    len = (size_t) bio_get_uint32(bio);
+    if (sz)
+        *sz = len;
+    return bio_get(bio, (len + 1) * sizeof(uint16_t));
+}
+
+static struct flat_binder_object *_bio_get_obj(struct binder_io *bio)
+{
+    size_t n;
+    size_t off = bio->data - bio->data0;
+
+    /* TODO: be smarter about this? */
+    for (n = 0; n < bio->offs_avail; n++) {
+        if (bio->offs[n] == off)
+            return bio_get(bio, sizeof(struct flat_binder_object));
+    }
+
+    bio->data_avail = 0;
+    bio->flags |= BIO_F_OVERFLOW;
+    return NULL;
+}
+
+uint32_t bio_get_ref(struct binder_io *bio)
+{
+    struct flat_binder_object *obj;
+
+    obj = _bio_get_obj(bio);
+    if (!obj)
+        return 0;
+
+    if (obj->hdr.type == BINDER_TYPE_HANDLE)
+        return obj->handle;
+
+    return 0;
+}
diff --git a/cmds/servicemanager/binder.h b/cmds/servicemanager/binder.h
new file mode 100644
index 0000000..a9ccc74
--- /dev/null
+++ b/cmds/servicemanager/binder.h
@@ -0,0 +1,94 @@
+/* Copyright 2008 The Android Open Source Project
+ */
+
+#ifndef _BINDER_H_
+#define _BINDER_H_
+
+#include <linux/android/binder.h>
+#include <sys/ioctl.h>
+
+struct binder_state;
+
+struct binder_io
+{
+    char *data;            /* pointer to read/write from */
+    binder_size_t *offs;   /* array of offsets */
+    size_t data_avail;     /* bytes available in data buffer */
+    size_t offs_avail;     /* entries available in offsets array */
+
+    char *data0;           /* start of data buffer */
+    binder_size_t *offs0;  /* start of offsets buffer */
+    uint32_t flags;
+    uint32_t unused;
+};
+
+struct binder_death {
+    void (*func)(struct binder_state *bs, void *ptr);
+    void *ptr;
+};
+
+/* the one magic handle */
+#define BINDER_SERVICE_MANAGER  0U
+
+#define SVC_MGR_NAME "android.os.IServiceManager"
+
+enum {
+    /* Must match definitions in IBinder.h and IServiceManager.h */
+    PING_TRANSACTION  = B_PACK_CHARS('_','P','N','G'),
+    SVC_MGR_GET_SERVICE = 1,
+    SVC_MGR_CHECK_SERVICE,
+    SVC_MGR_ADD_SERVICE,
+    SVC_MGR_LIST_SERVICES,
+};
+
+typedef int (*binder_handler)(struct binder_state *bs,
+                              struct binder_transaction_data_secctx *txn,
+                              struct binder_io *msg,
+                              struct binder_io *reply);
+
+struct binder_state *binder_open(const char* driver, size_t mapsize);
+void binder_close(struct binder_state *bs);
+
+/* initiate a blocking binder call
+ * - returns zero on success
+ */
+int binder_call(struct binder_state *bs,
+                struct binder_io *msg, struct binder_io *reply,
+                uint32_t target, uint32_t code);
+
+/* release any state associate with the binder_io
+ * - call once any necessary data has been extracted from the
+ *   binder_io after binder_call() returns
+ * - can safely be called even if binder_call() fails
+ */
+void binder_done(struct binder_state *bs,
+                 struct binder_io *msg, struct binder_io *reply);
+
+/* manipulate strong references */
+void binder_acquire(struct binder_state *bs, uint32_t target);
+void binder_release(struct binder_state *bs, uint32_t target);
+
+void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death);
+
+void binder_loop(struct binder_state *bs, binder_handler func);
+
+int binder_become_context_manager(struct binder_state *bs);
+
+/* allocate a binder_io, providing a stack-allocated working
+ * buffer, size of the working buffer, and how many object
+ * offset entries to reserve from the buffer
+ */
+void bio_init(struct binder_io *bio, void *data,
+           size_t maxdata, size_t maxobjects);
+
+void bio_put_obj(struct binder_io *bio, void *ptr);
+void bio_put_ref(struct binder_io *bio, uint32_t handle);
+void bio_put_uint32(struct binder_io *bio, uint32_t n);
+void bio_put_string16(struct binder_io *bio, const uint16_t *str);
+void bio_put_string16_x(struct binder_io *bio, const char *_str);
+
+uint32_t bio_get_uint32(struct binder_io *bio);
+uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz);
+uint32_t bio_get_ref(struct binder_io *bio);
+
+#endif
diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp
deleted file mode 100644
index 4b12fc6..0000000
--- a/cmds/servicemanager/main.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/Status.h>
-#include <utils/StrongPointer.h>
-
-#include "Access.h"
-#include "ServiceManager.h"
-
-using ::android::Access;
-using ::android::IPCThreadState;
-using ::android::ProcessState;
-using ::android::ServiceManager;
-using ::android::os::IServiceManager;
-using ::android::sp;
-
-int main(int argc, char** argv) {
-    if (argc > 2) {
-        LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
-    }
-
-    const char* driver = argc == 2 ? argv[1] : "/dev/binder";
-
-    sp<ProcessState> ps = ProcessState::initWithDriver(driver);
-    ps->setThreadPoolMaxThreadCount(0);
-    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
-
-    sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>());
-    if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
-        LOG(ERROR) << "Could not self register servicemanager";
-    }
-
-    IPCThreadState::self()->setTheContextObject(manager);
-    ps->becomeContextManager(nullptr, nullptr);
-
-    IPCThreadState::self()->joinThreadPool();
-
-    // should not be reached
-    return EXIT_FAILURE;
-}
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
new file mode 100644
index 0000000..ec3fac5
--- /dev/null
+++ b/cmds/servicemanager/service_manager.c
@@ -0,0 +1,442 @@
+/* Copyright 2008 The Android Open Source Project
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cutils/android_filesystem_config.h>
+#include <cutils/multiuser.h>
+
+#include <selinux/android.h>
+#include <selinux/avc.h>
+
+#include "binder.h"
+
+#ifdef VENDORSERVICEMANAGER
+#define LOG_TAG "VendorServiceManager"
+#else
+#define LOG_TAG "ServiceManager"
+#endif
+#include <log/log.h>
+
+struct audit_data {
+    pid_t pid;
+    uid_t uid;
+    const char *name;
+};
+
+const char *str8(const uint16_t *x, size_t x_len)
+{
+    static char buf[128];
+    size_t max = 127;
+    char *p = buf;
+
+    if (x_len < max) {
+        max = x_len;
+    }
+
+    if (x) {
+        while ((max > 0) && (*x != '\0')) {
+            *p++ = *x++;
+            max--;
+        }
+    }
+    *p++ = 0;
+    return buf;
+}
+
+int str16eq(const uint16_t *a, const char *b)
+{
+    while (*a && *b)
+        if (*a++ != *b++) return 0;
+    if (*a || *b)
+        return 0;
+    return 1;
+}
+
+static char *service_manager_context;
+static struct selabel_handle* sehandle;
+
+static bool check_mac_perms(pid_t spid, const char* sid, uid_t uid, const char *tctx, const char *perm, const char *name)
+{
+    char *lookup_sid = NULL;
+    const char *class = "service_manager";
+    bool allowed;
+    struct audit_data ad;
+
+    if (sid == NULL && getpidcon(spid, &lookup_sid) < 0) {
+        ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);
+        return false;
+    }
+
+    ad.pid = spid;
+    ad.uid = uid;
+    ad.name = name;
+
+    if (sid == NULL) {
+        android_errorWriteLog(0x534e4554, "121035042");
+    }
+
+    int result = selinux_check_access(sid ? sid : lookup_sid, tctx, class, perm, (void *) &ad);
+    allowed = (result == 0);
+
+    freecon(lookup_sid);
+    return allowed;
+}
+
+static bool check_mac_perms_from_getcon(pid_t spid, const char* sid, uid_t uid, const char *perm)
+{
+    return check_mac_perms(spid, sid, uid, service_manager_context, perm, NULL);
+}
+
+static bool check_mac_perms_from_lookup(pid_t spid, const char* sid, uid_t uid, const char *perm, const char *name)
+{
+    bool allowed;
+    char *tctx = NULL;
+
+    if (!sehandle) {
+        ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n");
+        abort();
+    }
+
+    if (selabel_lookup(sehandle, &tctx, name, 0) != 0) {
+        ALOGE("SELinux: No match for %s in service_contexts.\n", name);
+        return false;
+    }
+
+    allowed = check_mac_perms(spid, sid, uid, tctx, perm, name);
+    freecon(tctx);
+    return allowed;
+}
+
+static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
+{
+    const char *perm = "add";
+
+    if (multiuser_get_app_id(uid) >= AID_APP) {
+        return 0; /* Don't allow apps to register services */
+    }
+
+    return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
+}
+
+static int svc_can_list(pid_t spid, const char* sid, uid_t uid)
+{
+    const char *perm = "list";
+    return check_mac_perms_from_getcon(spid, sid, uid, perm) ? 1 : 0;
+}
+
+static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
+{
+    const char *perm = "find";
+    return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
+}
+
+struct svcinfo
+{
+    struct svcinfo *next;
+    uint32_t handle;
+    struct binder_death death;
+    int allow_isolated;
+    uint32_t dumpsys_priority;
+    size_t len;
+    uint16_t name[0];
+};
+
+struct svcinfo *svclist = NULL;
+
+struct svcinfo *find_svc(const uint16_t *s16, size_t len)
+{
+    struct svcinfo *si;
+
+    for (si = svclist; si; si = si->next) {
+        if ((len == si->len) &&
+            !memcmp(s16, si->name, len * sizeof(uint16_t))) {
+            return si;
+        }
+    }
+    return NULL;
+}
+
+void svcinfo_death(struct binder_state *bs, void *ptr)
+{
+    struct svcinfo *si = (struct svcinfo* ) ptr;
+
+    ALOGI("service '%s' died\n", str8(si->name, si->len));
+    if (si->handle) {
+        binder_release(bs, si->handle);
+        si->handle = 0;
+    }
+}
+
+uint16_t svcmgr_id[] = {
+    'a','n','d','r','o','i','d','.','o','s','.',
+    'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r'
+};
+
+
+uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid, const char* sid)
+{
+    struct svcinfo *si = find_svc(s, len);
+
+    if (!si || !si->handle) {
+        return 0;
+    }
+
+    if (!si->allow_isolated) {
+        // If this service doesn't allow access from isolated processes,
+        // then check the uid to see if it is isolated.
+        uid_t appid = uid % AID_USER;
+        if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
+            return 0;
+        }
+    }
+
+    if (!svc_can_find(s, len, spid, sid, uid)) {
+        return 0;
+    }
+
+    return si->handle;
+}
+
+int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle,
+                   uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid, const char* sid) {
+    struct svcinfo *si;
+
+    //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
+    //        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
+
+    if (!handle || (len == 0) || (len > 127))
+        return -1;
+
+    if (!svc_can_register(s, len, spid, sid, uid)) {
+        ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
+             str8(s, len), handle, uid);
+        return -1;
+    }
+
+    si = find_svc(s, len);
+    if (si) {
+        if (si->handle) {
+            ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
+                 str8(s, len), handle, uid);
+            svcinfo_death(bs, si);
+        }
+        si->handle = handle;
+    } else {
+        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
+        if (!si) {
+            ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
+                 str8(s, len), handle, uid);
+            return -1;
+        }
+        si->handle = handle;
+        si->len = len;
+        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
+        si->name[len] = '\0';
+        si->death.func = (void*) svcinfo_death;
+        si->death.ptr = si;
+        si->allow_isolated = allow_isolated;
+        si->dumpsys_priority = dumpsys_priority;
+        si->next = svclist;
+        svclist = si;
+    }
+
+    binder_acquire(bs, handle);
+    binder_link_to_death(bs, handle, &si->death);
+    return 0;
+}
+
+int svcmgr_handler(struct binder_state *bs,
+                   struct binder_transaction_data_secctx *txn_secctx,
+                   struct binder_io *msg,
+                   struct binder_io *reply)
+{
+    struct svcinfo *si;
+    uint16_t *s;
+    size_t len;
+    uint32_t handle;
+    uint32_t strict_policy;
+    int allow_isolated;
+    uint32_t dumpsys_priority;
+
+    struct binder_transaction_data *txn = &txn_secctx->transaction_data;
+
+    //ALOGI("target=%p code=%d pid=%d uid=%d\n",
+    //      (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
+
+    if (txn->target.ptr != BINDER_SERVICE_MANAGER)
+        return -1;
+
+    if (txn->code == PING_TRANSACTION)
+        return 0;
+
+    // Equivalent to Parcel::enforceInterface(), reading the RPC
+    // header with the strict mode policy mask and the interface name.
+    // Note that we ignore the strict_policy and don't propagate it
+    // further (since we do no outbound RPCs anyway).
+    strict_policy = bio_get_uint32(msg);
+    bio_get_uint32(msg);  // Ignore worksource header.
+    s = bio_get_string16(msg, &len);
+    if (s == NULL) {
+        return -1;
+    }
+
+    if ((len != (sizeof(svcmgr_id) / 2)) ||
+        memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
+        fprintf(stderr,"invalid id %s\n", str8(s, len));
+        return -1;
+    }
+
+    if (sehandle && selinux_status_updated() > 0) {
+#ifdef VENDORSERVICEMANAGER
+        struct selabel_handle *tmp_sehandle = selinux_android_vendor_service_context_handle();
+#else
+        struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
+#endif
+        if (tmp_sehandle) {
+            selabel_close(sehandle);
+            sehandle = tmp_sehandle;
+        }
+    }
+
+    switch(txn->code) {
+    case SVC_MGR_GET_SERVICE:
+    case SVC_MGR_CHECK_SERVICE:
+        s = bio_get_string16(msg, &len);
+        if (s == NULL) {
+            return -1;
+        }
+        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid,
+                                 (const char*) txn_secctx->secctx);
+        if (!handle)
+            break;
+        bio_put_ref(reply, handle);
+        return 0;
+
+    case SVC_MGR_ADD_SERVICE:
+        s = bio_get_string16(msg, &len);
+        if (s == NULL) {
+            return -1;
+        }
+        handle = bio_get_ref(msg);
+        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
+        dumpsys_priority = bio_get_uint32(msg);
+        if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
+                           txn->sender_pid, (const char*) txn_secctx->secctx))
+            return -1;
+        break;
+
+    case SVC_MGR_LIST_SERVICES: {
+        uint32_t n = bio_get_uint32(msg);
+        uint32_t req_dumpsys_priority = bio_get_uint32(msg);
+
+        if (!svc_can_list(txn->sender_pid, (const char*) txn_secctx->secctx, txn->sender_euid)) {
+            ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
+                    txn->sender_euid);
+            return -1;
+        }
+        si = svclist;
+        // walk through the list of services n times skipping services that
+        // do not support the requested priority
+        while (si) {
+            if (si->dumpsys_priority & req_dumpsys_priority) {
+                if (n == 0) break;
+                n--;
+            }
+            si = si->next;
+        }
+        if (si) {
+            bio_put_string16(reply, si->name);
+            return 0;
+        }
+        return -1;
+    }
+    default:
+        ALOGE("unknown code %d\n", txn->code);
+        return -1;
+    }
+
+    bio_put_uint32(reply, 0);
+    return 0;
+}
+
+
+static int audit_callback(void *data, __unused security_class_t cls, char *buf, size_t len)
+{
+    struct audit_data *ad = (struct audit_data *)data;
+
+    if (!ad || !ad->name) {
+        ALOGE("No service manager audit data");
+        return 0;
+    }
+
+    snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name, ad->pid, ad->uid);
+    return 0;
+}
+
+int main(int argc, char** argv)
+{
+    struct binder_state *bs;
+    union selinux_callback cb;
+    char *driver;
+
+    if (argc > 1) {
+        driver = argv[1];
+    } else {
+        driver = "/dev/binder";
+    }
+
+    bs = binder_open(driver, 128*1024);
+    if (!bs) {
+#ifdef VENDORSERVICEMANAGER
+        ALOGW("failed to open binder driver %s\n", driver);
+        while (true) {
+            sleep(UINT_MAX);
+        }
+#else
+        ALOGE("failed to open binder driver %s\n", driver);
+#endif
+        return -1;
+    }
+
+    if (binder_become_context_manager(bs)) {
+        ALOGE("cannot become context manager (%s)\n", strerror(errno));
+        return -1;
+    }
+
+    cb.func_audit = audit_callback;
+    selinux_set_callback(SELINUX_CB_AUDIT, cb);
+#ifdef VENDORSERVICEMANAGER
+    cb.func_log = selinux_vendor_log_callback;
+#else
+    cb.func_log = selinux_log_callback;
+#endif
+    selinux_set_callback(SELINUX_CB_LOG, cb);
+
+#ifdef VENDORSERVICEMANAGER
+    sehandle = selinux_android_vendor_service_context_handle();
+#else
+    sehandle = selinux_android_service_context_handle();
+#endif
+    selinux_status_open(true);
+
+    if (sehandle == NULL) {
+        ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
+        abort();
+    }
+
+    if (getcon(&service_manager_context) != 0) {
+        ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
+        abort();
+    }
+
+
+    binder_loop(bs, svcmgr_handler);
+
+    return 0;
+}
diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp
deleted file mode 100644
index 25245be..0000000
--- a/cmds/servicemanager/test_sm.cpp
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/os/BnServiceCallback.h>
-#include <binder/Binder.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <cutils/android_filesystem_config.h>
-#include <gtest/gtest.h>
-#include <gmock/gmock.h>
-
-#include "Access.h"
-#include "ServiceManager.h"
-
-using android::sp;
-using android::Access;
-using android::BBinder;
-using android::IBinder;
-using android::ServiceManager;
-using android::binder::Status;
-using android::os::BnServiceCallback;
-using android::os::IServiceManager;
-using testing::_;
-using testing::ElementsAre;
-using testing::NiceMock;
-using testing::Return;
-
-static sp<IBinder> getBinder() {
-    class LinkableBinder : public BBinder {
-        android::status_t linkToDeath(const sp<DeathRecipient>&, void*, uint32_t) override {
-            // let SM linkToDeath
-            return android::OK;
-        }
-    };
-
-    return new LinkableBinder;
-}
-
-class MockAccess : public Access {
-public:
-    MOCK_METHOD0(getCallingContext, CallingContext());
-    MOCK_METHOD2(canAdd, bool(const CallingContext&, const std::string& name));
-    MOCK_METHOD2(canFind, bool(const CallingContext&, const std::string& name));
-    MOCK_METHOD1(canList, bool(const CallingContext&));
-};
-
-class MockServiceManager : public ServiceManager {
- public:
-    MockServiceManager(std::unique_ptr<Access>&& access) : ServiceManager(std::move(access)) {}
-    MOCK_METHOD1(tryStartService, void(const std::string& name));
-};
-
-static sp<ServiceManager> getPermissiveServiceManager() {
-    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-
-    ON_CALL(*access, getCallingContext()).WillByDefault(Return(Access::CallingContext{}));
-    ON_CALL(*access, canAdd(_, _)).WillByDefault(Return(true));
-    ON_CALL(*access, canFind(_, _)).WillByDefault(Return(true));
-    ON_CALL(*access, canList(_)).WillByDefault(Return(true));
-
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
-    return sm;
-}
-
-TEST(AddService, HappyHappy) {
-    auto sm = getPermissiveServiceManager();
-    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-}
-
-TEST(AddService, EmptyNameDisallowed) {
-    auto sm = getPermissiveServiceManager();
-    EXPECT_FALSE(sm->addService("", getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-}
-
-TEST(AddService, JustShortEnoughServiceNameHappy) {
-    auto sm = getPermissiveServiceManager();
-    EXPECT_TRUE(sm->addService(std::string(127, 'a'), getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-}
-
-TEST(AddService, TooLongNameDisallowed) {
-    auto sm = getPermissiveServiceManager();
-    EXPECT_FALSE(sm->addService(std::string(128, 'a'), getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-}
-
-TEST(AddService, WeirdCharactersDisallowed) {
-    auto sm = getPermissiveServiceManager();
-    EXPECT_FALSE(sm->addService("happy$foo$foo", getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-}
-
-TEST(AddService, AddNullServiceDisallowed) {
-    auto sm = getPermissiveServiceManager();
-    EXPECT_FALSE(sm->addService("foo", nullptr, false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-}
-
-TEST(AddService, AddDisallowedFromApp) {
-    for (uid_t uid : { AID_APP_START, AID_APP_START + 1, AID_APP_END }) {
-        std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-        EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{
-            .debugPid = 1337,
-            .uid = uid,
-        }));
-        EXPECT_CALL(*access, canAdd(_, _)).Times(0);
-        sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
-
-        EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
-            IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-    }
-
-}
-
-TEST(AddService, HappyOverExistingService) {
-    auto sm = getPermissiveServiceManager();
-    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-}
-
-TEST(AddService, NoPermissions) {
-    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-
-    EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
-    EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(false));
-
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
-
-    EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-}
-
-TEST(GetService, HappyHappy) {
-    auto sm = getPermissiveServiceManager();
-    sp<IBinder> service = getBinder();
-
-    EXPECT_TRUE(sm->addService("foo", service, false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-
-    sp<IBinder> out;
-    EXPECT_TRUE(sm->getService("foo", &out).isOk());
-    EXPECT_EQ(service, out);
-}
-
-TEST(GetService, NonExistant) {
-    auto sm = getPermissiveServiceManager();
-
-    sp<IBinder> out;
-    EXPECT_TRUE(sm->getService("foo", &out).isOk());
-    EXPECT_EQ(nullptr, out.get());
-}
-
-TEST(GetService, NoPermissionsForGettingService) {
-    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-
-    EXPECT_CALL(*access, getCallingContext()).WillRepeatedly(Return(Access::CallingContext{}));
-    EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true));
-    EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(false));
-
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
-
-    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-
-    sp<IBinder> out;
-    // returns nullptr but has OK status for legacy compatibility
-    EXPECT_TRUE(sm->getService("foo", &out).isOk());
-    EXPECT_EQ(nullptr, out.get());
-}
-
-TEST(GetService, AllowedFromIsolated) {
-    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-
-    EXPECT_CALL(*access, getCallingContext())
-        // something adds it
-        .WillOnce(Return(Access::CallingContext{}))
-        // next call is from isolated app
-        .WillOnce(Return(Access::CallingContext{
-            .uid = AID_ISOLATED_START,
-        }));
-    EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true));
-    EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(true));
-
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
-
-    sp<IBinder> service = getBinder();
-    EXPECT_TRUE(sm->addService("foo", service, true /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-
-    sp<IBinder> out;
-    EXPECT_TRUE(sm->getService("foo", &out).isOk());
-    EXPECT_EQ(service, out.get());
-}
-
-TEST(GetService, NotAllowedFromIsolated) {
-    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-
-    EXPECT_CALL(*access, getCallingContext())
-        // something adds it
-        .WillOnce(Return(Access::CallingContext{}))
-        // next call is from isolated app
-        .WillOnce(Return(Access::CallingContext{
-            .uid = AID_ISOLATED_START,
-        }));
-    EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true));
-
-    // TODO(b/136023468): when security check is first, this should be called first
-    // EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(true));
-
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
-
-    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-
-    sp<IBinder> out;
-    // returns nullptr but has OK status for legacy compatibility
-    EXPECT_TRUE(sm->getService("foo", &out).isOk());
-    EXPECT_EQ(nullptr, out.get());
-}
-
-TEST(ListServices, NoPermissions) {
-    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-
-    EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
-    EXPECT_CALL(*access, canList(_)).WillOnce(Return(false));
-
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
-
-    std::vector<std::string> out;
-    EXPECT_FALSE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk());
-    EXPECT_TRUE(out.empty());
-}
-
-TEST(ListServices, AllServices) {
-    auto sm = getPermissiveServiceManager();
-
-    EXPECT_TRUE(sm->addService("sd", getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-    EXPECT_TRUE(sm->addService("sc", getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_NORMAL).isOk());
-    EXPECT_TRUE(sm->addService("sb", getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_HIGH).isOk());
-    EXPECT_TRUE(sm->addService("sa", getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL).isOk());
-
-    std::vector<std::string> out;
-    EXPECT_TRUE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk());
-
-    // all there and in the right order
-    EXPECT_THAT(out, ElementsAre("sa", "sb", "sc", "sd"));
-}
-
-TEST(ListServices, CriticalServices) {
-    auto sm = getPermissiveServiceManager();
-
-    EXPECT_TRUE(sm->addService("sd", getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-    EXPECT_TRUE(sm->addService("sc", getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_NORMAL).isOk());
-    EXPECT_TRUE(sm->addService("sb", getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_HIGH).isOk());
-    EXPECT_TRUE(sm->addService("sa", getBinder(), false /*allowIsolated*/,
-        IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL).isOk());
-
-    std::vector<std::string> out;
-    EXPECT_TRUE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL, &out).isOk());
-
-    // all there and in the right order
-    EXPECT_THAT(out, ElementsAre("sa"));
-}
-
-class CallbackHistorian : public BnServiceCallback {
-    Status onRegistration(const std::string& name, const sp<IBinder>& binder) override {
-        registrations.push_back(name);
-        binders.push_back(binder);
-        return Status::ok();
-    }
-
-    android::status_t linkToDeath(const sp<DeathRecipient>&, void*, uint32_t) override {
-        // let SM linkToDeath
-        return android::OK;
-    }
-
-public:
-    std::vector<std::string> registrations;
-    std::vector<sp<IBinder>> binders;
-};
-
-TEST(ServiceNotifications, NoPermissionsRegister) {
-    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-
-    EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
-    EXPECT_CALL(*access, canFind(_,_)).WillOnce(Return(false));
-
-    sp<ServiceManager> sm = new ServiceManager(std::move(access));
-
-    sp<CallbackHistorian> cb = new CallbackHistorian;
-
-    EXPECT_EQ(sm->registerForNotifications("foofoo", cb).exceptionCode(),
-        Status::EX_SECURITY);
-}
-
-TEST(ServiceNotifications, NoPermissionsUnregister) {
-    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-
-    EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
-    EXPECT_CALL(*access, canFind(_,_)).WillOnce(Return(false));
-
-    sp<ServiceManager> sm = new ServiceManager(std::move(access));
-
-    sp<CallbackHistorian> cb = new CallbackHistorian;
-
-    // should always hit security error first
-    EXPECT_EQ(sm->unregisterForNotifications("foofoo", cb).exceptionCode(),
-        Status::EX_SECURITY);
-}
-
-TEST(ServiceNotifications, InvalidName) {
-    auto sm = getPermissiveServiceManager();
-
-    sp<CallbackHistorian> cb = new CallbackHistorian;
-
-    EXPECT_EQ(sm->registerForNotifications("foo@foo", cb).exceptionCode(),
-        Status::EX_ILLEGAL_ARGUMENT);
-}
-
-TEST(ServiceNotifications, NullCallback) {
-    auto sm = getPermissiveServiceManager();
-
-    EXPECT_EQ(sm->registerForNotifications("foofoo", nullptr).exceptionCode(),
-        Status::EX_NULL_POINTER);
-}
-
-TEST(ServiceNotifications, Unregister) {
-    auto sm = getPermissiveServiceManager();
-
-    sp<CallbackHistorian> cb = new CallbackHistorian;
-
-    EXPECT_TRUE(sm->registerForNotifications("foofoo", cb).isOk());
-    EXPECT_EQ(sm->unregisterForNotifications("foofoo", cb).exceptionCode(), 0);
-}
-
-TEST(ServiceNotifications, UnregisterWhenNoRegistrationExists) {
-    auto sm = getPermissiveServiceManager();
-
-    sp<CallbackHistorian> cb = new CallbackHistorian;
-
-    EXPECT_EQ(sm->unregisterForNotifications("foofoo", cb).exceptionCode(),
-        Status::EX_ILLEGAL_STATE);
-}
-
-TEST(ServiceNotifications, NoNotification) {
-    auto sm = getPermissiveServiceManager();
-
-    sp<CallbackHistorian> cb = new CallbackHistorian;
-
-    EXPECT_TRUE(sm->registerForNotifications("foofoo", cb).isOk());
-    EXPECT_TRUE(sm->addService("otherservice", getBinder(),
-        false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-
-    EXPECT_THAT(cb->registrations, ElementsAre());
-    EXPECT_THAT(cb->binders, ElementsAre());
-}
-
-TEST(ServiceNotifications, GetNotification) {
-    auto sm = getPermissiveServiceManager();
-
-    sp<CallbackHistorian> cb = new CallbackHistorian;
-
-    sp<IBinder> service = getBinder();
-
-    EXPECT_TRUE(sm->registerForNotifications("asdfasdf", cb).isOk());
-    EXPECT_TRUE(sm->addService("asdfasdf", service,
-        false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-
-    EXPECT_THAT(cb->registrations, ElementsAre("asdfasdf"));
-    EXPECT_THAT(cb->binders, ElementsAre(service));
-}
-
-TEST(ServiceNotifications, GetNotificationForAlreadyRegisteredService) {
-    auto sm = getPermissiveServiceManager();
-
-    sp<CallbackHistorian> cb = new CallbackHistorian;
-
-    sp<IBinder> service = getBinder();
-
-    EXPECT_TRUE(sm->addService("asdfasdf", service,
-        false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-
-    EXPECT_TRUE(sm->registerForNotifications("asdfasdf", cb).isOk());
-
-    EXPECT_THAT(cb->registrations, ElementsAre("asdfasdf"));
-    EXPECT_THAT(cb->binders, ElementsAre(service));
-}
-
-TEST(ServiceNotifications, GetMultipleNotification) {
-    auto sm = getPermissiveServiceManager();
-
-    sp<CallbackHistorian> cb = new CallbackHistorian;
-
-    sp<IBinder> binder1 = getBinder();
-    sp<IBinder> binder2 = getBinder();
-
-    EXPECT_TRUE(sm->registerForNotifications("asdfasdf", cb).isOk());
-    EXPECT_TRUE(sm->addService("asdfasdf", binder1,
-        false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-    EXPECT_TRUE(sm->addService("asdfasdf", binder2,
-        false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-
-    EXPECT_THAT(cb->registrations, ElementsAre("asdfasdf", "asdfasdf"));
-    EXPECT_THAT(cb->registrations, ElementsAre("asdfasdf", "asdfasdf"));
-}
diff --git a/data/etc/android.hardware.se.omapi.ese.xml b/data/etc/android.hardware.se.omapi.ese.xml
deleted file mode 100644
index 3b1d81c..0000000
--- a/data/etc/android.hardware.se.omapi.ese.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<!-- This feature indicates that the device supports The device supports
-     Open Mobile API capable ESE-based secure elements-->
-<permissions>
-    <feature name="android.hardware.se.omapi.ese" />
-</permissions>
diff --git a/data/etc/android.hardware.se.omapi.sd.xml b/data/etc/android.hardware.se.omapi.sd.xml
deleted file mode 100644
index 8fc2869..0000000
--- a/data/etc/android.hardware.se.omapi.sd.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<!-- This feature indicates that the device supports The device supports
-     Open Mobile API capable SD-based secure elements-->
-<permissions>
-    <feature name="android.hardware.se.omapi.sd" />
-</permissions>
diff --git a/data/etc/android.hardware.se.omapi.uicc.xml b/data/etc/android.hardware.se.omapi.uicc.xml
deleted file mode 100644
index 9c6f143..0000000
--- a/data/etc/android.hardware.se.omapi.uicc.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<!-- This feature indicates that the device supports The device supports
-     Open Mobile API capable UICC-based secure elements-->
-<permissions>
-    <feature name="android.hardware.se.omapi.uicc" />
-</permissions>
diff --git a/headers/media_plugin/media/cas/CasAPI.h b/headers/media_plugin/media/cas/CasAPI.h
index 8cc9d36..c87ee56 100644
--- a/headers/media_plugin/media/cas/CasAPI.h
+++ b/headers/media_plugin/media/cas/CasAPI.h
@@ -56,11 +56,6 @@
         size_t size,
         const CasSessionId *sessionId);
 
-typedef void (*CasPluginStatusCallback)(
-        void *appData,
-        int32_t event,
-        int32_t arg);
-
 struct CasFactory {
     CasFactory() {}
     virtual ~CasFactory() {}
@@ -96,10 +91,6 @@
     CasPlugin() {}
     virtual ~CasPlugin() {}
 
-    // Provide a callback to report plugin status
-    virtual status_t setStatusCallback(
-            CasPluginStatusCallback callback) = 0;
-
     // Provide the CA private data from a CA_descriptor in the conditional
     // access table to a CasPlugin.
     virtual status_t setPrivateData(
@@ -109,11 +100,6 @@
     // streams.
     virtual status_t openSession(CasSessionId *sessionId) = 0;
 
-    // Open a session with intend and mode for descrambling a program, or one
-    // or more elementary streams.
-    virtual status_t openSession(uint32_t intent, uint32_t mode,
-                                     CasSessionId *sessionId) = 0;
-
     // Close a previously opened session.
     virtual status_t closeSession(const CasSessionId &sessionId) = 0;
 
diff --git a/headers/media_plugin/media/openmax/OMX_Video.h b/headers/media_plugin/media/openmax/OMX_Video.h
index 81ee5fb..b6edaa9 100644
--- a/headers/media_plugin/media/openmax/OMX_Video.h
+++ b/headers/media_plugin/media/openmax/OMX_Video.h
@@ -90,7 +90,6 @@
     OMX_VIDEO_CodingHEVC,       /**< ITU H.265/HEVC */
     OMX_VIDEO_CodingDolbyVision,/**< Dolby Vision */
     OMX_VIDEO_CodingImageHEIC,  /**< HEIF image encoded with HEVC */
-    OMX_VIDEO_CodingAV1,        /**< AV1 */
     OMX_VIDEO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_VIDEO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_VIDEO_CodingMax = 0x7FFFFFFF
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index 346861f..44883cc 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -59,8 +59,6 @@
 /**
  * Get the AChoreographer instance for the current thread. This must be called
  * on an ALooper thread.
- *
- * Available since API level 24.
  */
 AChoreographer* AChoreographer_getInstance() __INTRODUCED_IN(24);
 
@@ -84,8 +82,6 @@
 /**
  * Power a callback to be run on the next frame.  The data pointer provided will
  * be passed to the callback function when it's called.
- *
- * Available since API level 29.
  */
 void AChoreographer_postFrameCallback64(AChoreographer* chroreographer,
                 AChoreographer_frameCallback64 callback, void* data) __INTRODUCED_IN(29);
@@ -94,8 +90,6 @@
  * Post a callback to be run on the frame following the specified delay.  The
  * data pointer provided will be passed to the callback function when it's
  * called.
- *
- * Available since API level 29.
  */
 void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer,
                 AChoreographer_frameCallback64 callback, void* data, uint32_t delayMillis) __INTRODUCED_IN(29);
diff --git a/include/android/configuration.h b/include/android/configuration.h
index 3310722..ef6c5a2 100644
--- a/include/android/configuration.h
+++ b/include/android/configuration.h
@@ -675,52 +675,50 @@
  */
 void AConfiguration_setUiModeNight(AConfiguration* config, int32_t uiModeNight);
 
+#if __ANDROID_API__ >= 13
 /**
  * Return the current configuration screen width in dp units, or
  * ACONFIGURATION_SCREEN_WIDTH_DP_ANY if not set.
  */
-int32_t AConfiguration_getScreenWidthDp(AConfiguration* config);
+int32_t AConfiguration_getScreenWidthDp(AConfiguration* config) __INTRODUCED_IN(13);
 
 /**
  * Set the configuration's current screen width in dp units.
  */
-void AConfiguration_setScreenWidthDp(AConfiguration* config, int32_t value);
+void AConfiguration_setScreenWidthDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
 
 /**
  * Return the current configuration screen height in dp units, or
  * ACONFIGURATION_SCREEN_HEIGHT_DP_ANY if not set.
  */
-int32_t AConfiguration_getScreenHeightDp(AConfiguration* config);
+int32_t AConfiguration_getScreenHeightDp(AConfiguration* config) __INTRODUCED_IN(13);
 
 /**
  * Set the configuration's current screen width in dp units.
  */
-void AConfiguration_setScreenHeightDp(AConfiguration* config, int32_t value);
+void AConfiguration_setScreenHeightDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
 
 /**
  * Return the configuration's smallest screen width in dp units, or
  * ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY if not set.
  */
-int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config);
+int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config) __INTRODUCED_IN(13);
 
 /**
  * Set the configuration's smallest screen width in dp units.
  */
-void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value);
+void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
+#endif /* __ANDROID_API__ >= 13 */
 
 #if __ANDROID_API__ >= 17
 /**
  * Return the configuration's layout direction, or
  * ACONFIGURATION_LAYOUTDIR_ANY if not set.
- *
- * Available since API level 17.
  */
 int32_t AConfiguration_getLayoutDirection(AConfiguration* config) __INTRODUCED_IN(17);
 
 /**
  * Set the configuration's layout direction.
- *
- * Available since API level 17.
  */
 void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value) __INTRODUCED_IN(17);
 #endif /* __ANDROID_API__ >= 17 */
diff --git a/include/android/font.h b/include/android/font.h
index 1618096..435a573 100644
--- a/include/android/font.h
+++ b/include/android/font.h
@@ -16,7 +16,7 @@
 
 /**
  * @addtogroup Font
- * @{
+ * {
  */
 
 /**
@@ -96,8 +96,6 @@
 /**
  * Close an AFont.
  *
- * Available since API level 29.
- *
  * \param font a font returned by ASystemFontIterator_next or AFontMatchert_match.
  *        Do nothing if NULL is passed.
  */
@@ -118,8 +116,6 @@
  * The font file returned is guaranteed to be opend with O_RDONLY.
  * Note that the returned pointer is valid until AFont_close() is called for the given font.
  *
- * Available since API level 29.
- *
  * \param font a font object. Passing NULL is not allowed.
  * \return a string of the font file path.
  */
@@ -188,8 +184,6 @@
  *
  * For more information about font weight, read [OpenType usWeightClass](https://docs.microsoft.com/en-us/typography/opentype/spec/os2#usweightclass)
  *
- * Available since API level 29.
- *
  * \param font a font object. Passing NULL is not allowed.
  * \return a positive integer less than or equal to {@link ASYSTEM_FONT_MAX_WEIGHT} is returned.
  */
@@ -198,8 +192,6 @@
 /**
  * Return true if the current font is italic, otherwise returns false.
  *
- * Available since API level 29.
- *
  * \param font a font object. Passing NULL is not allowed.
  * \return true if italic, otherwise false.
  */
@@ -212,8 +204,6 @@
  *
  * Note that the returned pointer is valid until AFont_close() is called.
  *
- * Available since API level 29.
- *
  * \param font a font object. Passing NULL is not allowed.
  * \return a IETF BCP47 compliant language tag or nullptr if not available.
  */
@@ -226,8 +216,6 @@
  * returns a non-negative value as an font offset in the collection. This
  * always returns 0 if the target font file is a regular font.
  *
- * Available since API level 29.
- *
  * \param font a font object. Passing NULL is not allowed.
  * \return a font collection index.
  */
@@ -259,8 +247,6 @@
  *
  * For more information about font variation settings, read [Font Variations Table](https://docs.microsoft.com/en-us/typography/opentype/spec/fvar)
  *
- * Available since API level 29.
- *
  * \param font a font object. Passing NULL is not allowed.
  * \return a number of font variation settings.
  */
@@ -272,8 +258,6 @@
  *
  * See AFont_getAxisCount for more details.
  *
- * Available since API level 29.
- *
  * \param font a font object. Passing NULL is not allowed.
  * \param axisIndex an index to the font variation settings. Passing value larger than or
  *        equal to {@link AFont_getAxisCount} is not allowed.
@@ -287,8 +271,6 @@
  *
  * See AFont_getAxisCount for more details.
  *
- * Available since API level 29.
- *
  * \param font a font object. Passing NULL is not allowed.
  * \param axisIndex an index to the font variation settings. Passing value larger than or
  *         equal to {@link ASYstemFont_getAxisCount} is not allwed.
diff --git a/include/android/font_matcher.h b/include/android/font_matcher.h
index d4bd892..e286a4c 100644
--- a/include/android/font_matcher.h
+++ b/include/android/font_matcher.h
@@ -16,7 +16,7 @@
 
 /**
  * @addtogroup Font
- * @{
+ * {
  */
 
 /**
@@ -130,17 +130,13 @@
  */
 
 /**
- * Creates a new AFontMatcher object.
- *
- * Available since API level 29.
+ * Creates a new AFontMatcher object
  */
 AFontMatcher* _Nonnull AFontMatcher_create() __INTRODUCED_IN(29);
 
 /**
  * Destroy the matcher object.
  *
- * Available since API level 29.
- *
  * \param matcher a matcher object. Passing NULL is not allowed.
  */
 void AFontMatcher_destroy(AFontMatcher* _Nonnull matcher) __INTRODUCED_IN(29);
@@ -151,8 +147,6 @@
  * If this function is not called, the matcher performs with {@link ASYSTEM_FONT_WEIGHT_NORMAL}
  * with non-italic style.
  *
- * Available since API level 29.
- *
  * \param matcher a matcher object. Passing NULL is not allowed.
  * \param weight a font weight value. Only from 0 to 1000 value is valid
  * \param italic true if italic, otherwise false.
@@ -167,8 +161,6 @@
  *
  * If this function is not called, the matcher performs with empty locale list.
  *
- * Available since API level 29.
- *
  * \param matcher a matcher object. Passing NULL is not allowed.
  * \param languageTags a null character terminated comma separated IETF BCP47 compliant language
  *                     tags.
@@ -182,8 +174,6 @@
  *
  * If this function is not called, the matcher performs with {@link AFAMILY_VARIANT_DEFAULT}.
  *
- * Available since API level 29.
- *
  * \param matcher a matcher object. Passing NULL is not allowed.
  * \param familyVariant Must be one of {@link AFAMILY_VARIANT_DEFAULT},
  *                      {@link AFAMILY_VARIANT_COMPACT} or {@link AFAMILY_VARIANT_ELEGANT} is valid.
@@ -200,8 +190,6 @@
  * Even if no font can render the given text, this function will return a non-null result for
  * drawing Tofu character.
  *
- * Available since API level 29.
- *
  * \param matcher a matcher object. Passing NULL is not allowed.
  * \param familyName a null character terminated font family name
  * \param text a UTF-16 encoded text buffer to be rendered. Do not pass empty string.
diff --git a/include/android/hardware_buffer_jni.h b/include/android/hardware_buffer_jni.h
index 293e5ac..aedf369 100644
--- a/include/android/hardware_buffer_jni.h
+++ b/include/android/hardware_buffer_jni.h
@@ -42,8 +42,6 @@
  * that is returned. To keep the AHardwareBuffer live after the Java
  * HardwareBuffer object got garbage collected, be sure to use AHardwareBuffer_acquire()
  * to acquire an additional reference.
- *
- * Available since API level 26.
  */
 AHardwareBuffer* AHardwareBuffer_fromHardwareBuffer(JNIEnv* env,
         jobject hardwareBufferObj) __INTRODUCED_IN(26);
@@ -51,8 +49,6 @@
 /**
  * Return a new Java HardwareBuffer object that wraps the passed native
  * AHardwareBuffer object.
- *
- * Available since API level 26.
  */
 jobject AHardwareBuffer_toHardwareBuffer(JNIEnv* env,
         AHardwareBuffer* hardwareBuffer) __INTRODUCED_IN(26);
diff --git a/include/android/input.h b/include/android/input.h
index ce439c6..cfade6c 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -986,8 +986,10 @@
  */
 int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event);
 
+#if __ANDROID_API__ >= 14
 /** Get the button state of all buttons that are pressed. */
-int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event);
+int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event) __INTRODUCED_IN(14);
+#endif
 
 /**
  * Get a bitfield indicating which edges, if any, were touched by this motion event.
@@ -1052,12 +1054,14 @@
  */
 int32_t AMotionEvent_getPointerId(const AInputEvent* motion_event, size_t pointer_index);
 
+#if __ANDROID_API__ >= 14
 /**
  * Get the tool type of a pointer for the given pointer index.
  * The tool type indicates the type of tool used to make contact such as a
  * finger or stylus, if known.
  */
-int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index);
+int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index) __INTRODUCED_IN(14);
+#endif
 
 /**
  * Get the original raw X coordinate of this event.
@@ -1147,9 +1151,11 @@
  */
 float AMotionEvent_getOrientation(const AInputEvent* motion_event, size_t pointer_index);
 
+#if __ANDROID_API__ >= 13
 /** Get the value of the request axis for the given pointer index. */
 float AMotionEvent_getAxisValue(const AInputEvent* motion_event,
-        int32_t axis, size_t pointer_index);
+        int32_t axis, size_t pointer_index) __INTRODUCED_IN(13);
+#endif
 
 /**
  * Get the number of historical points in this event.  These are movements that
@@ -1280,12 +1286,14 @@
 float AMotionEvent_getHistoricalOrientation(const AInputEvent* motion_event, size_t pointer_index,
         size_t history_index);
 
+#if __ANDROID_API__ >= 13
 /**
  * Get the historical value of the request axis for the given pointer index
  * that occurred between this event and the previous motion event.
  */
 float AMotionEvent_getHistoricalAxisValue(const AInputEvent* motion_event,
-        int32_t axis, size_t pointer_index, size_t history_index);
+        int32_t axis, size_t pointer_index, size_t history_index) __INTRODUCED_IN(13);
+#endif
 
 
 struct AInputQueue;
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index 59b1deb..d31d1f1 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -69,7 +69,6 @@
  *
  * This is the equivalent of: [android.net.Network#bindSocket()](https://developer.android.com/reference/android/net/Network.html#bindSocket(java.net.Socket))
  *
- * Available since API level 23.
  */
 int android_setsocknetwork(net_handle_t network, int fd) __INTRODUCED_IN(23);
 
@@ -87,7 +86,6 @@
  *
  * This is the equivalent of: [android.net.ConnectivityManager#setProcessDefaultNetwork()](https://developer.android.com/reference/android/net/ConnectivityManager.html#setProcessDefaultNetwork(android.net.Network))
  *
- * Available since API level 23.
  */
 int android_setprocnetwork(net_handle_t network) __INTRODUCED_IN(23);
 
@@ -105,7 +103,6 @@
  *
  * This is the equivalent of: [android.net.Network#getAllByName()](https://developer.android.com/reference/android/net/Network.html#getAllByName(java.lang.String))
  *
- * Available since API level 23.
  */
 int android_getaddrinfofornetwork(net_handle_t network,
         const char *node, const char *service,
@@ -147,8 +144,6 @@
  *
  * Returns a file descriptor to watch for read events, or a negative
  * POSIX error code (see errno.h) if an immediate error occurs.
- *
- * Available since API level 29.
  */
 int android_res_nquery(net_handle_t network,
         const char *dname, int ns_class, int ns_type, uint32_t flags) __INTRODUCED_IN(29);
@@ -160,8 +155,6 @@
  *
  * Returns a file descriptor to watch for read events, or a negative
  * POSIX error code (see errno.h) if an immediate error occurs.
- *
- * Available since API level 29.
  */
 int android_res_nsend(net_handle_t network,
         const uint8_t *msg, size_t msglen, uint32_t flags) __INTRODUCED_IN(29);
@@ -170,8 +163,6 @@
  * Read a result for the query associated with the |fd| descriptor.
  * Closes |fd| before returning.
  *
- * Available since 29.
- *
  * Returns:
  *     < 0: negative POSIX error code (see errno.h for possible values). |rcode| is not set.
  *     >= 0: length of |answer|. |rcode| is the resolver return code (e.g., ns_r_nxdomain)
@@ -182,8 +173,6 @@
 /**
  * Attempts to cancel the in-progress query associated with the |nsend_fd|
  * descriptor.
- *
- * Available since API level 29.
  */
 void android_res_cancel(int nsend_fd) __INTRODUCED_IN(29);
 
diff --git a/include/android/native_window_jni.h b/include/android/native_window_jni.h
index 3a77ffe..0c196b9 100644
--- a/include/android/native_window_jni.h
+++ b/include/android/native_window_jni.h
@@ -51,8 +51,6 @@
  * the ANativeWindow; maintains it through general Java object's life cycle;
  * and will automatically release the reference when the Java object gets garbage
  * collected.
- *
- * Available since API level 26.
  */
 jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window) __INTRODUCED_IN(26);
 #endif
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 3ebe79f..e9d5c16 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -564,7 +564,6 @@
  *
  *     ASensorManager* sensorManager = ASensorManager_getInstanceForPackage("foo.bar.baz");
  *
- * Available since API level 26.
  */
 ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName) __INTRODUCED_IN(26);
 #endif
@@ -584,8 +583,6 @@
 /**
  * Returns the default sensor with the given type and wakeUp properties or NULL if no sensor
  * of this type and wakeUp properties exists.
- *
- * Available since API level 21.
  */
 ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type, bool wakeUp) __INTRODUCED_IN(21);
 #endif
@@ -612,8 +609,6 @@
  * Create a direct channel of {@link ASENSOR_DIRECT_CHANNEL_TYPE_SHARED_MEMORY} to be used
  * for configuring sensor direct report.
  *
- * Available since API level 26.
- *
  * \param manager the {@link ASensorManager} instance obtained from
  *                {@link ASensorManager_getInstanceForPackage}.
  * \param fd      file descriptor representing a shared memory created by
@@ -632,8 +627,6 @@
  * Create a direct channel of {@link ASENSOR_DIRECT_CHANNEL_TYPE_HARDWARE_BUFFER} type to be used
  * for configuring sensor direct report.
  *
- * Available since API level 26.
- *
  * \param manager the {@link ASensorManager} instance obtained from
  *                {@link ASensorManager_getInstanceForPackage}.
  * \param buffer  {@link AHardwareBuffer} instance created by {@link AHardwareBuffer_allocate}.
@@ -653,8 +646,6 @@
  * The buffer used for creating direct channel does not get destroyed with
  * {@link ASensorManager_destroy} and has to be close or released separately.
  *
- * Available since API level 26.
- *
  * \param manager the {@link ASensorManager} instance obtained from
  *                {@link ASensorManager_getInstanceForPackage}.
  * \param channelId channel id (a positive integer) returned from
@@ -687,8 +678,6 @@
  *
  *     ASensorManager_configureDirectReport(manager, sensor, channel_id, ASENSOR_DIRECT_RATE_FAST);
  *
- * Available since API level 26.
- *
  * \param manager   the {@link ASensorManager} instance obtained from
  *                  {@link ASensorManager_getInstanceForPackage}.
  * \param sensor    a {@link ASensor} to denote which sensor to be operate. It can be NULL if rate
@@ -791,7 +780,7 @@
  */
 ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, ASensorEvent* events, size_t count);
 
-#if __ANDROID_API__ >= 29
+#if __ANDROID_API__ >= __ANDROID_API_Q__
 /**
  * Request that {@link ASENSOR_TYPE_ADDITIONAL_INFO} events to be delivered on
  * the given {@link ASensorEventQueue}.
@@ -807,15 +796,13 @@
  * {@link AAdditionalInfoEvent#type}, as new values may be defined in the future
  * and may delivered to the client.
  *
- * Available since API level 29.
- *
  * \param queue {@link ASensorEventQueue} to configure
  * \param enable true to request {@link ASENSOR_TYPE_ADDITIONAL_INFO} events,
  *        false to stop receiving events
  * \return 0 on success or a negative error code on failure
  */
-int ASensorEventQueue_requestAdditionalInfoEvents(ASensorEventQueue* queue, bool enable) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
+int ASensorEventQueue_requestAdditionalInfoEvents(ASensorEventQueue* queue, bool enable);
+#endif /* __ANDROID_API__ >= __ANDRDOID_API_Q__ */
 
 /*****************************************************************************/
 
@@ -850,36 +837,26 @@
 /**
  * Returns the maximum size of batches for this sensor. Batches will often be
  * smaller, as the hardware fifo might be used for other sensors.
- *
- * Available since API level 21.
  */
 int ASensor_getFifoMaxEventCount(ASensor const* sensor) __INTRODUCED_IN(21);
 
 /**
  * Returns the hardware batch fifo size reserved to this sensor.
- *
- * Available since API level 21.
  */
 int ASensor_getFifoReservedEventCount(ASensor const* sensor) __INTRODUCED_IN(21);
 
 /**
  * Returns this sensor's string type.
- *
- * Available since API level 21.
  */
 const char* ASensor_getStringType(ASensor const* sensor) __INTRODUCED_IN(21);
 
 /**
  * Returns the reporting mode for this sensor. One of AREPORTING_MODE_* constants.
- *
- * Available since API level 21.
  */
 int ASensor_getReportingMode(ASensor const* sensor) __INTRODUCED_IN(21);
 
 /**
  * Returns true if this is a wake up sensor, false otherwise.
- *
- * Available since API level 21.
  */
 bool ASensor_isWakeUpSensor(ASensor const* sensor) __INTRODUCED_IN(21);
 #endif /* __ANDROID_API__ >= 21 */
@@ -888,8 +865,6 @@
 /**
  * Test if sensor supports a certain type of direct channel.
  *
- * Available since API level 26.
- *
  * \param sensor  a {@link ASensor} to denote the sensor to be checked.
  * \param channelType  Channel type constant, either
  *                     {@ASENSOR_DIRECT_CHANNEL_TYPE_SHARED_MEMORY}
@@ -899,9 +874,7 @@
 bool ASensor_isDirectChannelTypeSupported(ASensor const* sensor, int channelType) __INTRODUCED_IN(26);
 
 /**
- * Get the highest direct rate level that a sensor supports.
- *
- * Available since API level 26.
+ * Get the highest direct rate level that a sensor support.
  *
  * \param sensor  a {@link ASensor} to denote the sensor to be checked.
  *
@@ -912,7 +885,7 @@
 int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor) __INTRODUCED_IN(26);
 #endif /* __ANDROID_API__ >= 26 */
 
-#if __ANDROID_API__ >= 29
+#if __ANDROID_API__ >= __ANDROID_API_Q__
 /**
  * Returns the sensor's handle.
  *
@@ -926,11 +899,9 @@
  * It is important to note that the value returned by {@link ASensor_getHandle} is not the same as
  * the value returned by the Java API {@link android.hardware.Sensor#getId} and no mapping exists
  * between the values.
- *
- * Available since API level 29.
  */
-int ASensor_getHandle(ASensor const* sensor) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
+int ASensor_getHandle(ASensor const* sensor) __INTRODUCED_IN(__ANDROID_API_Q__);
+#endif /* __ANDROID_API__ >= ANDROID_API_Q__ */
 
 #ifdef __cplusplus
 };
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index 90e5653..ef2ad99 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -46,7 +46,7 @@
  */
 typedef struct ASurfaceControl ASurfaceControl;
 
-/**
+/*
  * Creates an ASurfaceControl with either ANativeWindow or an ASurfaceControl as its parent.
  * |debug_name| is a debug name associated with this surface. It can be used to
  * identify this surface in the SurfaceFlinger's layer tree. It must not be
@@ -54,17 +54,10 @@
  *
  * The caller takes ownership of the ASurfaceControl returned and must release it
  * using ASurfaceControl_release below.
- *
- * Available since API level 29.
  */
 ASurfaceControl* ASurfaceControl_createFromWindow(ANativeWindow* parent, const char* debug_name)
                                                   __INTRODUCED_IN(29);
 
-/**
- * See ASurfaceControl_createFromWindow.
- *
- * Available since API level 29.
- */
 ASurfaceControl* ASurfaceControl_create(ASurfaceControl* parent, const char* debug_name)
                                         __INTRODUCED_IN(29);
 
@@ -72,8 +65,6 @@
  * Releases the |surface_control| object. After releasing the ASurfaceControl the caller no longer
  * has ownership of the AsurfaceControl. The surface and it's children may remain on display as long
  * as their parent remains on display.
- *
- * Available since API level 29.
  */
 void ASurfaceControl_release(ASurfaceControl* surface_control) __INTRODUCED_IN(29);
 
@@ -88,15 +79,11 @@
 /**
  * The caller takes ownership of the transaction and must release it using
  * ASurfaceControl_delete below.
- *
- * Available since API level 29.
  */
 ASurfaceTransaction* ASurfaceTransaction_create() __INTRODUCED_IN(29);
 
 /**
  * Destroys the |transaction| object.
- *
- * Available since API level 29.
  */
 void ASurfaceTransaction_delete(ASurfaceTransaction* transaction) __INTRODUCED_IN(29);
 
@@ -106,8 +93,6 @@
  * Note that the transaction is guaranteed to be applied atomically. The
  * transactions which are applied on the same thread are also guaranteed to be
  * applied in order.
- *
- * Available since API level 29.
  */
 void ASurfaceTransaction_apply(ASurfaceTransaction* transaction) __INTRODUCED_IN(29);
 
@@ -131,8 +116,6 @@
  *
  * THREADING
  * The transaction completed callback can be invoked on any thread.
- *
- * Available since API level 29.
  */
 typedef void (*ASurfaceTransaction_OnComplete)(void* context, ASurfaceTransactionStats* stats)
                                                __INTRODUCED_IN(29);
@@ -140,8 +123,6 @@
 /**
  * Returns the timestamp of when the frame was latched by the framework. Once a frame is
  * latched by the framework, it is presented at the following hardware vsync.
- *
- * Available since API level 29.
  */
 int64_t ASurfaceTransactionStats_getLatchTime(ASurfaceTransactionStats* surface_transaction_stats)
                                               __INTRODUCED_IN(29);
@@ -150,8 +131,6 @@
  * Returns a sync fence that signals when the transaction has been presented.
  * The recipient of the callback takes ownership of the fence and is responsible for closing
  * it.
- *
- * Available since API level 29.
  */
 int ASurfaceTransactionStats_getPresentFenceFd(ASurfaceTransactionStats* surface_transaction_stats)
                                                __INTRODUCED_IN(29);
@@ -162,8 +141,6 @@
  * When the client is done using the array, it must release it by calling
  * ASurfaceTransactionStats_releaseASurfaceControls.
  *
- * Available since API level 29.
- *
  * |outASurfaceControlsSize| returns the size of the ASurfaceControls array.
  */
 void ASurfaceTransactionStats_getASurfaceControls(ASurfaceTransactionStats* surface_transaction_stats,
@@ -173,8 +150,6 @@
 /**
  * Releases the array of ASurfaceControls that were returned by
  * ASurfaceTransactionStats_getASurfaceControls.
- *
- * Available since API level 29.
  */
 void ASurfaceTransactionStats_releaseASurfaceControls(ASurfaceControl** surface_controls)
                                                       __INTRODUCED_IN(29);
@@ -183,8 +158,6 @@
  * Returns the timestamp of when the CURRENT buffer was acquired. A buffer is considered
  * acquired when its acquire_fence_fd has signaled. A buffer cannot be latched or presented until
  * it is acquired. If no acquire_fence_fd was provided, this timestamp will be set to -1.
- *
- * Available since API level 29.
  */
 int64_t ASurfaceTransactionStats_getAcquireTime(ASurfaceTransactionStats* surface_transaction_stats,
                                                 ASurfaceControl* surface_control)
@@ -207,8 +180,6 @@
  *
  * The client must ensure that all pending refs on a buffer are released before attempting to reuse
  * this buffer, otherwise synchronization errors may occur.
- *
- * Available since API level 29.
  */
 int ASurfaceTransactionStats_getPreviousReleaseFenceFd(
                                                 ASurfaceTransactionStats* surface_transaction_stats,
@@ -219,8 +190,6 @@
  * Sets the callback that will be invoked when the updates from this transaction
  * are presented. For details on the callback semantics and data, see the
  * comments on the ASurfaceTransaction_OnComplete declaration above.
- *
- * Available since API level 29.
  */
 void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* transaction, void* context,
                                        ASurfaceTransaction_OnComplete func) __INTRODUCED_IN(29);
@@ -230,8 +199,6 @@
  * Any children of the* reparented |surface_control| will remain children of the |surface_control|.
  *
  * The |new_parent| can be null. Surface controls with a null parent do not appear on the display.
- *
- * Available since API level 29.
  */
 void ASurfaceTransaction_reparent(ASurfaceTransaction* transaction,
                                   ASurfaceControl* surface_control, ASurfaceControl* new_parent)
@@ -246,8 +213,6 @@
  * Updates the visibility of |surface_control|. If show is set to
  * ASURFACE_TRANSACTION_VISIBILITY_HIDE, the |surface_control| and all surfaces in its subtree will
  * be hidden.
- *
- * Available since API level 29.
  */
 void ASurfaceTransaction_setVisibility(ASurfaceTransaction* transaction,
                                        ASurfaceControl* surface_control, int8_t visibility)
@@ -259,8 +224,6 @@
  * the same z order is undefined.
  *
  * Z orders may be from MIN_INT32 to MAX_INT32. A layer's default z order index is 0.
- *
- * Available since API level 29.
  */
 void ASurfaceTransaction_setZOrder(ASurfaceTransaction* transaction,
                                    ASurfaceControl* surface_control, int32_t z_order)
@@ -273,8 +236,6 @@
  *
  * The frameworks takes ownership of the |acquire_fence_fd| passed and is responsible
  * for closing it.
- *
- * Available since API level 29.
  */
 void ASurfaceTransaction_setBuffer(ASurfaceTransaction* transaction,
                                    ASurfaceControl* surface_control, AHardwareBuffer* buffer,
@@ -285,8 +246,6 @@
  * ASurfaceControl visible in transparent regions of the surface.  Colors |r|, |g|,
  * and |b| must be within the range that is valid for |dataspace|.  |dataspace| and |alpha|
  * will be the dataspace and alpha set for the background color layer.
- *
- * Available since API level 29.
  */
 void ASurfaceTransaction_setColor(ASurfaceTransaction* transaction,
                                   ASurfaceControl* surface_control, float r, float g, float b,
@@ -305,8 +264,6 @@
  * |transform| the transform applied after the source rect is applied to the buffer. This parameter
  * should be set to 0 for no transform. To specify a transfrom use the NATIVE_WINDOW_TRANSFORM_*
  * enum.
- *
- * Available since API level 29.
  */
 void ASurfaceTransaction_setGeometry(ASurfaceTransaction* transaction,
                                      ASurfaceControl* surface_control, const ARect& source,
@@ -324,8 +281,6 @@
  * Updates whether the content for the buffer associated with this surface is
  * completely opaque. If true, every pixel of content inside the buffer must be
  * opaque or visual errors can occur.
- *
- * Available since API level 29.
  */
 void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* transaction,
                                                ASurfaceControl* surface_control,
@@ -335,8 +290,6 @@
 /**
  * Updates the region for the content on this surface updated in this
  * transaction. If unspecified, the complete surface is assumed to be damaged.
- *
- * Available since API level 29.
  */
 void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* transaction,
                                          ASurfaceControl* surface_control, const ARect rects[],
@@ -351,8 +304,6 @@
  *
  * If an earlier transaction has a desired present time of x, and a later transaction has a desired
  * present time that is before x, the later transaction will not preempt the earlier transaction.
- *
- * Available since API level 29.
  */
 void ASurfaceTransaction_setDesiredPresentTime(ASurfaceTransaction* transaction,
                                                int64_t desiredPresentTime) __INTRODUCED_IN(29);
@@ -361,8 +312,6 @@
  * Sets the alpha for the buffer. It uses a premultiplied blending.
  *
  * The |alpha| must be between 0.0 and 1.0.
- *
- * Available since API level 29.
  */
 void ASurfaceTransaction_setBufferAlpha(ASurfaceTransaction* transaction,
                                         ASurfaceControl* surface_control, float alpha)
@@ -372,8 +321,6 @@
  * Sets the data space of the surface_control's buffers.
  *
  * If no data space is set, the surface control defaults to ADATASPACE_SRGB.
- *
- * Available since API level 29.
  */
 void ASurfaceTransaction_setBufferDataSpace(ASurfaceTransaction* transaction,
                                             ASurfaceControl* surface_control, ADataSpace data_space)
@@ -384,8 +331,6 @@
  *
  * When |metadata| is set to null, the framework does not use any smpte2086 metadata when rendering
  * the surface's buffer.
- *
- * Available since API level 29.
  */
 void ASurfaceTransaction_setHdrMetadata_smpte2086(ASurfaceTransaction* transaction,
                                                   ASurfaceControl* surface_control,
@@ -397,8 +342,6 @@
  *
  * When |metadata| is set to null, the framework does not use any cta861.3 metadata when rendering
  * the surface's buffer.
- *
- * Available since API level 29.
  */
 void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* transaction,
                                                  ASurfaceControl* surface_control,
diff --git a/include/android/surface_texture.h b/include/android/surface_texture.h
index dde7eaa..540d23a 100644
--- a/include/android/surface_texture.h
+++ b/include/android/surface_texture.h
@@ -65,9 +65,6 @@
  * Release the reference to the native ASurfaceTexture acquired with
  * ASurfaceTexture_fromSurfaceTexture().
  * Failing to do so will result in leaked memory and graphic resources.
- *
- * Available since API level 28.
- *
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  */
 void ASurfaceTexture_release(ASurfaceTexture* st) __INTRODUCED_IN(28);
@@ -76,8 +73,6 @@
  * Returns a reference to an ANativeWindow (i.e. the Producer) for this SurfaceTexture.
  * This is equivalent to Java's: Surface sur = new Surface(surfaceTexture);
  *
- * Available since API level 28.
- *
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  * @return A reference to an ANativeWindow. This reference MUST BE released when no longer needed
  * using ANativeWindow_release(). Failing to do so will result in leaked resources. nullptr is
@@ -95,8 +90,6 @@
  * contexts.  Note, however, that the image contents are only accessible from one OpenGL ES
  * context at a time.
  *
- * Available since API level 28.
- *
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  * \param texName The name of the OpenGL ES texture that will be created.  This texture name
  * must be unusued in the OpenGL ES context that is current on the calling thread.
@@ -115,8 +108,6 @@
  * contexts.  Note, however, that the image contents are only accessible from one OpenGL ES
  * context at a time.
  *
- * Available since API level 28.
- *
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  * \return 0 on success, negative posix error code otherwise (see <errno.h>)
  */
@@ -127,8 +118,6 @@
  * called while the OpenGL ES context that owns the texture is current on the calling thread.
  * It will implicitly bind its texture to the GL_TEXTURE_EXTERNAL_OES texture target.
  *
- * Available since API level 28.
- *
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  * \return 0 on success, negative posix error code otherwise (see <errno.h>)
  */
@@ -146,8 +135,6 @@
  * The matrix is stored in column-major order so that it may be passed directly to OpenGL ES via
  * the glLoadMatrixf or glUniformMatrix4fv functions.
  *
- * Available since API level 28.
- *
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  * \param mtx the array into which the 4x4 matrix will be stored.  The array must have exactly
  *     16 elements.
@@ -169,8 +156,6 @@
  * For EGL/Vulkan producers, this timestamp is the desired present time set with the
  * EGL_ANDROID_presentation_time or VK_GOOGLE_display_timing extensions
  *
- * Available since API level 28.
- *
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  */
 int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) __INTRODUCED_IN(28);
diff --git a/include/android/surface_texture_jni.h b/include/android/surface_texture_jni.h
index 2266d54..b0e1edd 100644
--- a/include/android/surface_texture_jni.h
+++ b/include/android/surface_texture_jni.h
@@ -32,8 +32,6 @@
 
 __BEGIN_DECLS
 
-#if __ANDROID_API__ >= 28
-
 /**
  * Get a reference to the native ASurfaceTexture from the corresponding java object.
  *
@@ -42,17 +40,13 @@
  * properly once the Java object gets finalized.
  * However, this will not result in program termination.
  *
- * Available since API level 28.
- *
  * \param env JNI environment
  * \param surfacetexture Instance of Java SurfaceTexture object
  * \return native ASurfaceTexture reference or nullptr if the java object is not a SurfaceTexture.
  *         The returned reference MUST BE released when it's no longer needed using
  *         ASurfaceTexture_release().
  */
-ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture) __INTRODUCED_IN(28);
-
-#endif
+ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture);
 
 __END_DECLS
 
diff --git a/include/android/system_fonts.h b/include/android/system_fonts.h
index 6fd7d2c..dde9055 100644
--- a/include/android/system_fonts.h
+++ b/include/android/system_fonts.h
@@ -16,7 +16,7 @@
 
 /**
  * @addtogroup Font
- * @{
+ * {
  */
 
 /**
@@ -102,8 +102,6 @@
  *
  * Use ASystemFont_close() to close the iterator.
  *
- * Available since API level 29.
- *
  * \return a pointer for a newly allocated iterator, nullptr on failure.
  */
 ASystemFontIterator* _Nullable ASystemFontIterator_open() __INTRODUCED_IN(29);
@@ -111,8 +109,6 @@
 /**
  * Close an opened system font iterator, freeing any related resources.
  *
- * Available since API level 29.
- *
  * \param iterator a pointer of an iterator for the system fonts. Do nothing if NULL is passed.
  */
 void ASystemFontIterator_close(ASystemFontIterator* _Nullable iterator) __INTRODUCED_IN(29);
@@ -120,8 +116,6 @@
 /**
  * Move to the next system font.
  *
- * Available since API level 29.
- *
  * \param iterator an iterator for the system fonts. Passing NULL is not allowed.
  * \return a font. If no more font is available, returns nullptr. You need to release the returned
  *         font by ASystemFont_close when it is no longer needed.
diff --git a/include/android/trace.h b/include/android/trace.h
index d59690a..bb7ff28 100644
--- a/include/android/trace.h
+++ b/include/android/trace.h
@@ -74,7 +74,7 @@
 
 #endif /* __ANDROID_API__ >= 23 */
 
-#if __ANDROID_API__ >= 29
+#if __ANDROID_API__ >= __ANDROID_API_Q__
 
 /**
  * Writes a trace message to indicate that a given section of code has
@@ -83,8 +83,6 @@
  * asynchronous events do not need to be nested. The name and cookie used to
  * begin an event must be used to end it.
  *
- * Available since API level 29.
- *
  * \param sectionName The method name to appear in the trace.
  * \param cookie Unique identifier for distinguishing simultaneous events
  */
@@ -95,8 +93,6 @@
  * Must be called exactly once for each call to {@link ATrace_beginAsyncSection}
  * using the same name and cookie.
  *
- * Available since API level 29.
- *
  * \param methodName The method name to appear in the trace.
  * \param cookie Unique identifier for distinguishing simultaneous events
  */
@@ -105,8 +101,6 @@
 /**
  * Writes trace message to indicate the value of a given counter.
  *
- * Available since API level 29.
- *
  * \param counterName The counter name to appear in the trace.
  * \param counterValue The counter value.
  */
diff --git a/include/audiomanager/OWNERS b/include/audiomanager/OWNERS
deleted file mode 100644
index 2bd527c..0000000
--- a/include/audiomanager/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-elaurent@google.com
-jmtrivi@google.com
diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h
index 4365a3c..d23e3b7 100644
--- a/include/input/IInputFlinger.h
+++ b/include/input/IInputFlinger.h
@@ -37,7 +37,6 @@
 
     virtual void setInputWindows(const std::vector<InputWindowInfo>& inputHandles,
             const sp<ISetInputWindowsListener>& setInputWindowsListener) = 0;
-    virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0;
     virtual void registerInputChannel(const sp<InputChannel>& channel) = 0;
     virtual void unregisterInputChannel(const sp<InputChannel>& channel) = 0;
 };
@@ -51,8 +50,7 @@
     enum {
         SET_INPUT_WINDOWS_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
         REGISTER_INPUT_CHANNEL_TRANSACTION,
-        UNREGISTER_INPUT_CHANNEL_TRANSACTION,
-        TRANSFER_TOUCH_FOCUS
+        UNREGISTER_INPUT_CHANNEL_TRANSACTION
     };
 
     virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/libs/adbd_auth/Android.bp b/libs/adbd_auth/Android.bp
deleted file mode 100644
index 9cf0143..0000000
--- a/libs/adbd_auth/Android.bp
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (C) 2019 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.
-
-cc_library {
-    name: "libadbd_auth",
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Wthread-safety",
-        "-Werror",
-    ],
-    srcs: ["adbd_auth.cpp"],
-    export_include_dirs: ["include"],
-
-    version_script: "libadbd_auth.map.txt",
-    stubs: {
-        symbol_file: "libadbd_auth.map.txt",
-    },
-
-    host_supported: true,
-    recovery_available: true,
-    target: {
-        darwin: {
-            enabled: false,
-        }
-    },
-
-    shared_libs: [
-        "libbase",
-        "libcutils",
-        "liblog",
-    ],
-}
diff --git a/libs/adbd_auth/adbd_auth.cpp b/libs/adbd_auth/adbd_auth.cpp
deleted file mode 100644
index 6479109..0000000
--- a/libs/adbd_auth/adbd_auth.cpp
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#define ANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION
-
-#include "include/adbd_auth.h"
-
-#include <inttypes.h>
-#include <sys/epoll.h>
-#include <sys/eventfd.h>
-#include <sys/uio.h>
-
-#include <chrono>
-#include <deque>
-#include <string>
-#include <string_view>
-#include <tuple>
-#include <unordered_map>
-#include <utility>
-#include <variant>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <android-base/strings.h>
-#include <android-base/thread_annotations.h>
-#include <android-base/unique_fd.h>
-#include <cutils/sockets.h>
-
-using android::base::unique_fd;
-
-struct AdbdAuthPacketAuthenticated {
-    std::string public_key;
-};
-
-struct AdbdAuthPacketDisconnected {
-    std::string public_key;
-};
-
-struct AdbdAuthPacketRequestAuthorization {
-    std::string public_key;
-};
-
-using AdbdAuthPacket = std::variant<AdbdAuthPacketAuthenticated, AdbdAuthPacketDisconnected,
-                                    AdbdAuthPacketRequestAuthorization>;
-
-struct AdbdAuthContext {
-    static constexpr uint64_t kEpollConstSocket = 0;
-    static constexpr uint64_t kEpollConstEventFd = 1;
-    static constexpr uint64_t kEpollConstFramework = 2;
-
-public:
-    explicit AdbdAuthContext(AdbdAuthCallbacksV1* callbacks) : next_id_(0), callbacks_(*callbacks) {
-        epoll_fd_.reset(epoll_create1(EPOLL_CLOEXEC));
-        if (epoll_fd_ == -1) {
-            PLOG(FATAL) << "failed to create epoll fd";
-        }
-
-        event_fd_.reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
-        if (event_fd_ == -1) {
-            PLOG(FATAL) << "failed to create eventfd";
-        }
-
-        sock_fd_.reset(android_get_control_socket("adbd"));
-        if (sock_fd_ == -1) {
-            PLOG(ERROR) << "failed to get adbd authentication socket";
-        } else {
-            if (fcntl(sock_fd_.get(), F_SETFD, FD_CLOEXEC) != 0) {
-                PLOG(FATAL) << "failed to make adbd authentication socket cloexec";
-            }
-
-            if (fcntl(sock_fd_.get(), F_SETFL, O_NONBLOCK) != 0) {
-                PLOG(FATAL) << "failed to make adbd authentication socket nonblocking";
-            }
-
-            if (listen(sock_fd_.get(), 4) != 0) {
-                PLOG(FATAL) << "failed to listen on adbd authentication socket";
-            }
-        }
-    }
-
-    AdbdAuthContext(const AdbdAuthContext& copy) = delete;
-    AdbdAuthContext(AdbdAuthContext&& move) = delete;
-    AdbdAuthContext& operator=(const AdbdAuthContext& copy) = delete;
-    AdbdAuthContext& operator=(AdbdAuthContext&& move) = delete;
-
-    uint64_t NextId() { return next_id_++; }
-
-    void DispatchPendingPrompt() REQUIRES(mutex_) {
-        if (dispatched_prompt_) {
-            LOG(INFO) << "adbd_auth: prompt currently pending, skipping";
-            return;
-        }
-
-        if (pending_prompts_.empty()) {
-            LOG(INFO) << "adbd_auth: no prompts to send";
-            return;
-        }
-
-        LOG(INFO) << "adbd_auth: prompting user for adb authentication";
-        auto [id, public_key, arg] = std::move(pending_prompts_.front());
-        pending_prompts_.pop_front();
-
-        this->output_queue_.emplace_back(
-                AdbdAuthPacketRequestAuthorization{.public_key = public_key});
-
-        Interrupt();
-        dispatched_prompt_ = std::make_tuple(id, public_key, arg);
-    }
-
-    void UpdateFrameworkWritable() REQUIRES(mutex_) {
-        // This might result in redundant calls to EPOLL_CTL_MOD if, for example, we get notified
-        // at the same time as a framework connection, but that's unlikely and this doesn't need to
-        // be fast anyway.
-        if (framework_fd_ != -1) {
-            struct epoll_event event;
-            event.events = EPOLLIN;
-            if (!output_queue_.empty()) {
-                LOG(INFO) << "marking framework writable";
-                event.events |= EPOLLOUT;
-            }
-            event.data.u64 = kEpollConstFramework;
-            CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_MOD, framework_fd_.get(), &event));
-        }
-    }
-
-    void ReplaceFrameworkFd(unique_fd new_fd) REQUIRES(mutex_) {
-        LOG(INFO) << "received new framework fd " << new_fd.get()
-                  << " (current = " << framework_fd_.get() << ")";
-
-        // If we already had a framework fd, clean up after ourselves.
-        if (framework_fd_ != -1) {
-            output_queue_.clear();
-            dispatched_prompt_.reset();
-            CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_DEL, framework_fd_.get(), nullptr));
-            framework_fd_.reset();
-        }
-
-        if (new_fd != -1) {
-            struct epoll_event event;
-            event.events = EPOLLIN;
-            if (!output_queue_.empty()) {
-                LOG(INFO) << "marking framework writable";
-                event.events |= EPOLLOUT;
-            }
-            event.data.u64 = kEpollConstFramework;
-            CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, new_fd.get(), &event));
-            framework_fd_ = std::move(new_fd);
-        }
-    }
-
-    void HandlePacket(std::string_view packet) REQUIRES(mutex_) {
-        LOG(INFO) << "received packet: " << packet;
-
-        if (packet.length() < 2) {
-          LOG(ERROR) << "received packet of invalid length";
-          ReplaceFrameworkFd(unique_fd());
-        }
-
-        if (packet[0] == 'O' && packet[1] == 'K') {
-          CHECK(this->dispatched_prompt_.has_value());
-          auto& [id, key, arg] = *this->dispatched_prompt_;
-          keys_.emplace(id, std::move(key));
-
-          this->callbacks_.key_authorized(arg, id);
-          this->dispatched_prompt_ = std::nullopt;
-        } else if (packet[0] == 'N' && packet[1] == 'O') {
-          CHECK_EQ(2UL, packet.length());
-          // TODO: Do we want a callback if the key is denied?
-          this->dispatched_prompt_ = std::nullopt;
-          DispatchPendingPrompt();
-        } else {
-          LOG(ERROR) << "unhandled packet: " << packet;
-          ReplaceFrameworkFd(unique_fd());
-        }
-    }
-
-    bool SendPacket() REQUIRES(mutex_) {
-        if (output_queue_.empty()) {
-            return false;
-        }
-
-        CHECK_NE(-1, framework_fd_.get());
-
-        auto& packet = output_queue_.front();
-        struct iovec iovs[2];
-        if (auto* p = std::get_if<AdbdAuthPacketAuthenticated>(&packet)) {
-            iovs[0].iov_base = const_cast<char*>("CK");
-            iovs[0].iov_len = 2;
-            iovs[1].iov_base = p->public_key.data();
-            iovs[1].iov_len = p->public_key.size();
-        } else if (auto* p = std::get_if<AdbdAuthPacketDisconnected>(&packet)) {
-            iovs[0].iov_base = const_cast<char*>("DC");
-            iovs[0].iov_len = 2;
-            iovs[1].iov_base = p->public_key.data();
-            iovs[1].iov_len = p->public_key.size();
-        } else if (auto* p = std::get_if<AdbdAuthPacketRequestAuthorization>(&packet)) {
-            iovs[0].iov_base = const_cast<char*>("PK");
-            iovs[0].iov_len = 2;
-            iovs[1].iov_base = p->public_key.data();
-            iovs[1].iov_len = p->public_key.size();
-        } else {
-            LOG(FATAL) << "unhandled packet type?";
-        }
-
-        output_queue_.pop_front();
-
-        ssize_t rc = writev(framework_fd_.get(), iovs, 2);
-        if (rc == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
-            PLOG(ERROR) << "failed to write to framework fd";
-            ReplaceFrameworkFd(unique_fd());
-            return false;
-        }
-
-        return true;
-    }
-
-    void Run() {
-        if (sock_fd_ == -1) {
-            LOG(ERROR) << "adbd authentication socket unavailable, disabling user prompts";
-        } else {
-            struct epoll_event event;
-            event.events = EPOLLIN;
-            event.data.u64 = kEpollConstSocket;
-            CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, sock_fd_.get(), &event));
-        }
-
-        {
-            struct epoll_event event;
-            event.events = EPOLLIN;
-            event.data.u64 = kEpollConstEventFd;
-            CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, event_fd_.get(), &event));
-        }
-
-        while (true) {
-            struct epoll_event events[3];
-            int rc = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_.get(), events, 3, -1));
-            if (rc == -1) {
-                PLOG(FATAL) << "epoll_wait failed";
-            } else if (rc == 0) {
-                LOG(FATAL) << "epoll_wait returned 0";
-            }
-
-            bool restart = false;
-            for (int i = 0; i < rc; ++i) {
-                if (restart) {
-                    break;
-                }
-
-                struct epoll_event& event = events[i];
-                switch (event.data.u64) {
-                    case kEpollConstSocket: {
-                        unique_fd new_framework_fd(accept4(sock_fd_.get(), nullptr, nullptr,
-                                                           SOCK_CLOEXEC | SOCK_NONBLOCK));
-                        if (new_framework_fd == -1) {
-                            PLOG(FATAL) << "failed to accept framework fd";
-                        }
-
-                        LOG(INFO) << "adbd_auth: received a new framework connection";
-                        std::lock_guard<std::mutex> lock(mutex_);
-                        ReplaceFrameworkFd(std::move(new_framework_fd));
-
-                        // Stop iterating over events: one of the later ones might be the old
-                        // framework fd.
-                        restart = false;
-                        break;
-                    }
-
-                    case kEpollConstEventFd: {
-                        // We were woken up to write something.
-                        uint64_t dummy;
-                        int rc = TEMP_FAILURE_RETRY(read(event_fd_.get(), &dummy, sizeof(dummy)));
-                        if (rc != 8) {
-                            PLOG(FATAL) << "failed to read from eventfd (rc = " << rc << ")";
-                        }
-
-                        std::lock_guard<std::mutex> lock(mutex_);
-                        UpdateFrameworkWritable();
-                        break;
-                    }
-
-                    case kEpollConstFramework: {
-                        char buf[4096];
-                        if (event.events & EPOLLIN) {
-                            int rc = TEMP_FAILURE_RETRY(read(framework_fd_.get(), buf, sizeof(buf)));
-                            if (rc == -1) {
-                                LOG(FATAL) << "failed to read from framework fd";
-                            } else if (rc == 0) {
-                                LOG(INFO) << "hit EOF on framework fd";
-                                std::lock_guard<std::mutex> lock(mutex_);
-                                ReplaceFrameworkFd(unique_fd());
-                            } else {
-                                std::lock_guard<std::mutex> lock(mutex_);
-                                HandlePacket(std::string_view(buf, rc));
-                            }
-                        }
-
-                        if (event.events & EPOLLOUT) {
-                            std::lock_guard<std::mutex> lock(mutex_);
-                            while (SendPacket()) {
-                                continue;
-                            }
-                            UpdateFrameworkWritable();
-                        }
-
-                        break;
-                    }
-                }
-            }
-        }
-    }
-
-    static constexpr const char* key_paths[] = {"/adb_keys", "/data/misc/adb/adb_keys"};
-    void IteratePublicKeys(bool (*callback)(const char*, size_t, void*), void* arg) {
-        for (const auto& path : key_paths) {
-            if (access(path, R_OK) == 0) {
-                LOG(INFO) << "Loading keys from " << path;
-                std::string content;
-                if (!android::base::ReadFileToString(path, &content)) {
-                    PLOG(ERROR) << "Couldn't read " << path;
-                    continue;
-                }
-                for (const auto& line : android::base::Split(content, "\n")) {
-                    if (!callback(line.data(), line.size(), arg)) {
-                        return;
-                    }
-                }
-            }
-        }
-    }
-
-    uint64_t PromptUser(std::string_view public_key, void* arg) EXCLUDES(mutex_) {
-        uint64_t id = NextId();
-
-        std::lock_guard<std::mutex> lock(mutex_);
-        pending_prompts_.emplace_back(id, public_key, arg);
-        DispatchPendingPrompt();
-        return id;
-    }
-
-    uint64_t NotifyAuthenticated(std::string_view public_key) EXCLUDES(mutex_) {
-        uint64_t id = NextId();
-        std::lock_guard<std::mutex> lock(mutex_);
-        keys_.emplace(id, public_key);
-        output_queue_.emplace_back(
-                AdbdAuthPacketDisconnected{.public_key = std::string(public_key)});
-        return id;
-    }
-
-    void NotifyDisconnected(uint64_t id) EXCLUDES(mutex_) {
-        std::lock_guard<std::mutex> lock(mutex_);
-        auto it = keys_.find(id);
-        if (it == keys_.end()) {
-            LOG(DEBUG) << "couldn't find public key to notify disconnection, skipping";
-            return;
-        }
-        output_queue_.emplace_back(AdbdAuthPacketDisconnected{.public_key = std::move(it->second)});
-        keys_.erase(it);
-    }
-
-    // Interrupt the worker thread to do some work.
-    void Interrupt() {
-        uint64_t value = 1;
-        ssize_t rc = write(event_fd_.get(), &value, sizeof(value));
-        if (rc == -1) {
-            PLOG(FATAL) << "write to eventfd failed";
-        } else if (rc != sizeof(value)) {
-            LOG(FATAL) << "write to eventfd returned short (" << rc << ")";
-        }
-    }
-
-    unique_fd epoll_fd_;
-    unique_fd event_fd_;
-    unique_fd sock_fd_;
-    unique_fd framework_fd_;
-
-    std::atomic<uint64_t> next_id_;
-    AdbdAuthCallbacksV1 callbacks_;
-
-    std::mutex mutex_;
-    std::unordered_map<uint64_t, std::string> keys_ GUARDED_BY(mutex_);
-
-    // We keep two separate queues: one to handle backpressure from the socket (output_queue_)
-    // and one to make sure we only dispatch one authrequest at a time (pending_prompts_).
-    std::deque<AdbdAuthPacket> output_queue_;
-
-    std::optional<std::tuple<uint64_t, std::string, void*>> dispatched_prompt_ GUARDED_BY(mutex_);
-    std::deque<std::tuple<uint64_t, std::string, void*>> pending_prompts_ GUARDED_BY(mutex_);
-};
-
-AdbdAuthContext* adbd_auth_new(AdbdAuthCallbacks* callbacks) {
-    if (callbacks->version != 1) {
-      LOG(ERROR) << "received unknown AdbdAuthCallbacks version " << callbacks->version;
-      return nullptr;
-    }
-
-    return new AdbdAuthContext(&callbacks->callbacks.v1);
-}
-
-void adbd_auth_delete(AdbdAuthContext* ctx) {
-    delete ctx;
-}
-
-void adbd_auth_run(AdbdAuthContext* ctx) {
-    return ctx->Run();
-}
-
-void adbd_auth_get_public_keys(AdbdAuthContext* ctx,
-                               bool (*callback)(const char* public_key, size_t len, void* arg),
-                               void* arg) {
-    ctx->IteratePublicKeys(callback, arg);
-}
-
-uint64_t adbd_auth_notify_auth(AdbdAuthContext* ctx, const char* public_key, size_t len) {
-    return ctx->NotifyAuthenticated(std::string_view(public_key, len));
-}
-
-void adbd_auth_notify_disconnect(AdbdAuthContext* ctx, uint64_t id) {
-    return ctx->NotifyDisconnected(id);
-}
-
-void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len,
-                               void* arg) {
-    ctx->PromptUser(std::string_view(public_key, len), arg);
-}
-
-bool adbd_auth_supports_feature(AdbdAuthFeature) {
-    return false;
-}
diff --git a/libs/adbd_auth/include/adbd_auth.h b/libs/adbd_auth/include/adbd_auth.h
deleted file mode 100644
index b7c1cb8..0000000
--- a/libs/adbd_auth/include/adbd_auth.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#pragma once
-
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-extern "C" {
-
-struct AdbdAuthCallbacksV1 {
-    // Callback for a successful user authorization.
-    void (*key_authorized)(void* arg, uint64_t id);
-};
-
-struct AdbdAuthCallbacks {
-    uint32_t version;
-    union {
-        AdbdAuthCallbacksV1 v1;
-    } callbacks;
-};
-
-struct AdbdAuthContext;
-
-AdbdAuthContext* adbd_auth_new(AdbdAuthCallbacks* callbacks);
-void adbd_auth_delete(AdbdAuthContext* ctx);
-
-void adbd_auth_run(AdbdAuthContext* ctx);
-
-// Iterate through the list of authorized public keys.
-// Return false from the callback to stop iteration.
-void adbd_auth_get_public_keys(AdbdAuthContext* ctx,
-                               bool (*callback)(const char* public_key, size_t len, void* arg),
-                               void* arg);
-
-// Let system_server know that a key has been successfully used for authentication.
-uint64_t adbd_auth_notify_auth(AdbdAuthContext* ctx, const char* public_key, size_t len);
-
-// Let system_server know that a connection has been closed.
-void adbd_auth_notify_disconnect(AdbdAuthContext* ctx, uint64_t id);
-
-// Prompt the user to authorize a public key.
-// When this happens, a callback will be run on the auth thread with the result.
-void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len, void* arg);
-
-enum AdbdAuthFeature {
-};
-
-bool adbd_auth_supports_feature(AdbdAuthFeature f);
-
-}
diff --git a/libs/adbd_auth/libadbd_auth.map.txt b/libs/adbd_auth/libadbd_auth.map.txt
deleted file mode 100644
index d01233c..0000000
--- a/libs/adbd_auth/libadbd_auth.map.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-LIBADBD_AUTH {
-  global:
-    adbd_auth_new; # apex
-    adbd_auth_delete; # apex
-    adbd_auth_run; # apex
-    adbd_auth_get_public_keys; #apex
-    adbd_auth_notify_auth; # apex
-    adbd_auth_notify_disconnect; # apex
-    adbd_auth_prompt_user; # apex
-    adbd_auth_supports_feature; # apex
-  local:
-    *;
-};
diff --git a/libs/android_runtime_lazy/Android.bp b/libs/android_runtime_lazy/Android.bp
index 09a5f39..9284acb 100644
--- a/libs/android_runtime_lazy/Android.bp
+++ b/libs/android_runtime_lazy/Android.bp
@@ -34,7 +34,6 @@
     name: "libandroid_runtime_lazy",
     vendor_available: true,
     double_loadable: true,
-    host_supported: true,
 
     cflags: [
         "-Wall",
@@ -52,6 +51,10 @@
         "libutils",
     ],
 
+    required: [
+        "libandroid_runtime",
+    ],
+
     export_include_dirs: [
         "include",
     ],
diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp
index 2518b14..ad8287c 100644
--- a/libs/arect/Android.bp
+++ b/libs/arect/Android.bp
@@ -13,18 +13,13 @@
 // limitations under the License.
 
 ndk_headers {
-    name: "libarect_headers_for_ndk",
+    name: "libarect_headers",
     from: "include/android",
     to: "android",
     srcs: ["include/android/*.h"],
     license: "NOTICE",
 }
 
-cc_library_headers {
-    name: "libarect_headers",
-    export_include_dirs: ["include"],
-}
-
 cc_library_static {
     name: "libarect",
     host_supported: true,
diff --git a/libs/binder/ActivityManager.cpp b/libs/binder/ActivityManager.cpp
index 5e4c98f..49a9414 100644
--- a/libs/binder/ActivityManager.cpp
+++ b/libs/binder/ActivityManager.cpp
@@ -114,4 +114,4 @@
     return INVALID_OPERATION;
 }
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 7ee4882..aedf6b0 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -16,8 +16,6 @@
     name: "libbinder_headers",
     export_include_dirs: ["include"],
     vendor_available: true,
-    host_supported: true,
-
     header_libs: [
         "libbase_headers",
         "libcutils_headers",
@@ -30,28 +28,7 @@
     ],
 }
 
-// These interfaces are android-specific implementation unrelated to binder
-// transport itself and should be moved to AIDL or in domain-specific libs.
-//
-// Currently, these are only on system android (not vendor, not host)
-libbinder_device_interface_sources = [
-    "ActivityManager.cpp",
-    "AppOpsManager.cpp",
-    "IActivityManager.cpp",
-    "IAppOpsCallback.cpp",
-    "IAppOpsService.cpp",
-    "IBatteryStats.cpp",
-    "IMediaResourceMonitor.cpp",
-    "IPermissionController.cpp",
-    "IProcessInfoService.cpp",
-    "IUidObserver.cpp",
-    "PermissionCache.cpp",
-    "PermissionController.cpp",
-    "ProcessInfoService.cpp",
-    "IpPrefix.cpp",
-]
-
-cc_library {
+cc_library_shared {
     name: "libbinder",
 
     // for vndbinder
@@ -60,61 +37,65 @@
         enabled: true,
     },
     double_loadable: true,
-    host_supported: true,
-
-    // TODO(b/31559095): get headers from bionic on host
-    include_dirs: [
-        "bionic/libc/kernel/android/uapi/",
-        "bionic/libc/kernel/uapi/",
-    ],
-
-    // libbinder does not offer a stable wire protocol.
-    // if a second copy of it is installed, then it may break after security
-    // or dessert updates. Instead, apex users should use libbinder_ndk.
-    apex_available: [
-        "//apex_available:platform",
-        "com.android.vndk.current",
-        // TODO(b/139016109) remove these three
-        "com.android.media.swcodec",
-        "test_com.android.media.swcodec",
-    ],
 
     srcs: [
+        "ActivityManager.cpp",
+        "AppOpsManager.cpp",
         "Binder.cpp",
         "BpBinder.cpp",
         "BufferedTextOutput.cpp",
         "Debug.cpp",
+        "IActivityManager.cpp",
+        "IAppOpsCallback.cpp",
+        "IAppOpsService.cpp",
+        "IBatteryStats.cpp",
         "IInterface.cpp",
+        "IMediaResourceMonitor.cpp",
         "IMemory.cpp",
         "IPCThreadState.cpp",
+        "IPermissionController.cpp",
+        "IProcessInfoService.cpp",
         "IResultReceiver.cpp",
         "IServiceManager.cpp",
         "IShellCallback.cpp",
+        "IUidObserver.cpp",
         "MemoryBase.cpp",
         "MemoryDealer.cpp",
         "MemoryHeapBase.cpp",
         "Parcel.cpp",
         "ParcelFileDescriptor.cpp",
+        "PermissionCache.cpp",
+        "PermissionController.cpp",
         "PersistableBundle.cpp",
+        "ProcessInfoService.cpp",
         "ProcessState.cpp",
         "Static.cpp",
-        "Stability.cpp",
         "Status.cpp",
         "TextOutput.cpp",
+        "IpPrefix.cpp",
+        "Value.cpp",
         ":libbinder_aidl",
     ],
 
     target: {
-        android: {
-            srcs: libbinder_device_interface_sources,
-
-            // NOT static to keep the wire protocol unfrozen
-            static: {
-                enabled: false,
-            },
-        },
         vendor: {
-            exclude_srcs: libbinder_device_interface_sources,
+            exclude_srcs: [
+                "ActivityManager.cpp",
+                "AppOpsManager.cpp",
+                "IActivityManager.cpp",
+                "IAppOpsCallback.cpp",
+                "IAppOpsService.cpp",
+                "IBatteryStats.cpp",
+                "IMediaResourceMonitor.cpp",
+                "IPermissionController.cpp",
+                "IProcessInfoService.cpp",
+                "IUidObserver.cpp",
+                "PermissionCache.cpp",
+                "PermissionController.cpp",
+                "ProcessInfoService.cpp",
+                "IpPrefix.cpp",
+                ":libbinder_aidl",
+            ],
         },
     },
 
@@ -135,6 +116,7 @@
     },
 
     shared_libs: [
+        "libbase",
         "liblog",
         "libcutils",
         "libutils",
@@ -160,21 +142,7 @@
     name: "libbinder_aidl",
     srcs: [
         "aidl/android/content/pm/IPackageManagerNative.aidl",
-        "aidl/android/os/IServiceCallback.aidl",
-        "aidl/android/os/IServiceManager.aidl",
     ],
-    path: "aidl",
 }
 
-aidl_interface {
-    name: "libbinder_aidl_test_stub",
-    local_include_dir: "aidl",
-    srcs: [":libbinder_aidl"],
-    visibility: [":__subpackages__"],
-    vendor_available: true,
-    backend: {
-        java: {
-            enabled: false,
-        },
-    },
-}
+subdirs = ["tests"]
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index 0a6685e..525685c 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -147,4 +147,4 @@
 }
 
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 2f6e9c3..cb0e08d 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -81,50 +81,6 @@
     return target->transact(SHELL_COMMAND_TRANSACTION, send, &reply);
 }
 
-status_t IBinder::getExtension(sp<IBinder>* out) {
-    BBinder* local = this->localBinder();
-    if (local != nullptr) {
-        *out = local->getExtension();
-        return OK;
-    }
-
-    BpBinder* proxy = this->remoteBinder();
-    LOG_ALWAYS_FATAL_IF(proxy == nullptr);
-
-    Parcel data;
-    Parcel reply;
-    status_t status = transact(EXTENSION_TRANSACTION, data, &reply);
-    if (status != OK) return status;
-
-    return reply.readNullableStrongBinder(out);
-}
-
-status_t IBinder::getDebugPid(pid_t* out) {
-    BBinder* local = this->localBinder();
-    if (local != nullptr) {
-      *out = local->getDebugPid();
-      return OK;
-    }
-
-    BpBinder* proxy = this->remoteBinder();
-    LOG_ALWAYS_FATAL_IF(proxy == nullptr);
-
-    Parcel data;
-    Parcel reply;
-    status_t status = transact(DEBUG_PID_TRANSACTION, data, &reply);
-    if (status != OK) return status;
-
-    int32_t pid;
-    status = reply.readInt32(&pid);
-    if (status != OK) return status;
-
-    if (pid < 0 || pid > std::numeric_limits<pid_t>::max()) {
-        return BAD_VALUE;
-    }
-    *out = pid;
-    return OK;
-}
-
 // ---------------------------------------------------------------------------
 
 class BBinder::Extras
@@ -132,7 +88,6 @@
 public:
     // unlocked objects
     bool mRequestingSid = false;
-    sp<IBinder> mExtension;
 
     // for below objects
     Mutex mLock;
@@ -173,20 +128,13 @@
     status_t err = NO_ERROR;
     switch (code) {
         case PING_TRANSACTION:
-            err = pingBinder();
-            break;
-        case EXTENSION_TRANSACTION:
-            err = reply->writeStrongBinder(getExtension());
-            break;
-        case DEBUG_PID_TRANSACTION:
-            err = reply->writeInt32(getDebugPid());
+            reply->writeInt32(pingBinder());
             break;
         default:
             err = onTransact(code, data, reply, flags);
             break;
     }
 
-    // In case this is being transacted on in the same process.
     if (reply != nullptr) {
         reply->setDataPosition(0);
     }
@@ -273,21 +221,6 @@
     e->mRequestingSid = requestingSid;
 }
 
-sp<IBinder> BBinder::getExtension() {
-    Extras* e = mExtras.load(std::memory_order_acquire);
-    if (e == nullptr) return nullptr;
-    return e->mExtension;
-}
-
-pid_t BBinder::getDebugPid() {
-    return getpid();
-}
-
-void BBinder::setExtension(const sp<IBinder>& extension) {
-    Extras* e = getOrCreateExtras();
-    e->mExtension = extension;
-}
-
 BBinder::~BBinder()
 {
     Extras* e = mExtras.load(std::memory_order_relaxed);
@@ -419,4 +352,4 @@
 
 // ---------------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 238c9dc..ec170f7 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -21,7 +21,6 @@
 
 #include <binder/IPCThreadState.h>
 #include <binder/IResultReceiver.h>
-#include <binder/Stability.h>
 #include <cutils/compiler.h>
 #include <utils/Log.h>
 
@@ -149,10 +148,6 @@
     IPCThreadState::self()->incWeakHandle(handle, this);
 }
 
-int32_t BpBinder::handle() const {
-    return mHandle;
-}
-
 bool BpBinder::isDescriptorCached() const {
     Mutex::Autolock _l(mLock);
     return mDescriptorCache.size() ? true : false;
@@ -191,7 +186,10 @@
 {
     Parcel send;
     Parcel reply;
-    return transact(PING_TRANSACTION, send, &reply);
+    status_t err = transact(PING_TRANSACTION, send, &reply);
+    if (err != NO_ERROR) return err;
+    if (reply.dataSize() < sizeof(status_t)) return NOT_ENOUGH_DATA;
+    return (status_t)reply.readInt32();
 }
 
 status_t BpBinder::dump(int fd, const Vector<String16>& args)
@@ -214,29 +212,9 @@
 {
     // Once a binder has died, it will never come back to life.
     if (mAlive) {
-        bool privateVendor = flags & FLAG_PRIVATE_VENDOR;
-        // don't send userspace flags to the kernel
-        flags = flags & ~FLAG_PRIVATE_VENDOR;
-
-        // user transactions require a given stability level
-        if (code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION) {
-            using android::internal::Stability;
-
-            auto stability = Stability::get(this);
-            auto required = privateVendor ? Stability::VENDOR : Stability::kLocalStability;
-
-            if (CC_UNLIKELY(!Stability::check(stability, required))) {
-                ALOGE("Cannot do a user transaction on a %s binder in a %s context.",
-                    Stability::stabilityString(stability).c_str(),
-                    Stability::stabilityString(required).c_str());
-                return BAD_TYPE;
-            }
-        }
-
         status_t status = IPCThreadState::self()->transact(
             mHandle, code, data, reply, flags);
         if (status == DEAD_OBJECT) mAlive = 0;
-
         return status;
     }
 
@@ -409,6 +387,21 @@
         }
     }
 
+    mLock.lock();
+    Vector<Obituary>* obits = mObituaries;
+    if(obits != nullptr) {
+        if (ipc) ipc->clearDeathNotification(mHandle, this);
+        mObituaries = nullptr;
+    }
+    mLock.unlock();
+
+    if (obits != nullptr) {
+        // XXX Should we tell any remaining DeathRecipient
+        // objects that the last strong ref has gone away, so they
+        // are no longer linked?
+        delete obits;
+    }
+
     if (ipc) {
         ipc->expungeHandle(mHandle, this);
         ipc->decWeakHandle(mHandle);
@@ -430,25 +423,6 @@
     }
     IPCThreadState* ipc = IPCThreadState::self();
     if (ipc) ipc->decStrongHandle(mHandle);
-
-    mLock.lock();
-    Vector<Obituary>* obits = mObituaries;
-    if(obits != nullptr) {
-        if (!obits->isEmpty()) {
-            ALOGI("onLastStrongRef automatically unlinking death recipients");
-        }
-
-        if (ipc) ipc->clearDeathNotification(mHandle, this);
-        mObituaries = nullptr;
-    }
-    mLock.unlock();
-
-    if (obits != nullptr) {
-        // XXX Should we tell any remaining DeathRecipient
-        // objects that the last strong ref has gone away, so they
-        // are no longer linked?
-        delete obits;
-    }
 }
 
 bool BpBinder::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/)
@@ -496,4 +470,4 @@
 
 // ---------------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index fb424fd..2978b53 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -23,12 +23,12 @@
 #include <utils/RefBase.h>
 #include <utils/Vector.h>
 
+#include <private/binder/Static.h>
+
 #include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "Static.h"
-
 // ---------------------------------------------------------------------------
 
 namespace android {
@@ -49,9 +49,10 @@
     }
     
     status_t append(const char* txt, size_t len) {
+        if (len > SIZE_MAX - bufferPos) return NO_MEMORY; // overflow
         if ((len+bufferPos) > bufferSize) {
+            if ((len + bufferPos) > SIZE_MAX / 3) return NO_MEMORY; // overflow
             size_t newSize = ((len+bufferPos)*3)/2;
-            if (newSize < (len+bufferPos)) return NO_MEMORY;    // overflow
             void* b = realloc(buffer, newSize);
             if (!b) return NO_MEMORY;
             buffer = (char*)b;
@@ -280,4 +281,4 @@
     return mGlobalState;
 }
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/Debug.cpp b/libs/binder/Debug.cpp
index 64c1ff6..a1c2a8b 100644
--- a/libs/binder/Debug.cpp
+++ b/libs/binder/Debug.cpp
@@ -308,5 +308,5 @@
     return proc->getKernelReferences(count, buf);
 }
 
-} // namespace android
+}; // namespace android
 
diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp
index 1eb5363..377f604 100644
--- a/libs/binder/IActivityManager.cpp
+++ b/libs/binder/IActivityManager.cpp
@@ -110,4 +110,4 @@
 
 IMPLEMENT_META_INTERFACE(ActivityManager, "android.app.IActivityManager");
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IAppOpsCallback.cpp b/libs/binder/IAppOpsCallback.cpp
index 0ce1dd5..aba4967 100644
--- a/libs/binder/IAppOpsCallback.cpp
+++ b/libs/binder/IAppOpsCallback.cpp
@@ -22,6 +22,8 @@
 #include <binder/Parcel.h>
 #include <utils/String8.h>
 
+#include <private/binder/Static.h>
+
 namespace android {
 
 // ----------------------------------------------------------------------
@@ -66,4 +68,4 @@
     }
 }
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index b2bd9e5..66d6e31 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -22,6 +22,8 @@
 #include <binder/Parcel.h>
 #include <utils/String8.h>
 
+#include <private/binder/Static.h>
+
 namespace android {
 
 // ----------------------------------------------------------------------
@@ -239,4 +241,4 @@
     }
 }
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IBatteryStats.cpp b/libs/binder/IBatteryStats.cpp
index a47dbac..b307e3e 100644
--- a/libs/binder/IBatteryStats.cpp
+++ b/libs/binder/IBatteryStats.cpp
@@ -20,6 +20,8 @@
 #include <binder/Parcel.h>
 #include <utils/String8.h>
 
+#include <private/binder/Static.h>
+
 namespace android {
 
 // ----------------------------------------------------------------------
@@ -240,4 +242,4 @@
     }
 }
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IInterface.cpp b/libs/binder/IInterface.cpp
index b19004d..59d51ed 100644
--- a/libs/binder/IInterface.cpp
+++ b/libs/binder/IInterface.cpp
@@ -46,4 +46,4 @@
 
 // ---------------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IMediaResourceMonitor.cpp b/libs/binder/IMediaResourceMonitor.cpp
index 4198e49..77e3d23 100644
--- a/libs/binder/IMediaResourceMonitor.cpp
+++ b/libs/binder/IMediaResourceMonitor.cpp
@@ -59,4 +59,4 @@
 
 // ----------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index 222b32c..caf2318 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -149,10 +149,6 @@
     return static_cast<char*>(base) + offset;
 }
 
-void* IMemory::unsecurePointer() const {
-    return pointer();
-}
-
 void* IMemory::pointer() const {
     ssize_t offset;
     sp<IMemoryHeap> heap = getMemory(&offset);
@@ -514,4 +510,4 @@
 
 
 // ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 4981d7a..9a561cb 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -31,8 +31,8 @@
 #include <utils/threads.h>
 
 #include <private/binder/binder_module.h>
+#include <private/binder/Static.h>
 
-#include <atomic>
 #include <errno.h>
 #include <inttypes.h>
 #include <pthread.h>
@@ -43,8 +43,6 @@
 #include <sys/resource.h>
 #include <unistd.h>
 
-#include "Static.h"
-
 #if LOG_NDEBUG
 
 #define IF_LOG_TRANSACTIONS() if (false)
@@ -118,7 +116,7 @@
 
 static const char* getReturnString(uint32_t cmd)
 {
-    size_t idx = cmd & _IOC_NRMASK;
+    size_t idx = cmd & 0xff;
     if (idx < sizeof(kReturnStrings) / sizeof(kReturnStrings[0]))
         return kReturnStrings[idx];
     else
@@ -280,14 +278,14 @@
 }
 
 static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
-static std::atomic<bool> gHaveTLS(false);
+static bool gHaveTLS = false;
 static pthread_key_t gTLS = 0;
-static std::atomic<bool> gShutdown = false;
-static std::atomic<bool> gDisableBackgroundScheduling = false;
+static bool gShutdown = false;
+static bool gDisableBackgroundScheduling = false;
 
 IPCThreadState* IPCThreadState::self()
 {
-    if (gHaveTLS.load(std::memory_order_acquire)) {
+    if (gHaveTLS) {
 restart:
         const pthread_key_t k = gTLS;
         IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
@@ -295,14 +293,13 @@
         return new IPCThreadState;
     }
 
-    // Racey, heuristic test for simultaneous shutdown.
-    if (gShutdown.load(std::memory_order_relaxed)) {
+    if (gShutdown) {
         ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
         return nullptr;
     }
 
     pthread_mutex_lock(&gTLSMutex);
-    if (!gHaveTLS.load(std::memory_order_relaxed)) {
+    if (!gHaveTLS) {
         int key_create_value = pthread_key_create(&gTLS, threadDestructor);
         if (key_create_value != 0) {
             pthread_mutex_unlock(&gTLSMutex);
@@ -310,7 +307,7 @@
                     strerror(key_create_value));
             return nullptr;
         }
-        gHaveTLS.store(true, std::memory_order_release);
+        gHaveTLS = true;
     }
     pthread_mutex_unlock(&gTLSMutex);
     goto restart;
@@ -318,7 +315,7 @@
 
 IPCThreadState* IPCThreadState::selfOrNull()
 {
-    if (gHaveTLS.load(std::memory_order_acquire)) {
+    if (gHaveTLS) {
         const pthread_key_t k = gTLS;
         IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
         return st;
@@ -328,9 +325,9 @@
 
 void IPCThreadState::shutdown()
 {
-    gShutdown.store(true, std::memory_order_relaxed);
+    gShutdown = true;
 
-    if (gHaveTLS.load(std::memory_order_acquire)) {
+    if (gHaveTLS) {
         // XXX Need to wait for all thread pool threads to exit!
         IPCThreadState* st = (IPCThreadState*)pthread_getspecific(gTLS);
         if (st) {
@@ -338,18 +335,18 @@
             pthread_setspecific(gTLS, nullptr);
         }
         pthread_key_delete(gTLS);
-        gHaveTLS.store(false, std::memory_order_release);
+        gHaveTLS = false;
     }
 }
 
 void IPCThreadState::disableBackgroundScheduling(bool disable)
 {
-    gDisableBackgroundScheduling.store(disable, std::memory_order_relaxed);
+    gDisableBackgroundScheduling = disable;
 }
 
 bool IPCThreadState::backgroundSchedulingDisabled()
 {
-    return gDisableBackgroundScheduling.load(std::memory_order_relaxed);
+    return gDisableBackgroundScheduling;
 }
 
 sp<ProcessState> IPCThreadState::process()
@@ -465,7 +462,7 @@
 
 void IPCThreadState::flushCommands()
 {
-    if (mProcess->mDriverFD < 0)
+    if (mProcess->mDriverFD <= 0)
         return;
     talkWithDriver(false);
     // The flush could have caused post-write refcount decrements to have
@@ -597,8 +594,9 @@
         result = getAndExecuteCommand();
 
         if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
-            LOG_ALWAYS_FATAL("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
+            ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
                   mProcess->mDriverFD, result);
+            abort();
         }
 
         // Let this thread exit the thread pool if it is no longer
@@ -617,7 +615,7 @@
 
 int IPCThreadState::setupPolling(int* fd)
 {
-    if (mProcess->mDriverFD < 0) {
+    if (mProcess->mDriverFD <= 0) {
         return -EBADF;
     }
 
@@ -676,11 +674,11 @@
     if ((flags & TF_ONE_WAY) == 0) {
         if (UNLIKELY(mCallRestriction != ProcessState::CallRestriction::NONE)) {
             if (mCallRestriction == ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY) {
-                ALOGE("Process making non-oneway call (code: %u) but is restricted.", code);
+                ALOGE("Process making non-oneway call but is restricted.");
                 CallStack::logStack("non-oneway call", CallStack::getCurrent(10).get(),
                     ANDROID_LOG_ERROR);
             } else /* FATAL_IF_NOT_ONEWAY */ {
-                LOG_ALWAYS_FATAL("Process may not make oneway calls (code: %u).", code);
+                LOG_ALWAYS_FATAL("Process may not make oneway calls.");
             }
         }
 
@@ -923,7 +921,7 @@
 
 status_t IPCThreadState::talkWithDriver(bool doReceive)
 {
-    if (mProcess->mDriverFD < 0) {
+    if (mProcess->mDriverFD <= 0) {
         return -EBADF;
     }
 
@@ -981,7 +979,7 @@
 #else
         err = INVALID_OPERATION;
 #endif
-        if (mProcess->mDriverFD < 0) {
+        if (mProcess->mDriverFD <= 0) {
             err = -EBADF;
         }
         IF_LOG_COMMANDS() {
@@ -998,7 +996,7 @@
     if (err >= NO_ERROR) {
         if (bwr.write_consumed > 0) {
             if (bwr.write_consumed < mOut.dataSize())
-                LOG_ALWAYS_FATAL("Driver did not consume write buffer");
+                mOut.remove(0, bwr.write_consumed);
             else {
                 mOut.setDataSize(0);
                 processPostWriteDerefs();
@@ -1062,7 +1060,7 @@
 
 sp<BBinder> the_context_object;
 
-void IPCThreadState::setTheContextObject(sp<BBinder> obj)
+void setTheContextObject(sp<BBinder> obj)
 {
     the_context_object = obj;
 }
@@ -1300,7 +1298,7 @@
         if (self) {
                 self->flushCommands();
 #if defined(__ANDROID__)
-        if (self->mProcess->mDriverFD >= 0) {
+        if (self->mProcess->mDriverFD > 0) {
             ioctl(self->mProcess->mDriverFD, BINDER_THREAD_EXIT, 0);
         }
 #endif
@@ -1325,4 +1323,4 @@
     state->mOut.writePointer((uintptr_t)data);
 }
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IPermissionController.cpp b/libs/binder/IPermissionController.cpp
index d9bf3cc..6b99150 100644
--- a/libs/binder/IPermissionController.cpp
+++ b/libs/binder/IPermissionController.cpp
@@ -22,6 +22,8 @@
 #include <binder/Parcel.h>
 #include <utils/String8.h>
 
+#include <private/binder/Static.h>
+
 namespace android {
 
 // ----------------------------------------------------------------------
@@ -172,4 +174,4 @@
     }
 }
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IProcessInfoService.cpp b/libs/binder/IProcessInfoService.cpp
index a38a27a..96e1a8c 100644
--- a/libs/binder/IProcessInfoService.cpp
+++ b/libs/binder/IProcessInfoService.cpp
@@ -88,4 +88,4 @@
 
 // ----------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IResultReceiver.cpp b/libs/binder/IResultReceiver.cpp
index 556288c..159763d 100644
--- a/libs/binder/IResultReceiver.cpp
+++ b/libs/binder/IResultReceiver.cpp
@@ -22,6 +22,8 @@
 #include <binder/Parcel.h>
 #include <utils/String8.h>
 
+#include <private/binder/Static.h>
+
 namespace android {
 
 // ----------------------------------------------------------------------
@@ -65,4 +67,4 @@
     }
 }
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 4f47db1..4ba6c2a 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -18,86 +18,31 @@
 
 #include <binder/IServiceManager.h>
 
-#include <android/os/BnServiceCallback.h>
-#include <android/os/IServiceManager.h>
-#include <binder/IPCThreadState.h>
-#include <binder/Parcel.h>
 #include <utils/Log.h>
-#include <utils/String8.h>
-#include <utils/SystemClock.h>
-
+#include <binder/IPCThreadState.h>
 #ifndef __ANDROID_VNDK__
 #include <binder/IPermissionController.h>
 #endif
-
-#ifdef __ANDROID__
+#include <binder/Parcel.h>
 #include <cutils/properties.h>
-#endif
+#include <utils/String8.h>
+#include <utils/SystemClock.h>
 
-#include "Static.h"
+#include <private/binder/Static.h>
 
 #include <unistd.h>
 
 namespace android {
 
-using AidlServiceManager = android::os::IServiceManager;
-using android::binder::Status;
-
-// libbinder's IServiceManager.h can't rely on the values generated by AIDL
-// because many places use its headers via include_dirs (meaning, without
-// declaring the dependency in the build system). So, for now, we can just check
-// the values here.
-static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_CRITICAL == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
-static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_HIGH == IServiceManager::DUMP_FLAG_PRIORITY_HIGH);
-static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_NORMAL == IServiceManager::DUMP_FLAG_PRIORITY_NORMAL);
-static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_DEFAULT == IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
-static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_ALL == IServiceManager::DUMP_FLAG_PRIORITY_ALL);
-static_assert(AidlServiceManager::DUMP_FLAG_PROTO == IServiceManager::DUMP_FLAG_PROTO);
-
-const String16& IServiceManager::getInterfaceDescriptor() const {
-    return AidlServiceManager::descriptor;
-}
-IServiceManager::IServiceManager() {}
-IServiceManager::~IServiceManager() {}
-
-// From the old libbinder IServiceManager interface to IServiceManager.
-class ServiceManagerShim : public IServiceManager
-{
-public:
-    explicit ServiceManagerShim (const sp<AidlServiceManager>& impl);
-
-    sp<IBinder> getService(const String16& name) const override;
-    sp<IBinder> checkService(const String16& name) const override;
-    status_t addService(const String16& name, const sp<IBinder>& service,
-                        bool allowIsolated, int dumpsysPriority) override;
-    Vector<String16> listServices(int dumpsysPriority) override;
-    sp<IBinder> waitForService(const String16& name16) override;
-    bool isDeclared(const String16& name) override;
-
-    // for legacy ABI
-    const String16& getInterfaceDescriptor() const override {
-        return mTheRealServiceManager->getInterfaceDescriptor();
-    }
-    IBinder* onAsBinder() override {
-        return IInterface::asBinder(mTheRealServiceManager).get();
-    }
-private:
-    sp<AidlServiceManager> mTheRealServiceManager;
-};
-
 sp<IServiceManager> defaultServiceManager()
 {
-    static Mutex gDefaultServiceManagerLock;
-    static sp<IServiceManager> gDefaultServiceManager;
-
     if (gDefaultServiceManager != nullptr) return gDefaultServiceManager;
 
     {
         AutoMutex _l(gDefaultServiceManagerLock);
         while (gDefaultServiceManager == nullptr) {
-            gDefaultServiceManager = new ServiceManagerShim(
-                interface_cast<AidlServiceManager>(
-                    ProcessState::self()->getContextObject(nullptr)));
+            gDefaultServiceManager = interface_cast<IServiceManager>(
+                ProcessState::self()->getContextObject(nullptr));
             if (gDefaultServiceManager == nullptr)
                 sleep(1);
         }
@@ -106,7 +51,7 @@
     return gDefaultServiceManager;
 }
 
-#if !defined(__ANDROID_VNDK__) && defined(__ANDROID__)
+#ifndef __ANDROID_VNDK__
 // IPermissionController is not accessible to vendors
 
 bool checkCallingPermission(const String16& permission)
@@ -129,13 +74,10 @@
 
 bool checkPermission(const String16& permission, pid_t pid, uid_t uid)
 {
-    static Mutex gPermissionControllerLock;
-    static sp<IPermissionController> gPermissionController;
-
     sp<IPermissionController> pc;
-    gPermissionControllerLock.lock();
+    gDefaultServiceManagerLock.lock();
     pc = gPermissionController;
-    gPermissionControllerLock.unlock();
+    gDefaultServiceManagerLock.unlock();
 
     int64_t startTime = 0;
 
@@ -159,11 +101,11 @@
             }
 
             // Object is dead!
-            gPermissionControllerLock.lock();
+            gDefaultServiceManagerLock.lock();
             if (gPermissionController == pc) {
                 gPermissionController = nullptr;
             }
-            gPermissionControllerLock.unlock();
+            gDefaultServiceManagerLock.unlock();
         }
 
         // Need to retrieve the permission controller.
@@ -179,9 +121,9 @@
         } else {
             pc = interface_cast<IPermissionController>(binder);
             // Install the new permission controller, and try again.
-            gPermissionControllerLock.lock();
+            gDefaultServiceManagerLock.lock();
             gPermissionController = pc;
-            gPermissionControllerLock.unlock();
+            gDefaultServiceManagerLock.unlock();
         }
     }
 }
@@ -190,144 +132,84 @@
 
 // ----------------------------------------------------------------------
 
-ServiceManagerShim::ServiceManagerShim(const sp<AidlServiceManager>& impl)
- : mTheRealServiceManager(impl)
-{}
-
-sp<IBinder> ServiceManagerShim::getService(const String16& name) const
+class BpServiceManager : public BpInterface<IServiceManager>
 {
-    static bool gSystemBootCompleted = false;
-
-    sp<IBinder> svc = checkService(name);
-    if (svc != nullptr) return svc;
-
-    const bool isVendorService =
-        strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0;
-    const long timeout = uptimeMillis() + 5000;
-    // Vendor code can't access system properties
-    if (!gSystemBootCompleted && !isVendorService) {
-#ifdef __ANDROID__
-        char bootCompleted[PROPERTY_VALUE_MAX];
-        property_get("sys.boot_completed", bootCompleted, "0");
-        gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false;
-#else
-        gSystemBootCompleted = true;
-#endif
+public:
+    explicit BpServiceManager(const sp<IBinder>& impl)
+        : BpInterface<IServiceManager>(impl)
+    {
     }
-    // retry interval in millisecond; note that vendor services stay at 100ms
-    const long sleepTime = gSystemBootCompleted ? 1000 : 100;
 
-    int n = 0;
-    while (uptimeMillis() < timeout) {
-        n++;
-        ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(),
-            ProcessState::self()->getDriverName().c_str());
-        usleep(1000*sleepTime);
-
+    virtual sp<IBinder> getService(const String16& name) const
+    {
         sp<IBinder> svc = checkService(name);
         if (svc != nullptr) return svc;
-    }
-    ALOGW("Service %s didn't start. Returning NULL", String8(name).string());
-    return nullptr;
-}
 
-sp<IBinder> ServiceManagerShim::checkService(const String16& name) const
-{
-    sp<IBinder> ret;
-    if (!mTheRealServiceManager->checkService(String8(name).c_str(), &ret).isOk()) {
-        return nullptr;
-    }
-    return ret;
-}
-
-status_t ServiceManagerShim::addService(const String16& name, const sp<IBinder>& service,
-                                        bool allowIsolated, int dumpsysPriority)
-{
-    Status status = mTheRealServiceManager->addService(
-        String8(name).c_str(), service, allowIsolated, dumpsysPriority);
-    return status.exceptionCode();
-}
-
-Vector<String16> ServiceManagerShim::listServices(int dumpsysPriority)
-{
-    std::vector<std::string> ret;
-    if (!mTheRealServiceManager->listServices(dumpsysPriority, &ret).isOk()) {
-        return {};
-    }
-
-    Vector<String16> res;
-    res.setCapacity(ret.size());
-    for (const std::string& name : ret) {
-        res.push(String16(name.c_str()));
-    }
-    return res;
-}
-
-sp<IBinder> ServiceManagerShim::waitForService(const String16& name16)
-{
-    class Waiter : public android::os::BnServiceCallback {
-        Status onRegistration(const std::string& /*name*/,
-                              const sp<IBinder>& binder) override {
-            std::unique_lock<std::mutex> lock(mMutex);
-            mBinder = binder;
-            lock.unlock();
-            mCv.notify_one();
-            return Status::ok();
+        const bool isVendorService =
+            strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0;
+        const long timeout = uptimeMillis() + 5000;
+        if (!gSystemBootCompleted && !isVendorService) {
+            // Vendor code can't access system properties
+            char bootCompleted[PROPERTY_VALUE_MAX];
+            property_get("sys.boot_completed", bootCompleted, "0");
+            gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false;
         }
-    public:
-        sp<IBinder> mBinder;
-        std::mutex mMutex;
-        std::condition_variable mCv;
-    };
+        // retry interval in millisecond; note that vendor services stay at 100ms
+        const long sleepTime = gSystemBootCompleted ? 1000 : 100;
 
-    const std::string name = String8(name16).c_str();
+        int n = 0;
+        while (uptimeMillis() < timeout) {
+            n++;
+            ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(),
+                ProcessState::self()->getDriverName().c_str());
+            usleep(1000*sleepTime);
 
-    sp<IBinder> out;
-    if (!mTheRealServiceManager->getService(name, &out).isOk()) {
-        return nullptr;
-    }
-    if(out != nullptr) return out;
-
-    sp<Waiter> waiter = new Waiter;
-    if (!mTheRealServiceManager->registerForNotifications(
-            name, waiter).isOk()) {
+            sp<IBinder> svc = checkService(name);
+            if (svc != nullptr) return svc;
+        }
+        ALOGW("Service %s didn't start. Returning NULL", String8(name).string());
         return nullptr;
     }
 
-    while(true) {
-        {
-            std::unique_lock<std::mutex> lock(waiter->mMutex);
-            using std::literals::chrono_literals::operator""s;
-            waiter->mCv.wait_for(lock, 1s, [&] {
-                return waiter->mBinder != nullptr;
-            });
-            if (waiter->mBinder != nullptr) return waiter->mBinder;
-        }
-
-        // Handle race condition for lazy services. Here is what can happen:
-        // - the service dies (not processed by init yet).
-        // - sm processes death notification.
-        // - sm gets getService and calls init to start service.
-        // - init gets the start signal, but the service already appears
-        //   started, so it does nothing.
-        // - init gets death signal, but doesn't know it needs to restart
-        //   the service
-        // - we need to request service again to get it to start
-        if (!mTheRealServiceManager->getService(name, &out).isOk()) {
-            return nullptr;
-        }
-        if(out != nullptr) return out;
-
-        ALOGW("Waited one second for %s", name.c_str());
+    virtual sp<IBinder> checkService( const String16& name) const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
+        data.writeString16(name);
+        remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
+        return reply.readStrongBinder();
     }
-}
 
-bool ServiceManagerShim::isDeclared(const String16& name) {
-    bool declared;
-    if (!mTheRealServiceManager->isDeclared(String8(name).c_str(), &declared).isOk()) {
-        return false;
+    virtual status_t addService(const String16& name, const sp<IBinder>& service,
+                                bool allowIsolated, int dumpsysPriority) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeStrongBinder(service);
+        data.writeInt32(allowIsolated ? 1 : 0);
+        data.writeInt32(dumpsysPriority);
+        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
+        return err == NO_ERROR ? reply.readExceptionCode() : err;
     }
-    return declared;
-}
 
-} // namespace android
+    virtual Vector<String16> listServices(int dumpsysPriority) {
+        Vector<String16> res;
+        int n = 0;
+
+        for (;;) {
+            Parcel data, reply;
+            data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
+            data.writeInt32(n++);
+            data.writeInt32(dumpsysPriority);
+            status_t err = remote()->transact(LIST_SERVICES_TRANSACTION, data, &reply);
+            if (err != NO_ERROR)
+                break;
+            res.add(reply.readString16());
+        }
+        return res;
+    }
+};
+
+IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
+
+}; // namespace android
diff --git a/libs/binder/IShellCallback.cpp b/libs/binder/IShellCallback.cpp
index a3e2b67..6c697de 100644
--- a/libs/binder/IShellCallback.cpp
+++ b/libs/binder/IShellCallback.cpp
@@ -25,6 +25,8 @@
 #include <binder/Parcel.h>
 #include <utils/String8.h>
 
+#include <private/binder/Static.h>
+
 namespace android {
 
 // ----------------------------------------------------------------------
@@ -85,4 +87,4 @@
     }
 }
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IUidObserver.cpp b/libs/binder/IUidObserver.cpp
index 038e6bf..82f9047 100644
--- a/libs/binder/IUidObserver.cpp
+++ b/libs/binder/IUidObserver.cpp
@@ -112,4 +112,4 @@
     }
 }
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IpPrefix.cpp b/libs/binder/IpPrefix.cpp
index 8d62266..3a8a63c 100644
--- a/libs/binder/IpPrefix.cpp
+++ b/libs/binder/IpPrefix.cpp
@@ -30,6 +30,7 @@
 using android::Parcel;
 using android::status_t;
 using android::UNEXPECTED_NULL;
+using namespace ::android::binder;
 
 namespace android {
 
diff --git a/libs/binder/MemoryBase.cpp b/libs/binder/MemoryBase.cpp
index 32300df..033066b 100644
--- a/libs/binder/MemoryBase.cpp
+++ b/libs/binder/MemoryBase.cpp
@@ -43,4 +43,4 @@
 }
 
 // ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
index ebf91f9..eacad3b 100644
--- a/libs/binder/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -481,4 +481,4 @@
 }
 
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index e4ea60f..4c300b4 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -181,4 +181,4 @@
 }
 
 // ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 9be06cd..11441ec 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -35,9 +35,9 @@
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
 #include <binder/ProcessState.h>
-#include <binder/Stability.h>
 #include <binder/Status.h>
 #include <binder/TextOutput.h>
+#include <binder/Value.h>
 
 #include <cutils/ashmem.h>
 #include <utils/Debug.h>
@@ -48,7 +48,11 @@
 #include <utils/String16.h>
 
 #include <private/binder/binder_module.h>
-#include "Static.h"
+#include <private/binder/Static.h>
+
+#ifndef INT32_MAX
+#define INT32_MAX ((int32_t)(2147483647))
+#endif
 
 #define LOG_REFS(...)
 //#define LOG_REFS(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
@@ -63,8 +67,8 @@
 #define PAD_SIZE_UNSAFE(s) (((s)+3)&~3)
 
 static size_t pad_size(size_t s) {
-    if (s > (std::numeric_limits<size_t>::max() - 3)) {
-        LOG_ALWAYS_FATAL("pad size too big %zu", s);
+    if (s > (SIZE_T_MAX - 3)) {
+        abort();
     }
     return PAD_SIZE_UNSAFE(s);
 }
@@ -74,9 +78,6 @@
 
 namespace android {
 
-// many things compile this into prebuilts on the stack
-static_assert(sizeof(Parcel) == 60 || sizeof(Parcel) == 120);
-
 static pthread_mutex_t gParcelGlobalAllocSizeLock = PTHREAD_MUTEX_INITIALIZER;
 static size_t gParcelGlobalAllocSize = 0;
 static size_t gParcelGlobalAllocCount = 0;
@@ -92,7 +93,7 @@
     BLOB_ASHMEM_MUTABLE = 2,
 };
 
-static void acquire_object(const sp<ProcessState>& proc,
+void acquire_object(const sp<ProcessState>& proc,
     const flat_binder_object& obj, const void* who, size_t* outAshmemSize)
 {
     switch (obj.hdr.type) {
@@ -102,6 +103,10 @@
                 reinterpret_cast<IBinder*>(obj.cookie)->incStrong(who);
             }
             return;
+        case BINDER_TYPE_WEAK_BINDER:
+            if (obj.binder)
+                reinterpret_cast<RefBase::weakref_type*>(obj.binder)->incWeak(who);
+            return;
         case BINDER_TYPE_HANDLE: {
             const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle);
             if (b != nullptr) {
@@ -110,6 +115,11 @@
             }
             return;
         }
+        case BINDER_TYPE_WEAK_HANDLE: {
+            const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle);
+            if (b != nullptr) b.get_refs()->incWeak(who);
+            return;
+        }
         case BINDER_TYPE_FD: {
             if ((obj.cookie != 0) && (outAshmemSize != nullptr) && ashmem_valid(obj.handle)) {
                 // If we own an ashmem fd, keep track of how much memory it refers to.
@@ -125,6 +135,12 @@
     ALOGD("Invalid object type 0x%08x", obj.hdr.type);
 }
 
+void acquire_object(const sp<ProcessState>& proc,
+    const flat_binder_object& obj, const void* who)
+{
+    acquire_object(proc, obj, who, nullptr);
+}
+
 static void release_object(const sp<ProcessState>& proc,
     const flat_binder_object& obj, const void* who, size_t* outAshmemSize)
 {
@@ -135,6 +151,10 @@
                 reinterpret_cast<IBinder*>(obj.cookie)->decStrong(who);
             }
             return;
+        case BINDER_TYPE_WEAK_BINDER:
+            if (obj.binder)
+                reinterpret_cast<RefBase::weakref_type*>(obj.binder)->decWeak(who);
+            return;
         case BINDER_TYPE_HANDLE: {
             const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle);
             if (b != nullptr) {
@@ -143,6 +163,11 @@
             }
             return;
         }
+        case BINDER_TYPE_WEAK_HANDLE: {
+            const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle);
+            if (b != nullptr) b.get_refs()->decWeak(who);
+            return;
+        }
         case BINDER_TYPE_FD: {
             if (obj.cookie != 0) { // owned
                 if ((outAshmemSize != nullptr) && ashmem_valid(obj.handle)) {
@@ -164,31 +189,20 @@
     ALOGE("Invalid object type 0x%08x", obj.hdr.type);
 }
 
-status_t Parcel::finishFlattenBinder(
-    const sp<IBinder>& binder, const flat_binder_object& flat)
+void release_object(const sp<ProcessState>& proc,
+    const flat_binder_object& obj, const void* who)
 {
-    status_t status = writeObject(flat, false);
-    if (status != OK) return status;
-
-    internal::Stability::tryMarkCompilationUnit(binder.get());
-    return writeInt32(internal::Stability::get(binder.get()));
+    release_object(proc, obj, who, nullptr);
 }
 
-status_t Parcel::finishUnflattenBinder(
-    const sp<IBinder>& binder, sp<IBinder>* out) const
+inline static status_t finish_flatten_binder(
+    const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out)
 {
-    int32_t stability;
-    status_t status = readInt32(&stability);
-    if (status != OK) return status;
-
-    status = internal::Stability::set(binder.get(), stability, true /*log*/);
-    if (status != OK) return status;
-
-    *out = binder;
-    return OK;
+    return out->writeObject(flat, false);
 }
 
-status_t Parcel::flattenBinder(const sp<IBinder>& binder)
+status_t flatten_binder(const sp<ProcessState>& /*proc*/,
+    const sp<IBinder>& binder, Parcel* out)
 {
     flat_binder_object obj;
 
@@ -226,24 +240,108 @@
         obj.cookie = 0;
     }
 
-    return finishFlattenBinder(binder, obj);
+    return finish_flatten_binder(binder, obj, out);
 }
 
-status_t Parcel::unflattenBinder(sp<IBinder>* out) const
+status_t flatten_binder(const sp<ProcessState>& /*proc*/,
+    const wp<IBinder>& binder, Parcel* out)
 {
-    const flat_binder_object* flat = readObject(false);
+    flat_binder_object obj;
+
+    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+    if (binder != nullptr) {
+        sp<IBinder> real = binder.promote();
+        if (real != nullptr) {
+            IBinder *local = real->localBinder();
+            if (!local) {
+                BpBinder *proxy = real->remoteBinder();
+                if (proxy == nullptr) {
+                    ALOGE("null proxy");
+                }
+                const int32_t handle = proxy ? proxy->handle() : 0;
+                obj.hdr.type = BINDER_TYPE_WEAK_HANDLE;
+                obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
+                obj.handle = handle;
+                obj.cookie = 0;
+            } else {
+                obj.hdr.type = BINDER_TYPE_WEAK_BINDER;
+                obj.binder = reinterpret_cast<uintptr_t>(binder.get_refs());
+                obj.cookie = reinterpret_cast<uintptr_t>(binder.unsafe_get());
+            }
+            return finish_flatten_binder(real, obj, out);
+        }
+
+        // XXX How to deal?  In order to flatten the given binder,
+        // we need to probe it for information, which requires a primary
+        // reference...  but we don't have one.
+        //
+        // The OpenBinder implementation uses a dynamic_cast<> here,
+        // but we can't do that with the different reference counting
+        // implementation we are using.
+        ALOGE("Unable to unflatten Binder weak reference!");
+        obj.hdr.type = BINDER_TYPE_BINDER;
+        obj.binder = 0;
+        obj.cookie = 0;
+        return finish_flatten_binder(nullptr, obj, out);
+
+    } else {
+        obj.hdr.type = BINDER_TYPE_BINDER;
+        obj.binder = 0;
+        obj.cookie = 0;
+        return finish_flatten_binder(nullptr, obj, out);
+    }
+}
+
+inline static status_t finish_unflatten_binder(
+    BpBinder* /*proxy*/, const flat_binder_object& /*flat*/,
+    const Parcel& /*in*/)
+{
+    return NO_ERROR;
+}
+
+status_t unflatten_binder(const sp<ProcessState>& proc,
+    const Parcel& in, sp<IBinder>* out)
+{
+    const flat_binder_object* flat = in.readObject(false);
 
     if (flat) {
         switch (flat->hdr.type) {
-            case BINDER_TYPE_BINDER: {
-                sp<IBinder> binder = reinterpret_cast<IBinder*>(flat->cookie);
-                return finishUnflattenBinder(binder, out);
-            }
-            case BINDER_TYPE_HANDLE: {
-                sp<IBinder> binder =
-                    ProcessState::self()->getStrongProxyForHandle(flat->handle);
-                return finishUnflattenBinder(binder, out);
-            }
+            case BINDER_TYPE_BINDER:
+                *out = reinterpret_cast<IBinder*>(flat->cookie);
+                return finish_unflatten_binder(nullptr, *flat, in);
+            case BINDER_TYPE_HANDLE:
+                *out = proc->getStrongProxyForHandle(flat->handle);
+                return finish_unflatten_binder(
+                    static_cast<BpBinder*>(out->get()), *flat, in);
+        }
+    }
+    return BAD_TYPE;
+}
+
+status_t unflatten_binder(const sp<ProcessState>& proc,
+    const Parcel& in, wp<IBinder>* out)
+{
+    const flat_binder_object* flat = in.readObject(false);
+
+    if (flat) {
+        switch (flat->hdr.type) {
+            case BINDER_TYPE_BINDER:
+                *out = reinterpret_cast<IBinder*>(flat->cookie);
+                return finish_unflatten_binder(nullptr, *flat, in);
+            case BINDER_TYPE_WEAK_BINDER:
+                if (flat->binder != 0) {
+                    out->set_object_and_refs(
+                        reinterpret_cast<IBinder*>(flat->cookie),
+                        reinterpret_cast<RefBase::weakref_type*>(flat->binder));
+                } else {
+                    *out = nullptr;
+                }
+                return finish_unflatten_binder(nullptr, *flat, in);
+            case BINDER_TYPE_HANDLE:
+            case BINDER_TYPE_WEAK_HANDLE:
+                *out = proc->getWeakProxyForHandle(flat->handle);
+                return finish_unflatten_binder(
+                    static_cast<BpBinder*>(out->unsafe_get()), *flat, in);
         }
     }
     return BAD_TYPE;
@@ -291,7 +389,7 @@
 {
     size_t result = dataSize() - dataPosition();
     if (result > INT32_MAX) {
-        LOG_ALWAYS_FATAL("result too big: %zu", result);
+        abort();
     }
     return result;
 }
@@ -328,7 +426,7 @@
     if (pos > INT32_MAX) {
         // don't accept size_t values which may have come from an
         // inadvertent conversion from a negative int.
-        LOG_ALWAYS_FATAL("pos too big: %zu", pos);
+        abort();
     }
 
     mDataPos = pos;
@@ -422,8 +520,10 @@
         const sp<ProcessState> proc(ProcessState::self());
         // grow objects
         if (mObjectsCapacity < mObjectsSize + numObjects) {
+            if ((size_t) numObjects > SIZE_MAX - mObjectsSize) return NO_MEMORY; // overflow
+            if (mObjectsSize + numObjects > SIZE_MAX / 3) return NO_MEMORY; // overflow
             size_t newSize = ((mObjectsSize + numObjects)*3)/2;
-            if (newSize*sizeof(binder_size_t) < mObjectsSize) return NO_MEMORY;   // overflow
+            if (newSize > SIZE_MAX / sizeof(binder_size_t)) return NO_MEMORY; // overflow
             binder_size_t *objects =
                 (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
             if (objects == (binder_size_t*)nullptr) {
@@ -505,12 +605,6 @@
     }
 }
 
-#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
-constexpr int32_t kHeader = B_PACK_CHARS('V', 'N', 'D', 'R');
-#else
-constexpr int32_t kHeader = B_PACK_CHARS('S', 'Y', 'S', 'T');
-#endif
-
 // Write RPC headers.  (previously just the interface token)
 status_t Parcel::writeInterfaceToken(const String16& interface)
 {
@@ -519,7 +613,6 @@
     updateWorkSourceRequestHeaderPosition();
     writeInt32(threadState->shouldPropagateWorkSource() ?
             threadState->getCallingWorkSourceUid() : IPCThreadState::kUnsetWorkSource);
-    writeInt32(kHeader);
     // currently the interface identification token is just its name as a string
     return writeString16(interface);
 }
@@ -537,7 +630,7 @@
     return err == NO_ERROR;
 }
 
-uid_t Parcel::readCallingWorkSourceUid() const
+uid_t Parcel::readCallingWorkSourceUid()
 {
     if (!mRequestHeaderPresent) {
         return IPCThreadState::kUnsetWorkSource;
@@ -577,12 +670,6 @@
     updateWorkSourceRequestHeaderPosition();
     int32_t workSource = readInt32();
     threadState->setCallingWorkSourceUidWithoutPropagation(workSource);
-    // vendor header
-    int32_t header = readInt32();
-    if (header != kHeader) {
-        ALOGE("Expecting header 0x%x but found 0x%x. Mixing copies of libbinder?", kHeader, header);
-        return false;
-    }
     // Interface descriptor.
     const String16 str(readString16());
     if (str == interface) {
@@ -594,6 +681,11 @@
     }
 }
 
+const binder_size_t* Parcel::objects() const
+{
+    return mObjects;
+}
+
 size_t Parcel::objectsCount() const
 {
     return mObjectsSize;
@@ -746,37 +838,61 @@
   return writeUtf8AsUtf16(*str);
 }
 
-status_t Parcel::writeByteVectorInternal(const int8_t* data, size_t size) {
-    if (size > std::numeric_limits<int32_t>::max()) {
-        return BAD_VALUE;
+namespace {
+
+template<typename T>
+status_t writeByteVectorInternal(Parcel* parcel, const std::vector<T>& val)
+{
+    status_t status;
+    if (val.size() > std::numeric_limits<int32_t>::max()) {
+        status = BAD_VALUE;
+        return status;
     }
 
-    status_t status = writeInt32(size);
+    status = parcel->writeInt32(val.size());
     if (status != OK) {
         return status;
     }
 
-    return write(data, size);
+    void* data = parcel->writeInplace(val.size());
+    if (!data) {
+        status = BAD_VALUE;
+        return status;
+    }
+
+    memcpy(data, val.data(), val.size());
+    return status;
 }
 
+template<typename T>
+status_t writeByteVectorInternalPtr(Parcel* parcel,
+                                    const std::unique_ptr<std::vector<T>>& val)
+{
+    if (!val) {
+        return parcel->writeInt32(-1);
+    }
+
+    return writeByteVectorInternal(parcel, *val);
+}
+
+}  // namespace
+
 status_t Parcel::writeByteVector(const std::vector<int8_t>& val) {
-    return writeByteVectorInternal(val.data(), val.size());
+    return writeByteVectorInternal(this, val);
 }
 
 status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val)
 {
-    if (!val) return writeInt32(-1);
-    return writeByteVectorInternal(val->data(), val->size());
+    return writeByteVectorInternalPtr(this, val);
 }
 
 status_t Parcel::writeByteVector(const std::vector<uint8_t>& val) {
-    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());
+    return writeByteVectorInternal(this, val);
 }
 
 status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val)
 {
-    if (!val) return writeInt32(-1);
-    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
+    return writeByteVectorInternalPtr(this, val);
 }
 
 status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val)
@@ -1019,7 +1135,7 @@
 
 status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
 {
-    return flattenBinder(val);
+    return flatten_binder(ProcessState::self(), val, this);
 }
 
 status_t Parcel::writeStrongBinderVector(const std::vector<sp<IBinder>>& val)
@@ -1040,6 +1156,11 @@
     return readTypedVector(val, &Parcel::readStrongBinder);
 }
 
+status_t Parcel::writeWeakBinder(const wp<IBinder>& val)
+{
+    return flatten_binder(ProcessState::self(), val, this);
+}
+
 status_t Parcel::writeRawNullableParcelable(const Parcelable* parcelable) {
     if (!parcelable) {
         return writeInt32(0);
@@ -1056,6 +1177,10 @@
     return parcelable.writeToParcel(this);
 }
 
+status_t Parcel::writeValue(const binder::Value& value) {
+    return value.writeToParcel(this);
+}
+
 status_t Parcel::writeNativeHandle(const native_handle* handle)
 {
     if (!handle || handle->version != sizeof(native_handle))
@@ -1276,8 +1401,10 @@
         if (err != NO_ERROR) return err;
     }
     if (!enoughObjects) {
+        if (mObjectsSize > SIZE_MAX - 2) return NO_MEMORY; // overflow
+        if ((mObjectsSize + 2) > SIZE_MAX / 3) return NO_MEMORY; // overflow
         size_t newSize = ((mObjectsSize+2)*3)/2;
-        if (newSize*sizeof(binder_size_t) < mObjectsSize) return NO_MEMORY;   // overflow
+        if (newSize > SIZE_MAX / sizeof(binder_size_t)) return NO_MEMORY; // overflow
         binder_size_t* objects = (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
         if (objects == nullptr) return NO_MEMORY;
         mObjects = objects;
@@ -1293,6 +1420,125 @@
     return status.writeToParcel(this);
 }
 
+status_t Parcel::writeMap(const ::android::binder::Map& map_in)
+{
+    using ::std::map;
+    using ::android::binder::Value;
+    using ::android::binder::Map;
+
+    Map::const_iterator iter;
+    status_t ret;
+
+    ret = writeInt32(map_in.size());
+
+    if (ret != NO_ERROR) {
+        return ret;
+    }
+
+    for (iter = map_in.begin(); iter != map_in.end(); ++iter) {
+        ret = writeValue(Value(iter->first));
+        if (ret != NO_ERROR) {
+            return ret;
+        }
+
+        ret = writeValue(iter->second);
+        if (ret != NO_ERROR) {
+            return ret;
+        }
+    }
+
+    return ret;
+}
+
+status_t Parcel::writeNullableMap(const std::unique_ptr<binder::Map>& map)
+{
+    if (map == nullptr) {
+        return writeInt32(-1);
+    }
+
+    return writeMap(*map.get());
+}
+
+status_t Parcel::readMap(::android::binder::Map* map_out)const
+{
+    using ::std::map;
+    using ::android::String16;
+    using ::android::String8;
+    using ::android::binder::Value;
+    using ::android::binder::Map;
+
+    status_t ret = NO_ERROR;
+    int32_t count;
+
+    ret = readInt32(&count);
+    if (ret != NO_ERROR) {
+        return ret;
+    }
+
+    if (count < 0) {
+        ALOGE("readMap: Unexpected count: %d", count);
+        return (count == -1)
+            ? UNEXPECTED_NULL
+            : BAD_VALUE;
+    }
+
+    map_out->clear();
+
+    while (count--) {
+        Map::key_type key;
+        Value value;
+
+        ret = readValue(&value);
+        if (ret != NO_ERROR) {
+            return ret;
+        }
+
+        if (!value.getString(&key)) {
+            ALOGE("readMap: Key type not a string (parcelType = %d)", value.parcelType());
+            return BAD_VALUE;
+        }
+
+        ret = readValue(&value);
+        if (ret != NO_ERROR) {
+            return ret;
+        }
+
+        (*map_out)[key] = value;
+    }
+
+    return ret;
+}
+
+status_t Parcel::readNullableMap(std::unique_ptr<binder::Map>* map) const
+{
+    const size_t start = dataPosition();
+    int32_t count;
+    status_t status = readInt32(&count);
+    map->reset();
+
+    if (status != OK || count == -1) {
+        return status;
+    }
+
+    setDataPosition(start);
+    map->reset(new binder::Map());
+
+    status = readMap(map->get());
+
+    if (status != OK) {
+        map->reset();
+    }
+
+    return status;
+}
+
+
+
+void Parcel::remove(size_t /*start*/, size_t /*amt*/)
+{
+    LOG_ALWAYS_FATAL("Parcel::remove() not yet implemented!");
+}
+
 status_t Parcel::validateReadData(size_t upperBound) const
 {
     // Don't allow non-object reads on object data
@@ -1449,38 +1695,81 @@
     return err;
 }
 
+namespace {
+
+template<typename T>
+status_t readByteVectorInternal(const Parcel* parcel,
+                                std::vector<T>* val) {
+    val->clear();
+
+    int32_t size;
+    status_t status = parcel->readInt32(&size);
+
+    if (status != OK) {
+        return status;
+    }
+
+    if (size < 0) {
+        status = UNEXPECTED_NULL;
+        return status;
+    }
+    if (size_t(size) > parcel->dataAvail()) {
+        status = BAD_VALUE;
+        return status;
+    }
+
+    T* data = const_cast<T*>(reinterpret_cast<const T*>(parcel->readInplace(size)));
+    if (!data) {
+        status = BAD_VALUE;
+        return status;
+    }
+    val->reserve(size);
+    val->insert(val->end(), data, data + size);
+
+    return status;
+}
+
+template<typename T>
+status_t readByteVectorInternalPtr(
+        const Parcel* parcel,
+        std::unique_ptr<std::vector<T>>* val) {
+    const int32_t start = parcel->dataPosition();
+    int32_t size;
+    status_t status = parcel->readInt32(&size);
+    val->reset();
+
+    if (status != OK || size < 0) {
+        return status;
+    }
+
+    parcel->setDataPosition(start);
+    val->reset(new (std::nothrow) std::vector<T>());
+
+    status = readByteVectorInternal(parcel, val->get());
+
+    if (status != OK) {
+        val->reset();
+    }
+
+    return status;
+}
+
+}  // namespace
+
 status_t Parcel::readByteVector(std::vector<int8_t>* val) const {
-    size_t size;
-    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
-    return readByteVectorInternal(val, size);
+    return readByteVectorInternal(this, val);
 }
 
 status_t Parcel::readByteVector(std::vector<uint8_t>* val) const {
-    size_t size;
-    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
-    return readByteVectorInternal(val, size);
+    return readByteVectorInternal(this, val);
 }
 
 status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const {
-    size_t size;
-    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
-    if (val->get() == nullptr) {
-        // reserveOutVector does not create the out vector if size is < 0.
-        // This occurs when writing a null byte vector.
-        return OK;
-    }
-    return readByteVectorInternal(val->get(), size);
+    return readByteVectorInternalPtr(this, val);
 }
 
 status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const {
-    size_t size;
-    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
-    if (val->get() == nullptr) {
-        // reserveOutVector does not create the out vector if size is < 0.
-        // This occurs when writing a null byte vector.
-        return OK;
-    }
-    return readByteVectorInternal(val->get(), size);
+    return readByteVectorInternalPtr(this, val);
 }
 
 status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const {
@@ -1922,7 +2211,7 @@
 
 status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
 {
-    return unflattenBinder(val);
+    return unflatten_binder(ProcessState::self(), *this, val);
 }
 
 sp<IBinder> Parcel::readStrongBinder() const
@@ -1935,6 +2224,13 @@
     return val;
 }
 
+wp<IBinder> Parcel::readWeakBinder() const
+{
+    wp<IBinder> val;
+    unflatten_binder(ProcessState::self(), *this, &val);
+    return val;
+}
+
 status_t Parcel::readParcelable(Parcelable* parcelable) const {
     int32_t have_parcelable = 0;
     status_t status = readInt32(&have_parcelable);
@@ -1947,6 +2243,10 @@
     return parcelable->readFromParcel(this);
 }
 
+status_t Parcel::readValue(binder::Value* value) const {
+    return value->readFromParcel(this);
+}
+
 int32_t Parcel::readExceptionCode() const
 {
     binder::Status status;
@@ -2298,7 +2598,7 @@
     } else if (dataSize() > 0) {
         const uint8_t* DATA = data();
         to << indent << HexDump(DATA, dataSize()) << dedent;
-        const binder_size_t* OBJS = mObjects;
+        const binder_size_t* OBJS = objects();
         const size_t N = objectsCount();
         for (size_t i=0; i<N; i++) {
             const flat_binder_object* flat
@@ -2389,6 +2689,8 @@
         return BAD_VALUE;
     }
 
+    if (len > SIZE_MAX - mDataSize) return NO_MEMORY; // overflow
+    if (mDataSize + len > SIZE_MAX / 3) return NO_MEMORY; // overflow
     size_t newSize = ((mDataSize+len)*3)/2;
     return (newSize <= mDataSize)
             ? (status_t) NO_MEMORY
@@ -2543,11 +2845,13 @@
             if (objectsSize == 0) {
                 free(mObjects);
                 mObjects = nullptr;
+                mObjectsCapacity = 0;
             } else {
                 binder_size_t* objects =
                     (binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t));
                 if (objects) {
                     mObjects = objects;
+                    mObjectsCapacity = objectsSize;
                 }
             }
             mObjectsSize = objectsSize;
@@ -2706,4 +3010,4 @@
     mMutable = false;
 }
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/PermissionCache.cpp b/libs/binder/PermissionCache.cpp
index 75a6d22..a4c28ad 100644
--- a/libs/binder/PermissionCache.cpp
+++ b/libs/binder/PermissionCache.cpp
@@ -110,4 +110,4 @@
 }
 
 // ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/PermissionController.cpp b/libs/binder/PermissionController.cpp
index 0c89245..34b2ca5 100644
--- a/libs/binder/PermissionController.cpp
+++ b/libs/binder/PermissionController.cpp
@@ -85,4 +85,4 @@
     return service != nullptr ? service->getPackageUid(package, flags) : -1;
 }
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index 97a6c94..c0aec0a 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "PersistableBundle"
 
 #include <binder/PersistableBundle.h>
+#include <private/binder/ParcelValTypes.h>
 
 #include <limits>
 
@@ -25,8 +26,6 @@
 #include <log/log.h>
 #include <utils/Errors.h>
 
-#include "ParcelValTypes.h"
-
 using android::BAD_TYPE;
 using android::BAD_VALUE;
 using android::NO_ERROR;
diff --git a/libs/binder/ProcessInfoService.cpp b/libs/binder/ProcessInfoService.cpp
index 00d6eef..5cb2033 100644
--- a/libs/binder/ProcessInfoService.cpp
+++ b/libs/binder/ProcessInfoService.cpp
@@ -101,4 +101,4 @@
 
 ANDROID_SINGLETON_STATIC_INSTANCE(ProcessInfoService);
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index ea61dc5..63f49dd 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -21,14 +21,14 @@
 #include <binder/BpBinder.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
-#include <binder/Stability.h>
 #include <cutils/atomic.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
+#include <utils/String8.h>
 #include <utils/threads.h>
 
 #include <private/binder/binder_module.h>
-#include "Static.h"
+#include <private/binder/Static.h>
 
 #include <errno.h>
 #include <fcntl.h>
@@ -108,15 +108,56 @@
     return gProcess;
 }
 
+void ProcessState::setContextObject(const sp<IBinder>& object)
+{
+    setContextObject(object, String16("default"));
+}
+
 sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
 {
-    sp<IBinder> context = getStrongProxyForHandle(0);
+    return getStrongProxyForHandle(0);
+}
 
-    // The root object is special since we get it directly from the driver, it is never
-    // written by Parcell::writeStrongBinder.
-    internal::Stability::tryMarkCompilationUnit(context.get());
+void ProcessState::setContextObject(const sp<IBinder>& object, const String16& name)
+{
+    AutoMutex _l(mLock);
+    mContexts.add(name, object);
+}
 
-    return context;
+sp<IBinder> ProcessState::getContextObject(const String16& name, const sp<IBinder>& caller)
+{
+    mLock.lock();
+    sp<IBinder> object(
+        mContexts.indexOfKey(name) >= 0 ? mContexts.valueFor(name) : nullptr);
+    mLock.unlock();
+    
+    //printf("Getting context object %s for %p\n", String8(name).string(), caller.get());
+    
+    if (object != nullptr) return object;
+
+    // Don't attempt to retrieve contexts if we manage them
+    if (mManagesContexts) {
+        ALOGE("getContextObject(%s) failed, but we manage the contexts!\n",
+            String8(name).string());
+        return nullptr;
+    }
+    
+    IPCThreadState* ipc = IPCThreadState::self();
+    {
+        Parcel data, reply;
+        // no interface token on this magic transaction
+        data.writeString16(name);
+        data.writeStrongBinder(caller);
+        status_t result = ipc->transact(0 /*magic*/, 0, data, &reply, 0);
+        if (result == NO_ERROR) {
+            object = reply.readStrongBinder();
+        }
+    }
+    
+    ipc->flushCommands();
+    
+    if (object != nullptr) setContextObject(object, name);
+    return object;
 }
 
 void ProcessState::startThreadPool()
@@ -128,33 +169,41 @@
     }
 }
 
+bool ProcessState::isContextManager(void) const
+{
+    return mManagesContexts;
+}
+
 bool ProcessState::becomeContextManager(context_check_func checkFunc, void* userData)
 {
-    AutoMutex _l(mLock);
-    mBinderContextCheckFunc = checkFunc;
-    mBinderContextUserData = userData;
+    if (!mManagesContexts) {
+        AutoMutex _l(mLock);
+        mBinderContextCheckFunc = checkFunc;
+        mBinderContextUserData = userData;
 
-    flat_binder_object obj {
-        .flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
-    };
+        flat_binder_object obj {
+            .flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
+        };
 
-    int result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR_EXT, &obj);
+        status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR_EXT, &obj);
 
-    // fallback to original method
-    if (result != 0) {
-        android_errorWriteLog(0x534e4554, "121035042");
+        // fallback to original method
+        if (result != 0) {
+            android_errorWriteLog(0x534e4554, "121035042");
 
-        int dummy = 0;
-        result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
+            int dummy = 0;
+            result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
+        }
+
+        if (result == 0) {
+            mManagesContexts = true;
+        } else if (result == -1) {
+            mBinderContextCheckFunc = nullptr;
+            mBinderContextUserData = nullptr;
+            ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
+        }
     }
-
-    if (result == -1) {
-        mBinderContextCheckFunc = nullptr;
-        mBinderContextUserData = nullptr;
-        ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
-    }
-
-    return result == 0;
+    return mManagesContexts;
 }
 
 // Get references to userspace objects held by the kernel binder driver
@@ -188,33 +237,8 @@
     return count;
 }
 
-// Queries the driver for the current strong reference count of the node
-// that the handle points to. Can only be used by the servicemanager.
-//
-// Returns -1 in case of failure, otherwise the strong reference count.
-ssize_t ProcessState::getStrongRefCountForNodeByHandle(int32_t handle) {
-    binder_node_info_for_ref info;
-    memset(&info, 0, sizeof(binder_node_info_for_ref));
-
-    info.handle = handle;
-
-    status_t result = ioctl(mDriverFD, BINDER_GET_NODE_INFO_FOR_REF, &info);
-
-    if (result != OK) {
-        static bool logged = false;
-        if (!logged) {
-          ALOGW("Kernel does not support BINDER_GET_NODE_INFO_FOR_REF.");
-          logged = true;
-        }
-        return -1;
-    }
-
-    return info.strong_count;
-}
-
 void ProcessState::setCallRestriction(CallRestriction restriction) {
-    LOG_ALWAYS_FATAL_IF(IPCThreadState::selfOrNull() != nullptr,
-        "Call restrictions must be set before the threadpool is started.");
+    LOG_ALWAYS_FATAL_IF(IPCThreadState::selfOrNull(), "Call restrictions must be set before the threadpool is started.");
 
     mCallRestriction = restriction;
 }
@@ -242,12 +266,8 @@
 
     if (e != nullptr) {
         // We need to create a new BpBinder if there isn't currently one, OR we
-        // are unable to acquire a weak reference on this current one.  The
-        // attemptIncWeak() is safe because we know the BpBinder destructor will always
-        // call expungeHandle(), which acquires the same lock we are holding now.
-        // We need to do this because there is a race condition between someone
-        // releasing a reference on this BpBinder, and a new reference on its handle
-        // arriving from the driver.
+        // are unable to acquire a weak reference on this current one.  See comment
+        // in getWeakProxyForHandle() for more info about this.
         IBinder* b = e->binder;
         if (b == nullptr || !e->refs->attemptIncWeak(this)) {
             if (handle == 0) {
@@ -293,6 +313,37 @@
     return result;
 }
 
+wp<IBinder> ProcessState::getWeakProxyForHandle(int32_t handle)
+{
+    wp<IBinder> result;
+
+    AutoMutex _l(mLock);
+
+    handle_entry* e = lookupHandleLocked(handle);
+
+    if (e != nullptr) {        
+        // We need to create a new BpBinder if there isn't currently one, OR we
+        // are unable to acquire a weak reference on this current one.  The
+        // attemptIncWeak() is safe because we know the BpBinder destructor will always
+        // call expungeHandle(), which acquires the same lock we are holding now.
+        // We need to do this because there is a race condition between someone
+        // releasing a reference on this BpBinder, and a new reference on its handle
+        // arriving from the driver.
+        IBinder* b = e->binder;
+        if (b == nullptr || !e->refs->attemptIncWeak(this)) {
+            b = BpBinder::create(handle);
+            result = b;
+            e->binder = b;
+            if (b) e->refs = b->getWeakRefs();
+        } else {
+            result = b;
+            e->refs->decWeak(this);
+        }
+    }
+
+    return result;
+}
+
 void ProcessState::expungeHandle(int32_t handle, IBinder* binder)
 {
     AutoMutex _l(mLock);
@@ -379,6 +430,7 @@
     , mExecutingThreadsCount(0)
     , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
     , mStarvationStartTimeMs(0)
+    , mManagesContexts(false)
     , mBinderContextCheckFunc(nullptr)
     , mBinderContextUserData(nullptr)
     , mThreadPoolStarted(false)
@@ -397,7 +449,7 @@
         }
     }
 
-    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver '%s' could not be opened.  Terminating.", driver);
+    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
 }
 
 ProcessState::~ProcessState()
@@ -411,4 +463,4 @@
     mDriverFD = -1;
 }
         
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/Stability.cpp b/libs/binder/Stability.cpp
deleted file mode 100644
index 7ce5e36..0000000
--- a/libs/binder/Stability.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <binder/Stability.h>
-
-namespace android {
-namespace internal {
-
-void Stability::markCompilationUnit(IBinder* binder) {
-    status_t result = set(binder, kLocalStability, true /*log*/);
-    LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
-}
-
-void Stability::markVintf(IBinder* binder) {
-    status_t result = set(binder, Level::VINTF, true /*log*/);
-    LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
-}
-
-void Stability::debugLogStability(const std::string& tag, const sp<IBinder>& binder) {
-    ALOGE("%s: stability is %s", tag.c_str(), stabilityString(get(binder.get())).c_str());
-}
-
-void Stability::markVndk(IBinder* binder) {
-    status_t result = set(binder, Level::VENDOR, true /*log*/);
-    LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
-}
-
-bool Stability::requiresVintfDeclaration(const sp<IBinder>& binder) {
-    return check(get(binder.get()), Level::VINTF);
-}
-
-void Stability::tryMarkCompilationUnit(IBinder* binder) {
-    (void) set(binder, kLocalStability, false /*log*/);
-}
-
-status_t Stability::set(IBinder* binder, int32_t stability, bool log) {
-    Level currentStability = get(binder);
-
-    // null binder is always written w/ 'UNDECLARED' stability
-    if (binder == nullptr) {
-        if (stability == UNDECLARED) {
-            return OK;
-        } else {
-            if (log) {
-                ALOGE("Null binder written with stability %s.",
-                    stabilityString(stability).c_str());
-            }
-            return BAD_TYPE;
-        }
-    }
-
-    if (!isDeclaredStability(stability)) {
-        if (log) {
-            ALOGE("Can only set known stability, not %d.", stability);
-        }
-        return BAD_TYPE;
-    }
-
-    if (currentStability != Level::UNDECLARED && currentStability != stability) {
-        if (log) {
-            ALOGE("Interface being set with %s but it is already marked as %s.",
-                stabilityString(stability).c_str(), stabilityString(currentStability).c_str());
-        }
-        return BAD_TYPE;
-    }
-
-    if (currentStability == stability) return OK;
-
-    binder->attachObject(
-        reinterpret_cast<void*>(&Stability::get),
-        reinterpret_cast<void*>(stability),
-        nullptr /*cleanupCookie*/,
-        nullptr /*cleanup function*/);
-
-    return OK;
-}
-
-Stability::Level Stability::get(IBinder* binder) {
-    if (binder == nullptr) return UNDECLARED;
-
-    return static_cast<Level>(reinterpret_cast<intptr_t>(
-        binder->findObject(reinterpret_cast<void*>(&Stability::get))));
-}
-
-bool Stability::check(int32_t provided, Level required) {
-    bool stable = (provided & required) == required;
-
-    if (!isDeclaredStability(provided) && provided != UNDECLARED) {
-        ALOGE("Unknown stability when checking interface stability %d.", provided);
-
-        stable = false;
-    }
-
-    return stable;
-}
-
-bool Stability::isDeclaredStability(int32_t stability) {
-    return stability == VENDOR || stability == SYSTEM || stability == VINTF;
-}
-
-std::string Stability::stabilityString(int32_t stability) {
-    switch (stability) {
-        case Level::UNDECLARED: return "undeclared stability";
-        case Level::VENDOR: return "vendor stability";
-        case Level::SYSTEM: return "system stability";
-        case Level::VINTF: return "vintf stability";
-    }
-    return "unknown stability " + std::to_string(stability);
-}
-
-}  // namespace internal
-}  // namespace stability
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
index bd40536..bd0e6f9 100644
--- a/libs/binder/Static.cpp
+++ b/libs/binder/Static.cpp
@@ -17,7 +17,7 @@
 // All static variables go here, to control initialization and
 // destruction order in the library.
 
-#include "Static.h"
+#include <private/binder/Static.h>
 
 #include <binder/BufferedTextOutput.h>
 #include <binder/IPCThreadState.h>
@@ -54,9 +54,7 @@
 protected:
     virtual status_t writeLines(const struct iovec& vec, size_t N)
     {
-        ssize_t ret = writev(mFD, &vec, N);
-        if (ret == -1) return -errno;
-        if (static_cast<size_t>(ret) != N) return UNKNOWN_ERROR;
+        writev(mFD, &vec, N);
         return NO_ERROR;
     }
 
@@ -77,4 +75,13 @@
 Mutex& gProcessMutex = *new Mutex;
 sp<ProcessState> gProcess;
 
+// ------------ IServiceManager.cpp
+
+Mutex gDefaultServiceManagerLock;
+sp<IServiceManager> gDefaultServiceManager;
+#ifndef __ANDROID_VNDK__
+sp<IPermissionController> gPermissionController;
+#endif
+bool gSystemBootCompleted = false;
+
 }   // namespace android
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
deleted file mode 100644
index b3afd81..0000000
--- a/libs/binder/TEST_MAPPING
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-  "presubmit": [
-    {
-      "name": "binderSafeInterfaceTest"
-    },
-    {
-      "name": "binderVendorDoubleLoadTest"
-    },
-    {
-      "name": "binderDriverInterfaceTest"
-    },
-    {
-      "name": "binderTextOutputTest"
-    },
-    {
-      "name": "binderLibTest"
-    },
-    {
-      "name": "binderStabilityTest"
-    },
-    {
-      "name": "CtsNdkBinderTestCases"
-    }
-  ]
-}
diff --git a/libs/binder/TextOutput.cpp b/libs/binder/TextOutput.cpp
index 684a7dc..101eba3 100644
--- a/libs/binder/TextOutput.cpp
+++ b/libs/binder/TextOutput.cpp
@@ -69,4 +69,4 @@
     return to;
 }
 
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/Value.cpp b/libs/binder/Value.cpp
new file mode 100644
index 0000000..19c57ba
--- /dev/null
+++ b/libs/binder/Value.cpp
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#define LOG_TAG "Value"
+
+#include <binder/Value.h>
+
+#include <limits>
+
+#include <binder/IBinder.h>
+#include <binder/Parcel.h>
+#include <binder/Map.h>
+#include <private/binder/ParcelValTypes.h>
+#include <log/log.h>
+#include <utils/Errors.h>
+
+using android::BAD_TYPE;
+using android::BAD_VALUE;
+using android::NO_ERROR;
+using android::UNEXPECTED_NULL;
+using android::Parcel;
+using android::sp;
+using android::status_t;
+using std::map;
+using std::set;
+using std::vector;
+using android::binder::Value;
+using android::IBinder;
+using android::os::PersistableBundle;
+using namespace android::binder;
+
+// ====================================================================
+
+#define RETURN_IF_FAILED(calledOnce)                                     \
+    do {                                                                 \
+        status_t returnStatus = calledOnce;                              \
+        if (returnStatus) {                                              \
+            ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
+            return returnStatus;                                         \
+         }                                                               \
+    } while(false)
+
+// ====================================================================
+
+/* These `internal_type_ptr()` functions allow this
+ * class to work without C++ RTTI support. This technique
+ * only works properly when called directly from this file,
+ * but that is OK because that is the only place we will
+ * be calling them from. */
+template<class T> const void* internal_type_ptr()
+{
+    static const T *marker;
+    return (void*)&marker;
+}
+
+/* Allows the type to be specified by the argument
+ * instead of inside angle brackets. */
+template<class T> const void* internal_type_ptr(const T&)
+{
+    return internal_type_ptr<T>();
+}
+
+// ====================================================================
+
+namespace android {
+
+namespace binder {
+
+class Value::ContentBase {
+public:
+    virtual ~ContentBase() = default;
+    virtual const void* type_ptr() const = 0;
+    virtual ContentBase * clone() const = 0;
+    virtual bool operator==(const ContentBase& rhs) const = 0;
+
+#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
+    virtual const std::type_info &type() const = 0;
+#endif
+
+    template<typename T> bool get(T* out) const;
+};
+
+/* This is the actual class that holds the value. */
+template<typename T> class Value::Content : public Value::ContentBase {
+public:
+    Content() = default;
+    explicit Content(const T & value) : mValue(value) { }
+
+    virtual ~Content() = default;
+
+#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
+    virtual const std::type_info &type() const override
+    {
+        return typeid(T);
+    }
+#endif
+
+    virtual const void* type_ptr() const override
+    {
+        return internal_type_ptr<T>();
+    }
+
+    virtual ContentBase * clone() const override
+    {
+        return new Content(mValue);
+    };
+
+    virtual bool operator==(const ContentBase& rhs) const override
+    {
+        if (type_ptr() != rhs.type_ptr()) {
+            return false;
+        }
+        return mValue == static_cast<const Content<T>* >(&rhs)->mValue;
+    }
+
+    T mValue;
+};
+
+template<typename T> bool Value::ContentBase::get(T* out) const
+{
+    if (internal_type_ptr(*out) != type_ptr())
+    {
+        return false;
+    }
+
+    *out = static_cast<const Content<T>*>(this)->mValue;
+
+    return true;
+}
+
+// ====================================================================
+
+Value::Value() : mContent(nullptr)
+{
+}
+
+Value::Value(const Value& value)
+    : mContent(value.mContent ? value.mContent->clone() : nullptr)
+{
+}
+
+Value::~Value()
+{
+    delete mContent;
+}
+
+bool Value::operator==(const Value& rhs) const
+{
+    const Value& lhs(*this);
+
+    if (lhs.empty() && rhs.empty()) {
+        return true;
+    }
+
+    if ( (lhs.mContent == nullptr)
+      || (rhs.mContent == nullptr)
+    ) {
+        return false;
+    }
+
+    return *lhs.mContent == *rhs.mContent;
+}
+
+Value& Value::swap(Value &rhs)
+{
+    std::swap(mContent, rhs.mContent);
+    return *this;
+}
+
+Value& Value::operator=(const Value& rhs)
+{
+    if (this != &rhs) {
+        delete mContent;
+        mContent = rhs.mContent
+            ? rhs.mContent->clone()
+            : nullptr;
+    }
+    return *this;
+}
+
+bool Value::empty() const
+{
+    return mContent == nullptr;
+}
+
+void Value::clear()
+{
+    delete mContent;
+    mContent = nullptr;
+}
+
+int32_t Value::parcelType() const
+{
+    const void* t_info(mContent ? mContent->type_ptr() : nullptr);
+
+    if (t_info == internal_type_ptr<bool>()) return VAL_BOOLEAN;
+    if (t_info == internal_type_ptr<uint8_t>()) return VAL_BYTE;
+    if (t_info == internal_type_ptr<int32_t>()) return VAL_INTEGER;
+    if (t_info == internal_type_ptr<int64_t>()) return VAL_LONG;
+    if (t_info == internal_type_ptr<double>()) return VAL_DOUBLE;
+    if (t_info == internal_type_ptr<String16>()) return VAL_STRING;
+
+    if (t_info == internal_type_ptr<vector<bool>>()) return VAL_BOOLEANARRAY;
+    if (t_info == internal_type_ptr<vector<uint8_t>>()) return VAL_BYTEARRAY;
+    if (t_info == internal_type_ptr<vector<int32_t>>()) return VAL_INTARRAY;
+    if (t_info == internal_type_ptr<vector<int64_t>>()) return VAL_LONGARRAY;
+    if (t_info == internal_type_ptr<vector<double>>()) return VAL_DOUBLEARRAY;
+    if (t_info == internal_type_ptr<vector<String16>>()) return VAL_STRINGARRAY;
+
+    if (t_info == internal_type_ptr<Map>()) return VAL_MAP;
+    if (t_info == internal_type_ptr<PersistableBundle>()) return VAL_PERSISTABLEBUNDLE;
+
+    return VAL_NULL;
+}
+
+#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
+const std::type_info& Value::type() const
+{
+    return mContent != nullptr
+        ? mContent->type()
+        : typeid(void);
+}
+#endif // ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
+
+#define DEF_TYPE_ACCESSORS(T, TYPENAME)                      \
+    bool Value::is ## TYPENAME() const                       \
+    {                                                        \
+        return mContent                                      \
+            ? internal_type_ptr<T>() == mContent->type_ptr() \
+            : false;                                         \
+    }                                                        \
+    bool Value::get ## TYPENAME(T* out) const                \
+    {                                                        \
+        return mContent                                      \
+            ? mContent->get(out)                             \
+            : false;                                         \
+    }                                                        \
+    void Value::put ## TYPENAME(const T& in)                 \
+    {                                                        \
+        *this = in;                                          \
+    }                                                        \
+    Value& Value::operator=(const T& rhs)                    \
+    {                                                        \
+        delete mContent;                                     \
+        mContent = new Content< T >(rhs);                    \
+        return *this;                                        \
+    }                                                        \
+    Value::Value(const T& value)                             \
+        : mContent(new Content< T >(value))                  \
+    { }
+
+DEF_TYPE_ACCESSORS(bool, Boolean)
+DEF_TYPE_ACCESSORS(int8_t, Byte)
+DEF_TYPE_ACCESSORS(int32_t, Int)
+DEF_TYPE_ACCESSORS(int64_t, Long)
+DEF_TYPE_ACCESSORS(double, Double)
+DEF_TYPE_ACCESSORS(String16, String)
+
+DEF_TYPE_ACCESSORS(std::vector<bool>, BooleanVector)
+DEF_TYPE_ACCESSORS(std::vector<uint8_t>, ByteVector)
+DEF_TYPE_ACCESSORS(std::vector<int32_t>, IntVector)
+DEF_TYPE_ACCESSORS(std::vector<int64_t>, LongVector)
+DEF_TYPE_ACCESSORS(std::vector<double>, DoubleVector)
+DEF_TYPE_ACCESSORS(std::vector<String16>, StringVector)
+
+DEF_TYPE_ACCESSORS(::android::binder::Map, Map)
+DEF_TYPE_ACCESSORS(PersistableBundle, PersistableBundle)
+
+bool Value::getString(String8* out) const
+{
+    String16 val;
+    bool ret = getString(&val);
+    if (ret) {
+        *out = String8(val);
+    }
+    return ret;
+}
+
+bool Value::getString(::std::string* out) const
+{
+    String8 val;
+    bool ret = getString(&val);
+    if (ret) {
+        *out = val.string();
+    }
+    return ret;
+}
+
+status_t Value::writeToParcel(Parcel* parcel) const
+{
+    // This implementation needs to be kept in sync with the writeValue
+    // implementation in frameworks/base/core/java/android/os/Parcel.java
+
+#define BEGIN_HANDLE_WRITE()                                                                      \
+    do {                                                                                          \
+        const void* t_info(mContent?mContent->type_ptr():nullptr);                                \
+        if (false) { }
+#define HANDLE_WRITE_TYPE(T, TYPEVAL, TYPEMETHOD)                                                 \
+    else if (t_info == internal_type_ptr<T>()) {                                                  \
+        RETURN_IF_FAILED(parcel->writeInt32(TYPEVAL));                                            \
+        RETURN_IF_FAILED(parcel->TYPEMETHOD(static_cast<const Content<T>*>(mContent)->mValue));   \
+    }
+#define HANDLE_WRITE_PARCELABLE(T, TYPEVAL)                                                       \
+    else if (t_info == internal_type_ptr<T>()) {                                                  \
+        RETURN_IF_FAILED(parcel->writeInt32(TYPEVAL));                                            \
+        RETURN_IF_FAILED(static_cast<const Content<T>*>(mContent)->mValue.writeToParcel(parcel)); \
+    }
+#define END_HANDLE_WRITE()                                                                        \
+        else {                                                                                    \
+            ALOGE("writeToParcel: Type not supported");                                           \
+            return BAD_TYPE;                                                                      \
+        }                                                                                         \
+    } while (false);
+
+    BEGIN_HANDLE_WRITE()
+
+    HANDLE_WRITE_TYPE(bool,     VAL_BOOLEAN, writeBool)
+    HANDLE_WRITE_TYPE(int8_t,   VAL_BYTE,    writeByte)
+    HANDLE_WRITE_TYPE(int8_t,   VAL_BYTE,    writeByte)
+    HANDLE_WRITE_TYPE(int32_t,  VAL_INTEGER, writeInt32)
+    HANDLE_WRITE_TYPE(int64_t,  VAL_LONG,    writeInt64)
+    HANDLE_WRITE_TYPE(double,   VAL_DOUBLE,  writeDouble)
+    HANDLE_WRITE_TYPE(String16, VAL_STRING,  writeString16)
+
+    HANDLE_WRITE_TYPE(vector<bool>,     VAL_BOOLEANARRAY, writeBoolVector)
+    HANDLE_WRITE_TYPE(vector<uint8_t>,  VAL_BYTEARRAY,    writeByteVector)
+    HANDLE_WRITE_TYPE(vector<int8_t>,   VAL_BYTEARRAY,    writeByteVector)
+    HANDLE_WRITE_TYPE(vector<int32_t>,  VAL_INTARRAY,     writeInt32Vector)
+    HANDLE_WRITE_TYPE(vector<int64_t>,  VAL_LONGARRAY,    writeInt64Vector)
+    HANDLE_WRITE_TYPE(vector<double>,   VAL_DOUBLEARRAY,  writeDoubleVector)
+    HANDLE_WRITE_TYPE(vector<String16>, VAL_STRINGARRAY,  writeString16Vector)
+
+    HANDLE_WRITE_PARCELABLE(PersistableBundle, VAL_PERSISTABLEBUNDLE)
+
+    END_HANDLE_WRITE()
+
+    return NO_ERROR;
+
+#undef BEGIN_HANDLE_WRITE
+#undef HANDLE_WRITE_TYPE
+#undef HANDLE_WRITE_PARCELABLE
+#undef END_HANDLE_WRITE
+}
+
+status_t Value::readFromParcel(const Parcel* parcel)
+{
+    // This implementation needs to be kept in sync with the readValue
+    // implementation in frameworks/base/core/java/android/os/Parcel.javai
+
+#define BEGIN_HANDLE_READ()                                                                      \
+    switch(value_type) {                                                                         \
+        default:                                                                                 \
+            ALOGE("readFromParcel: Parcel type %d is not supported", value_type);                \
+            return BAD_TYPE;
+#define HANDLE_READ_TYPE(T, TYPEVAL, TYPEMETHOD)                                                 \
+        case TYPEVAL:                                                                            \
+            mContent = new Content<T>();                                                         \
+            RETURN_IF_FAILED(parcel->TYPEMETHOD(&static_cast<Content<T>*>(mContent)->mValue));   \
+            break;
+#define HANDLE_READ_PARCELABLE(T, TYPEVAL)                                                       \
+        case TYPEVAL:                                                                            \
+            mContent = new Content<T>();                                                         \
+            RETURN_IF_FAILED(static_cast<Content<T>*>(mContent)->mValue.readFromParcel(parcel)); \
+            break;
+#define END_HANDLE_READ()                                                                        \
+    }
+
+    int32_t value_type = VAL_NULL;
+
+    delete mContent;
+    mContent = nullptr;
+
+    RETURN_IF_FAILED(parcel->readInt32(&value_type));
+
+    BEGIN_HANDLE_READ()
+
+    HANDLE_READ_TYPE(bool,     VAL_BOOLEAN, readBool)
+    HANDLE_READ_TYPE(int8_t,   VAL_BYTE,    readByte)
+    HANDLE_READ_TYPE(int32_t,  VAL_INTEGER, readInt32)
+    HANDLE_READ_TYPE(int64_t,  VAL_LONG,    readInt64)
+    HANDLE_READ_TYPE(double,   VAL_DOUBLE,  readDouble)
+    HANDLE_READ_TYPE(String16, VAL_STRING,  readString16)
+
+    HANDLE_READ_TYPE(vector<bool>,     VAL_BOOLEANARRAY, readBoolVector)
+    HANDLE_READ_TYPE(vector<uint8_t>,  VAL_BYTEARRAY,    readByteVector)
+    HANDLE_READ_TYPE(vector<int32_t>,  VAL_INTARRAY,     readInt32Vector)
+    HANDLE_READ_TYPE(vector<int64_t>,  VAL_LONGARRAY,    readInt64Vector)
+    HANDLE_READ_TYPE(vector<double>,   VAL_DOUBLEARRAY,  readDoubleVector)
+    HANDLE_READ_TYPE(vector<String16>, VAL_STRINGARRAY,  readString16Vector)
+
+    HANDLE_READ_PARCELABLE(PersistableBundle, VAL_PERSISTABLEBUNDLE)
+
+    END_HANDLE_READ()
+
+    return NO_ERROR;
+
+#undef BEGIN_HANDLE_READ
+#undef HANDLE_READ_TYPE
+#undef HANDLE_READ_PARCELABLE
+#undef END_HANDLE_READ
+}
+
+}  // namespace binder
+
+}  // namespace android
+
+/* vim: set ts=4 sw=4 tw=0 et :*/
diff --git a/libs/binder/aidl/android/os/IServiceCallback.aidl b/libs/binder/aidl/android/os/IServiceCallback.aidl
deleted file mode 100644
index b29dfed..0000000
--- a/libs/binder/aidl/android/os/IServiceCallback.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-package android.os;
-
-/**
- * @hide
- */
-oneway interface IServiceCallback {
-    /**
-     * Called when a service is registered.
-     *
-     * @param name the service name that has been registered with
-     * @param binder the binder that is registered
-     */
-    void onRegistration(@utf8InCpp String name, IBinder binder);
-}
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
deleted file mode 100644
index 8c7ebba..0000000
--- a/libs/binder/aidl/android/os/IServiceManager.aidl
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2006 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.
- */
-
-package android.os;
-
-import android.os.IServiceCallback;
-
-/**
- * Basic interface for finding and publishing system services.
- *
- * You likely want to use android.os.ServiceManager in Java or
- * android::IServiceManager in C++ in order to use this interface.
- *
- * @hide
- */
-interface IServiceManager {
-    /*
-     * Must update values in IServiceManager.h
-     */
-    /* Allows services to dump sections according to priorities. */
-    const int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0;
-    const int DUMP_FLAG_PRIORITY_HIGH = 1 << 1;
-    const int DUMP_FLAG_PRIORITY_NORMAL = 1 << 2;
-    /**
-     * Services are by default registered with a DEFAULT dump priority. DEFAULT priority has the
-     * same priority as NORMAL priority but the services are not called with dump priority
-     * arguments.
-     */
-    const int DUMP_FLAG_PRIORITY_DEFAULT = 1 << 3;
-
-    const int DUMP_FLAG_PRIORITY_ALL = 15;
-             // DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH
-             // | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PRIORITY_DEFAULT;
-
-    /* Allows services to dump sections in protobuf format. */
-    const int DUMP_FLAG_PROTO = 1 << 4;
-
-    /**
-     * Retrieve an existing service called @a name from the
-     * service manager.
-     *
-     * This is the same as checkService (returns immediately) but
-     * exists for legacy purposes.
-     *
-     * Returns null if the service does not exist.
-     */
-    @UnsupportedAppUsage
-    IBinder getService(@utf8InCpp String name);
-
-    /**
-     * Retrieve an existing service called @a name from the service
-     * manager. Non-blocking. Returns null if the service does not
-     * exist.
-     */
-    @UnsupportedAppUsage
-    IBinder checkService(@utf8InCpp String name);
-
-    /**
-     * Place a new @a service called @a name into the service
-     * manager.
-     */
-    void addService(@utf8InCpp String name, IBinder service,
-        boolean allowIsolated, int dumpPriority);
-
-    /**
-     * Return a list of all currently running services.
-     */
-    @utf8InCpp String[] listServices(int dumpPriority);
-
-    /**
-     * Request a callback when a service is registered.
-     */
-    void registerForNotifications(@utf8InCpp String name, IServiceCallback callback);
-
-    /**
-     * Unregisters all requests for notifications for a specific callback.
-     */
-    void unregisterForNotifications(@utf8InCpp String name, IServiceCallback callback);
-
-    /**
-     * Returns whether a given interface is declared on the device, even if it
-     * is not started yet. For instance, this could be a service declared in the VINTF
-     * manifest.
-     */
-    boolean isDeclared(@utf8InCpp String name);
-}
diff --git a/libs/binder/include/binder/ActivityManager.h b/libs/binder/include/binder/ActivityManager.h
index 9108e31..5f324c7 100644
--- a/libs/binder/include/binder/ActivityManager.h
+++ b/libs/binder/include/binder/ActivityManager.h
@@ -89,7 +89,7 @@
 };
 
 
-} // namespace android
+}; // namespace android
 // ---------------------------------------------------------------------------
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index b19cde7..17493b4 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -133,7 +133,7 @@
 };
 
 
-} // namespace android
+}; // namespace android
 // ---------------------------------------------------------------------------
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 3be61f9..cf3ef84 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -38,7 +38,7 @@
     virtual status_t    transact(   uint32_t code,
                                     const Parcel& data,
                                     Parcel* reply,
-                                    uint32_t flags = 0) final;
+                                    uint32_t flags = 0);
 
     // NOLINTNEXTLINE(google-default-arguments)
     virtual status_t    linkToDeath(const sp<DeathRecipient>& recipient,
@@ -54,9 +54,9 @@
     virtual void        attachObject(   const void* objectID,
                                         void* object,
                                         void* cleanupCookie,
-                                        object_cleanup_func func) final;
-    virtual void*       findObject(const void* objectID) const final;
-    virtual void        detachObject(const void* objectID) final;
+                                        object_cleanup_func func);
+    virtual void*       findObject(const void* objectID) const;
+    virtual void        detachObject(const void* objectID);
 
     virtual BBinder*    localBinder();
 
@@ -64,12 +64,6 @@
     // This must be called before the object is sent to another process. Not thread safe.
     void                setRequestingSid(bool requestSid);
 
-    sp<IBinder>         getExtension();
-    // This must be called before the object is sent to another process. Not thread safe.
-    void                setExtension(const sp<IBinder>& extension);
-
-    pid_t               getDebugPid();
-
 protected:
     virtual             ~BBinder();
 
@@ -114,7 +108,7 @@
     std::atomic<int32_t>    mState;
 };
 
-} // namespace android
+}; // namespace android
 
 // ---------------------------------------------------------------------------
 
diff --git a/libs/binder/include/binder/BinderService.h b/libs/binder/include/binder/BinderService.h
index c17ae6f..9230e89 100644
--- a/libs/binder/include/binder/BinderService.h
+++ b/libs/binder/include/binder/BinderService.h
@@ -62,6 +62,6 @@
 };
 
 
-} // namespace android
+}; // namespace android
 // ---------------------------------------------------------------------------
 #endif // ANDROID_BINDER_SERVICE_H
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 7dca733..1d4f881 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -34,7 +34,7 @@
 public:
     static BpBinder*    create(int32_t handle);
 
-    int32_t             handle() const;
+    inline  int32_t     handle() const { return mHandle; }
 
     virtual const String16&    getInterfaceDescriptor() const;
     virtual bool        isBinderAlive() const;
@@ -45,7 +45,7 @@
     virtual status_t    transact(   uint32_t code,
                                     const Parcel& data,
                                     Parcel* reply,
-                                    uint32_t flags = 0) final;
+                                    uint32_t flags = 0);
 
     // NOLINTNEXTLINE(google-default-arguments)
     virtual status_t    linkToDeath(const sp<DeathRecipient>& recipient,
@@ -61,12 +61,13 @@
     virtual void        attachObject(   const void* objectID,
                                         void* object,
                                         void* cleanupCookie,
-                                        object_cleanup_func func) final;
-    virtual void*       findObject(const void* objectID) const final;
-    virtual void        detachObject(const void* objectID) final;
+                                        object_cleanup_func func);
+    virtual void*       findObject(const void* objectID) const;
+    virtual void        detachObject(const void* objectID);
 
     virtual BpBinder*   remoteBinder();
 
+            status_t    setConstantData(const void* data, size_t size);
             void        sendObituary();
 
     static uint32_t     getBinderProxyCount(uint32_t uid);
@@ -144,7 +145,7 @@
     static bool                                 sBinderProxyThrottleCreate;
 };
 
-} // namespace android
+}; // namespace android
 
 // ---------------------------------------------------------------------------
 
diff --git a/libs/binder/include/binder/BufferedTextOutput.h b/libs/binder/include/binder/BufferedTextOutput.h
index 1b27bb2..feae93d 100644
--- a/libs/binder/include/binder/BufferedTextOutput.h
+++ b/libs/binder/include/binder/BufferedTextOutput.h
@@ -62,6 +62,6 @@
 };
 
 // ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
 
 #endif // ANDROID_BUFFEREDTEXTOUTPUT_H
diff --git a/libs/binder/include/binder/Debug.h b/libs/binder/include/binder/Debug.h
index 324e5c1..58e2b32 100644
--- a/libs/binder/include/binder/Debug.h
+++ b/libs/binder/include/binder/Debug.h
@@ -44,6 +44,6 @@
 __END_DECLS
 
 // ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
 
 #endif // ANDROID_BINDER_DEBUG_H
diff --git a/libs/binder/include/binder/IActivityManager.h b/libs/binder/include/binder/IActivityManager.h
index e0248f6..6abc071 100644
--- a/libs/binder/include/binder/IActivityManager.h
+++ b/libs/binder/include/binder/IActivityManager.h
@@ -51,7 +51,7 @@
 
 // ------------------------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
 
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IAppOpsCallback.h b/libs/binder/include/binder/IAppOpsCallback.h
index 7664260..b500219 100644
--- a/libs/binder/include/binder/IAppOpsCallback.h
+++ b/libs/binder/include/binder/IAppOpsCallback.h
@@ -52,7 +52,7 @@
 
 // ----------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
 
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h
index b74c623..3dbd0d9 100644
--- a/libs/binder/include/binder/IAppOpsService.h
+++ b/libs/binder/include/binder/IAppOpsService.h
@@ -79,7 +79,7 @@
 
 // ----------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
 
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IBatteryStats.h b/libs/binder/include/binder/IBatteryStats.h
index b786f89..48da865 100644
--- a/libs/binder/include/binder/IBatteryStats.h
+++ b/libs/binder/include/binder/IBatteryStats.h
@@ -77,7 +77,7 @@
 
 // ----------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
 
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index 64604b7..aa44285 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -22,8 +22,9 @@
 #include <utils/String16.h>
 #include <utils/Vector.h>
 
-// linux/binder.h defines this, but we don't want to include it here in order to
-// avoid exporting the kernel headers
+
+// linux/binder.h already defines this, but we can't just include it from there
+// because there are host builds that include this file.
 #ifndef B_PACK_CHARS
 #define B_PACK_CHARS(c1, c2, c3, c4) \
     ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
@@ -58,15 +59,9 @@
         SHELL_COMMAND_TRANSACTION = B_PACK_CHARS('_','C','M','D'),
         INTERFACE_TRANSACTION   = B_PACK_CHARS('_', 'N', 'T', 'F'),
         SYSPROPS_TRANSACTION    = B_PACK_CHARS('_', 'S', 'P', 'R'),
-        EXTENSION_TRANSACTION   = B_PACK_CHARS('_', 'E', 'X', 'T'),
-        DEBUG_PID_TRANSACTION   = B_PACK_CHARS('_', 'P', 'I', 'D'),
 
         // Corresponds to TF_ONE_WAY -- an asynchronous call.
-        FLAG_ONEWAY             = 0x00000001,
-
-        // Private userspace flag for transaction which is being requested from
-        // a vendor context.
-        FLAG_PRIVATE_VENDOR     = 0x10000000,
+        FLAG_ONEWAY             = 0x00000001
     };
 
                           IBinder();
@@ -91,54 +86,6 @@
                                          Vector<String16>& args, const sp<IShellCallback>& callback,
                                          const sp<IResultReceiver>& resultReceiver);
 
-    /**
-     * This allows someone to add their own additions to an interface without
-     * having to modify the original interface.
-     *
-     * For instance, imagine if we have this interface:
-     *     interface IFoo { void doFoo(); }
-     *
-     * If an unrelated owner (perhaps in a downstream codebase) wants to make a
-     * change to the interface, they have two options:
-     *
-     * A). Historical option that has proven to be BAD! Only the original
-     *     author of an interface should change an interface. If someone
-     *     downstream wants additional functionality, they should not ever
-     *     change the interface or use this method.
-     *
-     *    BAD TO DO:  interface IFoo {                       BAD TO DO
-     *    BAD TO DO:      void doFoo();                      BAD TO DO
-     *    BAD TO DO: +    void doBar(); // adding a method   BAD TO DO
-     *    BAD TO DO:  }                                      BAD TO DO
-     *
-     * B). Option that this method enables!
-     *     Leave the original interface unchanged (do not change IFoo!).
-     *     Instead, create a new interface in a downstream package:
-     *
-     *         package com.<name>; // new functionality in a new package
-     *         interface IBar { void doBar(); }
-     *
-     *     When registering the interface, add:
-     *         sp<MyFoo> foo = new MyFoo; // class in AOSP codebase
-     *         sp<MyBar> bar = new MyBar; // custom extension class
-     *         foo->setExtension(bar);    // use method in BBinder
-     *
-     *     Then, clients of IFoo can get this extension:
-     *         sp<IBinder> binder = ...;
-     *         sp<IFoo> foo = interface_cast<IFoo>(binder); // handle if null
-     *         sp<IBinder> barBinder;
-     *         ... handle error ... = binder->getExtension(&barBinder);
-     *         sp<IBar> bar = interface_cast<IBar>(barBinder);
-     *         // if bar is null, then there is no extension or a different
-     *         // type of extension
-     */
-    status_t                getExtension(sp<IBinder>* out);
-
-    /**
-     * Dump PID for a binder, for debugging.
-     */
-    status_t                getDebugPid(pid_t* outPid);
-
     // NOLINTNEXTLINE(google-default-arguments)
     virtual status_t        transact(   uint32_t code,
                                         const Parcel& data,
@@ -246,7 +193,7 @@
 private:
 };
 
-} // namespace android
+}; // namespace android
 
 // ---------------------------------------------------------------------------
 
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index 28ffa48..0d30560 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -88,12 +88,8 @@
 public:                                                                 \
 
 
-#define __IINTF_CONCAT(x, y) (x ## y)
 #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
-    const ::android::StaticString16                                     \
-        I##INTERFACE##_descriptor_static_str16(__IINTF_CONCAT(u, NAME));\
-    const ::android::String16 I##INTERFACE::descriptor(                 \
-        I##INTERFACE##_descriptor_static_str16);                        \
+    const ::android::String16 I##INTERFACE::descriptor(NAME);           \
     const ::android::String16&                                          \
             I##INTERFACE::getInterfaceDescriptor() const {              \
         return I##INTERFACE::descriptor;                                \
@@ -172,6 +168,6 @@
 
 // ----------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
 
 #endif // ANDROID_IINTERFACE_H
diff --git a/libs/binder/include/binder/IMediaResourceMonitor.h b/libs/binder/include/binder/IMediaResourceMonitor.h
index da2b7cf..213ee63 100644
--- a/libs/binder/include/binder/IMediaResourceMonitor.h
+++ b/libs/binder/include/binder/IMediaResourceMonitor.h
@@ -52,7 +52,7 @@
 
 // ----------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
 
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IMemory.h b/libs/binder/include/binder/IMemory.h
index 98e92c4..071946f 100644
--- a/libs/binder/include/binder/IMemory.h
+++ b/libs/binder/include/binder/IMemory.h
@@ -76,8 +76,6 @@
     // NOLINTNEXTLINE(google-default-arguments)
     virtual sp<IMemoryHeap> getMemory(ssize_t* offset=nullptr, size_t* size=nullptr) const = 0;
 
-    void* unsecurePointer() const;
-
     // helpers
     void* fastPointer(const sp<IBinder>& heap, ssize_t offset) const;
     void* pointer() const;
@@ -102,6 +100,6 @@
 
 // ----------------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
 
 #endif // ANDROID_IMEMORY_H
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index ff9244e..614b0b3 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -110,8 +110,6 @@
             // the maximum number of binder threads threads allowed for this process.
             void                blockUntilThreadAvailable();
 
-            // Service manager registration
-            void                setTheContextObject(sp<BBinder> obj);
 
             // Is this thread currently serving a binder call. This method
             // returns true if while traversing backwards from the function call
@@ -196,7 +194,7 @@
             ProcessState::CallRestriction mCallRestriction;
 };
 
-} // namespace android
+}; // namespace android
 
 // ---------------------------------------------------------------------------
 
diff --git a/libs/binder/include/binder/IPermissionController.h b/libs/binder/include/binder/IPermissionController.h
index 4b66df8..26a1b23 100644
--- a/libs/binder/include/binder/IPermissionController.h
+++ b/libs/binder/include/binder/IPermissionController.h
@@ -65,7 +65,7 @@
 
 // ----------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
 
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IProcessInfoService.h b/libs/binder/include/binder/IProcessInfoService.h
index ca30ad3..033c145 100644
--- a/libs/binder/include/binder/IProcessInfoService.h
+++ b/libs/binder/include/binder/IProcessInfoService.h
@@ -46,7 +46,7 @@
 
 // ----------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
 
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IResultReceiver.h b/libs/binder/include/binder/IResultReceiver.h
index 70e99e7..00b3d89 100644
--- a/libs/binder/include/binder/IResultReceiver.h
+++ b/libs/binder/include/binder/IResultReceiver.h
@@ -50,7 +50,7 @@
 
 // ----------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
 
 #endif // ANDROID_IRESULT_RECEIVER_H
 
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 2c43263..aeea1a2 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -26,22 +26,12 @@
 
 // ----------------------------------------------------------------------
 
-/**
- * Service manager for C++ services.
- *
- * IInterface is only for legacy ABI compatibility
- */
 class IServiceManager : public IInterface
 {
 public:
-    // for ABI compatibility
-    virtual const String16& getInterfaceDescriptor() const;
-
-    IServiceManager();
-    virtual ~IServiceManager();
-
+    DECLARE_META_INTERFACE(ServiceManager)
     /**
-     * Must match values in IServiceManager.aidl
+     * Must match values in IServiceManager.java
      */
     /* Allows services to dump sections according to priorities. */
     static const int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0;
@@ -82,59 +72,17 @@
     // NOLINTNEXTLINE(google-default-arguments)
     virtual Vector<String16> listServices(int dumpsysFlags = DUMP_FLAG_PRIORITY_ALL) = 0;
 
-    /**
-     * Efficiently wait for a service.
-     *
-     * Returns nullptr only for permission problem or fatal error.
-     */
-    virtual sp<IBinder> waitForService(const String16& name) = 0;
-
-    /**
-     * Check if a service is declared (e.g. VINTF manifest).
-     *
-     * If this returns true, waitForService should always be able to return the
-     * service.
-     */
-    virtual bool isDeclared(const String16& name) = 0;
+    enum {
+        GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+        CHECK_SERVICE_TRANSACTION,
+        ADD_SERVICE_TRANSACTION,
+        LIST_SERVICES_TRANSACTION,
+    };
 };
 
 sp<IServiceManager> defaultServiceManager();
 
 template<typename INTERFACE>
-sp<INTERFACE> waitForService(const String16& name) {
-    const sp<IServiceManager> sm = defaultServiceManager();
-    return interface_cast<INTERFACE>(sm->waitForService(name));
-}
-
-template<typename INTERFACE>
-sp<INTERFACE> waitForDeclaredService(const String16& name) {
-    const sp<IServiceManager> sm = defaultServiceManager();
-    if (!sm->isDeclared(name)) return nullptr;
-    return interface_cast<INTERFACE>(sm->waitForService(name));
-}
-
-template <typename INTERFACE>
-sp<INTERFACE> checkDeclaredService(const String16& name) {
-    const sp<IServiceManager> sm = defaultServiceManager();
-    if (!sm->isDeclared(name)) return nullptr;
-    return interface_cast<INTERFACE>(sm->checkService(name));
-}
-
-template<typename INTERFACE>
-sp<INTERFACE> waitForVintfService(
-        const String16& instance = String16("default")) {
-    return waitForDeclaredService<INTERFACE>(
-        INTERFACE::descriptor + String16("/") + instance);
-}
-
-template<typename INTERFACE>
-sp<INTERFACE> checkVintfService(
-        const String16& instance = String16("default")) {
-    return checkDeclaredService<INTERFACE>(
-        INTERFACE::descriptor + String16("/") + instance);
-}
-
-template<typename INTERFACE>
 status_t getService(const String16& name, sp<INTERFACE>* outService)
 {
     const sp<IServiceManager> sm = defaultServiceManager();
@@ -150,7 +98,7 @@
                             int32_t* outPid, int32_t* outUid);
 bool checkPermission(const String16& permission, pid_t pid, uid_t uid);
 
-} // namespace android
+}; // namespace android
 
 #endif // ANDROID_ISERVICE_MANAGER_H
 
diff --git a/libs/binder/include/binder/IShellCallback.h b/libs/binder/include/binder/IShellCallback.h
index b7ab6ea..6715678 100644
--- a/libs/binder/include/binder/IShellCallback.h
+++ b/libs/binder/include/binder/IShellCallback.h
@@ -51,7 +51,7 @@
 
 // ----------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
 
 #endif // ANDROID_ISHELL_CALLBACK_H
 
diff --git a/libs/binder/include/binder/IUidObserver.h b/libs/binder/include/binder/IUidObserver.h
index 09e50a9..a1f530d 100644
--- a/libs/binder/include/binder/IUidObserver.h
+++ b/libs/binder/include/binder/IUidObserver.h
@@ -58,7 +58,7 @@
 
 // ----------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
 
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/Map.h b/libs/binder/include/binder/Map.h
new file mode 100644
index 0000000..96a4f8a
--- /dev/null
+++ b/libs/binder/include/binder/Map.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_MAP_H
+#define ANDROID_MAP_H
+
+#include <map>
+#include <string>
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace binder {
+
+class Value;
+
+/**
+ * Convenience typedef for ::std::map<::std::string,::android::binder::Value>
+ */
+typedef ::std::map<::std::string, Value> Map;
+
+} // namespace binder
+} // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_MAP_H
diff --git a/libs/binder/include/binder/MemoryBase.h b/libs/binder/include/binder/MemoryBase.h
index 4dd3638..463e26d 100644
--- a/libs/binder/include/binder/MemoryBase.h
+++ b/libs/binder/include/binder/MemoryBase.h
@@ -46,6 +46,6 @@
 };
 
 // ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
 
 #endif // ANDROID_MEMORY_BASE_H
diff --git a/libs/binder/include/binder/MemoryDealer.h b/libs/binder/include/binder/MemoryDealer.h
index 6c1c412..b483be0 100644
--- a/libs/binder/include/binder/MemoryDealer.h
+++ b/libs/binder/include/binder/MemoryDealer.h
@@ -59,6 +59,6 @@
 
 
 // ----------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
 
 #endif // ANDROID_MEMORY_DEALER_H
diff --git a/libs/binder/include/binder/MemoryHeapBase.h b/libs/binder/include/binder/MemoryHeapBase.h
index 3fccddc..100d784 100644
--- a/libs/binder/include/binder/MemoryHeapBase.h
+++ b/libs/binder/include/binder/MemoryHeapBase.h
@@ -98,6 +98,6 @@
 };
 
 // ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
 
 #endif // ANDROID_MEMORY_HEAP_BASE_H
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index d4bb85b..e5219a5 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -17,11 +17,11 @@
 #ifndef ANDROID_PARCEL_H
 #define ANDROID_PARCEL_H
 
-#include <map> // for legacy reasons
 #include <string>
-#include <type_traits>
 #include <vector>
 
+#include <linux/android/binder.h>
+
 #include <android-base/unique_fd.h>
 #include <cutils/native_handle.h>
 #include <utils/Errors.h>
@@ -32,26 +32,23 @@
 
 #include <binder/IInterface.h>
 #include <binder/Parcelable.h>
-
-#ifdef BINDER_IPC_32BIT
-typedef unsigned int binder_size_t;
-#else
-typedef unsigned long long binder_size_t;
-#endif
-
+#include <binder/Map.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
 
 template <typename T> class Flattenable;
 template <typename T> class LightFlattenable;
-struct flat_binder_object;
 class IBinder;
 class IPCThreadState;
 class ProcessState;
 class String8;
 class TextOutput;
 
+namespace binder {
+class Value;
+};
+
 class Parcel {
     friend class IPCThreadState;
 public:
@@ -70,7 +67,7 @@
     status_t            setDataSize(size_t size);
     void                setDataPosition(size_t pos) const;
     status_t            setDataCapacity(size_t size);
-
+    
     status_t            setData(const uint8_t* buffer, size_t len);
 
     status_t            appendFrom(const Parcel *parcel,
@@ -100,6 +97,10 @@
 
     void                freeData();
 
+private:
+    const binder_size_t* objects() const;
+
+public:
     size_t              objectsCount() const;
     
     status_t            errorCheck() const;
@@ -120,6 +121,7 @@
     status_t            writeString16(const std::unique_ptr<String16>& str);
     status_t            writeString16(const char16_t* str, size_t len);
     status_t            writeStrongBinder(const sp<IBinder>& val);
+    status_t            writeWeakBinder(const wp<IBinder>& val);
     status_t            writeInt32Array(size_t len, const int32_t *val);
     status_t            writeByteArray(size_t len, const uint8_t *val);
     status_t            writeBool(bool val);
@@ -158,18 +160,6 @@
     status_t            writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val);
     status_t            writeStrongBinderVector(const std::vector<sp<IBinder>>& val);
 
-    // Write an Enum vector with underlying type int8_t.
-    // Does not use padding; each byte is contiguous.
-    template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            writeEnumVector(const std::vector<T>& val);
-    template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            writeEnumVector(const std::unique_ptr<std::vector<T>>& val);
-    // Write an Enum vector with underlying type != int8_t.
-    template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            writeEnumVector(const std::vector<T>& val);
-    template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            writeEnumVector(const std::unique_ptr<std::vector<T>>& val);
-
     template<typename T>
     status_t            writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val);
     template<typename T>
@@ -182,6 +172,8 @@
 
     status_t            writeParcelable(const Parcelable& parcelable);
 
+    status_t            writeValue(const binder::Value& value);
+
     template<typename T>
     status_t            write(const Flattenable<T>& val);
 
@@ -193,6 +185,9 @@
     template<typename T>
     status_t            writeVectorSize(const std::unique_ptr<std::vector<T>>& val);
 
+    status_t            writeMap(const binder::Map& map);
+    status_t            writeNullableMap(const std::unique_ptr<binder::Map>& map);
+
     // Place a native_handle into the parcel (the native_handle's file-
     // descriptors are dup'ed, so it is safe to delete the native_handle
     // when this function returns).
@@ -249,6 +244,8 @@
     // Currently the native implementation doesn't do any of the StrictMode
     // stack gathering and serialization that the Java implementation does.
     status_t            writeNoException();
+
+    void                remove(size_t start, size_t amt);
     
     status_t            read(void* outData, size_t len) const;
     const void*         readInplace(size_t len) const;
@@ -287,19 +284,7 @@
     sp<IBinder>         readStrongBinder() const;
     status_t            readStrongBinder(sp<IBinder>* val) const;
     status_t            readNullableStrongBinder(sp<IBinder>* val) const;
-
-
-    // Read an Enum vector with underlying type int8_t.
-    // Does not use padding; each byte is contiguous.
-    template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            readEnumVector(std::vector<T>* val) const;
-    template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            readEnumVector(std::unique_ptr<std::vector<T>>* val) const;
-    // Read an Enum vector with underlying type != int8_t.
-    template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            readEnumVector(std::vector<T>* val) const;
-    template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            readEnumVector(std::unique_ptr<std::vector<T>>* val) const;
+    wp<IBinder>         readWeakBinder() const;
 
     template<typename T>
     status_t            readParcelableVector(
@@ -312,6 +297,8 @@
     template<typename T>
     status_t            readParcelable(std::unique_ptr<T>* parcelable) const;
 
+    status_t            readValue(binder::Value* value) const;
+
     template<typename T>
     status_t            readStrongBinder(sp<T>* val) const;
 
@@ -356,11 +343,9 @@
     status_t            resizeOutVector(std::vector<T>* val) const;
     template<typename T>
     status_t            resizeOutVector(std::unique_ptr<std::vector<T>>* val) const;
-    template<typename T>
-    status_t            reserveOutVector(std::vector<T>* val, size_t* size) const;
-    template<typename T>
-    status_t            reserveOutVector(std::unique_ptr<std::vector<T>>* val,
-                                         size_t* size) const;
+
+    status_t            readMap(binder::Map* map)const;
+    status_t            readNullableMap(std::unique_ptr<binder::Map>* map) const;
 
     // Like Parcel.java's readExceptionCode().  Reads the first int32
     // off of a Parcel's header, returning 0 or the negative error
@@ -414,7 +399,8 @@
     bool                replaceCallingWorkSourceUid(uid_t uid);
     // Returns the work source provided by the caller. This can only be trusted for trusted calling
     // uid.
-    uid_t               readCallingWorkSourceUid() const;
+    uid_t               readCallingWorkSourceUid();
+    void                readRequestHeaders() const;
 
 private:
     typedef void        (*release_func)(Parcel* parcel,
@@ -451,13 +437,7 @@
     void                scanForFds() const;
     status_t            validateReadData(size_t len) const;
     void                updateWorkSourceRequestHeaderPosition() const;
-
-    status_t            finishFlattenBinder(const sp<IBinder>& binder,
-                                            const flat_binder_object& flat);
-    status_t            finishUnflattenBinder(const sp<IBinder>& binder, sp<IBinder>* out) const;
-    status_t            flattenBinder(const sp<IBinder>& binder);
-    status_t            unflattenBinder(sp<IBinder>* out) const;
-
+                        
     template<class T>
     status_t            readAligned(T *pArg) const;
 
@@ -469,20 +449,6 @@
     status_t            writeRawNullableParcelable(const Parcelable*
                                                    parcelable);
 
-    template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0>
-    status_t            writeEnum(const T& val);
-    template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0>
-    status_t            writeEnum(const T& val);
-
-    template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0>
-    status_t            readEnum(T* pArg) const;
-    template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0>
-    status_t            readEnum(T* pArg) const;
-
-    status_t writeByteVectorInternal(const int8_t* data, size_t size);
-    template<typename T>
-    status_t readByteVectorInternal(std::vector<T>* val, size_t size) const;
-
     template<typename T, typename U>
     status_t            unsafeReadTypedVector(std::vector<T>* val,
                                               status_t(Parcel::*read_func)(U*) const) const;
@@ -726,42 +692,6 @@
 }
 
 template<typename T>
-status_t Parcel::reserveOutVector(std::vector<T>* val, size_t* size) const {
-    int32_t read_size;
-    status_t err = readInt32(&read_size);
-    if (err != NO_ERROR) {
-        return err;
-    }
-
-    if (read_size < 0) {
-        return UNEXPECTED_NULL;
-    }
-    *size = static_cast<size_t>(read_size);
-    val->reserve(*size);
-    return OK;
-}
-
-template<typename T>
-status_t Parcel::reserveOutVector(std::unique_ptr<std::vector<T>>* val,
-                                  size_t* size) const {
-    int32_t read_size;
-    status_t err = readInt32(&read_size);
-    if (err != NO_ERROR) {
-        return err;
-    }
-
-    if (read_size >= 0) {
-        *size = static_cast<size_t>(read_size);
-        val->reset(new std::vector<T>());
-        (*val)->reserve(*size);
-    } else {
-        val->reset();
-    }
-
-    return OK;
-}
-
-template<typename T>
 status_t Parcel::readStrongBinder(sp<T>* val) const {
     sp<IBinder> tmp;
     status_t ret = readStrongBinder(&tmp);
@@ -994,79 +924,6 @@
     return unsafeWriteTypedVector(*val, &Parcel::writeNullableParcelable<T>);
 }
 
-template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
-status_t Parcel::writeEnum(const T& val) {
-    return writeInt32(static_cast<int32_t>(val));
-}
-template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>>
-status_t Parcel::writeEnum(const T& val) {
-    return writeInt64(static_cast<int64_t>(val));
-}
-
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::vector<T>& val) {
-    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) {
-    if (!val) return writeInt32(-1);
-    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::vector<T>& val) {
-    return writeTypedVector(val, &Parcel::writeEnum);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) {
-    return writeNullableTypedVector(val, &Parcel::writeEnum);
-}
-
-template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
-status_t Parcel::readEnum(T* pArg) const {
-    return readInt32(reinterpret_cast<int32_t *>(pArg));
-}
-template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>>
-status_t Parcel::readEnum(T* pArg) const {
-    return readInt64(reinterpret_cast<int64_t *>(pArg));
-}
-
-template<typename T>
-inline status_t Parcel::readByteVectorInternal(std::vector<T>* val, size_t size) const {
-  // readByteVectorInternal expects a vector that has been reserved (but not
-  // resized) to have the provided size.
-  const T* data = reinterpret_cast<const T*>(readInplace(size));
-  if (!data) return BAD_VALUE;
-  val->clear();
-  val->insert(val->begin(), data, data+size);
-  return NO_ERROR;
-}
-
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::vector<T>* val) const {
-    size_t size;
-    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
-    return readByteVectorInternal(val, size);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
-    size_t size;
-    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
-    if (val->get() == nullptr) {
-        // reserveOutVector does not create the out vector if size is < 0.
-        // This occurs when writing a null Enum vector.
-        return OK;
-    }
-    return readByteVectorInternal(val->get(), size);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::vector<T>* val) const {
-    return readTypedVector(val, &Parcel::readEnum);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readEnum);
-}
-
 // ---------------------------------------------------------------------------
 
 inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
@@ -1075,7 +932,24 @@
     return to;
 }
 
-} // namespace android
+// ---------------------------------------------------------------------------
+
+// Generic acquire and release of objects.
+void acquire_object(const sp<ProcessState>& proc,
+                    const flat_binder_object& obj, const void* who);
+void release_object(const sp<ProcessState>& proc,
+                    const flat_binder_object& obj, const void* who);
+
+void flatten_binder(const sp<ProcessState>& proc,
+                    const sp<IBinder>& binder, flat_binder_object* out);
+void flatten_binder(const sp<ProcessState>& proc,
+                    const wp<IBinder>& binder, flat_binder_object* out);
+status_t unflatten_binder(const sp<ProcessState>& proc,
+                          const flat_binder_object& flat, sp<IBinder>* out);
+status_t unflatten_binder(const sp<ProcessState>& proc,
+                          const flat_binder_object& flat, wp<IBinder>* out);
+
+}; // namespace android
 
 // ---------------------------------------------------------------------------
 
diff --git a/libs/binder/include/binder/ParcelFileDescriptor.h b/libs/binder/include/binder/ParcelFileDescriptor.h
index 4635ad8..662e56e 100644
--- a/libs/binder/include/binder/ParcelFileDescriptor.h
+++ b/libs/binder/include/binder/ParcelFileDescriptor.h
@@ -42,24 +42,6 @@
     android::status_t writeToParcel(android::Parcel* parcel) const override;
     android::status_t readFromParcel(const android::Parcel* parcel) override;
 
-    inline bool operator!=(const ParcelFileDescriptor& rhs) const {
-        return mFd != rhs.mFd;
-    }
-    inline bool operator<(const ParcelFileDescriptor& rhs) const {
-        return mFd < rhs.mFd;
-    }
-    inline bool operator<=(const ParcelFileDescriptor& rhs) const {
-        return mFd <= rhs.mFd;
-    }
-    inline bool operator==(const ParcelFileDescriptor& rhs) const {
-        return mFd == rhs.mFd;
-    }
-    inline bool operator>(const ParcelFileDescriptor& rhs) const {
-        return mFd > rhs.mFd;
-    }
-    inline bool operator>=(const ParcelFileDescriptor& rhs) const {
-        return mFd >= rhs.mFd;
-    }
 private:
     android::base::unique_fd mFd;
 };
diff --git a/libs/binder/include/binder/PermissionCache.h b/libs/binder/include/binder/PermissionCache.h
index c258215..95eabff 100644
--- a/libs/binder/include/binder/PermissionCache.h
+++ b/libs/binder/include/binder/PermissionCache.h
@@ -77,7 +77,7 @@
 };
 
 // ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
 
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/PermissionController.h b/libs/binder/include/binder/PermissionController.h
index 4db522a..d81f514 100644
--- a/libs/binder/include/binder/PermissionController.h
+++ b/libs/binder/include/binder/PermissionController.h
@@ -60,7 +60,7 @@
 };
 
 
-} // namespace android
+}; // namespace android
 // ---------------------------------------------------------------------------
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/ProcessInfoService.h b/libs/binder/include/binder/ProcessInfoService.h
index 6bfd1bc..a03aae9 100644
--- a/libs/binder/include/binder/ProcessInfoService.h
+++ b/libs/binder/include/binder/ProcessInfoService.h
@@ -78,7 +78,7 @@
 
 // ----------------------------------------------------------------------
 
-} // namespace android
+}; // namespace android
 
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index e57ff1c..224cb36 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -45,19 +45,27 @@
      */
     static  sp<ProcessState>    initWithDriver(const char *driver);
 
+            void                setContextObject(const sp<IBinder>& object);
             sp<IBinder>         getContextObject(const sp<IBinder>& caller);
+        
+            void                setContextObject(const sp<IBinder>& object,
+                                                 const String16& name);
+            sp<IBinder>         getContextObject(const String16& name,
+                                                 const sp<IBinder>& caller);
 
             void                startThreadPool();
                         
     typedef bool (*context_check_func)(const String16& name,
                                        const sp<IBinder>& caller,
                                        void* userData);
-
+        
+            bool                isContextManager(void) const;
             bool                becomeContextManager(
                                     context_check_func checkFunc,
                                     void* userData);
 
             sp<IBinder>         getStrongProxyForHandle(int32_t handle);
+            wp<IBinder>         getWeakProxyForHandle(int32_t handle);
             void                expungeHandle(int32_t handle, IBinder* binder);
 
             void                spawnPooledThread(bool isMain);
@@ -69,14 +77,6 @@
 
             ssize_t             getKernelReferences(size_t count, uintptr_t* buf);
 
-                                // Only usable by the context manager.
-                                // This refcount includes:
-                                // 1. Strong references to the node by this and other processes
-                                // 2. Temporary strong references held by the kernel during a
-                                //    transaction on the node.
-                                // It does NOT include local strong references to the node
-            ssize_t             getStrongRefCountForNodeByHandle(int32_t handle);
-
             enum class CallRestriction {
                 // all calls okay
                 NONE,
@@ -124,9 +124,14 @@
 
             Vector<handle_entry>mHandleToObject;
 
+            bool                mManagesContexts;
             context_check_func  mBinderContextCheckFunc;
             void*               mBinderContextUserData;
 
+            KeyedVector<String16, sp<IBinder> >
+                                mContexts;
+
+
             String8             mRootDir;
             bool                mThreadPoolStarted;
     volatile int32_t            mThreadPoolSeq;
@@ -134,7 +139,7 @@
             CallRestriction     mCallRestriction;
 };
     
-} // namespace android
+}; // namespace android
 
 // ---------------------------------------------------------------------------
 
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
deleted file mode 100644
index b2f51d3..0000000
--- a/libs/binder/include/binder/Stability.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <binder/IBinder.h>
-#include <string>
-
-namespace android {
-
-class BpBinder;
-class ProcessState;
-
-namespace internal {
-
-// WARNING: These APIs are only ever expected to be called by auto-generated code.
-//     Instead of calling them, you should set the stability of a .aidl interface
-class Stability final {
-public:
-    // WARNING: This is only ever expected to be called by auto-generated code. You likely want to
-    // change or modify the stability class of the interface you are using.
-    // This must be called as soon as the binder in question is constructed. No thread safety
-    // is provided.
-    // E.g. stability is according to libbinder compilation unit
-    static void markCompilationUnit(IBinder* binder);
-    // WARNING: This is only ever expected to be called by auto-generated code. You likely want to
-    // change or modify the stability class of the interface you are using.
-    // This must be called as soon as the binder in question is constructed. No thread safety
-    // is provided.
-    // E.g. stability is according to libbinder_ndk or Java SDK AND the interface
-    //     expressed here is guaranteed to be stable for multiple years (Stable AIDL)
-    static void markVintf(IBinder* binder);
-
-    // WARNING: for debugging only
-    static void debugLogStability(const std::string& tag, const sp<IBinder>& binder);
-
-    // WARNING: This is only ever expected to be called by auto-generated code or tests.
-    // You likely want to change or modify the stability of the interface you are using.
-    // This must be called as soon as the binder in question is constructed. No thread safety
-    // is provided.
-    // E.g. stability is according to libbinder_ndk or Java SDK AND the interface
-    //     expressed here is guaranteed to be stable for multiple years (Stable AIDL)
-    // If this is called when __ANDROID_VNDK__ is not defined, then it is UB and will likely
-    // break the device during GSI or other tests.
-    static void markVndk(IBinder* binder);
-
-    // Returns true if the binder needs to be declared in the VINTF manifest or
-    // else false if the binder is local to the current partition.
-    static bool requiresVintfDeclaration(const sp<IBinder>& binder);
-private:
-    // Parcel needs to read/write stability level in an unstable format.
-    friend ::android::Parcel;
-
-    // only expose internal APIs inside of libbinder, for checking stability
-    friend ::android::BpBinder;
-
-    // so that it can mark the context object (only the root object doesn't go
-    // through Parcel)
-    friend ::android::ProcessState;
-
-    static void tryMarkCompilationUnit(IBinder* binder);
-
-    enum Level : int32_t {
-        UNDECLARED = 0,
-
-        VENDOR = 0b000011,
-        SYSTEM = 0b001100,
-        VINTF = 0b111111,
-    };
-
-#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
-    static constexpr Level kLocalStability = Level::VENDOR;
-#else
-    static constexpr Level kLocalStability = Level::SYSTEM;
-#endif
-
-    // applies stability to binder if stability level is known
-    __attribute__((warn_unused_result))
-    static status_t set(IBinder* binder, int32_t stability, bool log);
-
-    static Level get(IBinder* binder);
-
-    static bool check(int32_t provided, Level required);
-
-    static bool isDeclaredStability(int32_t stability);
-    static std::string stabilityString(int32_t stability);
-
-    Stability();
-};
-
-}  // namespace internal
-}  // namespace android
diff --git a/libs/binder/include/binder/TextOutput.h b/libs/binder/include/binder/TextOutput.h
index f66406f..5b5f766 100644
--- a/libs/binder/include/binder/TextOutput.h
+++ b/libs/binder/include/binder/TextOutput.h
@@ -199,6 +199,6 @@
 inline bool HexDump::carrayStyle() const { return mCArrayStyle; }
 
 // ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
 
 #endif // ANDROID_TEXTOUTPUT_H
diff --git a/libs/binder/include/binder/Value.h b/libs/binder/include/binder/Value.h
new file mode 100644
index 0000000..735f40e
--- /dev/null
+++ b/libs/binder/include/binder/Value.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef ANDROID_VALUE_H
+#define ANDROID_VALUE_H
+
+#include <stdint.h>
+#include <map>
+#include <set>
+#include <vector>
+#include <string>
+
+#include <binder/Parcelable.h>
+#include <binder/PersistableBundle.h>
+#include <binder/Map.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+class Parcel;
+
+namespace binder {
+
+/**
+ * A limited C++ generic type. The purpose of this class is to allow C++
+ * programs to make use of (or implement) Binder interfaces which make use
+ * the Java "Object" generic type (either via the use of the Map type or
+ * some other mechanism).
+ *
+ * This class only supports a limited set of types, but additional types
+ * may be easily added to this class in the future as needed---without
+ * breaking binary compatability.
+ *
+ * This class was written in such a way as to help avoid type errors by
+ * giving each type their own explicity-named accessor methods (rather than
+ * overloaded methods).
+ *
+ * When reading or writing this class to a Parcel, use the `writeValue()`
+ * and `readValue()` methods.
+ */
+class Value {
+public:
+    Value();
+    virtual ~Value();
+
+    Value& swap(Value &);
+
+    bool empty() const;
+
+    void clear();
+
+#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
+    const std::type_info& type() const;
+#endif
+
+    int32_t parcelType() const;
+
+    bool operator==(const Value& rhs) const;
+    bool operator!=(const Value& rhs) const { return !this->operator==(rhs); }
+
+    Value(const Value& value);
+    Value(const bool& value); // NOLINT(google-explicit-constructor)
+    Value(const int8_t& value); // NOLINT(google-explicit-constructor)
+    Value(const int32_t& value); // NOLINT(google-explicit-constructor)
+    Value(const int64_t& value); // NOLINT(google-explicit-constructor)
+    Value(const double& value); // NOLINT(google-explicit-constructor)
+    Value(const String16& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<bool>& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<uint8_t>& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<int32_t>& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<int64_t>& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<double>& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<String16>& value); // NOLINT(google-explicit-constructor)
+    Value(const os::PersistableBundle& value); // NOLINT(google-explicit-constructor)
+    Value(const binder::Map& value); // NOLINT(google-explicit-constructor)
+
+    Value& operator=(const Value& rhs);
+    Value& operator=(const int8_t& rhs);
+    Value& operator=(const bool& rhs);
+    Value& operator=(const int32_t& rhs);
+    Value& operator=(const int64_t& rhs);
+    Value& operator=(const double& rhs);
+    Value& operator=(const String16& rhs);
+    Value& operator=(const std::vector<bool>& rhs);
+    Value& operator=(const std::vector<uint8_t>& rhs);
+    Value& operator=(const std::vector<int32_t>& rhs);
+    Value& operator=(const std::vector<int64_t>& rhs);
+    Value& operator=(const std::vector<double>& rhs);
+    Value& operator=(const std::vector<String16>& rhs);
+    Value& operator=(const os::PersistableBundle& rhs);
+    Value& operator=(const binder::Map& rhs);
+
+    void putBoolean(const bool& value);
+    void putByte(const int8_t& value);
+    void putInt(const int32_t& value);
+    void putLong(const int64_t& value);
+    void putDouble(const double& value);
+    void putString(const String16& value);
+    void putBooleanVector(const std::vector<bool>& value);
+    void putByteVector(const std::vector<uint8_t>& value);
+    void putIntVector(const std::vector<int32_t>& value);
+    void putLongVector(const std::vector<int64_t>& value);
+    void putDoubleVector(const std::vector<double>& value);
+    void putStringVector(const std::vector<String16>& value);
+    void putPersistableBundle(const os::PersistableBundle& value);
+    void putMap(const binder::Map& value);
+
+    bool getBoolean(bool* out) const;
+    bool getByte(int8_t* out) const;
+    bool getInt(int32_t* out) const;
+    bool getLong(int64_t* out) const;
+    bool getDouble(double* out) const;
+    bool getString(String16* out) const;
+    bool getBooleanVector(std::vector<bool>* out) const;
+    bool getByteVector(std::vector<uint8_t>* out) const;
+    bool getIntVector(std::vector<int32_t>* out) const;
+    bool getLongVector(std::vector<int64_t>* out) const;
+    bool getDoubleVector(std::vector<double>* out) const;
+    bool getStringVector(std::vector<String16>* out) const;
+    bool getPersistableBundle(os::PersistableBundle* out) const;
+    bool getMap(binder::Map* out) const;
+
+    bool isBoolean() const;
+    bool isByte() const;
+    bool isInt() const;
+    bool isLong() const;
+    bool isDouble() const;
+    bool isString() const;
+    bool isBooleanVector() const;
+    bool isByteVector() const;
+    bool isIntVector() const;
+    bool isLongVector() const;
+    bool isDoubleVector() const;
+    bool isStringVector() const;
+    bool isPersistableBundle() const;
+    bool isMap() const;
+
+    // String Convenience Adapters
+    // ---------------------------
+
+    explicit Value(const String8& value):               Value(String16(value)) { }
+    explicit Value(const ::std::string& value):         Value(String8(value.c_str())) { }
+    void putString(const String8& value)       { return putString(String16(value)); }
+    void putString(const ::std::string& value) { return putString(String8(value.c_str())); }
+    Value& operator=(const String8& rhs)       { return *this = String16(rhs); }
+    Value& operator=(const ::std::string& rhs) { return *this = String8(rhs.c_str()); }
+    bool getString(String8* out) const;
+    bool getString(::std::string* out) const;
+
+private:
+
+    // This allows ::android::Parcel to call the two methods below.
+    friend class ::android::Parcel;
+
+    // This is called by ::android::Parcel::writeValue()
+    status_t writeToParcel(Parcel* parcel) const;
+
+    // This is called by ::android::Parcel::readValue()
+    status_t readFromParcel(const Parcel* parcel);
+
+    template<typename T> class Content;
+    class ContentBase;
+
+    ContentBase* mContent;
+};
+
+}  // namespace binder
+
+}  // namespace android
+
+#endif  // ANDROID_VALUE_H
diff --git a/libs/binder/ParcelValTypes.h b/libs/binder/include/private/binder/ParcelValTypes.h
similarity index 100%
rename from libs/binder/ParcelValTypes.h
rename to libs/binder/include/private/binder/ParcelValTypes.h
diff --git a/libs/binder/Static.h b/libs/binder/include/private/binder/Static.h
similarity index 73%
rename from libs/binder/Static.h
rename to libs/binder/include/private/binder/Static.h
index f8e0ee5..171be77 100644
--- a/libs/binder/Static.h
+++ b/libs/binder/include/private/binder/Static.h
@@ -21,6 +21,10 @@
 
 #include <binder/IBinder.h>
 #include <binder/ProcessState.h>
+#ifndef __ANDROID_VNDK__
+#include <binder/IPermissionController.h>
+#endif
+#include <binder/IServiceManager.h>
 
 namespace android {
 
@@ -31,4 +35,12 @@
 extern Mutex& gProcessMutex;
 extern sp<ProcessState> gProcess;
 
+// For IServiceManager.cpp
+extern Mutex gDefaultServiceManagerLock;
+extern sp<IServiceManager> gDefaultServiceManager;
+#ifndef __ANDROID_VNDK__
+extern sp<IPermissionController> gPermissionController;
+#endif
+extern bool gSystemBootCompleted;
+
 }   // namespace android
diff --git a/libs/binder/include/private/binder/binder_module.h b/libs/binder/include/private/binder/binder_module.h
index c22be9f..2f11622 100644
--- a/libs/binder/include/private/binder/binder_module.h
+++ b/libs/binder/include/private/binder/binder_module.h
@@ -23,16 +23,6 @@
 
 /* obtain structures and constants from the kernel header */
 
-// TODO(b/31559095): bionic on host
-#ifndef __ANDROID__
-#define __packed __attribute__((__packed__))
-#endif
-
-// TODO(b/31559095): bionic on host
-#if defined(B_PACK_CHARS) && !defined(_UAPI_LINUX_BINDER_H)
-#undef B_PACK_CHARS
-#endif
-
 #include <sys/ioctl.h>
 #include <linux/android/binder.h>
 
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index c0ea6d7..21bef2e 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -14,30 +14,13 @@
  * limitations under the License.
  */
 
-// TODO(b/31559095): bionic on host should define this
-cc_defaults {
-    name: "libbinder_ndk_host_user",
-    target: {
-        host: {
-            cflags: [
-                "-D__INTRODUCED_IN(n)=",
-                "-D__assert(a,b,c)=",
-                // We want all the APIs to be available on the host.
-                "-D__ANDROID_API__=10000",
-            ],
-        },
-    },
-}
-
-cc_library_shared {
+cc_library {
     name: "libbinder_ndk",
-
-    defaults: ["libbinder_ndk_host_user"],
-    host_supported: true,
+    vendor_available: true,
 
     export_include_dirs: [
         "include_ndk",
-        "include_platform",
+        "include_apex",
     ],
 
     cflags: [
@@ -51,7 +34,6 @@
         "ibinder_jni.cpp",
         "parcel.cpp",
         "process.cpp",
-        "stability.cpp",
         "status.cpp",
         "service_manager.cpp",
     ],
@@ -70,17 +52,10 @@
         "jni_headers",
     ],
 
-    target: {
-        linux: {
-            version_script: "libbinder_ndk.map.txt",
-        },
-    },
+    version_script: "libbinder_ndk.map.txt",
     stubs: {
         symbol_file: "libbinder_ndk.map.txt",
-        versions: [
-            "29",
-            "30",
-        ],
+        versions: ["29"],
     },
 }
 
@@ -99,12 +74,3 @@
     symbol_file: "libbinder_ndk.map.txt",
     first_version: "29",
 }
-
-llndk_library {
-    name: "libbinder_ndk",
-    symbol_file: "libbinder_ndk.map.txt",
-    export_include_dirs: [
-        "include_ndk",
-        "include_platform",
-    ],
-}
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index e752c45..bd6886d 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -17,7 +17,6 @@
 #include <android/binder_ibinder.h>
 #include "ibinder_internal.h"
 
-#include <android/binder_stability.h>
 #include <android/binder_status.h>
 #include "parcel_internal.h"
 #include "status_internal.h"
@@ -543,8 +542,7 @@
         return STATUS_UNKNOWN_TRANSACTION;
     }
 
-    constexpr binder_flags_t kAllFlags = FLAG_PRIVATE_VENDOR | FLAG_ONEWAY;
-    if ((flags & ~kAllFlags) != 0) {
+    if ((flags & ~FLAG_ONEWAY) != 0) {
         LOG(ERROR) << __func__ << ": Unrecognized flags sent: " << flags;
         return STATUS_BAD_VALUE;
     }
@@ -591,40 +589,3 @@
 
     recipient->decStrong(nullptr);
 }
-
-binder_status_t AIBinder_getExtension(AIBinder* binder, AIBinder** outExt) {
-    if (binder == nullptr || outExt == nullptr) {
-        if (outExt != nullptr) {
-            *outExt = nullptr;
-        }
-        return STATUS_UNEXPECTED_NULL;
-    }
-
-    sp<IBinder> ext;
-    status_t res = binder->getBinder()->getExtension(&ext);
-
-    if (res != android::OK) {
-        *outExt = nullptr;
-        return PruneStatusT(res);
-    }
-
-    sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(ext);
-    if (ret != nullptr) ret->incStrong(binder);
-
-    *outExt = ret.get();
-    return STATUS_OK;
-}
-
-binder_status_t AIBinder_setExtension(AIBinder* binder, AIBinder* ext) {
-    if (binder == nullptr || ext == nullptr) {
-        return STATUS_UNEXPECTED_NULL;
-    }
-
-    ABBinder* rawBinder = binder->asABBinder();
-    if (rawBinder == nullptr) {
-        return STATUS_INVALID_OPERATION;
-    }
-
-    rawBinder->setExtension(ext->getBinder());
-    return STATUS_OK;
-}
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_apex/android/binder_manager.h
similarity index 100%
rename from libs/binder/ndk/include_platform/android/binder_manager.h
rename to libs/binder/ndk/include_apex/android/binder_manager.h
diff --git a/libs/binder/ndk/include_platform/android/binder_process.h b/libs/binder/ndk/include_apex/android/binder_process.h
similarity index 92%
rename from libs/binder/ndk/include_platform/android/binder_process.h
rename to libs/binder/ndk/include_apex/android/binder_process.h
index fdefbb4..69e6387 100644
--- a/libs/binder/ndk/include_platform/android/binder_process.h
+++ b/libs/binder/ndk/include_apex/android/binder_process.h
@@ -27,7 +27,7 @@
 void ABinderProcess_startThreadPool();
 /**
  * This sets the maximum number of threads that can be started in the threadpool. By default, after
- * startThreadPool is called, this is 15. If it is called additional times, it will only prevent
+ * startThreadPool is called, this is one. If it is called additional times, it will only prevent
  * the kernel from starting new threads and will not delete already existing threads.
  */
 bool ABinderProcess_setThreadPoolMaxThreadCount(uint32_t numThreads);
diff --git a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
index 946ccb7..c6868b0 100644
--- a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -21,7 +21,7 @@
 
 /**
  * @file binder_auto_utils.h
- * @brief These objects provide a more C++-like thin interface to the binder.
+ * @brief These objects provide a more C++-like thin interface to the .
  */
 
 #pragma once
@@ -159,17 +159,13 @@
      */
     T* getR() { return &mT; }
 
-    // copy-constructing/assignment is disallowed
+    // copy-constructing, or move/copy assignment is disallowed
     ScopedAResource(const ScopedAResource&) = delete;
     ScopedAResource& operator=(const ScopedAResource&) = delete;
+    ScopedAResource& operator=(ScopedAResource&&) = delete;
 
-    // move-constructing/assignment is okay
+    // move-constructing is okay
     ScopedAResource(ScopedAResource&& other) : mT(std::move(other.mT)) { other.mT = DEFAULT; }
-    ScopedAResource& operator=(ScopedAResource&& other) {
-        set(other.mT);
-        other.mT = DEFAULT;
-        return *this;
-    }
 
    private:
     T mT;
@@ -201,54 +197,16 @@
     explicit ScopedAStatus(AStatus* a = nullptr) : ScopedAResource(a) {}
     ~ScopedAStatus() {}
     ScopedAStatus(ScopedAStatus&&) = default;
-    ScopedAStatus& operator=(ScopedAStatus&&) = default;
 
     /**
      * See AStatus_isOk.
      */
-    bool isOk() const { return get() != nullptr && AStatus_isOk(get()); }
+    bool isOk() { return get() != nullptr && AStatus_isOk(get()); }
 
     /**
-     * See AStatus_getExceptionCode
-     */
-    binder_exception_t getExceptionCode() const { return AStatus_getExceptionCode(get()); }
-
-    /**
-     * See AStatus_getServiceSpecificError
-     */
-    int32_t getServiceSpecificError() const { return AStatus_getServiceSpecificError(get()); }
-
-    /**
-     * See AStatus_getStatus
-     */
-    binder_status_t getStatus() const { return AStatus_getStatus(get()); }
-
-    /**
-     * See AStatus_getMessage
-     */
-    const char* getMessage() const { return AStatus_getMessage(get()); }
-
-    /**
-     * Convenience methods for creating scoped statuses.
+     * Convenience method for okay status.
      */
     static ScopedAStatus ok() { return ScopedAStatus(AStatus_newOk()); }
-    static ScopedAStatus fromExceptionCode(binder_exception_t exception) {
-        return ScopedAStatus(AStatus_fromExceptionCode(exception));
-    }
-    static ScopedAStatus fromExceptionCodeWithMessage(binder_exception_t exception,
-                                                      const char* message) {
-        return ScopedAStatus(AStatus_fromExceptionCodeWithMessage(exception, message));
-    }
-    static ScopedAStatus fromServiceSpecificError(int32_t serviceSpecific) {
-        return ScopedAStatus(AStatus_fromServiceSpecificError(serviceSpecific));
-    }
-    static ScopedAStatus fromServiceSpecificErrorWithMessage(int32_t serviceSpecific,
-                                                             const char* message) {
-        return ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(serviceSpecific, message));
-    }
-    static ScopedAStatus fromStatus(binder_status_t status) {
-        return ScopedAStatus(AStatus_fromStatus(status));
-    }
 };
 
 /**
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 4d5c044..80d1254 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -34,7 +34,7 @@
 #include <android/binder_status.h>
 
 __BEGIN_DECLS
-#if __ANDROID_API__ >= 29
+#if __ANDROID_API__ >= __ANDROID_API_Q__
 
 // Also see TF_* in kernel's binder.h
 typedef uint32_t binder_flags_t;
@@ -165,8 +165,6 @@
  *
  * None of these parameters can be null.
  *
- * Available since API level 29.
- *
  * \param interfaceDescriptor this is a unique identifier for the class. This is used internally for
  * sanity checks on transactions.
  * \param onCreate see AIBinder_Class_onCreate.
@@ -201,8 +199,6 @@
  * If this isn't set, nothing will be dumped when dump is called (for instance with
  * android.os.Binder#dump). Must be called before any instance of the class is created.
  *
- * Available since API level 29.
- *
  * \param dump function to call when an instance of this binder class is being dumped.
  */
 void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) __INTRODUCED_IN(29);
@@ -224,8 +220,6 @@
  * these two objects are actually equal using the AIBinder pointer alone (which they should be able
  * to do). Also see the suggested memory ownership model suggested above.
  *
- * Available since API level 29.
- *
  * \param clazz the type of the object to be created.
  * \param args the args to pass to AIBinder_onCreate for that class.
  *
@@ -237,8 +231,6 @@
 /**
  * If this is hosted in a process other than the current one.
  *
- * Available since API level 29.
- *
  * \param binder the binder being queried.
  *
  * \return true if the AIBinder represents an object in another process.
@@ -252,8 +244,6 @@
  * updated as the result of a transaction made using AIBinder_transact, but it will also be updated
  * based on the results of bookkeeping or other transactions made internally.
  *
- * Available since API level 29.
- *
  * \param binder the binder being queried.
  *
  * \return true if the binder is alive.
@@ -265,8 +255,6 @@
  * return. Usually this is used to make sure that a binder is alive, as a placeholder call, or as a
  * sanity check.
  *
- * Available since API level 29.
- *
  * \param binder the binder being queried.
  *
  * \return STATUS_OK if the ping succeeds.
@@ -276,9 +264,7 @@
 /**
  * Built-in transaction for all binder objects. This dumps information about a given binder.
  *
- * See also AIBinder_Class_setOnDump, AIBinder_onDump.
- *
- * Available since API level 29.
+ * See also AIBinder_Class_setOnDump, AIBinder_onDump
  *
  * \param binder the binder to dump information about
  * \param fd where information should be dumped to
@@ -301,8 +287,6 @@
  *
  * If binder is local, this will return STATUS_INVALID_OPERATION.
  *
- * Available since API level 29.
- *
  * \param binder the binder object you want to receive death notifications from.
  * \param recipient the callback that will receive notifications when/if the binder dies.
  * \param cookie the value that will be passed to the death recipient on death.
@@ -322,8 +306,6 @@
  * If the binder dies, it will automatically unlink. If the binder is deleted, it will be
  * automatically unlinked.
  *
- * Available since API level 29.
- *
  * \param binder the binder object to remove a previously linked death recipient from.
  * \param recipient the callback to remove.
  * \param cookie the cookie used to link to death.
@@ -340,11 +322,9 @@
  * This can be used with higher-level system services to determine the caller's identity and check
  * permissions.
  *
- * Available since API level 29.
- *
  * \return calling uid or the current process's UID if this thread isn't processing a transaction.
  */
-uid_t AIBinder_getCallingUid() __INTRODUCED_IN(29);
+uid_t AIBinder_getCallingUid();
 
 /**
  * This returns the calling PID assuming that this thread is called from a thread that is processing
@@ -355,18 +335,14 @@
  * calling process dies and is replaced with another process with elevated permissions and the same
  * PID.
  *
- * Available since API level 29.
- *
  * \return calling pid or the current process's PID if this thread isn't processing a transaction.
  * If the transaction being processed is a oneway transaction, then this method will return 0.
  */
-pid_t AIBinder_getCallingPid() __INTRODUCED_IN(29);
+pid_t AIBinder_getCallingPid();
 
 /**
  * This can only be called if a strong reference to this object already exists in process.
  *
- * Available since API level 29.
- *
  * \param binder the binder object to add a refcount to.
  */
 void AIBinder_incStrong(AIBinder* binder) __INTRODUCED_IN(29);
@@ -374,8 +350,6 @@
 /**
  * This will delete the object and call onDestroy once the refcount reaches zero.
  *
- * Available since API level 29.
- *
  * \param binder the binder object to remove a refcount from.
  */
 void AIBinder_decStrong(AIBinder* binder) __INTRODUCED_IN(29);
@@ -383,8 +357,6 @@
 /**
  * For debugging only!
  *
- * Available since API level 29.
- *
  * \param binder the binder object to retrieve the refcount of.
  *
  * \return the number of strong-refs on this binder in this process. If binder is null, this will be
@@ -401,8 +373,6 @@
  * This returns true if the class association succeeds. If it fails, no change is made to the
  * binder object.
  *
- * Available since API level 29.
- *
  * \param binder the object to attach the class to.
  * \param clazz the clazz to attach to binder.
  *
@@ -413,8 +383,6 @@
 /**
  * Returns the class that this binder was constructed with or associated with.
  *
- * Available since API level 29.
- *
  * \param binder the object that is being queried.
  *
  * \return the class that this binder is associated with. If this binder wasn't created with
@@ -426,8 +394,6 @@
  * Value returned by onCreate for a local binder. For stateless classes (if onCreate returns
  * null), this also returns null. For a remote binder, this will always return null.
  *
- * Available since API level 29.
- *
  * \param binder the object that is being queried.
  *
  * \return the userdata returned from AIBinder_onCreate when this object was created. This may be
@@ -456,8 +422,6 @@
  * AIBinder_transact. Alternatively, if there is an error while filling out the parcel, it can be
  * deleted with AParcel_delete.
  *
- * Available since API level 29.
- *
  * \param binder the binder object to start a transaction on.
  * \param in out parameter for input data to the transaction.
  *
@@ -478,8 +442,6 @@
  * This does not affect the ownership of binder. The out parcel's ownership is passed to the caller
  * and must be released with AParcel_delete when finished reading.
  *
- * Available since API level 29.
- *
  * \param binder the binder object to transact on.
  * \param code the implementation-specific code representing which transaction should be taken.
  * \param in the implementation-specific input data to this transaction.
@@ -497,8 +459,6 @@
  * This does not take any ownership of the input binder, but it can be used to retrieve it if
  * something else in some process still holds a reference to it.
  *
- * Available since API level 29.
- *
  * \param binder object to create a weak pointer to.
  *
  * \return object representing a weak pointer to binder (or null if binder is null).
@@ -509,8 +469,6 @@
 /**
  * Deletes the weak reference. This will have no impact on the lifetime of the binder.
  *
- * Available since API level 29.
- *
  * \param weakBinder object created with AIBinder_Weak_new.
  */
 void AIBinder_Weak_delete(AIBinder_Weak* weakBinder) __INTRODUCED_IN(29);
@@ -519,8 +477,6 @@
  * If promotion succeeds, result will have one strong refcount added to it. Otherwise, this returns
  * null.
  *
- * Available since API level 29.
- *
  * \param weakBinder weak pointer to attempt retrieving the original object from.
  *
  * \return an AIBinder object with one refcount given to the caller or null.
@@ -531,8 +487,6 @@
 /**
  * This function is executed on death receipt. See AIBinder_linkToDeath/AIBinder_unlinkToDeath.
  *
- * Available since API level 29.
- *
  * \param cookie the cookie passed to AIBinder_linkToDeath.
  */
 typedef void (*AIBinder_DeathRecipient_onBinderDied)(void* cookie) __INTRODUCED_IN(29);
@@ -540,8 +494,6 @@
 /**
  * Creates a new binder death recipient. This can be attached to multiple different binder objects.
  *
- * Available since API level 29.
- *
  * \param onBinderDied the callback to call when this death recipient is invoked.
  *
  * \return the newly constructed object (or null if onBinderDied is null).
@@ -553,87 +505,11 @@
  * Deletes a binder death recipient. It is not necessary to call AIBinder_unlinkToDeath before
  * calling this as these will all be automatically unlinked.
  *
- * Available since API level 29.
- *
  * \param recipient the binder to delete (previously created with AIBinder_DeathRecipient_new).
  */
 void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) __INTRODUCED_IN(29);
 
-#endif  //__ANDROID_API__ >= 29
-
-#if __ANDROID_API__ >= 30
-
-/**
- * Gets the extension registered with AIBinder_setExtension.
- *
- * See AIBinder_setExtension.
- *
- * Available since API level 30.
- *
- * \param binder the object to get the extension of.
- * \param outExt the returned extension object. Will be null if there is no extension set or
- * non-null with one strong ref count.
- *
- * \return error of getting the interface (may be a transaction error if this is
- * remote binder). STATUS_UNEXPECTED_NULL if binder is null.
- */
-binder_status_t AIBinder_getExtension(AIBinder* binder, AIBinder** outExt) __INTRODUCED_IN(30);
-
-/**
- * Gets the extension of a binder interface. This allows a downstream developer to add
- * an extension to an interface without modifying its interface file. This should be
- * called immediately when the object is created before it is passed to another thread.
- * No thread safety is required.
- *
- * For instance, imagine if we have this interface:
- *     interface IFoo { void doFoo(); }
- *
- * A). Historical option that has proven to be BAD! Only the original
- *     author of an interface should change an interface. If someone
- *     downstream wants additional functionality, they should not ever
- *     change the interface or use this method.
- *
- *    BAD TO DO:  interface IFoo {                       BAD TO DO
- *    BAD TO DO:      void doFoo();                      BAD TO DO
- *    BAD TO DO: +    void doBar(); // adding a method   BAD TO DO
- *    BAD TO DO:  }                                      BAD TO DO
- *
- * B). Option that this method enables.
- *     Leave the original interface unchanged (do not change IFoo!).
- *     Instead, create a new interface in a downstream package:
- *
- *         package com.<name>; // new functionality in a new package
- *         interface IBar { void doBar(); }
- *
- *     When registering the interface, add:
- *         std::shared_ptr<MyFoo> foo = new MyFoo; // class in AOSP codebase
- *         std::shared_ptr<MyBar> bar = new MyBar; // custom extension class
- *         ... = AIBinder_setExtension(foo->asBinder().get(), bar->asBinder().get());
- *         // handle error
- *
- *     Then, clients of IFoo can get this extension:
- *         SpAIBinder binder = ...;
- *         std::shared_ptr<IFoo> foo = IFoo::fromBinder(binder); // handle if null
- *         SpAIBinder barBinder;
- *         ... = AIBinder_getExtension(barBinder.get());
- *         // handle error
- *         std::shared_ptr<IBar> bar = IBar::fromBinder(barBinder);
- *         // type is checked with AIBinder_associateClass
- *         // if bar is null, then there is no extension or a different
- *         // type of extension
- *
- * Available since API level 30.
- *
- * \param binder the object to get the extension on. Must be local.
- * \param ext the extension to set (binder will hold a strong reference to this)
- *
- * \return OK on success, STATUS_INVALID_OPERATION if binder is not local, STATUS_UNEXPECTED_NULL
- * if either binder is null.
- */
-binder_status_t AIBinder_setExtension(AIBinder* binder, AIBinder* ext) __INTRODUCED_IN(30);
-
-#endif  //__ANDROID_API__ >= 30
-
+#endif  //__ANDROID_API__ >= __ANDROID_API_Q__
 __END_DECLS
 
 /** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
index be3029c..124f36c 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
@@ -31,7 +31,7 @@
 #include <jni.h>
 
 __BEGIN_DECLS
-#if __ANDROID_API__ >= 29
+#if __ANDROID_API__ >= __ANDROID_API_Q__
 
 /**
  * Converts an android.os.IBinder object into an AIBinder* object.
@@ -40,8 +40,6 @@
  * AIBinder object, the original object is returned. The returned object has one refcount
  * associated with it, and so this should be accompanied with an AIBinder_decStrong call.
  *
- * Available since API level 29.
- *
  * \param env Java environment.
  * \param binder android.os.IBinder java object.
  *
@@ -57,8 +55,6 @@
  * If either env or the binder is null, null is returned. If this binder object was originally an
  * IBinder object, the original java object will be returned.
  *
- * Available since API level 29.
- *
  * \param env Java environment.
  * \param binder the object to convert.
  *
@@ -67,7 +63,7 @@
 __attribute__((warn_unused_result)) jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder)
         __INTRODUCED_IN(29);
 
-#endif  //__ANDROID_API__ >= 29
+#endif  //__ANDROID_API__ >= __ANDROID_API_Q__
 __END_DECLS
 
 /** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index 86b75b8..2258210 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -26,7 +26,6 @@
 
 #pragma once
 
-#include <stddef.h>
 #include <sys/cdefs.h>
 
 #include <android/binder_status.h>
@@ -35,7 +34,7 @@
 typedef struct AIBinder AIBinder;
 
 __BEGIN_DECLS
-#if __ANDROID_API__ >= 29
+#if __ANDROID_API__ >= __ANDROID_API_Q__
 
 /**
  * This object represents a package of data that can be sent between processes. When transacting, an
@@ -49,8 +48,6 @@
 /**
  * Cleans up a parcel.
  *
- * Available since API level 29.
- *
  * \param parcel A parcel returned by AIBinder_prepareTransaction or AIBinder_transact when a
  * transaction is being aborted.
  */
@@ -59,8 +56,6 @@
 /**
  * Sets the position within the parcel.
  *
- * Available since API level 29.
- *
  * \param parcel The parcel of which to set the position.
  * \param position Position of the parcel to set. This must be a value returned by
  * AParcel_getDataPosition. Positions are constant for a given parcel between processes.
@@ -73,8 +68,6 @@
 /**
  * Gets the current position within the parcel.
  *
- * Available since API level 29.
- *
  * \param parcel The parcel of which to get the position.
  *
  * \return The size of the parcel. This will always be greater than 0. The values returned by this
@@ -395,8 +388,6 @@
  * Writes an AIBinder to the next location in a non-null parcel. Can be null. This does not take any
  * refcounts of ownership of the binder from the client.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param binder the value to write to the parcel.
  *
@@ -408,8 +399,6 @@
  * Reads an AIBinder from the next location in a non-null parcel. One strong ref-count of ownership
  * is passed to the caller of this function.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param binder the out parameter for what is read from the parcel. This may be null.
  *
@@ -424,14 +413,12 @@
  *
  * This corresponds to the SDK's android.os.ParcelFileDescriptor.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param fd the value to write to the parcel (-1 to represent a null ParcelFileDescriptor).
  *
  * \return STATUS_OK on successful write.
  */
-binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd) __INTRODUCED_IN(29);
+binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd);
 
 /**
  * Reads an int from the next location in a non-null parcel.
@@ -440,16 +427,13 @@
  *
  * This corresponds to the SDK's android.os.ParcelFileDescriptor.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param fd the out parameter for what is read from the parcel (or -1 to represent a null
  * ParcelFileDescriptor)
  *
  * \return STATUS_OK on successful write.
  */
-binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd)
-        __INTRODUCED_IN(29);
+binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd);
 
 /**
  * Writes an AStatus object to the next location in a non-null parcel.
@@ -460,8 +444,6 @@
  * this happens or if writing the status object itself fails, the return value from this function
  * should be propagated to the client, and AParcel_readStatusHeader shouldn't be called.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param status the value to write to the parcel.
  *
@@ -474,8 +456,6 @@
  * Reads an AStatus from the next location in a non-null parcel. Ownership is passed to the caller
  * of this function.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param status the out parameter for what is read from the parcel.
  *
@@ -489,8 +469,6 @@
  *
  * If length is -1, and string is nullptr, this will write a 'null' string to the parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param string the null-terminated string to write to the parcel, at least of size 'length'.
  * \param length the length of the string to be written.
@@ -508,8 +486,6 @@
  * the output buffer from this read. If there is a 'null' string on the binder buffer, the allocator
  * will be called with length -1.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param stringData some external representation of a string.
  * \param allocator allocator that will be called once the size of the string is known.
@@ -527,8 +503,6 @@
  * returned from this function will be used to fill out the data from the parcel. If length is -1,
  * this will write a 'null' string array to the binder buffer.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param arrayData some external representation of an array.
  * \param length the length of the array to be written.
@@ -551,8 +525,6 @@
  * the contents of the string that is read. If the string array being read is 'null', this will
  * instead just pass -1 to AParcel_stringArrayAllocator.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called with arrayData once the size of the output
@@ -570,8 +542,6 @@
 /**
  * Writes an array of parcelables (user-defined types) to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -591,8 +561,6 @@
  * length is greater than zero, elementReader will be called for every index to read the
  * corresponding parcelable.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -609,8 +577,6 @@
 /**
  * Writes int32_t value to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -621,8 +587,6 @@
 /**
  * Writes uint32_t value to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -633,8 +597,6 @@
 /**
  * Writes int64_t value to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -645,8 +607,6 @@
 /**
  * Writes uint64_t value to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -657,8 +617,6 @@
 /**
  * Writes float value to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -669,8 +627,6 @@
 /**
  * Writes double value to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -681,8 +637,6 @@
 /**
  * Writes bool value to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -693,8 +647,6 @@
 /**
  * Writes char16_t value to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -705,8 +657,6 @@
 /**
  * Writes int8_t value to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -717,8 +667,6 @@
 /**
  * Reads into int32_t value from the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -729,8 +677,6 @@
 /**
  * Reads into uint32_t value from the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -741,8 +687,6 @@
 /**
  * Reads into int64_t value from the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -753,8 +697,6 @@
 /**
  * Reads into uint64_t value from the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -765,8 +707,6 @@
 /**
  * Reads into float value from the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -777,8 +717,6 @@
 /**
  * Reads into double value from the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -789,8 +727,6 @@
 /**
  * Reads into bool value from the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -801,8 +737,6 @@
 /**
  * Reads into char16_t value from the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -813,8 +747,6 @@
 /**
  * Reads into int8_t value from the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -825,8 +757,6 @@
 /**
  * Writes an array of int32_t to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -839,8 +769,6 @@
 /**
  * Writes an array of uint32_t to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -853,8 +781,6 @@
 /**
  * Writes an array of int64_t to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -867,8 +793,6 @@
 /**
  * Writes an array of uint64_t to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -881,8 +805,6 @@
 /**
  * Writes an array of float to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -895,8 +817,6 @@
 /**
  * Writes an array of double to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -912,8 +832,6 @@
  * getter(arrayData, i) will be called for each i in [0, length) in order to get the underlying
  * values to write to the parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param arrayData some external representation of an array.
  * \param length the length of arrayData (or -1 if this represents a null array).
@@ -927,8 +845,6 @@
 /**
  * Writes an array of char16_t to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -941,8 +857,6 @@
 /**
  * Writes an array of int8_t to the next location in a non-null parcel.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -959,8 +873,6 @@
  * length is greater than zero, the buffer returned by the allocator will be filled with the
  * corresponding data
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -977,8 +889,6 @@
  * length is greater than zero, the buffer returned by the allocator will be filled with the
  * corresponding data
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -995,8 +905,6 @@
  * length is greater than zero, the buffer returned by the allocator will be filled with the
  * corresponding data
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -1013,8 +921,6 @@
  * length is greater than zero, the buffer returned by the allocator will be filled with the
  * corresponding data
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -1031,8 +937,6 @@
  * length is greater than zero, the buffer returned by the allocator will be filled with the
  * corresponding data
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -1049,8 +953,6 @@
  * length is greater than zero, the buffer returned by the allocator will be filled with the
  * corresponding data
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -1066,8 +968,6 @@
  * First, allocator will be called with the length of the array. Then, for every i in [0, length),
  * setter(arrayData, i, x) will be called where x is the value at the associated index.
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -1087,8 +987,6 @@
  * length is greater than zero, the buffer returned by the allocator will be filled with the
  * corresponding data
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -1105,8 +1003,6 @@
  * length is greater than zero, the buffer returned by the allocator will be filled with the
  * corresponding data
  *
- * Available since API level 29.
- *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -1118,7 +1014,7 @@
 
 // @END-PRIMITIVE-READ-WRITE
 
-#endif  //__ANDROID_API__ >= 29
+#endif  //__ANDROID_API__ >= __ANDROID_API_Q__
 __END_DECLS
 
 /** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h
index 78d70f8..2671b9b 100644
--- a/libs/binder/ndk/include_ndk/android/binder_status.h
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -30,7 +30,7 @@
 #include <sys/cdefs.h>
 
 __BEGIN_DECLS
-#if __ANDROID_API__ >= 29
+#if __ANDROID_API__ >= __ANDROID_API_Q__
 
 enum {
     STATUS_OK = 0,
@@ -105,8 +105,6 @@
 /**
  * New status which is considered a success.
  *
- * Available since API level 29.
- *
  * \return a newly constructed status object that the caller owns.
  */
 __attribute__((warn_unused_result)) AStatus* AStatus_newOk() __INTRODUCED_IN(29);
@@ -114,8 +112,6 @@
 /**
  * New status with exception code.
  *
- * Available since API level 29.
- *
  * \param exception the code that this status should represent. If this is EX_NONE, then this
  * constructs an non-error status object.
  *
@@ -127,8 +123,6 @@
 /**
  * New status with exception code and message.
  *
- * Available since API level 29.
- *
  * \param exception the code that this status should represent. If this is EX_NONE, then this
  * constructs an non-error status object.
  * \param message the error message to associate with this status object.
@@ -143,8 +137,6 @@
  *
  * This is considered to be EX_TRANSACTION_FAILED with extra information.
  *
- * Available since API level 29.
- *
  * \param serviceSpecific an implementation defined error code.
  *
  * \return a newly constructed status object that the caller owns.
@@ -157,8 +149,6 @@
  *
  * This is considered to be EX_TRANSACTION_FAILED with extra information.
  *
- * Available since API level 29.
- *
  * \param serviceSpecific an implementation defined error code.
  * \param message the error message to associate with this status object.
  *
@@ -172,8 +162,6 @@
  * is returned by an API on AIBinder or AParcel, and that is to be returned from a method returning
  * an AStatus instance.
  *
- * Available since API level 29.
- *
  * \param a low-level error to associate with this status object.
  *
  * \return a newly constructed status object that the caller owns.
@@ -185,8 +173,6 @@
  * Whether this object represents a successful transaction. If this function returns true, then
  * AStatus_getExceptionCode will return EX_NONE.
  *
- * Available since API level 29.
- *
  * \param status the status being queried.
  *
  * \return whether the status represents a successful transaction. For more details, see below.
@@ -196,8 +182,6 @@
 /**
  * The exception that this status object represents.
  *
- * Available since API level 29.
- *
  * \param status the status being queried.
  *
  * \return the exception code that this object represents.
@@ -210,8 +194,6 @@
  * 0, the status object may still represent a different exception or status. To find out if this
  * transaction as a whole is okay, use AStatus_isOk instead.
  *
- * Available since API level 29.
- *
  * \param status the status being queried.
  *
  * \return the service-specific error code if the exception code is EX_SERVICE_SPECIFIC or 0.
@@ -224,8 +206,6 @@
  * object may represent a different exception or a service specific error. To find out if this
  * transaction as a whole is okay, use AStatus_isOk instead.
  *
- * Available since API level 29.
- *
  * \param status the status being queried.
  *
  * \return the status code if the exception code is EX_TRANSACTION_FAILED or 0.
@@ -238,8 +218,6 @@
  *
  * The returned string has the lifetime of the status object passed into this function.
  *
- * Available since API level 29.
- *
  * \param status the status being queried.
  *
  * \return the message associated with this error.
@@ -249,13 +227,11 @@
 /**
  * Deletes memory associated with the status instance.
  *
- * Available since API level 29.
- *
  * \param status the status to delete, returned from AStatus_newOk or one of the AStatus_from* APIs.
  */
 void AStatus_delete(AStatus* status) __INTRODUCED_IN(29);
 
-#endif  //__ANDROID_API__ >= 29
+#endif  //__ANDROID_API__ >= __ANDROID_API_Q__
 __END_DECLS
 
 /** @} */
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
deleted file mode 100644
index 2a4ded8..0000000
--- a/libs/binder/ndk/include_platform/android/binder_stability.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <android/binder_ibinder.h>
-
-__BEGIN_DECLS
-
-/**
- * Private addition to binder_flag_t.
- */
-enum {
-    /**
-     * Indicates that this transaction is coupled w/ vendor.img
-     */
-    FLAG_PRIVATE_VENDOR = 0x10000000,
-};
-
-#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || \
-        (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
-
-enum {
-    FLAG_PRIVATE_LOCAL = FLAG_PRIVATE_VENDOR,
-};
-
-/**
- * This interface has the stability of the vendor image.
- */
-void AIBinder_markVendorStability(AIBinder* binder);
-
-static inline void AIBinder_markCompilationUnitStability(AIBinder* binder) {
-    AIBinder_markVendorStability(binder);
-}
-
-#else  // defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) &&
-       // !defined(__ANDROID_APEX__))
-
-enum {
-    FLAG_PRIVATE_LOCAL = 0,
-};
-
-/**
- * This interface has the stability of the system image.
- */
-void AIBinder_markSystemStability(AIBinder* binder);
-
-static inline void AIBinder_markCompilationUnitStability(AIBinder* binder) {
-    AIBinder_markSystemStability(binder);
-}
-
-#endif  // defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) &&
-        // !defined(__ANDROID_APEX__))
-
-/**
- * This interface has system<->vendor stability
- */
-void AIBinder_markVintfStability(AIBinder* binder);
-
-__END_DECLS
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index d4d5387..7e65817 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -89,24 +89,12 @@
     AStatus_getStatus;
     AStatus_isOk;
     AStatus_newOk;
-    ABinderProcess_joinThreadPool; # apex vndk
-    ABinderProcess_setThreadPoolMaxThreadCount; # apex vndk
-    ABinderProcess_startThreadPool; # apex vndk
-    AServiceManager_addService; # apex vndk
-    AServiceManager_checkService; # apex vndk
-    AServiceManager_getService; # apex vndk
-  local:
-    *;
-};
-
-LIBBINDER_NDK30 { # introduced=30
-  global:
-    AIBinder_getExtension;
-    AIBinder_setExtension;
-
-    AIBinder_markSystemStability; # apex
-    AIBinder_markVendorStability; # vndk
-    AIBinder_markVintfStability; # apex vndk
+    ABinderProcess_joinThreadPool; # apex
+    ABinderProcess_setThreadPoolMaxThreadCount; # apex
+    ABinderProcess_startThreadPool; # apex
+    AServiceManager_addService; # apex
+    AServiceManager_checkService; # apex
+    AServiceManager_getService; # apex
   local:
     *;
 };
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index f18e118..ae2276e 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -50,7 +50,7 @@
     if (length < -1) return STATUS_BAD_VALUE;
 
     if (!isNullArray && length < 0) {
-        LOG(ERROR) << __func__ << ": non-null array but length is " << length;
+        LOG(ERROR) << __func__ << ": null array must be used with length == -1.";
         return STATUS_BAD_VALUE;
     }
     if (isNullArray && length > 0) {
diff --git a/libs/binder/ndk/scripts/format.sh b/libs/binder/ndk/scripts/format.sh
new file mode 100755
index 0000000..698d291
--- /dev/null
+++ b/libs/binder/ndk/scripts/format.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -e
+
+echo "Formatting code"
+
+bpfmt -w $(find $ANDROID_BUILD_TOP/frameworks/native/libs/binder/ndk/ -name "Android.bp")
+clang-format -i $(find $ANDROID_BUILD_TOP/frameworks/native/libs/binder/ndk/ -\( -name "*.cpp" -o -name "*.h" -\))
diff --git a/libs/binder/ndk/scripts/init_map.sh b/libs/binder/ndk/scripts/init_map.sh
new file mode 100755
index 0000000..3529b72
--- /dev/null
+++ b/libs/binder/ndk/scripts/init_map.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+# Simple helper for ease of development until this API is frozen.
+
+echo "LIBBINDER_NDK { # introduced=29"
+echo "  global:"
+{
+    grep -oP "AIBinder_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_ibinder.h;
+    grep -oP "AIBinder_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_ibinder_jni.h;
+    grep -oP "AParcel_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_parcel.h;
+    grep -oP "AStatus_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_status.h;
+} | sort | uniq | awk '{ print "    " $0 ";"; }'
+{
+    grep -oP "AServiceManager_[a-zA-Z0-9_]+(?=\()" include_apex/android/binder_manager.h;
+    grep -oP "ABinderProcess_[a-zA-Z0-9_]+(?=\()" include_apex/android/binder_process.h;
+} | sort | uniq | awk '{ print "    " $0 "; # apex"; }'
+echo "  local:"
+echo "    *;"
+echo "};"
diff --git a/libs/binder/ndk/stability.cpp b/libs/binder/ndk/stability.cpp
deleted file mode 100644
index a5b3ece..0000000
--- a/libs/binder/ndk/stability.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/binder_stability.h>
-
-#include <binder/Stability.h>
-#include "ibinder_internal.h"
-
-#include <log/log.h>
-
-using ::android::internal::Stability;
-
-#ifdef __ANDROID_VNDK__
-#error libbinder_ndk should only be built in a system context
-#endif
-
-#ifdef __ANDROID_NDK__
-#error libbinder_ndk should only be built in a system context
-#endif
-
-// explicit extern because symbol is only declared in header when __ANDROID_VNDK__
-extern "C" void AIBinder_markVendorStability(AIBinder* binder) {
-    Stability::markVndk(binder->getBinder().get());
-}
-
-void AIBinder_markSystemStability(AIBinder* binder) {
-    Stability::markCompilationUnit(binder->getBinder().get());
-}
-
-void AIBinder_markVintfStability(AIBinder* binder) {
-    Stability::markVintf(binder->getBinder().get());
-}
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index ebd08b2..8cd4e03 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -44,10 +44,10 @@
         "libandroid_runtime_lazy",
         "libbase",
         "libbinder",
-        "libbinder_ndk",
         "libutils",
     ],
     static_libs: [
+        "libbinder_ndk",
         "test_libbinder_ndk_library",
     ],
 }
@@ -67,32 +67,3 @@
     srcs: ["main_server.cpp"],
     gtest: false,
 }
-
-cc_test {
-    name: "binderVendorDoubleLoadTest",
-    vendor: true,
-    srcs: [
-        "binderVendorDoubleLoadTest.cpp",
-    ],
-    static_libs: [
-        "IBinderVendorDoubleLoadTest-cpp",
-        "IBinderVendorDoubleLoadTest-ndk_platform",
-        "libbinder_aidl_test_stub-ndk_platform",
-    ],
-    shared_libs: [
-        "libbase",
-        "libbinder",
-        "libbinder_ndk",
-        "libutils",
-    ],
-    test_suites: ["device-tests"],
-}
-
-aidl_interface {
-    name: "IBinderVendorDoubleLoadTest",
-    // TODO(b/119771576): only vendor is needed
-    vendor_available: true,
-    srcs: [
-        "IBinderVendorDoubleLoadTest.aidl",
-    ],
-}
diff --git a/libs/binder/ndk/test/AndroidTest.xml b/libs/binder/ndk/test/AndroidTest.xml
deleted file mode 100644
index 89646f7..0000000
--- a/libs/binder/ndk/test/AndroidTest.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 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.
--->
-<configuration description="Runs binderVendorDoubleLoadTest.">
-    <option name="test-suite-tag" value="apct" />
-    <option name="test-suite-tag" value="apct-native" />
-
-    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
-
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
-        <option name="cleanup" value="true" />
-        <option name="push" value="binderVendorDoubleLoadTest->/data/nativetest/vendor/binderVendorDoubleLoadTest" />
-    </target_preparer>
-
-    <test class="com.android.tradefed.testtype.GTest" >
-        <option name="native-test-device-path" value="/data/nativetest/vendor" />
-        <option name="module-name" value="binderVendorDoubleLoadTest" />
-    </test>
-</configuration>
-
diff --git a/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl b/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl
deleted file mode 100644
index 3a5bd9c..0000000
--- a/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-interface IBinderVendorDoubleLoadTest {
-    @utf8InCpp String RepeatString(@utf8InCpp String toRepeat);
-}
diff --git a/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp b/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp
deleted file mode 100644
index d3ccdc2..0000000
--- a/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <BnBinderVendorDoubleLoadTest.h>
-#include <aidl/BnBinderVendorDoubleLoadTest.h>
-#include <aidl/android/os/IServiceManager.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/strings.h>
-#include <android/binder_ibinder.h>
-#include <android/binder_manager.h>
-#include <android/binder_process.h>
-#include <android/binder_stability.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
-#include <binder/Stability.h>
-#include <binder/Status.h>
-#include <gtest/gtest.h>
-
-#include <sys/prctl.h>
-
-using namespace android;
-using ::android::base::EndsWith;
-using ::android::base::GetProperty;
-using ::android::base::Split;
-using ::android::binder::Status;
-using ::android::internal::Stability;
-using ::ndk::ScopedAStatus;
-using ::ndk::SharedRefBase;
-using ::ndk::SpAIBinder;
-
-static const std::string kLocalNdkServerName = "NdkServer-local-IBinderVendorDoubleLoadTest";
-static const std::string kRemoteNdkServerName = "NdkServer-remote-IBinderVendorDoubleLoadTest";
-
-class NdkServer : public aidl::BnBinderVendorDoubleLoadTest {
-    ScopedAStatus RepeatString(const std::string& in, std::string* out) override {
-        *out = in;
-        return ScopedAStatus::ok();
-    }
-};
-class CppServer : public BnBinderVendorDoubleLoadTest {
-    Status RepeatString(const std::string& in, std::string* out) override {
-        *out = in;
-        return Status::ok();
-    }
-};
-
-TEST(DoubleBinder, VendorCppCantCallIntoSystem) {
-    Vector<String16> services = defaultServiceManager()->listServices();
-    EXPECT_TRUE(services.empty());
-}
-
-TEST(DoubleBinder, VendorCppCantRegisterService) {
-    sp<CppServer> cppServer = new CppServer;
-    status_t status = defaultServiceManager()->addService(String16("anything"), cppServer);
-    EXPECT_EQ(EX_TRANSACTION_FAILED, status);
-}
-
-TEST(DoubleBinder, CppVendorCantManuallyMarkVintfStability) {
-    // this test also implies that stability logic is turned on in vendor
-    ASSERT_DEATH(
-            {
-                sp<IBinder> binder = new CppServer();
-                Stability::markVintf(binder.get());
-            },
-            "Should only mark known object.");
-}
-
-TEST(DoubleBinder, NdkVendorCantManuallyMarkVintfStability) {
-    // this test also implies that stability logic is turned on in vendor
-    ASSERT_DEATH(
-            {
-                std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
-                AIBinder_markVintfStability(ndkServer->asBinder().get());
-            },
-            "Should only mark known object.");
-}
-
-TEST(DoubleBinder, CallIntoNdk) {
-    for (const std::string& serviceName : {kLocalNdkServerName, kRemoteNdkServerName}) {
-        SpAIBinder binder = SpAIBinder(AServiceManager_checkService(serviceName.c_str()));
-        ASSERT_NE(nullptr, binder.get()) << serviceName;
-        EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get())) << serviceName;
-
-        std::shared_ptr<aidl::IBinderVendorDoubleLoadTest> server =
-                aidl::IBinderVendorDoubleLoadTest::fromBinder(binder);
-
-        ASSERT_NE(nullptr, server.get()) << serviceName;
-
-        EXPECT_EQ(STATUS_OK, AIBinder_ping(server->asBinder().get()));
-
-        std::string outString;
-        ScopedAStatus status = server->RepeatString("foo", &outString);
-        EXPECT_EQ(STATUS_OK, AStatus_getExceptionCode(status.get())) << serviceName;
-        EXPECT_EQ("foo", outString) << serviceName;
-    }
-}
-
-TEST(DoubleBinder, CallIntoSystemStabilityNdk) {
-    // picking an arbitrary system service
-    SpAIBinder binder = SpAIBinder(AServiceManager_checkService("manager"));
-    ASSERT_NE(nullptr, binder.get());
-
-    // can make stable transaction to system server
-    EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get()));
-
-    using aidl::android::os::IServiceManager;
-    std::shared_ptr<IServiceManager> manager = IServiceManager::fromBinder(binder);
-    ASSERT_NE(nullptr, manager.get());
-
-    std::vector<std::string> services;
-    ASSERT_EQ(
-            STATUS_BAD_TYPE,
-            manager->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &services).getStatus());
-}
-
-void initDrivers() {
-    // Explicitly instantiated with the same driver that system would use.
-    // __ANDROID_VNDK__ right now uses /dev/vndbinder by default.
-    ProcessState::initWithDriver("/dev/binder");
-    ProcessState::self()->startThreadPool();
-    ABinderProcess_startThreadPool();
-}
-
-int main(int argc, char** argv) {
-    ::testing::InitGoogleTest(&argc, argv);
-
-    if (fork() == 0) {
-        // child process
-
-        prctl(PR_SET_PDEATHSIG, SIGHUP);
-
-        initDrivers();
-
-        // REMOTE SERVERS
-        std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
-        CHECK(STATUS_OK == AServiceManager_addService(ndkServer->asBinder().get(),
-                                                      kRemoteNdkServerName.c_str()));
-
-        // OR sleep forever or whatever, it doesn't matter
-        IPCThreadState::self()->joinThreadPool(true);
-        exit(1);  // should not reach
-    }
-
-    sleep(1);
-
-    initDrivers();
-
-    // LOCAL SERVERS
-    std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
-    AServiceManager_addService(ndkServer->asBinder().get(), kLocalNdkServerName.c_str());
-
-    return RUN_ALL_TESTS();
-}
diff --git a/libs/binder/ndk/update.sh b/libs/binder/ndk/update.sh
new file mode 100755
index 0000000..9a4577f
--- /dev/null
+++ b/libs/binder/ndk/update.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+set -ex
+
+# This script makes sure that the source code is in sync with the various scripts
+./scripts/gen_parcel_helper.py
+./scripts/format.sh
+./scripts/init_map.sh > libbinder_ndk.map.txt
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 5a7f9a9..c451780 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -19,34 +19,45 @@
     cflags: [
         "-Wall",
         "-Werror",
+        "-Wno-unused-private-field",
+        "-Wno-unused-variable",
     ],
 }
 
 cc_test {
     name: "binderDriverInterfaceTest_IPC_32",
-    defaults: ["binder_test_defaults"],
     srcs: ["binderDriverInterfaceTest.cpp"],
+    defaults: ["binder_test_defaults"],
     compile_multilib: "32",
     cflags: ["-DBINDER_IPC_32BIT=1"],
 }
 
 cc_test {
-    name: "binderDriverInterfaceTest",
-    defaults: ["binder_test_defaults"],
     product_variables: {
         binder32bit: {
             cflags: ["-DBINDER_IPC_32BIT=1"],
         },
     },
 
+    name: "binderDriverInterfaceTest",
     srcs: ["binderDriverInterfaceTest.cpp"],
-    test_suites: ["device-tests"],
+    defaults: ["binder_test_defaults"],
+}
+
+cc_test {
+    name: "binderValueTypeTest",
+    srcs: ["binderValueTypeTest.cpp"],
+    defaults: ["binder_test_defaults"],
+    shared_libs: [
+        "libbinder",
+        "libutils",
+    ],
 }
 
 cc_test {
     name: "binderLibTest_IPC_32",
-    defaults: ["binder_test_defaults"],
     srcs: ["binderLibTest.cpp"],
+    defaults: ["binder_test_defaults"],
     shared_libs: [
         "libbinder",
         "libutils",
@@ -56,27 +67,25 @@
 }
 
 cc_test {
-    name: "binderLibTest",
-    defaults: ["binder_test_defaults"],
     product_variables: {
         binder32bit: {
             cflags: ["-DBINDER_IPC_32BIT=1"],
         },
     },
 
+    defaults: ["binder_test_defaults"],
+    name: "binderLibTest",
     srcs: ["binderLibTest.cpp"],
     shared_libs: [
         "libbinder",
         "libutils",
     ],
-    test_suites: ["device-tests"],
-    require_root: true,
 }
 
 cc_test {
     name: "binderThroughputTest",
-    defaults: ["binder_test_defaults"],
     srcs: ["binderThroughputTest.cpp"],
+    defaults: ["binder_test_defaults"],
     shared_libs: [
         "libbinder",
         "libutils",
@@ -92,20 +101,19 @@
 
 cc_test {
     name: "binderTextOutputTest",
-    defaults: ["binder_test_defaults"],
     srcs: ["binderTextOutputTest.cpp"],
+    defaults: ["binder_test_defaults"],
     shared_libs: [
         "libbinder",
         "libutils",
         "libbase",
     ],
-    test_suites: ["device-tests"],
 }
 
 cc_test {
     name: "schd-dbg",
-    defaults: ["binder_test_defaults"],
     srcs: ["schd-dbg.cpp"],
+    defaults: ["binder_test_defaults"],
     shared_libs: [
         "libbinder",
         "libutils",
@@ -115,11 +123,16 @@
 
 cc_test {
     name: "binderSafeInterfaceTest",
-    defaults: ["binder_test_defaults"],
     srcs: ["binderSafeInterfaceTest.cpp"],
+    defaults: ["binder_test_defaults"],
 
     cppflags: [
-        "-Wextra",
+        "-Weverything",
+        "-Wno-c++98-compat",
+        "-Wno-c++98-compat-pedantic",
+        "-Wno-global-constructors",
+        "-Wno-padded",
+        "-Wno-weak-vtables",
     ],
 
     cpp_std: "experimental",
@@ -131,35 +144,4 @@
         "liblog",
         "libutils",
     ],
-    test_suites: ["device-tests"],
-    require_root: true,
-}
-
-aidl_interface {
-    name: "binderStabilityTestIface",
-    srcs: [
-        "IBinderStabilityTest.aidl",
-    ],
-}
-
-cc_test {
-    name: "binderStabilityTest",
-    defaults: ["binder_test_defaults"],
-    srcs: [
-        "binderStabilityTest.cpp",
-    ],
-
-    shared_libs: [
-        "libbinder_ndk",
-        "libbinder",
-        "liblog",
-        "libutils",
-    ],
-    static_libs: [
-        "binderStabilityTestIface-cpp",
-        "binderStabilityTestIface-ndk_platform",
-    ],
-
-    test_suites: ["device-tests"],
-    require_root: true,
 }
diff --git a/libs/binder/tests/IBinderStabilityTest.aidl b/libs/binder/tests/IBinderStabilityTest.aidl
deleted file mode 100644
index 36e1c2c..0000000
--- a/libs/binder/tests/IBinderStabilityTest.aidl
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
-// THIS IS ONLY FOR TESTING!
-interface IBinderStabilityTest {
-    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
-    // THIS IS ONLY FOR TESTING!
-    void sendBinder(IBinder binder);
-
-    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
-    // THIS IS ONLY FOR TESTING!
-    void sendAndCallBinder(IBinder binder);
-
-    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
-    // THIS IS ONLY FOR TESTING!
-    IBinder returnNoStabilityBinder();
-
-    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
-    // THIS IS ONLY FOR TESTING!
-    IBinder returnLocalStabilityBinder();
-
-    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
-    // THIS IS ONLY FOR TESTING!
-    IBinder returnVintfStabilityBinder();
-
-    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
-    // THIS IS ONLY FOR TESTING!
-    IBinder returnVendorStabilityBinder();
-}
-// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
-// THIS IS ONLY FOR TESTING!
-// Construct and return a binder with a specific stability
diff --git a/libs/binder/tests/binderDriverInterfaceTest.cpp b/libs/binder/tests/binderDriverInterfaceTest.cpp
index f3ed6a6..77ebac8 100644
--- a/libs/binder/tests/binderDriverInterfaceTest.cpp
+++ b/libs/binder/tests/binderDriverInterfaceTest.cpp
@@ -230,6 +230,7 @@
 }
 
 TEST_F(BinderDriverInterfaceTest, Transaction) {
+    binder_uintptr_t cookie = 1234;
     struct {
         uint32_t cmd1;
         struct binder_transaction_data arg1;
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 5e0574a..78f1159 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -28,7 +28,6 @@
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 
-#include <private/binder/binder_module.h>
 #include <sys/epoll.h>
 
 #define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
@@ -67,6 +66,7 @@
     BINDER_LIB_TEST_LINK_DEATH_TRANSACTION,
     BINDER_LIB_TEST_WRITE_FILE_TRANSACTION,
     BINDER_LIB_TEST_WRITE_PARCEL_FILE_DESCRIPTOR_TRANSACTION,
+    BINDER_LIB_TEST_PROMOTE_WEAK_REF_TRANSACTION,
     BINDER_LIB_TEST_EXIT_TRANSACTION,
     BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION,
     BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION,
@@ -553,6 +553,50 @@
     ASSERT_TRUE(server != nullptr);
 }
 
+TEST_F(BinderLibTest, DeathNotificationNoRefs)
+{
+    status_t ret;
+
+    sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient();
+
+    {
+        sp<IBinder> binder = addServer();
+        ASSERT_TRUE(binder != nullptr);
+        ret = binder->linkToDeath(testDeathRecipient);
+        EXPECT_EQ(NO_ERROR, ret);
+    }
+    IPCThreadState::self()->flushCommands();
+    ret = testDeathRecipient->waitEvent(5);
+    EXPECT_EQ(NO_ERROR, ret);
+#if 0 /* Is there an unlink api that does not require a strong reference? */
+    ret = binder->unlinkToDeath(testDeathRecipient);
+    EXPECT_EQ(NO_ERROR, ret);
+#endif
+}
+
+TEST_F(BinderLibTest, DeathNotificationWeakRef)
+{
+    status_t ret;
+    wp<IBinder> wbinder;
+
+    sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient();
+
+    {
+        sp<IBinder> binder = addServer();
+        ASSERT_TRUE(binder != nullptr);
+        ret = binder->linkToDeath(testDeathRecipient);
+        EXPECT_EQ(NO_ERROR, ret);
+        wbinder = binder;
+    }
+    IPCThreadState::self()->flushCommands();
+    ret = testDeathRecipient->waitEvent(5);
+    EXPECT_EQ(NO_ERROR, ret);
+#if 0 /* Is there an unlink api that does not require a strong reference? */
+    ret = binder->unlinkToDeath(testDeathRecipient);
+    EXPECT_EQ(NO_ERROR, ret);
+#endif
+}
+
 TEST_F(BinderLibTest, DeathNotificationStrongRef)
 {
     status_t ret;
@@ -770,22 +814,20 @@
     EXPECT_TRUE(strong_from_weak == nullptr);
 }
 
-TEST_F(BinderLibTest, LocalGetExtension) {
-    sp<BBinder> binder = new BBinder();
-    sp<IBinder> ext = new BBinder();
-    binder->setExtension(ext);
-    EXPECT_EQ(ext, binder->getExtension());
-}
-
-TEST_F(BinderLibTest, RemoteGetExtension) {
+TEST_F(BinderLibTest, PromoteRemote) {
+    int ret;
+    Parcel data, reply;
+    sp<IBinder> strong = new BBinder();
     sp<IBinder> server = addServer();
+
     ASSERT_TRUE(server != nullptr);
+    ASSERT_TRUE(strong != nullptr);
 
-    sp<IBinder> extension;
-    EXPECT_EQ(NO_ERROR, server->getExtension(&extension));
-    ASSERT_NE(nullptr, extension.get());
+    ret = data.writeWeakBinder(strong);
+    EXPECT_EQ(NO_ERROR, ret);
 
-    EXPECT_EQ(NO_ERROR, extension->pingBinder());
+    ret = server->transact(BINDER_LIB_TEST_PROMOTE_WEAK_REF_TRANSACTION, data, &reply);
+    EXPECT_GE(ret, 0);
 }
 
 TEST_F(BinderLibTest, CheckHandleZeroBinderHighBitsZeroCookie) {
@@ -813,6 +855,7 @@
     wp<IBinder> keepFreedBinder;
     {
         Parcel data, reply;
+        data.writeBool(false); /* request weak reference */
         ret = server->transact(BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION, data, &reply);
         ASSERT_EQ(NO_ERROR, ret);
         struct flat_binder_object *freed = (struct flat_binder_object *)(reply.data());
@@ -821,9 +864,8 @@
          * delete its reference to it - otherwise the transaction
          * fails regardless of whether the driver is fixed.
          */
-        keepFreedBinder = reply.readStrongBinder();
+        keepFreedBinder = reply.readWeakBinder();
     }
-    IPCThreadState::self()->flushCommands();
     {
         Parcel data, reply;
         data.writeStrongBinder(server);
@@ -973,6 +1015,9 @@
 
 TEST_F(BinderLibTest, PropagateFlagSet)
 {
+    status_t ret;
+    Parcel data, reply;
+
     IPCThreadState::self()->clearPropagateWorkSource();
     IPCThreadState::self()->setCallingWorkSourceUid(100);
     EXPECT_EQ(true, IPCThreadState::self()->shouldPropagateWorkSource());
@@ -980,6 +1025,9 @@
 
 TEST_F(BinderLibTest, PropagateFlagCleared)
 {
+    status_t ret;
+    Parcel data, reply;
+
     IPCThreadState::self()->setCallingWorkSourceUid(100);
     IPCThreadState::self()->clearPropagateWorkSource();
     EXPECT_EQ(false, IPCThreadState::self()->shouldPropagateWorkSource());
@@ -987,6 +1035,9 @@
 
 TEST_F(BinderLibTest, PropagateFlagRestored)
 {
+    status_t ret;
+    Parcel data, reply;
+
     int token = IPCThreadState::self()->setCallingWorkSourceUid(100);
     IPCThreadState::self()->restoreCallingWorkSource(token);
 
@@ -1085,6 +1136,7 @@
             case BINDER_LIB_TEST_ADD_POLL_SERVER:
             case BINDER_LIB_TEST_ADD_SERVER: {
                 int ret;
+                uint8_t buf[1] = { 0 };
                 int serverid;
 
                 if (m_id != 0) {
@@ -1282,6 +1334,29 @@
                 if (ret != size) return UNKNOWN_ERROR;
                 return NO_ERROR;
             }
+            case BINDER_LIB_TEST_PROMOTE_WEAK_REF_TRANSACTION: {
+                int ret;
+                wp<IBinder> weak;
+                sp<IBinder> strong;
+                Parcel data2, reply2;
+                sp<IServiceManager> sm = defaultServiceManager();
+                sp<IBinder> server = sm->getService(binderLibTestServiceName);
+
+                weak = data.readWeakBinder();
+                if (weak == nullptr) {
+                    return BAD_VALUE;
+                }
+                strong = weak.promote();
+
+                ret = server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data2, &reply2);
+                if (ret != NO_ERROR)
+                    exit(EXIT_FAILURE);
+
+                if (strong == nullptr) {
+                    reply->setError(1);
+                }
+                return NO_ERROR;
+            }
             case BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION:
                 alarm(10);
                 return NO_ERROR;
@@ -1290,8 +1365,13 @@
                     ;
                 exit(EXIT_SUCCESS);
             case BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION: {
+                bool strongRef = data.readBool();
                 sp<IBinder> binder = new BBinder();
-                reply->writeStrongBinder(binder);
+                if (strongRef) {
+                    reply->writeStrongBinder(binder);
+                } else {
+                    reply->writeWeakBinder(binder);
+                }
                 return NO_ERROR;
             }
             case BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION: {
@@ -1319,6 +1399,7 @@
         bool m_serverStartRequested;
         sp<IBinder> m_serverStarted;
         sp<IBinder> m_strongRef;
+        bool m_callbackPending;
         sp<IBinder> m_callback;
 };
 
@@ -1331,13 +1412,6 @@
     BinderLibTestService* testServicePtr;
     {
         sp<BinderLibTestService> testService = new BinderLibTestService(index);
-
-        /*
-         * Normally would also contain functionality as well, but we are only
-         * testing the extension mechanism.
-         */
-        testService->setExtension(new BBinder());
-
         /*
          * We need this below, but can't hold a sp<> because it prevents the
          * node from being cleaned up automatically. It's safe in this case
@@ -1387,7 +1461,7 @@
               * We simulate a single-threaded process using the binder poll
               * interface; besides handling binder commands, it can also
               * issue outgoing transactions, by storing a callback in
-              * m_callback.
+              * m_callback and setting m_callbackPending.
               *
               * processPendingCall() will then issue that transaction.
               */
@@ -1414,6 +1488,8 @@
 }
 
 int main(int argc, char **argv) {
+    int ret;
+
     if (argc == 4 && !strcmp(argv[1], "--servername")) {
         binderservername = argv[2];
     } else {
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index 09f58cc..3b1db27 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -75,7 +75,7 @@
 
 private:
     int32_t mValue = 0;
-    __attribute__((unused)) uint8_t mPadding[4] = {}; // Avoids a warning from -Wpadded
+    uint8_t mPadding[4] = {}; // Avoids a warning from -Wpadded
 };
 
 struct TestFlattenable : Flattenable<TestFlattenable> {
@@ -743,7 +743,6 @@
     const std::vector<TestParcelable> a{TestParcelable{1}, TestParcelable{2}};
     std::vector<TestParcelable> aPlusOne;
     status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
-    ASSERT_EQ(NO_ERROR, result);
     ASSERT_EQ(a.size(), aPlusOne.size());
     for (size_t i = 0; i < a.size(); ++i) {
         ASSERT_EQ(a[i].getValue() + 1, aPlusOne[i].getValue());
diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp
deleted file mode 100644
index 1f2779a..0000000
--- a/libs/binder/tests/binderStabilityTest.cpp
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/binder_manager.h>
-#include <android/binder_stability.h>
-#include <binder/Binder.h>
-#include <binder/IBinder.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/Parcel.h>
-#include <binder/Stability.h>
-#include <gtest/gtest.h>
-
-#include <sys/prctl.h>
-
-#include "aidl/BnBinderStabilityTest.h"
-#include "BnBinderStabilityTest.h"
-
-using namespace android;
-using namespace ndk;
-using android::binder::Status;
-using android::internal::Stability; // for testing only!
-
-const String16 kSystemStabilityServer = String16("binder_stability_test_service_system");
-
-// This is handwritten so that we can test different stability levels w/o having the AIDL
-// compiler assign them. Hand-writing binder interfaces is considered a bad practice
-// sanity reasons. YOU SHOULD DEFINE AN AIDL INTERFACE INSTEAD!
-class BadStableBinder : public BBinder {
-public:
-    static constexpr uint32_t USER_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION;
-    static String16 kDescriptor;
-
-    bool gotUserTransaction = false;
-
-    static status_t doUserTransaction(const sp<IBinder>& binder) {
-        Parcel data, reply;
-        data.writeInterfaceToken(kDescriptor);
-        return binder->transact(USER_TRANSACTION, data, &reply, 0/*flags*/);
-    }
-
-    status_t onTransact(uint32_t code,
-            const Parcel& data, Parcel* reply, uint32_t flags) override {
-        if (code == USER_TRANSACTION) {
-            // not interested in this kind of stability. Make sure
-            // we have a test failure
-            LOG_ALWAYS_FATAL_IF(!data.enforceInterface(kDescriptor));
-
-            gotUserTransaction = true;
-
-            ALOGE("binder stability: Got user transaction");
-            return OK;
-        }
-        return BBinder::onTransact(code, data, reply, flags);
-    }
-
-    static sp<BadStableBinder> undef() {
-        sp<BadStableBinder> iface = new BadStableBinder();
-        return iface;
-    }
-
-    static sp<BadStableBinder> system() {
-        sp<BadStableBinder> iface = new BadStableBinder();
-        Stability::markCompilationUnit(iface.get()); // <- for test only
-        return iface;
-    }
-
-    static sp<BadStableBinder> vintf() {
-        sp<BadStableBinder> iface = new BadStableBinder();
-        Stability::markVintf(iface.get()); // <- for test only
-        return iface;
-    }
-
-    static sp<BadStableBinder> vendor() {
-        sp<BadStableBinder> iface = new BadStableBinder();
-        Stability::markVndk(iface.get()); // <- for test only
-        return iface;
-    }
-};
-String16 BadStableBinder::kDescriptor = String16("BadStableBinder.test");
-
-// NO! NO! NO! Do not even think of doing something like this!
-// This is for testing! If a class like this was actually used in production,
-// it would ruin everything!
-class MyBinderStabilityTest : public BnBinderStabilityTest {
-public:
-    Status sendBinder(const sp<IBinder>& /*binder*/) override {
-        return Status::ok();
-    }
-    Status sendAndCallBinder(const sp<IBinder>& binder) override {
-        Stability::debugLogStability("sendAndCallBinder got binder", binder);
-        return Status::fromExceptionCode(BadStableBinder::doUserTransaction(binder));
-    }
-    Status returnNoStabilityBinder(sp<IBinder>* _aidl_return) override {
-        *_aidl_return = BadStableBinder::undef();
-        return Status::ok();
-    }
-    Status returnLocalStabilityBinder(sp<IBinder>* _aidl_return) override {
-        *_aidl_return = BadStableBinder::system();
-        return Status::ok();
-    }
-    Status returnVintfStabilityBinder(sp<IBinder>* _aidl_return) override {
-        *_aidl_return = BadStableBinder::vintf();
-        return Status::ok();
-    }
-    Status returnVendorStabilityBinder(sp<IBinder>* _aidl_return) override {
-        *_aidl_return = BadStableBinder::vendor();
-        return Status::ok();
-    }
-};
-
-TEST(BinderStability, OnlyVintfStabilityBinderNeedsVintfDeclaration) {
-    EXPECT_FALSE(Stability::requiresVintfDeclaration(nullptr));
-    EXPECT_FALSE(Stability::requiresVintfDeclaration(BadStableBinder::undef()));
-    EXPECT_FALSE(Stability::requiresVintfDeclaration(BadStableBinder::system()));
-    EXPECT_FALSE(Stability::requiresVintfDeclaration(BadStableBinder::vendor()));
-
-    EXPECT_TRUE(Stability::requiresVintfDeclaration(BadStableBinder::vintf()));
-}
-
-TEST(BinderStability, VintfStabilityServerMustBeDeclaredInManifest) {
-    sp<IBinder> vintfServer = BadStableBinder::vintf();
-
-    for (const char* instance8 : {
-        ".", "/", "/.", "a.d.IFoo", "foo", "a.d.IFoo/foo"
-    }) {
-        String16 instance (instance8);
-
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-            android::defaultServiceManager()->addService(String16("."), vintfServer)) << instance8;
-        EXPECT_FALSE(android::defaultServiceManager()->isDeclared(instance)) << instance8;
-    }
-}
-
-TEST(BinderStability, CantCallVendorBinderInSystemContext) {
-    sp<IBinder> serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer);
-    auto server = interface_cast<IBinderStabilityTest>(serverBinder);
-
-    ASSERT_NE(nullptr, server.get());
-    ASSERT_NE(nullptr, IInterface::asBinder(server)->remoteBinder());
-
-    EXPECT_TRUE(server->sendBinder(BadStableBinder::undef()).isOk());
-    EXPECT_TRUE(server->sendBinder(BadStableBinder::system()).isOk());
-    EXPECT_TRUE(server->sendBinder(BadStableBinder::vintf()).isOk());
-    EXPECT_TRUE(server->sendBinder(BadStableBinder::vendor()).isOk());
-
-    {
-        sp<BadStableBinder> binder = BadStableBinder::undef();
-        EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
-        EXPECT_TRUE(binder->gotUserTransaction);
-    }
-    {
-        sp<BadStableBinder> binder = BadStableBinder::system();
-        EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
-        EXPECT_TRUE(binder->gotUserTransaction);
-    }
-    {
-        sp<BadStableBinder> binder = BadStableBinder::vintf();
-        EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
-        EXPECT_TRUE(binder->gotUserTransaction);
-    }
-    {
-        // !!! user-defined transaction may not be stable for remote server !!!
-        // !!! so, it does not work !!!
-        sp<BadStableBinder> binder = BadStableBinder::vendor();
-        EXPECT_EQ(BAD_TYPE, server->sendAndCallBinder(binder).exceptionCode());
-        EXPECT_FALSE(binder->gotUserTransaction);
-    }
-
-    sp<IBinder> out;
-    EXPECT_TRUE(server->returnNoStabilityBinder(&out).isOk());
-    ASSERT_NE(nullptr, out.get());
-    EXPECT_EQ(OK, out->pingBinder());
-    EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));
-
-    EXPECT_TRUE(server->returnLocalStabilityBinder(&out).isOk());
-    ASSERT_NE(nullptr, out.get());
-    EXPECT_EQ(OK, out->pingBinder());
-    EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));
-
-    EXPECT_TRUE(server->returnVintfStabilityBinder(&out).isOk());
-    ASSERT_NE(nullptr, out.get());
-    EXPECT_EQ(OK, out->pingBinder());
-    EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));
-
-    EXPECT_TRUE(server->returnVendorStabilityBinder(&out).isOk());
-    ASSERT_NE(nullptr, out.get());
-
-    // !!! libbinder-defined transaction works !!!
-    EXPECT_EQ(OK, out->pingBinder());
-
-    // !!! user-defined transaction may not be stable !!!
-    // !!! so, it does not work !!!
-    EXPECT_EQ(BAD_TYPE, BadStableBinder::doUserTransaction(out));
-}
-
-// This is handwritten so that we can test different stability levels w/o having the AIDL
-// compiler assign them. Hand-writing binder interfaces is considered a bad practice
-// sanity reasons. YOU SHOULD DEFINE AN AIDL INTERFACE INSTEAD!
-
-struct NdkBinderStable_DataClass {
-    bool gotUserTransaction = false;
-};
-void* NdkBadStableBinder_Class_onCreate(void* args) {
-    LOG_ALWAYS_FATAL_IF(args != nullptr, "Takes no args");
-    return static_cast<void*>(new NdkBinderStable_DataClass);
-}
-void NdkBadStableBinder_Class_onDestroy(void* userData) {
-    delete static_cast<NdkBinderStable_DataClass*>(userData);
-}
-NdkBinderStable_DataClass* NdkBadStableBinder_getUserData(AIBinder* binder) {
-    LOG_ALWAYS_FATAL_IF(binder == nullptr);
-    void* userData = AIBinder_getUserData(binder);
-    LOG_ALWAYS_FATAL_IF(userData == nullptr, "null data - binder is remote?");
-
-    return static_cast<NdkBinderStable_DataClass*>(userData);
-}
-binder_status_t NdkBadStableBinder_Class_onTransact(
-    AIBinder* binder, transaction_code_t code, const AParcel* /*in*/, AParcel* /*out*/) {
-
-    if (code == BadStableBinder::USER_TRANSACTION) {
-        ALOGE("ndk binder stability: Got user transaction");
-        NdkBadStableBinder_getUserData(binder)->gotUserTransaction = true;
-        return STATUS_OK;
-    }
-
-    return STATUS_UNKNOWN_TRANSACTION;
-}
-
-static AIBinder_Class* kNdkBadStableBinder =
-    AIBinder_Class_define(String8(BadStableBinder::kDescriptor).c_str(),
-                          NdkBadStableBinder_Class_onCreate,
-                          NdkBadStableBinder_Class_onDestroy,
-                          NdkBadStableBinder_Class_onTransact);
-
-// for testing only to get around __ANDROID_VNDK__ guard.
-extern "C" void AIBinder_markVendorStability(AIBinder* binder); // <- BAD DO NOT COPY
-
-TEST(BinderStability, NdkCantCallVendorBinderInSystemContext) {
-    SpAIBinder binder = SpAIBinder(AServiceManager_getService(
-        String8(kSystemStabilityServer).c_str()));
-
-    std::shared_ptr<aidl::IBinderStabilityTest> remoteServer =
-        aidl::IBinderStabilityTest::fromBinder(binder);
-
-    ASSERT_NE(nullptr, remoteServer.get());
-
-    SpAIBinder comp = SpAIBinder(AIBinder_new(kNdkBadStableBinder, nullptr /*args*/));
-    EXPECT_TRUE(remoteServer->sendBinder(comp).isOk());
-    EXPECT_TRUE(remoteServer->sendAndCallBinder(comp).isOk());
-    EXPECT_TRUE(NdkBadStableBinder_getUserData(comp.get())->gotUserTransaction);
-
-    SpAIBinder vendor = SpAIBinder(AIBinder_new(kNdkBadStableBinder, nullptr /*args*/));
-    AIBinder_markVendorStability(vendor.get());
-    EXPECT_TRUE(remoteServer->sendBinder(vendor).isOk());
-    EXPECT_FALSE(remoteServer->sendAndCallBinder(vendor).isOk());
-    EXPECT_FALSE(NdkBadStableBinder_getUserData(vendor.get())->gotUserTransaction);
-}
-
-class MarksStabilityInConstructor : public BBinder {
-public:
-    static bool gDestructed;
-
-    MarksStabilityInConstructor() {
-        Stability::markCompilationUnit(this);
-    }
-    ~MarksStabilityInConstructor() {
-        gDestructed = true;
-    }
-};
-bool MarksStabilityInConstructor::gDestructed = false;
-
-TEST(BinderStability, MarkingObjectNoDestructTest) {
-    ASSERT_FALSE(MarksStabilityInConstructor::gDestructed);
-
-    // best practice is to put this directly in an sp, but for this test, we
-    // want to explicitly check what happens before that happens
-    MarksStabilityInConstructor* binder = new MarksStabilityInConstructor();
-    ASSERT_FALSE(MarksStabilityInConstructor::gDestructed);
-
-    sp<MarksStabilityInConstructor> binderSp = binder;
-    ASSERT_FALSE(MarksStabilityInConstructor::gDestructed);
-
-    binderSp = nullptr;
-    ASSERT_TRUE(MarksStabilityInConstructor::gDestructed);
-}
-
-TEST(BinderStability, RemarkDies) {
-    ASSERT_DEATH({
-        sp<IBinder> binder = new BBinder();
-        Stability::markCompilationUnit(binder.get()); // <-- only called for tests
-        Stability::markVndk(binder.get()); // <-- only called for tests
-    }, "Should only mark known object.");
-}
-
-int main(int argc, char** argv) {
-    ::testing::InitGoogleTest(&argc, argv);
-
-    if (fork() == 0) {
-        // child process
-        prctl(PR_SET_PDEATHSIG, SIGHUP);
-
-        sp<IBinder> server = new MyBinderStabilityTest;
-        android::defaultServiceManager()->addService(kSystemStabilityServer, server);
-
-        IPCThreadState::self()->joinThreadPool(true);
-        exit(1);  // should not reach
-    }
-
-    // This is not racey. Just giving these services some time to register before we call
-    // getService which sleeps for much longer...
-    usleep(10000);
-
-    return RUN_ALL_TESTS();
-}
diff --git a/libs/binder/tests/binderValueTypeTest.cpp b/libs/binder/tests/binderValueTypeTest.cpp
new file mode 100644
index 0000000..f8922b0
--- /dev/null
+++ b/libs/binder/tests/binderValueTypeTest.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits>
+#include <cstddef>
+#include <vector>
+
+#include "android-base/file.h"
+#include <gtest/gtest.h>
+
+#include <binder/Parcel.h>
+#include <binder/Value.h>
+#include <binder/Debug.h>
+
+using ::android::binder::Value;
+using ::android::os::PersistableBundle;
+using ::android::String16;
+using ::std::vector;
+
+#define VALUE_TYPE_TEST(T, TYPENAME, VAL)         \
+    TEST(ValueType, Handles ## TYPENAME) {        \
+        T x = VAL;                                \
+        T y = T();                                \
+        Value value = VAL;                        \
+        ASSERT_FALSE(value.empty());              \
+        ASSERT_TRUE(value.is ## TYPENAME ());     \
+        ASSERT_TRUE(value.get ## TYPENAME (&y));  \
+        ASSERT_EQ(x, y);                          \
+        ASSERT_EQ(value, Value(y));               \
+        value.put ## TYPENAME (x);                \
+        ASSERT_EQ(value, Value(y));               \
+        value = Value();                          \
+        ASSERT_TRUE(value.empty());               \
+        ASSERT_NE(value, Value(y));               \
+        value = y;                                \
+        ASSERT_EQ(value, Value(x));               \
+    }
+
+#define VALUE_TYPE_VECTOR_TEST(T, TYPENAME, VAL)      \
+    TEST(ValueType, Handles ## TYPENAME ## Vector) {  \
+        vector<T> x;                                  \
+        vector<T> y;                                  \
+        x.push_back(VAL);                             \
+        x.push_back(T());                             \
+        Value value(x);                               \
+        ASSERT_FALSE(value.empty());                  \
+        ASSERT_TRUE(value.is ## TYPENAME ## Vector());    \
+        ASSERT_TRUE(value.get ## TYPENAME ## Vector(&y)); \
+        ASSERT_EQ(x, y);                              \
+        ASSERT_EQ(value, Value(y));                   \
+        value.put ## TYPENAME ## Vector(x);           \
+        ASSERT_EQ(value, Value(y));                   \
+        value = Value();                              \
+        ASSERT_TRUE(value.empty());                   \
+        ASSERT_NE(value, Value(y));                   \
+        value = y;                                    \
+        ASSERT_EQ(value, Value(x));                   \
+    }
+
+VALUE_TYPE_TEST(bool, Boolean, true)
+VALUE_TYPE_TEST(int32_t, Int, 31337)
+VALUE_TYPE_TEST(int64_t, Long, 13370133701337L)
+VALUE_TYPE_TEST(double, Double, 3.14159265358979323846)
+VALUE_TYPE_TEST(String16, String, String16("Lovely"))
+
+VALUE_TYPE_VECTOR_TEST(bool, Boolean, true)
+VALUE_TYPE_VECTOR_TEST(int32_t, Int, 31337)
+VALUE_TYPE_VECTOR_TEST(int64_t, Long, 13370133701337L)
+VALUE_TYPE_VECTOR_TEST(double, Double, 3.14159265358979323846)
+VALUE_TYPE_VECTOR_TEST(String16, String, String16("Lovely"))
+
+VALUE_TYPE_TEST(PersistableBundle, PersistableBundle, PersistableBundle())
+
+TEST(ValueType, HandlesClear) {
+    Value value;
+    ASSERT_TRUE(value.empty());
+    value.putInt(31337);
+    ASSERT_FALSE(value.empty());
+    value.clear();
+    ASSERT_TRUE(value.empty());
+}
+
+TEST(ValueType, HandlesSwap) {
+    Value value_a, value_b;
+    int32_t int_x;
+    value_a.putInt(31337);
+    ASSERT_FALSE(value_a.empty());
+    ASSERT_TRUE(value_b.empty());
+    value_a.swap(value_b);
+    ASSERT_FALSE(value_b.empty());
+    ASSERT_TRUE(value_a.empty());
+    ASSERT_TRUE(value_b.getInt(&int_x));
+    ASSERT_EQ(31337, int_x);
+}
diff --git a/libs/binder/tests/schd-dbg.cpp b/libs/binder/tests/schd-dbg.cpp
index ab4c56a..ec9534a 100644
--- a/libs/binder/tests/schd-dbg.cpp
+++ b/libs/binder/tests/schd-dbg.cpp
@@ -290,7 +290,6 @@
 
   sta = tickNow();
   status_t ret = workers[target]->transact(BINDER_NOP, data, &reply);
-  ASSERT(ret == NO_ERROR);
   end = tickNow();
   results_fifo->add_time(tickNano(sta, end));
 
diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp
index ee1a6a4..512b069 100644
--- a/libs/binderthreadstate/Android.bp
+++ b/libs/binderthreadstate/Android.bp
@@ -20,8 +20,6 @@
         enabled: true,
         support_system_process: true,
     },
-    host_supported: true,
-
     srcs: [
         "IPCThreadStateBase.cpp",
     ],
diff --git a/libs/dumputils/Android.bp b/libs/dumputils/Android.bp
index e403d36..3412e14 100644
--- a/libs/dumputils/Android.bp
+++ b/libs/dumputils/Android.bp
@@ -17,7 +17,9 @@
 
     shared_libs: [
         "libbase",
+        "libbinder",
         "libhidlbase",
+        "libhidltransport",
         "liblog",
         "libutils",
     ],
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 250f902..0477801 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -16,7 +16,9 @@
 #include <set>
 
 #include <android-base/file.h>
+#include <android-base/properties.h>
 #include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <dumputils/dump_utils.h>
 #include <log/log.h>
@@ -62,16 +64,40 @@
         "android.hardware.sensors@1.0::ISensors",
         "android.hardware.thermal@2.0::IThermal",
         "android.hardware.vr@1.0::IVr",
+        "android.hardware.automotive.audiocontrol@1.0::IAudioControl",
+        "android.hardware.automotive.vehicle@2.0::IVehicle",
+        "android.hardware.automotive.evs@1.0::IEvsCamera",
         NULL,
 };
 
-bool should_dump_hal_interface(const char* interface) {
+/* list of extra hal interfaces to dump containing process during native dumps */
+// This is filled when dumpstate is called.
+static std::set<const std::string> extra_hal_interfaces_to_dump;
+
+static void read_extra_hals_to_dump_from_property() {
+    // extra hals to dump are already filled
+    if (extra_hal_interfaces_to_dump.size() > 0) {
+        return;
+    }
+    std::string value = android::base::GetProperty("ro.dump.hals.extra", "");
+    std::vector<std::string> tokens = android::base::Split(value, ",");
+    for (const auto &token : tokens) {
+        std::string trimmed_token = android::base::Trim(token);
+        if (trimmed_token.length() == 0) {
+            continue;
+        }
+        extra_hal_interfaces_to_dump.insert(trimmed_token);
+    }
+}
+
+// check if interface is included in either default hal list or extra hal list
+bool should_dump_hal_interface(const std::string& interface) {
     for (const char** i = hal_interfaces_to_dump; *i; i++) {
-        if (!strcmp(*i, interface)) {
+        if (interface == *i) {
             return true;
         }
     }
-    return false;
+    return extra_hal_interfaces_to_dump.find(interface) != extra_hal_interfaces_to_dump.end();
 }
 
 bool should_dump_native_traces(const char* path) {
@@ -91,13 +117,15 @@
     sp<IServiceManager> manager = IServiceManager::getService();
     std::set<int> pids;
 
+    read_extra_hals_to_dump_from_property();
+
     Return<void> ret = manager->debugDump([&](auto& hals) {
         for (const auto &info : hals) {
             if (info.pid == static_cast<int>(IServiceManager::PidConstant::NO_PID)) {
                 continue;
             }
 
-            if (!should_dump_hal_interface(info.interfaceName.c_str())) {
+            if (!should_dump_hal_interface(info.interfaceName)) {
                 continue;
             }
 
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index bb9e263..6e59cc5 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -139,12 +139,8 @@
     return env;
 }
 
-int GraphicsEnv::getCanLoadSystemLibraries() {
-    if (property_get_bool("ro.debuggable", false) && prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
-        // Return an integer value since this crosses library boundaries
-        return 1;
-    }
-    return 0;
+bool GraphicsEnv::isDebuggable() {
+    return prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) > 0;
 }
 
 void GraphicsEnv::setDriverPathAndSphalLibraries(const std::string path,
diff --git a/libs/graphicsenv/OWNERS b/libs/graphicsenv/OWNERS
deleted file mode 100644
index c0bb75f..0000000
--- a/libs/graphicsenv/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-chrisforbes@google.com
-cnorthrop@google.com
-courtneygo@google.com
-lpy@google.com
-timvp@google.com
-zzyiwei@google.com
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 937bcd9..227b458 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -84,7 +84,16 @@
 public:
     static GraphicsEnv& getInstance();
 
-    int getCanLoadSystemLibraries();
+    // Check if the process is debuggable. It returns false except in any of the
+    // following circumstances:
+    // 1. ro.debuggable=1 (global debuggable enabled).
+    // 2. android:debuggable="true" in the manifest for an individual app.
+    // 3. An app which explicitly calls prctl(PR_SET_DUMPABLE, 1).
+    // 4. GraphicsEnv calls prctl(PR_SET_DUMPABLE, 1) in the presence of
+    //    <meta-data android:name="com.android.graphics.injectLayers.enable"
+    //               android:value="true"/>
+    //    in the application manifest.
+    bool isDebuggable();
 
     // Set a search path for loading graphics drivers. The path is a list of
     // directories separated by ':'. A directory can be contained in a zip file
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 166775b..e3e63ee 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -15,18 +15,6 @@
     name: "libgui_headers",
     vendor_available: true,
     export_include_dirs: ["include"],
-
-    // we must build this module to get the required header as that is generated
-    export_shared_lib_headers: [
-        "android.hidl.token@1.0-utils",
-        "android.hardware.graphics.bufferqueue@1.0",
-        "android.hardware.graphics.bufferqueue@2.0",
-    ],
-    shared_libs: [
-        "android.hidl.token@1.0-utils",
-        "android.hardware.graphics.bufferqueue@1.0",
-        "android.hardware.graphics.bufferqueue@2.0",
-    ],
 }
 
 cc_library_shared {
@@ -178,6 +166,8 @@
         "libEGL",
         "libGLESv2",
         "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
         "liblog",
         "libnativewindow",
         "libsync",
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 528bfb1..3a7cb44 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -166,7 +166,9 @@
                         mCore->mFreeBuffers.push_back(front->mSlot);
                     }
 
-                    listener = mCore->mConnectedProducerListener;
+                    if (mCore->mBufferReleasedCbEnabled) {
+                        listener = mCore->mConnectedProducerListener;
+                    }
                     ++numDroppedBuffers;
                 }
 
@@ -457,7 +459,9 @@
             mCore->mFreeBuffers.push_back(slot);
         }
 
-        listener = mCore->mConnectedProducerListener;
+        if (mCore->mBufferReleasedCbEnabled) {
+            listener = mCore->mConnectedProducerListener;
+        }
         BQ_LOGV("releaseBuffer: releasing slot %d", slot);
 
         mCore->mDequeueCondition.notify_all();
@@ -668,7 +672,7 @@
         BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers);
         mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
         VALIDATE_CONSISTENCY();
-        if (delta < 0) {
+        if (delta < 0 && mCore->mBufferReleasedCbEnabled) {
             listener = mCore->mConsumerListener;
         }
     }
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index e0e3431..0264bd2 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -65,6 +65,7 @@
     mConnectedApi(NO_CONNECTED_API),
     mLinkedToDeath(),
     mConnectedProducerListener(),
+    mBufferReleasedCbEnabled(false),
     mSlots(),
     mQueue(),
     mFreeSlots(),
@@ -260,6 +261,12 @@
 }
 
 void BufferQueueCore::discardFreeBuffersLocked() {
+    // Notify producer about the discarded buffers.
+    if (mConnectedProducerListener != nullptr && mFreeBuffers.size() > 0) {
+        std::vector<int32_t> freeBuffers(mFreeBuffers.begin(), mFreeBuffers.end());
+        mConnectedProducerListener->onBuffersDiscarded(freeBuffers);
+    }
+
     for (int s : mFreeBuffers) {
         mFreeSlots.insert(s);
         clearBufferSlotLocked(s);
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 92ab410..a317aaf 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -1221,9 +1221,8 @@
                     }
                     mCore->mLinkedToDeath = listener;
                 }
-                if (listener->needsReleaseNotify()) {
-                    mCore->mConnectedProducerListener = listener;
-                }
+                mCore->mConnectedProducerListener = listener;
+                mCore->mBufferReleasedCbEnabled = listener->needsReleaseNotify();
             }
             break;
         default:
diff --git a/libs/gui/IProducerListener.cpp b/libs/gui/IProducerListener.cpp
index 936063a..808e336 100644
--- a/libs/gui/IProducerListener.cpp
+++ b/libs/gui/IProducerListener.cpp
@@ -24,6 +24,7 @@
 enum {
     ON_BUFFER_RELEASED = IBinder::FIRST_CALL_TRANSACTION,
     NEEDS_RELEASE_NOTIFY,
+    ON_BUFFERS_DISCARDED,
 };
 
 class BpProducerListener : public BpInterface<IProducerListener>
@@ -56,6 +57,13 @@
         }
         return result;
     }
+
+    virtual void onBuffersDiscarded(const std::vector<int>& discardedSlots) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor());
+        data.writeInt32Vector(discardedSlots);
+        remote()->transact(ON_BUFFERS_DISCARDED, data, &reply, IBinder::FLAG_ONEWAY);
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -76,6 +84,10 @@
     virtual bool needsReleaseNotify() override {
         return mBase->needsReleaseNotify();
     }
+
+    virtual void onBuffersDiscarded(const std::vector<int32_t>& discardedSlots) override {
+        return mBase->onBuffersDiscarded(discardedSlots);
+    }
 };
 
 IMPLEMENT_HYBRID_META_INTERFACE(ProducerListener,
@@ -92,6 +104,17 @@
             CHECK_INTERFACE(IProducerListener, data, reply);
             reply->writeBool(needsReleaseNotify());
             return NO_ERROR;
+        case ON_BUFFERS_DISCARDED: {
+            CHECK_INTERFACE(IProducerListener, data, reply);
+            std::vector<int32_t> discardedSlots;
+            status_t result = data.readInt32Vector(&discardedSlots);
+            if (result != NO_ERROR) {
+                ALOGE("ON_BUFFERS_DISCARDED failed to read discardedSlots: %d", result);
+                return result;
+            }
+            onBuffersDiscarded(discardedSlots);
+            return NO_ERROR;
+        }
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
@@ -104,4 +127,7 @@
     return true;
 }
 
+void BnProducerListener::onBuffersDiscarded(const std::vector<int32_t>& /*discardedSlots*/) {
+}
+
 } // namespace android
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 12deaf0..e487792 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -88,7 +88,7 @@
         data.writeStrongBinder(applyToken);
         commands.write(data);
         data.writeInt64(desiredPresentTime);
-        data.writeStrongBinder(uncacheBuffer.token.promote());
+        data.writeWeakBinder(uncacheBuffer.token);
         data.writeUint64(uncacheBuffer.id);
 
         if (data.writeVectorSize(listenerCallbacks) == NO_ERROR) {
@@ -1036,7 +1036,7 @@
             int64_t desiredPresentTime = data.readInt64();
 
             client_cache_t uncachedBuffer;
-            uncachedBuffer.token = data.readStrongBinder();
+            uncachedBuffer.token = data.readWeakBinder();
             uncachedBuffer.id = data.readUint64();
 
             std::vector<ListenerCallbacks> listenerCallbacks;
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 42eb921..6066421 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -87,7 +87,7 @@
            colorTransform.asArray(), 16 * sizeof(float));
     output.writeFloat(cornerRadius);
     output.writeBool(hasListenerCallbacks);
-    output.writeStrongBinder(cachedBuffer.token.promote());
+    output.writeWeakBinder(cachedBuffer.token);
     output.writeUint64(cachedBuffer.id);
     output.writeParcelable(metadata);
 
@@ -157,7 +157,7 @@
     colorTransform = mat4(static_cast<const float*>(input.readInplace(16 * sizeof(float))));
     cornerRadius = input.readFloat();
     hasListenerCallbacks = input.readBool();
-    cachedBuffer.token = input.readStrongBinder();
+    cachedBuffer.token = input.readWeakBinder();
     cachedBuffer.id = input.readUint64();
     input.readParcelable(&metadata);
 
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 9fe5de8..b822319 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -35,6 +35,7 @@
 
 #include <ui/DisplayStatInfo.h>
 #include <ui/Fence.h>
+#include <ui/GraphicBuffer.h>
 #include <ui/HdrCapabilities.h>
 #include <ui/Region.h>
 
@@ -1287,6 +1288,14 @@
 }
 
 int Surface::connect(
+        int api, bool reportBufferRemoval, const sp<SurfaceListener>& sListener) {
+    if (sListener != nullptr) {
+        mListenerProxy = new ProducerListenerProxy(this, sListener);
+    }
+    return connect(api, mListenerProxy, reportBufferRemoval);
+}
+
+int Surface::connect(
         int api, const sp<IProducerListener>& listener, bool reportBufferRemoval) {
     ATRACE_CALL();
     ALOGV("Surface::connect");
@@ -1684,6 +1693,28 @@
     }
 }
 
+status_t Surface::getAndFlushBuffersFromSlots(const std::vector<int32_t>& slots,
+        std::vector<sp<GraphicBuffer>>* outBuffers) {
+    ALOGV("Surface::getAndFlushBuffersFromSlots");
+    for (int32_t i : slots) {
+        if (i < 0 || i >= NUM_BUFFER_SLOTS) {
+            ALOGE("%s: Invalid slotIndex: %d", __FUNCTION__, i);
+            return BAD_VALUE;
+        }
+    }
+
+    Mutex::Autolock lock(mMutex);
+    for (int32_t i : slots) {
+        if (mSlots[i].buffer == nullptr) {
+            ALOGW("%s: Discarded slot %d doesn't contain buffer!", __FUNCTION__, i);
+            continue;
+        }
+        outBuffers->push_back(mSlots[i].buffer);
+        mSlots[i].buffer = nullptr;
+    }
+    return OK;
+}
+
 void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) {
     ATRACE_CALL();
     ALOGV("Surface::setSurfaceDamage");
@@ -1951,4 +1982,22 @@
     return err;
 }
 
+void Surface::ProducerListenerProxy::onBuffersDiscarded(const std::vector<int32_t>& slots) {
+    ATRACE_CALL();
+    sp<Surface> parent = mParent.promote();
+    if (parent == nullptr) {
+        return;
+    }
+
+    std::vector<sp<GraphicBuffer>> discardedBufs;
+    status_t res = parent->getAndFlushBuffersFromSlots(slots, &discardedBufs);
+    if (res != OK) {
+        ALOGE("%s: Failed to get buffers from slots: %s(%d)", __FUNCTION__,
+                strerror(-res), res);
+        return;
+    }
+
+    mSurfaceListener->onBuffersDiscarded(discardedBufs);
+}
+
 }; // namespace android
diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h
index 690a85f..17617bc 100644
--- a/libs/gui/include/gui/BufferQueueCore.h
+++ b/libs/gui/include/gui/BufferQueueCore.h
@@ -189,8 +189,12 @@
     sp<IProducerListener> mLinkedToDeath;
 
     // mConnectedProducerListener is used to handle the onBufferReleased
-    // notification.
+    // and onBuffersDiscarded notification.
     sp<IProducerListener> mConnectedProducerListener;
+    // mBufferReleasedCbEnabled is used to indicate whether onBufferReleased()
+    // callback is registered by the listener. When set to false,
+    // mConnectedProducerListener will not trigger onBufferReleased() callback.
+    bool mBufferReleasedCbEnabled;
 
     // mSlots is an array of buffer slots that must be mirrored on the producer
     // side. This allows buffer ownership to be transferred between the producer
diff --git a/libs/gui/include/gui/IProducerListener.h b/libs/gui/include/gui/IProducerListener.h
index a13d8e4..32a3690 100644
--- a/libs/gui/include/gui/IProducerListener.h
+++ b/libs/gui/include/gui/IProducerListener.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_GUI_IPRODUCERLISTENER_H
 #define ANDROID_GUI_IPRODUCERLISTENER_H
 
+#include <vector>
+
 #include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
 #include <android/hardware/graphics/bufferqueue/2.0/IProducerListener.h>
 #include <binder/IInterface.h>
@@ -44,6 +46,9 @@
     // multiple threads.
     virtual void onBufferReleased() = 0; // Asynchronous
     virtual bool needsReleaseNotify() = 0;
+    // onBuffersFreed is called from IGraphicBufferConsumer::discardFreeBuffers
+    // to notify the producer that certain free buffers are discarded by the consumer.
+    virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) = 0; // Asynchronous
 };
 
 class IProducerListener : public ProducerListener, public IInterface
@@ -65,6 +70,7 @@
     virtual status_t onTransact(uint32_t code, const Parcel& data,
             Parcel* reply, uint32_t flags = 0);
     virtual bool needsReleaseNotify();
+    virtual void onBuffersDiscarded(const std::vector<int32_t>& slots);
 };
 
 class DummyProducerListener : public BnProducerListener
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 5c6a1ee..a5641b0 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -20,6 +20,7 @@
 #include <gui/BufferQueueDefs.h>
 #include <gui/HdrMetadata.h>
 #include <gui/IGraphicBufferProducer.h>
+#include <gui/IProducerListener.h>
 
 #include <ui/ANativeObjectBase.h>
 #include <ui/GraphicTypes.h>
@@ -35,6 +36,21 @@
 
 class ISurfaceComposer;
 
+/* This is the same as ProducerListener except that onBuffersDiscarded is
+ * called with a vector of graphic buffers instead of buffer slots.
+ */
+class SurfaceListener : public virtual RefBase
+{
+public:
+    SurfaceListener() = default;
+    virtual ~SurfaceListener() = default;
+
+    virtual void onBufferReleased() = 0;
+    virtual bool needsReleaseNotify() = 0;
+
+    virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& buffers) = 0;
+};
+
 /*
  * An implementation of ANativeWindow that feeds graphics buffers into a
  * BufferQueue.
@@ -283,6 +299,10 @@
             sp<Fence>* outFence);
     virtual int attachBuffer(ANativeWindowBuffer*);
 
+    virtual int connect(
+            int api, bool reportBufferRemoval,
+            const sp<SurfaceListener>& sListener);
+
     // When client connects to Surface with reportBufferRemoval set to true, any buffers removed
     // from this Surface will be collected and returned here. Once this method returns, these
     // buffers will no longer be referenced by this Surface unless they are attached to this
@@ -299,6 +319,26 @@
     enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS };
     enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
 
+    class ProducerListenerProxy : public BnProducerListener {
+    public:
+        ProducerListenerProxy(wp<Surface> parent, sp<SurfaceListener> listener)
+               : mParent(parent), mSurfaceListener(listener) {}
+        virtual ~ProducerListenerProxy() {}
+
+        virtual void onBufferReleased() {
+            mSurfaceListener->onBufferReleased();
+        }
+
+        virtual bool needsReleaseNotify() {
+            return mSurfaceListener->needsReleaseNotify();
+        }
+
+        virtual void onBuffersDiscarded(const std::vector<int32_t>& slots);
+    private:
+        wp<Surface> mParent;
+        sp<SurfaceListener> mSurfaceListener;
+    };
+
     void querySupportedTimestampsLocked() const;
 
     void freeAllBuffers();
@@ -466,6 +506,10 @@
 
     bool mReportRemovedBuffers = false;
     std::vector<sp<GraphicBuffer>> mRemovedBuffers;
+
+    sp<IProducerListener> mListenerProxy;
+    status_t getAndFlushBuffersFromSlots(const std::vector<int32_t>& slots,
+            std::vector<sp<GraphicBuffer>>* outBuffers);
 };
 
 } // namespace android
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index cbda6b2..ab6dcaa 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -47,6 +47,7 @@
         "libcutils",
         "libgui",
         "libhidlbase",
+        "libhidltransport",
         "libinput",
         "libui",
         "libutils",
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 119e888..406f21f 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -998,12 +998,31 @@
     ASSERT_EQ(true, thirdSegment.usedThirdBuffer);
 }
 
+struct BufferDiscardedListener : public BnProducerListener {
+public:
+    BufferDiscardedListener() = default;
+    virtual ~BufferDiscardedListener() = default;
+
+    virtual void onBufferReleased() {}
+    virtual bool needsReleaseNotify() { return false; }
+    virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) {
+        mDiscardedSlots.insert(mDiscardedSlots.end(), slots.begin(), slots.end());
+    }
+
+    const std::vector<int32_t>& getDiscardedSlots() const { return mDiscardedSlots; }
+private:
+    // No need to use lock given the test triggers the listener in the same
+    // thread context.
+    std::vector<int32_t> mDiscardedSlots;
+};
+
 TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
     createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
     IGraphicBufferProducer::QueueBufferOutput output;
-    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
+    sp<BufferDiscardedListener> pl(new BufferDiscardedListener);
+    ASSERT_EQ(OK, mProducer->connect(pl,
             NATIVE_WINDOW_API_CPU, false, &output));
 
     int slot = BufferQueue::INVALID_BUFFER_SLOT;
@@ -1044,12 +1063,19 @@
     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
     ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
                     EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+    int releasedSlot = item.mSlot;
+
     // Acquire 1 buffer, leaving 1 filled buffer in queue
     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
 
     // Now discard the free buffers
     ASSERT_EQ(OK, mConsumer->discardFreeBuffers());
 
+    // Check onBuffersDiscarded is called with correct slots
+    auto buffersDiscarded = pl->getDiscardedSlots();
+    ASSERT_EQ(buffersDiscarded.size(), 1);
+    ASSERT_EQ(buffersDiscarded[0], releasedSlot);
+
     // Check no free buffers in dump
     String8 dumpString;
     mConsumer->dumpState(String8{}, &dumpString);
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 0babd23..66a8a04 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -133,27 +133,6 @@
         EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction());
     }
 
-    void expectMotionEvent(int motionEventType, int x, int y) {
-        InputEvent *ev = consumeEvent();
-        ASSERT_NE(ev, nullptr);
-        ASSERT_EQ(ev->getType(), AINPUT_EVENT_TYPE_MOTION);
-        MotionEvent *mev = static_cast<MotionEvent *>(ev);
-        EXPECT_EQ(motionEventType, mev->getAction());
-        EXPECT_EQ(x, mev->getX(0));
-        EXPECT_EQ(y, mev->getY(0));
-    }
-
-    void expectNoMotionEvent(int motionEventType) {
-        InputEvent *ev = consumeEvent();
-        if (ev == nullptr || ev->getType() != AINPUT_EVENT_TYPE_MOTION) {
-            // Didn't find an event or a motion event so assume action didn't occur.
-            return;
-        }
-
-        MotionEvent *mev = static_cast<MotionEvent *>(ev);
-        EXPECT_NE(motionEventType, mev->getAction());
-    }
-
     ~InputSurface() {
         mInputFlinger->unregisterInputChannel(mServerChannel);
     }
@@ -278,15 +257,6 @@
     }
 }
 
-void injectMotionEvent(std::string event, int x, int y) {
-    char *buf1, *buf2;
-    asprintf(&buf1, "%d", x);
-    asprintf(&buf2, "%d", y);
-    if (fork() == 0) {
-        execlp("input", "input", "motionevent", event.c_str(), buf1, buf2, NULL);
-    }
-}
-
 TEST_F(InputSurfacesTest, can_receive_input) {
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
     surface->showAt(100, 100);
@@ -410,19 +380,6 @@
     bgSurface->expectTap(1, 1);
 }
 
-TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets_overflow) {
-    std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
-    // In case we pass the very big inset without any checking.
-    fgSurface->mInputInfo.surfaceInset = INT32_MAX;
-    fgSurface->showAt(100, 100);
-
-    fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); });
-
-    // expect no crash for overflow, and inset size to be clamped to surface size
-    injectTap(202, 202);
-    fgSurface->expectTap(1, 1);
-}
-
 // Ensure we ignore transparent region when getting screen bounds when positioning input frame.
 TEST_F(InputSurfacesTest, input_ignores_transparent_region) {
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
@@ -506,26 +463,6 @@
     bgSurface->expectTap(1, 1);
 }
 
-TEST_F(InputSurfacesTest, transfer_touch_focus) {
-    std::unique_ptr<InputSurface> fromSurface = makeSurface(100, 100);
-
-    fromSurface->showAt(10, 10);
-    injectMotionEvent("DOWN", 11, 11);
-    fromSurface->expectMotionEvent(AMOTION_EVENT_ACTION_DOWN, 1, 1);
-
-    std::unique_ptr<InputSurface> toSurface = makeSurface(100, 100);
-    toSurface->showAt(10, 10);
-
-    sp<IBinder> fromToken = fromSurface->mServerChannel->getToken();
-    sp<IBinder> toToken = toSurface->mServerChannel->getToken();
-    SurfaceComposerClient::Transaction t;
-    t.transferTouchFocus(fromToken, toToken).apply(true);
-
-    injectMotionEvent("UP", 11, 11);
-    toSurface->expectMotionEvent(AMOTION_EVENT_ACTION_UP, 1, 1);
-    fromSurface->expectNoMotionEvent(AMOTION_EVENT_ACTION_UP);
-}
-
 TEST_F(InputSurfacesTest, input_respects_outscreen) {
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
     surface->showAt(-1, -1);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index d370858..a851687 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -57,6 +57,37 @@
 
 static constexpr uint64_t NO_FRAME_INDEX = std::numeric_limits<uint64_t>::max();
 
+class DummySurfaceListener : public SurfaceListener {
+public:
+    DummySurfaceListener(bool enableReleasedCb = false) :
+            mEnableReleaseCb(enableReleasedCb),
+            mBuffersReleased(0) {}
+    virtual ~DummySurfaceListener() = default;
+
+    virtual void onBufferReleased() {
+        mBuffersReleased++;
+    }
+    virtual bool needsReleaseNotify() {
+        return mEnableReleaseCb;
+    }
+    virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& buffers) {
+        mDiscardedBuffers.insert(mDiscardedBuffers.end(), buffers.begin(), buffers.end());
+    }
+
+    int getReleaseNotifyCount() const {
+        return mBuffersReleased;
+    }
+    const std::vector<sp<GraphicBuffer>>& getDiscardedBuffers() const {
+        return mDiscardedBuffers;
+    }
+private:
+    // No need to use lock given the test triggers the listener in the same
+    // thread context.
+    bool mEnableReleaseCb;
+    int32_t mBuffersReleased;
+    std::vector<sp<GraphicBuffer>> mDiscardedBuffers;
+};
+
 class SurfaceTest : public ::testing::Test {
 protected:
     SurfaceTest() {
@@ -88,6 +119,86 @@
         mComposerClient->dispose();
     }
 
+    void testSurfaceListener(bool hasSurfaceListener, bool enableReleasedCb,
+            int32_t extraDiscardedBuffers) {
+        sp<IGraphicBufferProducer> producer;
+        sp<IGraphicBufferConsumer> consumer;
+        BufferQueue::createBufferQueue(&producer, &consumer);
+
+        sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+        consumer->consumerConnect(dummyConsumer, false);
+        consumer->setConsumerName(String8("TestConsumer"));
+
+        sp<Surface> surface = new Surface(producer);
+        sp<ANativeWindow> window(surface);
+        sp<DummySurfaceListener> listener;
+        if (hasSurfaceListener) {
+            listener = new DummySurfaceListener(enableReleasedCb);
+        }
+        ASSERT_EQ(OK, surface->connect(
+                NATIVE_WINDOW_API_CPU,
+                /*reportBufferRemoval*/true,
+                /*listener*/listener));
+        const int BUFFER_COUNT = 4 + extraDiscardedBuffers;
+        ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(window.get(), BUFFER_COUNT));
+
+        ANativeWindowBuffer* buffers[BUFFER_COUNT];
+        // Dequeue first to allocate a number of buffers
+        for (int i = 0; i < BUFFER_COUNT; i++) {
+            ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(window.get(), &buffers[i]));
+        }
+        for (int i = 0; i < BUFFER_COUNT; i++) {
+            ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffers[i], -1));
+        }
+
+        ANativeWindowBuffer* buffer;
+        // Fill BUFFER_COUNT-1 buffers
+        for (int i = 0; i < BUFFER_COUNT-1; i++) {
+            ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(window.get(), &buffer));
+            ASSERT_EQ(NO_ERROR, window->queueBuffer(window.get(), buffer, -1));
+        }
+
+        // Dequeue 1 buffer
+        ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(window.get(), &buffer));
+
+        // Acquire and free 1+extraDiscardedBuffers buffer, check onBufferReleased is called.
+        std::vector<BufferItem> releasedItems;
+        releasedItems.resize(1+extraDiscardedBuffers);
+        for (int i = 0; i < releasedItems.size(); i++) {
+            ASSERT_EQ(NO_ERROR, consumer->acquireBuffer(&releasedItems[i], 0));
+            ASSERT_EQ(NO_ERROR, consumer->releaseBuffer(releasedItems[i].mSlot,
+                    releasedItems[i].mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
+                    Fence::NO_FENCE));
+        }
+        int32_t expectedReleaseCb = (enableReleasedCb ? releasedItems.size() : 0);
+        if (hasSurfaceListener) {
+            ASSERT_EQ(expectedReleaseCb, listener->getReleaseNotifyCount());
+        }
+
+        // Acquire 1 buffer, leaving 1+extraDiscardedBuffers filled buffer in queue
+        BufferItem item;
+        ASSERT_EQ(NO_ERROR, consumer->acquireBuffer(&item, 0));
+
+        // Discard free buffers
+        ASSERT_EQ(NO_ERROR, consumer->discardFreeBuffers());
+
+        if (hasSurfaceListener) {
+            ASSERT_EQ(expectedReleaseCb, listener->getReleaseNotifyCount());
+
+            // Check onBufferDiscarded is called with correct buffer
+            auto discardedBuffers = listener->getDiscardedBuffers();
+            ASSERT_EQ(discardedBuffers.size(), releasedItems.size());
+            for (int i = 0; i < releasedItems.size(); i++) {
+                ASSERT_EQ(discardedBuffers[i], releasedItems[i].mGraphicBuffer);
+            }
+
+            ASSERT_EQ(expectedReleaseCb, listener->getReleaseNotifyCount());
+        }
+
+        // Disconnect the surface
+        ASSERT_EQ(NO_ERROR, surface->disconnect(NATIVE_WINDOW_API_CPU));
+    }
+
     sp<Surface> mSurface;
     sp<SurfaceComposerClient> mComposerClient;
     sp<SurfaceControl> mSurfaceControl;
@@ -480,6 +591,21 @@
     ASSERT_LE(removedBuffers.size(), 1u);
 }
 
+TEST_F(SurfaceTest, SurfaceListenerTest) {
+    // Test discarding 1 free buffers with no listener
+    testSurfaceListener(/*hasListener*/false, /*enableReleaseCb*/false, /*extraDiscardedBuffers*/0);
+    // Test discarding 2 free buffers with no listener
+    testSurfaceListener(/*hasListener*/false, /*enableReleaseCb*/false, /*extraDiscardedBuffers*/1);
+    // Test discarding 1 free buffers with a listener, disabling onBufferReleased
+    testSurfaceListener(/*hasListener*/true, /*enableReleasedCb*/false, /*extraDiscardedBuffers*/0);
+    // Test discarding 2 free buffers with a listener, disabling onBufferReleased
+    testSurfaceListener(/*hasListener*/true, /*enableReleasedCb*/false, /*extraDiscardedBuffers*/1);
+    // Test discarding 1 free buffers with a listener, enabling onBufferReleased
+    testSurfaceListener(/*hasListener*/true, /*enableReleasedCb*/true, /*extraDiscardedBuffers*/0);
+    // Test discarding 3 free buffers with a listener, enabling onBufferReleased
+    testSurfaceListener(/*hasListener*/true, /*enableReleasedCb*/true, /*extraDiscardedBuffers*/2);
+}
+
 TEST_F(SurfaceTest, TestGetLastDequeueStartTime) {
     sp<ANativeWindow> anw(mSurface);
     ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU));
diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp
index d6a73bf..de3a23d 100644
--- a/libs/input/IInputFlinger.cpp
+++ b/libs/input/IInputFlinger.cpp
@@ -45,16 +45,6 @@
                 IBinder::FLAG_ONEWAY);
     }
 
-    virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
-
-        data.writeStrongBinder(fromToken);
-        data.writeStrongBinder(toToken);
-        remote()->transact(BnInputFlinger::TRANSFER_TOUCH_FOCUS, data, &reply,
-                IBinder::FLAG_ONEWAY);
-    }
-
     virtual void registerInputChannel(const sp<InputChannel>& channel) {
         Parcel data, reply;
         data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
@@ -104,13 +94,6 @@
         unregisterInputChannel(channel);
         break;
     }
-    case TRANSFER_TOUCH_FOCUS: {
-        CHECK_INTERFACE(IInputFlinger, data, reply);
-        sp<IBinder> fromToken = data.readStrongBinder();
-        sp<IBinder> toToken = data.readStrongBinder();
-        transferTouchFocus(fromToken, toToken);
-        break;
-    }
     default:
         return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
index ec28757..5a60347 100644
--- a/libs/input/InputWindow.cpp
+++ b/libs/input/InputWindow.cpp
@@ -99,7 +99,7 @@
     applicationInfo.write(output);
     output.write(touchableRegion);
     output.writeBool(replaceTouchableRegionWithCrop);
-    output.writeStrongBinder(touchableRegionCropHandle.promote());
+    output.writeWeakBinder(touchableRegionCropHandle);
     return OK;
 }
 
@@ -142,7 +142,7 @@
     ret.applicationInfo = InputApplicationInfo::read(from);
     from.read(ret.touchableRegion);
     ret.replaceTouchableRegionWithCrop = from.readBool();
-    ret.touchableRegionCropHandle = from.readStrongBinder();
+    ret.touchableRegionCropHandle = from.readWeakBinder();
 
     return ret;
 }
diff --git a/libs/input/TouchVideoFrame.cpp b/libs/input/TouchVideoFrame.cpp
index 8a4298a..ce76e3f 100644
--- a/libs/input/TouchVideoFrame.cpp
+++ b/libs/input/TouchVideoFrame.cpp
@@ -42,13 +42,13 @@
 void TouchVideoFrame::rotate(int32_t orientation) {
     switch (orientation) {
         case DISPLAY_ORIENTATION_90:
-            rotateQuarterTurn(true /*clockwise*/);
+            rotateQuarterTurn(false /*clockwise*/);
             break;
         case DISPLAY_ORIENTATION_180:
             rotate180();
             break;
         case DISPLAY_ORIENTATION_270:
-            rotateQuarterTurn(false /*clockwise*/);
+            rotateQuarterTurn(true /*clockwise*/);
             break;
     }
 }
diff --git a/libs/input/tests/TouchVideoFrame_test.cpp b/libs/input/tests/TouchVideoFrame_test.cpp
index 815424e..fe06cad 100644
--- a/libs/input/tests/TouchVideoFrame_test.cpp
+++ b/libs/input/tests/TouchVideoFrame_test.cpp
@@ -85,14 +85,14 @@
 
 TEST(TouchVideoFrame, Rotate90_2x2) {
     TouchVideoFrame frame(2, 2, {1, 2, 3, 4}, TIMESTAMP);
-    TouchVideoFrame frameRotated(2, 2, {3, 1, 4, 2}, TIMESTAMP);
+    TouchVideoFrame frameRotated(2, 2, {2, 4, 1, 3}, TIMESTAMP);
     frame.rotate(DISPLAY_ORIENTATION_90);
     ASSERT_EQ(frame, frameRotated);
 }
 
 TEST(TouchVideoFrame, Rotate90_3x2) {
     TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, TIMESTAMP);
-    TouchVideoFrame frameRotated(2, 3, {5, 3, 1, 6, 4, 2}, TIMESTAMP);
+    TouchVideoFrame frameRotated(2, 3, {2, 4, 6, 1, 3, 5}, TIMESTAMP);
     frame.rotate(DISPLAY_ORIENTATION_90);
     ASSERT_EQ(frame, frameRotated);
 }
@@ -170,14 +170,14 @@
 
 TEST(TouchVideoFrame, Rotate270_2x2) {
     TouchVideoFrame frame(2, 2, {1, 2, 3, 4}, TIMESTAMP);
-    TouchVideoFrame frameRotated(2, 2, {2, 4, 1, 3}, TIMESTAMP);
+    TouchVideoFrame frameRotated(2, 2, {3, 1, 4, 2}, TIMESTAMP);
     frame.rotate(DISPLAY_ORIENTATION_270);
     ASSERT_EQ(frame, frameRotated);
 }
 
 TEST(TouchVideoFrame, Rotate270_3x2) {
     TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, TIMESTAMP);
-    TouchVideoFrame frameRotated(2, 3, {2, 4, 6, 1, 3, 5}, TIMESTAMP);
+    TouchVideoFrame frameRotated(2, 3, {5, 3, 1, 6, 4, 2}, TIMESTAMP);
     frame.rotate(DISPLAY_ORIENTATION_270);
     ASSERT_EQ(frame, frameRotated);
 }
diff --git a/libs/math/include/math/quat.h b/libs/math/include/math/quat.h
index 07573c5..1936a2b 100644
--- a/libs/math/include/math/quat.h
+++ b/libs/math/include/math/quat.h
@@ -109,7 +109,7 @@
 
     // initialize from 4 values to w + xi + yj + zk
     template<typename A, typename B, typename C, typename D>
-    constexpr TQuaternion(A w, B x, C y, D z) : x(static_cast<T>(x)), y(static_cast<T>(y)), z(static_cast<T>(z)), w(static_cast<T>(w)) { }
+    constexpr TQuaternion(A w, B x, C y, D z) : x(x), y(y), z(z), w(w) { }
 
     // initialize from a vec3 + a value to : v.xi + v.yj + v.zk + w
     template<typename A, typename B>
diff --git a/libs/math/include/math/vec2.h b/libs/math/include/math/vec2.h
index e0adb7f..a347633 100644
--- a/libs/math/include/math/vec2.h
+++ b/libs/math/include/math/vec2.h
@@ -89,7 +89,7 @@
     constexpr TVec2(A v) : x(v), y(v) { }
 
     template<typename A, typename B>
-    constexpr TVec2(A x, B y) : x(static_cast<T>(x)), y(static_cast<T>(y)) { }
+    constexpr TVec2(A x, B y) : x(x), y(y) { }
 
     template<typename A>
     explicit
diff --git a/libs/math/include/math/vec3.h b/libs/math/include/math/vec3.h
index 21fb684..009fd84 100644
--- a/libs/math/include/math/vec3.h
+++ b/libs/math/include/math/vec3.h
@@ -86,13 +86,13 @@
 
     // handles implicit conversion to a tvec4. must not be explicit.
     template<typename A, typename = typename std::enable_if<std::is_arithmetic<A>::value >::type>
-    constexpr TVec3(A v) : x(static_cast<T>(v)), y(static_cast<T>(v)), z(static_cast<T>(v)) { }
+    constexpr TVec3(A v) : x(v), y(v), z(v) { }
 
     template<typename A, typename B, typename C>
-    constexpr TVec3(A x, B y, C z) : x(static_cast<T>(x)), y(static_cast<T>(y)), z(static_cast<T>(z)) { }
+    constexpr TVec3(A x, B y, C z) : x(x), y(y), z(z) { }
 
     template<typename A, typename B>
-    constexpr TVec3(const TVec2<A>& v, B z) : x(v.x), y(v.y), z(static_cast<T>(z)) { }
+    constexpr TVec3(const TVec2<A>& v, B z) : x(v.x), y(v.y), z(z) { }
 
     template<typename A>
     explicit
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index 1ec73ce..9bd3095 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -266,10 +266,10 @@
 
     char buf[CMSG_SPACE(kFdBufferSize)];
     struct msghdr msg = {
-            .msg_iov = &iov[0],
-            .msg_iovlen = 1,
             .msg_control = buf,
             .msg_controllen = sizeof(buf),
+            .msg_iov = &iov[0],
+            .msg_iovlen = 1,
     };
 
     struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
@@ -306,10 +306,10 @@
     iov[0].iov_len = kMessageBufferSize;
 
     struct msghdr msg = {
-            .msg_iov = &iov[0],
-            .msg_iovlen = 1,
             .msg_control = fdBuf,
             .msg_controllen = sizeof(fdBuf),
+            .msg_iov = &iov[0],
+            .msg_iovlen = 1,
     };
 
     int result;
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index ae5e47b..da959e3 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -342,8 +342,6 @@
  * not compatible with its usage flags, the results are undefined and
  * may include program termination.
  *
- * Available since API level 26.
- *
  * \return 0 on success, or an error number of the allocation fails for
  * any reason. The returned buffer has a reference count of 1.
  */
@@ -354,24 +352,18 @@
  *
  * This prevents the object from being deleted until the last reference
  * is removed.
- *
- * Available since API level 26.
  */
 void AHardwareBuffer_acquire(AHardwareBuffer* buffer) __INTRODUCED_IN(26);
 
 /**
  * Remove a reference that was previously acquired with
  * AHardwareBuffer_acquire() or AHardwareBuffer_allocate().
- *
- * Available since API level 26.
  */
 void AHardwareBuffer_release(AHardwareBuffer* buffer) __INTRODUCED_IN(26);
 
 /**
  * Return a description of the AHardwareBuffer in the passed
  * AHardwareBuffer_Desc struct.
- *
- * Available since API level 26.
  */
 void AHardwareBuffer_describe(const AHardwareBuffer* buffer,
         AHardwareBuffer_Desc* outDesc) __INTRODUCED_IN(26);
@@ -421,8 +413,6 @@
  * simultaneously, and the contents of the buffer behave like shared
  * memory.
  *
- * Available since API level 26.
- *
  * \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags
  * are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer
  * has more than one layer. Error number if the lock fails for any other
@@ -451,8 +441,6 @@
  *
  * See the AHardwareBuffer_lock documentation for all other locking semantics.
  *
- * Available since API level 29.
- *
  * \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags
  * are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer
  * has more than one layer. Error number if the lock fails for any other
@@ -474,8 +462,6 @@
  * completed before the function returned and no further operations are
  * necessary.
  *
- * Available since API level 26.
- *
  * \return 0 on success. -EINVAL if \a buffer is NULL. Error number if
  * the unlock fails for any reason.
  */
@@ -484,8 +470,6 @@
 /**
  * Send the AHardwareBuffer to an AF_UNIX socket.
  *
- * Available since API level 26.
- *
  * \return 0 on success, -EINVAL if \a buffer is NULL, or an error
  * number if the operation fails for any reason.
  */
@@ -494,8 +478,6 @@
 /**
  * Receive an AHardwareBuffer from an AF_UNIX socket.
  *
- * Available since API level 26.
- *
  * \return 0 on success, -EINVAL if \a outBuffer is NULL, or an error
  * number if the operation fails for any reason.
  */
@@ -519,8 +501,6 @@
  * some implementations have implementation-defined limits on texture
  * size and layer count.
  *
- * Available since API level 29.
- *
  * \return 1 if the format and usage flag combination is allocatable,
  *     0 otherwise.
  */
@@ -534,8 +514,6 @@
  * of the locked buffer.  If the bytes per pixel or bytes per stride are unknown
  * or variable, or if the underlying mapper implementation does not support returning
  * additional information, then this call will fail with INVALID_OPERATION
- *
- * Available since API level 29.
  */
 int AHardwareBuffer_lockAndGetInfo(AHardwareBuffer* buffer, uint64_t usage,
         int32_t fence, const ARect* rect, void** outVirtualAddress,
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index 3e436e3..6730596 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -189,8 +189,6 @@
 /**
  * Set a transform that will be applied to future buffers posted to the window.
  *
- * Available since API level 26.
- *
  * \param transform combination of {@link ANativeWindowTransform} flags
  * \return 0 for success, or -EINVAL if \p transform is invalid
  */
@@ -210,8 +208,6 @@
  * measurement data instead of color images. The default dataSpace is 0,
  * ADATASPACE_UNKNOWN, unless it has been overridden by the producer.
  *
- * Available since API level 28.
- *
  * \param dataSpace data space of all buffers queued after this call.
  * \return 0 for success, -EINVAL if window is invalid or the dataspace is not
  * supported.
@@ -220,9 +216,6 @@
 
 /**
  * Get the dataspace of the buffers in window.
- *
- * Available since API level 28.
- *
  * \return the dataspace of buffers in window, ADATASPACE_UNKNOWN is returned if
  * dataspace is unknown, or -EINVAL if window is invalid.
  */
diff --git a/libs/sensor/Android.bp b/libs/sensor/Android.bp
index e8154a6..940ff5a 100644
--- a/libs/sensor/Android.bp
+++ b/libs/sensor/Android.bp
@@ -21,7 +21,22 @@
         "-Werror",
     ],
     cppflags: [
-        "-Wextra",
+        "-Weverything",
+
+        // The static constructors and destructors in this library have not been noted to
+        // introduce significant overheads
+        "-Wno-exit-time-destructors",
+        "-Wno-global-constructors",
+
+        // We only care about compiling as C++14
+        "-Wno-c++98-compat-pedantic",
+
+        // android/sensors.h uses nested anonymous unions and anonymous structs
+        "-Wno-nested-anon-types",
+        "-Wno-gnu-anonymous-struct",
+
+        // Don't warn about struct padding
+        "-Wno-padded",
     ],
 
     srcs: [
diff --git a/libs/sensor/OWNERS b/libs/sensor/OWNERS
index 90c2330..81099e8 100644
--- a/libs/sensor/OWNERS
+++ b/libs/sensor/OWNERS
@@ -1,3 +1,3 @@
 arthuri@google.com
 bduddie@google.com
-stange@google.com
+bstack@google.com
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
index bf8b9f7..96d5eb9 100644
--- a/libs/sensor/SensorManager.cpp
+++ b/libs/sensor/SensorManager.cpp
@@ -150,7 +150,7 @@
         class DeathObserver : public IBinder::DeathRecipient {
             SensorManager& mSensorManager;
             virtual void binderDied(const wp<IBinder>& who) {
-                ALOGW("sensorservice died [%p]", static_cast<void*>(who.unsafe_get()));
+                ALOGW("sensorservice died [%p]", who.unsafe_get());
                 mSensorManager.sensorManagerDied();
             }
         public:
diff --git a/libs/sensorprivacy/Android.bp b/libs/sensorprivacy/Android.bp
index 4a606ff..e0e3469 100644
--- a/libs/sensorprivacy/Android.bp
+++ b/libs/sensorprivacy/Android.bp
@@ -28,7 +28,8 @@
     ],
 
     srcs: [
-        ":libsensorprivacy_aidl",
+        "aidl/android/hardware/ISensorPrivacyListener.aidl",
+        "aidl/android/hardware/ISensorPrivacyManager.aidl",
         "SensorPrivacyManager.cpp",
     ],
 
@@ -44,12 +45,3 @@
 
     export_shared_lib_headers: ["libbinder"],
 }
-
-filegroup {
-    name: "libsensorprivacy_aidl",
-    srcs: [
-        "aidl/android/hardware/ISensorPrivacyListener.aidl",
-        "aidl/android/hardware/ISensorPrivacyManager.aidl",
-    ],
-    path: "aidl",
-}
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index db15e17..0407d88 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -26,7 +26,27 @@
         "-Werror",
     ],
     cppflags: [
-        "-Wextra",
+        "-Weverything",
+
+        // The static constructors and destructors in this library have not been noted to
+        // introduce significant overheads
+        "-Wno-exit-time-destructors",
+        "-Wno-global-constructors",
+
+        // We only care about compiling as C++14
+        "-Wno-c++98-compat-pedantic",
+
+        // We are aware of the risks inherent in comparing floats for equality
+        "-Wno-float-equal",
+
+        // We use four-character constants for the GraphicBuffer header, and don't care
+        // that they're non-portable as long as they're consistent within one execution
+        "-Wno-four-char-constants",
+
+        // Don't warn about struct padding
+        "-Wno-padded",
+
+        "-Wno-switch-enum",
     ],
 
     sanitize: {
@@ -75,7 +95,10 @@
         "android.hardware.graphics.mapper@3.0",
         "libbase",
         "libcutils",
+        "libhardware",
         "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
         "libsync",
         "libutils",
         "liblog",
diff --git a/libs/ui/ColorSpace.cpp b/libs/ui/ColorSpace.cpp
index df390e2..7a14af1 100644
--- a/libs/ui/ColorSpace.cpp
+++ b/libs/ui/ColorSpace.cpp
@@ -364,11 +364,7 @@
     for (uint32_t z = 0; z < size; z++) {
         for (int32_t y = int32_t(size - 1); y >= 0; y--) {
             for (uint32_t x = 0; x < size; x++) {
-                *data++ = connector.transform({
-                    static_cast<float>(x) * m,
-                    static_cast<float>(y) * m,
-                    static_cast<float>(z) * m,
-                });
+                *data++ = connector.transform({x * m, y * m, z * m});
             }
         }
     }
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index d02bb94..d588346 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -81,7 +81,7 @@
         if (rec.size) {
             StringAppendF(&result,
                           "%10p: %7.2f KiB | %4u (%4u) x %4u | %4u | %8X | 0x%" PRIx64 " | %s\n",
-                          list.keyAt(i), static_cast<double>(rec.size) / 1024.0, rec.width, rec.stride, rec.height,
+                          list.keyAt(i), rec.size / 1024.0, rec.width, rec.stride, rec.height,
                           rec.layerCount, rec.format, rec.usage, rec.requestorName.c_str());
         } else {
             StringAppendF(&result,
@@ -91,7 +91,7 @@
         }
         total += rec.size;
     }
-    StringAppendF(&result, "Total allocated (estimate): %.2f KB\n", static_cast<double>(total) / 1024.0);
+    StringAppendF(&result, "Total allocated (estimate): %.2f KB\n", total / 1024.0);
 
     result.append(mAllocator->dumpDebugInfo());
 }
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 1222cd6..55e3b99 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -339,10 +339,10 @@
     size_t count = mStorage.size();
     Rect* rects = mStorage.editArray();
     while (count) {
-        rects->left = static_cast<int32_t>(static_cast<float>(rects->left) * sx + 0.5f);
-        rects->right = static_cast<int32_t>(static_cast<float>(rects->right) * sx + 0.5f);
-        rects->top = static_cast<int32_t>(static_cast<float>(rects->top) * sy + 0.5f);
-        rects->bottom = static_cast<int32_t>(static_cast<float>(rects->bottom) * sy + 0.5f);
+        rects->left = static_cast<int32_t>(rects->left * sx + 0.5f);
+        rects->right = static_cast<int32_t>(rects->right * sx + 0.5f);
+        rects->top = static_cast<int32_t>(rects->top * sy + 0.5f);
+        rects->bottom = static_cast<int32_t>(rects->bottom * sy + 0.5f);
         rects++;
         count--;
     }
diff --git a/libs/ui/include/ui/Size.h b/libs/ui/include/ui/Size.h
index d9b713d..c39d8af 100644
--- a/libs/ui/include/ui/Size.h
+++ b/libs/ui/include/ui/Size.h
@@ -132,7 +132,7 @@
         // Otherwise we leverage implicit conversion to safely compare values of
         // different types, to ensure we return a value clamped to the range of
         // ToType.
-        return v < toLowest ? toLowest : (static_cast<ToType>(v) > toHighest ? toHighest : static_cast<ToType>(v));
+        return v < toLowest ? toLowest : (v > toHighest ? toHighest : static_cast<ToType>(v));
     }
 };
 
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index 0a07a48..15f4b64 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -58,6 +58,7 @@
         "android.frameworks.bufferhub@1.0",
         "libcutils",
         "libhidlbase",
+        "libhwbinder",
         "libui",
         "libutils",
     ],
@@ -78,6 +79,7 @@
         "android.frameworks.bufferhub@1.0",
         "libcutils",
         "libhidlbase",
+        "libhwbinder",
         "liblog",
         "libui",
         "libutils"
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 2fcee7b..6d202ae 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -29,9 +29,11 @@
 sharedLibraries = [
     "libbase",
     "libcutils",
+    "libhardware",
     "liblog",
     "libui",
     "libutils",
+    "libnativewindow",
     "libpdx_default_transport",
 ]
 
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index 77c7911..9f72c05 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -26,8 +26,10 @@
 ]
 
 sharedLibraries = [
+    "libbase",
     "libbinder",
     "libcutils",
+    "libhardware",
     "liblog",
     "libui",
     "libutils",
diff --git a/libs/vr/libdisplay/vsync_service.cpp b/libs/vr/libdisplay/vsync_service.cpp
index 04d4f30..4668b98 100644
--- a/libs/vr/libdisplay/vsync_service.cpp
+++ b/libs/vr/libdisplay/vsync_service.cpp
@@ -45,8 +45,8 @@
       ALOGE("onVsync failed to writeInt64: %d", result);
       return result;
     }
-    result = remote()->transact(BnVsyncCallback::ON_VSYNC, data, &reply,
-                                IBinder::FLAG_ONEWAY);
+    result = remote()->transact(
+        BnVsyncCallback::ON_VSYNC, data, &reply, TF_ONE_WAY);
     if (result != OK) {
       ALOGE("onVsync failed to transact: %d", result);
       return result;
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 12ce74b..2829353 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -57,6 +57,7 @@
     "libgui",
     "libsync",
     "libhidlbase",
+    "libhidltransport",
     "libfmq",
     "libpdx_default_transport",
 ]
diff --git a/opengl/OWNERS b/opengl/OWNERS
index b505712..881f1b8 100644
--- a/opengl/OWNERS
+++ b/opengl/OWNERS
@@ -1,7 +1,16 @@
+# alanward@google.com
+chiur@google.com
 chrisforbes@google.com
 cnorthrop@google.com
 courtneygo@google.com
+hliatis@google.com
 ianelliott@google.com
 jessehall@google.com
 lpy@google.com
+marissaw@google.com
+nduca@google.com
+pmuetschard@google.com
+timvp@google.com
+tobine@google.com
+vhau@google.com
 zzyiwei@google.com
diff --git a/opengl/libagl/Android.bp b/opengl/libagl/Android.bp
index f5bf015..6ec24b3 100644
--- a/opengl/libagl/Android.bp
+++ b/opengl/libagl/Android.bp
@@ -25,9 +25,8 @@
         "libnativewindow",
     ],
 
-    header_libs: [
-        "bionic_libc_platform_headers",
-    ],
+    // we need to access the private Bionic header <bionic_tls.h>
+    include_dirs: ["bionic/libc/private"],
 
     arch: {
         arm: {
diff --git a/opengl/libagl/context.h b/opengl/libagl/context.h
index 6e77a23..18ef7d5 100644
--- a/opengl/libagl/context.h
+++ b/opengl/libagl/context.h
@@ -22,7 +22,7 @@
 #include <sys/types.h>
 #include <pthread.h>
 #ifdef __ANDROID__
-#include <bionic/tls.h>
+#include <bionic_tls.h>
 #endif
 
 #include <private/pixelflinger/ggl_context.h>
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index eb90c8b..abc7a72 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -72,13 +72,15 @@
         "libarect",
     ],
     header_libs: [
-        "bionic_libc_platform_headers",
         "gl_headers",
         "libsystem_headers",
         "libhardware_headers",
         "libnativebase_headers",
     ],
     export_header_lib_headers: ["gl_headers"],
+
+    // we need to access the private Bionic header <bionic_tls.h>
+    include_dirs: ["bionic/libc/private"],
 }
 
 //##############################################################################
@@ -151,6 +153,7 @@
         "android.hardware.configstore-utils",
         "libbase",
         "libhidlbase",
+        "libhidltransport",
         "libnativebridge_lazy",
         "libnativeloader_lazy",
         "libutils",
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index c51a129..29a966d 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -40,6 +40,7 @@
 
 EGLDisplay eglGetDisplay(EGLNativeDisplayType display) {
     ATRACE_CALL();
+    clearError();
 
     if (egl_init_drivers() == EGL_FALSE) {
         return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
@@ -47,7 +48,6 @@
 
     // Call down the chain, which usually points directly to the impl
     // but may also be routed through layers
-    clearError();
     egl_connection_t* const cnx = &gEGLImpl;
     return cnx->platform.eglGetDisplay(display);
 }
@@ -55,6 +55,7 @@
 EGLDisplay eglGetPlatformDisplay(EGLenum platform, EGLNativeDisplayType display,
                                  const EGLAttrib* attrib_list) {
     ATRACE_CALL();
+    clearError();
 
     if (egl_init_drivers() == EGL_FALSE) {
         return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
@@ -62,7 +63,6 @@
 
     // Call down the chain, which usually points directly to the impl
     // but may also be routed through layers
-    clearError();
     egl_connection_t* const cnx = &gEGLImpl;
     return cnx->platform.eglGetPlatformDisplay(platform, display, attrib_list);
 }
@@ -239,12 +239,13 @@
     // in which case we must make sure we've initialized ourselves, this
     // happens the first time egl_get_display() is called.
 
+    clearError();
+
     if (egl_init_drivers() == EGL_FALSE) {
         setError(EGL_BAD_PARAMETER, NULL);
         return nullptr;
     }
 
-    clearError();
     egl_connection_t* const cnx = &gEGLImpl;
     return cnx->platform.eglGetProcAddress(procname);
 }
@@ -323,21 +324,23 @@
 }
 
 EGLBoolean eglBindAPI(EGLenum api) {
+    clearError();
+
     if (egl_init_drivers() == EGL_FALSE) {
         return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
     }
 
-    clearError();
     egl_connection_t* const cnx = &gEGLImpl;
     return cnx->platform.eglBindAPI(api);
 }
 
 EGLenum eglQueryAPI(void) {
+    clearError();
+
     if (egl_init_drivers() == EGL_FALSE) {
         return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
     }
 
-    clearError();
     egl_connection_t* const cnx = &gEGLImpl;
     return cnx->platform.eglQueryAPI();
 }
@@ -592,21 +595,23 @@
 }
 
 EGLuint64NV eglGetSystemTimeFrequencyNV() {
+    clearError();
+
     if (egl_init_drivers() == EGL_FALSE) {
         return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
     }
 
-    clearError();
     egl_connection_t* const cnx = &gEGLImpl;
     return cnx->platform.eglGetSystemTimeFrequencyNV();
 }
 
 EGLuint64NV eglGetSystemTimeNV() {
+    clearError();
+
     if (egl_init_drivers() == EGL_FALSE) {
         return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
     }
 
-    clearError();
     egl_connection_t* const cnx = &gEGLImpl;
     return cnx->platform.eglGetSystemTimeNV();
 }
diff --git a/opengl/libs/EGL/egl_layers.cpp b/opengl/libs/EGL/egl_layers.cpp
index ac01dc8..ba7cacd 100644
--- a/opengl/libs/EGL/egl_layers.cpp
+++ b/opengl/libs/EGL/egl_layers.cpp
@@ -337,7 +337,7 @@
 
     // Only enable the system search path for non-user builds
     std::string system_path;
-    if (property_get_bool("ro.debuggable", false) && prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
+    if (android::GraphicsEnv::getInstance().isDebuggable()) {
         system_path = kSystemLayerLibraryDir;
     }
 
diff --git a/opengl/libs/ETC1/etc1.cpp b/opengl/libs/ETC1/etc1.cpp
index 19d428a..97d1085 100644
--- a/opengl/libs/ETC1/etc1.cpp
+++ b/opengl/libs/ETC1/etc1.cpp
@@ -378,30 +378,34 @@
         const etc1_byte* pColors, etc_compressed* pCompressed) {
     int r1, g1, b1, r2, g2, b2; // 8 bit base colors for sub-blocks
     bool differential;
-    int r51 = convert8To5(pColors[0]);
-    int g51 = convert8To5(pColors[1]);
-    int b51 = convert8To5(pColors[2]);
-    int r52 = convert8To5(pColors[3]);
-    int g52 = convert8To5(pColors[4]);
-    int b52 = convert8To5(pColors[5]);
+    {
+        int r51 = convert8To5(pColors[0]);
+        int g51 = convert8To5(pColors[1]);
+        int b51 = convert8To5(pColors[2]);
+        int r52 = convert8To5(pColors[3]);
+        int g52 = convert8To5(pColors[4]);
+        int b52 = convert8To5(pColors[5]);
 
-    r1 = convert5To8(r51);
-    g1 = convert5To8(g51);
-    b1 = convert5To8(b51);
+        r1 = convert5To8(r51);
+        g1 = convert5To8(g51);
+        b1 = convert5To8(b51);
 
-    int dr = r52 - r51;
-    int dg = g52 - g51;
-    int db = b52 - b51;
+        int dr = r52 - r51;
+        int dg = g52 - g51;
+        int db = b52 - b51;
 
-    differential = inRange4bitSigned(dr) && inRange4bitSigned(dg)
-            && inRange4bitSigned(db);
-    if (differential) {
-        r2 = convert5To8(r51 + dr);
-        g2 = convert5To8(g51 + dg);
-        b2 = convert5To8(b51 + db);
-        pCompressed->high |= (r51 << 27) | ((7 & dr) << 24) | (g51 << 19)
-                | ((7 & dg) << 16) | (b51 << 11) | ((7 & db) << 8) | 2;
-    } else {
+        differential = inRange4bitSigned(dr) && inRange4bitSigned(dg)
+                && inRange4bitSigned(db);
+        if (differential) {
+            r2 = convert5To8(r51 + dr);
+            g2 = convert5To8(g51 + dg);
+            b2 = convert5To8(b51 + db);
+            pCompressed->high |= (r51 << 27) | ((7 & dr) << 24) | (g51 << 19)
+                    | ((7 & dg) << 16) | (b51 << 11) | ((7 & db) << 8) | 2;
+        }
+    }
+
+    if (!differential) {
         int r41 = convert8To4(pColors[0]);
         int g41 = convert8To4(pColors[1]);
         int b41 = convert8To4(pColors[2]);
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index 86fec21..63a0e14 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -46,7 +46,7 @@
 #define MAX_NUMBER_OF_GL_EXTENSIONS 256
 
 
-#include <bionic/tls.h>  /* special private C library header */
+#include <bionic_tls.h>  /* special private C library header */
 
 // ----------------------------------------------------------------------------
 namespace android {
diff --git a/opengl/tests/EGLTest/Android.bp b/opengl/tests/EGLTest/Android.bp
index 8bfe517..a9e873a 100644
--- a/opengl/tests/EGLTest/Android.bp
+++ b/opengl/tests/EGLTest/Android.bp
@@ -22,17 +22,16 @@
         "libbinder",
         "libgui",
         "libhidlbase",
+        "libhidltransport",
         "liblog",
         "libutils",
         "libnativewindow",
     ],
 
     include_dirs: [
+        "bionic/libc/private",
         "frameworks/native/opengl/libs",
         "frameworks/native/opengl/libs/EGL",
     ],
 
-    header_libs: [
-        "bionic_libc_platform_headers",
-    ],
 }
diff --git a/opengl/tests/gl_perf/fill_common.cpp b/opengl/tests/gl_perf/fill_common.cpp
index 613f1c6..fefedc0 100644
--- a/opengl/tests/gl_perf/fill_common.cpp
+++ b/opengl/tests/gl_perf/fill_common.cpp
@@ -191,10 +191,10 @@
 static void randUniform(int pgm, const char *var) {
     GLint loc = glGetUniformLocation(pgm, var);
     if (loc >= 0) {
-        float x = ((float)rand()) / (float)RAND_MAX;
-        float y = ((float)rand()) / (float)RAND_MAX;
-        float z = ((float)rand()) / (float)RAND_MAX;
-        float w = ((float)rand()) / (float)RAND_MAX;
+        float x = ((float)rand()) / RAND_MAX;
+        float y = ((float)rand()) / RAND_MAX;
+        float z = ((float)rand()) / RAND_MAX;
+        float w = ((float)rand()) / RAND_MAX;
         glUniform4f(loc, x, y, z, w);
     }
 }
diff --git a/services/bufferhub/Android.bp b/services/bufferhub/Android.bp
index 2bb6aef..cd03bc2 100644
--- a/services/bufferhub/Android.bp
+++ b/services/bufferhub/Android.bp
@@ -37,6 +37,8 @@
         "libcrypto",
         "libcutils",
         "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
         "liblog",
         "libui",
         "libutils",
@@ -62,6 +64,8 @@
         "libcrypto",
         "libcutils",
         "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
         "liblog",
         "libui",
         "libutils",
diff --git a/services/displayservice/Android.bp b/services/displayservice/Android.bp
index 4d2d873..3442cb2 100644
--- a/services/displayservice/Android.bp
+++ b/services/displayservice/Android.bp
@@ -27,6 +27,7 @@
         "liblog",
         "libgui",
         "libhidlbase",
+        "libhidltransport",
         "libutils",
         "android.frameworks.displayservice@1.0",
     ],
diff --git a/services/gpuservice/Android.bp b/services/gpuservice/Android.bp
index 7b8e0f8..dbb6ba6 100644
--- a/services/gpuservice/Android.bp
+++ b/services/gpuservice/Android.bp
@@ -59,6 +59,9 @@
 cc_defaults {
     name: "gpuservice_binary",
     defaults: ["gpuservice_defaults"],
+    whole_static_libs: [
+        "libsigchain",
+    ],
     shared_libs: [
         "libbinder",
         "libcutils",
diff --git a/services/gpuservice/OWNERS b/services/gpuservice/OWNERS
deleted file mode 100644
index 5d02839..0000000
--- a/services/gpuservice/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-chrisforbes@google.com
-lpy@google.com
-zzyiwei@google.com
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 11578c3..576c8d8 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -30,6 +30,7 @@
     srcs: [
         "InputClassifier.cpp",
         "InputClassifierConverter.cpp",
+        "InputDispatcher.cpp",
         "InputManager.cpp",
     ],
 
@@ -46,11 +47,6 @@
         "liblog",
         "libutils",
         "libui",
-        "server_configurable_flags",
-    ],
-
-    static_libs: [
-        "libinputdispatcher",
     ],
 
     cflags: [
@@ -63,16 +59,44 @@
         "include",
     ],
 
-    export_static_lib_headers: [
-        "libinputdispatcher",
-    ],
 }
 
 cc_library_headers {
     name: "libinputflinger_headers",
-    header_libs: ["libinputreporter_headers"],
     export_include_dirs: ["include"],
-    export_header_lib_headers: ["libinputreporter_headers"],
+}
+
+cc_library_shared {
+    name: "libinputreader",
+    defaults: ["inputflinger_defaults"],
+
+    srcs: [
+        "EventHub.cpp",
+        "InputReader.cpp",
+        "InputReaderFactory.cpp",
+        "TouchVideoDevice.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libinputflinger_base",
+        "libcrypto",
+        "libcutils",
+        "libinput",
+        "liblog",
+        "libui",
+        "libutils",
+        "libhardware_legacy",
+        "libstatslog",
+    ],
+
+    header_libs: [
+        "libinputflinger_headers",
+    ],
+
+    export_header_lib_headers: [
+        "libinputflinger_headers",
+    ],
 }
 
 cc_library_shared {
@@ -100,6 +124,28 @@
     ],
 }
 
+cc_library_shared {
+    name: "libinputreporter",
+    defaults: ["inputflinger_defaults"],
+
+    srcs: [
+        "InputReporter.cpp",
+    ],
+
+    shared_libs: [
+        "liblog",
+        "libutils",
+    ],
+
+    header_libs: [
+        "libinputflinger_headers",
+    ],
+
+    export_header_lib_headers: [
+        "libinputflinger_headers",
+    ],
+}
+
 subdirs = [
     "host",
     "tests",
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/EventHub.cpp
similarity index 83%
rename from services/inputflinger/reader/EventHub.cpp
rename to services/inputflinger/EventHub.cpp
index a5e5415..ce56272 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -25,9 +25,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/epoll.h>
+#include <sys/limits.h>
 #include <sys/inotify.h>
 #include <sys/ioctl.h>
-#include <sys/limits.h>
 #include <sys/utsname.h>
 #include <unistd.h>
 
@@ -42,13 +42,13 @@
 #include <android-base/stringprintf.h>
 #include <cutils/properties.h>
 #include <openssl/sha.h>
-#include <utils/Errors.h>
 #include <utils/Log.h>
 #include <utils/Timers.h>
 #include <utils/threads.h>
+#include <utils/Errors.h>
 
-#include <input/KeyCharacterMap.h>
 #include <input/KeyLayoutMap.h>
+#include <input/KeyCharacterMap.h>
 #include <input/VirtualKeyMap.h>
 
 /* this macro is used to tell if "bit" is set in "array"
@@ -56,10 +56,10 @@
  * operation with a byte that only has the relevant bit set.
  * eg. to check for the 12th bit, we do (array[1] & 1<<4)
  */
-#define test_bit(bit, array) ((array)[(bit) / 8] & (1 << ((bit) % 8)))
+#define test_bit(bit, array)    ((array)[(bit)/8] & (1<<((bit)%8)))
 
 /* this macro computes the number of bytes needed to represent a bit array of the specified size */
-#define sizeof_bit_array(bits) (((bits) + 7) / 8)
+#define sizeof_bit_array(bits)  (((bits) + 7) / 8)
 
 #define INDENT "  "
 #define INDENT2 "    "
@@ -71,10 +71,10 @@
 
 static constexpr bool DEBUG = false;
 
-static const char* WAKE_LOCK_ID = "KeyEvents";
-static const char* DEVICE_PATH = "/dev/input";
+static const char *WAKE_LOCK_ID = "KeyEvents";
+static const char *DEVICE_PATH = "/dev/input";
 // v4l2 devices go directly into /dev
-static const char* VIDEO_DEVICE_PATH = "/dev";
+static const char *VIDEO_DEVICE_PATH = "/dev";
 
 static inline const char* toString(bool value) {
     return value ? "true" : "false";
@@ -126,7 +126,7 @@
  * directly from /dev.
  */
 static bool isV4lScanningEnabled() {
-    return property_get_bool("ro.input.video_enabled", true /* default_value */);
+  return property_get_bool("ro.input.video_enabled", true /* default_value */);
 }
 
 static nsecs_t processEventTimestamp(const struct input_event& event) {
@@ -153,27 +153,27 @@
     // Touch devices get dibs on touch-related axes.
     if (deviceClasses & INPUT_DEVICE_CLASS_TOUCH) {
         switch (axis) {
-            case ABS_X:
-            case ABS_Y:
-            case ABS_PRESSURE:
-            case ABS_TOOL_WIDTH:
-            case ABS_DISTANCE:
-            case ABS_TILT_X:
-            case ABS_TILT_Y:
-            case ABS_MT_SLOT:
-            case ABS_MT_TOUCH_MAJOR:
-            case ABS_MT_TOUCH_MINOR:
-            case ABS_MT_WIDTH_MAJOR:
-            case ABS_MT_WIDTH_MINOR:
-            case ABS_MT_ORIENTATION:
-            case ABS_MT_POSITION_X:
-            case ABS_MT_POSITION_Y:
-            case ABS_MT_TOOL_TYPE:
-            case ABS_MT_BLOB_ID:
-            case ABS_MT_TRACKING_ID:
-            case ABS_MT_PRESSURE:
-            case ABS_MT_DISTANCE:
-                return INPUT_DEVICE_CLASS_TOUCH;
+        case ABS_X:
+        case ABS_Y:
+        case ABS_PRESSURE:
+        case ABS_TOOL_WIDTH:
+        case ABS_DISTANCE:
+        case ABS_TILT_X:
+        case ABS_TILT_Y:
+        case ABS_MT_SLOT:
+        case ABS_MT_TOUCH_MAJOR:
+        case ABS_MT_TOUCH_MINOR:
+        case ABS_MT_WIDTH_MAJOR:
+        case ABS_MT_WIDTH_MINOR:
+        case ABS_MT_ORIENTATION:
+        case ABS_MT_POSITION_X:
+        case ABS_MT_POSITION_Y:
+        case ABS_MT_TOOL_TYPE:
+        case ABS_MT_BLOB_ID:
+        case ABS_MT_TRACKING_ID:
+        case ABS_MT_PRESSURE:
+        case ABS_MT_DISTANCE:
+            return INPUT_DEVICE_CLASS_TOUCH;
         }
     }
 
@@ -191,20 +191,12 @@
 // --- EventHub::Device ---
 
 EventHub::Device::Device(int fd, int32_t id, const std::string& path,
-                         const InputDeviceIdentifier& identifier)
-      : next(nullptr),
-        fd(fd),
-        id(id),
-        path(path),
-        identifier(identifier),
-        classes(0),
-        configuration(nullptr),
-        virtualKeyMap(nullptr),
-        ffEffectPlaying(false),
-        ffEffectId(-1),
-        controllerNumber(0),
-        enabled(true),
-        isVirtual(fd < 0) {
+        const InputDeviceIdentifier& identifier) :
+        next(nullptr),
+        fd(fd), id(id), path(path), identifier(identifier),
+        classes(0), configuration(nullptr), virtualKeyMap(nullptr),
+        ffEffectPlaying(false), ffEffectId(-1), controllerNumber(0),
+        enabled(true), isVirtual(fd < 0) {
     memset(keyBitmask, 0, sizeof(keyBitmask));
     memset(absBitmask, 0, sizeof(absBitmask));
     memset(relBitmask, 0, sizeof(relBitmask));
@@ -228,7 +220,7 @@
 
 status_t EventHub::Device::enable() {
     fd = open(path.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
-    if (fd < 0) {
+    if(fd < 0) {
         ALOGE("could not open %s, %s\n", path.c_str(), strerror(errno));
         return -errno;
     }
@@ -250,18 +242,12 @@
 
 const int EventHub::EPOLL_MAX_EVENTS;
 
-EventHub::EventHub(void)
-      : mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
-        mNextDeviceId(1),
-        mControllerNumbers(),
-        mOpeningDevices(nullptr),
-        mClosingDevices(nullptr),
+EventHub::EventHub(void) :
+        mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
+        mOpeningDevices(nullptr), mClosingDevices(nullptr),
         mNeedToSendFinishedDeviceScan(false),
-        mNeedToReopenDevices(false),
-        mNeedToScanDevices(true),
-        mPendingEventCount(0),
-        mPendingEventIndex(0),
-        mPendingINotify(false) {
+        mNeedToReopenDevices(false), mNeedToScanDevices(true),
+        mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
     acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
 
     mEpollFd = epoll_create1(EPOLL_CLOEXEC);
@@ -269,12 +255,12 @@
 
     mINotifyFd = inotify_init();
     mInputWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
-    LOG_ALWAYS_FATAL_IF(mInputWd < 0, "Could not register INotify for %s: %s", DEVICE_PATH,
-                        strerror(errno));
+    LOG_ALWAYS_FATAL_IF(mInputWd < 0, "Could not register INotify for %s: %s",
+            DEVICE_PATH, strerror(errno));
     if (isV4lScanningEnabled()) {
         mVideoWd = inotify_add_watch(mINotifyFd, VIDEO_DEVICE_PATH, IN_DELETE | IN_CREATE);
         LOG_ALWAYS_FATAL_IF(mVideoWd < 0, "Could not register INotify for %s: %s",
-                            VIDEO_DEVICE_PATH, strerror(errno));
+                VIDEO_DEVICE_PATH, strerror(errno));
     } else {
         mVideoWd = -1;
         ALOGI("Video device scanning disabled");
@@ -296,16 +282,16 @@
 
     result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
     LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
-                        errno);
+            errno);
 
     result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
     LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
-                        errno);
+            errno);
 
     eventItem.data.fd = mWakeReadPipeFd;
     result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
     LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
-                        errno);
+            errno);
 
     int major, minor;
     getLinuxRelease(&major, &minor);
@@ -362,7 +348,7 @@
 }
 
 status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
-                                       RawAbsoluteAxisInfo* outAxisInfo) const {
+        RawAbsoluteAxisInfo* outAxisInfo) const {
     outAxisInfo->clear();
 
     if (axis >= 0 && axis <= ABS_MAX) {
@@ -371,9 +357,9 @@
         Device* device = getDeviceLocked(deviceId);
         if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) {
             struct input_absinfo info;
-            if (ioctl(device->fd, EVIOCGABS(axis), &info)) {
-                ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", axis,
-                      device->identifier.name.c_str(), device->fd, errno);
+            if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
+                ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
+                     axis, device->identifier.name.c_str(), device->fd, errno);
                 return -errno;
             }
 
@@ -480,9 +466,9 @@
         Device* device = getDeviceLocked(deviceId);
         if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) {
             struct input_absinfo info;
-            if (ioctl(device->fd, EVIOCGABS(axis), &info)) {
-                ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", axis,
-                      device->identifier.name.c_str(), device->fd, errno);
+            if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
+                ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
+                     axis, device->identifier.name.c_str(), device->fd, errno);
                 return -errno;
             }
 
@@ -493,8 +479,8 @@
     return -1;
 }
 
-bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
-                                     uint8_t* outFlags) const {
+bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
+        const int32_t* keyCodes, uint8_t* outFlags) const {
     AutoMutex _l(mLock);
 
     Device* device = getDeviceLocked(deviceId);
@@ -503,9 +489,9 @@
         for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
             scanCodes.clear();
 
-            status_t err = device->keyMap.keyLayoutMap->findScanCodesForKey(keyCodes[codeIndex],
-                                                                            &scanCodes);
-            if (!err) {
+            status_t err = device->keyMap.keyLayoutMap->findScanCodesForKey(
+                    keyCodes[codeIndex], &scanCodes);
+            if (! err) {
                 // check the possible scan codes identified by the layout map against the
                 // map of codes actually emitted by the driver
                 for (size_t sc = 0; sc < scanCodes.size(); sc++) {
@@ -521,8 +507,9 @@
     return false;
 }
 
-status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState,
-                          int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const {
+status_t EventHub::mapKey(int32_t deviceId,
+        int32_t scanCode, int32_t usageCode, int32_t metaState,
+        int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const {
     AutoMutex _l(mLock);
     Device* device = getDeviceLocked(deviceId);
     status_t status = NAME_NOT_FOUND;
@@ -629,7 +616,7 @@
 }
 
 void EventHub::getVirtualKeyDefinitions(int32_t deviceId,
-                                        std::vector<VirtualKeyDefinition>& outVirtualKeys) const {
+        std::vector<VirtualKeyDefinition>& outVirtualKeys) const {
     outVirtualKeys.clear();
 
     AutoMutex _l(mLock);
@@ -650,13 +637,15 @@
     return nullptr;
 }
 
-bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) {
+bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId,
+        const sp<KeyCharacterMap>& map) {
     AutoMutex _l(mLock);
     Device* device = getDeviceLocked(deviceId);
     if (device) {
         if (map != device->overlayKeyMap) {
             device->overlayKeyMap = map;
-            device->combinedKeyMap = KeyCharacterMap::combine(device->keyMap.keyCharacterMap, map);
+            device->combinedKeyMap = KeyCharacterMap::combine(
+                    device->keyMap.keyCharacterMap, map);
             return true;
         }
     }
@@ -665,7 +654,8 @@
 
 static std::string generateDescriptor(InputDeviceIdentifier& identifier) {
     std::string rawDescriptor;
-    rawDescriptor += StringPrintf(":%04x:%04x:", identifier.vendor, identifier.product);
+    rawDescriptor += StringPrintf(":%04x:%04x:", identifier.vendor,
+            identifier.product);
     // TODO add handling for USB devices to not uniqueify kbs that show up twice
     if (!identifier.uniqueId.empty()) {
         rawDescriptor += "uniqueId:";
@@ -704,13 +694,13 @@
     if (identifier.uniqueId.empty()) {
         // If it didn't have a unique id check for conflicts and enforce
         // uniqueness if necessary.
-        while (getDeviceByDescriptorLocked(identifier.descriptor) != nullptr) {
+        while(getDeviceByDescriptorLocked(identifier.descriptor) != nullptr) {
             identifier.nonce++;
             rawDescriptor = generateDescriptor(identifier);
         }
     }
     ALOGV("Created descriptor: raw=%s, cooked=%s", rawDescriptor.c_str(),
-          identifier.descriptor.c_str());
+            identifier.descriptor.c_str());
 }
 
 void EventHub::vibrate(int32_t deviceId, nsecs_t duration) {
@@ -727,7 +717,7 @@
         effect.replay.delay = 0;
         if (ioctl(device->fd, EVIOCSFF, &effect)) {
             ALOGW("Could not upload force feedback effect to device %s due to error %d.",
-                  device->identifier.name.c_str(), errno);
+                    device->identifier.name.c_str(), errno);
             return;
         }
         device->ffEffectId = effect.id;
@@ -740,7 +730,7 @@
         ev.value = 1;
         if (write(device->fd, &ev, sizeof(ev)) != sizeof(ev)) {
             ALOGW("Could not start force feedback effect on device %s due to error %d.",
-                  device->identifier.name.c_str(), errno);
+                    device->identifier.name.c_str(), errno);
             return;
         }
         device->ffEffectPlaying = true;
@@ -762,7 +752,7 @@
             ev.value = 0;
             if (write(device->fd, &ev, sizeof(ev)) != sizeof(ev)) {
                 ALOGW("Could not stop force feedback effect on device %s due to error %d.",
-                      device->identifier.name.c_str(), errno);
+                        device->identifier.name.c_str(), errno);
                 return;
             }
         }
@@ -849,12 +839,12 @@
         // Report any devices that had last been added/removed.
         while (mClosingDevices) {
             Device* device = mClosingDevices;
-            ALOGV("Reporting device closed: id=%d, name=%s\n", device->id, device->path.c_str());
+            ALOGV("Reporting device closed: id=%d, name=%s\n",
+                 device->id, device->path.c_str());
             mClosingDevices = device->next;
             event->when = now;
-            event->deviceId = (device->id == mBuiltInKeyboardId)
-                    ? ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID
-                    : device->id;
+            event->deviceId = (device->id == mBuiltInKeyboardId) ?
+                    ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID : device->id;
             event->type = DEVICE_REMOVED;
             event += 1;
             delete device;
@@ -872,7 +862,8 @@
 
         while (mOpeningDevices != nullptr) {
             Device* device = mOpeningDevices;
-            ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
+            ALOGV("Reporting device opened: id=%d, name=%s\n",
+                 device->id, device->path.c_str());
             mOpeningDevices = device->next;
             event->when = now;
             event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
@@ -918,15 +909,15 @@
                     } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
                 } else {
                     ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",
-                          eventItem.events);
+                            eventItem.events);
                 }
                 continue;
             }
 
             Device* device = getDeviceByFdLocked(eventItem.data.fd);
             if (!device) {
-                ALOGE("Received unexpected epoll event 0x%08x for unknown fd %d.", eventItem.events,
-                      eventItem.data.fd);
+                ALOGE("Received unexpected epoll event 0x%08x for unknown fd %d.",
+                        eventItem.events, eventItem.data.fd);
                 ALOG_ASSERT(!DEBUG);
                 continue;
             }
@@ -935,30 +926,30 @@
                     size_t numFrames = device->videoDevice->readAndQueueFrames();
                     if (numFrames == 0) {
                         ALOGE("Received epoll event for video device %s, but could not read frame",
-                              device->videoDevice->getName().c_str());
+                                device->videoDevice->getName().c_str());
                     }
                 } else if (eventItem.events & EPOLLHUP) {
                     // TODO(b/121395353) - consider adding EPOLLRDHUP
                     ALOGI("Removing video device %s due to epoll hang-up event.",
-                          device->videoDevice->getName().c_str());
+                            device->videoDevice->getName().c_str());
                     unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
                     device->videoDevice = nullptr;
                 } else {
-                    ALOGW("Received unexpected epoll event 0x%08x for device %s.", eventItem.events,
-                          device->videoDevice->getName().c_str());
+                    ALOGW("Received unexpected epoll event 0x%08x for device %s.",
+                            eventItem.events, device->videoDevice->getName().c_str());
                     ALOG_ASSERT(!DEBUG);
                 }
                 continue;
             }
             // This must be an input event
             if (eventItem.events & EPOLLIN) {
-                int32_t readSize =
-                        read(device->fd, readBuffer, sizeof(struct input_event) * capacity);
+                int32_t readSize = read(device->fd, readBuffer,
+                        sizeof(struct input_event) * capacity);
                 if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
                     // Device was removed before INotify noticed.
                     ALOGW("could not get event, removed? (fd: %d size: %" PRId32
-                          " bufferSize: %zu capacity: %zu errno: %d)\n",
-                          device->fd, readSize, bufferSize, capacity, errno);
+                            " bufferSize: %zu capacity: %zu errno: %d)\n",
+                            device->fd, readSize, bufferSize, capacity, errno);
                     deviceChanged = true;
                     closeDeviceLocked(device);
                 } else if (readSize < 0) {
@@ -990,12 +981,12 @@
                 }
             } else if (eventItem.events & EPOLLHUP) {
                 ALOGI("Removing device %s due to epoll hang-up event.",
-                      device->identifier.name.c_str());
+                        device->identifier.name.c_str());
                 deviceChanged = true;
                 closeDeviceLocked(device);
             } else {
-                ALOGW("Received unexpected epoll event 0x%08x for device %s.", eventItem.events,
-                      device->identifier.name.c_str());
+                ALOGW("Received unexpected epoll event 0x%08x for device %s.",
+                        eventItem.events, device->identifier.name.c_str());
             }
         }
 
@@ -1090,7 +1081,7 @@
 
 void EventHub::scanDevicesLocked() {
     status_t result = scanDirLocked(DEVICE_PATH);
-    if (result < 0) {
+    if(result < 0) {
         ALOGE("scan dir failed for %s", DEVICE_PATH);
     }
     if (isV4lScanningEnabled()) {
@@ -1118,12 +1109,12 @@
 }
 
 static const int32_t GAMEPAD_KEYCODES[] = {
-        AKEYCODE_BUTTON_A,      AKEYCODE_BUTTON_B,      AKEYCODE_BUTTON_C,    //
-        AKEYCODE_BUTTON_X,      AKEYCODE_BUTTON_Y,      AKEYCODE_BUTTON_Z,    //
-        AKEYCODE_BUTTON_L1,     AKEYCODE_BUTTON_R1,                           //
-        AKEYCODE_BUTTON_L2,     AKEYCODE_BUTTON_R2,                           //
-        AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR,                       //
-        AKEYCODE_BUTTON_START,  AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE, //
+        AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C,
+        AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z,
+        AKEYCODE_BUTTON_L1, AKEYCODE_BUTTON_R1,
+        AKEYCODE_BUTTON_L2, AKEYCODE_BUTTON_R2,
+        AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR,
+        AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE,
 };
 
 status_t EventHub::registerFdForEpoll(int fd) {
@@ -1190,7 +1181,7 @@
         status_t result = unregisterFdFromEpoll(videoDevice.getFd());
         if (result != OK) {
             ALOGW("Could not remove video device fd from epoll for device: %s",
-                  videoDevice.getName().c_str());
+                    videoDevice.getName().c_str());
         }
     }
 }
@@ -1201,7 +1192,7 @@
     ALOGV("Opening device: %s", devicePath);
 
     int fd = open(devicePath, O_RDWR | O_CLOEXEC | O_NONBLOCK);
-    if (fd < 0) {
+    if(fd < 0) {
         ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
         return -1;
     }
@@ -1209,7 +1200,7 @@
     InputDeviceIdentifier identifier;
 
     // Get device name.
-    if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
+    if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
         ALOGE("Could not get device name for %s: %s", devicePath, strerror(errno));
     } else {
         buffer[sizeof(buffer) - 1] = '\0';
@@ -1228,7 +1219,7 @@
 
     // Get device driver version.
     int driverVersion;
-    if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {
+    if(ioctl(fd, EVIOCGVERSION, &driverVersion)) {
         ALOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
         close(fd);
         return -1;
@@ -1236,7 +1227,7 @@
 
     // Get device identifier.
     struct input_id inputId;
-    if (ioctl(fd, EVIOCGID, &inputId)) {
+    if(ioctl(fd, EVIOCGID, &inputId)) {
         ALOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
         close(fd);
         return -1;
@@ -1247,16 +1238,16 @@
     identifier.version = inputId.version;
 
     // Get device physical location.
-    if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
-        // fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
+    if(ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
+        //fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
     } else {
         buffer[sizeof(buffer) - 1] = '\0';
         identifier.location = buffer;
     }
 
     // Get device unique id.
-    if (ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
-        // fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
+    if(ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
+        //fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
     } else {
         buffer[sizeof(buffer) - 1] = '\0';
         identifier.uniqueId = buffer;
@@ -1271,16 +1262,16 @@
 
     ALOGV("add device %d: %s\n", deviceId, devicePath);
     ALOGV("  bus:        %04x\n"
-          "  vendor      %04x\n"
-          "  product     %04x\n"
-          "  version     %04x\n",
-          identifier.bus, identifier.vendor, identifier.product, identifier.version);
+         "  vendor      %04x\n"
+         "  product     %04x\n"
+         "  version     %04x\n",
+        identifier.bus, identifier.vendor, identifier.product, identifier.version);
     ALOGV("  name:       \"%s\"\n", identifier.name.c_str());
     ALOGV("  location:   \"%s\"\n", identifier.location.c_str());
     ALOGV("  unique id:  \"%s\"\n", identifier.uniqueId.c_str());
     ALOGV("  descriptor: \"%s\"\n", identifier.descriptor.c_str());
-    ALOGV("  driver:     v%d.%d.%d\n", driverVersion >> 16, (driverVersion >> 8) & 0xff,
-          driverVersion & 0xff);
+    ALOGV("  driver:     v%d.%d.%d\n",
+        driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
 
     // Load the configuration file for the device.
     loadConfigurationLocked(device);
@@ -1296,21 +1287,21 @@
 
     // See if this is a keyboard.  Ignore everything in the button range except for
     // joystick and gamepad buttons which are handled like keyboards for the most part.
-    bool haveKeyboardKeys =
-            containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC)) ||
-            containsNonZeroByte(device->keyBitmask, sizeof_bit_array(KEY_OK),
-                                sizeof_bit_array(KEY_MAX + 1));
+    bool haveKeyboardKeys = containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC))
+            || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(KEY_OK),
+                    sizeof_bit_array(KEY_MAX + 1));
     bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC),
-                                                  sizeof_bit_array(BTN_MOUSE)) ||
-            containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK),
-                                sizeof_bit_array(BTN_DIGI));
+                    sizeof_bit_array(BTN_MOUSE))
+            || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK),
+                    sizeof_bit_array(BTN_DIGI));
     if (haveKeyboardKeys || haveGamepadButtons) {
         device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
     }
 
     // See if this is a cursor device such as a trackball or mouse.
-    if (test_bit(BTN_MOUSE, device->keyBitmask) && test_bit(REL_X, device->relBitmask) &&
-        test_bit(REL_Y, device->relBitmask)) {
+    if (test_bit(BTN_MOUSE, device->keyBitmask)
+            && test_bit(REL_X, device->relBitmask)
+            && test_bit(REL_Y, device->relBitmask)) {
         device->classes |= INPUT_DEVICE_CLASS_CURSOR;
     }
 
@@ -1318,29 +1309,31 @@
     String8 deviceType = String8();
     if (device->configuration &&
         device->configuration->tryGetProperty(String8("device.type"), deviceType)) {
-        if (!deviceType.compare(String8("rotaryEncoder"))) {
-            device->classes |= INPUT_DEVICE_CLASS_ROTARY_ENCODER;
-        }
+            if (!deviceType.compare(String8("rotaryEncoder"))) {
+                device->classes |= INPUT_DEVICE_CLASS_ROTARY_ENCODER;
+            }
     }
 
     // See if this is a touch pad.
     // Is this a new modern multi-touch driver?
-    if (test_bit(ABS_MT_POSITION_X, device->absBitmask) &&
-        test_bit(ABS_MT_POSITION_Y, device->absBitmask)) {
+    if (test_bit(ABS_MT_POSITION_X, device->absBitmask)
+            && test_bit(ABS_MT_POSITION_Y, device->absBitmask)) {
         // Some joysticks such as the PS3 controller report axes that conflict
         // with the ABS_MT range.  Try to confirm that the device really is
         // a touch screen.
         if (test_bit(BTN_TOUCH, device->keyBitmask) || !haveGamepadButtons) {
             device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
         }
-        // Is this an old style single-touch driver?
-    } else if (test_bit(BTN_TOUCH, device->keyBitmask) && test_bit(ABS_X, device->absBitmask) &&
-               test_bit(ABS_Y, device->absBitmask)) {
+    // Is this an old style single-touch driver?
+    } else if (test_bit(BTN_TOUCH, device->keyBitmask)
+            && test_bit(ABS_X, device->absBitmask)
+            && test_bit(ABS_Y, device->absBitmask)) {
         device->classes |= INPUT_DEVICE_CLASS_TOUCH;
-        // Is this a BT stylus?
+    // Is this a BT stylus?
     } else if ((test_bit(ABS_PRESSURE, device->absBitmask) ||
-                test_bit(BTN_TOUCH, device->keyBitmask)) &&
-               !test_bit(ABS_X, device->absBitmask) && !test_bit(ABS_Y, device->absBitmask)) {
+                test_bit(BTN_TOUCH, device->keyBitmask))
+            && !test_bit(ABS_X, device->absBitmask)
+            && !test_bit(ABS_Y, device->absBitmask)) {
         device->classes |= INPUT_DEVICE_CLASS_EXTERNAL_STYLUS;
         // Keyboard will try to claim some of the buttons but we really want to reserve those so we
         // can fuse it with the touch screen data, so just take them back. Note this means an
@@ -1354,8 +1347,8 @@
     if (haveGamepadButtons) {
         uint32_t assumedClasses = device->classes | INPUT_DEVICE_CLASS_JOYSTICK;
         for (int i = 0; i <= ABS_MAX; i++) {
-            if (test_bit(i, device->absBitmask) &&
-                (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) {
+            if (test_bit(i, device->absBitmask)
+                    && (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) {
                 device->classes = assumedClasses;
                 break;
             }
@@ -1396,8 +1389,10 @@
     // Configure the keyboard, gamepad or virtual keyboard.
     if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {
         // Register the keyboard as a built-in keyboard if it is eligible.
-        if (!keyMapStatus && mBuiltInKeyboardId == NO_BUILT_IN_KEYBOARD &&
-            isEligibleBuiltInKeyboard(device->identifier, device->configuration, &device->keyMap)) {
+        if (!keyMapStatus
+                && mBuiltInKeyboardId == NO_BUILT_IN_KEYBOARD
+                && isEligibleBuiltInKeyboard(device->identifier,
+                        device->configuration, &device->keyMap)) {
             mBuiltInKeyboardId = device->id;
         }
 
@@ -1408,15 +1403,15 @@
 
         // See if this device has a DPAD.
         if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
-            hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
-            hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
-            hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
-            hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
+                hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
+                hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
+                hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
+                hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
             device->classes |= INPUT_DEVICE_CLASS_DPAD;
         }
 
         // See if this device has a gamepad.
-        for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES) / sizeof(GAMEPAD_KEYCODES[0]); i++) {
+        for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
             if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
                 device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
                 break;
@@ -1426,8 +1421,8 @@
 
     // If the device isn't recognized as something we handle, don't monitor it.
     if (device->classes == 0) {
-        ALOGV("Dropping device: id=%d, path='%s', name='%s'", deviceId, devicePath,
-              device->identifier.name.c_str());
+        ALOGV("Dropping device: id=%d, path='%s', name='%s'",
+                deviceId, devicePath, device->identifier.name.c_str());
         delete device;
         return -1;
     }
@@ -1442,8 +1437,8 @@
         device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
     }
 
-    if (device->classes & (INPUT_DEVICE_CLASS_JOYSTICK | INPUT_DEVICE_CLASS_DPAD) &&
-        device->classes & INPUT_DEVICE_CLASS_GAMEPAD) {
+    if (device->classes & (INPUT_DEVICE_CLASS_JOYSTICK | INPUT_DEVICE_CLASS_DPAD)
+            && device->classes & INPUT_DEVICE_CLASS_GAMEPAD) {
         device->controllerNumber = getNextControllerNumberLocked(device);
         setLedForControllerLocked(device);
     }
@@ -1456,12 +1451,10 @@
             break;
         }
     }
-    mUnattachedVideoDevices
-            .erase(std::remove_if(mUnattachedVideoDevices.begin(), mUnattachedVideoDevices.end(),
-                                  [](const std::unique_ptr<TouchVideoDevice>& videoDevice) {
-                                      return videoDevice == nullptr;
-                                  }),
-                   mUnattachedVideoDevices.end());
+    mUnattachedVideoDevices.erase(std::remove_if(mUnattachedVideoDevices.begin(),
+            mUnattachedVideoDevices.end(),
+            [](const std::unique_ptr<TouchVideoDevice>& videoDevice){
+            return videoDevice == nullptr; }), mUnattachedVideoDevices.end());
 
     if (registerDeviceForEpollLocked(device) != OK) {
         delete device;
@@ -1471,10 +1464,13 @@
     configureFd(device);
 
     ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
-          "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
-          deviceId, fd, devicePath, device->identifier.name.c_str(), device->classes,
-          device->configurationFile.c_str(), device->keyMap.keyLayoutFile.c_str(),
-          device->keyMap.keyCharacterMapFile.c_str(), toString(mBuiltInKeyboardId == deviceId));
+            "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
+         deviceId, fd, devicePath, device->identifier.name.c_str(),
+         device->classes,
+         device->configurationFile.c_str(),
+         device->keyMap.keyLayoutFile.c_str(),
+         device->keyMap.keyCharacterMapFile.c_str(),
+         toString(mBuiltInKeyboardId == deviceId));
 
     addDeviceLocked(device);
     return OK;
@@ -1486,8 +1482,8 @@
         // Disable kernel key repeat since we handle it ourselves
         unsigned int repeatRate[] = {0, 0};
         if (ioctl(device->fd, EVIOCSREP, repeatRate)) {
-            ALOGW("Unable to disable kernel key repeat for %s: %s", device->path.c_str(),
-                  strerror(errno));
+            ALOGW("Unable to disable kernel key repeat for %s: %s",
+                  device->path.c_str(), strerror(errno));
         }
     }
 
@@ -1511,7 +1507,8 @@
     // clock.
     int clockId = CLOCK_MONOTONIC;
     bool usingClockIoctl = !ioctl(device->fd, EVIOCSCLOCKID, &clockId);
-    ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.c_str(), toString(usingClockIoctl));
+    ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.c_str(),
+          toString(usingClockIoctl));
 }
 
 void EventHub::openVideoDeviceLocked(const std::string& devicePath) {
@@ -1535,7 +1532,7 @@
     // Couldn't find a matching input device, so just add it to a temporary holding queue.
     // A matching input device may appear later.
     ALOGI("Adding video device %s to list of unattached video devices",
-          videoDevice->getName().c_str());
+            videoDevice->getName().c_str());
     mUnattachedVideoDevices.push_back(std::move(videoDevice));
 }
 
@@ -1592,10 +1589,12 @@
     identifier.uniqueId = "<virtual>";
     assignDescriptorLocked(identifier);
 
-    Device* device =
-            new Device(-1, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, "<virtual>", identifier);
-    device->classes = INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY |
-            INPUT_DEVICE_CLASS_DPAD | INPUT_DEVICE_CLASS_VIRTUAL;
+    Device* device = new Device(-1, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, "<virtual>",
+            identifier);
+    device->classes = INPUT_DEVICE_CLASS_KEYBOARD
+            | INPUT_DEVICE_CLASS_ALPHAKEY
+            | INPUT_DEVICE_CLASS_DPAD
+            | INPUT_DEVICE_CLASS_VIRTUAL;
     loadKeyMapLocked(device);
     addDeviceLocked(device);
 }
@@ -1611,14 +1610,14 @@
             device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
     if (device->configurationFile.empty()) {
         ALOGD("No input device configuration file found for device '%s'.",
-              device->identifier.name.c_str());
+                device->identifier.name.c_str());
     } else {
         status_t status = PropertyMap::load(String8(device->configurationFile.c_str()),
-                                            &device->configuration);
+                &device->configuration);
         if (status) {
             ALOGE("Error loading input device configuration file for device '%s'.  "
-                  "Using default configuration.",
-                  device->identifier.name.c_str());
+                    "Using default configuration.",
+                    device->identifier.name.c_str());
         }
     }
 }
@@ -1662,7 +1661,7 @@
 int32_t EventHub::getNextControllerNumberLocked(Device* device) {
     if (mControllerNumbers.isFull()) {
         ALOGI("Maximum number of controllers reached, assigning controller number 0 to device %s",
-              device->identifier.name.c_str());
+                device->identifier.name.c_str());
         return 0;
     }
     // Since the controller number 0 is reserved for non-controllers, translate all numbers up by
@@ -1672,7 +1671,7 @@
 
 void EventHub::releaseControllerNumberLocked(Device* device) {
     int32_t num = device->controllerNumber;
-    device->controllerNumber = 0;
+    device->controllerNumber= 0;
     if (num == 0) {
         return;
     }
@@ -1693,7 +1692,7 @@
     std::vector<int32_t> scanCodes;
     device->keyMap.keyLayoutMap->findScanCodesForKey(keycode, &scanCodes);
     const size_t N = scanCodes.size();
-    for (size_t i = 0; i < N && i <= KEY_MAX; i++) {
+    for (size_t i=0; i<N && i<=KEY_MAX; i++) {
         int32_t sc = scanCodes[i];
         if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
             return true;
@@ -1709,8 +1708,8 @@
     }
 
     int32_t scanCode;
-    if (device->keyMap.keyLayoutMap->findScanCodeForLed(led, &scanCode) != NAME_NOT_FOUND) {
-        if (scanCode >= 0 && scanCode <= LED_MAX && test_bit(scanCode, device->ledBitmask)) {
+    if(device->keyMap.keyLayoutMap->findScanCodeForLed(led, &scanCode) != NAME_NOT_FOUND) {
+        if(scanCode >= 0 && scanCode <= LED_MAX && test_bit(scanCode, device->ledBitmask)) {
             *outScanCode = scanCode;
             return NO_ERROR;
         }
@@ -1718,7 +1717,7 @@
     return NAME_NOT_FOUND;
 }
 
-void EventHub::closeDeviceByPathLocked(const char* devicePath) {
+void EventHub::closeDeviceByPathLocked(const char *devicePath) {
     Device* device = getDeviceByPathLocked(devicePath);
     if (device) {
         closeDeviceLocked(device);
@@ -1743,13 +1742,10 @@
             return;
         }
     }
-    mUnattachedVideoDevices
-            .erase(std::remove_if(mUnattachedVideoDevices.begin(), mUnattachedVideoDevices.end(),
-                                  [&devicePath](
-                                          const std::unique_ptr<TouchVideoDevice>& videoDevice) {
-                                      return videoDevice->getPath() == devicePath;
-                                  }),
-                   mUnattachedVideoDevices.end());
+    mUnattachedVideoDevices.erase(std::remove_if(mUnattachedVideoDevices.begin(),
+            mUnattachedVideoDevices.end(), [&devicePath](
+            const std::unique_ptr<TouchVideoDevice>& videoDevice) {
+            return videoDevice->getPath() == devicePath; }), mUnattachedVideoDevices.end());
 }
 
 void EventHub::closeAllDevicesLocked() {
@@ -1760,12 +1756,13 @@
 }
 
 void EventHub::closeDeviceLocked(Device* device) {
-    ALOGI("Removed device: path=%s name=%s id=%d fd=%d classes=0x%x", device->path.c_str(),
-          device->identifier.name.c_str(), device->id, device->fd, device->classes);
+    ALOGI("Removed device: path=%s name=%s id=%d fd=%d classes=0x%x",
+         device->path.c_str(), device->identifier.name.c_str(), device->id,
+         device->fd, device->classes);
 
     if (device->id == mBuiltInKeyboardId) {
         ALOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
-              device->path.c_str(), mBuiltInKeyboardId);
+                device->path.c_str(), mBuiltInKeyboardId);
         mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD;
     }
 
@@ -1783,7 +1780,7 @@
     // Unlink for opening devices list if it is present.
     Device* pred = nullptr;
     bool found = false;
-    for (Device* entry = mOpeningDevices; entry != nullptr;) {
+    for (Device* entry = mOpeningDevices; entry != nullptr; ) {
         if (entry == device) {
             found = true;
             break;
@@ -1815,28 +1812,30 @@
     char event_buf[512];
     int event_size;
     int event_pos = 0;
-    struct inotify_event* event;
+    struct inotify_event *event;
 
     ALOGV("EventHub::readNotify nfd: %d\n", mINotifyFd);
     res = read(mINotifyFd, event_buf, sizeof(event_buf));
-    if (res < (int)sizeof(*event)) {
-        if (errno == EINTR) return 0;
+    if(res < (int)sizeof(*event)) {
+        if(errno == EINTR)
+            return 0;
         ALOGW("could not get event, %s\n", strerror(errno));
         return -1;
     }
 
-    while (res >= (int)sizeof(*event)) {
-        event = (struct inotify_event*)(event_buf + event_pos);
-        if (event->len) {
+    while(res >= (int)sizeof(*event)) {
+        event = (struct inotify_event *)(event_buf + event_pos);
+        if(event->len) {
             if (event->wd == mInputWd) {
                 std::string filename = StringPrintf("%s/%s", DEVICE_PATH, event->name);
-                if (event->mask & IN_CREATE) {
+                if(event->mask & IN_CREATE) {
                     openDeviceLocked(filename.c_str());
                 } else {
                     ALOGI("Removing device '%s' due to inotify event\n", filename.c_str());
                     closeDeviceByPathLocked(filename.c_str());
                 }
-            } else if (event->wd == mVideoWd) {
+            }
+            else if (event->wd == mVideoWd) {
                 if (isV4lTouchNode(event->name)) {
                     std::string filename = StringPrintf("%s/%s", VIDEO_DEVICE_PATH, event->name);
                     if (event->mask & IN_CREATE) {
@@ -1846,7 +1845,8 @@
                         closeVideoDeviceByPathLocked(filename);
                     }
                 }
-            } else {
+            }
+            else {
                 LOG_ALWAYS_FATAL("Unexpected inotify event, wd = %i", event->wd);
             }
         }
@@ -1857,19 +1857,22 @@
     return 0;
 }
 
-status_t EventHub::scanDirLocked(const char* dirname) {
+status_t EventHub::scanDirLocked(const char *dirname)
+{
     char devname[PATH_MAX];
-    char* filename;
-    DIR* dir;
-    struct dirent* de;
+    char *filename;
+    DIR *dir;
+    struct dirent *de;
     dir = opendir(dirname);
-    if (dir == nullptr) return -1;
+    if(dir == nullptr)
+        return -1;
     strcpy(devname, dirname);
     filename = devname + strlen(devname);
     *filename++ = '/';
-    while ((de = readdir(dir))) {
-        if (de->d_name[0] == '.' &&
-            (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0')))
+    while((de = readdir(dir))) {
+        if(de->d_name[0] == '.' &&
+           (de->d_name[1] == '\0' ||
+            (de->d_name[1] == '.' && de->d_name[2] == '\0')))
             continue;
         strcpy(filename, de->d_name);
         openDeviceLocked(devname);
@@ -1881,16 +1884,17 @@
 /**
  * Look for all dirname/v4l-touch* devices, and open them.
  */
-status_t EventHub::scanVideoDirLocked(const std::string& dirname) {
+status_t EventHub::scanVideoDirLocked(const std::string& dirname)
+{
     DIR* dir;
     struct dirent* de;
     dir = opendir(dirname.c_str());
-    if (!dir) {
+    if(!dir) {
         ALOGE("Could not open video directory %s", dirname.c_str());
         return BAD_VALUE;
     }
 
-    while ((de = readdir(dir))) {
+    while((de = readdir(dir))) {
         const char* name = de->d_name;
         if (isV4lTouchNode(name)) {
             ALOGI("Found touch video device %s", name);
@@ -1922,10 +1926,10 @@
             const Device* device = mDevices.valueAt(i);
             if (mBuiltInKeyboardId == device->id) {
                 dump += StringPrintf(INDENT2 "%d: %s (aka device 0 - built-in keyboard)\n",
-                                     device->id, device->identifier.name.c_str());
+                        device->id, device->identifier.name.c_str());
             } else {
                 dump += StringPrintf(INDENT2 "%d: %s\n", device->id,
-                                     device->identifier.name.c_str());
+                        device->identifier.name.c_str());
             }
             dump += StringPrintf(INDENT3 "Classes: 0x%08x\n", device->classes);
             dump += StringPrintf(INDENT3 "Path: %s\n", device->path.c_str());
@@ -1935,17 +1939,17 @@
             dump += StringPrintf(INDENT3 "ControllerNumber: %d\n", device->controllerNumber);
             dump += StringPrintf(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.c_str());
             dump += StringPrintf(INDENT3 "Identifier: bus=0x%04x, vendor=0x%04x, "
-                                         "product=0x%04x, version=0x%04x\n",
-                                 device->identifier.bus, device->identifier.vendor,
-                                 device->identifier.product, device->identifier.version);
+                    "product=0x%04x, version=0x%04x\n",
+                    device->identifier.bus, device->identifier.vendor,
+                    device->identifier.product, device->identifier.version);
             dump += StringPrintf(INDENT3 "KeyLayoutFile: %s\n",
-                                 device->keyMap.keyLayoutFile.c_str());
+                    device->keyMap.keyLayoutFile.c_str());
             dump += StringPrintf(INDENT3 "KeyCharacterMapFile: %s\n",
-                                 device->keyMap.keyCharacterMapFile.c_str());
+                    device->keyMap.keyCharacterMapFile.c_str());
             dump += StringPrintf(INDENT3 "ConfigurationFile: %s\n",
-                                 device->configurationFile.c_str());
+                    device->configurationFile.c_str());
             dump += StringPrintf(INDENT3 "HaveKeyboardLayoutOverlay: %s\n",
-                                 toString(device->overlayKeyMap != nullptr));
+                    toString(device->overlayKeyMap != nullptr));
             dump += INDENT3 "VideoDevice: ";
             if (device->videoDevice) {
                 dump += device->videoDevice->dump() + "\n";
@@ -1970,4 +1974,5 @@
     mLock.unlock();
 }
 
+
 }; // namespace android
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/EventHub.h
similarity index 85%
rename from services/inputflinger/reader/include/EventHub.h
rename to services/inputflinger/EventHub.h
index 794396a..63a20ef 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+//
 #ifndef _RUNTIME_EVENT_HUB_H
 #define _RUNTIME_EVENT_HUB_H
 
@@ -21,17 +22,17 @@
 
 #include <input/Input.h>
 #include <input/InputDevice.h>
-#include <input/KeyCharacterMap.h>
-#include <input/KeyLayoutMap.h>
 #include <input/Keyboard.h>
+#include <input/KeyLayoutMap.h>
+#include <input/KeyCharacterMap.h>
 #include <input/VirtualKeyMap.h>
-#include <utils/BitSet.h>
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include <utils/List.h>
-#include <utils/Log.h>
 #include <utils/Mutex.h>
+#include <utils/Log.h>
+#include <utils/List.h>
+#include <utils/Errors.h>
 #include <utils/PropertyMap.h>
+#include <utils/KeyedVector.h>
+#include <utils/BitSet.h>
 
 #include <linux/input.h>
 #include <sys/epoll.h>
@@ -40,8 +41,8 @@
 
 /* Convenience constants. */
 
-#define BTN_FIRST 0x100 // first button code
-#define BTN_LAST 0x15f  // last button code
+#define BTN_FIRST 0x100  // first button code
+#define BTN_LAST 0x15f   // last button code
 
 namespace android {
 
@@ -60,10 +61,10 @@
 struct RawAbsoluteAxisInfo {
     bool valid; // true if the information is valid, false otherwise
 
-    int32_t minValue;   // minimum value
-    int32_t maxValue;   // maximum value
-    int32_t flat;       // center flat position, eg. flat == 8 means center is between -8 and 8
-    int32_t fuzz;       // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
+    int32_t minValue;  // minimum value
+    int32_t maxValue;  // maximum value
+    int32_t flat;      // center flat position, eg. flat == 8 means center is between -8 and 8
+    int32_t fuzz;      // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
     int32_t resolution; // resolution in units per mm or radians per mm
 
     inline void clear() {
@@ -81,37 +82,37 @@
  */
 enum {
     /* The input device is a keyboard or has buttons. */
-    INPUT_DEVICE_CLASS_KEYBOARD = 0x00000001,
+    INPUT_DEVICE_CLASS_KEYBOARD      = 0x00000001,
 
     /* The input device is an alpha-numeric keyboard (not just a dial pad). */
-    INPUT_DEVICE_CLASS_ALPHAKEY = 0x00000002,
+    INPUT_DEVICE_CLASS_ALPHAKEY      = 0x00000002,
 
     /* The input device is a touchscreen or a touchpad (either single-touch or multi-touch). */
-    INPUT_DEVICE_CLASS_TOUCH = 0x00000004,
+    INPUT_DEVICE_CLASS_TOUCH         = 0x00000004,
 
     /* The input device is a cursor device such as a trackball or mouse. */
-    INPUT_DEVICE_CLASS_CURSOR = 0x00000008,
+    INPUT_DEVICE_CLASS_CURSOR        = 0x00000008,
 
     /* The input device is a multi-touch touchscreen. */
-    INPUT_DEVICE_CLASS_TOUCH_MT = 0x00000010,
+    INPUT_DEVICE_CLASS_TOUCH_MT      = 0x00000010,
 
     /* The input device is a directional pad (implies keyboard, has DPAD keys). */
-    INPUT_DEVICE_CLASS_DPAD = 0x00000020,
+    INPUT_DEVICE_CLASS_DPAD          = 0x00000020,
 
     /* The input device is a gamepad (implies keyboard, has BUTTON keys). */
-    INPUT_DEVICE_CLASS_GAMEPAD = 0x00000040,
+    INPUT_DEVICE_CLASS_GAMEPAD       = 0x00000040,
 
     /* The input device has switches. */
-    INPUT_DEVICE_CLASS_SWITCH = 0x00000080,
+    INPUT_DEVICE_CLASS_SWITCH        = 0x00000080,
 
     /* The input device is a joystick (implies gamepad, has joystick absolute axes). */
-    INPUT_DEVICE_CLASS_JOYSTICK = 0x00000100,
+    INPUT_DEVICE_CLASS_JOYSTICK      = 0x00000100,
 
     /* The input device has a vibrator (supports FF_RUMBLE). */
-    INPUT_DEVICE_CLASS_VIBRATOR = 0x00000200,
+    INPUT_DEVICE_CLASS_VIBRATOR      = 0x00000200,
 
     /* The input device has a microphone. */
-    INPUT_DEVICE_CLASS_MIC = 0x00000400,
+    INPUT_DEVICE_CLASS_MIC           = 0x00000400,
 
     /* The input device is an external stylus (has data we want to fuse with touch data). */
     INPUT_DEVICE_CLASS_EXTERNAL_STYLUS = 0x00000800,
@@ -120,10 +121,10 @@
     INPUT_DEVICE_CLASS_ROTARY_ENCODER = 0x00001000,
 
     /* The input device is virtual (not a real device, not part of UI configuration). */
-    INPUT_DEVICE_CLASS_VIRTUAL = 0x40000000,
+    INPUT_DEVICE_CLASS_VIRTUAL       = 0x40000000,
 
     /* The input device is external (not built-in). */
-    INPUT_DEVICE_CLASS_EXTERNAL = 0x80000000,
+    INPUT_DEVICE_CLASS_EXTERNAL      = 0x80000000,
 };
 
 /*
@@ -147,8 +148,8 @@
  */
 class EventHubInterface : public virtual RefBase {
 protected:
-    EventHubInterface() {}
-    virtual ~EventHubInterface() {}
+    EventHubInterface() { }
+    virtual ~EventHubInterface() { }
 
 public:
     // Synthetic raw event type codes produced when devices are added or removed.
@@ -173,17 +174,18 @@
     virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const = 0;
 
     virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
-                                         RawAbsoluteAxisInfo* outAxisInfo) const = 0;
+            RawAbsoluteAxisInfo* outAxisInfo) const = 0;
 
     virtual bool hasRelativeAxis(int32_t deviceId, int axis) const = 0;
 
     virtual bool hasInputProperty(int32_t deviceId, int property) const = 0;
 
-    virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
-                            int32_t metaState, int32_t* outKeycode, int32_t* outMetaState,
-                            uint32_t* outFlags) const = 0;
+    virtual status_t mapKey(int32_t deviceId,
+            int32_t scanCode, int32_t usageCode, int32_t metaState,
+            int32_t* outKeycode, int32_t *outMetaState, uint32_t* outFlags) const = 0;
 
-    virtual status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const = 0;
+    virtual status_t mapAxis(int32_t deviceId, int32_t scanCode,
+            AxisInfo* outAxisInfo) const = 0;
 
     // Sets devices that are excluded from opening.
     // This can be used to ignore input devices for sensors.
@@ -211,13 +213,13 @@
     virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0;
     virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0;
     virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
-                                          int32_t* outValue) const = 0;
+            int32_t* outValue) const = 0;
 
     /*
      * Examine key input devices for specific framework keycode support
      */
     virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
-                                       uint8_t* outFlags) const = 0;
+            uint8_t* outFlags) const = 0;
 
     virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const = 0;
 
@@ -225,8 +227,8 @@
     virtual bool hasLed(int32_t deviceId, int32_t led) const = 0;
     virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0;
 
-    virtual void getVirtualKeyDefinitions(
-            int32_t deviceId, std::vector<VirtualKeyDefinition>& outVirtualKeys) const = 0;
+    virtual void getVirtualKeyDefinitions(int32_t deviceId,
+            std::vector<VirtualKeyDefinition>& outVirtualKeys) const = 0;
 
     virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const = 0;
     virtual bool setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) = 0;
@@ -257,7 +259,8 @@
     virtual status_t disableDevice(int32_t deviceId) = 0;
 };
 
-class EventHub : public EventHubInterface {
+class EventHub : public EventHubInterface
+{
 public:
     EventHub();
 
@@ -270,17 +273,18 @@
     virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const;
 
     virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
-                                         RawAbsoluteAxisInfo* outAxisInfo) const;
+            RawAbsoluteAxisInfo* outAxisInfo) const;
 
     virtual bool hasRelativeAxis(int32_t deviceId, int axis) const;
 
     virtual bool hasInputProperty(int32_t deviceId, int property) const;
 
-    virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
-                            int32_t metaState, int32_t* outKeycode, int32_t* outMetaState,
-                            uint32_t* outFlags) const;
+    virtual status_t mapKey(int32_t deviceId,
+            int32_t scanCode, int32_t usageCode, int32_t metaState,
+            int32_t* outKeycode, int32_t *outMetaState, uint32_t* outFlags) const;
 
-    virtual status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const;
+    virtual status_t mapAxis(int32_t deviceId, int32_t scanCode,
+            AxisInfo* outAxisInfo) const;
 
     virtual void setExcludedDevices(const std::vector<std::string>& devices);
 
@@ -289,8 +293,8 @@
     virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const;
     virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const;
 
-    virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
-                                       uint8_t* outFlags) const;
+    virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags) const;
 
     virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize);
     virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId);
@@ -300,7 +304,7 @@
     virtual void setLedState(int32_t deviceId, int32_t led, bool on);
 
     virtual void getVirtualKeyDefinitions(int32_t deviceId,
-                                          std::vector<VirtualKeyDefinition>& outVirtualKeys) const;
+            std::vector<VirtualKeyDefinition>& outVirtualKeys) const;
 
     virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const;
     virtual bool setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map);
@@ -353,7 +357,7 @@
         int32_t controllerNumber;
 
         Device(int fd, int32_t id, const std::string& path,
-               const InputDeviceIdentifier& identifier);
+                const InputDeviceIdentifier& identifier);
         ~Device();
 
         void close();
@@ -378,7 +382,7 @@
     void addDeviceLocked(Device* device);
     void assignDescriptorLocked(InputDeviceIdentifier& identifier);
 
-    void closeDeviceByPathLocked(const char* devicePath);
+    void closeDeviceByPathLocked(const char *devicePath);
     void closeVideoDeviceByPathLocked(const std::string& devicePath);
     void closeDeviceLocked(Device* device);
     void closeAllDevicesLocked();
@@ -395,7 +399,7 @@
     status_t unregisterDeviceFromEpollLocked(Device* device);
     void unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& videoDevice);
 
-    status_t scanDirLocked(const char* dirname);
+    status_t scanDirLocked(const char *dirname);
     status_t scanVideoDirLocked(const std::string& dirname);
     void scanDevicesLocked();
     status_t readNotifyLocked();
@@ -451,8 +455,8 @@
      */
     std::vector<std::unique_ptr<TouchVideoDevice>> mUnattachedVideoDevices;
 
-    Device* mOpeningDevices;
-    Device* mClosingDevices;
+    Device *mOpeningDevices;
+    Device *mClosingDevices;
 
     bool mNeedToSendFinishedDeviceScan;
     bool mNeedToReopenDevices;
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index 6a7f279..cda0e0c 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -27,7 +27,6 @@
 #if defined(__linux__)
     #include <pthread.h>
 #endif
-#include <server_configurable_flags/get_flags.h>
 #include <unordered_set>
 
 #include <android/hardware/input/classifier/1.0/IInputClassifier.h>
@@ -46,13 +45,6 @@
 
 namespace android {
 
-static constexpr bool DEBUG = false;
-
-// Category (=namespace) name for the input settings that are applied at boot time
-static const char* INPUT_NATIVE_BOOT = "input_native_boot";
-// Feature flag name for the deep press feature
-static const char* DEEP_PRESS_ENABLED = "deep_press_enabled";
-
 //Max number of elements to store in mEvents.
 static constexpr size_t MAX_EVENTS = 5;
 
@@ -79,20 +71,6 @@
     return args.source == AINPUT_SOURCE_TOUCHPAD || args.source == AINPUT_SOURCE_TOUCHSCREEN;
 }
 
-// Check if the "deep touch" feature is on.
-static bool deepPressEnabled() {
-    std::string flag_value = server_configurable_flags::GetServerConfigurableFlag(
-            INPUT_NATIVE_BOOT, DEEP_PRESS_ENABLED, "false");
-    std::transform(flag_value.begin(), flag_value.end(), flag_value.begin(), ::tolower);
-    if (flag_value == "1" || flag_value == "true") {
-        ALOGI("Deep press feature enabled.");
-        return true;
-    }
-    ALOGI("Deep press feature is not enabled.");
-    return false;
-}
-
-
 // --- ClassifierEvent ---
 
 ClassifierEvent::ClassifierEvent(std::unique_ptr<NotifyMotionArgs> args) :
@@ -141,53 +119,40 @@
 
 // --- MotionClassifier ---
 
-MotionClassifier::MotionClassifier(sp<android::hardware::hidl_death_recipient> deathRecipient) :
-        mDeathRecipient(deathRecipient), mEvents(MAX_EVENTS) {
-    mHalThread = std::thread(&MotionClassifier::callInputClassifierHal, this);
-#if defined(__linux__)
-    // Set the thread name for debugging
-    pthread_setname_np(mHalThread.native_handle(), "InputClassifier");
-#endif
-}
-
-/**
- * This function may block for some time to initialize the HAL, so it should only be called
- * from the "InputClassifier HAL" thread.
- */
-bool MotionClassifier::init() {
-    ensureHalThread(__func__);
-    sp<android::hardware::input::classifier::V1_0::IInputClassifier> service =
-            classifier::V1_0::IInputClassifier::getService();
-    if (!service) {
-        // Not really an error, maybe the device does not have this HAL,
-        // but somehow the feature flag is flipped
-        ALOGI("Could not obtain InputClassifier HAL");
-        return false;
-    }
-
-    sp<android::hardware::hidl_death_recipient> recipient = mDeathRecipient.promote();
-    if (recipient != nullptr) {
-        const bool linked = service->linkToDeath(recipient, 0 /* cookie */).withDefault(false);
-        if (!linked) {
-            ALOGE("Could not link MotionClassifier to the HAL death");
-            return false;
-        }
-    }
-
+MotionClassifier::MotionClassifier(
+        sp<android::hardware::input::classifier::V1_0::IInputClassifier> service)
+      : mEvents(MAX_EVENTS), mService(service) {
     // Under normal operation, we do not need to reset the HAL here. But in the case where system
     // crashed, but HAL didn't, we may be connecting to an existing HAL process that might already
     // have received events in the past. That means, that HAL could be in an inconsistent state
     // once it receives events from the newly created MotionClassifier.
     mEvents.push(ClassifierEvent::createHalResetEvent());
 
-    {
-        std::scoped_lock lock(mLock);
-        if (mService) {
-            ALOGE("MotionClassifier::%s should only be called once", __func__);
-        }
-        mService = service;
+    mHalThread = std::thread(&MotionClassifier::processEvents, this);
+#if defined(__linux__)
+    // Set the thread name for debugging
+    pthread_setname_np(mHalThread.native_handle(), "InputClassifier");
+#endif
+}
+
+std::unique_ptr<MotionClassifierInterface> MotionClassifier::create(
+        sp<android::hardware::hidl_death_recipient> deathRecipient) {
+    sp<android::hardware::input::classifier::V1_0::IInputClassifier> service =
+            classifier::V1_0::IInputClassifier::getService();
+    if (!service) {
+        // Not really an error, maybe the device does not have this HAL,
+        // but somehow the feature flag is flipped
+        ALOGI("Could not obtain InputClassifier HAL");
+        return nullptr;
     }
-    return true;
+
+    const bool linked = service->linkToDeath(deathRecipient, 0 /* cookie */).withDefault(false);
+    if (!linked) {
+        ALOGE("Could not link death recipient to the HAL death");
+        return nullptr;
+    }
+    // Using 'new' to access a non-public constructor
+    return std::unique_ptr<MotionClassifier>(new MotionClassifier(service));
 }
 
 MotionClassifier::~MotionClassifier() {
@@ -195,14 +160,6 @@
     mHalThread.join();
 }
 
-void MotionClassifier::ensureHalThread(const char* function) {
-    if (DEBUG) {
-        if (std::this_thread::get_id() != mHalThread.get_id()) {
-            LOG_FATAL("Function %s should only be called from InputClassifier thread", function);
-        }
-    }
-}
-
 /**
  * Obtain the classification from the HAL for a given MotionEvent.
  * Should only be called from the InputClassifier thread (mHalThread).
@@ -213,23 +170,7 @@
  * To remove any possibility of negatively affecting the touch latency, the HAL
  * is called from a dedicated thread.
  */
-void MotionClassifier::callInputClassifierHal() {
-    ensureHalThread(__func__);
-    const bool initialized = init();
-    if (!initialized) {
-        // MotionClassifier no longer useful.
-        // Deliver death notification from a separate thread
-        // because ~MotionClassifier may be invoked, which calls mHalThread.join()
-        std::thread([deathRecipient = mDeathRecipient](){
-                sp<android::hardware::hidl_death_recipient> recipient = deathRecipient.promote();
-                if (recipient != nullptr) {
-                    recipient->serviceDied(0 /*cookie*/, nullptr);
-                }
-        }).detach();
-        return;
-    }
-    // From this point on, mService is guaranteed to be non-null.
-
+void MotionClassifier::processEvents() {
     while (true) {
         ClassifierEvent event = mEvents.pop();
         bool halResponseOk = true;
@@ -383,24 +324,41 @@
     }
 }
 
+// --- HalDeathRecipient
+
+InputClassifier::HalDeathRecipient::HalDeathRecipient(InputClassifier& parent) : mParent(parent) {}
+
+void InputClassifier::HalDeathRecipient::serviceDied(
+        uint64_t cookie, const wp<android::hidl::base::V1_0::IBase>& who) {
+    sp<android::hidl::base::V1_0::IBase> service = who.promote();
+    if (service) {
+        service->unlinkToDeath(this);
+    }
+    mParent.setMotionClassifier(nullptr);
+}
 
 // --- InputClassifier ---
 
-InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener) :
-        mListener(listener) {
-    // The rest of the initialization is done in onFirstRef, because we need to obtain
-    // an sp to 'this' in order to register for HAL death notifications
-}
+InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener)
+      : mListener(listener), mHalDeathRecipient(new HalDeathRecipient(*this)) {}
 
-void InputClassifier::onFirstRef() {
-    if (!deepPressEnabled()) {
-        // If feature is not enabled, MotionClassifier should stay null to avoid unnecessary work.
-        // When MotionClassifier is null, InputClassifier will forward all events
-        // to the next InputListener, unmodified.
-        return;
+void InputClassifier::setMotionClassifierEnabled(bool enabled) {
+    if (enabled) {
+        ALOGI("Enabling motion classifier");
+        if (mInitializeMotionClassifierThread.joinable()) {
+            mInitializeMotionClassifierThread.join();
+        }
+        mInitializeMotionClassifierThread = std::thread(
+                [this] { setMotionClassifier(MotionClassifier::create(mHalDeathRecipient)); });
+#if defined(__linux__)
+        // Set the thread name for debugging
+        pthread_setname_np(mInitializeMotionClassifierThread.native_handle(),
+                           "Create MotionClassifier");
+#endif
+    } else {
+        ALOGI("Disabling motion classifier");
+        setMotionClassifier(nullptr);
     }
-    std::scoped_lock lock(mLock);
-    mMotionClassifier = std::make_unique<MotionClassifier>(this);
 }
 
 void InputClassifier::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
@@ -441,15 +399,10 @@
     mListener->notifyDeviceReset(args);
 }
 
-void InputClassifier::serviceDied(uint64_t /*cookie*/,
-        const wp<android::hidl::base::V1_0::IBase>& who) {
+void InputClassifier::setMotionClassifier(
+        std::unique_ptr<MotionClassifierInterface> motionClassifier) {
     std::scoped_lock lock(mLock);
-    ALOGE("InputClassifier HAL has died. Setting mMotionClassifier to null");
-    mMotionClassifier = nullptr;
-    sp<android::hidl::base::V1_0::IBase> service = who.promote();
-    if (service) {
-        service->unlinkToDeath(this);
-    }
+    mMotionClassifier = std::move(motionClassifier);
 }
 
 void InputClassifier::dump(std::string& dump) {
@@ -465,4 +418,10 @@
     dump += "\n";
 }
 
+InputClassifier::~InputClassifier() {
+    if (mInitializeMotionClassifierThread.joinable()) {
+        mInitializeMotionClassifierThread.join();
+    }
+}
+
 } // namespace android
diff --git a/services/inputflinger/InputClassifier.h b/services/inputflinger/InputClassifier.h
index 47e20db..9ac8e2d 100644
--- a/services/inputflinger/InputClassifier.h
+++ b/services/inputflinger/InputClassifier.h
@@ -19,8 +19,8 @@
 
 #include <android-base/thread_annotations.h>
 #include <utils/RefBase.h>
-#include <unordered_map>
 #include <thread>
+#include <unordered_map>
 
 #include "BlockingQueue.h"
 #include "InputListener.h"
@@ -90,6 +90,7 @@
  */
 class InputClassifierInterface : public virtual RefBase, public InputListenerInterface {
 public:
+    virtual void setMotionClassifierEnabled(bool enabled) = 0;
     /**
      * Dump the state of the input classifier.
      * This method may be called on any thread (usually by the input manager).
@@ -113,23 +114,23 @@
  */
 class MotionClassifier final : public MotionClassifierInterface {
 public:
-    /**
-     * The deathRecipient will be subscribed to the HAL death. If the death recipient
-     * owns MotionClassifier and receives HAL death, it should delete its copy of it.
-     * The callback serviceDied will also be sent if the MotionClassifier itself fails
-     * to initialize. If the MotionClassifier fails to initialize, it is not useful, and
-     * should be deleted.
-     * If no death recipient is supplied, then the registration step will be skipped, so there will
-     * be no listeners registered for the HAL death. This is useful for testing
-     * MotionClassifier in isolation.
+    /*
+     * Create an instance of MotionClassifier.
+     * The death recipient, if provided, will be subscribed to the HAL death.
+     * The death recipient could be used to destroy MotionClassifier.
+     *
+     * This function should be called asynchronously, because getService takes a long time.
      */
-    explicit MotionClassifier(sp<android::hardware::hidl_death_recipient> deathRecipient = nullptr);
+    static std::unique_ptr<MotionClassifierInterface> create(
+            sp<android::hardware::hidl_death_recipient> deathRecipient);
+
     ~MotionClassifier();
 
     /**
      * Classifies events asynchronously; that is, it doesn't block events on a classification,
-     * but instead sends them over to the classifier HAL and after a classification is
-     * determined, it then marks the next event it sees in the stream with it.
+     * but instead sends them over to the classifier HAL. After a classification of a specific
+     * event is determined, MotionClassifier then marks the next event in the stream with this
+     * classification.
      *
      * Therefore, it is acceptable to have the classifications be delayed by 1-2 events
      * in a particular gesture.
@@ -141,15 +142,9 @@
     virtual void dump(std::string& dump) override;
 
 private:
-    /**
-     * Initialize MotionClassifier.
-     * Return true if initializaion is successful.
-     */
-    bool init();
-    /**
-     * Entity that will be notified of the HAL death (most likely InputClassifier).
-     */
-    wp<android::hardware::hidl_death_recipient> mDeathRecipient;
+    friend class MotionClassifierTest; // to create MotionClassifier with a test HAL implementation
+    explicit MotionClassifier(
+            sp<android::hardware::input::classifier::V1_0::IInputClassifier> service);
 
     // The events that need to be sent to the HAL.
     BlockingQueue<ClassifierEvent> mEvents;
@@ -164,14 +159,9 @@
      */
     std::thread mHalThread;
     /**
-     * Print an error message if the caller is not on the InputClassifier thread.
-     * Caller must supply the name of the calling function as __func__
+     * Process events and call the InputClassifier HAL
      */
-    void ensureHalThread(const char* function);
-    /**
-     * Call the InputClassifier HAL
-     */
-    void callInputClassifierHal();
+    void processEvents();
     /**
      * Access to the InputClassifier HAL. May be null if init() hasn't completed yet.
      * When init() successfully completes, mService is guaranteed to remain non-null and to not
@@ -223,19 +213,15 @@
     const char* getServiceStatus() REQUIRES(mLock);
 };
 
-
 /**
  * Implementation of the InputClassifierInterface.
  * Represents a separate stage of input processing. All of the input events go through this stage.
  * Acts as a passthrough for all input events except for motion events.
  * The events of motion type are sent to MotionClassifier.
  */
-class InputClassifier : public InputClassifierInterface,
-        public android::hardware::hidl_death_recipient {
+class InputClassifier : public InputClassifierInterface {
 public:
     explicit InputClassifier(const sp<InputListenerInterface>& listener);
-    // Some of the constructor logic is finished in onFirstRef
-    virtual void onFirstRef() override;
 
     virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
     virtual void notifyKey(const NotifyKeyArgs* args) override;
@@ -243,17 +229,47 @@
     virtual void notifySwitch(const NotifySwitchArgs* args) override;
     virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
 
-    virtual void serviceDied(uint64_t cookie,
-            const wp<android::hidl::base::V1_0::IBase>& who) override;
-
     virtual void dump(std::string& dump) override;
 
+    ~InputClassifier();
+
+    // Called from InputManager
+    virtual void setMotionClassifierEnabled(bool enabled) override;
+
 private:
     // Protect access to mMotionClassifier, since it may become null via a hidl callback
     std::mutex mLock;
-    std::unique_ptr<MotionClassifierInterface> mMotionClassifier GUARDED_BY(mLock);
     // The next stage to pass input events to
     sp<InputListenerInterface> mListener;
+
+    std::unique_ptr<MotionClassifierInterface> mMotionClassifier GUARDED_BY(mLock);
+    std::thread mInitializeMotionClassifierThread;
+    /**
+     * Set the value of mMotionClassifier.
+     * This is called from 2 different threads:
+     * 1) mInitializeMotionClassifierThread, when we have constructed a MotionClassifier
+     * 2) A binder thread of the HalDeathRecipient, which is created when HAL dies. This would cause
+     *    mMotionClassifier to become nullptr.
+     */
+    void setMotionClassifier(std::unique_ptr<MotionClassifierInterface> motionClassifier);
+
+    /**
+     * The deathRecipient will call setMotionClassifier(null) when the HAL dies.
+     */
+    class HalDeathRecipient : public android::hardware::hidl_death_recipient {
+    public:
+        explicit HalDeathRecipient(InputClassifier& parent);
+        virtual void serviceDied(uint64_t cookie,
+                                 const wp<android::hidl::base::V1_0::IBase>& who) override;
+
+    private:
+        InputClassifier& mParent;
+    };
+    // We retain a reference to death recipient, because the death recipient will be calling
+    // ~MotionClassifier if the HAL dies.
+    // If we don't retain a reference, and MotionClassifier is the only owner of the death
+    // recipient, the serviceDied call will cause death recipient to call its own destructor.
+    sp<HalDeathRecipient> mHalDeathRecipient;
 };
 
 } // namespace android
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
new file mode 100644
index 0000000..b921d95
--- /dev/null
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -0,0 +1,5243 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#define LOG_TAG "InputDispatcher"
+#define ATRACE_TAG ATRACE_TAG_INPUT
+
+#define LOG_NDEBUG 0
+
+// Log detailed debug messages about each inbound event notification to the dispatcher.
+#define DEBUG_INBOUND_EVENT_DETAILS 0
+
+// Log detailed debug messages about each outbound event processed by the dispatcher.
+#define DEBUG_OUTBOUND_EVENT_DETAILS 0
+
+// Log debug messages about the dispatch cycle.
+#define DEBUG_DISPATCH_CYCLE 0
+
+// Log debug messages about registrations.
+#define DEBUG_REGISTRATION 0
+
+// Log debug messages about input event injection.
+#define DEBUG_INJECTION 0
+
+// Log debug messages about input focus tracking.
+#define DEBUG_FOCUS 0
+
+// Log debug messages about the app switch latency optimization.
+#define DEBUG_APP_SWITCH 0
+
+// Log debug messages about hover events.
+#define DEBUG_HOVER 0
+
+#include "InputDispatcher.h"
+
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <sstream>
+#include <stddef.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <android-base/chrono_utils.h>
+#include <android-base/stringprintf.h>
+#include <log/log.h>
+#include <utils/Trace.h>
+#include <powermanager/PowerManager.h>
+#include <binder/Binder.h>
+
+#define INDENT "  "
+#define INDENT2 "    "
+#define INDENT3 "      "
+#define INDENT4 "        "
+
+using android::base::StringPrintf;
+
+namespace android {
+
+// Default input dispatching timeout if there is no focused application or paused window
+// from which to determine an appropriate dispatching timeout.
+constexpr nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
+
+// Amount of time to allow for all pending events to be processed when an app switch
+// key is on the way.  This is used to preempt input dispatch and drop input events
+// when an application takes too long to respond and the user has pressed an app switch key.
+constexpr nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
+
+// Amount of time to allow for an event to be dispatched (measured since its eventTime)
+// before considering it stale and dropping it.
+constexpr nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec
+
+// Amount of time to allow touch events to be streamed out to a connection before requiring
+// that the first event be finished.  This value extends the ANR timeout by the specified
+// amount.  For example, if streaming is allowed to get ahead by one second relative to the
+// queue of waiting unfinished events, then ANRs will similarly be delayed by one second.
+constexpr nsecs_t STREAM_AHEAD_EVENT_TIMEOUT = 500 * 1000000LL; // 0.5sec
+
+// Log a warning when an event takes longer than this to process, even if an ANR does not occur.
+constexpr nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec
+
+// Log a warning when an interception call takes longer than this to process.
+constexpr std::chrono::milliseconds SLOW_INTERCEPTION_THRESHOLD = 50ms;
+
+// Number of recent events to keep for debugging purposes.
+constexpr size_t RECENT_QUEUE_MAX_SIZE = 10;
+
+// Sequence number for synthesized or injected events.
+constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0;
+
+
+static inline nsecs_t now() {
+    return systemTime(SYSTEM_TIME_MONOTONIC);
+}
+
+static inline const char* toString(bool value) {
+    return value ? "true" : "false";
+}
+
+static std::string dispatchModeToString(int32_t dispatchMode) {
+    switch (dispatchMode) {
+        case InputTarget::FLAG_DISPATCH_AS_IS:
+            return "DISPATCH_AS_IS";
+        case InputTarget::FLAG_DISPATCH_AS_OUTSIDE:
+            return "DISPATCH_AS_OUTSIDE";
+        case InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER:
+            return "DISPATCH_AS_HOVER_ENTER";
+        case InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT:
+            return "DISPATCH_AS_HOVER_EXIT";
+        case InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT:
+            return "DISPATCH_AS_SLIPPERY_EXIT";
+        case InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER:
+            return "DISPATCH_AS_SLIPPERY_ENTER";
+    }
+    return StringPrintf("%" PRId32, dispatchMode);
+}
+
+static inline int32_t getMotionEventActionPointerIndex(int32_t action) {
+    return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
+            >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+}
+
+static bool isValidKeyAction(int32_t action) {
+    switch (action) {
+    case AKEY_EVENT_ACTION_DOWN:
+    case AKEY_EVENT_ACTION_UP:
+        return true;
+    default:
+        return false;
+    }
+}
+
+static bool validateKeyEvent(int32_t action) {
+    if (! isValidKeyAction(action)) {
+        ALOGE("Key event has invalid action code 0x%x", action);
+        return false;
+    }
+    return true;
+}
+
+static bool isValidMotionAction(int32_t action, int32_t actionButton, int32_t pointerCount) {
+    switch (action & AMOTION_EVENT_ACTION_MASK) {
+    case AMOTION_EVENT_ACTION_DOWN:
+    case AMOTION_EVENT_ACTION_UP:
+    case AMOTION_EVENT_ACTION_CANCEL:
+    case AMOTION_EVENT_ACTION_MOVE:
+    case AMOTION_EVENT_ACTION_OUTSIDE:
+    case AMOTION_EVENT_ACTION_HOVER_ENTER:
+    case AMOTION_EVENT_ACTION_HOVER_MOVE:
+    case AMOTION_EVENT_ACTION_HOVER_EXIT:
+    case AMOTION_EVENT_ACTION_SCROLL:
+        return true;
+    case AMOTION_EVENT_ACTION_POINTER_DOWN:
+    case AMOTION_EVENT_ACTION_POINTER_UP: {
+        int32_t index = getMotionEventActionPointerIndex(action);
+        return index >= 0 && index < pointerCount;
+    }
+    case AMOTION_EVENT_ACTION_BUTTON_PRESS:
+    case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
+        return actionButton != 0;
+    default:
+        return false;
+    }
+}
+
+static bool validateMotionEvent(int32_t action, int32_t actionButton, size_t pointerCount,
+        const PointerProperties* pointerProperties) {
+    if (! isValidMotionAction(action, actionButton, pointerCount)) {
+        ALOGE("Motion event has invalid action code 0x%x", action);
+        return false;
+    }
+    if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
+        ALOGE("Motion event has invalid pointer count %zu; value must be between 1 and %d.",
+                pointerCount, MAX_POINTERS);
+        return false;
+    }
+    BitSet32 pointerIdBits;
+    for (size_t i = 0; i < pointerCount; i++) {
+        int32_t id = pointerProperties[i].id;
+        if (id < 0 || id > MAX_POINTER_ID) {
+            ALOGE("Motion event has invalid pointer id %d; value must be between 0 and %d",
+                    id, MAX_POINTER_ID);
+            return false;
+        }
+        if (pointerIdBits.hasBit(id)) {
+            ALOGE("Motion event has duplicate pointer id %d", id);
+            return false;
+        }
+        pointerIdBits.markBit(id);
+    }
+    return true;
+}
+
+static void dumpRegion(std::string& dump, const Region& region) {
+    if (region.isEmpty()) {
+        dump += "<empty>";
+        return;
+    }
+
+    bool first = true;
+    Region::const_iterator cur = region.begin();
+    Region::const_iterator const tail = region.end();
+    while (cur != tail) {
+        if (first) {
+            first = false;
+        } else {
+            dump += "|";
+        }
+        dump += StringPrintf("[%d,%d][%d,%d]", cur->left, cur->top, cur->right, cur->bottom);
+        cur++;
+    }
+}
+
+template<typename T, typename U>
+static T getValueByKey(std::unordered_map<U, T>& map, U key) {
+    typename std::unordered_map<U, T>::const_iterator it = map.find(key);
+    return it != map.end() ? it->second : T{};
+}
+
+
+// --- InputDispatcher ---
+
+InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
+    mPolicy(policy),
+    mPendingEvent(nullptr), mLastDropReason(DROP_REASON_NOT_DROPPED),
+    mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
+    mNextUnblockedEvent(nullptr),
+    mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
+    mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
+    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
+    mLooper = new Looper(false);
+    mReporter = createInputReporter();
+
+    mKeyRepeatState.lastKeyEntry = nullptr;
+
+    policy->getDispatcherConfiguration(&mConfig);
+}
+
+InputDispatcher::~InputDispatcher() {
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+
+        resetKeyRepeatLocked();
+        releasePendingEventLocked();
+        drainInboundQueueLocked();
+    }
+
+    while (mConnectionsByFd.size() != 0) {
+        unregisterInputChannel(mConnectionsByFd.valueAt(0)->inputChannel);
+    }
+}
+
+void InputDispatcher::dispatchOnce() {
+    nsecs_t nextWakeupTime = LONG_LONG_MAX;
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+        mDispatcherIsAlive.notify_all();
+
+        // Run a dispatch loop if there are no pending commands.
+        // The dispatch loop might enqueue commands to run afterwards.
+        if (!haveCommandsLocked()) {
+            dispatchOnceInnerLocked(&nextWakeupTime);
+        }
+
+        // Run all pending commands if there are any.
+        // If any commands were run then force the next poll to wake up immediately.
+        if (runCommandsLockedInterruptible()) {
+            nextWakeupTime = LONG_LONG_MIN;
+        }
+    } // release lock
+
+    // Wait for callback or timeout or wake.  (make sure we round up, not down)
+    nsecs_t currentTime = now();
+    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
+    mLooper->pollOnce(timeoutMillis);
+}
+
+void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
+    nsecs_t currentTime = now();
+
+    // Reset the key repeat timer whenever normal dispatch is suspended while the
+    // device is in a non-interactive state.  This is to ensure that we abort a key
+    // repeat if the device is just coming out of sleep.
+    if (!mDispatchEnabled) {
+        resetKeyRepeatLocked();
+    }
+
+    // If dispatching is frozen, do not process timeouts or try to deliver any new events.
+    if (mDispatchFrozen) {
+#if DEBUG_FOCUS
+        ALOGD("Dispatch frozen.  Waiting some more.");
+#endif
+        return;
+    }
+
+    // Optimize latency of app switches.
+    // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
+    // been pressed.  When it expires, we preempt dispatch and drop all other pending events.
+    bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
+    if (mAppSwitchDueTime < *nextWakeupTime) {
+        *nextWakeupTime = mAppSwitchDueTime;
+    }
+
+    // Ready to start a new event.
+    // If we don't already have a pending event, go grab one.
+    if (! mPendingEvent) {
+        if (mInboundQueue.isEmpty()) {
+            if (isAppSwitchDue) {
+                // The inbound queue is empty so the app switch key we were waiting
+                // for will never arrive.  Stop waiting for it.
+                resetPendingAppSwitchLocked(false);
+                isAppSwitchDue = false;
+            }
+
+            // Synthesize a key repeat if appropriate.
+            if (mKeyRepeatState.lastKeyEntry) {
+                if (currentTime >= mKeyRepeatState.nextRepeatTime) {
+                    mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
+                } else {
+                    if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
+                        *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
+                    }
+                }
+            }
+
+            // Nothing to do if there is no pending event.
+            if (!mPendingEvent) {
+                return;
+            }
+        } else {
+            // Inbound queue has at least one entry.
+            mPendingEvent = mInboundQueue.dequeueAtHead();
+            traceInboundQueueLengthLocked();
+        }
+
+        // Poke user activity for this event.
+        if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
+            pokeUserActivityLocked(mPendingEvent);
+        }
+
+        // Get ready to dispatch the event.
+        resetANRTimeoutsLocked();
+    }
+
+    // Now we have an event to dispatch.
+    // All events are eventually dequeued and processed this way, even if we intend to drop them.
+    ALOG_ASSERT(mPendingEvent != nullptr);
+    bool done = false;
+    DropReason dropReason = DROP_REASON_NOT_DROPPED;
+    if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
+        dropReason = DROP_REASON_POLICY;
+    } else if (!mDispatchEnabled) {
+        dropReason = DROP_REASON_DISABLED;
+    }
+
+    if (mNextUnblockedEvent == mPendingEvent) {
+        mNextUnblockedEvent = nullptr;
+    }
+
+    switch (mPendingEvent->type) {
+    case EventEntry::TYPE_CONFIGURATION_CHANGED: {
+        ConfigurationChangedEntry* typedEntry =
+                static_cast<ConfigurationChangedEntry*>(mPendingEvent);
+        done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
+        dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
+        break;
+    }
+
+    case EventEntry::TYPE_DEVICE_RESET: {
+        DeviceResetEntry* typedEntry =
+                static_cast<DeviceResetEntry*>(mPendingEvent);
+        done = dispatchDeviceResetLocked(currentTime, typedEntry);
+        dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
+        break;
+    }
+
+    case EventEntry::TYPE_KEY: {
+        KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
+        if (isAppSwitchDue) {
+            if (isAppSwitchKeyEvent(typedEntry)) {
+                resetPendingAppSwitchLocked(true);
+                isAppSwitchDue = false;
+            } else if (dropReason == DROP_REASON_NOT_DROPPED) {
+                dropReason = DROP_REASON_APP_SWITCH;
+            }
+        }
+        if (dropReason == DROP_REASON_NOT_DROPPED
+                && isStaleEvent(currentTime, typedEntry)) {
+            dropReason = DROP_REASON_STALE;
+        }
+        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
+            dropReason = DROP_REASON_BLOCKED;
+        }
+        done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
+        break;
+    }
+
+    case EventEntry::TYPE_MOTION: {
+        MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
+        if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
+            dropReason = DROP_REASON_APP_SWITCH;
+        }
+        if (dropReason == DROP_REASON_NOT_DROPPED
+                && isStaleEvent(currentTime, typedEntry)) {
+            dropReason = DROP_REASON_STALE;
+        }
+        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
+            dropReason = DROP_REASON_BLOCKED;
+        }
+        done = dispatchMotionLocked(currentTime, typedEntry,
+                &dropReason, nextWakeupTime);
+        break;
+    }
+
+    default:
+        ALOG_ASSERT(false);
+        break;
+    }
+
+    if (done) {
+        if (dropReason != DROP_REASON_NOT_DROPPED) {
+            dropInboundEventLocked(mPendingEvent, dropReason);
+        }
+        mLastDropReason = dropReason;
+
+        releasePendingEventLocked();
+        *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
+    }
+}
+
+bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
+    bool needWake = mInboundQueue.isEmpty();
+    mInboundQueue.enqueueAtTail(entry);
+    traceInboundQueueLengthLocked();
+
+    switch (entry->type) {
+    case EventEntry::TYPE_KEY: {
+        // Optimize app switch latency.
+        // If the application takes too long to catch up then we drop all events preceding
+        // the app switch key.
+        KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
+        if (isAppSwitchKeyEvent(keyEntry)) {
+            if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
+                mAppSwitchSawKeyDown = true;
+            } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
+                if (mAppSwitchSawKeyDown) {
+#if DEBUG_APP_SWITCH
+                    ALOGD("App switch is pending!");
+#endif
+                    mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
+                    mAppSwitchSawKeyDown = false;
+                    needWake = true;
+                }
+            }
+        }
+        break;
+    }
+
+    case EventEntry::TYPE_MOTION: {
+        // Optimize case where the current application is unresponsive and the user
+        // decides to touch a window in a different application.
+        // If the application takes too long to catch up then we drop all events preceding
+        // the touch into the other window.
+        MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
+        if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN
+                && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
+                && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY
+                && mInputTargetWaitApplicationToken != nullptr) {
+            int32_t displayId = motionEntry->displayId;
+            int32_t x = int32_t(motionEntry->pointerCoords[0].
+                    getAxisValue(AMOTION_EVENT_AXIS_X));
+            int32_t y = int32_t(motionEntry->pointerCoords[0].
+                    getAxisValue(AMOTION_EVENT_AXIS_Y));
+            sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y);
+            if (touchedWindowHandle != nullptr
+                    && touchedWindowHandle->getApplicationToken()
+                            != mInputTargetWaitApplicationToken) {
+                // User touched a different application than the one we are waiting on.
+                // Flag the event, and start pruning the input queue.
+                mNextUnblockedEvent = motionEntry;
+                needWake = true;
+            }
+        }
+        break;
+    }
+    }
+
+    return needWake;
+}
+
+void InputDispatcher::addRecentEventLocked(EventEntry* entry) {
+    entry->refCount += 1;
+    mRecentQueue.enqueueAtTail(entry);
+    if (mRecentQueue.count() > RECENT_QUEUE_MAX_SIZE) {
+        mRecentQueue.dequeueAtHead()->release();
+    }
+}
+
+sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId,
+        int32_t x, int32_t y, bool addOutsideTargets, bool addPortalWindows) {
+    // Traverse windows from front to back to find touched window.
+    const std::vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
+    for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
+        const InputWindowInfo* windowInfo = windowHandle->getInfo();
+        if (windowInfo->displayId == displayId) {
+            int32_t flags = windowInfo->layoutParamsFlags;
+
+            if (windowInfo->visible) {
+                if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
+                    bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
+                            | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
+                    if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
+                        int32_t portalToDisplayId = windowInfo->portalToDisplayId;
+                        if (portalToDisplayId != ADISPLAY_ID_NONE
+                                && portalToDisplayId != displayId) {
+                            if (addPortalWindows) {
+                                // For the monitoring channels of the display.
+                                mTempTouchState.addPortalWindow(windowHandle);
+                            }
+                            return findTouchedWindowAtLocked(
+                                    portalToDisplayId, x, y, addOutsideTargets, addPortalWindows);
+                        }
+                        // Found window.
+                        return windowHandle;
+                    }
+                }
+
+                if (addOutsideTargets && (flags & InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH)) {
+                    mTempTouchState.addOrUpdateWindow(
+                            windowHandle, InputTarget::FLAG_DISPATCH_AS_OUTSIDE, BitSet32(0));
+                }
+            }
+        }
+    }
+    return nullptr;
+}
+
+std::vector<InputDispatcher::TouchedMonitor> InputDispatcher::findTouchedGestureMonitorsLocked(
+        int32_t displayId, const std::vector<sp<InputWindowHandle>>& portalWindows) {
+    std::vector<TouchedMonitor> touchedMonitors;
+
+    std::vector<Monitor> monitors = getValueByKey(mGestureMonitorsByDisplay, displayId);
+    addGestureMonitors(monitors, touchedMonitors);
+    for (const sp<InputWindowHandle>& portalWindow : portalWindows) {
+        const InputWindowInfo* windowInfo = portalWindow->getInfo();
+        monitors = getValueByKey(mGestureMonitorsByDisplay, windowInfo->portalToDisplayId);
+        addGestureMonitors(monitors, touchedMonitors,
+                -windowInfo->frameLeft, -windowInfo->frameTop);
+    }
+    return touchedMonitors;
+}
+
+void InputDispatcher::addGestureMonitors(const std::vector<Monitor>& monitors,
+        std::vector<TouchedMonitor>& outTouchedMonitors, float xOffset, float yOffset) {
+    if (monitors.empty()) {
+        return;
+    }
+    outTouchedMonitors.reserve(monitors.size() + outTouchedMonitors.size());
+    for (const Monitor& monitor : monitors) {
+        outTouchedMonitors.emplace_back(monitor, xOffset, yOffset);
+    }
+}
+
+void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
+    const char* reason;
+    switch (dropReason) {
+    case DROP_REASON_POLICY:
+#if DEBUG_INBOUND_EVENT_DETAILS
+        ALOGD("Dropped event because policy consumed it.");
+#endif
+        reason = "inbound event was dropped because the policy consumed it";
+        break;
+    case DROP_REASON_DISABLED:
+        if (mLastDropReason != DROP_REASON_DISABLED) {
+            ALOGI("Dropped event because input dispatch is disabled.");
+        }
+        reason = "inbound event was dropped because input dispatch is disabled";
+        break;
+    case DROP_REASON_APP_SWITCH:
+        ALOGI("Dropped event because of pending overdue app switch.");
+        reason = "inbound event was dropped because of pending overdue app switch";
+        break;
+    case DROP_REASON_BLOCKED:
+        ALOGI("Dropped event because the current application is not responding and the user "
+                "has started interacting with a different application.");
+        reason = "inbound event was dropped because the current application is not responding "
+                "and the user has started interacting with a different application";
+        break;
+    case DROP_REASON_STALE:
+        ALOGI("Dropped event because it is stale.");
+        reason = "inbound event was dropped because it is stale";
+        break;
+    default:
+        ALOG_ASSERT(false);
+        return;
+    }
+
+    switch (entry->type) {
+    case EventEntry::TYPE_KEY: {
+        CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason);
+        synthesizeCancelationEventsForAllConnectionsLocked(options);
+        break;
+    }
+    case EventEntry::TYPE_MOTION: {
+        MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
+        if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
+            CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, reason);
+            synthesizeCancelationEventsForAllConnectionsLocked(options);
+        } else {
+            CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason);
+            synthesizeCancelationEventsForAllConnectionsLocked(options);
+        }
+        break;
+    }
+    }
+}
+
+static bool isAppSwitchKeyCode(int32_t keyCode) {
+    return keyCode == AKEYCODE_HOME
+            || keyCode == AKEYCODE_ENDCALL
+            || keyCode == AKEYCODE_APP_SWITCH;
+}
+
+bool InputDispatcher::isAppSwitchKeyEvent(KeyEntry* keyEntry) {
+    return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
+            && isAppSwitchKeyCode(keyEntry->keyCode)
+            && (keyEntry->policyFlags & POLICY_FLAG_TRUSTED)
+            && (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
+}
+
+bool InputDispatcher::isAppSwitchPendingLocked() {
+    return mAppSwitchDueTime != LONG_LONG_MAX;
+}
+
+void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
+    mAppSwitchDueTime = LONG_LONG_MAX;
+
+#if DEBUG_APP_SWITCH
+    if (handled) {
+        ALOGD("App switch has arrived.");
+    } else {
+        ALOGD("App switch was abandoned.");
+    }
+#endif
+}
+
+bool InputDispatcher::isStaleEvent(nsecs_t currentTime, EventEntry* entry) {
+    return currentTime - entry->eventTime >= STALE_EVENT_TIMEOUT;
+}
+
+bool InputDispatcher::haveCommandsLocked() const {
+    return !mCommandQueue.isEmpty();
+}
+
+bool InputDispatcher::runCommandsLockedInterruptible() {
+    if (mCommandQueue.isEmpty()) {
+        return false;
+    }
+
+    do {
+        CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
+
+        Command command = commandEntry->command;
+        (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
+
+        commandEntry->connection.clear();
+        delete commandEntry;
+    } while (! mCommandQueue.isEmpty());
+    return true;
+}
+
+InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
+    CommandEntry* commandEntry = new CommandEntry(command);
+    mCommandQueue.enqueueAtTail(commandEntry);
+    return commandEntry;
+}
+
+void InputDispatcher::drainInboundQueueLocked() {
+    while (! mInboundQueue.isEmpty()) {
+        EventEntry* entry = mInboundQueue.dequeueAtHead();
+        releaseInboundEventLocked(entry);
+    }
+    traceInboundQueueLengthLocked();
+}
+
+void InputDispatcher::releasePendingEventLocked() {
+    if (mPendingEvent) {
+        resetANRTimeoutsLocked();
+        releaseInboundEventLocked(mPendingEvent);
+        mPendingEvent = nullptr;
+    }
+}
+
+void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
+    InjectionState* injectionState = entry->injectionState;
+    if (injectionState && injectionState->injectionResult == INPUT_EVENT_INJECTION_PENDING) {
+#if DEBUG_DISPATCH_CYCLE
+        ALOGD("Injected inbound event was dropped.");
+#endif
+        setInjectionResult(entry, INPUT_EVENT_INJECTION_FAILED);
+    }
+    if (entry == mNextUnblockedEvent) {
+        mNextUnblockedEvent = nullptr;
+    }
+    addRecentEventLocked(entry);
+    entry->release();
+}
+
+void InputDispatcher::resetKeyRepeatLocked() {
+    if (mKeyRepeatState.lastKeyEntry) {
+        mKeyRepeatState.lastKeyEntry->release();
+        mKeyRepeatState.lastKeyEntry = nullptr;
+    }
+}
+
+InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t currentTime) {
+    KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
+
+    // Reuse the repeated key entry if it is otherwise unreferenced.
+    uint32_t policyFlags = entry->policyFlags &
+            (POLICY_FLAG_RAW_MASK | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED);
+    if (entry->refCount == 1) {
+        entry->recycle();
+        entry->eventTime = currentTime;
+        entry->policyFlags = policyFlags;
+        entry->repeatCount += 1;
+    } else {
+        KeyEntry* newEntry = new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
+                entry->deviceId, entry->source, entry->displayId, policyFlags,
+                entry->action, entry->flags, entry->keyCode, entry->scanCode,
+                entry->metaState, entry->repeatCount + 1, entry->downTime);
+
+        mKeyRepeatState.lastKeyEntry = newEntry;
+        entry->release();
+
+        entry = newEntry;
+    }
+    entry->syntheticRepeat = true;
+
+    // Increment reference count since we keep a reference to the event in
+    // mKeyRepeatState.lastKeyEntry in addition to the one we return.
+    entry->refCount += 1;
+
+    mKeyRepeatState.nextRepeatTime = currentTime + mConfig.keyRepeatDelay;
+    return entry;
+}
+
+bool InputDispatcher::dispatchConfigurationChangedLocked(
+        nsecs_t currentTime, ConfigurationChangedEntry* entry) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+    ALOGD("dispatchConfigurationChanged - eventTime=%" PRId64, entry->eventTime);
+#endif
+
+    // Reset key repeating in case a keyboard device was added or removed or something.
+    resetKeyRepeatLocked();
+
+    // Enqueue a command to run outside the lock to tell the policy that the configuration changed.
+    CommandEntry* commandEntry = postCommandLocked(
+            & InputDispatcher::doNotifyConfigurationChangedLockedInterruptible);
+    commandEntry->eventTime = entry->eventTime;
+    return true;
+}
+
+bool InputDispatcher::dispatchDeviceResetLocked(
+        nsecs_t currentTime, DeviceResetEntry* entry) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+    ALOGD("dispatchDeviceReset - eventTime=%" PRId64 ", deviceId=%d", entry->eventTime,
+            entry->deviceId);
+#endif
+
+    CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS,
+            "device was reset");
+    options.deviceId = entry->deviceId;
+    synthesizeCancelationEventsForAllConnectionsLocked(options);
+    return true;
+}
+
+bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
+        DropReason* dropReason, nsecs_t* nextWakeupTime) {
+    // Preprocessing.
+    if (! entry->dispatchInProgress) {
+        if (entry->repeatCount == 0
+                && entry->action == AKEY_EVENT_ACTION_DOWN
+                && (entry->policyFlags & POLICY_FLAG_TRUSTED)
+                && (!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) {
+            if (mKeyRepeatState.lastKeyEntry
+                    && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
+                // We have seen two identical key downs in a row which indicates that the device
+                // driver is automatically generating key repeats itself.  We take note of the
+                // repeat here, but we disable our own next key repeat timer since it is clear that
+                // we will not need to synthesize key repeats ourselves.
+                entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
+                resetKeyRepeatLocked();
+                mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
+            } else {
+                // Not a repeat.  Save key down state in case we do see a repeat later.
+                resetKeyRepeatLocked();
+                mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout;
+            }
+            mKeyRepeatState.lastKeyEntry = entry;
+            entry->refCount += 1;
+        } else if (! entry->syntheticRepeat) {
+            resetKeyRepeatLocked();
+        }
+
+        if (entry->repeatCount == 1) {
+            entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
+        } else {
+            entry->flags &= ~AKEY_EVENT_FLAG_LONG_PRESS;
+        }
+
+        entry->dispatchInProgress = true;
+
+        logOutboundKeyDetails("dispatchKey - ", entry);
+    }
+
+    // Handle case where the policy asked us to try again later last time.
+    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
+        if (currentTime < entry->interceptKeyWakeupTime) {
+            if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
+                *nextWakeupTime = entry->interceptKeyWakeupTime;
+            }
+            return false; // wait until next wakeup
+        }
+        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
+        entry->interceptKeyWakeupTime = 0;
+    }
+
+    // Give the policy a chance to intercept the key.
+    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
+        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
+            CommandEntry* commandEntry = postCommandLocked(
+                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
+            sp<InputWindowHandle> focusedWindowHandle =
+                    getValueByKey(mFocusedWindowHandlesByDisplay, getTargetDisplayId(entry));
+            if (focusedWindowHandle != nullptr) {
+                commandEntry->inputChannel =
+                    getInputChannelLocked(focusedWindowHandle->getToken());
+            }
+            commandEntry->keyEntry = entry;
+            entry->refCount += 1;
+            return false; // wait for the command to run
+        } else {
+            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
+        }
+    } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
+        if (*dropReason == DROP_REASON_NOT_DROPPED) {
+            *dropReason = DROP_REASON_POLICY;
+        }
+    }
+
+    // Clean up if dropping the event.
+    if (*dropReason != DROP_REASON_NOT_DROPPED) {
+        setInjectionResult(entry, *dropReason == DROP_REASON_POLICY
+                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
+        mReporter->reportDroppedKey(entry->sequenceNum);
+        return true;
+    }
+
+    // Identify targets.
+    std::vector<InputTarget> inputTargets;
+    int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
+            entry, inputTargets, nextWakeupTime);
+    if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
+        return false;
+    }
+
+    setInjectionResult(entry, injectionResult);
+    if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
+        return true;
+    }
+
+    // Add monitor channels from event's or focused display.
+    addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(entry));
+
+    // Dispatch the key.
+    dispatchEventLocked(currentTime, entry, inputTargets);
+    return true;
+}
+
+void InputDispatcher::logOutboundKeyDetails(const char* prefix, const KeyEntry* entry) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+    ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32 ", "
+            "policyFlags=0x%x, action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, "
+            "metaState=0x%x, repeatCount=%d, downTime=%" PRId64,
+            prefix,
+            entry->eventTime, entry->deviceId, entry->source, entry->displayId, entry->policyFlags,
+            entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
+            entry->repeatCount, entry->downTime);
+#endif
+}
+
+bool InputDispatcher::dispatchMotionLocked(
+        nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
+    ATRACE_CALL();
+    // Preprocessing.
+    if (! entry->dispatchInProgress) {
+        entry->dispatchInProgress = true;
+
+        logOutboundMotionDetails("dispatchMotion - ", entry);
+    }
+
+    // Clean up if dropping the event.
+    if (*dropReason != DROP_REASON_NOT_DROPPED) {
+        setInjectionResult(entry, *dropReason == DROP_REASON_POLICY
+                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
+        return true;
+    }
+
+    bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
+
+    // Identify targets.
+    std::vector<InputTarget> inputTargets;
+
+    bool conflictingPointerActions = false;
+    int32_t injectionResult;
+    if (isPointerEvent) {
+        // Pointer event.  (eg. touchscreen)
+        injectionResult = findTouchedWindowTargetsLocked(currentTime,
+                entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
+    } else {
+        // Non touch event.  (eg. trackball)
+        injectionResult = findFocusedWindowTargetsLocked(currentTime,
+                entry, inputTargets, nextWakeupTime);
+    }
+    if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
+        return false;
+    }
+
+    setInjectionResult(entry, injectionResult);
+    if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
+        if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
+            CancelationOptions::Mode mode(isPointerEvent ?
+                    CancelationOptions::CANCEL_POINTER_EVENTS :
+                    CancelationOptions::CANCEL_NON_POINTER_EVENTS);
+            CancelationOptions options(mode, "input event injection failed");
+            synthesizeCancelationEventsForMonitorsLocked(options);
+        }
+        return true;
+    }
+
+    // Add monitor channels from event's or focused display.
+    addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(entry));
+
+    if (isPointerEvent) {
+        ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(entry->displayId);
+        if (stateIndex >= 0) {
+            const TouchState& state = mTouchStatesByDisplay.valueAt(stateIndex);
+            if (!state.portalWindows.empty()) {
+                // The event has gone through these portal windows, so we add monitoring targets of
+                // the corresponding displays as well.
+                for (size_t i = 0; i < state.portalWindows.size(); i++) {
+                    const InputWindowInfo* windowInfo = state.portalWindows[i]->getInfo();
+                    addGlobalMonitoringTargetsLocked(inputTargets, windowInfo->portalToDisplayId,
+                            -windowInfo->frameLeft, -windowInfo->frameTop);
+                }
+            }
+        }
+    }
+
+    // Dispatch the motion.
+    if (conflictingPointerActions) {
+        CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
+                "conflicting pointer actions");
+        synthesizeCancelationEventsForAllConnectionsLocked(options);
+    }
+    dispatchEventLocked(currentTime, entry, inputTargets);
+    return true;
+}
+
+
+void InputDispatcher::logOutboundMotionDetails(const char* prefix, const MotionEntry* entry) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+    ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32
+            ", policyFlags=0x%x, "
+            "action=0x%x, actionButton=0x%x, flags=0x%x, "
+            "metaState=0x%x, buttonState=0x%x,"
+            "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
+            prefix,
+            entry->eventTime, entry->deviceId, entry->source, entry->displayId, entry->policyFlags,
+            entry->action, entry->actionButton, entry->flags,
+            entry->metaState, entry->buttonState,
+            entry->edgeFlags, entry->xPrecision, entry->yPrecision,
+            entry->downTime);
+
+    for (uint32_t i = 0; i < entry->pointerCount; i++) {
+        ALOGD("  Pointer %d: id=%d, toolType=%d, "
+                "x=%f, y=%f, pressure=%f, size=%f, "
+                "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
+                "orientation=%f",
+                i, entry->pointerProperties[i].id,
+                entry->pointerProperties[i].toolType,
+                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
+                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
+                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
+                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
+                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
+                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
+                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
+                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
+                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
+    }
+#endif
+}
+
+void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
+        EventEntry* eventEntry, const std::vector<InputTarget>& inputTargets) {
+    ATRACE_CALL();
+#if DEBUG_DISPATCH_CYCLE
+    ALOGD("dispatchEventToCurrentInputTargets");
+#endif
+
+    ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
+
+    pokeUserActivityLocked(eventEntry);
+
+    for (const InputTarget& inputTarget : inputTargets) {
+        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
+        if (connectionIndex >= 0) {
+            sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
+            prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
+        } else {
+#if DEBUG_FOCUS
+            ALOGD("Dropping event delivery to target with channel '%s' because it "
+                    "is no longer registered with the input dispatcher.",
+                    inputTarget.inputChannel->getName().c_str());
+#endif
+        }
+    }
+}
+
+int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
+        const EventEntry* entry,
+        const sp<InputApplicationHandle>& applicationHandle,
+        const sp<InputWindowHandle>& windowHandle,
+        nsecs_t* nextWakeupTime, const char* reason) {
+    if (applicationHandle == nullptr && windowHandle == nullptr) {
+        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
+#if DEBUG_FOCUS
+            ALOGD("Waiting for system to become ready for input.  Reason: %s", reason);
+#endif
+            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
+            mInputTargetWaitStartTime = currentTime;
+            mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
+            mInputTargetWaitTimeoutExpired = false;
+            mInputTargetWaitApplicationToken.clear();
+        }
+    } else {
+        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
+#if DEBUG_FOCUS
+            ALOGD("Waiting for application to become ready for input: %s.  Reason: %s",
+                    getApplicationWindowLabel(applicationHandle, windowHandle).c_str(),
+                    reason);
+#endif
+            nsecs_t timeout;
+            if (windowHandle != nullptr) {
+                timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
+            } else if (applicationHandle != nullptr) {
+                timeout = applicationHandle->getDispatchingTimeout(
+                        DEFAULT_INPUT_DISPATCHING_TIMEOUT);
+            } else {
+                timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
+            }
+
+            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
+            mInputTargetWaitStartTime = currentTime;
+            mInputTargetWaitTimeoutTime = currentTime + timeout;
+            mInputTargetWaitTimeoutExpired = false;
+            mInputTargetWaitApplicationToken.clear();
+
+            if (windowHandle != nullptr) {
+                mInputTargetWaitApplicationToken = windowHandle->getApplicationToken();
+            }
+            if (mInputTargetWaitApplicationToken == nullptr && applicationHandle != nullptr) {
+                mInputTargetWaitApplicationToken = applicationHandle->getApplicationToken();
+            }
+        }
+    }
+
+    if (mInputTargetWaitTimeoutExpired) {
+        return INPUT_EVENT_INJECTION_TIMED_OUT;
+    }
+
+    if (currentTime >= mInputTargetWaitTimeoutTime) {
+        onANRLocked(currentTime, applicationHandle, windowHandle,
+                entry->eventTime, mInputTargetWaitStartTime, reason);
+
+        // Force poll loop to wake up immediately on next iteration once we get the
+        // ANR response back from the policy.
+        *nextWakeupTime = LONG_LONG_MIN;
+        return INPUT_EVENT_INJECTION_PENDING;
+    } else {
+        // Force poll loop to wake up when timeout is due.
+        if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
+            *nextWakeupTime = mInputTargetWaitTimeoutTime;
+        }
+        return INPUT_EVENT_INJECTION_PENDING;
+    }
+}
+
+void InputDispatcher::removeWindowByTokenLocked(const sp<IBinder>& token) {
+    for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) {
+        TouchState& state = mTouchStatesByDisplay.editValueAt(d);
+        state.removeWindowByToken(token);
+    }
+}
+
+void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
+        const sp<InputChannel>& inputChannel) {
+    if (newTimeout > 0) {
+        // Extend the timeout.
+        mInputTargetWaitTimeoutTime = now() + newTimeout;
+    } else {
+        // Give up.
+        mInputTargetWaitTimeoutExpired = true;
+
+        // Input state will not be realistic.  Mark it out of sync.
+        if (inputChannel.get()) {
+            ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
+            if (connectionIndex >= 0) {
+                sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
+                sp<IBinder> token = connection->inputChannel->getToken();
+
+                if (token != nullptr) {
+                    removeWindowByTokenLocked(token);
+                }
+
+                if (connection->status == Connection::STATUS_NORMAL) {
+                    CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS,
+                            "application not responding");
+                    synthesizeCancelationEventsForConnectionLocked(connection, options);
+                }
+            }
+        }
+    }
+}
+
+nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(
+        nsecs_t currentTime) {
+    if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
+        return currentTime - mInputTargetWaitStartTime;
+    }
+    return 0;
+}
+
+void InputDispatcher::resetANRTimeoutsLocked() {
+#if DEBUG_FOCUS
+        ALOGD("Resetting ANR timeouts.");
+#endif
+
+    // Reset input target wait timeout.
+    mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
+    mInputTargetWaitApplicationToken.clear();
+}
+
+/**
+ * Get the display id that the given event should go to. If this event specifies a valid display id,
+ * then it should be dispatched to that display. Otherwise, the event goes to the focused display.
+ * Focused display is the display that the user most recently interacted with.
+ */
+int32_t InputDispatcher::getTargetDisplayId(const EventEntry* entry) {
+    int32_t displayId;
+    switch (entry->type) {
+    case EventEntry::TYPE_KEY: {
+        const KeyEntry* typedEntry = static_cast<const KeyEntry*>(entry);
+        displayId = typedEntry->displayId;
+        break;
+    }
+    case EventEntry::TYPE_MOTION: {
+        const MotionEntry* typedEntry = static_cast<const MotionEntry*>(entry);
+        displayId = typedEntry->displayId;
+        break;
+    }
+    default: {
+        ALOGE("Unsupported event type '%" PRId32 "' for target display.", entry->type);
+        return ADISPLAY_ID_NONE;
+    }
+    }
+    return displayId == ADISPLAY_ID_NONE ? mFocusedDisplayId : displayId;
+}
+
+int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
+        const EventEntry* entry, std::vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) {
+    int32_t injectionResult;
+    std::string reason;
+
+    int32_t displayId = getTargetDisplayId(entry);
+    sp<InputWindowHandle> focusedWindowHandle =
+            getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+    sp<InputApplicationHandle> focusedApplicationHandle =
+            getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
+
+    // If there is no currently focused window and no focused application
+    // then drop the event.
+    if (focusedWindowHandle == nullptr) {
+        if (focusedApplicationHandle != nullptr) {
+            injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
+                    focusedApplicationHandle, nullptr, nextWakeupTime,
+                    "Waiting because no window has focus but there is a "
+                    "focused application that may eventually add a window "
+                    "when it finishes starting up.");
+            goto Unresponsive;
+        }
+
+        ALOGI("Dropping event because there is no focused window or focused application in display "
+                "%" PRId32 ".", displayId);
+        injectionResult = INPUT_EVENT_INJECTION_FAILED;
+        goto Failed;
+    }
+
+    // Check permissions.
+    if (!checkInjectionPermission(focusedWindowHandle, entry->injectionState)) {
+        injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
+        goto Failed;
+    }
+
+    // Check whether the window is ready for more input.
+    reason = checkWindowReadyForMoreInputLocked(currentTime,
+            focusedWindowHandle, entry, "focused");
+    if (!reason.empty()) {
+        injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
+                focusedApplicationHandle, focusedWindowHandle, nextWakeupTime, reason.c_str());
+        goto Unresponsive;
+    }
+
+    // Success!  Output targets.
+    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
+    addWindowTargetLocked(focusedWindowHandle,
+            InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0),
+            inputTargets);
+
+    // Done.
+Failed:
+Unresponsive:
+    nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
+    updateDispatchStatistics(currentTime, entry, injectionResult, timeSpentWaitingForApplication);
+#if DEBUG_FOCUS
+    ALOGD("findFocusedWindow finished: injectionResult=%d, "
+            "timeSpentWaitingForApplication=%0.1fms",
+            injectionResult, timeSpentWaitingForApplication / 1000000.0);
+#endif
+    return injectionResult;
+}
+
+int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
+        const MotionEntry* entry, std::vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,
+        bool* outConflictingPointerActions) {
+    ATRACE_CALL();
+    enum InjectionPermission {
+        INJECTION_PERMISSION_UNKNOWN,
+        INJECTION_PERMISSION_GRANTED,
+        INJECTION_PERMISSION_DENIED
+    };
+
+    // For security reasons, we defer updating the touch state until we are sure that
+    // event injection will be allowed.
+    int32_t displayId = entry->displayId;
+    int32_t action = entry->action;
+    int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
+
+    // Update the touch state as needed based on the properties of the touch event.
+    int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
+    InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
+    sp<InputWindowHandle> newHoverWindowHandle;
+
+    // Copy current touch state into mTempTouchState.
+    // This state is always reset at the end of this function, so if we don't find state
+    // for the specified display then our initial state will be empty.
+    const TouchState* oldState = nullptr;
+    ssize_t oldStateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
+    if (oldStateIndex >= 0) {
+        oldState = &mTouchStatesByDisplay.valueAt(oldStateIndex);
+        mTempTouchState.copyFrom(*oldState);
+    }
+
+    bool isSplit = mTempTouchState.split;
+    bool switchedDevice = mTempTouchState.deviceId >= 0 && mTempTouchState.displayId >= 0
+            && (mTempTouchState.deviceId != entry->deviceId
+                    || mTempTouchState.source != entry->source
+                    || mTempTouchState.displayId != displayId);
+    bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
+            || maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
+            || maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT);
+    bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN
+            || maskedAction == AMOTION_EVENT_ACTION_SCROLL
+            || isHoverAction);
+    bool wrongDevice = false;
+    if (newGesture) {
+        bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
+        if (switchedDevice && mTempTouchState.down && !down && !isHoverAction) {
+#if DEBUG_FOCUS
+            ALOGD("Dropping event because a pointer for a different device is already down "
+                    "in display %" PRId32, displayId);
+#endif
+            // TODO: test multiple simultaneous input streams.
+            injectionResult = INPUT_EVENT_INJECTION_FAILED;
+            switchedDevice = false;
+            wrongDevice = true;
+            goto Failed;
+        }
+        mTempTouchState.reset();
+        mTempTouchState.down = down;
+        mTempTouchState.deviceId = entry->deviceId;
+        mTempTouchState.source = entry->source;
+        mTempTouchState.displayId = displayId;
+        isSplit = false;
+    } else if (switchedDevice && maskedAction == AMOTION_EVENT_ACTION_MOVE) {
+#if DEBUG_FOCUS
+        ALOGI("Dropping move event because a pointer for a different device is already active "
+                "in display %" PRId32, displayId);
+#endif
+        // TODO: test multiple simultaneous input streams.
+        injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
+        switchedDevice = false;
+        wrongDevice = true;
+        goto Failed;
+    }
+
+    if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
+        /* Case 1: New splittable pointer going down, or need target for hover or scroll. */
+
+        int32_t pointerIndex = getMotionEventActionPointerIndex(action);
+        int32_t x = int32_t(entry->pointerCoords[pointerIndex].
+                getAxisValue(AMOTION_EVENT_AXIS_X));
+        int32_t y = int32_t(entry->pointerCoords[pointerIndex].
+                getAxisValue(AMOTION_EVENT_AXIS_Y));
+        bool isDown = maskedAction == AMOTION_EVENT_ACTION_DOWN;
+        sp<InputWindowHandle> newTouchedWindowHandle = findTouchedWindowAtLocked(
+                displayId, x, y, isDown /*addOutsideTargets*/, true /*addPortalWindows*/);
+
+        std::vector<TouchedMonitor> newGestureMonitors = isDown
+                ? findTouchedGestureMonitorsLocked(displayId, mTempTouchState.portalWindows)
+                : std::vector<TouchedMonitor>{};
+
+        // Figure out whether splitting will be allowed for this window.
+        if (newTouchedWindowHandle != nullptr
+                && newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
+            // New window supports splitting.
+            isSplit = true;
+        } else if (isSplit) {
+            // New window does not support splitting but we have already split events.
+            // Ignore the new window.
+            newTouchedWindowHandle = nullptr;
+        }
+
+        // Handle the case where we did not find a window.
+        if (newTouchedWindowHandle == nullptr) {
+            // Try to assign the pointer to the first foreground window we find, if there is one.
+            newTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle();
+        }
+
+        if (newTouchedWindowHandle == nullptr && newGestureMonitors.empty()) {
+            ALOGI("Dropping event because there is no touchable window or gesture monitor at "
+                    "(%d, %d) in display %" PRId32 ".", x, y, displayId);
+            injectionResult = INPUT_EVENT_INJECTION_FAILED;
+            goto Failed;
+        }
+
+        if (newTouchedWindowHandle != nullptr) {
+            // Set target flags.
+            int32_t targetFlags = InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS;
+            if (isSplit) {
+                targetFlags |= InputTarget::FLAG_SPLIT;
+            }
+            if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
+                targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+            } else if (isWindowObscuredLocked(newTouchedWindowHandle)) {
+                targetFlags |= InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
+            }
+
+            // Update hover state.
+            if (isHoverAction) {
+                newHoverWindowHandle = newTouchedWindowHandle;
+            } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
+                newHoverWindowHandle = mLastHoverWindowHandle;
+            }
+
+            // Update the temporary touch state.
+            BitSet32 pointerIds;
+            if (isSplit) {
+                uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
+                pointerIds.markBit(pointerId);
+            }
+            mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
+        }
+
+        mTempTouchState.addGestureMonitors(newGestureMonitors);
+    } else {
+        /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
+
+        // If the pointer is not currently down, then ignore the event.
+        if (! mTempTouchState.down) {
+#if DEBUG_FOCUS
+            ALOGD("Dropping event because the pointer is not down or we previously "
+                    "dropped the pointer down event in display %" PRId32, displayId);
+#endif
+            injectionResult = INPUT_EVENT_INJECTION_FAILED;
+            goto Failed;
+        }
+
+        // Check whether touches should slip outside of the current foreground window.
+        if (maskedAction == AMOTION_EVENT_ACTION_MOVE
+                && entry->pointerCount == 1
+                && mTempTouchState.isSlippery()) {
+            int32_t x = int32_t(entry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
+            int32_t y = int32_t(entry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
+
+            sp<InputWindowHandle> oldTouchedWindowHandle =
+                    mTempTouchState.getFirstForegroundWindowHandle();
+            sp<InputWindowHandle> newTouchedWindowHandle =
+                    findTouchedWindowAtLocked(displayId, x, y);
+            if (oldTouchedWindowHandle != newTouchedWindowHandle
+                    && oldTouchedWindowHandle != nullptr
+                    && newTouchedWindowHandle != nullptr) {
+#if DEBUG_FOCUS
+                ALOGD("Touch is slipping out of window %s into window %s in display %" PRId32,
+                        oldTouchedWindowHandle->getName().c_str(),
+                        newTouchedWindowHandle->getName().c_str(),
+                        displayId);
+#endif
+                // Make a slippery exit from the old window.
+                mTempTouchState.addOrUpdateWindow(oldTouchedWindowHandle,
+                        InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT, BitSet32(0));
+
+                // Make a slippery entrance into the new window.
+                if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
+                    isSplit = true;
+                }
+
+                int32_t targetFlags = InputTarget::FLAG_FOREGROUND
+                        | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER;
+                if (isSplit) {
+                    targetFlags |= InputTarget::FLAG_SPLIT;
+                }
+                if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
+                    targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+                }
+
+                BitSet32 pointerIds;
+                if (isSplit) {
+                    pointerIds.markBit(entry->pointerProperties[0].id);
+                }
+                mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
+            }
+        }
+    }
+
+    if (newHoverWindowHandle != mLastHoverWindowHandle) {
+        // Let the previous window know that the hover sequence is over.
+        if (mLastHoverWindowHandle != nullptr) {
+#if DEBUG_HOVER
+            ALOGD("Sending hover exit event to window %s.",
+                    mLastHoverWindowHandle->getName().c_str());
+#endif
+            mTempTouchState.addOrUpdateWindow(mLastHoverWindowHandle,
+                    InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT, BitSet32(0));
+        }
+
+        // Let the new window know that the hover sequence is starting.
+        if (newHoverWindowHandle != nullptr) {
+#if DEBUG_HOVER
+            ALOGD("Sending hover enter event to window %s.",
+                    newHoverWindowHandle->getName().c_str());
+#endif
+            mTempTouchState.addOrUpdateWindow(newHoverWindowHandle,
+                    InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER, BitSet32(0));
+        }
+    }
+
+    // Check permission to inject into all touched foreground windows and ensure there
+    // is at least one touched foreground window.
+    {
+        bool haveForegroundWindow = false;
+        for (const TouchedWindow& touchedWindow : mTempTouchState.windows) {
+            if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
+                haveForegroundWindow = true;
+                if (! checkInjectionPermission(touchedWindow.windowHandle,
+                        entry->injectionState)) {
+                    injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
+                    injectionPermission = INJECTION_PERMISSION_DENIED;
+                    goto Failed;
+                }
+            }
+        }
+        bool hasGestureMonitor = !mTempTouchState.gestureMonitors.empty();
+        if (!haveForegroundWindow && !hasGestureMonitor) {
+#if DEBUG_FOCUS
+            ALOGD("Dropping event because there is no touched foreground window in display %"
+                    PRId32 " or gesture monitor to receive it.", displayId);
+#endif
+            injectionResult = INPUT_EVENT_INJECTION_FAILED;
+            goto Failed;
+        }
+
+        // Permission granted to injection into all touched foreground windows.
+        injectionPermission = INJECTION_PERMISSION_GRANTED;
+    }
+
+    // Check whether windows listening for outside touches are owned by the same UID. If it is
+    // set the policy flag that we will not reveal coordinate information to this window.
+    if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
+        sp<InputWindowHandle> foregroundWindowHandle =
+                mTempTouchState.getFirstForegroundWindowHandle();
+        if (foregroundWindowHandle) {
+            const int32_t foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid;
+            for (const TouchedWindow& touchedWindow : mTempTouchState.windows) {
+                if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
+                    sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle;
+                    if (inputWindowHandle->getInfo()->ownerUid != foregroundWindowUid) {
+                        mTempTouchState.addOrUpdateWindow(inputWindowHandle,
+                                InputTarget::FLAG_ZERO_COORDS, BitSet32(0));
+                    }
+                }
+            }
+        }
+    }
+
+    // Ensure all touched foreground windows are ready for new input.
+    for (const TouchedWindow& touchedWindow : mTempTouchState.windows) {
+        if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
+            // Check whether the window is ready for more input.
+            std::string reason = checkWindowReadyForMoreInputLocked(currentTime,
+                    touchedWindow.windowHandle, entry, "touched");
+            if (!reason.empty()) {
+                injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
+                        nullptr, touchedWindow.windowHandle, nextWakeupTime, reason.c_str());
+                goto Unresponsive;
+            }
+        }
+    }
+
+    // If this is the first pointer going down and the touched window has a wallpaper
+    // then also add the touched wallpaper windows so they are locked in for the duration
+    // of the touch gesture.
+    // We do not collect wallpapers during HOVER_MOVE or SCROLL because the wallpaper
+    // engine only supports touch events.  We would need to add a mechanism similar
+    // to View.onGenericMotionEvent to enable wallpapers to handle these events.
+    if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
+        sp<InputWindowHandle> foregroundWindowHandle =
+                mTempTouchState.getFirstForegroundWindowHandle();
+        if (foregroundWindowHandle && foregroundWindowHandle->getInfo()->hasWallpaper) {
+            const std::vector<sp<InputWindowHandle>> windowHandles =
+                    getWindowHandlesLocked(displayId);
+            for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
+                const InputWindowInfo* info = windowHandle->getInfo();
+                if (info->displayId == displayId
+                        && windowHandle->getInfo()->layoutParamsType
+                                == InputWindowInfo::TYPE_WALLPAPER) {
+                    mTempTouchState.addOrUpdateWindow(windowHandle,
+                            InputTarget::FLAG_WINDOW_IS_OBSCURED
+                                    | InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED
+                                    | InputTarget::FLAG_DISPATCH_AS_IS,
+                            BitSet32(0));
+                }
+            }
+        }
+    }
+
+    // Success!  Output targets.
+    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
+
+    for (const TouchedWindow& touchedWindow : mTempTouchState.windows) {
+        addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
+                touchedWindow.pointerIds, inputTargets);
+    }
+
+    for (const TouchedMonitor& touchedMonitor : mTempTouchState.gestureMonitors) {
+        addMonitoringTargetLocked(touchedMonitor.monitor, touchedMonitor.xOffset,
+                touchedMonitor.yOffset, inputTargets);
+    }
+
+    // Drop the outside or hover touch windows since we will not care about them
+    // in the next iteration.
+    mTempTouchState.filterNonAsIsTouchWindows();
+
+Failed:
+    // Check injection permission once and for all.
+    if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
+        if (checkInjectionPermission(nullptr, entry->injectionState)) {
+            injectionPermission = INJECTION_PERMISSION_GRANTED;
+        } else {
+            injectionPermission = INJECTION_PERMISSION_DENIED;
+        }
+    }
+
+    // Update final pieces of touch state if the injector had permission.
+    if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
+        if (!wrongDevice) {
+            if (switchedDevice) {
+#if DEBUG_FOCUS
+                ALOGD("Conflicting pointer actions: Switched to a different device.");
+#endif
+                *outConflictingPointerActions = true;
+            }
+
+            if (isHoverAction) {
+                // Started hovering, therefore no longer down.
+                if (oldState && oldState->down) {
+#if DEBUG_FOCUS
+                    ALOGD("Conflicting pointer actions: Hover received while pointer was down.");
+#endif
+                    *outConflictingPointerActions = true;
+                }
+                mTempTouchState.reset();
+                if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
+                        || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
+                    mTempTouchState.deviceId = entry->deviceId;
+                    mTempTouchState.source = entry->source;
+                    mTempTouchState.displayId = displayId;
+                }
+            } else if (maskedAction == AMOTION_EVENT_ACTION_UP
+                    || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
+                // All pointers up or canceled.
+                mTempTouchState.reset();
+            } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
+                // First pointer went down.
+                if (oldState && oldState->down) {
+#if DEBUG_FOCUS
+                    ALOGD("Conflicting pointer actions: Down received while already down.");
+#endif
+                    *outConflictingPointerActions = true;
+                }
+            } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
+                // One pointer went up.
+                if (isSplit) {
+                    int32_t pointerIndex = getMotionEventActionPointerIndex(action);
+                    uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
+
+                    for (size_t i = 0; i < mTempTouchState.windows.size(); ) {
+                        TouchedWindow& touchedWindow = mTempTouchState.windows[i];
+                        if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
+                            touchedWindow.pointerIds.clearBit(pointerId);
+                            if (touchedWindow.pointerIds.isEmpty()) {
+                                mTempTouchState.windows.erase(mTempTouchState.windows.begin() + i);
+                                continue;
+                            }
+                        }
+                        i += 1;
+                    }
+                }
+            }
+
+            // Save changes unless the action was scroll in which case the temporary touch
+            // state was only valid for this one action.
+            if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) {
+                if (mTempTouchState.displayId >= 0) {
+                    if (oldStateIndex >= 0) {
+                        mTouchStatesByDisplay.editValueAt(oldStateIndex).copyFrom(mTempTouchState);
+                    } else {
+                        mTouchStatesByDisplay.add(displayId, mTempTouchState);
+                    }
+                } else if (oldStateIndex >= 0) {
+                    mTouchStatesByDisplay.removeItemsAt(oldStateIndex);
+                }
+            }
+
+            // Update hover state.
+            mLastHoverWindowHandle = newHoverWindowHandle;
+        }
+    } else {
+#if DEBUG_FOCUS
+        ALOGD("Not updating touch focus because injection was denied.");
+#endif
+    }
+
+Unresponsive:
+    // Reset temporary touch state to ensure we release unnecessary references to input channels.
+    mTempTouchState.reset();
+
+    nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
+    updateDispatchStatistics(currentTime, entry, injectionResult, timeSpentWaitingForApplication);
+#if DEBUG_FOCUS
+    ALOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, "
+            "timeSpentWaitingForApplication=%0.1fms",
+            injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
+#endif
+    return injectionResult;
+}
+
+void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
+        int32_t targetFlags, BitSet32 pointerIds, std::vector<InputTarget>& inputTargets) {
+    sp<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken());
+    if (inputChannel == nullptr) {
+        ALOGW("Window %s already unregistered input channel", windowHandle->getName().c_str());
+        return;
+    }
+
+    const InputWindowInfo* windowInfo = windowHandle->getInfo();
+    InputTarget target;
+    target.inputChannel = inputChannel;
+    target.flags = targetFlags;
+    target.xOffset = - windowInfo->frameLeft;
+    target.yOffset = - windowInfo->frameTop;
+    target.globalScaleFactor = windowInfo->globalScaleFactor;
+    target.windowXScale = windowInfo->windowXScale;
+    target.windowYScale = windowInfo->windowYScale;
+    target.pointerIds = pointerIds;
+    inputTargets.push_back(target);
+}
+
+void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
+         int32_t displayId, float xOffset, float yOffset) {
+
+    std::unordered_map<int32_t, std::vector<Monitor>>::const_iterator it =
+            mGlobalMonitorsByDisplay.find(displayId);
+
+    if (it != mGlobalMonitorsByDisplay.end()) {
+        const std::vector<Monitor>& monitors = it->second;
+        for (const Monitor& monitor : monitors) {
+            addMonitoringTargetLocked(monitor, xOffset, yOffset, inputTargets);
+        }
+    }
+}
+
+void InputDispatcher::addMonitoringTargetLocked(const Monitor& monitor,
+        float xOffset, float yOffset, std::vector<InputTarget>& inputTargets) {
+    InputTarget target;
+    target.inputChannel = monitor.inputChannel;
+    target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
+    target.xOffset = xOffset;
+    target.yOffset = yOffset;
+    target.pointerIds.clear();
+    target.globalScaleFactor = 1.0f;
+    inputTargets.push_back(target);
+}
+
+bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
+        const InjectionState* injectionState) {
+    if (injectionState
+            && (windowHandle == nullptr
+                    || windowHandle->getInfo()->ownerUid != injectionState->injectorUid)
+            && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
+        if (windowHandle != nullptr) {
+            ALOGW("Permission denied: injecting event from pid %d uid %d to window %s "
+                    "owned by uid %d",
+                    injectionState->injectorPid, injectionState->injectorUid,
+                    windowHandle->getName().c_str(),
+                    windowHandle->getInfo()->ownerUid);
+        } else {
+            ALOGW("Permission denied: injecting event from pid %d uid %d",
+                    injectionState->injectorPid, injectionState->injectorUid);
+        }
+        return false;
+    }
+    return true;
+}
+
+bool InputDispatcher::isWindowObscuredAtPointLocked(
+        const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const {
+    int32_t displayId = windowHandle->getInfo()->displayId;
+    const std::vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
+    for (const sp<InputWindowHandle>& otherHandle : windowHandles) {
+        if (otherHandle == windowHandle) {
+            break;
+        }
+
+        const InputWindowInfo* otherInfo = otherHandle->getInfo();
+        if (otherInfo->displayId == displayId
+                && otherInfo->visible && !otherInfo->isTrustedOverlay()
+                && otherInfo->frameContainsPoint(x, y)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+
+bool InputDispatcher::isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const {
+    int32_t displayId = windowHandle->getInfo()->displayId;
+    const std::vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
+    const InputWindowInfo* windowInfo = windowHandle->getInfo();
+    for (const sp<InputWindowHandle>& otherHandle : windowHandles) {
+        if (otherHandle == windowHandle) {
+            break;
+        }
+
+        const InputWindowInfo* otherInfo = otherHandle->getInfo();
+        if (otherInfo->displayId == displayId
+                && otherInfo->visible && !otherInfo->isTrustedOverlay()
+                && otherInfo->overlaps(windowInfo)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+std::string InputDispatcher::checkWindowReadyForMoreInputLocked(nsecs_t currentTime,
+        const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry,
+        const char* targetType) {
+    // If the window is paused then keep waiting.
+    if (windowHandle->getInfo()->paused) {
+        return StringPrintf("Waiting because the %s window is paused.", targetType);
+    }
+
+    // If the window's connection is not registered then keep waiting.
+    ssize_t connectionIndex = getConnectionIndexLocked(
+            getInputChannelLocked(windowHandle->getToken()));
+    if (connectionIndex < 0) {
+        return StringPrintf("Waiting because the %s window's input channel is not "
+                "registered with the input dispatcher.  The window may be in the process "
+                "of being removed.", targetType);
+    }
+
+    // If the connection is dead then keep waiting.
+    sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
+    if (connection->status != Connection::STATUS_NORMAL) {
+        return StringPrintf("Waiting because the %s window's input connection is %s."
+                "The window may be in the process of being removed.", targetType,
+                connection->getStatusLabel());
+    }
+
+    // If the connection is backed up then keep waiting.
+    if (connection->inputPublisherBlocked) {
+        return StringPrintf("Waiting because the %s window's input channel is full.  "
+                "Outbound queue length: %d.  Wait queue length: %d.",
+                targetType, connection->outboundQueue.count(), connection->waitQueue.count());
+    }
+
+    // Ensure that the dispatch queues aren't too far backed up for this event.
+    if (eventEntry->type == EventEntry::TYPE_KEY) {
+        // If the event is a key event, then we must wait for all previous events to
+        // complete before delivering it because previous events may have the
+        // side-effect of transferring focus to a different window and we want to
+        // ensure that the following keys are sent to the new window.
+        //
+        // Suppose the user touches a button in a window then immediately presses "A".
+        // If the button causes a pop-up window to appear then we want to ensure that
+        // the "A" key is delivered to the new pop-up window.  This is because users
+        // often anticipate pending UI changes when typing on a keyboard.
+        // To obtain this behavior, we must serialize key events with respect to all
+        // prior input events.
+        if (!connection->outboundQueue.isEmpty() || !connection->waitQueue.isEmpty()) {
+            return StringPrintf("Waiting to send key event because the %s window has not "
+                    "finished processing all of the input events that were previously "
+                    "delivered to it.  Outbound queue length: %d.  Wait queue length: %d.",
+                    targetType, connection->outboundQueue.count(), connection->waitQueue.count());
+        }
+    } else {
+        // Touch events can always be sent to a window immediately because the user intended
+        // to touch whatever was visible at the time.  Even if focus changes or a new
+        // window appears moments later, the touch event was meant to be delivered to
+        // whatever window happened to be on screen at the time.
+        //
+        // Generic motion events, such as trackball or joystick events are a little trickier.
+        // Like key events, generic motion events are delivered to the focused window.
+        // Unlike key events, generic motion events don't tend to transfer focus to other
+        // windows and it is not important for them to be serialized.  So we prefer to deliver
+        // generic motion events as soon as possible to improve efficiency and reduce lag
+        // through batching.
+        //
+        // The one case where we pause input event delivery is when the wait queue is piling
+        // up with lots of events because the application is not responding.
+        // This condition ensures that ANRs are detected reliably.
+        if (!connection->waitQueue.isEmpty()
+                && currentTime >= connection->waitQueue.head->deliveryTime
+                        + STREAM_AHEAD_EVENT_TIMEOUT) {
+            return StringPrintf("Waiting to send non-key event because the %s window has not "
+                    "finished processing certain input events that were delivered to it over "
+                    "%0.1fms ago.  Wait queue length: %d.  Wait queue head age: %0.1fms.",
+                    targetType, STREAM_AHEAD_EVENT_TIMEOUT * 0.000001f,
+                    connection->waitQueue.count(),
+                    (currentTime - connection->waitQueue.head->deliveryTime) * 0.000001f);
+        }
+    }
+    return "";
+}
+
+std::string InputDispatcher::getApplicationWindowLabel(
+        const sp<InputApplicationHandle>& applicationHandle,
+        const sp<InputWindowHandle>& windowHandle) {
+    if (applicationHandle != nullptr) {
+        if (windowHandle != nullptr) {
+            std::string label(applicationHandle->getName());
+            label += " - ";
+            label += windowHandle->getName();
+            return label;
+        } else {
+            return applicationHandle->getName();
+        }
+    } else if (windowHandle != nullptr) {
+        return windowHandle->getName();
+    } else {
+        return "<unknown application or window>";
+    }
+}
+
+void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
+    int32_t displayId = getTargetDisplayId(eventEntry);
+    sp<InputWindowHandle> focusedWindowHandle =
+            getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+    if (focusedWindowHandle != nullptr) {
+        const InputWindowInfo* info = focusedWindowHandle->getInfo();
+        if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) {
+#if DEBUG_DISPATCH_CYCLE
+            ALOGD("Not poking user activity: disabled by window '%s'.", info->name.c_str());
+#endif
+            return;
+        }
+    }
+
+    int32_t eventType = USER_ACTIVITY_EVENT_OTHER;
+    switch (eventEntry->type) {
+    case EventEntry::TYPE_MOTION: {
+        const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
+        if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
+            return;
+        }
+
+        if (MotionEvent::isTouchEvent(motionEntry->source, motionEntry->action)) {
+            eventType = USER_ACTIVITY_EVENT_TOUCH;
+        }
+        break;
+    }
+    case EventEntry::TYPE_KEY: {
+        const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry);
+        if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
+            return;
+        }
+        eventType = USER_ACTIVITY_EVENT_BUTTON;
+        break;
+    }
+    }
+
+    CommandEntry* commandEntry = postCommandLocked(
+            & InputDispatcher::doPokeUserActivityLockedInterruptible);
+    commandEntry->eventTime = eventEntry->eventTime;
+    commandEntry->userActivityEventType = eventType;
+}
+
+void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
+        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
+    if (ATRACE_ENABLED()) {
+        std::string message = StringPrintf(
+                "prepareDispatchCycleLocked(inputChannel=%s, sequenceNum=%" PRIu32 ")",
+                connection->getInputChannelName().c_str(), eventEntry->sequenceNum);
+        ATRACE_NAME(message.c_str());
+    }
+#if DEBUG_DISPATCH_CYCLE
+    ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, "
+            "xOffset=%f, yOffset=%f, globalScaleFactor=%f, "
+            "windowScaleFactor=(%f, %f), pointerIds=0x%x",
+            connection->getInputChannelName().c_str(), inputTarget->flags,
+            inputTarget->xOffset, inputTarget->yOffset,
+            inputTarget->globalScaleFactor,
+            inputTarget->windowXScale, inputTarget->windowYScale,
+            inputTarget->pointerIds.value);
+#endif
+
+    // Skip this event if the connection status is not normal.
+    // We don't want to enqueue additional outbound events if the connection is broken.
+    if (connection->status != Connection::STATUS_NORMAL) {
+#if DEBUG_DISPATCH_CYCLE
+        ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
+                connection->getInputChannelName().c_str(), connection->getStatusLabel());
+#endif
+        return;
+    }
+
+    // Split a motion event if needed.
+    if (inputTarget->flags & InputTarget::FLAG_SPLIT) {
+        ALOG_ASSERT(eventEntry->type == EventEntry::TYPE_MOTION);
+
+        MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(eventEntry);
+        if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {
+            MotionEntry* splitMotionEntry = splitMotionEvent(
+                    originalMotionEntry, inputTarget->pointerIds);
+            if (!splitMotionEntry) {
+                return; // split event was dropped
+            }
+#if DEBUG_FOCUS
+            ALOGD("channel '%s' ~ Split motion event.",
+                    connection->getInputChannelName().c_str());
+            logOutboundMotionDetails("  ", splitMotionEntry);
+#endif
+            enqueueDispatchEntriesLocked(currentTime, connection,
+                    splitMotionEntry, inputTarget);
+            splitMotionEntry->release();
+            return;
+        }
+    }
+
+    // Not splitting.  Enqueue dispatch entries for the event as is.
+    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
+}
+
+void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
+        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
+    if (ATRACE_ENABLED()) {
+        std::string message = StringPrintf(
+                "enqueueDispatchEntriesLocked(inputChannel=%s, sequenceNum=%" PRIu32 ")",
+                connection->getInputChannelName().c_str(), eventEntry->sequenceNum);
+        ATRACE_NAME(message.c_str());
+    }
+
+    bool wasEmpty = connection->outboundQueue.isEmpty();
+
+    // Enqueue dispatch entries for the requested modes.
+    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
+            InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
+    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
+            InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
+    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
+            InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
+    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
+            InputTarget::FLAG_DISPATCH_AS_IS);
+    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
+            InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
+    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
+            InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
+
+    // If the outbound queue was previously empty, start the dispatch cycle going.
+    if (wasEmpty && !connection->outboundQueue.isEmpty()) {
+        startDispatchCycleLocked(currentTime, connection);
+    }
+}
+
+void InputDispatcher::enqueueDispatchEntryLocked(
+        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
+        int32_t dispatchMode) {
+    if (ATRACE_ENABLED()) {
+        std::string message = StringPrintf(
+                "enqueueDispatchEntry(inputChannel=%s, dispatchMode=%s)",
+                connection->getInputChannelName().c_str(),
+                dispatchModeToString(dispatchMode).c_str());
+        ATRACE_NAME(message.c_str());
+    }
+    int32_t inputTargetFlags = inputTarget->flags;
+    if (!(inputTargetFlags & dispatchMode)) {
+        return;
+    }
+    inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;
+
+    // This is a new event.
+    // Enqueue a new dispatch entry onto the outbound queue for this connection.
+    DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref
+            inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
+            inputTarget->globalScaleFactor, inputTarget->windowXScale,
+            inputTarget->windowYScale);
+
+    // Apply target flags and update the connection's input state.
+    switch (eventEntry->type) {
+    case EventEntry::TYPE_KEY: {
+        KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
+        dispatchEntry->resolvedAction = keyEntry->action;
+        dispatchEntry->resolvedFlags = keyEntry->flags;
+
+        if (!connection->inputState.trackKey(keyEntry,
+                dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
+#if DEBUG_DISPATCH_CYCLE
+            ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event",
+                    connection->getInputChannelName().c_str());
+#endif
+            delete dispatchEntry;
+            return; // skip the inconsistent event
+        }
+        break;
+    }
+
+    case EventEntry::TYPE_MOTION: {
+        MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
+        if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
+        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) {
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
+        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
+        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
+        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN;
+        } else {
+            dispatchEntry->resolvedAction = motionEntry->action;
+        }
+        if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
+                && !connection->inputState.isHovering(
+                        motionEntry->deviceId, motionEntry->source, motionEntry->displayId)) {
+#if DEBUG_DISPATCH_CYCLE
+        ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter event",
+                connection->getInputChannelName().c_str());
+#endif
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
+        }
+
+        dispatchEntry->resolvedFlags = motionEntry->flags;
+        if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
+            dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
+        }
+        if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED) {
+            dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
+        }
+
+        if (!connection->inputState.trackMotion(motionEntry,
+                dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
+#if DEBUG_DISPATCH_CYCLE
+            ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent motion event",
+                    connection->getInputChannelName().c_str());
+#endif
+            delete dispatchEntry;
+            return; // skip the inconsistent event
+        }
+
+        dispatchPointerDownOutsideFocus(motionEntry->source,
+                dispatchEntry->resolvedAction, inputTarget->inputChannel->getToken());
+
+        break;
+    }
+    }
+
+    // Remember that we are waiting for this dispatch to complete.
+    if (dispatchEntry->hasForegroundTarget()) {
+        incrementPendingForegroundDispatches(eventEntry);
+    }
+
+    // Enqueue the dispatch entry.
+    connection->outboundQueue.enqueueAtTail(dispatchEntry);
+    traceOutboundQueueLength(connection);
+
+}
+
+void InputDispatcher::dispatchPointerDownOutsideFocus(uint32_t source, int32_t action,
+        const sp<IBinder>& newToken) {
+    int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
+    uint32_t maskedSource = source & AINPUT_SOURCE_CLASS_MASK;
+    if (maskedSource != AINPUT_SOURCE_CLASS_POINTER || maskedAction != AMOTION_EVENT_ACTION_DOWN) {
+        return;
+    }
+
+    sp<InputWindowHandle> inputWindowHandle = getWindowHandleLocked(newToken);
+    if (inputWindowHandle == nullptr) {
+        return;
+    }
+
+    sp<InputWindowHandle> focusedWindowHandle =
+            getValueByKey(mFocusedWindowHandlesByDisplay, mFocusedDisplayId);
+
+    bool hasFocusChanged = !focusedWindowHandle || focusedWindowHandle->getToken() != newToken;
+
+    if (!hasFocusChanged) {
+        return;
+    }
+
+    CommandEntry* commandEntry = postCommandLocked(
+            & InputDispatcher::doOnPointerDownOutsideFocusLockedInterruptible);
+    commandEntry->newToken = newToken;
+}
+
+void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
+        const sp<Connection>& connection) {
+    if (ATRACE_ENABLED()) {
+        std::string message = StringPrintf("startDispatchCycleLocked(inputChannel=%s)",
+                connection->getInputChannelName().c_str());
+        ATRACE_NAME(message.c_str());
+    }
+#if DEBUG_DISPATCH_CYCLE
+    ALOGD("channel '%s' ~ startDispatchCycle",
+            connection->getInputChannelName().c_str());
+#endif
+
+    while (connection->status == Connection::STATUS_NORMAL
+            && !connection->outboundQueue.isEmpty()) {
+        DispatchEntry* dispatchEntry = connection->outboundQueue.head;
+        dispatchEntry->deliveryTime = currentTime;
+
+        // Publish the event.
+        status_t status;
+        EventEntry* eventEntry = dispatchEntry->eventEntry;
+        switch (eventEntry->type) {
+        case EventEntry::TYPE_KEY: {
+            KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
+
+            // Publish the key event.
+            status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,
+                    keyEntry->deviceId, keyEntry->source, keyEntry->displayId,
+                    dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
+                    keyEntry->keyCode, keyEntry->scanCode,
+                    keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
+                    keyEntry->eventTime);
+            break;
+        }
+
+        case EventEntry::TYPE_MOTION: {
+            MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
+
+            PointerCoords scaledCoords[MAX_POINTERS];
+            const PointerCoords* usingCoords = motionEntry->pointerCoords;
+
+            // Set the X and Y offset depending on the input source.
+            float xOffset, yOffset;
+            if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
+                    && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
+                float globalScaleFactor = dispatchEntry->globalScaleFactor;
+                float wxs = dispatchEntry->windowXScale;
+                float wys = dispatchEntry->windowYScale;
+                xOffset = dispatchEntry->xOffset * wxs;
+                yOffset = dispatchEntry->yOffset * wys;
+                if (wxs != 1.0f || wys != 1.0f || globalScaleFactor != 1.0f) {
+                    for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
+                        scaledCoords[i] = motionEntry->pointerCoords[i];
+                        scaledCoords[i].scale(globalScaleFactor, wxs, wys);
+                    }
+                    usingCoords = scaledCoords;
+                }
+            } else {
+                xOffset = 0.0f;
+                yOffset = 0.0f;
+
+                // We don't want the dispatch target to know.
+                if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
+                    for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
+                        scaledCoords[i].clear();
+                    }
+                    usingCoords = scaledCoords;
+                }
+            }
+
+            // Publish the motion event.
+            status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
+                    motionEntry->deviceId, motionEntry->source, motionEntry->displayId,
+                    dispatchEntry->resolvedAction, motionEntry->actionButton,
+                    dispatchEntry->resolvedFlags, motionEntry->edgeFlags,
+                    motionEntry->metaState, motionEntry->buttonState, motionEntry->classification,
+                    xOffset, yOffset, motionEntry->xPrecision, motionEntry->yPrecision,
+                    motionEntry->downTime, motionEntry->eventTime,
+                    motionEntry->pointerCount, motionEntry->pointerProperties,
+                    usingCoords);
+            break;
+        }
+
+        default:
+            ALOG_ASSERT(false);
+            return;
+        }
+
+        // Check the result.
+        if (status) {
+            if (status == WOULD_BLOCK) {
+                if (connection->waitQueue.isEmpty()) {
+                    ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "
+                            "This is unexpected because the wait queue is empty, so the pipe "
+                            "should be empty and we shouldn't have any problems writing an "
+                            "event to it, status=%d", connection->getInputChannelName().c_str(),
+                            status);
+                    abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
+                } else {
+                    // Pipe is full and we are waiting for the app to finish process some events
+                    // before sending more events to it.
+#if DEBUG_DISPATCH_CYCLE
+                    ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "
+                            "waiting for the application to catch up",
+                            connection->getInputChannelName().c_str());
+#endif
+                    connection->inputPublisherBlocked = true;
+                }
+            } else {
+                ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
+                        "status=%d", connection->getInputChannelName().c_str(), status);
+                abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
+            }
+            return;
+        }
+
+        // Re-enqueue the event on the wait queue.
+        connection->outboundQueue.dequeue(dispatchEntry);
+        traceOutboundQueueLength(connection);
+        connection->waitQueue.enqueueAtTail(dispatchEntry);
+        traceWaitQueueLength(connection);
+    }
+}
+
+void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
+        const sp<Connection>& connection, uint32_t seq, bool handled) {
+#if DEBUG_DISPATCH_CYCLE
+    ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s",
+            connection->getInputChannelName().c_str(), seq, toString(handled));
+#endif
+
+    connection->inputPublisherBlocked = false;
+
+    if (connection->status == Connection::STATUS_BROKEN
+            || connection->status == Connection::STATUS_ZOMBIE) {
+        return;
+    }
+
+    // Notify other system components and prepare to start the next dispatch cycle.
+    onDispatchCycleFinishedLocked(currentTime, connection, seq, handled);
+}
+
+void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
+        const sp<Connection>& connection, bool notify) {
+#if DEBUG_DISPATCH_CYCLE
+    ALOGD("channel '%s' ~ abortBrokenDispatchCycle - notify=%s",
+            connection->getInputChannelName().c_str(), toString(notify));
+#endif
+
+    // Clear the dispatch queues.
+    drainDispatchQueue(&connection->outboundQueue);
+    traceOutboundQueueLength(connection);
+    drainDispatchQueue(&connection->waitQueue);
+    traceWaitQueueLength(connection);
+
+    // The connection appears to be unrecoverably broken.
+    // Ignore already broken or zombie connections.
+    if (connection->status == Connection::STATUS_NORMAL) {
+        connection->status = Connection::STATUS_BROKEN;
+
+        if (notify) {
+            // Notify other system components.
+            onDispatchCycleBrokenLocked(currentTime, connection);
+        }
+    }
+}
+
+void InputDispatcher::drainDispatchQueue(Queue<DispatchEntry>* queue) {
+    while (!queue->isEmpty()) {
+        DispatchEntry* dispatchEntry = queue->dequeueAtHead();
+        releaseDispatchEntry(dispatchEntry);
+    }
+}
+
+void InputDispatcher::releaseDispatchEntry(DispatchEntry* dispatchEntry) {
+    if (dispatchEntry->hasForegroundTarget()) {
+        decrementPendingForegroundDispatches(dispatchEntry->eventEntry);
+    }
+    delete dispatchEntry;
+}
+
+int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
+    InputDispatcher* d = static_cast<InputDispatcher*>(data);
+
+    { // acquire lock
+        std::scoped_lock _l(d->mLock);
+
+        ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);
+        if (connectionIndex < 0) {
+            ALOGE("Received spurious receive callback for unknown input channel.  "
+                    "fd=%d, events=0x%x", fd, events);
+            return 0; // remove the callback
+        }
+
+        bool notify;
+        sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);
+        if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
+            if (!(events & ALOOPER_EVENT_INPUT)) {
+                ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
+                        "events=0x%x", connection->getInputChannelName().c_str(), events);
+                return 1;
+            }
+
+            nsecs_t currentTime = now();
+            bool gotOne = false;
+            status_t status;
+            for (;;) {
+                uint32_t seq;
+                bool handled;
+                status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
+                if (status) {
+                    break;
+                }
+                d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
+                gotOne = true;
+            }
+            if (gotOne) {
+                d->runCommandsLockedInterruptible();
+                if (status == WOULD_BLOCK) {
+                    return 1;
+                }
+            }
+
+            notify = status != DEAD_OBJECT || !connection->monitor;
+            if (notify) {
+                ALOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",
+                        connection->getInputChannelName().c_str(), status);
+            }
+        } else {
+            // Monitor channels are never explicitly unregistered.
+            // We do it automatically when the remote endpoint is closed so don't warn
+            // about them.
+            notify = !connection->monitor;
+            if (notify) {
+                ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred.  "
+                        "events=0x%x", connection->getInputChannelName().c_str(), events);
+            }
+        }
+
+        // Unregister the channel.
+        d->unregisterInputChannelLocked(connection->inputChannel, notify);
+        return 0; // remove the callback
+    } // release lock
+}
+
+void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked (
+        const CancelationOptions& options) {
+    for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
+        synthesizeCancelationEventsForConnectionLocked(
+                mConnectionsByFd.valueAt(i), options);
+    }
+}
+
+void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked (
+        const CancelationOptions& options) {
+    synthesizeCancelationEventsForMonitorsLocked(options, mGlobalMonitorsByDisplay);
+    synthesizeCancelationEventsForMonitorsLocked(options, mGestureMonitorsByDisplay);
+}
+
+void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked(
+        const CancelationOptions& options,
+        std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) {
+    for (const auto& it : monitorsByDisplay) {
+        const std::vector<Monitor>& monitors = it.second;
+        for (const Monitor& monitor : monitors) {
+            synthesizeCancelationEventsForInputChannelLocked(monitor.inputChannel, options);
+        }
+    }
+}
+
+void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
+        const sp<InputChannel>& channel, const CancelationOptions& options) {
+    ssize_t index = getConnectionIndexLocked(channel);
+    if (index >= 0) {
+        synthesizeCancelationEventsForConnectionLocked(
+                mConnectionsByFd.valueAt(index), options);
+    }
+}
+
+void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
+        const sp<Connection>& connection, const CancelationOptions& options) {
+    if (connection->status == Connection::STATUS_BROKEN) {
+        return;
+    }
+
+    nsecs_t currentTime = now();
+
+    std::vector<EventEntry*> cancelationEvents;
+    connection->inputState.synthesizeCancelationEvents(currentTime,
+            cancelationEvents, options);
+
+    if (!cancelationEvents.empty()) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        ALOGD("channel '%s' ~ Synthesized %zu cancelation events to bring channel back in sync "
+                "with reality: %s, mode=%d.",
+                connection->getInputChannelName().c_str(), cancelationEvents.size(),
+                options.reason, options.mode);
+#endif
+        for (size_t i = 0; i < cancelationEvents.size(); i++) {
+            EventEntry* cancelationEventEntry = cancelationEvents[i];
+            switch (cancelationEventEntry->type) {
+            case EventEntry::TYPE_KEY:
+                logOutboundKeyDetails("cancel - ",
+                        static_cast<KeyEntry*>(cancelationEventEntry));
+                break;
+            case EventEntry::TYPE_MOTION:
+                logOutboundMotionDetails("cancel - ",
+                        static_cast<MotionEntry*>(cancelationEventEntry));
+                break;
+            }
+
+            InputTarget target;
+            sp<InputWindowHandle> windowHandle = getWindowHandleLocked(
+                    connection->inputChannel->getToken());
+            if (windowHandle != nullptr) {
+                const InputWindowInfo* windowInfo = windowHandle->getInfo();
+                target.xOffset = -windowInfo->frameLeft;
+                target.yOffset = -windowInfo->frameTop;
+                target.globalScaleFactor = windowInfo->globalScaleFactor;
+                target.windowXScale = windowInfo->windowXScale;
+                target.windowYScale = windowInfo->windowYScale;
+            } else {
+                target.xOffset = 0;
+                target.yOffset = 0;
+                target.globalScaleFactor = 1.0f;
+            }
+            target.inputChannel = connection->inputChannel;
+            target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
+
+            enqueueDispatchEntryLocked(connection, cancelationEventEntry, // increments ref
+                    &target, InputTarget::FLAG_DISPATCH_AS_IS);
+
+            cancelationEventEntry->release();
+        }
+
+        startDispatchCycleLocked(currentTime, connection);
+    }
+}
+
+InputDispatcher::MotionEntry*
+InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds) {
+    ALOG_ASSERT(pointerIds.value != 0);
+
+    uint32_t splitPointerIndexMap[MAX_POINTERS];
+    PointerProperties splitPointerProperties[MAX_POINTERS];
+    PointerCoords splitPointerCoords[MAX_POINTERS];
+
+    uint32_t originalPointerCount = originalMotionEntry->pointerCount;
+    uint32_t splitPointerCount = 0;
+
+    for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount;
+            originalPointerIndex++) {
+        const PointerProperties& pointerProperties =
+                originalMotionEntry->pointerProperties[originalPointerIndex];
+        uint32_t pointerId = uint32_t(pointerProperties.id);
+        if (pointerIds.hasBit(pointerId)) {
+            splitPointerIndexMap[splitPointerCount] = originalPointerIndex;
+            splitPointerProperties[splitPointerCount].copyFrom(pointerProperties);
+            splitPointerCoords[splitPointerCount].copyFrom(
+                    originalMotionEntry->pointerCoords[originalPointerIndex]);
+            splitPointerCount += 1;
+        }
+    }
+
+    if (splitPointerCount != pointerIds.count()) {
+        // This is bad.  We are missing some of the pointers that we expected to deliver.
+        // Most likely this indicates that we received an ACTION_MOVE events that has
+        // different pointer ids than we expected based on the previous ACTION_DOWN
+        // or ACTION_POINTER_DOWN events that caused us to decide to split the pointers
+        // in this way.
+        ALOGW("Dropping split motion event because the pointer count is %d but "
+                "we expected there to be %d pointers.  This probably means we received "
+                "a broken sequence of pointer ids from the input device.",
+                splitPointerCount, pointerIds.count());
+        return nullptr;
+    }
+
+    int32_t action = originalMotionEntry->action;
+    int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
+    if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
+            || maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
+        int32_t originalPointerIndex = getMotionEventActionPointerIndex(action);
+        const PointerProperties& pointerProperties =
+                originalMotionEntry->pointerProperties[originalPointerIndex];
+        uint32_t pointerId = uint32_t(pointerProperties.id);
+        if (pointerIds.hasBit(pointerId)) {
+            if (pointerIds.count() == 1) {
+                // The first/last pointer went down/up.
+                action = maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
+                        ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
+            } else {
+                // A secondary pointer went down/up.
+                uint32_t splitPointerIndex = 0;
+                while (pointerId != uint32_t(splitPointerProperties[splitPointerIndex].id)) {
+                    splitPointerIndex += 1;
+                }
+                action = maskedAction | (splitPointerIndex
+                        << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+            }
+        } else {
+            // An unrelated pointer changed.
+            action = AMOTION_EVENT_ACTION_MOVE;
+        }
+    }
+
+    MotionEntry* splitMotionEntry = new MotionEntry(
+            originalMotionEntry->sequenceNum,
+            originalMotionEntry->eventTime,
+            originalMotionEntry->deviceId,
+            originalMotionEntry->source,
+            originalMotionEntry->displayId,
+            originalMotionEntry->policyFlags,
+            action,
+            originalMotionEntry->actionButton,
+            originalMotionEntry->flags,
+            originalMotionEntry->metaState,
+            originalMotionEntry->buttonState,
+            originalMotionEntry->classification,
+            originalMotionEntry->edgeFlags,
+            originalMotionEntry->xPrecision,
+            originalMotionEntry->yPrecision,
+            originalMotionEntry->downTime,
+            splitPointerCount, splitPointerProperties, splitPointerCoords, 0, 0);
+
+    if (originalMotionEntry->injectionState) {
+        splitMotionEntry->injectionState = originalMotionEntry->injectionState;
+        splitMotionEntry->injectionState->refCount += 1;
+    }
+
+    return splitMotionEntry;
+}
+
+void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+    ALOGD("notifyConfigurationChanged - eventTime=%" PRId64, args->eventTime);
+#endif
+
+    bool needWake;
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+
+        ConfigurationChangedEntry* newEntry =
+                new ConfigurationChangedEntry(args->sequenceNum, args->eventTime);
+        needWake = enqueueInboundEventLocked(newEntry);
+    } // release lock
+
+    if (needWake) {
+        mLooper->wake();
+    }
+}
+
+/**
+ * If one of the meta shortcuts is detected, process them here:
+ *     Meta + Backspace -> generate BACK
+ *     Meta + Enter -> generate HOME
+ * This will potentially overwrite keyCode and metaState.
+ */
+void InputDispatcher::accelerateMetaShortcuts(const int32_t deviceId, const int32_t action,
+        int32_t& keyCode, int32_t& metaState) {
+    if (metaState & AMETA_META_ON && action == AKEY_EVENT_ACTION_DOWN) {
+        int32_t newKeyCode = AKEYCODE_UNKNOWN;
+        if (keyCode == AKEYCODE_DEL) {
+            newKeyCode = AKEYCODE_BACK;
+        } else if (keyCode == AKEYCODE_ENTER) {
+            newKeyCode = AKEYCODE_HOME;
+        }
+        if (newKeyCode != AKEYCODE_UNKNOWN) {
+            std::scoped_lock _l(mLock);
+            struct KeyReplacement replacement = {keyCode, deviceId};
+            mReplacedKeys.add(replacement, newKeyCode);
+            keyCode = newKeyCode;
+            metaState &= ~(AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON);
+        }
+    } else if (action == AKEY_EVENT_ACTION_UP) {
+        // In order to maintain a consistent stream of up and down events, check to see if the key
+        // going up is one we've replaced in a down event and haven't yet replaced in an up event,
+        // even if the modifier was released between the down and the up events.
+        std::scoped_lock _l(mLock);
+        struct KeyReplacement replacement = {keyCode, deviceId};
+        ssize_t index = mReplacedKeys.indexOfKey(replacement);
+        if (index >= 0) {
+            keyCode = mReplacedKeys.valueAt(index);
+            mReplacedKeys.removeItemsAt(index);
+            metaState &= ~(AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON);
+        }
+    }
+}
+
+void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+    ALOGD("notifyKey - eventTime=%" PRId64
+            ", deviceId=%d, source=0x%x, displayId=%" PRId32 "policyFlags=0x%x, action=0x%x, "
+            "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%" PRId64,
+            args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
+            args->action, args->flags, args->keyCode, args->scanCode,
+            args->metaState, args->downTime);
+#endif
+    if (!validateKeyEvent(args->action)) {
+        return;
+    }
+
+    uint32_t policyFlags = args->policyFlags;
+    int32_t flags = args->flags;
+    int32_t metaState = args->metaState;
+    // InputDispatcher tracks and generates key repeats on behalf of
+    // whatever notifies it, so repeatCount should always be set to 0
+    constexpr int32_t repeatCount = 0;
+    if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
+        policyFlags |= POLICY_FLAG_VIRTUAL;
+        flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
+    }
+    if (policyFlags & POLICY_FLAG_FUNCTION) {
+        metaState |= AMETA_FUNCTION_ON;
+    }
+
+    policyFlags |= POLICY_FLAG_TRUSTED;
+
+    int32_t keyCode = args->keyCode;
+    accelerateMetaShortcuts(args->deviceId, args->action, keyCode, metaState);
+
+    KeyEvent event;
+    event.initialize(args->deviceId, args->source, args->displayId, args->action,
+            flags, keyCode, args->scanCode, metaState, repeatCount,
+            args->downTime, args->eventTime);
+
+    android::base::Timer t;
+    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
+    if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
+        ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
+                std::to_string(t.duration().count()).c_str());
+    }
+
+    bool needWake;
+    { // acquire lock
+        mLock.lock();
+
+        if (shouldSendKeyToInputFilterLocked(args)) {
+            mLock.unlock();
+
+            policyFlags |= POLICY_FLAG_FILTERED;
+            if (!mPolicy->filterInputEvent(&event, policyFlags)) {
+                return; // event was consumed by the filter
+            }
+
+            mLock.lock();
+        }
+
+        KeyEntry* newEntry = new KeyEntry(args->sequenceNum, args->eventTime,
+                args->deviceId, args->source, args->displayId, policyFlags,
+                args->action, flags, keyCode, args->scanCode,
+                metaState, repeatCount, args->downTime);
+
+        needWake = enqueueInboundEventLocked(newEntry);
+        mLock.unlock();
+    } // release lock
+
+    if (needWake) {
+        mLooper->wake();
+    }
+}
+
+bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) {
+    return mInputFilterEnabled;
+}
+
+void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+    ALOGD("notifyMotion - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32
+            ", policyFlags=0x%x, "
+            "action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x,"
+            "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
+            args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
+            args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
+            args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime);
+    for (uint32_t i = 0; i < args->pointerCount; i++) {
+        ALOGD("  Pointer %d: id=%d, toolType=%d, "
+                "x=%f, y=%f, pressure=%f, size=%f, "
+                "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
+                "orientation=%f",
+                i, args->pointerProperties[i].id,
+                args->pointerProperties[i].toolType,
+                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
+                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
+                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
+                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
+                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
+                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
+                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
+                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
+                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
+    }
+#endif
+    if (!validateMotionEvent(args->action, args->actionButton,
+                args->pointerCount, args->pointerProperties)) {
+        return;
+    }
+
+    uint32_t policyFlags = args->policyFlags;
+    policyFlags |= POLICY_FLAG_TRUSTED;
+
+    android::base::Timer t;
+    mPolicy->interceptMotionBeforeQueueing(args->displayId, args->eventTime, /*byref*/ policyFlags);
+    if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
+        ALOGW("Excessive delay in interceptMotionBeforeQueueing; took %s ms",
+                std::to_string(t.duration().count()).c_str());
+    }
+
+    bool needWake;
+    { // acquire lock
+        mLock.lock();
+
+        if (shouldSendMotionToInputFilterLocked(args)) {
+            mLock.unlock();
+
+            MotionEvent event;
+            event.initialize(args->deviceId, args->source, args->displayId,
+                    args->action, args->actionButton,
+                    args->flags, args->edgeFlags, args->metaState, args->buttonState,
+                    args->classification, 0, 0, args->xPrecision, args->yPrecision,
+                    args->downTime, args->eventTime,
+                    args->pointerCount, args->pointerProperties, args->pointerCoords);
+
+            policyFlags |= POLICY_FLAG_FILTERED;
+            if (!mPolicy->filterInputEvent(&event, policyFlags)) {
+                return; // event was consumed by the filter
+            }
+
+            mLock.lock();
+        }
+
+        // Just enqueue a new motion event.
+        MotionEntry* newEntry = new MotionEntry(args->sequenceNum, args->eventTime,
+                args->deviceId, args->source, args->displayId, policyFlags,
+                args->action, args->actionButton, args->flags,
+                args->metaState, args->buttonState, args->classification,
+                args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
+                args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
+
+        needWake = enqueueInboundEventLocked(newEntry);
+        mLock.unlock();
+    } // release lock
+
+    if (needWake) {
+        mLooper->wake();
+    }
+}
+
+bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) {
+    return mInputFilterEnabled;
+}
+
+void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+    ALOGD("notifySwitch - eventTime=%" PRId64 ", policyFlags=0x%x, switchValues=0x%08x, "
+            "switchMask=0x%08x",
+            args->eventTime, args->policyFlags, args->switchValues, args->switchMask);
+#endif
+
+    uint32_t policyFlags = args->policyFlags;
+    policyFlags |= POLICY_FLAG_TRUSTED;
+    mPolicy->notifySwitch(args->eventTime,
+            args->switchValues, args->switchMask, policyFlags);
+}
+
+void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+    ALOGD("notifyDeviceReset - eventTime=%" PRId64 ", deviceId=%d",
+            args->eventTime, args->deviceId);
+#endif
+
+    bool needWake;
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+
+        DeviceResetEntry* newEntry =
+                new DeviceResetEntry(args->sequenceNum, args->eventTime, args->deviceId);
+        needWake = enqueueInboundEventLocked(newEntry);
+    } // release lock
+
+    if (needWake) {
+        mLooper->wake();
+    }
+}
+
+int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
+        int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
+        uint32_t policyFlags) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+    ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
+            "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x",
+            event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags);
+#endif
+
+    nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
+
+    policyFlags |= POLICY_FLAG_INJECTED;
+    if (hasInjectionPermission(injectorPid, injectorUid)) {
+        policyFlags |= POLICY_FLAG_TRUSTED;
+    }
+
+    EventEntry* firstInjectedEntry;
+    EventEntry* lastInjectedEntry;
+    switch (event->getType()) {
+    case AINPUT_EVENT_TYPE_KEY: {
+        KeyEvent keyEvent;
+        keyEvent.initialize(*static_cast<const KeyEvent*>(event));
+        int32_t action = keyEvent.getAction();
+        if (! validateKeyEvent(action)) {
+            return INPUT_EVENT_INJECTION_FAILED;
+        }
+
+        int32_t flags = keyEvent.getFlags();
+        int32_t keyCode = keyEvent.getKeyCode();
+        int32_t metaState = keyEvent.getMetaState();
+        accelerateMetaShortcuts(keyEvent.getDeviceId(), action,
+                /*byref*/ keyCode, /*byref*/ metaState);
+        keyEvent.initialize(keyEvent.getDeviceId(), keyEvent.getSource(), keyEvent.getDisplayId(),
+            action, flags, keyCode, keyEvent.getScanCode(), metaState, keyEvent.getRepeatCount(),
+            keyEvent.getDownTime(), keyEvent.getEventTime());
+
+        if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) {
+            policyFlags |= POLICY_FLAG_VIRTUAL;
+        }
+
+        if (!(policyFlags & POLICY_FLAG_FILTERED)) {
+            android::base::Timer t;
+            mPolicy->interceptKeyBeforeQueueing(&keyEvent, /*byref*/ policyFlags);
+            if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
+                ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
+                        std::to_string(t.duration().count()).c_str());
+            }
+        }
+
+        mLock.lock();
+        firstInjectedEntry = new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, keyEvent.getEventTime(),
+                keyEvent.getDeviceId(), keyEvent.getSource(), keyEvent.getDisplayId(),
+                policyFlags, action, flags,
+                keyEvent.getKeyCode(), keyEvent.getScanCode(), keyEvent.getMetaState(),
+                keyEvent.getRepeatCount(), keyEvent.getDownTime());
+        lastInjectedEntry = firstInjectedEntry;
+        break;
+    }
+
+    case AINPUT_EVENT_TYPE_MOTION: {
+        const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
+        int32_t action = motionEvent->getAction();
+        size_t pointerCount = motionEvent->getPointerCount();
+        const PointerProperties* pointerProperties = motionEvent->getPointerProperties();
+        int32_t actionButton = motionEvent->getActionButton();
+        int32_t displayId = motionEvent->getDisplayId();
+        if (! validateMotionEvent(action, actionButton, pointerCount, pointerProperties)) {
+            return INPUT_EVENT_INJECTION_FAILED;
+        }
+
+        if (!(policyFlags & POLICY_FLAG_FILTERED)) {
+            nsecs_t eventTime = motionEvent->getEventTime();
+            android::base::Timer t;
+            mPolicy->interceptMotionBeforeQueueing(displayId, eventTime, /*byref*/ policyFlags);
+            if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
+                ALOGW("Excessive delay in interceptMotionBeforeQueueing; took %s ms",
+                        std::to_string(t.duration().count()).c_str());
+            }
+        }
+
+        mLock.lock();
+        const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
+        const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
+        firstInjectedEntry = new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, *sampleEventTimes,
+                motionEvent->getDeviceId(), motionEvent->getSource(), motionEvent->getDisplayId(),
+                policyFlags,
+                action, actionButton, motionEvent->getFlags(),
+                motionEvent->getMetaState(), motionEvent->getButtonState(),
+                motionEvent->getClassification(), motionEvent->getEdgeFlags(),
+                motionEvent->getXPrecision(), motionEvent->getYPrecision(),
+                motionEvent->getDownTime(),
+                uint32_t(pointerCount), pointerProperties, samplePointerCoords,
+                motionEvent->getXOffset(), motionEvent->getYOffset());
+        lastInjectedEntry = firstInjectedEntry;
+        for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
+            sampleEventTimes += 1;
+            samplePointerCoords += pointerCount;
+            MotionEntry* nextInjectedEntry = new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM,
+                    *sampleEventTimes,
+                    motionEvent->getDeviceId(), motionEvent->getSource(),
+                    motionEvent->getDisplayId(), policyFlags,
+                    action, actionButton, motionEvent->getFlags(),
+                    motionEvent->getMetaState(), motionEvent->getButtonState(),
+                    motionEvent->getClassification(), motionEvent->getEdgeFlags(),
+                    motionEvent->getXPrecision(), motionEvent->getYPrecision(),
+                    motionEvent->getDownTime(),
+                    uint32_t(pointerCount), pointerProperties, samplePointerCoords,
+                    motionEvent->getXOffset(), motionEvent->getYOffset());
+            lastInjectedEntry->next = nextInjectedEntry;
+            lastInjectedEntry = nextInjectedEntry;
+        }
+        break;
+    }
+
+    default:
+        ALOGW("Cannot inject event of type %d", event->getType());
+        return INPUT_EVENT_INJECTION_FAILED;
+    }
+
+    InjectionState* injectionState = new InjectionState(injectorPid, injectorUid);
+    if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
+        injectionState->injectionIsAsync = true;
+    }
+
+    injectionState->refCount += 1;
+    lastInjectedEntry->injectionState = injectionState;
+
+    bool needWake = false;
+    for (EventEntry* entry = firstInjectedEntry; entry != nullptr; ) {
+        EventEntry* nextEntry = entry->next;
+        needWake |= enqueueInboundEventLocked(entry);
+        entry = nextEntry;
+    }
+
+    mLock.unlock();
+
+    if (needWake) {
+        mLooper->wake();
+    }
+
+    int32_t injectionResult;
+    { // acquire lock
+        std::unique_lock _l(mLock);
+
+        if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
+            injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
+        } else {
+            for (;;) {
+                injectionResult = injectionState->injectionResult;
+                if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
+                    break;
+                }
+
+                nsecs_t remainingTimeout = endTime - now();
+                if (remainingTimeout <= 0) {
+#if DEBUG_INJECTION
+                    ALOGD("injectInputEvent - Timed out waiting for injection result "
+                            "to become available.");
+#endif
+                    injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
+                    break;
+                }
+
+                mInjectionResultAvailable.wait_for(_l, std::chrono::nanoseconds(remainingTimeout));
+            }
+
+            if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
+                    && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
+                while (injectionState->pendingForegroundDispatches != 0) {
+#if DEBUG_INJECTION
+                    ALOGD("injectInputEvent - Waiting for %d pending foreground dispatches.",
+                            injectionState->pendingForegroundDispatches);
+#endif
+                    nsecs_t remainingTimeout = endTime - now();
+                    if (remainingTimeout <= 0) {
+#if DEBUG_INJECTION
+                    ALOGD("injectInputEvent - Timed out waiting for pending foreground "
+                            "dispatches to finish.");
+#endif
+                        injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
+                        break;
+                    }
+
+                    mInjectionSyncFinished.wait_for(_l, std::chrono::nanoseconds(remainingTimeout));
+                }
+            }
+        }
+
+        injectionState->release();
+    } // release lock
+
+#if DEBUG_INJECTION
+    ALOGD("injectInputEvent - Finished with result %d.  "
+            "injectorPid=%d, injectorUid=%d",
+            injectionResult, injectorPid, injectorUid);
+#endif
+
+    return injectionResult;
+}
+
+bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
+    return injectorUid == 0
+            || mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
+}
+
+void InputDispatcher::setInjectionResult(EventEntry* entry, int32_t injectionResult) {
+    InjectionState* injectionState = entry->injectionState;
+    if (injectionState) {
+#if DEBUG_INJECTION
+        ALOGD("Setting input event injection result to %d.  "
+                "injectorPid=%d, injectorUid=%d",
+                 injectionResult, injectionState->injectorPid, injectionState->injectorUid);
+#endif
+
+        if (injectionState->injectionIsAsync
+                && !(entry->policyFlags & POLICY_FLAG_FILTERED)) {
+            // Log the outcome since the injector did not wait for the injection result.
+            switch (injectionResult) {
+            case INPUT_EVENT_INJECTION_SUCCEEDED:
+                ALOGV("Asynchronous input event injection succeeded.");
+                break;
+            case INPUT_EVENT_INJECTION_FAILED:
+                ALOGW("Asynchronous input event injection failed.");
+                break;
+            case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
+                ALOGW("Asynchronous input event injection permission denied.");
+                break;
+            case INPUT_EVENT_INJECTION_TIMED_OUT:
+                ALOGW("Asynchronous input event injection timed out.");
+                break;
+            }
+        }
+
+        injectionState->injectionResult = injectionResult;
+        mInjectionResultAvailable.notify_all();
+    }
+}
+
+void InputDispatcher::incrementPendingForegroundDispatches(EventEntry* entry) {
+    InjectionState* injectionState = entry->injectionState;
+    if (injectionState) {
+        injectionState->pendingForegroundDispatches += 1;
+    }
+}
+
+void InputDispatcher::decrementPendingForegroundDispatches(EventEntry* entry) {
+    InjectionState* injectionState = entry->injectionState;
+    if (injectionState) {
+        injectionState->pendingForegroundDispatches -= 1;
+
+        if (injectionState->pendingForegroundDispatches == 0) {
+            mInjectionSyncFinished.notify_all();
+        }
+    }
+}
+
+std::vector<sp<InputWindowHandle>> InputDispatcher::getWindowHandlesLocked(
+        int32_t displayId) const {
+    std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>>::const_iterator it =
+            mWindowHandlesByDisplay.find(displayId);
+    if(it != mWindowHandlesByDisplay.end()) {
+        return it->second;
+    }
+
+    // Return an empty one if nothing found.
+    return std::vector<sp<InputWindowHandle>>();
+}
+
+sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
+        const sp<IBinder>& windowHandleToken) const {
+    for (auto& it : mWindowHandlesByDisplay) {
+        const std::vector<sp<InputWindowHandle>> windowHandles = it.second;
+        for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
+            if (windowHandle->getToken() == windowHandleToken) {
+                return windowHandle;
+            }
+        }
+    }
+    return nullptr;
+}
+
+bool InputDispatcher::hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const {
+    for (auto& it : mWindowHandlesByDisplay) {
+        const std::vector<sp<InputWindowHandle>> windowHandles = it.second;
+        for (const sp<InputWindowHandle>& handle : windowHandles) {
+            if (handle->getToken() == windowHandle->getToken()) {
+                if (windowHandle->getInfo()->displayId != it.first) {
+                    ALOGE("Found window %s in display %" PRId32
+                            ", but it should belong to display %" PRId32,
+                            windowHandle->getName().c_str(), it.first,
+                            windowHandle->getInfo()->displayId);
+                }
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+sp<InputChannel> InputDispatcher::getInputChannelLocked(const sp<IBinder>& token) const {
+    size_t count = mInputChannelsByToken.count(token);
+    if (count == 0) {
+        return nullptr;
+    }
+    return mInputChannelsByToken.at(token);
+}
+
+/**
+ * Called from InputManagerService, update window handle list by displayId that can receive input.
+ * A window handle contains information about InputChannel, Touch Region, Types, Focused,...
+ * If set an empty list, remove all handles from the specific display.
+ * For focused handle, check if need to change and send a cancel event to previous one.
+ * For removed handle, check if need to send a cancel event if already in touch.
+ */
+void InputDispatcher::setInputWindows(const std::vector<sp<InputWindowHandle>>& inputWindowHandles,
+        int32_t displayId, const sp<ISetInputWindowsListener>& setInputWindowsListener) {
+#if DEBUG_FOCUS
+    ALOGD("setInputWindows displayId=%" PRId32, displayId);
+#endif
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+
+        // Copy old handles for release if they are no longer present.
+        const std::vector<sp<InputWindowHandle>> oldWindowHandles =
+                getWindowHandlesLocked(displayId);
+
+        sp<InputWindowHandle> newFocusedWindowHandle = nullptr;
+        bool foundHoveredWindow = false;
+
+        if (inputWindowHandles.empty()) {
+            // Remove all handles on a display if there are no windows left.
+            mWindowHandlesByDisplay.erase(displayId);
+        } else {
+            // Since we compare the pointer of input window handles across window updates, we need
+            // to make sure the handle object for the same window stays unchanged across updates.
+            const std::vector<sp<InputWindowHandle>>& oldHandles =
+                    mWindowHandlesByDisplay[displayId];
+            std::unordered_map<sp<IBinder>, sp<InputWindowHandle>, IBinderHash> oldHandlesByTokens;
+            for (const sp<InputWindowHandle>& handle : oldHandles) {
+                oldHandlesByTokens[handle->getToken()] = handle;
+            }
+
+            std::vector<sp<InputWindowHandle>> newHandles;
+            for (const sp<InputWindowHandle>& handle : inputWindowHandles) {
+                if (!handle->updateInfo()) {
+                    // handle no longer valid
+                    continue;
+                }
+                const InputWindowInfo* info = handle->getInfo();
+
+                if ((getInputChannelLocked(handle->getToken()) == nullptr &&
+                     info->portalToDisplayId == ADISPLAY_ID_NONE)) {
+                    const bool noInputChannel =
+                            info->inputFeatures & InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL;
+                    const bool canReceiveInput =
+                            !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_TOUCHABLE) ||
+                            !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_FOCUSABLE);
+                    if (canReceiveInput && !noInputChannel) {
+                        ALOGE("Window handle %s has no registered input channel",
+                              handle->getName().c_str());
+                    }
+                    continue;
+                }
+
+                if (info->displayId != displayId) {
+                    ALOGE("Window %s updated by wrong display %d, should belong to display %d",
+                          handle->getName().c_str(), displayId, info->displayId);
+                    continue;
+                }
+
+                if (oldHandlesByTokens.find(handle->getToken()) != oldHandlesByTokens.end()) {
+                    const sp<InputWindowHandle> oldHandle =
+                            oldHandlesByTokens.at(handle->getToken());
+                    oldHandle->updateFrom(handle);
+                    newHandles.push_back(oldHandle);
+                } else {
+                    newHandles.push_back(handle);
+                }
+            }
+
+            for (const sp<InputWindowHandle>& windowHandle : newHandles) {
+                // Set newFocusedWindowHandle to the top most focused window instead of the last one
+                if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus
+                        && windowHandle->getInfo()->visible) {
+                    newFocusedWindowHandle = windowHandle;
+                }
+                if (windowHandle == mLastHoverWindowHandle) {
+                    foundHoveredWindow = true;
+                }
+            }
+
+            // Insert or replace
+            mWindowHandlesByDisplay[displayId] = newHandles;
+        }
+
+        if (!foundHoveredWindow) {
+            mLastHoverWindowHandle = nullptr;
+        }
+
+        sp<InputWindowHandle> oldFocusedWindowHandle =
+                getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+
+        if (oldFocusedWindowHandle != newFocusedWindowHandle) {
+            if (oldFocusedWindowHandle != nullptr) {
+#if DEBUG_FOCUS
+                ALOGD("Focus left window: %s in display %" PRId32,
+                        oldFocusedWindowHandle->getName().c_str(), displayId);
+#endif
+                sp<InputChannel> focusedInputChannel = getInputChannelLocked(
+                        oldFocusedWindowHandle->getToken());
+                if (focusedInputChannel != nullptr) {
+                    CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
+                            "focus left window");
+                    synthesizeCancelationEventsForInputChannelLocked(
+                            focusedInputChannel, options);
+                }
+                mFocusedWindowHandlesByDisplay.erase(displayId);
+            }
+            if (newFocusedWindowHandle != nullptr) {
+#if DEBUG_FOCUS
+                ALOGD("Focus entered window: %s in display %" PRId32,
+                        newFocusedWindowHandle->getName().c_str(), displayId);
+#endif
+                mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle;
+            }
+
+            if (mFocusedDisplayId == displayId) {
+                onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
+            }
+
+        }
+
+        ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
+        if (stateIndex >= 0) {
+            TouchState& state = mTouchStatesByDisplay.editValueAt(stateIndex);
+            for (size_t i = 0; i < state.windows.size(); ) {
+                TouchedWindow& touchedWindow = state.windows[i];
+                if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
+#if DEBUG_FOCUS
+                    ALOGD("Touched window was removed: %s in display %" PRId32,
+                            touchedWindow.windowHandle->getName().c_str(), displayId);
+#endif
+                    sp<InputChannel> touchedInputChannel =
+                            getInputChannelLocked(touchedWindow.windowHandle->getToken());
+                    if (touchedInputChannel != nullptr) {
+                        CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
+                                "touched window was removed");
+                        synthesizeCancelationEventsForInputChannelLocked(
+                                touchedInputChannel, options);
+                    }
+                    state.windows.erase(state.windows.begin() + i);
+                } else {
+                  ++i;
+                }
+            }
+        }
+
+        // Release information for windows that are no longer present.
+        // This ensures that unused input channels are released promptly.
+        // Otherwise, they might stick around until the window handle is destroyed
+        // which might not happen until the next GC.
+        for (const sp<InputWindowHandle>& oldWindowHandle : oldWindowHandles) {
+            if (!hasWindowHandleLocked(oldWindowHandle)) {
+#if DEBUG_FOCUS
+                ALOGD("Window went away: %s", oldWindowHandle->getName().c_str());
+#endif
+                oldWindowHandle->releaseChannel();
+            }
+        }
+    } // release lock
+
+    // Wake up poll loop since it may need to make new input dispatching choices.
+    mLooper->wake();
+
+    if (setInputWindowsListener) {
+        setInputWindowsListener->onSetInputWindowsFinished();
+    }
+}
+
+void InputDispatcher::setFocusedApplication(
+        int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) {
+#if DEBUG_FOCUS
+    ALOGD("setFocusedApplication displayId=%" PRId32, displayId);
+#endif
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+
+        sp<InputApplicationHandle> oldFocusedApplicationHandle =
+                getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
+        if (inputApplicationHandle != nullptr && inputApplicationHandle->updateInfo()) {
+            if (oldFocusedApplicationHandle != inputApplicationHandle) {
+                if (oldFocusedApplicationHandle != nullptr) {
+                    resetANRTimeoutsLocked();
+                }
+                mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
+            }
+        } else if (oldFocusedApplicationHandle != nullptr) {
+            resetANRTimeoutsLocked();
+            oldFocusedApplicationHandle.clear();
+            mFocusedApplicationHandlesByDisplay.erase(displayId);
+        }
+
+#if DEBUG_FOCUS
+        //logDispatchStateLocked();
+#endif
+    } // release lock
+
+    // Wake up poll loop since it may need to make new input dispatching choices.
+    mLooper->wake();
+}
+
+/**
+ * Sets the focused display, which is responsible for receiving focus-dispatched input events where
+ * the display not specified.
+ *
+ * We track any unreleased events for each window. If a window loses the ability to receive the
+ * released event, we will send a cancel event to it. So when the focused display is changed, we
+ * cancel all the unreleased display-unspecified events for the focused window on the old focused
+ * display. The display-specified events won't be affected.
+ */
+void InputDispatcher::setFocusedDisplay(int32_t displayId) {
+#if DEBUG_FOCUS
+    ALOGD("setFocusedDisplay displayId=%" PRId32, displayId);
+#endif
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+
+        if (mFocusedDisplayId != displayId) {
+            sp<InputWindowHandle> oldFocusedWindowHandle =
+                    getValueByKey(mFocusedWindowHandlesByDisplay, mFocusedDisplayId);
+            if (oldFocusedWindowHandle != nullptr) {
+                sp<InputChannel> inputChannel =
+                    getInputChannelLocked(oldFocusedWindowHandle->getToken());
+                if (inputChannel != nullptr) {
+                    CancelationOptions options(
+                            CancelationOptions::CANCEL_NON_POINTER_EVENTS,
+                            "The display which contains this window no longer has focus.");
+                    options.displayId = ADISPLAY_ID_NONE;
+                    synthesizeCancelationEventsForInputChannelLocked(inputChannel, options);
+                }
+            }
+            mFocusedDisplayId = displayId;
+
+            // Sanity check
+            sp<InputWindowHandle> newFocusedWindowHandle =
+                    getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+            onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
+
+            if (newFocusedWindowHandle == nullptr) {
+                ALOGW("Focused display #%" PRId32 " does not have a focused window.", displayId);
+                if (!mFocusedWindowHandlesByDisplay.empty()) {
+                    ALOGE("But another display has a focused window:");
+                    for (auto& it : mFocusedWindowHandlesByDisplay) {
+                        const int32_t displayId = it.first;
+                        const sp<InputWindowHandle>& windowHandle = it.second;
+                        ALOGE("Display #%" PRId32 " has focused window: '%s'\n",
+                                displayId, windowHandle->getName().c_str());
+                    }
+                }
+            }
+        }
+
+#if DEBUG_FOCUS
+        logDispatchStateLocked();
+#endif
+    } // release lock
+
+    // Wake up poll loop since it may need to make new input dispatching choices.
+    mLooper->wake();
+}
+
+void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
+#if DEBUG_FOCUS
+    ALOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
+#endif
+
+    bool changed;
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+
+        if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
+            if (mDispatchFrozen && !frozen) {
+                resetANRTimeoutsLocked();
+            }
+
+            if (mDispatchEnabled && !enabled) {
+                resetAndDropEverythingLocked("dispatcher is being disabled");
+            }
+
+            mDispatchEnabled = enabled;
+            mDispatchFrozen = frozen;
+            changed = true;
+        } else {
+            changed = false;
+        }
+
+#if DEBUG_FOCUS
+        logDispatchStateLocked();
+#endif
+    } // release lock
+
+    if (changed) {
+        // Wake up poll loop since it may need to make new input dispatching choices.
+        mLooper->wake();
+    }
+}
+
+void InputDispatcher::setInputFilterEnabled(bool enabled) {
+#if DEBUG_FOCUS
+    ALOGD("setInputFilterEnabled: enabled=%d", enabled);
+#endif
+
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+
+        if (mInputFilterEnabled == enabled) {
+            return;
+        }
+
+        mInputFilterEnabled = enabled;
+        resetAndDropEverythingLocked("input filter is being enabled or disabled");
+    } // release lock
+
+    // Wake up poll loop since there might be work to do to drop everything.
+    mLooper->wake();
+}
+
+bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) {
+    if (fromToken == toToken) {
+#if DEBUG_FOCUS
+        ALOGD("Trivial transfer to same window.");
+#endif
+        return true;
+    }
+
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+
+        sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromToken);
+        sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toToken);
+        if (fromWindowHandle == nullptr || toWindowHandle == nullptr) {
+            ALOGW("Cannot transfer focus because from or to window not found.");
+            return false;
+        }
+#if DEBUG_FOCUS
+        ALOGD("transferTouchFocus: fromWindowHandle=%s, toWindowHandle=%s",
+            fromWindowHandle->getName().c_str(), toWindowHandle->getName().c_str());
+#endif
+        if (fromWindowHandle->getInfo()->displayId != toWindowHandle->getInfo()->displayId) {
+#if DEBUG_FOCUS
+            ALOGD("Cannot transfer focus because windows are on different displays.");
+#endif
+            return false;
+        }
+
+        bool found = false;
+        for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) {
+            TouchState& state = mTouchStatesByDisplay.editValueAt(d);
+            for (size_t i = 0; i < state.windows.size(); i++) {
+                const TouchedWindow& touchedWindow = state.windows[i];
+                if (touchedWindow.windowHandle == fromWindowHandle) {
+                    int32_t oldTargetFlags = touchedWindow.targetFlags;
+                    BitSet32 pointerIds = touchedWindow.pointerIds;
+
+                    state.windows.erase(state.windows.begin() + i);
+
+                    int32_t newTargetFlags = oldTargetFlags
+                            & (InputTarget::FLAG_FOREGROUND
+                                    | InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS);
+                    state.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds);
+
+                    found = true;
+                    goto Found;
+                }
+            }
+        }
+Found:
+
+        if (! found) {
+#if DEBUG_FOCUS
+            ALOGD("Focus transfer failed because from window did not have focus.");
+#endif
+            return false;
+        }
+
+
+        sp<InputChannel> fromChannel = getInputChannelLocked(fromToken);
+        sp<InputChannel> toChannel = getInputChannelLocked(toToken);
+        ssize_t fromConnectionIndex = getConnectionIndexLocked(fromChannel);
+        ssize_t toConnectionIndex = getConnectionIndexLocked(toChannel);
+        if (fromConnectionIndex >= 0 && toConnectionIndex >= 0) {
+            sp<Connection> fromConnection = mConnectionsByFd.valueAt(fromConnectionIndex);
+            sp<Connection> toConnection = mConnectionsByFd.valueAt(toConnectionIndex);
+
+            fromConnection->inputState.copyPointerStateTo(toConnection->inputState);
+            CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
+                    "transferring touch focus from this window to another window");
+            synthesizeCancelationEventsForConnectionLocked(fromConnection, options);
+        }
+
+#if DEBUG_FOCUS
+        logDispatchStateLocked();
+#endif
+    } // release lock
+
+    // Wake up poll loop since it may need to make new input dispatching choices.
+    mLooper->wake();
+    return true;
+}
+
+void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
+#if DEBUG_FOCUS
+    ALOGD("Resetting and dropping all events (%s).", reason);
+#endif
+
+    CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS, reason);
+    synthesizeCancelationEventsForAllConnectionsLocked(options);
+
+    resetKeyRepeatLocked();
+    releasePendingEventLocked();
+    drainInboundQueueLocked();
+    resetANRTimeoutsLocked();
+
+    mTouchStatesByDisplay.clear();
+    mLastHoverWindowHandle.clear();
+    mReplacedKeys.clear();
+}
+
+void InputDispatcher::logDispatchStateLocked() {
+    std::string dump;
+    dumpDispatchStateLocked(dump);
+
+    std::istringstream stream(dump);
+    std::string line;
+
+    while (std::getline(stream, line, '\n')) {
+        ALOGD("%s", line.c_str());
+    }
+}
+
+void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
+    dump += StringPrintf(INDENT "DispatchEnabled: %s\n", toString(mDispatchEnabled));
+    dump += StringPrintf(INDENT "DispatchFrozen: %s\n", toString(mDispatchFrozen));
+    dump += StringPrintf(INDENT "InputFilterEnabled: %s\n", toString(mInputFilterEnabled));
+    dump += StringPrintf(INDENT "FocusedDisplayId: %" PRId32 "\n", mFocusedDisplayId);
+
+    if (!mFocusedApplicationHandlesByDisplay.empty()) {
+        dump += StringPrintf(INDENT "FocusedApplications:\n");
+        for (auto& it : mFocusedApplicationHandlesByDisplay) {
+            const int32_t displayId = it.first;
+            const sp<InputApplicationHandle>& applicationHandle = it.second;
+            dump += StringPrintf(
+                    INDENT2 "displayId=%" PRId32 ", name='%s', dispatchingTimeout=%0.3fms\n",
+                    displayId,
+                    applicationHandle->getName().c_str(),
+                    applicationHandle->getDispatchingTimeout(
+                            DEFAULT_INPUT_DISPATCHING_TIMEOUT) / 1000000.0);
+        }
+    } else {
+        dump += StringPrintf(INDENT "FocusedApplications: <none>\n");
+    }
+
+    if (!mFocusedWindowHandlesByDisplay.empty()) {
+        dump += StringPrintf(INDENT "FocusedWindows:\n");
+        for (auto& it : mFocusedWindowHandlesByDisplay) {
+            const int32_t displayId = it.first;
+            const sp<InputWindowHandle>& windowHandle = it.second;
+            dump += StringPrintf(INDENT2 "displayId=%" PRId32 ", name='%s'\n",
+                    displayId, windowHandle->getName().c_str());
+        }
+    } else {
+        dump += StringPrintf(INDENT "FocusedWindows: <none>\n");
+    }
+
+    if (!mTouchStatesByDisplay.isEmpty()) {
+        dump += StringPrintf(INDENT "TouchStatesByDisplay:\n");
+        for (size_t i = 0; i < mTouchStatesByDisplay.size(); i++) {
+            const TouchState& state = mTouchStatesByDisplay.valueAt(i);
+            dump += StringPrintf(INDENT2 "%d: down=%s, split=%s, deviceId=%d, source=0x%08x\n",
+                    state.displayId, toString(state.down), toString(state.split),
+                    state.deviceId, state.source);
+            if (!state.windows.empty()) {
+                dump += INDENT3 "Windows:\n";
+                for (size_t i = 0; i < state.windows.size(); i++) {
+                    const TouchedWindow& touchedWindow = state.windows[i];
+                    dump += StringPrintf(INDENT4 "%zu: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
+                            i, touchedWindow.windowHandle->getName().c_str(),
+                            touchedWindow.pointerIds.value,
+                            touchedWindow.targetFlags);
+                }
+            } else {
+                dump += INDENT3 "Windows: <none>\n";
+            }
+            if (!state.portalWindows.empty()) {
+                dump += INDENT3 "Portal windows:\n";
+                for (size_t i = 0; i < state.portalWindows.size(); i++) {
+                    const sp<InputWindowHandle> portalWindowHandle = state.portalWindows[i];
+                    dump += StringPrintf(INDENT4 "%zu: name='%s'\n",
+                            i, portalWindowHandle->getName().c_str());
+                }
+            }
+        }
+    } else {
+        dump += INDENT "TouchStates: <no displays touched>\n";
+    }
+
+    if (!mWindowHandlesByDisplay.empty()) {
+       for (auto& it : mWindowHandlesByDisplay) {
+            const std::vector<sp<InputWindowHandle>> windowHandles = it.second;
+            dump += StringPrintf(INDENT "Display: %" PRId32 "\n", it.first);
+            if (!windowHandles.empty()) {
+                dump += INDENT2 "Windows:\n";
+                for (size_t i = 0; i < windowHandles.size(); i++) {
+                    const sp<InputWindowHandle>& windowHandle = windowHandles[i];
+                    const InputWindowInfo* windowInfo = windowHandle->getInfo();
+
+                    dump += StringPrintf(INDENT3 "%zu: name='%s', displayId=%d, "
+                            "portalToDisplayId=%d, paused=%s, hasFocus=%s, hasWallpaper=%s, "
+                            "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
+                            "frame=[%d,%d][%d,%d], globalScale=%f, windowScale=(%f,%f), "
+                            "touchableRegion=",
+                            i, windowInfo->name.c_str(), windowInfo->displayId,
+                            windowInfo->portalToDisplayId,
+                            toString(windowInfo->paused),
+                            toString(windowInfo->hasFocus),
+                            toString(windowInfo->hasWallpaper),
+                            toString(windowInfo->visible),
+                            toString(windowInfo->canReceiveKeys),
+                            windowInfo->layoutParamsFlags, windowInfo->layoutParamsType,
+                            windowInfo->layer,
+                            windowInfo->frameLeft, windowInfo->frameTop,
+                            windowInfo->frameRight, windowInfo->frameBottom,
+                            windowInfo->globalScaleFactor,
+                            windowInfo->windowXScale, windowInfo->windowYScale);
+                    dumpRegion(dump, windowInfo->touchableRegion);
+                    dump += StringPrintf(", inputFeatures=0x%08x", windowInfo->inputFeatures);
+                    dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
+                            windowInfo->ownerPid, windowInfo->ownerUid,
+                            windowInfo->dispatchingTimeout / 1000000.0);
+                }
+            } else {
+                dump += INDENT2 "Windows: <none>\n";
+            }
+        }
+    } else {
+        dump += INDENT "Displays: <none>\n";
+    }
+
+    if (!mGlobalMonitorsByDisplay.empty() || !mGestureMonitorsByDisplay.empty()) {
+       for (auto& it : mGlobalMonitorsByDisplay) {
+            const std::vector<Monitor>& monitors = it.second;
+            dump += StringPrintf(INDENT "Global monitors in display %" PRId32 ":\n", it.first);
+            dumpMonitors(dump, monitors);
+       }
+       for (auto& it : mGestureMonitorsByDisplay) {
+            const std::vector<Monitor>& monitors = it.second;
+            dump += StringPrintf(INDENT "Gesture monitors in display %" PRId32 ":\n", it.first);
+            dumpMonitors(dump, monitors);
+       }
+    } else {
+        dump += INDENT "Monitors: <none>\n";
+    }
+
+    nsecs_t currentTime = now();
+
+    // Dump recently dispatched or dropped events from oldest to newest.
+    if (!mRecentQueue.isEmpty()) {
+        dump += StringPrintf(INDENT "RecentQueue: length=%u\n", mRecentQueue.count());
+        for (EventEntry* entry = mRecentQueue.head; entry; entry = entry->next) {
+            dump += INDENT2;
+            entry->appendDescription(dump);
+            dump += StringPrintf(", age=%0.1fms\n",
+                    (currentTime - entry->eventTime) * 0.000001f);
+        }
+    } else {
+        dump += INDENT "RecentQueue: <empty>\n";
+    }
+
+    // Dump event currently being dispatched.
+    if (mPendingEvent) {
+        dump += INDENT "PendingEvent:\n";
+        dump += INDENT2;
+        mPendingEvent->appendDescription(dump);
+        dump += StringPrintf(", age=%0.1fms\n",
+                (currentTime - mPendingEvent->eventTime) * 0.000001f);
+    } else {
+        dump += INDENT "PendingEvent: <none>\n";
+    }
+
+    // Dump inbound events from oldest to newest.
+    if (!mInboundQueue.isEmpty()) {
+        dump += StringPrintf(INDENT "InboundQueue: length=%u\n", mInboundQueue.count());
+        for (EventEntry* entry = mInboundQueue.head; entry; entry = entry->next) {
+            dump += INDENT2;
+            entry->appendDescription(dump);
+            dump += StringPrintf(", age=%0.1fms\n",
+                    (currentTime - entry->eventTime) * 0.000001f);
+        }
+    } else {
+        dump += INDENT "InboundQueue: <empty>\n";
+    }
+
+    if (!mReplacedKeys.isEmpty()) {
+        dump += INDENT "ReplacedKeys:\n";
+        for (size_t i = 0; i < mReplacedKeys.size(); i++) {
+            const KeyReplacement& replacement = mReplacedKeys.keyAt(i);
+            int32_t newKeyCode = mReplacedKeys.valueAt(i);
+            dump += StringPrintf(INDENT2 "%zu: originalKeyCode=%d, deviceId=%d, newKeyCode=%d\n",
+                    i, replacement.keyCode, replacement.deviceId, newKeyCode);
+        }
+    } else {
+        dump += INDENT "ReplacedKeys: <empty>\n";
+    }
+
+    if (!mConnectionsByFd.isEmpty()) {
+        dump += INDENT "Connections:\n";
+        for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
+            const sp<Connection>& connection = mConnectionsByFd.valueAt(i);
+            dump += StringPrintf(INDENT2 "%zu: channelName='%s', windowName='%s', "
+                    "status=%s, monitor=%s, inputPublisherBlocked=%s\n",
+                    i, connection->getInputChannelName().c_str(),
+                    connection->getWindowName().c_str(),
+                    connection->getStatusLabel(), toString(connection->monitor),
+                    toString(connection->inputPublisherBlocked));
+
+            if (!connection->outboundQueue.isEmpty()) {
+                dump += StringPrintf(INDENT3 "OutboundQueue: length=%u\n",
+                        connection->outboundQueue.count());
+                for (DispatchEntry* entry = connection->outboundQueue.head; entry;
+                        entry = entry->next) {
+                    dump.append(INDENT4);
+                    entry->eventEntry->appendDescription(dump);
+                    dump += StringPrintf(", targetFlags=0x%08x, resolvedAction=%d, age=%0.1fms\n",
+                            entry->targetFlags, entry->resolvedAction,
+                            (currentTime - entry->eventEntry->eventTime) * 0.000001f);
+                }
+            } else {
+                dump += INDENT3 "OutboundQueue: <empty>\n";
+            }
+
+            if (!connection->waitQueue.isEmpty()) {
+                dump += StringPrintf(INDENT3 "WaitQueue: length=%u\n",
+                        connection->waitQueue.count());
+                for (DispatchEntry* entry = connection->waitQueue.head; entry;
+                        entry = entry->next) {
+                    dump += INDENT4;
+                    entry->eventEntry->appendDescription(dump);
+                    dump += StringPrintf(", targetFlags=0x%08x, resolvedAction=%d, "
+                            "age=%0.1fms, wait=%0.1fms\n",
+                            entry->targetFlags, entry->resolvedAction,
+                            (currentTime - entry->eventEntry->eventTime) * 0.000001f,
+                            (currentTime - entry->deliveryTime) * 0.000001f);
+                }
+            } else {
+                dump += INDENT3 "WaitQueue: <empty>\n";
+            }
+        }
+    } else {
+        dump += INDENT "Connections: <none>\n";
+    }
+
+    if (isAppSwitchPendingLocked()) {
+        dump += StringPrintf(INDENT "AppSwitch: pending, due in %0.1fms\n",
+                (mAppSwitchDueTime - now()) / 1000000.0);
+    } else {
+        dump += INDENT "AppSwitch: not pending\n";
+    }
+
+    dump += INDENT "Configuration:\n";
+    dump += StringPrintf(INDENT2 "KeyRepeatDelay: %0.1fms\n",
+            mConfig.keyRepeatDelay * 0.000001f);
+    dump += StringPrintf(INDENT2 "KeyRepeatTimeout: %0.1fms\n",
+            mConfig.keyRepeatTimeout * 0.000001f);
+}
+
+void InputDispatcher::dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors) {
+    const size_t numMonitors = monitors.size();
+    for (size_t i = 0; i < numMonitors; i++) {
+        const Monitor& monitor = monitors[i];
+        const sp<InputChannel>& channel = monitor.inputChannel;
+        dump += StringPrintf(INDENT2 "%zu: '%s', ", i, channel->getName().c_str());
+        dump += "\n";
+    }
+}
+
+status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
+        int32_t displayId) {
+#if DEBUG_REGISTRATION
+    ALOGD("channel '%s' ~ registerInputChannel - displayId=%" PRId32,
+            inputChannel->getName().c_str(), displayId);
+#endif
+
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+
+        if (getConnectionIndexLocked(inputChannel) >= 0) {
+            ALOGW("Attempted to register already registered input channel '%s'",
+                    inputChannel->getName().c_str());
+            return BAD_VALUE;
+        }
+
+        sp<Connection> connection = new Connection(inputChannel, false /*monitor*/);
+
+        int fd = inputChannel->getFd();
+        mConnectionsByFd.add(fd, connection);
+        mInputChannelsByToken[inputChannel->getToken()] = inputChannel;
+
+        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
+    } // release lock
+
+    // Wake the looper because some connections have changed.
+    mLooper->wake();
+    return OK;
+}
+
+status_t InputDispatcher::registerInputMonitor(const sp<InputChannel>& inputChannel,
+        int32_t displayId, bool isGestureMonitor) {
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+
+        if (displayId < 0) {
+            ALOGW("Attempted to register input monitor without a specified display.");
+            return BAD_VALUE;
+        }
+
+        if (inputChannel->getToken() == nullptr) {
+            ALOGW("Attempted to register input monitor without an identifying token.");
+            return BAD_VALUE;
+        }
+
+        sp<Connection> connection = new Connection(inputChannel, true /*monitor*/);
+
+        const int fd = inputChannel->getFd();
+        mConnectionsByFd.add(fd, connection);
+        mInputChannelsByToken[inputChannel->getToken()] = inputChannel;
+
+        auto& monitorsByDisplay = isGestureMonitor
+                ? mGestureMonitorsByDisplay
+                : mGlobalMonitorsByDisplay;
+        monitorsByDisplay[displayId].emplace_back(inputChannel);
+
+        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
+
+    }
+    // Wake the looper because some connections have changed.
+    mLooper->wake();
+    return OK;
+}
+
+status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
+#if DEBUG_REGISTRATION
+    ALOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().c_str());
+#endif
+
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+
+        status_t status = unregisterInputChannelLocked(inputChannel, false /*notify*/);
+        if (status) {
+            return status;
+        }
+    } // release lock
+
+    // Wake the poll loop because removing the connection may have changed the current
+    // synchronization state.
+    mLooper->wake();
+    return OK;
+}
+
+status_t InputDispatcher::unregisterInputChannelLocked(const sp<InputChannel>& inputChannel,
+        bool notify) {
+    ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
+    if (connectionIndex < 0) {
+        ALOGW("Attempted to unregister already unregistered input channel '%s'",
+                inputChannel->getName().c_str());
+        return BAD_VALUE;
+    }
+
+    sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
+    mConnectionsByFd.removeItemsAt(connectionIndex);
+
+    mInputChannelsByToken.erase(inputChannel->getToken());
+
+    if (connection->monitor) {
+        removeMonitorChannelLocked(inputChannel);
+    }
+
+    mLooper->removeFd(inputChannel->getFd());
+
+    nsecs_t currentTime = now();
+    abortBrokenDispatchCycleLocked(currentTime, connection, notify);
+
+    connection->status = Connection::STATUS_ZOMBIE;
+    return OK;
+}
+
+void InputDispatcher::removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) {
+    removeMonitorChannelLocked(inputChannel, mGlobalMonitorsByDisplay);
+    removeMonitorChannelLocked(inputChannel, mGestureMonitorsByDisplay);
+}
+
+void InputDispatcher::removeMonitorChannelLocked(const sp<InputChannel>& inputChannel,
+        std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) {
+    for (auto it = monitorsByDisplay.begin(); it != monitorsByDisplay.end(); ) {
+        std::vector<Monitor>& monitors = it->second;
+        const size_t numMonitors = monitors.size();
+        for (size_t i = 0; i < numMonitors; i++) {
+             if (monitors[i].inputChannel == inputChannel) {
+                 monitors.erase(monitors.begin() + i);
+                 break;
+             }
+        }
+        if (monitors.empty()) {
+            it = monitorsByDisplay.erase(it);
+        } else {
+            ++it;
+        }
+    }
+}
+
+status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) {
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+        std::optional<int32_t> foundDisplayId = findGestureMonitorDisplayByTokenLocked(token);
+
+        if (!foundDisplayId) {
+            ALOGW("Attempted to pilfer pointers from an un-registered monitor or invalid token");
+            return BAD_VALUE;
+        }
+        int32_t displayId = foundDisplayId.value();
+
+        ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
+        if (stateIndex < 0) {
+            ALOGW("Failed to pilfer pointers: no pointers on display %" PRId32 ".", displayId);
+            return BAD_VALUE;
+        }
+
+        TouchState& state = mTouchStatesByDisplay.editValueAt(stateIndex);
+        std::optional<int32_t> foundDeviceId;
+        for (const TouchedMonitor& touchedMonitor : state.gestureMonitors) {
+            if (touchedMonitor.monitor.inputChannel->getToken() == token) {
+                foundDeviceId = state.deviceId;
+            }
+        }
+        if (!foundDeviceId || !state.down) {
+            ALOGW("Attempted to pilfer points from a monitor without any on-going pointer streams."
+                    " Ignoring.");
+            return BAD_VALUE;
+        }
+        int32_t deviceId = foundDeviceId.value();
+
+        // Send cancel events to all the input channels we're stealing from.
+        CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
+                "gesture monitor stole pointer stream");
+        options.deviceId = deviceId;
+        options.displayId = displayId;
+        for (const TouchedWindow& window : state.windows) {
+            sp<InputChannel> channel = getInputChannelLocked(window.windowHandle->getToken());
+            synthesizeCancelationEventsForInputChannelLocked(channel, options);
+        }
+        // Then clear the current touch state so we stop dispatching to them as well.
+        state.filterNonMonitors();
+    }
+    return OK;
+}
+
+
+std::optional<int32_t> InputDispatcher::findGestureMonitorDisplayByTokenLocked(
+        const sp<IBinder>& token) {
+    for (const auto& it : mGestureMonitorsByDisplay) {
+        const std::vector<Monitor>& monitors = it.second;
+        for (const Monitor& monitor : monitors) {
+            if (monitor.inputChannel->getToken() == token) {
+                return it.first;
+            }
+        }
+    }
+    return std::nullopt;
+}
+
+ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
+    if (inputChannel == nullptr) {
+        return -1;
+    }
+
+    for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
+        sp<Connection> connection = mConnectionsByFd.valueAt(i);
+        if (connection->inputChannel->getToken() == inputChannel->getToken()) {
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+void InputDispatcher::onDispatchCycleFinishedLocked(
+        nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled) {
+    CommandEntry* commandEntry = postCommandLocked(
+            & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
+    commandEntry->connection = connection;
+    commandEntry->eventTime = currentTime;
+    commandEntry->seq = seq;
+    commandEntry->handled = handled;
+}
+
+void InputDispatcher::onDispatchCycleBrokenLocked(
+        nsecs_t currentTime, const sp<Connection>& connection) {
+    ALOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
+            connection->getInputChannelName().c_str());
+
+    CommandEntry* commandEntry = postCommandLocked(
+            & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
+    commandEntry->connection = connection;
+}
+
+void InputDispatcher::onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
+        const sp<InputWindowHandle>& newFocus) {
+    sp<IBinder> oldToken = oldFocus != nullptr ? oldFocus->getToken() : nullptr;
+    sp<IBinder> newToken = newFocus != nullptr ? newFocus->getToken() : nullptr;
+    CommandEntry* commandEntry = postCommandLocked(
+            & InputDispatcher::doNotifyFocusChangedLockedInterruptible);
+    commandEntry->oldToken = oldToken;
+    commandEntry->newToken = newToken;
+}
+
+void InputDispatcher::onANRLocked(
+        nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
+        const sp<InputWindowHandle>& windowHandle,
+        nsecs_t eventTime, nsecs_t waitStartTime, const char* reason) {
+    float dispatchLatency = (currentTime - eventTime) * 0.000001f;
+    float waitDuration = (currentTime - waitStartTime) * 0.000001f;
+    ALOGI("Application is not responding: %s.  "
+            "It has been %0.1fms since event, %0.1fms since wait started.  Reason: %s",
+            getApplicationWindowLabel(applicationHandle, windowHandle).c_str(),
+            dispatchLatency, waitDuration, reason);
+
+    // Capture a record of the InputDispatcher state at the time of the ANR.
+    time_t t = time(nullptr);
+    struct tm tm;
+    localtime_r(&t, &tm);
+    char timestr[64];
+    strftime(timestr, sizeof(timestr), "%F %T", &tm);
+    mLastANRState.clear();
+    mLastANRState += INDENT "ANR:\n";
+    mLastANRState += StringPrintf(INDENT2 "Time: %s\n", timestr);
+    mLastANRState += StringPrintf(INDENT2 "Window: %s\n",
+            getApplicationWindowLabel(applicationHandle, windowHandle).c_str());
+    mLastANRState += StringPrintf(INDENT2 "DispatchLatency: %0.1fms\n", dispatchLatency);
+    mLastANRState += StringPrintf(INDENT2 "WaitDuration: %0.1fms\n", waitDuration);
+    mLastANRState += StringPrintf(INDENT2 "Reason: %s\n", reason);
+    dumpDispatchStateLocked(mLastANRState);
+
+    CommandEntry* commandEntry = postCommandLocked(
+            & InputDispatcher::doNotifyANRLockedInterruptible);
+    commandEntry->inputApplicationHandle = applicationHandle;
+    commandEntry->inputChannel = windowHandle != nullptr ?
+            getInputChannelLocked(windowHandle->getToken()) : nullptr;
+    commandEntry->reason = reason;
+}
+
+void InputDispatcher::doNotifyConfigurationChangedLockedInterruptible (
+        CommandEntry* commandEntry) {
+    mLock.unlock();
+
+    mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
+
+    mLock.lock();
+}
+
+void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
+        CommandEntry* commandEntry) {
+    sp<Connection> connection = commandEntry->connection;
+
+    if (connection->status != Connection::STATUS_ZOMBIE) {
+        mLock.unlock();
+
+        mPolicy->notifyInputChannelBroken(connection->inputChannel->getToken());
+
+        mLock.lock();
+    }
+}
+
+void InputDispatcher::doNotifyFocusChangedLockedInterruptible(
+        CommandEntry* commandEntry) {
+    sp<IBinder> oldToken = commandEntry->oldToken;
+    sp<IBinder> newToken = commandEntry->newToken;
+    mLock.unlock();
+    mPolicy->notifyFocusChanged(oldToken, newToken);
+    mLock.lock();
+}
+
+void InputDispatcher::doNotifyANRLockedInterruptible(
+        CommandEntry* commandEntry) {
+    mLock.unlock();
+
+    nsecs_t newTimeout = mPolicy->notifyANR(
+            commandEntry->inputApplicationHandle,
+            commandEntry->inputChannel ? commandEntry->inputChannel->getToken() : nullptr,
+            commandEntry->reason);
+
+    mLock.lock();
+
+    resumeAfterTargetsNotReadyTimeoutLocked(newTimeout,
+            commandEntry->inputChannel);
+}
+
+void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
+        CommandEntry* commandEntry) {
+    KeyEntry* entry = commandEntry->keyEntry;
+
+    KeyEvent event;
+    initializeKeyEvent(&event, entry);
+
+    mLock.unlock();
+
+    android::base::Timer t;
+    sp<IBinder> token = commandEntry->inputChannel != nullptr ?
+        commandEntry->inputChannel->getToken() : nullptr;
+    nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(token,
+            &event, entry->policyFlags);
+    if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
+        ALOGW("Excessive delay in interceptKeyBeforeDispatching; took %s ms",
+                std::to_string(t.duration().count()).c_str());
+    }
+
+    mLock.lock();
+
+    if (delay < 0) {
+        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;
+    } else if (!delay) {
+        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
+    } else {
+        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;
+        entry->interceptKeyWakeupTime = now() + delay;
+    }
+    entry->release();
+}
+
+void InputDispatcher::doOnPointerDownOutsideFocusLockedInterruptible(CommandEntry* commandEntry) {
+    mLock.unlock();
+    mPolicy->onPointerDownOutsideFocus(commandEntry->newToken);
+    mLock.lock();
+}
+
+void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
+        CommandEntry* commandEntry) {
+    sp<Connection> connection = commandEntry->connection;
+    nsecs_t finishTime = commandEntry->eventTime;
+    uint32_t seq = commandEntry->seq;
+    bool handled = commandEntry->handled;
+
+    // Handle post-event policy actions.
+    DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq);
+    if (dispatchEntry) {
+        nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;
+        if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
+            std::string msg =
+                    StringPrintf("Window '%s' spent %0.1fms processing the last input event: ",
+                    connection->getWindowName().c_str(), eventDuration * 0.000001f);
+            dispatchEntry->eventEntry->appendDescription(msg);
+            ALOGI("%s", msg.c_str());
+        }
+
+        bool restartEvent;
+        if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
+            KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
+            restartEvent = afterKeyEventLockedInterruptible(connection,
+                    dispatchEntry, keyEntry, handled);
+        } else if (dispatchEntry->eventEntry->type == EventEntry::TYPE_MOTION) {
+            MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
+            restartEvent = afterMotionEventLockedInterruptible(connection,
+                    dispatchEntry, motionEntry, handled);
+        } else {
+            restartEvent = false;
+        }
+
+        // Dequeue the event and start the next cycle.
+        // Note that because the lock might have been released, it is possible that the
+        // contents of the wait queue to have been drained, so we need to double-check
+        // a few things.
+        if (dispatchEntry == connection->findWaitQueueEntry(seq)) {
+            connection->waitQueue.dequeue(dispatchEntry);
+            traceWaitQueueLength(connection);
+            if (restartEvent && connection->status == Connection::STATUS_NORMAL) {
+                connection->outboundQueue.enqueueAtHead(dispatchEntry);
+                traceOutboundQueueLength(connection);
+            } else {
+                releaseDispatchEntry(dispatchEntry);
+            }
+        }
+
+        // Start the next dispatch cycle for this connection.
+        startDispatchCycleLocked(now(), connection);
+    }
+}
+
+bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection,
+        DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled) {
+    if (keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK) {
+        if (!handled) {
+            // Report the key as unhandled, since the fallback was not handled.
+            mReporter->reportUnhandledKey(keyEntry->sequenceNum);
+        }
+        return false;
+    }
+
+    // Get the fallback key state.
+    // Clear it out after dispatching the UP.
+    int32_t originalKeyCode = keyEntry->keyCode;
+    int32_t fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode);
+    if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
+        connection->inputState.removeFallbackKey(originalKeyCode);
+    }
+
+    if (handled || !dispatchEntry->hasForegroundTarget()) {
+        // If the application handles the original key for which we previously
+        // generated a fallback or if the window is not a foreground window,
+        // then cancel the associated fallback key, if any.
+        if (fallbackKeyCode != -1) {
+            // Dispatch the unhandled key to the policy with the cancel flag.
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+            ALOGD("Unhandled key event: Asking policy to cancel fallback action.  "
+                    "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
+                    keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount,
+                    keyEntry->policyFlags);
+#endif
+            KeyEvent event;
+            initializeKeyEvent(&event, keyEntry);
+            event.setFlags(event.getFlags() | AKEY_EVENT_FLAG_CANCELED);
+
+            mLock.unlock();
+
+            mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(),
+                                          &event, keyEntry->policyFlags, &event);
+
+            mLock.lock();
+
+            // Cancel the fallback key.
+            if (fallbackKeyCode != AKEYCODE_UNKNOWN) {
+                CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
+                                           "application handled the original non-fallback key "
+                                           "or is no longer a foreground target, "
+                                           "canceling previously dispatched fallback key");
+                options.keyCode = fallbackKeyCode;
+                synthesizeCancelationEventsForConnectionLocked(connection, options);
+            }
+            connection->inputState.removeFallbackKey(originalKeyCode);
+        }
+    } else {
+        // If the application did not handle a non-fallback key, first check
+        // that we are in a good state to perform unhandled key event processing
+        // Then ask the policy what to do with it.
+        bool initialDown = keyEntry->action == AKEY_EVENT_ACTION_DOWN
+                && keyEntry->repeatCount == 0;
+        if (fallbackKeyCode == -1 && !initialDown) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+            ALOGD("Unhandled key event: Skipping unhandled key event processing "
+                    "since this is not an initial down.  "
+                    "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
+                    originalKeyCode, keyEntry->action, keyEntry->repeatCount,
+                    keyEntry->policyFlags);
+#endif
+            return false;
+        }
+
+        // Dispatch the unhandled key to the policy.
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        ALOGD("Unhandled key event: Asking policy to perform fallback action.  "
+                "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
+                keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount,
+                keyEntry->policyFlags);
+#endif
+        KeyEvent event;
+        initializeKeyEvent(&event, keyEntry);
+
+        mLock.unlock();
+
+        bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(),
+                                                      &event, keyEntry->policyFlags, &event);
+
+        mLock.lock();
+
+        if (connection->status != Connection::STATUS_NORMAL) {
+            connection->inputState.removeFallbackKey(originalKeyCode);
+            return false;
+        }
+
+        // Latch the fallback keycode for this key on an initial down.
+        // The fallback keycode cannot change at any other point in the lifecycle.
+        if (initialDown) {
+            if (fallback) {
+                fallbackKeyCode = event.getKeyCode();
+            } else {
+                fallbackKeyCode = AKEYCODE_UNKNOWN;
+            }
+            connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
+        }
+
+        ALOG_ASSERT(fallbackKeyCode != -1);
+
+        // Cancel the fallback key if the policy decides not to send it anymore.
+        // We will continue to dispatch the key to the policy but we will no
+        // longer dispatch a fallback key to the application.
+        if (fallbackKeyCode != AKEYCODE_UNKNOWN
+                && (!fallback || fallbackKeyCode != event.getKeyCode())) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+            if (fallback) {
+                ALOGD("Unhandled key event: Policy requested to send key %d"
+                        "as a fallback for %d, but on the DOWN it had requested "
+                        "to send %d instead.  Fallback canceled.",
+                        event.getKeyCode(), originalKeyCode, fallbackKeyCode);
+            } else {
+                ALOGD("Unhandled key event: Policy did not request fallback for %d, "
+                        "but on the DOWN it had requested to send %d.  "
+                        "Fallback canceled.",
+                        originalKeyCode, fallbackKeyCode);
+            }
+#endif
+
+            CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
+                                       "canceling fallback, policy no longer desires it");
+            options.keyCode = fallbackKeyCode;
+            synthesizeCancelationEventsForConnectionLocked(connection, options);
+
+            fallback = false;
+            fallbackKeyCode = AKEYCODE_UNKNOWN;
+            if (keyEntry->action != AKEY_EVENT_ACTION_UP) {
+                connection->inputState.setFallbackKey(originalKeyCode,
+                                                      fallbackKeyCode);
+            }
+        }
+
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        {
+            std::string msg;
+            const KeyedVector<int32_t, int32_t>& fallbackKeys =
+                    connection->inputState.getFallbackKeys();
+            for (size_t i = 0; i < fallbackKeys.size(); i++) {
+                msg += StringPrintf(", %d->%d", fallbackKeys.keyAt(i),
+                        fallbackKeys.valueAt(i));
+            }
+            ALOGD("Unhandled key event: %zu currently tracked fallback keys%s.",
+                    fallbackKeys.size(), msg.c_str());
+        }
+#endif
+
+        if (fallback) {
+            // Restart the dispatch cycle using the fallback key.
+            keyEntry->eventTime = event.getEventTime();
+            keyEntry->deviceId = event.getDeviceId();
+            keyEntry->source = event.getSource();
+            keyEntry->displayId = event.getDisplayId();
+            keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
+            keyEntry->keyCode = fallbackKeyCode;
+            keyEntry->scanCode = event.getScanCode();
+            keyEntry->metaState = event.getMetaState();
+            keyEntry->repeatCount = event.getRepeatCount();
+            keyEntry->downTime = event.getDownTime();
+            keyEntry->syntheticRepeat = false;
+
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+            ALOGD("Unhandled key event: Dispatching fallback key.  "
+                    "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
+                    originalKeyCode, fallbackKeyCode, keyEntry->metaState);
+#endif
+            return true; // restart the event
+        } else {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+            ALOGD("Unhandled key event: No fallback key.");
+#endif
+
+            // Report the key as unhandled, since there is no fallback key.
+            mReporter->reportUnhandledKey(keyEntry->sequenceNum);
+        }
+    }
+    return false;
+}
+
+bool InputDispatcher::afterMotionEventLockedInterruptible(const sp<Connection>& connection,
+        DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled) {
+    return false;
+}
+
+void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
+    mLock.unlock();
+
+    mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType);
+
+    mLock.lock();
+}
+
+void InputDispatcher::initializeKeyEvent(KeyEvent* event, const KeyEntry* entry) {
+    event->initialize(entry->deviceId, entry->source, entry->displayId, entry->action, entry->flags,
+            entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
+            entry->downTime, entry->eventTime);
+}
+
+void InputDispatcher::updateDispatchStatistics(nsecs_t currentTime, const EventEntry* entry,
+        int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) {
+    // TODO Write some statistics about how long we spend waiting.
+}
+
+void InputDispatcher::traceInboundQueueLengthLocked() {
+    if (ATRACE_ENABLED()) {
+        ATRACE_INT("iq", mInboundQueue.count());
+    }
+}
+
+void InputDispatcher::traceOutboundQueueLength(const sp<Connection>& connection) {
+    if (ATRACE_ENABLED()) {
+        char counterName[40];
+        snprintf(counterName, sizeof(counterName), "oq:%s", connection->getWindowName().c_str());
+        ATRACE_INT(counterName, connection->outboundQueue.count());
+    }
+}
+
+void InputDispatcher::traceWaitQueueLength(const sp<Connection>& connection) {
+    if (ATRACE_ENABLED()) {
+        char counterName[40];
+        snprintf(counterName, sizeof(counterName), "wq:%s", connection->getWindowName().c_str());
+        ATRACE_INT(counterName, connection->waitQueue.count());
+    }
+}
+
+void InputDispatcher::dump(std::string& dump) {
+    std::scoped_lock _l(mLock);
+
+    dump += "Input Dispatcher State:\n";
+    dumpDispatchStateLocked(dump);
+
+    if (!mLastANRState.empty()) {
+        dump += "\nInput Dispatcher State at time of last ANR:\n";
+        dump += mLastANRState;
+    }
+}
+
+void InputDispatcher::monitor() {
+    // Acquire and release the lock to ensure that the dispatcher has not deadlocked.
+    std::unique_lock _l(mLock);
+    mLooper->wake();
+    mDispatcherIsAlive.wait(_l);
+}
+
+
+// --- InputDispatcher::InjectionState ---
+
+InputDispatcher::InjectionState::InjectionState(int32_t injectorPid, int32_t injectorUid) :
+        refCount(1),
+        injectorPid(injectorPid), injectorUid(injectorUid),
+        injectionResult(INPUT_EVENT_INJECTION_PENDING), injectionIsAsync(false),
+        pendingForegroundDispatches(0) {
+}
+
+InputDispatcher::InjectionState::~InjectionState() {
+}
+
+void InputDispatcher::InjectionState::release() {
+    refCount -= 1;
+    if (refCount == 0) {
+        delete this;
+    } else {
+        ALOG_ASSERT(refCount > 0);
+    }
+}
+
+
+// --- InputDispatcher::EventEntry ---
+
+InputDispatcher::EventEntry::EventEntry(uint32_t sequenceNum, int32_t type,
+        nsecs_t eventTime, uint32_t policyFlags) :
+        sequenceNum(sequenceNum), refCount(1), type(type), eventTime(eventTime),
+        policyFlags(policyFlags), injectionState(nullptr), dispatchInProgress(false) {
+}
+
+InputDispatcher::EventEntry::~EventEntry() {
+    releaseInjectionState();
+}
+
+void InputDispatcher::EventEntry::release() {
+    refCount -= 1;
+    if (refCount == 0) {
+        delete this;
+    } else {
+        ALOG_ASSERT(refCount > 0);
+    }
+}
+
+void InputDispatcher::EventEntry::releaseInjectionState() {
+    if (injectionState) {
+        injectionState->release();
+        injectionState = nullptr;
+    }
+}
+
+
+// --- InputDispatcher::ConfigurationChangedEntry ---
+
+InputDispatcher::ConfigurationChangedEntry::ConfigurationChangedEntry(
+        uint32_t sequenceNum, nsecs_t eventTime) :
+        EventEntry(sequenceNum, TYPE_CONFIGURATION_CHANGED, eventTime, 0) {
+}
+
+InputDispatcher::ConfigurationChangedEntry::~ConfigurationChangedEntry() {
+}
+
+void InputDispatcher::ConfigurationChangedEntry::appendDescription(std::string& msg) const {
+    msg += StringPrintf("ConfigurationChangedEvent(), policyFlags=0x%08x", policyFlags);
+}
+
+
+// --- InputDispatcher::DeviceResetEntry ---
+
+InputDispatcher::DeviceResetEntry::DeviceResetEntry(
+        uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId) :
+        EventEntry(sequenceNum, TYPE_DEVICE_RESET, eventTime, 0),
+        deviceId(deviceId) {
+}
+
+InputDispatcher::DeviceResetEntry::~DeviceResetEntry() {
+}
+
+void InputDispatcher::DeviceResetEntry::appendDescription(std::string& msg) const {
+    msg += StringPrintf("DeviceResetEvent(deviceId=%d), policyFlags=0x%08x",
+            deviceId, policyFlags);
+}
+
+
+// --- InputDispatcher::KeyEntry ---
+
+InputDispatcher::KeyEntry::KeyEntry(uint32_t sequenceNum, nsecs_t eventTime,
+        int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action,
+        int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
+        int32_t repeatCount, nsecs_t downTime) :
+        EventEntry(sequenceNum, TYPE_KEY, eventTime, policyFlags),
+        deviceId(deviceId), source(source), displayId(displayId), action(action), flags(flags),
+        keyCode(keyCode), scanCode(scanCode), metaState(metaState),
+        repeatCount(repeatCount), downTime(downTime),
+        syntheticRepeat(false), interceptKeyResult(KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN),
+        interceptKeyWakeupTime(0) {
+}
+
+InputDispatcher::KeyEntry::~KeyEntry() {
+}
+
+void InputDispatcher::KeyEntry::appendDescription(std::string& msg) const {
+    msg += StringPrintf("KeyEvent");
+}
+
+void InputDispatcher::KeyEntry::recycle() {
+    releaseInjectionState();
+
+    dispatchInProgress = false;
+    syntheticRepeat = false;
+    interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
+    interceptKeyWakeupTime = 0;
+}
+
+
+// --- InputDispatcher::MotionEntry ---
+
+InputDispatcher::MotionEntry::MotionEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId,
+        uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action,
+        int32_t actionButton,
+        int32_t flags, int32_t metaState, int32_t buttonState, MotionClassification classification,
+        int32_t edgeFlags, float xPrecision, float yPrecision, nsecs_t downTime,
+        uint32_t pointerCount,
+        const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
+        float xOffset, float yOffset) :
+        EventEntry(sequenceNum, TYPE_MOTION, eventTime, policyFlags),
+        eventTime(eventTime),
+        deviceId(deviceId), source(source), displayId(displayId), action(action),
+        actionButton(actionButton), flags(flags), metaState(metaState), buttonState(buttonState),
+        classification(classification), edgeFlags(edgeFlags),
+        xPrecision(xPrecision), yPrecision(yPrecision),
+        downTime(downTime), pointerCount(pointerCount) {
+    for (uint32_t i = 0; i < pointerCount; i++) {
+        this->pointerProperties[i].copyFrom(pointerProperties[i]);
+        this->pointerCoords[i].copyFrom(pointerCoords[i]);
+        if (xOffset || yOffset) {
+            this->pointerCoords[i].applyOffset(xOffset, yOffset);
+        }
+    }
+}
+
+InputDispatcher::MotionEntry::~MotionEntry() {
+}
+
+void InputDispatcher::MotionEntry::appendDescription(std::string& msg) const {
+    msg += StringPrintf("MotionEvent");
+}
+
+
+// --- InputDispatcher::DispatchEntry ---
+
+volatile int32_t InputDispatcher::DispatchEntry::sNextSeqAtomic;
+
+InputDispatcher::DispatchEntry::DispatchEntry(EventEntry* eventEntry,
+        int32_t targetFlags, float xOffset, float yOffset, float globalScaleFactor,
+        float windowXScale, float windowYScale) :
+        seq(nextSeq()),
+        eventEntry(eventEntry), targetFlags(targetFlags),
+        xOffset(xOffset), yOffset(yOffset), globalScaleFactor(globalScaleFactor),
+        windowXScale(windowXScale), windowYScale(windowYScale),
+        deliveryTime(0), resolvedAction(0), resolvedFlags(0) {
+    eventEntry->refCount += 1;
+}
+
+InputDispatcher::DispatchEntry::~DispatchEntry() {
+    eventEntry->release();
+}
+
+uint32_t InputDispatcher::DispatchEntry::nextSeq() {
+    // Sequence number 0 is reserved and will never be returned.
+    uint32_t seq;
+    do {
+        seq = android_atomic_inc(&sNextSeqAtomic);
+    } while (!seq);
+    return seq;
+}
+
+
+// --- InputDispatcher::InputState ---
+
+InputDispatcher::InputState::InputState() {
+}
+
+InputDispatcher::InputState::~InputState() {
+}
+
+bool InputDispatcher::InputState::isNeutral() const {
+    return mKeyMementos.empty() && mMotionMementos.empty();
+}
+
+bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source,
+        int32_t displayId) const {
+    for (const MotionMemento& memento : mMotionMementos) {
+        if (memento.deviceId == deviceId
+                && memento.source == source
+                && memento.displayId == displayId
+                && memento.hovering) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool InputDispatcher::InputState::trackKey(const KeyEntry* entry,
+        int32_t action, int32_t flags) {
+    switch (action) {
+    case AKEY_EVENT_ACTION_UP: {
+        if (entry->flags & AKEY_EVENT_FLAG_FALLBACK) {
+            for (size_t i = 0; i < mFallbackKeys.size(); ) {
+                if (mFallbackKeys.valueAt(i) == entry->keyCode) {
+                    mFallbackKeys.removeItemsAt(i);
+                } else {
+                    i += 1;
+                }
+            }
+        }
+        ssize_t index = findKeyMemento(entry);
+        if (index >= 0) {
+            mKeyMementos.erase(mKeyMementos.begin() + index);
+            return true;
+        }
+        /* FIXME: We can't just drop the key up event because that prevents creating
+         * popup windows that are automatically shown when a key is held and then
+         * dismissed when the key is released.  The problem is that the popup will
+         * not have received the original key down, so the key up will be considered
+         * to be inconsistent with its observed state.  We could perhaps handle this
+         * by synthesizing a key down but that will cause other problems.
+         *
+         * So for now, allow inconsistent key up events to be dispatched.
+         *
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        ALOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
+                "keyCode=%d, scanCode=%d",
+                entry->deviceId, entry->source, entry->keyCode, entry->scanCode);
+#endif
+        return false;
+        */
+        return true;
+    }
+
+    case AKEY_EVENT_ACTION_DOWN: {
+        ssize_t index = findKeyMemento(entry);
+        if (index >= 0) {
+            mKeyMementos.erase(mKeyMementos.begin() + index);
+        }
+        addKeyMemento(entry, flags);
+        return true;
+    }
+
+    default:
+        return true;
+    }
+}
+
+bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry,
+        int32_t action, int32_t flags) {
+    int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
+    switch (actionMasked) {
+    case AMOTION_EVENT_ACTION_UP:
+    case AMOTION_EVENT_ACTION_CANCEL: {
+        ssize_t index = findMotionMemento(entry, false /*hovering*/);
+        if (index >= 0) {
+            mMotionMementos.erase(mMotionMementos.begin() + index);
+            return true;
+        }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        ALOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, "
+                "displayId=%" PRId32 ", actionMasked=%d",
+                entry->deviceId, entry->source, entry->displayId, actionMasked);
+#endif
+        return false;
+    }
+
+    case AMOTION_EVENT_ACTION_DOWN: {
+        ssize_t index = findMotionMemento(entry, false /*hovering*/);
+        if (index >= 0) {
+            mMotionMementos.erase(mMotionMementos.begin() + index);
+        }
+        addMotionMemento(entry, flags, false /*hovering*/);
+        return true;
+    }
+
+    case AMOTION_EVENT_ACTION_POINTER_UP:
+    case AMOTION_EVENT_ACTION_POINTER_DOWN:
+    case AMOTION_EVENT_ACTION_MOVE: {
+        if (entry->source & AINPUT_SOURCE_CLASS_NAVIGATION) {
+            // Trackballs can send MOVE events with a corresponding DOWN or UP. There's no need to
+            // generate cancellation events for these since they're based in relative rather than
+            // absolute units.
+            return true;
+        }
+
+        ssize_t index = findMotionMemento(entry, false /*hovering*/);
+
+        if (entry->source & AINPUT_SOURCE_CLASS_JOYSTICK) {
+            // Joysticks can send MOVE events without a corresponding DOWN or UP. Since all
+            // joystick axes are normalized to [-1, 1] we can trust that 0 means it's neutral. Any
+            // other value and we need to track the motion so we can send cancellation events for
+            // anything generating fallback events (e.g. DPad keys for joystick movements).
+            if (index >= 0) {
+                if (entry->pointerCoords[0].isEmpty()) {
+                    mMotionMementos.erase(mMotionMementos.begin() + index);
+                } else {
+                    MotionMemento& memento = mMotionMementos[index];
+                    memento.setPointers(entry);
+                }
+            } else if (!entry->pointerCoords[0].isEmpty()) {
+                addMotionMemento(entry, flags, false /*hovering*/);
+            }
+
+            // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
+            return true;
+        }
+        if (index >= 0) {
+            MotionMemento& memento = mMotionMementos[index];
+            memento.setPointers(entry);
+            return true;
+        }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        ALOGD("Dropping inconsistent motion pointer up/down or move event: "
+                "deviceId=%d, source=%08x, displayId=%" PRId32 ", actionMasked=%d",
+                entry->deviceId, entry->source, entry->displayId, actionMasked);
+#endif
+        return false;
+    }
+
+    case AMOTION_EVENT_ACTION_HOVER_EXIT: {
+        ssize_t index = findMotionMemento(entry, true /*hovering*/);
+        if (index >= 0) {
+            mMotionMementos.erase(mMotionMementos.begin() + index);
+            return true;
+        }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x, "
+                "displayId=%" PRId32,
+                entry->deviceId, entry->source, entry->displayId);
+#endif
+        return false;
+    }
+
+    case AMOTION_EVENT_ACTION_HOVER_ENTER:
+    case AMOTION_EVENT_ACTION_HOVER_MOVE: {
+        ssize_t index = findMotionMemento(entry, true /*hovering*/);
+        if (index >= 0) {
+            mMotionMementos.erase(mMotionMementos.begin() + index);
+        }
+        addMotionMemento(entry, flags, true /*hovering*/);
+        return true;
+    }
+
+    default:
+        return true;
+    }
+}
+
+ssize_t InputDispatcher::InputState::findKeyMemento(const KeyEntry* entry) const {
+    for (size_t i = 0; i < mKeyMementos.size(); i++) {
+        const KeyMemento& memento = mKeyMementos[i];
+        if (memento.deviceId == entry->deviceId
+                && memento.source == entry->source
+                && memento.displayId == entry->displayId
+                && memento.keyCode == entry->keyCode
+                && memento.scanCode == entry->scanCode) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+ssize_t InputDispatcher::InputState::findMotionMemento(const MotionEntry* entry,
+        bool hovering) const {
+    for (size_t i = 0; i < mMotionMementos.size(); i++) {
+        const MotionMemento& memento = mMotionMementos[i];
+        if (memento.deviceId == entry->deviceId
+                && memento.source == entry->source
+                && memento.displayId == entry->displayId
+                && memento.hovering == hovering) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+void InputDispatcher::InputState::addKeyMemento(const KeyEntry* entry, int32_t flags) {
+    KeyMemento memento;
+    memento.deviceId = entry->deviceId;
+    memento.source = entry->source;
+    memento.displayId = entry->displayId;
+    memento.keyCode = entry->keyCode;
+    memento.scanCode = entry->scanCode;
+    memento.metaState = entry->metaState;
+    memento.flags = flags;
+    memento.downTime = entry->downTime;
+    memento.policyFlags = entry->policyFlags;
+    mKeyMementos.push_back(memento);
+}
+
+void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry,
+        int32_t flags, bool hovering) {
+    MotionMemento memento;
+    memento.deviceId = entry->deviceId;
+    memento.source = entry->source;
+    memento.displayId = entry->displayId;
+    memento.flags = flags;
+    memento.xPrecision = entry->xPrecision;
+    memento.yPrecision = entry->yPrecision;
+    memento.downTime = entry->downTime;
+    memento.setPointers(entry);
+    memento.hovering = hovering;
+    memento.policyFlags = entry->policyFlags;
+    mMotionMementos.push_back(memento);
+}
+
+void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
+    pointerCount = entry->pointerCount;
+    for (uint32_t i = 0; i < entry->pointerCount; i++) {
+        pointerProperties[i].copyFrom(entry->pointerProperties[i]);
+        pointerCoords[i].copyFrom(entry->pointerCoords[i]);
+    }
+}
+
+void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
+        std::vector<EventEntry*>& outEvents, const CancelationOptions& options) {
+    for (KeyMemento& memento : mKeyMementos) {
+        if (shouldCancelKey(memento, options)) {
+            outEvents.push_back(new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
+                    memento.deviceId, memento.source, memento.displayId, memento.policyFlags,
+                    AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
+                    memento.keyCode, memento.scanCode, memento.metaState, 0, memento.downTime));
+        }
+    }
+
+    for (const MotionMemento& memento : mMotionMementos) {
+        if (shouldCancelMotion(memento, options)) {
+            const int32_t action = memento.hovering ?
+                    AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL;
+            outEvents.push_back(new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
+                    memento.deviceId, memento.source, memento.displayId, memento.policyFlags,
+                    action, 0 /*actionButton*/, memento.flags, AMETA_NONE, 0 /*buttonState*/,
+                    MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+                    memento.xPrecision, memento.yPrecision, memento.downTime,
+                    memento.pointerCount, memento.pointerProperties, memento.pointerCoords,
+                    0 /*xOffset*/, 0 /*yOffset*/));
+        }
+    }
+}
+
+void InputDispatcher::InputState::clear() {
+    mKeyMementos.clear();
+    mMotionMementos.clear();
+    mFallbackKeys.clear();
+}
+
+void InputDispatcher::InputState::copyPointerStateTo(InputState& other) const {
+    for (size_t i = 0; i < mMotionMementos.size(); i++) {
+        const MotionMemento& memento = mMotionMementos[i];
+        if (memento.source & AINPUT_SOURCE_CLASS_POINTER) {
+            for (size_t j = 0; j < other.mMotionMementos.size(); ) {
+                const MotionMemento& otherMemento = other.mMotionMementos[j];
+                if (memento.deviceId == otherMemento.deviceId
+                        && memento.source == otherMemento.source
+                        && memento.displayId == otherMemento.displayId) {
+                    other.mMotionMementos.erase(other.mMotionMementos.begin() + j);
+                } else {
+                    j += 1;
+                }
+            }
+            other.mMotionMementos.push_back(memento);
+        }
+    }
+}
+
+int32_t InputDispatcher::InputState::getFallbackKey(int32_t originalKeyCode) {
+    ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
+    return index >= 0 ? mFallbackKeys.valueAt(index) : -1;
+}
+
+void InputDispatcher::InputState::setFallbackKey(int32_t originalKeyCode,
+        int32_t fallbackKeyCode) {
+    ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
+    if (index >= 0) {
+        mFallbackKeys.replaceValueAt(index, fallbackKeyCode);
+    } else {
+        mFallbackKeys.add(originalKeyCode, fallbackKeyCode);
+    }
+}
+
+void InputDispatcher::InputState::removeFallbackKey(int32_t originalKeyCode) {
+    mFallbackKeys.removeItem(originalKeyCode);
+}
+
+bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
+        const CancelationOptions& options) {
+    if (options.keyCode && memento.keyCode != options.keyCode.value()) {
+        return false;
+    }
+
+    if (options.deviceId  && memento.deviceId != options.deviceId.value()) {
+        return false;
+    }
+
+    if (options.displayId && memento.displayId != options.displayId.value()) {
+        return false;
+    }
+
+    switch (options.mode) {
+    case CancelationOptions::CANCEL_ALL_EVENTS:
+    case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
+        return true;
+    case CancelationOptions::CANCEL_FALLBACK_EVENTS:
+        return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
+    default:
+        return false;
+    }
+}
+
+bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento,
+        const CancelationOptions& options) {
+    if (options.deviceId && memento.deviceId != options.deviceId.value()) {
+        return false;
+    }
+
+    if (options.displayId && memento.displayId != options.displayId.value()) {
+        return false;
+    }
+
+    switch (options.mode) {
+    case CancelationOptions::CANCEL_ALL_EVENTS:
+        return true;
+    case CancelationOptions::CANCEL_POINTER_EVENTS:
+        return memento.source & AINPUT_SOURCE_CLASS_POINTER;
+    case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
+        return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
+    default:
+        return false;
+    }
+}
+
+
+// --- InputDispatcher::Connection ---
+
+InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel, bool monitor) :
+        status(STATUS_NORMAL), inputChannel(inputChannel),
+        monitor(monitor),
+        inputPublisher(inputChannel), inputPublisherBlocked(false) {
+}
+
+InputDispatcher::Connection::~Connection() {
+}
+
+const std::string InputDispatcher::Connection::getWindowName() const {
+    if (inputChannel != nullptr) {
+        return inputChannel->getName();
+    }
+    if (monitor) {
+        return "monitor";
+    }
+    return "?";
+}
+
+const char* InputDispatcher::Connection::getStatusLabel() const {
+    switch (status) {
+    case STATUS_NORMAL:
+        return "NORMAL";
+
+    case STATUS_BROKEN:
+        return "BROKEN";
+
+    case STATUS_ZOMBIE:
+        return "ZOMBIE";
+
+    default:
+        return "UNKNOWN";
+    }
+}
+
+InputDispatcher::DispatchEntry* InputDispatcher::Connection::findWaitQueueEntry(uint32_t seq) {
+    for (DispatchEntry* entry = waitQueue.head; entry != nullptr; entry = entry->next) {
+        if (entry->seq == seq) {
+            return entry;
+        }
+    }
+    return nullptr;
+}
+
+// --- InputDispatcher::Monitor
+InputDispatcher::Monitor::Monitor(const sp<InputChannel>& inputChannel) :
+    inputChannel(inputChannel) {
+}
+
+
+// --- InputDispatcher::CommandEntry ---
+//
+InputDispatcher::CommandEntry::CommandEntry(Command command) :
+    command(command), eventTime(0), keyEntry(nullptr), userActivityEventType(0),
+    seq(0), handled(false) {
+}
+
+InputDispatcher::CommandEntry::~CommandEntry() {
+}
+
+// --- InputDispatcher::TouchedMonitor ---
+InputDispatcher::TouchedMonitor::TouchedMonitor(const Monitor& monitor, float xOffset,
+        float yOffset) : monitor(monitor), xOffset(xOffset), yOffset(yOffset) {
+}
+
+// --- InputDispatcher::TouchState ---
+
+InputDispatcher::TouchState::TouchState() :
+    down(false), split(false), deviceId(-1), source(0), displayId(ADISPLAY_ID_NONE) {
+}
+
+InputDispatcher::TouchState::~TouchState() {
+}
+
+void InputDispatcher::TouchState::reset() {
+    down = false;
+    split = false;
+    deviceId = -1;
+    source = 0;
+    displayId = ADISPLAY_ID_NONE;
+    windows.clear();
+    portalWindows.clear();
+    gestureMonitors.clear();
+}
+
+void InputDispatcher::TouchState::copyFrom(const TouchState& other) {
+    down = other.down;
+    split = other.split;
+    deviceId = other.deviceId;
+    source = other.source;
+    displayId = other.displayId;
+    windows = other.windows;
+    portalWindows = other.portalWindows;
+    gestureMonitors = other.gestureMonitors;
+}
+
+void InputDispatcher::TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
+        int32_t targetFlags, BitSet32 pointerIds) {
+    if (targetFlags & InputTarget::FLAG_SPLIT) {
+        split = true;
+    }
+
+    for (size_t i = 0; i < windows.size(); i++) {
+        TouchedWindow& touchedWindow = windows[i];
+        if (touchedWindow.windowHandle == windowHandle) {
+            touchedWindow.targetFlags |= targetFlags;
+            if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
+                touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
+            }
+            touchedWindow.pointerIds.value |= pointerIds.value;
+            return;
+        }
+    }
+
+    TouchedWindow touchedWindow;
+    touchedWindow.windowHandle = windowHandle;
+    touchedWindow.targetFlags = targetFlags;
+    touchedWindow.pointerIds = pointerIds;
+    windows.push_back(touchedWindow);
+}
+
+void InputDispatcher::TouchState::addPortalWindow(const sp<InputWindowHandle>& windowHandle) {
+    size_t numWindows = portalWindows.size();
+    for (size_t i = 0; i < numWindows; i++) {
+        if (portalWindows[i] == windowHandle) {
+            return;
+        }
+    }
+    portalWindows.push_back(windowHandle);
+}
+
+void InputDispatcher::TouchState::addGestureMonitors(
+        const std::vector<TouchedMonitor>& newMonitors) {
+    const size_t newSize = gestureMonitors.size() + newMonitors.size();
+    gestureMonitors.reserve(newSize);
+    gestureMonitors.insert(std::end(gestureMonitors),
+            std::begin(newMonitors), std::end(newMonitors));
+}
+
+void InputDispatcher::TouchState::removeWindow(const sp<InputWindowHandle>& windowHandle) {
+    for (size_t i = 0; i < windows.size(); i++) {
+        if (windows[i].windowHandle == windowHandle) {
+            windows.erase(windows.begin() + i);
+            return;
+        }
+    }
+}
+
+void InputDispatcher::TouchState::removeWindowByToken(const sp<IBinder>& token) {
+    for (size_t i = 0; i < windows.size(); i++) {
+        if (windows[i].windowHandle->getToken() == token) {
+            windows.erase(windows.begin() + i);
+            return;
+        }
+    }
+}
+
+void InputDispatcher::TouchState::filterNonAsIsTouchWindows() {
+    for (size_t i = 0 ; i < windows.size(); ) {
+        TouchedWindow& window = windows[i];
+        if (window.targetFlags & (InputTarget::FLAG_DISPATCH_AS_IS
+                | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) {
+            window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK;
+            window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS;
+            i += 1;
+        } else {
+            windows.erase(windows.begin() + i);
+        }
+    }
+}
+
+void InputDispatcher::TouchState::filterNonMonitors() {
+    windows.clear();
+    portalWindows.clear();
+}
+
+sp<InputWindowHandle> InputDispatcher::TouchState::getFirstForegroundWindowHandle() const {
+    for (size_t i = 0; i < windows.size(); i++) {
+        const TouchedWindow& window = windows[i];
+        if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
+            return window.windowHandle;
+        }
+    }
+    return nullptr;
+}
+
+bool InputDispatcher::TouchState::isSlippery() const {
+    // Must have exactly one foreground window.
+    bool haveSlipperyForegroundWindow = false;
+    for (const TouchedWindow& window : windows) {
+        if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
+            if (haveSlipperyForegroundWindow
+                    || !(window.windowHandle->getInfo()->layoutParamsFlags
+                            & InputWindowInfo::FLAG_SLIPPERY)) {
+                return false;
+            }
+            haveSlipperyForegroundWindow = true;
+        }
+    }
+    return haveSlipperyForegroundWindow;
+}
+
+
+// --- InputDispatcherThread ---
+
+InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
+        Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
+}
+
+InputDispatcherThread::~InputDispatcherThread() {
+}
+
+bool InputDispatcherThread::threadLoop() {
+    mDispatcher->dispatchOnce();
+    return true;
+}
+
+} // namespace android
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
new file mode 100644
index 0000000..753b748
--- /dev/null
+++ b/services/inputflinger/InputDispatcher.h
@@ -0,0 +1,1305 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef _UI_INPUT_DISPATCHER_H
+#define _UI_INPUT_DISPATCHER_H
+
+#include <condition_variable>
+#include <input/Input.h>
+#include <input/InputApplication.h>
+#include <input/InputTransport.h>
+#include <input/InputWindow.h>
+#include <input/ISetInputWindowsListener.h>
+#include <optional>
+#include <ui/Region.h>
+#include <utils/threads.h>
+#include <utils/Timers.h>
+#include <utils/RefBase.h>
+#include <utils/Looper.h>
+#include <utils/BitSet.h>
+#include <cutils/atomic.h>
+#include <unordered_map>
+
+#include <stddef.h>
+#include <unistd.h>
+#include <limits.h>
+#include <unordered_map>
+
+#include "InputListener.h"
+#include "InputReporterInterface.h"
+
+namespace android {
+
+/*
+ * Constants used to report the outcome of input event injection.
+ */
+enum {
+    /* (INTERNAL USE ONLY) Specifies that injection is pending and its outcome is unknown. */
+    INPUT_EVENT_INJECTION_PENDING = -1,
+
+    /* Injection succeeded. */
+    INPUT_EVENT_INJECTION_SUCCEEDED = 0,
+
+    /* Injection failed because the injector did not have permission to inject
+     * into the application with input focus. */
+    INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1,
+
+    /* Injection failed because there were no available input targets. */
+    INPUT_EVENT_INJECTION_FAILED = 2,
+
+    /* Injection failed due to a timeout. */
+    INPUT_EVENT_INJECTION_TIMED_OUT = 3
+};
+
+/*
+ * Constants used to determine the input event injection synchronization mode.
+ */
+enum {
+    /* Injection is asynchronous and is assumed always to be successful. */
+    INPUT_EVENT_INJECTION_SYNC_NONE = 0,
+
+    /* Waits for previous events to be dispatched so that the input dispatcher can determine
+     * whether input event injection willbe permitted based on the current input focus.
+     * Does not wait for the input event to finish processing. */
+    INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1,
+
+    /* Waits for the input event to be completely processed. */
+    INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED = 2,
+};
+
+
+/*
+ * An input target specifies how an input event is to be dispatched to a particular window
+ * including the window's input channel, control flags, a timeout, and an X / Y offset to
+ * be added to input event coordinates to compensate for the absolute position of the
+ * window area.
+ */
+struct InputTarget {
+    enum {
+        /* This flag indicates that the event is being delivered to a foreground application. */
+        FLAG_FOREGROUND = 1 << 0,
+
+        /* This flag indicates that the MotionEvent falls within the area of the target
+         * obscured by another visible window above it.  The motion event should be
+         * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
+        FLAG_WINDOW_IS_OBSCURED = 1 << 1,
+
+        /* This flag indicates that a motion event is being split across multiple windows. */
+        FLAG_SPLIT = 1 << 2,
+
+        /* This flag indicates that the pointer coordinates dispatched to the application
+         * will be zeroed out to avoid revealing information to an application. This is
+         * used in conjunction with FLAG_DISPATCH_AS_OUTSIDE to prevent apps not sharing
+         * the same UID from watching all touches. */
+        FLAG_ZERO_COORDS = 1 << 3,
+
+        /* This flag indicates that the event should be sent as is.
+         * Should always be set unless the event is to be transmuted. */
+        FLAG_DISPATCH_AS_IS = 1 << 8,
+
+        /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
+         * of the area of this target and so should instead be delivered as an
+         * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
+        FLAG_DISPATCH_AS_OUTSIDE = 1 << 9,
+
+        /* This flag indicates that a hover sequence is starting in the given window.
+         * The event is transmuted into ACTION_HOVER_ENTER. */
+        FLAG_DISPATCH_AS_HOVER_ENTER = 1 << 10,
+
+        /* This flag indicates that a hover event happened outside of a window which handled
+         * previous hover events, signifying the end of the current hover sequence for that
+         * window.
+         * The event is transmuted into ACTION_HOVER_ENTER. */
+        FLAG_DISPATCH_AS_HOVER_EXIT = 1 << 11,
+
+        /* This flag indicates that the event should be canceled.
+         * It is used to transmute ACTION_MOVE into ACTION_CANCEL when a touch slips
+         * outside of a window. */
+        FLAG_DISPATCH_AS_SLIPPERY_EXIT = 1 << 12,
+
+        /* This flag indicates that the event should be dispatched as an initial down.
+         * It is used to transmute ACTION_MOVE into ACTION_DOWN when a touch slips
+         * into a new window. */
+        FLAG_DISPATCH_AS_SLIPPERY_ENTER = 1 << 13,
+
+        /* Mask for all dispatch modes. */
+        FLAG_DISPATCH_MASK = FLAG_DISPATCH_AS_IS
+                | FLAG_DISPATCH_AS_OUTSIDE
+                | FLAG_DISPATCH_AS_HOVER_ENTER
+                | FLAG_DISPATCH_AS_HOVER_EXIT
+                | FLAG_DISPATCH_AS_SLIPPERY_EXIT
+                | FLAG_DISPATCH_AS_SLIPPERY_ENTER,
+
+        /* This flag indicates that the target of a MotionEvent is partly or wholly
+         * obscured by another visible window above it.  The motion event should be
+         * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED. */
+        FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 1 << 14,
+
+    };
+
+    // The input channel to be targeted.
+    sp<InputChannel> inputChannel;
+
+    // Flags for the input target.
+    int32_t flags;
+
+    // The x and y offset to add to a MotionEvent as it is delivered.
+    // (ignored for KeyEvents)
+    float xOffset, yOffset;
+
+    // Scaling factor to apply to MotionEvent as it is delivered.
+    // (ignored for KeyEvents)
+    float globalScaleFactor;
+    float windowXScale = 1.0f;
+    float windowYScale = 1.0f;
+
+    // The subset of pointer ids to include in motion events dispatched to this input target
+    // if FLAG_SPLIT is set.
+    BitSet32 pointerIds;
+};
+
+
+/*
+ * Input dispatcher configuration.
+ *
+ * Specifies various options that modify the behavior of the input dispatcher.
+ * The values provided here are merely defaults. The actual values will come from ViewConfiguration
+ * and are passed into the dispatcher during initialization.
+ */
+struct InputDispatcherConfiguration {
+    // The key repeat initial timeout.
+    nsecs_t keyRepeatTimeout;
+
+    // The key repeat inter-key delay.
+    nsecs_t keyRepeatDelay;
+
+    InputDispatcherConfiguration() :
+            keyRepeatTimeout(500 * 1000000LL),
+            keyRepeatDelay(50 * 1000000LL) { }
+};
+
+
+/*
+ * Input dispatcher policy interface.
+ *
+ * The input reader policy is used by the input reader to interact with the Window Manager
+ * and other system components.
+ *
+ * The actual implementation is partially supported by callbacks into the DVM
+ * via JNI.  This interface is also mocked in the unit tests.
+ */
+class InputDispatcherPolicyInterface : public virtual RefBase {
+protected:
+    InputDispatcherPolicyInterface() { }
+    virtual ~InputDispatcherPolicyInterface() { }
+
+public:
+    /* Notifies the system that a configuration change has occurred. */
+    virtual void notifyConfigurationChanged(nsecs_t when) = 0;
+
+    /* Notifies the system that an application is not responding.
+     * Returns a new timeout to continue waiting, or 0 to abort dispatch. */
+    virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
+            const sp<IBinder>& token,
+            const std::string& reason) = 0;
+
+    /* Notifies the system that an input channel is unrecoverably broken. */
+    virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0;
+    virtual void notifyFocusChanged(const sp<IBinder>& oldToken, const sp<IBinder>& newToken) = 0;
+
+    /* Gets the input dispatcher configuration. */
+    virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0;
+
+    /* Filters an input event.
+     * Return true to dispatch the event unmodified, false to consume the event.
+     * A filter can also transform and inject events later by passing POLICY_FLAG_FILTERED
+     * to injectInputEvent.
+     */
+    virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) = 0;
+
+    /* Intercepts a key event immediately before queueing it.
+     * The policy can use this method as an opportunity to perform power management functions
+     * and early event preprocessing such as updating policy flags.
+     *
+     * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
+     * should be dispatched to applications.
+     */
+    virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) = 0;
+
+    /* Intercepts a touch, trackball or other motion event before queueing it.
+     * The policy can use this method as an opportunity to perform power management functions
+     * and early event preprocessing such as updating policy flags.
+     *
+     * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
+     * should be dispatched to applications.
+     */
+    virtual void interceptMotionBeforeQueueing(const int32_t displayId, nsecs_t when,
+            uint32_t& policyFlags) = 0;
+
+    /* Allows the policy a chance to intercept a key before dispatching. */
+    virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>& token,
+            const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
+
+    /* Allows the policy a chance to perform default processing for an unhandled key.
+     * Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
+    virtual bool dispatchUnhandledKey(const sp<IBinder>& token,
+            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
+
+    /* Notifies the policy about switch events.
+     */
+    virtual void notifySwitch(nsecs_t when,
+            uint32_t switchValues, uint32_t switchMask, uint32_t policyFlags) = 0;
+
+    /* Poke user activity for an event dispatched to a window. */
+    virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) = 0;
+
+    /* Checks whether a given application pid/uid has permission to inject input events
+     * into other applications.
+     *
+     * This method is special in that its implementation promises to be non-reentrant and
+     * is safe to call while holding other locks.  (Most other methods make no such guarantees!)
+     */
+    virtual bool checkInjectEventsPermissionNonReentrant(
+            int32_t injectorPid, int32_t injectorUid) = 0;
+
+    /* Notifies the policy that a pointer down event has occurred outside the current focused
+     * window.
+     *
+     * The touchedToken passed as an argument is the window that received the input event.
+     */
+    virtual void onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) = 0;
+};
+
+
+/* Notifies the system about input events generated by the input reader.
+ * The dispatcher is expected to be mostly asynchronous. */
+class InputDispatcherInterface : public virtual RefBase, public InputListenerInterface {
+protected:
+    InputDispatcherInterface() { }
+    virtual ~InputDispatcherInterface() { }
+
+public:
+    /* Dumps the state of the input dispatcher.
+     *
+     * This method may be called on any thread (usually by the input manager). */
+    virtual void dump(std::string& dump) = 0;
+
+    /* Called by the heatbeat to ensures that the dispatcher has not deadlocked. */
+    virtual void monitor() = 0;
+
+    /* Runs a single iteration of the dispatch loop.
+     * Nominally processes one queued event, a timeout, or a response from an input consumer.
+     *
+     * This method should only be called on the input dispatcher thread.
+     */
+    virtual void dispatchOnce() = 0;
+
+    /* Injects an input event and optionally waits for sync.
+     * The synchronization mode determines whether the method blocks while waiting for
+     * input injection to proceed.
+     * Returns one of the INPUT_EVENT_INJECTION_XXX constants.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual int32_t injectInputEvent(const InputEvent* event,
+            int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
+            uint32_t policyFlags) = 0;
+
+    /* Sets the list of input windows.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual void setInputWindows(const std::vector<sp<InputWindowHandle> >& inputWindowHandles,
+            int32_t displayId,
+            const sp<ISetInputWindowsListener>& setInputWindowsListener = nullptr) = 0;
+
+    /* Sets the focused application on the given display.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual void setFocusedApplication(
+            int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) = 0;
+
+    /* Sets the focused display.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual void setFocusedDisplay(int32_t displayId) = 0;
+
+    /* Sets the input dispatching mode.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual void setInputDispatchMode(bool enabled, bool frozen) = 0;
+
+    /* Sets whether input event filtering is enabled.
+     * When enabled, incoming input events are sent to the policy's filterInputEvent
+     * method instead of being dispatched.  The filter is expected to use
+     * injectInputEvent to inject the events it would like to have dispatched.
+     * It should include POLICY_FLAG_FILTERED in the policy flags during injection.
+     */
+    virtual void setInputFilterEnabled(bool enabled) = 0;
+
+    /* Transfers touch focus from one window to another window.
+     *
+     * Returns true on success.  False if the window did not actually have touch focus.
+     */
+    virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0;
+
+    /* Registers input channels that may be used as targets for input events.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual status_t registerInputChannel(
+            const sp<InputChannel>& inputChannel, int32_t displayId) = 0;
+
+    /* Registers input channels to be used to monitor input events.
+     *
+     * Each monitor must target a specific display and will only receive input events sent to that
+     * display. If the monitor is a gesture monitor, it will only receive pointer events on the
+     * targeted display.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual status_t registerInputMonitor(
+            const sp<InputChannel>& inputChannel, int32_t displayId, bool gestureMonitor) = 0;
+
+    /* Unregister input channels that will no longer receive input events.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
+
+    /* Allows an input monitor steal the current pointer stream away from normal input windows.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual status_t pilferPointers(const sp<IBinder>& token) = 0;
+
+};
+
+/* Dispatches events to input targets.  Some functions of the input dispatcher, such as
+ * identifying input targets, are controlled by a separate policy object.
+ *
+ * IMPORTANT INVARIANT:
+ *     Because the policy can potentially block or cause re-entrance into the input dispatcher,
+ *     the input dispatcher never calls into the policy while holding its internal locks.
+ *     The implementation is also carefully designed to recover from scenarios such as an
+ *     input channel becoming unregistered while identifying input targets or processing timeouts.
+ *
+ *     Methods marked 'Locked' must be called with the lock acquired.
+ *
+ *     Methods marked 'LockedInterruptible' must be called with the lock acquired but
+ *     may during the course of their execution release the lock, call into the policy, and
+ *     then reacquire the lock.  The caller is responsible for recovering gracefully.
+ *
+ *     A 'LockedInterruptible' method may called a 'Locked' method, but NOT vice-versa.
+ */
+class InputDispatcher : public InputDispatcherInterface {
+protected:
+    virtual ~InputDispatcher();
+
+public:
+    explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
+
+    virtual void dump(std::string& dump) override;
+    virtual void monitor() override;
+
+    virtual void dispatchOnce() override;
+
+    virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
+    virtual void notifyKey(const NotifyKeyArgs* args) override;
+    virtual void notifyMotion(const NotifyMotionArgs* args) override;
+    virtual void notifySwitch(const NotifySwitchArgs* args) override;
+    virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
+
+    virtual int32_t injectInputEvent(const InputEvent* event,
+            int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
+            uint32_t policyFlags) override;
+
+    virtual void setInputWindows(const std::vector<sp<InputWindowHandle> >& inputWindowHandles,
+            int32_t displayId,
+            const sp<ISetInputWindowsListener>& setInputWindowsListener = nullptr) override;
+    virtual void setFocusedApplication(int32_t displayId,
+            const sp<InputApplicationHandle>& inputApplicationHandle) override;
+    virtual void setFocusedDisplay(int32_t displayId) override;
+    virtual void setInputDispatchMode(bool enabled, bool frozen) override;
+    virtual void setInputFilterEnabled(bool enabled) override;
+
+    virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken)
+            override;
+
+    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
+            int32_t displayId) override;
+    virtual status_t registerInputMonitor(const sp<InputChannel>& inputChannel,
+            int32_t displayId, bool isGestureMonitor) override;
+    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) override;
+    virtual status_t pilferPointers(const sp<IBinder>& token) override;
+
+private:
+    template <typename T>
+    struct Link {
+        T* next;
+        T* prev;
+
+    protected:
+        inline Link() : next(nullptr), prev(nullptr) { }
+    };
+
+    struct InjectionState {
+        mutable int32_t refCount;
+
+        int32_t injectorPid;
+        int32_t injectorUid;
+        int32_t injectionResult;  // initially INPUT_EVENT_INJECTION_PENDING
+        bool injectionIsAsync; // set to true if injection is not waiting for the result
+        int32_t pendingForegroundDispatches; // the number of foreground dispatches in progress
+
+        InjectionState(int32_t injectorPid, int32_t injectorUid);
+        void release();
+
+    private:
+        ~InjectionState();
+    };
+
+    struct EventEntry : Link<EventEntry> {
+        enum {
+            TYPE_CONFIGURATION_CHANGED,
+            TYPE_DEVICE_RESET,
+            TYPE_KEY,
+            TYPE_MOTION
+        };
+
+        uint32_t sequenceNum;
+        mutable int32_t refCount;
+        int32_t type;
+        nsecs_t eventTime;
+        uint32_t policyFlags;
+        InjectionState* injectionState;
+
+        bool dispatchInProgress; // initially false, set to true while dispatching
+
+        inline bool isInjected() const { return injectionState != nullptr; }
+
+        void release();
+
+        virtual void appendDescription(std::string& msg) const = 0;
+
+    protected:
+        EventEntry(uint32_t sequenceNum, int32_t type, nsecs_t eventTime, uint32_t policyFlags);
+        virtual ~EventEntry();
+        void releaseInjectionState();
+    };
+
+    struct ConfigurationChangedEntry : EventEntry {
+        explicit ConfigurationChangedEntry(uint32_t sequenceNum, nsecs_t eventTime);
+        virtual void appendDescription(std::string& msg) const;
+
+    protected:
+        virtual ~ConfigurationChangedEntry();
+    };
+
+    struct DeviceResetEntry : EventEntry {
+        int32_t deviceId;
+
+        DeviceResetEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId);
+        virtual void appendDescription(std::string& msg) const;
+
+    protected:
+        virtual ~DeviceResetEntry();
+    };
+
+    struct KeyEntry : EventEntry {
+        int32_t deviceId;
+        uint32_t source;
+        int32_t displayId;
+        int32_t action;
+        int32_t flags;
+        int32_t keyCode;
+        int32_t scanCode;
+        int32_t metaState;
+        int32_t repeatCount;
+        nsecs_t downTime;
+
+        bool syntheticRepeat; // set to true for synthetic key repeats
+
+        enum InterceptKeyResult {
+            INTERCEPT_KEY_RESULT_UNKNOWN,
+            INTERCEPT_KEY_RESULT_SKIP,
+            INTERCEPT_KEY_RESULT_CONTINUE,
+            INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER,
+        };
+        InterceptKeyResult interceptKeyResult; // set based on the interception result
+        nsecs_t interceptKeyWakeupTime; // used with INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER
+
+        KeyEntry(uint32_t sequenceNum, nsecs_t eventTime,
+                int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags,
+                int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
+                int32_t repeatCount, nsecs_t downTime);
+        virtual void appendDescription(std::string& msg) const;
+        void recycle();
+
+    protected:
+        virtual ~KeyEntry();
+    };
+
+    struct MotionEntry : EventEntry {
+        nsecs_t eventTime;
+        int32_t deviceId;
+        uint32_t source;
+        int32_t displayId;
+        int32_t action;
+        int32_t actionButton;
+        int32_t flags;
+        int32_t metaState;
+        int32_t buttonState;
+        MotionClassification classification;
+        int32_t edgeFlags;
+        float xPrecision;
+        float yPrecision;
+        nsecs_t downTime;
+        uint32_t pointerCount;
+        PointerProperties pointerProperties[MAX_POINTERS];
+        PointerCoords pointerCoords[MAX_POINTERS];
+
+        MotionEntry(uint32_t sequenceNum, nsecs_t eventTime,
+                int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags,
+                int32_t action, int32_t actionButton, int32_t flags,
+                int32_t metaState, int32_t buttonState, MotionClassification classification,
+                int32_t edgeFlags, float xPrecision, float yPrecision,
+                nsecs_t downTime, uint32_t pointerCount,
+                const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
+                float xOffset, float yOffset);
+        virtual void appendDescription(std::string& msg) const;
+
+    protected:
+        virtual ~MotionEntry();
+    };
+
+    // Tracks the progress of dispatching a particular event to a particular connection.
+    struct DispatchEntry : Link<DispatchEntry> {
+        const uint32_t seq; // unique sequence number, never 0
+
+        EventEntry* eventEntry; // the event to dispatch
+        int32_t targetFlags;
+        float xOffset;
+        float yOffset;
+        float globalScaleFactor;
+        float windowXScale = 1.0f;
+        float windowYScale = 1.0f;
+        nsecs_t deliveryTime; // time when the event was actually delivered
+
+        // Set to the resolved action and flags when the event is enqueued.
+        int32_t resolvedAction;
+        int32_t resolvedFlags;
+
+        DispatchEntry(EventEntry* eventEntry,
+                int32_t targetFlags, float xOffset, float yOffset,
+                float globalScaleFactor, float windowXScale, float windowYScale);
+        ~DispatchEntry();
+
+        inline bool hasForegroundTarget() const {
+            return targetFlags & InputTarget::FLAG_FOREGROUND;
+        }
+
+        inline bool isSplit() const {
+            return targetFlags & InputTarget::FLAG_SPLIT;
+        }
+
+    private:
+        static volatile int32_t sNextSeqAtomic;
+
+        static uint32_t nextSeq();
+    };
+
+    // A command entry captures state and behavior for an action to be performed in the
+    // dispatch loop after the initial processing has taken place.  It is essentially
+    // a kind of continuation used to postpone sensitive policy interactions to a point
+    // in the dispatch loop where it is safe to release the lock (generally after finishing
+    // the critical parts of the dispatch cycle).
+    //
+    // The special thing about commands is that they can voluntarily release and reacquire
+    // the dispatcher lock at will.  Initially when the command starts running, the
+    // dispatcher lock is held.  However, if the command needs to call into the policy to
+    // do some work, it can release the lock, do the work, then reacquire the lock again
+    // before returning.
+    //
+    // This mechanism is a bit clunky but it helps to preserve the invariant that the dispatch
+    // never calls into the policy while holding its lock.
+    //
+    // Commands are implicitly 'LockedInterruptible'.
+    struct CommandEntry;
+    typedef void (InputDispatcher::*Command)(CommandEntry* commandEntry);
+
+    class Connection;
+    struct CommandEntry : Link<CommandEntry> {
+        explicit CommandEntry(Command command);
+        ~CommandEntry();
+
+        Command command;
+
+        // parameters for the command (usage varies by command)
+        sp<Connection> connection;
+        nsecs_t eventTime;
+        KeyEntry* keyEntry;
+        sp<InputApplicationHandle> inputApplicationHandle;
+        std::string reason;
+        int32_t userActivityEventType;
+        uint32_t seq;
+        bool handled;
+        sp<InputChannel> inputChannel;
+        sp<IBinder> oldToken;
+        sp<IBinder> newToken;
+    };
+
+    // Generic queue implementation.
+    template <typename T>
+    struct Queue {
+        T* head;
+        T* tail;
+        uint32_t entryCount;
+
+        inline Queue() : head(nullptr), tail(nullptr), entryCount(0) {
+        }
+
+        inline bool isEmpty() const {
+            return !head;
+        }
+
+        inline void enqueueAtTail(T* entry) {
+            entryCount++;
+            entry->prev = tail;
+            if (tail) {
+                tail->next = entry;
+            } else {
+                head = entry;
+            }
+            entry->next = nullptr;
+            tail = entry;
+        }
+
+        inline void enqueueAtHead(T* entry) {
+            entryCount++;
+            entry->next = head;
+            if (head) {
+                head->prev = entry;
+            } else {
+                tail = entry;
+            }
+            entry->prev = nullptr;
+            head = entry;
+        }
+
+        inline void dequeue(T* entry) {
+            entryCount--;
+            if (entry->prev) {
+                entry->prev->next = entry->next;
+            } else {
+                head = entry->next;
+            }
+            if (entry->next) {
+                entry->next->prev = entry->prev;
+            } else {
+                tail = entry->prev;
+            }
+        }
+
+        inline T* dequeueAtHead() {
+            entryCount--;
+            T* entry = head;
+            head = entry->next;
+            if (head) {
+                head->prev = nullptr;
+            } else {
+                tail = nullptr;
+            }
+            return entry;
+        }
+
+        uint32_t count() const {
+            return entryCount;
+        }
+    };
+
+    /* Specifies which events are to be canceled and why. */
+    struct CancelationOptions {
+        enum Mode {
+            CANCEL_ALL_EVENTS = 0,
+            CANCEL_POINTER_EVENTS = 1,
+            CANCEL_NON_POINTER_EVENTS = 2,
+            CANCEL_FALLBACK_EVENTS = 3,
+        };
+
+        // The criterion to use to determine which events should be canceled.
+        Mode mode;
+
+        // Descriptive reason for the cancelation.
+        const char* reason;
+
+        // The specific keycode of the key event to cancel, or nullopt to cancel any key event.
+        std::optional<int32_t> keyCode = std::nullopt;
+
+        // The specific device id of events to cancel, or nullopt to cancel events from any device.
+        std::optional<int32_t> deviceId = std::nullopt;
+
+        // The specific display id of events to cancel, or nullopt to cancel events on any display.
+        std::optional<int32_t> displayId = std::nullopt;
+
+        CancelationOptions(Mode mode, const char* reason) : mode(mode), reason(reason) { }
+    };
+
+    /* Tracks dispatched key and motion event state so that cancelation events can be
+     * synthesized when events are dropped. */
+    class InputState {
+    public:
+        InputState();
+        ~InputState();
+
+        // Returns true if there is no state to be canceled.
+        bool isNeutral() const;
+
+        // Returns true if the specified source is known to have received a hover enter
+        // motion event.
+        bool isHovering(int32_t deviceId, uint32_t source, int32_t displayId) const;
+
+        // Records tracking information for a key event that has just been published.
+        // Returns true if the event should be delivered, false if it is inconsistent
+        // and should be skipped.
+        bool trackKey(const KeyEntry* entry, int32_t action, int32_t flags);
+
+        // Records tracking information for a motion event that has just been published.
+        // Returns true if the event should be delivered, false if it is inconsistent
+        // and should be skipped.
+        bool trackMotion(const MotionEntry* entry, int32_t action, int32_t flags);
+
+        // Synthesizes cancelation events for the current state and resets the tracked state.
+        void synthesizeCancelationEvents(nsecs_t currentTime,
+                std::vector<EventEntry*>& outEvents, const CancelationOptions& options);
+
+        // Clears the current state.
+        void clear();
+
+        // Copies pointer-related parts of the input state to another instance.
+        void copyPointerStateTo(InputState& other) const;
+
+        // Gets the fallback key associated with a keycode.
+        // Returns -1 if none.
+        // Returns AKEYCODE_UNKNOWN if we are only dispatching the unhandled key to the policy.
+        int32_t getFallbackKey(int32_t originalKeyCode);
+
+        // Sets the fallback key for a particular keycode.
+        void setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode);
+
+        // Removes the fallback key for a particular keycode.
+        void removeFallbackKey(int32_t originalKeyCode);
+
+        inline const KeyedVector<int32_t, int32_t>& getFallbackKeys() const {
+            return mFallbackKeys;
+        }
+
+    private:
+        struct KeyMemento {
+            int32_t deviceId;
+            uint32_t source;
+            int32_t displayId;
+            int32_t keyCode;
+            int32_t scanCode;
+            int32_t metaState;
+            int32_t flags;
+            nsecs_t downTime;
+            uint32_t policyFlags;
+        };
+
+        struct MotionMemento {
+            int32_t deviceId;
+            uint32_t source;
+            int32_t displayId;
+            int32_t flags;
+            float xPrecision;
+            float yPrecision;
+            nsecs_t downTime;
+            uint32_t pointerCount;
+            PointerProperties pointerProperties[MAX_POINTERS];
+            PointerCoords pointerCoords[MAX_POINTERS];
+            bool hovering;
+            uint32_t policyFlags;
+
+            void setPointers(const MotionEntry* entry);
+        };
+
+        std::vector<KeyMemento> mKeyMementos;
+        std::vector<MotionMemento> mMotionMementos;
+        KeyedVector<int32_t, int32_t> mFallbackKeys;
+
+        ssize_t findKeyMemento(const KeyEntry* entry) const;
+        ssize_t findMotionMemento(const MotionEntry* entry, bool hovering) const;
+
+        void addKeyMemento(const KeyEntry* entry, int32_t flags);
+        void addMotionMemento(const MotionEntry* entry, int32_t flags, bool hovering);
+
+        static bool shouldCancelKey(const KeyMemento& memento,
+                const CancelationOptions& options);
+        static bool shouldCancelMotion(const MotionMemento& memento,
+                const CancelationOptions& options);
+    };
+
+    /* Manages the dispatch state associated with a single input channel. */
+    class Connection : public RefBase {
+    protected:
+        virtual ~Connection();
+
+    public:
+        enum Status {
+            // Everything is peachy.
+            STATUS_NORMAL,
+            // An unrecoverable communication error has occurred.
+            STATUS_BROKEN,
+            // The input channel has been unregistered.
+            STATUS_ZOMBIE
+        };
+
+        Status status;
+        sp<InputChannel> inputChannel; // never null
+        bool monitor;
+        InputPublisher inputPublisher;
+        InputState inputState;
+
+        // True if the socket is full and no further events can be published until
+        // the application consumes some of the input.
+        bool inputPublisherBlocked;
+
+        // Queue of events that need to be published to the connection.
+        Queue<DispatchEntry> outboundQueue;
+
+        // Queue of events that have been published to the connection but that have not
+        // yet received a "finished" response from the application.
+        Queue<DispatchEntry> waitQueue;
+
+        explicit Connection(const sp<InputChannel>& inputChannel, bool monitor);
+
+        inline const std::string getInputChannelName() const { return inputChannel->getName(); }
+
+        const std::string getWindowName() const;
+        const char* getStatusLabel() const;
+
+        DispatchEntry* findWaitQueueEntry(uint32_t seq);
+    };
+
+    struct Monitor {
+        sp<InputChannel> inputChannel; // never null
+
+        explicit Monitor(const sp<InputChannel>& inputChannel);
+    };
+
+    enum DropReason {
+        DROP_REASON_NOT_DROPPED = 0,
+        DROP_REASON_POLICY = 1,
+        DROP_REASON_APP_SWITCH = 2,
+        DROP_REASON_DISABLED = 3,
+        DROP_REASON_BLOCKED = 4,
+        DROP_REASON_STALE = 5,
+    };
+
+    sp<InputDispatcherPolicyInterface> mPolicy;
+    InputDispatcherConfiguration mConfig;
+
+    std::mutex mLock;
+
+    std::condition_variable mDispatcherIsAlive;
+
+    sp<Looper> mLooper;
+
+    EventEntry* mPendingEvent GUARDED_BY(mLock);
+    Queue<EventEntry> mInboundQueue GUARDED_BY(mLock);
+    Queue<EventEntry> mRecentQueue GUARDED_BY(mLock);
+    Queue<CommandEntry> mCommandQueue GUARDED_BY(mLock);
+
+    DropReason mLastDropReason GUARDED_BY(mLock);
+
+    void dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) REQUIRES(mLock);
+
+    // Enqueues an inbound event.  Returns true if mLooper->wake() should be called.
+    bool enqueueInboundEventLocked(EventEntry* entry) REQUIRES(mLock);
+
+    // Cleans up input state when dropping an inbound event.
+    void dropInboundEventLocked(EventEntry* entry, DropReason dropReason) REQUIRES(mLock);
+
+    // Adds an event to a queue of recent events for debugging purposes.
+    void addRecentEventLocked(EventEntry* entry) REQUIRES(mLock);
+
+    // App switch latency optimization.
+    bool mAppSwitchSawKeyDown GUARDED_BY(mLock);
+    nsecs_t mAppSwitchDueTime GUARDED_BY(mLock);
+
+    bool isAppSwitchKeyEvent(KeyEntry* keyEntry);
+    bool isAppSwitchPendingLocked() REQUIRES(mLock);
+    void resetPendingAppSwitchLocked(bool handled) REQUIRES(mLock);
+
+    // Stale event latency optimization.
+    static bool isStaleEvent(nsecs_t currentTime, EventEntry* entry);
+
+    // Blocked event latency optimization.  Drops old events when the user intends
+    // to transfer focus to a new application.
+    EventEntry* mNextUnblockedEvent GUARDED_BY(mLock);
+
+    sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y,
+            bool addOutsideTargets = false, bool addPortalWindows = false) REQUIRES(mLock);
+
+    // All registered connections mapped by channel file descriptor.
+    KeyedVector<int, sp<Connection> > mConnectionsByFd GUARDED_BY(mLock);
+
+    struct IBinderHash {
+        std::size_t operator()(const sp<IBinder>& b) const {
+            return std::hash<IBinder *>{}(b.get());
+        }
+    };
+    std::unordered_map<sp<IBinder>, sp<InputChannel>, IBinderHash> mInputChannelsByToken
+            GUARDED_BY(mLock);
+
+    // Finds the display ID of the gesture monitor identified by the provided token.
+    std::optional<int32_t> findGestureMonitorDisplayByTokenLocked(const sp<IBinder>& token)
+            REQUIRES(mLock);
+
+    ssize_t getConnectionIndexLocked(const sp<InputChannel>& inputChannel) REQUIRES(mLock);
+
+    // Input channels that will receive a copy of all input events sent to the provided display.
+    std::unordered_map<int32_t, std::vector<Monitor>> mGlobalMonitorsByDisplay
+            GUARDED_BY(mLock);
+
+    // Input channels that will receive pointer events that start within the corresponding display.
+    // These are a bit special when compared to global monitors since they'll cause gesture streams
+    // to continue even when there isn't a touched window,and have the ability to steal the rest of
+    // the pointer stream in order to claim it for a system gesture.
+    std::unordered_map<int32_t, std::vector<Monitor>> mGestureMonitorsByDisplay
+            GUARDED_BY(mLock);
+
+
+    // Event injection and synchronization.
+    std::condition_variable mInjectionResultAvailable;
+    bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
+    void setInjectionResult(EventEntry* entry, int32_t injectionResult);
+
+    std::condition_variable mInjectionSyncFinished;
+    void incrementPendingForegroundDispatches(EventEntry* entry);
+    void decrementPendingForegroundDispatches(EventEntry* entry);
+
+    // Key repeat tracking.
+    struct KeyRepeatState {
+        KeyEntry* lastKeyEntry; // or null if no repeat
+        nsecs_t nextRepeatTime;
+    } mKeyRepeatState GUARDED_BY(mLock);
+
+    void resetKeyRepeatLocked() REQUIRES(mLock);
+    KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime) REQUIRES(mLock);
+
+    // Key replacement tracking
+    struct KeyReplacement {
+        int32_t keyCode;
+        int32_t deviceId;
+        bool operator==(const KeyReplacement& rhs) const {
+            return keyCode == rhs.keyCode && deviceId == rhs.deviceId;
+        }
+        bool operator<(const KeyReplacement& rhs) const {
+            return keyCode != rhs.keyCode ? keyCode < rhs.keyCode : deviceId < rhs.deviceId;
+        }
+    };
+    // Maps the key code replaced, device id tuple to the key code it was replaced with
+    KeyedVector<KeyReplacement, int32_t> mReplacedKeys GUARDED_BY(mLock);
+    // Process certain Meta + Key combinations
+    void accelerateMetaShortcuts(const int32_t deviceId, const int32_t action,
+            int32_t& keyCode, int32_t& metaState);
+
+    // Deferred command processing.
+    bool haveCommandsLocked() const REQUIRES(mLock);
+    bool runCommandsLockedInterruptible() REQUIRES(mLock);
+    CommandEntry* postCommandLocked(Command command) REQUIRES(mLock);
+
+    // Input filter processing.
+    bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) REQUIRES(mLock);
+    bool shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) REQUIRES(mLock);
+
+    // Inbound event processing.
+    void drainInboundQueueLocked() REQUIRES(mLock);
+    void releasePendingEventLocked() REQUIRES(mLock);
+    void releaseInboundEventLocked(EventEntry* entry) REQUIRES(mLock);
+
+    // Dispatch state.
+    bool mDispatchEnabled GUARDED_BY(mLock);
+    bool mDispatchFrozen GUARDED_BY(mLock);
+    bool mInputFilterEnabled GUARDED_BY(mLock);
+
+    std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mWindowHandlesByDisplay
+            GUARDED_BY(mLock);
+    // Get window handles by display, return an empty vector if not found.
+    std::vector<sp<InputWindowHandle>> getWindowHandlesLocked(int32_t displayId) const
+            REQUIRES(mLock);
+    sp<InputWindowHandle> getWindowHandleLocked(const sp<IBinder>& windowHandleToken) const
+            REQUIRES(mLock);
+    sp<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken) const REQUIRES(mLock);
+    bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock);
+
+    // Focus tracking for keys, trackball, etc.
+    std::unordered_map<int32_t, sp<InputWindowHandle>> mFocusedWindowHandlesByDisplay
+            GUARDED_BY(mLock);
+
+    // Focus tracking for touch.
+    struct TouchedWindow {
+        sp<InputWindowHandle> windowHandle;
+        int32_t targetFlags;
+        BitSet32 pointerIds;        // zero unless target flag FLAG_SPLIT is set
+    };
+
+    // For tracking the offsets we need to apply when adding gesture monitor targets.
+    struct TouchedMonitor {
+        Monitor monitor;
+        float xOffset = 0.f;
+        float yOffset = 0.f;
+
+        explicit TouchedMonitor(const Monitor& monitor, float xOffset, float yOffset);
+    };
+
+    struct TouchState {
+        bool down;
+        bool split;
+        int32_t deviceId; // id of the device that is currently down, others are rejected
+        uint32_t source;  // source of the device that is current down, others are rejected
+        int32_t displayId; // id to the display that currently has a touch, others are rejected
+        std::vector<TouchedWindow> windows;
+
+        // This collects the portal windows that the touch has gone through. Each portal window
+        // targets a display (embedded display for most cases). With this info, we can add the
+        // monitoring channels of the displays touched.
+        std::vector<sp<InputWindowHandle>> portalWindows;
+
+        std::vector<TouchedMonitor> gestureMonitors;
+
+        TouchState();
+        ~TouchState();
+        void reset();
+        void copyFrom(const TouchState& other);
+        void addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
+                int32_t targetFlags, BitSet32 pointerIds);
+        void addPortalWindow(const sp<InputWindowHandle>& windowHandle);
+        void addGestureMonitors(const std::vector<TouchedMonitor>& monitors);
+        void removeWindow(const sp<InputWindowHandle>& windowHandle);
+        void removeWindowByToken(const sp<IBinder>& token);
+        void filterNonAsIsTouchWindows();
+        void filterNonMonitors();
+        sp<InputWindowHandle> getFirstForegroundWindowHandle() const;
+        bool isSlippery() const;
+    };
+
+    KeyedVector<int32_t, TouchState> mTouchStatesByDisplay GUARDED_BY(mLock);
+    TouchState mTempTouchState GUARDED_BY(mLock);
+
+    // Focused applications.
+    std::unordered_map<int32_t, sp<InputApplicationHandle>> mFocusedApplicationHandlesByDisplay
+            GUARDED_BY(mLock);
+
+    // Top focused display.
+    int32_t mFocusedDisplayId GUARDED_BY(mLock);
+
+    // Dispatcher state at time of last ANR.
+    std::string mLastANRState GUARDED_BY(mLock);
+
+    // Dispatch inbound events.
+    bool dispatchConfigurationChangedLocked(
+            nsecs_t currentTime, ConfigurationChangedEntry* entry) REQUIRES(mLock);
+    bool dispatchDeviceResetLocked(
+            nsecs_t currentTime, DeviceResetEntry* entry) REQUIRES(mLock);
+    bool dispatchKeyLocked(
+            nsecs_t currentTime, KeyEntry* entry,
+            DropReason* dropReason, nsecs_t* nextWakeupTime) REQUIRES(mLock);
+    bool dispatchMotionLocked(
+            nsecs_t currentTime, MotionEntry* entry,
+            DropReason* dropReason, nsecs_t* nextWakeupTime) REQUIRES(mLock);
+    void dispatchEventLocked(nsecs_t currentTime, EventEntry* entry,
+            const std::vector<InputTarget>& inputTargets) REQUIRES(mLock);
+
+    void logOutboundKeyDetails(const char* prefix, const KeyEntry* entry);
+    void logOutboundMotionDetails(const char* prefix, const MotionEntry* entry);
+
+    // Keeping track of ANR timeouts.
+    enum InputTargetWaitCause {
+        INPUT_TARGET_WAIT_CAUSE_NONE,
+        INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY,
+        INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY,
+    };
+
+    InputTargetWaitCause mInputTargetWaitCause GUARDED_BY(mLock);
+    nsecs_t mInputTargetWaitStartTime GUARDED_BY(mLock);
+    nsecs_t mInputTargetWaitTimeoutTime GUARDED_BY(mLock);
+    bool mInputTargetWaitTimeoutExpired GUARDED_BY(mLock);
+    sp<IBinder> mInputTargetWaitApplicationToken GUARDED_BY(mLock);
+
+    // Contains the last window which received a hover event.
+    sp<InputWindowHandle> mLastHoverWindowHandle GUARDED_BY(mLock);
+
+    // Finding targets for input events.
+    int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry,
+            const sp<InputApplicationHandle>& applicationHandle,
+            const sp<InputWindowHandle>& windowHandle,
+            nsecs_t* nextWakeupTime, const char* reason) REQUIRES(mLock);
+
+    void removeWindowByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock);
+
+    void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
+            const sp<InputChannel>& inputChannel) REQUIRES(mLock);
+    nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime) REQUIRES(mLock);
+    void resetANRTimeoutsLocked() REQUIRES(mLock);
+
+    int32_t getTargetDisplayId(const EventEntry* entry);
+    int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry* entry,
+            std::vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) REQUIRES(mLock);
+    int32_t findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry,
+            std::vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,
+            bool* outConflictingPointerActions) REQUIRES(mLock);
+    std::vector<TouchedMonitor> findTouchedGestureMonitorsLocked(int32_t displayId,
+            const std::vector<sp<InputWindowHandle>>& portalWindows) REQUIRES(mLock);
+    void addGestureMonitors(const std::vector<Monitor>& monitors,
+            std::vector<TouchedMonitor>& outTouchedMonitors, float xOffset = 0, float yOffset = 0);
+
+    void addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
+            int32_t targetFlags, BitSet32 pointerIds, std::vector<InputTarget>& inputTargets)
+            REQUIRES(mLock);
+    void addMonitoringTargetLocked(const Monitor& monitor, float xOffset, float yOffset,
+            std::vector<InputTarget>& inputTargets) REQUIRES(mLock);
+    void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
+            int32_t displayId, float xOffset = 0, float yOffset = 0) REQUIRES(mLock);
+
+    void pokeUserActivityLocked(const EventEntry* eventEntry) REQUIRES(mLock);
+    bool checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
+            const InjectionState* injectionState);
+    bool isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle,
+            int32_t x, int32_t y) const REQUIRES(mLock);
+    bool isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock);
+    std::string getApplicationWindowLabel(const sp<InputApplicationHandle>& applicationHandle,
+            const sp<InputWindowHandle>& windowHandle);
+
+    std::string checkWindowReadyForMoreInputLocked(nsecs_t currentTime,
+            const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry,
+            const char* targetType) REQUIRES(mLock);
+
+    // Manage the dispatch cycle for a single connection.
+    // These methods are deliberately not Interruptible because doing all of the work
+    // with the mutex held makes it easier to ensure that connection invariants are maintained.
+    // If needed, the methods post commands to run later once the critical bits are done.
+    void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
+            EventEntry* eventEntry, const InputTarget* inputTarget) REQUIRES(mLock);
+    void enqueueDispatchEntriesLocked(nsecs_t currentTime, const sp<Connection>& connection,
+            EventEntry* eventEntry, const InputTarget* inputTarget) REQUIRES(mLock);
+    void enqueueDispatchEntryLocked(const sp<Connection>& connection,
+            EventEntry* eventEntry, const InputTarget* inputTarget, int32_t dispatchMode)
+            REQUIRES(mLock);
+    void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection)
+            REQUIRES(mLock);
+    void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
+            uint32_t seq, bool handled) REQUIRES(mLock);
+    void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
+            bool notify) REQUIRES(mLock);
+    void drainDispatchQueue(Queue<DispatchEntry>* queue);
+    void releaseDispatchEntry(DispatchEntry* dispatchEntry);
+    static int handleReceiveCallback(int fd, int events, void* data);
+    // The action sent should only be of type AMOTION_EVENT_*
+    void dispatchPointerDownOutsideFocus(uint32_t source, int32_t action,
+            const sp<IBinder>& newToken) REQUIRES(mLock);
+
+    void synthesizeCancelationEventsForAllConnectionsLocked(
+            const CancelationOptions& options) REQUIRES(mLock);
+    void synthesizeCancelationEventsForMonitorsLocked(
+            const CancelationOptions& options) REQUIRES(mLock);
+    void synthesizeCancelationEventsForMonitorsLocked(const CancelationOptions& options,
+            std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) REQUIRES(mLock);
+    void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel,
+            const CancelationOptions& options) REQUIRES(mLock);
+    void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
+            const CancelationOptions& options) REQUIRES(mLock);
+
+    // Splitting motion events across windows.
+    MotionEntry* splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds);
+
+    // Reset and drop everything the dispatcher is doing.
+    void resetAndDropEverythingLocked(const char* reason) REQUIRES(mLock);
+
+    // Dump state.
+    void dumpDispatchStateLocked(std::string& dump) REQUIRES(mLock);
+    void dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors);
+    void logDispatchStateLocked() REQUIRES(mLock);
+
+    // Registration.
+    void removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) REQUIRES(mLock);
+    void removeMonitorChannelLocked(const sp<InputChannel>& inputChannel,
+        std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay)
+            REQUIRES(mLock);
+    status_t unregisterInputChannelLocked(const sp<InputChannel>& inputChannel, bool notify)
+            REQUIRES(mLock);
+
+    // Interesting events that we might like to log or tell the framework about.
+    void onDispatchCycleFinishedLocked(
+            nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled)
+             REQUIRES(mLock);
+    void onDispatchCycleBrokenLocked(
+            nsecs_t currentTime, const sp<Connection>& connection) REQUIRES(mLock);
+    void onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
+            const sp<InputWindowHandle>& newFocus) REQUIRES(mLock);
+    void onANRLocked(
+            nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
+            const sp<InputWindowHandle>& windowHandle,
+            nsecs_t eventTime, nsecs_t waitStartTime, const char* reason) REQUIRES(mLock);
+
+    // Outbound policy interactions.
+    void doNotifyConfigurationChangedLockedInterruptible(CommandEntry* commandEntry)
+            REQUIRES(mLock);
+    void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
+    void doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
+    void doNotifyANRLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
+    void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry)
+            REQUIRES(mLock);
+    void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
+    bool afterKeyEventLockedInterruptible(const sp<Connection>& connection,
+            DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled) REQUIRES(mLock);
+    bool afterMotionEventLockedInterruptible(const sp<Connection>& connection,
+            DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled) REQUIRES(mLock);
+    void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
+    void initializeKeyEvent(KeyEvent* event, const KeyEntry* entry);
+    void doOnPointerDownOutsideFocusLockedInterruptible(CommandEntry* commandEntry)
+            REQUIRES(mLock);
+
+    // Statistics gathering.
+    void updateDispatchStatistics(nsecs_t currentTime, const EventEntry* entry,
+            int32_t injectionResult, nsecs_t timeSpentWaitingForApplication);
+    void traceInboundQueueLengthLocked() REQUIRES(mLock);
+    void traceOutboundQueueLength(const sp<Connection>& connection);
+    void traceWaitQueueLength(const sp<Connection>& connection);
+
+    sp<InputReporterInterface> mReporter;
+};
+
+/* Enqueues and dispatches input events, endlessly. */
+class InputDispatcherThread : public Thread {
+public:
+    explicit InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher);
+    ~InputDispatcherThread();
+
+private:
+    virtual bool threadLoop();
+
+    sp<InputDispatcherInterface> mDispatcher;
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_DISPATCHER_H
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 359325f..52e9080 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -19,8 +19,6 @@
 //#define LOG_NDEBUG 0
 
 #include "InputManager.h"
-#include "InputDispatcherFactory.h"
-#include "InputDispatcherThread.h"
 #include "InputReaderFactory.h"
 
 #include <binder/IPCThreadState.h>
@@ -35,7 +33,7 @@
 InputManager::InputManager(
         const sp<InputReaderPolicyInterface>& readerPolicy,
         const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
-    mDispatcher = createInputDispatcher(dispatcherPolicy);
+    mDispatcher = new InputDispatcher(dispatcherPolicy);
     mClassifier = new InputClassifier(mDispatcher);
     mReader = createInputReader(readerPolicy, mClassifier);
     initialize();
@@ -119,10 +117,6 @@
     }
 }
 
-void InputManager::transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) {
-    mDispatcher->transferTouchFocus(fromToken, toToken);
-}
-
 // Used by tests only.
 void InputManager::registerInputChannel(const sp<InputChannel>& channel) {
     IPCThreadState* ipc = IPCThreadState::self();
@@ -139,4 +133,8 @@
     mDispatcher->unregisterInputChannel(channel);
 }
 
+void InputManager::setMotionClassifierEnabled(bool enabled) {
+    mClassifier->setMotionClassifierEnabled(enabled);
+}
+
 } // namespace android
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index f3da324..c75611f 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -21,14 +21,15 @@
  * Native input manager.
  */
 
-#include "InputClassifier.h"
+#include "EventHub.h"
 #include "InputReaderBase.h"
+#include "InputClassifier.h"
+#include "InputDispatcher.h"
+#include "InputReader.h"
 
-#include <InputDispatcherInterface.h>
-#include <InputDispatcherPolicyInterface.h>
-#include <input/ISetInputWindowsListener.h>
 #include <input/Input.h>
 #include <input/InputTransport.h>
+#include <input/ISetInputWindowsListener.h>
 
 #include <input/IInputFlinger.h>
 #include <utils/Errors.h>
@@ -38,7 +39,6 @@
 
 namespace android {
 class InputChannel;
-class InputDispatcherThread;
 
 /*
  * The input manager is the core of the system event processing.
@@ -96,11 +96,12 @@
 
     virtual void setInputWindows(const std::vector<InputWindowInfo>& handles,
             const sp<ISetInputWindowsListener>& setInputWindowsListener);
-    virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
 
     virtual void registerInputChannel(const sp<InputChannel>& channel);
     virtual void unregisterInputChannel(const sp<InputChannel>& channel);
 
+    void setMotionClassifierEnabled(bool enabled);
+
 private:
     sp<InputReaderInterface> mReader;
     sp<InputReaderThread> mReaderThread;
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
new file mode 100644
index 0000000..a45b8a5
--- /dev/null
+++ b/services/inputflinger/InputReader.cpp
@@ -0,0 +1,7534 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#define LOG_TAG "InputReader"
+
+//#define LOG_NDEBUG 0
+
+// Log debug messages for each raw event received from the EventHub.
+#define DEBUG_RAW_EVENTS 0
+
+// Log debug messages about touch screen filtering hacks.
+#define DEBUG_HACKS 0
+
+// Log debug messages about virtual key processing.
+#define DEBUG_VIRTUAL_KEYS 0
+
+// Log debug messages about pointers.
+#define DEBUG_POINTERS 0
+
+// Log debug messages about pointer assignment calculations.
+#define DEBUG_POINTER_ASSIGNMENT 0
+
+// Log debug messages about gesture detection.
+#define DEBUG_GESTURES 0
+
+// Log debug messages about the vibrator.
+#define DEBUG_VIBRATOR 0
+
+// Log debug messages about fusing stylus data.
+#define DEBUG_STYLUS_FUSION 0
+
+#include "InputReader.h"
+
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <math.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <log/log.h>
+
+#include <android-base/stringprintf.h>
+#include <input/Keyboard.h>
+#include <input/VirtualKeyMap.h>
+#include <statslog.h>
+
+#define INDENT "  "
+#define INDENT2 "    "
+#define INDENT3 "      "
+#define INDENT4 "        "
+#define INDENT5 "          "
+
+using android::base::StringPrintf;
+
+namespace android {
+
+// --- Constants ---
+
+// Maximum number of slots supported when using the slot-based Multitouch Protocol B.
+static constexpr size_t MAX_SLOTS = 32;
+
+// Maximum amount of latency to add to touch events while waiting for data from an
+// external stylus.
+static constexpr nsecs_t EXTERNAL_STYLUS_DATA_TIMEOUT = ms2ns(72);
+
+// Maximum amount of time to wait on touch data before pushing out new pressure data.
+static constexpr nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20);
+
+// Artificial latency on synthetic events created from stylus data without corresponding touch
+// data.
+static constexpr nsecs_t STYLUS_DATA_LATENCY = ms2ns(10);
+
+// How often to report input event statistics
+static constexpr nsecs_t STATISTICS_REPORT_FREQUENCY = seconds_to_nanoseconds(5 * 60);
+
+// --- Static Functions ---
+
+template<typename T>
+inline static T abs(const T& value) {
+    return value < 0 ? - value : value;
+}
+
+template<typename T>
+inline static T min(const T& a, const T& b) {
+    return a < b ? a : b;
+}
+
+template<typename T>
+inline static void swap(T& a, T& b) {
+    T temp = a;
+    a = b;
+    b = temp;
+}
+
+inline static float avg(float x, float y) {
+    return (x + y) / 2;
+}
+
+inline static float distance(float x1, float y1, float x2, float y2) {
+    return hypotf(x1 - x2, y1 - y2);
+}
+
+inline static int32_t signExtendNybble(int32_t value) {
+    return value >= 8 ? value - 16 : value;
+}
+
+static inline const char* toString(bool value) {
+    return value ? "true" : "false";
+}
+
+static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
+        const int32_t map[][4], size_t mapSize) {
+    if (orientation != DISPLAY_ORIENTATION_0) {
+        for (size_t i = 0; i < mapSize; i++) {
+            if (value == map[i][0]) {
+                return map[i][orientation];
+            }
+        }
+    }
+    return value;
+}
+
+static const int32_t keyCodeRotationMap[][4] = {
+        // key codes enumerated counter-clockwise with the original (unrotated) key first
+        // no rotation,        90 degree rotation,  180 degree rotation, 270 degree rotation
+        { AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT },
+        { AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN },
+        { AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT },
+        { AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP },
+        { AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT,
+            AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT },
+        { AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP,
+            AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN },
+        { AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT,
+            AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT },
+        { AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN,
+            AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP },
+};
+static const size_t keyCodeRotationMapSize =
+        sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
+
+static int32_t rotateStemKey(int32_t value, int32_t orientation,
+        const int32_t map[][2], size_t mapSize) {
+    if (orientation == DISPLAY_ORIENTATION_180) {
+        for (size_t i = 0; i < mapSize; i++) {
+            if (value == map[i][0]) {
+                return map[i][1];
+            }
+        }
+    }
+    return value;
+}
+
+// The mapping can be defined using input device configuration properties keyboard.rotated.stem_X
+static int32_t stemKeyRotationMap[][2] = {
+        // key codes enumerated with the original (unrotated) key first
+        // no rotation,           180 degree rotation
+        { AKEYCODE_STEM_PRIMARY, AKEYCODE_STEM_PRIMARY },
+        { AKEYCODE_STEM_1,       AKEYCODE_STEM_1 },
+        { AKEYCODE_STEM_2,       AKEYCODE_STEM_2 },
+        { AKEYCODE_STEM_3,       AKEYCODE_STEM_3 },
+};
+static const size_t stemKeyRotationMapSize =
+        sizeof(stemKeyRotationMap) / sizeof(stemKeyRotationMap[0]);
+
+static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
+    keyCode = rotateStemKey(keyCode, orientation,
+            stemKeyRotationMap, stemKeyRotationMapSize);
+    return rotateValueUsingRotationMap(keyCode, orientation,
+            keyCodeRotationMap, keyCodeRotationMapSize);
+}
+
+static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) {
+    float temp;
+    switch (orientation) {
+    case DISPLAY_ORIENTATION_90:
+        temp = *deltaX;
+        *deltaX = *deltaY;
+        *deltaY = -temp;
+        break;
+
+    case DISPLAY_ORIENTATION_180:
+        *deltaX = -*deltaX;
+        *deltaY = -*deltaY;
+        break;
+
+    case DISPLAY_ORIENTATION_270:
+        temp = *deltaX;
+        *deltaX = -*deltaY;
+        *deltaY = temp;
+        break;
+    }
+}
+
+static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
+    return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
+}
+
+// Returns true if the pointer should be reported as being down given the specified
+// button states.  This determines whether the event is reported as a touch event.
+static bool isPointerDown(int32_t buttonState) {
+    return buttonState &
+            (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY
+                    | AMOTION_EVENT_BUTTON_TERTIARY);
+}
+
+static float calculateCommonVector(float a, float b) {
+    if (a > 0 && b > 0) {
+        return a < b ? a : b;
+    } else if (a < 0 && b < 0) {
+        return a > b ? a : b;
+    } else {
+        return 0;
+    }
+}
+
+static void synthesizeButtonKey(InputReaderContext* context, int32_t action,
+        nsecs_t when, int32_t deviceId, uint32_t source, int32_t displayId,
+        uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState,
+        int32_t buttonState, int32_t keyCode) {
+    if (
+            (action == AKEY_EVENT_ACTION_DOWN
+                    && !(lastButtonState & buttonState)
+                    && (currentButtonState & buttonState))
+            || (action == AKEY_EVENT_ACTION_UP
+                    && (lastButtonState & buttonState)
+                    && !(currentButtonState & buttonState))) {
+        NotifyKeyArgs args(context->getNextSequenceNum(), when, deviceId, source, displayId,
+                policyFlags, action, 0, keyCode, 0, context->getGlobalMetaState(), when);
+        context->getListener()->notifyKey(&args);
+    }
+}
+
+static void synthesizeButtonKeys(InputReaderContext* context, int32_t action,
+        nsecs_t when, int32_t deviceId, uint32_t source, int32_t displayId,
+        uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) {
+    synthesizeButtonKey(context, action, when, deviceId, source, displayId, policyFlags,
+            lastButtonState, currentButtonState,
+            AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK);
+    synthesizeButtonKey(context, action, when, deviceId, source, displayId, policyFlags,
+            lastButtonState, currentButtonState,
+            AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD);
+}
+
+
+// --- InputReader ---
+
+InputReader::InputReader(const sp<EventHubInterface>& eventHub,
+        const sp<InputReaderPolicyInterface>& policy,
+        const sp<InputListenerInterface>& listener) :
+        mContext(this), mEventHub(eventHub), mPolicy(policy),
+        mNextSequenceNum(1), mGlobalMetaState(0), mGeneration(1),
+        mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
+        mConfigurationChangesToRefresh(0) {
+    mQueuedListener = new QueuedInputListener(listener);
+
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        refreshConfigurationLocked(0);
+        updateGlobalMetaStateLocked();
+    } // release lock
+}
+
+InputReader::~InputReader() {
+    for (size_t i = 0; i < mDevices.size(); i++) {
+        delete mDevices.valueAt(i);
+    }
+}
+
+void InputReader::loopOnce() {
+    int32_t oldGeneration;
+    int32_t timeoutMillis;
+    bool inputDevicesChanged = false;
+    std::vector<InputDeviceInfo> inputDevices;
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        oldGeneration = mGeneration;
+        timeoutMillis = -1;
+
+        uint32_t changes = mConfigurationChangesToRefresh;
+        if (changes) {
+            mConfigurationChangesToRefresh = 0;
+            timeoutMillis = 0;
+            refreshConfigurationLocked(changes);
+        } else if (mNextTimeout != LLONG_MAX) {
+            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+            timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
+        }
+    } // release lock
+
+    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
+
+    { // acquire lock
+        AutoMutex _l(mLock);
+        mReaderIsAliveCondition.broadcast();
+
+        if (count) {
+            processEventsLocked(mEventBuffer, count);
+        }
+
+        if (mNextTimeout != LLONG_MAX) {
+            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+            if (now >= mNextTimeout) {
+#if DEBUG_RAW_EVENTS
+                ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
+#endif
+                mNextTimeout = LLONG_MAX;
+                timeoutExpiredLocked(now);
+            }
+        }
+
+        if (oldGeneration != mGeneration) {
+            inputDevicesChanged = true;
+            getInputDevicesLocked(inputDevices);
+        }
+    } // release lock
+
+    // Send out a message that the describes the changed input devices.
+    if (inputDevicesChanged) {
+        mPolicy->notifyInputDevicesChanged(inputDevices);
+    }
+
+    // Flush queued events out to the listener.
+    // This must happen outside of the lock because the listener could potentially call
+    // back into the InputReader's methods, such as getScanCodeState, or become blocked
+    // on another thread similarly waiting to acquire the InputReader lock thereby
+    // resulting in a deadlock.  This situation is actually quite plausible because the
+    // listener is actually the input dispatcher, which calls into the window manager,
+    // which occasionally calls into the input reader.
+    mQueuedListener->flush();
+}
+
+void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
+    for (const RawEvent* rawEvent = rawEvents; count;) {
+        int32_t type = rawEvent->type;
+        size_t batchSize = 1;
+        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
+            int32_t deviceId = rawEvent->deviceId;
+            while (batchSize < count) {
+                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
+                        || rawEvent[batchSize].deviceId != deviceId) {
+                    break;
+                }
+                batchSize += 1;
+            }
+#if DEBUG_RAW_EVENTS
+            ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
+#endif
+            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
+        } else {
+            switch (rawEvent->type) {
+            case EventHubInterface::DEVICE_ADDED:
+                addDeviceLocked(rawEvent->when, rawEvent->deviceId);
+                break;
+            case EventHubInterface::DEVICE_REMOVED:
+                removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
+                break;
+            case EventHubInterface::FINISHED_DEVICE_SCAN:
+                handleConfigurationChangedLocked(rawEvent->when);
+                break;
+            default:
+                ALOG_ASSERT(false); // can't happen
+                break;
+            }
+        }
+        count -= batchSize;
+        rawEvent += batchSize;
+    }
+}
+
+void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
+    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+    if (deviceIndex >= 0) {
+        ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
+        return;
+    }
+
+    InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
+    uint32_t classes = mEventHub->getDeviceClasses(deviceId);
+    int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
+
+    InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
+    device->configure(when, &mConfig, 0);
+    device->reset(when);
+
+    if (device->isIgnored()) {
+        ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
+                identifier.name.c_str());
+    } else {
+        ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
+                identifier.name.c_str(), device->getSources());
+    }
+
+    mDevices.add(deviceId, device);
+    bumpGenerationLocked();
+
+    if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
+        notifyExternalStylusPresenceChanged();
+    }
+}
+
+void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
+    InputDevice* device = nullptr;
+    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+    if (deviceIndex < 0) {
+        ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
+        return;
+    }
+
+    device = mDevices.valueAt(deviceIndex);
+    mDevices.removeItemsAt(deviceIndex, 1);
+    bumpGenerationLocked();
+
+    if (device->isIgnored()) {
+        ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
+                device->getId(), device->getName().c_str());
+    } else {
+        ALOGI("Device removed: id=%d, name='%s', sources=0x%08x",
+                device->getId(), device->getName().c_str(), device->getSources());
+    }
+
+    if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
+        notifyExternalStylusPresenceChanged();
+    }
+
+    device->reset(when);
+    delete device;
+}
+
+InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
+        const InputDeviceIdentifier& identifier, uint32_t classes) {
+    InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
+            controllerNumber, identifier, classes);
+
+    // External devices.
+    if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
+        device->setExternal(true);
+    }
+
+    // Devices with mics.
+    if (classes & INPUT_DEVICE_CLASS_MIC) {
+        device->setMic(true);
+    }
+
+    // Switch-like devices.
+    if (classes & INPUT_DEVICE_CLASS_SWITCH) {
+        device->addMapper(new SwitchInputMapper(device));
+    }
+
+    // Scroll wheel-like devices.
+    if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
+        device->addMapper(new RotaryEncoderInputMapper(device));
+    }
+
+    // Vibrator-like devices.
+    if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
+        device->addMapper(new VibratorInputMapper(device));
+    }
+
+    // Keyboard-like devices.
+    uint32_t keyboardSource = 0;
+    int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
+    if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
+        keyboardSource |= AINPUT_SOURCE_KEYBOARD;
+    }
+    if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
+        keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
+    }
+    if (classes & INPUT_DEVICE_CLASS_DPAD) {
+        keyboardSource |= AINPUT_SOURCE_DPAD;
+    }
+    if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
+        keyboardSource |= AINPUT_SOURCE_GAMEPAD;
+    }
+
+    if (keyboardSource != 0) {
+        device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
+    }
+
+    // Cursor-like devices.
+    if (classes & INPUT_DEVICE_CLASS_CURSOR) {
+        device->addMapper(new CursorInputMapper(device));
+    }
+
+    // Touchscreens and touchpad devices.
+    if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
+        device->addMapper(new MultiTouchInputMapper(device));
+    } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
+        device->addMapper(new SingleTouchInputMapper(device));
+    }
+
+    // Joystick-like devices.
+    if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
+        device->addMapper(new JoystickInputMapper(device));
+    }
+
+    // External stylus-like devices.
+    if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
+        device->addMapper(new ExternalStylusInputMapper(device));
+    }
+
+    return device;
+}
+
+void InputReader::processEventsForDeviceLocked(int32_t deviceId,
+        const RawEvent* rawEvents, size_t count) {
+    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+    if (deviceIndex < 0) {
+        ALOGW("Discarding event for unknown deviceId %d.", deviceId);
+        return;
+    }
+
+    InputDevice* device = mDevices.valueAt(deviceIndex);
+    if (device->isIgnored()) {
+        //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
+        return;
+    }
+
+    device->process(rawEvents, count);
+}
+
+void InputReader::timeoutExpiredLocked(nsecs_t when) {
+    for (size_t i = 0; i < mDevices.size(); i++) {
+        InputDevice* device = mDevices.valueAt(i);
+        if (!device->isIgnored()) {
+            device->timeoutExpired(when);
+        }
+    }
+}
+
+void InputReader::handleConfigurationChangedLocked(nsecs_t when) {
+    // Reset global meta state because it depends on the list of all configured devices.
+    updateGlobalMetaStateLocked();
+
+    // Enqueue configuration changed.
+    NotifyConfigurationChangedArgs args(mContext.getNextSequenceNum(), when);
+    mQueuedListener->notifyConfigurationChanged(&args);
+}
+
+void InputReader::refreshConfigurationLocked(uint32_t changes) {
+    mPolicy->getReaderConfiguration(&mConfig);
+    mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
+
+    if (changes) {
+        ALOGI("Reconfiguring input devices.  changes=0x%08x", changes);
+        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+
+        if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
+            mEventHub->requestReopenDevices();
+        } else {
+            for (size_t i = 0; i < mDevices.size(); i++) {
+                InputDevice* device = mDevices.valueAt(i);
+                device->configure(now, &mConfig, changes);
+            }
+        }
+    }
+}
+
+void InputReader::updateGlobalMetaStateLocked() {
+    mGlobalMetaState = 0;
+
+    for (size_t i = 0; i < mDevices.size(); i++) {
+        InputDevice* device = mDevices.valueAt(i);
+        mGlobalMetaState |= device->getMetaState();
+    }
+}
+
+int32_t InputReader::getGlobalMetaStateLocked() {
+    return mGlobalMetaState;
+}
+
+void InputReader::notifyExternalStylusPresenceChanged() {
+    refreshConfigurationLocked(InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE);
+}
+
+void InputReader::getExternalStylusDevicesLocked(std::vector<InputDeviceInfo>& outDevices) {
+    for (size_t i = 0; i < mDevices.size(); i++) {
+        InputDevice* device = mDevices.valueAt(i);
+        if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS && !device->isIgnored()) {
+            InputDeviceInfo info;
+            device->getDeviceInfo(&info);
+            outDevices.push_back(info);
+        }
+    }
+}
+
+void InputReader::dispatchExternalStylusState(const StylusState& state) {
+    for (size_t i = 0; i < mDevices.size(); i++) {
+        InputDevice* device = mDevices.valueAt(i);
+        device->updateExternalStylusState(state);
+    }
+}
+
+void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) {
+    mDisableVirtualKeysTimeout = time;
+}
+
+bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now,
+        InputDevice* device, int32_t keyCode, int32_t scanCode) {
+    if (now < mDisableVirtualKeysTimeout) {
+        ALOGI("Dropping virtual key from device %s because virtual keys are "
+                "temporarily disabled for the next %0.3fms.  keyCode=%d, scanCode=%d",
+                device->getName().c_str(),
+                (mDisableVirtualKeysTimeout - now) * 0.000001,
+                keyCode, scanCode);
+        return true;
+    } else {
+        return false;
+    }
+}
+
+void InputReader::fadePointerLocked() {
+    for (size_t i = 0; i < mDevices.size(); i++) {
+        InputDevice* device = mDevices.valueAt(i);
+        device->fadePointer();
+    }
+}
+
+void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
+    if (when < mNextTimeout) {
+        mNextTimeout = when;
+        mEventHub->wake();
+    }
+}
+
+int32_t InputReader::bumpGenerationLocked() {
+    return ++mGeneration;
+}
+
+void InputReader::getInputDevices(std::vector<InputDeviceInfo>& outInputDevices) {
+    AutoMutex _l(mLock);
+    getInputDevicesLocked(outInputDevices);
+}
+
+void InputReader::getInputDevicesLocked(std::vector<InputDeviceInfo>& outInputDevices) {
+    outInputDevices.clear();
+
+    size_t numDevices = mDevices.size();
+    for (size_t i = 0; i < numDevices; i++) {
+        InputDevice* device = mDevices.valueAt(i);
+        if (!device->isIgnored()) {
+            InputDeviceInfo info;
+            device->getDeviceInfo(&info);
+            outInputDevices.push_back(info);
+        }
+    }
+}
+
+int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
+        int32_t keyCode) {
+    AutoMutex _l(mLock);
+
+    return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState);
+}
+
+int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
+        int32_t scanCode) {
+    AutoMutex _l(mLock);
+
+    return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState);
+}
+
+int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
+    AutoMutex _l(mLock);
+
+    return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState);
+}
+
+int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
+        GetStateFunc getStateFunc) {
+    int32_t result = AKEY_STATE_UNKNOWN;
+    if (deviceId >= 0) {
+        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+        if (deviceIndex >= 0) {
+            InputDevice* device = mDevices.valueAt(deviceIndex);
+            if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
+                result = (device->*getStateFunc)(sourceMask, code);
+            }
+        }
+    } else {
+        size_t numDevices = mDevices.size();
+        for (size_t i = 0; i < numDevices; i++) {
+            InputDevice* device = mDevices.valueAt(i);
+            if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
+                // If any device reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
+                // value.  Otherwise, return AKEY_STATE_UP as long as one device reports it.
+                int32_t currentResult = (device->*getStateFunc)(sourceMask, code);
+                if (currentResult >= AKEY_STATE_DOWN) {
+                    return currentResult;
+                } else if (currentResult == AKEY_STATE_UP) {
+                    result = currentResult;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+void InputReader::toggleCapsLockState(int32_t deviceId) {
+    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+    if (deviceIndex < 0) {
+        ALOGW("Ignoring toggleCapsLock for unknown deviceId %" PRId32 ".", deviceId);
+        return;
+    }
+
+    InputDevice* device = mDevices.valueAt(deviceIndex);
+    if (device->isIgnored()) {
+        return;
+    }
+
+    device->updateMetaState(AKEYCODE_CAPS_LOCK);
+}
+
+bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
+        size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
+    AutoMutex _l(mLock);
+
+    memset(outFlags, 0, numCodes);
+    return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags);
+}
+
+bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask,
+        size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
+    bool result = false;
+    if (deviceId >= 0) {
+        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+        if (deviceIndex >= 0) {
+            InputDevice* device = mDevices.valueAt(deviceIndex);
+            if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
+                result = device->markSupportedKeyCodes(sourceMask,
+                        numCodes, keyCodes, outFlags);
+            }
+        }
+    } else {
+        size_t numDevices = mDevices.size();
+        for (size_t i = 0; i < numDevices; i++) {
+            InputDevice* device = mDevices.valueAt(i);
+            if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
+                result |= device->markSupportedKeyCodes(sourceMask,
+                        numCodes, keyCodes, outFlags);
+            }
+        }
+    }
+    return result;
+}
+
+void InputReader::requestRefreshConfiguration(uint32_t changes) {
+    AutoMutex _l(mLock);
+
+    if (changes) {
+        bool needWake = !mConfigurationChangesToRefresh;
+        mConfigurationChangesToRefresh |= changes;
+
+        if (needWake) {
+            mEventHub->wake();
+        }
+    }
+}
+
+void InputReader::vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
+        ssize_t repeat, int32_t token) {
+    AutoMutex _l(mLock);
+
+    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+    if (deviceIndex >= 0) {
+        InputDevice* device = mDevices.valueAt(deviceIndex);
+        device->vibrate(pattern, patternSize, repeat, token);
+    }
+}
+
+void InputReader::cancelVibrate(int32_t deviceId, int32_t token) {
+    AutoMutex _l(mLock);
+
+    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+    if (deviceIndex >= 0) {
+        InputDevice* device = mDevices.valueAt(deviceIndex);
+        device->cancelVibrate(token);
+    }
+}
+
+bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
+    AutoMutex _l(mLock);
+
+    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+    if (deviceIndex >= 0) {
+        InputDevice* device = mDevices.valueAt(deviceIndex);
+        return device->isEnabled();
+    }
+    ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
+    return false;
+}
+
+bool InputReader::canDispatchToDisplay(int32_t deviceId, int32_t displayId) {
+    AutoMutex _l(mLock);
+
+    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+    if (deviceIndex < 0) {
+        ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
+        return false;
+    }
+
+    InputDevice* device = mDevices.valueAt(deviceIndex);
+    std::optional<int32_t> associatedDisplayId = device->getAssociatedDisplay();
+    // No associated display. By default, can dispatch to all displays.
+    if (!associatedDisplayId) {
+        return true;
+    }
+
+    if (*associatedDisplayId == ADISPLAY_ID_NONE) {
+        ALOGW("Device has associated, but no associated display id.");
+        return true;
+    }
+
+    return *associatedDisplayId == displayId;
+}
+
+void InputReader::dump(std::string& dump) {
+    AutoMutex _l(mLock);
+
+    mEventHub->dump(dump);
+    dump += "\n";
+
+    dump += "Input Reader State:\n";
+
+    for (size_t i = 0; i < mDevices.size(); i++) {
+        mDevices.valueAt(i)->dump(dump);
+    }
+
+    dump += INDENT "Configuration:\n";
+    dump += INDENT2 "ExcludedDeviceNames: [";
+    for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
+        if (i != 0) {
+            dump += ", ";
+        }
+        dump += mConfig.excludedDeviceNames[i];
+    }
+    dump += "]\n";
+    dump += StringPrintf(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
+            mConfig.virtualKeyQuietTime * 0.000001f);
+
+    dump += StringPrintf(INDENT2 "PointerVelocityControlParameters: "
+            "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
+            mConfig.pointerVelocityControlParameters.scale,
+            mConfig.pointerVelocityControlParameters.lowThreshold,
+            mConfig.pointerVelocityControlParameters.highThreshold,
+            mConfig.pointerVelocityControlParameters.acceleration);
+
+    dump += StringPrintf(INDENT2 "WheelVelocityControlParameters: "
+            "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
+            mConfig.wheelVelocityControlParameters.scale,
+            mConfig.wheelVelocityControlParameters.lowThreshold,
+            mConfig.wheelVelocityControlParameters.highThreshold,
+            mConfig.wheelVelocityControlParameters.acceleration);
+
+    dump += StringPrintf(INDENT2 "PointerGesture:\n");
+    dump += StringPrintf(INDENT3 "Enabled: %s\n",
+            toString(mConfig.pointerGesturesEnabled));
+    dump += StringPrintf(INDENT3 "QuietInterval: %0.1fms\n",
+            mConfig.pointerGestureQuietInterval * 0.000001f);
+    dump += StringPrintf(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
+            mConfig.pointerGestureDragMinSwitchSpeed);
+    dump += StringPrintf(INDENT3 "TapInterval: %0.1fms\n",
+            mConfig.pointerGestureTapInterval * 0.000001f);
+    dump += StringPrintf(INDENT3 "TapDragInterval: %0.1fms\n",
+            mConfig.pointerGestureTapDragInterval * 0.000001f);
+    dump += StringPrintf(INDENT3 "TapSlop: %0.1fpx\n",
+            mConfig.pointerGestureTapSlop);
+    dump += StringPrintf(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
+            mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
+    dump += StringPrintf(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
+            mConfig.pointerGestureMultitouchMinDistance);
+    dump += StringPrintf(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
+            mConfig.pointerGestureSwipeTransitionAngleCosine);
+    dump += StringPrintf(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
+            mConfig.pointerGestureSwipeMaxWidthRatio);
+    dump += StringPrintf(INDENT3 "MovementSpeedRatio: %0.1f\n",
+            mConfig.pointerGestureMovementSpeedRatio);
+    dump += StringPrintf(INDENT3 "ZoomSpeedRatio: %0.1f\n",
+            mConfig.pointerGestureZoomSpeedRatio);
+
+    dump += INDENT3 "Viewports:\n";
+    mConfig.dump(dump);
+}
+
+void InputReader::monitor() {
+    // Acquire and release the lock to ensure that the reader has not deadlocked.
+    mLock.lock();
+    mEventHub->wake();
+    mReaderIsAliveCondition.wait(mLock);
+    mLock.unlock();
+
+    // Check the EventHub
+    mEventHub->monitor();
+}
+
+
+// --- InputReader::ContextImpl ---
+
+InputReader::ContextImpl::ContextImpl(InputReader* reader) :
+        mReader(reader) {
+}
+
+void InputReader::ContextImpl::updateGlobalMetaState() {
+    // lock is already held by the input loop
+    mReader->updateGlobalMetaStateLocked();
+}
+
+int32_t InputReader::ContextImpl::getGlobalMetaState() {
+    // lock is already held by the input loop
+    return mReader->getGlobalMetaStateLocked();
+}
+
+void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) {
+    // lock is already held by the input loop
+    mReader->disableVirtualKeysUntilLocked(time);
+}
+
+bool InputReader::ContextImpl::shouldDropVirtualKey(nsecs_t now,
+        InputDevice* device, int32_t keyCode, int32_t scanCode) {
+    // lock is already held by the input loop
+    return mReader->shouldDropVirtualKeyLocked(now, device, keyCode, scanCode);
+}
+
+void InputReader::ContextImpl::fadePointer() {
+    // lock is already held by the input loop
+    mReader->fadePointerLocked();
+}
+
+void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
+    // lock is already held by the input loop
+    mReader->requestTimeoutAtTimeLocked(when);
+}
+
+int32_t InputReader::ContextImpl::bumpGeneration() {
+    // lock is already held by the input loop
+    return mReader->bumpGenerationLocked();
+}
+
+void InputReader::ContextImpl::getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) {
+    // lock is already held by whatever called refreshConfigurationLocked
+    mReader->getExternalStylusDevicesLocked(outDevices);
+}
+
+void InputReader::ContextImpl::dispatchExternalStylusState(const StylusState& state) {
+    mReader->dispatchExternalStylusState(state);
+}
+
+InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
+    return mReader->mPolicy.get();
+}
+
+InputListenerInterface* InputReader::ContextImpl::getListener() {
+    return mReader->mQueuedListener.get();
+}
+
+EventHubInterface* InputReader::ContextImpl::getEventHub() {
+    return mReader->mEventHub.get();
+}
+
+uint32_t InputReader::ContextImpl::getNextSequenceNum() {
+    return (mReader->mNextSequenceNum)++;
+}
+
+// --- InputDevice ---
+
+InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
+        int32_t controllerNumber, const InputDeviceIdentifier& identifier, uint32_t classes) :
+        mContext(context), mId(id), mGeneration(generation), mControllerNumber(controllerNumber),
+        mIdentifier(identifier), mClasses(classes),
+        mSources(0), mIsExternal(false), mHasMic(false), mDropUntilNextSync(false) {
+}
+
+InputDevice::~InputDevice() {
+    size_t numMappers = mMappers.size();
+    for (size_t i = 0; i < numMappers; i++) {
+        delete mMappers[i];
+    }
+    mMappers.clear();
+}
+
+bool InputDevice::isEnabled() {
+    return getEventHub()->isDeviceEnabled(mId);
+}
+
+void InputDevice::setEnabled(bool enabled, nsecs_t when) {
+    if (isEnabled() == enabled) {
+        return;
+    }
+
+    if (enabled) {
+        getEventHub()->enableDevice(mId);
+        reset(when);
+    } else {
+        reset(when);
+        getEventHub()->disableDevice(mId);
+    }
+    // Must change generation to flag this device as changed
+    bumpGeneration();
+}
+
+void InputDevice::dump(std::string& dump) {
+    InputDeviceInfo deviceInfo;
+    getDeviceInfo(&deviceInfo);
+
+    dump += StringPrintf(INDENT "Device %d: %s\n", deviceInfo.getId(),
+            deviceInfo.getDisplayName().c_str());
+    dump += StringPrintf(INDENT2 "Generation: %d\n", mGeneration);
+    dump += StringPrintf(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
+    dump += StringPrintf(INDENT2 "AssociatedDisplayPort: ");
+    if (mAssociatedDisplayPort) {
+        dump += StringPrintf("%" PRIu8 "\n", *mAssociatedDisplayPort);
+    } else {
+        dump += "<none>\n";
+    }
+    dump += StringPrintf(INDENT2 "HasMic:     %s\n", toString(mHasMic));
+    dump += StringPrintf(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
+    dump += StringPrintf(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
+
+    const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
+    if (!ranges.empty()) {
+        dump += INDENT2 "Motion Ranges:\n";
+        for (size_t i = 0; i < ranges.size(); i++) {
+            const InputDeviceInfo::MotionRange& range = ranges[i];
+            const char* label = getAxisLabel(range.axis);
+            char name[32];
+            if (label) {
+                strncpy(name, label, sizeof(name));
+                name[sizeof(name) - 1] = '\0';
+            } else {
+                snprintf(name, sizeof(name), "%d", range.axis);
+            }
+            dump += StringPrintf(INDENT3 "%s: source=0x%08x, "
+                    "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, resolution=%0.3f\n",
+                    name, range.source, range.min, range.max, range.flat, range.fuzz,
+                    range.resolution);
+        }
+    }
+
+    size_t numMappers = mMappers.size();
+    for (size_t i = 0; i < numMappers; i++) {
+        InputMapper* mapper = mMappers[i];
+        mapper->dump(dump);
+    }
+}
+
+void InputDevice::addMapper(InputMapper* mapper) {
+    mMappers.push_back(mapper);
+}
+
+void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) {
+    mSources = 0;
+
+    if (!isIgnored()) {
+        if (!changes) { // first time only
+            mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
+        }
+
+        if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
+            if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
+                sp<KeyCharacterMap> keyboardLayout =
+                        mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier);
+                if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {
+                    bumpGeneration();
+                }
+            }
+        }
+
+        if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
+            if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
+                std::string alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
+                if (mAlias != alias) {
+                    mAlias = alias;
+                    bumpGeneration();
+                }
+            }
+        }
+
+        if (!changes || (changes & InputReaderConfiguration::CHANGE_ENABLED_STATE)) {
+            ssize_t index = config->disabledDevices.indexOf(mId);
+            bool enabled = index < 0;
+            setEnabled(enabled, when);
+        }
+
+        if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+             // In most situations, no port will be specified.
+            mAssociatedDisplayPort = std::nullopt;
+            // Find the display port that corresponds to the current input port.
+            const std::string& inputPort = mIdentifier.location;
+            if (!inputPort.empty()) {
+                const std::unordered_map<std::string, uint8_t>& ports = config->portAssociations;
+                const auto& displayPort = ports.find(inputPort);
+                if (displayPort != ports.end()) {
+                    mAssociatedDisplayPort = std::make_optional(displayPort->second);
+                }
+            }
+        }
+
+        for (InputMapper* mapper : mMappers) {
+            mapper->configure(when, config, changes);
+            mSources |= mapper->getSources();
+        }
+    }
+}
+
+void InputDevice::reset(nsecs_t when) {
+    for (InputMapper* mapper : mMappers) {
+        mapper->reset(when);
+    }
+
+    mContext->updateGlobalMetaState();
+
+    notifyReset(when);
+}
+
+void InputDevice::process(const RawEvent* rawEvents, size_t count) {
+    // Process all of the events in order for each mapper.
+    // We cannot simply ask each mapper to process them in bulk because mappers may
+    // have side-effects that must be interleaved.  For example, joystick movement events and
+    // gamepad button presses are handled by different mappers but they should be dispatched
+    // in the order received.
+    for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
+#if DEBUG_RAW_EVENTS
+        ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
+                rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
+                rawEvent->when);
+#endif
+
+        if (mDropUntilNextSync) {
+            if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
+                mDropUntilNextSync = false;
+#if DEBUG_RAW_EVENTS
+                ALOGD("Recovered from input event buffer overrun.");
+#endif
+            } else {
+#if DEBUG_RAW_EVENTS
+                ALOGD("Dropped input event while waiting for next input sync.");
+#endif
+            }
+        } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
+            ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
+            mDropUntilNextSync = true;
+            reset(rawEvent->when);
+        } else {
+            for (InputMapper* mapper : mMappers) {
+                mapper->process(rawEvent);
+            }
+        }
+        --count;
+    }
+}
+
+void InputDevice::timeoutExpired(nsecs_t when) {
+    for (InputMapper* mapper : mMappers) {
+        mapper->timeoutExpired(when);
+    }
+}
+
+void InputDevice::updateExternalStylusState(const StylusState& state) {
+    for (InputMapper* mapper : mMappers) {
+        mapper->updateExternalStylusState(state);
+    }
+}
+
+void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
+    outDeviceInfo->initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias,
+            mIsExternal, mHasMic);
+    for (InputMapper* mapper : mMappers) {
+        mapper->populateDeviceInfo(outDeviceInfo);
+    }
+}
+
+int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
+    return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
+}
+
+int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+    return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
+}
+
+int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
+    return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
+}
+
+int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
+    int32_t result = AKEY_STATE_UNKNOWN;
+    for (InputMapper* mapper : mMappers) {
+        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
+            // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
+            // value.  Otherwise, return AKEY_STATE_UP as long as one mapper reports it.
+            int32_t currentResult = (mapper->*getStateFunc)(sourceMask, code);
+            if (currentResult >= AKEY_STATE_DOWN) {
+                return currentResult;
+            } else if (currentResult == AKEY_STATE_UP) {
+                result = currentResult;
+            }
+        }
+    }
+    return result;
+}
+
+bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+        const int32_t* keyCodes, uint8_t* outFlags) {
+    bool result = false;
+    for (InputMapper* mapper : mMappers) {
+        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
+            result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
+        }
+    }
+    return result;
+}
+
+void InputDevice::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
+        int32_t token) {
+    for (InputMapper* mapper : mMappers) {
+        mapper->vibrate(pattern, patternSize, repeat, token);
+    }
+}
+
+void InputDevice::cancelVibrate(int32_t token) {
+    for (InputMapper* mapper : mMappers) {
+        mapper->cancelVibrate(token);
+    }
+}
+
+void InputDevice::cancelTouch(nsecs_t when) {
+    for (InputMapper* mapper : mMappers) {
+        mapper->cancelTouch(when);
+    }
+}
+
+int32_t InputDevice::getMetaState() {
+    int32_t result = 0;
+    for (InputMapper* mapper : mMappers) {
+        result |= mapper->getMetaState();
+    }
+    return result;
+}
+
+void InputDevice::updateMetaState(int32_t keyCode) {
+    for (InputMapper* mapper : mMappers) {
+        mapper->updateMetaState(keyCode);
+    }
+}
+
+void InputDevice::fadePointer() {
+    for (InputMapper* mapper : mMappers) {
+        mapper->fadePointer();
+    }
+}
+
+void InputDevice::bumpGeneration() {
+    mGeneration = mContext->bumpGeneration();
+}
+
+void InputDevice::notifyReset(nsecs_t when) {
+    NotifyDeviceResetArgs args(mContext->getNextSequenceNum(), when, mId);
+    mContext->getListener()->notifyDeviceReset(&args);
+}
+
+std::optional<int32_t> InputDevice::getAssociatedDisplay() {
+    for (InputMapper* mapper : mMappers) {
+        std::optional<int32_t> associatedDisplayId = mapper->getAssociatedDisplay();
+        if (associatedDisplayId) {
+            return associatedDisplayId;
+        }
+    }
+
+    return std::nullopt;
+}
+
+// --- CursorButtonAccumulator ---
+
+CursorButtonAccumulator::CursorButtonAccumulator() {
+    clearButtons();
+}
+
+void CursorButtonAccumulator::reset(InputDevice* device) {
+    mBtnLeft = device->isKeyPressed(BTN_LEFT);
+    mBtnRight = device->isKeyPressed(BTN_RIGHT);
+    mBtnMiddle = device->isKeyPressed(BTN_MIDDLE);
+    mBtnBack = device->isKeyPressed(BTN_BACK);
+    mBtnSide = device->isKeyPressed(BTN_SIDE);
+    mBtnForward = device->isKeyPressed(BTN_FORWARD);
+    mBtnExtra = device->isKeyPressed(BTN_EXTRA);
+    mBtnTask = device->isKeyPressed(BTN_TASK);
+}
+
+void CursorButtonAccumulator::clearButtons() {
+    mBtnLeft = 0;
+    mBtnRight = 0;
+    mBtnMiddle = 0;
+    mBtnBack = 0;
+    mBtnSide = 0;
+    mBtnForward = 0;
+    mBtnExtra = 0;
+    mBtnTask = 0;
+}
+
+void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
+    if (rawEvent->type == EV_KEY) {
+        switch (rawEvent->code) {
+        case BTN_LEFT:
+            mBtnLeft = rawEvent->value;
+            break;
+        case BTN_RIGHT:
+            mBtnRight = rawEvent->value;
+            break;
+        case BTN_MIDDLE:
+            mBtnMiddle = rawEvent->value;
+            break;
+        case BTN_BACK:
+            mBtnBack = rawEvent->value;
+            break;
+        case BTN_SIDE:
+            mBtnSide = rawEvent->value;
+            break;
+        case BTN_FORWARD:
+            mBtnForward = rawEvent->value;
+            break;
+        case BTN_EXTRA:
+            mBtnExtra = rawEvent->value;
+            break;
+        case BTN_TASK:
+            mBtnTask = rawEvent->value;
+            break;
+        }
+    }
+}
+
+uint32_t CursorButtonAccumulator::getButtonState() const {
+    uint32_t result = 0;
+    if (mBtnLeft) {
+        result |= AMOTION_EVENT_BUTTON_PRIMARY;
+    }
+    if (mBtnRight) {
+        result |= AMOTION_EVENT_BUTTON_SECONDARY;
+    }
+    if (mBtnMiddle) {
+        result |= AMOTION_EVENT_BUTTON_TERTIARY;
+    }
+    if (mBtnBack || mBtnSide) {
+        result |= AMOTION_EVENT_BUTTON_BACK;
+    }
+    if (mBtnForward || mBtnExtra) {
+        result |= AMOTION_EVENT_BUTTON_FORWARD;
+    }
+    return result;
+}
+
+
+// --- CursorMotionAccumulator ---
+
+CursorMotionAccumulator::CursorMotionAccumulator() {
+    clearRelativeAxes();
+}
+
+void CursorMotionAccumulator::reset(InputDevice* device) {
+    clearRelativeAxes();
+}
+
+void CursorMotionAccumulator::clearRelativeAxes() {
+    mRelX = 0;
+    mRelY = 0;
+}
+
+void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
+    if (rawEvent->type == EV_REL) {
+        switch (rawEvent->code) {
+        case REL_X:
+            mRelX = rawEvent->value;
+            break;
+        case REL_Y:
+            mRelY = rawEvent->value;
+            break;
+        }
+    }
+}
+
+void CursorMotionAccumulator::finishSync() {
+    clearRelativeAxes();
+}
+
+
+// --- CursorScrollAccumulator ---
+
+CursorScrollAccumulator::CursorScrollAccumulator() :
+        mHaveRelWheel(false), mHaveRelHWheel(false) {
+    clearRelativeAxes();
+}
+
+void CursorScrollAccumulator::configure(InputDevice* device) {
+    mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
+    mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
+}
+
+void CursorScrollAccumulator::reset(InputDevice* device) {
+    clearRelativeAxes();
+}
+
+void CursorScrollAccumulator::clearRelativeAxes() {
+    mRelWheel = 0;
+    mRelHWheel = 0;
+}
+
+void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
+    if (rawEvent->type == EV_REL) {
+        switch (rawEvent->code) {
+        case REL_WHEEL:
+            mRelWheel = rawEvent->value;
+            break;
+        case REL_HWHEEL:
+            mRelHWheel = rawEvent->value;
+            break;
+        }
+    }
+}
+
+void CursorScrollAccumulator::finishSync() {
+    clearRelativeAxes();
+}
+
+
+// --- TouchButtonAccumulator ---
+
+TouchButtonAccumulator::TouchButtonAccumulator() :
+        mHaveBtnTouch(false), mHaveStylus(false) {
+    clearButtons();
+}
+
+void TouchButtonAccumulator::configure(InputDevice* device) {
+    mHaveBtnTouch = device->hasKey(BTN_TOUCH);
+    mHaveStylus = device->hasKey(BTN_TOOL_PEN)
+            || device->hasKey(BTN_TOOL_RUBBER)
+            || device->hasKey(BTN_TOOL_BRUSH)
+            || device->hasKey(BTN_TOOL_PENCIL)
+            || device->hasKey(BTN_TOOL_AIRBRUSH);
+}
+
+void TouchButtonAccumulator::reset(InputDevice* device) {
+    mBtnTouch = device->isKeyPressed(BTN_TOUCH);
+    mBtnStylus = device->isKeyPressed(BTN_STYLUS);
+    // BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
+    mBtnStylus2 =
+            device->isKeyPressed(BTN_STYLUS2) || device->isKeyPressed(BTN_0);
+    mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER);
+    mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN);
+    mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER);
+    mBtnToolBrush = device->isKeyPressed(BTN_TOOL_BRUSH);
+    mBtnToolPencil = device->isKeyPressed(BTN_TOOL_PENCIL);
+    mBtnToolAirbrush = device->isKeyPressed(BTN_TOOL_AIRBRUSH);
+    mBtnToolMouse = device->isKeyPressed(BTN_TOOL_MOUSE);
+    mBtnToolLens = device->isKeyPressed(BTN_TOOL_LENS);
+    mBtnToolDoubleTap = device->isKeyPressed(BTN_TOOL_DOUBLETAP);
+    mBtnToolTripleTap = device->isKeyPressed(BTN_TOOL_TRIPLETAP);
+    mBtnToolQuadTap = device->isKeyPressed(BTN_TOOL_QUADTAP);
+}
+
+void TouchButtonAccumulator::clearButtons() {
+    mBtnTouch = 0;
+    mBtnStylus = 0;
+    mBtnStylus2 = 0;
+    mBtnToolFinger = 0;
+    mBtnToolPen = 0;
+    mBtnToolRubber = 0;
+    mBtnToolBrush = 0;
+    mBtnToolPencil = 0;
+    mBtnToolAirbrush = 0;
+    mBtnToolMouse = 0;
+    mBtnToolLens = 0;
+    mBtnToolDoubleTap = 0;
+    mBtnToolTripleTap = 0;
+    mBtnToolQuadTap = 0;
+}
+
+void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
+    if (rawEvent->type == EV_KEY) {
+        switch (rawEvent->code) {
+        case BTN_TOUCH:
+            mBtnTouch = rawEvent->value;
+            break;
+        case BTN_STYLUS:
+            mBtnStylus = rawEvent->value;
+            break;
+        case BTN_STYLUS2:
+        case BTN_0:// BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
+            mBtnStylus2 = rawEvent->value;
+            break;
+        case BTN_TOOL_FINGER:
+            mBtnToolFinger = rawEvent->value;
+            break;
+        case BTN_TOOL_PEN:
+            mBtnToolPen = rawEvent->value;
+            break;
+        case BTN_TOOL_RUBBER:
+            mBtnToolRubber = rawEvent->value;
+            break;
+        case BTN_TOOL_BRUSH:
+            mBtnToolBrush = rawEvent->value;
+            break;
+        case BTN_TOOL_PENCIL:
+            mBtnToolPencil = rawEvent->value;
+            break;
+        case BTN_TOOL_AIRBRUSH:
+            mBtnToolAirbrush = rawEvent->value;
+            break;
+        case BTN_TOOL_MOUSE:
+            mBtnToolMouse = rawEvent->value;
+            break;
+        case BTN_TOOL_LENS:
+            mBtnToolLens = rawEvent->value;
+            break;
+        case BTN_TOOL_DOUBLETAP:
+            mBtnToolDoubleTap = rawEvent->value;
+            break;
+        case BTN_TOOL_TRIPLETAP:
+            mBtnToolTripleTap = rawEvent->value;
+            break;
+        case BTN_TOOL_QUADTAP:
+            mBtnToolQuadTap = rawEvent->value;
+            break;
+        }
+    }
+}
+
+uint32_t TouchButtonAccumulator::getButtonState() const {
+    uint32_t result = 0;
+    if (mBtnStylus) {
+        result |= AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
+    }
+    if (mBtnStylus2) {
+        result |= AMOTION_EVENT_BUTTON_STYLUS_SECONDARY;
+    }
+    return result;
+}
+
+int32_t TouchButtonAccumulator::getToolType() const {
+    if (mBtnToolMouse || mBtnToolLens) {
+        return AMOTION_EVENT_TOOL_TYPE_MOUSE;
+    }
+    if (mBtnToolRubber) {
+        return AMOTION_EVENT_TOOL_TYPE_ERASER;
+    }
+    if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) {
+        return AMOTION_EVENT_TOOL_TYPE_STYLUS;
+    }
+    if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap) {
+        return AMOTION_EVENT_TOOL_TYPE_FINGER;
+    }
+    return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+}
+
+bool TouchButtonAccumulator::isToolActive() const {
+    return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber
+            || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush
+            || mBtnToolMouse || mBtnToolLens
+            || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap;
+}
+
+bool TouchButtonAccumulator::isHovering() const {
+    return mHaveBtnTouch && !mBtnTouch;
+}
+
+bool TouchButtonAccumulator::hasStylus() const {
+    return mHaveStylus;
+}
+
+
+// --- RawPointerAxes ---
+
+RawPointerAxes::RawPointerAxes() {
+    clear();
+}
+
+void RawPointerAxes::clear() {
+    x.clear();
+    y.clear();
+    pressure.clear();
+    touchMajor.clear();
+    touchMinor.clear();
+    toolMajor.clear();
+    toolMinor.clear();
+    orientation.clear();
+    distance.clear();
+    tiltX.clear();
+    tiltY.clear();
+    trackingId.clear();
+    slot.clear();
+}
+
+
+// --- RawPointerData ---
+
+RawPointerData::RawPointerData() {
+    clear();
+}
+
+void RawPointerData::clear() {
+    pointerCount = 0;
+    clearIdBits();
+}
+
+void RawPointerData::copyFrom(const RawPointerData& other) {
+    pointerCount = other.pointerCount;
+    hoveringIdBits = other.hoveringIdBits;
+    touchingIdBits = other.touchingIdBits;
+
+    for (uint32_t i = 0; i < pointerCount; i++) {
+        pointers[i] = other.pointers[i];
+
+        int id = pointers[i].id;
+        idToIndex[id] = other.idToIndex[id];
+    }
+}
+
+void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) const {
+    float x = 0, y = 0;
+    uint32_t count = touchingIdBits.count();
+    if (count) {
+        for (BitSet32 idBits(touchingIdBits); !idBits.isEmpty(); ) {
+            uint32_t id = idBits.clearFirstMarkedBit();
+            const Pointer& pointer = pointerForId(id);
+            x += pointer.x;
+            y += pointer.y;
+        }
+        x /= count;
+        y /= count;
+    }
+    *outX = x;
+    *outY = y;
+}
+
+
+// --- CookedPointerData ---
+
+CookedPointerData::CookedPointerData() {
+    clear();
+}
+
+void CookedPointerData::clear() {
+    pointerCount = 0;
+    hoveringIdBits.clear();
+    touchingIdBits.clear();
+}
+
+void CookedPointerData::copyFrom(const CookedPointerData& other) {
+    pointerCount = other.pointerCount;
+    hoveringIdBits = other.hoveringIdBits;
+    touchingIdBits = other.touchingIdBits;
+
+    for (uint32_t i = 0; i < pointerCount; i++) {
+        pointerProperties[i].copyFrom(other.pointerProperties[i]);
+        pointerCoords[i].copyFrom(other.pointerCoords[i]);
+
+        int id = pointerProperties[i].id;
+        idToIndex[id] = other.idToIndex[id];
+    }
+}
+
+
+// --- SingleTouchMotionAccumulator ---
+
+SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
+    clearAbsoluteAxes();
+}
+
+void SingleTouchMotionAccumulator::reset(InputDevice* device) {
+    mAbsX = device->getAbsoluteAxisValue(ABS_X);
+    mAbsY = device->getAbsoluteAxisValue(ABS_Y);
+    mAbsPressure = device->getAbsoluteAxisValue(ABS_PRESSURE);
+    mAbsToolWidth = device->getAbsoluteAxisValue(ABS_TOOL_WIDTH);
+    mAbsDistance = device->getAbsoluteAxisValue(ABS_DISTANCE);
+    mAbsTiltX = device->getAbsoluteAxisValue(ABS_TILT_X);
+    mAbsTiltY = device->getAbsoluteAxisValue(ABS_TILT_Y);
+}
+
+void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
+    mAbsX = 0;
+    mAbsY = 0;
+    mAbsPressure = 0;
+    mAbsToolWidth = 0;
+    mAbsDistance = 0;
+    mAbsTiltX = 0;
+    mAbsTiltY = 0;
+}
+
+void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
+    if (rawEvent->type == EV_ABS) {
+        switch (rawEvent->code) {
+        case ABS_X:
+            mAbsX = rawEvent->value;
+            break;
+        case ABS_Y:
+            mAbsY = rawEvent->value;
+            break;
+        case ABS_PRESSURE:
+            mAbsPressure = rawEvent->value;
+            break;
+        case ABS_TOOL_WIDTH:
+            mAbsToolWidth = rawEvent->value;
+            break;
+        case ABS_DISTANCE:
+            mAbsDistance = rawEvent->value;
+            break;
+        case ABS_TILT_X:
+            mAbsTiltX = rawEvent->value;
+            break;
+        case ABS_TILT_Y:
+            mAbsTiltY = rawEvent->value;
+            break;
+        }
+    }
+}
+
+
+// --- MultiTouchMotionAccumulator ---
+
+MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() :
+        mCurrentSlot(-1), mSlots(nullptr), mSlotCount(0), mUsingSlotsProtocol(false),
+        mHaveStylus(false), mDeviceTimestamp(0) {
+}
+
+MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
+    delete[] mSlots;
+}
+
+void MultiTouchMotionAccumulator::configure(InputDevice* device,
+        size_t slotCount, bool usingSlotsProtocol) {
+    mSlotCount = slotCount;
+    mUsingSlotsProtocol = usingSlotsProtocol;
+    mHaveStylus = device->hasAbsoluteAxis(ABS_MT_TOOL_TYPE);
+
+    delete[] mSlots;
+    mSlots = new Slot[slotCount];
+}
+
+void MultiTouchMotionAccumulator::reset(InputDevice* device) {
+    // Unfortunately there is no way to read the initial contents of the slots.
+    // So when we reset the accumulator, we must assume they are all zeroes.
+    if (mUsingSlotsProtocol) {
+        // Query the driver for the current slot index and use it as the initial slot
+        // before we start reading events from the device.  It is possible that the
+        // current slot index will not be the same as it was when the first event was
+        // written into the evdev buffer, which means the input mapper could start
+        // out of sync with the initial state of the events in the evdev buffer.
+        // In the extremely unlikely case that this happens, the data from
+        // two slots will be confused until the next ABS_MT_SLOT event is received.
+        // This can cause the touch point to "jump", but at least there will be
+        // no stuck touches.
+        int32_t initialSlot;
+        status_t status = device->getEventHub()->getAbsoluteAxisValue(device->getId(),
+                ABS_MT_SLOT, &initialSlot);
+        if (status) {
+            ALOGD("Could not retrieve current multitouch slot index.  status=%d", status);
+            initialSlot = -1;
+        }
+        clearSlots(initialSlot);
+    } else {
+        clearSlots(-1);
+    }
+    mDeviceTimestamp = 0;
+}
+
+void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
+    if (mSlots) {
+        for (size_t i = 0; i < mSlotCount; i++) {
+            mSlots[i].clear();
+        }
+    }
+    mCurrentSlot = initialSlot;
+}
+
+void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
+    if (rawEvent->type == EV_ABS) {
+        bool newSlot = false;
+        if (mUsingSlotsProtocol) {
+            if (rawEvent->code == ABS_MT_SLOT) {
+                mCurrentSlot = rawEvent->value;
+                newSlot = true;
+            }
+        } else if (mCurrentSlot < 0) {
+            mCurrentSlot = 0;
+        }
+
+        if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
+#if DEBUG_POINTERS
+            if (newSlot) {
+                ALOGW("MultiTouch device emitted invalid slot index %d but it "
+                        "should be between 0 and %zd; ignoring this slot.",
+                        mCurrentSlot, mSlotCount - 1);
+            }
+#endif
+        } else {
+            Slot* slot = &mSlots[mCurrentSlot];
+
+            switch (rawEvent->code) {
+            case ABS_MT_POSITION_X:
+                slot->mInUse = true;
+                slot->mAbsMTPositionX = rawEvent->value;
+                break;
+            case ABS_MT_POSITION_Y:
+                slot->mInUse = true;
+                slot->mAbsMTPositionY = rawEvent->value;
+                break;
+            case ABS_MT_TOUCH_MAJOR:
+                slot->mInUse = true;
+                slot->mAbsMTTouchMajor = rawEvent->value;
+                break;
+            case ABS_MT_TOUCH_MINOR:
+                slot->mInUse = true;
+                slot->mAbsMTTouchMinor = rawEvent->value;
+                slot->mHaveAbsMTTouchMinor = true;
+                break;
+            case ABS_MT_WIDTH_MAJOR:
+                slot->mInUse = true;
+                slot->mAbsMTWidthMajor = rawEvent->value;
+                break;
+            case ABS_MT_WIDTH_MINOR:
+                slot->mInUse = true;
+                slot->mAbsMTWidthMinor = rawEvent->value;
+                slot->mHaveAbsMTWidthMinor = true;
+                break;
+            case ABS_MT_ORIENTATION:
+                slot->mInUse = true;
+                slot->mAbsMTOrientation = rawEvent->value;
+                break;
+            case ABS_MT_TRACKING_ID:
+                if (mUsingSlotsProtocol && rawEvent->value < 0) {
+                    // The slot is no longer in use but it retains its previous contents,
+                    // which may be reused for subsequent touches.
+                    slot->mInUse = false;
+                } else {
+                    slot->mInUse = true;
+                    slot->mAbsMTTrackingId = rawEvent->value;
+                }
+                break;
+            case ABS_MT_PRESSURE:
+                slot->mInUse = true;
+                slot->mAbsMTPressure = rawEvent->value;
+                break;
+            case ABS_MT_DISTANCE:
+                slot->mInUse = true;
+                slot->mAbsMTDistance = rawEvent->value;
+                break;
+            case ABS_MT_TOOL_TYPE:
+                slot->mInUse = true;
+                slot->mAbsMTToolType = rawEvent->value;
+                slot->mHaveAbsMTToolType = true;
+                break;
+            }
+        }
+    } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
+        // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
+        mCurrentSlot += 1;
+    } else if (rawEvent->type == EV_MSC && rawEvent->code == MSC_TIMESTAMP) {
+        mDeviceTimestamp = rawEvent->value;
+    }
+}
+
+void MultiTouchMotionAccumulator::finishSync() {
+    if (!mUsingSlotsProtocol) {
+        clearSlots(-1);
+    }
+}
+
+bool MultiTouchMotionAccumulator::hasStylus() const {
+    return mHaveStylus;
+}
+
+
+// --- MultiTouchMotionAccumulator::Slot ---
+
+MultiTouchMotionAccumulator::Slot::Slot() {
+    clear();
+}
+
+void MultiTouchMotionAccumulator::Slot::clear() {
+    mInUse = false;
+    mHaveAbsMTTouchMinor = false;
+    mHaveAbsMTWidthMinor = false;
+    mHaveAbsMTToolType = false;
+    mAbsMTPositionX = 0;
+    mAbsMTPositionY = 0;
+    mAbsMTTouchMajor = 0;
+    mAbsMTTouchMinor = 0;
+    mAbsMTWidthMajor = 0;
+    mAbsMTWidthMinor = 0;
+    mAbsMTOrientation = 0;
+    mAbsMTTrackingId = -1;
+    mAbsMTPressure = 0;
+    mAbsMTDistance = 0;
+    mAbsMTToolType = 0;
+}
+
+int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
+    if (mHaveAbsMTToolType) {
+        switch (mAbsMTToolType) {
+        case MT_TOOL_FINGER:
+            return AMOTION_EVENT_TOOL_TYPE_FINGER;
+        case MT_TOOL_PEN:
+            return AMOTION_EVENT_TOOL_TYPE_STYLUS;
+        }
+    }
+    return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+}
+
+
+// --- InputMapper ---
+
+InputMapper::InputMapper(InputDevice* device) :
+        mDevice(device), mContext(device->getContext()) {
+}
+
+InputMapper::~InputMapper() {
+}
+
+void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+    info->addSource(getSources());
+}
+
+void InputMapper::dump(std::string& dump) {
+}
+
+void InputMapper::configure(nsecs_t when,
+        const InputReaderConfiguration* config, uint32_t changes) {
+}
+
+void InputMapper::reset(nsecs_t when) {
+}
+
+void InputMapper::timeoutExpired(nsecs_t when) {
+}
+
+int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
+    return AKEY_STATE_UNKNOWN;
+}
+
+int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+    return AKEY_STATE_UNKNOWN;
+}
+
+int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
+    return AKEY_STATE_UNKNOWN;
+}
+
+bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+        const int32_t* keyCodes, uint8_t* outFlags) {
+    return false;
+}
+
+void InputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
+        int32_t token) {
+}
+
+void InputMapper::cancelVibrate(int32_t token) {
+}
+
+void InputMapper::cancelTouch(nsecs_t when) {
+}
+
+int32_t InputMapper::getMetaState() {
+    return 0;
+}
+
+void InputMapper::updateMetaState(int32_t keyCode) {
+}
+
+void InputMapper::updateExternalStylusState(const StylusState& state) {
+
+}
+
+void InputMapper::fadePointer() {
+}
+
+status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) {
+    return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo);
+}
+
+void InputMapper::bumpGeneration() {
+    mDevice->bumpGeneration();
+}
+
+void InputMapper::dumpRawAbsoluteAxisInfo(std::string& dump,
+        const RawAbsoluteAxisInfo& axis, const char* name) {
+    if (axis.valid) {
+        dump += StringPrintf(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n",
+                name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution);
+    } else {
+        dump += StringPrintf(INDENT4 "%s: unknown range\n", name);
+    }
+}
+
+void InputMapper::dumpStylusState(std::string& dump, const StylusState& state) {
+    dump += StringPrintf(INDENT4 "When: %" PRId64 "\n", state.when);
+    dump += StringPrintf(INDENT4 "Pressure: %f\n", state.pressure);
+    dump += StringPrintf(INDENT4 "Button State: 0x%08x\n", state.buttons);
+    dump += StringPrintf(INDENT4 "Tool Type: %" PRId32 "\n", state.toolType);
+}
+
+// --- SwitchInputMapper ---
+
+SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
+        InputMapper(device), mSwitchValues(0), mUpdatedSwitchMask(0) {
+}
+
+SwitchInputMapper::~SwitchInputMapper() {
+}
+
+uint32_t SwitchInputMapper::getSources() {
+    return AINPUT_SOURCE_SWITCH;
+}
+
+void SwitchInputMapper::process(const RawEvent* rawEvent) {
+    switch (rawEvent->type) {
+    case EV_SW:
+        processSwitch(rawEvent->code, rawEvent->value);
+        break;
+
+    case EV_SYN:
+        if (rawEvent->code == SYN_REPORT) {
+            sync(rawEvent->when);
+        }
+    }
+}
+
+void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
+    if (switchCode >= 0 && switchCode < 32) {
+        if (switchValue) {
+            mSwitchValues |= 1 << switchCode;
+        } else {
+            mSwitchValues &= ~(1 << switchCode);
+        }
+        mUpdatedSwitchMask |= 1 << switchCode;
+    }
+}
+
+void SwitchInputMapper::sync(nsecs_t when) {
+    if (mUpdatedSwitchMask) {
+        uint32_t updatedSwitchValues = mSwitchValues & mUpdatedSwitchMask;
+        NotifySwitchArgs args(mContext->getNextSequenceNum(), when, 0, updatedSwitchValues,
+                mUpdatedSwitchMask);
+        getListener()->notifySwitch(&args);
+
+        mUpdatedSwitchMask = 0;
+    }
+}
+
+int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
+    return getEventHub()->getSwitchState(getDeviceId(), switchCode);
+}
+
+void SwitchInputMapper::dump(std::string& dump) {
+    dump += INDENT2 "Switch Input Mapper:\n";
+    dump += StringPrintf(INDENT3 "SwitchValues: %x\n", mSwitchValues);
+}
+
+// --- VibratorInputMapper ---
+
+VibratorInputMapper::VibratorInputMapper(InputDevice* device) :
+        InputMapper(device), mVibrating(false) {
+}
+
+VibratorInputMapper::~VibratorInputMapper() {
+}
+
+uint32_t VibratorInputMapper::getSources() {
+    return 0;
+}
+
+void VibratorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+    InputMapper::populateDeviceInfo(info);
+
+    info->setVibrator(true);
+}
+
+void VibratorInputMapper::process(const RawEvent* rawEvent) {
+    // TODO: Handle FF_STATUS, although it does not seem to be widely supported.
+}
+
+void VibratorInputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
+        int32_t token) {
+#if DEBUG_VIBRATOR
+    std::string patternStr;
+    for (size_t i = 0; i < patternSize; i++) {
+        if (i != 0) {
+            patternStr += ", ";
+        }
+        patternStr += StringPrintf("%" PRId64, pattern[i]);
+    }
+    ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%zd, token=%d",
+            getDeviceId(), patternStr.c_str(), repeat, token);
+#endif
+
+    mVibrating = true;
+    memcpy(mPattern, pattern, patternSize * sizeof(nsecs_t));
+    mPatternSize = patternSize;
+    mRepeat = repeat;
+    mToken = token;
+    mIndex = -1;
+
+    nextStep();
+}
+
+void VibratorInputMapper::cancelVibrate(int32_t token) {
+#if DEBUG_VIBRATOR
+    ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
+#endif
+
+    if (mVibrating && mToken == token) {
+        stopVibrating();
+    }
+}
+
+void VibratorInputMapper::timeoutExpired(nsecs_t when) {
+    if (mVibrating) {
+        if (when >= mNextStepTime) {
+            nextStep();
+        } else {
+            getContext()->requestTimeoutAtTime(mNextStepTime);
+        }
+    }
+}
+
+void VibratorInputMapper::nextStep() {
+    mIndex += 1;
+    if (size_t(mIndex) >= mPatternSize) {
+        if (mRepeat < 0) {
+            // We are done.
+            stopVibrating();
+            return;
+        }
+        mIndex = mRepeat;
+    }
+
+    bool vibratorOn = mIndex & 1;
+    nsecs_t duration = mPattern[mIndex];
+    if (vibratorOn) {
+#if DEBUG_VIBRATOR
+        ALOGD("nextStep: sending vibrate deviceId=%d, duration=%" PRId64, getDeviceId(), duration);
+#endif
+        getEventHub()->vibrate(getDeviceId(), duration);
+    } else {
+#if DEBUG_VIBRATOR
+        ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
+#endif
+        getEventHub()->cancelVibrate(getDeviceId());
+    }
+    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+    mNextStepTime = now + duration;
+    getContext()->requestTimeoutAtTime(mNextStepTime);
+#if DEBUG_VIBRATOR
+    ALOGD("nextStep: scheduled timeout in %0.3fms", duration * 0.000001f);
+#endif
+}
+
+void VibratorInputMapper::stopVibrating() {
+    mVibrating = false;
+#if DEBUG_VIBRATOR
+    ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
+#endif
+    getEventHub()->cancelVibrate(getDeviceId());
+}
+
+void VibratorInputMapper::dump(std::string& dump) {
+    dump += INDENT2 "Vibrator Input Mapper:\n";
+    dump += StringPrintf(INDENT3 "Vibrating: %s\n", toString(mVibrating));
+}
+
+
+// --- KeyboardInputMapper ---
+
+KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
+        uint32_t source, int32_t keyboardType) :
+        InputMapper(device), mSource(source), mKeyboardType(keyboardType) {
+}
+
+KeyboardInputMapper::~KeyboardInputMapper() {
+}
+
+uint32_t KeyboardInputMapper::getSources() {
+    return mSource;
+}
+
+int32_t KeyboardInputMapper::getOrientation() {
+    if (mViewport) {
+        return mViewport->orientation;
+    }
+    return DISPLAY_ORIENTATION_0;
+}
+
+int32_t KeyboardInputMapper::getDisplayId() {
+    if (mViewport) {
+        return mViewport->displayId;
+    }
+    return ADISPLAY_ID_NONE;
+}
+
+void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+    InputMapper::populateDeviceInfo(info);
+
+    info->setKeyboardType(mKeyboardType);
+    info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId()));
+}
+
+void KeyboardInputMapper::dump(std::string& dump) {
+    dump += INDENT2 "Keyboard Input Mapper:\n";
+    dumpParameters(dump);
+    dump += StringPrintf(INDENT3 "KeyboardType: %d\n", mKeyboardType);
+    dump += StringPrintf(INDENT3 "Orientation: %d\n", getOrientation());
+    dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
+    dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState);
+    dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
+}
+
+void KeyboardInputMapper::configure(nsecs_t when,
+        const InputReaderConfiguration* config, uint32_t changes) {
+    InputMapper::configure(when, config, changes);
+
+    if (!changes) { // first time only
+        // Configure basic parameters.
+        configureParameters();
+    }
+
+    if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+        if (mParameters.orientationAware) {
+            mViewport = config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+        }
+    }
+}
+
+static void mapStemKey(int32_t keyCode, const PropertyMap& config, char const *property) {
+    int32_t mapped = 0;
+    if (config.tryGetProperty(String8(property), mapped) && mapped > 0) {
+        for (size_t i = 0; i < stemKeyRotationMapSize; i++) {
+            if (stemKeyRotationMap[i][0] == keyCode) {
+                stemKeyRotationMap[i][1] = mapped;
+                return;
+            }
+        }
+    }
+}
+
+void KeyboardInputMapper::configureParameters() {
+    mParameters.orientationAware = false;
+    const PropertyMap& config = getDevice()->getConfiguration();
+    config.tryGetProperty(String8("keyboard.orientationAware"),
+            mParameters.orientationAware);
+
+    if (mParameters.orientationAware) {
+        mapStemKey(AKEYCODE_STEM_PRIMARY, config, "keyboard.rotated.stem_primary");
+        mapStemKey(AKEYCODE_STEM_1, config, "keyboard.rotated.stem_1");
+        mapStemKey(AKEYCODE_STEM_2, config, "keyboard.rotated.stem_2");
+        mapStemKey(AKEYCODE_STEM_3, config, "keyboard.rotated.stem_3");
+    }
+
+    mParameters.handlesKeyRepeat = false;
+    config.tryGetProperty(String8("keyboard.handlesKeyRepeat"),
+            mParameters.handlesKeyRepeat);
+}
+
+void KeyboardInputMapper::dumpParameters(std::string& dump) {
+    dump += INDENT3 "Parameters:\n";
+    dump += StringPrintf(INDENT4 "OrientationAware: %s\n",
+            toString(mParameters.orientationAware));
+    dump += StringPrintf(INDENT4 "HandlesKeyRepeat: %s\n",
+            toString(mParameters.handlesKeyRepeat));
+}
+
+void KeyboardInputMapper::reset(nsecs_t when) {
+    mMetaState = AMETA_NONE;
+    mDownTime = 0;
+    mKeyDowns.clear();
+    mCurrentHidUsage = 0;
+
+    resetLedState();
+
+    InputMapper::reset(when);
+}
+
+void KeyboardInputMapper::process(const RawEvent* rawEvent) {
+    switch (rawEvent->type) {
+    case EV_KEY: {
+        int32_t scanCode = rawEvent->code;
+        int32_t usageCode = mCurrentHidUsage;
+        mCurrentHidUsage = 0;
+
+        if (isKeyboardOrGamepadKey(scanCode)) {
+            processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);
+        }
+        break;
+    }
+    case EV_MSC: {
+        if (rawEvent->code == MSC_SCAN) {
+            mCurrentHidUsage = rawEvent->value;
+        }
+        break;
+    }
+    case EV_SYN: {
+        if (rawEvent->code == SYN_REPORT) {
+            mCurrentHidUsage = 0;
+        }
+    }
+    }
+}
+
+bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
+    return scanCode < BTN_MOUSE
+        || scanCode >= KEY_OK
+        || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
+        || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
+}
+
+bool KeyboardInputMapper::isMediaKey(int32_t keyCode) {
+    switch (keyCode) {
+    case AKEYCODE_MEDIA_PLAY:
+    case AKEYCODE_MEDIA_PAUSE:
+    case AKEYCODE_MEDIA_PLAY_PAUSE:
+    case AKEYCODE_MUTE:
+    case AKEYCODE_HEADSETHOOK:
+    case AKEYCODE_MEDIA_STOP:
+    case AKEYCODE_MEDIA_NEXT:
+    case AKEYCODE_MEDIA_PREVIOUS:
+    case AKEYCODE_MEDIA_REWIND:
+    case AKEYCODE_MEDIA_RECORD:
+    case AKEYCODE_MEDIA_FAST_FORWARD:
+    case AKEYCODE_MEDIA_SKIP_FORWARD:
+    case AKEYCODE_MEDIA_SKIP_BACKWARD:
+    case AKEYCODE_MEDIA_STEP_FORWARD:
+    case AKEYCODE_MEDIA_STEP_BACKWARD:
+    case AKEYCODE_MEDIA_AUDIO_TRACK:
+    case AKEYCODE_VOLUME_UP:
+    case AKEYCODE_VOLUME_DOWN:
+    case AKEYCODE_VOLUME_MUTE:
+    case AKEYCODE_TV_AUDIO_DESCRIPTION:
+    case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP:
+    case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN:
+        return true;
+    }
+    return false;
+}
+
+void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
+        int32_t usageCode) {
+    int32_t keyCode;
+    int32_t keyMetaState;
+    uint32_t policyFlags;
+
+    if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, mMetaState,
+                              &keyCode, &keyMetaState, &policyFlags)) {
+        keyCode = AKEYCODE_UNKNOWN;
+        keyMetaState = mMetaState;
+        policyFlags = 0;
+    }
+
+    if (down) {
+        // Rotate key codes according to orientation if needed.
+        if (mParameters.orientationAware) {
+            keyCode = rotateKeyCode(keyCode, getOrientation());
+        }
+
+        // Add key down.
+        ssize_t keyDownIndex = findKeyDown(scanCode);
+        if (keyDownIndex >= 0) {
+            // key repeat, be sure to use same keycode as before in case of rotation
+            keyCode = mKeyDowns[keyDownIndex].keyCode;
+        } else {
+            // key down
+            if ((policyFlags & POLICY_FLAG_VIRTUAL)
+                    && mContext->shouldDropVirtualKey(when,
+                            getDevice(), keyCode, scanCode)) {
+                return;
+            }
+            if (policyFlags & POLICY_FLAG_GESTURE) {
+                mDevice->cancelTouch(when);
+            }
+
+            KeyDown keyDown;
+            keyDown.keyCode = keyCode;
+            keyDown.scanCode = scanCode;
+            mKeyDowns.push_back(keyDown);
+        }
+
+        mDownTime = when;
+    } else {
+        // Remove key down.
+        ssize_t keyDownIndex = findKeyDown(scanCode);
+        if (keyDownIndex >= 0) {
+            // key up, be sure to use same keycode as before in case of rotation
+            keyCode = mKeyDowns[keyDownIndex].keyCode;
+            mKeyDowns.erase(mKeyDowns.begin() + (size_t)keyDownIndex);
+        } else {
+            // key was not actually down
+            ALOGI("Dropping key up from device %s because the key was not down.  "
+                    "keyCode=%d, scanCode=%d",
+                    getDeviceName().c_str(), keyCode, scanCode);
+            return;
+        }
+    }
+
+    if (updateMetaStateIfNeeded(keyCode, down)) {
+        // If global meta state changed send it along with the key.
+        // If it has not changed then we'll use what keymap gave us,
+        // since key replacement logic might temporarily reset a few
+        // meta bits for given key.
+        keyMetaState = mMetaState;
+    }
+
+    nsecs_t downTime = mDownTime;
+
+    // Key down on external an keyboard should wake the device.
+    // We don't do this for internal keyboards to prevent them from waking up in your pocket.
+    // For internal keyboards, the key layout file should specify the policy flags for
+    // each wake key individually.
+    // TODO: Use the input device configuration to control this behavior more finely.
+    if (down && getDevice()->isExternal() && !isMediaKey(keyCode)) {
+        policyFlags |= POLICY_FLAG_WAKE;
+    }
+
+    if (mParameters.handlesKeyRepeat) {
+        policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
+    }
+
+    NotifyKeyArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+            getDisplayId(), policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
+            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
+    getListener()->notifyKey(&args);
+}
+
+ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) {
+    size_t n = mKeyDowns.size();
+    for (size_t i = 0; i < n; i++) {
+        if (mKeyDowns[i].scanCode == scanCode) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
+    return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
+}
+
+int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+    return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
+}
+
+bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+        const int32_t* keyCodes, uint8_t* outFlags) {
+    return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
+}
+
+int32_t KeyboardInputMapper::getMetaState() {
+    return mMetaState;
+}
+
+void KeyboardInputMapper::updateMetaState(int32_t keyCode) {
+    updateMetaStateIfNeeded(keyCode, false);
+}
+
+bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
+    int32_t oldMetaState = mMetaState;
+    int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
+    bool metaStateChanged = oldMetaState != newMetaState;
+    if (metaStateChanged) {
+        mMetaState = newMetaState;
+        updateLedState(false);
+
+        getContext()->updateGlobalMetaState();
+    }
+
+    return metaStateChanged;
+}
+
+void KeyboardInputMapper::resetLedState() {
+    initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
+    initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
+    initializeLedState(mScrollLockLedState, ALED_SCROLL_LOCK);
+
+    updateLedState(true);
+}
+
+void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
+    ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
+    ledState.on = false;
+}
+
+void KeyboardInputMapper::updateLedState(bool reset) {
+    updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK,
+            AMETA_CAPS_LOCK_ON, reset);
+    updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK,
+            AMETA_NUM_LOCK_ON, reset);
+    updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK,
+            AMETA_SCROLL_LOCK_ON, reset);
+}
+
+void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState,
+        int32_t led, int32_t modifier, bool reset) {
+    if (ledState.avail) {
+        bool desiredState = (mMetaState & modifier) != 0;
+        if (reset || ledState.on != desiredState) {
+            getEventHub()->setLedState(getDeviceId(), led, desiredState);
+            ledState.on = desiredState;
+        }
+    }
+}
+
+
+// --- CursorInputMapper ---
+
+CursorInputMapper::CursorInputMapper(InputDevice* device) :
+        InputMapper(device) {
+}
+
+CursorInputMapper::~CursorInputMapper() {
+}
+
+uint32_t CursorInputMapper::getSources() {
+    return mSource;
+}
+
+void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+    InputMapper::populateDeviceInfo(info);
+
+    if (mParameters.mode == Parameters::MODE_POINTER) {
+        float minX, minY, maxX, maxY;
+        if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
+            info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f, 0.0f);
+            info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f, 0.0f);
+        }
+    } else {
+        info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
+        info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
+    }
+    info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
+
+    if (mCursorScrollAccumulator.haveRelativeVWheel()) {
+        info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
+    }
+    if (mCursorScrollAccumulator.haveRelativeHWheel()) {
+        info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
+    }
+}
+
+void CursorInputMapper::dump(std::string& dump) {
+    dump += INDENT2 "Cursor Input Mapper:\n";
+    dumpParameters(dump);
+    dump += StringPrintf(INDENT3 "XScale: %0.3f\n", mXScale);
+    dump += StringPrintf(INDENT3 "YScale: %0.3f\n", mYScale);
+    dump += StringPrintf(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
+    dump += StringPrintf(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
+    dump += StringPrintf(INDENT3 "HaveVWheel: %s\n",
+            toString(mCursorScrollAccumulator.haveRelativeVWheel()));
+    dump += StringPrintf(INDENT3 "HaveHWheel: %s\n",
+            toString(mCursorScrollAccumulator.haveRelativeHWheel()));
+    dump += StringPrintf(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
+    dump += StringPrintf(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
+    dump += StringPrintf(INDENT3 "Orientation: %d\n", mOrientation);
+    dump += StringPrintf(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
+    dump += StringPrintf(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
+    dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
+}
+
+void CursorInputMapper::configure(nsecs_t when,
+        const InputReaderConfiguration* config, uint32_t changes) {
+    InputMapper::configure(when, config, changes);
+
+    if (!changes) { // first time only
+        mCursorScrollAccumulator.configure(getDevice());
+
+        // Configure basic parameters.
+        configureParameters();
+
+        // Configure device mode.
+        switch (mParameters.mode) {
+        case Parameters::MODE_POINTER_RELATIVE:
+            // Should not happen during first time configuration.
+            ALOGE("Cannot start a device in MODE_POINTER_RELATIVE, starting in MODE_POINTER");
+            mParameters.mode = Parameters::MODE_POINTER;
+            [[fallthrough]];
+        case Parameters::MODE_POINTER:
+            mSource = AINPUT_SOURCE_MOUSE;
+            mXPrecision = 1.0f;
+            mYPrecision = 1.0f;
+            mXScale = 1.0f;
+            mYScale = 1.0f;
+            mPointerController = getPolicy()->obtainPointerController(getDeviceId());
+            break;
+        case Parameters::MODE_NAVIGATION:
+            mSource = AINPUT_SOURCE_TRACKBALL;
+            mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
+            mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
+            mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
+            mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
+            break;
+        }
+
+        mVWheelScale = 1.0f;
+        mHWheelScale = 1.0f;
+    }
+
+    if ((!changes && config->pointerCapture)
+            || (changes & InputReaderConfiguration::CHANGE_POINTER_CAPTURE)) {
+        if (config->pointerCapture) {
+            if (mParameters.mode == Parameters::MODE_POINTER) {
+                mParameters.mode = Parameters::MODE_POINTER_RELATIVE;
+                mSource = AINPUT_SOURCE_MOUSE_RELATIVE;
+                // Keep PointerController around in order to preserve the pointer position.
+                mPointerController->fade(PointerControllerInterface::TRANSITION_IMMEDIATE);
+            } else {
+                ALOGE("Cannot request pointer capture, device is not in MODE_POINTER");
+            }
+        } else {
+            if (mParameters.mode == Parameters::MODE_POINTER_RELATIVE) {
+                mParameters.mode = Parameters::MODE_POINTER;
+                mSource = AINPUT_SOURCE_MOUSE;
+            } else {
+                ALOGE("Cannot release pointer capture, device is not in MODE_POINTER_RELATIVE");
+            }
+        }
+        bumpGeneration();
+        if (changes) {
+            getDevice()->notifyReset(when);
+        }
+    }
+
+    if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
+        mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
+        mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
+        mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
+    }
+
+    if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+        mOrientation = DISPLAY_ORIENTATION_0;
+        if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
+            std::optional<DisplayViewport> internalViewport =
+                    config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+            if (internalViewport) {
+                mOrientation = internalViewport->orientation;
+            }
+        }
+
+        // Update the PointerController if viewports changed.
+        if (mParameters.mode == Parameters::MODE_POINTER) {
+            getPolicy()->obtainPointerController(getDeviceId());
+        }
+        bumpGeneration();
+    }
+}
+
+void CursorInputMapper::configureParameters() {
+    mParameters.mode = Parameters::MODE_POINTER;
+    String8 cursorModeString;
+    if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
+        if (cursorModeString == "navigation") {
+            mParameters.mode = Parameters::MODE_NAVIGATION;
+        } else if (cursorModeString != "pointer" && cursorModeString != "default") {
+            ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
+        }
+    }
+
+    mParameters.orientationAware = false;
+    getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
+            mParameters.orientationAware);
+
+    mParameters.hasAssociatedDisplay = false;
+    if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) {
+        mParameters.hasAssociatedDisplay = true;
+    }
+}
+
+void CursorInputMapper::dumpParameters(std::string& dump) {
+    dump += INDENT3 "Parameters:\n";
+    dump += StringPrintf(INDENT4 "HasAssociatedDisplay: %s\n",
+            toString(mParameters.hasAssociatedDisplay));
+
+    switch (mParameters.mode) {
+    case Parameters::MODE_POINTER:
+        dump += INDENT4 "Mode: pointer\n";
+        break;
+    case Parameters::MODE_POINTER_RELATIVE:
+        dump += INDENT4 "Mode: relative pointer\n";
+        break;
+    case Parameters::MODE_NAVIGATION:
+        dump += INDENT4 "Mode: navigation\n";
+        break;
+    default:
+        ALOG_ASSERT(false);
+    }
+
+    dump += StringPrintf(INDENT4 "OrientationAware: %s\n",
+            toString(mParameters.orientationAware));
+}
+
+void CursorInputMapper::reset(nsecs_t when) {
+    mButtonState = 0;
+    mDownTime = 0;
+
+    mPointerVelocityControl.reset();
+    mWheelXVelocityControl.reset();
+    mWheelYVelocityControl.reset();
+
+    mCursorButtonAccumulator.reset(getDevice());
+    mCursorMotionAccumulator.reset(getDevice());
+    mCursorScrollAccumulator.reset(getDevice());
+
+    InputMapper::reset(when);
+}
+
+void CursorInputMapper::process(const RawEvent* rawEvent) {
+    mCursorButtonAccumulator.process(rawEvent);
+    mCursorMotionAccumulator.process(rawEvent);
+    mCursorScrollAccumulator.process(rawEvent);
+
+    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
+        sync(rawEvent->when);
+    }
+}
+
+void CursorInputMapper::sync(nsecs_t when) {
+    int32_t lastButtonState = mButtonState;
+    int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
+    mButtonState = currentButtonState;
+
+    bool wasDown = isPointerDown(lastButtonState);
+    bool down = isPointerDown(currentButtonState);
+    bool downChanged;
+    if (!wasDown && down) {
+        mDownTime = when;
+        downChanged = true;
+    } else if (wasDown && !down) {
+        downChanged = true;
+    } else {
+        downChanged = false;
+    }
+    nsecs_t downTime = mDownTime;
+    bool buttonsChanged = currentButtonState != lastButtonState;
+    int32_t buttonsPressed = currentButtonState & ~lastButtonState;
+    int32_t buttonsReleased = lastButtonState & ~currentButtonState;
+
+    float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
+    float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
+    bool moved = deltaX != 0 || deltaY != 0;
+
+    // Rotate delta according to orientation if needed.
+    if (mParameters.orientationAware && mParameters.hasAssociatedDisplay
+            && (deltaX != 0.0f || deltaY != 0.0f)) {
+        rotateDelta(mOrientation, &deltaX, &deltaY);
+    }
+
+    // Move the pointer.
+    PointerProperties pointerProperties;
+    pointerProperties.clear();
+    pointerProperties.id = 0;
+    pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
+
+    PointerCoords pointerCoords;
+    pointerCoords.clear();
+
+    float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
+    float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
+    bool scrolled = vscroll != 0 || hscroll != 0;
+
+    mWheelYVelocityControl.move(when, nullptr, &vscroll);
+    mWheelXVelocityControl.move(when, &hscroll, nullptr);
+
+    mPointerVelocityControl.move(when, &deltaX, &deltaY);
+
+    int32_t displayId;
+    if (mSource == AINPUT_SOURCE_MOUSE) {
+        if (moved || scrolled || buttonsChanged) {
+            mPointerController->setPresentation(
+                    PointerControllerInterface::PRESENTATION_POINTER);
+
+            if (moved) {
+                mPointerController->move(deltaX, deltaY);
+            }
+
+            if (buttonsChanged) {
+                mPointerController->setButtonState(currentButtonState);
+            }
+
+            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
+        }
+
+        float x, y;
+        mPointerController->getPosition(&x, &y);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
+        displayId = mPointerController->getDisplayId();
+    } else {
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
+        displayId = ADISPLAY_ID_NONE;
+    }
+
+    pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
+
+    // Moving an external trackball or mouse should wake the device.
+    // We don't do this for internal cursor devices to prevent them from waking up
+    // the device in your pocket.
+    // TODO: Use the input device configuration to control this behavior more finely.
+    uint32_t policyFlags = 0;
+    if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) {
+        policyFlags |= POLICY_FLAG_WAKE;
+    }
+
+    // Synthesize key down from buttons if needed.
+    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
+            displayId, policyFlags, lastButtonState, currentButtonState);
+
+    // Send motion event.
+    if (downChanged || moved || scrolled || buttonsChanged) {
+        int32_t metaState = mContext->getGlobalMetaState();
+        int32_t buttonState = lastButtonState;
+        int32_t motionEventAction;
+        if (downChanged) {
+            motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
+        } else if (down || (mSource != AINPUT_SOURCE_MOUSE)) {
+            motionEventAction = AMOTION_EVENT_ACTION_MOVE;
+        } else {
+            motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
+        }
+
+        if (buttonsReleased) {
+            BitSet32 released(buttonsReleased);
+            while (!released.isEmpty()) {
+                int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
+                buttonState &= ~actionButton;
+                NotifyMotionArgs releaseArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
+                        mSource, displayId, policyFlags,
+                        AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
+                        metaState, buttonState,
+                        MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+                        /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+                        mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+                getListener()->notifyMotion(&releaseArgs);
+            }
+        }
+
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                displayId, policyFlags, motionEventAction, 0, 0, metaState, currentButtonState,
+                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+                /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+                mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+        getListener()->notifyMotion(&args);
+
+        if (buttonsPressed) {
+            BitSet32 pressed(buttonsPressed);
+            while (!pressed.isEmpty()) {
+                int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
+                buttonState |= actionButton;
+                NotifyMotionArgs pressArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
+                        mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_BUTTON_PRESS,
+                        actionButton, 0, metaState, buttonState,
+                        MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+                        /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+                        mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+                getListener()->notifyMotion(&pressArgs);
+            }
+        }
+
+        ALOG_ASSERT(buttonState == currentButtonState);
+
+        // Send hover move after UP to tell the application that the mouse is hovering now.
+        if (motionEventAction == AMOTION_EVENT_ACTION_UP
+                && (mSource == AINPUT_SOURCE_MOUSE)) {
+            NotifyMotionArgs hoverArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
+                    mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
+                    metaState, currentButtonState,
+                    MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+                    /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+                    mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+            getListener()->notifyMotion(&hoverArgs);
+        }
+
+        // Send scroll events.
+        if (scrolled) {
+            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
+            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
+
+            NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
+                    mSource, displayId, policyFlags,
+                    AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, currentButtonState,
+                    MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+                    /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+                    mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+            getListener()->notifyMotion(&scrollArgs);
+        }
+    }
+
+    // Synthesize key up from buttons if needed.
+    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
+            displayId, policyFlags, lastButtonState, currentButtonState);
+
+    mCursorMotionAccumulator.finishSync();
+    mCursorScrollAccumulator.finishSync();
+}
+
+int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+    if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
+        return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
+    } else {
+        return AKEY_STATE_UNKNOWN;
+    }
+}
+
+void CursorInputMapper::fadePointer() {
+    if (mPointerController != nullptr) {
+        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+    }
+}
+
+std::optional<int32_t> CursorInputMapper::getAssociatedDisplay() {
+    if (mParameters.hasAssociatedDisplay) {
+        if (mParameters.mode == Parameters::MODE_POINTER) {
+            return std::make_optional(mPointerController->getDisplayId());
+        } else {
+            // If the device is orientationAware and not a mouse,
+            // it expects to dispatch events to any display
+            return std::make_optional(ADISPLAY_ID_NONE);
+        }
+    }
+    return std::nullopt;
+}
+
+// --- RotaryEncoderInputMapper ---
+
+RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDevice* device) :
+        InputMapper(device), mOrientation(DISPLAY_ORIENTATION_0) {
+    mSource = AINPUT_SOURCE_ROTARY_ENCODER;
+}
+
+RotaryEncoderInputMapper::~RotaryEncoderInputMapper() {
+}
+
+uint32_t RotaryEncoderInputMapper::getSources() {
+    return mSource;
+}
+
+void RotaryEncoderInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+    InputMapper::populateDeviceInfo(info);
+
+    if (mRotaryEncoderScrollAccumulator.haveRelativeVWheel()) {
+        float res = 0.0f;
+        if (!mDevice->getConfiguration().tryGetProperty(String8("device.res"), res)) {
+            ALOGW("Rotary Encoder device configuration file didn't specify resolution!\n");
+        }
+        if (!mDevice->getConfiguration().tryGetProperty(String8("device.scalingFactor"),
+            mScalingFactor)) {
+            ALOGW("Rotary Encoder device configuration file didn't specify scaling factor,"
+              "default to 1.0!\n");
+            mScalingFactor = 1.0f;
+        }
+        info->addMotionRange(AMOTION_EVENT_AXIS_SCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
+            res * mScalingFactor);
+    }
+}
+
+void RotaryEncoderInputMapper::dump(std::string& dump) {
+    dump += INDENT2 "Rotary Encoder Input Mapper:\n";
+    dump += StringPrintf(INDENT3 "HaveWheel: %s\n",
+            toString(mRotaryEncoderScrollAccumulator.haveRelativeVWheel()));
+}
+
+void RotaryEncoderInputMapper::configure(nsecs_t when,
+        const InputReaderConfiguration* config, uint32_t changes) {
+    InputMapper::configure(when, config, changes);
+    if (!changes) {
+        mRotaryEncoderScrollAccumulator.configure(getDevice());
+    }
+    if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+        std::optional<DisplayViewport> internalViewport =
+                config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+        if (internalViewport) {
+            mOrientation = internalViewport->orientation;
+        } else {
+            mOrientation = DISPLAY_ORIENTATION_0;
+        }
+    }
+}
+
+void RotaryEncoderInputMapper::reset(nsecs_t when) {
+    mRotaryEncoderScrollAccumulator.reset(getDevice());
+
+    InputMapper::reset(when);
+}
+
+void RotaryEncoderInputMapper::process(const RawEvent* rawEvent) {
+    mRotaryEncoderScrollAccumulator.process(rawEvent);
+
+    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
+        sync(rawEvent->when);
+    }
+}
+
+void RotaryEncoderInputMapper::sync(nsecs_t when) {
+    PointerCoords pointerCoords;
+    pointerCoords.clear();
+
+    PointerProperties pointerProperties;
+    pointerProperties.clear();
+    pointerProperties.id = 0;
+    pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+
+    float scroll = mRotaryEncoderScrollAccumulator.getRelativeVWheel();
+    bool scrolled = scroll != 0;
+
+    // This is not a pointer, so it's not associated with a display.
+    int32_t displayId = ADISPLAY_ID_NONE;
+
+    // Moving the rotary encoder should wake the device (if specified).
+    uint32_t policyFlags = 0;
+    if (scrolled && getDevice()->isExternal()) {
+        policyFlags |= POLICY_FLAG_WAKE;
+    }
+
+    if (mOrientation == DISPLAY_ORIENTATION_180) {
+        scroll = -scroll;
+    }
+
+    // Send motion event.
+    if (scrolled) {
+        int32_t metaState = mContext->getGlobalMetaState();
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor);
+
+        NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
+                AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, /* buttonState */ 0,
+                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+                /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+                0, 0, 0, /* videoFrames */ {});
+        getListener()->notifyMotion(&scrollArgs);
+    }
+
+    mRotaryEncoderScrollAccumulator.finishSync();
+}
+
+// --- TouchInputMapper ---
+
+TouchInputMapper::TouchInputMapper(InputDevice* device) :
+        InputMapper(device),
+        mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
+        mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0),
+        mPhysicalWidth(-1), mPhysicalHeight(-1), mPhysicalLeft(0), mPhysicalTop(0),
+        mSurfaceOrientation(DISPLAY_ORIENTATION_0) {
+}
+
+TouchInputMapper::~TouchInputMapper() {
+}
+
+uint32_t TouchInputMapper::getSources() {
+    return mSource;
+}
+
+void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+    InputMapper::populateDeviceInfo(info);
+
+    if (mDeviceMode != DEVICE_MODE_DISABLED) {
+        info->addMotionRange(mOrientedRanges.x);
+        info->addMotionRange(mOrientedRanges.y);
+        info->addMotionRange(mOrientedRanges.pressure);
+
+        if (mOrientedRanges.haveSize) {
+            info->addMotionRange(mOrientedRanges.size);
+        }
+
+        if (mOrientedRanges.haveTouchSize) {
+            info->addMotionRange(mOrientedRanges.touchMajor);
+            info->addMotionRange(mOrientedRanges.touchMinor);
+        }
+
+        if (mOrientedRanges.haveToolSize) {
+            info->addMotionRange(mOrientedRanges.toolMajor);
+            info->addMotionRange(mOrientedRanges.toolMinor);
+        }
+
+        if (mOrientedRanges.haveOrientation) {
+            info->addMotionRange(mOrientedRanges.orientation);
+        }
+
+        if (mOrientedRanges.haveDistance) {
+            info->addMotionRange(mOrientedRanges.distance);
+        }
+
+        if (mOrientedRanges.haveTilt) {
+            info->addMotionRange(mOrientedRanges.tilt);
+        }
+
+        if (mCursorScrollAccumulator.haveRelativeVWheel()) {
+            info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
+                    0.0f);
+        }
+        if (mCursorScrollAccumulator.haveRelativeHWheel()) {
+            info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
+                    0.0f);
+        }
+        if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
+            const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
+            const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
+            info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat,
+                    x.fuzz, x.resolution);
+            info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat,
+                    y.fuzz, y.resolution);
+            info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat,
+                    x.fuzz, x.resolution);
+            info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat,
+                    y.fuzz, y.resolution);
+        }
+        info->setButtonUnderPad(mParameters.hasButtonUnderPad);
+    }
+}
+
+void TouchInputMapper::dump(std::string& dump) {
+    dump += StringPrintf(INDENT2 "Touch Input Mapper (mode - %s):\n", modeToString(mDeviceMode));
+    dumpParameters(dump);
+    dumpVirtualKeys(dump);
+    dumpRawPointerAxes(dump);
+    dumpCalibration(dump);
+    dumpAffineTransformation(dump);
+    dumpSurface(dump);
+
+    dump += StringPrintf(INDENT3 "Translation and Scaling Factors:\n");
+    dump += StringPrintf(INDENT4 "XTranslate: %0.3f\n", mXTranslate);
+    dump += StringPrintf(INDENT4 "YTranslate: %0.3f\n", mYTranslate);
+    dump += StringPrintf(INDENT4 "XScale: %0.3f\n", mXScale);
+    dump += StringPrintf(INDENT4 "YScale: %0.3f\n", mYScale);
+    dump += StringPrintf(INDENT4 "XPrecision: %0.3f\n", mXPrecision);
+    dump += StringPrintf(INDENT4 "YPrecision: %0.3f\n", mYPrecision);
+    dump += StringPrintf(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
+    dump += StringPrintf(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
+    dump += StringPrintf(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
+    dump += StringPrintf(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
+    dump += StringPrintf(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
+    dump += StringPrintf(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
+    dump += StringPrintf(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter);
+    dump += StringPrintf(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale);
+    dump += StringPrintf(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
+    dump += StringPrintf(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
+
+    dump += StringPrintf(INDENT3 "Last Raw Button State: 0x%08x\n", mLastRawState.buttonState);
+    dump += StringPrintf(INDENT3 "Last Raw Touch: pointerCount=%d\n",
+            mLastRawState.rawPointerData.pointerCount);
+    for (uint32_t i = 0; i < mLastRawState.rawPointerData.pointerCount; i++) {
+        const RawPointerData::Pointer& pointer = mLastRawState.rawPointerData.pointers[i];
+        dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
+                "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
+                "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, "
+                "toolType=%d, isHovering=%s\n", i,
+                pointer.id, pointer.x, pointer.y, pointer.pressure,
+                pointer.touchMajor, pointer.touchMinor,
+                pointer.toolMajor, pointer.toolMinor,
+                pointer.orientation, pointer.tiltX, pointer.tiltY, pointer.distance,
+                pointer.toolType, toString(pointer.isHovering));
+    }
+
+    dump += StringPrintf(INDENT3 "Last Cooked Button State: 0x%08x\n", mLastCookedState.buttonState);
+    dump += StringPrintf(INDENT3 "Last Cooked Touch: pointerCount=%d\n",
+            mLastCookedState.cookedPointerData.pointerCount);
+    for (uint32_t i = 0; i < mLastCookedState.cookedPointerData.pointerCount; i++) {
+        const PointerProperties& pointerProperties =
+                mLastCookedState.cookedPointerData.pointerProperties[i];
+        const PointerCoords& pointerCoords = mLastCookedState.cookedPointerData.pointerCoords[i];
+        dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
+                "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, toolMinor=%0.3f, "
+                "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
+                "toolType=%d, isHovering=%s\n", i,
+                pointerProperties.id,
+                pointerCoords.getX(),
+                pointerCoords.getY(),
+                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
+                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
+                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
+                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
+                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
+                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
+                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT),
+                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE),
+                pointerProperties.toolType,
+                toString(mLastCookedState.cookedPointerData.isHovering(i)));
+    }
+
+    dump += INDENT3 "Stylus Fusion:\n";
+    dump += StringPrintf(INDENT4 "ExternalStylusConnected: %s\n",
+            toString(mExternalStylusConnected));
+    dump += StringPrintf(INDENT4 "External Stylus ID: %" PRId64 "\n", mExternalStylusId);
+    dump += StringPrintf(INDENT4 "External Stylus Data Timeout: %" PRId64 "\n",
+            mExternalStylusFusionTimeout);
+    dump += INDENT3 "External Stylus State:\n";
+    dumpStylusState(dump, mExternalStylusState);
+
+    if (mDeviceMode == DEVICE_MODE_POINTER) {
+        dump += StringPrintf(INDENT3 "Pointer Gesture Detector:\n");
+        dump += StringPrintf(INDENT4 "XMovementScale: %0.3f\n",
+                mPointerXMovementScale);
+        dump += StringPrintf(INDENT4 "YMovementScale: %0.3f\n",
+                mPointerYMovementScale);
+        dump += StringPrintf(INDENT4 "XZoomScale: %0.3f\n",
+                mPointerXZoomScale);
+        dump += StringPrintf(INDENT4 "YZoomScale: %0.3f\n",
+                mPointerYZoomScale);
+        dump += StringPrintf(INDENT4 "MaxSwipeWidth: %f\n",
+                mPointerGestureMaxSwipeWidth);
+    }
+}
+
+const char* TouchInputMapper::modeToString(DeviceMode deviceMode) {
+    switch (deviceMode) {
+    case DEVICE_MODE_DISABLED:
+        return "disabled";
+    case DEVICE_MODE_DIRECT:
+        return "direct";
+    case DEVICE_MODE_UNSCALED:
+        return "unscaled";
+    case DEVICE_MODE_NAVIGATION:
+        return "navigation";
+    case DEVICE_MODE_POINTER:
+        return "pointer";
+    }
+    return "unknown";
+}
+
+void TouchInputMapper::configure(nsecs_t when,
+        const InputReaderConfiguration* config, uint32_t changes) {
+    InputMapper::configure(when, config, changes);
+
+    mConfig = *config;
+
+    if (!changes) { // first time only
+        // Configure basic parameters.
+        configureParameters();
+
+        // Configure common accumulators.
+        mCursorScrollAccumulator.configure(getDevice());
+        mTouchButtonAccumulator.configure(getDevice());
+
+        // Configure absolute axis information.
+        configureRawPointerAxes();
+
+        // Prepare input device calibration.
+        parseCalibration();
+        resolveCalibration();
+    }
+
+    if (!changes || (changes & InputReaderConfiguration::CHANGE_TOUCH_AFFINE_TRANSFORMATION)) {
+        // Update location calibration to reflect current settings
+        updateAffineTransformation();
+    }
+
+    if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
+        // Update pointer speed.
+        mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters);
+        mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
+        mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
+    }
+
+    bool resetNeeded = false;
+    if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO
+            | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT
+            | InputReaderConfiguration::CHANGE_SHOW_TOUCHES
+            | InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE))) {
+        // Configure device sources, surface dimensions, orientation and
+        // scaling factors.
+        configureSurface(when, &resetNeeded);
+    }
+
+    if (changes && resetNeeded) {
+        // Send reset, unless this is the first time the device has been configured,
+        // in which case the reader will call reset itself after all mappers are ready.
+        getDevice()->notifyReset(when);
+    }
+}
+
+void TouchInputMapper::resolveExternalStylusPresence() {
+    std::vector<InputDeviceInfo> devices;
+    mContext->getExternalStylusDevices(devices);
+    mExternalStylusConnected = !devices.empty();
+
+    if (!mExternalStylusConnected) {
+        resetExternalStylus();
+    }
+}
+
+void TouchInputMapper::configureParameters() {
+    // Use the pointer presentation mode for devices that do not support distinct
+    // multitouch.  The spot-based presentation relies on being able to accurately
+    // locate two or more fingers on the touch pad.
+    mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
+            ? Parameters::GESTURE_MODE_SINGLE_TOUCH : Parameters::GESTURE_MODE_MULTI_TOUCH;
+
+    String8 gestureModeString;
+    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
+            gestureModeString)) {
+        if (gestureModeString == "single-touch") {
+            mParameters.gestureMode = Parameters::GESTURE_MODE_SINGLE_TOUCH;
+        } else if (gestureModeString == "multi-touch") {
+            mParameters.gestureMode = Parameters::GESTURE_MODE_MULTI_TOUCH;
+        } else if (gestureModeString != "default") {
+            ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
+        }
+    }
+
+    if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
+        // The device is a touch screen.
+        mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
+    } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
+        // The device is a pointing device like a track pad.
+        mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
+    } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
+            || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
+        // The device is a cursor device with a touch pad attached.
+        // By default don't use the touch pad to move the pointer.
+        mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
+    } else {
+        // The device is a touch pad of unknown purpose.
+        mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
+    }
+
+    mParameters.hasButtonUnderPad=
+            getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_BUTTONPAD);
+
+    String8 deviceTypeString;
+    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
+            deviceTypeString)) {
+        if (deviceTypeString == "touchScreen") {
+            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
+        } else if (deviceTypeString == "touchPad") {
+            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
+        } else if (deviceTypeString == "touchNavigation") {
+            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION;
+        } else if (deviceTypeString == "pointer") {
+            mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
+        } else if (deviceTypeString != "default") {
+            ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
+        }
+    }
+
+    mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
+    getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
+            mParameters.orientationAware);
+
+    mParameters.hasAssociatedDisplay = false;
+    mParameters.associatedDisplayIsExternal = false;
+    if (mParameters.orientationAware
+            || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
+            || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
+        mParameters.hasAssociatedDisplay = true;
+        if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
+            mParameters.associatedDisplayIsExternal = getDevice()->isExternal();
+            String8 uniqueDisplayId;
+            getDevice()->getConfiguration().tryGetProperty(String8("touch.displayId"),
+                    uniqueDisplayId);
+            mParameters.uniqueDisplayId = uniqueDisplayId.c_str();
+        }
+    }
+    if (getDevice()->getAssociatedDisplayPort()) {
+        mParameters.hasAssociatedDisplay = true;
+    }
+
+    // Initial downs on external touch devices should wake the device.
+    // Normally we don't do this for internal touch screens to prevent them from waking
+    // up in your pocket but you can enable it using the input device configuration.
+    mParameters.wake = getDevice()->isExternal();
+    getDevice()->getConfiguration().tryGetProperty(String8("touch.wake"),
+            mParameters.wake);
+}
+
+void TouchInputMapper::dumpParameters(std::string& dump) {
+    dump += INDENT3 "Parameters:\n";
+
+    switch (mParameters.gestureMode) {
+    case Parameters::GESTURE_MODE_SINGLE_TOUCH:
+        dump += INDENT4 "GestureMode: single-touch\n";
+        break;
+    case Parameters::GESTURE_MODE_MULTI_TOUCH:
+        dump += INDENT4 "GestureMode: multi-touch\n";
+        break;
+    default:
+        assert(false);
+    }
+
+    switch (mParameters.deviceType) {
+    case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
+        dump += INDENT4 "DeviceType: touchScreen\n";
+        break;
+    case Parameters::DEVICE_TYPE_TOUCH_PAD:
+        dump += INDENT4 "DeviceType: touchPad\n";
+        break;
+    case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
+        dump += INDENT4 "DeviceType: touchNavigation\n";
+        break;
+    case Parameters::DEVICE_TYPE_POINTER:
+        dump += INDENT4 "DeviceType: pointer\n";
+        break;
+    default:
+        ALOG_ASSERT(false);
+    }
+
+    dump += StringPrintf(
+            INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s, displayId='%s'\n",
+            toString(mParameters.hasAssociatedDisplay),
+            toString(mParameters.associatedDisplayIsExternal),
+            mParameters.uniqueDisplayId.c_str());
+    dump += StringPrintf(INDENT4 "OrientationAware: %s\n",
+            toString(mParameters.orientationAware));
+}
+
+void TouchInputMapper::configureRawPointerAxes() {
+    mRawPointerAxes.clear();
+}
+
+void TouchInputMapper::dumpRawPointerAxes(std::string& dump) {
+    dump += INDENT3 "Raw Touch Axes:\n";
+    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X");
+    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y");
+    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure");
+    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor");
+    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor");
+    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor");
+    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor");
+    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation");
+    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance");
+    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX");
+    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY");
+    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId");
+    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
+}
+
+bool TouchInputMapper::hasExternalStylus() const {
+    return mExternalStylusConnected;
+}
+
+/**
+ * Determine which DisplayViewport to use.
+ * 1. If display port is specified, return the matching viewport. If matching viewport not
+ * found, then return.
+ * 2. If a device has associated display, get the matching viewport by either unique id or by
+ * the display type (internal or external).
+ * 3. Otherwise, use a non-display viewport.
+ */
+std::optional<DisplayViewport> TouchInputMapper::findViewport() {
+    if (mParameters.hasAssociatedDisplay) {
+        const std::optional<uint8_t> displayPort = mDevice->getAssociatedDisplayPort();
+        if (displayPort) {
+            // Find the viewport that contains the same port
+            std::optional<DisplayViewport> v = mConfig.getDisplayViewportByPort(*displayPort);
+            if (!v) {
+                ALOGW("Input device %s should be associated with display on port %" PRIu8 ", "
+                        "but the corresponding viewport is not found.",
+                        getDeviceName().c_str(), *displayPort);
+            }
+            return v;
+        }
+
+        if (!mParameters.uniqueDisplayId.empty()) {
+            return mConfig.getDisplayViewportByUniqueId(mParameters.uniqueDisplayId);
+        }
+
+        ViewportType viewportTypeToUse;
+        if (mParameters.associatedDisplayIsExternal) {
+            viewportTypeToUse = ViewportType::VIEWPORT_EXTERNAL;
+        } else {
+            viewportTypeToUse = ViewportType::VIEWPORT_INTERNAL;
+        }
+
+        std::optional<DisplayViewport> viewport =
+                mConfig.getDisplayViewportByType(viewportTypeToUse);
+        if (!viewport && viewportTypeToUse == ViewportType::VIEWPORT_EXTERNAL) {
+            ALOGW("Input device %s should be associated with external display, "
+                    "fallback to internal one for the external viewport is not found.",
+                        getDeviceName().c_str());
+            viewport = mConfig.getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+        }
+
+        return viewport;
+    }
+
+    DisplayViewport newViewport;
+    // Raw width and height in the natural orientation.
+    int32_t rawWidth = mRawPointerAxes.getRawWidth();
+    int32_t rawHeight = mRawPointerAxes.getRawHeight();
+    newViewport.setNonDisplayViewport(rawWidth, rawHeight);
+    return std::make_optional(newViewport);
+}
+
+void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
+    int32_t oldDeviceMode = mDeviceMode;
+
+    resolveExternalStylusPresence();
+
+    // Determine device mode.
+    if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
+            && mConfig.pointerGesturesEnabled) {
+        mSource = AINPUT_SOURCE_MOUSE;
+        mDeviceMode = DEVICE_MODE_POINTER;
+        if (hasStylus()) {
+            mSource |= AINPUT_SOURCE_STYLUS;
+        }
+    } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
+            && mParameters.hasAssociatedDisplay) {
+        mSource = AINPUT_SOURCE_TOUCHSCREEN;
+        mDeviceMode = DEVICE_MODE_DIRECT;
+        if (hasStylus()) {
+            mSource |= AINPUT_SOURCE_STYLUS;
+        }
+        if (hasExternalStylus()) {
+            mSource |= AINPUT_SOURCE_BLUETOOTH_STYLUS;
+        }
+    } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
+        mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
+        mDeviceMode = DEVICE_MODE_NAVIGATION;
+    } else {
+        mSource = AINPUT_SOURCE_TOUCHPAD;
+        mDeviceMode = DEVICE_MODE_UNSCALED;
+    }
+
+    // Ensure we have valid X and Y axes.
+    if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
+        ALOGW("Touch device '%s' did not report support for X or Y axis!  "
+                "The device will be inoperable.", getDeviceName().c_str());
+        mDeviceMode = DEVICE_MODE_DISABLED;
+        return;
+    }
+
+    // Get associated display dimensions.
+    std::optional<DisplayViewport> newViewport = findViewport();
+    if (!newViewport) {
+        ALOGI("Touch device '%s' could not query the properties of its associated "
+                "display.  The device will be inoperable until the display size "
+                "becomes available.",
+                getDeviceName().c_str());
+        mDeviceMode = DEVICE_MODE_DISABLED;
+        return;
+    }
+
+    // Raw width and height in the natural orientation.
+    int32_t rawWidth = mRawPointerAxes.getRawWidth();
+    int32_t rawHeight = mRawPointerAxes.getRawHeight();
+
+    bool viewportChanged = mViewport != *newViewport;
+    if (viewportChanged) {
+        mViewport = *newViewport;
+
+        if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
+            // Convert rotated viewport to natural surface coordinates.
+            int32_t naturalLogicalWidth, naturalLogicalHeight;
+            int32_t naturalPhysicalWidth, naturalPhysicalHeight;
+            int32_t naturalPhysicalLeft, naturalPhysicalTop;
+            int32_t naturalDeviceWidth, naturalDeviceHeight;
+            switch (mViewport.orientation) {
+            case DISPLAY_ORIENTATION_90:
+                naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
+                naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
+                naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
+                naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
+                naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
+                naturalPhysicalTop = mViewport.physicalLeft;
+                naturalDeviceWidth = mViewport.deviceHeight;
+                naturalDeviceHeight = mViewport.deviceWidth;
+                break;
+            case DISPLAY_ORIENTATION_180:
+                naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
+                naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
+                naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
+                naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
+                naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight;
+                naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom;
+                naturalDeviceWidth = mViewport.deviceWidth;
+                naturalDeviceHeight = mViewport.deviceHeight;
+                break;
+            case DISPLAY_ORIENTATION_270:
+                naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
+                naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
+                naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
+                naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
+                naturalPhysicalLeft = mViewport.physicalTop;
+                naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
+                naturalDeviceWidth = mViewport.deviceHeight;
+                naturalDeviceHeight = mViewport.deviceWidth;
+                break;
+            case DISPLAY_ORIENTATION_0:
+            default:
+                naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
+                naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
+                naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
+                naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
+                naturalPhysicalLeft = mViewport.physicalLeft;
+                naturalPhysicalTop = mViewport.physicalTop;
+                naturalDeviceWidth = mViewport.deviceWidth;
+                naturalDeviceHeight = mViewport.deviceHeight;
+                break;
+            }
+
+            if (naturalPhysicalHeight == 0 || naturalPhysicalWidth == 0) {
+                ALOGE("Viewport is not set properly: %s", mViewport.toString().c_str());
+                naturalPhysicalHeight = naturalPhysicalHeight == 0 ? 1 : naturalPhysicalHeight;
+                naturalPhysicalWidth = naturalPhysicalWidth == 0 ? 1 : naturalPhysicalWidth;
+            }
+
+            mPhysicalWidth = naturalPhysicalWidth;
+            mPhysicalHeight = naturalPhysicalHeight;
+            mPhysicalLeft = naturalPhysicalLeft;
+            mPhysicalTop = naturalPhysicalTop;
+
+            mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
+            mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
+            mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
+            mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight;
+
+            mSurfaceOrientation = mParameters.orientationAware ?
+                    mViewport.orientation : DISPLAY_ORIENTATION_0;
+        } else {
+            mPhysicalWidth = rawWidth;
+            mPhysicalHeight = rawHeight;
+            mPhysicalLeft = 0;
+            mPhysicalTop = 0;
+
+            mSurfaceWidth = rawWidth;
+            mSurfaceHeight = rawHeight;
+            mSurfaceLeft = 0;
+            mSurfaceTop = 0;
+            mSurfaceOrientation = DISPLAY_ORIENTATION_0;
+        }
+    }
+
+    // If moving between pointer modes, need to reset some state.
+    bool deviceModeChanged = mDeviceMode != oldDeviceMode;
+    if (deviceModeChanged) {
+        mOrientedRanges.clear();
+    }
+
+    // Create or update pointer controller if needed.
+    if (mDeviceMode == DEVICE_MODE_POINTER ||
+            (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
+        if (mPointerController == nullptr || viewportChanged) {
+            mPointerController = getPolicy()->obtainPointerController(getDeviceId());
+        }
+    } else {
+        mPointerController.clear();
+    }
+
+    if (viewportChanged || deviceModeChanged) {
+        ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
+                "display id %d",
+                getDeviceId(), getDeviceName().c_str(), mSurfaceWidth, mSurfaceHeight,
+                mSurfaceOrientation, mDeviceMode, mViewport.displayId);
+
+        // Configure X and Y factors.
+        mXScale = float(mSurfaceWidth) / rawWidth;
+        mYScale = float(mSurfaceHeight) / rawHeight;
+        mXTranslate = -mSurfaceLeft;
+        mYTranslate = -mSurfaceTop;
+        mXPrecision = 1.0f / mXScale;
+        mYPrecision = 1.0f / mYScale;
+
+        mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
+        mOrientedRanges.x.source = mSource;
+        mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
+        mOrientedRanges.y.source = mSource;
+
+        configureVirtualKeys();
+
+        // Scale factor for terms that are not oriented in a particular axis.
+        // If the pixels are square then xScale == yScale otherwise we fake it
+        // by choosing an average.
+        mGeometricScale = avg(mXScale, mYScale);
+
+        // Size of diagonal axis.
+        float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight);
+
+        // Size factors.
+        if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
+            if (mRawPointerAxes.touchMajor.valid
+                    && mRawPointerAxes.touchMajor.maxValue != 0) {
+                mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
+            } else if (mRawPointerAxes.toolMajor.valid
+                    && mRawPointerAxes.toolMajor.maxValue != 0) {
+                mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue;
+            } else {
+                mSizeScale = 0.0f;
+            }
+
+            mOrientedRanges.haveTouchSize = true;
+            mOrientedRanges.haveToolSize = true;
+            mOrientedRanges.haveSize = true;
+
+            mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
+            mOrientedRanges.touchMajor.source = mSource;
+            mOrientedRanges.touchMajor.min = 0;
+            mOrientedRanges.touchMajor.max = diagonalSize;
+            mOrientedRanges.touchMajor.flat = 0;
+            mOrientedRanges.touchMajor.fuzz = 0;
+            mOrientedRanges.touchMajor.resolution = 0;
+
+            mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
+            mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
+
+            mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
+            mOrientedRanges.toolMajor.source = mSource;
+            mOrientedRanges.toolMajor.min = 0;
+            mOrientedRanges.toolMajor.max = diagonalSize;
+            mOrientedRanges.toolMajor.flat = 0;
+            mOrientedRanges.toolMajor.fuzz = 0;
+            mOrientedRanges.toolMajor.resolution = 0;
+
+            mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
+            mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
+
+            mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
+            mOrientedRanges.size.source = mSource;
+            mOrientedRanges.size.min = 0;
+            mOrientedRanges.size.max = 1.0;
+            mOrientedRanges.size.flat = 0;
+            mOrientedRanges.size.fuzz = 0;
+            mOrientedRanges.size.resolution = 0;
+        } else {
+            mSizeScale = 0.0f;
+        }
+
+        // Pressure factors.
+        mPressureScale = 0;
+        float pressureMax = 1.0;
+        if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
+                || mCalibration.pressureCalibration
+                        == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
+            if (mCalibration.havePressureScale) {
+                mPressureScale = mCalibration.pressureScale;
+                pressureMax = mPressureScale * mRawPointerAxes.pressure.maxValue;
+            } else if (mRawPointerAxes.pressure.valid
+                    && mRawPointerAxes.pressure.maxValue != 0) {
+                mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
+            }
+        }
+
+        mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
+        mOrientedRanges.pressure.source = mSource;
+        mOrientedRanges.pressure.min = 0;
+        mOrientedRanges.pressure.max = pressureMax;
+        mOrientedRanges.pressure.flat = 0;
+        mOrientedRanges.pressure.fuzz = 0;
+        mOrientedRanges.pressure.resolution = 0;
+
+        // Tilt
+        mTiltXCenter = 0;
+        mTiltXScale = 0;
+        mTiltYCenter = 0;
+        mTiltYScale = 0;
+        mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
+        if (mHaveTilt) {
+            mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue,
+                    mRawPointerAxes.tiltX.maxValue);
+            mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue,
+                    mRawPointerAxes.tiltY.maxValue);
+            mTiltXScale = M_PI / 180;
+            mTiltYScale = M_PI / 180;
+
+            mOrientedRanges.haveTilt = true;
+
+            mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
+            mOrientedRanges.tilt.source = mSource;
+            mOrientedRanges.tilt.min = 0;
+            mOrientedRanges.tilt.max = M_PI_2;
+            mOrientedRanges.tilt.flat = 0;
+            mOrientedRanges.tilt.fuzz = 0;
+            mOrientedRanges.tilt.resolution = 0;
+        }
+
+        // Orientation
+        mOrientationScale = 0;
+        if (mHaveTilt) {
+            mOrientedRanges.haveOrientation = true;
+
+            mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
+            mOrientedRanges.orientation.source = mSource;
+            mOrientedRanges.orientation.min = -M_PI;
+            mOrientedRanges.orientation.max = M_PI;
+            mOrientedRanges.orientation.flat = 0;
+            mOrientedRanges.orientation.fuzz = 0;
+            mOrientedRanges.orientation.resolution = 0;
+        } else if (mCalibration.orientationCalibration !=
+                Calibration::ORIENTATION_CALIBRATION_NONE) {
+            if (mCalibration.orientationCalibration
+                    == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
+                if (mRawPointerAxes.orientation.valid) {
+                    if (mRawPointerAxes.orientation.maxValue > 0) {
+                        mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
+                    } else if (mRawPointerAxes.orientation.minValue < 0) {
+                        mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue;
+                    } else {
+                        mOrientationScale = 0;
+                    }
+                }
+            }
+
+            mOrientedRanges.haveOrientation = true;
+
+            mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
+            mOrientedRanges.orientation.source = mSource;
+            mOrientedRanges.orientation.min = -M_PI_2;
+            mOrientedRanges.orientation.max = M_PI_2;
+            mOrientedRanges.orientation.flat = 0;
+            mOrientedRanges.orientation.fuzz = 0;
+            mOrientedRanges.orientation.resolution = 0;
+        }
+
+        // Distance
+        mDistanceScale = 0;
+        if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
+            if (mCalibration.distanceCalibration
+                    == Calibration::DISTANCE_CALIBRATION_SCALED) {
+                if (mCalibration.haveDistanceScale) {
+                    mDistanceScale = mCalibration.distanceScale;
+                } else {
+                    mDistanceScale = 1.0f;
+                }
+            }
+
+            mOrientedRanges.haveDistance = true;
+
+            mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
+            mOrientedRanges.distance.source = mSource;
+            mOrientedRanges.distance.min =
+                    mRawPointerAxes.distance.minValue * mDistanceScale;
+            mOrientedRanges.distance.max =
+                    mRawPointerAxes.distance.maxValue * mDistanceScale;
+            mOrientedRanges.distance.flat = 0;
+            mOrientedRanges.distance.fuzz =
+                    mRawPointerAxes.distance.fuzz * mDistanceScale;
+            mOrientedRanges.distance.resolution = 0;
+        }
+
+        // Compute oriented precision, scales and ranges.
+        // Note that the maximum value reported is an inclusive maximum value so it is one
+        // unit less than the total width or height of surface.
+        switch (mSurfaceOrientation) {
+        case DISPLAY_ORIENTATION_90:
+        case DISPLAY_ORIENTATION_270:
+            mOrientedXPrecision = mYPrecision;
+            mOrientedYPrecision = mXPrecision;
+
+            mOrientedRanges.x.min = mYTranslate;
+            mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1;
+            mOrientedRanges.x.flat = 0;
+            mOrientedRanges.x.fuzz = 0;
+            mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale;
+
+            mOrientedRanges.y.min = mXTranslate;
+            mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1;
+            mOrientedRanges.y.flat = 0;
+            mOrientedRanges.y.fuzz = 0;
+            mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale;
+            break;
+
+        default:
+            mOrientedXPrecision = mXPrecision;
+            mOrientedYPrecision = mYPrecision;
+
+            mOrientedRanges.x.min = mXTranslate;
+            mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1;
+            mOrientedRanges.x.flat = 0;
+            mOrientedRanges.x.fuzz = 0;
+            mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale;
+
+            mOrientedRanges.y.min = mYTranslate;
+            mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1;
+            mOrientedRanges.y.flat = 0;
+            mOrientedRanges.y.fuzz = 0;
+            mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale;
+            break;
+        }
+
+        // Location
+        updateAffineTransformation();
+
+        if (mDeviceMode == DEVICE_MODE_POINTER) {
+            // Compute pointer gesture detection parameters.
+            float rawDiagonal = hypotf(rawWidth, rawHeight);
+            float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight);
+
+            // Scale movements such that one whole swipe of the touch pad covers a
+            // given area relative to the diagonal size of the display when no acceleration
+            // is applied.
+            // Assume that the touch pad has a square aspect ratio such that movements in
+            // X and Y of the same number of raw units cover the same physical distance.
+            mPointerXMovementScale = mConfig.pointerGestureMovementSpeedRatio
+                    * displayDiagonal / rawDiagonal;
+            mPointerYMovementScale = mPointerXMovementScale;
+
+            // Scale zooms to cover a smaller range of the display than movements do.
+            // This value determines the area around the pointer that is affected by freeform
+            // pointer gestures.
+            mPointerXZoomScale = mConfig.pointerGestureZoomSpeedRatio
+                    * displayDiagonal / rawDiagonal;
+            mPointerYZoomScale = mPointerXZoomScale;
+
+            // Max width between pointers to detect a swipe gesture is more than some fraction
+            // of the diagonal axis of the touch pad.  Touches that are wider than this are
+            // translated into freeform gestures.
+            mPointerGestureMaxSwipeWidth =
+                    mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
+
+            // Abort current pointer usages because the state has changed.
+            abortPointerUsage(when, 0 /*policyFlags*/);
+        }
+
+        // Inform the dispatcher about the changes.
+        *outResetNeeded = true;
+        bumpGeneration();
+    }
+}
+
+void TouchInputMapper::dumpSurface(std::string& dump) {
+    dump += StringPrintf(INDENT3 "%s\n", mViewport.toString().c_str());
+    dump += StringPrintf(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
+    dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
+    dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
+    dump += StringPrintf(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
+    dump += StringPrintf(INDENT3 "PhysicalWidth: %dpx\n", mPhysicalWidth);
+    dump += StringPrintf(INDENT3 "PhysicalHeight: %dpx\n", mPhysicalHeight);
+    dump += StringPrintf(INDENT3 "PhysicalLeft: %d\n", mPhysicalLeft);
+    dump += StringPrintf(INDENT3 "PhysicalTop: %d\n", mPhysicalTop);
+    dump += StringPrintf(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
+}
+
+void TouchInputMapper::configureVirtualKeys() {
+    std::vector<VirtualKeyDefinition> virtualKeyDefinitions;
+    getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
+
+    mVirtualKeys.clear();
+
+    if (virtualKeyDefinitions.size() == 0) {
+        return;
+    }
+
+    int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
+    int32_t touchScreenTop = mRawPointerAxes.y.minValue;
+    int32_t touchScreenWidth = mRawPointerAxes.getRawWidth();
+    int32_t touchScreenHeight = mRawPointerAxes.getRawHeight();
+
+    for (const VirtualKeyDefinition& virtualKeyDefinition : virtualKeyDefinitions) {
+        VirtualKey virtualKey;
+
+        virtualKey.scanCode = virtualKeyDefinition.scanCode;
+        int32_t keyCode;
+        int32_t dummyKeyMetaState;
+        uint32_t flags;
+        if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, 0,
+                                  &keyCode, &dummyKeyMetaState, &flags)) {
+            ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
+                    virtualKey.scanCode);
+            continue; // drop the key
+        }
+
+        virtualKey.keyCode = keyCode;
+        virtualKey.flags = flags;
+
+        // convert the key definition's display coordinates into touch coordinates for a hit box
+        int32_t halfWidth = virtualKeyDefinition.width / 2;
+        int32_t halfHeight = virtualKeyDefinition.height / 2;
+
+        virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
+                * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
+        virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
+                * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
+        virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
+                * touchScreenHeight / mSurfaceHeight + touchScreenTop;
+        virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
+                * touchScreenHeight / mSurfaceHeight + touchScreenTop;
+        mVirtualKeys.push_back(virtualKey);
+    }
+}
+
+void TouchInputMapper::dumpVirtualKeys(std::string& dump) {
+    if (!mVirtualKeys.empty()) {
+        dump += INDENT3 "Virtual Keys:\n";
+
+        for (size_t i = 0; i < mVirtualKeys.size(); i++) {
+            const VirtualKey& virtualKey = mVirtualKeys[i];
+            dump += StringPrintf(INDENT4 "%zu: scanCode=%d, keyCode=%d, "
+                    "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
+                    i, virtualKey.scanCode, virtualKey.keyCode,
+                    virtualKey.hitLeft, virtualKey.hitRight,
+                    virtualKey.hitTop, virtualKey.hitBottom);
+        }
+    }
+}
+
+void TouchInputMapper::parseCalibration() {
+    const PropertyMap& in = getDevice()->getConfiguration();
+    Calibration& out = mCalibration;
+
+    // Size
+    out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
+    String8 sizeCalibrationString;
+    if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
+        if (sizeCalibrationString == "none") {
+            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
+        } else if (sizeCalibrationString == "geometric") {
+            out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
+        } else if (sizeCalibrationString == "diameter") {
+            out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
+        } else if (sizeCalibrationString == "box") {
+            out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX;
+        } else if (sizeCalibrationString == "area") {
+            out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
+        } else if (sizeCalibrationString != "default") {
+            ALOGW("Invalid value for touch.size.calibration: '%s'",
+                    sizeCalibrationString.string());
+        }
+    }
+
+    out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"),
+            out.sizeScale);
+    out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"),
+            out.sizeBias);
+    out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"),
+            out.sizeIsSummed);
+
+    // Pressure
+    out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
+    String8 pressureCalibrationString;
+    if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
+        if (pressureCalibrationString == "none") {
+            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
+        } else if (pressureCalibrationString == "physical") {
+            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
+        } else if (pressureCalibrationString == "amplitude") {
+            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
+        } else if (pressureCalibrationString != "default") {
+            ALOGW("Invalid value for touch.pressure.calibration: '%s'",
+                    pressureCalibrationString.string());
+        }
+    }
+
+    out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
+            out.pressureScale);
+
+    // Orientation
+    out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
+    String8 orientationCalibrationString;
+    if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
+        if (orientationCalibrationString == "none") {
+            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
+        } else if (orientationCalibrationString == "interpolated") {
+            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
+        } else if (orientationCalibrationString == "vector") {
+            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
+        } else if (orientationCalibrationString != "default") {
+            ALOGW("Invalid value for touch.orientation.calibration: '%s'",
+                    orientationCalibrationString.string());
+        }
+    }
+
+    // Distance
+    out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
+    String8 distanceCalibrationString;
+    if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
+        if (distanceCalibrationString == "none") {
+            out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
+        } else if (distanceCalibrationString == "scaled") {
+            out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
+        } else if (distanceCalibrationString != "default") {
+            ALOGW("Invalid value for touch.distance.calibration: '%s'",
+                    distanceCalibrationString.string());
+        }
+    }
+
+    out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
+            out.distanceScale);
+
+    out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT;
+    String8 coverageCalibrationString;
+    if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) {
+        if (coverageCalibrationString == "none") {
+            out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
+        } else if (coverageCalibrationString == "box") {
+            out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX;
+        } else if (coverageCalibrationString != "default") {
+            ALOGW("Invalid value for touch.coverage.calibration: '%s'",
+                    coverageCalibrationString.string());
+        }
+    }
+}
+
+void TouchInputMapper::resolveCalibration() {
+    // Size
+    if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
+        if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) {
+            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
+        }
+    } else {
+        mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
+    }
+
+    // Pressure
+    if (mRawPointerAxes.pressure.valid) {
+        if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) {
+            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
+        }
+    } else {
+        mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
+    }
+
+    // Orientation
+    if (mRawPointerAxes.orientation.valid) {
+        if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) {
+            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
+        }
+    } else {
+        mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
+    }
+
+    // Distance
+    if (mRawPointerAxes.distance.valid) {
+        if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) {
+            mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
+        }
+    } else {
+        mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
+    }
+
+    // Coverage
+    if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) {
+        mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
+    }
+}
+
+void TouchInputMapper::dumpCalibration(std::string& dump) {
+    dump += INDENT3 "Calibration:\n";
+
+    // Size
+    switch (mCalibration.sizeCalibration) {
+    case Calibration::SIZE_CALIBRATION_NONE:
+        dump += INDENT4 "touch.size.calibration: none\n";
+        break;
+    case Calibration::SIZE_CALIBRATION_GEOMETRIC:
+        dump += INDENT4 "touch.size.calibration: geometric\n";
+        break;
+    case Calibration::SIZE_CALIBRATION_DIAMETER:
+        dump += INDENT4 "touch.size.calibration: diameter\n";
+        break;
+    case Calibration::SIZE_CALIBRATION_BOX:
+        dump += INDENT4 "touch.size.calibration: box\n";
+        break;
+    case Calibration::SIZE_CALIBRATION_AREA:
+        dump += INDENT4 "touch.size.calibration: area\n";
+        break;
+    default:
+        ALOG_ASSERT(false);
+    }
+
+    if (mCalibration.haveSizeScale) {
+        dump += StringPrintf(INDENT4 "touch.size.scale: %0.3f\n",
+                mCalibration.sizeScale);
+    }
+
+    if (mCalibration.haveSizeBias) {
+        dump += StringPrintf(INDENT4 "touch.size.bias: %0.3f\n",
+                mCalibration.sizeBias);
+    }
+
+    if (mCalibration.haveSizeIsSummed) {
+        dump += StringPrintf(INDENT4 "touch.size.isSummed: %s\n",
+                toString(mCalibration.sizeIsSummed));
+    }
+
+    // Pressure
+    switch (mCalibration.pressureCalibration) {
+    case Calibration::PRESSURE_CALIBRATION_NONE:
+        dump += INDENT4 "touch.pressure.calibration: none\n";
+        break;
+    case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
+        dump += INDENT4 "touch.pressure.calibration: physical\n";
+        break;
+    case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
+        dump += INDENT4 "touch.pressure.calibration: amplitude\n";
+        break;
+    default:
+        ALOG_ASSERT(false);
+    }
+
+    if (mCalibration.havePressureScale) {
+        dump += StringPrintf(INDENT4 "touch.pressure.scale: %0.3f\n",
+                mCalibration.pressureScale);
+    }
+
+    // Orientation
+    switch (mCalibration.orientationCalibration) {
+    case Calibration::ORIENTATION_CALIBRATION_NONE:
+        dump += INDENT4 "touch.orientation.calibration: none\n";
+        break;
+    case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
+        dump += INDENT4 "touch.orientation.calibration: interpolated\n";
+        break;
+    case Calibration::ORIENTATION_CALIBRATION_VECTOR:
+        dump += INDENT4 "touch.orientation.calibration: vector\n";
+        break;
+    default:
+        ALOG_ASSERT(false);
+    }
+
+    // Distance
+    switch (mCalibration.distanceCalibration) {
+    case Calibration::DISTANCE_CALIBRATION_NONE:
+        dump += INDENT4 "touch.distance.calibration: none\n";
+        break;
+    case Calibration::DISTANCE_CALIBRATION_SCALED:
+        dump += INDENT4 "touch.distance.calibration: scaled\n";
+        break;
+    default:
+        ALOG_ASSERT(false);
+    }
+
+    if (mCalibration.haveDistanceScale) {
+        dump += StringPrintf(INDENT4 "touch.distance.scale: %0.3f\n",
+                mCalibration.distanceScale);
+    }
+
+    switch (mCalibration.coverageCalibration) {
+    case Calibration::COVERAGE_CALIBRATION_NONE:
+        dump += INDENT4 "touch.coverage.calibration: none\n";
+        break;
+    case Calibration::COVERAGE_CALIBRATION_BOX:
+        dump += INDENT4 "touch.coverage.calibration: box\n";
+        break;
+    default:
+        ALOG_ASSERT(false);
+    }
+}
+
+void TouchInputMapper::dumpAffineTransformation(std::string& dump) {
+    dump += INDENT3 "Affine Transformation:\n";
+
+    dump += StringPrintf(INDENT4 "X scale: %0.3f\n", mAffineTransform.x_scale);
+    dump += StringPrintf(INDENT4 "X ymix: %0.3f\n", mAffineTransform.x_ymix);
+    dump += StringPrintf(INDENT4 "X offset: %0.3f\n", mAffineTransform.x_offset);
+    dump += StringPrintf(INDENT4 "Y xmix: %0.3f\n", mAffineTransform.y_xmix);
+    dump += StringPrintf(INDENT4 "Y scale: %0.3f\n", mAffineTransform.y_scale);
+    dump += StringPrintf(INDENT4 "Y offset: %0.3f\n", mAffineTransform.y_offset);
+}
+
+void TouchInputMapper::updateAffineTransformation() {
+    mAffineTransform = getPolicy()->getTouchAffineTransformation(mDevice->getDescriptor(),
+            mSurfaceOrientation);
+}
+
+void TouchInputMapper::reset(nsecs_t when) {
+    mCursorButtonAccumulator.reset(getDevice());
+    mCursorScrollAccumulator.reset(getDevice());
+    mTouchButtonAccumulator.reset(getDevice());
+
+    mPointerVelocityControl.reset();
+    mWheelXVelocityControl.reset();
+    mWheelYVelocityControl.reset();
+
+    mRawStatesPending.clear();
+    mCurrentRawState.clear();
+    mCurrentCookedState.clear();
+    mLastRawState.clear();
+    mLastCookedState.clear();
+    mPointerUsage = POINTER_USAGE_NONE;
+    mSentHoverEnter = false;
+    mHavePointerIds = false;
+    mCurrentMotionAborted = false;
+    mDownTime = 0;
+
+    mCurrentVirtualKey.down = false;
+
+    mPointerGesture.reset();
+    mPointerSimple.reset();
+    resetExternalStylus();
+
+    if (mPointerController != nullptr) {
+        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+        mPointerController->clearSpots();
+    }
+
+    InputMapper::reset(when);
+}
+
+void TouchInputMapper::resetExternalStylus() {
+    mExternalStylusState.clear();
+    mExternalStylusId = -1;
+    mExternalStylusFusionTimeout = LLONG_MAX;
+    mExternalStylusDataPending = false;
+}
+
+void TouchInputMapper::clearStylusDataPendingFlags() {
+    mExternalStylusDataPending = false;
+    mExternalStylusFusionTimeout = LLONG_MAX;
+}
+
+void TouchInputMapper::reportEventForStatistics(nsecs_t evdevTime) {
+    nsecs_t now = systemTime(CLOCK_MONOTONIC);
+    nsecs_t latency = now - evdevTime;
+    mStatistics.addValue(nanoseconds_to_microseconds(latency));
+    nsecs_t timeSinceLastReport = now - mStatistics.lastReportTime;
+    if (timeSinceLastReport > STATISTICS_REPORT_FREQUENCY) {
+        android::util::stats_write(android::util::TOUCH_EVENT_REPORTED,
+                mStatistics.min, mStatistics.max,
+                mStatistics.mean(), mStatistics.stdev(), mStatistics.count);
+        mStatistics.reset(now);
+    }
+}
+
+void TouchInputMapper::process(const RawEvent* rawEvent) {
+    mCursorButtonAccumulator.process(rawEvent);
+    mCursorScrollAccumulator.process(rawEvent);
+    mTouchButtonAccumulator.process(rawEvent);
+
+    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
+        reportEventForStatistics(rawEvent->when);
+        sync(rawEvent->when);
+    }
+}
+
+void TouchInputMapper::sync(nsecs_t when) {
+    const RawState* last = mRawStatesPending.empty() ?
+            &mCurrentRawState : &mRawStatesPending.back();
+
+    // Push a new state.
+    mRawStatesPending.emplace_back();
+
+    RawState* next = &mRawStatesPending.back();
+    next->clear();
+    next->when = when;
+
+    // Sync button state.
+    next->buttonState = mTouchButtonAccumulator.getButtonState()
+            | mCursorButtonAccumulator.getButtonState();
+
+    // Sync scroll
+    next->rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
+    next->rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
+    mCursorScrollAccumulator.finishSync();
+
+    // Sync touch
+    syncTouch(when, next);
+
+    // Assign pointer ids.
+    if (!mHavePointerIds) {
+        assignPointerIds(last, next);
+    }
+
+#if DEBUG_RAW_EVENTS
+    ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
+            "hovering ids 0x%08x -> 0x%08x",
+            last->rawPointerData.pointerCount,
+            next->rawPointerData.pointerCount,
+            last->rawPointerData.touchingIdBits.value,
+            next->rawPointerData.touchingIdBits.value,
+            last->rawPointerData.hoveringIdBits.value,
+            next->rawPointerData.hoveringIdBits.value);
+#endif
+
+    processRawTouches(false /*timeout*/);
+}
+
+void TouchInputMapper::processRawTouches(bool timeout) {
+    if (mDeviceMode == DEVICE_MODE_DISABLED) {
+        // Drop all input if the device is disabled.
+        mCurrentRawState.clear();
+        mRawStatesPending.clear();
+        return;
+    }
+
+    // Drain any pending touch states. The invariant here is that the mCurrentRawState is always
+    // valid and must go through the full cook and dispatch cycle. This ensures that anything
+    // touching the current state will only observe the events that have been dispatched to the
+    // rest of the pipeline.
+    const size_t N = mRawStatesPending.size();
+    size_t count;
+    for(count = 0; count < N; count++) {
+        const RawState& next = mRawStatesPending[count];
+
+        // A failure to assign the stylus id means that we're waiting on stylus data
+        // and so should defer the rest of the pipeline.
+        if (assignExternalStylusId(next, timeout)) {
+            break;
+        }
+
+        // All ready to go.
+        clearStylusDataPendingFlags();
+        mCurrentRawState.copyFrom(next);
+        if (mCurrentRawState.when < mLastRawState.when) {
+            mCurrentRawState.when = mLastRawState.when;
+        }
+        cookAndDispatch(mCurrentRawState.when);
+    }
+    if (count != 0) {
+        mRawStatesPending.erase(mRawStatesPending.begin(), mRawStatesPending.begin() + count);
+    }
+
+    if (mExternalStylusDataPending) {
+        if (timeout) {
+            nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;
+            clearStylusDataPendingFlags();
+            mCurrentRawState.copyFrom(mLastRawState);
+#if DEBUG_STYLUS_FUSION
+            ALOGD("Timeout expired, synthesizing event with new stylus data");
+#endif
+            cookAndDispatch(when);
+        } else if (mExternalStylusFusionTimeout == LLONG_MAX) {
+            mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;
+            getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
+        }
+    }
+}
+
+void TouchInputMapper::cookAndDispatch(nsecs_t when) {
+    // Always start with a clean state.
+    mCurrentCookedState.clear();
+
+    // Apply stylus buttons to current raw state.
+    applyExternalStylusButtonState(when);
+
+    // Handle policy on initial down or hover events.
+    bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
+            && mCurrentRawState.rawPointerData.pointerCount != 0;
+
+    uint32_t policyFlags = 0;
+    bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
+    if (initialDown || buttonsPressed) {
+        // If this is a touch screen, hide the pointer on an initial down.
+        if (mDeviceMode == DEVICE_MODE_DIRECT) {
+            getContext()->fadePointer();
+        }
+
+        if (mParameters.wake) {
+            policyFlags |= POLICY_FLAG_WAKE;
+        }
+    }
+
+    // Consume raw off-screen touches before cooking pointer data.
+    // If touches are consumed, subsequent code will not receive any pointer data.
+    if (consumeRawTouches(when, policyFlags)) {
+        mCurrentRawState.rawPointerData.clear();
+    }
+
+    // Cook pointer data.  This call populates the mCurrentCookedState.cookedPointerData structure
+    // with cooked pointer data that has the same ids and indices as the raw data.
+    // The following code can use either the raw or cooked data, as needed.
+    cookPointerData();
+
+    // Apply stylus pressure to current cooked state.
+    applyExternalStylusTouchState(when);
+
+    // Synthesize key down from raw buttons if needed.
+    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
+            mViewport.displayId, policyFlags,
+            mLastCookedState.buttonState, mCurrentCookedState.buttonState);
+
+    // Dispatch the touches either directly or by translation through a pointer on screen.
+    if (mDeviceMode == DEVICE_MODE_POINTER) {
+        for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits);
+                !idBits.isEmpty(); ) {
+            uint32_t id = idBits.clearFirstMarkedBit();
+            const RawPointerData::Pointer& pointer =
+                    mCurrentRawState.rawPointerData.pointerForId(id);
+            if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
+                    || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
+                mCurrentCookedState.stylusIdBits.markBit(id);
+            } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
+                    || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+                mCurrentCookedState.fingerIdBits.markBit(id);
+            } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
+                mCurrentCookedState.mouseIdBits.markBit(id);
+            }
+        }
+        for (BitSet32 idBits(mCurrentRawState.rawPointerData.hoveringIdBits);
+                !idBits.isEmpty(); ) {
+            uint32_t id = idBits.clearFirstMarkedBit();
+            const RawPointerData::Pointer& pointer =
+                    mCurrentRawState.rawPointerData.pointerForId(id);
+            if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
+                    || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
+                mCurrentCookedState.stylusIdBits.markBit(id);
+            }
+        }
+
+        // Stylus takes precedence over all tools, then mouse, then finger.
+        PointerUsage pointerUsage = mPointerUsage;
+        if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
+            mCurrentCookedState.mouseIdBits.clear();
+            mCurrentCookedState.fingerIdBits.clear();
+            pointerUsage = POINTER_USAGE_STYLUS;
+        } else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
+            mCurrentCookedState.fingerIdBits.clear();
+            pointerUsage = POINTER_USAGE_MOUSE;
+        } else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||
+                isPointerDown(mCurrentRawState.buttonState)) {
+            pointerUsage = POINTER_USAGE_GESTURES;
+        }
+
+        dispatchPointerUsage(when, policyFlags, pointerUsage);
+    } else {
+        if (mDeviceMode == DEVICE_MODE_DIRECT
+                && mConfig.showTouches && mPointerController != nullptr) {
+            mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
+            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+
+            mPointerController->setButtonState(mCurrentRawState.buttonState);
+            mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
+                    mCurrentCookedState.cookedPointerData.idToIndex,
+                    mCurrentCookedState.cookedPointerData.touchingIdBits,
+                    mViewport.displayId);
+        }
+
+        if (!mCurrentMotionAborted) {
+            dispatchButtonRelease(when, policyFlags);
+            dispatchHoverExit(when, policyFlags);
+            dispatchTouches(when, policyFlags);
+            dispatchHoverEnterAndMove(when, policyFlags);
+            dispatchButtonPress(when, policyFlags);
+        }
+
+        if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
+            mCurrentMotionAborted = false;
+        }
+    }
+
+    // Synthesize key up from raw buttons if needed.
+    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
+            mViewport.displayId, policyFlags,
+            mLastCookedState.buttonState, mCurrentCookedState.buttonState);
+
+    // Clear some transient state.
+    mCurrentRawState.rawVScroll = 0;
+    mCurrentRawState.rawHScroll = 0;
+
+    // Copy current touch to last touch in preparation for the next cycle.
+    mLastRawState.copyFrom(mCurrentRawState);
+    mLastCookedState.copyFrom(mCurrentCookedState);
+}
+
+void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) {
+    if (mDeviceMode == DEVICE_MODE_DIRECT && hasExternalStylus() && mExternalStylusId != -1) {
+        mCurrentRawState.buttonState |= mExternalStylusState.buttons;
+    }
+}
+
+void TouchInputMapper::applyExternalStylusTouchState(nsecs_t when) {
+    CookedPointerData& currentPointerData = mCurrentCookedState.cookedPointerData;
+    const CookedPointerData& lastPointerData = mLastCookedState.cookedPointerData;
+
+    if (mExternalStylusId != -1 && currentPointerData.isTouching(mExternalStylusId)) {
+        float pressure = mExternalStylusState.pressure;
+        if (pressure == 0.0f && lastPointerData.isTouching(mExternalStylusId)) {
+            const PointerCoords& coords = lastPointerData.pointerCoordsForId(mExternalStylusId);
+            pressure = coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
+        }
+        PointerCoords& coords = currentPointerData.editPointerCoordsWithId(mExternalStylusId);
+        coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
+
+        PointerProperties& properties =
+                currentPointerData.editPointerPropertiesWithId(mExternalStylusId);
+        if (mExternalStylusState.toolType != AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+            properties.toolType = mExternalStylusState.toolType;
+        }
+    }
+}
+
+bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeout) {
+    if (mDeviceMode != DEVICE_MODE_DIRECT || !hasExternalStylus()) {
+        return false;
+    }
+
+    const bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
+            && state.rawPointerData.pointerCount != 0;
+    if (initialDown) {
+        if (mExternalStylusState.pressure != 0.0f) {
+#if DEBUG_STYLUS_FUSION
+            ALOGD("Have both stylus and touch data, beginning fusion");
+#endif
+            mExternalStylusId = state.rawPointerData.touchingIdBits.firstMarkedBit();
+        } else if (timeout) {
+#if DEBUG_STYLUS_FUSION
+            ALOGD("Timeout expired, assuming touch is not a stylus.");
+#endif
+            resetExternalStylus();
+        } else {
+            if (mExternalStylusFusionTimeout == LLONG_MAX) {
+                mExternalStylusFusionTimeout = state.when + EXTERNAL_STYLUS_DATA_TIMEOUT;
+            }
+#if DEBUG_STYLUS_FUSION
+            ALOGD("No stylus data but stylus is connected, requesting timeout "
+                    "(%" PRId64 "ms)", mExternalStylusFusionTimeout);
+#endif
+            getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
+            return true;
+        }
+    }
+
+    // Check if the stylus pointer has gone up.
+    if (mExternalStylusId != -1 &&
+            !state.rawPointerData.touchingIdBits.hasBit(mExternalStylusId)) {
+#if DEBUG_STYLUS_FUSION
+            ALOGD("Stylus pointer is going up");
+#endif
+        mExternalStylusId = -1;
+    }
+
+    return false;
+}
+
+void TouchInputMapper::timeoutExpired(nsecs_t when) {
+    if (mDeviceMode == DEVICE_MODE_POINTER) {
+        if (mPointerUsage == POINTER_USAGE_GESTURES) {
+            dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
+        }
+    } else if (mDeviceMode == DEVICE_MODE_DIRECT) {
+        if (mExternalStylusFusionTimeout < when) {
+            processRawTouches(true /*timeout*/);
+        } else if (mExternalStylusFusionTimeout != LLONG_MAX) {
+            getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
+        }
+    }
+}
+
+void TouchInputMapper::updateExternalStylusState(const StylusState& state) {
+    mExternalStylusState.copyFrom(state);
+    if (mExternalStylusId != -1 || mExternalStylusFusionTimeout != LLONG_MAX) {
+        // We're either in the middle of a fused stream of data or we're waiting on data before
+        // dispatching the initial down, so go ahead and dispatch now that we have fresh stylus
+        // data.
+        mExternalStylusDataPending = true;
+        processRawTouches(false /*timeout*/);
+    }
+}
+
+bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) {
+    // Check for release of a virtual key.
+    if (mCurrentVirtualKey.down) {
+        if (mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
+            // Pointer went up while virtual key was down.
+            mCurrentVirtualKey.down = false;
+            if (!mCurrentVirtualKey.ignored) {
+#if DEBUG_VIRTUAL_KEYS
+                ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
+                        mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
+#endif
+                dispatchVirtualKey(when, policyFlags,
+                        AKEY_EVENT_ACTION_UP,
+                        AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
+            }
+            return true;
+        }
+
+        if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
+            uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
+            const RawPointerData::Pointer& pointer =
+                    mCurrentRawState.rawPointerData.pointerForId(id);
+            const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
+            if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
+                // Pointer is still within the space of the virtual key.
+                return true;
+            }
+        }
+
+        // Pointer left virtual key area or another pointer also went down.
+        // Send key cancellation but do not consume the touch yet.
+        // This is useful when the user swipes through from the virtual key area
+        // into the main display surface.
+        mCurrentVirtualKey.down = false;
+        if (!mCurrentVirtualKey.ignored) {
+#if DEBUG_VIRTUAL_KEYS
+            ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
+                    mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
+#endif
+            dispatchVirtualKey(when, policyFlags,
+                    AKEY_EVENT_ACTION_UP,
+                    AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
+                            | AKEY_EVENT_FLAG_CANCELED);
+        }
+    }
+
+    if (mLastRawState.rawPointerData.touchingIdBits.isEmpty()
+            && !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
+        // Pointer just went down.  Check for virtual key press or off-screen touches.
+        uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
+        const RawPointerData::Pointer& pointer = mCurrentRawState.rawPointerData.pointerForId(id);
+        if (!isPointInsideSurface(pointer.x, pointer.y)) {
+            // If exactly one pointer went down, check for virtual key hit.
+            // Otherwise we will drop the entire stroke.
+            if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
+                const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
+                if (virtualKey) {
+                    mCurrentVirtualKey.down = true;
+                    mCurrentVirtualKey.downTime = when;
+                    mCurrentVirtualKey.keyCode = virtualKey->keyCode;
+                    mCurrentVirtualKey.scanCode = virtualKey->scanCode;
+                    mCurrentVirtualKey.ignored = mContext->shouldDropVirtualKey(
+                            when, getDevice(), virtualKey->keyCode, virtualKey->scanCode);
+
+                    if (!mCurrentVirtualKey.ignored) {
+#if DEBUG_VIRTUAL_KEYS
+                        ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
+                                mCurrentVirtualKey.keyCode,
+                                mCurrentVirtualKey.scanCode);
+#endif
+                        dispatchVirtualKey(when, policyFlags,
+                                AKEY_EVENT_ACTION_DOWN,
+                                AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
+                    }
+                }
+            }
+            return true;
+        }
+    }
+
+    // Disable all virtual key touches that happen within a short time interval of the
+    // most recent touch within the screen area.  The idea is to filter out stray
+    // virtual key presses when interacting with the touch screen.
+    //
+    // Problems we're trying to solve:
+    //
+    // 1. While scrolling a list or dragging the window shade, the user swipes down into a
+    //    virtual key area that is implemented by a separate touch panel and accidentally
+    //    triggers a virtual key.
+    //
+    // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
+    //    area and accidentally triggers a virtual key.  This often happens when virtual keys
+    //    are layed out below the screen near to where the on screen keyboard's space bar
+    //    is displayed.
+    if (mConfig.virtualKeyQuietTime > 0 &&
+            !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
+        mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
+    }
+    return false;
+}
+
+void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
+        int32_t keyEventAction, int32_t keyEventFlags) {
+    int32_t keyCode = mCurrentVirtualKey.keyCode;
+    int32_t scanCode = mCurrentVirtualKey.scanCode;
+    nsecs_t downTime = mCurrentVirtualKey.downTime;
+    int32_t metaState = mContext->getGlobalMetaState();
+    policyFlags |= POLICY_FLAG_VIRTUAL;
+
+    NotifyKeyArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), AINPUT_SOURCE_KEYBOARD,
+            mViewport.displayId,
+            policyFlags, keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
+    getListener()->notifyKey(&args);
+}
+
+void TouchInputMapper::abortTouches(nsecs_t when, uint32_t policyFlags) {
+    BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
+    if (!currentIdBits.isEmpty()) {
+        int32_t metaState = getContext()->getGlobalMetaState();
+        int32_t buttonState = mCurrentCookedState.buttonState;
+        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0,
+                metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                mCurrentCookedState.deviceTimestamp,
+                mCurrentCookedState.cookedPointerData.pointerProperties,
+                mCurrentCookedState.cookedPointerData.pointerCoords,
+                mCurrentCookedState.cookedPointerData.idToIndex,
+                currentIdBits, -1,
+                mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+        mCurrentMotionAborted = true;
+    }
+}
+
+void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
+    BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
+    BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;
+    int32_t metaState = getContext()->getGlobalMetaState();
+    int32_t buttonState = mCurrentCookedState.buttonState;
+
+    if (currentIdBits == lastIdBits) {
+        if (!currentIdBits.isEmpty()) {
+            // No pointer id changes so this is a move event.
+            // The listener takes care of batching moves so we don't have to deal with that here.
+            dispatchMotion(when, policyFlags, mSource,
+                    AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
+                    AMOTION_EVENT_EDGE_FLAG_NONE,
+                    mCurrentCookedState.deviceTimestamp,
+                    mCurrentCookedState.cookedPointerData.pointerProperties,
+                    mCurrentCookedState.cookedPointerData.pointerCoords,
+                    mCurrentCookedState.cookedPointerData.idToIndex,
+                    currentIdBits, -1,
+                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+        }
+    } else {
+        // There may be pointers going up and pointers going down and pointers moving
+        // all at the same time.
+        BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
+        BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
+        BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
+        BitSet32 dispatchedIdBits(lastIdBits.value);
+
+        // Update last coordinates of pointers that have moved so that we observe the new
+        // pointer positions at the same time as other pointers that have just gone up.
+        bool moveNeeded = updateMovedPointers(
+                mCurrentCookedState.cookedPointerData.pointerProperties,
+                mCurrentCookedState.cookedPointerData.pointerCoords,
+                mCurrentCookedState.cookedPointerData.idToIndex,
+                mLastCookedState.cookedPointerData.pointerProperties,
+                mLastCookedState.cookedPointerData.pointerCoords,
+                mLastCookedState.cookedPointerData.idToIndex,
+                moveIdBits);
+        if (buttonState != mLastCookedState.buttonState) {
+            moveNeeded = true;
+        }
+
+        // Dispatch pointer up events.
+        while (!upIdBits.isEmpty()) {
+            uint32_t upId = upIdBits.clearFirstMarkedBit();
+
+            dispatchMotion(when, policyFlags, mSource,
+                    AMOTION_EVENT_ACTION_POINTER_UP, 0, 0, metaState, buttonState, 0,
+                    mCurrentCookedState.deviceTimestamp,
+                    mLastCookedState.cookedPointerData.pointerProperties,
+                    mLastCookedState.cookedPointerData.pointerCoords,
+                    mLastCookedState.cookedPointerData.idToIndex,
+                    dispatchedIdBits, upId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+            dispatchedIdBits.clearBit(upId);
+        }
+
+        // Dispatch move events if any of the remaining pointers moved from their old locations.
+        // Although applications receive new locations as part of individual pointer up
+        // events, they do not generally handle them except when presented in a move event.
+        if (moveNeeded && !moveIdBits.isEmpty()) {
+            ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
+            dispatchMotion(when, policyFlags, mSource,
+                    AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, 0,
+                    mCurrentCookedState.deviceTimestamp,
+                    mCurrentCookedState.cookedPointerData.pointerProperties,
+                    mCurrentCookedState.cookedPointerData.pointerCoords,
+                    mCurrentCookedState.cookedPointerData.idToIndex,
+                    dispatchedIdBits, -1, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+        }
+
+        // Dispatch pointer down events using the new pointer locations.
+        while (!downIdBits.isEmpty()) {
+            uint32_t downId = downIdBits.clearFirstMarkedBit();
+            dispatchedIdBits.markBit(downId);
+
+            if (dispatchedIdBits.count() == 1) {
+                // First pointer is going down.  Set down time.
+                mDownTime = when;
+            }
+
+            dispatchMotion(when, policyFlags, mSource,
+                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
+                    mCurrentCookedState.deviceTimestamp,
+                    mCurrentCookedState.cookedPointerData.pointerProperties,
+                    mCurrentCookedState.cookedPointerData.pointerCoords,
+                    mCurrentCookedState.cookedPointerData.idToIndex,
+                    dispatchedIdBits, downId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+        }
+    }
+}
+
+void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
+    if (mSentHoverEnter &&
+            (mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()
+                    || !mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty())) {
+        int32_t metaState = getContext()->getGlobalMetaState();
+        dispatchMotion(when, policyFlags, mSource,
+                AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastCookedState.buttonState, 0,
+                mLastCookedState.deviceTimestamp,
+                mLastCookedState.cookedPointerData.pointerProperties,
+                mLastCookedState.cookedPointerData.pointerCoords,
+                mLastCookedState.cookedPointerData.idToIndex,
+                mLastCookedState.cookedPointerData.hoveringIdBits, -1,
+                mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+        mSentHoverEnter = false;
+    }
+}
+
+void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) {
+    if (mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty()
+            && !mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()) {
+        int32_t metaState = getContext()->getGlobalMetaState();
+        if (!mSentHoverEnter) {
+            dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_ENTER,
+                    0, 0, metaState, mCurrentRawState.buttonState, 0,
+                    mCurrentCookedState.deviceTimestamp,
+                    mCurrentCookedState.cookedPointerData.pointerProperties,
+                    mCurrentCookedState.cookedPointerData.pointerCoords,
+                    mCurrentCookedState.cookedPointerData.idToIndex,
+                    mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
+                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+            mSentHoverEnter = true;
+        }
+
+        dispatchMotion(when, policyFlags, mSource,
+                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
+                mCurrentRawState.buttonState, 0,
+                mCurrentCookedState.deviceTimestamp,
+                mCurrentCookedState.cookedPointerData.pointerProperties,
+                mCurrentCookedState.cookedPointerData.pointerCoords,
+                mCurrentCookedState.cookedPointerData.idToIndex,
+                mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
+                mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+    }
+}
+
+void TouchInputMapper::dispatchButtonRelease(nsecs_t when, uint32_t policyFlags) {
+    BitSet32 releasedButtons(mLastCookedState.buttonState & ~mCurrentCookedState.buttonState);
+    const BitSet32& idBits = findActiveIdBits(mLastCookedState.cookedPointerData);
+    const int32_t metaState = getContext()->getGlobalMetaState();
+    int32_t buttonState = mLastCookedState.buttonState;
+    while (!releasedButtons.isEmpty()) {
+        int32_t actionButton = BitSet32::valueForBit(releasedButtons.clearFirstMarkedBit());
+        buttonState &= ~actionButton;
+        dispatchMotion(when, policyFlags, mSource,
+                    AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton,
+                    0, metaState, buttonState, 0,
+                    mCurrentCookedState.deviceTimestamp,
+                    mCurrentCookedState.cookedPointerData.pointerProperties,
+                    mCurrentCookedState.cookedPointerData.pointerCoords,
+                    mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
+                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+    }
+}
+
+void TouchInputMapper::dispatchButtonPress(nsecs_t when, uint32_t policyFlags) {
+    BitSet32 pressedButtons(mCurrentCookedState.buttonState & ~mLastCookedState.buttonState);
+    const BitSet32& idBits = findActiveIdBits(mCurrentCookedState.cookedPointerData);
+    const int32_t metaState = getContext()->getGlobalMetaState();
+    int32_t buttonState = mLastCookedState.buttonState;
+    while (!pressedButtons.isEmpty()) {
+        int32_t actionButton = BitSet32::valueForBit(pressedButtons.clearFirstMarkedBit());
+        buttonState |= actionButton;
+        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton,
+                    0, metaState, buttonState, 0,
+                    mCurrentCookedState.deviceTimestamp,
+                    mCurrentCookedState.cookedPointerData.pointerProperties,
+                    mCurrentCookedState.cookedPointerData.pointerCoords,
+                    mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
+                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+    }
+}
+
+const BitSet32& TouchInputMapper::findActiveIdBits(const CookedPointerData& cookedPointerData) {
+    if (!cookedPointerData.touchingIdBits.isEmpty()) {
+        return cookedPointerData.touchingIdBits;
+    }
+    return cookedPointerData.hoveringIdBits;
+}
+
+void TouchInputMapper::cookPointerData() {
+    uint32_t currentPointerCount = mCurrentRawState.rawPointerData.pointerCount;
+
+    mCurrentCookedState.cookedPointerData.clear();
+    mCurrentCookedState.deviceTimestamp =
+            mCurrentRawState.deviceTimestamp;
+    mCurrentCookedState.cookedPointerData.pointerCount = currentPointerCount;
+    mCurrentCookedState.cookedPointerData.hoveringIdBits =
+            mCurrentRawState.rawPointerData.hoveringIdBits;
+    mCurrentCookedState.cookedPointerData.touchingIdBits =
+            mCurrentRawState.rawPointerData.touchingIdBits;
+
+    if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
+        mCurrentCookedState.buttonState = 0;
+    } else {
+        mCurrentCookedState.buttonState = mCurrentRawState.buttonState;
+    }
+
+    // Walk through the the active pointers and map device coordinates onto
+    // surface coordinates and adjust for display orientation.
+    for (uint32_t i = 0; i < currentPointerCount; i++) {
+        const RawPointerData::Pointer& in = mCurrentRawState.rawPointerData.pointers[i];
+
+        // Size
+        float touchMajor, touchMinor, toolMajor, toolMinor, size;
+        switch (mCalibration.sizeCalibration) {
+        case Calibration::SIZE_CALIBRATION_GEOMETRIC:
+        case Calibration::SIZE_CALIBRATION_DIAMETER:
+        case Calibration::SIZE_CALIBRATION_BOX:
+        case Calibration::SIZE_CALIBRATION_AREA:
+            if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
+                touchMajor = in.touchMajor;
+                touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
+                toolMajor = in.toolMajor;
+                toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
+                size = mRawPointerAxes.touchMinor.valid
+                        ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
+            } else if (mRawPointerAxes.touchMajor.valid) {
+                toolMajor = touchMajor = in.touchMajor;
+                toolMinor = touchMinor = mRawPointerAxes.touchMinor.valid
+                        ? in.touchMinor : in.touchMajor;
+                size = mRawPointerAxes.touchMinor.valid
+                        ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
+            } else if (mRawPointerAxes.toolMajor.valid) {
+                touchMajor = toolMajor = in.toolMajor;
+                touchMinor = toolMinor = mRawPointerAxes.toolMinor.valid
+                        ? in.toolMinor : in.toolMajor;
+                size = mRawPointerAxes.toolMinor.valid
+                        ? avg(in.toolMajor, in.toolMinor) : in.toolMajor;
+            } else {
+                ALOG_ASSERT(false, "No touch or tool axes.  "
+                        "Size calibration should have been resolved to NONE.");
+                touchMajor = 0;
+                touchMinor = 0;
+                toolMajor = 0;
+                toolMinor = 0;
+                size = 0;
+            }
+
+            if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
+                uint32_t touchingCount =
+                        mCurrentRawState.rawPointerData.touchingIdBits.count();
+                if (touchingCount > 1) {
+                    touchMajor /= touchingCount;
+                    touchMinor /= touchingCount;
+                    toolMajor /= touchingCount;
+                    toolMinor /= touchingCount;
+                    size /= touchingCount;
+                }
+            }
+
+            if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {
+                touchMajor *= mGeometricScale;
+                touchMinor *= mGeometricScale;
+                toolMajor *= mGeometricScale;
+                toolMinor *= mGeometricScale;
+            } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
+                touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
+                touchMinor = touchMajor;
+                toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
+                toolMinor = toolMajor;
+            } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {
+                touchMinor = touchMajor;
+                toolMinor = toolMajor;
+            }
+
+            mCalibration.applySizeScaleAndBias(&touchMajor);
+            mCalibration.applySizeScaleAndBias(&touchMinor);
+            mCalibration.applySizeScaleAndBias(&toolMajor);
+            mCalibration.applySizeScaleAndBias(&toolMinor);
+            size *= mSizeScale;
+            break;
+        default:
+            touchMajor = 0;
+            touchMinor = 0;
+            toolMajor = 0;
+            toolMinor = 0;
+            size = 0;
+            break;
+        }
+
+        // Pressure
+        float pressure;
+        switch (mCalibration.pressureCalibration) {
+        case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
+        case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
+            pressure = in.pressure * mPressureScale;
+            break;
+        default:
+            pressure = in.isHovering ? 0 : 1;
+            break;
+        }
+
+        // Tilt and Orientation
+        float tilt;
+        float orientation;
+        if (mHaveTilt) {
+            float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
+            float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
+            orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
+            tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
+        } else {
+            tilt = 0;
+
+            switch (mCalibration.orientationCalibration) {
+            case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
+                orientation = in.orientation * mOrientationScale;
+                break;
+            case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
+                int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
+                int32_t c2 = signExtendNybble(in.orientation & 0x0f);
+                if (c1 != 0 || c2 != 0) {
+                    orientation = atan2f(c1, c2) * 0.5f;
+                    float confidence = hypotf(c1, c2);
+                    float scale = 1.0f + confidence / 16.0f;
+                    touchMajor *= scale;
+                    touchMinor /= scale;
+                    toolMajor *= scale;
+                    toolMinor /= scale;
+                } else {
+                    orientation = 0;
+                }
+                break;
+            }
+            default:
+                orientation = 0;
+            }
+        }
+
+        // Distance
+        float distance;
+        switch (mCalibration.distanceCalibration) {
+        case Calibration::DISTANCE_CALIBRATION_SCALED:
+            distance = in.distance * mDistanceScale;
+            break;
+        default:
+            distance = 0;
+        }
+
+        // Coverage
+        int32_t rawLeft, rawTop, rawRight, rawBottom;
+        switch (mCalibration.coverageCalibration) {
+        case Calibration::COVERAGE_CALIBRATION_BOX:
+            rawLeft = (in.toolMinor & 0xffff0000) >> 16;
+            rawRight = in.toolMinor & 0x0000ffff;
+            rawBottom = in.toolMajor & 0x0000ffff;
+            rawTop = (in.toolMajor & 0xffff0000) >> 16;
+            break;
+        default:
+            rawLeft = rawTop = rawRight = rawBottom = 0;
+            break;
+        }
+
+        // Adjust X,Y coords for device calibration
+        // TODO: Adjust coverage coords?
+        float xTransformed = in.x, yTransformed = in.y;
+        mAffineTransform.applyTo(xTransformed, yTransformed);
+
+        // Adjust X, Y, and coverage coords for surface orientation.
+        float x, y;
+        float left, top, right, bottom;
+
+        switch (mSurfaceOrientation) {
+        case DISPLAY_ORIENTATION_90:
+            x = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+            y = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
+            left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+            right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+            bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
+            top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
+            orientation -= M_PI_2;
+            if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {
+                orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
+            }
+            break;
+        case DISPLAY_ORIENTATION_180:
+            x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale;
+            y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
+            left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
+            right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
+            bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
+            top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
+            orientation -= M_PI;
+            if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {
+                orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
+            }
+            break;
+        case DISPLAY_ORIENTATION_270:
+            x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale;
+            y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+            left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
+            right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
+            bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+            top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+            orientation += M_PI_2;
+            if (mOrientedRanges.haveOrientation && orientation > mOrientedRanges.orientation.max) {
+                orientation -= (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
+            }
+            break;
+        default:
+            x = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+            y = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+            left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+            right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+            bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+            top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+            break;
+        }
+
+        // Write output coords.
+        PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i];
+        out.clear();
+        out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
+        out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+        out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
+        out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
+        out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
+        out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
+        out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
+        out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
+        out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
+        if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
+            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);
+            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);
+            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);
+            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom);
+        } else {
+            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
+            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
+        }
+
+        // Write output properties.
+        PointerProperties& properties =
+                mCurrentCookedState.cookedPointerData.pointerProperties[i];
+        uint32_t id = in.id;
+        properties.clear();
+        properties.id = id;
+        properties.toolType = in.toolType;
+
+        // Write id index.
+        mCurrentCookedState.cookedPointerData.idToIndex[id] = i;
+    }
+}
+
+void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags,
+        PointerUsage pointerUsage) {
+    if (pointerUsage != mPointerUsage) {
+        abortPointerUsage(when, policyFlags);
+        mPointerUsage = pointerUsage;
+    }
+
+    switch (mPointerUsage) {
+    case POINTER_USAGE_GESTURES:
+        dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
+        break;
+    case POINTER_USAGE_STYLUS:
+        dispatchPointerStylus(when, policyFlags);
+        break;
+    case POINTER_USAGE_MOUSE:
+        dispatchPointerMouse(when, policyFlags);
+        break;
+    default:
+        break;
+    }
+}
+
+void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) {
+    switch (mPointerUsage) {
+    case POINTER_USAGE_GESTURES:
+        abortPointerGestures(when, policyFlags);
+        break;
+    case POINTER_USAGE_STYLUS:
+        abortPointerStylus(when, policyFlags);
+        break;
+    case POINTER_USAGE_MOUSE:
+        abortPointerMouse(when, policyFlags);
+        break;
+    default:
+        break;
+    }
+
+    mPointerUsage = POINTER_USAGE_NONE;
+}
+
+void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
+        bool isTimeout) {
+    // Update current gesture coordinates.
+    bool cancelPreviousGesture, finishPreviousGesture;
+    bool sendEvents = preparePointerGestures(when,
+            &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
+    if (!sendEvents) {
+        return;
+    }
+    if (finishPreviousGesture) {
+        cancelPreviousGesture = false;
+    }
+
+    // Update the pointer presentation and spots.
+    if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
+        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
+        if (finishPreviousGesture || cancelPreviousGesture) {
+            mPointerController->clearSpots();
+        }
+
+        if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
+            mPointerController->setSpots(mPointerGesture.currentGestureCoords,
+                     mPointerGesture.currentGestureIdToIndex,
+                     mPointerGesture.currentGestureIdBits,
+                     mPointerController->getDisplayId());
+        }
+    } else {
+        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
+    }
+
+    // Show or hide the pointer if needed.
+    switch (mPointerGesture.currentGestureMode) {
+    case PointerGesture::NEUTRAL:
+    case PointerGesture::QUIET:
+        if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH
+                && mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) {
+            // Remind the user of where the pointer is after finishing a gesture with spots.
+            mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
+        }
+        break;
+    case PointerGesture::TAP:
+    case PointerGesture::TAP_DRAG:
+    case PointerGesture::BUTTON_CLICK_OR_DRAG:
+    case PointerGesture::HOVER:
+    case PointerGesture::PRESS:
+    case PointerGesture::SWIPE:
+        // Unfade the pointer when the current gesture manipulates the
+        // area directly under the pointer.
+        mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
+        break;
+    case PointerGesture::FREEFORM:
+        // Fade the pointer when the current gesture manipulates a different
+        // area and there are spots to guide the user experience.
+        if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
+            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+        } else {
+            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
+        }
+        break;
+    }
+
+    // Send events!
+    int32_t metaState = getContext()->getGlobalMetaState();
+    int32_t buttonState = mCurrentCookedState.buttonState;
+
+    // Update last coordinates of pointers that have moved so that we observe the new
+    // pointer positions at the same time as other pointers that have just gone up.
+    bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
+            || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
+            || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
+            || mPointerGesture.currentGestureMode == PointerGesture::PRESS
+            || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
+            || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
+    bool moveNeeded = false;
+    if (down && !cancelPreviousGesture && !finishPreviousGesture
+            && !mPointerGesture.lastGestureIdBits.isEmpty()
+            && !mPointerGesture.currentGestureIdBits.isEmpty()) {
+        BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
+                & mPointerGesture.lastGestureIdBits.value);
+        moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
+                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
+                mPointerGesture.lastGestureProperties,
+                mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
+                movedGestureIdBits);
+        if (buttonState != mLastCookedState.buttonState) {
+            moveNeeded = true;
+        }
+    }
+
+    // Send motion events for all pointers that went up or were canceled.
+    BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
+    if (!dispatchedGestureIdBits.isEmpty()) {
+        if (cancelPreviousGesture) {
+            dispatchMotion(when, policyFlags, mSource,
+                    AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, buttonState,
+                    AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+                    mPointerGesture.lastGestureProperties,
+                    mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
+                    dispatchedGestureIdBits, -1, 0,
+                    0, mPointerGesture.downTime);
+
+            dispatchedGestureIdBits.clear();
+        } else {
+            BitSet32 upGestureIdBits;
+            if (finishPreviousGesture) {
+                upGestureIdBits = dispatchedGestureIdBits;
+            } else {
+                upGestureIdBits.value = dispatchedGestureIdBits.value
+                        & ~mPointerGesture.currentGestureIdBits.value;
+            }
+            while (!upGestureIdBits.isEmpty()) {
+                uint32_t id = upGestureIdBits.clearFirstMarkedBit();
+
+                dispatchMotion(when, policyFlags, mSource,
+                        AMOTION_EVENT_ACTION_POINTER_UP, 0, 0,
+                        metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                        /* deviceTimestamp */ 0,
+                        mPointerGesture.lastGestureProperties,
+                        mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
+                        dispatchedGestureIdBits, id,
+                        0, 0, mPointerGesture.downTime);
+
+                dispatchedGestureIdBits.clearBit(id);
+            }
+        }
+    }
+
+    // Send motion events for all pointers that moved.
+    if (moveNeeded) {
+        dispatchMotion(when, policyFlags, mSource,
+                AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
+                AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+                mPointerGesture.currentGestureProperties,
+                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
+                dispatchedGestureIdBits, -1,
+                0, 0, mPointerGesture.downTime);
+    }
+
+    // Send motion events for all pointers that went down.
+    if (down) {
+        BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
+                & ~dispatchedGestureIdBits.value);
+        while (!downGestureIdBits.isEmpty()) {
+            uint32_t id = downGestureIdBits.clearFirstMarkedBit();
+            dispatchedGestureIdBits.markBit(id);
+
+            if (dispatchedGestureIdBits.count() == 1) {
+                mPointerGesture.downTime = when;
+            }
+
+            dispatchMotion(when, policyFlags, mSource,
+                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
+                    /* deviceTimestamp */ 0,
+                    mPointerGesture.currentGestureProperties,
+                    mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
+                    dispatchedGestureIdBits, id,
+                    0, 0, mPointerGesture.downTime);
+        }
+    }
+
+    // Send motion events for hover.
+    if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
+        dispatchMotion(when, policyFlags, mSource,
+                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
+                metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+                mPointerGesture.currentGestureProperties,
+                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
+                mPointerGesture.currentGestureIdBits, -1,
+                0, 0, mPointerGesture.downTime);
+    } else if (dispatchedGestureIdBits.isEmpty()
+            && !mPointerGesture.lastGestureIdBits.isEmpty()) {
+        // Synthesize a hover move event after all pointers go up to indicate that
+        // the pointer is hovering again even if the user is not currently touching
+        // the touch pad.  This ensures that a view will receive a fresh hover enter
+        // event after a tap.
+        float x, y;
+        mPointerController->getPosition(&x, &y);
+
+        PointerProperties pointerProperties;
+        pointerProperties.clear();
+        pointerProperties.id = 0;
+        pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+
+        PointerCoords pointerCoords;
+        pointerCoords.clear();
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+
+        const int32_t displayId = mPointerController->getDisplayId();
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
+                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
+                metaState, buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+                /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+                0, 0, mPointerGesture.downTime, /* videoFrames */ {});
+        getListener()->notifyMotion(&args);
+    }
+
+    // Update state.
+    mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
+    if (!down) {
+        mPointerGesture.lastGestureIdBits.clear();
+    } else {
+        mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
+        for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
+            uint32_t id = idBits.clearFirstMarkedBit();
+            uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
+            mPointerGesture.lastGestureProperties[index].copyFrom(
+                    mPointerGesture.currentGestureProperties[index]);
+            mPointerGesture.lastGestureCoords[index].copyFrom(
+                    mPointerGesture.currentGestureCoords[index]);
+            mPointerGesture.lastGestureIdToIndex[id] = index;
+        }
+    }
+}
+
+void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) {
+    // Cancel previously dispatches pointers.
+    if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
+        int32_t metaState = getContext()->getGlobalMetaState();
+        int32_t buttonState = mCurrentRawState.buttonState;
+        dispatchMotion(when, policyFlags, mSource,
+                AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, buttonState,
+                AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+                mPointerGesture.lastGestureProperties,
+                mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
+                mPointerGesture.lastGestureIdBits, -1,
+                0, 0, mPointerGesture.downTime);
+    }
+
+    // Reset the current pointer gesture.
+    mPointerGesture.reset();
+    mPointerVelocityControl.reset();
+
+    // Remove any current spots.
+    if (mPointerController != nullptr) {
+        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+        mPointerController->clearSpots();
+    }
+}
+
+bool TouchInputMapper::preparePointerGestures(nsecs_t when,
+        bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
+    *outCancelPreviousGesture = false;
+    *outFinishPreviousGesture = false;
+
+    // Handle TAP timeout.
+    if (isTimeout) {
+#if DEBUG_GESTURES
+        ALOGD("Gestures: Processing timeout");
+#endif
+
+        if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
+            if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
+                // The tap/drag timeout has not yet expired.
+                getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
+                        + mConfig.pointerGestureTapDragInterval);
+            } else {
+                // The tap is finished.
+#if DEBUG_GESTURES
+                ALOGD("Gestures: TAP finished");
+#endif
+                *outFinishPreviousGesture = true;
+
+                mPointerGesture.activeGestureId = -1;
+                mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
+                mPointerGesture.currentGestureIdBits.clear();
+
+                mPointerVelocityControl.reset();
+                return true;
+            }
+        }
+
+        // We did not handle this timeout.
+        return false;
+    }
+
+    const uint32_t currentFingerCount = mCurrentCookedState.fingerIdBits.count();
+    const uint32_t lastFingerCount = mLastCookedState.fingerIdBits.count();
+
+    // Update the velocity tracker.
+    {
+        VelocityTracker::Position positions[MAX_POINTERS];
+        uint32_t count = 0;
+        for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty(); count++) {
+            uint32_t id = idBits.clearFirstMarkedBit();
+            const RawPointerData::Pointer& pointer =
+                    mCurrentRawState.rawPointerData.pointerForId(id);
+            positions[count].x = pointer.x * mPointerXMovementScale;
+            positions[count].y = pointer.y * mPointerYMovementScale;
+        }
+        mPointerGesture.velocityTracker.addMovement(when,
+                mCurrentCookedState.fingerIdBits, positions);
+    }
+
+    // If the gesture ever enters a mode other than TAP, HOVER or TAP_DRAG, without first returning
+    // to NEUTRAL, then we should not generate tap event.
+    if (mPointerGesture.lastGestureMode != PointerGesture::HOVER
+            && mPointerGesture.lastGestureMode != PointerGesture::TAP
+            && mPointerGesture.lastGestureMode != PointerGesture::TAP_DRAG) {
+        mPointerGesture.resetTap();
+    }
+
+    // Pick a new active touch id if needed.
+    // Choose an arbitrary pointer that just went down, if there is one.
+    // Otherwise choose an arbitrary remaining pointer.
+    // This guarantees we always have an active touch id when there is at least one pointer.
+    // We keep the same active touch id for as long as possible.
+    int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
+    int32_t activeTouchId = lastActiveTouchId;
+    if (activeTouchId < 0) {
+        if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
+            activeTouchId = mPointerGesture.activeTouchId =
+                    mCurrentCookedState.fingerIdBits.firstMarkedBit();
+            mPointerGesture.firstTouchTime = when;
+        }
+    } else if (!mCurrentCookedState.fingerIdBits.hasBit(activeTouchId)) {
+        if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
+            activeTouchId = mPointerGesture.activeTouchId =
+                    mCurrentCookedState.fingerIdBits.firstMarkedBit();
+        } else {
+            activeTouchId = mPointerGesture.activeTouchId = -1;
+        }
+    }
+
+    // Determine whether we are in quiet time.
+    bool isQuietTime = false;
+    if (activeTouchId < 0) {
+        mPointerGesture.resetQuietTime();
+    } else {
+        isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
+        if (!isQuietTime) {
+            if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
+                    || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
+                    || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
+                    && currentFingerCount < 2) {
+                // Enter quiet time when exiting swipe or freeform state.
+                // This is to prevent accidentally entering the hover state and flinging the
+                // pointer when finishing a swipe and there is still one pointer left onscreen.
+                isQuietTime = true;
+            } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
+                    && currentFingerCount >= 2
+                    && !isPointerDown(mCurrentRawState.buttonState)) {
+                // Enter quiet time when releasing the button and there are still two or more
+                // fingers down.  This may indicate that one finger was used to press the button
+                // but it has not gone up yet.
+                isQuietTime = true;
+            }
+            if (isQuietTime) {
+                mPointerGesture.quietTime = when;
+            }
+        }
+    }
+
+    // Switch states based on button and pointer state.
+    if (isQuietTime) {
+        // Case 1: Quiet time. (QUIET)
+#if DEBUG_GESTURES
+        ALOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
+                + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
+#endif
+        if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
+            *outFinishPreviousGesture = true;
+        }
+
+        mPointerGesture.activeGestureId = -1;
+        mPointerGesture.currentGestureMode = PointerGesture::QUIET;
+        mPointerGesture.currentGestureIdBits.clear();
+
+        mPointerVelocityControl.reset();
+    } else if (isPointerDown(mCurrentRawState.buttonState)) {
+        // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
+        // The pointer follows the active touch point.
+        // Emit DOWN, MOVE, UP events at the pointer location.
+        //
+        // Only the active touch matters; other fingers are ignored.  This policy helps
+        // to handle the case where the user places a second finger on the touch pad
+        // to apply the necessary force to depress an integrated button below the surface.
+        // We don't want the second finger to be delivered to applications.
+        //
+        // For this to work well, we need to make sure to track the pointer that is really
+        // active.  If the user first puts one finger down to click then adds another
+        // finger to drag then the active pointer should switch to the finger that is
+        // being dragged.
+#if DEBUG_GESTURES
+        ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
+                "currentFingerCount=%d", activeTouchId, currentFingerCount);
+#endif
+        // Reset state when just starting.
+        if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
+            *outFinishPreviousGesture = true;
+            mPointerGesture.activeGestureId = 0;
+        }
+
+        // Switch pointers if needed.
+        // Find the fastest pointer and follow it.
+        if (activeTouchId >= 0 && currentFingerCount > 1) {
+            int32_t bestId = -1;
+            float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
+            for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty(); ) {
+                uint32_t id = idBits.clearFirstMarkedBit();
+                float vx, vy;
+                if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
+                    float speed = hypotf(vx, vy);
+                    if (speed > bestSpeed) {
+                        bestId = id;
+                        bestSpeed = speed;
+                    }
+                }
+            }
+            if (bestId >= 0 && bestId != activeTouchId) {
+                mPointerGesture.activeTouchId = activeTouchId = bestId;
+#if DEBUG_GESTURES
+                ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
+                        "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
+#endif
+            }
+        }
+
+        float deltaX = 0, deltaY = 0;
+        if (activeTouchId >= 0 && mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
+            const RawPointerData::Pointer& currentPointer =
+                    mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
+            const RawPointerData::Pointer& lastPointer =
+                    mLastRawState.rawPointerData.pointerForId(activeTouchId);
+            deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
+            deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
+
+            rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
+            mPointerVelocityControl.move(when, &deltaX, &deltaY);
+
+            // Move the pointer using a relative motion.
+            // When using spots, the click will occur at the position of the anchor
+            // spot and all other spots will move there.
+            mPointerController->move(deltaX, deltaY);
+        } else {
+            mPointerVelocityControl.reset();
+        }
+
+        float x, y;
+        mPointerController->getPosition(&x, &y);
+
+        mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
+        mPointerGesture.currentGestureIdBits.clear();
+        mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
+        mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
+        mPointerGesture.currentGestureProperties[0].clear();
+        mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
+        mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+        mPointerGesture.currentGestureCoords[0].clear();
+        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
+        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
+    } else if (currentFingerCount == 0) {
+        // Case 3. No fingers down and button is not pressed. (NEUTRAL)
+        if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
+            *outFinishPreviousGesture = true;
+        }
+
+        // Watch for taps coming out of HOVER or TAP_DRAG mode.
+        // Checking for taps after TAP_DRAG allows us to detect double-taps.
+        bool tapped = false;
+        if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
+                || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
+                && lastFingerCount == 1) {
+            if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
+                float x, y;
+                mPointerController->getPosition(&x, &y);
+                if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
+                        && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
+#if DEBUG_GESTURES
+                    ALOGD("Gestures: TAP");
+#endif
+
+                    mPointerGesture.tapUpTime = when;
+                    getContext()->requestTimeoutAtTime(when
+                            + mConfig.pointerGestureTapDragInterval);
+
+                    mPointerGesture.activeGestureId = 0;
+                    mPointerGesture.currentGestureMode = PointerGesture::TAP;
+                    mPointerGesture.currentGestureIdBits.clear();
+                    mPointerGesture.currentGestureIdBits.markBit(
+                            mPointerGesture.activeGestureId);
+                    mPointerGesture.currentGestureIdToIndex[
+                            mPointerGesture.activeGestureId] = 0;
+                    mPointerGesture.currentGestureProperties[0].clear();
+                    mPointerGesture.currentGestureProperties[0].id =
+                            mPointerGesture.activeGestureId;
+                    mPointerGesture.currentGestureProperties[0].toolType =
+                            AMOTION_EVENT_TOOL_TYPE_FINGER;
+                    mPointerGesture.currentGestureCoords[0].clear();
+                    mPointerGesture.currentGestureCoords[0].setAxisValue(
+                            AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
+                    mPointerGesture.currentGestureCoords[0].setAxisValue(
+                            AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
+                    mPointerGesture.currentGestureCoords[0].setAxisValue(
+                            AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
+
+                    tapped = true;
+                } else {
+#if DEBUG_GESTURES
+                    ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
+                            x - mPointerGesture.tapX,
+                            y - mPointerGesture.tapY);
+#endif
+                }
+            } else {
+#if DEBUG_GESTURES
+                if (mPointerGesture.tapDownTime != LLONG_MIN) {
+                    ALOGD("Gestures: Not a TAP, %0.3fms since down",
+                            (when - mPointerGesture.tapDownTime) * 0.000001f);
+                } else {
+                    ALOGD("Gestures: Not a TAP, incompatible mode transitions");
+                }
+#endif
+            }
+        }
+
+        mPointerVelocityControl.reset();
+
+        if (!tapped) {
+#if DEBUG_GESTURES
+            ALOGD("Gestures: NEUTRAL");
+#endif
+            mPointerGesture.activeGestureId = -1;
+            mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
+            mPointerGesture.currentGestureIdBits.clear();
+        }
+    } else if (currentFingerCount == 1) {
+        // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
+        // The pointer follows the active touch point.
+        // When in HOVER, emit HOVER_MOVE events at the pointer location.
+        // When in TAP_DRAG, emit MOVE events at the pointer location.
+        ALOG_ASSERT(activeTouchId >= 0);
+
+        mPointerGesture.currentGestureMode = PointerGesture::HOVER;
+        if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
+            if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
+                float x, y;
+                mPointerController->getPosition(&x, &y);
+                if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
+                        && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
+                    mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
+                } else {
+#if DEBUG_GESTURES
+                    ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
+                            x - mPointerGesture.tapX,
+                            y - mPointerGesture.tapY);
+#endif
+                }
+            } else {
+#if DEBUG_GESTURES
+                ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
+                        (when - mPointerGesture.tapUpTime) * 0.000001f);
+#endif
+            }
+        } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
+            mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
+        }
+
+        float deltaX = 0, deltaY = 0;
+        if (mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
+            const RawPointerData::Pointer& currentPointer =
+                    mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
+            const RawPointerData::Pointer& lastPointer =
+                    mLastRawState.rawPointerData.pointerForId(activeTouchId);
+            deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
+            deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
+
+            rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
+            mPointerVelocityControl.move(when, &deltaX, &deltaY);
+
+            // Move the pointer using a relative motion.
+            // When using spots, the hover or drag will occur at the position of the anchor spot.
+            mPointerController->move(deltaX, deltaY);
+        } else {
+            mPointerVelocityControl.reset();
+        }
+
+        bool down;
+        if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
+#if DEBUG_GESTURES
+            ALOGD("Gestures: TAP_DRAG");
+#endif
+            down = true;
+        } else {
+#if DEBUG_GESTURES
+            ALOGD("Gestures: HOVER");
+#endif
+            if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
+                *outFinishPreviousGesture = true;
+            }
+            mPointerGesture.activeGestureId = 0;
+            down = false;
+        }
+
+        float x, y;
+        mPointerController->getPosition(&x, &y);
+
+        mPointerGesture.currentGestureIdBits.clear();
+        mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
+        mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
+        mPointerGesture.currentGestureProperties[0].clear();
+        mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
+        mPointerGesture.currentGestureProperties[0].toolType =
+                AMOTION_EVENT_TOOL_TYPE_FINGER;
+        mPointerGesture.currentGestureCoords[0].clear();
+        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
+        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
+                down ? 1.0f : 0.0f);
+
+        if (lastFingerCount == 0 && currentFingerCount != 0) {
+            mPointerGesture.resetTap();
+            mPointerGesture.tapDownTime = when;
+            mPointerGesture.tapX = x;
+            mPointerGesture.tapY = y;
+        }
+    } else {
+        // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
+        // We need to provide feedback for each finger that goes down so we cannot wait
+        // for the fingers to move before deciding what to do.
+        //
+        // The ambiguous case is deciding what to do when there are two fingers down but they
+        // have not moved enough to determine whether they are part of a drag or part of a
+        // freeform gesture, or just a press or long-press at the pointer location.
+        //
+        // When there are two fingers we start with the PRESS hypothesis and we generate a
+        // down at the pointer location.
+        //
+        // When the two fingers move enough or when additional fingers are added, we make
+        // a decision to transition into SWIPE or FREEFORM mode accordingly.
+        ALOG_ASSERT(activeTouchId >= 0);
+
+        bool settled = when >= mPointerGesture.firstTouchTime
+                + mConfig.pointerGestureMultitouchSettleInterval;
+        if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
+                && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
+                && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
+            *outFinishPreviousGesture = true;
+        } else if (!settled && currentFingerCount > lastFingerCount) {
+            // Additional pointers have gone down but not yet settled.
+            // Reset the gesture.
+#if DEBUG_GESTURES
+            ALOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
+                    "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
+                            + mConfig.pointerGestureMultitouchSettleInterval - when)
+                            * 0.000001f);
+#endif
+            *outCancelPreviousGesture = true;
+        } else {
+            // Continue previous gesture.
+            mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
+        }
+
+        if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
+            mPointerGesture.currentGestureMode = PointerGesture::PRESS;
+            mPointerGesture.activeGestureId = 0;
+            mPointerGesture.referenceIdBits.clear();
+            mPointerVelocityControl.reset();
+
+            // Use the centroid and pointer location as the reference points for the gesture.
+#if DEBUG_GESTURES
+            ALOGD("Gestures: Using centroid as reference for MULTITOUCH, "
+                    "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
+                            + mConfig.pointerGestureMultitouchSettleInterval - when)
+                            * 0.000001f);
+#endif
+            mCurrentRawState.rawPointerData.getCentroidOfTouchingPointers(
+                    &mPointerGesture.referenceTouchX,
+                    &mPointerGesture.referenceTouchY);
+            mPointerController->getPosition(&mPointerGesture.referenceGestureX,
+                    &mPointerGesture.referenceGestureY);
+        }
+
+        // Clear the reference deltas for fingers not yet included in the reference calculation.
+        for (BitSet32 idBits(mCurrentCookedState.fingerIdBits.value
+                & ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) {
+            uint32_t id = idBits.clearFirstMarkedBit();
+            mPointerGesture.referenceDeltas[id].dx = 0;
+            mPointerGesture.referenceDeltas[id].dy = 0;
+        }
+        mPointerGesture.referenceIdBits = mCurrentCookedState.fingerIdBits;
+
+        // Add delta for all fingers and calculate a common movement delta.
+        float commonDeltaX = 0, commonDeltaY = 0;
+        BitSet32 commonIdBits(mLastCookedState.fingerIdBits.value
+                & mCurrentCookedState.fingerIdBits.value);
+        for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
+            bool first = (idBits == commonIdBits);
+            uint32_t id = idBits.clearFirstMarkedBit();
+            const RawPointerData::Pointer& cpd = mCurrentRawState.rawPointerData.pointerForId(id);
+            const RawPointerData::Pointer& lpd = mLastRawState.rawPointerData.pointerForId(id);
+            PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
+            delta.dx += cpd.x - lpd.x;
+            delta.dy += cpd.y - lpd.y;
+
+            if (first) {
+                commonDeltaX = delta.dx;
+                commonDeltaY = delta.dy;
+            } else {
+                commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
+                commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
+            }
+        }
+
+        // Consider transitions from PRESS to SWIPE or MULTITOUCH.
+        if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
+            float dist[MAX_POINTER_ID + 1];
+            int32_t distOverThreshold = 0;
+            for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
+                uint32_t id = idBits.clearFirstMarkedBit();
+                PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
+                dist[id] = hypotf(delta.dx * mPointerXZoomScale,
+                        delta.dy * mPointerYZoomScale);
+                if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
+                    distOverThreshold += 1;
+                }
+            }
+
+            // Only transition when at least two pointers have moved further than
+            // the minimum distance threshold.
+            if (distOverThreshold >= 2) {
+                if (currentFingerCount > 2) {
+                    // There are more than two pointers, switch to FREEFORM.
+#if DEBUG_GESTURES
+                    ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
+                            currentFingerCount);
+#endif
+                    *outCancelPreviousGesture = true;
+                    mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+                } else {
+                    // There are exactly two pointers.
+                    BitSet32 idBits(mCurrentCookedState.fingerIdBits);
+                    uint32_t id1 = idBits.clearFirstMarkedBit();
+                    uint32_t id2 = idBits.firstMarkedBit();
+                    const RawPointerData::Pointer& p1 =
+                            mCurrentRawState.rawPointerData.pointerForId(id1);
+                    const RawPointerData::Pointer& p2 =
+                            mCurrentRawState.rawPointerData.pointerForId(id2);
+                    float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y);
+                    if (mutualDistance > mPointerGestureMaxSwipeWidth) {
+                        // There are two pointers but they are too far apart for a SWIPE,
+                        // switch to FREEFORM.
+#if DEBUG_GESTURES
+                        ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
+                                mutualDistance, mPointerGestureMaxSwipeWidth);
+#endif
+                        *outCancelPreviousGesture = true;
+                        mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+                    } else {
+                        // There are two pointers.  Wait for both pointers to start moving
+                        // before deciding whether this is a SWIPE or FREEFORM gesture.
+                        float dist1 = dist[id1];
+                        float dist2 = dist[id2];
+                        if (dist1 >= mConfig.pointerGestureMultitouchMinDistance
+                                && dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
+                            // Calculate the dot product of the displacement vectors.
+                            // When the vectors are oriented in approximately the same direction,
+                            // the angle betweeen them is near zero and the cosine of the angle
+                            // approches 1.0.  Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
+                            PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
+                            PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
+                            float dx1 = delta1.dx * mPointerXZoomScale;
+                            float dy1 = delta1.dy * mPointerYZoomScale;
+                            float dx2 = delta2.dx * mPointerXZoomScale;
+                            float dy2 = delta2.dy * mPointerYZoomScale;
+                            float dot = dx1 * dx2 + dy1 * dy2;
+                            float cosine = dot / (dist1 * dist2); // denominator always > 0
+                            if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
+                                // Pointers are moving in the same direction.  Switch to SWIPE.
+#if DEBUG_GESTURES
+                                ALOGD("Gestures: PRESS transitioned to SWIPE, "
+                                        "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
+                                        "cosine %0.3f >= %0.3f",
+                                        dist1, mConfig.pointerGestureMultitouchMinDistance,
+                                        dist2, mConfig.pointerGestureMultitouchMinDistance,
+                                        cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
+#endif
+                                mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
+                            } else {
+                                // Pointers are moving in different directions.  Switch to FREEFORM.
+#if DEBUG_GESTURES
+                                ALOGD("Gestures: PRESS transitioned to FREEFORM, "
+                                        "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
+                                        "cosine %0.3f < %0.3f",
+                                        dist1, mConfig.pointerGestureMultitouchMinDistance,
+                                        dist2, mConfig.pointerGestureMultitouchMinDistance,
+                                        cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
+#endif
+                                *outCancelPreviousGesture = true;
+                                mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+                            }
+                        }
+                    }
+                }
+            }
+        } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
+            // Switch from SWIPE to FREEFORM if additional pointers go down.
+            // Cancel previous gesture.
+            if (currentFingerCount > 2) {
+#if DEBUG_GESTURES
+                ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
+                        currentFingerCount);
+#endif
+                *outCancelPreviousGesture = true;
+                mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+            }
+        }
+
+        // Move the reference points based on the overall group motion of the fingers
+        // except in PRESS mode while waiting for a transition to occur.
+        if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
+                && (commonDeltaX || commonDeltaY)) {
+            for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
+                uint32_t id = idBits.clearFirstMarkedBit();
+                PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
+                delta.dx = 0;
+                delta.dy = 0;
+            }
+
+            mPointerGesture.referenceTouchX += commonDeltaX;
+            mPointerGesture.referenceTouchY += commonDeltaY;
+
+            commonDeltaX *= mPointerXMovementScale;
+            commonDeltaY *= mPointerYMovementScale;
+
+            rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY);
+            mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
+
+            mPointerGesture.referenceGestureX += commonDeltaX;
+            mPointerGesture.referenceGestureY += commonDeltaY;
+        }
+
+        // Report gestures.
+        if (mPointerGesture.currentGestureMode == PointerGesture::PRESS
+                || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
+            // PRESS or SWIPE mode.
+#if DEBUG_GESTURES
+            ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
+                    "activeGestureId=%d, currentTouchPointerCount=%d",
+                    activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
+#endif
+            ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
+
+            mPointerGesture.currentGestureIdBits.clear();
+            mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
+            mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
+            mPointerGesture.currentGestureProperties[0].clear();
+            mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
+            mPointerGesture.currentGestureProperties[0].toolType =
+                    AMOTION_EVENT_TOOL_TYPE_FINGER;
+            mPointerGesture.currentGestureCoords[0].clear();
+            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
+                    mPointerGesture.referenceGestureX);
+            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
+                    mPointerGesture.referenceGestureY);
+            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
+        } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
+            // FREEFORM mode.
+#if DEBUG_GESTURES
+            ALOGD("Gestures: FREEFORM activeTouchId=%d,"
+                    "activeGestureId=%d, currentTouchPointerCount=%d",
+                    activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
+#endif
+            ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
+
+            mPointerGesture.currentGestureIdBits.clear();
+
+            BitSet32 mappedTouchIdBits;
+            BitSet32 usedGestureIdBits;
+            if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
+                // Initially, assign the active gesture id to the active touch point
+                // if there is one.  No other touch id bits are mapped yet.
+                if (!*outCancelPreviousGesture) {
+                    mappedTouchIdBits.markBit(activeTouchId);
+                    usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
+                    mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
+                            mPointerGesture.activeGestureId;
+                } else {
+                    mPointerGesture.activeGestureId = -1;
+                }
+            } else {
+                // Otherwise, assume we mapped all touches from the previous frame.
+                // Reuse all mappings that are still applicable.
+                mappedTouchIdBits.value = mLastCookedState.fingerIdBits.value
+                        & mCurrentCookedState.fingerIdBits.value;
+                usedGestureIdBits = mPointerGesture.lastGestureIdBits;
+
+                // Check whether we need to choose a new active gesture id because the
+                // current went went up.
+                for (BitSet32 upTouchIdBits(mLastCookedState.fingerIdBits.value
+                        & ~mCurrentCookedState.fingerIdBits.value);
+                        !upTouchIdBits.isEmpty(); ) {
+                    uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
+                    uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
+                    if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
+                        mPointerGesture.activeGestureId = -1;
+                        break;
+                    }
+                }
+            }
+
+#if DEBUG_GESTURES
+            ALOGD("Gestures: FREEFORM follow up "
+                    "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
+                    "activeGestureId=%d",
+                    mappedTouchIdBits.value, usedGestureIdBits.value,
+                    mPointerGesture.activeGestureId);
+#endif
+
+            BitSet32 idBits(mCurrentCookedState.fingerIdBits);
+            for (uint32_t i = 0; i < currentFingerCount; i++) {
+                uint32_t touchId = idBits.clearFirstMarkedBit();
+                uint32_t gestureId;
+                if (!mappedTouchIdBits.hasBit(touchId)) {
+                    gestureId = usedGestureIdBits.markFirstUnmarkedBit();
+                    mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
+#if DEBUG_GESTURES
+                    ALOGD("Gestures: FREEFORM "
+                            "new mapping for touch id %d -> gesture id %d",
+                            touchId, gestureId);
+#endif
+                } else {
+                    gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
+#if DEBUG_GESTURES
+                    ALOGD("Gestures: FREEFORM "
+                            "existing mapping for touch id %d -> gesture id %d",
+                            touchId, gestureId);
+#endif
+                }
+                mPointerGesture.currentGestureIdBits.markBit(gestureId);
+                mPointerGesture.currentGestureIdToIndex[gestureId] = i;
+
+                const RawPointerData::Pointer& pointer =
+                        mCurrentRawState.rawPointerData.pointerForId(touchId);
+                float deltaX = (pointer.x - mPointerGesture.referenceTouchX)
+                        * mPointerXZoomScale;
+                float deltaY = (pointer.y - mPointerGesture.referenceTouchY)
+                        * mPointerYZoomScale;
+                rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
+
+                mPointerGesture.currentGestureProperties[i].clear();
+                mPointerGesture.currentGestureProperties[i].id = gestureId;
+                mPointerGesture.currentGestureProperties[i].toolType =
+                        AMOTION_EVENT_TOOL_TYPE_FINGER;
+                mPointerGesture.currentGestureCoords[i].clear();
+                mPointerGesture.currentGestureCoords[i].setAxisValue(
+                        AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX);
+                mPointerGesture.currentGestureCoords[i].setAxisValue(
+                        AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY);
+                mPointerGesture.currentGestureCoords[i].setAxisValue(
+                        AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
+            }
+
+            if (mPointerGesture.activeGestureId < 0) {
+                mPointerGesture.activeGestureId =
+                        mPointerGesture.currentGestureIdBits.firstMarkedBit();
+#if DEBUG_GESTURES
+                ALOGD("Gestures: FREEFORM new "
+                        "activeGestureId=%d", mPointerGesture.activeGestureId);
+#endif
+            }
+        }
+    }
+
+    mPointerController->setButtonState(mCurrentRawState.buttonState);
+
+#if DEBUG_GESTURES
+    ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
+            "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
+            "lastGestureMode=%d, lastGestureIdBits=0x%08x",
+            toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
+            mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
+            mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
+    for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
+        uint32_t id = idBits.clearFirstMarkedBit();
+        uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
+        const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
+        const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
+        ALOGD("  currentGesture[%d]: index=%d, toolType=%d, "
+                "x=%0.3f, y=%0.3f, pressure=%0.3f",
+                id, index, properties.toolType,
+                coords.getAxisValue(AMOTION_EVENT_AXIS_X),
+                coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
+                coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
+    }
+    for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
+        uint32_t id = idBits.clearFirstMarkedBit();
+        uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
+        const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
+        const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
+        ALOGD("  lastGesture[%d]: index=%d, toolType=%d, "
+                "x=%0.3f, y=%0.3f, pressure=%0.3f",
+                id, index, properties.toolType,
+                coords.getAxisValue(AMOTION_EVENT_AXIS_X),
+                coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
+                coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
+    }
+#endif
+    return true;
+}
+
+void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) {
+    mPointerSimple.currentCoords.clear();
+    mPointerSimple.currentProperties.clear();
+
+    bool down, hovering;
+    if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
+        uint32_t id = mCurrentCookedState.stylusIdBits.firstMarkedBit();
+        uint32_t index = mCurrentCookedState.cookedPointerData.idToIndex[id];
+        float x = mCurrentCookedState.cookedPointerData.pointerCoords[index].getX();
+        float y = mCurrentCookedState.cookedPointerData.pointerCoords[index].getY();
+        mPointerController->setPosition(x, y);
+
+        hovering = mCurrentCookedState.cookedPointerData.hoveringIdBits.hasBit(id);
+        down = !hovering;
+
+        mPointerController->getPosition(&x, &y);
+        mPointerSimple.currentCoords.copyFrom(
+                mCurrentCookedState.cookedPointerData.pointerCoords[index]);
+        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
+        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+        mPointerSimple.currentProperties.id = 0;
+        mPointerSimple.currentProperties.toolType =
+                mCurrentCookedState.cookedPointerData.pointerProperties[index].toolType;
+    } else {
+        down = false;
+        hovering = false;
+    }
+
+    dispatchPointerSimple(when, policyFlags, down, hovering);
+}
+
+void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) {
+    abortPointerSimple(when, policyFlags);
+}
+
+void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) {
+    mPointerSimple.currentCoords.clear();
+    mPointerSimple.currentProperties.clear();
+
+    bool down, hovering;
+    if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
+        uint32_t id = mCurrentCookedState.mouseIdBits.firstMarkedBit();
+        uint32_t currentIndex = mCurrentRawState.rawPointerData.idToIndex[id];
+        float deltaX = 0, deltaY = 0;
+        if (mLastCookedState.mouseIdBits.hasBit(id)) {
+            uint32_t lastIndex = mCurrentRawState.rawPointerData.idToIndex[id];
+            deltaX = (mCurrentRawState.rawPointerData.pointers[currentIndex].x
+                    - mLastRawState.rawPointerData.pointers[lastIndex].x)
+                    * mPointerXMovementScale;
+            deltaY = (mCurrentRawState.rawPointerData.pointers[currentIndex].y
+                    - mLastRawState.rawPointerData.pointers[lastIndex].y)
+                    * mPointerYMovementScale;
+
+            rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
+            mPointerVelocityControl.move(when, &deltaX, &deltaY);
+
+            mPointerController->move(deltaX, deltaY);
+        } else {
+            mPointerVelocityControl.reset();
+        }
+
+        down = isPointerDown(mCurrentRawState.buttonState);
+        hovering = !down;
+
+        float x, y;
+        mPointerController->getPosition(&x, &y);
+        mPointerSimple.currentCoords.copyFrom(
+                mCurrentCookedState.cookedPointerData.pointerCoords[currentIndex]);
+        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
+        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
+                hovering ? 0.0f : 1.0f);
+        mPointerSimple.currentProperties.id = 0;
+        mPointerSimple.currentProperties.toolType =
+                mCurrentCookedState.cookedPointerData.pointerProperties[currentIndex].toolType;
+    } else {
+        mPointerVelocityControl.reset();
+
+        down = false;
+        hovering = false;
+    }
+
+    dispatchPointerSimple(when, policyFlags, down, hovering);
+}
+
+void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) {
+    abortPointerSimple(when, policyFlags);
+
+    mPointerVelocityControl.reset();
+}
+
+void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
+        bool down, bool hovering) {
+    int32_t metaState = getContext()->getGlobalMetaState();
+    int32_t displayId = mViewport.displayId;
+
+    if (mPointerController != nullptr) {
+        if (down || hovering) {
+            mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
+            mPointerController->clearSpots();
+            mPointerController->setButtonState(mCurrentRawState.buttonState);
+            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
+        } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
+            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+        }
+        displayId = mPointerController->getDisplayId();
+    }
+
+    if (mPointerSimple.down && !down) {
+        mPointerSimple.down = false;
+
+        // Send up.
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
+                AMOTION_EVENT_ACTION_UP, 0, 0, metaState, mLastRawState.buttonState,
+                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+                1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
+                mOrientedXPrecision, mOrientedYPrecision,
+                mPointerSimple.downTime, /* videoFrames */ {});
+        getListener()->notifyMotion(&args);
+    }
+
+    if (mPointerSimple.hovering && !hovering) {
+        mPointerSimple.hovering = false;
+
+        // Send hover exit.
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
+                AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastRawState.buttonState,
+                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+                1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
+                mOrientedXPrecision, mOrientedYPrecision,
+                mPointerSimple.downTime, /* videoFrames */ {});
+        getListener()->notifyMotion(&args);
+    }
+
+    if (down) {
+        if (!mPointerSimple.down) {
+            mPointerSimple.down = true;
+            mPointerSimple.downTime = when;
+
+            // Send down.
+            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                    mSource, displayId, policyFlags,
+                    AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState, mCurrentRawState.buttonState,
+                    MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+                    /* deviceTimestamp */ 0,
+                    1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+                    mOrientedXPrecision, mOrientedYPrecision,
+                    mPointerSimple.downTime, /* videoFrames */ {});
+            getListener()->notifyMotion(&args);
+        }
+
+        // Send move.
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
+                AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, mCurrentRawState.buttonState,
+                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+                1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+                mOrientedXPrecision, mOrientedYPrecision,
+                mPointerSimple.downTime, /* videoFrames */ {});
+        getListener()->notifyMotion(&args);
+    }
+
+    if (hovering) {
+        if (!mPointerSimple.hovering) {
+            mPointerSimple.hovering = true;
+
+            // Send hover enter.
+            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                    mSource, displayId, policyFlags,
+                    AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState,
+                    mCurrentRawState.buttonState, MotionClassification::NONE,
+                    AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+                    1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+                    mOrientedXPrecision, mOrientedYPrecision,
+                    mPointerSimple.downTime, /* videoFrames */ {});
+            getListener()->notifyMotion(&args);
+        }
+
+        // Send hover move.
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
+                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
+                mCurrentRawState.buttonState, MotionClassification::NONE,
+                AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+                1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+                mOrientedXPrecision, mOrientedYPrecision,
+                mPointerSimple.downTime, /* videoFrames */ {});
+        getListener()->notifyMotion(&args);
+    }
+
+    if (mCurrentRawState.rawVScroll || mCurrentRawState.rawHScroll) {
+        float vscroll = mCurrentRawState.rawVScroll;
+        float hscroll = mCurrentRawState.rawHScroll;
+        mWheelYVelocityControl.move(when, nullptr, &vscroll);
+        mWheelXVelocityControl.move(when, &hscroll, nullptr);
+
+        // Send scroll.
+        PointerCoords pointerCoords;
+        pointerCoords.copyFrom(mPointerSimple.currentCoords);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
+
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
+                AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, mCurrentRawState.buttonState,
+                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+                1, &mPointerSimple.currentProperties, &pointerCoords,
+                mOrientedXPrecision, mOrientedYPrecision,
+                mPointerSimple.downTime, /* videoFrames */ {});
+        getListener()->notifyMotion(&args);
+    }
+
+    // Save state.
+    if (down || hovering) {
+        mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
+        mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
+    } else {
+        mPointerSimple.reset();
+    }
+}
+
+void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) {
+    mPointerSimple.currentCoords.clear();
+    mPointerSimple.currentProperties.clear();
+
+    dispatchPointerSimple(when, policyFlags, false, false);
+}
+
+void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
+        int32_t action, int32_t actionButton, int32_t flags,
+        int32_t metaState, int32_t buttonState, int32_t edgeFlags, uint32_t deviceTimestamp,
+        const PointerProperties* properties, const PointerCoords* coords,
+        const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId,
+        float xPrecision, float yPrecision, nsecs_t downTime) {
+    PointerCoords pointerCoords[MAX_POINTERS];
+    PointerProperties pointerProperties[MAX_POINTERS];
+    uint32_t pointerCount = 0;
+    while (!idBits.isEmpty()) {
+        uint32_t id = idBits.clearFirstMarkedBit();
+        uint32_t index = idToIndex[id];
+        pointerProperties[pointerCount].copyFrom(properties[index]);
+        pointerCoords[pointerCount].copyFrom(coords[index]);
+
+        if (changedId >= 0 && id == uint32_t(changedId)) {
+            action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+        }
+
+        pointerCount += 1;
+    }
+
+    ALOG_ASSERT(pointerCount != 0);
+
+    if (changedId >= 0 && pointerCount == 1) {
+        // Replace initial down and final up action.
+        // We can compare the action without masking off the changed pointer index
+        // because we know the index is 0.
+        if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
+            action = AMOTION_EVENT_ACTION_DOWN;
+        } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
+            action = AMOTION_EVENT_ACTION_UP;
+        } else {
+            // Can't happen.
+            ALOG_ASSERT(false);
+        }
+    }
+    const int32_t displayId = getAssociatedDisplay().value_or(ADISPLAY_ID_NONE);
+    const int32_t deviceId = getDeviceId();
+    std::vector<TouchVideoFrame> frames = mDevice->getEventHub()->getVideoFrames(deviceId);
+    std::for_each(frames.begin(), frames.end(),
+            [this](TouchVideoFrame& frame) { frame.rotate(this->mSurfaceOrientation); });
+    NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId,
+            source, displayId, policyFlags,
+            action, actionButton, flags, metaState, buttonState, MotionClassification::NONE,
+            edgeFlags, deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
+            xPrecision, yPrecision, downTime, std::move(frames));
+    getListener()->notifyMotion(&args);
+}
+
+bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
+        const PointerCoords* inCoords, const uint32_t* inIdToIndex,
+        PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex,
+        BitSet32 idBits) const {
+    bool changed = false;
+    while (!idBits.isEmpty()) {
+        uint32_t id = idBits.clearFirstMarkedBit();
+        uint32_t inIndex = inIdToIndex[id];
+        uint32_t outIndex = outIdToIndex[id];
+
+        const PointerProperties& curInProperties = inProperties[inIndex];
+        const PointerCoords& curInCoords = inCoords[inIndex];
+        PointerProperties& curOutProperties = outProperties[outIndex];
+        PointerCoords& curOutCoords = outCoords[outIndex];
+
+        if (curInProperties != curOutProperties) {
+            curOutProperties.copyFrom(curInProperties);
+            changed = true;
+        }
+
+        if (curInCoords != curOutCoords) {
+            curOutCoords.copyFrom(curInCoords);
+            changed = true;
+        }
+    }
+    return changed;
+}
+
+void TouchInputMapper::fadePointer() {
+    if (mPointerController != nullptr) {
+        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+    }
+}
+
+void TouchInputMapper::cancelTouch(nsecs_t when) {
+    abortPointerUsage(when, 0 /*policyFlags*/);
+    abortTouches(when, 0 /* policyFlags*/);
+}
+
+bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
+    const float scaledX = x * mXScale;
+    const float scaledY = y * mYScale;
+    return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
+            && scaledX >= mPhysicalLeft && scaledX <= mPhysicalLeft + mPhysicalWidth
+            && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue
+            && scaledY >= mPhysicalTop && scaledY <= mPhysicalTop + mPhysicalHeight;
+}
+
+const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(int32_t x, int32_t y) {
+
+    for (const VirtualKey& virtualKey: mVirtualKeys) {
+#if DEBUG_VIRTUAL_KEYS
+        ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
+                "left=%d, top=%d, right=%d, bottom=%d",
+                x, y,
+                virtualKey.keyCode, virtualKey.scanCode,
+                virtualKey.hitLeft, virtualKey.hitTop,
+                virtualKey.hitRight, virtualKey.hitBottom);
+#endif
+
+        if (virtualKey.isHit(x, y)) {
+            return & virtualKey;
+        }
+    }
+
+    return nullptr;
+}
+
+void TouchInputMapper::assignPointerIds(const RawState* last, RawState* current) {
+    uint32_t currentPointerCount = current->rawPointerData.pointerCount;
+    uint32_t lastPointerCount = last->rawPointerData.pointerCount;
+
+    current->rawPointerData.clearIdBits();
+
+    if (currentPointerCount == 0) {
+        // No pointers to assign.
+        return;
+    }
+
+    if (lastPointerCount == 0) {
+        // All pointers are new.
+        for (uint32_t i = 0; i < currentPointerCount; i++) {
+            uint32_t id = i;
+            current->rawPointerData.pointers[i].id = id;
+            current->rawPointerData.idToIndex[id] = i;
+            current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(i));
+        }
+        return;
+    }
+
+    if (currentPointerCount == 1 && lastPointerCount == 1
+            && current->rawPointerData.pointers[0].toolType
+                    == last->rawPointerData.pointers[0].toolType) {
+        // Only one pointer and no change in count so it must have the same id as before.
+        uint32_t id = last->rawPointerData.pointers[0].id;
+        current->rawPointerData.pointers[0].id = id;
+        current->rawPointerData.idToIndex[id] = 0;
+        current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(0));
+        return;
+    }
+
+    // General case.
+    // We build a heap of squared euclidean distances between current and last pointers
+    // associated with the current and last pointer indices.  Then, we find the best
+    // match (by distance) for each current pointer.
+    // The pointers must have the same tool type but it is possible for them to
+    // transition from hovering to touching or vice-versa while retaining the same id.
+    PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
+
+    uint32_t heapSize = 0;
+    for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
+            currentPointerIndex++) {
+        for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
+                lastPointerIndex++) {
+            const RawPointerData::Pointer& currentPointer =
+                    current->rawPointerData.pointers[currentPointerIndex];
+            const RawPointerData::Pointer& lastPointer =
+                    last->rawPointerData.pointers[lastPointerIndex];
+            if (currentPointer.toolType == lastPointer.toolType) {
+                int64_t deltaX = currentPointer.x - lastPointer.x;
+                int64_t deltaY = currentPointer.y - lastPointer.y;
+
+                uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
+
+                // Insert new element into the heap (sift up).
+                heap[heapSize].currentPointerIndex = currentPointerIndex;
+                heap[heapSize].lastPointerIndex = lastPointerIndex;
+                heap[heapSize].distance = distance;
+                heapSize += 1;
+            }
+        }
+    }
+
+    // Heapify
+    for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
+        startIndex -= 1;
+        for (uint32_t parentIndex = startIndex; ;) {
+            uint32_t childIndex = parentIndex * 2 + 1;
+            if (childIndex >= heapSize) {
+                break;
+            }
+
+            if (childIndex + 1 < heapSize
+                    && heap[childIndex + 1].distance < heap[childIndex].distance) {
+                childIndex += 1;
+            }
+
+            if (heap[parentIndex].distance <= heap[childIndex].distance) {
+                break;
+            }
+
+            swap(heap[parentIndex], heap[childIndex]);
+            parentIndex = childIndex;
+        }
+    }
+
+#if DEBUG_POINTER_ASSIGNMENT
+    ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
+    for (size_t i = 0; i < heapSize; i++) {
+        ALOGD("  heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64,
+                i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
+                heap[i].distance);
+    }
+#endif
+
+    // Pull matches out by increasing order of distance.
+    // To avoid reassigning pointers that have already been matched, the loop keeps track
+    // of which last and current pointers have been matched using the matchedXXXBits variables.
+    // It also tracks the used pointer id bits.
+    BitSet32 matchedLastBits(0);
+    BitSet32 matchedCurrentBits(0);
+    BitSet32 usedIdBits(0);
+    bool first = true;
+    for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) {
+        while (heapSize > 0) {
+            if (first) {
+                // The first time through the loop, we just consume the root element of
+                // the heap (the one with smallest distance).
+                first = false;
+            } else {
+                // Previous iterations consumed the root element of the heap.
+                // Pop root element off of the heap (sift down).
+                heap[0] = heap[heapSize];
+                for (uint32_t parentIndex = 0; ;) {
+                    uint32_t childIndex = parentIndex * 2 + 1;
+                    if (childIndex >= heapSize) {
+                        break;
+                    }
+
+                    if (childIndex + 1 < heapSize
+                            && heap[childIndex + 1].distance < heap[childIndex].distance) {
+                        childIndex += 1;
+                    }
+
+                    if (heap[parentIndex].distance <= heap[childIndex].distance) {
+                        break;
+                    }
+
+                    swap(heap[parentIndex], heap[childIndex]);
+                    parentIndex = childIndex;
+                }
+
+#if DEBUG_POINTER_ASSIGNMENT
+                ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
+                for (size_t i = 0; i < heapSize; i++) {
+                    ALOGD("  heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64,
+                            i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
+                            heap[i].distance);
+                }
+#endif
+            }
+
+            heapSize -= 1;
+
+            uint32_t currentPointerIndex = heap[0].currentPointerIndex;
+            if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
+
+            uint32_t lastPointerIndex = heap[0].lastPointerIndex;
+            if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
+
+            matchedCurrentBits.markBit(currentPointerIndex);
+            matchedLastBits.markBit(lastPointerIndex);
+
+            uint32_t id = last->rawPointerData.pointers[lastPointerIndex].id;
+            current->rawPointerData.pointers[currentPointerIndex].id = id;
+            current->rawPointerData.idToIndex[id] = currentPointerIndex;
+            current->rawPointerData.markIdBit(id,
+                    current->rawPointerData.isHovering(currentPointerIndex));
+            usedIdBits.markBit(id);
+
+#if DEBUG_POINTER_ASSIGNMENT
+            ALOGD("assignPointerIds - matched: cur=%" PRIu32 ", last=%" PRIu32
+                    ", id=%" PRIu32 ", distance=%" PRIu64,
+                    lastPointerIndex, currentPointerIndex, id, heap[0].distance);
+#endif
+            break;
+        }
+    }
+
+    // Assign fresh ids to pointers that were not matched in the process.
+    for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) {
+        uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();
+        uint32_t id = usedIdBits.markFirstUnmarkedBit();
+
+        current->rawPointerData.pointers[currentPointerIndex].id = id;
+        current->rawPointerData.idToIndex[id] = currentPointerIndex;
+        current->rawPointerData.markIdBit(id,
+                current->rawPointerData.isHovering(currentPointerIndex));
+
+#if DEBUG_POINTER_ASSIGNMENT
+        ALOGD("assignPointerIds - assigned: cur=%" PRIu32 ", id=%" PRIu32, currentPointerIndex, id);
+#endif
+    }
+}
+
+int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
+    if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
+        return AKEY_STATE_VIRTUAL;
+    }
+
+    for (const VirtualKey& virtualKey : mVirtualKeys) {
+        if (virtualKey.keyCode == keyCode) {
+            return AKEY_STATE_UP;
+        }
+    }
+
+    return AKEY_STATE_UNKNOWN;
+}
+
+int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+    if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) {
+        return AKEY_STATE_VIRTUAL;
+    }
+
+    for (const VirtualKey& virtualKey : mVirtualKeys) {
+        if (virtualKey.scanCode == scanCode) {
+            return AKEY_STATE_UP;
+        }
+    }
+
+    return AKEY_STATE_UNKNOWN;
+}
+
+bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+        const int32_t* keyCodes, uint8_t* outFlags) {
+    for (const VirtualKey& virtualKey : mVirtualKeys) {
+        for (size_t i = 0; i < numCodes; i++) {
+            if (virtualKey.keyCode == keyCodes[i]) {
+                outFlags[i] = 1;
+            }
+        }
+    }
+
+    return true;
+}
+
+std::optional<int32_t> TouchInputMapper::getAssociatedDisplay() {
+    if (mParameters.hasAssociatedDisplay) {
+        if (mDeviceMode == DEVICE_MODE_POINTER) {
+            return std::make_optional(mPointerController->getDisplayId());
+        } else {
+            return std::make_optional(mViewport.displayId);
+        }
+    }
+    return std::nullopt;
+}
+
+// --- SingleTouchInputMapper ---
+
+SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
+        TouchInputMapper(device) {
+}
+
+SingleTouchInputMapper::~SingleTouchInputMapper() {
+}
+
+void SingleTouchInputMapper::reset(nsecs_t when) {
+    mSingleTouchMotionAccumulator.reset(getDevice());
+
+    TouchInputMapper::reset(when);
+}
+
+void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
+    TouchInputMapper::process(rawEvent);
+
+    mSingleTouchMotionAccumulator.process(rawEvent);
+}
+
+void SingleTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
+    if (mTouchButtonAccumulator.isToolActive()) {
+        outState->rawPointerData.pointerCount = 1;
+        outState->rawPointerData.idToIndex[0] = 0;
+
+        bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
+                && (mTouchButtonAccumulator.isHovering()
+                        || (mRawPointerAxes.pressure.valid
+                                && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
+        outState->rawPointerData.markIdBit(0, isHovering);
+
+        RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[0];
+        outPointer.id = 0;
+        outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
+        outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
+        outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
+        outPointer.touchMajor = 0;
+        outPointer.touchMinor = 0;
+        outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
+        outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
+        outPointer.orientation = 0;
+        outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
+        outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX();
+        outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY();
+        outPointer.toolType = mTouchButtonAccumulator.getToolType();
+        if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+            outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+        }
+        outPointer.isHovering = isHovering;
+    }
+}
+
+void SingleTouchInputMapper::configureRawPointerAxes() {
+    TouchInputMapper::configureRawPointerAxes();
+
+    getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x);
+    getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y);
+    getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure);
+    getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor);
+    getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance);
+    getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX);
+    getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
+}
+
+bool SingleTouchInputMapper::hasStylus() const {
+    return mTouchButtonAccumulator.hasStylus();
+}
+
+
+// --- MultiTouchInputMapper ---
+
+MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
+        TouchInputMapper(device) {
+}
+
+MultiTouchInputMapper::~MultiTouchInputMapper() {
+}
+
+void MultiTouchInputMapper::reset(nsecs_t when) {
+    mMultiTouchMotionAccumulator.reset(getDevice());
+
+    mPointerIdBits.clear();
+
+    TouchInputMapper::reset(when);
+}
+
+void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
+    TouchInputMapper::process(rawEvent);
+
+    mMultiTouchMotionAccumulator.process(rawEvent);
+}
+
+void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
+    size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
+    size_t outCount = 0;
+    BitSet32 newPointerIdBits;
+    mHavePointerIds = true;
+
+    for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
+        const MultiTouchMotionAccumulator::Slot* inSlot =
+                mMultiTouchMotionAccumulator.getSlot(inIndex);
+        if (!inSlot->isInUse()) {
+            continue;
+        }
+
+        if (outCount >= MAX_POINTERS) {
+#if DEBUG_POINTERS
+            ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
+                    "ignoring the rest.",
+                    getDeviceName().c_str(), MAX_POINTERS);
+#endif
+            break; // too many fingers!
+        }
+
+        RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount];
+        outPointer.x = inSlot->getX();
+        outPointer.y = inSlot->getY();
+        outPointer.pressure = inSlot->getPressure();
+        outPointer.touchMajor = inSlot->getTouchMajor();
+        outPointer.touchMinor = inSlot->getTouchMinor();
+        outPointer.toolMajor = inSlot->getToolMajor();
+        outPointer.toolMinor = inSlot->getToolMinor();
+        outPointer.orientation = inSlot->getOrientation();
+        outPointer.distance = inSlot->getDistance();
+        outPointer.tiltX = 0;
+        outPointer.tiltY = 0;
+
+        outPointer.toolType = inSlot->getToolType();
+        if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+            outPointer.toolType = mTouchButtonAccumulator.getToolType();
+            if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+                outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+            }
+        }
+
+        bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
+                && (mTouchButtonAccumulator.isHovering()
+                        || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
+        outPointer.isHovering = isHovering;
+
+        // Assign pointer id using tracking id if available.
+        if (mHavePointerIds) {
+            int32_t trackingId = inSlot->getTrackingId();
+            int32_t id = -1;
+            if (trackingId >= 0) {
+                for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
+                    uint32_t n = idBits.clearFirstMarkedBit();
+                    if (mPointerTrackingIdMap[n] == trackingId) {
+                        id = n;
+                    }
+                }
+
+                if (id < 0 && !mPointerIdBits.isFull()) {
+                    id = mPointerIdBits.markFirstUnmarkedBit();
+                    mPointerTrackingIdMap[id] = trackingId;
+                }
+            }
+            if (id < 0) {
+                mHavePointerIds = false;
+                outState->rawPointerData.clearIdBits();
+                newPointerIdBits.clear();
+            } else {
+                outPointer.id = id;
+                outState->rawPointerData.idToIndex[id] = outCount;
+                outState->rawPointerData.markIdBit(id, isHovering);
+                newPointerIdBits.markBit(id);
+            }
+        }
+        outCount += 1;
+    }
+
+    outState->deviceTimestamp = mMultiTouchMotionAccumulator.getDeviceTimestamp();
+    outState->rawPointerData.pointerCount = outCount;
+    mPointerIdBits = newPointerIdBits;
+
+    mMultiTouchMotionAccumulator.finishSync();
+}
+
+void MultiTouchInputMapper::configureRawPointerAxes() {
+    TouchInputMapper::configureRawPointerAxes();
+
+    getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);
+    getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);
+    getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);
+    getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor);
+    getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor);
+    getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor);
+    getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation);
+    getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure);
+    getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance);
+    getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId);
+    getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot);
+
+    if (mRawPointerAxes.trackingId.valid
+            && mRawPointerAxes.slot.valid
+            && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
+        size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
+        if (slotCount > MAX_SLOTS) {
+            ALOGW("MultiTouch Device %s reported %zu slots but the framework "
+                    "only supports a maximum of %zu slots at this time.",
+                    getDeviceName().c_str(), slotCount, MAX_SLOTS);
+            slotCount = MAX_SLOTS;
+        }
+        mMultiTouchMotionAccumulator.configure(getDevice(),
+                slotCount, true /*usingSlotsProtocol*/);
+    } else {
+        mMultiTouchMotionAccumulator.configure(getDevice(),
+                MAX_POINTERS, false /*usingSlotsProtocol*/);
+    }
+}
+
+bool MultiTouchInputMapper::hasStylus() const {
+    return mMultiTouchMotionAccumulator.hasStylus()
+            || mTouchButtonAccumulator.hasStylus();
+}
+
+// --- ExternalStylusInputMapper
+
+ExternalStylusInputMapper::ExternalStylusInputMapper(InputDevice* device) :
+    InputMapper(device) {
+
+}
+
+uint32_t ExternalStylusInputMapper::getSources() {
+    return AINPUT_SOURCE_STYLUS;
+}
+
+void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+    InputMapper::populateDeviceInfo(info);
+    info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS,
+            0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
+}
+
+void ExternalStylusInputMapper::dump(std::string& dump) {
+    dump += INDENT2 "External Stylus Input Mapper:\n";
+    dump += INDENT3 "Raw Stylus Axes:\n";
+    dumpRawAbsoluteAxisInfo(dump, mRawPressureAxis, "Pressure");
+    dump += INDENT3 "Stylus State:\n";
+    dumpStylusState(dump, mStylusState);
+}
+
+void ExternalStylusInputMapper::configure(nsecs_t when,
+        const InputReaderConfiguration* config, uint32_t changes) {
+    getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPressureAxis);
+    mTouchButtonAccumulator.configure(getDevice());
+}
+
+void ExternalStylusInputMapper::reset(nsecs_t when) {
+    InputDevice* device = getDevice();
+    mSingleTouchMotionAccumulator.reset(device);
+    mTouchButtonAccumulator.reset(device);
+    InputMapper::reset(when);
+}
+
+void ExternalStylusInputMapper::process(const RawEvent* rawEvent) {
+    mSingleTouchMotionAccumulator.process(rawEvent);
+    mTouchButtonAccumulator.process(rawEvent);
+
+    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
+        sync(rawEvent->when);
+    }
+}
+
+void ExternalStylusInputMapper::sync(nsecs_t when) {
+    mStylusState.clear();
+
+    mStylusState.when = when;
+
+    mStylusState.toolType = mTouchButtonAccumulator.getToolType();
+    if (mStylusState.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+        mStylusState.toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
+    }
+
+    int32_t pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
+    if (mRawPressureAxis.valid) {
+        mStylusState.pressure = float(pressure) / mRawPressureAxis.maxValue;
+    } else if (mTouchButtonAccumulator.isToolActive()) {
+        mStylusState.pressure = 1.0f;
+    } else {
+        mStylusState.pressure = 0.0f;
+    }
+
+    mStylusState.buttons = mTouchButtonAccumulator.getButtonState();
+
+    mContext->dispatchExternalStylusState(mStylusState);
+}
+
+
+// --- JoystickInputMapper ---
+
+JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
+        InputMapper(device) {
+}
+
+JoystickInputMapper::~JoystickInputMapper() {
+}
+
+uint32_t JoystickInputMapper::getSources() {
+    return AINPUT_SOURCE_JOYSTICK;
+}
+
+void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+    InputMapper::populateDeviceInfo(info);
+
+    for (size_t i = 0; i < mAxes.size(); i++) {
+        const Axis& axis = mAxes.valueAt(i);
+        addMotionRange(axis.axisInfo.axis, axis, info);
+
+        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
+            addMotionRange(axis.axisInfo.highAxis, axis, info);
+
+        }
+    }
+}
+
+void JoystickInputMapper::addMotionRange(int32_t axisId, const Axis& axis,
+        InputDeviceInfo* info) {
+    info->addMotionRange(axisId, AINPUT_SOURCE_JOYSTICK,
+            axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
+    /* In order to ease the transition for developers from using the old axes
+     * to the newer, more semantically correct axes, we'll continue to register
+     * the old axes as duplicates of their corresponding new ones.  */
+    int32_t compatAxis = getCompatAxis(axisId);
+    if (compatAxis >= 0) {
+        info->addMotionRange(compatAxis, AINPUT_SOURCE_JOYSTICK,
+                axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
+    }
+}
+
+/* A mapping from axes the joystick actually has to the axes that should be
+ * artificially created for compatibility purposes.
+ * Returns -1 if no compatibility axis is needed. */
+int32_t JoystickInputMapper::getCompatAxis(int32_t axis) {
+    switch(axis) {
+    case AMOTION_EVENT_AXIS_LTRIGGER:
+        return AMOTION_EVENT_AXIS_BRAKE;
+    case AMOTION_EVENT_AXIS_RTRIGGER:
+        return AMOTION_EVENT_AXIS_GAS;
+    }
+    return -1;
+}
+
+void JoystickInputMapper::dump(std::string& dump) {
+    dump += INDENT2 "Joystick Input Mapper:\n";
+
+    dump += INDENT3 "Axes:\n";
+    size_t numAxes = mAxes.size();
+    for (size_t i = 0; i < numAxes; i++) {
+        const Axis& axis = mAxes.valueAt(i);
+        const char* label = getAxisLabel(axis.axisInfo.axis);
+        if (label) {
+            dump += StringPrintf(INDENT4 "%s", label);
+        } else {
+            dump += StringPrintf(INDENT4 "%d", axis.axisInfo.axis);
+        }
+        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
+            label = getAxisLabel(axis.axisInfo.highAxis);
+            if (label) {
+                dump += StringPrintf(" / %s (split at %d)", label, axis.axisInfo.splitValue);
+            } else {
+                dump += StringPrintf(" / %d (split at %d)", axis.axisInfo.highAxis,
+                        axis.axisInfo.splitValue);
+            }
+        } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
+            dump += " (invert)";
+        }
+
+        dump += StringPrintf(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f, resolution=%0.5f\n",
+                axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
+        dump += StringPrintf(INDENT4 "  scale=%0.5f, offset=%0.5f, "
+                "highScale=%0.5f, highOffset=%0.5f\n",
+                axis.scale, axis.offset, axis.highScale, axis.highOffset);
+        dump += StringPrintf(INDENT4 "  rawAxis=%d, rawMin=%d, rawMax=%d, "
+                "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
+                mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
+                axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution);
+    }
+}
+
+void JoystickInputMapper::configure(nsecs_t when,
+        const InputReaderConfiguration* config, uint32_t changes) {
+    InputMapper::configure(when, config, changes);
+
+    if (!changes) { // first time only
+        // Collect all axes.
+        for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
+            if (!(getAbsAxisUsage(abs, getDevice()->getClasses())
+                    & INPUT_DEVICE_CLASS_JOYSTICK)) {
+                continue; // axis must be claimed by a different device
+            }
+
+            RawAbsoluteAxisInfo rawAxisInfo;
+            getAbsoluteAxisInfo(abs, &rawAxisInfo);
+            if (rawAxisInfo.valid) {
+                // Map axis.
+                AxisInfo axisInfo;
+                bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
+                if (!explicitlyMapped) {
+                    // Axis is not explicitly mapped, will choose a generic axis later.
+                    axisInfo.mode = AxisInfo::MODE_NORMAL;
+                    axisInfo.axis = -1;
+                }
+
+                // Apply flat override.
+                int32_t rawFlat = axisInfo.flatOverride < 0
+                        ? rawAxisInfo.flat : axisInfo.flatOverride;
+
+                // Calculate scaling factors and limits.
+                Axis axis;
+                if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
+                    float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
+                    float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
+                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
+                            scale, 0.0f, highScale, 0.0f,
+                            0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
+                            rawAxisInfo.resolution * scale);
+                } else if (isCenteredAxis(axisInfo.axis)) {
+                    float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
+                    float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
+                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
+                            scale, offset, scale, offset,
+                            -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
+                            rawAxisInfo.resolution * scale);
+                } else {
+                    float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
+                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
+                            scale, 0.0f, scale, 0.0f,
+                            0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
+                            rawAxisInfo.resolution * scale);
+                }
+
+                // To eliminate noise while the joystick is at rest, filter out small variations
+                // in axis values up front.
+                axis.filter = axis.fuzz ? axis.fuzz : axis.flat * 0.25f;
+
+                mAxes.add(abs, axis);
+            }
+        }
+
+        // If there are too many axes, start dropping them.
+        // Prefer to keep explicitly mapped axes.
+        if (mAxes.size() > PointerCoords::MAX_AXES) {
+            ALOGI("Joystick '%s' has %zu axes but the framework only supports a maximum of %d.",
+                    getDeviceName().c_str(), mAxes.size(), PointerCoords::MAX_AXES);
+            pruneAxes(true);
+            pruneAxes(false);
+        }
+
+        // Assign generic axis ids to remaining axes.
+        int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
+        size_t numAxes = mAxes.size();
+        for (size_t i = 0; i < numAxes; i++) {
+            Axis& axis = mAxes.editValueAt(i);
+            if (axis.axisInfo.axis < 0) {
+                while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
+                        && haveAxis(nextGenericAxisId)) {
+                    nextGenericAxisId += 1;
+                }
+
+                if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
+                    axis.axisInfo.axis = nextGenericAxisId;
+                    nextGenericAxisId += 1;
+                } else {
+                    ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
+                            "have already been assigned to other axes.",
+                            getDeviceName().c_str(), mAxes.keyAt(i));
+                    mAxes.removeItemsAt(i--);
+                    numAxes -= 1;
+                }
+            }
+        }
+    }
+}
+
+bool JoystickInputMapper::haveAxis(int32_t axisId) {
+    size_t numAxes = mAxes.size();
+    for (size_t i = 0; i < numAxes; i++) {
+        const Axis& axis = mAxes.valueAt(i);
+        if (axis.axisInfo.axis == axisId
+                || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
+                        && axis.axisInfo.highAxis == axisId)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
+    size_t i = mAxes.size();
+    while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
+        if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
+            continue;
+        }
+        ALOGI("Discarding joystick '%s' axis %d because there are too many axes.",
+                getDeviceName().c_str(), mAxes.keyAt(i));
+        mAxes.removeItemsAt(i);
+    }
+}
+
+bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
+    switch (axis) {
+    case AMOTION_EVENT_AXIS_X:
+    case AMOTION_EVENT_AXIS_Y:
+    case AMOTION_EVENT_AXIS_Z:
+    case AMOTION_EVENT_AXIS_RX:
+    case AMOTION_EVENT_AXIS_RY:
+    case AMOTION_EVENT_AXIS_RZ:
+    case AMOTION_EVENT_AXIS_HAT_X:
+    case AMOTION_EVENT_AXIS_HAT_Y:
+    case AMOTION_EVENT_AXIS_ORIENTATION:
+    case AMOTION_EVENT_AXIS_RUDDER:
+    case AMOTION_EVENT_AXIS_WHEEL:
+        return true;
+    default:
+        return false;
+    }
+}
+
+void JoystickInputMapper::reset(nsecs_t when) {
+    // Recenter all axes.
+    size_t numAxes = mAxes.size();
+    for (size_t i = 0; i < numAxes; i++) {
+        Axis& axis = mAxes.editValueAt(i);
+        axis.resetValue();
+    }
+
+    InputMapper::reset(when);
+}
+
+void JoystickInputMapper::process(const RawEvent* rawEvent) {
+    switch (rawEvent->type) {
+    case EV_ABS: {
+        ssize_t index = mAxes.indexOfKey(rawEvent->code);
+        if (index >= 0) {
+            Axis& axis = mAxes.editValueAt(index);
+            float newValue, highNewValue;
+            switch (axis.axisInfo.mode) {
+            case AxisInfo::MODE_INVERT:
+                newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
+                        * axis.scale + axis.offset;
+                highNewValue = 0.0f;
+                break;
+            case AxisInfo::MODE_SPLIT:
+                if (rawEvent->value < axis.axisInfo.splitValue) {
+                    newValue = (axis.axisInfo.splitValue - rawEvent->value)
+                            * axis.scale + axis.offset;
+                    highNewValue = 0.0f;
+                } else if (rawEvent->value > axis.axisInfo.splitValue) {
+                    newValue = 0.0f;
+                    highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
+                            * axis.highScale + axis.highOffset;
+                } else {
+                    newValue = 0.0f;
+                    highNewValue = 0.0f;
+                }
+                break;
+            default:
+                newValue = rawEvent->value * axis.scale + axis.offset;
+                highNewValue = 0.0f;
+                break;
+            }
+            axis.newValue = newValue;
+            axis.highNewValue = highNewValue;
+        }
+        break;
+    }
+
+    case EV_SYN:
+        switch (rawEvent->code) {
+        case SYN_REPORT:
+            sync(rawEvent->when, false /*force*/);
+            break;
+        }
+        break;
+    }
+}
+
+void JoystickInputMapper::sync(nsecs_t when, bool force) {
+    if (!filterAxes(force)) {
+        return;
+    }
+
+    int32_t metaState = mContext->getGlobalMetaState();
+    int32_t buttonState = 0;
+
+    PointerProperties pointerProperties;
+    pointerProperties.clear();
+    pointerProperties.id = 0;
+    pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+
+    PointerCoords pointerCoords;
+    pointerCoords.clear();
+
+    size_t numAxes = mAxes.size();
+    for (size_t i = 0; i < numAxes; i++) {
+        const Axis& axis = mAxes.valueAt(i);
+        setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.axis, axis.currentValue);
+        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
+            setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.highAxis,
+                    axis.highCurrentValue);
+        }
+    }
+
+    // Moving a joystick axis should not wake the device because joysticks can
+    // be fairly noisy even when not in use.  On the other hand, pushing a gamepad
+    // button will likely wake the device.
+    // TODO: Use the input device configuration to control this behavior more finely.
+    uint32_t policyFlags = 0;
+
+    NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+            AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE, policyFlags,
+            AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, MotionClassification::NONE,
+            AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1,
+            &pointerProperties, &pointerCoords, 0, 0, 0, /* videoFrames */ {});
+    getListener()->notifyMotion(&args);
+}
+
+void JoystickInputMapper::setPointerCoordsAxisValue(PointerCoords* pointerCoords,
+        int32_t axis, float value) {
+    pointerCoords->setAxisValue(axis, value);
+    /* In order to ease the transition for developers from using the old axes
+     * to the newer, more semantically correct axes, we'll continue to produce
+     * values for the old axes as mirrors of the value of their corresponding
+     * new axes. */
+    int32_t compatAxis = getCompatAxis(axis);
+    if (compatAxis >= 0) {
+        pointerCoords->setAxisValue(compatAxis, value);
+    }
+}
+
+bool JoystickInputMapper::filterAxes(bool force) {
+    bool atLeastOneSignificantChange = force;
+    size_t numAxes = mAxes.size();
+    for (size_t i = 0; i < numAxes; i++) {
+        Axis& axis = mAxes.editValueAt(i);
+        if (force || hasValueChangedSignificantly(axis.filter,
+                axis.newValue, axis.currentValue, axis.min, axis.max)) {
+            axis.currentValue = axis.newValue;
+            atLeastOneSignificantChange = true;
+        }
+        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
+            if (force || hasValueChangedSignificantly(axis.filter,
+                    axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
+                axis.highCurrentValue = axis.highNewValue;
+                atLeastOneSignificantChange = true;
+            }
+        }
+    }
+    return atLeastOneSignificantChange;
+}
+
+bool JoystickInputMapper::hasValueChangedSignificantly(
+        float filter, float newValue, float currentValue, float min, float max) {
+    if (newValue != currentValue) {
+        // Filter out small changes in value unless the value is converging on the axis
+        // bounds or center point.  This is intended to reduce the amount of information
+        // sent to applications by particularly noisy joysticks (such as PS3).
+        if (fabs(newValue - currentValue) > filter
+                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
+                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
+                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
+        float filter, float newValue, float currentValue, float thresholdValue) {
+    float newDistance = fabs(newValue - thresholdValue);
+    if (newDistance < filter) {
+        float oldDistance = fabs(currentValue - thresholdValue);
+        if (newDistance < oldDistance) {
+            return true;
+        }
+    }
+    return false;
+}
+
+} // namespace android
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
new file mode 100644
index 0000000..9777779
--- /dev/null
+++ b/services/inputflinger/InputReader.h
@@ -0,0 +1,1809 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef _UI_INPUT_READER_H
+#define _UI_INPUT_READER_H
+
+#include "EventHub.h"
+#include "PointerControllerInterface.h"
+#include "InputListener.h"
+#include "InputReaderBase.h"
+
+#include <input/DisplayViewport.h>
+#include <input/Input.h>
+#include <input/VelocityControl.h>
+#include <input/VelocityTracker.h>
+#include <ui/DisplayInfo.h>
+#include <utils/KeyedVector.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <utils/Timers.h>
+#include <utils/BitSet.h>
+
+#include <optional>
+#include <stddef.h>
+#include <unistd.h>
+#include <vector>
+
+namespace android {
+
+class InputDevice;
+class InputMapper;
+
+
+struct StylusState {
+    /* Time the stylus event was received. */
+    nsecs_t when;
+    /* Pressure as reported by the stylus, normalized to the range [0, 1.0]. */
+    float pressure;
+    /* The state of the stylus buttons as a bitfield (e.g. AMOTION_EVENT_BUTTON_SECONDARY). */
+    uint32_t buttons;
+    /* Which tool type the stylus is currently using (e.g. AMOTION_EVENT_TOOL_TYPE_ERASER). */
+    int32_t toolType;
+
+    void copyFrom(const StylusState& other) {
+        when = other.when;
+        pressure = other.pressure;
+        buttons = other.buttons;
+        toolType = other.toolType;
+    }
+
+    void clear() {
+        when = LLONG_MAX;
+        pressure = 0.f;
+        buttons = 0;
+        toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+    }
+};
+
+
+/* Internal interface used by individual input devices to access global input device state
+ * and parameters maintained by the input reader.
+ */
+class InputReaderContext {
+public:
+    InputReaderContext() { }
+    virtual ~InputReaderContext() { }
+
+    virtual void updateGlobalMetaState() = 0;
+    virtual int32_t getGlobalMetaState() = 0;
+
+    virtual void disableVirtualKeysUntil(nsecs_t time) = 0;
+    virtual bool shouldDropVirtualKey(nsecs_t now,
+            InputDevice* device, int32_t keyCode, int32_t scanCode) = 0;
+
+    virtual void fadePointer() = 0;
+
+    virtual void requestTimeoutAtTime(nsecs_t when) = 0;
+    virtual int32_t bumpGeneration() = 0;
+
+    virtual void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) = 0;
+    virtual void dispatchExternalStylusState(const StylusState& outState) = 0;
+
+    virtual InputReaderPolicyInterface* getPolicy() = 0;
+    virtual InputListenerInterface* getListener() = 0;
+    virtual EventHubInterface* getEventHub() = 0;
+
+    virtual uint32_t getNextSequenceNum() = 0;
+};
+
+
+/* The input reader reads raw event data from the event hub and processes it into input events
+ * that it sends to the input listener.  Some functions of the input reader, such as early
+ * event filtering in low power states, are controlled by a separate policy object.
+ *
+ * The InputReader owns a collection of InputMappers.  Most of the work it does happens
+ * on the input reader thread but the InputReader can receive queries from other system
+ * components running on arbitrary threads.  To keep things manageable, the InputReader
+ * uses a single Mutex to guard its state.  The Mutex may be held while calling into the
+ * EventHub or the InputReaderPolicy but it is never held while calling into the
+ * InputListener.
+ */
+class InputReader : public InputReaderInterface {
+public:
+    InputReader(const sp<EventHubInterface>& eventHub,
+            const sp<InputReaderPolicyInterface>& policy,
+            const sp<InputListenerInterface>& listener);
+    virtual ~InputReader();
+
+    virtual void dump(std::string& dump);
+    virtual void monitor();
+
+    virtual void loopOnce();
+
+    virtual void getInputDevices(std::vector<InputDeviceInfo>& outInputDevices);
+
+    virtual bool isInputDeviceEnabled(int32_t deviceId);
+
+    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
+            int32_t scanCode);
+    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
+            int32_t keyCode);
+    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
+            int32_t sw);
+
+    virtual void toggleCapsLockState(int32_t deviceId);
+
+    virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
+            size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
+
+    virtual void requestRefreshConfiguration(uint32_t changes);
+
+    virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
+            ssize_t repeat, int32_t token);
+    virtual void cancelVibrate(int32_t deviceId, int32_t token);
+
+    virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId);
+protected:
+    // These members are protected so they can be instrumented by test cases.
+    virtual InputDevice* createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
+            const InputDeviceIdentifier& identifier, uint32_t classes);
+
+    class ContextImpl : public InputReaderContext {
+        InputReader* mReader;
+
+    public:
+        explicit ContextImpl(InputReader* reader);
+
+        virtual void updateGlobalMetaState();
+        virtual int32_t getGlobalMetaState();
+        virtual void disableVirtualKeysUntil(nsecs_t time);
+        virtual bool shouldDropVirtualKey(nsecs_t now,
+                InputDevice* device, int32_t keyCode, int32_t scanCode);
+        virtual void fadePointer();
+        virtual void requestTimeoutAtTime(nsecs_t when);
+        virtual int32_t bumpGeneration();
+        virtual void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices);
+        virtual void dispatchExternalStylusState(const StylusState& outState);
+        virtual InputReaderPolicyInterface* getPolicy();
+        virtual InputListenerInterface* getListener();
+        virtual EventHubInterface* getEventHub();
+        virtual uint32_t getNextSequenceNum();
+    } mContext;
+
+    friend class ContextImpl;
+
+private:
+    Mutex mLock;
+
+    Condition mReaderIsAliveCondition;
+
+    sp<EventHubInterface> mEventHub;
+    sp<InputReaderPolicyInterface> mPolicy;
+    sp<QueuedInputListener> mQueuedListener;
+
+    InputReaderConfiguration mConfig;
+
+    // used by InputReaderContext::getNextSequenceNum() as a counter for event sequence numbers
+    uint32_t mNextSequenceNum;
+
+    // The event queue.
+    static const int EVENT_BUFFER_SIZE = 256;
+    RawEvent mEventBuffer[EVENT_BUFFER_SIZE];
+
+    KeyedVector<int32_t, InputDevice*> mDevices;
+
+    // low-level input event decoding and device management
+    void processEventsLocked(const RawEvent* rawEvents, size_t count);
+
+    void addDeviceLocked(nsecs_t when, int32_t deviceId);
+    void removeDeviceLocked(nsecs_t when, int32_t deviceId);
+    void processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents, size_t count);
+    void timeoutExpiredLocked(nsecs_t when);
+
+    void handleConfigurationChangedLocked(nsecs_t when);
+
+    int32_t mGlobalMetaState;
+    void updateGlobalMetaStateLocked();
+    int32_t getGlobalMetaStateLocked();
+
+    void notifyExternalStylusPresenceChanged();
+    void getExternalStylusDevicesLocked(std::vector<InputDeviceInfo>& outDevices);
+    void dispatchExternalStylusState(const StylusState& state);
+
+    void fadePointerLocked();
+
+    int32_t mGeneration;
+    int32_t bumpGenerationLocked();
+
+    void getInputDevicesLocked(std::vector<InputDeviceInfo>& outInputDevices);
+
+    nsecs_t mDisableVirtualKeysTimeout;
+    void disableVirtualKeysUntilLocked(nsecs_t time);
+    bool shouldDropVirtualKeyLocked(nsecs_t now,
+            InputDevice* device, int32_t keyCode, int32_t scanCode);
+
+    nsecs_t mNextTimeout;
+    void requestTimeoutAtTimeLocked(nsecs_t when);
+
+    uint32_t mConfigurationChangesToRefresh;
+    void refreshConfigurationLocked(uint32_t changes);
+
+    // state queries
+    typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code);
+    int32_t getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
+            GetStateFunc getStateFunc);
+    bool markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags);
+};
+
+
+/* Represents the state of a single input device. */
+class InputDevice {
+public:
+    InputDevice(InputReaderContext* context, int32_t id, int32_t generation, int32_t
+            controllerNumber, const InputDeviceIdentifier& identifier, uint32_t classes);
+    ~InputDevice();
+
+    inline InputReaderContext* getContext() { return mContext; }
+    inline int32_t getId() const { return mId; }
+    inline int32_t getControllerNumber() const { return mControllerNumber; }
+    inline int32_t getGeneration() const { return mGeneration; }
+    inline const std::string getName() const { return mIdentifier.name; }
+    inline const std::string getDescriptor() { return mIdentifier.descriptor; }
+    inline uint32_t getClasses() const { return mClasses; }
+    inline uint32_t getSources() const { return mSources; }
+
+    inline bool isExternal() { return mIsExternal; }
+    inline void setExternal(bool external) { mIsExternal = external; }
+    inline std::optional<uint8_t> getAssociatedDisplayPort() const {
+        return mAssociatedDisplayPort;
+    }
+
+    inline void setMic(bool hasMic) { mHasMic = hasMic; }
+    inline bool hasMic() const { return mHasMic; }
+
+    inline bool isIgnored() { return mMappers.empty(); }
+
+    bool isEnabled();
+    void setEnabled(bool enabled, nsecs_t when);
+
+    void dump(std::string& dump);
+    void addMapper(InputMapper* mapper);
+    void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+    void reset(nsecs_t when);
+    void process(const RawEvent* rawEvents, size_t count);
+    void timeoutExpired(nsecs_t when);
+    void updateExternalStylusState(const StylusState& state);
+
+    void getDeviceInfo(InputDeviceInfo* outDeviceInfo);
+    int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
+    int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+    int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
+    bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags);
+    void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, int32_t token);
+    void cancelVibrate(int32_t token);
+    void cancelTouch(nsecs_t when);
+
+    int32_t getMetaState();
+    void updateMetaState(int32_t keyCode);
+
+    void fadePointer();
+
+    void bumpGeneration();
+
+    void notifyReset(nsecs_t when);
+
+    inline const PropertyMap& getConfiguration() { return mConfiguration; }
+    inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
+
+    bool hasKey(int32_t code) {
+        return getEventHub()->hasScanCode(mId, code);
+    }
+
+    bool hasAbsoluteAxis(int32_t code) {
+        RawAbsoluteAxisInfo info;
+        getEventHub()->getAbsoluteAxisInfo(mId, code, &info);
+        return info.valid;
+    }
+
+    bool isKeyPressed(int32_t code) {
+        return getEventHub()->getScanCodeState(mId, code) == AKEY_STATE_DOWN;
+    }
+
+    int32_t getAbsoluteAxisValue(int32_t code) {
+        int32_t value;
+        getEventHub()->getAbsoluteAxisValue(mId, code, &value);
+        return value;
+    }
+
+    std::optional<int32_t> getAssociatedDisplay();
+private:
+    InputReaderContext* mContext;
+    int32_t mId;
+    int32_t mGeneration;
+    int32_t mControllerNumber;
+    InputDeviceIdentifier mIdentifier;
+    std::string mAlias;
+    uint32_t mClasses;
+
+    std::vector<InputMapper*> mMappers;
+
+    uint32_t mSources;
+    bool mIsExternal;
+    std::optional<uint8_t> mAssociatedDisplayPort;
+    bool mHasMic;
+    bool mDropUntilNextSync;
+
+    typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
+    int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
+
+    PropertyMap mConfiguration;
+};
+
+
+/* Keeps track of the state of mouse or touch pad buttons. */
+class CursorButtonAccumulator {
+public:
+    CursorButtonAccumulator();
+    void reset(InputDevice* device);
+
+    void process(const RawEvent* rawEvent);
+
+    uint32_t getButtonState() const;
+
+private:
+    bool mBtnLeft;
+    bool mBtnRight;
+    bool mBtnMiddle;
+    bool mBtnBack;
+    bool mBtnSide;
+    bool mBtnForward;
+    bool mBtnExtra;
+    bool mBtnTask;
+
+    void clearButtons();
+};
+
+
+/* Keeps track of cursor movements. */
+
+class CursorMotionAccumulator {
+public:
+    CursorMotionAccumulator();
+    void reset(InputDevice* device);
+
+    void process(const RawEvent* rawEvent);
+    void finishSync();
+
+    inline int32_t getRelativeX() const { return mRelX; }
+    inline int32_t getRelativeY() const { return mRelY; }
+
+private:
+    int32_t mRelX;
+    int32_t mRelY;
+
+    void clearRelativeAxes();
+};
+
+
+/* Keeps track of cursor scrolling motions. */
+
+class CursorScrollAccumulator {
+public:
+    CursorScrollAccumulator();
+    void configure(InputDevice* device);
+    void reset(InputDevice* device);
+
+    void process(const RawEvent* rawEvent);
+    void finishSync();
+
+    inline bool haveRelativeVWheel() const { return mHaveRelWheel; }
+    inline bool haveRelativeHWheel() const { return mHaveRelHWheel; }
+
+    inline int32_t getRelativeX() const { return mRelX; }
+    inline int32_t getRelativeY() const { return mRelY; }
+    inline int32_t getRelativeVWheel() const { return mRelWheel; }
+    inline int32_t getRelativeHWheel() const { return mRelHWheel; }
+
+private:
+    bool mHaveRelWheel;
+    bool mHaveRelHWheel;
+
+    int32_t mRelX;
+    int32_t mRelY;
+    int32_t mRelWheel;
+    int32_t mRelHWheel;
+
+    void clearRelativeAxes();
+};
+
+
+/* Keeps track of the state of touch, stylus and tool buttons. */
+class TouchButtonAccumulator {
+public:
+    TouchButtonAccumulator();
+    void configure(InputDevice* device);
+    void reset(InputDevice* device);
+
+    void process(const RawEvent* rawEvent);
+
+    uint32_t getButtonState() const;
+    int32_t getToolType() const;
+    bool isToolActive() const;
+    bool isHovering() const;
+    bool hasStylus() const;
+
+private:
+    bool mHaveBtnTouch;
+    bool mHaveStylus;
+
+    bool mBtnTouch;
+    bool mBtnStylus;
+    bool mBtnStylus2;
+    bool mBtnToolFinger;
+    bool mBtnToolPen;
+    bool mBtnToolRubber;
+    bool mBtnToolBrush;
+    bool mBtnToolPencil;
+    bool mBtnToolAirbrush;
+    bool mBtnToolMouse;
+    bool mBtnToolLens;
+    bool mBtnToolDoubleTap;
+    bool mBtnToolTripleTap;
+    bool mBtnToolQuadTap;
+
+    void clearButtons();
+};
+
+
+/* Raw axis information from the driver. */
+struct RawPointerAxes {
+    RawAbsoluteAxisInfo x;
+    RawAbsoluteAxisInfo y;
+    RawAbsoluteAxisInfo pressure;
+    RawAbsoluteAxisInfo touchMajor;
+    RawAbsoluteAxisInfo touchMinor;
+    RawAbsoluteAxisInfo toolMajor;
+    RawAbsoluteAxisInfo toolMinor;
+    RawAbsoluteAxisInfo orientation;
+    RawAbsoluteAxisInfo distance;
+    RawAbsoluteAxisInfo tiltX;
+    RawAbsoluteAxisInfo tiltY;
+    RawAbsoluteAxisInfo trackingId;
+    RawAbsoluteAxisInfo slot;
+
+    RawPointerAxes();
+    inline int32_t getRawWidth() const { return x.maxValue - x.minValue + 1; }
+    inline int32_t getRawHeight() const { return y.maxValue - y.minValue + 1; }
+    void clear();
+};
+
+
+/* Raw data for a collection of pointers including a pointer id mapping table. */
+struct RawPointerData {
+    struct Pointer {
+        uint32_t id;
+        int32_t x;
+        int32_t y;
+        int32_t pressure;
+        int32_t touchMajor;
+        int32_t touchMinor;
+        int32_t toolMajor;
+        int32_t toolMinor;
+        int32_t orientation;
+        int32_t distance;
+        int32_t tiltX;
+        int32_t tiltY;
+        int32_t toolType; // a fully decoded AMOTION_EVENT_TOOL_TYPE constant
+        bool isHovering;
+    };
+
+    uint32_t pointerCount;
+    Pointer pointers[MAX_POINTERS];
+    BitSet32 hoveringIdBits, touchingIdBits;
+    uint32_t idToIndex[MAX_POINTER_ID + 1];
+
+    RawPointerData();
+    void clear();
+    void copyFrom(const RawPointerData& other);
+    void getCentroidOfTouchingPointers(float* outX, float* outY) const;
+
+    inline void markIdBit(uint32_t id, bool isHovering) {
+        if (isHovering) {
+            hoveringIdBits.markBit(id);
+        } else {
+            touchingIdBits.markBit(id);
+        }
+    }
+
+    inline void clearIdBits() {
+        hoveringIdBits.clear();
+        touchingIdBits.clear();
+    }
+
+    inline const Pointer& pointerForId(uint32_t id) const {
+        return pointers[idToIndex[id]];
+    }
+
+    inline bool isHovering(uint32_t pointerIndex) {
+        return pointers[pointerIndex].isHovering;
+    }
+};
+
+
+/* Cooked data for a collection of pointers including a pointer id mapping table. */
+struct CookedPointerData {
+    uint32_t pointerCount;
+    PointerProperties pointerProperties[MAX_POINTERS];
+    PointerCoords pointerCoords[MAX_POINTERS];
+    BitSet32 hoveringIdBits, touchingIdBits;
+    uint32_t idToIndex[MAX_POINTER_ID + 1];
+
+    CookedPointerData();
+    void clear();
+    void copyFrom(const CookedPointerData& other);
+
+    inline const PointerCoords& pointerCoordsForId(uint32_t id) const {
+        return pointerCoords[idToIndex[id]];
+    }
+
+    inline PointerCoords& editPointerCoordsWithId(uint32_t id) {
+        return pointerCoords[idToIndex[id]];
+    }
+
+    inline PointerProperties& editPointerPropertiesWithId(uint32_t id) {
+        return pointerProperties[idToIndex[id]];
+    }
+
+    inline bool isHovering(uint32_t pointerIndex) const {
+        return hoveringIdBits.hasBit(pointerProperties[pointerIndex].id);
+    }
+
+    inline bool isTouching(uint32_t pointerIndex) const {
+        return touchingIdBits.hasBit(pointerProperties[pointerIndex].id);
+    }
+};
+
+/**
+ * Basic statistics information.
+ * Keep track of min, max, average, and standard deviation of the received samples.
+ * Used to report latency information about input events.
+ */
+struct LatencyStatistics {
+    float min;
+    float max;
+    // Sum of all samples
+    float sum;
+    // Sum of squares of all samples
+    float sum2;
+    // The number of samples
+    size_t count;
+    // The last time statistics were reported.
+    nsecs_t lastReportTime;
+
+    LatencyStatistics() {
+        reset(systemTime(SYSTEM_TIME_MONOTONIC));
+    }
+
+    inline void addValue(float x) {
+        if (x < min) {
+            min = x;
+        }
+        if (x > max) {
+            max = x;
+        }
+        sum += x;
+        sum2 += x * x;
+        count++;
+    }
+
+    // Get the average value. Should not be called if no samples have been added.
+    inline float mean() {
+        if (count == 0) {
+            return 0;
+        }
+        return sum / count;
+    }
+
+    // Get the standard deviation. Should not be called if no samples have been added.
+    inline float stdev() {
+        if (count == 0) {
+            return 0;
+        }
+        float average = mean();
+        return sqrt(sum2 / count - average * average);
+    }
+
+    /**
+     * Reset internal state. The variable 'when' is the time when the data collection started.
+     * Call this to start a new data collection window.
+     */
+    inline void reset(nsecs_t when) {
+        max = 0;
+        min = std::numeric_limits<float>::max();
+        sum = 0;
+        sum2 = 0;
+        count = 0;
+        lastReportTime = when;
+    }
+};
+
+/* Keeps track of the state of single-touch protocol. */
+class SingleTouchMotionAccumulator {
+public:
+    SingleTouchMotionAccumulator();
+
+    void process(const RawEvent* rawEvent);
+    void reset(InputDevice* device);
+
+    inline int32_t getAbsoluteX() const { return mAbsX; }
+    inline int32_t getAbsoluteY() const { return mAbsY; }
+    inline int32_t getAbsolutePressure() const { return mAbsPressure; }
+    inline int32_t getAbsoluteToolWidth() const { return mAbsToolWidth; }
+    inline int32_t getAbsoluteDistance() const { return mAbsDistance; }
+    inline int32_t getAbsoluteTiltX() const { return mAbsTiltX; }
+    inline int32_t getAbsoluteTiltY() const { return mAbsTiltY; }
+
+private:
+    int32_t mAbsX;
+    int32_t mAbsY;
+    int32_t mAbsPressure;
+    int32_t mAbsToolWidth;
+    int32_t mAbsDistance;
+    int32_t mAbsTiltX;
+    int32_t mAbsTiltY;
+
+    void clearAbsoluteAxes();
+};
+
+
+/* Keeps track of the state of multi-touch protocol. */
+class MultiTouchMotionAccumulator {
+public:
+    class Slot {
+    public:
+        inline bool isInUse() const { return mInUse; }
+        inline int32_t getX() const { return mAbsMTPositionX; }
+        inline int32_t getY() const { return mAbsMTPositionY; }
+        inline int32_t getTouchMajor() const { return mAbsMTTouchMajor; }
+        inline int32_t getTouchMinor() const {
+            return mHaveAbsMTTouchMinor ? mAbsMTTouchMinor : mAbsMTTouchMajor; }
+        inline int32_t getToolMajor() const { return mAbsMTWidthMajor; }
+        inline int32_t getToolMinor() const {
+            return mHaveAbsMTWidthMinor ? mAbsMTWidthMinor : mAbsMTWidthMajor; }
+        inline int32_t getOrientation() const { return mAbsMTOrientation; }
+        inline int32_t getTrackingId() const { return mAbsMTTrackingId; }
+        inline int32_t getPressure() const { return mAbsMTPressure; }
+        inline int32_t getDistance() const { return mAbsMTDistance; }
+        inline int32_t getToolType() const;
+
+    private:
+        friend class MultiTouchMotionAccumulator;
+
+        bool mInUse;
+        bool mHaveAbsMTTouchMinor;
+        bool mHaveAbsMTWidthMinor;
+        bool mHaveAbsMTToolType;
+
+        int32_t mAbsMTPositionX;
+        int32_t mAbsMTPositionY;
+        int32_t mAbsMTTouchMajor;
+        int32_t mAbsMTTouchMinor;
+        int32_t mAbsMTWidthMajor;
+        int32_t mAbsMTWidthMinor;
+        int32_t mAbsMTOrientation;
+        int32_t mAbsMTTrackingId;
+        int32_t mAbsMTPressure;
+        int32_t mAbsMTDistance;
+        int32_t mAbsMTToolType;
+
+        Slot();
+        void clear();
+    };
+
+    MultiTouchMotionAccumulator();
+    ~MultiTouchMotionAccumulator();
+
+    void configure(InputDevice* device, size_t slotCount, bool usingSlotsProtocol);
+    void reset(InputDevice* device);
+    void process(const RawEvent* rawEvent);
+    void finishSync();
+    bool hasStylus() const;
+
+    inline size_t getSlotCount() const { return mSlotCount; }
+    inline const Slot* getSlot(size_t index) const { return &mSlots[index]; }
+    inline uint32_t getDeviceTimestamp() const { return mDeviceTimestamp; }
+
+private:
+    int32_t mCurrentSlot;
+    Slot* mSlots;
+    size_t mSlotCount;
+    bool mUsingSlotsProtocol;
+    bool mHaveStylus;
+    uint32_t mDeviceTimestamp;
+
+    void clearSlots(int32_t initialSlot);
+};
+
+
+/* An input mapper transforms raw input events into cooked event data.
+ * A single input device can have multiple associated input mappers in order to interpret
+ * different classes of events.
+ *
+ * InputMapper lifecycle:
+ * - create
+ * - configure with 0 changes
+ * - reset
+ * - process, process, process (may occasionally reconfigure with non-zero changes or reset)
+ * - reset
+ * - destroy
+ */
+class InputMapper {
+public:
+    explicit InputMapper(InputDevice* device);
+    virtual ~InputMapper();
+
+    inline InputDevice* getDevice() { return mDevice; }
+    inline int32_t getDeviceId() { return mDevice->getId(); }
+    inline const std::string getDeviceName() { return mDevice->getName(); }
+    inline InputReaderContext* getContext() { return mContext; }
+    inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); }
+    inline InputListenerInterface* getListener() { return mContext->getListener(); }
+    inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
+
+    virtual uint32_t getSources() = 0;
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void dump(std::string& dump);
+    virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+    virtual void reset(nsecs_t when);
+    virtual void process(const RawEvent* rawEvent) = 0;
+    virtual void timeoutExpired(nsecs_t when);
+
+    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
+    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+    virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
+    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags);
+    virtual void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
+            int32_t token);
+    virtual void cancelVibrate(int32_t token);
+    virtual void cancelTouch(nsecs_t when);
+
+    virtual int32_t getMetaState();
+    virtual void updateMetaState(int32_t keyCode);
+
+    virtual void updateExternalStylusState(const StylusState& state);
+
+    virtual void fadePointer();
+    virtual std::optional<int32_t> getAssociatedDisplay() {
+        return std::nullopt;
+    }
+protected:
+    InputDevice* mDevice;
+    InputReaderContext* mContext;
+
+    status_t getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo);
+    void bumpGeneration();
+
+    static void dumpRawAbsoluteAxisInfo(std::string& dump,
+            const RawAbsoluteAxisInfo& axis, const char* name);
+    static void dumpStylusState(std::string& dump, const StylusState& state);
+};
+
+
+class SwitchInputMapper : public InputMapper {
+public:
+    explicit SwitchInputMapper(InputDevice* device);
+    virtual ~SwitchInputMapper();
+
+    virtual uint32_t getSources();
+    virtual void process(const RawEvent* rawEvent);
+
+    virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
+    virtual void dump(std::string& dump);
+
+private:
+    uint32_t mSwitchValues;
+    uint32_t mUpdatedSwitchMask;
+
+    void processSwitch(int32_t switchCode, int32_t switchValue);
+    void sync(nsecs_t when);
+};
+
+
+class VibratorInputMapper : public InputMapper {
+public:
+    explicit VibratorInputMapper(InputDevice* device);
+    virtual ~VibratorInputMapper();
+
+    virtual uint32_t getSources();
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void process(const RawEvent* rawEvent);
+
+    virtual void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
+            int32_t token);
+    virtual void cancelVibrate(int32_t token);
+    virtual void timeoutExpired(nsecs_t when);
+    virtual void dump(std::string& dump);
+
+private:
+    bool mVibrating;
+    nsecs_t mPattern[MAX_VIBRATE_PATTERN_SIZE];
+    size_t mPatternSize;
+    ssize_t mRepeat;
+    int32_t mToken;
+    ssize_t mIndex;
+    nsecs_t mNextStepTime;
+
+    void nextStep();
+    void stopVibrating();
+};
+
+
+class KeyboardInputMapper : public InputMapper {
+public:
+    KeyboardInputMapper(InputDevice* device, uint32_t source, int32_t keyboardType);
+    virtual ~KeyboardInputMapper();
+
+    virtual uint32_t getSources();
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void dump(std::string& dump);
+    virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+    virtual void reset(nsecs_t when);
+    virtual void process(const RawEvent* rawEvent);
+
+    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
+    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags);
+
+    virtual int32_t getMetaState();
+    virtual void updateMetaState(int32_t keyCode);
+
+private:
+    // The current viewport.
+    std::optional<DisplayViewport> mViewport;
+
+    struct KeyDown {
+        int32_t keyCode;
+        int32_t scanCode;
+    };
+
+    uint32_t mSource;
+    int32_t mKeyboardType;
+
+    std::vector<KeyDown> mKeyDowns; // keys that are down
+    int32_t mMetaState;
+    nsecs_t mDownTime; // time of most recent key down
+
+    int32_t mCurrentHidUsage; // most recent HID usage seen this packet, or 0 if none
+
+    struct LedState {
+        bool avail; // led is available
+        bool on;    // we think the led is currently on
+    };
+    LedState mCapsLockLedState;
+    LedState mNumLockLedState;
+    LedState mScrollLockLedState;
+
+    // Immutable configuration parameters.
+    struct Parameters {
+        bool orientationAware;
+        bool handlesKeyRepeat;
+    } mParameters;
+
+    void configureParameters();
+    void dumpParameters(std::string& dump);
+
+    int32_t getOrientation();
+    int32_t getDisplayId();
+
+    bool isKeyboardOrGamepadKey(int32_t scanCode);
+    bool isMediaKey(int32_t keyCode);
+
+    void processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode);
+
+    bool updateMetaStateIfNeeded(int32_t keyCode, bool down);
+
+    ssize_t findKeyDown(int32_t scanCode);
+
+    void resetLedState();
+    void initializeLedState(LedState& ledState, int32_t led);
+    void updateLedState(bool reset);
+    void updateLedStateForModifier(LedState& ledState, int32_t led,
+            int32_t modifier, bool reset);
+};
+
+
+class CursorInputMapper : public InputMapper {
+public:
+    explicit CursorInputMapper(InputDevice* device);
+    virtual ~CursorInputMapper();
+
+    virtual uint32_t getSources();
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void dump(std::string& dump);
+    virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+    virtual void reset(nsecs_t when);
+    virtual void process(const RawEvent* rawEvent);
+
+    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+
+    virtual void fadePointer();
+
+    virtual std::optional<int32_t> getAssociatedDisplay();
+private:
+    // Amount that trackball needs to move in order to generate a key event.
+    static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6;
+
+    // Immutable configuration parameters.
+    struct Parameters {
+        enum Mode {
+            MODE_POINTER,
+            MODE_POINTER_RELATIVE,
+            MODE_NAVIGATION,
+        };
+
+        Mode mode;
+        bool hasAssociatedDisplay;
+        bool orientationAware;
+    } mParameters;
+
+    CursorButtonAccumulator mCursorButtonAccumulator;
+    CursorMotionAccumulator mCursorMotionAccumulator;
+    CursorScrollAccumulator mCursorScrollAccumulator;
+
+    int32_t mSource;
+    float mXScale;
+    float mYScale;
+    float mXPrecision;
+    float mYPrecision;
+
+    float mVWheelScale;
+    float mHWheelScale;
+
+    // Velocity controls for mouse pointer and wheel movements.
+    // The controls for X and Y wheel movements are separate to keep them decoupled.
+    VelocityControl mPointerVelocityControl;
+    VelocityControl mWheelXVelocityControl;
+    VelocityControl mWheelYVelocityControl;
+
+    int32_t mOrientation;
+
+    sp<PointerControllerInterface> mPointerController;
+
+    int32_t mButtonState;
+    nsecs_t mDownTime;
+
+    void configureParameters();
+    void dumpParameters(std::string& dump);
+
+    void sync(nsecs_t when);
+};
+
+
+class RotaryEncoderInputMapper : public InputMapper {
+public:
+    explicit RotaryEncoderInputMapper(InputDevice* device);
+    virtual ~RotaryEncoderInputMapper();
+
+    virtual uint32_t getSources();
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void dump(std::string& dump);
+    virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+    virtual void reset(nsecs_t when);
+    virtual void process(const RawEvent* rawEvent);
+
+private:
+    CursorScrollAccumulator mRotaryEncoderScrollAccumulator;
+
+    int32_t mSource;
+    float mScalingFactor;
+    int32_t mOrientation;
+
+    void sync(nsecs_t when);
+};
+
+class TouchInputMapper : public InputMapper {
+public:
+    explicit TouchInputMapper(InputDevice* device);
+    virtual ~TouchInputMapper();
+
+    virtual uint32_t getSources();
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void dump(std::string& dump);
+    virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+    virtual void reset(nsecs_t when);
+    virtual void process(const RawEvent* rawEvent);
+
+    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
+    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags);
+
+    virtual void fadePointer();
+    virtual void cancelTouch(nsecs_t when);
+    virtual void timeoutExpired(nsecs_t when);
+    virtual void updateExternalStylusState(const StylusState& state);
+    virtual std::optional<int32_t> getAssociatedDisplay();
+protected:
+    CursorButtonAccumulator mCursorButtonAccumulator;
+    CursorScrollAccumulator mCursorScrollAccumulator;
+    TouchButtonAccumulator mTouchButtonAccumulator;
+
+    struct VirtualKey {
+        int32_t keyCode;
+        int32_t scanCode;
+        uint32_t flags;
+
+        // computed hit box, specified in touch screen coords based on known display size
+        int32_t hitLeft;
+        int32_t hitTop;
+        int32_t hitRight;
+        int32_t hitBottom;
+
+        inline bool isHit(int32_t x, int32_t y) const {
+            return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom;
+        }
+    };
+
+    // Input sources and device mode.
+    uint32_t mSource;
+
+    enum DeviceMode {
+        DEVICE_MODE_DISABLED, // input is disabled
+        DEVICE_MODE_DIRECT, // direct mapping (touchscreen)
+        DEVICE_MODE_UNSCALED, // unscaled mapping (touchpad)
+        DEVICE_MODE_NAVIGATION, // unscaled mapping with assist gesture (touch navigation)
+        DEVICE_MODE_POINTER, // pointer mapping (pointer)
+    };
+    DeviceMode mDeviceMode;
+
+    // The reader's configuration.
+    InputReaderConfiguration mConfig;
+
+    // Immutable configuration parameters.
+    struct Parameters {
+        enum DeviceType {
+            DEVICE_TYPE_TOUCH_SCREEN,
+            DEVICE_TYPE_TOUCH_PAD,
+            DEVICE_TYPE_TOUCH_NAVIGATION,
+            DEVICE_TYPE_POINTER,
+        };
+
+        DeviceType deviceType;
+        bool hasAssociatedDisplay;
+        bool associatedDisplayIsExternal;
+        bool orientationAware;
+        bool hasButtonUnderPad;
+        std::string uniqueDisplayId;
+
+        enum GestureMode {
+            GESTURE_MODE_SINGLE_TOUCH,
+            GESTURE_MODE_MULTI_TOUCH,
+        };
+        GestureMode gestureMode;
+
+        bool wake;
+    } mParameters;
+
+    // Immutable calibration parameters in parsed form.
+    struct Calibration {
+        // Size
+        enum SizeCalibration {
+            SIZE_CALIBRATION_DEFAULT,
+            SIZE_CALIBRATION_NONE,
+            SIZE_CALIBRATION_GEOMETRIC,
+            SIZE_CALIBRATION_DIAMETER,
+            SIZE_CALIBRATION_BOX,
+            SIZE_CALIBRATION_AREA,
+        };
+
+        SizeCalibration sizeCalibration;
+
+        bool haveSizeScale;
+        float sizeScale;
+        bool haveSizeBias;
+        float sizeBias;
+        bool haveSizeIsSummed;
+        bool sizeIsSummed;
+
+        // Pressure
+        enum PressureCalibration {
+            PRESSURE_CALIBRATION_DEFAULT,
+            PRESSURE_CALIBRATION_NONE,
+            PRESSURE_CALIBRATION_PHYSICAL,
+            PRESSURE_CALIBRATION_AMPLITUDE,
+        };
+
+        PressureCalibration pressureCalibration;
+        bool havePressureScale;
+        float pressureScale;
+
+        // Orientation
+        enum OrientationCalibration {
+            ORIENTATION_CALIBRATION_DEFAULT,
+            ORIENTATION_CALIBRATION_NONE,
+            ORIENTATION_CALIBRATION_INTERPOLATED,
+            ORIENTATION_CALIBRATION_VECTOR,
+        };
+
+        OrientationCalibration orientationCalibration;
+
+        // Distance
+        enum DistanceCalibration {
+            DISTANCE_CALIBRATION_DEFAULT,
+            DISTANCE_CALIBRATION_NONE,
+            DISTANCE_CALIBRATION_SCALED,
+        };
+
+        DistanceCalibration distanceCalibration;
+        bool haveDistanceScale;
+        float distanceScale;
+
+        enum CoverageCalibration {
+            COVERAGE_CALIBRATION_DEFAULT,
+            COVERAGE_CALIBRATION_NONE,
+            COVERAGE_CALIBRATION_BOX,
+        };
+
+        CoverageCalibration coverageCalibration;
+
+        inline void applySizeScaleAndBias(float* outSize) const {
+            if (haveSizeScale) {
+                *outSize *= sizeScale;
+            }
+            if (haveSizeBias) {
+                *outSize += sizeBias;
+            }
+            if (*outSize < 0) {
+                *outSize = 0;
+            }
+        }
+    } mCalibration;
+
+    // Affine location transformation/calibration
+    struct TouchAffineTransformation mAffineTransform;
+
+    RawPointerAxes mRawPointerAxes;
+
+    struct RawState {
+        nsecs_t when;
+        uint32_t deviceTimestamp;
+
+        // Raw pointer sample data.
+        RawPointerData rawPointerData;
+
+        int32_t buttonState;
+
+        // Scroll state.
+        int32_t rawVScroll;
+        int32_t rawHScroll;
+
+        void copyFrom(const RawState& other) {
+            when = other.when;
+            deviceTimestamp = other.deviceTimestamp;
+            rawPointerData.copyFrom(other.rawPointerData);
+            buttonState = other.buttonState;
+            rawVScroll = other.rawVScroll;
+            rawHScroll = other.rawHScroll;
+        }
+
+        void clear() {
+            when = 0;
+            deviceTimestamp = 0;
+            rawPointerData.clear();
+            buttonState = 0;
+            rawVScroll = 0;
+            rawHScroll = 0;
+        }
+    };
+
+    struct CookedState {
+        uint32_t deviceTimestamp;
+        // Cooked pointer sample data.
+        CookedPointerData cookedPointerData;
+
+        // Id bits used to differentiate fingers, stylus and mouse tools.
+        BitSet32 fingerIdBits;
+        BitSet32 stylusIdBits;
+        BitSet32 mouseIdBits;
+
+        int32_t buttonState;
+
+        void copyFrom(const CookedState& other) {
+            deviceTimestamp = other.deviceTimestamp;
+            cookedPointerData.copyFrom(other.cookedPointerData);
+            fingerIdBits = other.fingerIdBits;
+            stylusIdBits = other.stylusIdBits;
+            mouseIdBits = other.mouseIdBits;
+            buttonState = other.buttonState;
+        }
+
+        void clear() {
+            deviceTimestamp = 0;
+            cookedPointerData.clear();
+            fingerIdBits.clear();
+            stylusIdBits.clear();
+            mouseIdBits.clear();
+            buttonState = 0;
+        }
+    };
+
+    std::vector<RawState> mRawStatesPending;
+    RawState mCurrentRawState;
+    CookedState mCurrentCookedState;
+    RawState mLastRawState;
+    CookedState mLastCookedState;
+
+    // State provided by an external stylus
+    StylusState mExternalStylusState;
+    int64_t mExternalStylusId;
+    nsecs_t mExternalStylusFusionTimeout;
+    bool mExternalStylusDataPending;
+
+    // True if we sent a HOVER_ENTER event.
+    bool mSentHoverEnter;
+
+    // Have we assigned pointer IDs for this stream
+    bool mHavePointerIds;
+
+    // Is the current stream of direct touch events aborted
+    bool mCurrentMotionAborted;
+
+    // The time the primary pointer last went down.
+    nsecs_t mDownTime;
+
+    // The pointer controller, or null if the device is not a pointer.
+    sp<PointerControllerInterface> mPointerController;
+
+    std::vector<VirtualKey> mVirtualKeys;
+
+    virtual void configureParameters();
+    virtual void dumpParameters(std::string& dump);
+    virtual void configureRawPointerAxes();
+    virtual void dumpRawPointerAxes(std::string& dump);
+    virtual void configureSurface(nsecs_t when, bool* outResetNeeded);
+    virtual void dumpSurface(std::string& dump);
+    virtual void configureVirtualKeys();
+    virtual void dumpVirtualKeys(std::string& dump);
+    virtual void parseCalibration();
+    virtual void resolveCalibration();
+    virtual void dumpCalibration(std::string& dump);
+    virtual void updateAffineTransformation();
+    virtual void dumpAffineTransformation(std::string& dump);
+    virtual void resolveExternalStylusPresence();
+    virtual bool hasStylus() const = 0;
+    virtual bool hasExternalStylus() const;
+
+    virtual void syncTouch(nsecs_t when, RawState* outState) = 0;
+
+private:
+    // The current viewport.
+    // The components of the viewport are specified in the display's rotated orientation.
+    DisplayViewport mViewport;
+
+    // The surface orientation, width and height set by configureSurface().
+    // The width and height are derived from the viewport but are specified
+    // in the natural orientation.
+    // The surface origin specifies how the surface coordinates should be translated
+    // to align with the logical display coordinate space.
+    int32_t mSurfaceWidth;
+    int32_t mSurfaceHeight;
+    int32_t mSurfaceLeft;
+    int32_t mSurfaceTop;
+
+    // Similar to the surface coordinates, but in the raw display coordinate space rather than in
+    // the logical coordinate space.
+    int32_t mPhysicalWidth;
+    int32_t mPhysicalHeight;
+    int32_t mPhysicalLeft;
+    int32_t mPhysicalTop;
+
+    // The orientation may be different from the viewport orientation as it specifies
+    // the rotation of the surface coordinates required to produce the viewport's
+    // requested orientation, so it will depend on whether the device is orientation aware.
+    int32_t mSurfaceOrientation;
+
+    // Translation and scaling factors, orientation-independent.
+    float mXTranslate;
+    float mXScale;
+    float mXPrecision;
+
+    float mYTranslate;
+    float mYScale;
+    float mYPrecision;
+
+    float mGeometricScale;
+
+    float mPressureScale;
+
+    float mSizeScale;
+
+    float mOrientationScale;
+
+    float mDistanceScale;
+
+    bool mHaveTilt;
+    float mTiltXCenter;
+    float mTiltXScale;
+    float mTiltYCenter;
+    float mTiltYScale;
+
+    bool mExternalStylusConnected;
+
+    // Oriented motion ranges for input device info.
+    struct OrientedRanges {
+        InputDeviceInfo::MotionRange x;
+        InputDeviceInfo::MotionRange y;
+        InputDeviceInfo::MotionRange pressure;
+
+        bool haveSize;
+        InputDeviceInfo::MotionRange size;
+
+        bool haveTouchSize;
+        InputDeviceInfo::MotionRange touchMajor;
+        InputDeviceInfo::MotionRange touchMinor;
+
+        bool haveToolSize;
+        InputDeviceInfo::MotionRange toolMajor;
+        InputDeviceInfo::MotionRange toolMinor;
+
+        bool haveOrientation;
+        InputDeviceInfo::MotionRange orientation;
+
+        bool haveDistance;
+        InputDeviceInfo::MotionRange distance;
+
+        bool haveTilt;
+        InputDeviceInfo::MotionRange tilt;
+
+        OrientedRanges() {
+            clear();
+        }
+
+        void clear() {
+            haveSize = false;
+            haveTouchSize = false;
+            haveToolSize = false;
+            haveOrientation = false;
+            haveDistance = false;
+            haveTilt = false;
+        }
+    } mOrientedRanges;
+
+    // Oriented dimensions and precision.
+    float mOrientedXPrecision;
+    float mOrientedYPrecision;
+
+    struct CurrentVirtualKeyState {
+        bool down;
+        bool ignored;
+        nsecs_t downTime;
+        int32_t keyCode;
+        int32_t scanCode;
+    } mCurrentVirtualKey;
+
+    // Scale factor for gesture or mouse based pointer movements.
+    float mPointerXMovementScale;
+    float mPointerYMovementScale;
+
+    // Scale factor for gesture based zooming and other freeform motions.
+    float mPointerXZoomScale;
+    float mPointerYZoomScale;
+
+    // The maximum swipe width.
+    float mPointerGestureMaxSwipeWidth;
+
+    struct PointerDistanceHeapElement {
+        uint32_t currentPointerIndex : 8;
+        uint32_t lastPointerIndex : 8;
+        uint64_t distance : 48; // squared distance
+    };
+
+    enum PointerUsage {
+        POINTER_USAGE_NONE,
+        POINTER_USAGE_GESTURES,
+        POINTER_USAGE_STYLUS,
+        POINTER_USAGE_MOUSE,
+    };
+    PointerUsage mPointerUsage;
+
+    struct PointerGesture {
+        enum Mode {
+            // No fingers, button is not pressed.
+            // Nothing happening.
+            NEUTRAL,
+
+            // No fingers, button is not pressed.
+            // Tap detected.
+            // Emits DOWN and UP events at the pointer location.
+            TAP,
+
+            // Exactly one finger dragging following a tap.
+            // Pointer follows the active finger.
+            // Emits DOWN, MOVE and UP events at the pointer location.
+            //
+            // Detect double-taps when the finger goes up while in TAP_DRAG mode.
+            TAP_DRAG,
+
+            // Button is pressed.
+            // Pointer follows the active finger if there is one.  Other fingers are ignored.
+            // Emits DOWN, MOVE and UP events at the pointer location.
+            BUTTON_CLICK_OR_DRAG,
+
+            // Exactly one finger, button is not pressed.
+            // Pointer follows the active finger.
+            // Emits HOVER_MOVE events at the pointer location.
+            //
+            // Detect taps when the finger goes up while in HOVER mode.
+            HOVER,
+
+            // Exactly two fingers but neither have moved enough to clearly indicate
+            // whether a swipe or freeform gesture was intended.  We consider the
+            // pointer to be pressed so this enables clicking or long-pressing on buttons.
+            // Pointer does not move.
+            // Emits DOWN, MOVE and UP events with a single stationary pointer coordinate.
+            PRESS,
+
+            // Exactly two fingers moving in the same direction, button is not pressed.
+            // Pointer does not move.
+            // Emits DOWN, MOVE and UP events with a single pointer coordinate that
+            // follows the midpoint between both fingers.
+            SWIPE,
+
+            // Two or more fingers moving in arbitrary directions, button is not pressed.
+            // Pointer does not move.
+            // Emits DOWN, POINTER_DOWN, MOVE, POINTER_UP and UP events that follow
+            // each finger individually relative to the initial centroid of the finger.
+            FREEFORM,
+
+            // Waiting for quiet time to end before starting the next gesture.
+            QUIET,
+        };
+
+        // Time the first finger went down.
+        nsecs_t firstTouchTime;
+
+        // The active pointer id from the raw touch data.
+        int32_t activeTouchId; // -1 if none
+
+        // The active pointer id from the gesture last delivered to the application.
+        int32_t activeGestureId; // -1 if none
+
+        // Pointer coords and ids for the current and previous pointer gesture.
+        Mode currentGestureMode;
+        BitSet32 currentGestureIdBits;
+        uint32_t currentGestureIdToIndex[MAX_POINTER_ID + 1];
+        PointerProperties currentGestureProperties[MAX_POINTERS];
+        PointerCoords currentGestureCoords[MAX_POINTERS];
+
+        Mode lastGestureMode;
+        BitSet32 lastGestureIdBits;
+        uint32_t lastGestureIdToIndex[MAX_POINTER_ID + 1];
+        PointerProperties lastGestureProperties[MAX_POINTERS];
+        PointerCoords lastGestureCoords[MAX_POINTERS];
+
+        // Time the pointer gesture last went down.
+        nsecs_t downTime;
+
+        // Time when the pointer went down for a TAP.
+        nsecs_t tapDownTime;
+
+        // Time when the pointer went up for a TAP.
+        nsecs_t tapUpTime;
+
+        // Location of initial tap.
+        float tapX, tapY;
+
+        // Time we started waiting for quiescence.
+        nsecs_t quietTime;
+
+        // Reference points for multitouch gestures.
+        float referenceTouchX;    // reference touch X/Y coordinates in surface units
+        float referenceTouchY;
+        float referenceGestureX;  // reference gesture X/Y coordinates in pixels
+        float referenceGestureY;
+
+        // Distance that each pointer has traveled which has not yet been
+        // subsumed into the reference gesture position.
+        BitSet32 referenceIdBits;
+        struct Delta {
+            float dx, dy;
+        };
+        Delta referenceDeltas[MAX_POINTER_ID + 1];
+
+        // Describes how touch ids are mapped to gesture ids for freeform gestures.
+        uint32_t freeformTouchToGestureIdMap[MAX_POINTER_ID + 1];
+
+        // A velocity tracker for determining whether to switch active pointers during drags.
+        VelocityTracker velocityTracker;
+
+        void reset() {
+            firstTouchTime = LLONG_MIN;
+            activeTouchId = -1;
+            activeGestureId = -1;
+            currentGestureMode = NEUTRAL;
+            currentGestureIdBits.clear();
+            lastGestureMode = NEUTRAL;
+            lastGestureIdBits.clear();
+            downTime = 0;
+            velocityTracker.clear();
+            resetTap();
+            resetQuietTime();
+        }
+
+        void resetTap() {
+            tapDownTime = LLONG_MIN;
+            tapUpTime = LLONG_MIN;
+        }
+
+        void resetQuietTime() {
+            quietTime = LLONG_MIN;
+        }
+    } mPointerGesture;
+
+    struct PointerSimple {
+        PointerCoords currentCoords;
+        PointerProperties currentProperties;
+        PointerCoords lastCoords;
+        PointerProperties lastProperties;
+
+        // True if the pointer is down.
+        bool down;
+
+        // True if the pointer is hovering.
+        bool hovering;
+
+        // Time the pointer last went down.
+        nsecs_t downTime;
+
+        void reset() {
+            currentCoords.clear();
+            currentProperties.clear();
+            lastCoords.clear();
+            lastProperties.clear();
+            down = false;
+            hovering = false;
+            downTime = 0;
+        }
+    } mPointerSimple;
+
+    // The pointer and scroll velocity controls.
+    VelocityControl mPointerVelocityControl;
+    VelocityControl mWheelXVelocityControl;
+    VelocityControl mWheelYVelocityControl;
+
+    // Latency statistics for touch events
+    struct LatencyStatistics mStatistics;
+
+    std::optional<DisplayViewport> findViewport();
+
+    void resetExternalStylus();
+    void clearStylusDataPendingFlags();
+
+    void sync(nsecs_t when);
+
+    bool consumeRawTouches(nsecs_t when, uint32_t policyFlags);
+    void processRawTouches(bool timeout);
+    void cookAndDispatch(nsecs_t when);
+    void dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
+            int32_t keyEventAction, int32_t keyEventFlags);
+
+    void dispatchTouches(nsecs_t when, uint32_t policyFlags);
+    void dispatchHoverExit(nsecs_t when, uint32_t policyFlags);
+    void dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags);
+    void dispatchButtonRelease(nsecs_t when, uint32_t policyFlags);
+    void dispatchButtonPress(nsecs_t when, uint32_t policyFlags);
+    const BitSet32& findActiveIdBits(const CookedPointerData& cookedPointerData);
+    void cookPointerData();
+    void abortTouches(nsecs_t when, uint32_t policyFlags);
+
+    void dispatchPointerUsage(nsecs_t when, uint32_t policyFlags, PointerUsage pointerUsage);
+    void abortPointerUsage(nsecs_t when, uint32_t policyFlags);
+
+    void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout);
+    void abortPointerGestures(nsecs_t when, uint32_t policyFlags);
+    bool preparePointerGestures(nsecs_t when,
+            bool* outCancelPreviousGesture, bool* outFinishPreviousGesture,
+            bool isTimeout);
+
+    void dispatchPointerStylus(nsecs_t when, uint32_t policyFlags);
+    void abortPointerStylus(nsecs_t when, uint32_t policyFlags);
+
+    void dispatchPointerMouse(nsecs_t when, uint32_t policyFlags);
+    void abortPointerMouse(nsecs_t when, uint32_t policyFlags);
+
+    void dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
+            bool down, bool hovering);
+    void abortPointerSimple(nsecs_t when, uint32_t policyFlags);
+
+    bool assignExternalStylusId(const RawState& state, bool timeout);
+    void applyExternalStylusButtonState(nsecs_t when);
+    void applyExternalStylusTouchState(nsecs_t when);
+
+    // Dispatches a motion event.
+    // If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the
+    // method will take care of setting the index and transmuting the action to DOWN or UP
+    // it is the first / last pointer to go down / up.
+    void dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
+            int32_t action, int32_t actionButton,
+            int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+            uint32_t deviceTimestamp,
+            const PointerProperties* properties, const PointerCoords* coords,
+            const uint32_t* idToIndex, BitSet32 idBits,
+            int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime);
+
+    // Updates pointer coords and properties for pointers with specified ids that have moved.
+    // Returns true if any of them changed.
+    bool updateMovedPointers(const PointerProperties* inProperties,
+            const PointerCoords* inCoords, const uint32_t* inIdToIndex,
+            PointerProperties* outProperties, PointerCoords* outCoords,
+            const uint32_t* outIdToIndex, BitSet32 idBits) const;
+
+    bool isPointInsideSurface(int32_t x, int32_t y);
+    const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y);
+
+    static void assignPointerIds(const RawState* last, RawState* current);
+
+    void reportEventForStatistics(nsecs_t evdevTime);
+
+    const char* modeToString(DeviceMode deviceMode);
+};
+
+
+class SingleTouchInputMapper : public TouchInputMapper {
+public:
+    explicit SingleTouchInputMapper(InputDevice* device);
+    virtual ~SingleTouchInputMapper();
+
+    virtual void reset(nsecs_t when);
+    virtual void process(const RawEvent* rawEvent);
+
+protected:
+    virtual void syncTouch(nsecs_t when, RawState* outState);
+    virtual void configureRawPointerAxes();
+    virtual bool hasStylus() const;
+
+private:
+    SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
+};
+
+
+class MultiTouchInputMapper : public TouchInputMapper {
+public:
+    explicit MultiTouchInputMapper(InputDevice* device);
+    virtual ~MultiTouchInputMapper();
+
+    virtual void reset(nsecs_t when);
+    virtual void process(const RawEvent* rawEvent);
+
+protected:
+    virtual void syncTouch(nsecs_t when, RawState* outState);
+    virtual void configureRawPointerAxes();
+    virtual bool hasStylus() const;
+
+private:
+    MultiTouchMotionAccumulator mMultiTouchMotionAccumulator;
+
+    // Specifies the pointer id bits that are in use, and their associated tracking id.
+    BitSet32 mPointerIdBits;
+    int32_t mPointerTrackingIdMap[MAX_POINTER_ID + 1];
+};
+
+class ExternalStylusInputMapper : public InputMapper {
+public:
+    explicit ExternalStylusInputMapper(InputDevice* device);
+    virtual ~ExternalStylusInputMapper() = default;
+
+    virtual uint32_t getSources();
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void dump(std::string& dump);
+    virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+    virtual void reset(nsecs_t when);
+    virtual void process(const RawEvent* rawEvent);
+    virtual void sync(nsecs_t when);
+
+private:
+    SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
+    RawAbsoluteAxisInfo mRawPressureAxis;
+    TouchButtonAccumulator mTouchButtonAccumulator;
+
+    StylusState mStylusState;
+};
+
+
+class JoystickInputMapper : public InputMapper {
+public:
+    explicit JoystickInputMapper(InputDevice* device);
+    virtual ~JoystickInputMapper();
+
+    virtual uint32_t getSources();
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void dump(std::string& dump);
+    virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+    virtual void reset(nsecs_t when);
+    virtual void process(const RawEvent* rawEvent);
+
+private:
+    struct Axis {
+        RawAbsoluteAxisInfo rawAxisInfo;
+        AxisInfo axisInfo;
+
+        bool explicitlyMapped; // true if the axis was explicitly assigned an axis id
+
+        float scale;   // scale factor from raw to normalized values
+        float offset;  // offset to add after scaling for normalization
+        float highScale;  // scale factor from raw to normalized values of high split
+        float highOffset; // offset to add after scaling for normalization of high split
+
+        float min;        // normalized inclusive minimum
+        float max;        // normalized inclusive maximum
+        float flat;       // normalized flat region size
+        float fuzz;       // normalized error tolerance
+        float resolution; // normalized resolution in units/mm
+
+        float filter;  // filter out small variations of this size
+        float currentValue; // current value
+        float newValue; // most recent value
+        float highCurrentValue; // current value of high split
+        float highNewValue; // most recent value of high split
+
+        void initialize(const RawAbsoluteAxisInfo& rawAxisInfo, const AxisInfo& axisInfo,
+                bool explicitlyMapped, float scale, float offset,
+                float highScale, float highOffset,
+                float min, float max, float flat, float fuzz, float resolution) {
+            this->rawAxisInfo = rawAxisInfo;
+            this->axisInfo = axisInfo;
+            this->explicitlyMapped = explicitlyMapped;
+            this->scale = scale;
+            this->offset = offset;
+            this->highScale = highScale;
+            this->highOffset = highOffset;
+            this->min = min;
+            this->max = max;
+            this->flat = flat;
+            this->fuzz = fuzz;
+            this->resolution = resolution;
+            this->filter = 0;
+            resetValue();
+        }
+
+        void resetValue() {
+            this->currentValue = 0;
+            this->newValue = 0;
+            this->highCurrentValue = 0;
+            this->highNewValue = 0;
+        }
+    };
+
+    // Axes indexed by raw ABS_* axis index.
+    KeyedVector<int32_t, Axis> mAxes;
+
+    void sync(nsecs_t when, bool force);
+
+    bool haveAxis(int32_t axisId);
+    void pruneAxes(bool ignoreExplicitlyMappedAxes);
+    bool filterAxes(bool force);
+
+    static bool hasValueChangedSignificantly(float filter,
+            float newValue, float currentValue, float min, float max);
+    static bool hasMovedNearerToValueWithinFilteredRange(float filter,
+            float newValue, float currentValue, float thresholdValue);
+
+    static bool isCenteredAxis(int32_t axis);
+    static int32_t getCompatAxis(int32_t axis);
+
+    static void addMotionRange(int32_t axisId, const Axis& axis, InputDeviceInfo* info);
+    static void setPointerCoordsAxisValue(PointerCoords* pointerCoords, int32_t axis,
+            float value);
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_READER_H
diff --git a/services/inputflinger/reader/InputReaderFactory.cpp b/services/inputflinger/InputReaderFactory.cpp
similarity index 81%
rename from services/inputflinger/reader/InputReaderFactory.cpp
rename to services/inputflinger/InputReaderFactory.cpp
index 9f73680..3534f6b 100644
--- a/services/inputflinger/reader/InputReaderFactory.cpp
+++ b/services/inputflinger/InputReaderFactory.cpp
@@ -15,13 +15,13 @@
  */
 
 #include "InputReaderFactory.h"
-
 #include "InputReader.h"
 
 namespace android {
 
-sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,
-                                           const sp<InputListenerInterface>& listener) {
+sp<InputReaderInterface> createInputReader(
+        const sp<InputReaderPolicyInterface>& policy,
+        const sp<InputListenerInterface>& listener) {
     return new InputReader(new EventHub(), policy, listener);
 }
 
diff --git a/services/inputflinger/reporter/InputReporter.cpp b/services/inputflinger/InputReporter.cpp
similarity index 93%
rename from services/inputflinger/reporter/InputReporter.cpp
rename to services/inputflinger/InputReporter.cpp
index b591d3f..8d3153c 100644
--- a/services/inputflinger/reporter/InputReporter.cpp
+++ b/services/inputflinger/InputReporter.cpp
@@ -27,15 +27,15 @@
 };
 
 void InputReporter::reportUnhandledKey(uint32_t sequenceNum) {
-    // do nothing
+  // do nothing
 }
 
 void InputReporter::reportDroppedKey(uint32_t sequenceNum) {
-    // do nothing
+  // do nothing
 }
 
 sp<InputReporterInterface> createInputReporter() {
-    return new InputReporter();
+  return new InputReporter();
 }
 
 } // namespace android
diff --git a/services/inputflinger/reader/TouchVideoDevice.cpp b/services/inputflinger/TouchVideoDevice.cpp
similarity index 84%
rename from services/inputflinger/reader/TouchVideoDevice.cpp
rename to services/inputflinger/TouchVideoDevice.cpp
index c075078..19c1313 100644
--- a/services/inputflinger/reader/TouchVideoDevice.cpp
+++ b/services/inputflinger/TouchVideoDevice.cpp
@@ -37,13 +37,10 @@
 namespace android {
 
 TouchVideoDevice::TouchVideoDevice(int fd, std::string&& name, std::string&& devicePath,
-                                   uint32_t height, uint32_t width,
-                                   const std::array<const int16_t*, NUM_BUFFERS>& readLocations)
-      : mFd(fd),
-        mName(std::move(name)),
-        mPath(std::move(devicePath)),
-        mHeight(height),
-        mWidth(width),
+        uint32_t height, uint32_t width,
+        const std::array<const int16_t*, NUM_BUFFERS>& readLocations) :
+        mFd(fd), mName(std::move(name)), mPath(std::move(devicePath)),
+        mHeight(height), mWidth(width),
         mReadLocations(readLocations) {
     mFrames.reserve(MAX_QUEUE_SIZE);
 };
@@ -63,11 +60,11 @@
     }
     if (!(cap.capabilities & V4L2_CAP_TOUCH)) {
         ALOGE("Capability V4L2_CAP_TOUCH is not present, can't use device for heatmap data. "
-              "Make sure device specifies V4L2_CAP_TOUCH");
+                "Make sure device specifies V4L2_CAP_TOUCH");
         return nullptr;
     }
-    ALOGI("Opening video device: driver = %s, card = %s, bus_info = %s, version = %i", cap.driver,
-          cap.card, cap.bus_info, cap.version);
+    ALOGI("Opening video device: driver = %s, card = %s, bus_info = %s, version = %i",
+            cap.driver, cap.card, cap.bus_info, cap.version);
     std::string name = reinterpret_cast<const char*>(cap.card);
 
     struct v4l2_input v4l2_input_struct;
@@ -80,7 +77,7 @@
 
     if (v4l2_input_struct.type != V4L2_INPUT_TYPE_TOUCH) {
         ALOGE("Video device does not provide touch data. "
-              "Make sure device specifies V4L2_INPUT_TYPE_TOUCH.");
+                "Make sure device specifies V4L2_INPUT_TYPE_TOUCH.");
         return nullptr;
     }
 
@@ -123,14 +120,14 @@
             return nullptr;
         }
         if (buf.length != height * width * sizeof(int16_t)) {
-            ALOGE("Unexpected value of buf.length = %i (offset = %" PRIu32 ")", buf.length,
-                  buf.m.offset);
+            ALOGE("Unexpected value of buf.length = %i (offset = %" PRIu32 ")",
+                    buf.length, buf.m.offset);
             return nullptr;
         }
 
-        readLocations[i] = static_cast<const int16_t*>(
-                mmap(nullptr /* start anywhere */, buf.length, PROT_READ /* required */,
-                     MAP_SHARED /* recommended */, fd.get(), buf.m.offset));
+        readLocations[i] = static_cast<const int16_t*>(mmap(nullptr /* start anywhere */,
+                buf.length, PROT_READ /* required */, MAP_SHARED /* recommended */,
+                fd.get(), buf.m.offset));
         if (readLocations[i] == MAP_FAILED) {
             ALOGE("%s: map failed: %s", __func__, strerror(errno));
             return nullptr;
@@ -153,9 +150,8 @@
         }
     }
     // Using 'new' to access a non-public constructor.
-    return std::unique_ptr<TouchVideoDevice>(new TouchVideoDevice(fd.release(), std::move(name),
-                                                                  std::move(devicePath), height,
-                                                                  width, readLocations));
+    return std::unique_ptr<TouchVideoDevice>(new TouchVideoDevice(
+            fd.release(), std::move(name), std::move(devicePath), height, width, readLocations));
 }
 
 size_t TouchVideoDevice::readAndQueueFrames() {
@@ -167,10 +163,10 @@
     }
     // Concatenate the vectors, then clip up to maximum size allowed
     mFrames.insert(mFrames.end(), std::make_move_iterator(frames.begin()),
-                   std::make_move_iterator(frames.end()));
+            std::make_move_iterator(frames.end()));
     if (mFrames.size() > MAX_QUEUE_SIZE) {
         ALOGE("More than %zu frames have been accumulated. Dropping %zu frames", MAX_QUEUE_SIZE,
-              mFrames.size() - MAX_QUEUE_SIZE);
+                mFrames.size() - MAX_QUEUE_SIZE);
         mFrames.erase(mFrames.begin(), mFrames.end() - MAX_QUEUE_SIZE);
     }
     return numFrames;
@@ -197,8 +193,8 @@
     if ((buf.flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) != V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) {
         // We use CLOCK_MONOTONIC for input events, so if the clocks don't match,
         // we can't compare timestamps. Just log a warning, since this is a driver issue
-        ALOGW("The timestamp %ld.%ld was not acquired using CLOCK_MONOTONIC", buf.timestamp.tv_sec,
-              buf.timestamp.tv_usec);
+        ALOGW("The timestamp %ld.%ld was not acquired using CLOCK_MONOTONIC",
+                buf.timestamp.tv_sec, buf.timestamp.tv_usec);
     }
     std::vector<int16_t> data(mHeight * mWidth);
     const int16_t* readFrom = mReadLocations[buf.index];
@@ -237,7 +233,7 @@
     }
     for (const int16_t* buffer : mReadLocations) {
         void* bufferAddress = static_cast<void*>(const_cast<int16_t*>(buffer));
-        result = munmap(bufferAddress, mHeight * mWidth * sizeof(int16_t));
+        result = munmap(bufferAddress,  mHeight * mWidth * sizeof(int16_t));
         if (result == -1) {
             ALOGE("%s: Couldn't unmap: [%s]", __func__, strerror(errno));
         }
@@ -246,9 +242,9 @@
 
 std::string TouchVideoDevice::dump() const {
     return StringPrintf("Video device %s (%s) : height=%" PRIu32 ", width=%" PRIu32
-                        ", fd=%i, hasValidFd=%s",
-                        mName.c_str(), mPath.c_str(), mHeight, mWidth, mFd.get(),
-                        hasValidFd() ? "true" : "false");
+            ", fd=%i, hasValidFd=%s",
+            mName.c_str(), mPath.c_str(), mHeight, mWidth, mFd.get(),
+            hasValidFd() ? "true" : "false");
 }
 
 } // namespace android
diff --git a/services/inputflinger/reader/include/TouchVideoDevice.h b/services/inputflinger/TouchVideoDevice.h
similarity index 92%
rename from services/inputflinger/reader/include/TouchVideoDevice.h
rename to services/inputflinger/TouchVideoDevice.h
index 5a32443..0e7e2ef 100644
--- a/services/inputflinger/reader/include/TouchVideoDevice.h
+++ b/services/inputflinger/TouchVideoDevice.h
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-#ifndef _UI_INPUTFLINGER_TOUCH_VIDEO_DEVICE_H
-#define _UI_INPUTFLINGER_TOUCH_VIDEO_DEVICE_H
+#ifndef _INPUTFLINGER_TOUCH_VIDEO_DEVICE_H
+#define _INPUTFLINGER_TOUCH_VIDEO_DEVICE_H
 
+#include <array>
 #include <android-base/unique_fd.h>
 #include <input/TouchVideoFrame.h>
-#include <stdint.h>
-#include <array>
 #include <optional>
+#include <stdint.h>
 #include <string>
 #include <vector>
 
@@ -109,9 +109,9 @@
      * The constructor is private because opening a v4l2 device requires many checks.
      * To get a new TouchVideoDevice, use 'create' instead.
      */
-    explicit TouchVideoDevice(int fd, std::string&& name, std::string&& devicePath, uint32_t height,
-                              uint32_t width,
-                              const std::array<const int16_t*, NUM_BUFFERS>& readLocations);
+    explicit TouchVideoDevice(int fd, std::string&& name, std::string&& devicePath,
+            uint32_t height, uint32_t width,
+            const std::array<const int16_t*, NUM_BUFFERS>& readLocations);
     /**
      * Read all currently available frames.
      */
@@ -121,7 +121,5 @@
      */
     std::optional<TouchVideoFrame> readFrame();
 };
-
 } // namespace android
-
-#endif // _UI_INPUTFLINGER_TOUCH_VIDEO_DEVICE_H
+#endif //_INPUTFLINGER_TOUCH_VIDEO_DEVICE_H
diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp
deleted file mode 100644
index b8c3a80..0000000
--- a/services/inputflinger/dispatcher/Android.bp
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (C) 2019 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.
-
-cc_library_static {
-    name: "libinputdispatcher",
-    defaults: ["inputflinger_defaults"],
-    srcs: [
-        "Connection.cpp",
-        "Entry.cpp",
-        "InjectionState.cpp",
-        "InputDispatcher.cpp",
-        "InputDispatcherFactory.cpp",
-        "InputDispatcherThread.cpp",
-        "InputState.cpp",
-        "InputTarget.cpp",
-        "Monitor.cpp",
-        "TouchState.cpp"
-    ],
-    shared_libs: [
-        "libbase",
-        "libcutils",
-        "libinput",
-        "libinputreporter",
-        "libinputflinger_base",
-        "liblog",
-        "libui",
-        "libutils",
-    ],
-
-    export_include_dirs: ["include"],
-}
diff --git a/services/inputflinger/dispatcher/CancelationOptions.h b/services/inputflinger/dispatcher/CancelationOptions.h
deleted file mode 100644
index 99e2108..0000000
--- a/services/inputflinger/dispatcher/CancelationOptions.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_CANCELLATIONOPTIONS_H
-#define _UI_INPUT_INPUTDISPATCHER_CANCELLATIONOPTIONS_H
-
-#include <optional>
-
-namespace android::inputdispatcher {
-
-/* Specifies which events are to be canceled and why. */
-struct CancelationOptions {
-    enum Mode {
-        CANCEL_ALL_EVENTS = 0,
-        CANCEL_POINTER_EVENTS = 1,
-        CANCEL_NON_POINTER_EVENTS = 2,
-        CANCEL_FALLBACK_EVENTS = 3,
-    };
-
-    // The criterion to use to determine which events should be canceled.
-    Mode mode;
-
-    // Descriptive reason for the cancelation.
-    const char* reason;
-
-    // The specific keycode of the key event to cancel, or nullopt to cancel any key event.
-    std::optional<int32_t> keyCode = std::nullopt;
-
-    // The specific device id of events to cancel, or nullopt to cancel events from any device.
-    std::optional<int32_t> deviceId = std::nullopt;
-
-    // The specific display id of events to cancel, or nullopt to cancel events on any display.
-    std::optional<int32_t> displayId = std::nullopt;
-
-    CancelationOptions(Mode mode, const char* reason) : mode(mode), reason(reason) {}
-};
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_INPUTDISPATCHER_CANCELLATIONOPTIONS_H
diff --git a/services/inputflinger/dispatcher/Connection.cpp b/services/inputflinger/dispatcher/Connection.cpp
deleted file mode 100644
index ef7f650..0000000
--- a/services/inputflinger/dispatcher/Connection.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Connection.h"
-
-#include "Entry.h"
-
-namespace android::inputdispatcher {
-
-Connection::Connection(const sp<InputChannel>& inputChannel, bool monitor)
-      : status(STATUS_NORMAL),
-        inputChannel(inputChannel),
-        monitor(monitor),
-        inputPublisher(inputChannel),
-        inputPublisherBlocked(false) {}
-
-Connection::~Connection() {}
-
-const std::string Connection::getWindowName() const {
-    if (inputChannel != nullptr) {
-        return inputChannel->getName();
-    }
-    if (monitor) {
-        return "monitor";
-    }
-    return "?";
-}
-
-const char* Connection::getStatusLabel() const {
-    switch (status) {
-        case STATUS_NORMAL:
-            return "NORMAL";
-        case STATUS_BROKEN:
-            return "BROKEN";
-        case STATUS_ZOMBIE:
-            return "ZOMBIE";
-        default:
-            return "UNKNOWN";
-    }
-}
-
-DispatchEntry* Connection::findWaitQueueEntry(uint32_t seq) {
-    for (DispatchEntry* entry = waitQueue.head; entry != nullptr; entry = entry->next) {
-        if (entry->seq == seq) {
-            return entry;
-        }
-    }
-    return nullptr;
-}
-
-} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/Connection.h b/services/inputflinger/dispatcher/Connection.h
deleted file mode 100644
index ed4eebd..0000000
--- a/services/inputflinger/dispatcher/Connection.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_CONNECTION_H
-#define _UI_INPUT_INPUTDISPATCHER_CONNECTION_H
-
-#include "InputState.h"
-#include "Queue.h"
-
-#include <input/InputTransport.h>
-#include <deque>
-
-namespace android::inputdispatcher {
-
-struct DispatchEntry;
-
-/* Manages the dispatch state associated with a single input channel. */
-class Connection : public RefBase {
-protected:
-    virtual ~Connection();
-
-public:
-    enum Status {
-        // Everything is peachy.
-        STATUS_NORMAL,
-        // An unrecoverable communication error has occurred.
-        STATUS_BROKEN,
-        // The input channel has been unregistered.
-        STATUS_ZOMBIE
-    };
-
-    Status status;
-    sp<InputChannel> inputChannel; // never null
-    bool monitor;
-    InputPublisher inputPublisher;
-    InputState inputState;
-
-    // True if the socket is full and no further events can be published until
-    // the application consumes some of the input.
-    bool inputPublisherBlocked;
-
-    // Queue of events that need to be published to the connection.
-    Queue<DispatchEntry> outboundQueue;
-
-    // Queue of events that have been published to the connection but that have not
-    // yet received a "finished" response from the application.
-    Queue<DispatchEntry> waitQueue;
-
-    explicit Connection(const sp<InputChannel>& inputChannel, bool monitor);
-
-    inline const std::string getInputChannelName() const { return inputChannel->getName(); }
-
-    const std::string getWindowName() const;
-    const char* getStatusLabel() const;
-
-    DispatchEntry* findWaitQueueEntry(uint32_t seq);
-};
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_INPUTDISPATCHER_CONNECTION_H
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
deleted file mode 100644
index 8d05640..0000000
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Entry.h"
-
-#include "Connection.h"
-
-#include <android-base/stringprintf.h>
-#include <cutils/atomic.h>
-#include <inttypes.h>
-
-using android::base::StringPrintf;
-
-namespace android::inputdispatcher {
-
-static std::string motionActionToString(int32_t action) {
-    // Convert MotionEvent action to string
-    switch (action & AMOTION_EVENT_ACTION_MASK) {
-        case AMOTION_EVENT_ACTION_DOWN:
-            return "DOWN";
-        case AMOTION_EVENT_ACTION_MOVE:
-            return "MOVE";
-        case AMOTION_EVENT_ACTION_UP:
-            return "UP";
-        case AMOTION_EVENT_ACTION_POINTER_DOWN:
-            return "POINTER_DOWN";
-        case AMOTION_EVENT_ACTION_POINTER_UP:
-            return "POINTER_UP";
-    }
-    return StringPrintf("%" PRId32, action);
-}
-
-static std::string keyActionToString(int32_t action) {
-    // Convert KeyEvent action to string
-    switch (action) {
-        case AKEY_EVENT_ACTION_DOWN:
-            return "DOWN";
-        case AKEY_EVENT_ACTION_UP:
-            return "UP";
-        case AKEY_EVENT_ACTION_MULTIPLE:
-            return "MULTIPLE";
-    }
-    return StringPrintf("%" PRId32, action);
-}
-
-// --- EventEntry ---
-
-EventEntry::EventEntry(uint32_t sequenceNum, int32_t type, nsecs_t eventTime, uint32_t policyFlags)
-      : sequenceNum(sequenceNum),
-        refCount(1),
-        type(type),
-        eventTime(eventTime),
-        policyFlags(policyFlags),
-        injectionState(nullptr),
-        dispatchInProgress(false) {}
-
-EventEntry::~EventEntry() {
-    releaseInjectionState();
-}
-
-void EventEntry::release() {
-    refCount -= 1;
-    if (refCount == 0) {
-        delete this;
-    } else {
-        ALOG_ASSERT(refCount > 0);
-    }
-}
-
-void EventEntry::releaseInjectionState() {
-    if (injectionState) {
-        injectionState->release();
-        injectionState = nullptr;
-    }
-}
-
-// --- ConfigurationChangedEntry ---
-
-ConfigurationChangedEntry::ConfigurationChangedEntry(uint32_t sequenceNum, nsecs_t eventTime)
-      : EventEntry(sequenceNum, TYPE_CONFIGURATION_CHANGED, eventTime, 0) {}
-
-ConfigurationChangedEntry::~ConfigurationChangedEntry() {}
-
-void ConfigurationChangedEntry::appendDescription(std::string& msg) const {
-    msg += StringPrintf("ConfigurationChangedEvent(), policyFlags=0x%08x", policyFlags);
-}
-
-// --- DeviceResetEntry ---
-
-DeviceResetEntry::DeviceResetEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId)
-      : EventEntry(sequenceNum, TYPE_DEVICE_RESET, eventTime, 0), deviceId(deviceId) {}
-
-DeviceResetEntry::~DeviceResetEntry() {}
-
-void DeviceResetEntry::appendDescription(std::string& msg) const {
-    msg += StringPrintf("DeviceResetEvent(deviceId=%d), policyFlags=0x%08x", deviceId, policyFlags);
-}
-
-// --- KeyEntry ---
-
-KeyEntry::KeyEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
-                   int32_t displayId, uint32_t policyFlags, int32_t action, int32_t flags,
-                   int32_t keyCode, int32_t scanCode, int32_t metaState, int32_t repeatCount,
-                   nsecs_t downTime)
-      : EventEntry(sequenceNum, TYPE_KEY, eventTime, policyFlags),
-        deviceId(deviceId),
-        source(source),
-        displayId(displayId),
-        action(action),
-        flags(flags),
-        keyCode(keyCode),
-        scanCode(scanCode),
-        metaState(metaState),
-        repeatCount(repeatCount),
-        downTime(downTime),
-        syntheticRepeat(false),
-        interceptKeyResult(KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN),
-        interceptKeyWakeupTime(0) {}
-
-KeyEntry::~KeyEntry() {}
-
-void KeyEntry::appendDescription(std::string& msg) const {
-    msg += StringPrintf("KeyEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32 ", action=%s, "
-                        "flags=0x%08x, keyCode=%d, scanCode=%d, metaState=0x%08x, "
-                        "repeatCount=%d), policyFlags=0x%08x",
-                        deviceId, source, displayId, keyActionToString(action).c_str(), flags,
-                        keyCode, scanCode, metaState, repeatCount, policyFlags);
-}
-
-void KeyEntry::recycle() {
-    releaseInjectionState();
-
-    dispatchInProgress = false;
-    syntheticRepeat = false;
-    interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
-    interceptKeyWakeupTime = 0;
-}
-
-// --- MotionEntry ---
-
-MotionEntry::MotionEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
-                         int32_t displayId, uint32_t policyFlags, int32_t action,
-                         int32_t actionButton, int32_t flags, int32_t metaState,
-                         int32_t buttonState, MotionClassification classification,
-                         int32_t edgeFlags, float xPrecision, float yPrecision, nsecs_t downTime,
-                         uint32_t pointerCount, const PointerProperties* pointerProperties,
-                         const PointerCoords* pointerCoords, float xOffset, float yOffset)
-      : EventEntry(sequenceNum, TYPE_MOTION, eventTime, policyFlags),
-        eventTime(eventTime),
-        deviceId(deviceId),
-        source(source),
-        displayId(displayId),
-        action(action),
-        actionButton(actionButton),
-        flags(flags),
-        metaState(metaState),
-        buttonState(buttonState),
-        classification(classification),
-        edgeFlags(edgeFlags),
-        xPrecision(xPrecision),
-        yPrecision(yPrecision),
-        downTime(downTime),
-        pointerCount(pointerCount) {
-    for (uint32_t i = 0; i < pointerCount; i++) {
-        this->pointerProperties[i].copyFrom(pointerProperties[i]);
-        this->pointerCoords[i].copyFrom(pointerCoords[i]);
-        if (xOffset || yOffset) {
-            this->pointerCoords[i].applyOffset(xOffset, yOffset);
-        }
-    }
-}
-
-MotionEntry::~MotionEntry() {}
-
-void MotionEntry::appendDescription(std::string& msg) const {
-    msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32
-                        ", action=%s, actionButton=0x%08x, flags=0x%08x, metaState=0x%08x, "
-                        "buttonState=0x%08x, "
-                        "classification=%s, edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, "
-                        "pointers=[",
-                        deviceId, source, displayId, motionActionToString(action).c_str(),
-                        actionButton, flags, metaState, buttonState,
-                        motionClassificationToString(classification), edgeFlags, xPrecision,
-                        yPrecision);
-
-    for (uint32_t i = 0; i < pointerCount; i++) {
-        if (i) {
-            msg += ", ";
-        }
-        msg += StringPrintf("%d: (%.1f, %.1f)", pointerProperties[i].id, pointerCoords[i].getX(),
-                            pointerCoords[i].getY());
-    }
-    msg += StringPrintf("]), policyFlags=0x%08x", policyFlags);
-}
-
-// --- DispatchEntry ---
-
-volatile int32_t DispatchEntry::sNextSeqAtomic;
-
-DispatchEntry::DispatchEntry(EventEntry* eventEntry, int32_t targetFlags, float xOffset,
-                             float yOffset, float globalScaleFactor, float windowXScale,
-                             float windowYScale)
-      : seq(nextSeq()),
-        eventEntry(eventEntry),
-        targetFlags(targetFlags),
-        xOffset(xOffset),
-        yOffset(yOffset),
-        globalScaleFactor(globalScaleFactor),
-        windowXScale(windowXScale),
-        windowYScale(windowYScale),
-        deliveryTime(0),
-        resolvedAction(0),
-        resolvedFlags(0) {
-    eventEntry->refCount += 1;
-}
-
-DispatchEntry::~DispatchEntry() {
-    eventEntry->release();
-}
-
-uint32_t DispatchEntry::nextSeq() {
-    // Sequence number 0 is reserved and will never be returned.
-    uint32_t seq;
-    do {
-        seq = android_atomic_inc(&sNextSeqAtomic);
-    } while (!seq);
-    return seq;
-}
-
-// --- CommandEntry ---
-
-CommandEntry::CommandEntry(Command command)
-      : command(command),
-        eventTime(0),
-        keyEntry(nullptr),
-        userActivityEventType(0),
-        seq(0),
-        handled(false) {}
-
-CommandEntry::~CommandEntry() {}
-
-} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
deleted file mode 100644
index b904caf..0000000
--- a/services/inputflinger/dispatcher/Entry.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_ENTRY_H
-#define _UI_INPUT_INPUTDISPATCHER_ENTRY_H
-
-#include "InjectionState.h"
-#include "InputTarget.h"
-
-#include <input/Input.h>
-#include <input/InputApplication.h>
-#include <stdint.h>
-#include <utils/Timers.h>
-#include <functional>
-#include <string>
-
-namespace android::inputdispatcher {
-
-template <typename T>
-struct Link {
-    T* next;
-    T* prev;
-
-protected:
-    inline Link() : next(nullptr), prev(nullptr) {}
-};
-
-struct EventEntry : Link<EventEntry> {
-    enum { TYPE_CONFIGURATION_CHANGED, TYPE_DEVICE_RESET, TYPE_KEY, TYPE_MOTION };
-
-    uint32_t sequenceNum;
-    mutable int32_t refCount;
-    int32_t type;
-    nsecs_t eventTime;
-    uint32_t policyFlags;
-    InjectionState* injectionState;
-
-    bool dispatchInProgress; // initially false, set to true while dispatching
-
-    inline bool isInjected() const { return injectionState != nullptr; }
-
-    void release();
-
-    virtual void appendDescription(std::string& msg) const = 0;
-
-protected:
-    EventEntry(uint32_t sequenceNum, int32_t type, nsecs_t eventTime, uint32_t policyFlags);
-    virtual ~EventEntry();
-    void releaseInjectionState();
-};
-
-struct ConfigurationChangedEntry : EventEntry {
-    explicit ConfigurationChangedEntry(uint32_t sequenceNum, nsecs_t eventTime);
-    virtual void appendDescription(std::string& msg) const;
-
-protected:
-    virtual ~ConfigurationChangedEntry();
-};
-
-struct DeviceResetEntry : EventEntry {
-    int32_t deviceId;
-
-    DeviceResetEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId);
-    virtual void appendDescription(std::string& msg) const;
-
-protected:
-    virtual ~DeviceResetEntry();
-};
-
-struct KeyEntry : EventEntry {
-    int32_t deviceId;
-    uint32_t source;
-    int32_t displayId;
-    int32_t action;
-    int32_t flags;
-    int32_t keyCode;
-    int32_t scanCode;
-    int32_t metaState;
-    int32_t repeatCount;
-    nsecs_t downTime;
-
-    bool syntheticRepeat; // set to true for synthetic key repeats
-
-    enum InterceptKeyResult {
-        INTERCEPT_KEY_RESULT_UNKNOWN,
-        INTERCEPT_KEY_RESULT_SKIP,
-        INTERCEPT_KEY_RESULT_CONTINUE,
-        INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER,
-    };
-    InterceptKeyResult interceptKeyResult; // set based on the interception result
-    nsecs_t interceptKeyWakeupTime;        // used with INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER
-
-    KeyEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
-             int32_t displayId, uint32_t policyFlags, int32_t action, int32_t flags,
-             int32_t keyCode, int32_t scanCode, int32_t metaState, int32_t repeatCount,
-             nsecs_t downTime);
-    virtual void appendDescription(std::string& msg) const;
-    void recycle();
-
-protected:
-    virtual ~KeyEntry();
-};
-
-struct MotionEntry : EventEntry {
-    nsecs_t eventTime;
-    int32_t deviceId;
-    uint32_t source;
-    int32_t displayId;
-    int32_t action;
-    int32_t actionButton;
-    int32_t flags;
-    int32_t metaState;
-    int32_t buttonState;
-    MotionClassification classification;
-    int32_t edgeFlags;
-    float xPrecision;
-    float yPrecision;
-    nsecs_t downTime;
-    uint32_t pointerCount;
-    PointerProperties pointerProperties[MAX_POINTERS];
-    PointerCoords pointerCoords[MAX_POINTERS];
-
-    MotionEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
-                int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
-                int32_t flags, int32_t metaState, int32_t buttonState,
-                MotionClassification classification, int32_t edgeFlags, float xPrecision,
-                float yPrecision, nsecs_t downTime, uint32_t pointerCount,
-                const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
-                float xOffset, float yOffset);
-    virtual void appendDescription(std::string& msg) const;
-
-protected:
-    virtual ~MotionEntry();
-};
-
-// Tracks the progress of dispatching a particular event to a particular connection.
-struct DispatchEntry : Link<DispatchEntry> {
-    const uint32_t seq; // unique sequence number, never 0
-
-    EventEntry* eventEntry; // the event to dispatch
-    int32_t targetFlags;
-    float xOffset;
-    float yOffset;
-    float globalScaleFactor;
-    float windowXScale = 1.0f;
-    float windowYScale = 1.0f;
-    nsecs_t deliveryTime; // time when the event was actually delivered
-
-    // Set to the resolved action and flags when the event is enqueued.
-    int32_t resolvedAction;
-    int32_t resolvedFlags;
-
-    DispatchEntry(EventEntry* eventEntry, int32_t targetFlags, float xOffset, float yOffset,
-                  float globalScaleFactor, float windowXScale, float windowYScale);
-    ~DispatchEntry();
-
-    inline bool hasForegroundTarget() const { return targetFlags & InputTarget::FLAG_FOREGROUND; }
-
-    inline bool isSplit() const { return targetFlags & InputTarget::FLAG_SPLIT; }
-
-private:
-    static volatile int32_t sNextSeqAtomic;
-
-    static uint32_t nextSeq();
-};
-
-class InputDispatcher;
-// A command entry captures state and behavior for an action to be performed in the
-// dispatch loop after the initial processing has taken place.  It is essentially
-// a kind of continuation used to postpone sensitive policy interactions to a point
-// in the dispatch loop where it is safe to release the lock (generally after finishing
-// the critical parts of the dispatch cycle).
-//
-// The special thing about commands is that they can voluntarily release and reacquire
-// the dispatcher lock at will.  Initially when the command starts running, the
-// dispatcher lock is held.  However, if the command needs to call into the policy to
-// do some work, it can release the lock, do the work, then reacquire the lock again
-// before returning.
-//
-// This mechanism is a bit clunky but it helps to preserve the invariant that the dispatch
-// never calls into the policy while holding its lock.
-//
-// Commands are implicitly 'LockedInterruptible'.
-struct CommandEntry;
-typedef void (InputDispatcher::*Command)(CommandEntry* commandEntry);
-
-class Connection;
-struct CommandEntry : Link<CommandEntry> {
-    explicit CommandEntry(Command command);
-    ~CommandEntry();
-
-    Command command;
-
-    // parameters for the command (usage varies by command)
-    sp<Connection> connection;
-    nsecs_t eventTime;
-    KeyEntry* keyEntry;
-    sp<InputApplicationHandle> inputApplicationHandle;
-    std::string reason;
-    int32_t userActivityEventType;
-    uint32_t seq;
-    bool handled;
-    sp<InputChannel> inputChannel;
-    sp<IBinder> oldToken;
-    sp<IBinder> newToken;
-};
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_INPUTDISPATCHER_ENTRY_H
diff --git a/services/inputflinger/dispatcher/InjectionState.cpp b/services/inputflinger/dispatcher/InjectionState.cpp
deleted file mode 100644
index b2d0a26..0000000
--- a/services/inputflinger/dispatcher/InjectionState.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "InjectionState.h"
-
-#include <log/log.h>
-
-namespace android::inputdispatcher {
-
-InjectionState::InjectionState(int32_t injectorPid, int32_t injectorUid)
-      : refCount(1),
-        injectorPid(injectorPid),
-        injectorUid(injectorUid),
-        injectionResult(INPUT_EVENT_INJECTION_PENDING),
-        injectionIsAsync(false),
-        pendingForegroundDispatches(0) {}
-
-InjectionState::~InjectionState() {}
-
-void InjectionState::release() {
-    refCount -= 1;
-    if (refCount == 0) {
-        delete this;
-    } else {
-        ALOG_ASSERT(refCount > 0);
-    }
-}
-
-} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InjectionState.h b/services/inputflinger/dispatcher/InjectionState.h
deleted file mode 100644
index 311a0f1..0000000
--- a/services/inputflinger/dispatcher/InjectionState.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_INJECTIONSTATE_H
-#define _UI_INPUT_INPUTDISPATCHER_INJECTIONSTATE_H
-
-#include "InputDispatcherInterface.h"
-
-#include <stdint.h>
-
-namespace android::inputdispatcher {
-
-/*
- * Constants used to determine the input event injection synchronization mode.
- */
-enum {
-    /* Injection is asynchronous and is assumed always to be successful. */
-    INPUT_EVENT_INJECTION_SYNC_NONE = 0,
-
-    /* Waits for previous events to be dispatched so that the input dispatcher can determine
-     * whether input event injection willbe permitted based on the current input focus.
-     * Does not wait for the input event to finish processing. */
-    INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1,
-
-    /* Waits for the input event to be completely processed. */
-    INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED = 2,
-};
-
-struct InjectionState {
-    mutable int32_t refCount;
-
-    int32_t injectorPid;
-    int32_t injectorUid;
-    int32_t injectionResult;             // initially INPUT_EVENT_INJECTION_PENDING
-    bool injectionIsAsync;               // set to true if injection is not waiting for the result
-    int32_t pendingForegroundDispatches; // the number of foreground dispatches in progress
-
-    InjectionState(int32_t injectorPid, int32_t injectorUid);
-    void release();
-
-private:
-    ~InjectionState();
-};
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_INPUTDISPATCHER_INJECTIONSTATE_H
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
deleted file mode 100644
index 4410008..0000000
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ /dev/null
@@ -1,4473 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#define LOG_TAG "InputDispatcher"
-#define ATRACE_TAG ATRACE_TAG_INPUT
-
-#define LOG_NDEBUG 0
-
-// Log detailed debug messages about each inbound event notification to the dispatcher.
-#define DEBUG_INBOUND_EVENT_DETAILS 0
-
-// Log detailed debug messages about each outbound event processed by the dispatcher.
-#define DEBUG_OUTBOUND_EVENT_DETAILS 0
-
-// Log debug messages about the dispatch cycle.
-#define DEBUG_DISPATCH_CYCLE 0
-
-// Log debug messages about registrations.
-#define DEBUG_REGISTRATION 0
-
-// Log debug messages about input event injection.
-#define DEBUG_INJECTION 0
-
-// Log debug messages about input focus tracking.
-#define DEBUG_FOCUS 0
-
-// Log debug messages about the app switch latency optimization.
-#define DEBUG_APP_SWITCH 0
-
-// Log debug messages about hover events.
-#define DEBUG_HOVER 0
-
-#include "InputDispatcher.h"
-
-#include "Connection.h"
-
-#include <errno.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <stddef.h>
-#include <time.h>
-#include <unistd.h>
-#include <sstream>
-
-#include <android-base/chrono_utils.h>
-#include <android-base/stringprintf.h>
-#include <binder/Binder.h>
-#include <log/log.h>
-#include <powermanager/PowerManager.h>
-#include <utils/Trace.h>
-
-#define INDENT "  "
-#define INDENT2 "    "
-#define INDENT3 "      "
-#define INDENT4 "        "
-
-using android::base::StringPrintf;
-
-namespace android::inputdispatcher {
-
-// Default input dispatching timeout if there is no focused application or paused window
-// from which to determine an appropriate dispatching timeout.
-constexpr nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
-
-// Amount of time to allow for all pending events to be processed when an app switch
-// key is on the way.  This is used to preempt input dispatch and drop input events
-// when an application takes too long to respond and the user has pressed an app switch key.
-constexpr nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
-
-// Amount of time to allow for an event to be dispatched (measured since its eventTime)
-// before considering it stale and dropping it.
-constexpr nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec
-
-// Amount of time to allow touch events to be streamed out to a connection before requiring
-// that the first event be finished.  This value extends the ANR timeout by the specified
-// amount.  For example, if streaming is allowed to get ahead by one second relative to the
-// queue of waiting unfinished events, then ANRs will similarly be delayed by one second.
-constexpr nsecs_t STREAM_AHEAD_EVENT_TIMEOUT = 500 * 1000000LL; // 0.5sec
-
-// Log a warning when an event takes longer than this to process, even if an ANR does not occur.
-constexpr nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec
-
-// Log a warning when an interception call takes longer than this to process.
-constexpr std::chrono::milliseconds SLOW_INTERCEPTION_THRESHOLD = 50ms;
-
-// Number of recent events to keep for debugging purposes.
-constexpr size_t RECENT_QUEUE_MAX_SIZE = 10;
-
-static inline nsecs_t now() {
-    return systemTime(SYSTEM_TIME_MONOTONIC);
-}
-
-static inline const char* toString(bool value) {
-    return value ? "true" : "false";
-}
-
-static inline int32_t getMotionEventActionPointerIndex(int32_t action) {
-    return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
-            AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-}
-
-static bool isValidKeyAction(int32_t action) {
-    switch (action) {
-        case AKEY_EVENT_ACTION_DOWN:
-        case AKEY_EVENT_ACTION_UP:
-            return true;
-        default:
-            return false;
-    }
-}
-
-static bool validateKeyEvent(int32_t action) {
-    if (!isValidKeyAction(action)) {
-        ALOGE("Key event has invalid action code 0x%x", action);
-        return false;
-    }
-    return true;
-}
-
-static bool isValidMotionAction(int32_t action, int32_t actionButton, int32_t pointerCount) {
-    switch (action & AMOTION_EVENT_ACTION_MASK) {
-        case AMOTION_EVENT_ACTION_DOWN:
-        case AMOTION_EVENT_ACTION_UP:
-        case AMOTION_EVENT_ACTION_CANCEL:
-        case AMOTION_EVENT_ACTION_MOVE:
-        case AMOTION_EVENT_ACTION_OUTSIDE:
-        case AMOTION_EVENT_ACTION_HOVER_ENTER:
-        case AMOTION_EVENT_ACTION_HOVER_MOVE:
-        case AMOTION_EVENT_ACTION_HOVER_EXIT:
-        case AMOTION_EVENT_ACTION_SCROLL:
-            return true;
-        case AMOTION_EVENT_ACTION_POINTER_DOWN:
-        case AMOTION_EVENT_ACTION_POINTER_UP: {
-            int32_t index = getMotionEventActionPointerIndex(action);
-            return index >= 0 && index < pointerCount;
-        }
-        case AMOTION_EVENT_ACTION_BUTTON_PRESS:
-        case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
-            return actionButton != 0;
-        default:
-            return false;
-    }
-}
-
-static bool validateMotionEvent(int32_t action, int32_t actionButton, size_t pointerCount,
-                                const PointerProperties* pointerProperties) {
-    if (!isValidMotionAction(action, actionButton, pointerCount)) {
-        ALOGE("Motion event has invalid action code 0x%x", action);
-        return false;
-    }
-    if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
-        ALOGE("Motion event has invalid pointer count %zu; value must be between 1 and %d.",
-              pointerCount, MAX_POINTERS);
-        return false;
-    }
-    BitSet32 pointerIdBits;
-    for (size_t i = 0; i < pointerCount; i++) {
-        int32_t id = pointerProperties[i].id;
-        if (id < 0 || id > MAX_POINTER_ID) {
-            ALOGE("Motion event has invalid pointer id %d; value must be between 0 and %d", id,
-                  MAX_POINTER_ID);
-            return false;
-        }
-        if (pointerIdBits.hasBit(id)) {
-            ALOGE("Motion event has duplicate pointer id %d", id);
-            return false;
-        }
-        pointerIdBits.markBit(id);
-    }
-    return true;
-}
-
-static void dumpRegion(std::string& dump, const Region& region) {
-    if (region.isEmpty()) {
-        dump += "<empty>";
-        return;
-    }
-
-    bool first = true;
-    Region::const_iterator cur = region.begin();
-    Region::const_iterator const tail = region.end();
-    while (cur != tail) {
-        if (first) {
-            first = false;
-        } else {
-            dump += "|";
-        }
-        dump += StringPrintf("[%d,%d][%d,%d]", cur->left, cur->top, cur->right, cur->bottom);
-        cur++;
-    }
-}
-
-template <typename T, typename U>
-static T getValueByKey(std::unordered_map<U, T>& map, U key) {
-    typename std::unordered_map<U, T>::const_iterator it = map.find(key);
-    return it != map.end() ? it->second : T{};
-}
-
-// --- InputDispatcher ---
-
-InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
-      : mPolicy(policy),
-        mPendingEvent(nullptr),
-        mLastDropReason(DROP_REASON_NOT_DROPPED),
-        mAppSwitchSawKeyDown(false),
-        mAppSwitchDueTime(LONG_LONG_MAX),
-        mNextUnblockedEvent(nullptr),
-        mDispatchEnabled(false),
-        mDispatchFrozen(false),
-        mInputFilterEnabled(false),
-        mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
-        mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
-    mLooper = new Looper(false);
-    mReporter = createInputReporter();
-
-    mKeyRepeatState.lastKeyEntry = nullptr;
-
-    policy->getDispatcherConfiguration(&mConfig);
-}
-
-InputDispatcher::~InputDispatcher() {
-    { // acquire lock
-        std::scoped_lock _l(mLock);
-
-        resetKeyRepeatLocked();
-        releasePendingEventLocked();
-        drainInboundQueueLocked();
-    }
-
-    while (mConnectionsByFd.size() != 0) {
-        unregisterInputChannel(mConnectionsByFd.valueAt(0)->inputChannel);
-    }
-}
-
-void InputDispatcher::dispatchOnce() {
-    nsecs_t nextWakeupTime = LONG_LONG_MAX;
-    { // acquire lock
-        std::scoped_lock _l(mLock);
-        mDispatcherIsAlive.notify_all();
-
-        // Run a dispatch loop if there are no pending commands.
-        // The dispatch loop might enqueue commands to run afterwards.
-        if (!haveCommandsLocked()) {
-            dispatchOnceInnerLocked(&nextWakeupTime);
-        }
-
-        // Run all pending commands if there are any.
-        // If any commands were run then force the next poll to wake up immediately.
-        if (runCommandsLockedInterruptible()) {
-            nextWakeupTime = LONG_LONG_MIN;
-        }
-    } // release lock
-
-    // Wait for callback or timeout or wake.  (make sure we round up, not down)
-    nsecs_t currentTime = now();
-    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
-    mLooper->pollOnce(timeoutMillis);
-}
-
-void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
-    nsecs_t currentTime = now();
-
-    // Reset the key repeat timer whenever normal dispatch is suspended while the
-    // device is in a non-interactive state.  This is to ensure that we abort a key
-    // repeat if the device is just coming out of sleep.
-    if (!mDispatchEnabled) {
-        resetKeyRepeatLocked();
-    }
-
-    // If dispatching is frozen, do not process timeouts or try to deliver any new events.
-    if (mDispatchFrozen) {
-#if DEBUG_FOCUS
-        ALOGD("Dispatch frozen.  Waiting some more.");
-#endif
-        return;
-    }
-
-    // Optimize latency of app switches.
-    // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
-    // been pressed.  When it expires, we preempt dispatch and drop all other pending events.
-    bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
-    if (mAppSwitchDueTime < *nextWakeupTime) {
-        *nextWakeupTime = mAppSwitchDueTime;
-    }
-
-    // Ready to start a new event.
-    // If we don't already have a pending event, go grab one.
-    if (!mPendingEvent) {
-        if (mInboundQueue.isEmpty()) {
-            if (isAppSwitchDue) {
-                // The inbound queue is empty so the app switch key we were waiting
-                // for will never arrive.  Stop waiting for it.
-                resetPendingAppSwitchLocked(false);
-                isAppSwitchDue = false;
-            }
-
-            // Synthesize a key repeat if appropriate.
-            if (mKeyRepeatState.lastKeyEntry) {
-                if (currentTime >= mKeyRepeatState.nextRepeatTime) {
-                    mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
-                } else {
-                    if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
-                        *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
-                    }
-                }
-            }
-
-            // Nothing to do if there is no pending event.
-            if (!mPendingEvent) {
-                return;
-            }
-        } else {
-            // Inbound queue has at least one entry.
-            mPendingEvent = mInboundQueue.dequeueAtHead();
-            traceInboundQueueLengthLocked();
-        }
-
-        // Poke user activity for this event.
-        if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
-            pokeUserActivityLocked(mPendingEvent);
-        }
-
-        // Get ready to dispatch the event.
-        resetANRTimeoutsLocked();
-    }
-
-    // Now we have an event to dispatch.
-    // All events are eventually dequeued and processed this way, even if we intend to drop them.
-    ALOG_ASSERT(mPendingEvent != nullptr);
-    bool done = false;
-    DropReason dropReason = DROP_REASON_NOT_DROPPED;
-    if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
-        dropReason = DROP_REASON_POLICY;
-    } else if (!mDispatchEnabled) {
-        dropReason = DROP_REASON_DISABLED;
-    }
-
-    if (mNextUnblockedEvent == mPendingEvent) {
-        mNextUnblockedEvent = nullptr;
-    }
-
-    switch (mPendingEvent->type) {
-        case EventEntry::TYPE_CONFIGURATION_CHANGED: {
-            ConfigurationChangedEntry* typedEntry =
-                    static_cast<ConfigurationChangedEntry*>(mPendingEvent);
-            done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
-            dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
-            break;
-        }
-
-        case EventEntry::TYPE_DEVICE_RESET: {
-            DeviceResetEntry* typedEntry = static_cast<DeviceResetEntry*>(mPendingEvent);
-            done = dispatchDeviceResetLocked(currentTime, typedEntry);
-            dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
-            break;
-        }
-
-        case EventEntry::TYPE_KEY: {
-            KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
-            if (isAppSwitchDue) {
-                if (isAppSwitchKeyEvent(typedEntry)) {
-                    resetPendingAppSwitchLocked(true);
-                    isAppSwitchDue = false;
-                } else if (dropReason == DROP_REASON_NOT_DROPPED) {
-                    dropReason = DROP_REASON_APP_SWITCH;
-                }
-            }
-            if (dropReason == DROP_REASON_NOT_DROPPED && isStaleEvent(currentTime, typedEntry)) {
-                dropReason = DROP_REASON_STALE;
-            }
-            if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
-                dropReason = DROP_REASON_BLOCKED;
-            }
-            done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
-            break;
-        }
-
-        case EventEntry::TYPE_MOTION: {
-            MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
-            if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
-                dropReason = DROP_REASON_APP_SWITCH;
-            }
-            if (dropReason == DROP_REASON_NOT_DROPPED && isStaleEvent(currentTime, typedEntry)) {
-                dropReason = DROP_REASON_STALE;
-            }
-            if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
-                dropReason = DROP_REASON_BLOCKED;
-            }
-            done = dispatchMotionLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
-            break;
-        }
-
-        default:
-            ALOG_ASSERT(false);
-            break;
-    }
-
-    if (done) {
-        if (dropReason != DROP_REASON_NOT_DROPPED) {
-            dropInboundEventLocked(mPendingEvent, dropReason);
-        }
-        mLastDropReason = dropReason;
-
-        releasePendingEventLocked();
-        *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
-    }
-}
-
-bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
-    bool needWake = mInboundQueue.isEmpty();
-    mInboundQueue.enqueueAtTail(entry);
-    traceInboundQueueLengthLocked();
-
-    switch (entry->type) {
-        case EventEntry::TYPE_KEY: {
-            // Optimize app switch latency.
-            // If the application takes too long to catch up then we drop all events preceding
-            // the app switch key.
-            KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
-            if (isAppSwitchKeyEvent(keyEntry)) {
-                if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
-                    mAppSwitchSawKeyDown = true;
-                } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
-                    if (mAppSwitchSawKeyDown) {
-#if DEBUG_APP_SWITCH
-                        ALOGD("App switch is pending!");
-#endif
-                        mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
-                        mAppSwitchSawKeyDown = false;
-                        needWake = true;
-                    }
-                }
-            }
-            break;
-        }
-
-        case EventEntry::TYPE_MOTION: {
-            // Optimize case where the current application is unresponsive and the user
-            // decides to touch a window in a different application.
-            // If the application takes too long to catch up then we drop all events preceding
-            // the touch into the other window.
-            MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
-            if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN &&
-                (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) &&
-                mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY &&
-                mInputTargetWaitApplicationToken != nullptr) {
-                int32_t displayId = motionEntry->displayId;
-                int32_t x =
-                        int32_t(motionEntry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
-                int32_t y =
-                        int32_t(motionEntry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
-                sp<InputWindowHandle> touchedWindowHandle =
-                        findTouchedWindowAtLocked(displayId, x, y);
-                if (touchedWindowHandle != nullptr &&
-                    touchedWindowHandle->getApplicationToken() !=
-                            mInputTargetWaitApplicationToken) {
-                    // User touched a different application than the one we are waiting on.
-                    // Flag the event, and start pruning the input queue.
-                    mNextUnblockedEvent = motionEntry;
-                    needWake = true;
-                }
-            }
-            break;
-        }
-    }
-
-    return needWake;
-}
-
-void InputDispatcher::addRecentEventLocked(EventEntry* entry) {
-    entry->refCount += 1;
-    mRecentQueue.enqueueAtTail(entry);
-    if (mRecentQueue.count() > RECENT_QUEUE_MAX_SIZE) {
-        mRecentQueue.dequeueAtHead()->release();
-    }
-}
-
-sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, int32_t x,
-                                                                 int32_t y, bool addOutsideTargets,
-                                                                 bool addPortalWindows) {
-    // Traverse windows from front to back to find touched window.
-    const std::vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
-    for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
-        const InputWindowInfo* windowInfo = windowHandle->getInfo();
-        if (windowInfo->displayId == displayId) {
-            int32_t flags = windowInfo->layoutParamsFlags;
-
-            if (windowInfo->visible) {
-                if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
-                    bool isTouchModal = (flags &
-                                         (InputWindowInfo::FLAG_NOT_FOCUSABLE |
-                                          InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
-                    if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
-                        int32_t portalToDisplayId = windowInfo->portalToDisplayId;
-                        if (portalToDisplayId != ADISPLAY_ID_NONE &&
-                            portalToDisplayId != displayId) {
-                            if (addPortalWindows) {
-                                // For the monitoring channels of the display.
-                                mTempTouchState.addPortalWindow(windowHandle);
-                            }
-                            return findTouchedWindowAtLocked(portalToDisplayId, x, y,
-                                                             addOutsideTargets, addPortalWindows);
-                        }
-                        // Found window.
-                        return windowHandle;
-                    }
-                }
-
-                if (addOutsideTargets && (flags & InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH)) {
-                    mTempTouchState.addOrUpdateWindow(windowHandle,
-                                                      InputTarget::FLAG_DISPATCH_AS_OUTSIDE,
-                                                      BitSet32(0));
-                }
-            }
-        }
-    }
-    return nullptr;
-}
-
-std::vector<TouchedMonitor> InputDispatcher::findTouchedGestureMonitorsLocked(
-        int32_t displayId, const std::vector<sp<InputWindowHandle>>& portalWindows) {
-    std::vector<TouchedMonitor> touchedMonitors;
-
-    std::vector<Monitor> monitors = getValueByKey(mGestureMonitorsByDisplay, displayId);
-    addGestureMonitors(monitors, touchedMonitors);
-    for (const sp<InputWindowHandle>& portalWindow : portalWindows) {
-        const InputWindowInfo* windowInfo = portalWindow->getInfo();
-        monitors = getValueByKey(mGestureMonitorsByDisplay, windowInfo->portalToDisplayId);
-        addGestureMonitors(monitors, touchedMonitors, -windowInfo->frameLeft,
-                           -windowInfo->frameTop);
-    }
-    return touchedMonitors;
-}
-
-void InputDispatcher::addGestureMonitors(const std::vector<Monitor>& monitors,
-                                         std::vector<TouchedMonitor>& outTouchedMonitors,
-                                         float xOffset, float yOffset) {
-    if (monitors.empty()) {
-        return;
-    }
-    outTouchedMonitors.reserve(monitors.size() + outTouchedMonitors.size());
-    for (const Monitor& monitor : monitors) {
-        outTouchedMonitors.emplace_back(monitor, xOffset, yOffset);
-    }
-}
-
-void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
-    const char* reason;
-    switch (dropReason) {
-        case DROP_REASON_POLICY:
-#if DEBUG_INBOUND_EVENT_DETAILS
-            ALOGD("Dropped event because policy consumed it.");
-#endif
-            reason = "inbound event was dropped because the policy consumed it";
-            break;
-        case DROP_REASON_DISABLED:
-            if (mLastDropReason != DROP_REASON_DISABLED) {
-                ALOGI("Dropped event because input dispatch is disabled.");
-            }
-            reason = "inbound event was dropped because input dispatch is disabled";
-            break;
-        case DROP_REASON_APP_SWITCH:
-            ALOGI("Dropped event because of pending overdue app switch.");
-            reason = "inbound event was dropped because of pending overdue app switch";
-            break;
-        case DROP_REASON_BLOCKED:
-            ALOGI("Dropped event because the current application is not responding and the user "
-                  "has started interacting with a different application.");
-            reason = "inbound event was dropped because the current application is not responding "
-                     "and the user has started interacting with a different application";
-            break;
-        case DROP_REASON_STALE:
-            ALOGI("Dropped event because it is stale.");
-            reason = "inbound event was dropped because it is stale";
-            break;
-        default:
-            ALOG_ASSERT(false);
-            return;
-    }
-
-    switch (entry->type) {
-        case EventEntry::TYPE_KEY: {
-            CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason);
-            synthesizeCancelationEventsForAllConnectionsLocked(options);
-            break;
-        }
-        case EventEntry::TYPE_MOTION: {
-            MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
-            if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
-                CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, reason);
-                synthesizeCancelationEventsForAllConnectionsLocked(options);
-            } else {
-                CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason);
-                synthesizeCancelationEventsForAllConnectionsLocked(options);
-            }
-            break;
-        }
-    }
-}
-
-static bool isAppSwitchKeyCode(int32_t keyCode) {
-    return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL ||
-            keyCode == AKEYCODE_APP_SWITCH;
-}
-
-bool InputDispatcher::isAppSwitchKeyEvent(KeyEntry* keyEntry) {
-    return !(keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) && isAppSwitchKeyCode(keyEntry->keyCode) &&
-            (keyEntry->policyFlags & POLICY_FLAG_TRUSTED) &&
-            (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
-}
-
-bool InputDispatcher::isAppSwitchPendingLocked() {
-    return mAppSwitchDueTime != LONG_LONG_MAX;
-}
-
-void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
-    mAppSwitchDueTime = LONG_LONG_MAX;
-
-#if DEBUG_APP_SWITCH
-    if (handled) {
-        ALOGD("App switch has arrived.");
-    } else {
-        ALOGD("App switch was abandoned.");
-    }
-#endif
-}
-
-bool InputDispatcher::isStaleEvent(nsecs_t currentTime, EventEntry* entry) {
-    return currentTime - entry->eventTime >= STALE_EVENT_TIMEOUT;
-}
-
-bool InputDispatcher::haveCommandsLocked() const {
-    return !mCommandQueue.isEmpty();
-}
-
-bool InputDispatcher::runCommandsLockedInterruptible() {
-    if (mCommandQueue.isEmpty()) {
-        return false;
-    }
-
-    do {
-        CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
-
-        Command command = commandEntry->command;
-        (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
-
-        commandEntry->connection.clear();
-        delete commandEntry;
-    } while (!mCommandQueue.isEmpty());
-    return true;
-}
-
-CommandEntry* InputDispatcher::postCommandLocked(Command command) {
-    CommandEntry* commandEntry = new CommandEntry(command);
-    mCommandQueue.enqueueAtTail(commandEntry);
-    return commandEntry;
-}
-
-void InputDispatcher::drainInboundQueueLocked() {
-    while (!mInboundQueue.isEmpty()) {
-        EventEntry* entry = mInboundQueue.dequeueAtHead();
-        releaseInboundEventLocked(entry);
-    }
-    traceInboundQueueLengthLocked();
-}
-
-void InputDispatcher::releasePendingEventLocked() {
-    if (mPendingEvent) {
-        resetANRTimeoutsLocked();
-        releaseInboundEventLocked(mPendingEvent);
-        mPendingEvent = nullptr;
-    }
-}
-
-void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
-    InjectionState* injectionState = entry->injectionState;
-    if (injectionState && injectionState->injectionResult == INPUT_EVENT_INJECTION_PENDING) {
-#if DEBUG_DISPATCH_CYCLE
-        ALOGD("Injected inbound event was dropped.");
-#endif
-        setInjectionResult(entry, INPUT_EVENT_INJECTION_FAILED);
-    }
-    if (entry == mNextUnblockedEvent) {
-        mNextUnblockedEvent = nullptr;
-    }
-    addRecentEventLocked(entry);
-    entry->release();
-}
-
-void InputDispatcher::resetKeyRepeatLocked() {
-    if (mKeyRepeatState.lastKeyEntry) {
-        mKeyRepeatState.lastKeyEntry->release();
-        mKeyRepeatState.lastKeyEntry = nullptr;
-    }
-}
-
-KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t currentTime) {
-    KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
-
-    // Reuse the repeated key entry if it is otherwise unreferenced.
-    uint32_t policyFlags = entry->policyFlags &
-            (POLICY_FLAG_RAW_MASK | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED);
-    if (entry->refCount == 1) {
-        entry->recycle();
-        entry->eventTime = currentTime;
-        entry->policyFlags = policyFlags;
-        entry->repeatCount += 1;
-    } else {
-        KeyEntry* newEntry =
-                new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime, entry->deviceId,
-                             entry->source, entry->displayId, policyFlags, entry->action,
-                             entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
-                             entry->repeatCount + 1, entry->downTime);
-
-        mKeyRepeatState.lastKeyEntry = newEntry;
-        entry->release();
-
-        entry = newEntry;
-    }
-    entry->syntheticRepeat = true;
-
-    // Increment reference count since we keep a reference to the event in
-    // mKeyRepeatState.lastKeyEntry in addition to the one we return.
-    entry->refCount += 1;
-
-    mKeyRepeatState.nextRepeatTime = currentTime + mConfig.keyRepeatDelay;
-    return entry;
-}
-
-bool InputDispatcher::dispatchConfigurationChangedLocked(nsecs_t currentTime,
-                                                         ConfigurationChangedEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-    ALOGD("dispatchConfigurationChanged - eventTime=%" PRId64, entry->eventTime);
-#endif
-
-    // Reset key repeating in case a keyboard device was added or removed or something.
-    resetKeyRepeatLocked();
-
-    // Enqueue a command to run outside the lock to tell the policy that the configuration changed.
-    CommandEntry* commandEntry =
-            postCommandLocked(&InputDispatcher::doNotifyConfigurationChangedLockedInterruptible);
-    commandEntry->eventTime = entry->eventTime;
-    return true;
-}
-
-bool InputDispatcher::dispatchDeviceResetLocked(nsecs_t currentTime, DeviceResetEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-    ALOGD("dispatchDeviceReset - eventTime=%" PRId64 ", deviceId=%d", entry->eventTime,
-          entry->deviceId);
-#endif
-
-    CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS, "device was reset");
-    options.deviceId = entry->deviceId;
-    synthesizeCancelationEventsForAllConnectionsLocked(options);
-    return true;
-}
-
-bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
-                                        DropReason* dropReason, nsecs_t* nextWakeupTime) {
-    // Preprocessing.
-    if (!entry->dispatchInProgress) {
-        if (entry->repeatCount == 0 && entry->action == AKEY_EVENT_ACTION_DOWN &&
-            (entry->policyFlags & POLICY_FLAG_TRUSTED) &&
-            (!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) {
-            if (mKeyRepeatState.lastKeyEntry &&
-                mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
-                // We have seen two identical key downs in a row which indicates that the device
-                // driver is automatically generating key repeats itself.  We take note of the
-                // repeat here, but we disable our own next key repeat timer since it is clear that
-                // we will not need to synthesize key repeats ourselves.
-                entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
-                resetKeyRepeatLocked();
-                mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
-            } else {
-                // Not a repeat.  Save key down state in case we do see a repeat later.
-                resetKeyRepeatLocked();
-                mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout;
-            }
-            mKeyRepeatState.lastKeyEntry = entry;
-            entry->refCount += 1;
-        } else if (!entry->syntheticRepeat) {
-            resetKeyRepeatLocked();
-        }
-
-        if (entry->repeatCount == 1) {
-            entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
-        } else {
-            entry->flags &= ~AKEY_EVENT_FLAG_LONG_PRESS;
-        }
-
-        entry->dispatchInProgress = true;
-
-        logOutboundKeyDetails("dispatchKey - ", entry);
-    }
-
-    // Handle case where the policy asked us to try again later last time.
-    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
-        if (currentTime < entry->interceptKeyWakeupTime) {
-            if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
-                *nextWakeupTime = entry->interceptKeyWakeupTime;
-            }
-            return false; // wait until next wakeup
-        }
-        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
-        entry->interceptKeyWakeupTime = 0;
-    }
-
-    // Give the policy a chance to intercept the key.
-    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
-        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
-            CommandEntry* commandEntry = postCommandLocked(
-                    &InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
-            sp<InputWindowHandle> focusedWindowHandle =
-                    getValueByKey(mFocusedWindowHandlesByDisplay, getTargetDisplayId(entry));
-            if (focusedWindowHandle != nullptr) {
-                commandEntry->inputChannel = getInputChannelLocked(focusedWindowHandle->getToken());
-            }
-            commandEntry->keyEntry = entry;
-            entry->refCount += 1;
-            return false; // wait for the command to run
-        } else {
-            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
-        }
-    } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
-        if (*dropReason == DROP_REASON_NOT_DROPPED) {
-            *dropReason = DROP_REASON_POLICY;
-        }
-    }
-
-    // Clean up if dropping the event.
-    if (*dropReason != DROP_REASON_NOT_DROPPED) {
-        setInjectionResult(entry,
-                           *dropReason == DROP_REASON_POLICY ? INPUT_EVENT_INJECTION_SUCCEEDED
-                                                             : INPUT_EVENT_INJECTION_FAILED);
-        mReporter->reportDroppedKey(entry->sequenceNum);
-        return true;
-    }
-
-    // Identify targets.
-    std::vector<InputTarget> inputTargets;
-    int32_t injectionResult =
-            findFocusedWindowTargetsLocked(currentTime, entry, inputTargets, nextWakeupTime);
-    if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
-        return false;
-    }
-
-    setInjectionResult(entry, injectionResult);
-    if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
-        return true;
-    }
-
-    // Add monitor channels from event's or focused display.
-    addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(entry));
-
-    // Dispatch the key.
-    dispatchEventLocked(currentTime, entry, inputTargets);
-    return true;
-}
-
-void InputDispatcher::logOutboundKeyDetails(const char* prefix, const KeyEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-    ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32 ", "
-          "policyFlags=0x%x, action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, "
-          "metaState=0x%x, repeatCount=%d, downTime=%" PRId64,
-          prefix, entry->eventTime, entry->deviceId, entry->source, entry->displayId,
-          entry->policyFlags, entry->action, entry->flags, entry->keyCode, entry->scanCode,
-          entry->metaState, entry->repeatCount, entry->downTime);
-#endif
-}
-
-bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, MotionEntry* entry,
-                                           DropReason* dropReason, nsecs_t* nextWakeupTime) {
-    ATRACE_CALL();
-    // Preprocessing.
-    if (!entry->dispatchInProgress) {
-        entry->dispatchInProgress = true;
-
-        logOutboundMotionDetails("dispatchMotion - ", entry);
-    }
-
-    // Clean up if dropping the event.
-    if (*dropReason != DROP_REASON_NOT_DROPPED) {
-        setInjectionResult(entry,
-                           *dropReason == DROP_REASON_POLICY ? INPUT_EVENT_INJECTION_SUCCEEDED
-                                                             : INPUT_EVENT_INJECTION_FAILED);
-        return true;
-    }
-
-    bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
-
-    // Identify targets.
-    std::vector<InputTarget> inputTargets;
-
-    bool conflictingPointerActions = false;
-    int32_t injectionResult;
-    if (isPointerEvent) {
-        // Pointer event.  (eg. touchscreen)
-        injectionResult =
-                findTouchedWindowTargetsLocked(currentTime, entry, inputTargets, nextWakeupTime,
-                                               &conflictingPointerActions);
-    } else {
-        // Non touch event.  (eg. trackball)
-        injectionResult =
-                findFocusedWindowTargetsLocked(currentTime, entry, inputTargets, nextWakeupTime);
-    }
-    if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
-        return false;
-    }
-
-    setInjectionResult(entry, injectionResult);
-    if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
-        if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
-            CancelationOptions::Mode mode(isPointerEvent
-                                                  ? CancelationOptions::CANCEL_POINTER_EVENTS
-                                                  : CancelationOptions::CANCEL_NON_POINTER_EVENTS);
-            CancelationOptions options(mode, "input event injection failed");
-            synthesizeCancelationEventsForMonitorsLocked(options);
-        }
-        return true;
-    }
-
-    // Add monitor channels from event's or focused display.
-    addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(entry));
-
-    if (isPointerEvent) {
-        ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(entry->displayId);
-        if (stateIndex >= 0) {
-            const TouchState& state = mTouchStatesByDisplay.valueAt(stateIndex);
-            if (!state.portalWindows.empty()) {
-                // The event has gone through these portal windows, so we add monitoring targets of
-                // the corresponding displays as well.
-                for (size_t i = 0; i < state.portalWindows.size(); i++) {
-                    const InputWindowInfo* windowInfo = state.portalWindows[i]->getInfo();
-                    addGlobalMonitoringTargetsLocked(inputTargets, windowInfo->portalToDisplayId,
-                                                     -windowInfo->frameLeft, -windowInfo->frameTop);
-                }
-            }
-        }
-    }
-
-    // Dispatch the motion.
-    if (conflictingPointerActions) {
-        CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
-                                   "conflicting pointer actions");
-        synthesizeCancelationEventsForAllConnectionsLocked(options);
-    }
-    dispatchEventLocked(currentTime, entry, inputTargets);
-    return true;
-}
-
-void InputDispatcher::logOutboundMotionDetails(const char* prefix, const MotionEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-    ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32
-          ", policyFlags=0x%x, "
-          "action=0x%x, actionButton=0x%x, flags=0x%x, "
-          "metaState=0x%x, buttonState=0x%x,"
-          "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
-          prefix, entry->eventTime, entry->deviceId, entry->source, entry->displayId,
-          entry->policyFlags, entry->action, entry->actionButton, entry->flags, entry->metaState,
-          entry->buttonState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
-          entry->downTime);
-
-    for (uint32_t i = 0; i < entry->pointerCount; i++) {
-        ALOGD("  Pointer %d: id=%d, toolType=%d, "
-              "x=%f, y=%f, pressure=%f, size=%f, "
-              "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
-              "orientation=%f",
-              i, entry->pointerProperties[i].id, entry->pointerProperties[i].toolType,
-              entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
-              entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
-              entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
-              entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
-              entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
-              entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
-              entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
-              entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
-              entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
-    }
-#endif
-}
-
-void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, EventEntry* eventEntry,
-                                          const std::vector<InputTarget>& inputTargets) {
-    ATRACE_CALL();
-#if DEBUG_DISPATCH_CYCLE
-    ALOGD("dispatchEventToCurrentInputTargets");
-#endif
-
-    ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
-
-    pokeUserActivityLocked(eventEntry);
-
-    for (const InputTarget& inputTarget : inputTargets) {
-        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
-        if (connectionIndex >= 0) {
-            sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
-            prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
-        } else {
-#if DEBUG_FOCUS
-            ALOGD("Dropping event delivery to target with channel '%s' because it "
-                  "is no longer registered with the input dispatcher.",
-                  inputTarget.inputChannel->getName().c_str());
-#endif
-        }
-    }
-}
-
-int32_t InputDispatcher::handleTargetsNotReadyLocked(
-        nsecs_t currentTime, const EventEntry* entry,
-        const sp<InputApplicationHandle>& applicationHandle,
-        const sp<InputWindowHandle>& windowHandle, nsecs_t* nextWakeupTime, const char* reason) {
-    if (applicationHandle == nullptr && windowHandle == nullptr) {
-        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
-#if DEBUG_FOCUS
-            ALOGD("Waiting for system to become ready for input.  Reason: %s", reason);
-#endif
-            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
-            mInputTargetWaitStartTime = currentTime;
-            mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
-            mInputTargetWaitTimeoutExpired = false;
-            mInputTargetWaitApplicationToken.clear();
-        }
-    } else {
-        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
-#if DEBUG_FOCUS
-            ALOGD("Waiting for application to become ready for input: %s.  Reason: %s",
-                  getApplicationWindowLabel(applicationHandle, windowHandle).c_str(), reason);
-#endif
-            nsecs_t timeout;
-            if (windowHandle != nullptr) {
-                timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
-            } else if (applicationHandle != nullptr) {
-                timeout =
-                        applicationHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
-            } else {
-                timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
-            }
-
-            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
-            mInputTargetWaitStartTime = currentTime;
-            mInputTargetWaitTimeoutTime = currentTime + timeout;
-            mInputTargetWaitTimeoutExpired = false;
-            mInputTargetWaitApplicationToken.clear();
-
-            if (windowHandle != nullptr) {
-                mInputTargetWaitApplicationToken = windowHandle->getApplicationToken();
-            }
-            if (mInputTargetWaitApplicationToken == nullptr && applicationHandle != nullptr) {
-                mInputTargetWaitApplicationToken = applicationHandle->getApplicationToken();
-            }
-        }
-    }
-
-    if (mInputTargetWaitTimeoutExpired) {
-        return INPUT_EVENT_INJECTION_TIMED_OUT;
-    }
-
-    if (currentTime >= mInputTargetWaitTimeoutTime) {
-        onANRLocked(currentTime, applicationHandle, windowHandle, entry->eventTime,
-                    mInputTargetWaitStartTime, reason);
-
-        // Force poll loop to wake up immediately on next iteration once we get the
-        // ANR response back from the policy.
-        *nextWakeupTime = LONG_LONG_MIN;
-        return INPUT_EVENT_INJECTION_PENDING;
-    } else {
-        // Force poll loop to wake up when timeout is due.
-        if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
-            *nextWakeupTime = mInputTargetWaitTimeoutTime;
-        }
-        return INPUT_EVENT_INJECTION_PENDING;
-    }
-}
-
-void InputDispatcher::removeWindowByTokenLocked(const sp<IBinder>& token) {
-    for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) {
-        TouchState& state = mTouchStatesByDisplay.editValueAt(d);
-        state.removeWindowByToken(token);
-    }
-}
-
-void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(
-        nsecs_t newTimeout, const sp<InputChannel>& inputChannel) {
-    if (newTimeout > 0) {
-        // Extend the timeout.
-        mInputTargetWaitTimeoutTime = now() + newTimeout;
-    } else {
-        // Give up.
-        mInputTargetWaitTimeoutExpired = true;
-
-        // Input state will not be realistic.  Mark it out of sync.
-        if (inputChannel.get()) {
-            ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
-            if (connectionIndex >= 0) {
-                sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
-                sp<IBinder> token = connection->inputChannel->getToken();
-
-                if (token != nullptr) {
-                    removeWindowByTokenLocked(token);
-                }
-
-                if (connection->status == Connection::STATUS_NORMAL) {
-                    CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS,
-                                               "application not responding");
-                    synthesizeCancelationEventsForConnectionLocked(connection, options);
-                }
-            }
-        }
-    }
-}
-
-nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime) {
-    if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
-        return currentTime - mInputTargetWaitStartTime;
-    }
-    return 0;
-}
-
-void InputDispatcher::resetANRTimeoutsLocked() {
-#if DEBUG_FOCUS
-    ALOGD("Resetting ANR timeouts.");
-#endif
-
-    // Reset input target wait timeout.
-    mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
-    mInputTargetWaitApplicationToken.clear();
-}
-
-/**
- * Get the display id that the given event should go to. If this event specifies a valid display id,
- * then it should be dispatched to that display. Otherwise, the event goes to the focused display.
- * Focused display is the display that the user most recently interacted with.
- */
-int32_t InputDispatcher::getTargetDisplayId(const EventEntry* entry) {
-    int32_t displayId;
-    switch (entry->type) {
-        case EventEntry::TYPE_KEY: {
-            const KeyEntry* typedEntry = static_cast<const KeyEntry*>(entry);
-            displayId = typedEntry->displayId;
-            break;
-        }
-        case EventEntry::TYPE_MOTION: {
-            const MotionEntry* typedEntry = static_cast<const MotionEntry*>(entry);
-            displayId = typedEntry->displayId;
-            break;
-        }
-        default: {
-            ALOGE("Unsupported event type '%" PRId32 "' for target display.", entry->type);
-            return ADISPLAY_ID_NONE;
-        }
-    }
-    return displayId == ADISPLAY_ID_NONE ? mFocusedDisplayId : displayId;
-}
-
-int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
-                                                        const EventEntry* entry,
-                                                        std::vector<InputTarget>& inputTargets,
-                                                        nsecs_t* nextWakeupTime) {
-    int32_t injectionResult;
-    std::string reason;
-
-    int32_t displayId = getTargetDisplayId(entry);
-    sp<InputWindowHandle> focusedWindowHandle =
-            getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
-    sp<InputApplicationHandle> focusedApplicationHandle =
-            getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
-
-    // If there is no currently focused window and no focused application
-    // then drop the event.
-    if (focusedWindowHandle == nullptr) {
-        if (focusedApplicationHandle != nullptr) {
-            injectionResult =
-                    handleTargetsNotReadyLocked(currentTime, entry, focusedApplicationHandle,
-                                                nullptr, nextWakeupTime,
-                                                "Waiting because no window has focus but there is "
-                                                "a "
-                                                "focused application that may eventually add a "
-                                                "window "
-                                                "when it finishes starting up.");
-            goto Unresponsive;
-        }
-
-        ALOGI("Dropping event because there is no focused window or focused application in display "
-              "%" PRId32 ".",
-              displayId);
-        injectionResult = INPUT_EVENT_INJECTION_FAILED;
-        goto Failed;
-    }
-
-    // Check permissions.
-    if (!checkInjectionPermission(focusedWindowHandle, entry->injectionState)) {
-        injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
-        goto Failed;
-    }
-
-    // Check whether the window is ready for more input.
-    reason = checkWindowReadyForMoreInputLocked(currentTime, focusedWindowHandle, entry, "focused");
-    if (!reason.empty()) {
-        injectionResult =
-                handleTargetsNotReadyLocked(currentTime, entry, focusedApplicationHandle,
-                                            focusedWindowHandle, nextWakeupTime, reason.c_str());
-        goto Unresponsive;
-    }
-
-    // Success!  Output targets.
-    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
-    addWindowTargetLocked(focusedWindowHandle,
-                          InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,
-                          BitSet32(0), inputTargets);
-
-    // Done.
-Failed:
-Unresponsive:
-    nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
-    updateDispatchStatistics(currentTime, entry, injectionResult, timeSpentWaitingForApplication);
-#if DEBUG_FOCUS
-    ALOGD("findFocusedWindow finished: injectionResult=%d, "
-          "timeSpentWaitingForApplication=%0.1fms",
-          injectionResult, timeSpentWaitingForApplication / 1000000.0);
-#endif
-    return injectionResult;
-}
-
-int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
-                                                        const MotionEntry* entry,
-                                                        std::vector<InputTarget>& inputTargets,
-                                                        nsecs_t* nextWakeupTime,
-                                                        bool* outConflictingPointerActions) {
-    ATRACE_CALL();
-    enum InjectionPermission {
-        INJECTION_PERMISSION_UNKNOWN,
-        INJECTION_PERMISSION_GRANTED,
-        INJECTION_PERMISSION_DENIED
-    };
-
-    // For security reasons, we defer updating the touch state until we are sure that
-    // event injection will be allowed.
-    int32_t displayId = entry->displayId;
-    int32_t action = entry->action;
-    int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
-
-    // Update the touch state as needed based on the properties of the touch event.
-    int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
-    InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
-    sp<InputWindowHandle> newHoverWindowHandle;
-
-    // Copy current touch state into mTempTouchState.
-    // This state is always reset at the end of this function, so if we don't find state
-    // for the specified display then our initial state will be empty.
-    const TouchState* oldState = nullptr;
-    ssize_t oldStateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
-    if (oldStateIndex >= 0) {
-        oldState = &mTouchStatesByDisplay.valueAt(oldStateIndex);
-        mTempTouchState.copyFrom(*oldState);
-    }
-
-    bool isSplit = mTempTouchState.split;
-    bool switchedDevice = mTempTouchState.deviceId >= 0 && mTempTouchState.displayId >= 0 &&
-            (mTempTouchState.deviceId != entry->deviceId ||
-             mTempTouchState.source != entry->source || mTempTouchState.displayId != displayId);
-    bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE ||
-                          maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
-                          maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT);
-    bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN ||
-                       maskedAction == AMOTION_EVENT_ACTION_SCROLL || isHoverAction);
-    bool wrongDevice = false;
-    if (newGesture) {
-        bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
-        if (switchedDevice && mTempTouchState.down && !down && !isHoverAction) {
-#if DEBUG_FOCUS
-            ALOGD("Dropping event because a pointer for a different device is already down "
-                  "in display %" PRId32,
-                  displayId);
-#endif
-            // TODO: test multiple simultaneous input streams.
-            injectionResult = INPUT_EVENT_INJECTION_FAILED;
-            switchedDevice = false;
-            wrongDevice = true;
-            goto Failed;
-        }
-        mTempTouchState.reset();
-        mTempTouchState.down = down;
-        mTempTouchState.deviceId = entry->deviceId;
-        mTempTouchState.source = entry->source;
-        mTempTouchState.displayId = displayId;
-        isSplit = false;
-    } else if (switchedDevice && maskedAction == AMOTION_EVENT_ACTION_MOVE) {
-#if DEBUG_FOCUS
-        ALOGI("Dropping move event because a pointer for a different device is already active "
-              "in display %" PRId32,
-              displayId);
-#endif
-        // TODO: test multiple simultaneous input streams.
-        injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
-        switchedDevice = false;
-        wrongDevice = true;
-        goto Failed;
-    }
-
-    if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
-        /* Case 1: New splittable pointer going down, or need target for hover or scroll. */
-
-        int32_t pointerIndex = getMotionEventActionPointerIndex(action);
-        int32_t x = int32_t(entry->pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_X));
-        int32_t y = int32_t(entry->pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_Y));
-        bool isDown = maskedAction == AMOTION_EVENT_ACTION_DOWN;
-        sp<InputWindowHandle> newTouchedWindowHandle =
-                findTouchedWindowAtLocked(displayId, x, y, isDown /*addOutsideTargets*/,
-                                          true /*addPortalWindows*/);
-
-        std::vector<TouchedMonitor> newGestureMonitors = isDown
-                ? findTouchedGestureMonitorsLocked(displayId, mTempTouchState.portalWindows)
-                : std::vector<TouchedMonitor>{};
-
-        // Figure out whether splitting will be allowed for this window.
-        if (newTouchedWindowHandle != nullptr &&
-            newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
-            // New window supports splitting.
-            isSplit = true;
-        } else if (isSplit) {
-            // New window does not support splitting but we have already split events.
-            // Ignore the new window.
-            newTouchedWindowHandle = nullptr;
-        }
-
-        // Handle the case where we did not find a window.
-        if (newTouchedWindowHandle == nullptr) {
-            // Try to assign the pointer to the first foreground window we find, if there is one.
-            newTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle();
-        }
-
-        if (newTouchedWindowHandle == nullptr && newGestureMonitors.empty()) {
-            ALOGI("Dropping event because there is no touchable window or gesture monitor at "
-                  "(%d, %d) in display %" PRId32 ".",
-                  x, y, displayId);
-            injectionResult = INPUT_EVENT_INJECTION_FAILED;
-            goto Failed;
-        }
-
-        if (newTouchedWindowHandle != nullptr) {
-            // Set target flags.
-            int32_t targetFlags = InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS;
-            if (isSplit) {
-                targetFlags |= InputTarget::FLAG_SPLIT;
-            }
-            if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
-                targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
-            } else if (isWindowObscuredLocked(newTouchedWindowHandle)) {
-                targetFlags |= InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
-            }
-
-            // Update hover state.
-            if (isHoverAction) {
-                newHoverWindowHandle = newTouchedWindowHandle;
-            } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
-                newHoverWindowHandle = mLastHoverWindowHandle;
-            }
-
-            // Update the temporary touch state.
-            BitSet32 pointerIds;
-            if (isSplit) {
-                uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
-                pointerIds.markBit(pointerId);
-            }
-            mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
-        }
-
-        mTempTouchState.addGestureMonitors(newGestureMonitors);
-    } else {
-        /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
-
-        // If the pointer is not currently down, then ignore the event.
-        if (!mTempTouchState.down) {
-#if DEBUG_FOCUS
-            ALOGD("Dropping event because the pointer is not down or we previously "
-                  "dropped the pointer down event in display %" PRId32,
-                  displayId);
-#endif
-            injectionResult = INPUT_EVENT_INJECTION_FAILED;
-            goto Failed;
-        }
-
-        // Check whether touches should slip outside of the current foreground window.
-        if (maskedAction == AMOTION_EVENT_ACTION_MOVE && entry->pointerCount == 1 &&
-            mTempTouchState.isSlippery()) {
-            int32_t x = int32_t(entry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
-            int32_t y = int32_t(entry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
-
-            sp<InputWindowHandle> oldTouchedWindowHandle =
-                    mTempTouchState.getFirstForegroundWindowHandle();
-            sp<InputWindowHandle> newTouchedWindowHandle =
-                    findTouchedWindowAtLocked(displayId, x, y);
-            if (oldTouchedWindowHandle != newTouchedWindowHandle &&
-                oldTouchedWindowHandle != nullptr && newTouchedWindowHandle != nullptr) {
-#if DEBUG_FOCUS
-                ALOGD("Touch is slipping out of window %s into window %s in display %" PRId32,
-                      oldTouchedWindowHandle->getName().c_str(),
-                      newTouchedWindowHandle->getName().c_str(), displayId);
-#endif
-                // Make a slippery exit from the old window.
-                mTempTouchState.addOrUpdateWindow(oldTouchedWindowHandle,
-                                                  InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT,
-                                                  BitSet32(0));
-
-                // Make a slippery entrance into the new window.
-                if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
-                    isSplit = true;
-                }
-
-                int32_t targetFlags =
-                        InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER;
-                if (isSplit) {
-                    targetFlags |= InputTarget::FLAG_SPLIT;
-                }
-                if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
-                    targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
-                }
-
-                BitSet32 pointerIds;
-                if (isSplit) {
-                    pointerIds.markBit(entry->pointerProperties[0].id);
-                }
-                mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
-            }
-        }
-    }
-
-    if (newHoverWindowHandle != mLastHoverWindowHandle) {
-        // Let the previous window know that the hover sequence is over.
-        if (mLastHoverWindowHandle != nullptr) {
-#if DEBUG_HOVER
-            ALOGD("Sending hover exit event to window %s.",
-                  mLastHoverWindowHandle->getName().c_str());
-#endif
-            mTempTouchState.addOrUpdateWindow(mLastHoverWindowHandle,
-                                              InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT,
-                                              BitSet32(0));
-        }
-
-        // Let the new window know that the hover sequence is starting.
-        if (newHoverWindowHandle != nullptr) {
-#if DEBUG_HOVER
-            ALOGD("Sending hover enter event to window %s.",
-                  newHoverWindowHandle->getName().c_str());
-#endif
-            mTempTouchState.addOrUpdateWindow(newHoverWindowHandle,
-                                              InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER,
-                                              BitSet32(0));
-        }
-    }
-
-    // Check permission to inject into all touched foreground windows and ensure there
-    // is at least one touched foreground window.
-    {
-        bool haveForegroundWindow = false;
-        for (const TouchedWindow& touchedWindow : mTempTouchState.windows) {
-            if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
-                haveForegroundWindow = true;
-                if (!checkInjectionPermission(touchedWindow.windowHandle, entry->injectionState)) {
-                    injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
-                    injectionPermission = INJECTION_PERMISSION_DENIED;
-                    goto Failed;
-                }
-            }
-        }
-        bool hasGestureMonitor = !mTempTouchState.gestureMonitors.empty();
-        if (!haveForegroundWindow && !hasGestureMonitor) {
-#if DEBUG_FOCUS
-            ALOGD("Dropping event because there is no touched foreground window in display %" PRId32
-                  " or gesture monitor to receive it.",
-                  displayId);
-#endif
-            injectionResult = INPUT_EVENT_INJECTION_FAILED;
-            goto Failed;
-        }
-
-        // Permission granted to injection into all touched foreground windows.
-        injectionPermission = INJECTION_PERMISSION_GRANTED;
-    }
-
-    // Check whether windows listening for outside touches are owned by the same UID. If it is
-    // set the policy flag that we will not reveal coordinate information to this window.
-    if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
-        sp<InputWindowHandle> foregroundWindowHandle =
-                mTempTouchState.getFirstForegroundWindowHandle();
-        if (foregroundWindowHandle) {
-            const int32_t foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid;
-            for (const TouchedWindow& touchedWindow : mTempTouchState.windows) {
-                if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
-                    sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle;
-                    if (inputWindowHandle->getInfo()->ownerUid != foregroundWindowUid) {
-                        mTempTouchState.addOrUpdateWindow(inputWindowHandle,
-                                                          InputTarget::FLAG_ZERO_COORDS,
-                                                          BitSet32(0));
-                    }
-                }
-            }
-        }
-    }
-
-    // Ensure all touched foreground windows are ready for new input.
-    for (const TouchedWindow& touchedWindow : mTempTouchState.windows) {
-        if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
-            // Check whether the window is ready for more input.
-            std::string reason =
-                    checkWindowReadyForMoreInputLocked(currentTime, touchedWindow.windowHandle,
-                                                       entry, "touched");
-            if (!reason.empty()) {
-                injectionResult = handleTargetsNotReadyLocked(currentTime, entry, nullptr,
-                                                              touchedWindow.windowHandle,
-                                                              nextWakeupTime, reason.c_str());
-                goto Unresponsive;
-            }
-        }
-    }
-
-    // If this is the first pointer going down and the touched window has a wallpaper
-    // then also add the touched wallpaper windows so they are locked in for the duration
-    // of the touch gesture.
-    // We do not collect wallpapers during HOVER_MOVE or SCROLL because the wallpaper
-    // engine only supports touch events.  We would need to add a mechanism similar
-    // to View.onGenericMotionEvent to enable wallpapers to handle these events.
-    if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
-        sp<InputWindowHandle> foregroundWindowHandle =
-                mTempTouchState.getFirstForegroundWindowHandle();
-        if (foregroundWindowHandle && foregroundWindowHandle->getInfo()->hasWallpaper) {
-            const std::vector<sp<InputWindowHandle>> windowHandles =
-                    getWindowHandlesLocked(displayId);
-            for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
-                const InputWindowInfo* info = windowHandle->getInfo();
-                if (info->displayId == displayId &&
-                    windowHandle->getInfo()->layoutParamsType == InputWindowInfo::TYPE_WALLPAPER) {
-                    mTempTouchState
-                            .addOrUpdateWindow(windowHandle,
-                                               InputTarget::FLAG_WINDOW_IS_OBSCURED |
-                                                       InputTarget::
-                                                               FLAG_WINDOW_IS_PARTIALLY_OBSCURED |
-                                                       InputTarget::FLAG_DISPATCH_AS_IS,
-                                               BitSet32(0));
-                }
-            }
-        }
-    }
-
-    // Success!  Output targets.
-    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
-
-    for (const TouchedWindow& touchedWindow : mTempTouchState.windows) {
-        addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
-                              touchedWindow.pointerIds, inputTargets);
-    }
-
-    for (const TouchedMonitor& touchedMonitor : mTempTouchState.gestureMonitors) {
-        addMonitoringTargetLocked(touchedMonitor.monitor, touchedMonitor.xOffset,
-                                  touchedMonitor.yOffset, inputTargets);
-    }
-
-    // Drop the outside or hover touch windows since we will not care about them
-    // in the next iteration.
-    mTempTouchState.filterNonAsIsTouchWindows();
-
-Failed:
-    // Check injection permission once and for all.
-    if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
-        if (checkInjectionPermission(nullptr, entry->injectionState)) {
-            injectionPermission = INJECTION_PERMISSION_GRANTED;
-        } else {
-            injectionPermission = INJECTION_PERMISSION_DENIED;
-        }
-    }
-
-    // Update final pieces of touch state if the injector had permission.
-    if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
-        if (!wrongDevice) {
-            if (switchedDevice) {
-#if DEBUG_FOCUS
-                ALOGD("Conflicting pointer actions: Switched to a different device.");
-#endif
-                *outConflictingPointerActions = true;
-            }
-
-            if (isHoverAction) {
-                // Started hovering, therefore no longer down.
-                if (oldState && oldState->down) {
-#if DEBUG_FOCUS
-                    ALOGD("Conflicting pointer actions: Hover received while pointer was down.");
-#endif
-                    *outConflictingPointerActions = true;
-                }
-                mTempTouchState.reset();
-                if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
-                    maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
-                    mTempTouchState.deviceId = entry->deviceId;
-                    mTempTouchState.source = entry->source;
-                    mTempTouchState.displayId = displayId;
-                }
-            } else if (maskedAction == AMOTION_EVENT_ACTION_UP ||
-                       maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
-                // All pointers up or canceled.
-                mTempTouchState.reset();
-            } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
-                // First pointer went down.
-                if (oldState && oldState->down) {
-#if DEBUG_FOCUS
-                    ALOGD("Conflicting pointer actions: Down received while already down.");
-#endif
-                    *outConflictingPointerActions = true;
-                }
-            } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
-                // One pointer went up.
-                if (isSplit) {
-                    int32_t pointerIndex = getMotionEventActionPointerIndex(action);
-                    uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
-
-                    for (size_t i = 0; i < mTempTouchState.windows.size();) {
-                        TouchedWindow& touchedWindow = mTempTouchState.windows[i];
-                        if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
-                            touchedWindow.pointerIds.clearBit(pointerId);
-                            if (touchedWindow.pointerIds.isEmpty()) {
-                                mTempTouchState.windows.erase(mTempTouchState.windows.begin() + i);
-                                continue;
-                            }
-                        }
-                        i += 1;
-                    }
-                }
-            }
-
-            // Save changes unless the action was scroll in which case the temporary touch
-            // state was only valid for this one action.
-            if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) {
-                if (mTempTouchState.displayId >= 0) {
-                    if (oldStateIndex >= 0) {
-                        mTouchStatesByDisplay.editValueAt(oldStateIndex).copyFrom(mTempTouchState);
-                    } else {
-                        mTouchStatesByDisplay.add(displayId, mTempTouchState);
-                    }
-                } else if (oldStateIndex >= 0) {
-                    mTouchStatesByDisplay.removeItemsAt(oldStateIndex);
-                }
-            }
-
-            // Update hover state.
-            mLastHoverWindowHandle = newHoverWindowHandle;
-        }
-    } else {
-#if DEBUG_FOCUS
-        ALOGD("Not updating touch focus because injection was denied.");
-#endif
-    }
-
-Unresponsive:
-    // Reset temporary touch state to ensure we release unnecessary references to input channels.
-    mTempTouchState.reset();
-
-    nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
-    updateDispatchStatistics(currentTime, entry, injectionResult, timeSpentWaitingForApplication);
-#if DEBUG_FOCUS
-    ALOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, "
-          "timeSpentWaitingForApplication=%0.1fms",
-          injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
-#endif
-    return injectionResult;
-}
-
-void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
-                                            int32_t targetFlags, BitSet32 pointerIds,
-                                            std::vector<InputTarget>& inputTargets) {
-    sp<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken());
-    if (inputChannel == nullptr) {
-        ALOGW("Window %s already unregistered input channel", windowHandle->getName().c_str());
-        return;
-    }
-
-    const InputWindowInfo* windowInfo = windowHandle->getInfo();
-    InputTarget target;
-    target.inputChannel = inputChannel;
-    target.flags = targetFlags;
-    target.xOffset = -windowInfo->frameLeft;
-    target.yOffset = -windowInfo->frameTop;
-    target.globalScaleFactor = windowInfo->globalScaleFactor;
-    target.windowXScale = windowInfo->windowXScale;
-    target.windowYScale = windowInfo->windowYScale;
-    target.pointerIds = pointerIds;
-    inputTargets.push_back(target);
-}
-
-void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
-                                                       int32_t displayId, float xOffset,
-                                                       float yOffset) {
-    std::unordered_map<int32_t, std::vector<Monitor>>::const_iterator it =
-            mGlobalMonitorsByDisplay.find(displayId);
-
-    if (it != mGlobalMonitorsByDisplay.end()) {
-        const std::vector<Monitor>& monitors = it->second;
-        for (const Monitor& monitor : monitors) {
-            addMonitoringTargetLocked(monitor, xOffset, yOffset, inputTargets);
-        }
-    }
-}
-
-void InputDispatcher::addMonitoringTargetLocked(const Monitor& monitor, float xOffset,
-                                                float yOffset,
-                                                std::vector<InputTarget>& inputTargets) {
-    InputTarget target;
-    target.inputChannel = monitor.inputChannel;
-    target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
-    target.xOffset = xOffset;
-    target.yOffset = yOffset;
-    target.pointerIds.clear();
-    target.globalScaleFactor = 1.0f;
-    inputTargets.push_back(target);
-}
-
-bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
-                                               const InjectionState* injectionState) {
-    if (injectionState &&
-        (windowHandle == nullptr ||
-         windowHandle->getInfo()->ownerUid != injectionState->injectorUid) &&
-        !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
-        if (windowHandle != nullptr) {
-            ALOGW("Permission denied: injecting event from pid %d uid %d to window %s "
-                  "owned by uid %d",
-                  injectionState->injectorPid, injectionState->injectorUid,
-                  windowHandle->getName().c_str(), windowHandle->getInfo()->ownerUid);
-        } else {
-            ALOGW("Permission denied: injecting event from pid %d uid %d",
-                  injectionState->injectorPid, injectionState->injectorUid);
-        }
-        return false;
-    }
-    return true;
-}
-
-bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle,
-                                                    int32_t x, int32_t y) const {
-    int32_t displayId = windowHandle->getInfo()->displayId;
-    const std::vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
-    for (const sp<InputWindowHandle>& otherHandle : windowHandles) {
-        if (otherHandle == windowHandle) {
-            break;
-        }
-
-        const InputWindowInfo* otherInfo = otherHandle->getInfo();
-        if (otherInfo->displayId == displayId && otherInfo->visible &&
-            !otherInfo->isTrustedOverlay() && otherInfo->frameContainsPoint(x, y)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool InputDispatcher::isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const {
-    int32_t displayId = windowHandle->getInfo()->displayId;
-    const std::vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
-    const InputWindowInfo* windowInfo = windowHandle->getInfo();
-    for (const sp<InputWindowHandle>& otherHandle : windowHandles) {
-        if (otherHandle == windowHandle) {
-            break;
-        }
-
-        const InputWindowInfo* otherInfo = otherHandle->getInfo();
-        if (otherInfo->displayId == displayId && otherInfo->visible &&
-            !otherInfo->isTrustedOverlay() && otherInfo->overlaps(windowInfo)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-std::string InputDispatcher::checkWindowReadyForMoreInputLocked(
-        nsecs_t currentTime, const sp<InputWindowHandle>& windowHandle,
-        const EventEntry* eventEntry, const char* targetType) {
-    // If the window is paused then keep waiting.
-    if (windowHandle->getInfo()->paused) {
-        return StringPrintf("Waiting because the %s window is paused.", targetType);
-    }
-
-    // If the window's connection is not registered then keep waiting.
-    ssize_t connectionIndex =
-            getConnectionIndexLocked(getInputChannelLocked(windowHandle->getToken()));
-    if (connectionIndex < 0) {
-        return StringPrintf("Waiting because the %s window's input channel is not "
-                            "registered with the input dispatcher.  The window may be in the "
-                            "process "
-                            "of being removed.",
-                            targetType);
-    }
-
-    // If the connection is dead then keep waiting.
-    sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
-    if (connection->status != Connection::STATUS_NORMAL) {
-        return StringPrintf("Waiting because the %s window's input connection is %s."
-                            "The window may be in the process of being removed.",
-                            targetType, connection->getStatusLabel());
-    }
-
-    // If the connection is backed up then keep waiting.
-    if (connection->inputPublisherBlocked) {
-        return StringPrintf("Waiting because the %s window's input channel is full.  "
-                            "Outbound queue length: %d.  Wait queue length: %d.",
-                            targetType, connection->outboundQueue.count(),
-                            connection->waitQueue.count());
-    }
-
-    // Ensure that the dispatch queues aren't too far backed up for this event.
-    if (eventEntry->type == EventEntry::TYPE_KEY) {
-        // If the event is a key event, then we must wait for all previous events to
-        // complete before delivering it because previous events may have the
-        // side-effect of transferring focus to a different window and we want to
-        // ensure that the following keys are sent to the new window.
-        //
-        // Suppose the user touches a button in a window then immediately presses "A".
-        // If the button causes a pop-up window to appear then we want to ensure that
-        // the "A" key is delivered to the new pop-up window.  This is because users
-        // often anticipate pending UI changes when typing on a keyboard.
-        // To obtain this behavior, we must serialize key events with respect to all
-        // prior input events.
-        if (!connection->outboundQueue.isEmpty() || !connection->waitQueue.isEmpty()) {
-            return StringPrintf("Waiting to send key event because the %s window has not "
-                                "finished processing all of the input events that were previously "
-                                "delivered to it.  Outbound queue length: %d.  Wait queue length: "
-                                "%d.",
-                                targetType, connection->outboundQueue.count(),
-                                connection->waitQueue.count());
-        }
-    } else {
-        // Touch events can always be sent to a window immediately because the user intended
-        // to touch whatever was visible at the time.  Even if focus changes or a new
-        // window appears moments later, the touch event was meant to be delivered to
-        // whatever window happened to be on screen at the time.
-        //
-        // Generic motion events, such as trackball or joystick events are a little trickier.
-        // Like key events, generic motion events are delivered to the focused window.
-        // Unlike key events, generic motion events don't tend to transfer focus to other
-        // windows and it is not important for them to be serialized.  So we prefer to deliver
-        // generic motion events as soon as possible to improve efficiency and reduce lag
-        // through batching.
-        //
-        // The one case where we pause input event delivery is when the wait queue is piling
-        // up with lots of events because the application is not responding.
-        // This condition ensures that ANRs are detected reliably.
-        if (!connection->waitQueue.isEmpty() &&
-            currentTime >= connection->waitQueue.head->deliveryTime + STREAM_AHEAD_EVENT_TIMEOUT) {
-            return StringPrintf("Waiting to send non-key event because the %s window has not "
-                                "finished processing certain input events that were delivered to "
-                                "it over "
-                                "%0.1fms ago.  Wait queue length: %d.  Wait queue head age: "
-                                "%0.1fms.",
-                                targetType, STREAM_AHEAD_EVENT_TIMEOUT * 0.000001f,
-                                connection->waitQueue.count(),
-                                (currentTime - connection->waitQueue.head->deliveryTime) *
-                                        0.000001f);
-        }
-    }
-    return "";
-}
-
-std::string InputDispatcher::getApplicationWindowLabel(
-        const sp<InputApplicationHandle>& applicationHandle,
-        const sp<InputWindowHandle>& windowHandle) {
-    if (applicationHandle != nullptr) {
-        if (windowHandle != nullptr) {
-            std::string label(applicationHandle->getName());
-            label += " - ";
-            label += windowHandle->getName();
-            return label;
-        } else {
-            return applicationHandle->getName();
-        }
-    } else if (windowHandle != nullptr) {
-        return windowHandle->getName();
-    } else {
-        return "<unknown application or window>";
-    }
-}
-
-void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
-    int32_t displayId = getTargetDisplayId(eventEntry);
-    sp<InputWindowHandle> focusedWindowHandle =
-            getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
-    if (focusedWindowHandle != nullptr) {
-        const InputWindowInfo* info = focusedWindowHandle->getInfo();
-        if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) {
-#if DEBUG_DISPATCH_CYCLE
-            ALOGD("Not poking user activity: disabled by window '%s'.", info->name.c_str());
-#endif
-            return;
-        }
-    }
-
-    int32_t eventType = USER_ACTIVITY_EVENT_OTHER;
-    switch (eventEntry->type) {
-        case EventEntry::TYPE_MOTION: {
-            const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
-            if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
-                return;
-            }
-
-            if (MotionEvent::isTouchEvent(motionEntry->source, motionEntry->action)) {
-                eventType = USER_ACTIVITY_EVENT_TOUCH;
-            }
-            break;
-        }
-        case EventEntry::TYPE_KEY: {
-            const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry);
-            if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
-                return;
-            }
-            eventType = USER_ACTIVITY_EVENT_BUTTON;
-            break;
-        }
-    }
-
-    CommandEntry* commandEntry =
-            postCommandLocked(&InputDispatcher::doPokeUserActivityLockedInterruptible);
-    commandEntry->eventTime = eventEntry->eventTime;
-    commandEntry->userActivityEventType = eventType;
-}
-
-void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
-                                                 const sp<Connection>& connection,
-                                                 EventEntry* eventEntry,
-                                                 const InputTarget* inputTarget) {
-    if (ATRACE_ENABLED()) {
-        std::string message =
-                StringPrintf("prepareDispatchCycleLocked(inputChannel=%s, sequenceNum=%" PRIu32 ")",
-                             connection->getInputChannelName().c_str(), eventEntry->sequenceNum);
-        ATRACE_NAME(message.c_str());
-    }
-#if DEBUG_DISPATCH_CYCLE
-    ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, "
-          "xOffset=%f, yOffset=%f, globalScaleFactor=%f, "
-          "windowScaleFactor=(%f, %f), pointerIds=0x%x",
-          connection->getInputChannelName().c_str(), inputTarget->flags, inputTarget->xOffset,
-          inputTarget->yOffset, inputTarget->globalScaleFactor, inputTarget->windowXScale,
-          inputTarget->windowYScale, inputTarget->pointerIds.value);
-#endif
-
-    // Skip this event if the connection status is not normal.
-    // We don't want to enqueue additional outbound events if the connection is broken.
-    if (connection->status != Connection::STATUS_NORMAL) {
-#if DEBUG_DISPATCH_CYCLE
-        ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
-              connection->getInputChannelName().c_str(), connection->getStatusLabel());
-#endif
-        return;
-    }
-
-    // Split a motion event if needed.
-    if (inputTarget->flags & InputTarget::FLAG_SPLIT) {
-        ALOG_ASSERT(eventEntry->type == EventEntry::TYPE_MOTION);
-
-        MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(eventEntry);
-        if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {
-            MotionEntry* splitMotionEntry =
-                    splitMotionEvent(originalMotionEntry, inputTarget->pointerIds);
-            if (!splitMotionEntry) {
-                return; // split event was dropped
-            }
-#if DEBUG_FOCUS
-            ALOGD("channel '%s' ~ Split motion event.", connection->getInputChannelName().c_str());
-            logOutboundMotionDetails("  ", splitMotionEntry);
-#endif
-            enqueueDispatchEntriesLocked(currentTime, connection, splitMotionEntry, inputTarget);
-            splitMotionEntry->release();
-            return;
-        }
-    }
-
-    // Not splitting.  Enqueue dispatch entries for the event as is.
-    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
-}
-
-void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
-                                                   const sp<Connection>& connection,
-                                                   EventEntry* eventEntry,
-                                                   const InputTarget* inputTarget) {
-    if (ATRACE_ENABLED()) {
-        std::string message =
-                StringPrintf("enqueueDispatchEntriesLocked(inputChannel=%s, sequenceNum=%" PRIu32
-                             ")",
-                             connection->getInputChannelName().c_str(), eventEntry->sequenceNum);
-        ATRACE_NAME(message.c_str());
-    }
-
-    bool wasEmpty = connection->outboundQueue.isEmpty();
-
-    // Enqueue dispatch entries for the requested modes.
-    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
-                               InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
-    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
-                               InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
-    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
-                               InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
-    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
-                               InputTarget::FLAG_DISPATCH_AS_IS);
-    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
-                               InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
-    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
-                               InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
-
-    // If the outbound queue was previously empty, start the dispatch cycle going.
-    if (wasEmpty && !connection->outboundQueue.isEmpty()) {
-        startDispatchCycleLocked(currentTime, connection);
-    }
-}
-
-void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection,
-                                                 EventEntry* eventEntry,
-                                                 const InputTarget* inputTarget,
-                                                 int32_t dispatchMode) {
-    if (ATRACE_ENABLED()) {
-        std::string message = StringPrintf("enqueueDispatchEntry(inputChannel=%s, dispatchMode=%s)",
-                                           connection->getInputChannelName().c_str(),
-                                           dispatchModeToString(dispatchMode).c_str());
-        ATRACE_NAME(message.c_str());
-    }
-    int32_t inputTargetFlags = inputTarget->flags;
-    if (!(inputTargetFlags & dispatchMode)) {
-        return;
-    }
-    inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;
-
-    // This is a new event.
-    // Enqueue a new dispatch entry onto the outbound queue for this connection.
-    DispatchEntry* dispatchEntry =
-            new DispatchEntry(eventEntry, // increments ref
-                              inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
-                              inputTarget->globalScaleFactor, inputTarget->windowXScale,
-                              inputTarget->windowYScale);
-
-    // Apply target flags and update the connection's input state.
-    switch (eventEntry->type) {
-        case EventEntry::TYPE_KEY: {
-            KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
-            dispatchEntry->resolvedAction = keyEntry->action;
-            dispatchEntry->resolvedFlags = keyEntry->flags;
-
-            if (!connection->inputState.trackKey(keyEntry, dispatchEntry->resolvedAction,
-                                                 dispatchEntry->resolvedFlags)) {
-#if DEBUG_DISPATCH_CYCLE
-                ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event",
-                      connection->getInputChannelName().c_str());
-#endif
-                delete dispatchEntry;
-                return; // skip the inconsistent event
-            }
-            break;
-        }
-
-        case EventEntry::TYPE_MOTION: {
-            MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
-            if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
-                dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
-            } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) {
-                dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
-            } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
-                dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
-            } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
-                dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
-            } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
-                dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN;
-            } else {
-                dispatchEntry->resolvedAction = motionEntry->action;
-            }
-            if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE &&
-                !connection->inputState.isHovering(motionEntry->deviceId, motionEntry->source,
-                                                   motionEntry->displayId)) {
-#if DEBUG_DISPATCH_CYCLE
-                ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter "
-                      "event",
-                      connection->getInputChannelName().c_str());
-#endif
-                dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
-            }
-
-            dispatchEntry->resolvedFlags = motionEntry->flags;
-            if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
-                dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
-            }
-            if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED) {
-                dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
-            }
-
-            if (!connection->inputState.trackMotion(motionEntry, dispatchEntry->resolvedAction,
-                                                    dispatchEntry->resolvedFlags)) {
-#if DEBUG_DISPATCH_CYCLE
-                ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent motion "
-                      "event",
-                      connection->getInputChannelName().c_str());
-#endif
-                delete dispatchEntry;
-                return; // skip the inconsistent event
-            }
-
-            dispatchPointerDownOutsideFocus(motionEntry->source, dispatchEntry->resolvedAction,
-                                            inputTarget->inputChannel->getToken());
-
-            break;
-        }
-    }
-
-    // Remember that we are waiting for this dispatch to complete.
-    if (dispatchEntry->hasForegroundTarget()) {
-        incrementPendingForegroundDispatches(eventEntry);
-    }
-
-    // Enqueue the dispatch entry.
-    connection->outboundQueue.enqueueAtTail(dispatchEntry);
-    traceOutboundQueueLength(connection);
-}
-
-void InputDispatcher::dispatchPointerDownOutsideFocus(uint32_t source, int32_t action,
-                                                      const sp<IBinder>& newToken) {
-    int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
-    uint32_t maskedSource = source & AINPUT_SOURCE_CLASS_MASK;
-    if (maskedSource != AINPUT_SOURCE_CLASS_POINTER || maskedAction != AMOTION_EVENT_ACTION_DOWN) {
-        return;
-    }
-
-    sp<InputWindowHandle> inputWindowHandle = getWindowHandleLocked(newToken);
-    if (inputWindowHandle == nullptr) {
-        return;
-    }
-
-    sp<InputWindowHandle> focusedWindowHandle =
-            getValueByKey(mFocusedWindowHandlesByDisplay, mFocusedDisplayId);
-
-    bool hasFocusChanged = !focusedWindowHandle || focusedWindowHandle->getToken() != newToken;
-
-    if (!hasFocusChanged) {
-        return;
-    }
-
-    CommandEntry* commandEntry =
-            postCommandLocked(&InputDispatcher::doOnPointerDownOutsideFocusLockedInterruptible);
-    commandEntry->newToken = newToken;
-}
-
-void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
-                                               const sp<Connection>& connection) {
-    if (ATRACE_ENABLED()) {
-        std::string message = StringPrintf("startDispatchCycleLocked(inputChannel=%s)",
-                                           connection->getInputChannelName().c_str());
-        ATRACE_NAME(message.c_str());
-    }
-#if DEBUG_DISPATCH_CYCLE
-    ALOGD("channel '%s' ~ startDispatchCycle", connection->getInputChannelName().c_str());
-#endif
-
-    while (connection->status == Connection::STATUS_NORMAL &&
-           !connection->outboundQueue.isEmpty()) {
-        DispatchEntry* dispatchEntry = connection->outboundQueue.head;
-        dispatchEntry->deliveryTime = currentTime;
-
-        // Publish the event.
-        status_t status;
-        EventEntry* eventEntry = dispatchEntry->eventEntry;
-        switch (eventEntry->type) {
-            case EventEntry::TYPE_KEY: {
-                KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
-
-                // Publish the key event.
-                status = connection->inputPublisher
-                                 .publishKeyEvent(dispatchEntry->seq, keyEntry->deviceId,
-                                                  keyEntry->source, keyEntry->displayId,
-                                                  dispatchEntry->resolvedAction,
-                                                  dispatchEntry->resolvedFlags, keyEntry->keyCode,
-                                                  keyEntry->scanCode, keyEntry->metaState,
-                                                  keyEntry->repeatCount, keyEntry->downTime,
-                                                  keyEntry->eventTime);
-                break;
-            }
-
-            case EventEntry::TYPE_MOTION: {
-                MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
-
-                PointerCoords scaledCoords[MAX_POINTERS];
-                const PointerCoords* usingCoords = motionEntry->pointerCoords;
-
-                // Set the X and Y offset depending on the input source.
-                float xOffset, yOffset;
-                if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) &&
-                    !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
-                    float globalScaleFactor = dispatchEntry->globalScaleFactor;
-                    float wxs = dispatchEntry->windowXScale;
-                    float wys = dispatchEntry->windowYScale;
-                    xOffset = dispatchEntry->xOffset * wxs;
-                    yOffset = dispatchEntry->yOffset * wys;
-                    if (wxs != 1.0f || wys != 1.0f || globalScaleFactor != 1.0f) {
-                        for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
-                            scaledCoords[i] = motionEntry->pointerCoords[i];
-                            scaledCoords[i].scale(globalScaleFactor, wxs, wys);
-                        }
-                        usingCoords = scaledCoords;
-                    }
-                } else {
-                    xOffset = 0.0f;
-                    yOffset = 0.0f;
-
-                    // We don't want the dispatch target to know.
-                    if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
-                        for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
-                            scaledCoords[i].clear();
-                        }
-                        usingCoords = scaledCoords;
-                    }
-                }
-
-                // Publish the motion event.
-                status = connection->inputPublisher
-                                 .publishMotionEvent(dispatchEntry->seq, motionEntry->deviceId,
-                                                     motionEntry->source, motionEntry->displayId,
-                                                     dispatchEntry->resolvedAction,
-                                                     motionEntry->actionButton,
-                                                     dispatchEntry->resolvedFlags,
-                                                     motionEntry->edgeFlags, motionEntry->metaState,
-                                                     motionEntry->buttonState,
-                                                     motionEntry->classification, xOffset, yOffset,
-                                                     motionEntry->xPrecision,
-                                                     motionEntry->yPrecision, motionEntry->downTime,
-                                                     motionEntry->eventTime,
-                                                     motionEntry->pointerCount,
-                                                     motionEntry->pointerProperties, usingCoords);
-                break;
-            }
-
-            default:
-                ALOG_ASSERT(false);
-                return;
-        }
-
-        // Check the result.
-        if (status) {
-            if (status == WOULD_BLOCK) {
-                if (connection->waitQueue.isEmpty()) {
-                    ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "
-                          "This is unexpected because the wait queue is empty, so the pipe "
-                          "should be empty and we shouldn't have any problems writing an "
-                          "event to it, status=%d",
-                          connection->getInputChannelName().c_str(), status);
-                    abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
-                } else {
-                    // Pipe is full and we are waiting for the app to finish process some events
-                    // before sending more events to it.
-#if DEBUG_DISPATCH_CYCLE
-                    ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "
-                          "waiting for the application to catch up",
-                          connection->getInputChannelName().c_str());
-#endif
-                    connection->inputPublisherBlocked = true;
-                }
-            } else {
-                ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
-                      "status=%d",
-                      connection->getInputChannelName().c_str(), status);
-                abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
-            }
-            return;
-        }
-
-        // Re-enqueue the event on the wait queue.
-        connection->outboundQueue.dequeue(dispatchEntry);
-        traceOutboundQueueLength(connection);
-        connection->waitQueue.enqueueAtTail(dispatchEntry);
-        traceWaitQueueLength(connection);
-    }
-}
-
-void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
-                                                const sp<Connection>& connection, uint32_t seq,
-                                                bool handled) {
-#if DEBUG_DISPATCH_CYCLE
-    ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s",
-          connection->getInputChannelName().c_str(), seq, toString(handled));
-#endif
-
-    connection->inputPublisherBlocked = false;
-
-    if (connection->status == Connection::STATUS_BROKEN ||
-        connection->status == Connection::STATUS_ZOMBIE) {
-        return;
-    }
-
-    // Notify other system components and prepare to start the next dispatch cycle.
-    onDispatchCycleFinishedLocked(currentTime, connection, seq, handled);
-}
-
-void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
-                                                     const sp<Connection>& connection,
-                                                     bool notify) {
-#if DEBUG_DISPATCH_CYCLE
-    ALOGD("channel '%s' ~ abortBrokenDispatchCycle - notify=%s",
-          connection->getInputChannelName().c_str(), toString(notify));
-#endif
-
-    // Clear the dispatch queues.
-    drainDispatchQueue(&connection->outboundQueue);
-    traceOutboundQueueLength(connection);
-    drainDispatchQueue(&connection->waitQueue);
-    traceWaitQueueLength(connection);
-
-    // The connection appears to be unrecoverably broken.
-    // Ignore already broken or zombie connections.
-    if (connection->status == Connection::STATUS_NORMAL) {
-        connection->status = Connection::STATUS_BROKEN;
-
-        if (notify) {
-            // Notify other system components.
-            onDispatchCycleBrokenLocked(currentTime, connection);
-        }
-    }
-}
-
-void InputDispatcher::drainDispatchQueue(Queue<DispatchEntry>* queue) {
-    while (!queue->isEmpty()) {
-        DispatchEntry* dispatchEntry = queue->dequeueAtHead();
-        releaseDispatchEntry(dispatchEntry);
-    }
-}
-
-void InputDispatcher::releaseDispatchEntry(DispatchEntry* dispatchEntry) {
-    if (dispatchEntry->hasForegroundTarget()) {
-        decrementPendingForegroundDispatches(dispatchEntry->eventEntry);
-    }
-    delete dispatchEntry;
-}
-
-int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
-    InputDispatcher* d = static_cast<InputDispatcher*>(data);
-
-    { // acquire lock
-        std::scoped_lock _l(d->mLock);
-
-        ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);
-        if (connectionIndex < 0) {
-            ALOGE("Received spurious receive callback for unknown input channel.  "
-                  "fd=%d, events=0x%x",
-                  fd, events);
-            return 0; // remove the callback
-        }
-
-        bool notify;
-        sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);
-        if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
-            if (!(events & ALOOPER_EVENT_INPUT)) {
-                ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
-                      "events=0x%x",
-                      connection->getInputChannelName().c_str(), events);
-                return 1;
-            }
-
-            nsecs_t currentTime = now();
-            bool gotOne = false;
-            status_t status;
-            for (;;) {
-                uint32_t seq;
-                bool handled;
-                status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
-                if (status) {
-                    break;
-                }
-                d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
-                gotOne = true;
-            }
-            if (gotOne) {
-                d->runCommandsLockedInterruptible();
-                if (status == WOULD_BLOCK) {
-                    return 1;
-                }
-            }
-
-            notify = status != DEAD_OBJECT || !connection->monitor;
-            if (notify) {
-                ALOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",
-                      connection->getInputChannelName().c_str(), status);
-            }
-        } else {
-            // Monitor channels are never explicitly unregistered.
-            // We do it automatically when the remote endpoint is closed so don't warn
-            // about them.
-            notify = !connection->monitor;
-            if (notify) {
-                ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred.  "
-                      "events=0x%x",
-                      connection->getInputChannelName().c_str(), events);
-            }
-        }
-
-        // Unregister the channel.
-        d->unregisterInputChannelLocked(connection->inputChannel, notify);
-        return 0; // remove the callback
-    }             // release lock
-}
-
-void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked(
-        const CancelationOptions& options) {
-    for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
-        synthesizeCancelationEventsForConnectionLocked(mConnectionsByFd.valueAt(i), options);
-    }
-}
-
-void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked(
-        const CancelationOptions& options) {
-    synthesizeCancelationEventsForMonitorsLocked(options, mGlobalMonitorsByDisplay);
-    synthesizeCancelationEventsForMonitorsLocked(options, mGestureMonitorsByDisplay);
-}
-
-void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked(
-        const CancelationOptions& options,
-        std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) {
-    for (const auto& it : monitorsByDisplay) {
-        const std::vector<Monitor>& monitors = it.second;
-        for (const Monitor& monitor : monitors) {
-            synthesizeCancelationEventsForInputChannelLocked(monitor.inputChannel, options);
-        }
-    }
-}
-
-void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
-        const sp<InputChannel>& channel, const CancelationOptions& options) {
-    ssize_t index = getConnectionIndexLocked(channel);
-    if (index >= 0) {
-        synthesizeCancelationEventsForConnectionLocked(mConnectionsByFd.valueAt(index), options);
-    }
-}
-
-void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
-        const sp<Connection>& connection, const CancelationOptions& options) {
-    if (connection->status == Connection::STATUS_BROKEN) {
-        return;
-    }
-
-    nsecs_t currentTime = now();
-
-    std::vector<EventEntry*> cancelationEvents;
-    connection->inputState.synthesizeCancelationEvents(currentTime, cancelationEvents, options);
-
-    if (!cancelationEvents.empty()) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-        ALOGD("channel '%s' ~ Synthesized %zu cancelation events to bring channel back in sync "
-              "with reality: %s, mode=%d.",
-              connection->getInputChannelName().c_str(), cancelationEvents.size(), options.reason,
-              options.mode);
-#endif
-        for (size_t i = 0; i < cancelationEvents.size(); i++) {
-            EventEntry* cancelationEventEntry = cancelationEvents[i];
-            switch (cancelationEventEntry->type) {
-                case EventEntry::TYPE_KEY:
-                    logOutboundKeyDetails("cancel - ",
-                                          static_cast<KeyEntry*>(cancelationEventEntry));
-                    break;
-                case EventEntry::TYPE_MOTION:
-                    logOutboundMotionDetails("cancel - ",
-                                             static_cast<MotionEntry*>(cancelationEventEntry));
-                    break;
-            }
-
-            InputTarget target;
-            sp<InputWindowHandle> windowHandle =
-                    getWindowHandleLocked(connection->inputChannel->getToken());
-            if (windowHandle != nullptr) {
-                const InputWindowInfo* windowInfo = windowHandle->getInfo();
-                target.xOffset = -windowInfo->frameLeft;
-                target.yOffset = -windowInfo->frameTop;
-                target.globalScaleFactor = windowInfo->globalScaleFactor;
-                target.windowXScale = windowInfo->windowXScale;
-                target.windowYScale = windowInfo->windowYScale;
-            } else {
-                target.xOffset = 0;
-                target.yOffset = 0;
-                target.globalScaleFactor = 1.0f;
-            }
-            target.inputChannel = connection->inputChannel;
-            target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
-
-            enqueueDispatchEntryLocked(connection, cancelationEventEntry, // increments ref
-                                       &target, InputTarget::FLAG_DISPATCH_AS_IS);
-
-            cancelationEventEntry->release();
-        }
-
-        startDispatchCycleLocked(currentTime, connection);
-    }
-}
-
-MotionEntry* InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry,
-                                               BitSet32 pointerIds) {
-    ALOG_ASSERT(pointerIds.value != 0);
-
-    uint32_t splitPointerIndexMap[MAX_POINTERS];
-    PointerProperties splitPointerProperties[MAX_POINTERS];
-    PointerCoords splitPointerCoords[MAX_POINTERS];
-
-    uint32_t originalPointerCount = originalMotionEntry->pointerCount;
-    uint32_t splitPointerCount = 0;
-
-    for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount;
-         originalPointerIndex++) {
-        const PointerProperties& pointerProperties =
-                originalMotionEntry->pointerProperties[originalPointerIndex];
-        uint32_t pointerId = uint32_t(pointerProperties.id);
-        if (pointerIds.hasBit(pointerId)) {
-            splitPointerIndexMap[splitPointerCount] = originalPointerIndex;
-            splitPointerProperties[splitPointerCount].copyFrom(pointerProperties);
-            splitPointerCoords[splitPointerCount].copyFrom(
-                    originalMotionEntry->pointerCoords[originalPointerIndex]);
-            splitPointerCount += 1;
-        }
-    }
-
-    if (splitPointerCount != pointerIds.count()) {
-        // This is bad.  We are missing some of the pointers that we expected to deliver.
-        // Most likely this indicates that we received an ACTION_MOVE events that has
-        // different pointer ids than we expected based on the previous ACTION_DOWN
-        // or ACTION_POINTER_DOWN events that caused us to decide to split the pointers
-        // in this way.
-        ALOGW("Dropping split motion event because the pointer count is %d but "
-              "we expected there to be %d pointers.  This probably means we received "
-              "a broken sequence of pointer ids from the input device.",
-              splitPointerCount, pointerIds.count());
-        return nullptr;
-    }
-
-    int32_t action = originalMotionEntry->action;
-    int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
-    if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN ||
-        maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
-        int32_t originalPointerIndex = getMotionEventActionPointerIndex(action);
-        const PointerProperties& pointerProperties =
-                originalMotionEntry->pointerProperties[originalPointerIndex];
-        uint32_t pointerId = uint32_t(pointerProperties.id);
-        if (pointerIds.hasBit(pointerId)) {
-            if (pointerIds.count() == 1) {
-                // The first/last pointer went down/up.
-                action = maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
-                        ? AMOTION_EVENT_ACTION_DOWN
-                        : AMOTION_EVENT_ACTION_UP;
-            } else {
-                // A secondary pointer went down/up.
-                uint32_t splitPointerIndex = 0;
-                while (pointerId != uint32_t(splitPointerProperties[splitPointerIndex].id)) {
-                    splitPointerIndex += 1;
-                }
-                action = maskedAction |
-                        (splitPointerIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
-            }
-        } else {
-            // An unrelated pointer changed.
-            action = AMOTION_EVENT_ACTION_MOVE;
-        }
-    }
-
-    MotionEntry* splitMotionEntry =
-            new MotionEntry(originalMotionEntry->sequenceNum, originalMotionEntry->eventTime,
-                            originalMotionEntry->deviceId, originalMotionEntry->source,
-                            originalMotionEntry->displayId, originalMotionEntry->policyFlags,
-                            action, originalMotionEntry->actionButton, originalMotionEntry->flags,
-                            originalMotionEntry->metaState, originalMotionEntry->buttonState,
-                            originalMotionEntry->classification, originalMotionEntry->edgeFlags,
-                            originalMotionEntry->xPrecision, originalMotionEntry->yPrecision,
-                            originalMotionEntry->downTime, splitPointerCount,
-                            splitPointerProperties, splitPointerCoords, 0, 0);
-
-    if (originalMotionEntry->injectionState) {
-        splitMotionEntry->injectionState = originalMotionEntry->injectionState;
-        splitMotionEntry->injectionState->refCount += 1;
-    }
-
-    return splitMotionEntry;
-}
-
-void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
-#if DEBUG_INBOUND_EVENT_DETAILS
-    ALOGD("notifyConfigurationChanged - eventTime=%" PRId64, args->eventTime);
-#endif
-
-    bool needWake;
-    { // acquire lock
-        std::scoped_lock _l(mLock);
-
-        ConfigurationChangedEntry* newEntry =
-                new ConfigurationChangedEntry(args->sequenceNum, args->eventTime);
-        needWake = enqueueInboundEventLocked(newEntry);
-    } // release lock
-
-    if (needWake) {
-        mLooper->wake();
-    }
-}
-
-/**
- * If one of the meta shortcuts is detected, process them here:
- *     Meta + Backspace -> generate BACK
- *     Meta + Enter -> generate HOME
- * This will potentially overwrite keyCode and metaState.
- */
-void InputDispatcher::accelerateMetaShortcuts(const int32_t deviceId, const int32_t action,
-                                              int32_t& keyCode, int32_t& metaState) {
-    if (metaState & AMETA_META_ON && action == AKEY_EVENT_ACTION_DOWN) {
-        int32_t newKeyCode = AKEYCODE_UNKNOWN;
-        if (keyCode == AKEYCODE_DEL) {
-            newKeyCode = AKEYCODE_BACK;
-        } else if (keyCode == AKEYCODE_ENTER) {
-            newKeyCode = AKEYCODE_HOME;
-        }
-        if (newKeyCode != AKEYCODE_UNKNOWN) {
-            std::scoped_lock _l(mLock);
-            struct KeyReplacement replacement = {keyCode, deviceId};
-            mReplacedKeys.add(replacement, newKeyCode);
-            keyCode = newKeyCode;
-            metaState &= ~(AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON);
-        }
-    } else if (action == AKEY_EVENT_ACTION_UP) {
-        // In order to maintain a consistent stream of up and down events, check to see if the key
-        // going up is one we've replaced in a down event and haven't yet replaced in an up event,
-        // even if the modifier was released between the down and the up events.
-        std::scoped_lock _l(mLock);
-        struct KeyReplacement replacement = {keyCode, deviceId};
-        ssize_t index = mReplacedKeys.indexOfKey(replacement);
-        if (index >= 0) {
-            keyCode = mReplacedKeys.valueAt(index);
-            mReplacedKeys.removeItemsAt(index);
-            metaState &= ~(AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON);
-        }
-    }
-}
-
-void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
-#if DEBUG_INBOUND_EVENT_DETAILS
-    ALOGD("notifyKey - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32
-          "policyFlags=0x%x, action=0x%x, "
-          "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%" PRId64,
-          args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
-          args->action, args->flags, args->keyCode, args->scanCode, args->metaState,
-          args->downTime);
-#endif
-    if (!validateKeyEvent(args->action)) {
-        return;
-    }
-
-    uint32_t policyFlags = args->policyFlags;
-    int32_t flags = args->flags;
-    int32_t metaState = args->metaState;
-    // InputDispatcher tracks and generates key repeats on behalf of
-    // whatever notifies it, so repeatCount should always be set to 0
-    constexpr int32_t repeatCount = 0;
-    if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
-        policyFlags |= POLICY_FLAG_VIRTUAL;
-        flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
-    }
-    if (policyFlags & POLICY_FLAG_FUNCTION) {
-        metaState |= AMETA_FUNCTION_ON;
-    }
-
-    policyFlags |= POLICY_FLAG_TRUSTED;
-
-    int32_t keyCode = args->keyCode;
-    accelerateMetaShortcuts(args->deviceId, args->action, keyCode, metaState);
-
-    KeyEvent event;
-    event.initialize(args->deviceId, args->source, args->displayId, args->action, flags, keyCode,
-                     args->scanCode, metaState, repeatCount, args->downTime, args->eventTime);
-
-    android::base::Timer t;
-    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
-    if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
-        ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
-              std::to_string(t.duration().count()).c_str());
-    }
-
-    bool needWake;
-    { // acquire lock
-        mLock.lock();
-
-        if (shouldSendKeyToInputFilterLocked(args)) {
-            mLock.unlock();
-
-            policyFlags |= POLICY_FLAG_FILTERED;
-            if (!mPolicy->filterInputEvent(&event, policyFlags)) {
-                return; // event was consumed by the filter
-            }
-
-            mLock.lock();
-        }
-
-        KeyEntry* newEntry =
-                new KeyEntry(args->sequenceNum, args->eventTime, args->deviceId, args->source,
-                             args->displayId, policyFlags, args->action, flags, keyCode,
-                             args->scanCode, metaState, repeatCount, args->downTime);
-
-        needWake = enqueueInboundEventLocked(newEntry);
-        mLock.unlock();
-    } // release lock
-
-    if (needWake) {
-        mLooper->wake();
-    }
-}
-
-bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) {
-    return mInputFilterEnabled;
-}
-
-void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
-#if DEBUG_INBOUND_EVENT_DETAILS
-    ALOGD("notifyMotion - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32
-          ", policyFlags=0x%x, "
-          "action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x,"
-          "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
-          args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
-          args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
-          args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime);
-    for (uint32_t i = 0; i < args->pointerCount; i++) {
-        ALOGD("  Pointer %d: id=%d, toolType=%d, "
-              "x=%f, y=%f, pressure=%f, size=%f, "
-              "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
-              "orientation=%f",
-              i, args->pointerProperties[i].id, args->pointerProperties[i].toolType,
-              args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
-              args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
-              args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
-              args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
-              args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
-              args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
-              args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
-              args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
-              args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
-    }
-#endif
-    if (!validateMotionEvent(args->action, args->actionButton, args->pointerCount,
-                             args->pointerProperties)) {
-        return;
-    }
-
-    uint32_t policyFlags = args->policyFlags;
-    policyFlags |= POLICY_FLAG_TRUSTED;
-
-    android::base::Timer t;
-    mPolicy->interceptMotionBeforeQueueing(args->displayId, args->eventTime, /*byref*/ policyFlags);
-    if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
-        ALOGW("Excessive delay in interceptMotionBeforeQueueing; took %s ms",
-              std::to_string(t.duration().count()).c_str());
-    }
-
-    bool needWake;
-    { // acquire lock
-        mLock.lock();
-
-        if (shouldSendMotionToInputFilterLocked(args)) {
-            mLock.unlock();
-
-            MotionEvent event;
-            event.initialize(args->deviceId, args->source, args->displayId, args->action,
-                             args->actionButton, args->flags, args->edgeFlags, args->metaState,
-                             args->buttonState, args->classification, 0, 0, args->xPrecision,
-                             args->yPrecision, args->downTime, args->eventTime, args->pointerCount,
-                             args->pointerProperties, args->pointerCoords);
-
-            policyFlags |= POLICY_FLAG_FILTERED;
-            if (!mPolicy->filterInputEvent(&event, policyFlags)) {
-                return; // event was consumed by the filter
-            }
-
-            mLock.lock();
-        }
-
-        // Just enqueue a new motion event.
-        MotionEntry* newEntry =
-                new MotionEntry(args->sequenceNum, args->eventTime, args->deviceId, args->source,
-                                args->displayId, policyFlags, args->action, args->actionButton,
-                                args->flags, args->metaState, args->buttonState,
-                                args->classification, args->edgeFlags, args->xPrecision,
-                                args->yPrecision, args->downTime, args->pointerCount,
-                                args->pointerProperties, args->pointerCoords, 0, 0);
-
-        needWake = enqueueInboundEventLocked(newEntry);
-        mLock.unlock();
-    } // release lock
-
-    if (needWake) {
-        mLooper->wake();
-    }
-}
-
-bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) {
-    return mInputFilterEnabled;
-}
-
-void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) {
-#if DEBUG_INBOUND_EVENT_DETAILS
-    ALOGD("notifySwitch - eventTime=%" PRId64 ", policyFlags=0x%x, switchValues=0x%08x, "
-          "switchMask=0x%08x",
-          args->eventTime, args->policyFlags, args->switchValues, args->switchMask);
-#endif
-
-    uint32_t policyFlags = args->policyFlags;
-    policyFlags |= POLICY_FLAG_TRUSTED;
-    mPolicy->notifySwitch(args->eventTime, args->switchValues, args->switchMask, policyFlags);
-}
-
-void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
-#if DEBUG_INBOUND_EVENT_DETAILS
-    ALOGD("notifyDeviceReset - eventTime=%" PRId64 ", deviceId=%d", args->eventTime,
-          args->deviceId);
-#endif
-
-    bool needWake;
-    { // acquire lock
-        std::scoped_lock _l(mLock);
-
-        DeviceResetEntry* newEntry =
-                new DeviceResetEntry(args->sequenceNum, args->eventTime, args->deviceId);
-        needWake = enqueueInboundEventLocked(newEntry);
-    } // release lock
-
-    if (needWake) {
-        mLooper->wake();
-    }
-}
-
-int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t injectorPid,
-                                          int32_t injectorUid, int32_t syncMode,
-                                          int32_t timeoutMillis, uint32_t policyFlags) {
-#if DEBUG_INBOUND_EVENT_DETAILS
-    ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
-          "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x",
-          event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags);
-#endif
-
-    nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
-
-    policyFlags |= POLICY_FLAG_INJECTED;
-    if (hasInjectionPermission(injectorPid, injectorUid)) {
-        policyFlags |= POLICY_FLAG_TRUSTED;
-    }
-
-    EventEntry* firstInjectedEntry;
-    EventEntry* lastInjectedEntry;
-    switch (event->getType()) {
-        case AINPUT_EVENT_TYPE_KEY: {
-            KeyEvent keyEvent;
-            keyEvent.initialize(*static_cast<const KeyEvent*>(event));
-            int32_t action = keyEvent.getAction();
-            if (!validateKeyEvent(action)) {
-                return INPUT_EVENT_INJECTION_FAILED;
-            }
-
-            int32_t flags = keyEvent.getFlags();
-            int32_t keyCode = keyEvent.getKeyCode();
-            int32_t metaState = keyEvent.getMetaState();
-            accelerateMetaShortcuts(keyEvent.getDeviceId(), action,
-                                    /*byref*/ keyCode, /*byref*/ metaState);
-            keyEvent.initialize(keyEvent.getDeviceId(), keyEvent.getSource(),
-                                keyEvent.getDisplayId(), action, flags, keyCode,
-                                keyEvent.getScanCode(), metaState, keyEvent.getRepeatCount(),
-                                keyEvent.getDownTime(), keyEvent.getEventTime());
-
-            if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) {
-                policyFlags |= POLICY_FLAG_VIRTUAL;
-            }
-
-            if (!(policyFlags & POLICY_FLAG_FILTERED)) {
-                android::base::Timer t;
-                mPolicy->interceptKeyBeforeQueueing(&keyEvent, /*byref*/ policyFlags);
-                if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
-                    ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
-                          std::to_string(t.duration().count()).c_str());
-                }
-            }
-
-            mLock.lock();
-            firstInjectedEntry = new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM,
-                                              keyEvent.getEventTime(), keyEvent.getDeviceId(),
-                                              keyEvent.getSource(), keyEvent.getDisplayId(),
-                                              policyFlags, action, flags, keyEvent.getKeyCode(),
-                                              keyEvent.getScanCode(), keyEvent.getMetaState(),
-                                              keyEvent.getRepeatCount(), keyEvent.getDownTime());
-            lastInjectedEntry = firstInjectedEntry;
-            break;
-        }
-
-        case AINPUT_EVENT_TYPE_MOTION: {
-            const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
-            int32_t action = motionEvent->getAction();
-            size_t pointerCount = motionEvent->getPointerCount();
-            const PointerProperties* pointerProperties = motionEvent->getPointerProperties();
-            int32_t actionButton = motionEvent->getActionButton();
-            int32_t displayId = motionEvent->getDisplayId();
-            if (!validateMotionEvent(action, actionButton, pointerCount, pointerProperties)) {
-                return INPUT_EVENT_INJECTION_FAILED;
-            }
-
-            if (!(policyFlags & POLICY_FLAG_FILTERED)) {
-                nsecs_t eventTime = motionEvent->getEventTime();
-                android::base::Timer t;
-                mPolicy->interceptMotionBeforeQueueing(displayId, eventTime, /*byref*/ policyFlags);
-                if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
-                    ALOGW("Excessive delay in interceptMotionBeforeQueueing; took %s ms",
-                          std::to_string(t.duration().count()).c_str());
-                }
-            }
-
-            mLock.lock();
-            const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
-            const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
-            firstInjectedEntry =
-                    new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, *sampleEventTimes,
-                                    motionEvent->getDeviceId(), motionEvent->getSource(),
-                                    motionEvent->getDisplayId(), policyFlags, action, actionButton,
-                                    motionEvent->getFlags(), motionEvent->getMetaState(),
-                                    motionEvent->getButtonState(), motionEvent->getClassification(),
-                                    motionEvent->getEdgeFlags(), motionEvent->getXPrecision(),
-                                    motionEvent->getYPrecision(), motionEvent->getDownTime(),
-                                    uint32_t(pointerCount), pointerProperties, samplePointerCoords,
-                                    motionEvent->getXOffset(), motionEvent->getYOffset());
-            lastInjectedEntry = firstInjectedEntry;
-            for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
-                sampleEventTimes += 1;
-                samplePointerCoords += pointerCount;
-                MotionEntry* nextInjectedEntry =
-                        new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, *sampleEventTimes,
-                                        motionEvent->getDeviceId(), motionEvent->getSource(),
-                                        motionEvent->getDisplayId(), policyFlags, action,
-                                        actionButton, motionEvent->getFlags(),
-                                        motionEvent->getMetaState(), motionEvent->getButtonState(),
-                                        motionEvent->getClassification(),
-                                        motionEvent->getEdgeFlags(), motionEvent->getXPrecision(),
-                                        motionEvent->getYPrecision(), motionEvent->getDownTime(),
-                                        uint32_t(pointerCount), pointerProperties,
-                                        samplePointerCoords, motionEvent->getXOffset(),
-                                        motionEvent->getYOffset());
-                lastInjectedEntry->next = nextInjectedEntry;
-                lastInjectedEntry = nextInjectedEntry;
-            }
-            break;
-        }
-
-        default:
-            ALOGW("Cannot inject event of type %d", event->getType());
-            return INPUT_EVENT_INJECTION_FAILED;
-    }
-
-    InjectionState* injectionState = new InjectionState(injectorPid, injectorUid);
-    if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
-        injectionState->injectionIsAsync = true;
-    }
-
-    injectionState->refCount += 1;
-    lastInjectedEntry->injectionState = injectionState;
-
-    bool needWake = false;
-    for (EventEntry* entry = firstInjectedEntry; entry != nullptr;) {
-        EventEntry* nextEntry = entry->next;
-        needWake |= enqueueInboundEventLocked(entry);
-        entry = nextEntry;
-    }
-
-    mLock.unlock();
-
-    if (needWake) {
-        mLooper->wake();
-    }
-
-    int32_t injectionResult;
-    { // acquire lock
-        std::unique_lock _l(mLock);
-
-        if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
-            injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
-        } else {
-            for (;;) {
-                injectionResult = injectionState->injectionResult;
-                if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
-                    break;
-                }
-
-                nsecs_t remainingTimeout = endTime - now();
-                if (remainingTimeout <= 0) {
-#if DEBUG_INJECTION
-                    ALOGD("injectInputEvent - Timed out waiting for injection result "
-                          "to become available.");
-#endif
-                    injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
-                    break;
-                }
-
-                mInjectionResultAvailable.wait_for(_l, std::chrono::nanoseconds(remainingTimeout));
-            }
-
-            if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED &&
-                syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
-                while (injectionState->pendingForegroundDispatches != 0) {
-#if DEBUG_INJECTION
-                    ALOGD("injectInputEvent - Waiting for %d pending foreground dispatches.",
-                          injectionState->pendingForegroundDispatches);
-#endif
-                    nsecs_t remainingTimeout = endTime - now();
-                    if (remainingTimeout <= 0) {
-#if DEBUG_INJECTION
-                        ALOGD("injectInputEvent - Timed out waiting for pending foreground "
-                              "dispatches to finish.");
-#endif
-                        injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
-                        break;
-                    }
-
-                    mInjectionSyncFinished.wait_for(_l, std::chrono::nanoseconds(remainingTimeout));
-                }
-            }
-        }
-
-        injectionState->release();
-    } // release lock
-
-#if DEBUG_INJECTION
-    ALOGD("injectInputEvent - Finished with result %d.  "
-          "injectorPid=%d, injectorUid=%d",
-          injectionResult, injectorPid, injectorUid);
-#endif
-
-    return injectionResult;
-}
-
-bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
-    return injectorUid == 0 ||
-            mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
-}
-
-void InputDispatcher::setInjectionResult(EventEntry* entry, int32_t injectionResult) {
-    InjectionState* injectionState = entry->injectionState;
-    if (injectionState) {
-#if DEBUG_INJECTION
-        ALOGD("Setting input event injection result to %d.  "
-              "injectorPid=%d, injectorUid=%d",
-              injectionResult, injectionState->injectorPid, injectionState->injectorUid);
-#endif
-
-        if (injectionState->injectionIsAsync && !(entry->policyFlags & POLICY_FLAG_FILTERED)) {
-            // Log the outcome since the injector did not wait for the injection result.
-            switch (injectionResult) {
-                case INPUT_EVENT_INJECTION_SUCCEEDED:
-                    ALOGV("Asynchronous input event injection succeeded.");
-                    break;
-                case INPUT_EVENT_INJECTION_FAILED:
-                    ALOGW("Asynchronous input event injection failed.");
-                    break;
-                case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
-                    ALOGW("Asynchronous input event injection permission denied.");
-                    break;
-                case INPUT_EVENT_INJECTION_TIMED_OUT:
-                    ALOGW("Asynchronous input event injection timed out.");
-                    break;
-            }
-        }
-
-        injectionState->injectionResult = injectionResult;
-        mInjectionResultAvailable.notify_all();
-    }
-}
-
-void InputDispatcher::incrementPendingForegroundDispatches(EventEntry* entry) {
-    InjectionState* injectionState = entry->injectionState;
-    if (injectionState) {
-        injectionState->pendingForegroundDispatches += 1;
-    }
-}
-
-void InputDispatcher::decrementPendingForegroundDispatches(EventEntry* entry) {
-    InjectionState* injectionState = entry->injectionState;
-    if (injectionState) {
-        injectionState->pendingForegroundDispatches -= 1;
-
-        if (injectionState->pendingForegroundDispatches == 0) {
-            mInjectionSyncFinished.notify_all();
-        }
-    }
-}
-
-std::vector<sp<InputWindowHandle>> InputDispatcher::getWindowHandlesLocked(
-        int32_t displayId) const {
-    std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>>::const_iterator it =
-            mWindowHandlesByDisplay.find(displayId);
-    if (it != mWindowHandlesByDisplay.end()) {
-        return it->second;
-    }
-
-    // Return an empty one if nothing found.
-    return std::vector<sp<InputWindowHandle>>();
-}
-
-sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
-        const sp<IBinder>& windowHandleToken) const {
-    for (auto& it : mWindowHandlesByDisplay) {
-        const std::vector<sp<InputWindowHandle>> windowHandles = it.second;
-        for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
-            if (windowHandle->getToken() == windowHandleToken) {
-                return windowHandle;
-            }
-        }
-    }
-    return nullptr;
-}
-
-bool InputDispatcher::hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const {
-    for (auto& it : mWindowHandlesByDisplay) {
-        const std::vector<sp<InputWindowHandle>> windowHandles = it.second;
-        for (const sp<InputWindowHandle>& handle : windowHandles) {
-            if (handle->getToken() == windowHandle->getToken()) {
-                if (windowHandle->getInfo()->displayId != it.first) {
-                    ALOGE("Found window %s in display %" PRId32
-                          ", but it should belong to display %" PRId32,
-                          windowHandle->getName().c_str(), it.first,
-                          windowHandle->getInfo()->displayId);
-                }
-                return true;
-            }
-        }
-    }
-    return false;
-}
-
-sp<InputChannel> InputDispatcher::getInputChannelLocked(const sp<IBinder>& token) const {
-    size_t count = mInputChannelsByToken.count(token);
-    if (count == 0) {
-        return nullptr;
-    }
-    return mInputChannelsByToken.at(token);
-}
-
-/**
- * Called from InputManagerService, update window handle list by displayId that can receive input.
- * A window handle contains information about InputChannel, Touch Region, Types, Focused,...
- * If set an empty list, remove all handles from the specific display.
- * For focused handle, check if need to change and send a cancel event to previous one.
- * For removed handle, check if need to send a cancel event if already in touch.
- */
-void InputDispatcher::setInputWindows(const std::vector<sp<InputWindowHandle>>& inputWindowHandles,
-                                      int32_t displayId,
-                                      const sp<ISetInputWindowsListener>& setInputWindowsListener) {
-#if DEBUG_FOCUS
-    ALOGD("setInputWindows displayId=%" PRId32, displayId);
-#endif
-    { // acquire lock
-        std::scoped_lock _l(mLock);
-
-        // Copy old handles for release if they are no longer present.
-        const std::vector<sp<InputWindowHandle>> oldWindowHandles =
-                getWindowHandlesLocked(displayId);
-
-        sp<InputWindowHandle> newFocusedWindowHandle = nullptr;
-        bool foundHoveredWindow = false;
-
-        if (inputWindowHandles.empty()) {
-            // Remove all handles on a display if there are no windows left.
-            mWindowHandlesByDisplay.erase(displayId);
-        } else {
-            // Since we compare the pointer of input window handles across window updates, we need
-            // to make sure the handle object for the same window stays unchanged across updates.
-            const std::vector<sp<InputWindowHandle>>& oldHandles =
-                    mWindowHandlesByDisplay[displayId];
-            std::unordered_map<sp<IBinder>, sp<InputWindowHandle>, IBinderHash> oldHandlesByTokens;
-            for (const sp<InputWindowHandle>& handle : oldHandles) {
-                oldHandlesByTokens[handle->getToken()] = handle;
-            }
-
-            std::vector<sp<InputWindowHandle>> newHandles;
-            for (const sp<InputWindowHandle>& handle : inputWindowHandles) {
-                if (!handle->updateInfo()) {
-                    // handle no longer valid
-                    continue;
-                }
-                const InputWindowInfo* info = handle->getInfo();
-
-                if ((getInputChannelLocked(handle->getToken()) == nullptr &&
-                     info->portalToDisplayId == ADISPLAY_ID_NONE)) {
-                    const bool noInputChannel =
-                            info->inputFeatures & InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL;
-                    const bool canReceiveInput =
-                            !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_TOUCHABLE) ||
-                            !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_FOCUSABLE);
-                    if (canReceiveInput && !noInputChannel) {
-                        ALOGE("Window handle %s has no registered input channel",
-                              handle->getName().c_str());
-                    }
-                    continue;
-                }
-
-                if (info->displayId != displayId) {
-                    ALOGE("Window %s updated by wrong display %d, should belong to display %d",
-                          handle->getName().c_str(), displayId, info->displayId);
-                    continue;
-                }
-
-                if (oldHandlesByTokens.find(handle->getToken()) != oldHandlesByTokens.end()) {
-                    const sp<InputWindowHandle> oldHandle =
-                            oldHandlesByTokens.at(handle->getToken());
-                    oldHandle->updateFrom(handle);
-                    newHandles.push_back(oldHandle);
-                } else {
-                    newHandles.push_back(handle);
-                }
-            }
-
-            for (const sp<InputWindowHandle>& windowHandle : newHandles) {
-                // Set newFocusedWindowHandle to the top most focused window instead of the last one
-                if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus &&
-                    windowHandle->getInfo()->visible) {
-                    newFocusedWindowHandle = windowHandle;
-                }
-                if (windowHandle == mLastHoverWindowHandle) {
-                    foundHoveredWindow = true;
-                }
-            }
-
-            // Insert or replace
-            mWindowHandlesByDisplay[displayId] = newHandles;
-        }
-
-        if (!foundHoveredWindow) {
-            mLastHoverWindowHandle = nullptr;
-        }
-
-        sp<InputWindowHandle> oldFocusedWindowHandle =
-                getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
-
-        if (oldFocusedWindowHandle != newFocusedWindowHandle) {
-            if (oldFocusedWindowHandle != nullptr) {
-#if DEBUG_FOCUS
-                ALOGD("Focus left window: %s in display %" PRId32,
-                      oldFocusedWindowHandle->getName().c_str(), displayId);
-#endif
-                sp<InputChannel> focusedInputChannel =
-                        getInputChannelLocked(oldFocusedWindowHandle->getToken());
-                if (focusedInputChannel != nullptr) {
-                    CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
-                                               "focus left window");
-                    synthesizeCancelationEventsForInputChannelLocked(focusedInputChannel, options);
-                }
-                mFocusedWindowHandlesByDisplay.erase(displayId);
-            }
-            if (newFocusedWindowHandle != nullptr) {
-#if DEBUG_FOCUS
-                ALOGD("Focus entered window: %s in display %" PRId32,
-                      newFocusedWindowHandle->getName().c_str(), displayId);
-#endif
-                mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle;
-            }
-
-            if (mFocusedDisplayId == displayId) {
-                onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
-            }
-        }
-
-        ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
-        if (stateIndex >= 0) {
-            TouchState& state = mTouchStatesByDisplay.editValueAt(stateIndex);
-            for (size_t i = 0; i < state.windows.size();) {
-                TouchedWindow& touchedWindow = state.windows[i];
-                if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
-#if DEBUG_FOCUS
-                    ALOGD("Touched window was removed: %s in display %" PRId32,
-                          touchedWindow.windowHandle->getName().c_str(), displayId);
-#endif
-                    sp<InputChannel> touchedInputChannel =
-                            getInputChannelLocked(touchedWindow.windowHandle->getToken());
-                    if (touchedInputChannel != nullptr) {
-                        CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
-                                                   "touched window was removed");
-                        synthesizeCancelationEventsForInputChannelLocked(touchedInputChannel,
-                                                                         options);
-                    }
-                    state.windows.erase(state.windows.begin() + i);
-                } else {
-                    ++i;
-                }
-            }
-        }
-
-        // Release information for windows that are no longer present.
-        // This ensures that unused input channels are released promptly.
-        // Otherwise, they might stick around until the window handle is destroyed
-        // which might not happen until the next GC.
-        for (const sp<InputWindowHandle>& oldWindowHandle : oldWindowHandles) {
-            if (!hasWindowHandleLocked(oldWindowHandle)) {
-#if DEBUG_FOCUS
-                ALOGD("Window went away: %s", oldWindowHandle->getName().c_str());
-#endif
-                oldWindowHandle->releaseChannel();
-            }
-        }
-    } // release lock
-
-    // Wake up poll loop since it may need to make new input dispatching choices.
-    mLooper->wake();
-
-    if (setInputWindowsListener) {
-        setInputWindowsListener->onSetInputWindowsFinished();
-    }
-}
-
-void InputDispatcher::setFocusedApplication(
-        int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) {
-#if DEBUG_FOCUS
-    ALOGD("setFocusedApplication displayId=%" PRId32, displayId);
-#endif
-    { // acquire lock
-        std::scoped_lock _l(mLock);
-
-        sp<InputApplicationHandle> oldFocusedApplicationHandle =
-                getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
-        if (inputApplicationHandle != nullptr && inputApplicationHandle->updateInfo()) {
-            if (oldFocusedApplicationHandle != inputApplicationHandle) {
-                if (oldFocusedApplicationHandle != nullptr) {
-                    resetANRTimeoutsLocked();
-                }
-                mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
-            }
-        } else if (oldFocusedApplicationHandle != nullptr) {
-            resetANRTimeoutsLocked();
-            oldFocusedApplicationHandle.clear();
-            mFocusedApplicationHandlesByDisplay.erase(displayId);
-        }
-
-#if DEBUG_FOCUS
-        // logDispatchStateLocked();
-#endif
-    } // release lock
-
-    // Wake up poll loop since it may need to make new input dispatching choices.
-    mLooper->wake();
-}
-
-/**
- * Sets the focused display, which is responsible for receiving focus-dispatched input events where
- * the display not specified.
- *
- * We track any unreleased events for each window. If a window loses the ability to receive the
- * released event, we will send a cancel event to it. So when the focused display is changed, we
- * cancel all the unreleased display-unspecified events for the focused window on the old focused
- * display. The display-specified events won't be affected.
- */
-void InputDispatcher::setFocusedDisplay(int32_t displayId) {
-#if DEBUG_FOCUS
-    ALOGD("setFocusedDisplay displayId=%" PRId32, displayId);
-#endif
-    { // acquire lock
-        std::scoped_lock _l(mLock);
-
-        if (mFocusedDisplayId != displayId) {
-            sp<InputWindowHandle> oldFocusedWindowHandle =
-                    getValueByKey(mFocusedWindowHandlesByDisplay, mFocusedDisplayId);
-            if (oldFocusedWindowHandle != nullptr) {
-                sp<InputChannel> inputChannel =
-                        getInputChannelLocked(oldFocusedWindowHandle->getToken());
-                if (inputChannel != nullptr) {
-                    CancelationOptions
-                            options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
-                                    "The display which contains this window no longer has focus.");
-                    options.displayId = ADISPLAY_ID_NONE;
-                    synthesizeCancelationEventsForInputChannelLocked(inputChannel, options);
-                }
-            }
-            mFocusedDisplayId = displayId;
-
-            // Sanity check
-            sp<InputWindowHandle> newFocusedWindowHandle =
-                    getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
-            onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
-
-            if (newFocusedWindowHandle == nullptr) {
-                ALOGW("Focused display #%" PRId32 " does not have a focused window.", displayId);
-                if (!mFocusedWindowHandlesByDisplay.empty()) {
-                    ALOGE("But another display has a focused window:");
-                    for (auto& it : mFocusedWindowHandlesByDisplay) {
-                        const int32_t displayId = it.first;
-                        const sp<InputWindowHandle>& windowHandle = it.second;
-                        ALOGE("Display #%" PRId32 " has focused window: '%s'\n", displayId,
-                              windowHandle->getName().c_str());
-                    }
-                }
-            }
-        }
-
-#if DEBUG_FOCUS
-        logDispatchStateLocked();
-#endif
-    } // release lock
-
-    // Wake up poll loop since it may need to make new input dispatching choices.
-    mLooper->wake();
-}
-
-void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
-#if DEBUG_FOCUS
-    ALOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
-#endif
-
-    bool changed;
-    { // acquire lock
-        std::scoped_lock _l(mLock);
-
-        if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
-            if (mDispatchFrozen && !frozen) {
-                resetANRTimeoutsLocked();
-            }
-
-            if (mDispatchEnabled && !enabled) {
-                resetAndDropEverythingLocked("dispatcher is being disabled");
-            }
-
-            mDispatchEnabled = enabled;
-            mDispatchFrozen = frozen;
-            changed = true;
-        } else {
-            changed = false;
-        }
-
-#if DEBUG_FOCUS
-        logDispatchStateLocked();
-#endif
-    } // release lock
-
-    if (changed) {
-        // Wake up poll loop since it may need to make new input dispatching choices.
-        mLooper->wake();
-    }
-}
-
-void InputDispatcher::setInputFilterEnabled(bool enabled) {
-#if DEBUG_FOCUS
-    ALOGD("setInputFilterEnabled: enabled=%d", enabled);
-#endif
-
-    { // acquire lock
-        std::scoped_lock _l(mLock);
-
-        if (mInputFilterEnabled == enabled) {
-            return;
-        }
-
-        mInputFilterEnabled = enabled;
-        resetAndDropEverythingLocked("input filter is being enabled or disabled");
-    } // release lock
-
-    // Wake up poll loop since there might be work to do to drop everything.
-    mLooper->wake();
-}
-
-bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) {
-    if (fromToken == toToken) {
-#if DEBUG_FOCUS
-        ALOGD("Trivial transfer to same window.");
-#endif
-        return true;
-    }
-
-    { // acquire lock
-        std::scoped_lock _l(mLock);
-
-        sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromToken);
-        sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toToken);
-        if (fromWindowHandle == nullptr || toWindowHandle == nullptr) {
-            ALOGW("Cannot transfer focus because from or to window not found.");
-            return false;
-        }
-#if DEBUG_FOCUS
-        ALOGD("transferTouchFocus: fromWindowHandle=%s, toWindowHandle=%s",
-              fromWindowHandle->getName().c_str(), toWindowHandle->getName().c_str());
-#endif
-        if (fromWindowHandle->getInfo()->displayId != toWindowHandle->getInfo()->displayId) {
-#if DEBUG_FOCUS
-            ALOGD("Cannot transfer focus because windows are on different displays.");
-#endif
-            return false;
-        }
-
-        bool found = false;
-        for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) {
-            TouchState& state = mTouchStatesByDisplay.editValueAt(d);
-            for (size_t i = 0; i < state.windows.size(); i++) {
-                const TouchedWindow& touchedWindow = state.windows[i];
-                if (touchedWindow.windowHandle == fromWindowHandle) {
-                    int32_t oldTargetFlags = touchedWindow.targetFlags;
-                    BitSet32 pointerIds = touchedWindow.pointerIds;
-
-                    state.windows.erase(state.windows.begin() + i);
-
-                    int32_t newTargetFlags = oldTargetFlags &
-                            (InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_SPLIT |
-                             InputTarget::FLAG_DISPATCH_AS_IS);
-                    state.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds);
-
-                    found = true;
-                    goto Found;
-                }
-            }
-        }
-    Found:
-
-        if (!found) {
-#if DEBUG_FOCUS
-            ALOGD("Focus transfer failed because from window did not have focus.");
-#endif
-            return false;
-        }
-
-        sp<InputChannel> fromChannel = getInputChannelLocked(fromToken);
-        sp<InputChannel> toChannel = getInputChannelLocked(toToken);
-        ssize_t fromConnectionIndex = getConnectionIndexLocked(fromChannel);
-        ssize_t toConnectionIndex = getConnectionIndexLocked(toChannel);
-        if (fromConnectionIndex >= 0 && toConnectionIndex >= 0) {
-            sp<Connection> fromConnection = mConnectionsByFd.valueAt(fromConnectionIndex);
-            sp<Connection> toConnection = mConnectionsByFd.valueAt(toConnectionIndex);
-
-            fromConnection->inputState.copyPointerStateTo(toConnection->inputState);
-            CancelationOptions
-                    options(CancelationOptions::CANCEL_POINTER_EVENTS,
-                            "transferring touch focus from this window to another window");
-            synthesizeCancelationEventsForConnectionLocked(fromConnection, options);
-        }
-
-#if DEBUG_FOCUS
-        logDispatchStateLocked();
-#endif
-    } // release lock
-
-    // Wake up poll loop since it may need to make new input dispatching choices.
-    mLooper->wake();
-    return true;
-}
-
-void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
-#if DEBUG_FOCUS
-    ALOGD("Resetting and dropping all events (%s).", reason);
-#endif
-
-    CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS, reason);
-    synthesizeCancelationEventsForAllConnectionsLocked(options);
-
-    resetKeyRepeatLocked();
-    releasePendingEventLocked();
-    drainInboundQueueLocked();
-    resetANRTimeoutsLocked();
-
-    mTouchStatesByDisplay.clear();
-    mLastHoverWindowHandle.clear();
-    mReplacedKeys.clear();
-}
-
-void InputDispatcher::logDispatchStateLocked() {
-    std::string dump;
-    dumpDispatchStateLocked(dump);
-
-    std::istringstream stream(dump);
-    std::string line;
-
-    while (std::getline(stream, line, '\n')) {
-        ALOGD("%s", line.c_str());
-    }
-}
-
-void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
-    dump += StringPrintf(INDENT "DispatchEnabled: %s\n", toString(mDispatchEnabled));
-    dump += StringPrintf(INDENT "DispatchFrozen: %s\n", toString(mDispatchFrozen));
-    dump += StringPrintf(INDENT "InputFilterEnabled: %s\n", toString(mInputFilterEnabled));
-    dump += StringPrintf(INDENT "FocusedDisplayId: %" PRId32 "\n", mFocusedDisplayId);
-
-    if (!mFocusedApplicationHandlesByDisplay.empty()) {
-        dump += StringPrintf(INDENT "FocusedApplications:\n");
-        for (auto& it : mFocusedApplicationHandlesByDisplay) {
-            const int32_t displayId = it.first;
-            const sp<InputApplicationHandle>& applicationHandle = it.second;
-            dump += StringPrintf(INDENT2 "displayId=%" PRId32
-                                         ", name='%s', dispatchingTimeout=%0.3fms\n",
-                                 displayId, applicationHandle->getName().c_str(),
-                                 applicationHandle->getDispatchingTimeout(
-                                         DEFAULT_INPUT_DISPATCHING_TIMEOUT) /
-                                         1000000.0);
-        }
-    } else {
-        dump += StringPrintf(INDENT "FocusedApplications: <none>\n");
-    }
-
-    if (!mFocusedWindowHandlesByDisplay.empty()) {
-        dump += StringPrintf(INDENT "FocusedWindows:\n");
-        for (auto& it : mFocusedWindowHandlesByDisplay) {
-            const int32_t displayId = it.first;
-            const sp<InputWindowHandle>& windowHandle = it.second;
-            dump += StringPrintf(INDENT2 "displayId=%" PRId32 ", name='%s'\n", displayId,
-                                 windowHandle->getName().c_str());
-        }
-    } else {
-        dump += StringPrintf(INDENT "FocusedWindows: <none>\n");
-    }
-
-    if (!mTouchStatesByDisplay.isEmpty()) {
-        dump += StringPrintf(INDENT "TouchStatesByDisplay:\n");
-        for (size_t i = 0; i < mTouchStatesByDisplay.size(); i++) {
-            const TouchState& state = mTouchStatesByDisplay.valueAt(i);
-            dump += StringPrintf(INDENT2 "%d: down=%s, split=%s, deviceId=%d, source=0x%08x\n",
-                                 state.displayId, toString(state.down), toString(state.split),
-                                 state.deviceId, state.source);
-            if (!state.windows.empty()) {
-                dump += INDENT3 "Windows:\n";
-                for (size_t i = 0; i < state.windows.size(); i++) {
-                    const TouchedWindow& touchedWindow = state.windows[i];
-                    dump += StringPrintf(INDENT4
-                                         "%zu: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
-                                         i, touchedWindow.windowHandle->getName().c_str(),
-                                         touchedWindow.pointerIds.value, touchedWindow.targetFlags);
-                }
-            } else {
-                dump += INDENT3 "Windows: <none>\n";
-            }
-            if (!state.portalWindows.empty()) {
-                dump += INDENT3 "Portal windows:\n";
-                for (size_t i = 0; i < state.portalWindows.size(); i++) {
-                    const sp<InputWindowHandle> portalWindowHandle = state.portalWindows[i];
-                    dump += StringPrintf(INDENT4 "%zu: name='%s'\n", i,
-                                         portalWindowHandle->getName().c_str());
-                }
-            }
-        }
-    } else {
-        dump += INDENT "TouchStates: <no displays touched>\n";
-    }
-
-    if (!mWindowHandlesByDisplay.empty()) {
-        for (auto& it : mWindowHandlesByDisplay) {
-            const std::vector<sp<InputWindowHandle>> windowHandles = it.second;
-            dump += StringPrintf(INDENT "Display: %" PRId32 "\n", it.first);
-            if (!windowHandles.empty()) {
-                dump += INDENT2 "Windows:\n";
-                for (size_t i = 0; i < windowHandles.size(); i++) {
-                    const sp<InputWindowHandle>& windowHandle = windowHandles[i];
-                    const InputWindowInfo* windowInfo = windowHandle->getInfo();
-
-                    dump += StringPrintf(INDENT3 "%zu: name='%s', displayId=%d, "
-                                                 "portalToDisplayId=%d, paused=%s, hasFocus=%s, "
-                                                 "hasWallpaper=%s, "
-                                                 "visible=%s, canReceiveKeys=%s, flags=0x%08x, "
-                                                 "type=0x%08x, layer=%d, "
-                                                 "frame=[%d,%d][%d,%d], globalScale=%f, "
-                                                 "windowScale=(%f,%f), "
-                                                 "touchableRegion=",
-                                         i, windowInfo->name.c_str(), windowInfo->displayId,
-                                         windowInfo->portalToDisplayId,
-                                         toString(windowInfo->paused),
-                                         toString(windowInfo->hasFocus),
-                                         toString(windowInfo->hasWallpaper),
-                                         toString(windowInfo->visible),
-                                         toString(windowInfo->canReceiveKeys),
-                                         windowInfo->layoutParamsFlags,
-                                         windowInfo->layoutParamsType, windowInfo->layer,
-                                         windowInfo->frameLeft, windowInfo->frameTop,
-                                         windowInfo->frameRight, windowInfo->frameBottom,
-                                         windowInfo->globalScaleFactor, windowInfo->windowXScale,
-                                         windowInfo->windowYScale);
-                    dumpRegion(dump, windowInfo->touchableRegion);
-                    dump += StringPrintf(", inputFeatures=0x%08x", windowInfo->inputFeatures);
-                    dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
-                                         windowInfo->ownerPid, windowInfo->ownerUid,
-                                         windowInfo->dispatchingTimeout / 1000000.0);
-                }
-            } else {
-                dump += INDENT2 "Windows: <none>\n";
-            }
-        }
-    } else {
-        dump += INDENT "Displays: <none>\n";
-    }
-
-    if (!mGlobalMonitorsByDisplay.empty() || !mGestureMonitorsByDisplay.empty()) {
-        for (auto& it : mGlobalMonitorsByDisplay) {
-            const std::vector<Monitor>& monitors = it.second;
-            dump += StringPrintf(INDENT "Global monitors in display %" PRId32 ":\n", it.first);
-            dumpMonitors(dump, monitors);
-        }
-        for (auto& it : mGestureMonitorsByDisplay) {
-            const std::vector<Monitor>& monitors = it.second;
-            dump += StringPrintf(INDENT "Gesture monitors in display %" PRId32 ":\n", it.first);
-            dumpMonitors(dump, monitors);
-        }
-    } else {
-        dump += INDENT "Monitors: <none>\n";
-    }
-
-    nsecs_t currentTime = now();
-
-    // Dump recently dispatched or dropped events from oldest to newest.
-    if (!mRecentQueue.isEmpty()) {
-        dump += StringPrintf(INDENT "RecentQueue: length=%u\n", mRecentQueue.count());
-        for (EventEntry* entry = mRecentQueue.head; entry; entry = entry->next) {
-            dump += INDENT2;
-            entry->appendDescription(dump);
-            dump += StringPrintf(", age=%0.1fms\n", (currentTime - entry->eventTime) * 0.000001f);
-        }
-    } else {
-        dump += INDENT "RecentQueue: <empty>\n";
-    }
-
-    // Dump event currently being dispatched.
-    if (mPendingEvent) {
-        dump += INDENT "PendingEvent:\n";
-        dump += INDENT2;
-        mPendingEvent->appendDescription(dump);
-        dump += StringPrintf(", age=%0.1fms\n",
-                             (currentTime - mPendingEvent->eventTime) * 0.000001f);
-    } else {
-        dump += INDENT "PendingEvent: <none>\n";
-    }
-
-    // Dump inbound events from oldest to newest.
-    if (!mInboundQueue.isEmpty()) {
-        dump += StringPrintf(INDENT "InboundQueue: length=%u\n", mInboundQueue.count());
-        for (EventEntry* entry = mInboundQueue.head; entry; entry = entry->next) {
-            dump += INDENT2;
-            entry->appendDescription(dump);
-            dump += StringPrintf(", age=%0.1fms\n", (currentTime - entry->eventTime) * 0.000001f);
-        }
-    } else {
-        dump += INDENT "InboundQueue: <empty>\n";
-    }
-
-    if (!mReplacedKeys.isEmpty()) {
-        dump += INDENT "ReplacedKeys:\n";
-        for (size_t i = 0; i < mReplacedKeys.size(); i++) {
-            const KeyReplacement& replacement = mReplacedKeys.keyAt(i);
-            int32_t newKeyCode = mReplacedKeys.valueAt(i);
-            dump += StringPrintf(INDENT2 "%zu: originalKeyCode=%d, deviceId=%d, newKeyCode=%d\n", i,
-                                 replacement.keyCode, replacement.deviceId, newKeyCode);
-        }
-    } else {
-        dump += INDENT "ReplacedKeys: <empty>\n";
-    }
-
-    if (!mConnectionsByFd.isEmpty()) {
-        dump += INDENT "Connections:\n";
-        for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
-            const sp<Connection>& connection = mConnectionsByFd.valueAt(i);
-            dump += StringPrintf(INDENT2 "%zu: channelName='%s', windowName='%s', "
-                                         "status=%s, monitor=%s, inputPublisherBlocked=%s\n",
-                                 i, connection->getInputChannelName().c_str(),
-                                 connection->getWindowName().c_str(), connection->getStatusLabel(),
-                                 toString(connection->monitor),
-                                 toString(connection->inputPublisherBlocked));
-
-            if (!connection->outboundQueue.isEmpty()) {
-                dump += StringPrintf(INDENT3 "OutboundQueue: length=%u\n",
-                                     connection->outboundQueue.count());
-                for (DispatchEntry* entry = connection->outboundQueue.head; entry;
-                     entry = entry->next) {
-                    dump.append(INDENT4);
-                    entry->eventEntry->appendDescription(dump);
-                    dump += StringPrintf(", targetFlags=0x%08x, resolvedAction=%d, age=%0.1fms\n",
-                                         entry->targetFlags, entry->resolvedAction,
-                                         (currentTime - entry->eventEntry->eventTime) * 0.000001f);
-                }
-            } else {
-                dump += INDENT3 "OutboundQueue: <empty>\n";
-            }
-
-            if (!connection->waitQueue.isEmpty()) {
-                dump += StringPrintf(INDENT3 "WaitQueue: length=%u\n",
-                                     connection->waitQueue.count());
-                for (DispatchEntry* entry = connection->waitQueue.head; entry;
-                     entry = entry->next) {
-                    dump += INDENT4;
-                    entry->eventEntry->appendDescription(dump);
-                    dump += StringPrintf(", targetFlags=0x%08x, resolvedAction=%d, "
-                                         "age=%0.1fms, wait=%0.1fms\n",
-                                         entry->targetFlags, entry->resolvedAction,
-                                         (currentTime - entry->eventEntry->eventTime) * 0.000001f,
-                                         (currentTime - entry->deliveryTime) * 0.000001f);
-                }
-            } else {
-                dump += INDENT3 "WaitQueue: <empty>\n";
-            }
-        }
-    } else {
-        dump += INDENT "Connections: <none>\n";
-    }
-
-    if (isAppSwitchPendingLocked()) {
-        dump += StringPrintf(INDENT "AppSwitch: pending, due in %0.1fms\n",
-                             (mAppSwitchDueTime - now()) / 1000000.0);
-    } else {
-        dump += INDENT "AppSwitch: not pending\n";
-    }
-
-    dump += INDENT "Configuration:\n";
-    dump += StringPrintf(INDENT2 "KeyRepeatDelay: %0.1fms\n", mConfig.keyRepeatDelay * 0.000001f);
-    dump += StringPrintf(INDENT2 "KeyRepeatTimeout: %0.1fms\n",
-                         mConfig.keyRepeatTimeout * 0.000001f);
-}
-
-void InputDispatcher::dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors) {
-    const size_t numMonitors = monitors.size();
-    for (size_t i = 0; i < numMonitors; i++) {
-        const Monitor& monitor = monitors[i];
-        const sp<InputChannel>& channel = monitor.inputChannel;
-        dump += StringPrintf(INDENT2 "%zu: '%s', ", i, channel->getName().c_str());
-        dump += "\n";
-    }
-}
-
-status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
-                                               int32_t displayId) {
-#if DEBUG_REGISTRATION
-    ALOGD("channel '%s' ~ registerInputChannel - displayId=%" PRId32,
-          inputChannel->getName().c_str(), displayId);
-#endif
-
-    { // acquire lock
-        std::scoped_lock _l(mLock);
-
-        if (getConnectionIndexLocked(inputChannel) >= 0) {
-            ALOGW("Attempted to register already registered input channel '%s'",
-                  inputChannel->getName().c_str());
-            return BAD_VALUE;
-        }
-
-        sp<Connection> connection = new Connection(inputChannel, false /*monitor*/);
-
-        int fd = inputChannel->getFd();
-        mConnectionsByFd.add(fd, connection);
-        mInputChannelsByToken[inputChannel->getToken()] = inputChannel;
-
-        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
-    } // release lock
-
-    // Wake the looper because some connections have changed.
-    mLooper->wake();
-    return OK;
-}
-
-status_t InputDispatcher::registerInputMonitor(const sp<InputChannel>& inputChannel,
-                                               int32_t displayId, bool isGestureMonitor) {
-    { // acquire lock
-        std::scoped_lock _l(mLock);
-
-        if (displayId < 0) {
-            ALOGW("Attempted to register input monitor without a specified display.");
-            return BAD_VALUE;
-        }
-
-        if (inputChannel->getToken() == nullptr) {
-            ALOGW("Attempted to register input monitor without an identifying token.");
-            return BAD_VALUE;
-        }
-
-        sp<Connection> connection = new Connection(inputChannel, true /*monitor*/);
-
-        const int fd = inputChannel->getFd();
-        mConnectionsByFd.add(fd, connection);
-        mInputChannelsByToken[inputChannel->getToken()] = inputChannel;
-
-        auto& monitorsByDisplay =
-                isGestureMonitor ? mGestureMonitorsByDisplay : mGlobalMonitorsByDisplay;
-        monitorsByDisplay[displayId].emplace_back(inputChannel);
-
-        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
-    }
-    // Wake the looper because some connections have changed.
-    mLooper->wake();
-    return OK;
-}
-
-status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
-#if DEBUG_REGISTRATION
-    ALOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().c_str());
-#endif
-
-    { // acquire lock
-        std::scoped_lock _l(mLock);
-
-        status_t status = unregisterInputChannelLocked(inputChannel, false /*notify*/);
-        if (status) {
-            return status;
-        }
-    } // release lock
-
-    // Wake the poll loop because removing the connection may have changed the current
-    // synchronization state.
-    mLooper->wake();
-    return OK;
-}
-
-status_t InputDispatcher::unregisterInputChannelLocked(const sp<InputChannel>& inputChannel,
-                                                       bool notify) {
-    ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
-    if (connectionIndex < 0) {
-        ALOGW("Attempted to unregister already unregistered input channel '%s'",
-              inputChannel->getName().c_str());
-        return BAD_VALUE;
-    }
-
-    sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
-    mConnectionsByFd.removeItemsAt(connectionIndex);
-
-    mInputChannelsByToken.erase(inputChannel->getToken());
-
-    if (connection->monitor) {
-        removeMonitorChannelLocked(inputChannel);
-    }
-
-    mLooper->removeFd(inputChannel->getFd());
-
-    nsecs_t currentTime = now();
-    abortBrokenDispatchCycleLocked(currentTime, connection, notify);
-
-    connection->status = Connection::STATUS_ZOMBIE;
-    return OK;
-}
-
-void InputDispatcher::removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) {
-    removeMonitorChannelLocked(inputChannel, mGlobalMonitorsByDisplay);
-    removeMonitorChannelLocked(inputChannel, mGestureMonitorsByDisplay);
-}
-
-void InputDispatcher::removeMonitorChannelLocked(
-        const sp<InputChannel>& inputChannel,
-        std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) {
-    for (auto it = monitorsByDisplay.begin(); it != monitorsByDisplay.end();) {
-        std::vector<Monitor>& monitors = it->second;
-        const size_t numMonitors = monitors.size();
-        for (size_t i = 0; i < numMonitors; i++) {
-            if (monitors[i].inputChannel == inputChannel) {
-                monitors.erase(monitors.begin() + i);
-                break;
-            }
-        }
-        if (monitors.empty()) {
-            it = monitorsByDisplay.erase(it);
-        } else {
-            ++it;
-        }
-    }
-}
-
-status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) {
-    { // acquire lock
-        std::scoped_lock _l(mLock);
-        std::optional<int32_t> foundDisplayId = findGestureMonitorDisplayByTokenLocked(token);
-
-        if (!foundDisplayId) {
-            ALOGW("Attempted to pilfer pointers from an un-registered monitor or invalid token");
-            return BAD_VALUE;
-        }
-        int32_t displayId = foundDisplayId.value();
-
-        ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
-        if (stateIndex < 0) {
-            ALOGW("Failed to pilfer pointers: no pointers on display %" PRId32 ".", displayId);
-            return BAD_VALUE;
-        }
-
-        TouchState& state = mTouchStatesByDisplay.editValueAt(stateIndex);
-        std::optional<int32_t> foundDeviceId;
-        for (const TouchedMonitor& touchedMonitor : state.gestureMonitors) {
-            if (touchedMonitor.monitor.inputChannel->getToken() == token) {
-                foundDeviceId = state.deviceId;
-            }
-        }
-        if (!foundDeviceId || !state.down) {
-            ALOGW("Attempted to pilfer points from a monitor without any on-going pointer streams."
-                  " Ignoring.");
-            return BAD_VALUE;
-        }
-        int32_t deviceId = foundDeviceId.value();
-
-        // Send cancel events to all the input channels we're stealing from.
-        CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
-                                   "gesture monitor stole pointer stream");
-        options.deviceId = deviceId;
-        options.displayId = displayId;
-        for (const TouchedWindow& window : state.windows) {
-            sp<InputChannel> channel = getInputChannelLocked(window.windowHandle->getToken());
-            synthesizeCancelationEventsForInputChannelLocked(channel, options);
-        }
-        // Then clear the current touch state so we stop dispatching to them as well.
-        state.filterNonMonitors();
-    }
-    return OK;
-}
-
-std::optional<int32_t> InputDispatcher::findGestureMonitorDisplayByTokenLocked(
-        const sp<IBinder>& token) {
-    for (const auto& it : mGestureMonitorsByDisplay) {
-        const std::vector<Monitor>& monitors = it.second;
-        for (const Monitor& monitor : monitors) {
-            if (monitor.inputChannel->getToken() == token) {
-                return it.first;
-            }
-        }
-    }
-    return std::nullopt;
-}
-
-ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
-    if (inputChannel == nullptr) {
-        return -1;
-    }
-
-    for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
-        sp<Connection> connection = mConnectionsByFd.valueAt(i);
-        if (connection->inputChannel->getToken() == inputChannel->getToken()) {
-            return i;
-        }
-    }
-
-    return -1;
-}
-
-void InputDispatcher::onDispatchCycleFinishedLocked(nsecs_t currentTime,
-                                                    const sp<Connection>& connection, uint32_t seq,
-                                                    bool handled) {
-    CommandEntry* commandEntry =
-            postCommandLocked(&InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
-    commandEntry->connection = connection;
-    commandEntry->eventTime = currentTime;
-    commandEntry->seq = seq;
-    commandEntry->handled = handled;
-}
-
-void InputDispatcher::onDispatchCycleBrokenLocked(nsecs_t currentTime,
-                                                  const sp<Connection>& connection) {
-    ALOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
-          connection->getInputChannelName().c_str());
-
-    CommandEntry* commandEntry =
-            postCommandLocked(&InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
-    commandEntry->connection = connection;
-}
-
-void InputDispatcher::onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
-                                           const sp<InputWindowHandle>& newFocus) {
-    sp<IBinder> oldToken = oldFocus != nullptr ? oldFocus->getToken() : nullptr;
-    sp<IBinder> newToken = newFocus != nullptr ? newFocus->getToken() : nullptr;
-    CommandEntry* commandEntry =
-            postCommandLocked(&InputDispatcher::doNotifyFocusChangedLockedInterruptible);
-    commandEntry->oldToken = oldToken;
-    commandEntry->newToken = newToken;
-}
-
-void InputDispatcher::onANRLocked(nsecs_t currentTime,
-                                  const sp<InputApplicationHandle>& applicationHandle,
-                                  const sp<InputWindowHandle>& windowHandle, nsecs_t eventTime,
-                                  nsecs_t waitStartTime, const char* reason) {
-    float dispatchLatency = (currentTime - eventTime) * 0.000001f;
-    float waitDuration = (currentTime - waitStartTime) * 0.000001f;
-    ALOGI("Application is not responding: %s.  "
-          "It has been %0.1fms since event, %0.1fms since wait started.  Reason: %s",
-          getApplicationWindowLabel(applicationHandle, windowHandle).c_str(), dispatchLatency,
-          waitDuration, reason);
-
-    // Capture a record of the InputDispatcher state at the time of the ANR.
-    time_t t = time(nullptr);
-    struct tm tm;
-    localtime_r(&t, &tm);
-    char timestr[64];
-    strftime(timestr, sizeof(timestr), "%F %T", &tm);
-    mLastANRState.clear();
-    mLastANRState += INDENT "ANR:\n";
-    mLastANRState += StringPrintf(INDENT2 "Time: %s\n", timestr);
-    mLastANRState +=
-            StringPrintf(INDENT2 "Window: %s\n",
-                         getApplicationWindowLabel(applicationHandle, windowHandle).c_str());
-    mLastANRState += StringPrintf(INDENT2 "DispatchLatency: %0.1fms\n", dispatchLatency);
-    mLastANRState += StringPrintf(INDENT2 "WaitDuration: %0.1fms\n", waitDuration);
-    mLastANRState += StringPrintf(INDENT2 "Reason: %s\n", reason);
-    dumpDispatchStateLocked(mLastANRState);
-
-    CommandEntry* commandEntry =
-            postCommandLocked(&InputDispatcher::doNotifyANRLockedInterruptible);
-    commandEntry->inputApplicationHandle = applicationHandle;
-    commandEntry->inputChannel =
-            windowHandle != nullptr ? getInputChannelLocked(windowHandle->getToken()) : nullptr;
-    commandEntry->reason = reason;
-}
-
-void InputDispatcher::doNotifyConfigurationChangedLockedInterruptible(CommandEntry* commandEntry) {
-    mLock.unlock();
-
-    mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
-
-    mLock.lock();
-}
-
-void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry) {
-    sp<Connection> connection = commandEntry->connection;
-
-    if (connection->status != Connection::STATUS_ZOMBIE) {
-        mLock.unlock();
-
-        mPolicy->notifyInputChannelBroken(connection->inputChannel->getToken());
-
-        mLock.lock();
-    }
-}
-
-void InputDispatcher::doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) {
-    sp<IBinder> oldToken = commandEntry->oldToken;
-    sp<IBinder> newToken = commandEntry->newToken;
-    mLock.unlock();
-    mPolicy->notifyFocusChanged(oldToken, newToken);
-    mLock.lock();
-}
-
-void InputDispatcher::doNotifyANRLockedInterruptible(CommandEntry* commandEntry) {
-    mLock.unlock();
-
-    nsecs_t newTimeout =
-            mPolicy->notifyANR(commandEntry->inputApplicationHandle,
-                               commandEntry->inputChannel ? commandEntry->inputChannel->getToken()
-                                                          : nullptr,
-                               commandEntry->reason);
-
-    mLock.lock();
-
-    resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, commandEntry->inputChannel);
-}
-
-void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
-        CommandEntry* commandEntry) {
-    KeyEntry* entry = commandEntry->keyEntry;
-
-    KeyEvent event;
-    initializeKeyEvent(&event, entry);
-
-    mLock.unlock();
-
-    android::base::Timer t;
-    sp<IBinder> token = commandEntry->inputChannel != nullptr
-            ? commandEntry->inputChannel->getToken()
-            : nullptr;
-    nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(token, &event, entry->policyFlags);
-    if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
-        ALOGW("Excessive delay in interceptKeyBeforeDispatching; took %s ms",
-              std::to_string(t.duration().count()).c_str());
-    }
-
-    mLock.lock();
-
-    if (delay < 0) {
-        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;
-    } else if (!delay) {
-        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
-    } else {
-        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;
-        entry->interceptKeyWakeupTime = now() + delay;
-    }
-    entry->release();
-}
-
-void InputDispatcher::doOnPointerDownOutsideFocusLockedInterruptible(CommandEntry* commandEntry) {
-    mLock.unlock();
-    mPolicy->onPointerDownOutsideFocus(commandEntry->newToken);
-    mLock.lock();
-}
-
-void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry) {
-    sp<Connection> connection = commandEntry->connection;
-    nsecs_t finishTime = commandEntry->eventTime;
-    uint32_t seq = commandEntry->seq;
-    bool handled = commandEntry->handled;
-
-    // Handle post-event policy actions.
-    DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq);
-    if (dispatchEntry) {
-        nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;
-        if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
-            std::string msg =
-                    StringPrintf("Window '%s' spent %0.1fms processing the last input event: ",
-                                 connection->getWindowName().c_str(), eventDuration * 0.000001f);
-            dispatchEntry->eventEntry->appendDescription(msg);
-            ALOGI("%s", msg.c_str());
-        }
-
-        bool restartEvent;
-        if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
-            KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
-            restartEvent =
-                    afterKeyEventLockedInterruptible(connection, dispatchEntry, keyEntry, handled);
-        } else if (dispatchEntry->eventEntry->type == EventEntry::TYPE_MOTION) {
-            MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
-            restartEvent = afterMotionEventLockedInterruptible(connection, dispatchEntry,
-                                                               motionEntry, handled);
-        } else {
-            restartEvent = false;
-        }
-
-        // Dequeue the event and start the next cycle.
-        // Note that because the lock might have been released, it is possible that the
-        // contents of the wait queue to have been drained, so we need to double-check
-        // a few things.
-        if (dispatchEntry == connection->findWaitQueueEntry(seq)) {
-            connection->waitQueue.dequeue(dispatchEntry);
-            traceWaitQueueLength(connection);
-            if (restartEvent && connection->status == Connection::STATUS_NORMAL) {
-                connection->outboundQueue.enqueueAtHead(dispatchEntry);
-                traceOutboundQueueLength(connection);
-            } else {
-                releaseDispatchEntry(dispatchEntry);
-            }
-        }
-
-        // Start the next dispatch cycle for this connection.
-        startDispatchCycleLocked(now(), connection);
-    }
-}
-
-bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection,
-                                                       DispatchEntry* dispatchEntry,
-                                                       KeyEntry* keyEntry, bool handled) {
-    if (keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK) {
-        if (!handled) {
-            // Report the key as unhandled, since the fallback was not handled.
-            mReporter->reportUnhandledKey(keyEntry->sequenceNum);
-        }
-        return false;
-    }
-
-    // Get the fallback key state.
-    // Clear it out after dispatching the UP.
-    int32_t originalKeyCode = keyEntry->keyCode;
-    int32_t fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode);
-    if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
-        connection->inputState.removeFallbackKey(originalKeyCode);
-    }
-
-    if (handled || !dispatchEntry->hasForegroundTarget()) {
-        // If the application handles the original key for which we previously
-        // generated a fallback or if the window is not a foreground window,
-        // then cancel the associated fallback key, if any.
-        if (fallbackKeyCode != -1) {
-            // Dispatch the unhandled key to the policy with the cancel flag.
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-            ALOGD("Unhandled key event: Asking policy to cancel fallback action.  "
-                  "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
-                  keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount,
-                  keyEntry->policyFlags);
-#endif
-            KeyEvent event;
-            initializeKeyEvent(&event, keyEntry);
-            event.setFlags(event.getFlags() | AKEY_EVENT_FLAG_CANCELED);
-
-            mLock.unlock();
-
-            mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(), &event,
-                                          keyEntry->policyFlags, &event);
-
-            mLock.lock();
-
-            // Cancel the fallback key.
-            if (fallbackKeyCode != AKEYCODE_UNKNOWN) {
-                CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
-                                           "application handled the original non-fallback key "
-                                           "or is no longer a foreground target, "
-                                           "canceling previously dispatched fallback key");
-                options.keyCode = fallbackKeyCode;
-                synthesizeCancelationEventsForConnectionLocked(connection, options);
-            }
-            connection->inputState.removeFallbackKey(originalKeyCode);
-        }
-    } else {
-        // If the application did not handle a non-fallback key, first check
-        // that we are in a good state to perform unhandled key event processing
-        // Then ask the policy what to do with it.
-        bool initialDown = keyEntry->action == AKEY_EVENT_ACTION_DOWN && keyEntry->repeatCount == 0;
-        if (fallbackKeyCode == -1 && !initialDown) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-            ALOGD("Unhandled key event: Skipping unhandled key event processing "
-                  "since this is not an initial down.  "
-                  "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
-                  originalKeyCode, keyEntry->action, keyEntry->repeatCount, keyEntry->policyFlags);
-#endif
-            return false;
-        }
-
-        // Dispatch the unhandled key to the policy.
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-        ALOGD("Unhandled key event: Asking policy to perform fallback action.  "
-              "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
-              keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount, keyEntry->policyFlags);
-#endif
-        KeyEvent event;
-        initializeKeyEvent(&event, keyEntry);
-
-        mLock.unlock();
-
-        bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(), &event,
-                                                      keyEntry->policyFlags, &event);
-
-        mLock.lock();
-
-        if (connection->status != Connection::STATUS_NORMAL) {
-            connection->inputState.removeFallbackKey(originalKeyCode);
-            return false;
-        }
-
-        // Latch the fallback keycode for this key on an initial down.
-        // The fallback keycode cannot change at any other point in the lifecycle.
-        if (initialDown) {
-            if (fallback) {
-                fallbackKeyCode = event.getKeyCode();
-            } else {
-                fallbackKeyCode = AKEYCODE_UNKNOWN;
-            }
-            connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
-        }
-
-        ALOG_ASSERT(fallbackKeyCode != -1);
-
-        // Cancel the fallback key if the policy decides not to send it anymore.
-        // We will continue to dispatch the key to the policy but we will no
-        // longer dispatch a fallback key to the application.
-        if (fallbackKeyCode != AKEYCODE_UNKNOWN &&
-            (!fallback || fallbackKeyCode != event.getKeyCode())) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-            if (fallback) {
-                ALOGD("Unhandled key event: Policy requested to send key %d"
-                      "as a fallback for %d, but on the DOWN it had requested "
-                      "to send %d instead.  Fallback canceled.",
-                      event.getKeyCode(), originalKeyCode, fallbackKeyCode);
-            } else {
-                ALOGD("Unhandled key event: Policy did not request fallback for %d, "
-                      "but on the DOWN it had requested to send %d.  "
-                      "Fallback canceled.",
-                      originalKeyCode, fallbackKeyCode);
-            }
-#endif
-
-            CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
-                                       "canceling fallback, policy no longer desires it");
-            options.keyCode = fallbackKeyCode;
-            synthesizeCancelationEventsForConnectionLocked(connection, options);
-
-            fallback = false;
-            fallbackKeyCode = AKEYCODE_UNKNOWN;
-            if (keyEntry->action != AKEY_EVENT_ACTION_UP) {
-                connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
-            }
-        }
-
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-        {
-            std::string msg;
-            const KeyedVector<int32_t, int32_t>& fallbackKeys =
-                    connection->inputState.getFallbackKeys();
-            for (size_t i = 0; i < fallbackKeys.size(); i++) {
-                msg += StringPrintf(", %d->%d", fallbackKeys.keyAt(i), fallbackKeys.valueAt(i));
-            }
-            ALOGD("Unhandled key event: %zu currently tracked fallback keys%s.",
-                  fallbackKeys.size(), msg.c_str());
-        }
-#endif
-
-        if (fallback) {
-            // Restart the dispatch cycle using the fallback key.
-            keyEntry->eventTime = event.getEventTime();
-            keyEntry->deviceId = event.getDeviceId();
-            keyEntry->source = event.getSource();
-            keyEntry->displayId = event.getDisplayId();
-            keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
-            keyEntry->keyCode = fallbackKeyCode;
-            keyEntry->scanCode = event.getScanCode();
-            keyEntry->metaState = event.getMetaState();
-            keyEntry->repeatCount = event.getRepeatCount();
-            keyEntry->downTime = event.getDownTime();
-            keyEntry->syntheticRepeat = false;
-
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-            ALOGD("Unhandled key event: Dispatching fallback key.  "
-                  "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
-                  originalKeyCode, fallbackKeyCode, keyEntry->metaState);
-#endif
-            return true; // restart the event
-        } else {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-            ALOGD("Unhandled key event: No fallback key.");
-#endif
-
-            // Report the key as unhandled, since there is no fallback key.
-            mReporter->reportUnhandledKey(keyEntry->sequenceNum);
-        }
-    }
-    return false;
-}
-
-bool InputDispatcher::afterMotionEventLockedInterruptible(const sp<Connection>& connection,
-                                                          DispatchEntry* dispatchEntry,
-                                                          MotionEntry* motionEntry, bool handled) {
-    return false;
-}
-
-void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
-    mLock.unlock();
-
-    mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType);
-
-    mLock.lock();
-}
-
-void InputDispatcher::initializeKeyEvent(KeyEvent* event, const KeyEntry* entry) {
-    event->initialize(entry->deviceId, entry->source, entry->displayId, entry->action, entry->flags,
-                      entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
-                      entry->downTime, entry->eventTime);
-}
-
-void InputDispatcher::updateDispatchStatistics(nsecs_t currentTime, const EventEntry* entry,
-                                               int32_t injectionResult,
-                                               nsecs_t timeSpentWaitingForApplication) {
-    // TODO Write some statistics about how long we spend waiting.
-}
-
-void InputDispatcher::traceInboundQueueLengthLocked() {
-    if (ATRACE_ENABLED()) {
-        ATRACE_INT("iq", mInboundQueue.count());
-    }
-}
-
-void InputDispatcher::traceOutboundQueueLength(const sp<Connection>& connection) {
-    if (ATRACE_ENABLED()) {
-        char counterName[40];
-        snprintf(counterName, sizeof(counterName), "oq:%s", connection->getWindowName().c_str());
-        ATRACE_INT(counterName, connection->outboundQueue.count());
-    }
-}
-
-void InputDispatcher::traceWaitQueueLength(const sp<Connection>& connection) {
-    if (ATRACE_ENABLED()) {
-        char counterName[40];
-        snprintf(counterName, sizeof(counterName), "wq:%s", connection->getWindowName().c_str());
-        ATRACE_INT(counterName, connection->waitQueue.count());
-    }
-}
-
-void InputDispatcher::dump(std::string& dump) {
-    std::scoped_lock _l(mLock);
-
-    dump += "Input Dispatcher State:\n";
-    dumpDispatchStateLocked(dump);
-
-    if (!mLastANRState.empty()) {
-        dump += "\nInput Dispatcher State at time of last ANR:\n";
-        dump += mLastANRState;
-    }
-}
-
-void InputDispatcher::monitor() {
-    // Acquire and release the lock to ensure that the dispatcher has not deadlocked.
-    std::unique_lock _l(mLock);
-    mLooper->wake();
-    mDispatcherIsAlive.wait(_l);
-}
-
-} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
deleted file mode 100644
index 67bf199..0000000
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#ifndef _UI_INPUT_DISPATCHER_H
-#define _UI_INPUT_DISPATCHER_H
-
-#include "CancelationOptions.h"
-#include "Entry.h"
-#include "InjectionState.h"
-#include "InputDispatcherConfiguration.h"
-#include "InputDispatcherInterface.h"
-#include "InputDispatcherPolicyInterface.h"
-#include "InputState.h"
-#include "InputTarget.h"
-#include "Monitor.h"
-#include "Queue.h"
-#include "TouchState.h"
-#include "TouchedWindow.h"
-
-#include <cutils/atomic.h>
-#include <input/Input.h>
-#include <input/InputApplication.h>
-#include <input/InputTransport.h>
-#include <input/InputWindow.h>
-#include <limits.h>
-#include <stddef.h>
-#include <ui/Region.h>
-#include <unistd.h>
-#include <utils/BitSet.h>
-#include <utils/Looper.h>
-#include <utils/RefBase.h>
-#include <utils/Timers.h>
-#include <utils/threads.h>
-#include <condition_variable>
-#include <deque>
-#include <optional>
-#include <unordered_map>
-
-#include <InputListener.h>
-#include <InputReporterInterface.h>
-
-namespace android::inputdispatcher {
-
-class Connection;
-
-/* Dispatches events to input targets.  Some functions of the input dispatcher, such as
- * identifying input targets, are controlled by a separate policy object.
- *
- * IMPORTANT INVARIANT:
- *     Because the policy can potentially block or cause re-entrance into the input dispatcher,
- *     the input dispatcher never calls into the policy while holding its internal locks.
- *     The implementation is also carefully designed to recover from scenarios such as an
- *     input channel becoming unregistered while identifying input targets or processing timeouts.
- *
- *     Methods marked 'Locked' must be called with the lock acquired.
- *
- *     Methods marked 'LockedInterruptible' must be called with the lock acquired but
- *     may during the course of their execution release the lock, call into the policy, and
- *     then reacquire the lock.  The caller is responsible for recovering gracefully.
- *
- *     A 'LockedInterruptible' method may called a 'Locked' method, but NOT vice-versa.
- */
-class InputDispatcher : public android::InputDispatcherInterface {
-protected:
-    virtual ~InputDispatcher();
-
-public:
-    explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
-
-    virtual void dump(std::string& dump) override;
-    virtual void monitor() override;
-
-    virtual void dispatchOnce() override;
-
-    virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
-    virtual void notifyKey(const NotifyKeyArgs* args) override;
-    virtual void notifyMotion(const NotifyMotionArgs* args) override;
-    virtual void notifySwitch(const NotifySwitchArgs* args) override;
-    virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
-
-    virtual int32_t injectInputEvent(const InputEvent* event, int32_t injectorPid,
-                                     int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
-                                     uint32_t policyFlags) override;
-
-    virtual void setInputWindows(
-            const std::vector<sp<InputWindowHandle>>& inputWindowHandles, int32_t displayId,
-            const sp<ISetInputWindowsListener>& setInputWindowsListener = nullptr) override;
-    virtual void setFocusedApplication(
-            int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) override;
-    virtual void setFocusedDisplay(int32_t displayId) override;
-    virtual void setInputDispatchMode(bool enabled, bool frozen) override;
-    virtual void setInputFilterEnabled(bool enabled) override;
-
-    virtual bool transferTouchFocus(const sp<IBinder>& fromToken,
-                                    const sp<IBinder>& toToken) override;
-
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
-                                          int32_t displayId) override;
-    virtual status_t registerInputMonitor(const sp<InputChannel>& inputChannel, int32_t displayId,
-                                          bool isGestureMonitor) override;
-    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) override;
-    virtual status_t pilferPointers(const sp<IBinder>& token) override;
-
-private:
-
-    enum DropReason {
-        DROP_REASON_NOT_DROPPED = 0,
-        DROP_REASON_POLICY = 1,
-        DROP_REASON_APP_SWITCH = 2,
-        DROP_REASON_DISABLED = 3,
-        DROP_REASON_BLOCKED = 4,
-        DROP_REASON_STALE = 5,
-    };
-
-    sp<InputDispatcherPolicyInterface> mPolicy;
-    android::InputDispatcherConfiguration mConfig;
-
-    std::mutex mLock;
-
-    std::condition_variable mDispatcherIsAlive;
-
-    sp<Looper> mLooper;
-
-    EventEntry* mPendingEvent GUARDED_BY(mLock);
-    Queue<EventEntry> mInboundQueue GUARDED_BY(mLock);
-    Queue<EventEntry> mRecentQueue GUARDED_BY(mLock);
-    Queue<CommandEntry> mCommandQueue GUARDED_BY(mLock);
-
-    DropReason mLastDropReason GUARDED_BY(mLock);
-
-    void dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) REQUIRES(mLock);
-
-    // Enqueues an inbound event.  Returns true if mLooper->wake() should be called.
-    bool enqueueInboundEventLocked(EventEntry* entry) REQUIRES(mLock);
-
-    // Cleans up input state when dropping an inbound event.
-    void dropInboundEventLocked(EventEntry* entry, DropReason dropReason) REQUIRES(mLock);
-
-    // Adds an event to a queue of recent events for debugging purposes.
-    void addRecentEventLocked(EventEntry* entry) REQUIRES(mLock);
-
-    // App switch latency optimization.
-    bool mAppSwitchSawKeyDown GUARDED_BY(mLock);
-    nsecs_t mAppSwitchDueTime GUARDED_BY(mLock);
-
-    bool isAppSwitchKeyEvent(KeyEntry* keyEntry);
-    bool isAppSwitchPendingLocked() REQUIRES(mLock);
-    void resetPendingAppSwitchLocked(bool handled) REQUIRES(mLock);
-
-    // Stale event latency optimization.
-    static bool isStaleEvent(nsecs_t currentTime, EventEntry* entry);
-
-    // Blocked event latency optimization.  Drops old events when the user intends
-    // to transfer focus to a new application.
-    EventEntry* mNextUnblockedEvent GUARDED_BY(mLock);
-
-    sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y,
-                                                    bool addOutsideTargets = false,
-                                                    bool addPortalWindows = false) REQUIRES(mLock);
-
-    // All registered connections mapped by channel file descriptor.
-    KeyedVector<int, sp<Connection>> mConnectionsByFd GUARDED_BY(mLock);
-
-    struct IBinderHash {
-        std::size_t operator()(const sp<IBinder>& b) const {
-            return std::hash<IBinder*>{}(b.get());
-        }
-    };
-    std::unordered_map<sp<IBinder>, sp<InputChannel>, IBinderHash> mInputChannelsByToken
-            GUARDED_BY(mLock);
-
-    // Finds the display ID of the gesture monitor identified by the provided token.
-    std::optional<int32_t> findGestureMonitorDisplayByTokenLocked(const sp<IBinder>& token)
-            REQUIRES(mLock);
-
-    ssize_t getConnectionIndexLocked(const sp<InputChannel>& inputChannel) REQUIRES(mLock);
-
-    // Input channels that will receive a copy of all input events sent to the provided display.
-    std::unordered_map<int32_t, std::vector<Monitor>> mGlobalMonitorsByDisplay GUARDED_BY(mLock);
-
-    // Input channels that will receive pointer events that start within the corresponding display.
-    // These are a bit special when compared to global monitors since they'll cause gesture streams
-    // to continue even when there isn't a touched window,and have the ability to steal the rest of
-    // the pointer stream in order to claim it for a system gesture.
-    std::unordered_map<int32_t, std::vector<Monitor>> mGestureMonitorsByDisplay GUARDED_BY(mLock);
-
-    // Event injection and synchronization.
-    std::condition_variable mInjectionResultAvailable;
-    bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
-    void setInjectionResult(EventEntry* entry, int32_t injectionResult);
-
-    std::condition_variable mInjectionSyncFinished;
-    void incrementPendingForegroundDispatches(EventEntry* entry);
-    void decrementPendingForegroundDispatches(EventEntry* entry);
-
-    // Key repeat tracking.
-    struct KeyRepeatState {
-        KeyEntry* lastKeyEntry; // or null if no repeat
-        nsecs_t nextRepeatTime;
-    } mKeyRepeatState GUARDED_BY(mLock);
-
-    void resetKeyRepeatLocked() REQUIRES(mLock);
-    KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime) REQUIRES(mLock);
-
-    // Key replacement tracking
-    struct KeyReplacement {
-        int32_t keyCode;
-        int32_t deviceId;
-        bool operator==(const KeyReplacement& rhs) const {
-            return keyCode == rhs.keyCode && deviceId == rhs.deviceId;
-        }
-        bool operator<(const KeyReplacement& rhs) const {
-            return keyCode != rhs.keyCode ? keyCode < rhs.keyCode : deviceId < rhs.deviceId;
-        }
-    };
-    // Maps the key code replaced, device id tuple to the key code it was replaced with
-    KeyedVector<KeyReplacement, int32_t> mReplacedKeys GUARDED_BY(mLock);
-    // Process certain Meta + Key combinations
-    void accelerateMetaShortcuts(const int32_t deviceId, const int32_t action, int32_t& keyCode,
-                                 int32_t& metaState);
-
-    // Deferred command processing.
-    bool haveCommandsLocked() const REQUIRES(mLock);
-    bool runCommandsLockedInterruptible() REQUIRES(mLock);
-    CommandEntry* postCommandLocked(Command command) REQUIRES(mLock);
-
-    // Input filter processing.
-    bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) REQUIRES(mLock);
-    bool shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) REQUIRES(mLock);
-
-    // Inbound event processing.
-    void drainInboundQueueLocked() REQUIRES(mLock);
-    void releasePendingEventLocked() REQUIRES(mLock);
-    void releaseInboundEventLocked(EventEntry* entry) REQUIRES(mLock);
-
-    // Dispatch state.
-    bool mDispatchEnabled GUARDED_BY(mLock);
-    bool mDispatchFrozen GUARDED_BY(mLock);
-    bool mInputFilterEnabled GUARDED_BY(mLock);
-
-    std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mWindowHandlesByDisplay
-            GUARDED_BY(mLock);
-    // Get window handles by display, return an empty vector if not found.
-    std::vector<sp<InputWindowHandle>> getWindowHandlesLocked(int32_t displayId) const
-            REQUIRES(mLock);
-    sp<InputWindowHandle> getWindowHandleLocked(const sp<IBinder>& windowHandleToken) const
-            REQUIRES(mLock);
-    sp<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken) const REQUIRES(mLock);
-    bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock);
-
-    // Focus tracking for keys, trackball, etc.
-    std::unordered_map<int32_t, sp<InputWindowHandle>> mFocusedWindowHandlesByDisplay
-            GUARDED_BY(mLock);
-
-    KeyedVector<int32_t, TouchState> mTouchStatesByDisplay GUARDED_BY(mLock);
-    TouchState mTempTouchState GUARDED_BY(mLock);
-
-    // Focused applications.
-    std::unordered_map<int32_t, sp<InputApplicationHandle>> mFocusedApplicationHandlesByDisplay
-            GUARDED_BY(mLock);
-
-    // Top focused display.
-    int32_t mFocusedDisplayId GUARDED_BY(mLock);
-
-    // Dispatcher state at time of last ANR.
-    std::string mLastANRState GUARDED_BY(mLock);
-
-    // Dispatch inbound events.
-    bool dispatchConfigurationChangedLocked(nsecs_t currentTime, ConfigurationChangedEntry* entry)
-            REQUIRES(mLock);
-    bool dispatchDeviceResetLocked(nsecs_t currentTime, DeviceResetEntry* entry) REQUIRES(mLock);
-    bool dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry, DropReason* dropReason,
-                           nsecs_t* nextWakeupTime) REQUIRES(mLock);
-    bool dispatchMotionLocked(nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason,
-                              nsecs_t* nextWakeupTime) REQUIRES(mLock);
-    void dispatchEventLocked(nsecs_t currentTime, EventEntry* entry,
-                             const std::vector<InputTarget>& inputTargets) REQUIRES(mLock);
-
-    void logOutboundKeyDetails(const char* prefix, const KeyEntry* entry);
-    void logOutboundMotionDetails(const char* prefix, const MotionEntry* entry);
-
-    // Keeping track of ANR timeouts.
-    enum InputTargetWaitCause {
-        INPUT_TARGET_WAIT_CAUSE_NONE,
-        INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY,
-        INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY,
-    };
-
-    InputTargetWaitCause mInputTargetWaitCause GUARDED_BY(mLock);
-    nsecs_t mInputTargetWaitStartTime GUARDED_BY(mLock);
-    nsecs_t mInputTargetWaitTimeoutTime GUARDED_BY(mLock);
-    bool mInputTargetWaitTimeoutExpired GUARDED_BY(mLock);
-    sp<IBinder> mInputTargetWaitApplicationToken GUARDED_BY(mLock);
-
-    // Contains the last window which received a hover event.
-    sp<InputWindowHandle> mLastHoverWindowHandle GUARDED_BY(mLock);
-
-    // Finding targets for input events.
-    int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry,
-                                        const sp<InputApplicationHandle>& applicationHandle,
-                                        const sp<InputWindowHandle>& windowHandle,
-                                        nsecs_t* nextWakeupTime, const char* reason)
-            REQUIRES(mLock);
-
-    void removeWindowByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock);
-
-    void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
-                                                 const sp<InputChannel>& inputChannel)
-            REQUIRES(mLock);
-    nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime) REQUIRES(mLock);
-    void resetANRTimeoutsLocked() REQUIRES(mLock);
-
-    int32_t getTargetDisplayId(const EventEntry* entry);
-    int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry* entry,
-                                           std::vector<InputTarget>& inputTargets,
-                                           nsecs_t* nextWakeupTime) REQUIRES(mLock);
-    int32_t findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry,
-                                           std::vector<InputTarget>& inputTargets,
-                                           nsecs_t* nextWakeupTime,
-                                           bool* outConflictingPointerActions) REQUIRES(mLock);
-    std::vector<TouchedMonitor> findTouchedGestureMonitorsLocked(
-            int32_t displayId, const std::vector<sp<InputWindowHandle>>& portalWindows)
-            REQUIRES(mLock);
-    void addGestureMonitors(const std::vector<Monitor>& monitors,
-                            std::vector<TouchedMonitor>& outTouchedMonitors, float xOffset = 0,
-                            float yOffset = 0);
-
-    void addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle, int32_t targetFlags,
-                               BitSet32 pointerIds, std::vector<InputTarget>& inputTargets)
-            REQUIRES(mLock);
-    void addMonitoringTargetLocked(const Monitor& monitor, float xOffset, float yOffset,
-                                   std::vector<InputTarget>& inputTargets) REQUIRES(mLock);
-    void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId,
-                                          float xOffset = 0, float yOffset = 0) REQUIRES(mLock);
-
-    void pokeUserActivityLocked(const EventEntry* eventEntry) REQUIRES(mLock);
-    bool checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
-                                  const InjectionState* injectionState);
-    bool isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle, int32_t x,
-                                       int32_t y) const REQUIRES(mLock);
-    bool isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock);
-    std::string getApplicationWindowLabel(const sp<InputApplicationHandle>& applicationHandle,
-                                          const sp<InputWindowHandle>& windowHandle);
-
-    std::string checkWindowReadyForMoreInputLocked(nsecs_t currentTime,
-                                                   const sp<InputWindowHandle>& windowHandle,
-                                                   const EventEntry* eventEntry,
-                                                   const char* targetType) REQUIRES(mLock);
-
-    // Manage the dispatch cycle for a single connection.
-    // These methods are deliberately not Interruptible because doing all of the work
-    // with the mutex held makes it easier to ensure that connection invariants are maintained.
-    // If needed, the methods post commands to run later once the critical bits are done.
-    void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
-                                    EventEntry* eventEntry, const InputTarget* inputTarget)
-            REQUIRES(mLock);
-    void enqueueDispatchEntriesLocked(nsecs_t currentTime, const sp<Connection>& connection,
-                                      EventEntry* eventEntry, const InputTarget* inputTarget)
-            REQUIRES(mLock);
-    void enqueueDispatchEntryLocked(const sp<Connection>& connection, EventEntry* eventEntry,
-                                    const InputTarget* inputTarget, int32_t dispatchMode)
-            REQUIRES(mLock);
-    void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection)
-            REQUIRES(mLock);
-    void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
-                                   uint32_t seq, bool handled) REQUIRES(mLock);
-    void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
-                                        bool notify) REQUIRES(mLock);
-    void drainDispatchQueue(Queue<DispatchEntry>* queue);
-    void releaseDispatchEntry(DispatchEntry* dispatchEntry);
-    static int handleReceiveCallback(int fd, int events, void* data);
-    // The action sent should only be of type AMOTION_EVENT_*
-    void dispatchPointerDownOutsideFocus(uint32_t source, int32_t action,
-                                         const sp<IBinder>& newToken) REQUIRES(mLock);
-
-    void synthesizeCancelationEventsForAllConnectionsLocked(const CancelationOptions& options)
-            REQUIRES(mLock);
-    void synthesizeCancelationEventsForMonitorsLocked(const CancelationOptions& options)
-            REQUIRES(mLock);
-    void synthesizeCancelationEventsForMonitorsLocked(
-            const CancelationOptions& options,
-            std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) REQUIRES(mLock);
-    void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel,
-                                                          const CancelationOptions& options)
-            REQUIRES(mLock);
-    void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
-                                                        const CancelationOptions& options)
-            REQUIRES(mLock);
-
-    // Splitting motion events across windows.
-    MotionEntry* splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds);
-
-    // Reset and drop everything the dispatcher is doing.
-    void resetAndDropEverythingLocked(const char* reason) REQUIRES(mLock);
-
-    // Dump state.
-    void dumpDispatchStateLocked(std::string& dump) REQUIRES(mLock);
-    void dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors);
-    void logDispatchStateLocked() REQUIRES(mLock);
-
-    // Registration.
-    void removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) REQUIRES(mLock);
-    void removeMonitorChannelLocked(
-            const sp<InputChannel>& inputChannel,
-            std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) REQUIRES(mLock);
-    status_t unregisterInputChannelLocked(const sp<InputChannel>& inputChannel, bool notify)
-            REQUIRES(mLock);
-
-    // Interesting events that we might like to log or tell the framework about.
-    void onDispatchCycleFinishedLocked(nsecs_t currentTime, const sp<Connection>& connection,
-                                       uint32_t seq, bool handled) REQUIRES(mLock);
-    void onDispatchCycleBrokenLocked(nsecs_t currentTime, const sp<Connection>& connection)
-            REQUIRES(mLock);
-    void onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
-                              const sp<InputWindowHandle>& newFocus) REQUIRES(mLock);
-    void onANRLocked(nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
-                     const sp<InputWindowHandle>& windowHandle, nsecs_t eventTime,
-                     nsecs_t waitStartTime, const char* reason) REQUIRES(mLock);
-
-    // Outbound policy interactions.
-    void doNotifyConfigurationChangedLockedInterruptible(CommandEntry* commandEntry)
-            REQUIRES(mLock);
-    void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
-    void doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
-    void doNotifyANRLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
-    void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry)
-            REQUIRES(mLock);
-    void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
-    bool afterKeyEventLockedInterruptible(const sp<Connection>& connection,
-                                          DispatchEntry* dispatchEntry, KeyEntry* keyEntry,
-                                          bool handled) REQUIRES(mLock);
-    bool afterMotionEventLockedInterruptible(const sp<Connection>& connection,
-                                             DispatchEntry* dispatchEntry, MotionEntry* motionEntry,
-                                             bool handled) REQUIRES(mLock);
-    void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
-    void initializeKeyEvent(KeyEvent* event, const KeyEntry* entry);
-    void doOnPointerDownOutsideFocusLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
-
-    // Statistics gathering.
-    void updateDispatchStatistics(nsecs_t currentTime, const EventEntry* entry,
-                                  int32_t injectionResult, nsecs_t timeSpentWaitingForApplication);
-    void traceInboundQueueLengthLocked() REQUIRES(mLock);
-    void traceOutboundQueueLength(const sp<Connection>& connection);
-    void traceWaitQueueLength(const sp<Connection>& connection);
-
-    sp<InputReporterInterface> mReporter;
-};
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_DISPATCHER_H
diff --git a/services/inputflinger/dispatcher/InputDispatcherFactory.cpp b/services/inputflinger/dispatcher/InputDispatcherFactory.cpp
deleted file mode 100644
index 8d7fa75..0000000
--- a/services/inputflinger/dispatcher/InputDispatcherFactory.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "InputDispatcherFactory.h"
-#include "InputDispatcher.h"
-
-namespace android {
-
-sp<InputDispatcherInterface> createInputDispatcher(
-        const sp<InputDispatcherPolicyInterface>& policy) {
-    return new android::inputdispatcher::InputDispatcher(policy);
-}
-
-} // namespace android
diff --git a/services/inputflinger/dispatcher/InputDispatcherThread.cpp b/services/inputflinger/dispatcher/InputDispatcherThread.cpp
deleted file mode 100644
index 18b1b8c..0000000
--- a/services/inputflinger/dispatcher/InputDispatcherThread.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "InputDispatcherThread.h"
-
-#include "InputDispatcherInterface.h"
-
-namespace android {
-
-InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher)
-      : Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {}
-
-InputDispatcherThread::~InputDispatcherThread() {}
-
-bool InputDispatcherThread::threadLoop() {
-    mDispatcher->dispatchOnce();
-    return true;
-}
-
-} // namespace android
diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp
deleted file mode 100644
index 7d9b03a..0000000
--- a/services/inputflinger/dispatcher/InputState.cpp
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "InputState.h"
-
-namespace android::inputdispatcher {
-
-InputState::InputState() {}
-
-InputState::~InputState() {}
-
-bool InputState::isNeutral() const {
-    return mKeyMementos.empty() && mMotionMementos.empty();
-}
-
-bool InputState::isHovering(int32_t deviceId, uint32_t source, int32_t displayId) const {
-    for (const MotionMemento& memento : mMotionMementos) {
-        if (memento.deviceId == deviceId && memento.source == source &&
-            memento.displayId == displayId && memento.hovering) {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool InputState::trackKey(const KeyEntry* entry, int32_t action, int32_t flags) {
-    switch (action) {
-        case AKEY_EVENT_ACTION_UP: {
-            if (entry->flags & AKEY_EVENT_FLAG_FALLBACK) {
-                for (size_t i = 0; i < mFallbackKeys.size();) {
-                    if (mFallbackKeys.valueAt(i) == entry->keyCode) {
-                        mFallbackKeys.removeItemsAt(i);
-                    } else {
-                        i += 1;
-                    }
-                }
-            }
-            ssize_t index = findKeyMemento(entry);
-            if (index >= 0) {
-                mKeyMementos.erase(mKeyMementos.begin() + index);
-                return true;
-            }
-            /* FIXME: We can't just drop the key up event because that prevents creating
-             * popup windows that are automatically shown when a key is held and then
-             * dismissed when the key is released.  The problem is that the popup will
-             * not have received the original key down, so the key up will be considered
-             * to be inconsistent with its observed state.  We could perhaps handle this
-             * by synthesizing a key down but that will cause other problems.
-             *
-             * So for now, allow inconsistent key up events to be dispatched.
-             *
-    #if DEBUG_OUTBOUND_EVENT_DETAILS
-            ALOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
-                    "keyCode=%d, scanCode=%d",
-                    entry->deviceId, entry->source, entry->keyCode, entry->scanCode);
-    #endif
-            return false;
-            */
-            return true;
-        }
-
-        case AKEY_EVENT_ACTION_DOWN: {
-            ssize_t index = findKeyMemento(entry);
-            if (index >= 0) {
-                mKeyMementos.erase(mKeyMementos.begin() + index);
-            }
-            addKeyMemento(entry, flags);
-            return true;
-        }
-
-        default:
-            return true;
-    }
-}
-
-bool InputState::trackMotion(const MotionEntry* entry, int32_t action, int32_t flags) {
-    int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
-    switch (actionMasked) {
-        case AMOTION_EVENT_ACTION_UP:
-        case AMOTION_EVENT_ACTION_CANCEL: {
-            ssize_t index = findMotionMemento(entry, false /*hovering*/);
-            if (index >= 0) {
-                mMotionMementos.erase(mMotionMementos.begin() + index);
-                return true;
-            }
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-            ALOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, "
-                  "displayId=%" PRId32 ", actionMasked=%d",
-                  entry->deviceId, entry->source, entry->displayId, actionMasked);
-#endif
-            return false;
-        }
-
-        case AMOTION_EVENT_ACTION_DOWN: {
-            ssize_t index = findMotionMemento(entry, false /*hovering*/);
-            if (index >= 0) {
-                mMotionMementos.erase(mMotionMementos.begin() + index);
-            }
-            addMotionMemento(entry, flags, false /*hovering*/);
-            return true;
-        }
-
-        case AMOTION_EVENT_ACTION_POINTER_UP:
-        case AMOTION_EVENT_ACTION_POINTER_DOWN:
-        case AMOTION_EVENT_ACTION_MOVE: {
-            if (entry->source & AINPUT_SOURCE_CLASS_NAVIGATION) {
-                // Trackballs can send MOVE events with a corresponding DOWN or UP. There's no need
-                // to generate cancellation events for these since they're based in relative rather
-                // than absolute units.
-                return true;
-            }
-
-            ssize_t index = findMotionMemento(entry, false /*hovering*/);
-
-            if (entry->source & AINPUT_SOURCE_CLASS_JOYSTICK) {
-                // Joysticks can send MOVE events without a corresponding DOWN or UP. Since all
-                // joystick axes are normalized to [-1, 1] we can trust that 0 means it's neutral.
-                // Any other value and we need to track the motion so we can send cancellation
-                // events for anything generating fallback events (e.g. DPad keys for joystick
-                // movements).
-                if (index >= 0) {
-                    if (entry->pointerCoords[0].isEmpty()) {
-                        mMotionMementos.erase(mMotionMementos.begin() + index);
-                    } else {
-                        MotionMemento& memento = mMotionMementos[index];
-                        memento.setPointers(entry);
-                    }
-                } else if (!entry->pointerCoords[0].isEmpty()) {
-                    addMotionMemento(entry, flags, false /*hovering*/);
-                }
-
-                // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
-                return true;
-            }
-            if (index >= 0) {
-                MotionMemento& memento = mMotionMementos[index];
-                memento.setPointers(entry);
-                return true;
-            }
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-            ALOGD("Dropping inconsistent motion pointer up/down or move event: "
-                  "deviceId=%d, source=%08x, displayId=%" PRId32 ", actionMasked=%d",
-                  entry->deviceId, entry->source, entry->displayId, actionMasked);
-#endif
-            return false;
-        }
-
-        case AMOTION_EVENT_ACTION_HOVER_EXIT: {
-            ssize_t index = findMotionMemento(entry, true /*hovering*/);
-            if (index >= 0) {
-                mMotionMementos.erase(mMotionMementos.begin() + index);
-                return true;
-            }
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-            ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x, "
-                  "displayId=%" PRId32,
-                  entry->deviceId, entry->source, entry->displayId);
-#endif
-            return false;
-        }
-
-        case AMOTION_EVENT_ACTION_HOVER_ENTER:
-        case AMOTION_EVENT_ACTION_HOVER_MOVE: {
-            ssize_t index = findMotionMemento(entry, true /*hovering*/);
-            if (index >= 0) {
-                mMotionMementos.erase(mMotionMementos.begin() + index);
-            }
-            addMotionMemento(entry, flags, true /*hovering*/);
-            return true;
-        }
-
-        default:
-            return true;
-    }
-}
-
-ssize_t InputState::findKeyMemento(const KeyEntry* entry) const {
-    for (size_t i = 0; i < mKeyMementos.size(); i++) {
-        const KeyMemento& memento = mKeyMementos[i];
-        if (memento.deviceId == entry->deviceId && memento.source == entry->source &&
-            memento.displayId == entry->displayId && memento.keyCode == entry->keyCode &&
-            memento.scanCode == entry->scanCode) {
-            return i;
-        }
-    }
-    return -1;
-}
-
-ssize_t InputState::findMotionMemento(const MotionEntry* entry, bool hovering) const {
-    for (size_t i = 0; i < mMotionMementos.size(); i++) {
-        const MotionMemento& memento = mMotionMementos[i];
-        if (memento.deviceId == entry->deviceId && memento.source == entry->source &&
-            memento.displayId == entry->displayId && memento.hovering == hovering) {
-            return i;
-        }
-    }
-    return -1;
-}
-
-void InputState::addKeyMemento(const KeyEntry* entry, int32_t flags) {
-    KeyMemento memento;
-    memento.deviceId = entry->deviceId;
-    memento.source = entry->source;
-    memento.displayId = entry->displayId;
-    memento.keyCode = entry->keyCode;
-    memento.scanCode = entry->scanCode;
-    memento.metaState = entry->metaState;
-    memento.flags = flags;
-    memento.downTime = entry->downTime;
-    memento.policyFlags = entry->policyFlags;
-    mKeyMementos.push_back(memento);
-}
-
-void InputState::addMotionMemento(const MotionEntry* entry, int32_t flags, bool hovering) {
-    MotionMemento memento;
-    memento.deviceId = entry->deviceId;
-    memento.source = entry->source;
-    memento.displayId = entry->displayId;
-    memento.flags = flags;
-    memento.xPrecision = entry->xPrecision;
-    memento.yPrecision = entry->yPrecision;
-    memento.downTime = entry->downTime;
-    memento.setPointers(entry);
-    memento.hovering = hovering;
-    memento.policyFlags = entry->policyFlags;
-    mMotionMementos.push_back(memento);
-}
-
-void InputState::MotionMemento::setPointers(const MotionEntry* entry) {
-    pointerCount = entry->pointerCount;
-    for (uint32_t i = 0; i < entry->pointerCount; i++) {
-        pointerProperties[i].copyFrom(entry->pointerProperties[i]);
-        pointerCoords[i].copyFrom(entry->pointerCoords[i]);
-    }
-}
-
-void InputState::synthesizeCancelationEvents(nsecs_t currentTime,
-                                             std::vector<EventEntry*>& outEvents,
-                                             const CancelationOptions& options) {
-    for (KeyMemento& memento : mKeyMementos) {
-        if (shouldCancelKey(memento, options)) {
-            outEvents.push_back(new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
-                                             memento.deviceId, memento.source, memento.displayId,
-                                             memento.policyFlags, AKEY_EVENT_ACTION_UP,
-                                             memento.flags | AKEY_EVENT_FLAG_CANCELED,
-                                             memento.keyCode, memento.scanCode, memento.metaState,
-                                             0, memento.downTime));
-        }
-    }
-
-    for (const MotionMemento& memento : mMotionMementos) {
-        if (shouldCancelMotion(memento, options)) {
-            const int32_t action = memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT
-                                                    : AMOTION_EVENT_ACTION_CANCEL;
-            outEvents.push_back(
-                    new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime, memento.deviceId,
-                                    memento.source, memento.displayId, memento.policyFlags, action,
-                                    0 /*actionButton*/, memento.flags, AMETA_NONE,
-                                    0 /*buttonState*/, MotionClassification::NONE,
-                                    AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
-                                    memento.yPrecision, memento.downTime, memento.pointerCount,
-                                    memento.pointerProperties, memento.pointerCoords, 0 /*xOffset*/,
-                                    0 /*yOffset*/));
-        }
-    }
-}
-
-void InputState::clear() {
-    mKeyMementos.clear();
-    mMotionMementos.clear();
-    mFallbackKeys.clear();
-}
-
-void InputState::copyPointerStateTo(InputState& other) const {
-    for (size_t i = 0; i < mMotionMementos.size(); i++) {
-        const MotionMemento& memento = mMotionMementos[i];
-        if (memento.source & AINPUT_SOURCE_CLASS_POINTER) {
-            for (size_t j = 0; j < other.mMotionMementos.size();) {
-                const MotionMemento& otherMemento = other.mMotionMementos[j];
-                if (memento.deviceId == otherMemento.deviceId &&
-                    memento.source == otherMemento.source &&
-                    memento.displayId == otherMemento.displayId) {
-                    other.mMotionMementos.erase(other.mMotionMementos.begin() + j);
-                } else {
-                    j += 1;
-                }
-            }
-            other.mMotionMementos.push_back(memento);
-        }
-    }
-}
-
-int32_t InputState::getFallbackKey(int32_t originalKeyCode) {
-    ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
-    return index >= 0 ? mFallbackKeys.valueAt(index) : -1;
-}
-
-void InputState::setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode) {
-    ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
-    if (index >= 0) {
-        mFallbackKeys.replaceValueAt(index, fallbackKeyCode);
-    } else {
-        mFallbackKeys.add(originalKeyCode, fallbackKeyCode);
-    }
-}
-
-void InputState::removeFallbackKey(int32_t originalKeyCode) {
-    mFallbackKeys.removeItem(originalKeyCode);
-}
-
-bool InputState::shouldCancelKey(const KeyMemento& memento, const CancelationOptions& options) {
-    if (options.keyCode && memento.keyCode != options.keyCode.value()) {
-        return false;
-    }
-
-    if (options.deviceId && memento.deviceId != options.deviceId.value()) {
-        return false;
-    }
-
-    if (options.displayId && memento.displayId != options.displayId.value()) {
-        return false;
-    }
-
-    switch (options.mode) {
-        case CancelationOptions::CANCEL_ALL_EVENTS:
-        case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
-            return true;
-        case CancelationOptions::CANCEL_FALLBACK_EVENTS:
-            return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
-        default:
-            return false;
-    }
-}
-
-bool InputState::shouldCancelMotion(const MotionMemento& memento,
-                                    const CancelationOptions& options) {
-    if (options.deviceId && memento.deviceId != options.deviceId.value()) {
-        return false;
-    }
-
-    if (options.displayId && memento.displayId != options.displayId.value()) {
-        return false;
-    }
-
-    switch (options.mode) {
-        case CancelationOptions::CANCEL_ALL_EVENTS:
-            return true;
-        case CancelationOptions::CANCEL_POINTER_EVENTS:
-            return memento.source & AINPUT_SOURCE_CLASS_POINTER;
-        case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
-            return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
-        default:
-            return false;
-    }
-}
-
-} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputState.h b/services/inputflinger/dispatcher/InputState.h
deleted file mode 100644
index 205b647..0000000
--- a/services/inputflinger/dispatcher/InputState.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_INPUTSTATE_H
-#define _UI_INPUT_INPUTDISPATCHER_INPUTSTATE_H
-
-#include "CancelationOptions.h"
-#include "Entry.h"
-
-#include <utils/Timers.h>
-
-namespace android::inputdispatcher {
-
-// Sequence number for synthesized or injected events.
-constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0;
-
-/* Tracks dispatched key and motion event state so that cancellation events can be
- * synthesized when events are dropped. */
-class InputState {
-public:
-    InputState();
-    ~InputState();
-
-    // Returns true if there is no state to be canceled.
-    bool isNeutral() const;
-
-    // Returns true if the specified source is known to have received a hover enter
-    // motion event.
-    bool isHovering(int32_t deviceId, uint32_t source, int32_t displayId) const;
-
-    // Records tracking information for a key event that has just been published.
-    // Returns true if the event should be delivered, false if it is inconsistent
-    // and should be skipped.
-    bool trackKey(const KeyEntry* entry, int32_t action, int32_t flags);
-
-    // Records tracking information for a motion event that has just been published.
-    // Returns true if the event should be delivered, false if it is inconsistent
-    // and should be skipped.
-    bool trackMotion(const MotionEntry* entry, int32_t action, int32_t flags);
-
-    // Synthesizes cancelation events for the current state and resets the tracked state.
-    void synthesizeCancelationEvents(nsecs_t currentTime, std::vector<EventEntry*>& outEvents,
-                                     const CancelationOptions& options);
-
-    // Clears the current state.
-    void clear();
-
-    // Copies pointer-related parts of the input state to another instance.
-    void copyPointerStateTo(InputState& other) const;
-
-    // Gets the fallback key associated with a keycode.
-    // Returns -1 if none.
-    // Returns AKEYCODE_UNKNOWN if we are only dispatching the unhandled key to the policy.
-    int32_t getFallbackKey(int32_t originalKeyCode);
-
-    // Sets the fallback key for a particular keycode.
-    void setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode);
-
-    // Removes the fallback key for a particular keycode.
-    void removeFallbackKey(int32_t originalKeyCode);
-
-    inline const KeyedVector<int32_t, int32_t>& getFallbackKeys() const { return mFallbackKeys; }
-
-private:
-    struct KeyMemento {
-        int32_t deviceId;
-        uint32_t source;
-        int32_t displayId;
-        int32_t keyCode;
-        int32_t scanCode;
-        int32_t metaState;
-        int32_t flags;
-        nsecs_t downTime;
-        uint32_t policyFlags;
-    };
-
-    struct MotionMemento {
-        int32_t deviceId;
-        uint32_t source;
-        int32_t displayId;
-        int32_t flags;
-        float xPrecision;
-        float yPrecision;
-        nsecs_t downTime;
-        uint32_t pointerCount;
-        PointerProperties pointerProperties[MAX_POINTERS];
-        PointerCoords pointerCoords[MAX_POINTERS];
-        bool hovering;
-        uint32_t policyFlags;
-
-        void setPointers(const MotionEntry* entry);
-    };
-
-    std::vector<KeyMemento> mKeyMementos;
-    std::vector<MotionMemento> mMotionMementos;
-    KeyedVector<int32_t, int32_t> mFallbackKeys;
-
-    ssize_t findKeyMemento(const KeyEntry* entry) const;
-    ssize_t findMotionMemento(const MotionEntry* entry, bool hovering) const;
-
-    void addKeyMemento(const KeyEntry* entry, int32_t flags);
-    void addMotionMemento(const MotionEntry* entry, int32_t flags, bool hovering);
-
-    static bool shouldCancelKey(const KeyMemento& memento, const CancelationOptions& options);
-    static bool shouldCancelMotion(const MotionMemento& memento, const CancelationOptions& options);
-};
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_INPUTDISPATCHER_INPUTSTATE_H
diff --git a/services/inputflinger/dispatcher/InputTarget.cpp b/services/inputflinger/dispatcher/InputTarget.cpp
deleted file mode 100644
index 80fa2cb..0000000
--- a/services/inputflinger/dispatcher/InputTarget.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "InputTarget.h"
-
-#include <android-base/stringprintf.h>
-#include <inttypes.h>
-#include <string>
-
-using android::base::StringPrintf;
-
-namespace android::inputdispatcher {
-
-std::string dispatchModeToString(int32_t dispatchMode) {
-    switch (dispatchMode) {
-        case InputTarget::FLAG_DISPATCH_AS_IS:
-            return "DISPATCH_AS_IS";
-        case InputTarget::FLAG_DISPATCH_AS_OUTSIDE:
-            return "DISPATCH_AS_OUTSIDE";
-        case InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER:
-            return "DISPATCH_AS_HOVER_ENTER";
-        case InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT:
-            return "DISPATCH_AS_HOVER_EXIT";
-        case InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT:
-            return "DISPATCH_AS_SLIPPERY_EXIT";
-        case InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER:
-            return "DISPATCH_AS_SLIPPERY_ENTER";
-    }
-    return StringPrintf("%" PRId32, dispatchMode);
-}
-
-} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputTarget.h b/services/inputflinger/dispatcher/InputTarget.h
deleted file mode 100644
index 5acf92b..0000000
--- a/services/inputflinger/dispatcher/InputTarget.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_INPUTTARGET_H
-#define _UI_INPUT_INPUTDISPATCHER_INPUTTARGET_H
-
-#include <input/InputTransport.h>
-#include <utils/BitSet.h>
-#include <utils/RefBase.h>
-
-namespace android::inputdispatcher {
-
-/*
- * An input target specifies how an input event is to be dispatched to a particular window
- * including the window's input channel, control flags, a timeout, and an X / Y offset to
- * be added to input event coordinates to compensate for the absolute position of the
- * window area.
- */
-struct InputTarget {
-    enum {
-        /* This flag indicates that the event is being delivered to a foreground application. */
-        FLAG_FOREGROUND = 1 << 0,
-
-        /* This flag indicates that the MotionEvent falls within the area of the target
-         * obscured by another visible window above it.  The motion event should be
-         * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
-        FLAG_WINDOW_IS_OBSCURED = 1 << 1,
-
-        /* This flag indicates that a motion event is being split across multiple windows. */
-        FLAG_SPLIT = 1 << 2,
-
-        /* This flag indicates that the pointer coordinates dispatched to the application
-         * will be zeroed out to avoid revealing information to an application. This is
-         * used in conjunction with FLAG_DISPATCH_AS_OUTSIDE to prevent apps not sharing
-         * the same UID from watching all touches. */
-        FLAG_ZERO_COORDS = 1 << 3,
-
-        /* This flag indicates that the event should be sent as is.
-         * Should always be set unless the event is to be transmuted. */
-        FLAG_DISPATCH_AS_IS = 1 << 8,
-
-        /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
-         * of the area of this target and so should instead be delivered as an
-         * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
-        FLAG_DISPATCH_AS_OUTSIDE = 1 << 9,
-
-        /* This flag indicates that a hover sequence is starting in the given window.
-         * The event is transmuted into ACTION_HOVER_ENTER. */
-        FLAG_DISPATCH_AS_HOVER_ENTER = 1 << 10,
-
-        /* This flag indicates that a hover event happened outside of a window which handled
-         * previous hover events, signifying the end of the current hover sequence for that
-         * window.
-         * The event is transmuted into ACTION_HOVER_ENTER. */
-        FLAG_DISPATCH_AS_HOVER_EXIT = 1 << 11,
-
-        /* This flag indicates that the event should be canceled.
-         * It is used to transmute ACTION_MOVE into ACTION_CANCEL when a touch slips
-         * outside of a window. */
-        FLAG_DISPATCH_AS_SLIPPERY_EXIT = 1 << 12,
-
-        /* This flag indicates that the event should be dispatched as an initial down.
-         * It is used to transmute ACTION_MOVE into ACTION_DOWN when a touch slips
-         * into a new window. */
-        FLAG_DISPATCH_AS_SLIPPERY_ENTER = 1 << 13,
-
-        /* Mask for all dispatch modes. */
-        FLAG_DISPATCH_MASK = FLAG_DISPATCH_AS_IS | FLAG_DISPATCH_AS_OUTSIDE |
-                FLAG_DISPATCH_AS_HOVER_ENTER | FLAG_DISPATCH_AS_HOVER_EXIT |
-                FLAG_DISPATCH_AS_SLIPPERY_EXIT | FLAG_DISPATCH_AS_SLIPPERY_ENTER,
-
-        /* This flag indicates that the target of a MotionEvent is partly or wholly
-         * obscured by another visible window above it.  The motion event should be
-         * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED. */
-        FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 1 << 14,
-
-    };
-
-    // The input channel to be targeted.
-    sp<InputChannel> inputChannel;
-
-    // Flags for the input target.
-    int32_t flags;
-
-    // The x and y offset to add to a MotionEvent as it is delivered.
-    // (ignored for KeyEvents)
-    float xOffset, yOffset;
-
-    // Scaling factor to apply to MotionEvent as it is delivered.
-    // (ignored for KeyEvents)
-    float globalScaleFactor;
-    float windowXScale = 1.0f;
-    float windowYScale = 1.0f;
-
-    // The subset of pointer ids to include in motion events dispatched to this input target
-    // if FLAG_SPLIT is set.
-    BitSet32 pointerIds;
-};
-
-std::string dispatchModeToString(int32_t dispatchMode);
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_INPUTDISPATCHER_INPUTTARGET_H
diff --git a/services/inputflinger/dispatcher/Monitor.cpp b/services/inputflinger/dispatcher/Monitor.cpp
deleted file mode 100644
index 289b084..0000000
--- a/services/inputflinger/dispatcher/Monitor.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Monitor.h"
-
-namespace android::inputdispatcher {
-
-// --- Monitor ---
-Monitor::Monitor(const sp<InputChannel>& inputChannel) : inputChannel(inputChannel) {}
-
-// --- TouchedMonitor ---
-TouchedMonitor::TouchedMonitor(const Monitor& monitor, float xOffset, float yOffset)
-      : monitor(monitor), xOffset(xOffset), yOffset(yOffset) {}
-
-} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/Monitor.h b/services/inputflinger/dispatcher/Monitor.h
deleted file mode 100644
index b67c9eb..0000000
--- a/services/inputflinger/dispatcher/Monitor.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_MONITOR_H
-#define _UI_INPUT_INPUTDISPATCHER_MONITOR_H
-
-#include <input/InputTransport.h>
-
-namespace android::inputdispatcher {
-
-struct Monitor {
-    sp<InputChannel> inputChannel; // never null
-
-    explicit Monitor(const sp<InputChannel>& inputChannel);
-};
-
-// For tracking the offsets we need to apply when adding gesture monitor targets.
-struct TouchedMonitor {
-    Monitor monitor;
-    float xOffset = 0.f;
-    float yOffset = 0.f;
-
-    explicit TouchedMonitor(const Monitor& monitor, float xOffset, float yOffset);
-};
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_INPUTDISPATCHER_MONITOR_H
diff --git a/services/inputflinger/dispatcher/Queue.h b/services/inputflinger/dispatcher/Queue.h
deleted file mode 100644
index 0e75821..0000000
--- a/services/inputflinger/dispatcher/Queue.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_QUEUE_H
-#define _UI_INPUT_INPUTDISPATCHER_QUEUE_H
-
-namespace android::inputdispatcher {
-
-// Generic queue implementation.
-template <typename T>
-struct Queue {
-    T* head;
-    T* tail;
-    uint32_t entryCount;
-
-    inline Queue() : head(nullptr), tail(nullptr), entryCount(0) {}
-
-    inline bool isEmpty() const { return !head; }
-
-    inline void enqueueAtTail(T* entry) {
-        entryCount++;
-        entry->prev = tail;
-        if (tail) {
-            tail->next = entry;
-        } else {
-            head = entry;
-        }
-        entry->next = nullptr;
-        tail = entry;
-    }
-
-    inline void enqueueAtHead(T* entry) {
-        entryCount++;
-        entry->next = head;
-        if (head) {
-            head->prev = entry;
-        } else {
-            tail = entry;
-        }
-        entry->prev = nullptr;
-        head = entry;
-    }
-
-    inline void dequeue(T* entry) {
-        entryCount--;
-        if (entry->prev) {
-            entry->prev->next = entry->next;
-        } else {
-            head = entry->next;
-        }
-        if (entry->next) {
-            entry->next->prev = entry->prev;
-        } else {
-            tail = entry->prev;
-        }
-    }
-
-    inline T* dequeueAtHead() {
-        entryCount--;
-        T* entry = head;
-        head = entry->next;
-        if (head) {
-            head->prev = nullptr;
-        } else {
-            tail = nullptr;
-        }
-        return entry;
-    }
-
-    uint32_t count() const { return entryCount; }
-};
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_INPUTDISPATCHER_QUEUE_H
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
deleted file mode 100644
index 18848a0..0000000
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <input/InputWindow.h>
-
-#include "InputTarget.h"
-
-#include "TouchState.h"
-
-using android::InputWindowHandle;
-
-namespace android::inputdispatcher {
-
-TouchState::TouchState()
-      : down(false), split(false), deviceId(-1), source(0), displayId(ADISPLAY_ID_NONE) {}
-
-TouchState::~TouchState() {}
-
-void TouchState::reset() {
-    down = false;
-    split = false;
-    deviceId = -1;
-    source = 0;
-    displayId = ADISPLAY_ID_NONE;
-    windows.clear();
-    portalWindows.clear();
-    gestureMonitors.clear();
-}
-
-void TouchState::copyFrom(const TouchState& other) {
-    down = other.down;
-    split = other.split;
-    deviceId = other.deviceId;
-    source = other.source;
-    displayId = other.displayId;
-    windows = other.windows;
-    portalWindows = other.portalWindows;
-    gestureMonitors = other.gestureMonitors;
-}
-
-void TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle, int32_t targetFlags,
-                                   BitSet32 pointerIds) {
-    if (targetFlags & InputTarget::FLAG_SPLIT) {
-        split = true;
-    }
-
-    for (size_t i = 0; i < windows.size(); i++) {
-        TouchedWindow& touchedWindow = windows[i];
-        if (touchedWindow.windowHandle == windowHandle) {
-            touchedWindow.targetFlags |= targetFlags;
-            if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
-                touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
-            }
-            touchedWindow.pointerIds.value |= pointerIds.value;
-            return;
-        }
-    }
-
-    TouchedWindow touchedWindow;
-    touchedWindow.windowHandle = windowHandle;
-    touchedWindow.targetFlags = targetFlags;
-    touchedWindow.pointerIds = pointerIds;
-    windows.push_back(touchedWindow);
-}
-
-void TouchState::addPortalWindow(const sp<InputWindowHandle>& windowHandle) {
-    size_t numWindows = portalWindows.size();
-    for (size_t i = 0; i < numWindows; i++) {
-        if (portalWindows[i] == windowHandle) {
-            return;
-        }
-    }
-    portalWindows.push_back(windowHandle);
-}
-
-void TouchState::addGestureMonitors(const std::vector<TouchedMonitor>& newMonitors) {
-    const size_t newSize = gestureMonitors.size() + newMonitors.size();
-    gestureMonitors.reserve(newSize);
-    gestureMonitors.insert(std::end(gestureMonitors), std::begin(newMonitors),
-                           std::end(newMonitors));
-}
-
-void TouchState::removeWindow(const sp<InputWindowHandle>& windowHandle) {
-    for (size_t i = 0; i < windows.size(); i++) {
-        if (windows[i].windowHandle == windowHandle) {
-            windows.erase(windows.begin() + i);
-            return;
-        }
-    }
-}
-
-void TouchState::removeWindowByToken(const sp<IBinder>& token) {
-    for (size_t i = 0; i < windows.size(); i++) {
-        if (windows[i].windowHandle->getToken() == token) {
-            windows.erase(windows.begin() + i);
-            return;
-        }
-    }
-}
-
-void TouchState::filterNonAsIsTouchWindows() {
-    for (size_t i = 0; i < windows.size();) {
-        TouchedWindow& window = windows[i];
-        if (window.targetFlags &
-            (InputTarget::FLAG_DISPATCH_AS_IS | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) {
-            window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK;
-            window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS;
-            i += 1;
-        } else {
-            windows.erase(windows.begin() + i);
-        }
-    }
-}
-
-void TouchState::filterNonMonitors() {
-    windows.clear();
-    portalWindows.clear();
-}
-
-sp<InputWindowHandle> TouchState::getFirstForegroundWindowHandle() const {
-    for (size_t i = 0; i < windows.size(); i++) {
-        const TouchedWindow& window = windows[i];
-        if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
-            return window.windowHandle;
-        }
-    }
-    return nullptr;
-}
-
-bool TouchState::isSlippery() const {
-    // Must have exactly one foreground window.
-    bool haveSlipperyForegroundWindow = false;
-    for (const TouchedWindow& window : windows) {
-        if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
-            if (haveSlipperyForegroundWindow ||
-                !(window.windowHandle->getInfo()->layoutParamsFlags &
-                  InputWindowInfo::FLAG_SLIPPERY)) {
-                return false;
-            }
-            haveSlipperyForegroundWindow = true;
-        }
-    }
-    return haveSlipperyForegroundWindow;
-}
-
-} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h
deleted file mode 100644
index 3e0e0eb..0000000
--- a/services/inputflinger/dispatcher/TouchState.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_TOUCHSTATE_H
-#define _UI_INPUT_INPUTDISPATCHER_TOUCHSTATE_H
-
-#include "Monitor.h"
-#include "TouchedWindow.h"
-
-namespace android {
-
-class InputWindowHandle;
-
-namespace inputdispatcher {
-
-struct TouchState {
-    bool down;
-    bool split;
-    int32_t deviceId;  // id of the device that is currently down, others are rejected
-    uint32_t source;   // source of the device that is current down, others are rejected
-    int32_t displayId; // id to the display that currently has a touch, others are rejected
-    std::vector<TouchedWindow> windows;
-
-    // This collects the portal windows that the touch has gone through. Each portal window
-    // targets a display (embedded display for most cases). With this info, we can add the
-    // monitoring channels of the displays touched.
-    std::vector<sp<android::InputWindowHandle>> portalWindows;
-
-    std::vector<TouchedMonitor> gestureMonitors;
-
-    TouchState();
-    ~TouchState();
-    void reset();
-    void copyFrom(const TouchState& other);
-    void addOrUpdateWindow(const sp<android::InputWindowHandle>& windowHandle, int32_t targetFlags,
-                           BitSet32 pointerIds);
-    void addPortalWindow(const sp<android::InputWindowHandle>& windowHandle);
-    void addGestureMonitors(const std::vector<TouchedMonitor>& monitors);
-    void removeWindow(const sp<android::InputWindowHandle>& windowHandle);
-    void removeWindowByToken(const sp<IBinder>& token);
-    void filterNonAsIsTouchWindows();
-    void filterNonMonitors();
-    sp<InputWindowHandle> getFirstForegroundWindowHandle() const;
-    bool isSlippery() const;
-};
-
-} // namespace inputdispatcher
-} // namespace android
-
-#endif // _UI_INPUT_INPUTDISPATCHER_TOUCHSTATE_H
diff --git a/services/inputflinger/dispatcher/TouchedWindow.h b/services/inputflinger/dispatcher/TouchedWindow.h
deleted file mode 100644
index 8713aa3..0000000
--- a/services/inputflinger/dispatcher/TouchedWindow.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_TOUCHEDWINDOW_H
-#define _UI_INPUT_INPUTDISPATCHER_TOUCHEDWINDOW_H
-
-namespace android {
-
-class InputWindowHandle;
-
-namespace inputdispatcher {
-
-// Focus tracking for touch.
-struct TouchedWindow {
-    sp<android::InputWindowHandle> windowHandle;
-    int32_t targetFlags;
-    BitSet32 pointerIds; // zero unless target flag FLAG_SPLIT is set
-};
-
-} // namespace inputdispatcher
-} // namespace android
-
-#endif // _UI_INPUT_INPUTDISPATCHER_TOUCHEDWINDOW_H
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherConfiguration.h b/services/inputflinger/dispatcher/include/InputDispatcherConfiguration.h
deleted file mode 100644
index 00abf47..0000000
--- a/services/inputflinger/dispatcher/include/InputDispatcherConfiguration.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERCONFIGURATION_H
-#define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERCONFIGURATION_H
-
-#include <utils/Timers.h>
-
-namespace android {
-
-/*
- * Input dispatcher configuration.
- *
- * Specifies various options that modify the behavior of the input dispatcher.
- * The values provided here are merely defaults. The actual values will come from ViewConfiguration
- * and are passed into the dispatcher during initialization.
- */
-struct InputDispatcherConfiguration {
-    // The key repeat initial timeout.
-    nsecs_t keyRepeatTimeout;
-
-    // The key repeat inter-key delay.
-    nsecs_t keyRepeatDelay;
-
-    InputDispatcherConfiguration()
-          : keyRepeatTimeout(500 * 1000000LL), keyRepeatDelay(50 * 1000000LL) {}
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERCONFIGURATION_H
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherFactory.h b/services/inputflinger/dispatcher/include/InputDispatcherFactory.h
deleted file mode 100644
index a359557..0000000
--- a/services/inputflinger/dispatcher/include/InputDispatcherFactory.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERFACTORY_H
-#define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERFACTORY_H
-
-#include <utils/RefBase.h>
-
-#include "InputDispatcherInterface.h"
-#include "InputDispatcherPolicyInterface.h"
-
-namespace android {
-
-// This factory method is used to encapsulate implementation details in internal header files.
-sp<InputDispatcherInterface> createInputDispatcher(
-        const sp<InputDispatcherPolicyInterface>& policy);
-
-} // namespace android
-
-#endif // _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERFACTORY_H
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
deleted file mode 100644
index 9329ca6..0000000
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERINTERFACE_H
-#define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERINTERFACE_H
-
-#include <InputListener.h>
-#include <input/ISetInputWindowsListener.h>
-
-namespace android {
-
-class InputApplicationHandle;
-class InputChannel;
-class InputWindowHandle;
-
-/*
- * Constants used to report the outcome of input event injection.
- */
-enum {
-    /* (INTERNAL USE ONLY) Specifies that injection is pending and its outcome is unknown. */
-    INPUT_EVENT_INJECTION_PENDING = -1,
-
-    /* Injection succeeded. */
-    INPUT_EVENT_INJECTION_SUCCEEDED = 0,
-
-    /* Injection failed because the injector did not have permission to inject
-     * into the application with input focus. */
-    INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1,
-
-    /* Injection failed because there were no available input targets. */
-    INPUT_EVENT_INJECTION_FAILED = 2,
-
-    /* Injection failed due to a timeout. */
-    INPUT_EVENT_INJECTION_TIMED_OUT = 3
-};
-
-/* Notifies the system about input events generated by the input reader.
- * The dispatcher is expected to be mostly asynchronous. */
-class InputDispatcherInterface : public virtual RefBase, public InputListenerInterface {
-protected:
-    InputDispatcherInterface() {}
-    virtual ~InputDispatcherInterface() {}
-
-public:
-    /* Dumps the state of the input dispatcher.
-     *
-     * This method may be called on any thread (usually by the input manager). */
-    virtual void dump(std::string& dump) = 0;
-
-    /* Called by the heatbeat to ensures that the dispatcher has not deadlocked. */
-    virtual void monitor() = 0;
-
-    /* Runs a single iteration of the dispatch loop.
-     * Nominally processes one queued event, a timeout, or a response from an input consumer.
-     *
-     * This method should only be called on the input dispatcher thread.
-     */
-    virtual void dispatchOnce() = 0;
-
-    /* Injects an input event and optionally waits for sync.
-     * The synchronization mode determines whether the method blocks while waiting for
-     * input injection to proceed.
-     * Returns one of the INPUT_EVENT_INJECTION_XXX constants.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual int32_t injectInputEvent(const InputEvent* event, int32_t injectorPid,
-                                     int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
-                                     uint32_t policyFlags) = 0;
-
-    /* Sets the list of input windows.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual void setInputWindows(
-            const std::vector<sp<InputWindowHandle> >& inputWindowHandles, int32_t displayId,
-            const sp<ISetInputWindowsListener>& setInputWindowsListener = nullptr) = 0;
-
-    /* Sets the focused application on the given display.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual void setFocusedApplication(
-            int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) = 0;
-
-    /* Sets the focused display.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual void setFocusedDisplay(int32_t displayId) = 0;
-
-    /* Sets the input dispatching mode.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual void setInputDispatchMode(bool enabled, bool frozen) = 0;
-
-    /* Sets whether input event filtering is enabled.
-     * When enabled, incoming input events are sent to the policy's filterInputEvent
-     * method instead of being dispatched.  The filter is expected to use
-     * injectInputEvent to inject the events it would like to have dispatched.
-     * It should include POLICY_FLAG_FILTERED in the policy flags during injection.
-     */
-    virtual void setInputFilterEnabled(bool enabled) = 0;
-
-    /* Transfers touch focus from one window to another window.
-     *
-     * Returns true on success.  False if the window did not actually have touch focus.
-     */
-    virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0;
-
-    /* Registers input channels that may be used as targets for input events.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
-                                          int32_t displayId) = 0;
-
-    /* Registers input channels to be used to monitor input events.
-     *
-     * Each monitor must target a specific display and will only receive input events sent to that
-     * display. If the monitor is a gesture monitor, it will only receive pointer events on the
-     * targeted display.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual status_t registerInputMonitor(const sp<InputChannel>& inputChannel, int32_t displayId,
-                                          bool gestureMonitor) = 0;
-
-    /* Unregister input channels that will no longer receive input events.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
-
-    /* Allows an input monitor steal the current pointer stream away from normal input windows.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual status_t pilferPointers(const sp<IBinder>& token) = 0;
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERINTERFACE_H
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
deleted file mode 100644
index 4214488..0000000
--- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERPOLICYINTERFACE_H
-#define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERPOLICYINTERFACE_H
-
-#include "InputDispatcherConfiguration.h"
-
-#include <binder/IBinder.h>
-#include <input/Input.h>
-#include <utils/RefBase.h>
-
-namespace android {
-
-class InputApplicationHandle;
-
-/*
- * Input dispatcher policy interface.
- *
- * The input reader policy is used by the input reader to interact with the Window Manager
- * and other system components.
- *
- * The actual implementation is partially supported by callbacks into the DVM
- * via JNI.  This interface is also mocked in the unit tests.
- */
-class InputDispatcherPolicyInterface : public virtual RefBase {
-protected:
-    InputDispatcherPolicyInterface() {}
-    virtual ~InputDispatcherPolicyInterface() {}
-
-public:
-    /* Notifies the system that a configuration change has occurred. */
-    virtual void notifyConfigurationChanged(nsecs_t when) = 0;
-
-    /* Notifies the system that an application is not responding.
-     * Returns a new timeout to continue waiting, or 0 to abort dispatch. */
-    virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
-                              const sp<IBinder>& token, const std::string& reason) = 0;
-
-    /* Notifies the system that an input channel is unrecoverably broken. */
-    virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0;
-    virtual void notifyFocusChanged(const sp<IBinder>& oldToken, const sp<IBinder>& newToken) = 0;
-
-    /* Gets the input dispatcher configuration. */
-    virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0;
-
-    /* Filters an input event.
-     * Return true to dispatch the event unmodified, false to consume the event.
-     * A filter can also transform and inject events later by passing POLICY_FLAG_FILTERED
-     * to injectInputEvent.
-     */
-    virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) = 0;
-
-    /* Intercepts a key event immediately before queueing it.
-     * The policy can use this method as an opportunity to perform power management functions
-     * and early event preprocessing such as updating policy flags.
-     *
-     * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
-     * should be dispatched to applications.
-     */
-    virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) = 0;
-
-    /* Intercepts a touch, trackball or other motion event before queueing it.
-     * The policy can use this method as an opportunity to perform power management functions
-     * and early event preprocessing such as updating policy flags.
-     *
-     * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
-     * should be dispatched to applications.
-     */
-    virtual void interceptMotionBeforeQueueing(const int32_t displayId, nsecs_t when,
-                                               uint32_t& policyFlags) = 0;
-
-    /* Allows the policy a chance to intercept a key before dispatching. */
-    virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>& token,
-                                                  const KeyEvent* keyEvent,
-                                                  uint32_t policyFlags) = 0;
-
-    /* Allows the policy a chance to perform default processing for an unhandled key.
-     * Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
-    virtual bool dispatchUnhandledKey(const sp<IBinder>& token, const KeyEvent* keyEvent,
-                                      uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
-
-    /* Notifies the policy about switch events.
-     */
-    virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
-                              uint32_t policyFlags) = 0;
-
-    /* Poke user activity for an event dispatched to a window. */
-    virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) = 0;
-
-    /* Checks whether a given application pid/uid has permission to inject input events
-     * into other applications.
-     *
-     * This method is special in that its implementation promises to be non-reentrant and
-     * is safe to call while holding other locks.  (Most other methods make no such guarantees!)
-     */
-    virtual bool checkInjectEventsPermissionNonReentrant(int32_t injectorPid,
-                                                         int32_t injectorUid) = 0;
-
-    /* Notifies the policy that a pointer down event has occurred outside the current focused
-     * window.
-     *
-     * The touchedToken passed as an argument is the window that received the input event.
-     */
-    virtual void onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) = 0;
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERPOLICYINTERFACE_H
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherThread.h b/services/inputflinger/dispatcher/include/InputDispatcherThread.h
deleted file mode 100644
index 2604959..0000000
--- a/services/inputflinger/dispatcher/include/InputDispatcherThread.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERTHREAD_H
-#define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERTHREAD_H
-
-#include <utils/RefBase.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class InputDispatcherInterface;
-
-/* Enqueues and dispatches input events, endlessly. */
-class InputDispatcherThread : public Thread {
-public:
-    explicit InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher);
-    ~InputDispatcherThread();
-
-private:
-    virtual bool threadLoop();
-
-    sp<InputDispatcherInterface> mDispatcher;
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERTHREAD_H
diff --git a/services/inputflinger/host/InputDriver.cpp b/services/inputflinger/host/InputDriver.cpp
index 683c05d..2f046c3 100644
--- a/services/inputflinger/host/InputDriver.cpp
+++ b/services/inputflinger/host/InputDriver.cpp
@@ -127,10 +127,10 @@
             input_bus_t bus, const char* uniqueId) {
     auto identifier = new ::input_device_identifier {
         .name = name,
-        .uniqueId = uniqueId,
-        .bus = bus,
-        .vendorId = vendorId,
         .productId = productId,
+        .vendorId = vendorId,
+        .bus = bus,
+        .uniqueId = uniqueId,
     };
     // TODO: store this identifier somewhere
     return identifier;
diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h
index d8b352c..973b4f9 100644
--- a/services/inputflinger/host/InputFlinger.h
+++ b/services/inputflinger/host/InputFlinger.h
@@ -42,7 +42,6 @@
     virtual status_t dump(int fd, const Vector<String16>& args);
     void setInputWindows(const std::vector<InputWindowInfo>&,
             const sp<ISetInputWindowsListener>&) {}
-    void transferTouchFocus(const sp<IBinder>&, const sp<IBinder>&) {}
     void registerInputChannel(const sp<InputChannel>&) {}
     void unregisterInputChannel(const sp<InputChannel>&) {}
 
diff --git a/services/inputflinger/reporter/InputReporterInterface.h b/services/inputflinger/include/InputReporterInterface.h
similarity index 97%
rename from services/inputflinger/reporter/InputReporterInterface.h
rename to services/inputflinger/include/InputReporterInterface.h
index e5d3606..906d7f2 100644
--- a/services/inputflinger/reporter/InputReporterInterface.h
+++ b/services/inputflinger/include/InputReporterInterface.h
@@ -27,7 +27,7 @@
  */
 class InputReporterInterface : public virtual RefBase {
 protected:
-    virtual ~InputReporterInterface() {}
+    virtual ~InputReporterInterface() { }
 
 public:
     // Report a key that was not handled by the system or apps.
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
deleted file mode 100644
index 4e97397..0000000
--- a/services/inputflinger/reader/Android.bp
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (C) 2019 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.
-
-cc_library_headers {
-    name: "libinputreader_headers",
-    export_include_dirs: [
-        "include",
-        "mapper",
-        "mapper/accumulator",
-    ],
-}
-
-cc_library_shared {
-    name: "libinputreader",
-    defaults: ["inputflinger_defaults"],
-
-    srcs: [
-        "EventHub.cpp",
-        "InputDevice.cpp",
-        "mapper/accumulator/CursorButtonAccumulator.cpp",
-        "mapper/accumulator/CursorScrollAccumulator.cpp",
-        "mapper/accumulator/SingleTouchMotionAccumulator.cpp",
-        "mapper/accumulator/TouchButtonAccumulator.cpp",
-        "mapper/CursorInputMapper.cpp",
-        "mapper/ExternalStylusInputMapper.cpp",
-        "mapper/InputMapper.cpp",
-        "mapper/JoystickInputMapper.cpp",
-        "mapper/KeyboardInputMapper.cpp",
-        "mapper/MultiTouchInputMapper.cpp",
-        "mapper/RotaryEncoderInputMapper.cpp",
-        "mapper/SingleTouchInputMapper.cpp",
-        "mapper/SwitchInputMapper.cpp",
-        "mapper/TouchInputMapper.cpp",
-        "mapper/VibratorInputMapper.cpp",
-        "InputReader.cpp",
-        "InputReaderFactory.cpp",
-        "TouchVideoDevice.cpp",
-    ],
-
-    shared_libs: [
-        "libbase",
-        "libinputflinger_base",
-        "libcrypto",
-        "libcutils",
-        "libinput",
-        "liblog",
-        "libui",
-        "libutils",
-        "libhardware_legacy",
-        "libstatslog",
-    ],
-
-    header_libs: [
-        "libinputflinger_headers",
-        "libinputreader_headers",
-    ],
-
-    export_header_lib_headers: [
-        "libinputflinger_headers",
-    ],
-}
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
deleted file mode 100644
index d0613b0..0000000
--- a/services/inputflinger/reader/InputDevice.cpp
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Macros.h"
-
-#include "InputDevice.h"
-
-#include "InputMapper.h"
-
-namespace android {
-
-InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
-                         int32_t controllerNumber, const InputDeviceIdentifier& identifier,
-                         uint32_t classes)
-      : mContext(context),
-        mId(id),
-        mGeneration(generation),
-        mControllerNumber(controllerNumber),
-        mIdentifier(identifier),
-        mClasses(classes),
-        mSources(0),
-        mIsExternal(false),
-        mHasMic(false),
-        mDropUntilNextSync(false) {}
-
-InputDevice::~InputDevice() {
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        delete mMappers[i];
-    }
-    mMappers.clear();
-}
-
-bool InputDevice::isEnabled() {
-    return getEventHub()->isDeviceEnabled(mId);
-}
-
-void InputDevice::setEnabled(bool enabled, nsecs_t when) {
-    if (isEnabled() == enabled) {
-        return;
-    }
-
-    if (enabled) {
-        getEventHub()->enableDevice(mId);
-        reset(when);
-    } else {
-        reset(when);
-        getEventHub()->disableDevice(mId);
-    }
-    // Must change generation to flag this device as changed
-    bumpGeneration();
-}
-
-void InputDevice::dump(std::string& dump) {
-    InputDeviceInfo deviceInfo;
-    getDeviceInfo(&deviceInfo);
-
-    dump += StringPrintf(INDENT "Device %d: %s\n", deviceInfo.getId(),
-                         deviceInfo.getDisplayName().c_str());
-    dump += StringPrintf(INDENT2 "Generation: %d\n", mGeneration);
-    dump += StringPrintf(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
-    dump += StringPrintf(INDENT2 "AssociatedDisplayPort: ");
-    if (mAssociatedDisplayPort) {
-        dump += StringPrintf("%" PRIu8 "\n", *mAssociatedDisplayPort);
-    } else {
-        dump += "<none>\n";
-    }
-    dump += StringPrintf(INDENT2 "HasMic:     %s\n", toString(mHasMic));
-    dump += StringPrintf(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
-    dump += StringPrintf(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
-
-    const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
-    if (!ranges.empty()) {
-        dump += INDENT2 "Motion Ranges:\n";
-        for (size_t i = 0; i < ranges.size(); i++) {
-            const InputDeviceInfo::MotionRange& range = ranges[i];
-            const char* label = getAxisLabel(range.axis);
-            char name[32];
-            if (label) {
-                strncpy(name, label, sizeof(name));
-                name[sizeof(name) - 1] = '\0';
-            } else {
-                snprintf(name, sizeof(name), "%d", range.axis);
-            }
-            dump += StringPrintf(INDENT3
-                                 "%s: source=0x%08x, "
-                                 "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, resolution=%0.3f\n",
-                                 name, range.source, range.min, range.max, range.flat, range.fuzz,
-                                 range.resolution);
-        }
-    }
-
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        mapper->dump(dump);
-    }
-}
-
-void InputDevice::addMapper(InputMapper* mapper) {
-    mMappers.push_back(mapper);
-}
-
-void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config,
-                            uint32_t changes) {
-    mSources = 0;
-
-    if (!isIgnored()) {
-        if (!changes) { // first time only
-            mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
-        }
-
-        if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
-            if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
-                sp<KeyCharacterMap> keyboardLayout =
-                        mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier);
-                if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {
-                    bumpGeneration();
-                }
-            }
-        }
-
-        if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
-            if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
-                std::string alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
-                if (mAlias != alias) {
-                    mAlias = alias;
-                    bumpGeneration();
-                }
-            }
-        }
-
-        if (!changes || (changes & InputReaderConfiguration::CHANGE_ENABLED_STATE)) {
-            ssize_t index = config->disabledDevices.indexOf(mId);
-            bool enabled = index < 0;
-            setEnabled(enabled, when);
-        }
-
-        if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
-            // In most situations, no port will be specified.
-            mAssociatedDisplayPort = std::nullopt;
-            // Find the display port that corresponds to the current input port.
-            const std::string& inputPort = mIdentifier.location;
-            if (!inputPort.empty()) {
-                const std::unordered_map<std::string, uint8_t>& ports = config->portAssociations;
-                const auto& displayPort = ports.find(inputPort);
-                if (displayPort != ports.end()) {
-                    mAssociatedDisplayPort = std::make_optional(displayPort->second);
-                }
-            }
-        }
-
-        for (InputMapper* mapper : mMappers) {
-            mapper->configure(when, config, changes);
-            mSources |= mapper->getSources();
-        }
-    }
-}
-
-void InputDevice::reset(nsecs_t when) {
-    for (InputMapper* mapper : mMappers) {
-        mapper->reset(when);
-    }
-
-    mContext->updateGlobalMetaState();
-
-    notifyReset(when);
-}
-
-void InputDevice::process(const RawEvent* rawEvents, size_t count) {
-    // Process all of the events in order for each mapper.
-    // We cannot simply ask each mapper to process them in bulk because mappers may
-    // have side-effects that must be interleaved.  For example, joystick movement events and
-    // gamepad button presses are handled by different mappers but they should be dispatched
-    // in the order received.
-    for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
-#if DEBUG_RAW_EVENTS
-        ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
-              rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value, rawEvent->when);
-#endif
-
-        if (mDropUntilNextSync) {
-            if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
-                mDropUntilNextSync = false;
-#if DEBUG_RAW_EVENTS
-                ALOGD("Recovered from input event buffer overrun.");
-#endif
-            } else {
-#if DEBUG_RAW_EVENTS
-                ALOGD("Dropped input event while waiting for next input sync.");
-#endif
-            }
-        } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
-            ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
-            mDropUntilNextSync = true;
-            reset(rawEvent->when);
-        } else {
-            for (InputMapper* mapper : mMappers) {
-                mapper->process(rawEvent);
-            }
-        }
-        --count;
-    }
-}
-
-void InputDevice::timeoutExpired(nsecs_t when) {
-    for (InputMapper* mapper : mMappers) {
-        mapper->timeoutExpired(when);
-    }
-}
-
-void InputDevice::updateExternalStylusState(const StylusState& state) {
-    for (InputMapper* mapper : mMappers) {
-        mapper->updateExternalStylusState(state);
-    }
-}
-
-void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
-    outDeviceInfo->initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias, mIsExternal,
-                              mHasMic);
-    for (InputMapper* mapper : mMappers) {
-        mapper->populateDeviceInfo(outDeviceInfo);
-    }
-}
-
-int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
-    return getState(sourceMask, keyCode, &InputMapper::getKeyCodeState);
-}
-
-int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-    return getState(sourceMask, scanCode, &InputMapper::getScanCodeState);
-}
-
-int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
-    return getState(sourceMask, switchCode, &InputMapper::getSwitchState);
-}
-
-int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
-    int32_t result = AKEY_STATE_UNKNOWN;
-    for (InputMapper* mapper : mMappers) {
-        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
-            // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
-            // value.  Otherwise, return AKEY_STATE_UP as long as one mapper reports it.
-            int32_t currentResult = (mapper->*getStateFunc)(sourceMask, code);
-            if (currentResult >= AKEY_STATE_DOWN) {
-                return currentResult;
-            } else if (currentResult == AKEY_STATE_UP) {
-                result = currentResult;
-            }
-        }
-    }
-    return result;
-}
-
-bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-                                        const int32_t* keyCodes, uint8_t* outFlags) {
-    bool result = false;
-    for (InputMapper* mapper : mMappers) {
-        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
-            result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
-        }
-    }
-    return result;
-}
-
-void InputDevice::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
-                          int32_t token) {
-    for (InputMapper* mapper : mMappers) {
-        mapper->vibrate(pattern, patternSize, repeat, token);
-    }
-}
-
-void InputDevice::cancelVibrate(int32_t token) {
-    for (InputMapper* mapper : mMappers) {
-        mapper->cancelVibrate(token);
-    }
-}
-
-void InputDevice::cancelTouch(nsecs_t when) {
-    for (InputMapper* mapper : mMappers) {
-        mapper->cancelTouch(when);
-    }
-}
-
-int32_t InputDevice::getMetaState() {
-    int32_t result = 0;
-    for (InputMapper* mapper : mMappers) {
-        result |= mapper->getMetaState();
-    }
-    return result;
-}
-
-void InputDevice::updateMetaState(int32_t keyCode) {
-    for (InputMapper* mapper : mMappers) {
-        mapper->updateMetaState(keyCode);
-    }
-}
-
-void InputDevice::fadePointer() {
-    for (InputMapper* mapper : mMappers) {
-        mapper->fadePointer();
-    }
-}
-
-void InputDevice::bumpGeneration() {
-    mGeneration = mContext->bumpGeneration();
-}
-
-void InputDevice::notifyReset(nsecs_t when) {
-    NotifyDeviceResetArgs args(mContext->getNextSequenceNum(), when, mId);
-    mContext->getListener()->notifyDeviceReset(&args);
-}
-
-std::optional<int32_t> InputDevice::getAssociatedDisplay() {
-    for (InputMapper* mapper : mMappers) {
-        std::optional<int32_t> associatedDisplayId = mapper->getAssociatedDisplay();
-        if (associatedDisplayId) {
-            return associatedDisplayId;
-        }
-    }
-
-    return std::nullopt;
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
deleted file mode 100644
index 27cbf19..0000000
--- a/services/inputflinger/reader/InputReader.cpp
+++ /dev/null
@@ -1,767 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#include "Macros.h"
-
-#include "InputReader.h"
-
-#include "CursorInputMapper.h"
-#include "ExternalStylusInputMapper.h"
-#include "InputReaderContext.h"
-#include "JoystickInputMapper.h"
-#include "KeyboardInputMapper.h"
-#include "MultiTouchInputMapper.h"
-#include "RotaryEncoderInputMapper.h"
-#include "SingleTouchInputMapper.h"
-#include "SwitchInputMapper.h"
-#include "VibratorInputMapper.h"
-
-#include <errno.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <math.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <log/log.h>
-
-#include <android-base/stringprintf.h>
-#include <input/Keyboard.h>
-#include <input/VirtualKeyMap.h>
-
-
-using android::base::StringPrintf;
-
-namespace android {
-
-InputReader::InputReader(const sp<EventHubInterface>& eventHub,
-                         const sp<InputReaderPolicyInterface>& policy,
-                         const sp<InputListenerInterface>& listener)
-      : mContext(this),
-        mEventHub(eventHub),
-        mPolicy(policy),
-        mNextSequenceNum(1),
-        mGlobalMetaState(0),
-        mGeneration(1),
-        mDisableVirtualKeysTimeout(LLONG_MIN),
-        mNextTimeout(LLONG_MAX),
-        mConfigurationChangesToRefresh(0) {
-    mQueuedListener = new QueuedInputListener(listener);
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        refreshConfigurationLocked(0);
-        updateGlobalMetaStateLocked();
-    } // release lock
-}
-
-InputReader::~InputReader() {
-    for (size_t i = 0; i < mDevices.size(); i++) {
-        delete mDevices.valueAt(i);
-    }
-}
-
-void InputReader::loopOnce() {
-    int32_t oldGeneration;
-    int32_t timeoutMillis;
-    bool inputDevicesChanged = false;
-    std::vector<InputDeviceInfo> inputDevices;
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        oldGeneration = mGeneration;
-        timeoutMillis = -1;
-
-        uint32_t changes = mConfigurationChangesToRefresh;
-        if (changes) {
-            mConfigurationChangesToRefresh = 0;
-            timeoutMillis = 0;
-            refreshConfigurationLocked(changes);
-        } else if (mNextTimeout != LLONG_MAX) {
-            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-            timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
-        }
-    } // release lock
-
-    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-        mReaderIsAliveCondition.broadcast();
-
-        if (count) {
-            processEventsLocked(mEventBuffer, count);
-        }
-
-        if (mNextTimeout != LLONG_MAX) {
-            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-            if (now >= mNextTimeout) {
-#if DEBUG_RAW_EVENTS
-                ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
-#endif
-                mNextTimeout = LLONG_MAX;
-                timeoutExpiredLocked(now);
-            }
-        }
-
-        if (oldGeneration != mGeneration) {
-            inputDevicesChanged = true;
-            getInputDevicesLocked(inputDevices);
-        }
-    } // release lock
-
-    // Send out a message that the describes the changed input devices.
-    if (inputDevicesChanged) {
-        mPolicy->notifyInputDevicesChanged(inputDevices);
-    }
-
-    // Flush queued events out to the listener.
-    // This must happen outside of the lock because the listener could potentially call
-    // back into the InputReader's methods, such as getScanCodeState, or become blocked
-    // on another thread similarly waiting to acquire the InputReader lock thereby
-    // resulting in a deadlock.  This situation is actually quite plausible because the
-    // listener is actually the input dispatcher, which calls into the window manager,
-    // which occasionally calls into the input reader.
-    mQueuedListener->flush();
-}
-
-void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
-    for (const RawEvent* rawEvent = rawEvents; count;) {
-        int32_t type = rawEvent->type;
-        size_t batchSize = 1;
-        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
-            int32_t deviceId = rawEvent->deviceId;
-            while (batchSize < count) {
-                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT ||
-                    rawEvent[batchSize].deviceId != deviceId) {
-                    break;
-                }
-                batchSize += 1;
-            }
-#if DEBUG_RAW_EVENTS
-            ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
-#endif
-            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
-        } else {
-            switch (rawEvent->type) {
-                case EventHubInterface::DEVICE_ADDED:
-                    addDeviceLocked(rawEvent->when, rawEvent->deviceId);
-                    break;
-                case EventHubInterface::DEVICE_REMOVED:
-                    removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
-                    break;
-                case EventHubInterface::FINISHED_DEVICE_SCAN:
-                    handleConfigurationChangedLocked(rawEvent->when);
-                    break;
-                default:
-                    ALOG_ASSERT(false); // can't happen
-                    break;
-            }
-        }
-        count -= batchSize;
-        rawEvent += batchSize;
-    }
-}
-
-void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
-    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-    if (deviceIndex >= 0) {
-        ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
-        return;
-    }
-
-    InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
-    uint32_t classes = mEventHub->getDeviceClasses(deviceId);
-    int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
-
-    InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
-    device->configure(when, &mConfig, 0);
-    device->reset(when);
-
-    if (device->isIgnored()) {
-        ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
-              identifier.name.c_str());
-    } else {
-        ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, identifier.name.c_str(),
-              device->getSources());
-    }
-
-    mDevices.add(deviceId, device);
-    bumpGenerationLocked();
-
-    if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
-        notifyExternalStylusPresenceChanged();
-    }
-}
-
-void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
-    InputDevice* device = nullptr;
-    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-    if (deviceIndex < 0) {
-        ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
-        return;
-    }
-
-    device = mDevices.valueAt(deviceIndex);
-    mDevices.removeItemsAt(deviceIndex, 1);
-    bumpGenerationLocked();
-
-    if (device->isIgnored()) {
-        ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)", device->getId(),
-              device->getName().c_str());
-    } else {
-        ALOGI("Device removed: id=%d, name='%s', sources=0x%08x", device->getId(),
-              device->getName().c_str(), device->getSources());
-    }
-
-    if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
-        notifyExternalStylusPresenceChanged();
-    }
-
-    device->reset(when);
-    delete device;
-}
-
-InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
-                                             const InputDeviceIdentifier& identifier,
-                                             uint32_t classes) {
-    InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
-                                          controllerNumber, identifier, classes);
-
-    // External devices.
-    if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
-        device->setExternal(true);
-    }
-
-    // Devices with mics.
-    if (classes & INPUT_DEVICE_CLASS_MIC) {
-        device->setMic(true);
-    }
-
-    // Switch-like devices.
-    if (classes & INPUT_DEVICE_CLASS_SWITCH) {
-        device->addMapper(new SwitchInputMapper(device));
-    }
-
-    // Scroll wheel-like devices.
-    if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
-        device->addMapper(new RotaryEncoderInputMapper(device));
-    }
-
-    // Vibrator-like devices.
-    if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
-        device->addMapper(new VibratorInputMapper(device));
-    }
-
-    // Keyboard-like devices.
-    uint32_t keyboardSource = 0;
-    int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
-    if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
-        keyboardSource |= AINPUT_SOURCE_KEYBOARD;
-    }
-    if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
-        keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
-    }
-    if (classes & INPUT_DEVICE_CLASS_DPAD) {
-        keyboardSource |= AINPUT_SOURCE_DPAD;
-    }
-    if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
-        keyboardSource |= AINPUT_SOURCE_GAMEPAD;
-    }
-
-    if (keyboardSource != 0) {
-        device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
-    }
-
-    // Cursor-like devices.
-    if (classes & INPUT_DEVICE_CLASS_CURSOR) {
-        device->addMapper(new CursorInputMapper(device));
-    }
-
-    // Touchscreens and touchpad devices.
-    if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
-        device->addMapper(new MultiTouchInputMapper(device));
-    } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
-        device->addMapper(new SingleTouchInputMapper(device));
-    }
-
-    // Joystick-like devices.
-    if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
-        device->addMapper(new JoystickInputMapper(device));
-    }
-
-    // External stylus-like devices.
-    if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
-        device->addMapper(new ExternalStylusInputMapper(device));
-    }
-
-    return device;
-}
-
-void InputReader::processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents,
-                                               size_t count) {
-    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-    if (deviceIndex < 0) {
-        ALOGW("Discarding event for unknown deviceId %d.", deviceId);
-        return;
-    }
-
-    InputDevice* device = mDevices.valueAt(deviceIndex);
-    if (device->isIgnored()) {
-        // ALOGD("Discarding event for ignored deviceId %d.", deviceId);
-        return;
-    }
-
-    device->process(rawEvents, count);
-}
-
-void InputReader::timeoutExpiredLocked(nsecs_t when) {
-    for (size_t i = 0; i < mDevices.size(); i++) {
-        InputDevice* device = mDevices.valueAt(i);
-        if (!device->isIgnored()) {
-            device->timeoutExpired(when);
-        }
-    }
-}
-
-void InputReader::handleConfigurationChangedLocked(nsecs_t when) {
-    // Reset global meta state because it depends on the list of all configured devices.
-    updateGlobalMetaStateLocked();
-
-    // Enqueue configuration changed.
-    NotifyConfigurationChangedArgs args(mContext.getNextSequenceNum(), when);
-    mQueuedListener->notifyConfigurationChanged(&args);
-}
-
-void InputReader::refreshConfigurationLocked(uint32_t changes) {
-    mPolicy->getReaderConfiguration(&mConfig);
-    mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
-
-    if (changes) {
-        ALOGI("Reconfiguring input devices.  changes=0x%08x", changes);
-        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-
-        if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
-            mEventHub->requestReopenDevices();
-        } else {
-            for (size_t i = 0; i < mDevices.size(); i++) {
-                InputDevice* device = mDevices.valueAt(i);
-                device->configure(now, &mConfig, changes);
-            }
-        }
-    }
-}
-
-void InputReader::updateGlobalMetaStateLocked() {
-    mGlobalMetaState = 0;
-
-    for (size_t i = 0; i < mDevices.size(); i++) {
-        InputDevice* device = mDevices.valueAt(i);
-        mGlobalMetaState |= device->getMetaState();
-    }
-}
-
-int32_t InputReader::getGlobalMetaStateLocked() {
-    return mGlobalMetaState;
-}
-
-void InputReader::notifyExternalStylusPresenceChanged() {
-    refreshConfigurationLocked(InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE);
-}
-
-void InputReader::getExternalStylusDevicesLocked(std::vector<InputDeviceInfo>& outDevices) {
-    for (size_t i = 0; i < mDevices.size(); i++) {
-        InputDevice* device = mDevices.valueAt(i);
-        if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS && !device->isIgnored()) {
-            InputDeviceInfo info;
-            device->getDeviceInfo(&info);
-            outDevices.push_back(info);
-        }
-    }
-}
-
-void InputReader::dispatchExternalStylusState(const StylusState& state) {
-    for (size_t i = 0; i < mDevices.size(); i++) {
-        InputDevice* device = mDevices.valueAt(i);
-        device->updateExternalStylusState(state);
-    }
-}
-
-void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) {
-    mDisableVirtualKeysTimeout = time;
-}
-
-bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now, InputDevice* device, int32_t keyCode,
-                                             int32_t scanCode) {
-    if (now < mDisableVirtualKeysTimeout) {
-        ALOGI("Dropping virtual key from device %s because virtual keys are "
-              "temporarily disabled for the next %0.3fms.  keyCode=%d, scanCode=%d",
-              device->getName().c_str(), (mDisableVirtualKeysTimeout - now) * 0.000001, keyCode,
-              scanCode);
-        return true;
-    } else {
-        return false;
-    }
-}
-
-void InputReader::fadePointerLocked() {
-    for (size_t i = 0; i < mDevices.size(); i++) {
-        InputDevice* device = mDevices.valueAt(i);
-        device->fadePointer();
-    }
-}
-
-void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
-    if (when < mNextTimeout) {
-        mNextTimeout = when;
-        mEventHub->wake();
-    }
-}
-
-int32_t InputReader::bumpGenerationLocked() {
-    return ++mGeneration;
-}
-
-void InputReader::getInputDevices(std::vector<InputDeviceInfo>& outInputDevices) {
-    AutoMutex _l(mLock);
-    getInputDevicesLocked(outInputDevices);
-}
-
-void InputReader::getInputDevicesLocked(std::vector<InputDeviceInfo>& outInputDevices) {
-    outInputDevices.clear();
-
-    size_t numDevices = mDevices.size();
-    for (size_t i = 0; i < numDevices; i++) {
-        InputDevice* device = mDevices.valueAt(i);
-        if (!device->isIgnored()) {
-            InputDeviceInfo info;
-            device->getDeviceInfo(&info);
-            outInputDevices.push_back(info);
-        }
-    }
-}
-
-int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask, int32_t keyCode) {
-    AutoMutex _l(mLock);
-
-    return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState);
-}
-
-int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask, int32_t scanCode) {
-    AutoMutex _l(mLock);
-
-    return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState);
-}
-
-int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
-    AutoMutex _l(mLock);
-
-    return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState);
-}
-
-int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
-                                    GetStateFunc getStateFunc) {
-    int32_t result = AKEY_STATE_UNKNOWN;
-    if (deviceId >= 0) {
-        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-        if (deviceIndex >= 0) {
-            InputDevice* device = mDevices.valueAt(deviceIndex);
-            if (!device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
-                result = (device->*getStateFunc)(sourceMask, code);
-            }
-        }
-    } else {
-        size_t numDevices = mDevices.size();
-        for (size_t i = 0; i < numDevices; i++) {
-            InputDevice* device = mDevices.valueAt(i);
-            if (!device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
-                // If any device reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
-                // value.  Otherwise, return AKEY_STATE_UP as long as one device reports it.
-                int32_t currentResult = (device->*getStateFunc)(sourceMask, code);
-                if (currentResult >= AKEY_STATE_DOWN) {
-                    return currentResult;
-                } else if (currentResult == AKEY_STATE_UP) {
-                    result = currentResult;
-                }
-            }
-        }
-    }
-    return result;
-}
-
-void InputReader::toggleCapsLockState(int32_t deviceId) {
-    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-    if (deviceIndex < 0) {
-        ALOGW("Ignoring toggleCapsLock for unknown deviceId %" PRId32 ".", deviceId);
-        return;
-    }
-
-    InputDevice* device = mDevices.valueAt(deviceIndex);
-    if (device->isIgnored()) {
-        return;
-    }
-
-    device->updateMetaState(AKEYCODE_CAPS_LOCK);
-}
-
-bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
-                          const int32_t* keyCodes, uint8_t* outFlags) {
-    AutoMutex _l(mLock);
-
-    memset(outFlags, 0, numCodes);
-    return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags);
-}
-
-bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask,
-                                              size_t numCodes, const int32_t* keyCodes,
-                                              uint8_t* outFlags) {
-    bool result = false;
-    if (deviceId >= 0) {
-        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-        if (deviceIndex >= 0) {
-            InputDevice* device = mDevices.valueAt(deviceIndex);
-            if (!device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
-                result = device->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
-            }
-        }
-    } else {
-        size_t numDevices = mDevices.size();
-        for (size_t i = 0; i < numDevices; i++) {
-            InputDevice* device = mDevices.valueAt(i);
-            if (!device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
-                result |= device->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
-            }
-        }
-    }
-    return result;
-}
-
-void InputReader::requestRefreshConfiguration(uint32_t changes) {
-    AutoMutex _l(mLock);
-
-    if (changes) {
-        bool needWake = !mConfigurationChangesToRefresh;
-        mConfigurationChangesToRefresh |= changes;
-
-        if (needWake) {
-            mEventHub->wake();
-        }
-    }
-}
-
-void InputReader::vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
-                          ssize_t repeat, int32_t token) {
-    AutoMutex _l(mLock);
-
-    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-    if (deviceIndex >= 0) {
-        InputDevice* device = mDevices.valueAt(deviceIndex);
-        device->vibrate(pattern, patternSize, repeat, token);
-    }
-}
-
-void InputReader::cancelVibrate(int32_t deviceId, int32_t token) {
-    AutoMutex _l(mLock);
-
-    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-    if (deviceIndex >= 0) {
-        InputDevice* device = mDevices.valueAt(deviceIndex);
-        device->cancelVibrate(token);
-    }
-}
-
-bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
-    AutoMutex _l(mLock);
-
-    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-    if (deviceIndex >= 0) {
-        InputDevice* device = mDevices.valueAt(deviceIndex);
-        return device->isEnabled();
-    }
-    ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
-    return false;
-}
-
-bool InputReader::canDispatchToDisplay(int32_t deviceId, int32_t displayId) {
-    AutoMutex _l(mLock);
-
-    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-    if (deviceIndex < 0) {
-        ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
-        return false;
-    }
-
-    InputDevice* device = mDevices.valueAt(deviceIndex);
-    std::optional<int32_t> associatedDisplayId = device->getAssociatedDisplay();
-    // No associated display. By default, can dispatch to all displays.
-    if (!associatedDisplayId) {
-        return true;
-    }
-
-    if (*associatedDisplayId == ADISPLAY_ID_NONE) {
-        ALOGW("Device has associated, but no associated display id.");
-        return true;
-    }
-
-    return *associatedDisplayId == displayId;
-}
-
-void InputReader::dump(std::string& dump) {
-    AutoMutex _l(mLock);
-
-    mEventHub->dump(dump);
-    dump += "\n";
-
-    dump += "Input Reader State:\n";
-
-    for (size_t i = 0; i < mDevices.size(); i++) {
-        mDevices.valueAt(i)->dump(dump);
-    }
-
-    dump += INDENT "Configuration:\n";
-    dump += INDENT2 "ExcludedDeviceNames: [";
-    for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
-        if (i != 0) {
-            dump += ", ";
-        }
-        dump += mConfig.excludedDeviceNames[i];
-    }
-    dump += "]\n";
-    dump += StringPrintf(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
-                         mConfig.virtualKeyQuietTime * 0.000001f);
-
-    dump += StringPrintf(INDENT2 "PointerVelocityControlParameters: "
-                                 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, "
-                                 "acceleration=%0.3f\n",
-                         mConfig.pointerVelocityControlParameters.scale,
-                         mConfig.pointerVelocityControlParameters.lowThreshold,
-                         mConfig.pointerVelocityControlParameters.highThreshold,
-                         mConfig.pointerVelocityControlParameters.acceleration);
-
-    dump += StringPrintf(INDENT2 "WheelVelocityControlParameters: "
-                                 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, "
-                                 "acceleration=%0.3f\n",
-                         mConfig.wheelVelocityControlParameters.scale,
-                         mConfig.wheelVelocityControlParameters.lowThreshold,
-                         mConfig.wheelVelocityControlParameters.highThreshold,
-                         mConfig.wheelVelocityControlParameters.acceleration);
-
-    dump += StringPrintf(INDENT2 "PointerGesture:\n");
-    dump += StringPrintf(INDENT3 "Enabled: %s\n", toString(mConfig.pointerGesturesEnabled));
-    dump += StringPrintf(INDENT3 "QuietInterval: %0.1fms\n",
-                         mConfig.pointerGestureQuietInterval * 0.000001f);
-    dump += StringPrintf(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
-                         mConfig.pointerGestureDragMinSwitchSpeed);
-    dump += StringPrintf(INDENT3 "TapInterval: %0.1fms\n",
-                         mConfig.pointerGestureTapInterval * 0.000001f);
-    dump += StringPrintf(INDENT3 "TapDragInterval: %0.1fms\n",
-                         mConfig.pointerGestureTapDragInterval * 0.000001f);
-    dump += StringPrintf(INDENT3 "TapSlop: %0.1fpx\n", mConfig.pointerGestureTapSlop);
-    dump += StringPrintf(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
-                         mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
-    dump += StringPrintf(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
-                         mConfig.pointerGestureMultitouchMinDistance);
-    dump += StringPrintf(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
-                         mConfig.pointerGestureSwipeTransitionAngleCosine);
-    dump += StringPrintf(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
-                         mConfig.pointerGestureSwipeMaxWidthRatio);
-    dump += StringPrintf(INDENT3 "MovementSpeedRatio: %0.1f\n",
-                         mConfig.pointerGestureMovementSpeedRatio);
-    dump += StringPrintf(INDENT3 "ZoomSpeedRatio: %0.1f\n", mConfig.pointerGestureZoomSpeedRatio);
-
-    dump += INDENT3 "Viewports:\n";
-    mConfig.dump(dump);
-}
-
-void InputReader::monitor() {
-    // Acquire and release the lock to ensure that the reader has not deadlocked.
-    mLock.lock();
-    mEventHub->wake();
-    mReaderIsAliveCondition.wait(mLock);
-    mLock.unlock();
-
-    // Check the EventHub
-    mEventHub->monitor();
-}
-
-// --- InputReader::ContextImpl ---
-
-InputReader::ContextImpl::ContextImpl(InputReader* reader) : mReader(reader) {}
-
-void InputReader::ContextImpl::updateGlobalMetaState() {
-    // lock is already held by the input loop
-    mReader->updateGlobalMetaStateLocked();
-}
-
-int32_t InputReader::ContextImpl::getGlobalMetaState() {
-    // lock is already held by the input loop
-    return mReader->getGlobalMetaStateLocked();
-}
-
-void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) {
-    // lock is already held by the input loop
-    mReader->disableVirtualKeysUntilLocked(time);
-}
-
-bool InputReader::ContextImpl::shouldDropVirtualKey(nsecs_t now, InputDevice* device,
-                                                    int32_t keyCode, int32_t scanCode) {
-    // lock is already held by the input loop
-    return mReader->shouldDropVirtualKeyLocked(now, device, keyCode, scanCode);
-}
-
-void InputReader::ContextImpl::fadePointer() {
-    // lock is already held by the input loop
-    mReader->fadePointerLocked();
-}
-
-void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
-    // lock is already held by the input loop
-    mReader->requestTimeoutAtTimeLocked(when);
-}
-
-int32_t InputReader::ContextImpl::bumpGeneration() {
-    // lock is already held by the input loop
-    return mReader->bumpGenerationLocked();
-}
-
-void InputReader::ContextImpl::getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) {
-    // lock is already held by whatever called refreshConfigurationLocked
-    mReader->getExternalStylusDevicesLocked(outDevices);
-}
-
-void InputReader::ContextImpl::dispatchExternalStylusState(const StylusState& state) {
-    mReader->dispatchExternalStylusState(state);
-}
-
-InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
-    return mReader->mPolicy.get();
-}
-
-InputListenerInterface* InputReader::ContextImpl::getListener() {
-    return mReader->mQueuedListener.get();
-}
-
-EventHubInterface* InputReader::ContextImpl::getEventHub() {
-    return mReader->mEventHub.get();
-}
-
-uint32_t InputReader::ContextImpl::getNextSequenceNum() {
-    return (mReader->mNextSequenceNum)++;
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/Macros.h b/services/inputflinger/reader/Macros.h
deleted file mode 100644
index 827e31a..0000000
--- a/services/inputflinger/reader/Macros.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_MACROS_H
-#define _UI_INPUTREADER_MACROS_H
-
-#define LOG_TAG "InputReader"
-
-//#define LOG_NDEBUG 0
-
-// Log debug messages for each raw event received from the EventHub.
-#define DEBUG_RAW_EVENTS 0
-
-// Log debug messages about touch screen filtering hacks.
-#define DEBUG_HACKS 0
-
-// Log debug messages about virtual key processing.
-#define DEBUG_VIRTUAL_KEYS 0
-
-// Log debug messages about pointers.
-#define DEBUG_POINTERS 0
-
-// Log debug messages about pointer assignment calculations.
-#define DEBUG_POINTER_ASSIGNMENT 0
-
-// Log debug messages about gesture detection.
-#define DEBUG_GESTURES 0
-
-// Log debug messages about the vibrator.
-#define DEBUG_VIBRATOR 0
-
-// Log debug messages about fusing stylus data.
-#define DEBUG_STYLUS_FUSION 0
-
-#define INDENT "  "
-#define INDENT2 "    "
-#define INDENT3 "      "
-#define INDENT4 "        "
-#define INDENT5 "          "
-
-#include <input/Input.h>
-
-namespace android {
-
-// --- Static Functions ---
-
-template <typename T>
-inline static T abs(const T& value) {
-    return value < 0 ? -value : value;
-}
-
-template <typename T>
-inline static T min(const T& a, const T& b) {
-    return a < b ? a : b;
-}
-
-inline static float avg(float x, float y) {
-    return (x + y) / 2;
-}
-
-static inline const char* toString(bool value) {
-    return value ? "true" : "false";
-}
-
-static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
-    return (sources & sourceMask & ~AINPUT_SOURCE_CLASS_MASK) != 0;
-}
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_MACROS_H
\ No newline at end of file
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
deleted file mode 100644
index 57f0b31..0000000
--- a/services/inputflinger/reader/include/InputDevice.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_INPUT_DEVICE_H
-#define _UI_INPUTREADER_INPUT_DEVICE_H
-
-#include "EventHub.h"
-#include "InputReaderBase.h"
-#include "InputReaderContext.h"
-
-#include <input/DisplayViewport.h>
-#include <input/InputDevice.h>
-#include <utils/PropertyMap.h>
-
-#include <stdint.h>
-#include <optional>
-#include <vector>
-
-namespace android {
-
-class InputMapper;
-
-/* Represents the state of a single input device. */
-class InputDevice {
-public:
-    InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
-                int32_t controllerNumber, const InputDeviceIdentifier& identifier,
-                uint32_t classes);
-    ~InputDevice();
-
-    inline InputReaderContext* getContext() { return mContext; }
-    inline int32_t getId() const { return mId; }
-    inline int32_t getControllerNumber() const { return mControllerNumber; }
-    inline int32_t getGeneration() const { return mGeneration; }
-    inline const std::string getName() const { return mIdentifier.name; }
-    inline const std::string getDescriptor() { return mIdentifier.descriptor; }
-    inline uint32_t getClasses() const { return mClasses; }
-    inline uint32_t getSources() const { return mSources; }
-
-    inline bool isExternal() { return mIsExternal; }
-    inline void setExternal(bool external) { mIsExternal = external; }
-    inline std::optional<uint8_t> getAssociatedDisplayPort() const {
-        return mAssociatedDisplayPort;
-    }
-
-    inline void setMic(bool hasMic) { mHasMic = hasMic; }
-    inline bool hasMic() const { return mHasMic; }
-
-    inline bool isIgnored() { return mMappers.empty(); }
-
-    bool isEnabled();
-    void setEnabled(bool enabled, nsecs_t when);
-
-    void dump(std::string& dump);
-    void addMapper(InputMapper* mapper);
-    void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
-    void reset(nsecs_t when);
-    void process(const RawEvent* rawEvents, size_t count);
-    void timeoutExpired(nsecs_t when);
-    void updateExternalStylusState(const StylusState& state);
-
-    void getDeviceInfo(InputDeviceInfo* outDeviceInfo);
-    int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
-    int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-    int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
-    bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, const int32_t* keyCodes,
-                               uint8_t* outFlags);
-    void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, int32_t token);
-    void cancelVibrate(int32_t token);
-    void cancelTouch(nsecs_t when);
-
-    int32_t getMetaState();
-    void updateMetaState(int32_t keyCode);
-
-    void fadePointer();
-
-    void bumpGeneration();
-
-    void notifyReset(nsecs_t when);
-
-    inline const PropertyMap& getConfiguration() { return mConfiguration; }
-    inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
-
-    bool hasKey(int32_t code) { return getEventHub()->hasScanCode(mId, code); }
-
-    bool hasAbsoluteAxis(int32_t code) {
-        RawAbsoluteAxisInfo info;
-        getEventHub()->getAbsoluteAxisInfo(mId, code, &info);
-        return info.valid;
-    }
-
-    bool isKeyPressed(int32_t code) {
-        return getEventHub()->getScanCodeState(mId, code) == AKEY_STATE_DOWN;
-    }
-
-    int32_t getAbsoluteAxisValue(int32_t code) {
-        int32_t value;
-        getEventHub()->getAbsoluteAxisValue(mId, code, &value);
-        return value;
-    }
-
-    std::optional<int32_t> getAssociatedDisplay();
-
-private:
-    InputReaderContext* mContext;
-    int32_t mId;
-    int32_t mGeneration;
-    int32_t mControllerNumber;
-    InputDeviceIdentifier mIdentifier;
-    std::string mAlias;
-    uint32_t mClasses;
-
-    std::vector<InputMapper*> mMappers;
-
-    uint32_t mSources;
-    bool mIsExternal;
-    std::optional<uint8_t> mAssociatedDisplayPort;
-    bool mHasMic;
-    bool mDropUntilNextSync;
-
-    typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
-    int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
-
-    PropertyMap mConfiguration;
-};
-
-} // namespace android
-
-#endif //_UI_INPUTREADER_INPUT_DEVICE_H
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
deleted file mode 100644
index e29c8f2..0000000
--- a/services/inputflinger/reader/include/InputReader.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#ifndef _UI_INPUTREADER_INPUT_READER_H
-#define _UI_INPUTREADER_INPUT_READER_H
-
-#include "EventHub.h"
-#include "InputListener.h"
-#include "InputReaderBase.h"
-#include "InputReaderContext.h"
-
-#include <utils/BitSet.h>
-#include <utils/Condition.h>
-#include <utils/KeyedVector.h>
-#include <utils/Mutex.h>
-#include <utils/Timers.h>
-
-#include <vector>
-
-namespace android {
-
-class InputDevice;
-class InputMapper;
-struct StylusState;
-
-/* The input reader reads raw event data from the event hub and processes it into input events
- * that it sends to the input listener.  Some functions of the input reader, such as early
- * event filtering in low power states, are controlled by a separate policy object.
- *
- * The InputReader owns a collection of InputMappers.  Most of the work it does happens
- * on the input reader thread but the InputReader can receive queries from other system
- * components running on arbitrary threads.  To keep things manageable, the InputReader
- * uses a single Mutex to guard its state.  The Mutex may be held while calling into the
- * EventHub or the InputReaderPolicy but it is never held while calling into the
- * InputListener.
- */
-class InputReader : public InputReaderInterface {
-public:
-    InputReader(const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& policy,
-                const sp<InputListenerInterface>& listener);
-    virtual ~InputReader();
-
-    virtual void dump(std::string& dump);
-    virtual void monitor();
-
-    virtual void loopOnce();
-
-    virtual void getInputDevices(std::vector<InputDeviceInfo>& outInputDevices);
-
-    virtual bool isInputDeviceEnabled(int32_t deviceId);
-
-    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask, int32_t scanCode);
-    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, int32_t keyCode);
-    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t sw);
-
-    virtual void toggleCapsLockState(int32_t deviceId);
-
-    virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
-                         const int32_t* keyCodes, uint8_t* outFlags);
-
-    virtual void requestRefreshConfiguration(uint32_t changes);
-
-    virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
-                         ssize_t repeat, int32_t token);
-    virtual void cancelVibrate(int32_t deviceId, int32_t token);
-
-    virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId);
-protected:
-    // These members are protected so they can be instrumented by test cases.
-    virtual InputDevice* createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
-                                            const InputDeviceIdentifier& identifier,
-                                            uint32_t classes);
-
-    class ContextImpl : public InputReaderContext {
-        InputReader* mReader;
-
-    public:
-        explicit ContextImpl(InputReader* reader);
-
-        virtual void updateGlobalMetaState();
-        virtual int32_t getGlobalMetaState();
-        virtual void disableVirtualKeysUntil(nsecs_t time);
-        virtual bool shouldDropVirtualKey(nsecs_t now, InputDevice* device, int32_t keyCode,
-                                          int32_t scanCode);
-        virtual void fadePointer();
-        virtual void requestTimeoutAtTime(nsecs_t when);
-        virtual int32_t bumpGeneration();
-        virtual void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices);
-        virtual void dispatchExternalStylusState(const StylusState& outState);
-        virtual InputReaderPolicyInterface* getPolicy();
-        virtual InputListenerInterface* getListener();
-        virtual EventHubInterface* getEventHub();
-        virtual uint32_t getNextSequenceNum();
-    } mContext;
-
-    friend class ContextImpl;
-
-private:
-    Mutex mLock;
-
-    Condition mReaderIsAliveCondition;
-
-    sp<EventHubInterface> mEventHub;
-    sp<InputReaderPolicyInterface> mPolicy;
-    sp<QueuedInputListener> mQueuedListener;
-
-    InputReaderConfiguration mConfig;
-
-    // used by InputReaderContext::getNextSequenceNum() as a counter for event sequence numbers
-    uint32_t mNextSequenceNum;
-
-    // The event queue.
-    static const int EVENT_BUFFER_SIZE = 256;
-    RawEvent mEventBuffer[EVENT_BUFFER_SIZE];
-
-    KeyedVector<int32_t, InputDevice*> mDevices;
-
-    // low-level input event decoding and device management
-    void processEventsLocked(const RawEvent* rawEvents, size_t count);
-
-    void addDeviceLocked(nsecs_t when, int32_t deviceId);
-    void removeDeviceLocked(nsecs_t when, int32_t deviceId);
-    void processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents, size_t count);
-    void timeoutExpiredLocked(nsecs_t when);
-
-    void handleConfigurationChangedLocked(nsecs_t when);
-
-    int32_t mGlobalMetaState;
-    void updateGlobalMetaStateLocked();
-    int32_t getGlobalMetaStateLocked();
-
-    void notifyExternalStylusPresenceChanged();
-    void getExternalStylusDevicesLocked(std::vector<InputDeviceInfo>& outDevices);
-    void dispatchExternalStylusState(const StylusState& state);
-
-    void fadePointerLocked();
-
-    int32_t mGeneration;
-    int32_t bumpGenerationLocked();
-
-    void getInputDevicesLocked(std::vector<InputDeviceInfo>& outInputDevices);
-
-    nsecs_t mDisableVirtualKeysTimeout;
-    void disableVirtualKeysUntilLocked(nsecs_t time);
-    bool shouldDropVirtualKeyLocked(nsecs_t now, InputDevice* device, int32_t keyCode,
-                                    int32_t scanCode);
-
-    nsecs_t mNextTimeout;
-    void requestTimeoutAtTimeLocked(nsecs_t when);
-
-    uint32_t mConfigurationChangesToRefresh;
-    void refreshConfigurationLocked(uint32_t changes);
-
-    // state queries
-    typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code);
-    int32_t getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
-                           GetStateFunc getStateFunc);
-    bool markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
-                                     const int32_t* keyCodes, uint8_t* outFlags);
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_INPUT_READER_H
diff --git a/services/inputflinger/reader/include/InputReaderContext.h b/services/inputflinger/reader/include/InputReaderContext.h
deleted file mode 100644
index 3472346..0000000
--- a/services/inputflinger/reader/include/InputReaderContext.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_INPUT_READER_CONTEXT_H
-#define _UI_INPUTREADER_INPUT_READER_CONTEXT_H
-
-#include <input/InputDevice.h>
-
-#include <vector>
-
-namespace android {
-
-class EventHubInterface;
-class InputDevice;
-class InputListenerInterface;
-class InputMapper;
-class InputReaderPolicyInterface;
-struct StylusState;
-
-/* Internal interface used by individual input devices to access global input device state
- * and parameters maintained by the input reader.
- */
-class InputReaderContext {
-public:
-    InputReaderContext() {}
-    virtual ~InputReaderContext() {}
-
-    virtual void updateGlobalMetaState() = 0;
-    virtual int32_t getGlobalMetaState() = 0;
-
-    virtual void disableVirtualKeysUntil(nsecs_t time) = 0;
-    virtual bool shouldDropVirtualKey(nsecs_t now, InputDevice* device, int32_t keyCode,
-                                      int32_t scanCode) = 0;
-
-    virtual void fadePointer() = 0;
-
-    virtual void requestTimeoutAtTime(nsecs_t when) = 0;
-    virtual int32_t bumpGeneration() = 0;
-
-    virtual void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) = 0;
-    virtual void dispatchExternalStylusState(const StylusState& outState) = 0;
-
-    virtual InputReaderPolicyInterface* getPolicy() = 0;
-    virtual InputListenerInterface* getListener() = 0;
-    virtual EventHubInterface* getEventHub() = 0;
-
-    virtual uint32_t getNextSequenceNum() = 0;
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_INPUT_READER_CONTEXT_H
diff --git a/services/inputflinger/reader/include/StylusState.h b/services/inputflinger/reader/include/StylusState.h
deleted file mode 100644
index 17f158c..0000000
--- a/services/inputflinger/reader/include/StylusState.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_STYLUS_STATE_H
-#define _UI_INPUTREADER_STYLUS_STATE_H
-
-#include <input/Input.h>
-
-#include <limits.h>
-
-namespace android {
-
-struct StylusState {
-    /* Time the stylus event was received. */
-    nsecs_t when;
-    /* Pressure as reported by the stylus, normalized to the range [0, 1.0]. */
-    float pressure;
-    /* The state of the stylus buttons as a bitfield (e.g. AMOTION_EVENT_BUTTON_SECONDARY). */
-    uint32_t buttons;
-    /* Which tool type the stylus is currently using (e.g. AMOTION_EVENT_TOOL_TYPE_ERASER). */
-    int32_t toolType;
-
-    void copyFrom(const StylusState& other) {
-        when = other.when;
-        pressure = other.pressure;
-        buttons = other.buttons;
-        toolType = other.toolType;
-    }
-
-    void clear() {
-        when = LLONG_MAX;
-        pressure = 0.f;
-        buttons = 0;
-        toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
-    }
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_STYLUS_STATE_H
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
deleted file mode 100644
index da85fda..0000000
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Macros.h"
-
-#include "CursorInputMapper.h"
-
-#include "CursorButtonAccumulator.h"
-#include "CursorScrollAccumulator.h"
-#include "TouchCursorInputMapperCommon.h"
-
-namespace android {
-
-// --- CursorMotionAccumulator ---
-
-CursorMotionAccumulator::CursorMotionAccumulator() {
-    clearRelativeAxes();
-}
-
-void CursorMotionAccumulator::reset(InputDevice* device) {
-    clearRelativeAxes();
-}
-
-void CursorMotionAccumulator::clearRelativeAxes() {
-    mRelX = 0;
-    mRelY = 0;
-}
-
-void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
-    if (rawEvent->type == EV_REL) {
-        switch (rawEvent->code) {
-            case REL_X:
-                mRelX = rawEvent->value;
-                break;
-            case REL_Y:
-                mRelY = rawEvent->value;
-                break;
-        }
-    }
-}
-
-void CursorMotionAccumulator::finishSync() {
-    clearRelativeAxes();
-}
-
-// --- CursorInputMapper ---
-
-CursorInputMapper::CursorInputMapper(InputDevice* device) : InputMapper(device) {}
-
-CursorInputMapper::~CursorInputMapper() {}
-
-uint32_t CursorInputMapper::getSources() {
-    return mSource;
-}
-
-void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    InputMapper::populateDeviceInfo(info);
-
-    if (mParameters.mode == Parameters::MODE_POINTER) {
-        float minX, minY, maxX, maxY;
-        if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
-            info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f, 0.0f);
-            info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f, 0.0f);
-        }
-    } else {
-        info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
-        info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
-    }
-    info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
-
-    if (mCursorScrollAccumulator.haveRelativeVWheel()) {
-        info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
-    }
-    if (mCursorScrollAccumulator.haveRelativeHWheel()) {
-        info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
-    }
-}
-
-void CursorInputMapper::dump(std::string& dump) {
-    dump += INDENT2 "Cursor Input Mapper:\n";
-    dumpParameters(dump);
-    dump += StringPrintf(INDENT3 "XScale: %0.3f\n", mXScale);
-    dump += StringPrintf(INDENT3 "YScale: %0.3f\n", mYScale);
-    dump += StringPrintf(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
-    dump += StringPrintf(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
-    dump += StringPrintf(INDENT3 "HaveVWheel: %s\n",
-                         toString(mCursorScrollAccumulator.haveRelativeVWheel()));
-    dump += StringPrintf(INDENT3 "HaveHWheel: %s\n",
-                         toString(mCursorScrollAccumulator.haveRelativeHWheel()));
-    dump += StringPrintf(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
-    dump += StringPrintf(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
-    dump += StringPrintf(INDENT3 "Orientation: %d\n", mOrientation);
-    dump += StringPrintf(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
-    dump += StringPrintf(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
-    dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
-}
-
-void CursorInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
-                                  uint32_t changes) {
-    InputMapper::configure(when, config, changes);
-
-    if (!changes) { // first time only
-        mCursorScrollAccumulator.configure(getDevice());
-
-        // Configure basic parameters.
-        configureParameters();
-
-        // Configure device mode.
-        switch (mParameters.mode) {
-            case Parameters::MODE_POINTER_RELATIVE:
-                // Should not happen during first time configuration.
-                ALOGE("Cannot start a device in MODE_POINTER_RELATIVE, starting in MODE_POINTER");
-                mParameters.mode = Parameters::MODE_POINTER;
-                [[fallthrough]];
-            case Parameters::MODE_POINTER:
-                mSource = AINPUT_SOURCE_MOUSE;
-                mXPrecision = 1.0f;
-                mYPrecision = 1.0f;
-                mXScale = 1.0f;
-                mYScale = 1.0f;
-                mPointerController = getPolicy()->obtainPointerController(getDeviceId());
-                break;
-            case Parameters::MODE_NAVIGATION:
-                mSource = AINPUT_SOURCE_TRACKBALL;
-                mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
-                mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
-                mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
-                mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
-                break;
-        }
-
-        mVWheelScale = 1.0f;
-        mHWheelScale = 1.0f;
-    }
-
-    if ((!changes && config->pointerCapture) ||
-        (changes & InputReaderConfiguration::CHANGE_POINTER_CAPTURE)) {
-        if (config->pointerCapture) {
-            if (mParameters.mode == Parameters::MODE_POINTER) {
-                mParameters.mode = Parameters::MODE_POINTER_RELATIVE;
-                mSource = AINPUT_SOURCE_MOUSE_RELATIVE;
-                // Keep PointerController around in order to preserve the pointer position.
-                mPointerController->fade(PointerControllerInterface::TRANSITION_IMMEDIATE);
-            } else {
-                ALOGE("Cannot request pointer capture, device is not in MODE_POINTER");
-            }
-        } else {
-            if (mParameters.mode == Parameters::MODE_POINTER_RELATIVE) {
-                mParameters.mode = Parameters::MODE_POINTER;
-                mSource = AINPUT_SOURCE_MOUSE;
-            } else {
-                ALOGE("Cannot release pointer capture, device is not in MODE_POINTER_RELATIVE");
-            }
-        }
-        bumpGeneration();
-        if (changes) {
-            getDevice()->notifyReset(when);
-        }
-    }
-
-    if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
-        mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
-        mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
-        mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
-    }
-
-    if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
-        mOrientation = DISPLAY_ORIENTATION_0;
-        if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
-            std::optional<DisplayViewport> internalViewport =
-                    config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
-            if (internalViewport) {
-                mOrientation = internalViewport->orientation;
-            }
-        }
-
-        // Update the PointerController if viewports changed.
-        if (mParameters.mode == Parameters::MODE_POINTER) {
-            getPolicy()->obtainPointerController(getDeviceId());
-        }
-        bumpGeneration();
-    }
-}
-
-void CursorInputMapper::configureParameters() {
-    mParameters.mode = Parameters::MODE_POINTER;
-    String8 cursorModeString;
-    if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
-        if (cursorModeString == "navigation") {
-            mParameters.mode = Parameters::MODE_NAVIGATION;
-        } else if (cursorModeString != "pointer" && cursorModeString != "default") {
-            ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
-        }
-    }
-
-    mParameters.orientationAware = false;
-    getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
-                                                   mParameters.orientationAware);
-
-    mParameters.hasAssociatedDisplay = false;
-    if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) {
-        mParameters.hasAssociatedDisplay = true;
-    }
-}
-
-void CursorInputMapper::dumpParameters(std::string& dump) {
-    dump += INDENT3 "Parameters:\n";
-    dump += StringPrintf(INDENT4 "HasAssociatedDisplay: %s\n",
-                         toString(mParameters.hasAssociatedDisplay));
-
-    switch (mParameters.mode) {
-        case Parameters::MODE_POINTER:
-            dump += INDENT4 "Mode: pointer\n";
-            break;
-        case Parameters::MODE_POINTER_RELATIVE:
-            dump += INDENT4 "Mode: relative pointer\n";
-            break;
-        case Parameters::MODE_NAVIGATION:
-            dump += INDENT4 "Mode: navigation\n";
-            break;
-        default:
-            ALOG_ASSERT(false);
-    }
-
-    dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
-}
-
-void CursorInputMapper::reset(nsecs_t when) {
-    mButtonState = 0;
-    mDownTime = 0;
-
-    mPointerVelocityControl.reset();
-    mWheelXVelocityControl.reset();
-    mWheelYVelocityControl.reset();
-
-    mCursorButtonAccumulator.reset(getDevice());
-    mCursorMotionAccumulator.reset(getDevice());
-    mCursorScrollAccumulator.reset(getDevice());
-
-    InputMapper::reset(when);
-}
-
-void CursorInputMapper::process(const RawEvent* rawEvent) {
-    mCursorButtonAccumulator.process(rawEvent);
-    mCursorMotionAccumulator.process(rawEvent);
-    mCursorScrollAccumulator.process(rawEvent);
-
-    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
-        sync(rawEvent->when);
-    }
-}
-
-void CursorInputMapper::sync(nsecs_t when) {
-    int32_t lastButtonState = mButtonState;
-    int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
-    mButtonState = currentButtonState;
-
-    bool wasDown = isPointerDown(lastButtonState);
-    bool down = isPointerDown(currentButtonState);
-    bool downChanged;
-    if (!wasDown && down) {
-        mDownTime = when;
-        downChanged = true;
-    } else if (wasDown && !down) {
-        downChanged = true;
-    } else {
-        downChanged = false;
-    }
-    nsecs_t downTime = mDownTime;
-    bool buttonsChanged = currentButtonState != lastButtonState;
-    int32_t buttonsPressed = currentButtonState & ~lastButtonState;
-    int32_t buttonsReleased = lastButtonState & ~currentButtonState;
-
-    float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
-    float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
-    bool moved = deltaX != 0 || deltaY != 0;
-
-    // Rotate delta according to orientation if needed.
-    if (mParameters.orientationAware && mParameters.hasAssociatedDisplay &&
-        (deltaX != 0.0f || deltaY != 0.0f)) {
-        rotateDelta(mOrientation, &deltaX, &deltaY);
-    }
-
-    // Move the pointer.
-    PointerProperties pointerProperties;
-    pointerProperties.clear();
-    pointerProperties.id = 0;
-    pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
-
-    PointerCoords pointerCoords;
-    pointerCoords.clear();
-
-    float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
-    float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
-    bool scrolled = vscroll != 0 || hscroll != 0;
-
-    mWheelYVelocityControl.move(when, nullptr, &vscroll);
-    mWheelXVelocityControl.move(when, &hscroll, nullptr);
-
-    mPointerVelocityControl.move(when, &deltaX, &deltaY);
-
-    int32_t displayId;
-    if (mSource == AINPUT_SOURCE_MOUSE) {
-        if (moved || scrolled || buttonsChanged) {
-            mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
-
-            if (moved) {
-                mPointerController->move(deltaX, deltaY);
-            }
-
-            if (buttonsChanged) {
-                mPointerController->setButtonState(currentButtonState);
-            }
-
-            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
-        }
-
-        float x, y;
-        mPointerController->getPosition(&x, &y);
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
-        displayId = mPointerController->getDisplayId();
-    } else {
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
-        displayId = ADISPLAY_ID_NONE;
-    }
-
-    pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
-
-    // Moving an external trackball or mouse should wake the device.
-    // We don't do this for internal cursor devices to prevent them from waking up
-    // the device in your pocket.
-    // TODO: Use the input device configuration to control this behavior more finely.
-    uint32_t policyFlags = 0;
-    if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) {
-        policyFlags |= POLICY_FLAG_WAKE;
-    }
-
-    // Synthesize key down from buttons if needed.
-    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
-                         displayId, policyFlags, lastButtonState, currentButtonState);
-
-    // Send motion event.
-    if (downChanged || moved || scrolled || buttonsChanged) {
-        int32_t metaState = mContext->getGlobalMetaState();
-        int32_t buttonState = lastButtonState;
-        int32_t motionEventAction;
-        if (downChanged) {
-            motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
-        } else if (down || (mSource != AINPUT_SOURCE_MOUSE)) {
-            motionEventAction = AMOTION_EVENT_ACTION_MOVE;
-        } else {
-            motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
-        }
-
-        if (buttonsReleased) {
-            BitSet32 released(buttonsReleased);
-            while (!released.isEmpty()) {
-                int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
-                buttonState &= ~actionButton;
-                NotifyMotionArgs releaseArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
-                                             mSource, displayId, policyFlags,
-                                             AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
-                                             metaState, buttonState, MotionClassification::NONE,
-                                             AMOTION_EVENT_EDGE_FLAG_NONE,
-                                             /* deviceTimestamp */ 0, 1, &pointerProperties,
-                                             &pointerCoords, mXPrecision, mYPrecision, downTime,
-                                             /* videoFrames */ {});
-                getListener()->notifyMotion(&releaseArgs);
-            }
-        }
-
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
-                              displayId, policyFlags, motionEventAction, 0, 0, metaState,
-                              currentButtonState, MotionClassification::NONE,
-                              AMOTION_EVENT_EDGE_FLAG_NONE,
-                              /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-                              mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
-        getListener()->notifyMotion(&args);
-
-        if (buttonsPressed) {
-            BitSet32 pressed(buttonsPressed);
-            while (!pressed.isEmpty()) {
-                int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
-                buttonState |= actionButton;
-                NotifyMotionArgs pressArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
-                                           mSource, displayId, policyFlags,
-                                           AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
-                                           metaState, buttonState, MotionClassification::NONE,
-                                           AMOTION_EVENT_EDGE_FLAG_NONE,
-                                           /* deviceTimestamp */ 0, 1, &pointerProperties,
-                                           &pointerCoords, mXPrecision, mYPrecision, downTime,
-                                           /* videoFrames */ {});
-                getListener()->notifyMotion(&pressArgs);
-            }
-        }
-
-        ALOG_ASSERT(buttonState == currentButtonState);
-
-        // Send hover move after UP to tell the application that the mouse is hovering now.
-        if (motionEventAction == AMOTION_EVENT_ACTION_UP && (mSource == AINPUT_SOURCE_MOUSE)) {
-            NotifyMotionArgs hoverArgs(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
-                                       displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
-                                       0, metaState, currentButtonState, MotionClassification::NONE,
-                                       AMOTION_EVENT_EDGE_FLAG_NONE,
-                                       /* deviceTimestamp */ 0, 1, &pointerProperties,
-                                       &pointerCoords, mXPrecision, mYPrecision, downTime,
-                                       /* videoFrames */ {});
-            getListener()->notifyMotion(&hoverArgs);
-        }
-
-        // Send scroll events.
-        if (scrolled) {
-            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
-            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
-
-            NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
-                                        mSource, displayId, policyFlags,
-                                        AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
-                                        currentButtonState, MotionClassification::NONE,
-                                        AMOTION_EVENT_EDGE_FLAG_NONE,
-                                        /* deviceTimestamp */ 0, 1, &pointerProperties,
-                                        &pointerCoords, mXPrecision, mYPrecision, downTime,
-                                        /* videoFrames */ {});
-            getListener()->notifyMotion(&scrollArgs);
-        }
-    }
-
-    // Synthesize key up from buttons if needed.
-    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
-                         displayId, policyFlags, lastButtonState, currentButtonState);
-
-    mCursorMotionAccumulator.finishSync();
-    mCursorScrollAccumulator.finishSync();
-}
-
-int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-    if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
-        return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
-    } else {
-        return AKEY_STATE_UNKNOWN;
-    }
-}
-
-void CursorInputMapper::fadePointer() {
-    if (mPointerController != nullptr) {
-        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
-    }
-}
-
-std::optional<int32_t> CursorInputMapper::getAssociatedDisplay() {
-    if (mParameters.hasAssociatedDisplay) {
-        if (mParameters.mode == Parameters::MODE_POINTER) {
-            return std::make_optional(mPointerController->getDisplayId());
-        } else {
-            // If the device is orientationAware and not a mouse,
-            // it expects to dispatch events to any display
-            return std::make_optional(ADISPLAY_ID_NONE);
-        }
-    }
-    return std::nullopt;
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h
deleted file mode 100644
index eb2ad54..0000000
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_CURSOR_INPUT_MAPPER_H
-#define _UI_INPUTREADER_CURSOR_INPUT_MAPPER_H
-
-#include "CursorButtonAccumulator.h"
-#include "CursorScrollAccumulator.h"
-#include "InputMapper.h"
-
-#include <PointerControllerInterface.h>
-#include <input/VelocityControl.h>
-
-namespace android {
-
-class VelocityControl;
-class PointerControllerInterface;
-
-class CursorButtonAccumulator;
-class CursorScrollAccumulator;
-
-/* Keeps track of cursor movements. */
-class CursorMotionAccumulator {
-public:
-    CursorMotionAccumulator();
-    void reset(InputDevice* device);
-
-    void process(const RawEvent* rawEvent);
-    void finishSync();
-
-    inline int32_t getRelativeX() const { return mRelX; }
-    inline int32_t getRelativeY() const { return mRelY; }
-
-private:
-    int32_t mRelX;
-    int32_t mRelY;
-
-    void clearRelativeAxes();
-};
-
-class CursorInputMapper : public InputMapper {
-public:
-    explicit CursorInputMapper(InputDevice* device);
-    virtual ~CursorInputMapper();
-
-    virtual uint32_t getSources();
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void dump(std::string& dump);
-    virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
-    virtual void reset(nsecs_t when);
-    virtual void process(const RawEvent* rawEvent);
-
-    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-
-    virtual void fadePointer();
-
-    virtual std::optional<int32_t> getAssociatedDisplay();
-
-private:
-    // Amount that trackball needs to move in order to generate a key event.
-    static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6;
-
-    // Immutable configuration parameters.
-    struct Parameters {
-        enum Mode {
-            MODE_POINTER,
-            MODE_POINTER_RELATIVE,
-            MODE_NAVIGATION,
-        };
-
-        Mode mode;
-        bool hasAssociatedDisplay;
-        bool orientationAware;
-    } mParameters;
-
-    CursorButtonAccumulator mCursorButtonAccumulator;
-    CursorMotionAccumulator mCursorMotionAccumulator;
-    CursorScrollAccumulator mCursorScrollAccumulator;
-
-    int32_t mSource;
-    float mXScale;
-    float mYScale;
-    float mXPrecision;
-    float mYPrecision;
-
-    float mVWheelScale;
-    float mHWheelScale;
-
-    // Velocity controls for mouse pointer and wheel movements.
-    // The controls for X and Y wheel movements are separate to keep them decoupled.
-    VelocityControl mPointerVelocityControl;
-    VelocityControl mWheelXVelocityControl;
-    VelocityControl mWheelYVelocityControl;
-
-    int32_t mOrientation;
-
-    sp<PointerControllerInterface> mPointerController;
-
-    int32_t mButtonState;
-    nsecs_t mDownTime;
-
-    void configureParameters();
-    void dumpParameters(std::string& dump);
-
-    void sync(nsecs_t when);
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_CURSOR_INPUT_MAPPER_H
\ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
deleted file mode 100644
index 9aa0770..0000000
--- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Macros.h"
-
-#include "ExternalStylusInputMapper.h"
-
-#include "SingleTouchMotionAccumulator.h"
-#include "TouchButtonAccumulator.h"
-
-namespace android {
-
-ExternalStylusInputMapper::ExternalStylusInputMapper(InputDevice* device) : InputMapper(device) {}
-
-uint32_t ExternalStylusInputMapper::getSources() {
-    return AINPUT_SOURCE_STYLUS;
-}
-
-void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    InputMapper::populateDeviceInfo(info);
-    info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS, 0.0f, 1.0f, 0.0f, 0.0f,
-                         0.0f);
-}
-
-void ExternalStylusInputMapper::dump(std::string& dump) {
-    dump += INDENT2 "External Stylus Input Mapper:\n";
-    dump += INDENT3 "Raw Stylus Axes:\n";
-    dumpRawAbsoluteAxisInfo(dump, mRawPressureAxis, "Pressure");
-    dump += INDENT3 "Stylus State:\n";
-    dumpStylusState(dump, mStylusState);
-}
-
-void ExternalStylusInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
-                                          uint32_t changes) {
-    getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPressureAxis);
-    mTouchButtonAccumulator.configure(getDevice());
-}
-
-void ExternalStylusInputMapper::reset(nsecs_t when) {
-    InputDevice* device = getDevice();
-    mSingleTouchMotionAccumulator.reset(device);
-    mTouchButtonAccumulator.reset(device);
-    InputMapper::reset(when);
-}
-
-void ExternalStylusInputMapper::process(const RawEvent* rawEvent) {
-    mSingleTouchMotionAccumulator.process(rawEvent);
-    mTouchButtonAccumulator.process(rawEvent);
-
-    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
-        sync(rawEvent->when);
-    }
-}
-
-void ExternalStylusInputMapper::sync(nsecs_t when) {
-    mStylusState.clear();
-
-    mStylusState.when = when;
-
-    mStylusState.toolType = mTouchButtonAccumulator.getToolType();
-    if (mStylusState.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
-        mStylusState.toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
-    }
-
-    int32_t pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
-    if (mRawPressureAxis.valid) {
-        mStylusState.pressure = float(pressure) / mRawPressureAxis.maxValue;
-    } else if (mTouchButtonAccumulator.isToolActive()) {
-        mStylusState.pressure = 1.0f;
-    } else {
-        mStylusState.pressure = 0.0f;
-    }
-
-    mStylusState.buttons = mTouchButtonAccumulator.getButtonState();
-
-    mContext->dispatchExternalStylusState(mStylusState);
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
deleted file mode 100644
index 9764fbb..0000000
--- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_EXTERNAL_STYLUS_INPUT_MAPPER_H
-#define _UI_INPUTREADER_EXTERNAL_STYLUS_INPUT_MAPPER_H
-
-#include "InputMapper.h"
-
-#include "SingleTouchMotionAccumulator.h"
-#include "StylusState.h"
-#include "TouchButtonAccumulator.h"
-
-namespace android {
-
-class ExternalStylusInputMapper : public InputMapper {
-public:
-    explicit ExternalStylusInputMapper(InputDevice* device);
-    virtual ~ExternalStylusInputMapper() = default;
-
-    virtual uint32_t getSources();
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void dump(std::string& dump);
-    virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
-    virtual void reset(nsecs_t when);
-    virtual void process(const RawEvent* rawEvent);
-    virtual void sync(nsecs_t when);
-
-private:
-    SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
-    RawAbsoluteAxisInfo mRawPressureAxis;
-    TouchButtonAccumulator mTouchButtonAccumulator;
-
-    StylusState mStylusState;
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_EXTERNAL_STYLUS_INPUT_MAPPER_H
\ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/InputMapper.cpp b/services/inputflinger/reader/mapper/InputMapper.cpp
deleted file mode 100644
index d941528..0000000
--- a/services/inputflinger/reader/mapper/InputMapper.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Macros.h"
-
-#include "InputMapper.h"
-
-#include "InputDevice.h"
-
-namespace android {
-
-InputMapper::InputMapper(InputDevice* device) : mDevice(device), mContext(device->getContext()) {}
-
-InputMapper::~InputMapper() {}
-
-void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    info->addSource(getSources());
-}
-
-void InputMapper::dump(std::string& dump) {}
-
-void InputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
-                            uint32_t changes) {}
-
-void InputMapper::reset(nsecs_t when) {}
-
-void InputMapper::timeoutExpired(nsecs_t when) {}
-
-int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
-    return AKEY_STATE_UNKNOWN;
-}
-
-bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-                                        const int32_t* keyCodes, uint8_t* outFlags) {
-    return false;
-}
-
-void InputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
-                          int32_t token) {}
-
-void InputMapper::cancelVibrate(int32_t token) {}
-
-void InputMapper::cancelTouch(nsecs_t when) {}
-
-int32_t InputMapper::getMetaState() {
-    return 0;
-}
-
-void InputMapper::updateMetaState(int32_t keyCode) {}
-
-void InputMapper::updateExternalStylusState(const StylusState& state) {}
-
-void InputMapper::fadePointer() {}
-
-status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) {
-    return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo);
-}
-
-void InputMapper::bumpGeneration() {
-    mDevice->bumpGeneration();
-}
-
-void InputMapper::dumpRawAbsoluteAxisInfo(std::string& dump, const RawAbsoluteAxisInfo& axis,
-                                          const char* name) {
-    if (axis.valid) {
-        dump += StringPrintf(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n", name,
-                             axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution);
-    } else {
-        dump += StringPrintf(INDENT4 "%s: unknown range\n", name);
-    }
-}
-
-void InputMapper::dumpStylusState(std::string& dump, const StylusState& state) {
-    dump += StringPrintf(INDENT4 "When: %" PRId64 "\n", state.when);
-    dump += StringPrintf(INDENT4 "Pressure: %f\n", state.pressure);
-    dump += StringPrintf(INDENT4 "Button State: 0x%08x\n", state.buttons);
-    dump += StringPrintf(INDENT4 "Tool Type: %" PRId32 "\n", state.toolType);
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
deleted file mode 100644
index cfd207c..0000000
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_INPUT_MAPPER_H
-#define _UI_INPUTREADER_INPUT_MAPPER_H
-
-#include "EventHub.h"
-#include "InputDevice.h"
-#include "InputListener.h"
-#include "InputReaderContext.h"
-#include "StylusState.h"
-
-namespace android {
-
-/* An input mapper transforms raw input events into cooked event data.
- * A single input device can have multiple associated input mappers in order to interpret
- * different classes of events.
- *
- * InputMapper lifecycle:
- * - create
- * - configure with 0 changes
- * - reset
- * - process, process, process (may occasionally reconfigure with non-zero changes or reset)
- * - reset
- * - destroy
- */
-class InputMapper {
-public:
-    explicit InputMapper(InputDevice* device);
-    virtual ~InputMapper();
-
-    inline InputDevice* getDevice() { return mDevice; }
-    inline int32_t getDeviceId() { return mDevice->getId(); }
-    inline const std::string getDeviceName() { return mDevice->getName(); }
-    inline InputReaderContext* getContext() { return mContext; }
-    inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); }
-    inline InputListenerInterface* getListener() { return mContext->getListener(); }
-    inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
-
-    virtual uint32_t getSources() = 0;
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void dump(std::string& dump);
-    virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
-    virtual void reset(nsecs_t when);
-    virtual void process(const RawEvent* rawEvent) = 0;
-    virtual void timeoutExpired(nsecs_t when);
-
-    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
-    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-    virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
-    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-                                       const int32_t* keyCodes, uint8_t* outFlags);
-    virtual void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, int32_t token);
-    virtual void cancelVibrate(int32_t token);
-    virtual void cancelTouch(nsecs_t when);
-
-    virtual int32_t getMetaState();
-    virtual void updateMetaState(int32_t keyCode);
-
-    virtual void updateExternalStylusState(const StylusState& state);
-
-    virtual void fadePointer();
-    virtual std::optional<int32_t> getAssociatedDisplay() { return std::nullopt; }
-
-protected:
-    InputDevice* mDevice;
-    InputReaderContext* mContext;
-
-    status_t getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo);
-    void bumpGeneration();
-
-    static void dumpRawAbsoluteAxisInfo(std::string& dump, const RawAbsoluteAxisInfo& axis,
-                                        const char* name);
-    static void dumpStylusState(std::string& dump, const StylusState& state);
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_INPUT_MAPPER_H
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
deleted file mode 100644
index b493e83..0000000
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Macros.h"
-
-#include "JoystickInputMapper.h"
-
-namespace android {
-
-JoystickInputMapper::JoystickInputMapper(InputDevice* device) : InputMapper(device) {}
-
-JoystickInputMapper::~JoystickInputMapper() {}
-
-uint32_t JoystickInputMapper::getSources() {
-    return AINPUT_SOURCE_JOYSTICK;
-}
-
-void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    InputMapper::populateDeviceInfo(info);
-
-    for (size_t i = 0; i < mAxes.size(); i++) {
-        const Axis& axis = mAxes.valueAt(i);
-        addMotionRange(axis.axisInfo.axis, axis, info);
-
-        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
-            addMotionRange(axis.axisInfo.highAxis, axis, info);
-        }
-    }
-}
-
-void JoystickInputMapper::addMotionRange(int32_t axisId, const Axis& axis, InputDeviceInfo* info) {
-    info->addMotionRange(axisId, AINPUT_SOURCE_JOYSTICK, axis.min, axis.max, axis.flat, axis.fuzz,
-                         axis.resolution);
-    /* In order to ease the transition for developers from using the old axes
-     * to the newer, more semantically correct axes, we'll continue to register
-     * the old axes as duplicates of their corresponding new ones.  */
-    int32_t compatAxis = getCompatAxis(axisId);
-    if (compatAxis >= 0) {
-        info->addMotionRange(compatAxis, AINPUT_SOURCE_JOYSTICK, axis.min, axis.max, axis.flat,
-                             axis.fuzz, axis.resolution);
-    }
-}
-
-/* A mapping from axes the joystick actually has to the axes that should be
- * artificially created for compatibility purposes.
- * Returns -1 if no compatibility axis is needed. */
-int32_t JoystickInputMapper::getCompatAxis(int32_t axis) {
-    switch (axis) {
-        case AMOTION_EVENT_AXIS_LTRIGGER:
-            return AMOTION_EVENT_AXIS_BRAKE;
-        case AMOTION_EVENT_AXIS_RTRIGGER:
-            return AMOTION_EVENT_AXIS_GAS;
-    }
-    return -1;
-}
-
-void JoystickInputMapper::dump(std::string& dump) {
-    dump += INDENT2 "Joystick Input Mapper:\n";
-
-    dump += INDENT3 "Axes:\n";
-    size_t numAxes = mAxes.size();
-    for (size_t i = 0; i < numAxes; i++) {
-        const Axis& axis = mAxes.valueAt(i);
-        const char* label = getAxisLabel(axis.axisInfo.axis);
-        if (label) {
-            dump += StringPrintf(INDENT4 "%s", label);
-        } else {
-            dump += StringPrintf(INDENT4 "%d", axis.axisInfo.axis);
-        }
-        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
-            label = getAxisLabel(axis.axisInfo.highAxis);
-            if (label) {
-                dump += StringPrintf(" / %s (split at %d)", label, axis.axisInfo.splitValue);
-            } else {
-                dump += StringPrintf(" / %d (split at %d)", axis.axisInfo.highAxis,
-                                     axis.axisInfo.splitValue);
-            }
-        } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
-            dump += " (invert)";
-        }
-
-        dump += StringPrintf(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f, resolution=%0.5f\n",
-                             axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
-        dump += StringPrintf(INDENT4 "  scale=%0.5f, offset=%0.5f, "
-                                     "highScale=%0.5f, highOffset=%0.5f\n",
-                             axis.scale, axis.offset, axis.highScale, axis.highOffset);
-        dump += StringPrintf(INDENT4 "  rawAxis=%d, rawMin=%d, rawMax=%d, "
-                                     "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
-                             mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
-                             axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz,
-                             axis.rawAxisInfo.resolution);
-    }
-}
-
-void JoystickInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
-                                    uint32_t changes) {
-    InputMapper::configure(when, config, changes);
-
-    if (!changes) { // first time only
-        // Collect all axes.
-        for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
-            if (!(getAbsAxisUsage(abs, getDevice()->getClasses()) & INPUT_DEVICE_CLASS_JOYSTICK)) {
-                continue; // axis must be claimed by a different device
-            }
-
-            RawAbsoluteAxisInfo rawAxisInfo;
-            getAbsoluteAxisInfo(abs, &rawAxisInfo);
-            if (rawAxisInfo.valid) {
-                // Map axis.
-                AxisInfo axisInfo;
-                bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
-                if (!explicitlyMapped) {
-                    // Axis is not explicitly mapped, will choose a generic axis later.
-                    axisInfo.mode = AxisInfo::MODE_NORMAL;
-                    axisInfo.axis = -1;
-                }
-
-                // Apply flat override.
-                int32_t rawFlat =
-                        axisInfo.flatOverride < 0 ? rawAxisInfo.flat : axisInfo.flatOverride;
-
-                // Calculate scaling factors and limits.
-                Axis axis;
-                if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
-                    float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
-                    float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
-                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, scale, 0.0f, highScale,
-                                    0.0f, 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
-                                    rawAxisInfo.resolution * scale);
-                } else if (isCenteredAxis(axisInfo.axis)) {
-                    float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
-                    float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
-                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, scale, offset, scale,
-                                    offset, -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
-                                    rawAxisInfo.resolution * scale);
-                } else {
-                    float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
-                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, scale, 0.0f, scale,
-                                    0.0f, 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
-                                    rawAxisInfo.resolution * scale);
-                }
-
-                // To eliminate noise while the joystick is at rest, filter out small variations
-                // in axis values up front.
-                axis.filter = axis.fuzz ? axis.fuzz : axis.flat * 0.25f;
-
-                mAxes.add(abs, axis);
-            }
-        }
-
-        // If there are too many axes, start dropping them.
-        // Prefer to keep explicitly mapped axes.
-        if (mAxes.size() > PointerCoords::MAX_AXES) {
-            ALOGI("Joystick '%s' has %zu axes but the framework only supports a maximum of %d.",
-                  getDeviceName().c_str(), mAxes.size(), PointerCoords::MAX_AXES);
-            pruneAxes(true);
-            pruneAxes(false);
-        }
-
-        // Assign generic axis ids to remaining axes.
-        int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
-        size_t numAxes = mAxes.size();
-        for (size_t i = 0; i < numAxes; i++) {
-            Axis& axis = mAxes.editValueAt(i);
-            if (axis.axisInfo.axis < 0) {
-                while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16 &&
-                       haveAxis(nextGenericAxisId)) {
-                    nextGenericAxisId += 1;
-                }
-
-                if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
-                    axis.axisInfo.axis = nextGenericAxisId;
-                    nextGenericAxisId += 1;
-                } else {
-                    ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
-                          "have already been assigned to other axes.",
-                          getDeviceName().c_str(), mAxes.keyAt(i));
-                    mAxes.removeItemsAt(i--);
-                    numAxes -= 1;
-                }
-            }
-        }
-    }
-}
-
-bool JoystickInputMapper::haveAxis(int32_t axisId) {
-    size_t numAxes = mAxes.size();
-    for (size_t i = 0; i < numAxes; i++) {
-        const Axis& axis = mAxes.valueAt(i);
-        if (axis.axisInfo.axis == axisId ||
-            (axis.axisInfo.mode == AxisInfo::MODE_SPLIT && axis.axisInfo.highAxis == axisId)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
-    size_t i = mAxes.size();
-    while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
-        if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
-            continue;
-        }
-        ALOGI("Discarding joystick '%s' axis %d because there are too many axes.",
-              getDeviceName().c_str(), mAxes.keyAt(i));
-        mAxes.removeItemsAt(i);
-    }
-}
-
-bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
-    switch (axis) {
-        case AMOTION_EVENT_AXIS_X:
-        case AMOTION_EVENT_AXIS_Y:
-        case AMOTION_EVENT_AXIS_Z:
-        case AMOTION_EVENT_AXIS_RX:
-        case AMOTION_EVENT_AXIS_RY:
-        case AMOTION_EVENT_AXIS_RZ:
-        case AMOTION_EVENT_AXIS_HAT_X:
-        case AMOTION_EVENT_AXIS_HAT_Y:
-        case AMOTION_EVENT_AXIS_ORIENTATION:
-        case AMOTION_EVENT_AXIS_RUDDER:
-        case AMOTION_EVENT_AXIS_WHEEL:
-            return true;
-        default:
-            return false;
-    }
-}
-
-void JoystickInputMapper::reset(nsecs_t when) {
-    // Recenter all axes.
-    size_t numAxes = mAxes.size();
-    for (size_t i = 0; i < numAxes; i++) {
-        Axis& axis = mAxes.editValueAt(i);
-        axis.resetValue();
-    }
-
-    InputMapper::reset(when);
-}
-
-void JoystickInputMapper::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-        case EV_ABS: {
-            ssize_t index = mAxes.indexOfKey(rawEvent->code);
-            if (index >= 0) {
-                Axis& axis = mAxes.editValueAt(index);
-                float newValue, highNewValue;
-                switch (axis.axisInfo.mode) {
-                    case AxisInfo::MODE_INVERT:
-                        newValue = (axis.rawAxisInfo.maxValue - rawEvent->value) * axis.scale +
-                                axis.offset;
-                        highNewValue = 0.0f;
-                        break;
-                    case AxisInfo::MODE_SPLIT:
-                        if (rawEvent->value < axis.axisInfo.splitValue) {
-                            newValue = (axis.axisInfo.splitValue - rawEvent->value) * axis.scale +
-                                    axis.offset;
-                            highNewValue = 0.0f;
-                        } else if (rawEvent->value > axis.axisInfo.splitValue) {
-                            newValue = 0.0f;
-                            highNewValue =
-                                    (rawEvent->value - axis.axisInfo.splitValue) * axis.highScale +
-                                    axis.highOffset;
-                        } else {
-                            newValue = 0.0f;
-                            highNewValue = 0.0f;
-                        }
-                        break;
-                    default:
-                        newValue = rawEvent->value * axis.scale + axis.offset;
-                        highNewValue = 0.0f;
-                        break;
-                }
-                axis.newValue = newValue;
-                axis.highNewValue = highNewValue;
-            }
-            break;
-        }
-
-        case EV_SYN:
-            switch (rawEvent->code) {
-                case SYN_REPORT:
-                    sync(rawEvent->when, false /*force*/);
-                    break;
-            }
-            break;
-    }
-}
-
-void JoystickInputMapper::sync(nsecs_t when, bool force) {
-    if (!filterAxes(force)) {
-        return;
-    }
-
-    int32_t metaState = mContext->getGlobalMetaState();
-    int32_t buttonState = 0;
-
-    PointerProperties pointerProperties;
-    pointerProperties.clear();
-    pointerProperties.id = 0;
-    pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
-
-    PointerCoords pointerCoords;
-    pointerCoords.clear();
-
-    size_t numAxes = mAxes.size();
-    for (size_t i = 0; i < numAxes; i++) {
-        const Axis& axis = mAxes.valueAt(i);
-        setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.axis, axis.currentValue);
-        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
-            setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.highAxis,
-                                      axis.highCurrentValue);
-        }
-    }
-
-    // Moving a joystick axis should not wake the device because joysticks can
-    // be fairly noisy even when not in use.  On the other hand, pushing a gamepad
-    // button will likely wake the device.
-    // TODO: Use the input device configuration to control this behavior more finely.
-    uint32_t policyFlags = 0;
-
-    NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                          AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE, policyFlags,
-                          AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
-                          MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                          /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, 0, 0, 0,
-                          /* videoFrames */ {});
-    getListener()->notifyMotion(&args);
-}
-
-void JoystickInputMapper::setPointerCoordsAxisValue(PointerCoords* pointerCoords, int32_t axis,
-                                                    float value) {
-    pointerCoords->setAxisValue(axis, value);
-    /* In order to ease the transition for developers from using the old axes
-     * to the newer, more semantically correct axes, we'll continue to produce
-     * values for the old axes as mirrors of the value of their corresponding
-     * new axes. */
-    int32_t compatAxis = getCompatAxis(axis);
-    if (compatAxis >= 0) {
-        pointerCoords->setAxisValue(compatAxis, value);
-    }
-}
-
-bool JoystickInputMapper::filterAxes(bool force) {
-    bool atLeastOneSignificantChange = force;
-    size_t numAxes = mAxes.size();
-    for (size_t i = 0; i < numAxes; i++) {
-        Axis& axis = mAxes.editValueAt(i);
-        if (force ||
-            hasValueChangedSignificantly(axis.filter, axis.newValue, axis.currentValue, axis.min,
-                                         axis.max)) {
-            axis.currentValue = axis.newValue;
-            atLeastOneSignificantChange = true;
-        }
-        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
-            if (force ||
-                hasValueChangedSignificantly(axis.filter, axis.highNewValue, axis.highCurrentValue,
-                                             axis.min, axis.max)) {
-                axis.highCurrentValue = axis.highNewValue;
-                atLeastOneSignificantChange = true;
-            }
-        }
-    }
-    return atLeastOneSignificantChange;
-}
-
-bool JoystickInputMapper::hasValueChangedSignificantly(float filter, float newValue,
-                                                       float currentValue, float min, float max) {
-    if (newValue != currentValue) {
-        // Filter out small changes in value unless the value is converging on the axis
-        // bounds or center point.  This is intended to reduce the amount of information
-        // sent to applications by particularly noisy joysticks (such as PS3).
-        if (fabs(newValue - currentValue) > filter ||
-            hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min) ||
-            hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max) ||
-            hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(float filter, float newValue,
-                                                                   float currentValue,
-                                                                   float thresholdValue) {
-    float newDistance = fabs(newValue - thresholdValue);
-    if (newDistance < filter) {
-        float oldDistance = fabs(currentValue - thresholdValue);
-        if (newDistance < oldDistance) {
-            return true;
-        }
-    }
-    return false;
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.h b/services/inputflinger/reader/mapper/JoystickInputMapper.h
deleted file mode 100644
index 1b071d0..0000000
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_JOYSTICK_INPUT_MAPPER_H
-#define _UI_INPUTREADER_JOYSTICK_INPUT_MAPPER_H
-
-#include "InputMapper.h"
-
-namespace android {
-
-class JoystickInputMapper : public InputMapper {
-public:
-    explicit JoystickInputMapper(InputDevice* device);
-    virtual ~JoystickInputMapper();
-
-    virtual uint32_t getSources();
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void dump(std::string& dump);
-    virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
-    virtual void reset(nsecs_t when);
-    virtual void process(const RawEvent* rawEvent);
-
-private:
-    struct Axis {
-        RawAbsoluteAxisInfo rawAxisInfo;
-        AxisInfo axisInfo;
-
-        bool explicitlyMapped; // true if the axis was explicitly assigned an axis id
-
-        float scale;      // scale factor from raw to normalized values
-        float offset;     // offset to add after scaling for normalization
-        float highScale;  // scale factor from raw to normalized values of high split
-        float highOffset; // offset to add after scaling for normalization of high split
-
-        float min;        // normalized inclusive minimum
-        float max;        // normalized inclusive maximum
-        float flat;       // normalized flat region size
-        float fuzz;       // normalized error tolerance
-        float resolution; // normalized resolution in units/mm
-
-        float filter;           // filter out small variations of this size
-        float currentValue;     // current value
-        float newValue;         // most recent value
-        float highCurrentValue; // current value of high split
-        float highNewValue;     // most recent value of high split
-
-        void initialize(const RawAbsoluteAxisInfo& rawAxisInfo, const AxisInfo& axisInfo,
-                        bool explicitlyMapped, float scale, float offset, float highScale,
-                        float highOffset, float min, float max, float flat, float fuzz,
-                        float resolution) {
-            this->rawAxisInfo = rawAxisInfo;
-            this->axisInfo = axisInfo;
-            this->explicitlyMapped = explicitlyMapped;
-            this->scale = scale;
-            this->offset = offset;
-            this->highScale = highScale;
-            this->highOffset = highOffset;
-            this->min = min;
-            this->max = max;
-            this->flat = flat;
-            this->fuzz = fuzz;
-            this->resolution = resolution;
-            this->filter = 0;
-            resetValue();
-        }
-
-        void resetValue() {
-            this->currentValue = 0;
-            this->newValue = 0;
-            this->highCurrentValue = 0;
-            this->highNewValue = 0;
-        }
-    };
-
-    // Axes indexed by raw ABS_* axis index.
-    KeyedVector<int32_t, Axis> mAxes;
-
-    void sync(nsecs_t when, bool force);
-
-    bool haveAxis(int32_t axisId);
-    void pruneAxes(bool ignoreExplicitlyMappedAxes);
-    bool filterAxes(bool force);
-
-    static bool hasValueChangedSignificantly(float filter, float newValue, float currentValue,
-                                             float min, float max);
-    static bool hasMovedNearerToValueWithinFilteredRange(float filter, float newValue,
-                                                         float currentValue, float thresholdValue);
-
-    static bool isCenteredAxis(int32_t axis);
-    static int32_t getCompatAxis(int32_t axis);
-
-    static void addMotionRange(int32_t axisId, const Axis& axis, InputDeviceInfo* info);
-    static void setPointerCoordsAxisValue(PointerCoords* pointerCoords, int32_t axis, float value);
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_JOYSTICK_INPUT_MAPPER_H
\ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
deleted file mode 100644
index 0e91c0e..0000000
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Macros.h"
-
-#include "KeyboardInputMapper.h"
-
-namespace android {
-
-// --- Static Definitions ---
-
-static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
-                                           const int32_t map[][4], size_t mapSize) {
-    if (orientation != DISPLAY_ORIENTATION_0) {
-        for (size_t i = 0; i < mapSize; i++) {
-            if (value == map[i][0]) {
-                return map[i][orientation];
-            }
-        }
-    }
-    return value;
-}
-
-static const int32_t keyCodeRotationMap[][4] = {
-        // key codes enumerated counter-clockwise with the original (unrotated) key first
-        // no rotation,        90 degree rotation,  180 degree rotation, 270 degree rotation
-        {AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT},
-        {AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN},
-        {AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT},
-        {AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP},
-        {AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT,
-         AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT},
-        {AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP,
-         AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN},
-        {AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT,
-         AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT},
-        {AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN,
-         AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP},
-};
-
-static const size_t keyCodeRotationMapSize =
-        sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
-
-static int32_t rotateStemKey(int32_t value, int32_t orientation, const int32_t map[][2],
-                             size_t mapSize) {
-    if (orientation == DISPLAY_ORIENTATION_180) {
-        for (size_t i = 0; i < mapSize; i++) {
-            if (value == map[i][0]) {
-                return map[i][1];
-            }
-        }
-    }
-    return value;
-}
-
-// The mapping can be defined using input device configuration properties keyboard.rotated.stem_X
-static int32_t stemKeyRotationMap[][2] = {
-        // key codes enumerated with the original (unrotated) key first
-        // no rotation,           180 degree rotation
-        {AKEYCODE_STEM_PRIMARY, AKEYCODE_STEM_PRIMARY},
-        {AKEYCODE_STEM_1, AKEYCODE_STEM_1},
-        {AKEYCODE_STEM_2, AKEYCODE_STEM_2},
-        {AKEYCODE_STEM_3, AKEYCODE_STEM_3},
-};
-
-static const size_t stemKeyRotationMapSize =
-        sizeof(stemKeyRotationMap) / sizeof(stemKeyRotationMap[0]);
-
-static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
-    keyCode = rotateStemKey(keyCode, orientation, stemKeyRotationMap, stemKeyRotationMapSize);
-    return rotateValueUsingRotationMap(keyCode, orientation, keyCodeRotationMap,
-                                       keyCodeRotationMapSize);
-}
-
-// --- KeyboardInputMapper ---
-
-KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, uint32_t source, int32_t keyboardType)
-      : InputMapper(device), mSource(source), mKeyboardType(keyboardType) {}
-
-KeyboardInputMapper::~KeyboardInputMapper() {}
-
-uint32_t KeyboardInputMapper::getSources() {
-    return mSource;
-}
-
-int32_t KeyboardInputMapper::getOrientation() {
-    if (mViewport) {
-        return mViewport->orientation;
-    }
-    return DISPLAY_ORIENTATION_0;
-}
-
-int32_t KeyboardInputMapper::getDisplayId() {
-    if (mViewport) {
-        return mViewport->displayId;
-    }
-    return ADISPLAY_ID_NONE;
-}
-
-void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    InputMapper::populateDeviceInfo(info);
-
-    info->setKeyboardType(mKeyboardType);
-    info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId()));
-}
-
-void KeyboardInputMapper::dump(std::string& dump) {
-    dump += INDENT2 "Keyboard Input Mapper:\n";
-    dumpParameters(dump);
-    dump += StringPrintf(INDENT3 "KeyboardType: %d\n", mKeyboardType);
-    dump += StringPrintf(INDENT3 "Orientation: %d\n", getOrientation());
-    dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
-    dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState);
-    dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
-}
-
-void KeyboardInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
-                                    uint32_t changes) {
-    InputMapper::configure(when, config, changes);
-
-    if (!changes) { // first time only
-        // Configure basic parameters.
-        configureParameters();
-    }
-
-    if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
-        if (mParameters.orientationAware) {
-            mViewport = config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
-        }
-    }
-}
-
-static void mapStemKey(int32_t keyCode, const PropertyMap& config, char const* property) {
-    int32_t mapped = 0;
-    if (config.tryGetProperty(String8(property), mapped) && mapped > 0) {
-        for (size_t i = 0; i < stemKeyRotationMapSize; i++) {
-            if (stemKeyRotationMap[i][0] == keyCode) {
-                stemKeyRotationMap[i][1] = mapped;
-                return;
-            }
-        }
-    }
-}
-
-void KeyboardInputMapper::configureParameters() {
-    mParameters.orientationAware = false;
-    const PropertyMap& config = getDevice()->getConfiguration();
-    config.tryGetProperty(String8("keyboard.orientationAware"), mParameters.orientationAware);
-
-    if (mParameters.orientationAware) {
-        mapStemKey(AKEYCODE_STEM_PRIMARY, config, "keyboard.rotated.stem_primary");
-        mapStemKey(AKEYCODE_STEM_1, config, "keyboard.rotated.stem_1");
-        mapStemKey(AKEYCODE_STEM_2, config, "keyboard.rotated.stem_2");
-        mapStemKey(AKEYCODE_STEM_3, config, "keyboard.rotated.stem_3");
-    }
-
-    mParameters.handlesKeyRepeat = false;
-    config.tryGetProperty(String8("keyboard.handlesKeyRepeat"), mParameters.handlesKeyRepeat);
-}
-
-void KeyboardInputMapper::dumpParameters(std::string& dump) {
-    dump += INDENT3 "Parameters:\n";
-    dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
-    dump += StringPrintf(INDENT4 "HandlesKeyRepeat: %s\n", toString(mParameters.handlesKeyRepeat));
-}
-
-void KeyboardInputMapper::reset(nsecs_t when) {
-    mMetaState = AMETA_NONE;
-    mDownTime = 0;
-    mKeyDowns.clear();
-    mCurrentHidUsage = 0;
-
-    resetLedState();
-
-    InputMapper::reset(when);
-}
-
-void KeyboardInputMapper::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-        case EV_KEY: {
-            int32_t scanCode = rawEvent->code;
-            int32_t usageCode = mCurrentHidUsage;
-            mCurrentHidUsage = 0;
-
-            if (isKeyboardOrGamepadKey(scanCode)) {
-                processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);
-            }
-            break;
-        }
-        case EV_MSC: {
-            if (rawEvent->code == MSC_SCAN) {
-                mCurrentHidUsage = rawEvent->value;
-            }
-            break;
-        }
-        case EV_SYN: {
-            if (rawEvent->code == SYN_REPORT) {
-                mCurrentHidUsage = 0;
-            }
-        }
-    }
-}
-
-bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
-    return scanCode < BTN_MOUSE || scanCode >= KEY_OK ||
-            (scanCode >= BTN_MISC && scanCode < BTN_MOUSE) ||
-            (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
-}
-
-bool KeyboardInputMapper::isMediaKey(int32_t keyCode) {
-    switch (keyCode) {
-        case AKEYCODE_MEDIA_PLAY:
-        case AKEYCODE_MEDIA_PAUSE:
-        case AKEYCODE_MEDIA_PLAY_PAUSE:
-        case AKEYCODE_MUTE:
-        case AKEYCODE_HEADSETHOOK:
-        case AKEYCODE_MEDIA_STOP:
-        case AKEYCODE_MEDIA_NEXT:
-        case AKEYCODE_MEDIA_PREVIOUS:
-        case AKEYCODE_MEDIA_REWIND:
-        case AKEYCODE_MEDIA_RECORD:
-        case AKEYCODE_MEDIA_FAST_FORWARD:
-        case AKEYCODE_MEDIA_SKIP_FORWARD:
-        case AKEYCODE_MEDIA_SKIP_BACKWARD:
-        case AKEYCODE_MEDIA_STEP_FORWARD:
-        case AKEYCODE_MEDIA_STEP_BACKWARD:
-        case AKEYCODE_MEDIA_AUDIO_TRACK:
-        case AKEYCODE_VOLUME_UP:
-        case AKEYCODE_VOLUME_DOWN:
-        case AKEYCODE_VOLUME_MUTE:
-        case AKEYCODE_TV_AUDIO_DESCRIPTION:
-        case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP:
-        case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN:
-            return true;
-    }
-    return false;
-}
-
-void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode) {
-    int32_t keyCode;
-    int32_t keyMetaState;
-    uint32_t policyFlags;
-
-    if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, mMetaState, &keyCode,
-                              &keyMetaState, &policyFlags)) {
-        keyCode = AKEYCODE_UNKNOWN;
-        keyMetaState = mMetaState;
-        policyFlags = 0;
-    }
-
-    if (down) {
-        // Rotate key codes according to orientation if needed.
-        if (mParameters.orientationAware) {
-            keyCode = rotateKeyCode(keyCode, getOrientation());
-        }
-
-        // Add key down.
-        ssize_t keyDownIndex = findKeyDown(scanCode);
-        if (keyDownIndex >= 0) {
-            // key repeat, be sure to use same keycode as before in case of rotation
-            keyCode = mKeyDowns[keyDownIndex].keyCode;
-        } else {
-            // key down
-            if ((policyFlags & POLICY_FLAG_VIRTUAL) &&
-                mContext->shouldDropVirtualKey(when, getDevice(), keyCode, scanCode)) {
-                return;
-            }
-            if (policyFlags & POLICY_FLAG_GESTURE) {
-                mDevice->cancelTouch(when);
-            }
-
-            KeyDown keyDown;
-            keyDown.keyCode = keyCode;
-            keyDown.scanCode = scanCode;
-            mKeyDowns.push_back(keyDown);
-        }
-
-        mDownTime = when;
-    } else {
-        // Remove key down.
-        ssize_t keyDownIndex = findKeyDown(scanCode);
-        if (keyDownIndex >= 0) {
-            // key up, be sure to use same keycode as before in case of rotation
-            keyCode = mKeyDowns[keyDownIndex].keyCode;
-            mKeyDowns.erase(mKeyDowns.begin() + (size_t)keyDownIndex);
-        } else {
-            // key was not actually down
-            ALOGI("Dropping key up from device %s because the key was not down.  "
-                  "keyCode=%d, scanCode=%d",
-                  getDeviceName().c_str(), keyCode, scanCode);
-            return;
-        }
-    }
-
-    if (updateMetaStateIfNeeded(keyCode, down)) {
-        // If global meta state changed send it along with the key.
-        // If it has not changed then we'll use what keymap gave us,
-        // since key replacement logic might temporarily reset a few
-        // meta bits for given key.
-        keyMetaState = mMetaState;
-    }
-
-    nsecs_t downTime = mDownTime;
-
-    // Key down on external an keyboard should wake the device.
-    // We don't do this for internal keyboards to prevent them from waking up in your pocket.
-    // For internal keyboards, the key layout file should specify the policy flags for
-    // each wake key individually.
-    // TODO: Use the input device configuration to control this behavior more finely.
-    if (down && getDevice()->isExternal() && !isMediaKey(keyCode)) {
-        policyFlags |= POLICY_FLAG_WAKE;
-    }
-
-    if (mParameters.handlesKeyRepeat) {
-        policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
-    }
-
-    NotifyKeyArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource, getDisplayId(),
-                       policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
-                       AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
-    getListener()->notifyKey(&args);
-}
-
-ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) {
-    size_t n = mKeyDowns.size();
-    for (size_t i = 0; i < n; i++) {
-        if (mKeyDowns[i].scanCode == scanCode) {
-            return i;
-        }
-    }
-    return -1;
-}
-
-int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
-    return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
-}
-
-int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-    return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
-}
-
-bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-                                                const int32_t* keyCodes, uint8_t* outFlags) {
-    return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
-}
-
-int32_t KeyboardInputMapper::getMetaState() {
-    return mMetaState;
-}
-
-void KeyboardInputMapper::updateMetaState(int32_t keyCode) {
-    updateMetaStateIfNeeded(keyCode, false);
-}
-
-bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
-    int32_t oldMetaState = mMetaState;
-    int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
-    bool metaStateChanged = oldMetaState != newMetaState;
-    if (metaStateChanged) {
-        mMetaState = newMetaState;
-        updateLedState(false);
-
-        getContext()->updateGlobalMetaState();
-    }
-
-    return metaStateChanged;
-}
-
-void KeyboardInputMapper::resetLedState() {
-    initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
-    initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
-    initializeLedState(mScrollLockLedState, ALED_SCROLL_LOCK);
-
-    updateLedState(true);
-}
-
-void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
-    ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
-    ledState.on = false;
-}
-
-void KeyboardInputMapper::updateLedState(bool reset) {
-    updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK, AMETA_CAPS_LOCK_ON, reset);
-    updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK, AMETA_NUM_LOCK_ON, reset);
-    updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, reset);
-}
-
-void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState, int32_t led,
-                                                    int32_t modifier, bool reset) {
-    if (ledState.avail) {
-        bool desiredState = (mMetaState & modifier) != 0;
-        if (reset || ledState.on != desiredState) {
-            getEventHub()->setLedState(getDeviceId(), led, desiredState);
-            ledState.on = desiredState;
-        }
-    }
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
deleted file mode 100644
index 7a68fc3..0000000
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_KEYBOARD_INPUT_MAPPER_H
-#define _UI_INPUTREADER_KEYBOARD_INPUT_MAPPER_H
-
-#include "InputMapper.h"
-
-namespace android {
-
-class KeyboardInputMapper : public InputMapper {
-public:
-    KeyboardInputMapper(InputDevice* device, uint32_t source, int32_t keyboardType);
-    virtual ~KeyboardInputMapper();
-
-    virtual uint32_t getSources();
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void dump(std::string& dump);
-    virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
-    virtual void reset(nsecs_t when);
-    virtual void process(const RawEvent* rawEvent);
-
-    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
-    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-                                       const int32_t* keyCodes, uint8_t* outFlags);
-
-    virtual int32_t getMetaState();
-    virtual void updateMetaState(int32_t keyCode);
-
-private:
-    // The current viewport.
-    std::optional<DisplayViewport> mViewport;
-
-    struct KeyDown {
-        int32_t keyCode;
-        int32_t scanCode;
-    };
-
-    uint32_t mSource;
-    int32_t mKeyboardType;
-
-    std::vector<KeyDown> mKeyDowns; // keys that are down
-    int32_t mMetaState;
-    nsecs_t mDownTime; // time of most recent key down
-
-    int32_t mCurrentHidUsage; // most recent HID usage seen this packet, or 0 if none
-
-    struct LedState {
-        bool avail; // led is available
-        bool on;    // we think the led is currently on
-    };
-    LedState mCapsLockLedState;
-    LedState mNumLockLedState;
-    LedState mScrollLockLedState;
-
-    // Immutable configuration parameters.
-    struct Parameters {
-        bool orientationAware;
-        bool handlesKeyRepeat;
-    } mParameters;
-
-    void configureParameters();
-    void dumpParameters(std::string& dump);
-
-    int32_t getOrientation();
-    int32_t getDisplayId();
-
-    bool isKeyboardOrGamepadKey(int32_t scanCode);
-    bool isMediaKey(int32_t keyCode);
-
-    void processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode);
-
-    bool updateMetaStateIfNeeded(int32_t keyCode, bool down);
-
-    ssize_t findKeyDown(int32_t scanCode);
-
-    void resetLedState();
-    void initializeLedState(LedState& ledState, int32_t led);
-    void updateLedState(bool reset);
-    void updateLedStateForModifier(LedState& ledState, int32_t led, int32_t modifier, bool reset);
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_KEYBOARD_INPUT_MAPPER_H
\ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
deleted file mode 100644
index 7460a31..0000000
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Macros.h"
-
-#include "MultiTouchInputMapper.h"
-
-namespace android {
-
-// --- Constants ---
-
-// Maximum number of slots supported when using the slot-based Multitouch Protocol B.
-static constexpr size_t MAX_SLOTS = 32;
-
-// --- MultiTouchMotionAccumulator ---
-
-MultiTouchMotionAccumulator::MultiTouchMotionAccumulator()
-      : mCurrentSlot(-1),
-        mSlots(nullptr),
-        mSlotCount(0),
-        mUsingSlotsProtocol(false),
-        mHaveStylus(false) {}
-
-MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
-    delete[] mSlots;
-}
-
-void MultiTouchMotionAccumulator::configure(InputDevice* device, size_t slotCount,
-                                            bool usingSlotsProtocol) {
-    mSlotCount = slotCount;
-    mUsingSlotsProtocol = usingSlotsProtocol;
-    mHaveStylus = device->hasAbsoluteAxis(ABS_MT_TOOL_TYPE);
-
-    delete[] mSlots;
-    mSlots = new Slot[slotCount];
-}
-
-void MultiTouchMotionAccumulator::reset(InputDevice* device) {
-    // Unfortunately there is no way to read the initial contents of the slots.
-    // So when we reset the accumulator, we must assume they are all zeroes.
-    if (mUsingSlotsProtocol) {
-        // Query the driver for the current slot index and use it as the initial slot
-        // before we start reading events from the device.  It is possible that the
-        // current slot index will not be the same as it was when the first event was
-        // written into the evdev buffer, which means the input mapper could start
-        // out of sync with the initial state of the events in the evdev buffer.
-        // In the extremely unlikely case that this happens, the data from
-        // two slots will be confused until the next ABS_MT_SLOT event is received.
-        // This can cause the touch point to "jump", but at least there will be
-        // no stuck touches.
-        int32_t initialSlot;
-        status_t status = device->getEventHub()->getAbsoluteAxisValue(device->getId(), ABS_MT_SLOT,
-                                                                      &initialSlot);
-        if (status) {
-            ALOGD("Could not retrieve current multitouch slot index.  status=%d", status);
-            initialSlot = -1;
-        }
-        clearSlots(initialSlot);
-    } else {
-        clearSlots(-1);
-    }
-    mDeviceTimestamp = 0;
-}
-
-void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
-    if (mSlots) {
-        for (size_t i = 0; i < mSlotCount; i++) {
-            mSlots[i].clear();
-        }
-    }
-    mCurrentSlot = initialSlot;
-}
-
-void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
-    if (rawEvent->type == EV_ABS) {
-        bool newSlot = false;
-        if (mUsingSlotsProtocol) {
-            if (rawEvent->code == ABS_MT_SLOT) {
-                mCurrentSlot = rawEvent->value;
-                newSlot = true;
-            }
-        } else if (mCurrentSlot < 0) {
-            mCurrentSlot = 0;
-        }
-
-        if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
-#if DEBUG_POINTERS
-            if (newSlot) {
-                ALOGW("MultiTouch device emitted invalid slot index %d but it "
-                      "should be between 0 and %zd; ignoring this slot.",
-                      mCurrentSlot, mSlotCount - 1);
-            }
-#endif
-        } else {
-            Slot* slot = &mSlots[mCurrentSlot];
-
-            switch (rawEvent->code) {
-                case ABS_MT_POSITION_X:
-                    slot->mInUse = true;
-                    slot->mAbsMTPositionX = rawEvent->value;
-                    break;
-                case ABS_MT_POSITION_Y:
-                    slot->mInUse = true;
-                    slot->mAbsMTPositionY = rawEvent->value;
-                    break;
-                case ABS_MT_TOUCH_MAJOR:
-                    slot->mInUse = true;
-                    slot->mAbsMTTouchMajor = rawEvent->value;
-                    break;
-                case ABS_MT_TOUCH_MINOR:
-                    slot->mInUse = true;
-                    slot->mAbsMTTouchMinor = rawEvent->value;
-                    slot->mHaveAbsMTTouchMinor = true;
-                    break;
-                case ABS_MT_WIDTH_MAJOR:
-                    slot->mInUse = true;
-                    slot->mAbsMTWidthMajor = rawEvent->value;
-                    break;
-                case ABS_MT_WIDTH_MINOR:
-                    slot->mInUse = true;
-                    slot->mAbsMTWidthMinor = rawEvent->value;
-                    slot->mHaveAbsMTWidthMinor = true;
-                    break;
-                case ABS_MT_ORIENTATION:
-                    slot->mInUse = true;
-                    slot->mAbsMTOrientation = rawEvent->value;
-                    break;
-                case ABS_MT_TRACKING_ID:
-                    if (mUsingSlotsProtocol && rawEvent->value < 0) {
-                        // The slot is no longer in use but it retains its previous contents,
-                        // which may be reused for subsequent touches.
-                        slot->mInUse = false;
-                    } else {
-                        slot->mInUse = true;
-                        slot->mAbsMTTrackingId = rawEvent->value;
-                    }
-                    break;
-                case ABS_MT_PRESSURE:
-                    slot->mInUse = true;
-                    slot->mAbsMTPressure = rawEvent->value;
-                    break;
-                case ABS_MT_DISTANCE:
-                    slot->mInUse = true;
-                    slot->mAbsMTDistance = rawEvent->value;
-                    break;
-                case ABS_MT_TOOL_TYPE:
-                    slot->mInUse = true;
-                    slot->mAbsMTToolType = rawEvent->value;
-                    slot->mHaveAbsMTToolType = true;
-                    break;
-            }
-        }
-    } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
-        // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
-        mCurrentSlot += 1;
-    } else if (rawEvent->type == EV_MSC && rawEvent->code == MSC_TIMESTAMP) {
-        mDeviceTimestamp = rawEvent->value;
-    }
-}
-
-void MultiTouchMotionAccumulator::finishSync() {
-    if (!mUsingSlotsProtocol) {
-        clearSlots(-1);
-    }
-}
-
-bool MultiTouchMotionAccumulator::hasStylus() const {
-    return mHaveStylus;
-}
-
-// --- MultiTouchMotionAccumulator::Slot ---
-
-MultiTouchMotionAccumulator::Slot::Slot() {
-    clear();
-}
-
-void MultiTouchMotionAccumulator::Slot::clear() {
-    mInUse = false;
-    mHaveAbsMTTouchMinor = false;
-    mHaveAbsMTWidthMinor = false;
-    mHaveAbsMTToolType = false;
-    mAbsMTPositionX = 0;
-    mAbsMTPositionY = 0;
-    mAbsMTTouchMajor = 0;
-    mAbsMTTouchMinor = 0;
-    mAbsMTWidthMajor = 0;
-    mAbsMTWidthMinor = 0;
-    mAbsMTOrientation = 0;
-    mAbsMTTrackingId = -1;
-    mAbsMTPressure = 0;
-    mAbsMTDistance = 0;
-    mAbsMTToolType = 0;
-}
-
-int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
-    if (mHaveAbsMTToolType) {
-        switch (mAbsMTToolType) {
-            case MT_TOOL_FINGER:
-                return AMOTION_EVENT_TOOL_TYPE_FINGER;
-            case MT_TOOL_PEN:
-                return AMOTION_EVENT_TOOL_TYPE_STYLUS;
-        }
-    }
-    return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
-}
-
-// --- MultiTouchInputMapper ---
-
-MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) : TouchInputMapper(device) {}
-
-MultiTouchInputMapper::~MultiTouchInputMapper() {}
-
-void MultiTouchInputMapper::reset(nsecs_t when) {
-    mMultiTouchMotionAccumulator.reset(getDevice());
-
-    mPointerIdBits.clear();
-
-    TouchInputMapper::reset(when);
-}
-
-void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
-    TouchInputMapper::process(rawEvent);
-
-    mMultiTouchMotionAccumulator.process(rawEvent);
-}
-
-void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
-    size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
-    size_t outCount = 0;
-    BitSet32 newPointerIdBits;
-    mHavePointerIds = true;
-
-    for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
-        const MultiTouchMotionAccumulator::Slot* inSlot =
-                mMultiTouchMotionAccumulator.getSlot(inIndex);
-        if (!inSlot->isInUse()) {
-            continue;
-        }
-
-        if (outCount >= MAX_POINTERS) {
-#if DEBUG_POINTERS
-            ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
-                  "ignoring the rest.",
-                  getDeviceName().c_str(), MAX_POINTERS);
-#endif
-            break; // too many fingers!
-        }
-
-        RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount];
-        outPointer.x = inSlot->getX();
-        outPointer.y = inSlot->getY();
-        outPointer.pressure = inSlot->getPressure();
-        outPointer.touchMajor = inSlot->getTouchMajor();
-        outPointer.touchMinor = inSlot->getTouchMinor();
-        outPointer.toolMajor = inSlot->getToolMajor();
-        outPointer.toolMinor = inSlot->getToolMinor();
-        outPointer.orientation = inSlot->getOrientation();
-        outPointer.distance = inSlot->getDistance();
-        outPointer.tiltX = 0;
-        outPointer.tiltY = 0;
-
-        outPointer.toolType = inSlot->getToolType();
-        if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
-            outPointer.toolType = mTouchButtonAccumulator.getToolType();
-            if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
-                outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
-            }
-        }
-
-        bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE &&
-                (mTouchButtonAccumulator.isHovering() ||
-                 (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
-        outPointer.isHovering = isHovering;
-
-        // Assign pointer id using tracking id if available.
-        if (mHavePointerIds) {
-            int32_t trackingId = inSlot->getTrackingId();
-            int32_t id = -1;
-            if (trackingId >= 0) {
-                for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty();) {
-                    uint32_t n = idBits.clearFirstMarkedBit();
-                    if (mPointerTrackingIdMap[n] == trackingId) {
-                        id = n;
-                    }
-                }
-
-                if (id < 0 && !mPointerIdBits.isFull()) {
-                    id = mPointerIdBits.markFirstUnmarkedBit();
-                    mPointerTrackingIdMap[id] = trackingId;
-                }
-            }
-            if (id < 0) {
-                mHavePointerIds = false;
-                outState->rawPointerData.clearIdBits();
-                newPointerIdBits.clear();
-            } else {
-                outPointer.id = id;
-                outState->rawPointerData.idToIndex[id] = outCount;
-                outState->rawPointerData.markIdBit(id, isHovering);
-                newPointerIdBits.markBit(id);
-            }
-        }
-        outCount += 1;
-    }
-
-    outState->deviceTimestamp = mMultiTouchMotionAccumulator.getDeviceTimestamp();
-    outState->rawPointerData.pointerCount = outCount;
-    mPointerIdBits = newPointerIdBits;
-
-    mMultiTouchMotionAccumulator.finishSync();
-}
-
-void MultiTouchInputMapper::configureRawPointerAxes() {
-    TouchInputMapper::configureRawPointerAxes();
-
-    getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);
-    getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);
-    getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);
-    getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor);
-    getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor);
-    getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor);
-    getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation);
-    getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure);
-    getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance);
-    getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId);
-    getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot);
-
-    if (mRawPointerAxes.trackingId.valid && mRawPointerAxes.slot.valid &&
-        mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
-        size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
-        if (slotCount > MAX_SLOTS) {
-            ALOGW("MultiTouch Device %s reported %zu slots but the framework "
-                  "only supports a maximum of %zu slots at this time.",
-                  getDeviceName().c_str(), slotCount, MAX_SLOTS);
-            slotCount = MAX_SLOTS;
-        }
-        mMultiTouchMotionAccumulator.configure(getDevice(), slotCount, true /*usingSlotsProtocol*/);
-    } else {
-        mMultiTouchMotionAccumulator.configure(getDevice(), MAX_POINTERS,
-                                               false /*usingSlotsProtocol*/);
-    }
-}
-
-bool MultiTouchInputMapper::hasStylus() const {
-    return mMultiTouchMotionAccumulator.hasStylus() || mTouchButtonAccumulator.hasStylus();
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
deleted file mode 100644
index 873dda1..0000000
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_MULTI_TOUCH_INPUT_MAPPER_H
-#define _UI_INPUTREADER_MULTI_TOUCH_INPUT_MAPPER_H
-
-#include "TouchInputMapper.h"
-
-namespace android {
-
-/* Keeps track of the state of multi-touch protocol. */
-class MultiTouchMotionAccumulator {
-public:
-    class Slot {
-    public:
-        inline bool isInUse() const { return mInUse; }
-        inline int32_t getX() const { return mAbsMTPositionX; }
-        inline int32_t getY() const { return mAbsMTPositionY; }
-        inline int32_t getTouchMajor() const { return mAbsMTTouchMajor; }
-        inline int32_t getTouchMinor() const {
-            return mHaveAbsMTTouchMinor ? mAbsMTTouchMinor : mAbsMTTouchMajor;
-        }
-        inline int32_t getToolMajor() const { return mAbsMTWidthMajor; }
-        inline int32_t getToolMinor() const {
-            return mHaveAbsMTWidthMinor ? mAbsMTWidthMinor : mAbsMTWidthMajor;
-        }
-        inline int32_t getOrientation() const { return mAbsMTOrientation; }
-        inline int32_t getTrackingId() const { return mAbsMTTrackingId; }
-        inline int32_t getPressure() const { return mAbsMTPressure; }
-        inline int32_t getDistance() const { return mAbsMTDistance; }
-        inline int32_t getToolType() const;
-
-    private:
-        friend class MultiTouchMotionAccumulator;
-
-        bool mInUse;
-        bool mHaveAbsMTTouchMinor;
-        bool mHaveAbsMTWidthMinor;
-        bool mHaveAbsMTToolType;
-
-        int32_t mAbsMTPositionX;
-        int32_t mAbsMTPositionY;
-        int32_t mAbsMTTouchMajor;
-        int32_t mAbsMTTouchMinor;
-        int32_t mAbsMTWidthMajor;
-        int32_t mAbsMTWidthMinor;
-        int32_t mAbsMTOrientation;
-        int32_t mAbsMTTrackingId;
-        int32_t mAbsMTPressure;
-        int32_t mAbsMTDistance;
-        int32_t mAbsMTToolType;
-
-        Slot();
-        void clear();
-    };
-
-    MultiTouchMotionAccumulator();
-    ~MultiTouchMotionAccumulator();
-
-    void configure(InputDevice* device, size_t slotCount, bool usingSlotsProtocol);
-    void reset(InputDevice* device);
-    void process(const RawEvent* rawEvent);
-    void finishSync();
-    bool hasStylus() const;
-
-    inline size_t getSlotCount() const { return mSlotCount; }
-    inline const Slot* getSlot(size_t index) const { return &mSlots[index]; }
-    inline uint32_t getDeviceTimestamp() const { return mDeviceTimestamp; }
-
-private:
-    int32_t mCurrentSlot;
-    Slot* mSlots;
-    size_t mSlotCount;
-    bool mUsingSlotsProtocol;
-    bool mHaveStylus;
-    uint32_t mDeviceTimestamp;
-
-    void clearSlots(int32_t initialSlot);
-};
-
-class MultiTouchInputMapper : public TouchInputMapper {
-public:
-    explicit MultiTouchInputMapper(InputDevice* device);
-    virtual ~MultiTouchInputMapper();
-
-    virtual void reset(nsecs_t when);
-    virtual void process(const RawEvent* rawEvent);
-
-protected:
-    virtual void syncTouch(nsecs_t when, RawState* outState);
-    virtual void configureRawPointerAxes();
-    virtual bool hasStylus() const;
-
-private:
-    MultiTouchMotionAccumulator mMultiTouchMotionAccumulator;
-
-    // Specifies the pointer id bits that are in use, and their associated tracking id.
-    BitSet32 mPointerIdBits;
-    int32_t mPointerTrackingIdMap[MAX_POINTER_ID + 1];
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_MULTI_TOUCH_INPUT_MAPPER_H
\ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
deleted file mode 100644
index 803fdf3..0000000
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Macros.h"
-
-#include "RotaryEncoderInputMapper.h"
-
-#include "CursorScrollAccumulator.h"
-
-namespace android {
-
-RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDevice* device)
-      : InputMapper(device), mOrientation(DISPLAY_ORIENTATION_0) {
-    mSource = AINPUT_SOURCE_ROTARY_ENCODER;
-}
-
-RotaryEncoderInputMapper::~RotaryEncoderInputMapper() {}
-
-uint32_t RotaryEncoderInputMapper::getSources() {
-    return mSource;
-}
-
-void RotaryEncoderInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    InputMapper::populateDeviceInfo(info);
-
-    if (mRotaryEncoderScrollAccumulator.haveRelativeVWheel()) {
-        float res = 0.0f;
-        if (!mDevice->getConfiguration().tryGetProperty(String8("device.res"), res)) {
-            ALOGW("Rotary Encoder device configuration file didn't specify resolution!\n");
-        }
-        if (!mDevice->getConfiguration().tryGetProperty(String8("device.scalingFactor"),
-                                                        mScalingFactor)) {
-            ALOGW("Rotary Encoder device configuration file didn't specify scaling factor,"
-                  "default to 1.0!\n");
-            mScalingFactor = 1.0f;
-        }
-        info->addMotionRange(AMOTION_EVENT_AXIS_SCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
-                             res * mScalingFactor);
-    }
-}
-
-void RotaryEncoderInputMapper::dump(std::string& dump) {
-    dump += INDENT2 "Rotary Encoder Input Mapper:\n";
-    dump += StringPrintf(INDENT3 "HaveWheel: %s\n",
-                         toString(mRotaryEncoderScrollAccumulator.haveRelativeVWheel()));
-}
-
-void RotaryEncoderInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
-                                         uint32_t changes) {
-    InputMapper::configure(when, config, changes);
-    if (!changes) {
-        mRotaryEncoderScrollAccumulator.configure(getDevice());
-    }
-    if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
-        std::optional<DisplayViewport> internalViewport =
-                config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
-        if (internalViewport) {
-            mOrientation = internalViewport->orientation;
-        } else {
-            mOrientation = DISPLAY_ORIENTATION_0;
-        }
-    }
-}
-
-void RotaryEncoderInputMapper::reset(nsecs_t when) {
-    mRotaryEncoderScrollAccumulator.reset(getDevice());
-
-    InputMapper::reset(when);
-}
-
-void RotaryEncoderInputMapper::process(const RawEvent* rawEvent) {
-    mRotaryEncoderScrollAccumulator.process(rawEvent);
-
-    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
-        sync(rawEvent->when);
-    }
-}
-
-void RotaryEncoderInputMapper::sync(nsecs_t when) {
-    PointerCoords pointerCoords;
-    pointerCoords.clear();
-
-    PointerProperties pointerProperties;
-    pointerProperties.clear();
-    pointerProperties.id = 0;
-    pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
-
-    float scroll = mRotaryEncoderScrollAccumulator.getRelativeVWheel();
-    bool scrolled = scroll != 0;
-
-    // This is not a pointer, so it's not associated with a display.
-    int32_t displayId = ADISPLAY_ID_NONE;
-
-    // Moving the rotary encoder should wake the device (if specified).
-    uint32_t policyFlags = 0;
-    if (scrolled && getDevice()->isExternal()) {
-        policyFlags |= POLICY_FLAG_WAKE;
-    }
-
-    if (mOrientation == DISPLAY_ORIENTATION_180) {
-        scroll = -scroll;
-    }
-
-    // Send motion event.
-    if (scrolled) {
-        int32_t metaState = mContext->getGlobalMetaState();
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor);
-
-        NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
-                                    displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0,
-                                    metaState, /* buttonState */ 0, MotionClassification::NONE,
-                                    AMOTION_EVENT_EDGE_FLAG_NONE,
-                                    /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-                                    0, 0, 0, /* videoFrames */ {});
-        getListener()->notifyMotion(&scrollArgs);
-    }
-
-    mRotaryEncoderScrollAccumulator.finishSync();
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
deleted file mode 100644
index 2648837..0000000
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_ROTARY_ENCODER_INPUT_MAPPER_H
-#define _UI_INPUTREADER_ROTARY_ENCODER_INPUT_MAPPER_H
-
-#include "CursorScrollAccumulator.h"
-#include "InputMapper.h"
-
-namespace android {
-
-class RotaryEncoderInputMapper : public InputMapper {
-public:
-    explicit RotaryEncoderInputMapper(InputDevice* device);
-    virtual ~RotaryEncoderInputMapper();
-
-    virtual uint32_t getSources();
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void dump(std::string& dump);
-    virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
-    virtual void reset(nsecs_t when);
-    virtual void process(const RawEvent* rawEvent);
-
-private:
-    CursorScrollAccumulator mRotaryEncoderScrollAccumulator;
-
-    int32_t mSource;
-    float mScalingFactor;
-    int32_t mOrientation;
-
-    void sync(nsecs_t when);
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_ROTARY_ENCODER_INPUT_MAPPER_H
\ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp
deleted file mode 100644
index 440d282..0000000
--- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "SingleTouchInputMapper.h"
-
-namespace android {
-
-SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) : TouchInputMapper(device) {}
-
-SingleTouchInputMapper::~SingleTouchInputMapper() {}
-
-void SingleTouchInputMapper::reset(nsecs_t when) {
-    mSingleTouchMotionAccumulator.reset(getDevice());
-
-    TouchInputMapper::reset(when);
-}
-
-void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
-    TouchInputMapper::process(rawEvent);
-
-    mSingleTouchMotionAccumulator.process(rawEvent);
-}
-
-void SingleTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
-    if (mTouchButtonAccumulator.isToolActive()) {
-        outState->rawPointerData.pointerCount = 1;
-        outState->rawPointerData.idToIndex[0] = 0;
-
-        bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE &&
-                (mTouchButtonAccumulator.isHovering() ||
-                 (mRawPointerAxes.pressure.valid &&
-                  mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
-        outState->rawPointerData.markIdBit(0, isHovering);
-
-        RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[0];
-        outPointer.id = 0;
-        outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
-        outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
-        outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
-        outPointer.touchMajor = 0;
-        outPointer.touchMinor = 0;
-        outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
-        outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
-        outPointer.orientation = 0;
-        outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
-        outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX();
-        outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY();
-        outPointer.toolType = mTouchButtonAccumulator.getToolType();
-        if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
-            outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
-        }
-        outPointer.isHovering = isHovering;
-    }
-}
-
-void SingleTouchInputMapper::configureRawPointerAxes() {
-    TouchInputMapper::configureRawPointerAxes();
-
-    getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x);
-    getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y);
-    getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure);
-    getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor);
-    getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance);
-    getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX);
-    getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
-}
-
-bool SingleTouchInputMapper::hasStylus() const {
-    return mTouchButtonAccumulator.hasStylus();
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
deleted file mode 100644
index d6b1455..0000000
--- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_SINGLE_TOUCH_INPUT_MAPPER_H
-#define _UI_INPUTREADER_SINGLE_TOUCH_INPUT_MAPPER_H
-
-#include "SingleTouchMotionAccumulator.h"
-#include "TouchInputMapper.h"
-
-namespace android {
-
-class SingleTouchInputMapper : public TouchInputMapper {
-public:
-    explicit SingleTouchInputMapper(InputDevice* device);
-    virtual ~SingleTouchInputMapper();
-
-    virtual void reset(nsecs_t when);
-    virtual void process(const RawEvent* rawEvent);
-
-protected:
-    virtual void syncTouch(nsecs_t when, RawState* outState);
-    virtual void configureRawPointerAxes();
-    virtual bool hasStylus() const;
-
-private:
-    SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_SINGLE_TOUCH_INPUT_MAPPER_H
\ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp b/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
deleted file mode 100644
index 4ff941f..0000000
--- a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Macros.h"
-
-#include "SwitchInputMapper.h"
-
-namespace android {
-
-SwitchInputMapper::SwitchInputMapper(InputDevice* device)
-      : InputMapper(device), mSwitchValues(0), mUpdatedSwitchMask(0) {}
-
-SwitchInputMapper::~SwitchInputMapper() {}
-
-uint32_t SwitchInputMapper::getSources() {
-    return AINPUT_SOURCE_SWITCH;
-}
-
-void SwitchInputMapper::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-        case EV_SW:
-            processSwitch(rawEvent->code, rawEvent->value);
-            break;
-
-        case EV_SYN:
-            if (rawEvent->code == SYN_REPORT) {
-                sync(rawEvent->when);
-            }
-    }
-}
-
-void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
-    if (switchCode >= 0 && switchCode < 32) {
-        if (switchValue) {
-            mSwitchValues |= 1 << switchCode;
-        } else {
-            mSwitchValues &= ~(1 << switchCode);
-        }
-        mUpdatedSwitchMask |= 1 << switchCode;
-    }
-}
-
-void SwitchInputMapper::sync(nsecs_t when) {
-    if (mUpdatedSwitchMask) {
-        uint32_t updatedSwitchValues = mSwitchValues & mUpdatedSwitchMask;
-        NotifySwitchArgs args(mContext->getNextSequenceNum(), when, 0, updatedSwitchValues,
-                              mUpdatedSwitchMask);
-        getListener()->notifySwitch(&args);
-
-        mUpdatedSwitchMask = 0;
-    }
-}
-
-int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
-    return getEventHub()->getSwitchState(getDeviceId(), switchCode);
-}
-
-void SwitchInputMapper::dump(std::string& dump) {
-    dump += INDENT2 "Switch Input Mapper:\n";
-    dump += StringPrintf(INDENT3 "SwitchValues: %x\n", mSwitchValues);
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.h b/services/inputflinger/reader/mapper/SwitchInputMapper.h
deleted file mode 100644
index dd4bb9e..0000000
--- a/services/inputflinger/reader/mapper/SwitchInputMapper.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_SWITCH_INPUT_MAPPER_H
-#define _UI_INPUTREADER_SWITCH_INPUT_MAPPER_H
-
-#include "InputMapper.h"
-
-namespace android {
-
-class SwitchInputMapper : public InputMapper {
-public:
-    explicit SwitchInputMapper(InputDevice* device);
-    virtual ~SwitchInputMapper();
-
-    virtual uint32_t getSources();
-    virtual void process(const RawEvent* rawEvent);
-
-    virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
-    virtual void dump(std::string& dump);
-
-private:
-    uint32_t mSwitchValues;
-    uint32_t mUpdatedSwitchMask;
-
-    void processSwitch(int32_t switchCode, int32_t switchValue);
-    void sync(nsecs_t when);
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_SWITCH_INPUT_MAPPER_H
\ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
deleted file mode 100644
index efa3d6d..0000000
--- a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_TOUCH_CURSOR_INPUT_MAPPER_COMMON_H
-#define _UI_INPUTREADER_TOUCH_CURSOR_INPUT_MAPPER_COMMON_H
-
-#include "EventHub.h"
-#include "InputListener.h"
-#include "InputReaderContext.h"
-
-#include <stdint.h>
-
-namespace android {
-
-// --- Static Definitions ---
-
-static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) {
-    float temp;
-    switch (orientation) {
-        case DISPLAY_ORIENTATION_90:
-            temp = *deltaX;
-            *deltaX = *deltaY;
-            *deltaY = -temp;
-            break;
-
-        case DISPLAY_ORIENTATION_180:
-            *deltaX = -*deltaX;
-            *deltaY = -*deltaY;
-            break;
-
-        case DISPLAY_ORIENTATION_270:
-            temp = *deltaX;
-            *deltaX = -*deltaY;
-            *deltaY = temp;
-            break;
-    }
-}
-
-// Returns true if the pointer should be reported as being down given the specified
-// button states.  This determines whether the event is reported as a touch event.
-static bool isPointerDown(int32_t buttonState) {
-    return buttonState &
-            (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY |
-             AMOTION_EVENT_BUTTON_TERTIARY);
-}
-
-static void synthesizeButtonKey(InputReaderContext* context, int32_t action, nsecs_t when,
-                                int32_t deviceId, uint32_t source, int32_t displayId,
-                                uint32_t policyFlags, int32_t lastButtonState,
-                                int32_t currentButtonState, int32_t buttonState, int32_t keyCode) {
-    if ((action == AKEY_EVENT_ACTION_DOWN && !(lastButtonState & buttonState) &&
-         (currentButtonState & buttonState)) ||
-        (action == AKEY_EVENT_ACTION_UP && (lastButtonState & buttonState) &&
-         !(currentButtonState & buttonState))) {
-        NotifyKeyArgs args(context->getNextSequenceNum(), when, deviceId, source, displayId,
-                           policyFlags, action, 0, keyCode, 0, context->getGlobalMetaState(), when);
-        context->getListener()->notifyKey(&args);
-    }
-}
-
-static void synthesizeButtonKeys(InputReaderContext* context, int32_t action, nsecs_t when,
-                                 int32_t deviceId, uint32_t source, int32_t displayId,
-                                 uint32_t policyFlags, int32_t lastButtonState,
-                                 int32_t currentButtonState) {
-    synthesizeButtonKey(context, action, when, deviceId, source, displayId, policyFlags,
-                        lastButtonState, currentButtonState, AMOTION_EVENT_BUTTON_BACK,
-                        AKEYCODE_BACK);
-    synthesizeButtonKey(context, action, when, deviceId, source, displayId, policyFlags,
-                        lastButtonState, currentButtonState, AMOTION_EVENT_BUTTON_FORWARD,
-                        AKEYCODE_FORWARD);
-}
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_TOUCH_CURSOR_INPUT_MAPPER_COMMON_H
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
deleted file mode 100644
index 32ed97b..0000000
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ /dev/null
@@ -1,3909 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Macros.h"
-
-#include "TouchInputMapper.h"
-
-#include "CursorButtonAccumulator.h"
-#include "CursorScrollAccumulator.h"
-#include "TouchButtonAccumulator.h"
-#include "TouchCursorInputMapperCommon.h"
-
-#include <statslog.h>
-
-// How often to report input event statistics
-static constexpr nsecs_t STATISTICS_REPORT_FREQUENCY = seconds_to_nanoseconds(5 * 60);
-
-namespace android {
-
-// --- Constants ---
-
-// Maximum amount of latency to add to touch events while waiting for data from an
-// external stylus.
-static constexpr nsecs_t EXTERNAL_STYLUS_DATA_TIMEOUT = ms2ns(72);
-
-// Maximum amount of time to wait on touch data before pushing out new pressure data.
-static constexpr nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20);
-
-// Artificial latency on synthetic events created from stylus data without corresponding touch
-// data.
-static constexpr nsecs_t STYLUS_DATA_LATENCY = ms2ns(10);
-
-// --- Static Definitions ---
-
-template <typename T>
-inline static void swap(T& a, T& b) {
-    T temp = a;
-    a = b;
-    b = temp;
-}
-
-static float calculateCommonVector(float a, float b) {
-    if (a > 0 && b > 0) {
-        return a < b ? a : b;
-    } else if (a < 0 && b < 0) {
-        return a > b ? a : b;
-    } else {
-        return 0;
-    }
-}
-
-inline static float distance(float x1, float y1, float x2, float y2) {
-    return hypotf(x1 - x2, y1 - y2);
-}
-
-inline static int32_t signExtendNybble(int32_t value) {
-    return value >= 8 ? value - 16 : value;
-}
-
-// --- RawPointerAxes ---
-
-RawPointerAxes::RawPointerAxes() {
-    clear();
-}
-
-void RawPointerAxes::clear() {
-    x.clear();
-    y.clear();
-    pressure.clear();
-    touchMajor.clear();
-    touchMinor.clear();
-    toolMajor.clear();
-    toolMinor.clear();
-    orientation.clear();
-    distance.clear();
-    tiltX.clear();
-    tiltY.clear();
-    trackingId.clear();
-    slot.clear();
-}
-
-// --- RawPointerData ---
-
-RawPointerData::RawPointerData() {
-    clear();
-}
-
-void RawPointerData::clear() {
-    pointerCount = 0;
-    clearIdBits();
-}
-
-void RawPointerData::copyFrom(const RawPointerData& other) {
-    pointerCount = other.pointerCount;
-    hoveringIdBits = other.hoveringIdBits;
-    touchingIdBits = other.touchingIdBits;
-
-    for (uint32_t i = 0; i < pointerCount; i++) {
-        pointers[i] = other.pointers[i];
-
-        int id = pointers[i].id;
-        idToIndex[id] = other.idToIndex[id];
-    }
-}
-
-void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) const {
-    float x = 0, y = 0;
-    uint32_t count = touchingIdBits.count();
-    if (count) {
-        for (BitSet32 idBits(touchingIdBits); !idBits.isEmpty();) {
-            uint32_t id = idBits.clearFirstMarkedBit();
-            const Pointer& pointer = pointerForId(id);
-            x += pointer.x;
-            y += pointer.y;
-        }
-        x /= count;
-        y /= count;
-    }
-    *outX = x;
-    *outY = y;
-}
-
-// --- CookedPointerData ---
-
-CookedPointerData::CookedPointerData() {
-    clear();
-}
-
-void CookedPointerData::clear() {
-    pointerCount = 0;
-    hoveringIdBits.clear();
-    touchingIdBits.clear();
-}
-
-void CookedPointerData::copyFrom(const CookedPointerData& other) {
-    pointerCount = other.pointerCount;
-    hoveringIdBits = other.hoveringIdBits;
-    touchingIdBits = other.touchingIdBits;
-
-    for (uint32_t i = 0; i < pointerCount; i++) {
-        pointerProperties[i].copyFrom(other.pointerProperties[i]);
-        pointerCoords[i].copyFrom(other.pointerCoords[i]);
-
-        int id = pointerProperties[i].id;
-        idToIndex[id] = other.idToIndex[id];
-    }
-}
-
-// --- TouchInputMapper ---
-
-TouchInputMapper::TouchInputMapper(InputDevice* device)
-      : InputMapper(device),
-        mSource(0),
-        mDeviceMode(DEVICE_MODE_DISABLED),
-        mSurfaceWidth(-1),
-        mSurfaceHeight(-1),
-        mSurfaceLeft(0),
-        mSurfaceTop(0),
-        mPhysicalWidth(-1),
-        mPhysicalHeight(-1),
-        mPhysicalLeft(0),
-        mPhysicalTop(0),
-        mSurfaceOrientation(DISPLAY_ORIENTATION_0) {}
-
-TouchInputMapper::~TouchInputMapper() {}
-
-uint32_t TouchInputMapper::getSources() {
-    return mSource;
-}
-
-void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    InputMapper::populateDeviceInfo(info);
-
-    if (mDeviceMode != DEVICE_MODE_DISABLED) {
-        info->addMotionRange(mOrientedRanges.x);
-        info->addMotionRange(mOrientedRanges.y);
-        info->addMotionRange(mOrientedRanges.pressure);
-
-        if (mOrientedRanges.haveSize) {
-            info->addMotionRange(mOrientedRanges.size);
-        }
-
-        if (mOrientedRanges.haveTouchSize) {
-            info->addMotionRange(mOrientedRanges.touchMajor);
-            info->addMotionRange(mOrientedRanges.touchMinor);
-        }
-
-        if (mOrientedRanges.haveToolSize) {
-            info->addMotionRange(mOrientedRanges.toolMajor);
-            info->addMotionRange(mOrientedRanges.toolMinor);
-        }
-
-        if (mOrientedRanges.haveOrientation) {
-            info->addMotionRange(mOrientedRanges.orientation);
-        }
-
-        if (mOrientedRanges.haveDistance) {
-            info->addMotionRange(mOrientedRanges.distance);
-        }
-
-        if (mOrientedRanges.haveTilt) {
-            info->addMotionRange(mOrientedRanges.tilt);
-        }
-
-        if (mCursorScrollAccumulator.haveRelativeVWheel()) {
-            info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
-                                 0.0f);
-        }
-        if (mCursorScrollAccumulator.haveRelativeHWheel()) {
-            info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
-                                 0.0f);
-        }
-        if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
-            const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
-            const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
-            info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat,
-                                 x.fuzz, x.resolution);
-            info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat,
-                                 y.fuzz, y.resolution);
-            info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat,
-                                 x.fuzz, x.resolution);
-            info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat,
-                                 y.fuzz, y.resolution);
-        }
-        info->setButtonUnderPad(mParameters.hasButtonUnderPad);
-    }
-}
-
-void TouchInputMapper::dump(std::string& dump) {
-    dump += StringPrintf(INDENT2 "Touch Input Mapper (mode - %s):\n", modeToString(mDeviceMode));
-    dumpParameters(dump);
-    dumpVirtualKeys(dump);
-    dumpRawPointerAxes(dump);
-    dumpCalibration(dump);
-    dumpAffineTransformation(dump);
-    dumpSurface(dump);
-
-    dump += StringPrintf(INDENT3 "Translation and Scaling Factors:\n");
-    dump += StringPrintf(INDENT4 "XTranslate: %0.3f\n", mXTranslate);
-    dump += StringPrintf(INDENT4 "YTranslate: %0.3f\n", mYTranslate);
-    dump += StringPrintf(INDENT4 "XScale: %0.3f\n", mXScale);
-    dump += StringPrintf(INDENT4 "YScale: %0.3f\n", mYScale);
-    dump += StringPrintf(INDENT4 "XPrecision: %0.3f\n", mXPrecision);
-    dump += StringPrintf(INDENT4 "YPrecision: %0.3f\n", mYPrecision);
-    dump += StringPrintf(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
-    dump += StringPrintf(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
-    dump += StringPrintf(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
-    dump += StringPrintf(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
-    dump += StringPrintf(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
-    dump += StringPrintf(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
-    dump += StringPrintf(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter);
-    dump += StringPrintf(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale);
-    dump += StringPrintf(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
-    dump += StringPrintf(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
-
-    dump += StringPrintf(INDENT3 "Last Raw Button State: 0x%08x\n", mLastRawState.buttonState);
-    dump += StringPrintf(INDENT3 "Last Raw Touch: pointerCount=%d\n",
-                         mLastRawState.rawPointerData.pointerCount);
-    for (uint32_t i = 0; i < mLastRawState.rawPointerData.pointerCount; i++) {
-        const RawPointerData::Pointer& pointer = mLastRawState.rawPointerData.pointers[i];
-        dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
-                                     "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
-                                     "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, "
-                                     "toolType=%d, isHovering=%s\n",
-                             i, pointer.id, pointer.x, pointer.y, pointer.pressure,
-                             pointer.touchMajor, pointer.touchMinor, pointer.toolMajor,
-                             pointer.toolMinor, pointer.orientation, pointer.tiltX, pointer.tiltY,
-                             pointer.distance, pointer.toolType, toString(pointer.isHovering));
-    }
-
-    dump += StringPrintf(INDENT3 "Last Cooked Button State: 0x%08x\n",
-                         mLastCookedState.buttonState);
-    dump += StringPrintf(INDENT3 "Last Cooked Touch: pointerCount=%d\n",
-                         mLastCookedState.cookedPointerData.pointerCount);
-    for (uint32_t i = 0; i < mLastCookedState.cookedPointerData.pointerCount; i++) {
-        const PointerProperties& pointerProperties =
-                mLastCookedState.cookedPointerData.pointerProperties[i];
-        const PointerCoords& pointerCoords = mLastCookedState.cookedPointerData.pointerCoords[i];
-        dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
-                                     "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, "
-                                     "toolMinor=%0.3f, "
-                                     "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
-                                     "toolType=%d, isHovering=%s\n",
-                             i, pointerProperties.id, pointerCoords.getX(), pointerCoords.getY(),
-                             pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
-                             pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
-                             pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
-                             pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
-                             pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
-                             pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
-                             pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT),
-                             pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE),
-                             pointerProperties.toolType,
-                             toString(mLastCookedState.cookedPointerData.isHovering(i)));
-    }
-
-    dump += INDENT3 "Stylus Fusion:\n";
-    dump += StringPrintf(INDENT4 "ExternalStylusConnected: %s\n",
-                         toString(mExternalStylusConnected));
-    dump += StringPrintf(INDENT4 "External Stylus ID: %" PRId64 "\n", mExternalStylusId);
-    dump += StringPrintf(INDENT4 "External Stylus Data Timeout: %" PRId64 "\n",
-                         mExternalStylusFusionTimeout);
-    dump += INDENT3 "External Stylus State:\n";
-    dumpStylusState(dump, mExternalStylusState);
-
-    if (mDeviceMode == DEVICE_MODE_POINTER) {
-        dump += StringPrintf(INDENT3 "Pointer Gesture Detector:\n");
-        dump += StringPrintf(INDENT4 "XMovementScale: %0.3f\n", mPointerXMovementScale);
-        dump += StringPrintf(INDENT4 "YMovementScale: %0.3f\n", mPointerYMovementScale);
-        dump += StringPrintf(INDENT4 "XZoomScale: %0.3f\n", mPointerXZoomScale);
-        dump += StringPrintf(INDENT4 "YZoomScale: %0.3f\n", mPointerYZoomScale);
-        dump += StringPrintf(INDENT4 "MaxSwipeWidth: %f\n", mPointerGestureMaxSwipeWidth);
-    }
-}
-
-const char* TouchInputMapper::modeToString(DeviceMode deviceMode) {
-    switch (deviceMode) {
-        case DEVICE_MODE_DISABLED:
-            return "disabled";
-        case DEVICE_MODE_DIRECT:
-            return "direct";
-        case DEVICE_MODE_UNSCALED:
-            return "unscaled";
-        case DEVICE_MODE_NAVIGATION:
-            return "navigation";
-        case DEVICE_MODE_POINTER:
-            return "pointer";
-    }
-    return "unknown";
-}
-
-void TouchInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
-                                 uint32_t changes) {
-    InputMapper::configure(when, config, changes);
-
-    mConfig = *config;
-
-    if (!changes) { // first time only
-        // Configure basic parameters.
-        configureParameters();
-
-        // Configure common accumulators.
-        mCursorScrollAccumulator.configure(getDevice());
-        mTouchButtonAccumulator.configure(getDevice());
-
-        // Configure absolute axis information.
-        configureRawPointerAxes();
-
-        // Prepare input device calibration.
-        parseCalibration();
-        resolveCalibration();
-    }
-
-    if (!changes || (changes & InputReaderConfiguration::CHANGE_TOUCH_AFFINE_TRANSFORMATION)) {
-        // Update location calibration to reflect current settings
-        updateAffineTransformation();
-    }
-
-    if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
-        // Update pointer speed.
-        mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters);
-        mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
-        mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
-    }
-
-    bool resetNeeded = false;
-    if (!changes ||
-        (changes &
-         (InputReaderConfiguration::CHANGE_DISPLAY_INFO |
-          InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT |
-          InputReaderConfiguration::CHANGE_SHOW_TOUCHES |
-          InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE))) {
-        // Configure device sources, surface dimensions, orientation and
-        // scaling factors.
-        configureSurface(when, &resetNeeded);
-    }
-
-    if (changes && resetNeeded) {
-        // Send reset, unless this is the first time the device has been configured,
-        // in which case the reader will call reset itself after all mappers are ready.
-        getDevice()->notifyReset(when);
-    }
-}
-
-void TouchInputMapper::resolveExternalStylusPresence() {
-    std::vector<InputDeviceInfo> devices;
-    mContext->getExternalStylusDevices(devices);
-    mExternalStylusConnected = !devices.empty();
-
-    if (!mExternalStylusConnected) {
-        resetExternalStylus();
-    }
-}
-
-void TouchInputMapper::configureParameters() {
-    // Use the pointer presentation mode for devices that do not support distinct
-    // multitouch.  The spot-based presentation relies on being able to accurately
-    // locate two or more fingers on the touch pad.
-    mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
-            ? Parameters::GESTURE_MODE_SINGLE_TOUCH
-            : Parameters::GESTURE_MODE_MULTI_TOUCH;
-
-    String8 gestureModeString;
-    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
-                                                       gestureModeString)) {
-        if (gestureModeString == "single-touch") {
-            mParameters.gestureMode = Parameters::GESTURE_MODE_SINGLE_TOUCH;
-        } else if (gestureModeString == "multi-touch") {
-            mParameters.gestureMode = Parameters::GESTURE_MODE_MULTI_TOUCH;
-        } else if (gestureModeString != "default") {
-            ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
-        }
-    }
-
-    if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
-        // The device is a touch screen.
-        mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
-    } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
-        // The device is a pointing device like a track pad.
-        mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
-    } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X) ||
-               getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
-        // The device is a cursor device with a touch pad attached.
-        // By default don't use the touch pad to move the pointer.
-        mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
-    } else {
-        // The device is a touch pad of unknown purpose.
-        mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
-    }
-
-    mParameters.hasButtonUnderPad =
-            getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_BUTTONPAD);
-
-    String8 deviceTypeString;
-    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
-                                                       deviceTypeString)) {
-        if (deviceTypeString == "touchScreen") {
-            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
-        } else if (deviceTypeString == "touchPad") {
-            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
-        } else if (deviceTypeString == "touchNavigation") {
-            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION;
-        } else if (deviceTypeString == "pointer") {
-            mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
-        } else if (deviceTypeString != "default") {
-            ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
-        }
-    }
-
-    mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
-    getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
-                                                   mParameters.orientationAware);
-
-    mParameters.hasAssociatedDisplay = false;
-    mParameters.associatedDisplayIsExternal = false;
-    if (mParameters.orientationAware ||
-        mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN ||
-        mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
-        mParameters.hasAssociatedDisplay = true;
-        if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
-            mParameters.associatedDisplayIsExternal = getDevice()->isExternal();
-            String8 uniqueDisplayId;
-            getDevice()->getConfiguration().tryGetProperty(String8("touch.displayId"),
-                                                           uniqueDisplayId);
-            mParameters.uniqueDisplayId = uniqueDisplayId.c_str();
-        }
-    }
-    if (getDevice()->getAssociatedDisplayPort()) {
-        mParameters.hasAssociatedDisplay = true;
-    }
-
-    // Initial downs on external touch devices should wake the device.
-    // Normally we don't do this for internal touch screens to prevent them from waking
-    // up in your pocket but you can enable it using the input device configuration.
-    mParameters.wake = getDevice()->isExternal();
-    getDevice()->getConfiguration().tryGetProperty(String8("touch.wake"), mParameters.wake);
-}
-
-void TouchInputMapper::dumpParameters(std::string& dump) {
-    dump += INDENT3 "Parameters:\n";
-
-    switch (mParameters.gestureMode) {
-        case Parameters::GESTURE_MODE_SINGLE_TOUCH:
-            dump += INDENT4 "GestureMode: single-touch\n";
-            break;
-        case Parameters::GESTURE_MODE_MULTI_TOUCH:
-            dump += INDENT4 "GestureMode: multi-touch\n";
-            break;
-        default:
-            assert(false);
-    }
-
-    switch (mParameters.deviceType) {
-        case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
-            dump += INDENT4 "DeviceType: touchScreen\n";
-            break;
-        case Parameters::DEVICE_TYPE_TOUCH_PAD:
-            dump += INDENT4 "DeviceType: touchPad\n";
-            break;
-        case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
-            dump += INDENT4 "DeviceType: touchNavigation\n";
-            break;
-        case Parameters::DEVICE_TYPE_POINTER:
-            dump += INDENT4 "DeviceType: pointer\n";
-            break;
-        default:
-            ALOG_ASSERT(false);
-    }
-
-    dump += StringPrintf(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s, "
-                                 "displayId='%s'\n",
-                         toString(mParameters.hasAssociatedDisplay),
-                         toString(mParameters.associatedDisplayIsExternal),
-                         mParameters.uniqueDisplayId.c_str());
-    dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
-}
-
-void TouchInputMapper::configureRawPointerAxes() {
-    mRawPointerAxes.clear();
-}
-
-void TouchInputMapper::dumpRawPointerAxes(std::string& dump) {
-    dump += INDENT3 "Raw Touch Axes:\n";
-    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X");
-    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y");
-    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure");
-    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor");
-    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor");
-    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor");
-    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor");
-    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation");
-    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance");
-    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX");
-    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY");
-    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId");
-    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
-}
-
-bool TouchInputMapper::hasExternalStylus() const {
-    return mExternalStylusConnected;
-}
-
-/**
- * Determine which DisplayViewport to use.
- * 1. If display port is specified, return the matching viewport. If matching viewport not
- * found, then return.
- * 2. If a device has associated display, get the matching viewport by either unique id or by
- * the display type (internal or external).
- * 3. Otherwise, use a non-display viewport.
- */
-std::optional<DisplayViewport> TouchInputMapper::findViewport() {
-    if (mParameters.hasAssociatedDisplay) {
-        const std::optional<uint8_t> displayPort = mDevice->getAssociatedDisplayPort();
-        if (displayPort) {
-            // Find the viewport that contains the same port
-            std::optional<DisplayViewport> v = mConfig.getDisplayViewportByPort(*displayPort);
-            if (!v) {
-                ALOGW("Input device %s should be associated with display on port %" PRIu8 ", "
-                      "but the corresponding viewport is not found.",
-                      getDeviceName().c_str(), *displayPort);
-            }
-            return v;
-        }
-
-        if (!mParameters.uniqueDisplayId.empty()) {
-            return mConfig.getDisplayViewportByUniqueId(mParameters.uniqueDisplayId);
-        }
-
-        ViewportType viewportTypeToUse;
-        if (mParameters.associatedDisplayIsExternal) {
-            viewportTypeToUse = ViewportType::VIEWPORT_EXTERNAL;
-        } else {
-            viewportTypeToUse = ViewportType::VIEWPORT_INTERNAL;
-        }
-
-        std::optional<DisplayViewport> viewport =
-                mConfig.getDisplayViewportByType(viewportTypeToUse);
-        if (!viewport && viewportTypeToUse == ViewportType::VIEWPORT_EXTERNAL) {
-            ALOGW("Input device %s should be associated with external display, "
-                  "fallback to internal one for the external viewport is not found.",
-                  getDeviceName().c_str());
-            viewport = mConfig.getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
-        }
-
-        return viewport;
-    }
-
-    DisplayViewport newViewport;
-    // Raw width and height in the natural orientation.
-    int32_t rawWidth = mRawPointerAxes.getRawWidth();
-    int32_t rawHeight = mRawPointerAxes.getRawHeight();
-    newViewport.setNonDisplayViewport(rawWidth, rawHeight);
-    return std::make_optional(newViewport);
-}
-
-void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
-    int32_t oldDeviceMode = mDeviceMode;
-
-    resolveExternalStylusPresence();
-
-    // Determine device mode.
-    if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER &&
-        mConfig.pointerGesturesEnabled) {
-        mSource = AINPUT_SOURCE_MOUSE;
-        mDeviceMode = DEVICE_MODE_POINTER;
-        if (hasStylus()) {
-            mSource |= AINPUT_SOURCE_STYLUS;
-        }
-    } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN &&
-               mParameters.hasAssociatedDisplay) {
-        mSource = AINPUT_SOURCE_TOUCHSCREEN;
-        mDeviceMode = DEVICE_MODE_DIRECT;
-        if (hasStylus()) {
-            mSource |= AINPUT_SOURCE_STYLUS;
-        }
-        if (hasExternalStylus()) {
-            mSource |= AINPUT_SOURCE_BLUETOOTH_STYLUS;
-        }
-    } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
-        mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
-        mDeviceMode = DEVICE_MODE_NAVIGATION;
-    } else {
-        mSource = AINPUT_SOURCE_TOUCHPAD;
-        mDeviceMode = DEVICE_MODE_UNSCALED;
-    }
-
-    // Ensure we have valid X and Y axes.
-    if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
-        ALOGW("Touch device '%s' did not report support for X or Y axis!  "
-              "The device will be inoperable.",
-              getDeviceName().c_str());
-        mDeviceMode = DEVICE_MODE_DISABLED;
-        return;
-    }
-
-    // Get associated display dimensions.
-    std::optional<DisplayViewport> newViewport = findViewport();
-    if (!newViewport) {
-        ALOGI("Touch device '%s' could not query the properties of its associated "
-              "display.  The device will be inoperable until the display size "
-              "becomes available.",
-              getDeviceName().c_str());
-        mDeviceMode = DEVICE_MODE_DISABLED;
-        return;
-    }
-
-    // Raw width and height in the natural orientation.
-    int32_t rawWidth = mRawPointerAxes.getRawWidth();
-    int32_t rawHeight = mRawPointerAxes.getRawHeight();
-
-    bool viewportChanged = mViewport != *newViewport;
-    if (viewportChanged) {
-        mViewport = *newViewport;
-
-        if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
-            // Convert rotated viewport to natural surface coordinates.
-            int32_t naturalLogicalWidth, naturalLogicalHeight;
-            int32_t naturalPhysicalWidth, naturalPhysicalHeight;
-            int32_t naturalPhysicalLeft, naturalPhysicalTop;
-            int32_t naturalDeviceWidth, naturalDeviceHeight;
-            switch (mViewport.orientation) {
-                case DISPLAY_ORIENTATION_90:
-                    naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
-                    naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
-                    naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
-                    naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
-                    naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
-                    naturalPhysicalTop = mViewport.physicalLeft;
-                    naturalDeviceWidth = mViewport.deviceHeight;
-                    naturalDeviceHeight = mViewport.deviceWidth;
-                    break;
-                case DISPLAY_ORIENTATION_180:
-                    naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
-                    naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
-                    naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
-                    naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
-                    naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight;
-                    naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom;
-                    naturalDeviceWidth = mViewport.deviceWidth;
-                    naturalDeviceHeight = mViewport.deviceHeight;
-                    break;
-                case DISPLAY_ORIENTATION_270:
-                    naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
-                    naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
-                    naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
-                    naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
-                    naturalPhysicalLeft = mViewport.physicalTop;
-                    naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
-                    naturalDeviceWidth = mViewport.deviceHeight;
-                    naturalDeviceHeight = mViewport.deviceWidth;
-                    break;
-                case DISPLAY_ORIENTATION_0:
-                default:
-                    naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
-                    naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
-                    naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
-                    naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
-                    naturalPhysicalLeft = mViewport.physicalLeft;
-                    naturalPhysicalTop = mViewport.physicalTop;
-                    naturalDeviceWidth = mViewport.deviceWidth;
-                    naturalDeviceHeight = mViewport.deviceHeight;
-                    break;
-            }
-
-            if (naturalPhysicalHeight == 0 || naturalPhysicalWidth == 0) {
-                ALOGE("Viewport is not set properly: %s", mViewport.toString().c_str());
-                naturalPhysicalHeight = naturalPhysicalHeight == 0 ? 1 : naturalPhysicalHeight;
-                naturalPhysicalWidth = naturalPhysicalWidth == 0 ? 1 : naturalPhysicalWidth;
-            }
-
-            mPhysicalWidth = naturalPhysicalWidth;
-            mPhysicalHeight = naturalPhysicalHeight;
-            mPhysicalLeft = naturalPhysicalLeft;
-            mPhysicalTop = naturalPhysicalTop;
-
-            mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
-            mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
-            mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
-            mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight;
-
-            mSurfaceOrientation =
-                    mParameters.orientationAware ? mViewport.orientation : DISPLAY_ORIENTATION_0;
-        } else {
-            mPhysicalWidth = rawWidth;
-            mPhysicalHeight = rawHeight;
-            mPhysicalLeft = 0;
-            mPhysicalTop = 0;
-
-            mSurfaceWidth = rawWidth;
-            mSurfaceHeight = rawHeight;
-            mSurfaceLeft = 0;
-            mSurfaceTop = 0;
-            mSurfaceOrientation = DISPLAY_ORIENTATION_0;
-        }
-    }
-
-    // If moving between pointer modes, need to reset some state.
-    bool deviceModeChanged = mDeviceMode != oldDeviceMode;
-    if (deviceModeChanged) {
-        mOrientedRanges.clear();
-    }
-
-    // Create or update pointer controller if needed.
-    if (mDeviceMode == DEVICE_MODE_POINTER ||
-        (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
-        if (mPointerController == nullptr || viewportChanged) {
-            mPointerController = getPolicy()->obtainPointerController(getDeviceId());
-        }
-    } else {
-        mPointerController.clear();
-    }
-
-    if (viewportChanged || deviceModeChanged) {
-        ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
-              "display id %d",
-              getDeviceId(), getDeviceName().c_str(), mSurfaceWidth, mSurfaceHeight,
-              mSurfaceOrientation, mDeviceMode, mViewport.displayId);
-
-        // Configure X and Y factors.
-        mXScale = float(mSurfaceWidth) / rawWidth;
-        mYScale = float(mSurfaceHeight) / rawHeight;
-        mXTranslate = -mSurfaceLeft;
-        mYTranslate = -mSurfaceTop;
-        mXPrecision = 1.0f / mXScale;
-        mYPrecision = 1.0f / mYScale;
-
-        mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
-        mOrientedRanges.x.source = mSource;
-        mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
-        mOrientedRanges.y.source = mSource;
-
-        configureVirtualKeys();
-
-        // Scale factor for terms that are not oriented in a particular axis.
-        // If the pixels are square then xScale == yScale otherwise we fake it
-        // by choosing an average.
-        mGeometricScale = avg(mXScale, mYScale);
-
-        // Size of diagonal axis.
-        float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight);
-
-        // Size factors.
-        if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
-            if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.touchMajor.maxValue != 0) {
-                mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
-            } else if (mRawPointerAxes.toolMajor.valid && mRawPointerAxes.toolMajor.maxValue != 0) {
-                mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue;
-            } else {
-                mSizeScale = 0.0f;
-            }
-
-            mOrientedRanges.haveTouchSize = true;
-            mOrientedRanges.haveToolSize = true;
-            mOrientedRanges.haveSize = true;
-
-            mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
-            mOrientedRanges.touchMajor.source = mSource;
-            mOrientedRanges.touchMajor.min = 0;
-            mOrientedRanges.touchMajor.max = diagonalSize;
-            mOrientedRanges.touchMajor.flat = 0;
-            mOrientedRanges.touchMajor.fuzz = 0;
-            mOrientedRanges.touchMajor.resolution = 0;
-
-            mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
-            mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
-
-            mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
-            mOrientedRanges.toolMajor.source = mSource;
-            mOrientedRanges.toolMajor.min = 0;
-            mOrientedRanges.toolMajor.max = diagonalSize;
-            mOrientedRanges.toolMajor.flat = 0;
-            mOrientedRanges.toolMajor.fuzz = 0;
-            mOrientedRanges.toolMajor.resolution = 0;
-
-            mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
-            mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
-
-            mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
-            mOrientedRanges.size.source = mSource;
-            mOrientedRanges.size.min = 0;
-            mOrientedRanges.size.max = 1.0;
-            mOrientedRanges.size.flat = 0;
-            mOrientedRanges.size.fuzz = 0;
-            mOrientedRanges.size.resolution = 0;
-        } else {
-            mSizeScale = 0.0f;
-        }
-
-        // Pressure factors.
-        mPressureScale = 0;
-        float pressureMax = 1.0;
-        if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL ||
-            mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
-            if (mCalibration.havePressureScale) {
-                mPressureScale = mCalibration.pressureScale;
-                pressureMax = mPressureScale * mRawPointerAxes.pressure.maxValue;
-            } else if (mRawPointerAxes.pressure.valid && mRawPointerAxes.pressure.maxValue != 0) {
-                mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
-            }
-        }
-
-        mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
-        mOrientedRanges.pressure.source = mSource;
-        mOrientedRanges.pressure.min = 0;
-        mOrientedRanges.pressure.max = pressureMax;
-        mOrientedRanges.pressure.flat = 0;
-        mOrientedRanges.pressure.fuzz = 0;
-        mOrientedRanges.pressure.resolution = 0;
-
-        // Tilt
-        mTiltXCenter = 0;
-        mTiltXScale = 0;
-        mTiltYCenter = 0;
-        mTiltYScale = 0;
-        mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
-        if (mHaveTilt) {
-            mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue, mRawPointerAxes.tiltX.maxValue);
-            mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue, mRawPointerAxes.tiltY.maxValue);
-            mTiltXScale = M_PI / 180;
-            mTiltYScale = M_PI / 180;
-
-            mOrientedRanges.haveTilt = true;
-
-            mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
-            mOrientedRanges.tilt.source = mSource;
-            mOrientedRanges.tilt.min = 0;
-            mOrientedRanges.tilt.max = M_PI_2;
-            mOrientedRanges.tilt.flat = 0;
-            mOrientedRanges.tilt.fuzz = 0;
-            mOrientedRanges.tilt.resolution = 0;
-        }
-
-        // Orientation
-        mOrientationScale = 0;
-        if (mHaveTilt) {
-            mOrientedRanges.haveOrientation = true;
-
-            mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
-            mOrientedRanges.orientation.source = mSource;
-            mOrientedRanges.orientation.min = -M_PI;
-            mOrientedRanges.orientation.max = M_PI;
-            mOrientedRanges.orientation.flat = 0;
-            mOrientedRanges.orientation.fuzz = 0;
-            mOrientedRanges.orientation.resolution = 0;
-        } else if (mCalibration.orientationCalibration !=
-                   Calibration::ORIENTATION_CALIBRATION_NONE) {
-            if (mCalibration.orientationCalibration ==
-                Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
-                if (mRawPointerAxes.orientation.valid) {
-                    if (mRawPointerAxes.orientation.maxValue > 0) {
-                        mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
-                    } else if (mRawPointerAxes.orientation.minValue < 0) {
-                        mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue;
-                    } else {
-                        mOrientationScale = 0;
-                    }
-                }
-            }
-
-            mOrientedRanges.haveOrientation = true;
-
-            mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
-            mOrientedRanges.orientation.source = mSource;
-            mOrientedRanges.orientation.min = -M_PI_2;
-            mOrientedRanges.orientation.max = M_PI_2;
-            mOrientedRanges.orientation.flat = 0;
-            mOrientedRanges.orientation.fuzz = 0;
-            mOrientedRanges.orientation.resolution = 0;
-        }
-
-        // Distance
-        mDistanceScale = 0;
-        if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
-            if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_SCALED) {
-                if (mCalibration.haveDistanceScale) {
-                    mDistanceScale = mCalibration.distanceScale;
-                } else {
-                    mDistanceScale = 1.0f;
-                }
-            }
-
-            mOrientedRanges.haveDistance = true;
-
-            mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
-            mOrientedRanges.distance.source = mSource;
-            mOrientedRanges.distance.min = mRawPointerAxes.distance.minValue * mDistanceScale;
-            mOrientedRanges.distance.max = mRawPointerAxes.distance.maxValue * mDistanceScale;
-            mOrientedRanges.distance.flat = 0;
-            mOrientedRanges.distance.fuzz = mRawPointerAxes.distance.fuzz * mDistanceScale;
-            mOrientedRanges.distance.resolution = 0;
-        }
-
-        // Compute oriented precision, scales and ranges.
-        // Note that the maximum value reported is an inclusive maximum value so it is one
-        // unit less than the total width or height of surface.
-        switch (mSurfaceOrientation) {
-            case DISPLAY_ORIENTATION_90:
-            case DISPLAY_ORIENTATION_270:
-                mOrientedXPrecision = mYPrecision;
-                mOrientedYPrecision = mXPrecision;
-
-                mOrientedRanges.x.min = mYTranslate;
-                mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1;
-                mOrientedRanges.x.flat = 0;
-                mOrientedRanges.x.fuzz = 0;
-                mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale;
-
-                mOrientedRanges.y.min = mXTranslate;
-                mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1;
-                mOrientedRanges.y.flat = 0;
-                mOrientedRanges.y.fuzz = 0;
-                mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale;
-                break;
-
-            default:
-                mOrientedXPrecision = mXPrecision;
-                mOrientedYPrecision = mYPrecision;
-
-                mOrientedRanges.x.min = mXTranslate;
-                mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1;
-                mOrientedRanges.x.flat = 0;
-                mOrientedRanges.x.fuzz = 0;
-                mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale;
-
-                mOrientedRanges.y.min = mYTranslate;
-                mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1;
-                mOrientedRanges.y.flat = 0;
-                mOrientedRanges.y.fuzz = 0;
-                mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale;
-                break;
-        }
-
-        // Location
-        updateAffineTransformation();
-
-        if (mDeviceMode == DEVICE_MODE_POINTER) {
-            // Compute pointer gesture detection parameters.
-            float rawDiagonal = hypotf(rawWidth, rawHeight);
-            float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight);
-
-            // Scale movements such that one whole swipe of the touch pad covers a
-            // given area relative to the diagonal size of the display when no acceleration
-            // is applied.
-            // Assume that the touch pad has a square aspect ratio such that movements in
-            // X and Y of the same number of raw units cover the same physical distance.
-            mPointerXMovementScale =
-                    mConfig.pointerGestureMovementSpeedRatio * displayDiagonal / rawDiagonal;
-            mPointerYMovementScale = mPointerXMovementScale;
-
-            // Scale zooms to cover a smaller range of the display than movements do.
-            // This value determines the area around the pointer that is affected by freeform
-            // pointer gestures.
-            mPointerXZoomScale =
-                    mConfig.pointerGestureZoomSpeedRatio * displayDiagonal / rawDiagonal;
-            mPointerYZoomScale = mPointerXZoomScale;
-
-            // Max width between pointers to detect a swipe gesture is more than some fraction
-            // of the diagonal axis of the touch pad.  Touches that are wider than this are
-            // translated into freeform gestures.
-            mPointerGestureMaxSwipeWidth = mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
-
-            // Abort current pointer usages because the state has changed.
-            abortPointerUsage(when, 0 /*policyFlags*/);
-        }
-
-        // Inform the dispatcher about the changes.
-        *outResetNeeded = true;
-        bumpGeneration();
-    }
-}
-
-void TouchInputMapper::dumpSurface(std::string& dump) {
-    dump += StringPrintf(INDENT3 "%s\n", mViewport.toString().c_str());
-    dump += StringPrintf(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
-    dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
-    dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
-    dump += StringPrintf(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
-    dump += StringPrintf(INDENT3 "PhysicalWidth: %dpx\n", mPhysicalWidth);
-    dump += StringPrintf(INDENT3 "PhysicalHeight: %dpx\n", mPhysicalHeight);
-    dump += StringPrintf(INDENT3 "PhysicalLeft: %d\n", mPhysicalLeft);
-    dump += StringPrintf(INDENT3 "PhysicalTop: %d\n", mPhysicalTop);
-    dump += StringPrintf(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
-}
-
-void TouchInputMapper::configureVirtualKeys() {
-    std::vector<VirtualKeyDefinition> virtualKeyDefinitions;
-    getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
-
-    mVirtualKeys.clear();
-
-    if (virtualKeyDefinitions.size() == 0) {
-        return;
-    }
-
-    int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
-    int32_t touchScreenTop = mRawPointerAxes.y.minValue;
-    int32_t touchScreenWidth = mRawPointerAxes.getRawWidth();
-    int32_t touchScreenHeight = mRawPointerAxes.getRawHeight();
-
-    for (const VirtualKeyDefinition& virtualKeyDefinition : virtualKeyDefinitions) {
-        VirtualKey virtualKey;
-
-        virtualKey.scanCode = virtualKeyDefinition.scanCode;
-        int32_t keyCode;
-        int32_t dummyKeyMetaState;
-        uint32_t flags;
-        if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, 0, &keyCode,
-                                  &dummyKeyMetaState, &flags)) {
-            ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode);
-            continue; // drop the key
-        }
-
-        virtualKey.keyCode = keyCode;
-        virtualKey.flags = flags;
-
-        // convert the key definition's display coordinates into touch coordinates for a hit box
-        int32_t halfWidth = virtualKeyDefinition.width / 2;
-        int32_t halfHeight = virtualKeyDefinition.height / 2;
-
-        virtualKey.hitLeft =
-                (virtualKeyDefinition.centerX - halfWidth) * touchScreenWidth / mSurfaceWidth +
-                touchScreenLeft;
-        virtualKey.hitRight =
-                (virtualKeyDefinition.centerX + halfWidth) * touchScreenWidth / mSurfaceWidth +
-                touchScreenLeft;
-        virtualKey.hitTop =
-                (virtualKeyDefinition.centerY - halfHeight) * touchScreenHeight / mSurfaceHeight +
-                touchScreenTop;
-        virtualKey.hitBottom =
-                (virtualKeyDefinition.centerY + halfHeight) * touchScreenHeight / mSurfaceHeight +
-                touchScreenTop;
-        mVirtualKeys.push_back(virtualKey);
-    }
-}
-
-void TouchInputMapper::dumpVirtualKeys(std::string& dump) {
-    if (!mVirtualKeys.empty()) {
-        dump += INDENT3 "Virtual Keys:\n";
-
-        for (size_t i = 0; i < mVirtualKeys.size(); i++) {
-            const VirtualKey& virtualKey = mVirtualKeys[i];
-            dump += StringPrintf(INDENT4 "%zu: scanCode=%d, keyCode=%d, "
-                                         "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
-                                 i, virtualKey.scanCode, virtualKey.keyCode, virtualKey.hitLeft,
-                                 virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
-        }
-    }
-}
-
-void TouchInputMapper::parseCalibration() {
-    const PropertyMap& in = getDevice()->getConfiguration();
-    Calibration& out = mCalibration;
-
-    // Size
-    out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
-    String8 sizeCalibrationString;
-    if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
-        if (sizeCalibrationString == "none") {
-            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
-        } else if (sizeCalibrationString == "geometric") {
-            out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
-        } else if (sizeCalibrationString == "diameter") {
-            out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
-        } else if (sizeCalibrationString == "box") {
-            out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX;
-        } else if (sizeCalibrationString == "area") {
-            out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
-        } else if (sizeCalibrationString != "default") {
-            ALOGW("Invalid value for touch.size.calibration: '%s'", sizeCalibrationString.string());
-        }
-    }
-
-    out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"), out.sizeScale);
-    out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"), out.sizeBias);
-    out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"), out.sizeIsSummed);
-
-    // Pressure
-    out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
-    String8 pressureCalibrationString;
-    if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
-        if (pressureCalibrationString == "none") {
-            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
-        } else if (pressureCalibrationString == "physical") {
-            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
-        } else if (pressureCalibrationString == "amplitude") {
-            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
-        } else if (pressureCalibrationString != "default") {
-            ALOGW("Invalid value for touch.pressure.calibration: '%s'",
-                  pressureCalibrationString.string());
-        }
-    }
-
-    out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"), out.pressureScale);
-
-    // Orientation
-    out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
-    String8 orientationCalibrationString;
-    if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
-        if (orientationCalibrationString == "none") {
-            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
-        } else if (orientationCalibrationString == "interpolated") {
-            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
-        } else if (orientationCalibrationString == "vector") {
-            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
-        } else if (orientationCalibrationString != "default") {
-            ALOGW("Invalid value for touch.orientation.calibration: '%s'",
-                  orientationCalibrationString.string());
-        }
-    }
-
-    // Distance
-    out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
-    String8 distanceCalibrationString;
-    if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
-        if (distanceCalibrationString == "none") {
-            out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
-        } else if (distanceCalibrationString == "scaled") {
-            out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
-        } else if (distanceCalibrationString != "default") {
-            ALOGW("Invalid value for touch.distance.calibration: '%s'",
-                  distanceCalibrationString.string());
-        }
-    }
-
-    out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"), out.distanceScale);
-
-    out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT;
-    String8 coverageCalibrationString;
-    if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) {
-        if (coverageCalibrationString == "none") {
-            out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
-        } else if (coverageCalibrationString == "box") {
-            out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX;
-        } else if (coverageCalibrationString != "default") {
-            ALOGW("Invalid value for touch.coverage.calibration: '%s'",
-                  coverageCalibrationString.string());
-        }
-    }
-}
-
-void TouchInputMapper::resolveCalibration() {
-    // Size
-    if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
-        if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) {
-            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
-        }
-    } else {
-        mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
-    }
-
-    // Pressure
-    if (mRawPointerAxes.pressure.valid) {
-        if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) {
-            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
-        }
-    } else {
-        mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
-    }
-
-    // Orientation
-    if (mRawPointerAxes.orientation.valid) {
-        if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) {
-            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
-        }
-    } else {
-        mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
-    }
-
-    // Distance
-    if (mRawPointerAxes.distance.valid) {
-        if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) {
-            mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
-        }
-    } else {
-        mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
-    }
-
-    // Coverage
-    if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) {
-        mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
-    }
-}
-
-void TouchInputMapper::dumpCalibration(std::string& dump) {
-    dump += INDENT3 "Calibration:\n";
-
-    // Size
-    switch (mCalibration.sizeCalibration) {
-        case Calibration::SIZE_CALIBRATION_NONE:
-            dump += INDENT4 "touch.size.calibration: none\n";
-            break;
-        case Calibration::SIZE_CALIBRATION_GEOMETRIC:
-            dump += INDENT4 "touch.size.calibration: geometric\n";
-            break;
-        case Calibration::SIZE_CALIBRATION_DIAMETER:
-            dump += INDENT4 "touch.size.calibration: diameter\n";
-            break;
-        case Calibration::SIZE_CALIBRATION_BOX:
-            dump += INDENT4 "touch.size.calibration: box\n";
-            break;
-        case Calibration::SIZE_CALIBRATION_AREA:
-            dump += INDENT4 "touch.size.calibration: area\n";
-            break;
-        default:
-            ALOG_ASSERT(false);
-    }
-
-    if (mCalibration.haveSizeScale) {
-        dump += StringPrintf(INDENT4 "touch.size.scale: %0.3f\n", mCalibration.sizeScale);
-    }
-
-    if (mCalibration.haveSizeBias) {
-        dump += StringPrintf(INDENT4 "touch.size.bias: %0.3f\n", mCalibration.sizeBias);
-    }
-
-    if (mCalibration.haveSizeIsSummed) {
-        dump += StringPrintf(INDENT4 "touch.size.isSummed: %s\n",
-                             toString(mCalibration.sizeIsSummed));
-    }
-
-    // Pressure
-    switch (mCalibration.pressureCalibration) {
-        case Calibration::PRESSURE_CALIBRATION_NONE:
-            dump += INDENT4 "touch.pressure.calibration: none\n";
-            break;
-        case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
-            dump += INDENT4 "touch.pressure.calibration: physical\n";
-            break;
-        case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
-            dump += INDENT4 "touch.pressure.calibration: amplitude\n";
-            break;
-        default:
-            ALOG_ASSERT(false);
-    }
-
-    if (mCalibration.havePressureScale) {
-        dump += StringPrintf(INDENT4 "touch.pressure.scale: %0.3f\n", mCalibration.pressureScale);
-    }
-
-    // Orientation
-    switch (mCalibration.orientationCalibration) {
-        case Calibration::ORIENTATION_CALIBRATION_NONE:
-            dump += INDENT4 "touch.orientation.calibration: none\n";
-            break;
-        case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
-            dump += INDENT4 "touch.orientation.calibration: interpolated\n";
-            break;
-        case Calibration::ORIENTATION_CALIBRATION_VECTOR:
-            dump += INDENT4 "touch.orientation.calibration: vector\n";
-            break;
-        default:
-            ALOG_ASSERT(false);
-    }
-
-    // Distance
-    switch (mCalibration.distanceCalibration) {
-        case Calibration::DISTANCE_CALIBRATION_NONE:
-            dump += INDENT4 "touch.distance.calibration: none\n";
-            break;
-        case Calibration::DISTANCE_CALIBRATION_SCALED:
-            dump += INDENT4 "touch.distance.calibration: scaled\n";
-            break;
-        default:
-            ALOG_ASSERT(false);
-    }
-
-    if (mCalibration.haveDistanceScale) {
-        dump += StringPrintf(INDENT4 "touch.distance.scale: %0.3f\n", mCalibration.distanceScale);
-    }
-
-    switch (mCalibration.coverageCalibration) {
-        case Calibration::COVERAGE_CALIBRATION_NONE:
-            dump += INDENT4 "touch.coverage.calibration: none\n";
-            break;
-        case Calibration::COVERAGE_CALIBRATION_BOX:
-            dump += INDENT4 "touch.coverage.calibration: box\n";
-            break;
-        default:
-            ALOG_ASSERT(false);
-    }
-}
-
-void TouchInputMapper::dumpAffineTransformation(std::string& dump) {
-    dump += INDENT3 "Affine Transformation:\n";
-
-    dump += StringPrintf(INDENT4 "X scale: %0.3f\n", mAffineTransform.x_scale);
-    dump += StringPrintf(INDENT4 "X ymix: %0.3f\n", mAffineTransform.x_ymix);
-    dump += StringPrintf(INDENT4 "X offset: %0.3f\n", mAffineTransform.x_offset);
-    dump += StringPrintf(INDENT4 "Y xmix: %0.3f\n", mAffineTransform.y_xmix);
-    dump += StringPrintf(INDENT4 "Y scale: %0.3f\n", mAffineTransform.y_scale);
-    dump += StringPrintf(INDENT4 "Y offset: %0.3f\n", mAffineTransform.y_offset);
-}
-
-void TouchInputMapper::updateAffineTransformation() {
-    mAffineTransform = getPolicy()->getTouchAffineTransformation(mDevice->getDescriptor(),
-                                                                 mSurfaceOrientation);
-}
-
-void TouchInputMapper::reset(nsecs_t when) {
-    mCursorButtonAccumulator.reset(getDevice());
-    mCursorScrollAccumulator.reset(getDevice());
-    mTouchButtonAccumulator.reset(getDevice());
-
-    mPointerVelocityControl.reset();
-    mWheelXVelocityControl.reset();
-    mWheelYVelocityControl.reset();
-
-    mRawStatesPending.clear();
-    mCurrentRawState.clear();
-    mCurrentCookedState.clear();
-    mLastRawState.clear();
-    mLastCookedState.clear();
-    mPointerUsage = POINTER_USAGE_NONE;
-    mSentHoverEnter = false;
-    mHavePointerIds = false;
-    mCurrentMotionAborted = false;
-    mDownTime = 0;
-
-    mCurrentVirtualKey.down = false;
-
-    mPointerGesture.reset();
-    mPointerSimple.reset();
-    resetExternalStylus();
-
-    if (mPointerController != nullptr) {
-        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
-        mPointerController->clearSpots();
-    }
-
-    InputMapper::reset(when);
-}
-
-void TouchInputMapper::resetExternalStylus() {
-    mExternalStylusState.clear();
-    mExternalStylusId = -1;
-    mExternalStylusFusionTimeout = LLONG_MAX;
-    mExternalStylusDataPending = false;
-}
-
-void TouchInputMapper::clearStylusDataPendingFlags() {
-    mExternalStylusDataPending = false;
-    mExternalStylusFusionTimeout = LLONG_MAX;
-}
-
-void TouchInputMapper::reportEventForStatistics(nsecs_t evdevTime) {
-    nsecs_t now = systemTime(CLOCK_MONOTONIC);
-    nsecs_t latency = now - evdevTime;
-    mStatistics.addValue(nanoseconds_to_microseconds(latency));
-    nsecs_t timeSinceLastReport = now - mStatistics.lastReportTime;
-    if (timeSinceLastReport > STATISTICS_REPORT_FREQUENCY) {
-        android::util::stats_write(android::util::TOUCH_EVENT_REPORTED, mStatistics.min,
-                                   mStatistics.max, mStatistics.mean(), mStatistics.stdev(),
-                                   mStatistics.count);
-        mStatistics.reset(now);
-    }
-}
-
-void TouchInputMapper::process(const RawEvent* rawEvent) {
-    mCursorButtonAccumulator.process(rawEvent);
-    mCursorScrollAccumulator.process(rawEvent);
-    mTouchButtonAccumulator.process(rawEvent);
-
-    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
-        reportEventForStatistics(rawEvent->when);
-        sync(rawEvent->when);
-    }
-}
-
-void TouchInputMapper::sync(nsecs_t when) {
-    const RawState* last =
-            mRawStatesPending.empty() ? &mCurrentRawState : &mRawStatesPending.back();
-
-    // Push a new state.
-    mRawStatesPending.emplace_back();
-
-    RawState* next = &mRawStatesPending.back();
-    next->clear();
-    next->when = when;
-
-    // Sync button state.
-    next->buttonState =
-            mTouchButtonAccumulator.getButtonState() | mCursorButtonAccumulator.getButtonState();
-
-    // Sync scroll
-    next->rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
-    next->rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
-    mCursorScrollAccumulator.finishSync();
-
-    // Sync touch
-    syncTouch(when, next);
-
-    // Assign pointer ids.
-    if (!mHavePointerIds) {
-        assignPointerIds(last, next);
-    }
-
-#if DEBUG_RAW_EVENTS
-    ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
-          "hovering ids 0x%08x -> 0x%08x",
-          last->rawPointerData.pointerCount, next->rawPointerData.pointerCount,
-          last->rawPointerData.touchingIdBits.value, next->rawPointerData.touchingIdBits.value,
-          last->rawPointerData.hoveringIdBits.value, next->rawPointerData.hoveringIdBits.value);
-#endif
-
-    processRawTouches(false /*timeout*/);
-}
-
-void TouchInputMapper::processRawTouches(bool timeout) {
-    if (mDeviceMode == DEVICE_MODE_DISABLED) {
-        // Drop all input if the device is disabled.
-        mCurrentRawState.clear();
-        mRawStatesPending.clear();
-        return;
-    }
-
-    // Drain any pending touch states. The invariant here is that the mCurrentRawState is always
-    // valid and must go through the full cook and dispatch cycle. This ensures that anything
-    // touching the current state will only observe the events that have been dispatched to the
-    // rest of the pipeline.
-    const size_t N = mRawStatesPending.size();
-    size_t count;
-    for (count = 0; count < N; count++) {
-        const RawState& next = mRawStatesPending[count];
-
-        // A failure to assign the stylus id means that we're waiting on stylus data
-        // and so should defer the rest of the pipeline.
-        if (assignExternalStylusId(next, timeout)) {
-            break;
-        }
-
-        // All ready to go.
-        clearStylusDataPendingFlags();
-        mCurrentRawState.copyFrom(next);
-        if (mCurrentRawState.when < mLastRawState.when) {
-            mCurrentRawState.when = mLastRawState.when;
-        }
-        cookAndDispatch(mCurrentRawState.when);
-    }
-    if (count != 0) {
-        mRawStatesPending.erase(mRawStatesPending.begin(), mRawStatesPending.begin() + count);
-    }
-
-    if (mExternalStylusDataPending) {
-        if (timeout) {
-            nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;
-            clearStylusDataPendingFlags();
-            mCurrentRawState.copyFrom(mLastRawState);
-#if DEBUG_STYLUS_FUSION
-            ALOGD("Timeout expired, synthesizing event with new stylus data");
-#endif
-            cookAndDispatch(when);
-        } else if (mExternalStylusFusionTimeout == LLONG_MAX) {
-            mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;
-            getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
-        }
-    }
-}
-
-void TouchInputMapper::cookAndDispatch(nsecs_t when) {
-    // Always start with a clean state.
-    mCurrentCookedState.clear();
-
-    // Apply stylus buttons to current raw state.
-    applyExternalStylusButtonState(when);
-
-    // Handle policy on initial down or hover events.
-    bool initialDown = mLastRawState.rawPointerData.pointerCount == 0 &&
-            mCurrentRawState.rawPointerData.pointerCount != 0;
-
-    uint32_t policyFlags = 0;
-    bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
-    if (initialDown || buttonsPressed) {
-        // If this is a touch screen, hide the pointer on an initial down.
-        if (mDeviceMode == DEVICE_MODE_DIRECT) {
-            getContext()->fadePointer();
-        }
-
-        if (mParameters.wake) {
-            policyFlags |= POLICY_FLAG_WAKE;
-        }
-    }
-
-    // Consume raw off-screen touches before cooking pointer data.
-    // If touches are consumed, subsequent code will not receive any pointer data.
-    if (consumeRawTouches(when, policyFlags)) {
-        mCurrentRawState.rawPointerData.clear();
-    }
-
-    // Cook pointer data.  This call populates the mCurrentCookedState.cookedPointerData structure
-    // with cooked pointer data that has the same ids and indices as the raw data.
-    // The following code can use either the raw or cooked data, as needed.
-    cookPointerData();
-
-    // Apply stylus pressure to current cooked state.
-    applyExternalStylusTouchState(when);
-
-    // Synthesize key down from raw buttons if needed.
-    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
-                         mViewport.displayId, policyFlags, mLastCookedState.buttonState,
-                         mCurrentCookedState.buttonState);
-
-    // Dispatch the touches either directly or by translation through a pointer on screen.
-    if (mDeviceMode == DEVICE_MODE_POINTER) {
-        for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits); !idBits.isEmpty();) {
-            uint32_t id = idBits.clearFirstMarkedBit();
-            const RawPointerData::Pointer& pointer =
-                    mCurrentRawState.rawPointerData.pointerForId(id);
-            if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS ||
-                pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
-                mCurrentCookedState.stylusIdBits.markBit(id);
-            } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER ||
-                       pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
-                mCurrentCookedState.fingerIdBits.markBit(id);
-            } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
-                mCurrentCookedState.mouseIdBits.markBit(id);
-            }
-        }
-        for (BitSet32 idBits(mCurrentRawState.rawPointerData.hoveringIdBits); !idBits.isEmpty();) {
-            uint32_t id = idBits.clearFirstMarkedBit();
-            const RawPointerData::Pointer& pointer =
-                    mCurrentRawState.rawPointerData.pointerForId(id);
-            if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS ||
-                pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
-                mCurrentCookedState.stylusIdBits.markBit(id);
-            }
-        }
-
-        // Stylus takes precedence over all tools, then mouse, then finger.
-        PointerUsage pointerUsage = mPointerUsage;
-        if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
-            mCurrentCookedState.mouseIdBits.clear();
-            mCurrentCookedState.fingerIdBits.clear();
-            pointerUsage = POINTER_USAGE_STYLUS;
-        } else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
-            mCurrentCookedState.fingerIdBits.clear();
-            pointerUsage = POINTER_USAGE_MOUSE;
-        } else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||
-                   isPointerDown(mCurrentRawState.buttonState)) {
-            pointerUsage = POINTER_USAGE_GESTURES;
-        }
-
-        dispatchPointerUsage(when, policyFlags, pointerUsage);
-    } else {
-        if (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches &&
-            mPointerController != nullptr) {
-            mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
-            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
-
-            mPointerController->setButtonState(mCurrentRawState.buttonState);
-            mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
-                                         mCurrentCookedState.cookedPointerData.idToIndex,
-                                         mCurrentCookedState.cookedPointerData.touchingIdBits,
-                                         mViewport.displayId);
-        }
-
-        if (!mCurrentMotionAborted) {
-            dispatchButtonRelease(when, policyFlags);
-            dispatchHoverExit(when, policyFlags);
-            dispatchTouches(when, policyFlags);
-            dispatchHoverEnterAndMove(when, policyFlags);
-            dispatchButtonPress(when, policyFlags);
-        }
-
-        if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
-            mCurrentMotionAborted = false;
-        }
-    }
-
-    // Synthesize key up from raw buttons if needed.
-    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
-                         mViewport.displayId, policyFlags, mLastCookedState.buttonState,
-                         mCurrentCookedState.buttonState);
-
-    // Clear some transient state.
-    mCurrentRawState.rawVScroll = 0;
-    mCurrentRawState.rawHScroll = 0;
-
-    // Copy current touch to last touch in preparation for the next cycle.
-    mLastRawState.copyFrom(mCurrentRawState);
-    mLastCookedState.copyFrom(mCurrentCookedState);
-}
-
-void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) {
-    if (mDeviceMode == DEVICE_MODE_DIRECT && hasExternalStylus() && mExternalStylusId != -1) {
-        mCurrentRawState.buttonState |= mExternalStylusState.buttons;
-    }
-}
-
-void TouchInputMapper::applyExternalStylusTouchState(nsecs_t when) {
-    CookedPointerData& currentPointerData = mCurrentCookedState.cookedPointerData;
-    const CookedPointerData& lastPointerData = mLastCookedState.cookedPointerData;
-
-    if (mExternalStylusId != -1 && currentPointerData.isTouching(mExternalStylusId)) {
-        float pressure = mExternalStylusState.pressure;
-        if (pressure == 0.0f && lastPointerData.isTouching(mExternalStylusId)) {
-            const PointerCoords& coords = lastPointerData.pointerCoordsForId(mExternalStylusId);
-            pressure = coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
-        }
-        PointerCoords& coords = currentPointerData.editPointerCoordsWithId(mExternalStylusId);
-        coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
-
-        PointerProperties& properties =
-                currentPointerData.editPointerPropertiesWithId(mExternalStylusId);
-        if (mExternalStylusState.toolType != AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
-            properties.toolType = mExternalStylusState.toolType;
-        }
-    }
-}
-
-bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeout) {
-    if (mDeviceMode != DEVICE_MODE_DIRECT || !hasExternalStylus()) {
-        return false;
-    }
-
-    const bool initialDown = mLastRawState.rawPointerData.pointerCount == 0 &&
-            state.rawPointerData.pointerCount != 0;
-    if (initialDown) {
-        if (mExternalStylusState.pressure != 0.0f) {
-#if DEBUG_STYLUS_FUSION
-            ALOGD("Have both stylus and touch data, beginning fusion");
-#endif
-            mExternalStylusId = state.rawPointerData.touchingIdBits.firstMarkedBit();
-        } else if (timeout) {
-#if DEBUG_STYLUS_FUSION
-            ALOGD("Timeout expired, assuming touch is not a stylus.");
-#endif
-            resetExternalStylus();
-        } else {
-            if (mExternalStylusFusionTimeout == LLONG_MAX) {
-                mExternalStylusFusionTimeout = state.when + EXTERNAL_STYLUS_DATA_TIMEOUT;
-            }
-#if DEBUG_STYLUS_FUSION
-            ALOGD("No stylus data but stylus is connected, requesting timeout "
-                  "(%" PRId64 "ms)",
-                  mExternalStylusFusionTimeout);
-#endif
-            getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
-            return true;
-        }
-    }
-
-    // Check if the stylus pointer has gone up.
-    if (mExternalStylusId != -1 && !state.rawPointerData.touchingIdBits.hasBit(mExternalStylusId)) {
-#if DEBUG_STYLUS_FUSION
-        ALOGD("Stylus pointer is going up");
-#endif
-        mExternalStylusId = -1;
-    }
-
-    return false;
-}
-
-void TouchInputMapper::timeoutExpired(nsecs_t when) {
-    if (mDeviceMode == DEVICE_MODE_POINTER) {
-        if (mPointerUsage == POINTER_USAGE_GESTURES) {
-            dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
-        }
-    } else if (mDeviceMode == DEVICE_MODE_DIRECT) {
-        if (mExternalStylusFusionTimeout < when) {
-            processRawTouches(true /*timeout*/);
-        } else if (mExternalStylusFusionTimeout != LLONG_MAX) {
-            getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
-        }
-    }
-}
-
-void TouchInputMapper::updateExternalStylusState(const StylusState& state) {
-    mExternalStylusState.copyFrom(state);
-    if (mExternalStylusId != -1 || mExternalStylusFusionTimeout != LLONG_MAX) {
-        // We're either in the middle of a fused stream of data or we're waiting on data before
-        // dispatching the initial down, so go ahead and dispatch now that we have fresh stylus
-        // data.
-        mExternalStylusDataPending = true;
-        processRawTouches(false /*timeout*/);
-    }
-}
-
-bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) {
-    // Check for release of a virtual key.
-    if (mCurrentVirtualKey.down) {
-        if (mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
-            // Pointer went up while virtual key was down.
-            mCurrentVirtualKey.down = false;
-            if (!mCurrentVirtualKey.ignored) {
-#if DEBUG_VIRTUAL_KEYS
-                ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
-                      mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
-#endif
-                dispatchVirtualKey(when, policyFlags, AKEY_EVENT_ACTION_UP,
-                                   AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
-            }
-            return true;
-        }
-
-        if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
-            uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
-            const RawPointerData::Pointer& pointer =
-                    mCurrentRawState.rawPointerData.pointerForId(id);
-            const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
-            if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
-                // Pointer is still within the space of the virtual key.
-                return true;
-            }
-        }
-
-        // Pointer left virtual key area or another pointer also went down.
-        // Send key cancellation but do not consume the touch yet.
-        // This is useful when the user swipes through from the virtual key area
-        // into the main display surface.
-        mCurrentVirtualKey.down = false;
-        if (!mCurrentVirtualKey.ignored) {
-#if DEBUG_VIRTUAL_KEYS
-            ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d", mCurrentVirtualKey.keyCode,
-                  mCurrentVirtualKey.scanCode);
-#endif
-            dispatchVirtualKey(when, policyFlags, AKEY_EVENT_ACTION_UP,
-                               AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY |
-                                       AKEY_EVENT_FLAG_CANCELED);
-        }
-    }
-
-    if (mLastRawState.rawPointerData.touchingIdBits.isEmpty() &&
-        !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
-        // Pointer just went down.  Check for virtual key press or off-screen touches.
-        uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
-        const RawPointerData::Pointer& pointer = mCurrentRawState.rawPointerData.pointerForId(id);
-        if (!isPointInsideSurface(pointer.x, pointer.y)) {
-            // If exactly one pointer went down, check for virtual key hit.
-            // Otherwise we will drop the entire stroke.
-            if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
-                const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
-                if (virtualKey) {
-                    mCurrentVirtualKey.down = true;
-                    mCurrentVirtualKey.downTime = when;
-                    mCurrentVirtualKey.keyCode = virtualKey->keyCode;
-                    mCurrentVirtualKey.scanCode = virtualKey->scanCode;
-                    mCurrentVirtualKey.ignored =
-                            mContext->shouldDropVirtualKey(when, getDevice(), virtualKey->keyCode,
-                                                           virtualKey->scanCode);
-
-                    if (!mCurrentVirtualKey.ignored) {
-#if DEBUG_VIRTUAL_KEYS
-                        ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
-                              mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
-#endif
-                        dispatchVirtualKey(when, policyFlags, AKEY_EVENT_ACTION_DOWN,
-                                           AKEY_EVENT_FLAG_FROM_SYSTEM |
-                                                   AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
-                    }
-                }
-            }
-            return true;
-        }
-    }
-
-    // Disable all virtual key touches that happen within a short time interval of the
-    // most recent touch within the screen area.  The idea is to filter out stray
-    // virtual key presses when interacting with the touch screen.
-    //
-    // Problems we're trying to solve:
-    //
-    // 1. While scrolling a list or dragging the window shade, the user swipes down into a
-    //    virtual key area that is implemented by a separate touch panel and accidentally
-    //    triggers a virtual key.
-    //
-    // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
-    //    area and accidentally triggers a virtual key.  This often happens when virtual keys
-    //    are layed out below the screen near to where the on screen keyboard's space bar
-    //    is displayed.
-    if (mConfig.virtualKeyQuietTime > 0 &&
-        !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
-        mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
-    }
-    return false;
-}
-
-void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
-                                          int32_t keyEventAction, int32_t keyEventFlags) {
-    int32_t keyCode = mCurrentVirtualKey.keyCode;
-    int32_t scanCode = mCurrentVirtualKey.scanCode;
-    nsecs_t downTime = mCurrentVirtualKey.downTime;
-    int32_t metaState = mContext->getGlobalMetaState();
-    policyFlags |= POLICY_FLAG_VIRTUAL;
-
-    NotifyKeyArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), AINPUT_SOURCE_KEYBOARD,
-                       mViewport.displayId, policyFlags, keyEventAction, keyEventFlags, keyCode,
-                       scanCode, metaState, downTime);
-    getListener()->notifyKey(&args);
-}
-
-void TouchInputMapper::abortTouches(nsecs_t when, uint32_t policyFlags) {
-    BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
-    if (!currentIdBits.isEmpty()) {
-        int32_t metaState = getContext()->getGlobalMetaState();
-        int32_t buttonState = mCurrentCookedState.buttonState;
-        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState,
-                       buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
-                       mCurrentCookedState.deviceTimestamp,
-                       mCurrentCookedState.cookedPointerData.pointerProperties,
-                       mCurrentCookedState.cookedPointerData.pointerCoords,
-                       mCurrentCookedState.cookedPointerData.idToIndex, currentIdBits, -1,
-                       mOrientedXPrecision, mOrientedYPrecision, mDownTime);
-        mCurrentMotionAborted = true;
-    }
-}
-
-void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
-    BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
-    BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;
-    int32_t metaState = getContext()->getGlobalMetaState();
-    int32_t buttonState = mCurrentCookedState.buttonState;
-
-    if (currentIdBits == lastIdBits) {
-        if (!currentIdBits.isEmpty()) {
-            // No pointer id changes so this is a move event.
-            // The listener takes care of batching moves so we don't have to deal with that here.
-            dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
-                           buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
-                           mCurrentCookedState.deviceTimestamp,
-                           mCurrentCookedState.cookedPointerData.pointerProperties,
-                           mCurrentCookedState.cookedPointerData.pointerCoords,
-                           mCurrentCookedState.cookedPointerData.idToIndex, currentIdBits, -1,
-                           mOrientedXPrecision, mOrientedYPrecision, mDownTime);
-        }
-    } else {
-        // There may be pointers going up and pointers going down and pointers moving
-        // all at the same time.
-        BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
-        BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
-        BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
-        BitSet32 dispatchedIdBits(lastIdBits.value);
-
-        // Update last coordinates of pointers that have moved so that we observe the new
-        // pointer positions at the same time as other pointers that have just gone up.
-        bool moveNeeded =
-                updateMovedPointers(mCurrentCookedState.cookedPointerData.pointerProperties,
-                                    mCurrentCookedState.cookedPointerData.pointerCoords,
-                                    mCurrentCookedState.cookedPointerData.idToIndex,
-                                    mLastCookedState.cookedPointerData.pointerProperties,
-                                    mLastCookedState.cookedPointerData.pointerCoords,
-                                    mLastCookedState.cookedPointerData.idToIndex, moveIdBits);
-        if (buttonState != mLastCookedState.buttonState) {
-            moveNeeded = true;
-        }
-
-        // Dispatch pointer up events.
-        while (!upIdBits.isEmpty()) {
-            uint32_t upId = upIdBits.clearFirstMarkedBit();
-
-            dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_UP, 0, 0,
-                           metaState, buttonState, 0, mCurrentCookedState.deviceTimestamp,
-                           mLastCookedState.cookedPointerData.pointerProperties,
-                           mLastCookedState.cookedPointerData.pointerCoords,
-                           mLastCookedState.cookedPointerData.idToIndex, dispatchedIdBits, upId,
-                           mOrientedXPrecision, mOrientedYPrecision, mDownTime);
-            dispatchedIdBits.clearBit(upId);
-        }
-
-        // Dispatch move events if any of the remaining pointers moved from their old locations.
-        // Although applications receive new locations as part of individual pointer up
-        // events, they do not generally handle them except when presented in a move event.
-        if (moveNeeded && !moveIdBits.isEmpty()) {
-            ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
-            dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
-                           buttonState, 0, mCurrentCookedState.deviceTimestamp,
-                           mCurrentCookedState.cookedPointerData.pointerProperties,
-                           mCurrentCookedState.cookedPointerData.pointerCoords,
-                           mCurrentCookedState.cookedPointerData.idToIndex, dispatchedIdBits, -1,
-                           mOrientedXPrecision, mOrientedYPrecision, mDownTime);
-        }
-
-        // Dispatch pointer down events using the new pointer locations.
-        while (!downIdBits.isEmpty()) {
-            uint32_t downId = downIdBits.clearFirstMarkedBit();
-            dispatchedIdBits.markBit(downId);
-
-            if (dispatchedIdBits.count() == 1) {
-                // First pointer is going down.  Set down time.
-                mDownTime = when;
-            }
-
-            dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0,
-                           metaState, buttonState, 0, mCurrentCookedState.deviceTimestamp,
-                           mCurrentCookedState.cookedPointerData.pointerProperties,
-                           mCurrentCookedState.cookedPointerData.pointerCoords,
-                           mCurrentCookedState.cookedPointerData.idToIndex, dispatchedIdBits,
-                           downId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
-        }
-    }
-}
-
-void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
-    if (mSentHoverEnter &&
-        (mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty() ||
-         !mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty())) {
-        int32_t metaState = getContext()->getGlobalMetaState();
-        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState,
-                       mLastCookedState.buttonState, 0, mLastCookedState.deviceTimestamp,
-                       mLastCookedState.cookedPointerData.pointerProperties,
-                       mLastCookedState.cookedPointerData.pointerCoords,
-                       mLastCookedState.cookedPointerData.idToIndex,
-                       mLastCookedState.cookedPointerData.hoveringIdBits, -1, mOrientedXPrecision,
-                       mOrientedYPrecision, mDownTime);
-        mSentHoverEnter = false;
-    }
-}
-
-void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) {
-    if (mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty() &&
-        !mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()) {
-        int32_t metaState = getContext()->getGlobalMetaState();
-        if (!mSentHoverEnter) {
-            dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0,
-                           metaState, mCurrentRawState.buttonState, 0,
-                           mCurrentCookedState.deviceTimestamp,
-                           mCurrentCookedState.cookedPointerData.pointerProperties,
-                           mCurrentCookedState.cookedPointerData.pointerCoords,
-                           mCurrentCookedState.cookedPointerData.idToIndex,
-                           mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
-                           mOrientedXPrecision, mOrientedYPrecision, mDownTime);
-            mSentHoverEnter = true;
-        }
-
-        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
-                       mCurrentRawState.buttonState, 0, mCurrentCookedState.deviceTimestamp,
-                       mCurrentCookedState.cookedPointerData.pointerProperties,
-                       mCurrentCookedState.cookedPointerData.pointerCoords,
-                       mCurrentCookedState.cookedPointerData.idToIndex,
-                       mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
-                       mOrientedXPrecision, mOrientedYPrecision, mDownTime);
-    }
-}
-
-void TouchInputMapper::dispatchButtonRelease(nsecs_t when, uint32_t policyFlags) {
-    BitSet32 releasedButtons(mLastCookedState.buttonState & ~mCurrentCookedState.buttonState);
-    const BitSet32& idBits = findActiveIdBits(mLastCookedState.cookedPointerData);
-    const int32_t metaState = getContext()->getGlobalMetaState();
-    int32_t buttonState = mLastCookedState.buttonState;
-    while (!releasedButtons.isEmpty()) {
-        int32_t actionButton = BitSet32::valueForBit(releasedButtons.clearFirstMarkedBit());
-        buttonState &= ~actionButton;
-        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
-                       actionButton, 0, metaState, buttonState, 0,
-                       mCurrentCookedState.deviceTimestamp,
-                       mCurrentCookedState.cookedPointerData.pointerProperties,
-                       mCurrentCookedState.cookedPointerData.pointerCoords,
-                       mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
-                       mOrientedXPrecision, mOrientedYPrecision, mDownTime);
-    }
-}
-
-void TouchInputMapper::dispatchButtonPress(nsecs_t when, uint32_t policyFlags) {
-    BitSet32 pressedButtons(mCurrentCookedState.buttonState & ~mLastCookedState.buttonState);
-    const BitSet32& idBits = findActiveIdBits(mCurrentCookedState.cookedPointerData);
-    const int32_t metaState = getContext()->getGlobalMetaState();
-    int32_t buttonState = mLastCookedState.buttonState;
-    while (!pressedButtons.isEmpty()) {
-        int32_t actionButton = BitSet32::valueForBit(pressedButtons.clearFirstMarkedBit());
-        buttonState |= actionButton;
-        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton,
-                       0, metaState, buttonState, 0, mCurrentCookedState.deviceTimestamp,
-                       mCurrentCookedState.cookedPointerData.pointerProperties,
-                       mCurrentCookedState.cookedPointerData.pointerCoords,
-                       mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
-                       mOrientedXPrecision, mOrientedYPrecision, mDownTime);
-    }
-}
-
-const BitSet32& TouchInputMapper::findActiveIdBits(const CookedPointerData& cookedPointerData) {
-    if (!cookedPointerData.touchingIdBits.isEmpty()) {
-        return cookedPointerData.touchingIdBits;
-    }
-    return cookedPointerData.hoveringIdBits;
-}
-
-void TouchInputMapper::cookPointerData() {
-    uint32_t currentPointerCount = mCurrentRawState.rawPointerData.pointerCount;
-
-    mCurrentCookedState.cookedPointerData.clear();
-    mCurrentCookedState.deviceTimestamp = mCurrentRawState.deviceTimestamp;
-    mCurrentCookedState.cookedPointerData.pointerCount = currentPointerCount;
-    mCurrentCookedState.cookedPointerData.hoveringIdBits =
-            mCurrentRawState.rawPointerData.hoveringIdBits;
-    mCurrentCookedState.cookedPointerData.touchingIdBits =
-            mCurrentRawState.rawPointerData.touchingIdBits;
-
-    if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
-        mCurrentCookedState.buttonState = 0;
-    } else {
-        mCurrentCookedState.buttonState = mCurrentRawState.buttonState;
-    }
-
-    // Walk through the the active pointers and map device coordinates onto
-    // surface coordinates and adjust for display orientation.
-    for (uint32_t i = 0; i < currentPointerCount; i++) {
-        const RawPointerData::Pointer& in = mCurrentRawState.rawPointerData.pointers[i];
-
-        // Size
-        float touchMajor, touchMinor, toolMajor, toolMinor, size;
-        switch (mCalibration.sizeCalibration) {
-            case Calibration::SIZE_CALIBRATION_GEOMETRIC:
-            case Calibration::SIZE_CALIBRATION_DIAMETER:
-            case Calibration::SIZE_CALIBRATION_BOX:
-            case Calibration::SIZE_CALIBRATION_AREA:
-                if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
-                    touchMajor = in.touchMajor;
-                    touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
-                    toolMajor = in.toolMajor;
-                    toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
-                    size = mRawPointerAxes.touchMinor.valid ? avg(in.touchMajor, in.touchMinor)
-                                                            : in.touchMajor;
-                } else if (mRawPointerAxes.touchMajor.valid) {
-                    toolMajor = touchMajor = in.touchMajor;
-                    toolMinor = touchMinor =
-                            mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
-                    size = mRawPointerAxes.touchMinor.valid ? avg(in.touchMajor, in.touchMinor)
-                                                            : in.touchMajor;
-                } else if (mRawPointerAxes.toolMajor.valid) {
-                    touchMajor = toolMajor = in.toolMajor;
-                    touchMinor = toolMinor =
-                            mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
-                    size = mRawPointerAxes.toolMinor.valid ? avg(in.toolMajor, in.toolMinor)
-                                                           : in.toolMajor;
-                } else {
-                    ALOG_ASSERT(false,
-                                "No touch or tool axes.  "
-                                "Size calibration should have been resolved to NONE.");
-                    touchMajor = 0;
-                    touchMinor = 0;
-                    toolMajor = 0;
-                    toolMinor = 0;
-                    size = 0;
-                }
-
-                if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
-                    uint32_t touchingCount = mCurrentRawState.rawPointerData.touchingIdBits.count();
-                    if (touchingCount > 1) {
-                        touchMajor /= touchingCount;
-                        touchMinor /= touchingCount;
-                        toolMajor /= touchingCount;
-                        toolMinor /= touchingCount;
-                        size /= touchingCount;
-                    }
-                }
-
-                if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {
-                    touchMajor *= mGeometricScale;
-                    touchMinor *= mGeometricScale;
-                    toolMajor *= mGeometricScale;
-                    toolMinor *= mGeometricScale;
-                } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
-                    touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
-                    touchMinor = touchMajor;
-                    toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
-                    toolMinor = toolMajor;
-                } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {
-                    touchMinor = touchMajor;
-                    toolMinor = toolMajor;
-                }
-
-                mCalibration.applySizeScaleAndBias(&touchMajor);
-                mCalibration.applySizeScaleAndBias(&touchMinor);
-                mCalibration.applySizeScaleAndBias(&toolMajor);
-                mCalibration.applySizeScaleAndBias(&toolMinor);
-                size *= mSizeScale;
-                break;
-            default:
-                touchMajor = 0;
-                touchMinor = 0;
-                toolMajor = 0;
-                toolMinor = 0;
-                size = 0;
-                break;
-        }
-
-        // Pressure
-        float pressure;
-        switch (mCalibration.pressureCalibration) {
-            case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
-            case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
-                pressure = in.pressure * mPressureScale;
-                break;
-            default:
-                pressure = in.isHovering ? 0 : 1;
-                break;
-        }
-
-        // Tilt and Orientation
-        float tilt;
-        float orientation;
-        if (mHaveTilt) {
-            float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
-            float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
-            orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
-            tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
-        } else {
-            tilt = 0;
-
-            switch (mCalibration.orientationCalibration) {
-                case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
-                    orientation = in.orientation * mOrientationScale;
-                    break;
-                case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
-                    int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
-                    int32_t c2 = signExtendNybble(in.orientation & 0x0f);
-                    if (c1 != 0 || c2 != 0) {
-                        orientation = atan2f(c1, c2) * 0.5f;
-                        float confidence = hypotf(c1, c2);
-                        float scale = 1.0f + confidence / 16.0f;
-                        touchMajor *= scale;
-                        touchMinor /= scale;
-                        toolMajor *= scale;
-                        toolMinor /= scale;
-                    } else {
-                        orientation = 0;
-                    }
-                    break;
-                }
-                default:
-                    orientation = 0;
-            }
-        }
-
-        // Distance
-        float distance;
-        switch (mCalibration.distanceCalibration) {
-            case Calibration::DISTANCE_CALIBRATION_SCALED:
-                distance = in.distance * mDistanceScale;
-                break;
-            default:
-                distance = 0;
-        }
-
-        // Coverage
-        int32_t rawLeft, rawTop, rawRight, rawBottom;
-        switch (mCalibration.coverageCalibration) {
-            case Calibration::COVERAGE_CALIBRATION_BOX:
-                rawLeft = (in.toolMinor & 0xffff0000) >> 16;
-                rawRight = in.toolMinor & 0x0000ffff;
-                rawBottom = in.toolMajor & 0x0000ffff;
-                rawTop = (in.toolMajor & 0xffff0000) >> 16;
-                break;
-            default:
-                rawLeft = rawTop = rawRight = rawBottom = 0;
-                break;
-        }
-
-        // Adjust X,Y coords for device calibration
-        // TODO: Adjust coverage coords?
-        float xTransformed = in.x, yTransformed = in.y;
-        mAffineTransform.applyTo(xTransformed, yTransformed);
-
-        // Adjust X, Y, and coverage coords for surface orientation.
-        float x, y;
-        float left, top, right, bottom;
-
-        switch (mSurfaceOrientation) {
-            case DISPLAY_ORIENTATION_90:
-                x = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
-                y = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
-                left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
-                right = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
-                bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
-                top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
-                orientation -= M_PI_2;
-                if (mOrientedRanges.haveOrientation &&
-                    orientation < mOrientedRanges.orientation.min) {
-                    orientation +=
-                            (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
-                }
-                break;
-            case DISPLAY_ORIENTATION_180:
-                x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale;
-                y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
-                left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
-                right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
-                bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
-                top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
-                orientation -= M_PI;
-                if (mOrientedRanges.haveOrientation &&
-                    orientation < mOrientedRanges.orientation.min) {
-                    orientation +=
-                            (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
-                }
-                break;
-            case DISPLAY_ORIENTATION_270:
-                x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale;
-                y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
-                left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
-                right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
-                bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
-                top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
-                orientation += M_PI_2;
-                if (mOrientedRanges.haveOrientation &&
-                    orientation > mOrientedRanges.orientation.max) {
-                    orientation -=
-                            (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
-                }
-                break;
-            default:
-                x = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
-                y = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
-                left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
-                right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
-                bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
-                top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
-                break;
-        }
-
-        // Write output coords.
-        PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i];
-        out.clear();
-        out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
-        out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
-        out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
-        out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
-        out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
-        out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
-        out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
-        out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
-        out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
-        if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
-            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);
-            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);
-            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);
-            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom);
-        } else {
-            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
-            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
-        }
-
-        // Write output properties.
-        PointerProperties& properties = mCurrentCookedState.cookedPointerData.pointerProperties[i];
-        uint32_t id = in.id;
-        properties.clear();
-        properties.id = id;
-        properties.toolType = in.toolType;
-
-        // Write id index.
-        mCurrentCookedState.cookedPointerData.idToIndex[id] = i;
-    }
-}
-
-void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags,
-                                            PointerUsage pointerUsage) {
-    if (pointerUsage != mPointerUsage) {
-        abortPointerUsage(when, policyFlags);
-        mPointerUsage = pointerUsage;
-    }
-
-    switch (mPointerUsage) {
-        case POINTER_USAGE_GESTURES:
-            dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
-            break;
-        case POINTER_USAGE_STYLUS:
-            dispatchPointerStylus(when, policyFlags);
-            break;
-        case POINTER_USAGE_MOUSE:
-            dispatchPointerMouse(when, policyFlags);
-            break;
-        default:
-            break;
-    }
-}
-
-void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) {
-    switch (mPointerUsage) {
-        case POINTER_USAGE_GESTURES:
-            abortPointerGestures(when, policyFlags);
-            break;
-        case POINTER_USAGE_STYLUS:
-            abortPointerStylus(when, policyFlags);
-            break;
-        case POINTER_USAGE_MOUSE:
-            abortPointerMouse(when, policyFlags);
-            break;
-        default:
-            break;
-    }
-
-    mPointerUsage = POINTER_USAGE_NONE;
-}
-
-void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout) {
-    // Update current gesture coordinates.
-    bool cancelPreviousGesture, finishPreviousGesture;
-    bool sendEvents =
-            preparePointerGestures(when, &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
-    if (!sendEvents) {
-        return;
-    }
-    if (finishPreviousGesture) {
-        cancelPreviousGesture = false;
-    }
-
-    // Update the pointer presentation and spots.
-    if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
-        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
-        if (finishPreviousGesture || cancelPreviousGesture) {
-            mPointerController->clearSpots();
-        }
-
-        if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
-            mPointerController->setSpots(mPointerGesture.currentGestureCoords,
-                                         mPointerGesture.currentGestureIdToIndex,
-                                         mPointerGesture.currentGestureIdBits,
-                                         mPointerController->getDisplayId());
-        }
-    } else {
-        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
-    }
-
-    // Show or hide the pointer if needed.
-    switch (mPointerGesture.currentGestureMode) {
-        case PointerGesture::NEUTRAL:
-        case PointerGesture::QUIET:
-            if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH &&
-                mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) {
-                // Remind the user of where the pointer is after finishing a gesture with spots.
-                mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
-            }
-            break;
-        case PointerGesture::TAP:
-        case PointerGesture::TAP_DRAG:
-        case PointerGesture::BUTTON_CLICK_OR_DRAG:
-        case PointerGesture::HOVER:
-        case PointerGesture::PRESS:
-        case PointerGesture::SWIPE:
-            // Unfade the pointer when the current gesture manipulates the
-            // area directly under the pointer.
-            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
-            break;
-        case PointerGesture::FREEFORM:
-            // Fade the pointer when the current gesture manipulates a different
-            // area and there are spots to guide the user experience.
-            if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
-                mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
-            } else {
-                mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
-            }
-            break;
-    }
-
-    // Send events!
-    int32_t metaState = getContext()->getGlobalMetaState();
-    int32_t buttonState = mCurrentCookedState.buttonState;
-
-    // Update last coordinates of pointers that have moved so that we observe the new
-    // pointer positions at the same time as other pointers that have just gone up.
-    bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP ||
-            mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG ||
-            mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG ||
-            mPointerGesture.currentGestureMode == PointerGesture::PRESS ||
-            mPointerGesture.currentGestureMode == PointerGesture::SWIPE ||
-            mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
-    bool moveNeeded = false;
-    if (down && !cancelPreviousGesture && !finishPreviousGesture &&
-        !mPointerGesture.lastGestureIdBits.isEmpty() &&
-        !mPointerGesture.currentGestureIdBits.isEmpty()) {
-        BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value &
-                                    mPointerGesture.lastGestureIdBits.value);
-        moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
-                                         mPointerGesture.currentGestureCoords,
-                                         mPointerGesture.currentGestureIdToIndex,
-                                         mPointerGesture.lastGestureProperties,
-                                         mPointerGesture.lastGestureCoords,
-                                         mPointerGesture.lastGestureIdToIndex, movedGestureIdBits);
-        if (buttonState != mLastCookedState.buttonState) {
-            moveNeeded = true;
-        }
-    }
-
-    // Send motion events for all pointers that went up or were canceled.
-    BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
-    if (!dispatchedGestureIdBits.isEmpty()) {
-        if (cancelPreviousGesture) {
-            dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState,
-                           buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                           mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords,
-                           mPointerGesture.lastGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0,
-                           mPointerGesture.downTime);
-
-            dispatchedGestureIdBits.clear();
-        } else {
-            BitSet32 upGestureIdBits;
-            if (finishPreviousGesture) {
-                upGestureIdBits = dispatchedGestureIdBits;
-            } else {
-                upGestureIdBits.value =
-                        dispatchedGestureIdBits.value & ~mPointerGesture.currentGestureIdBits.value;
-            }
-            while (!upGestureIdBits.isEmpty()) {
-                uint32_t id = upGestureIdBits.clearFirstMarkedBit();
-
-                dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_UP, 0, 0,
-                               metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
-                               /* deviceTimestamp */ 0, mPointerGesture.lastGestureProperties,
-                               mPointerGesture.lastGestureCoords,
-                               mPointerGesture.lastGestureIdToIndex, dispatchedGestureIdBits, id, 0,
-                               0, mPointerGesture.downTime);
-
-                dispatchedGestureIdBits.clearBit(id);
-            }
-        }
-    }
-
-    // Send motion events for all pointers that moved.
-    if (moveNeeded) {
-        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
-                       buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                       mPointerGesture.currentGestureProperties,
-                       mPointerGesture.currentGestureCoords,
-                       mPointerGesture.currentGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0,
-                       mPointerGesture.downTime);
-    }
-
-    // Send motion events for all pointers that went down.
-    if (down) {
-        BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value &
-                                   ~dispatchedGestureIdBits.value);
-        while (!downGestureIdBits.isEmpty()) {
-            uint32_t id = downGestureIdBits.clearFirstMarkedBit();
-            dispatchedGestureIdBits.markBit(id);
-
-            if (dispatchedGestureIdBits.count() == 1) {
-                mPointerGesture.downTime = when;
-            }
-
-            dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0,
-                           metaState, buttonState, 0,
-                           /* deviceTimestamp */ 0, mPointerGesture.currentGestureProperties,
-                           mPointerGesture.currentGestureCoords,
-                           mPointerGesture.currentGestureIdToIndex, dispatchedGestureIdBits, id, 0,
-                           0, mPointerGesture.downTime);
-        }
-    }
-
-    // Send motion events for hover.
-    if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
-        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
-                       buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                       mPointerGesture.currentGestureProperties,
-                       mPointerGesture.currentGestureCoords,
-                       mPointerGesture.currentGestureIdToIndex,
-                       mPointerGesture.currentGestureIdBits, -1, 0, 0, mPointerGesture.downTime);
-    } else if (dispatchedGestureIdBits.isEmpty() && !mPointerGesture.lastGestureIdBits.isEmpty()) {
-        // Synthesize a hover move event after all pointers go up to indicate that
-        // the pointer is hovering again even if the user is not currently touching
-        // the touch pad.  This ensures that a view will receive a fresh hover enter
-        // event after a tap.
-        float x, y;
-        mPointerController->getPosition(&x, &y);
-
-        PointerProperties pointerProperties;
-        pointerProperties.clear();
-        pointerProperties.id = 0;
-        pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
-
-        PointerCoords pointerCoords;
-        pointerCoords.clear();
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
-
-        const int32_t displayId = mPointerController->getDisplayId();
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
-                              displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
-                              metaState, buttonState, MotionClassification::NONE,
-                              AMOTION_EVENT_EDGE_FLAG_NONE,
-                              /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, 0, 0,
-                              mPointerGesture.downTime, /* videoFrames */ {});
-        getListener()->notifyMotion(&args);
-    }
-
-    // Update state.
-    mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
-    if (!down) {
-        mPointerGesture.lastGestureIdBits.clear();
-    } else {
-        mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
-        for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty();) {
-            uint32_t id = idBits.clearFirstMarkedBit();
-            uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
-            mPointerGesture.lastGestureProperties[index].copyFrom(
-                    mPointerGesture.currentGestureProperties[index]);
-            mPointerGesture.lastGestureCoords[index].copyFrom(
-                    mPointerGesture.currentGestureCoords[index]);
-            mPointerGesture.lastGestureIdToIndex[id] = index;
-        }
-    }
-}
-
-void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) {
-    // Cancel previously dispatches pointers.
-    if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
-        int32_t metaState = getContext()->getGlobalMetaState();
-        int32_t buttonState = mCurrentRawState.buttonState;
-        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState,
-                       buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                       mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords,
-                       mPointerGesture.lastGestureIdToIndex, mPointerGesture.lastGestureIdBits, -1,
-                       0, 0, mPointerGesture.downTime);
-    }
-
-    // Reset the current pointer gesture.
-    mPointerGesture.reset();
-    mPointerVelocityControl.reset();
-
-    // Remove any current spots.
-    if (mPointerController != nullptr) {
-        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
-        mPointerController->clearSpots();
-    }
-}
-
-bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPreviousGesture,
-                                              bool* outFinishPreviousGesture, bool isTimeout) {
-    *outCancelPreviousGesture = false;
-    *outFinishPreviousGesture = false;
-
-    // Handle TAP timeout.
-    if (isTimeout) {
-#if DEBUG_GESTURES
-        ALOGD("Gestures: Processing timeout");
-#endif
-
-        if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
-            if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
-                // The tap/drag timeout has not yet expired.
-                getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime +
-                                                   mConfig.pointerGestureTapDragInterval);
-            } else {
-                // The tap is finished.
-#if DEBUG_GESTURES
-                ALOGD("Gestures: TAP finished");
-#endif
-                *outFinishPreviousGesture = true;
-
-                mPointerGesture.activeGestureId = -1;
-                mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
-                mPointerGesture.currentGestureIdBits.clear();
-
-                mPointerVelocityControl.reset();
-                return true;
-            }
-        }
-
-        // We did not handle this timeout.
-        return false;
-    }
-
-    const uint32_t currentFingerCount = mCurrentCookedState.fingerIdBits.count();
-    const uint32_t lastFingerCount = mLastCookedState.fingerIdBits.count();
-
-    // Update the velocity tracker.
-    {
-        VelocityTracker::Position positions[MAX_POINTERS];
-        uint32_t count = 0;
-        for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty(); count++) {
-            uint32_t id = idBits.clearFirstMarkedBit();
-            const RawPointerData::Pointer& pointer =
-                    mCurrentRawState.rawPointerData.pointerForId(id);
-            positions[count].x = pointer.x * mPointerXMovementScale;
-            positions[count].y = pointer.y * mPointerYMovementScale;
-        }
-        mPointerGesture.velocityTracker.addMovement(when, mCurrentCookedState.fingerIdBits,
-                                                    positions);
-    }
-
-    // If the gesture ever enters a mode other than TAP, HOVER or TAP_DRAG, without first returning
-    // to NEUTRAL, then we should not generate tap event.
-    if (mPointerGesture.lastGestureMode != PointerGesture::HOVER &&
-        mPointerGesture.lastGestureMode != PointerGesture::TAP &&
-        mPointerGesture.lastGestureMode != PointerGesture::TAP_DRAG) {
-        mPointerGesture.resetTap();
-    }
-
-    // Pick a new active touch id if needed.
-    // Choose an arbitrary pointer that just went down, if there is one.
-    // Otherwise choose an arbitrary remaining pointer.
-    // This guarantees we always have an active touch id when there is at least one pointer.
-    // We keep the same active touch id for as long as possible.
-    int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
-    int32_t activeTouchId = lastActiveTouchId;
-    if (activeTouchId < 0) {
-        if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
-            activeTouchId = mPointerGesture.activeTouchId =
-                    mCurrentCookedState.fingerIdBits.firstMarkedBit();
-            mPointerGesture.firstTouchTime = when;
-        }
-    } else if (!mCurrentCookedState.fingerIdBits.hasBit(activeTouchId)) {
-        if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
-            activeTouchId = mPointerGesture.activeTouchId =
-                    mCurrentCookedState.fingerIdBits.firstMarkedBit();
-        } else {
-            activeTouchId = mPointerGesture.activeTouchId = -1;
-        }
-    }
-
-    // Determine whether we are in quiet time.
-    bool isQuietTime = false;
-    if (activeTouchId < 0) {
-        mPointerGesture.resetQuietTime();
-    } else {
-        isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
-        if (!isQuietTime) {
-            if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS ||
-                 mPointerGesture.lastGestureMode == PointerGesture::SWIPE ||
-                 mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) &&
-                currentFingerCount < 2) {
-                // Enter quiet time when exiting swipe or freeform state.
-                // This is to prevent accidentally entering the hover state and flinging the
-                // pointer when finishing a swipe and there is still one pointer left onscreen.
-                isQuietTime = true;
-            } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG &&
-                       currentFingerCount >= 2 && !isPointerDown(mCurrentRawState.buttonState)) {
-                // Enter quiet time when releasing the button and there are still two or more
-                // fingers down.  This may indicate that one finger was used to press the button
-                // but it has not gone up yet.
-                isQuietTime = true;
-            }
-            if (isQuietTime) {
-                mPointerGesture.quietTime = when;
-            }
-        }
-    }
-
-    // Switch states based on button and pointer state.
-    if (isQuietTime) {
-        // Case 1: Quiet time. (QUIET)
-#if DEBUG_GESTURES
-        ALOGD("Gestures: QUIET for next %0.3fms",
-              (mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
-#endif
-        if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
-            *outFinishPreviousGesture = true;
-        }
-
-        mPointerGesture.activeGestureId = -1;
-        mPointerGesture.currentGestureMode = PointerGesture::QUIET;
-        mPointerGesture.currentGestureIdBits.clear();
-
-        mPointerVelocityControl.reset();
-    } else if (isPointerDown(mCurrentRawState.buttonState)) {
-        // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
-        // The pointer follows the active touch point.
-        // Emit DOWN, MOVE, UP events at the pointer location.
-        //
-        // Only the active touch matters; other fingers are ignored.  This policy helps
-        // to handle the case where the user places a second finger on the touch pad
-        // to apply the necessary force to depress an integrated button below the surface.
-        // We don't want the second finger to be delivered to applications.
-        //
-        // For this to work well, we need to make sure to track the pointer that is really
-        // active.  If the user first puts one finger down to click then adds another
-        // finger to drag then the active pointer should switch to the finger that is
-        // being dragged.
-#if DEBUG_GESTURES
-        ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
-              "currentFingerCount=%d",
-              activeTouchId, currentFingerCount);
-#endif
-        // Reset state when just starting.
-        if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
-            *outFinishPreviousGesture = true;
-            mPointerGesture.activeGestureId = 0;
-        }
-
-        // Switch pointers if needed.
-        // Find the fastest pointer and follow it.
-        if (activeTouchId >= 0 && currentFingerCount > 1) {
-            int32_t bestId = -1;
-            float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
-            for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty();) {
-                uint32_t id = idBits.clearFirstMarkedBit();
-                float vx, vy;
-                if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
-                    float speed = hypotf(vx, vy);
-                    if (speed > bestSpeed) {
-                        bestId = id;
-                        bestSpeed = speed;
-                    }
-                }
-            }
-            if (bestId >= 0 && bestId != activeTouchId) {
-                mPointerGesture.activeTouchId = activeTouchId = bestId;
-#if DEBUG_GESTURES
-                ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
-                      "bestId=%d, bestSpeed=%0.3f",
-                      bestId, bestSpeed);
-#endif
-            }
-        }
-
-        float deltaX = 0, deltaY = 0;
-        if (activeTouchId >= 0 && mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
-            const RawPointerData::Pointer& currentPointer =
-                    mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
-            const RawPointerData::Pointer& lastPointer =
-                    mLastRawState.rawPointerData.pointerForId(activeTouchId);
-            deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
-            deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
-
-            rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
-            mPointerVelocityControl.move(when, &deltaX, &deltaY);
-
-            // Move the pointer using a relative motion.
-            // When using spots, the click will occur at the position of the anchor
-            // spot and all other spots will move there.
-            mPointerController->move(deltaX, deltaY);
-        } else {
-            mPointerVelocityControl.reset();
-        }
-
-        float x, y;
-        mPointerController->getPosition(&x, &y);
-
-        mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
-        mPointerGesture.currentGestureIdBits.clear();
-        mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
-        mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
-        mPointerGesture.currentGestureProperties[0].clear();
-        mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
-        mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
-        mPointerGesture.currentGestureCoords[0].clear();
-        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
-        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
-        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
-    } else if (currentFingerCount == 0) {
-        // Case 3. No fingers down and button is not pressed. (NEUTRAL)
-        if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
-            *outFinishPreviousGesture = true;
-        }
-
-        // Watch for taps coming out of HOVER or TAP_DRAG mode.
-        // Checking for taps after TAP_DRAG allows us to detect double-taps.
-        bool tapped = false;
-        if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER ||
-             mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) &&
-            lastFingerCount == 1) {
-            if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
-                float x, y;
-                mPointerController->getPosition(&x, &y);
-                if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop &&
-                    fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
-#if DEBUG_GESTURES
-                    ALOGD("Gestures: TAP");
-#endif
-
-                    mPointerGesture.tapUpTime = when;
-                    getContext()->requestTimeoutAtTime(when +
-                                                       mConfig.pointerGestureTapDragInterval);
-
-                    mPointerGesture.activeGestureId = 0;
-                    mPointerGesture.currentGestureMode = PointerGesture::TAP;
-                    mPointerGesture.currentGestureIdBits.clear();
-                    mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
-                    mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
-                    mPointerGesture.currentGestureProperties[0].clear();
-                    mPointerGesture.currentGestureProperties[0].id =
-                            mPointerGesture.activeGestureId;
-                    mPointerGesture.currentGestureProperties[0].toolType =
-                            AMOTION_EVENT_TOOL_TYPE_FINGER;
-                    mPointerGesture.currentGestureCoords[0].clear();
-                    mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
-                                                                         mPointerGesture.tapX);
-                    mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
-                                                                         mPointerGesture.tapY);
-                    mPointerGesture.currentGestureCoords[0]
-                            .setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
-
-                    tapped = true;
-                } else {
-#if DEBUG_GESTURES
-                    ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f", x - mPointerGesture.tapX,
-                          y - mPointerGesture.tapY);
-#endif
-                }
-            } else {
-#if DEBUG_GESTURES
-                if (mPointerGesture.tapDownTime != LLONG_MIN) {
-                    ALOGD("Gestures: Not a TAP, %0.3fms since down",
-                          (when - mPointerGesture.tapDownTime) * 0.000001f);
-                } else {
-                    ALOGD("Gestures: Not a TAP, incompatible mode transitions");
-                }
-#endif
-            }
-        }
-
-        mPointerVelocityControl.reset();
-
-        if (!tapped) {
-#if DEBUG_GESTURES
-            ALOGD("Gestures: NEUTRAL");
-#endif
-            mPointerGesture.activeGestureId = -1;
-            mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
-            mPointerGesture.currentGestureIdBits.clear();
-        }
-    } else if (currentFingerCount == 1) {
-        // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
-        // The pointer follows the active touch point.
-        // When in HOVER, emit HOVER_MOVE events at the pointer location.
-        // When in TAP_DRAG, emit MOVE events at the pointer location.
-        ALOG_ASSERT(activeTouchId >= 0);
-
-        mPointerGesture.currentGestureMode = PointerGesture::HOVER;
-        if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
-            if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
-                float x, y;
-                mPointerController->getPosition(&x, &y);
-                if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop &&
-                    fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
-                    mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
-                } else {
-#if DEBUG_GESTURES
-                    ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
-                          x - mPointerGesture.tapX, y - mPointerGesture.tapY);
-#endif
-                }
-            } else {
-#if DEBUG_GESTURES
-                ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
-                      (when - mPointerGesture.tapUpTime) * 0.000001f);
-#endif
-            }
-        } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
-            mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
-        }
-
-        float deltaX = 0, deltaY = 0;
-        if (mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
-            const RawPointerData::Pointer& currentPointer =
-                    mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
-            const RawPointerData::Pointer& lastPointer =
-                    mLastRawState.rawPointerData.pointerForId(activeTouchId);
-            deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
-            deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
-
-            rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
-            mPointerVelocityControl.move(when, &deltaX, &deltaY);
-
-            // Move the pointer using a relative motion.
-            // When using spots, the hover or drag will occur at the position of the anchor spot.
-            mPointerController->move(deltaX, deltaY);
-        } else {
-            mPointerVelocityControl.reset();
-        }
-
-        bool down;
-        if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
-#if DEBUG_GESTURES
-            ALOGD("Gestures: TAP_DRAG");
-#endif
-            down = true;
-        } else {
-#if DEBUG_GESTURES
-            ALOGD("Gestures: HOVER");
-#endif
-            if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
-                *outFinishPreviousGesture = true;
-            }
-            mPointerGesture.activeGestureId = 0;
-            down = false;
-        }
-
-        float x, y;
-        mPointerController->getPosition(&x, &y);
-
-        mPointerGesture.currentGestureIdBits.clear();
-        mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
-        mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
-        mPointerGesture.currentGestureProperties[0].clear();
-        mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
-        mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
-        mPointerGesture.currentGestureCoords[0].clear();
-        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
-        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
-        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
-                                                             down ? 1.0f : 0.0f);
-
-        if (lastFingerCount == 0 && currentFingerCount != 0) {
-            mPointerGesture.resetTap();
-            mPointerGesture.tapDownTime = when;
-            mPointerGesture.tapX = x;
-            mPointerGesture.tapY = y;
-        }
-    } else {
-        // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
-        // We need to provide feedback for each finger that goes down so we cannot wait
-        // for the fingers to move before deciding what to do.
-        //
-        // The ambiguous case is deciding what to do when there are two fingers down but they
-        // have not moved enough to determine whether they are part of a drag or part of a
-        // freeform gesture, or just a press or long-press at the pointer location.
-        //
-        // When there are two fingers we start with the PRESS hypothesis and we generate a
-        // down at the pointer location.
-        //
-        // When the two fingers move enough or when additional fingers are added, we make
-        // a decision to transition into SWIPE or FREEFORM mode accordingly.
-        ALOG_ASSERT(activeTouchId >= 0);
-
-        bool settled = when >=
-                mPointerGesture.firstTouchTime + mConfig.pointerGestureMultitouchSettleInterval;
-        if (mPointerGesture.lastGestureMode != PointerGesture::PRESS &&
-            mPointerGesture.lastGestureMode != PointerGesture::SWIPE &&
-            mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
-            *outFinishPreviousGesture = true;
-        } else if (!settled && currentFingerCount > lastFingerCount) {
-            // Additional pointers have gone down but not yet settled.
-            // Reset the gesture.
-#if DEBUG_GESTURES
-            ALOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
-                  "settle time remaining %0.3fms",
-                  (mPointerGesture.firstTouchTime + mConfig.pointerGestureMultitouchSettleInterval -
-                   when) * 0.000001f);
-#endif
-            *outCancelPreviousGesture = true;
-        } else {
-            // Continue previous gesture.
-            mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
-        }
-
-        if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
-            mPointerGesture.currentGestureMode = PointerGesture::PRESS;
-            mPointerGesture.activeGestureId = 0;
-            mPointerGesture.referenceIdBits.clear();
-            mPointerVelocityControl.reset();
-
-            // Use the centroid and pointer location as the reference points for the gesture.
-#if DEBUG_GESTURES
-            ALOGD("Gestures: Using centroid as reference for MULTITOUCH, "
-                  "settle time remaining %0.3fms",
-                  (mPointerGesture.firstTouchTime + mConfig.pointerGestureMultitouchSettleInterval -
-                   when) * 0.000001f);
-#endif
-            mCurrentRawState.rawPointerData
-                    .getCentroidOfTouchingPointers(&mPointerGesture.referenceTouchX,
-                                                   &mPointerGesture.referenceTouchY);
-            mPointerController->getPosition(&mPointerGesture.referenceGestureX,
-                                            &mPointerGesture.referenceGestureY);
-        }
-
-        // Clear the reference deltas for fingers not yet included in the reference calculation.
-        for (BitSet32 idBits(mCurrentCookedState.fingerIdBits.value &
-                             ~mPointerGesture.referenceIdBits.value);
-             !idBits.isEmpty();) {
-            uint32_t id = idBits.clearFirstMarkedBit();
-            mPointerGesture.referenceDeltas[id].dx = 0;
-            mPointerGesture.referenceDeltas[id].dy = 0;
-        }
-        mPointerGesture.referenceIdBits = mCurrentCookedState.fingerIdBits;
-
-        // Add delta for all fingers and calculate a common movement delta.
-        float commonDeltaX = 0, commonDeltaY = 0;
-        BitSet32 commonIdBits(mLastCookedState.fingerIdBits.value &
-                              mCurrentCookedState.fingerIdBits.value);
-        for (BitSet32 idBits(commonIdBits); !idBits.isEmpty();) {
-            bool first = (idBits == commonIdBits);
-            uint32_t id = idBits.clearFirstMarkedBit();
-            const RawPointerData::Pointer& cpd = mCurrentRawState.rawPointerData.pointerForId(id);
-            const RawPointerData::Pointer& lpd = mLastRawState.rawPointerData.pointerForId(id);
-            PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
-            delta.dx += cpd.x - lpd.x;
-            delta.dy += cpd.y - lpd.y;
-
-            if (first) {
-                commonDeltaX = delta.dx;
-                commonDeltaY = delta.dy;
-            } else {
-                commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
-                commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
-            }
-        }
-
-        // Consider transitions from PRESS to SWIPE or MULTITOUCH.
-        if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
-            float dist[MAX_POINTER_ID + 1];
-            int32_t distOverThreshold = 0;
-            for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty();) {
-                uint32_t id = idBits.clearFirstMarkedBit();
-                PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
-                dist[id] = hypotf(delta.dx * mPointerXZoomScale, delta.dy * mPointerYZoomScale);
-                if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
-                    distOverThreshold += 1;
-                }
-            }
-
-            // Only transition when at least two pointers have moved further than
-            // the minimum distance threshold.
-            if (distOverThreshold >= 2) {
-                if (currentFingerCount > 2) {
-                    // There are more than two pointers, switch to FREEFORM.
-#if DEBUG_GESTURES
-                    ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
-                          currentFingerCount);
-#endif
-                    *outCancelPreviousGesture = true;
-                    mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
-                } else {
-                    // There are exactly two pointers.
-                    BitSet32 idBits(mCurrentCookedState.fingerIdBits);
-                    uint32_t id1 = idBits.clearFirstMarkedBit();
-                    uint32_t id2 = idBits.firstMarkedBit();
-                    const RawPointerData::Pointer& p1 =
-                            mCurrentRawState.rawPointerData.pointerForId(id1);
-                    const RawPointerData::Pointer& p2 =
-                            mCurrentRawState.rawPointerData.pointerForId(id2);
-                    float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y);
-                    if (mutualDistance > mPointerGestureMaxSwipeWidth) {
-                        // There are two pointers but they are too far apart for a SWIPE,
-                        // switch to FREEFORM.
-#if DEBUG_GESTURES
-                        ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
-                              mutualDistance, mPointerGestureMaxSwipeWidth);
-#endif
-                        *outCancelPreviousGesture = true;
-                        mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
-                    } else {
-                        // There are two pointers.  Wait for both pointers to start moving
-                        // before deciding whether this is a SWIPE or FREEFORM gesture.
-                        float dist1 = dist[id1];
-                        float dist2 = dist[id2];
-                        if (dist1 >= mConfig.pointerGestureMultitouchMinDistance &&
-                            dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
-                            // Calculate the dot product of the displacement vectors.
-                            // When the vectors are oriented in approximately the same direction,
-                            // the angle betweeen them is near zero and the cosine of the angle
-                            // approches 1.0.  Recall that dot(v1, v2) = cos(angle) * mag(v1) *
-                            // mag(v2).
-                            PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
-                            PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
-                            float dx1 = delta1.dx * mPointerXZoomScale;
-                            float dy1 = delta1.dy * mPointerYZoomScale;
-                            float dx2 = delta2.dx * mPointerXZoomScale;
-                            float dy2 = delta2.dy * mPointerYZoomScale;
-                            float dot = dx1 * dx2 + dy1 * dy2;
-                            float cosine = dot / (dist1 * dist2); // denominator always > 0
-                            if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
-                                // Pointers are moving in the same direction.  Switch to SWIPE.
-#if DEBUG_GESTURES
-                                ALOGD("Gestures: PRESS transitioned to SWIPE, "
-                                      "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
-                                      "cosine %0.3f >= %0.3f",
-                                      dist1, mConfig.pointerGestureMultitouchMinDistance, dist2,
-                                      mConfig.pointerGestureMultitouchMinDistance, cosine,
-                                      mConfig.pointerGestureSwipeTransitionAngleCosine);
-#endif
-                                mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
-                            } else {
-                                // Pointers are moving in different directions.  Switch to FREEFORM.
-#if DEBUG_GESTURES
-                                ALOGD("Gestures: PRESS transitioned to FREEFORM, "
-                                      "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
-                                      "cosine %0.3f < %0.3f",
-                                      dist1, mConfig.pointerGestureMultitouchMinDistance, dist2,
-                                      mConfig.pointerGestureMultitouchMinDistance, cosine,
-                                      mConfig.pointerGestureSwipeTransitionAngleCosine);
-#endif
-                                *outCancelPreviousGesture = true;
-                                mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
-                            }
-                        }
-                    }
-                }
-            }
-        } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
-            // Switch from SWIPE to FREEFORM if additional pointers go down.
-            // Cancel previous gesture.
-            if (currentFingerCount > 2) {
-#if DEBUG_GESTURES
-                ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
-                      currentFingerCount);
-#endif
-                *outCancelPreviousGesture = true;
-                mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
-            }
-        }
-
-        // Move the reference points based on the overall group motion of the fingers
-        // except in PRESS mode while waiting for a transition to occur.
-        if (mPointerGesture.currentGestureMode != PointerGesture::PRESS &&
-            (commonDeltaX || commonDeltaY)) {
-            for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty();) {
-                uint32_t id = idBits.clearFirstMarkedBit();
-                PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
-                delta.dx = 0;
-                delta.dy = 0;
-            }
-
-            mPointerGesture.referenceTouchX += commonDeltaX;
-            mPointerGesture.referenceTouchY += commonDeltaY;
-
-            commonDeltaX *= mPointerXMovementScale;
-            commonDeltaY *= mPointerYMovementScale;
-
-            rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY);
-            mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
-
-            mPointerGesture.referenceGestureX += commonDeltaX;
-            mPointerGesture.referenceGestureY += commonDeltaY;
-        }
-
-        // Report gestures.
-        if (mPointerGesture.currentGestureMode == PointerGesture::PRESS ||
-            mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
-            // PRESS or SWIPE mode.
-#if DEBUG_GESTURES
-            ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
-                  "activeGestureId=%d, currentTouchPointerCount=%d",
-                  activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
-#endif
-            ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
-
-            mPointerGesture.currentGestureIdBits.clear();
-            mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
-            mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
-            mPointerGesture.currentGestureProperties[0].clear();
-            mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
-            mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
-            mPointerGesture.currentGestureCoords[0].clear();
-            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
-                                                                 mPointerGesture.referenceGestureX);
-            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
-                                                                 mPointerGesture.referenceGestureY);
-            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
-        } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
-            // FREEFORM mode.
-#if DEBUG_GESTURES
-            ALOGD("Gestures: FREEFORM activeTouchId=%d,"
-                  "activeGestureId=%d, currentTouchPointerCount=%d",
-                  activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
-#endif
-            ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
-
-            mPointerGesture.currentGestureIdBits.clear();
-
-            BitSet32 mappedTouchIdBits;
-            BitSet32 usedGestureIdBits;
-            if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
-                // Initially, assign the active gesture id to the active touch point
-                // if there is one.  No other touch id bits are mapped yet.
-                if (!*outCancelPreviousGesture) {
-                    mappedTouchIdBits.markBit(activeTouchId);
-                    usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
-                    mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
-                            mPointerGesture.activeGestureId;
-                } else {
-                    mPointerGesture.activeGestureId = -1;
-                }
-            } else {
-                // Otherwise, assume we mapped all touches from the previous frame.
-                // Reuse all mappings that are still applicable.
-                mappedTouchIdBits.value = mLastCookedState.fingerIdBits.value &
-                        mCurrentCookedState.fingerIdBits.value;
-                usedGestureIdBits = mPointerGesture.lastGestureIdBits;
-
-                // Check whether we need to choose a new active gesture id because the
-                // current went went up.
-                for (BitSet32 upTouchIdBits(mLastCookedState.fingerIdBits.value &
-                                            ~mCurrentCookedState.fingerIdBits.value);
-                     !upTouchIdBits.isEmpty();) {
-                    uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
-                    uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
-                    if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
-                        mPointerGesture.activeGestureId = -1;
-                        break;
-                    }
-                }
-            }
-
-#if DEBUG_GESTURES
-            ALOGD("Gestures: FREEFORM follow up "
-                  "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
-                  "activeGestureId=%d",
-                  mappedTouchIdBits.value, usedGestureIdBits.value,
-                  mPointerGesture.activeGestureId);
-#endif
-
-            BitSet32 idBits(mCurrentCookedState.fingerIdBits);
-            for (uint32_t i = 0; i < currentFingerCount; i++) {
-                uint32_t touchId = idBits.clearFirstMarkedBit();
-                uint32_t gestureId;
-                if (!mappedTouchIdBits.hasBit(touchId)) {
-                    gestureId = usedGestureIdBits.markFirstUnmarkedBit();
-                    mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
-#if DEBUG_GESTURES
-                    ALOGD("Gestures: FREEFORM "
-                          "new mapping for touch id %d -> gesture id %d",
-                          touchId, gestureId);
-#endif
-                } else {
-                    gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
-#if DEBUG_GESTURES
-                    ALOGD("Gestures: FREEFORM "
-                          "existing mapping for touch id %d -> gesture id %d",
-                          touchId, gestureId);
-#endif
-                }
-                mPointerGesture.currentGestureIdBits.markBit(gestureId);
-                mPointerGesture.currentGestureIdToIndex[gestureId] = i;
-
-                const RawPointerData::Pointer& pointer =
-                        mCurrentRawState.rawPointerData.pointerForId(touchId);
-                float deltaX = (pointer.x - mPointerGesture.referenceTouchX) * mPointerXZoomScale;
-                float deltaY = (pointer.y - mPointerGesture.referenceTouchY) * mPointerYZoomScale;
-                rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
-
-                mPointerGesture.currentGestureProperties[i].clear();
-                mPointerGesture.currentGestureProperties[i].id = gestureId;
-                mPointerGesture.currentGestureProperties[i].toolType =
-                        AMOTION_EVENT_TOOL_TYPE_FINGER;
-                mPointerGesture.currentGestureCoords[i].clear();
-                mPointerGesture.currentGestureCoords[i]
-                        .setAxisValue(AMOTION_EVENT_AXIS_X,
-                                      mPointerGesture.referenceGestureX + deltaX);
-                mPointerGesture.currentGestureCoords[i]
-                        .setAxisValue(AMOTION_EVENT_AXIS_Y,
-                                      mPointerGesture.referenceGestureY + deltaY);
-                mPointerGesture.currentGestureCoords[i].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
-                                                                     1.0f);
-            }
-
-            if (mPointerGesture.activeGestureId < 0) {
-                mPointerGesture.activeGestureId =
-                        mPointerGesture.currentGestureIdBits.firstMarkedBit();
-#if DEBUG_GESTURES
-                ALOGD("Gestures: FREEFORM new "
-                      "activeGestureId=%d",
-                      mPointerGesture.activeGestureId);
-#endif
-            }
-        }
-    }
-
-    mPointerController->setButtonState(mCurrentRawState.buttonState);
-
-#if DEBUG_GESTURES
-    ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
-          "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
-          "lastGestureMode=%d, lastGestureIdBits=0x%08x",
-          toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
-          mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
-          mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
-    for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty();) {
-        uint32_t id = idBits.clearFirstMarkedBit();
-        uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
-        const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
-        const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
-        ALOGD("  currentGesture[%d]: index=%d, toolType=%d, "
-              "x=%0.3f, y=%0.3f, pressure=%0.3f",
-              id, index, properties.toolType, coords.getAxisValue(AMOTION_EVENT_AXIS_X),
-              coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
-              coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
-    }
-    for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty();) {
-        uint32_t id = idBits.clearFirstMarkedBit();
-        uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
-        const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
-        const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
-        ALOGD("  lastGesture[%d]: index=%d, toolType=%d, "
-              "x=%0.3f, y=%0.3f, pressure=%0.3f",
-              id, index, properties.toolType, coords.getAxisValue(AMOTION_EVENT_AXIS_X),
-              coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
-              coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
-    }
-#endif
-    return true;
-}
-
-void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) {
-    mPointerSimple.currentCoords.clear();
-    mPointerSimple.currentProperties.clear();
-
-    bool down, hovering;
-    if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
-        uint32_t id = mCurrentCookedState.stylusIdBits.firstMarkedBit();
-        uint32_t index = mCurrentCookedState.cookedPointerData.idToIndex[id];
-        float x = mCurrentCookedState.cookedPointerData.pointerCoords[index].getX();
-        float y = mCurrentCookedState.cookedPointerData.pointerCoords[index].getY();
-        mPointerController->setPosition(x, y);
-
-        hovering = mCurrentCookedState.cookedPointerData.hoveringIdBits.hasBit(id);
-        down = !hovering;
-
-        mPointerController->getPosition(&x, &y);
-        mPointerSimple.currentCoords.copyFrom(
-                mCurrentCookedState.cookedPointerData.pointerCoords[index]);
-        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
-        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
-        mPointerSimple.currentProperties.id = 0;
-        mPointerSimple.currentProperties.toolType =
-                mCurrentCookedState.cookedPointerData.pointerProperties[index].toolType;
-    } else {
-        down = false;
-        hovering = false;
-    }
-
-    dispatchPointerSimple(when, policyFlags, down, hovering);
-}
-
-void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) {
-    abortPointerSimple(when, policyFlags);
-}
-
-void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) {
-    mPointerSimple.currentCoords.clear();
-    mPointerSimple.currentProperties.clear();
-
-    bool down, hovering;
-    if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
-        uint32_t id = mCurrentCookedState.mouseIdBits.firstMarkedBit();
-        uint32_t currentIndex = mCurrentRawState.rawPointerData.idToIndex[id];
-        float deltaX = 0, deltaY = 0;
-        if (mLastCookedState.mouseIdBits.hasBit(id)) {
-            uint32_t lastIndex = mCurrentRawState.rawPointerData.idToIndex[id];
-            deltaX = (mCurrentRawState.rawPointerData.pointers[currentIndex].x -
-                      mLastRawState.rawPointerData.pointers[lastIndex].x) *
-                    mPointerXMovementScale;
-            deltaY = (mCurrentRawState.rawPointerData.pointers[currentIndex].y -
-                      mLastRawState.rawPointerData.pointers[lastIndex].y) *
-                    mPointerYMovementScale;
-
-            rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
-            mPointerVelocityControl.move(when, &deltaX, &deltaY);
-
-            mPointerController->move(deltaX, deltaY);
-        } else {
-            mPointerVelocityControl.reset();
-        }
-
-        down = isPointerDown(mCurrentRawState.buttonState);
-        hovering = !down;
-
-        float x, y;
-        mPointerController->getPosition(&x, &y);
-        mPointerSimple.currentCoords.copyFrom(
-                mCurrentCookedState.cookedPointerData.pointerCoords[currentIndex]);
-        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
-        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
-        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
-                                                  hovering ? 0.0f : 1.0f);
-        mPointerSimple.currentProperties.id = 0;
-        mPointerSimple.currentProperties.toolType =
-                mCurrentCookedState.cookedPointerData.pointerProperties[currentIndex].toolType;
-    } else {
-        mPointerVelocityControl.reset();
-
-        down = false;
-        hovering = false;
-    }
-
-    dispatchPointerSimple(when, policyFlags, down, hovering);
-}
-
-void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) {
-    abortPointerSimple(when, policyFlags);
-
-    mPointerVelocityControl.reset();
-}
-
-void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, bool down,
-                                             bool hovering) {
-    int32_t metaState = getContext()->getGlobalMetaState();
-    int32_t displayId = mViewport.displayId;
-
-    if (mPointerController != nullptr) {
-        if (down || hovering) {
-            mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
-            mPointerController->clearSpots();
-            mPointerController->setButtonState(mCurrentRawState.buttonState);
-            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
-        } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
-            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
-        }
-        displayId = mPointerController->getDisplayId();
-    }
-
-    if (mPointerSimple.down && !down) {
-        mPointerSimple.down = false;
-
-        // Send up.
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
-                              displayId, policyFlags, AMOTION_EVENT_ACTION_UP, 0, 0, metaState,
-                              mLastRawState.buttonState, MotionClassification::NONE,
-                              AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1,
-                              &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
-                              mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime,
-                              /* videoFrames */ {});
-        getListener()->notifyMotion(&args);
-    }
-
-    if (mPointerSimple.hovering && !hovering) {
-        mPointerSimple.hovering = false;
-
-        // Send hover exit.
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
-                              displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0,
-                              metaState, mLastRawState.buttonState, MotionClassification::NONE,
-                              AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1,
-                              &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
-                              mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime,
-                              /* videoFrames */ {});
-        getListener()->notifyMotion(&args);
-    }
-
-    if (down) {
-        if (!mPointerSimple.down) {
-            mPointerSimple.down = true;
-            mPointerSimple.downTime = when;
-
-            // Send down.
-            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
-                                  displayId, policyFlags, AMOTION_EVENT_ACTION_DOWN, 0, 0,
-                                  metaState, mCurrentRawState.buttonState,
-                                  MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                                  /* deviceTimestamp */ 0, 1, &mPointerSimple.currentProperties,
-                                  &mPointerSimple.currentCoords, mOrientedXPrecision,
-                                  mOrientedYPrecision, mPointerSimple.downTime,
-                                  /* videoFrames */ {});
-            getListener()->notifyMotion(&args);
-        }
-
-        // Send move.
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
-                              displayId, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
-                              mCurrentRawState.buttonState, MotionClassification::NONE,
-                              AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1,
-                              &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
-                              mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime,
-                              /* videoFrames */ {});
-        getListener()->notifyMotion(&args);
-    }
-
-    if (hovering) {
-        if (!mPointerSimple.hovering) {
-            mPointerSimple.hovering = true;
-
-            // Send hover enter.
-            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
-                                  displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0,
-                                  metaState, mCurrentRawState.buttonState,
-                                  MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                                  /* deviceTimestamp */ 0, 1, &mPointerSimple.currentProperties,
-                                  &mPointerSimple.currentCoords, mOrientedXPrecision,
-                                  mOrientedYPrecision, mPointerSimple.downTime,
-                                  /* videoFrames */ {});
-            getListener()->notifyMotion(&args);
-        }
-
-        // Send hover move.
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
-                              displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
-                              metaState, mCurrentRawState.buttonState, MotionClassification::NONE,
-                              AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1,
-                              &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
-                              mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime,
-                              /* videoFrames */ {});
-        getListener()->notifyMotion(&args);
-    }
-
-    if (mCurrentRawState.rawVScroll || mCurrentRawState.rawHScroll) {
-        float vscroll = mCurrentRawState.rawVScroll;
-        float hscroll = mCurrentRawState.rawHScroll;
-        mWheelYVelocityControl.move(when, nullptr, &vscroll);
-        mWheelXVelocityControl.move(when, &hscroll, nullptr);
-
-        // Send scroll.
-        PointerCoords pointerCoords;
-        pointerCoords.copyFrom(mPointerSimple.currentCoords);
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
-
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
-                              displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
-                              mCurrentRawState.buttonState, MotionClassification::NONE,
-                              AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1,
-                              &mPointerSimple.currentProperties, &pointerCoords,
-                              mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime,
-                              /* videoFrames */ {});
-        getListener()->notifyMotion(&args);
-    }
-
-    // Save state.
-    if (down || hovering) {
-        mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
-        mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
-    } else {
-        mPointerSimple.reset();
-    }
-}
-
-void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) {
-    mPointerSimple.currentCoords.clear();
-    mPointerSimple.currentProperties.clear();
-
-    dispatchPointerSimple(when, policyFlags, false, false);
-}
-
-void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
-                                      int32_t action, int32_t actionButton, int32_t flags,
-                                      int32_t metaState, int32_t buttonState, int32_t edgeFlags,
-                                      uint32_t deviceTimestamp, const PointerProperties* properties,
-                                      const PointerCoords* coords, const uint32_t* idToIndex,
-                                      BitSet32 idBits, int32_t changedId, float xPrecision,
-                                      float yPrecision, nsecs_t downTime) {
-    PointerCoords pointerCoords[MAX_POINTERS];
-    PointerProperties pointerProperties[MAX_POINTERS];
-    uint32_t pointerCount = 0;
-    while (!idBits.isEmpty()) {
-        uint32_t id = idBits.clearFirstMarkedBit();
-        uint32_t index = idToIndex[id];
-        pointerProperties[pointerCount].copyFrom(properties[index]);
-        pointerCoords[pointerCount].copyFrom(coords[index]);
-
-        if (changedId >= 0 && id == uint32_t(changedId)) {
-            action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-        }
-
-        pointerCount += 1;
-    }
-
-    ALOG_ASSERT(pointerCount != 0);
-
-    if (changedId >= 0 && pointerCount == 1) {
-        // Replace initial down and final up action.
-        // We can compare the action without masking off the changed pointer index
-        // because we know the index is 0.
-        if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
-            action = AMOTION_EVENT_ACTION_DOWN;
-        } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
-            action = AMOTION_EVENT_ACTION_UP;
-        } else {
-            // Can't happen.
-            ALOG_ASSERT(false);
-        }
-    }
-    const int32_t displayId = getAssociatedDisplay().value_or(ADISPLAY_ID_NONE);
-    const int32_t deviceId = getDeviceId();
-    std::vector<TouchVideoFrame> frames = mDevice->getEventHub()->getVideoFrames(deviceId);
-    std::for_each(frames.begin(), frames.end(),
-                  [this](TouchVideoFrame& frame) { frame.rotate(this->mSurfaceOrientation); });
-    NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId, source, displayId,
-                          policyFlags, action, actionButton, flags, metaState, buttonState,
-                          MotionClassification::NONE, edgeFlags, deviceTimestamp, pointerCount,
-                          pointerProperties, pointerCoords, xPrecision, yPrecision, downTime,
-                          std::move(frames));
-    getListener()->notifyMotion(&args);
-}
-
-bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
-                                           const PointerCoords* inCoords,
-                                           const uint32_t* inIdToIndex,
-                                           PointerProperties* outProperties,
-                                           PointerCoords* outCoords, const uint32_t* outIdToIndex,
-                                           BitSet32 idBits) const {
-    bool changed = false;
-    while (!idBits.isEmpty()) {
-        uint32_t id = idBits.clearFirstMarkedBit();
-        uint32_t inIndex = inIdToIndex[id];
-        uint32_t outIndex = outIdToIndex[id];
-
-        const PointerProperties& curInProperties = inProperties[inIndex];
-        const PointerCoords& curInCoords = inCoords[inIndex];
-        PointerProperties& curOutProperties = outProperties[outIndex];
-        PointerCoords& curOutCoords = outCoords[outIndex];
-
-        if (curInProperties != curOutProperties) {
-            curOutProperties.copyFrom(curInProperties);
-            changed = true;
-        }
-
-        if (curInCoords != curOutCoords) {
-            curOutCoords.copyFrom(curInCoords);
-            changed = true;
-        }
-    }
-    return changed;
-}
-
-void TouchInputMapper::fadePointer() {
-    if (mPointerController != nullptr) {
-        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
-    }
-}
-
-void TouchInputMapper::cancelTouch(nsecs_t when) {
-    abortPointerUsage(when, 0 /*policyFlags*/);
-    abortTouches(when, 0 /* policyFlags*/);
-}
-
-bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
-    const float scaledX = x * mXScale;
-    const float scaledY = y * mYScale;
-    return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue &&
-            scaledX >= mPhysicalLeft && scaledX <= mPhysicalLeft + mPhysicalWidth &&
-            y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue &&
-            scaledY >= mPhysicalTop && scaledY <= mPhysicalTop + mPhysicalHeight;
-}
-
-const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(int32_t x, int32_t y) {
-    for (const VirtualKey& virtualKey : mVirtualKeys) {
-#if DEBUG_VIRTUAL_KEYS
-        ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
-              "left=%d, top=%d, right=%d, bottom=%d",
-              x, y, virtualKey.keyCode, virtualKey.scanCode, virtualKey.hitLeft, virtualKey.hitTop,
-              virtualKey.hitRight, virtualKey.hitBottom);
-#endif
-
-        if (virtualKey.isHit(x, y)) {
-            return &virtualKey;
-        }
-    }
-
-    return nullptr;
-}
-
-void TouchInputMapper::assignPointerIds(const RawState* last, RawState* current) {
-    uint32_t currentPointerCount = current->rawPointerData.pointerCount;
-    uint32_t lastPointerCount = last->rawPointerData.pointerCount;
-
-    current->rawPointerData.clearIdBits();
-
-    if (currentPointerCount == 0) {
-        // No pointers to assign.
-        return;
-    }
-
-    if (lastPointerCount == 0) {
-        // All pointers are new.
-        for (uint32_t i = 0; i < currentPointerCount; i++) {
-            uint32_t id = i;
-            current->rawPointerData.pointers[i].id = id;
-            current->rawPointerData.idToIndex[id] = i;
-            current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(i));
-        }
-        return;
-    }
-
-    if (currentPointerCount == 1 && lastPointerCount == 1 &&
-        current->rawPointerData.pointers[0].toolType == last->rawPointerData.pointers[0].toolType) {
-        // Only one pointer and no change in count so it must have the same id as before.
-        uint32_t id = last->rawPointerData.pointers[0].id;
-        current->rawPointerData.pointers[0].id = id;
-        current->rawPointerData.idToIndex[id] = 0;
-        current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(0));
-        return;
-    }
-
-    // General case.
-    // We build a heap of squared euclidean distances between current and last pointers
-    // associated with the current and last pointer indices.  Then, we find the best
-    // match (by distance) for each current pointer.
-    // The pointers must have the same tool type but it is possible for them to
-    // transition from hovering to touching or vice-versa while retaining the same id.
-    PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
-
-    uint32_t heapSize = 0;
-    for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
-         currentPointerIndex++) {
-        for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
-             lastPointerIndex++) {
-            const RawPointerData::Pointer& currentPointer =
-                    current->rawPointerData.pointers[currentPointerIndex];
-            const RawPointerData::Pointer& lastPointer =
-                    last->rawPointerData.pointers[lastPointerIndex];
-            if (currentPointer.toolType == lastPointer.toolType) {
-                int64_t deltaX = currentPointer.x - lastPointer.x;
-                int64_t deltaY = currentPointer.y - lastPointer.y;
-
-                uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
-
-                // Insert new element into the heap (sift up).
-                heap[heapSize].currentPointerIndex = currentPointerIndex;
-                heap[heapSize].lastPointerIndex = lastPointerIndex;
-                heap[heapSize].distance = distance;
-                heapSize += 1;
-            }
-        }
-    }
-
-    // Heapify
-    for (uint32_t startIndex = heapSize / 2; startIndex != 0;) {
-        startIndex -= 1;
-        for (uint32_t parentIndex = startIndex;;) {
-            uint32_t childIndex = parentIndex * 2 + 1;
-            if (childIndex >= heapSize) {
-                break;
-            }
-
-            if (childIndex + 1 < heapSize &&
-                heap[childIndex + 1].distance < heap[childIndex].distance) {
-                childIndex += 1;
-            }
-
-            if (heap[parentIndex].distance <= heap[childIndex].distance) {
-                break;
-            }
-
-            swap(heap[parentIndex], heap[childIndex]);
-            parentIndex = childIndex;
-        }
-    }
-
-#if DEBUG_POINTER_ASSIGNMENT
-    ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
-    for (size_t i = 0; i < heapSize; i++) {
-        ALOGD("  heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64, i,
-              heap[i].currentPointerIndex, heap[i].lastPointerIndex, heap[i].distance);
-    }
-#endif
-
-    // Pull matches out by increasing order of distance.
-    // To avoid reassigning pointers that have already been matched, the loop keeps track
-    // of which last and current pointers have been matched using the matchedXXXBits variables.
-    // It also tracks the used pointer id bits.
-    BitSet32 matchedLastBits(0);
-    BitSet32 matchedCurrentBits(0);
-    BitSet32 usedIdBits(0);
-    bool first = true;
-    for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) {
-        while (heapSize > 0) {
-            if (first) {
-                // The first time through the loop, we just consume the root element of
-                // the heap (the one with smallest distance).
-                first = false;
-            } else {
-                // Previous iterations consumed the root element of the heap.
-                // Pop root element off of the heap (sift down).
-                heap[0] = heap[heapSize];
-                for (uint32_t parentIndex = 0;;) {
-                    uint32_t childIndex = parentIndex * 2 + 1;
-                    if (childIndex >= heapSize) {
-                        break;
-                    }
-
-                    if (childIndex + 1 < heapSize &&
-                        heap[childIndex + 1].distance < heap[childIndex].distance) {
-                        childIndex += 1;
-                    }
-
-                    if (heap[parentIndex].distance <= heap[childIndex].distance) {
-                        break;
-                    }
-
-                    swap(heap[parentIndex], heap[childIndex]);
-                    parentIndex = childIndex;
-                }
-
-#if DEBUG_POINTER_ASSIGNMENT
-                ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
-                for (size_t i = 0; i < heapSize; i++) {
-                    ALOGD("  heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64, i,
-                          heap[i].currentPointerIndex, heap[i].lastPointerIndex, heap[i].distance);
-                }
-#endif
-            }
-
-            heapSize -= 1;
-
-            uint32_t currentPointerIndex = heap[0].currentPointerIndex;
-            if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
-
-            uint32_t lastPointerIndex = heap[0].lastPointerIndex;
-            if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
-
-            matchedCurrentBits.markBit(currentPointerIndex);
-            matchedLastBits.markBit(lastPointerIndex);
-
-            uint32_t id = last->rawPointerData.pointers[lastPointerIndex].id;
-            current->rawPointerData.pointers[currentPointerIndex].id = id;
-            current->rawPointerData.idToIndex[id] = currentPointerIndex;
-            current->rawPointerData.markIdBit(id,
-                                              current->rawPointerData.isHovering(
-                                                      currentPointerIndex));
-            usedIdBits.markBit(id);
-
-#if DEBUG_POINTER_ASSIGNMENT
-            ALOGD("assignPointerIds - matched: cur=%" PRIu32 ", last=%" PRIu32 ", id=%" PRIu32
-                  ", distance=%" PRIu64,
-                  lastPointerIndex, currentPointerIndex, id, heap[0].distance);
-#endif
-            break;
-        }
-    }
-
-    // Assign fresh ids to pointers that were not matched in the process.
-    for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) {
-        uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();
-        uint32_t id = usedIdBits.markFirstUnmarkedBit();
-
-        current->rawPointerData.pointers[currentPointerIndex].id = id;
-        current->rawPointerData.idToIndex[id] = currentPointerIndex;
-        current->rawPointerData.markIdBit(id,
-                                          current->rawPointerData.isHovering(currentPointerIndex));
-
-#if DEBUG_POINTER_ASSIGNMENT
-        ALOGD("assignPointerIds - assigned: cur=%" PRIu32 ", id=%" PRIu32, currentPointerIndex, id);
-#endif
-    }
-}
-
-int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
-    if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
-        return AKEY_STATE_VIRTUAL;
-    }
-
-    for (const VirtualKey& virtualKey : mVirtualKeys) {
-        if (virtualKey.keyCode == keyCode) {
-            return AKEY_STATE_UP;
-        }
-    }
-
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-    if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) {
-        return AKEY_STATE_VIRTUAL;
-    }
-
-    for (const VirtualKey& virtualKey : mVirtualKeys) {
-        if (virtualKey.scanCode == scanCode) {
-            return AKEY_STATE_UP;
-        }
-    }
-
-    return AKEY_STATE_UNKNOWN;
-}
-
-bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-                                             const int32_t* keyCodes, uint8_t* outFlags) {
-    for (const VirtualKey& virtualKey : mVirtualKeys) {
-        for (size_t i = 0; i < numCodes; i++) {
-            if (virtualKey.keyCode == keyCodes[i]) {
-                outFlags[i] = 1;
-            }
-        }
-    }
-
-    return true;
-}
-
-std::optional<int32_t> TouchInputMapper::getAssociatedDisplay() {
-    if (mParameters.hasAssociatedDisplay) {
-        if (mDeviceMode == DEVICE_MODE_POINTER) {
-            return std::make_optional(mPointerController->getDisplayId());
-        } else {
-            return std::make_optional(mViewport.displayId);
-        }
-    }
-    return std::nullopt;
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
deleted file mode 100644
index d14812a..0000000
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ /dev/null
@@ -1,838 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_TOUCH_INPUT_MAPPER_H
-#define _UI_INPUTREADER_TOUCH_INPUT_MAPPER_H
-
-#include "CursorButtonAccumulator.h"
-#include "CursorScrollAccumulator.h"
-#include "EventHub.h"
-#include "InputMapper.h"
-#include "InputReaderBase.h"
-#include "TouchButtonAccumulator.h"
-
-#include <stdint.h>
-
-namespace android {
-
-/**
- * Basic statistics information.
- * Keep track of min, max, average, and standard deviation of the received samples.
- * Used to report latency information about input events.
- */
-struct LatencyStatistics {
-    float min;
-    float max;
-    // Sum of all samples
-    float sum;
-    // Sum of squares of all samples
-    float sum2;
-    // The number of samples
-    size_t count;
-    // The last time statistics were reported.
-    nsecs_t lastReportTime;
-
-    LatencyStatistics() { reset(systemTime(SYSTEM_TIME_MONOTONIC)); }
-
-    inline void addValue(float x) {
-        if (x < min) {
-            min = x;
-        }
-        if (x > max) {
-            max = x;
-        }
-        sum += x;
-        sum2 += x * x;
-        count++;
-    }
-
-    // Get the average value. Should not be called if no samples have been added.
-    inline float mean() {
-        if (count == 0) {
-            return 0;
-        }
-        return sum / count;
-    }
-
-    // Get the standard deviation. Should not be called if no samples have been added.
-    inline float stdev() {
-        if (count == 0) {
-            return 0;
-        }
-        float average = mean();
-        return sqrt(sum2 / count - average * average);
-    }
-
-    /**
-     * Reset internal state. The variable 'when' is the time when the data collection started.
-     * Call this to start a new data collection window.
-     */
-    inline void reset(nsecs_t when) {
-        max = 0;
-        min = std::numeric_limits<float>::max();
-        sum = 0;
-        sum2 = 0;
-        count = 0;
-        lastReportTime = when;
-    }
-};
-
-/* Raw axis information from the driver. */
-struct RawPointerAxes {
-    RawAbsoluteAxisInfo x;
-    RawAbsoluteAxisInfo y;
-    RawAbsoluteAxisInfo pressure;
-    RawAbsoluteAxisInfo touchMajor;
-    RawAbsoluteAxisInfo touchMinor;
-    RawAbsoluteAxisInfo toolMajor;
-    RawAbsoluteAxisInfo toolMinor;
-    RawAbsoluteAxisInfo orientation;
-    RawAbsoluteAxisInfo distance;
-    RawAbsoluteAxisInfo tiltX;
-    RawAbsoluteAxisInfo tiltY;
-    RawAbsoluteAxisInfo trackingId;
-    RawAbsoluteAxisInfo slot;
-
-    RawPointerAxes();
-    inline int32_t getRawWidth() const { return x.maxValue - x.minValue + 1; }
-    inline int32_t getRawHeight() const { return y.maxValue - y.minValue + 1; }
-    void clear();
-};
-
-/* Raw data for a collection of pointers including a pointer id mapping table. */
-struct RawPointerData {
-    struct Pointer {
-        uint32_t id;
-        int32_t x;
-        int32_t y;
-        int32_t pressure;
-        int32_t touchMajor;
-        int32_t touchMinor;
-        int32_t toolMajor;
-        int32_t toolMinor;
-        int32_t orientation;
-        int32_t distance;
-        int32_t tiltX;
-        int32_t tiltY;
-        int32_t toolType; // a fully decoded AMOTION_EVENT_TOOL_TYPE constant
-        bool isHovering;
-    };
-
-    uint32_t pointerCount;
-    Pointer pointers[MAX_POINTERS];
-    BitSet32 hoveringIdBits, touchingIdBits;
-    uint32_t idToIndex[MAX_POINTER_ID + 1];
-
-    RawPointerData();
-    void clear();
-    void copyFrom(const RawPointerData& other);
-    void getCentroidOfTouchingPointers(float* outX, float* outY) const;
-
-    inline void markIdBit(uint32_t id, bool isHovering) {
-        if (isHovering) {
-            hoveringIdBits.markBit(id);
-        } else {
-            touchingIdBits.markBit(id);
-        }
-    }
-
-    inline void clearIdBits() {
-        hoveringIdBits.clear();
-        touchingIdBits.clear();
-    }
-
-    inline const Pointer& pointerForId(uint32_t id) const { return pointers[idToIndex[id]]; }
-
-    inline bool isHovering(uint32_t pointerIndex) { return pointers[pointerIndex].isHovering; }
-};
-
-/* Cooked data for a collection of pointers including a pointer id mapping table. */
-struct CookedPointerData {
-    uint32_t pointerCount;
-    PointerProperties pointerProperties[MAX_POINTERS];
-    PointerCoords pointerCoords[MAX_POINTERS];
-    BitSet32 hoveringIdBits, touchingIdBits;
-    uint32_t idToIndex[MAX_POINTER_ID + 1];
-
-    CookedPointerData();
-    void clear();
-    void copyFrom(const CookedPointerData& other);
-
-    inline const PointerCoords& pointerCoordsForId(uint32_t id) const {
-        return pointerCoords[idToIndex[id]];
-    }
-
-    inline PointerCoords& editPointerCoordsWithId(uint32_t id) {
-        return pointerCoords[idToIndex[id]];
-    }
-
-    inline PointerProperties& editPointerPropertiesWithId(uint32_t id) {
-        return pointerProperties[idToIndex[id]];
-    }
-
-    inline bool isHovering(uint32_t pointerIndex) const {
-        return hoveringIdBits.hasBit(pointerProperties[pointerIndex].id);
-    }
-
-    inline bool isTouching(uint32_t pointerIndex) const {
-        return touchingIdBits.hasBit(pointerProperties[pointerIndex].id);
-    }
-};
-
-class TouchInputMapper : public InputMapper {
-public:
-    explicit TouchInputMapper(InputDevice* device);
-    virtual ~TouchInputMapper();
-
-    virtual uint32_t getSources();
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void dump(std::string& dump);
-    virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
-    virtual void reset(nsecs_t when);
-    virtual void process(const RawEvent* rawEvent);
-
-    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
-    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-                                       const int32_t* keyCodes, uint8_t* outFlags);
-
-    virtual void fadePointer();
-    virtual void cancelTouch(nsecs_t when);
-    virtual void timeoutExpired(nsecs_t when);
-    virtual void updateExternalStylusState(const StylusState& state);
-    virtual std::optional<int32_t> getAssociatedDisplay();
-
-protected:
-    CursorButtonAccumulator mCursorButtonAccumulator;
-    CursorScrollAccumulator mCursorScrollAccumulator;
-    TouchButtonAccumulator mTouchButtonAccumulator;
-
-    struct VirtualKey {
-        int32_t keyCode;
-        int32_t scanCode;
-        uint32_t flags;
-
-        // computed hit box, specified in touch screen coords based on known display size
-        int32_t hitLeft;
-        int32_t hitTop;
-        int32_t hitRight;
-        int32_t hitBottom;
-
-        inline bool isHit(int32_t x, int32_t y) const {
-            return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom;
-        }
-    };
-
-    // Input sources and device mode.
-    uint32_t mSource;
-
-    enum DeviceMode {
-        DEVICE_MODE_DISABLED,   // input is disabled
-        DEVICE_MODE_DIRECT,     // direct mapping (touchscreen)
-        DEVICE_MODE_UNSCALED,   // unscaled mapping (touchpad)
-        DEVICE_MODE_NAVIGATION, // unscaled mapping with assist gesture (touch navigation)
-        DEVICE_MODE_POINTER,    // pointer mapping (pointer)
-    };
-    DeviceMode mDeviceMode;
-
-    // The reader's configuration.
-    InputReaderConfiguration mConfig;
-
-    // Immutable configuration parameters.
-    struct Parameters {
-        enum DeviceType {
-            DEVICE_TYPE_TOUCH_SCREEN,
-            DEVICE_TYPE_TOUCH_PAD,
-            DEVICE_TYPE_TOUCH_NAVIGATION,
-            DEVICE_TYPE_POINTER,
-        };
-
-        DeviceType deviceType;
-        bool hasAssociatedDisplay;
-        bool associatedDisplayIsExternal;
-        bool orientationAware;
-        bool hasButtonUnderPad;
-        std::string uniqueDisplayId;
-
-        enum GestureMode {
-            GESTURE_MODE_SINGLE_TOUCH,
-            GESTURE_MODE_MULTI_TOUCH,
-        };
-        GestureMode gestureMode;
-
-        bool wake;
-    } mParameters;
-
-    // Immutable calibration parameters in parsed form.
-    struct Calibration {
-        // Size
-        enum SizeCalibration {
-            SIZE_CALIBRATION_DEFAULT,
-            SIZE_CALIBRATION_NONE,
-            SIZE_CALIBRATION_GEOMETRIC,
-            SIZE_CALIBRATION_DIAMETER,
-            SIZE_CALIBRATION_BOX,
-            SIZE_CALIBRATION_AREA,
-        };
-
-        SizeCalibration sizeCalibration;
-
-        bool haveSizeScale;
-        float sizeScale;
-        bool haveSizeBias;
-        float sizeBias;
-        bool haveSizeIsSummed;
-        bool sizeIsSummed;
-
-        // Pressure
-        enum PressureCalibration {
-            PRESSURE_CALIBRATION_DEFAULT,
-            PRESSURE_CALIBRATION_NONE,
-            PRESSURE_CALIBRATION_PHYSICAL,
-            PRESSURE_CALIBRATION_AMPLITUDE,
-        };
-
-        PressureCalibration pressureCalibration;
-        bool havePressureScale;
-        float pressureScale;
-
-        // Orientation
-        enum OrientationCalibration {
-            ORIENTATION_CALIBRATION_DEFAULT,
-            ORIENTATION_CALIBRATION_NONE,
-            ORIENTATION_CALIBRATION_INTERPOLATED,
-            ORIENTATION_CALIBRATION_VECTOR,
-        };
-
-        OrientationCalibration orientationCalibration;
-
-        // Distance
-        enum DistanceCalibration {
-            DISTANCE_CALIBRATION_DEFAULT,
-            DISTANCE_CALIBRATION_NONE,
-            DISTANCE_CALIBRATION_SCALED,
-        };
-
-        DistanceCalibration distanceCalibration;
-        bool haveDistanceScale;
-        float distanceScale;
-
-        enum CoverageCalibration {
-            COVERAGE_CALIBRATION_DEFAULT,
-            COVERAGE_CALIBRATION_NONE,
-            COVERAGE_CALIBRATION_BOX,
-        };
-
-        CoverageCalibration coverageCalibration;
-
-        inline void applySizeScaleAndBias(float* outSize) const {
-            if (haveSizeScale) {
-                *outSize *= sizeScale;
-            }
-            if (haveSizeBias) {
-                *outSize += sizeBias;
-            }
-            if (*outSize < 0) {
-                *outSize = 0;
-            }
-        }
-    } mCalibration;
-
-    // Affine location transformation/calibration
-    struct TouchAffineTransformation mAffineTransform;
-
-    RawPointerAxes mRawPointerAxes;
-
-    struct RawState {
-        nsecs_t when;
-        uint32_t deviceTimestamp;
-
-        // Raw pointer sample data.
-        RawPointerData rawPointerData;
-
-        int32_t buttonState;
-
-        // Scroll state.
-        int32_t rawVScroll;
-        int32_t rawHScroll;
-
-        void copyFrom(const RawState& other) {
-            when = other.when;
-            deviceTimestamp = other.deviceTimestamp;
-            rawPointerData.copyFrom(other.rawPointerData);
-            buttonState = other.buttonState;
-            rawVScroll = other.rawVScroll;
-            rawHScroll = other.rawHScroll;
-        }
-
-        void clear() {
-            when = 0;
-            deviceTimestamp = 0;
-            rawPointerData.clear();
-            buttonState = 0;
-            rawVScroll = 0;
-            rawHScroll = 0;
-        }
-    };
-
-    struct CookedState {
-        uint32_t deviceTimestamp;
-        // Cooked pointer sample data.
-        CookedPointerData cookedPointerData;
-
-        // Id bits used to differentiate fingers, stylus and mouse tools.
-        BitSet32 fingerIdBits;
-        BitSet32 stylusIdBits;
-        BitSet32 mouseIdBits;
-
-        int32_t buttonState;
-
-        void copyFrom(const CookedState& other) {
-            deviceTimestamp = other.deviceTimestamp;
-            cookedPointerData.copyFrom(other.cookedPointerData);
-            fingerIdBits = other.fingerIdBits;
-            stylusIdBits = other.stylusIdBits;
-            mouseIdBits = other.mouseIdBits;
-            buttonState = other.buttonState;
-        }
-
-        void clear() {
-            deviceTimestamp = 0;
-            cookedPointerData.clear();
-            fingerIdBits.clear();
-            stylusIdBits.clear();
-            mouseIdBits.clear();
-            buttonState = 0;
-        }
-    };
-
-    std::vector<RawState> mRawStatesPending;
-    RawState mCurrentRawState;
-    CookedState mCurrentCookedState;
-    RawState mLastRawState;
-    CookedState mLastCookedState;
-
-    // State provided by an external stylus
-    StylusState mExternalStylusState;
-    int64_t mExternalStylusId;
-    nsecs_t mExternalStylusFusionTimeout;
-    bool mExternalStylusDataPending;
-
-    // True if we sent a HOVER_ENTER event.
-    bool mSentHoverEnter;
-
-    // Have we assigned pointer IDs for this stream
-    bool mHavePointerIds;
-
-    // Is the current stream of direct touch events aborted
-    bool mCurrentMotionAborted;
-
-    // The time the primary pointer last went down.
-    nsecs_t mDownTime;
-
-    // The pointer controller, or null if the device is not a pointer.
-    sp<PointerControllerInterface> mPointerController;
-
-    std::vector<VirtualKey> mVirtualKeys;
-
-    virtual void configureParameters();
-    virtual void dumpParameters(std::string& dump);
-    virtual void configureRawPointerAxes();
-    virtual void dumpRawPointerAxes(std::string& dump);
-    virtual void configureSurface(nsecs_t when, bool* outResetNeeded);
-    virtual void dumpSurface(std::string& dump);
-    virtual void configureVirtualKeys();
-    virtual void dumpVirtualKeys(std::string& dump);
-    virtual void parseCalibration();
-    virtual void resolveCalibration();
-    virtual void dumpCalibration(std::string& dump);
-    virtual void updateAffineTransformation();
-    virtual void dumpAffineTransformation(std::string& dump);
-    virtual void resolveExternalStylusPresence();
-    virtual bool hasStylus() const = 0;
-    virtual bool hasExternalStylus() const;
-
-    virtual void syncTouch(nsecs_t when, RawState* outState) = 0;
-
-private:
-    // The current viewport.
-    // The components of the viewport are specified in the display's rotated orientation.
-    DisplayViewport mViewport;
-
-    // The surface orientation, width and height set by configureSurface().
-    // The width and height are derived from the viewport but are specified
-    // in the natural orientation.
-    // The surface origin specifies how the surface coordinates should be translated
-    // to align with the logical display coordinate space.
-    int32_t mSurfaceWidth;
-    int32_t mSurfaceHeight;
-    int32_t mSurfaceLeft;
-    int32_t mSurfaceTop;
-
-    // Similar to the surface coordinates, but in the raw display coordinate space rather than in
-    // the logical coordinate space.
-    int32_t mPhysicalWidth;
-    int32_t mPhysicalHeight;
-    int32_t mPhysicalLeft;
-    int32_t mPhysicalTop;
-
-    // The orientation may be different from the viewport orientation as it specifies
-    // the rotation of the surface coordinates required to produce the viewport's
-    // requested orientation, so it will depend on whether the device is orientation aware.
-    int32_t mSurfaceOrientation;
-
-    // Translation and scaling factors, orientation-independent.
-    float mXTranslate;
-    float mXScale;
-    float mXPrecision;
-
-    float mYTranslate;
-    float mYScale;
-    float mYPrecision;
-
-    float mGeometricScale;
-
-    float mPressureScale;
-
-    float mSizeScale;
-
-    float mOrientationScale;
-
-    float mDistanceScale;
-
-    bool mHaveTilt;
-    float mTiltXCenter;
-    float mTiltXScale;
-    float mTiltYCenter;
-    float mTiltYScale;
-
-    bool mExternalStylusConnected;
-
-    // Oriented motion ranges for input device info.
-    struct OrientedRanges {
-        InputDeviceInfo::MotionRange x;
-        InputDeviceInfo::MotionRange y;
-        InputDeviceInfo::MotionRange pressure;
-
-        bool haveSize;
-        InputDeviceInfo::MotionRange size;
-
-        bool haveTouchSize;
-        InputDeviceInfo::MotionRange touchMajor;
-        InputDeviceInfo::MotionRange touchMinor;
-
-        bool haveToolSize;
-        InputDeviceInfo::MotionRange toolMajor;
-        InputDeviceInfo::MotionRange toolMinor;
-
-        bool haveOrientation;
-        InputDeviceInfo::MotionRange orientation;
-
-        bool haveDistance;
-        InputDeviceInfo::MotionRange distance;
-
-        bool haveTilt;
-        InputDeviceInfo::MotionRange tilt;
-
-        OrientedRanges() { clear(); }
-
-        void clear() {
-            haveSize = false;
-            haveTouchSize = false;
-            haveToolSize = false;
-            haveOrientation = false;
-            haveDistance = false;
-            haveTilt = false;
-        }
-    } mOrientedRanges;
-
-    // Oriented dimensions and precision.
-    float mOrientedXPrecision;
-    float mOrientedYPrecision;
-
-    struct CurrentVirtualKeyState {
-        bool down;
-        bool ignored;
-        nsecs_t downTime;
-        int32_t keyCode;
-        int32_t scanCode;
-    } mCurrentVirtualKey;
-
-    // Scale factor for gesture or mouse based pointer movements.
-    float mPointerXMovementScale;
-    float mPointerYMovementScale;
-
-    // Scale factor for gesture based zooming and other freeform motions.
-    float mPointerXZoomScale;
-    float mPointerYZoomScale;
-
-    // The maximum swipe width.
-    float mPointerGestureMaxSwipeWidth;
-
-    struct PointerDistanceHeapElement {
-        uint32_t currentPointerIndex : 8;
-        uint32_t lastPointerIndex : 8;
-        uint64_t distance : 48; // squared distance
-    };
-
-    enum PointerUsage {
-        POINTER_USAGE_NONE,
-        POINTER_USAGE_GESTURES,
-        POINTER_USAGE_STYLUS,
-        POINTER_USAGE_MOUSE,
-    };
-    PointerUsage mPointerUsage;
-
-    struct PointerGesture {
-        enum Mode {
-            // No fingers, button is not pressed.
-            // Nothing happening.
-            NEUTRAL,
-
-            // No fingers, button is not pressed.
-            // Tap detected.
-            // Emits DOWN and UP events at the pointer location.
-            TAP,
-
-            // Exactly one finger dragging following a tap.
-            // Pointer follows the active finger.
-            // Emits DOWN, MOVE and UP events at the pointer location.
-            //
-            // Detect double-taps when the finger goes up while in TAP_DRAG mode.
-            TAP_DRAG,
-
-            // Button is pressed.
-            // Pointer follows the active finger if there is one.  Other fingers are ignored.
-            // Emits DOWN, MOVE and UP events at the pointer location.
-            BUTTON_CLICK_OR_DRAG,
-
-            // Exactly one finger, button is not pressed.
-            // Pointer follows the active finger.
-            // Emits HOVER_MOVE events at the pointer location.
-            //
-            // Detect taps when the finger goes up while in HOVER mode.
-            HOVER,
-
-            // Exactly two fingers but neither have moved enough to clearly indicate
-            // whether a swipe or freeform gesture was intended.  We consider the
-            // pointer to be pressed so this enables clicking or long-pressing on buttons.
-            // Pointer does not move.
-            // Emits DOWN, MOVE and UP events with a single stationary pointer coordinate.
-            PRESS,
-
-            // Exactly two fingers moving in the same direction, button is not pressed.
-            // Pointer does not move.
-            // Emits DOWN, MOVE and UP events with a single pointer coordinate that
-            // follows the midpoint between both fingers.
-            SWIPE,
-
-            // Two or more fingers moving in arbitrary directions, button is not pressed.
-            // Pointer does not move.
-            // Emits DOWN, POINTER_DOWN, MOVE, POINTER_UP and UP events that follow
-            // each finger individually relative to the initial centroid of the finger.
-            FREEFORM,
-
-            // Waiting for quiet time to end before starting the next gesture.
-            QUIET,
-        };
-
-        // Time the first finger went down.
-        nsecs_t firstTouchTime;
-
-        // The active pointer id from the raw touch data.
-        int32_t activeTouchId; // -1 if none
-
-        // The active pointer id from the gesture last delivered to the application.
-        int32_t activeGestureId; // -1 if none
-
-        // Pointer coords and ids for the current and previous pointer gesture.
-        Mode currentGestureMode;
-        BitSet32 currentGestureIdBits;
-        uint32_t currentGestureIdToIndex[MAX_POINTER_ID + 1];
-        PointerProperties currentGestureProperties[MAX_POINTERS];
-        PointerCoords currentGestureCoords[MAX_POINTERS];
-
-        Mode lastGestureMode;
-        BitSet32 lastGestureIdBits;
-        uint32_t lastGestureIdToIndex[MAX_POINTER_ID + 1];
-        PointerProperties lastGestureProperties[MAX_POINTERS];
-        PointerCoords lastGestureCoords[MAX_POINTERS];
-
-        // Time the pointer gesture last went down.
-        nsecs_t downTime;
-
-        // Time when the pointer went down for a TAP.
-        nsecs_t tapDownTime;
-
-        // Time when the pointer went up for a TAP.
-        nsecs_t tapUpTime;
-
-        // Location of initial tap.
-        float tapX, tapY;
-
-        // Time we started waiting for quiescence.
-        nsecs_t quietTime;
-
-        // Reference points for multitouch gestures.
-        float referenceTouchX; // reference touch X/Y coordinates in surface units
-        float referenceTouchY;
-        float referenceGestureX; // reference gesture X/Y coordinates in pixels
-        float referenceGestureY;
-
-        // Distance that each pointer has traveled which has not yet been
-        // subsumed into the reference gesture position.
-        BitSet32 referenceIdBits;
-        struct Delta {
-            float dx, dy;
-        };
-        Delta referenceDeltas[MAX_POINTER_ID + 1];
-
-        // Describes how touch ids are mapped to gesture ids for freeform gestures.
-        uint32_t freeformTouchToGestureIdMap[MAX_POINTER_ID + 1];
-
-        // A velocity tracker for determining whether to switch active pointers during drags.
-        VelocityTracker velocityTracker;
-
-        void reset() {
-            firstTouchTime = LLONG_MIN;
-            activeTouchId = -1;
-            activeGestureId = -1;
-            currentGestureMode = NEUTRAL;
-            currentGestureIdBits.clear();
-            lastGestureMode = NEUTRAL;
-            lastGestureIdBits.clear();
-            downTime = 0;
-            velocityTracker.clear();
-            resetTap();
-            resetQuietTime();
-        }
-
-        void resetTap() {
-            tapDownTime = LLONG_MIN;
-            tapUpTime = LLONG_MIN;
-        }
-
-        void resetQuietTime() { quietTime = LLONG_MIN; }
-    } mPointerGesture;
-
-    struct PointerSimple {
-        PointerCoords currentCoords;
-        PointerProperties currentProperties;
-        PointerCoords lastCoords;
-        PointerProperties lastProperties;
-
-        // True if the pointer is down.
-        bool down;
-
-        // True if the pointer is hovering.
-        bool hovering;
-
-        // Time the pointer last went down.
-        nsecs_t downTime;
-
-        void reset() {
-            currentCoords.clear();
-            currentProperties.clear();
-            lastCoords.clear();
-            lastProperties.clear();
-            down = false;
-            hovering = false;
-            downTime = 0;
-        }
-    } mPointerSimple;
-
-    // The pointer and scroll velocity controls.
-    VelocityControl mPointerVelocityControl;
-    VelocityControl mWheelXVelocityControl;
-    VelocityControl mWheelYVelocityControl;
-
-    // Latency statistics for touch events
-    struct LatencyStatistics mStatistics;
-
-    std::optional<DisplayViewport> findViewport();
-
-    void resetExternalStylus();
-    void clearStylusDataPendingFlags();
-
-    void sync(nsecs_t when);
-
-    bool consumeRawTouches(nsecs_t when, uint32_t policyFlags);
-    void processRawTouches(bool timeout);
-    void cookAndDispatch(nsecs_t when);
-    void dispatchVirtualKey(nsecs_t when, uint32_t policyFlags, int32_t keyEventAction,
-                            int32_t keyEventFlags);
-
-    void dispatchTouches(nsecs_t when, uint32_t policyFlags);
-    void dispatchHoverExit(nsecs_t when, uint32_t policyFlags);
-    void dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags);
-    void dispatchButtonRelease(nsecs_t when, uint32_t policyFlags);
-    void dispatchButtonPress(nsecs_t when, uint32_t policyFlags);
-    const BitSet32& findActiveIdBits(const CookedPointerData& cookedPointerData);
-    void cookPointerData();
-    void abortTouches(nsecs_t when, uint32_t policyFlags);
-
-    void dispatchPointerUsage(nsecs_t when, uint32_t policyFlags, PointerUsage pointerUsage);
-    void abortPointerUsage(nsecs_t when, uint32_t policyFlags);
-
-    void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout);
-    void abortPointerGestures(nsecs_t when, uint32_t policyFlags);
-    bool preparePointerGestures(nsecs_t when, bool* outCancelPreviousGesture,
-                                bool* outFinishPreviousGesture, bool isTimeout);
-
-    void dispatchPointerStylus(nsecs_t when, uint32_t policyFlags);
-    void abortPointerStylus(nsecs_t when, uint32_t policyFlags);
-
-    void dispatchPointerMouse(nsecs_t when, uint32_t policyFlags);
-    void abortPointerMouse(nsecs_t when, uint32_t policyFlags);
-
-    void dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, bool down, bool hovering);
-    void abortPointerSimple(nsecs_t when, uint32_t policyFlags);
-
-    bool assignExternalStylusId(const RawState& state, bool timeout);
-    void applyExternalStylusButtonState(nsecs_t when);
-    void applyExternalStylusTouchState(nsecs_t when);
-
-    // Dispatches a motion event.
-    // If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the
-    // method will take care of setting the index and transmuting the action to DOWN or UP
-    // it is the first / last pointer to go down / up.
-    void dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source, int32_t action,
-                        int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState,
-                        int32_t edgeFlags, uint32_t deviceTimestamp,
-                        const PointerProperties* properties, const PointerCoords* coords,
-                        const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId,
-                        float xPrecision, float yPrecision, nsecs_t downTime);
-
-    // Updates pointer coords and properties for pointers with specified ids that have moved.
-    // Returns true if any of them changed.
-    bool updateMovedPointers(const PointerProperties* inProperties, const PointerCoords* inCoords,
-                             const uint32_t* inIdToIndex, PointerProperties* outProperties,
-                             PointerCoords* outCoords, const uint32_t* outIdToIndex,
-                             BitSet32 idBits) const;
-
-    bool isPointInsideSurface(int32_t x, int32_t y);
-    const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y);
-
-    static void assignPointerIds(const RawState* last, RawState* current);
-
-    void reportEventForStatistics(nsecs_t evdevTime);
-
-    const char* modeToString(DeviceMode deviceMode);
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_TOUCH_INPUT_MAPPER_H
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
deleted file mode 100644
index a27fab4..0000000
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Macros.h"
-
-#include "VibratorInputMapper.h"
-
-namespace android {
-
-VibratorInputMapper::VibratorInputMapper(InputDevice* device)
-      : InputMapper(device), mVibrating(false) {}
-
-VibratorInputMapper::~VibratorInputMapper() {}
-
-uint32_t VibratorInputMapper::getSources() {
-    return 0;
-}
-
-void VibratorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    InputMapper::populateDeviceInfo(info);
-
-    info->setVibrator(true);
-}
-
-void VibratorInputMapper::process(const RawEvent* rawEvent) {
-    // TODO: Handle FF_STATUS, although it does not seem to be widely supported.
-}
-
-void VibratorInputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
-                                  int32_t token) {
-#if DEBUG_VIBRATOR
-    std::string patternStr;
-    for (size_t i = 0; i < patternSize; i++) {
-        if (i != 0) {
-            patternStr += ", ";
-        }
-        patternStr += StringPrintf("%" PRId64, pattern[i]);
-    }
-    ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%zd, token=%d", getDeviceId(),
-          patternStr.c_str(), repeat, token);
-#endif
-
-    mVibrating = true;
-    memcpy(mPattern, pattern, patternSize * sizeof(nsecs_t));
-    mPatternSize = patternSize;
-    mRepeat = repeat;
-    mToken = token;
-    mIndex = -1;
-
-    nextStep();
-}
-
-void VibratorInputMapper::cancelVibrate(int32_t token) {
-#if DEBUG_VIBRATOR
-    ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
-#endif
-
-    if (mVibrating && mToken == token) {
-        stopVibrating();
-    }
-}
-
-void VibratorInputMapper::timeoutExpired(nsecs_t when) {
-    if (mVibrating) {
-        if (when >= mNextStepTime) {
-            nextStep();
-        } else {
-            getContext()->requestTimeoutAtTime(mNextStepTime);
-        }
-    }
-}
-
-void VibratorInputMapper::nextStep() {
-    mIndex += 1;
-    if (size_t(mIndex) >= mPatternSize) {
-        if (mRepeat < 0) {
-            // We are done.
-            stopVibrating();
-            return;
-        }
-        mIndex = mRepeat;
-    }
-
-    bool vibratorOn = mIndex & 1;
-    nsecs_t duration = mPattern[mIndex];
-    if (vibratorOn) {
-#if DEBUG_VIBRATOR
-        ALOGD("nextStep: sending vibrate deviceId=%d, duration=%" PRId64, getDeviceId(), duration);
-#endif
-        getEventHub()->vibrate(getDeviceId(), duration);
-    } else {
-#if DEBUG_VIBRATOR
-        ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
-#endif
-        getEventHub()->cancelVibrate(getDeviceId());
-    }
-    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-    mNextStepTime = now + duration;
-    getContext()->requestTimeoutAtTime(mNextStepTime);
-#if DEBUG_VIBRATOR
-    ALOGD("nextStep: scheduled timeout in %0.3fms", duration * 0.000001f);
-#endif
-}
-
-void VibratorInputMapper::stopVibrating() {
-    mVibrating = false;
-#if DEBUG_VIBRATOR
-    ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
-#endif
-    getEventHub()->cancelVibrate(getDeviceId());
-}
-
-void VibratorInputMapper::dump(std::string& dump) {
-    dump += INDENT2 "Vibrator Input Mapper:\n";
-    dump += StringPrintf(INDENT3 "Vibrating: %s\n", toString(mVibrating));
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.h b/services/inputflinger/reader/mapper/VibratorInputMapper.h
deleted file mode 100644
index 6b33f48..0000000
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_VIBRATOR_INPUT_MAPPER_H
-#define _UI_INPUTREADER_VIBRATOR_INPUT_MAPPER_H
-
-#include "InputMapper.h"
-
-namespace android {
-
-class VibratorInputMapper : public InputMapper {
-public:
-    explicit VibratorInputMapper(InputDevice* device);
-    virtual ~VibratorInputMapper();
-
-    virtual uint32_t getSources();
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void process(const RawEvent* rawEvent);
-
-    virtual void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, int32_t token);
-    virtual void cancelVibrate(int32_t token);
-    virtual void timeoutExpired(nsecs_t when);
-    virtual void dump(std::string& dump);
-
-private:
-    bool mVibrating;
-    nsecs_t mPattern[MAX_VIBRATE_PATTERN_SIZE];
-    size_t mPatternSize;
-    ssize_t mRepeat;
-    int32_t mToken;
-    ssize_t mIndex;
-    nsecs_t mNextStepTime;
-
-    void nextStep();
-    void stopVibrating();
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_VIBRATOR_INPUT_MAPPER_H
\ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp
deleted file mode 100644
index 0337d51..0000000
--- a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "CursorButtonAccumulator.h"
-
-#include "EventHub.h"
-#include "InputDevice.h"
-
-namespace android {
-
-CursorButtonAccumulator::CursorButtonAccumulator() {
-    clearButtons();
-}
-
-void CursorButtonAccumulator::reset(InputDevice* device) {
-    mBtnLeft = device->isKeyPressed(BTN_LEFT);
-    mBtnRight = device->isKeyPressed(BTN_RIGHT);
-    mBtnMiddle = device->isKeyPressed(BTN_MIDDLE);
-    mBtnBack = device->isKeyPressed(BTN_BACK);
-    mBtnSide = device->isKeyPressed(BTN_SIDE);
-    mBtnForward = device->isKeyPressed(BTN_FORWARD);
-    mBtnExtra = device->isKeyPressed(BTN_EXTRA);
-    mBtnTask = device->isKeyPressed(BTN_TASK);
-}
-
-void CursorButtonAccumulator::clearButtons() {
-    mBtnLeft = 0;
-    mBtnRight = 0;
-    mBtnMiddle = 0;
-    mBtnBack = 0;
-    mBtnSide = 0;
-    mBtnForward = 0;
-    mBtnExtra = 0;
-    mBtnTask = 0;
-}
-
-void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
-    if (rawEvent->type == EV_KEY) {
-        switch (rawEvent->code) {
-            case BTN_LEFT:
-                mBtnLeft = rawEvent->value;
-                break;
-            case BTN_RIGHT:
-                mBtnRight = rawEvent->value;
-                break;
-            case BTN_MIDDLE:
-                mBtnMiddle = rawEvent->value;
-                break;
-            case BTN_BACK:
-                mBtnBack = rawEvent->value;
-                break;
-            case BTN_SIDE:
-                mBtnSide = rawEvent->value;
-                break;
-            case BTN_FORWARD:
-                mBtnForward = rawEvent->value;
-                break;
-            case BTN_EXTRA:
-                mBtnExtra = rawEvent->value;
-                break;
-            case BTN_TASK:
-                mBtnTask = rawEvent->value;
-                break;
-        }
-    }
-}
-
-uint32_t CursorButtonAccumulator::getButtonState() const {
-    uint32_t result = 0;
-    if (mBtnLeft) {
-        result |= AMOTION_EVENT_BUTTON_PRIMARY;
-    }
-    if (mBtnRight) {
-        result |= AMOTION_EVENT_BUTTON_SECONDARY;
-    }
-    if (mBtnMiddle) {
-        result |= AMOTION_EVENT_BUTTON_TERTIARY;
-    }
-    if (mBtnBack || mBtnSide) {
-        result |= AMOTION_EVENT_BUTTON_BACK;
-    }
-    if (mBtnForward || mBtnExtra) {
-        result |= AMOTION_EVENT_BUTTON_FORWARD;
-    }
-    return result;
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h
deleted file mode 100644
index d912310..0000000
--- a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_CURSOR_BUTTON_ACCUMULATOR_H
-#define _UI_INPUTREADER_CURSOR_BUTTON_ACCUMULATOR_H
-
-#include <stdint.h>
-
-namespace android {
-
-class InputDevice;
-struct RawEvent;
-
-/* Keeps track of the state of mouse or touch pad buttons. */
-class CursorButtonAccumulator {
-public:
-    CursorButtonAccumulator();
-    void reset(InputDevice* device);
-
-    void process(const RawEvent* rawEvent);
-
-    uint32_t getButtonState() const;
-
-private:
-    bool mBtnLeft;
-    bool mBtnRight;
-    bool mBtnMiddle;
-    bool mBtnBack;
-    bool mBtnSide;
-    bool mBtnForward;
-    bool mBtnExtra;
-    bool mBtnTask;
-
-    void clearButtons();
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_CURSOR_BUTTON_ACCUMULATOR_H
\ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp
deleted file mode 100644
index d744096..0000000
--- a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "CursorScrollAccumulator.h"
-
-#include "EventHub.h"
-#include "InputDevice.h"
-
-namespace android {
-
-CursorScrollAccumulator::CursorScrollAccumulator() : mHaveRelWheel(false), mHaveRelHWheel(false) {
-    clearRelativeAxes();
-}
-
-void CursorScrollAccumulator::configure(InputDevice* device) {
-    mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
-    mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
-}
-
-void CursorScrollAccumulator::reset(InputDevice* device) {
-    clearRelativeAxes();
-}
-
-void CursorScrollAccumulator::clearRelativeAxes() {
-    mRelWheel = 0;
-    mRelHWheel = 0;
-}
-
-void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
-    if (rawEvent->type == EV_REL) {
-        switch (rawEvent->code) {
-            case REL_WHEEL:
-                mRelWheel = rawEvent->value;
-                break;
-            case REL_HWHEEL:
-                mRelHWheel = rawEvent->value;
-                break;
-        }
-    }
-}
-
-void CursorScrollAccumulator::finishSync() {
-    clearRelativeAxes();
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h
deleted file mode 100644
index 85f331f..0000000
--- a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_CURSOR_SCROLL_ACCUMULATOR_H
-#define _UI_INPUTREADER_CURSOR_SCROLL_ACCUMULATOR_H
-
-#include <stdint.h>
-
-namespace android {
-
-class InputDevice;
-struct RawEvent;
-
-/* Keeps track of cursor scrolling motions. */
-
-class CursorScrollAccumulator {
-public:
-    CursorScrollAccumulator();
-    void configure(InputDevice* device);
-    void reset(InputDevice* device);
-
-    void process(const RawEvent* rawEvent);
-    void finishSync();
-
-    inline bool haveRelativeVWheel() const { return mHaveRelWheel; }
-    inline bool haveRelativeHWheel() const { return mHaveRelHWheel; }
-
-    inline int32_t getRelativeX() const { return mRelX; }
-    inline int32_t getRelativeY() const { return mRelY; }
-    inline int32_t getRelativeVWheel() const { return mRelWheel; }
-    inline int32_t getRelativeHWheel() const { return mRelHWheel; }
-
-private:
-    bool mHaveRelWheel;
-    bool mHaveRelHWheel;
-
-    int32_t mRelX;
-    int32_t mRelY;
-    int32_t mRelWheel;
-    int32_t mRelHWheel;
-
-    void clearRelativeAxes();
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_CURSOR_SCROLL_ACCUMULATOR_H
\ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp
deleted file mode 100644
index e9ba727..0000000
--- a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "SingleTouchMotionAccumulator.h"
-
-#include "EventHub.h"
-#include "InputDevice.h"
-
-namespace android {
-
-SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
-    clearAbsoluteAxes();
-}
-
-void SingleTouchMotionAccumulator::reset(InputDevice* device) {
-    mAbsX = device->getAbsoluteAxisValue(ABS_X);
-    mAbsY = device->getAbsoluteAxisValue(ABS_Y);
-    mAbsPressure = device->getAbsoluteAxisValue(ABS_PRESSURE);
-    mAbsToolWidth = device->getAbsoluteAxisValue(ABS_TOOL_WIDTH);
-    mAbsDistance = device->getAbsoluteAxisValue(ABS_DISTANCE);
-    mAbsTiltX = device->getAbsoluteAxisValue(ABS_TILT_X);
-    mAbsTiltY = device->getAbsoluteAxisValue(ABS_TILT_Y);
-}
-
-void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
-    mAbsX = 0;
-    mAbsY = 0;
-    mAbsPressure = 0;
-    mAbsToolWidth = 0;
-    mAbsDistance = 0;
-    mAbsTiltX = 0;
-    mAbsTiltY = 0;
-}
-
-void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
-    if (rawEvent->type == EV_ABS) {
-        switch (rawEvent->code) {
-            case ABS_X:
-                mAbsX = rawEvent->value;
-                break;
-            case ABS_Y:
-                mAbsY = rawEvent->value;
-                break;
-            case ABS_PRESSURE:
-                mAbsPressure = rawEvent->value;
-                break;
-            case ABS_TOOL_WIDTH:
-                mAbsToolWidth = rawEvent->value;
-                break;
-            case ABS_DISTANCE:
-                mAbsDistance = rawEvent->value;
-                break;
-            case ABS_TILT_X:
-                mAbsTiltX = rawEvent->value;
-                break;
-            case ABS_TILT_Y:
-                mAbsTiltY = rawEvent->value;
-                break;
-        }
-    }
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h
deleted file mode 100644
index 75f8a96..0000000
--- a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_SINGLE_TOUCH_MOTION_ACCUMULATOR_H
-#define _UI_INPUTREADER_SINGLE_TOUCH_MOTION_ACCUMULATOR_H
-
-#include <stdint.h>
-
-namespace android {
-
-class InputDevice;
-struct RawEvent;
-
-/* Keeps track of the state of single-touch protocol. */
-class SingleTouchMotionAccumulator {
-public:
-    SingleTouchMotionAccumulator();
-
-    void process(const RawEvent* rawEvent);
-    void reset(InputDevice* device);
-
-    inline int32_t getAbsoluteX() const { return mAbsX; }
-    inline int32_t getAbsoluteY() const { return mAbsY; }
-    inline int32_t getAbsolutePressure() const { return mAbsPressure; }
-    inline int32_t getAbsoluteToolWidth() const { return mAbsToolWidth; }
-    inline int32_t getAbsoluteDistance() const { return mAbsDistance; }
-    inline int32_t getAbsoluteTiltX() const { return mAbsTiltX; }
-    inline int32_t getAbsoluteTiltY() const { return mAbsTiltY; }
-
-private:
-    int32_t mAbsX;
-    int32_t mAbsY;
-    int32_t mAbsPressure;
-    int32_t mAbsToolWidth;
-    int32_t mAbsDistance;
-    int32_t mAbsTiltX;
-    int32_t mAbsTiltY;
-
-    void clearAbsoluteAxes();
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_SINGLE_TOUCH_MOTION_ACCUMULATOR_H
\ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp
deleted file mode 100644
index d2f06c8..0000000
--- a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "TouchButtonAccumulator.h"
-
-#include "EventHub.h"
-#include "InputDevice.h"
-
-namespace android {
-
-TouchButtonAccumulator::TouchButtonAccumulator() : mHaveBtnTouch(false), mHaveStylus(false) {
-    clearButtons();
-}
-
-void TouchButtonAccumulator::configure(InputDevice* device) {
-    mHaveBtnTouch = device->hasKey(BTN_TOUCH);
-    mHaveStylus = device->hasKey(BTN_TOOL_PEN) || device->hasKey(BTN_TOOL_RUBBER) ||
-            device->hasKey(BTN_TOOL_BRUSH) || device->hasKey(BTN_TOOL_PENCIL) ||
-            device->hasKey(BTN_TOOL_AIRBRUSH);
-}
-
-void TouchButtonAccumulator::reset(InputDevice* device) {
-    mBtnTouch = device->isKeyPressed(BTN_TOUCH);
-    mBtnStylus = device->isKeyPressed(BTN_STYLUS);
-    // BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
-    mBtnStylus2 = device->isKeyPressed(BTN_STYLUS2) || device->isKeyPressed(BTN_0);
-    mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER);
-    mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN);
-    mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER);
-    mBtnToolBrush = device->isKeyPressed(BTN_TOOL_BRUSH);
-    mBtnToolPencil = device->isKeyPressed(BTN_TOOL_PENCIL);
-    mBtnToolAirbrush = device->isKeyPressed(BTN_TOOL_AIRBRUSH);
-    mBtnToolMouse = device->isKeyPressed(BTN_TOOL_MOUSE);
-    mBtnToolLens = device->isKeyPressed(BTN_TOOL_LENS);
-    mBtnToolDoubleTap = device->isKeyPressed(BTN_TOOL_DOUBLETAP);
-    mBtnToolTripleTap = device->isKeyPressed(BTN_TOOL_TRIPLETAP);
-    mBtnToolQuadTap = device->isKeyPressed(BTN_TOOL_QUADTAP);
-}
-
-void TouchButtonAccumulator::clearButtons() {
-    mBtnTouch = 0;
-    mBtnStylus = 0;
-    mBtnStylus2 = 0;
-    mBtnToolFinger = 0;
-    mBtnToolPen = 0;
-    mBtnToolRubber = 0;
-    mBtnToolBrush = 0;
-    mBtnToolPencil = 0;
-    mBtnToolAirbrush = 0;
-    mBtnToolMouse = 0;
-    mBtnToolLens = 0;
-    mBtnToolDoubleTap = 0;
-    mBtnToolTripleTap = 0;
-    mBtnToolQuadTap = 0;
-}
-
-void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
-    if (rawEvent->type == EV_KEY) {
-        switch (rawEvent->code) {
-            case BTN_TOUCH:
-                mBtnTouch = rawEvent->value;
-                break;
-            case BTN_STYLUS:
-                mBtnStylus = rawEvent->value;
-                break;
-            case BTN_STYLUS2:
-            case BTN_0: // BTN_0 is what gets mapped for the HID usage
-                        // Digitizers.SecondaryBarrelSwitch
-                mBtnStylus2 = rawEvent->value;
-                break;
-            case BTN_TOOL_FINGER:
-                mBtnToolFinger = rawEvent->value;
-                break;
-            case BTN_TOOL_PEN:
-                mBtnToolPen = rawEvent->value;
-                break;
-            case BTN_TOOL_RUBBER:
-                mBtnToolRubber = rawEvent->value;
-                break;
-            case BTN_TOOL_BRUSH:
-                mBtnToolBrush = rawEvent->value;
-                break;
-            case BTN_TOOL_PENCIL:
-                mBtnToolPencil = rawEvent->value;
-                break;
-            case BTN_TOOL_AIRBRUSH:
-                mBtnToolAirbrush = rawEvent->value;
-                break;
-            case BTN_TOOL_MOUSE:
-                mBtnToolMouse = rawEvent->value;
-                break;
-            case BTN_TOOL_LENS:
-                mBtnToolLens = rawEvent->value;
-                break;
-            case BTN_TOOL_DOUBLETAP:
-                mBtnToolDoubleTap = rawEvent->value;
-                break;
-            case BTN_TOOL_TRIPLETAP:
-                mBtnToolTripleTap = rawEvent->value;
-                break;
-            case BTN_TOOL_QUADTAP:
-                mBtnToolQuadTap = rawEvent->value;
-                break;
-        }
-    }
-}
-
-uint32_t TouchButtonAccumulator::getButtonState() const {
-    uint32_t result = 0;
-    if (mBtnStylus) {
-        result |= AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
-    }
-    if (mBtnStylus2) {
-        result |= AMOTION_EVENT_BUTTON_STYLUS_SECONDARY;
-    }
-    return result;
-}
-
-int32_t TouchButtonAccumulator::getToolType() const {
-    if (mBtnToolMouse || mBtnToolLens) {
-        return AMOTION_EVENT_TOOL_TYPE_MOUSE;
-    }
-    if (mBtnToolRubber) {
-        return AMOTION_EVENT_TOOL_TYPE_ERASER;
-    }
-    if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) {
-        return AMOTION_EVENT_TOOL_TYPE_STYLUS;
-    }
-    if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap) {
-        return AMOTION_EVENT_TOOL_TYPE_FINGER;
-    }
-    return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
-}
-
-bool TouchButtonAccumulator::isToolActive() const {
-    return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber || mBtnToolBrush ||
-            mBtnToolPencil || mBtnToolAirbrush || mBtnToolMouse || mBtnToolLens ||
-            mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap;
-}
-
-bool TouchButtonAccumulator::isHovering() const {
-    return mHaveBtnTouch && !mBtnTouch;
-}
-
-bool TouchButtonAccumulator::hasStylus() const {
-    return mHaveStylus;
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h
deleted file mode 100644
index 65b6bdc..0000000
--- a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_TOUCH_BUTTON_ACCUMULATOR_H
-#define _UI_INPUTREADER_TOUCH_BUTTON_ACCUMULATOR_H
-
-#include <stdint.h>
-
-namespace android {
-
-class InputDevice;
-struct RawEvent;
-
-/* Keeps track of the state of touch, stylus and tool buttons. */
-class TouchButtonAccumulator {
-public:
-    TouchButtonAccumulator();
-    void configure(InputDevice* device);
-    void reset(InputDevice* device);
-
-    void process(const RawEvent* rawEvent);
-
-    uint32_t getButtonState() const;
-    int32_t getToolType() const;
-    bool isToolActive() const;
-    bool isHovering() const;
-    bool hasStylus() const;
-
-private:
-    bool mHaveBtnTouch;
-    bool mHaveStylus;
-
-    bool mBtnTouch;
-    bool mBtnStylus;
-    bool mBtnStylus2;
-    bool mBtnToolFinger;
-    bool mBtnToolPen;
-    bool mBtnToolRubber;
-    bool mBtnToolBrush;
-    bool mBtnToolPencil;
-    bool mBtnToolAirbrush;
-    bool mBtnToolMouse;
-    bool mBtnToolLens;
-    bool mBtnToolDoubleTap;
-    bool mBtnToolTripleTap;
-    bool mBtnToolQuadTap;
-
-    void clearButtons();
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_TOUCH_BUTTON_ACCUMULATOR_H
\ No newline at end of file
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index c4f8626..9054316 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -32,7 +32,4 @@
         "libinputflinger_base",
         "libinputservice",
     ],
-    header_libs: [
-        "libinputreader_headers",
-    ],
 }
diff --git a/services/inputflinger/tests/InputClassifier_test.cpp b/services/inputflinger/tests/InputClassifier_test.cpp
index 7cc17a2..4cddec5 100644
--- a/services/inputflinger/tests/InputClassifier_test.cpp
+++ b/services/inputflinger/tests/InputClassifier_test.cpp
@@ -22,6 +22,9 @@
 #include <android/hardware/input/classifier/1.0/IInputClassifier.h>
 
 using namespace android::hardware::input;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::input::common::V1_0::Classification;
 
 namespace android {
 
@@ -129,6 +132,49 @@
     ASSERT_EQ(args, outArgs);
 }
 
+TEST_F(InputClassifierTest, SetMotionClassifier_Enabled) {
+    mClassifier->setMotionClassifierEnabled(true);
+}
+
+TEST_F(InputClassifierTest, SetMotionClassifier_Disabled) {
+    mClassifier->setMotionClassifierEnabled(false);
+}
+
+/**
+ * Try to break it by calling setMotionClassifierEnabled multiple times.
+ */
+TEST_F(InputClassifierTest, SetMotionClassifier_Multiple) {
+    mClassifier->setMotionClassifierEnabled(true);
+    mClassifier->setMotionClassifierEnabled(true);
+    mClassifier->setMotionClassifierEnabled(true);
+    mClassifier->setMotionClassifierEnabled(false);
+    mClassifier->setMotionClassifierEnabled(false);
+    mClassifier->setMotionClassifierEnabled(true);
+    mClassifier->setMotionClassifierEnabled(true);
+    mClassifier->setMotionClassifierEnabled(true);
+}
+
+/**
+ * A minimal implementation of IInputClassifier.
+ */
+struct TestHal : public android::hardware::input::classifier::V1_0::IInputClassifier {
+    Return<Classification> classify(
+            const android::hardware::input::common::V1_0::MotionEvent& event) override {
+        return Classification::NONE;
+    };
+    Return<void> reset() override { return Void(); };
+    Return<void> resetDevice(int32_t deviceId) override { return Void(); };
+};
+
+/**
+ * An entity that will be subscribed to the HAL death.
+ */
+class TestDeathRecipient : public android::hardware::hidl_death_recipient {
+public:
+    virtual void serviceDied(uint64_t cookie,
+                             const wp<android::hidl::base::V1_0::IBase>& who) override{};
+};
+
 // --- MotionClassifierTest ---
 
 class MotionClassifierTest : public testing::Test {
@@ -136,7 +182,14 @@
     std::unique_ptr<MotionClassifierInterface> mMotionClassifier;
 
     virtual void SetUp() override {
-        mMotionClassifier = std::make_unique<MotionClassifier>();
+        mMotionClassifier = MotionClassifier::create(new TestDeathRecipient());
+        if (mMotionClassifier == nullptr) {
+            // If the device running this test does not have IInputClassifier service,
+            // use the test HAL instead.
+            // Using 'new' to access non-public constructor
+            mMotionClassifier =
+                    std::unique_ptr<MotionClassifier>(new MotionClassifier(new TestHal()));
+        }
     }
 };
 
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 551bee1..9fe6481 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -14,16 +14,14 @@
  * limitations under the License.
  */
 
-#include "../dispatcher/InputDispatcher.h"
-
-#include <InputDispatcherThread.h>
+#include "../InputDispatcher.h"
 
 #include <binder/Binder.h>
 
 #include <gtest/gtest.h>
 #include <linux/input.h>
 
-namespace android::inputdispatcher {
+namespace android {
 
 // An arbitrary time value.
 static const nsecs_t ARBITRARY_TIME = 1234;
@@ -1027,4 +1025,4 @@
     mFakePolicy->assertOnPointerDownEquals(nullptr);
 }
 
-} // namespace android::inputdispatcher
+} // namespace android
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index aeb4ad6..d353028 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -14,16 +14,8 @@
  * limitations under the License.
  */
 
-#include <CursorInputMapper.h>
-#include <InputDevice.h>
-#include <InputMapper.h>
-#include <InputReader.h>
-#include <KeyboardInputMapper.h>
-#include <MultiTouchInputMapper.h>
-#include <SingleTouchInputMapper.h>
-#include <SwitchInputMapper.h>
-#include <TestInputListener.h>
-#include <TouchInputMapper.h>
+#include "../InputReader.h"
+#include "TestInputListener.h"
 
 #include <gtest/gtest.h>
 #include <inttypes.h>
diff --git a/services/nativeperms/.clang-format b/services/nativeperms/.clang-format
new file mode 100644
index 0000000..6006e6f
--- /dev/null
+++ b/services/nativeperms/.clang-format
@@ -0,0 +1,13 @@
+BasedOnStyle: Google
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: true
+AllowShortLoopsOnASingleLine: true
+BinPackArguments: true
+BinPackParameters: true
+ColumnLimit: 80
+CommentPragmas: NOLINT:.*
+ContinuationIndentWidth: 8
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
diff --git a/services/inputflinger/reporter/Android.bp b/services/nativeperms/Android.bp
similarity index 60%
rename from services/inputflinger/reporter/Android.bp
rename to services/nativeperms/Android.bp
index 5956fb0..cbc7d66 100644
--- a/services/inputflinger/reporter/Android.bp
+++ b/services/nativeperms/Android.bp
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 The Android Open Source Project
+// Copyright 2016 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -11,31 +11,24 @@
 // 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.
+//
 
-cc_library_headers {
-    name: "libinputreporter_headers",
-    export_include_dirs: ["."],
-}
-
-cc_library_shared {
-    name: "libinputreporter",
-    defaults: ["inputflinger_defaults"],
-
+cc_binary {
+    name: "nativeperms",
     srcs: [
-        "InputReporter.cpp",
+        "nativeperms.cpp",
+        "android/os/IPermissionController.aidl",
     ],
-
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
     shared_libs: [
-        "liblog",
+        "libbinder",
+        "libbrillo",
+        "libbrillo-binder",
+        "libchrome",
         "libutils",
     ],
-
-    header_libs: [
-        "libinputflinger_headers",
-    ],
-
-    export_header_lib_headers: [
-        "libinputflinger_headers",
-    ],
+    init_rc: ["nativeperms.rc"],
 }
-
diff --git a/services/nativeperms/android/os/IPermissionController.aidl b/services/nativeperms/android/os/IPermissionController.aidl
new file mode 100644
index 0000000..89db85c
--- /dev/null
+++ b/services/nativeperms/android/os/IPermissionController.aidl
@@ -0,0 +1,25 @@
+/* //device/java/android/android/os/IPowerManager.aidl
+**
+** Copyright 2007, 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.
+*/
+
+package android.os;
+
+/** @hide */
+interface IPermissionController {
+    boolean checkPermission(String permission, int pid, int uid);
+    String[] getPackagesForUid(int uid);
+    boolean isRuntimePermission(String permission);
+}
diff --git a/services/nativeperms/android/os/README b/services/nativeperms/android/os/README
new file mode 100644
index 0000000..e414499
--- /dev/null
+++ b/services/nativeperms/android/os/README
@@ -0,0 +1,4 @@
+IPermissionController.aidl in this directory is a verbatim copy of
+https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/IPermissionController.aidl,
+because some Brillo manifests do not currently include the frameworks/base repo.
+TODO(jorgelo): Figure out a way to use the .aidl file in frameworks/base.
diff --git a/services/nativeperms/nativeperms.cpp b/services/nativeperms/nativeperms.cpp
new file mode 100644
index 0000000..7f03bed
--- /dev/null
+++ b/services/nativeperms/nativeperms.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <base/at_exit.h>
+#include <base/logging.h>
+#include <base/message_loop/message_loop.h>
+#include <binder/IServiceManager.h>
+#include <binder/Status.h>
+#include <brillo/binder_watcher.h>
+#include <brillo/message_loops/base_message_loop.h>
+#include <brillo/syslog_logging.h>
+#include <utils/String16.h>
+
+#include "android/os/BnPermissionController.h"
+
+namespace {
+static android::String16 serviceName("permission");
+}
+
+namespace android {
+
+class PermissionService : public android::os::BnPermissionController {
+   public:
+    ::android::binder::Status checkPermission(
+            const ::android::String16& permission, int32_t pid, int32_t uid,
+            bool* _aidl_return) {
+        (void)permission;
+        (void)pid;
+        (void)uid;
+        *_aidl_return = true;
+        return binder::Status::ok();
+    }
+
+    ::android::binder::Status getPackagesForUid(
+            int32_t uid, ::std::vector<::android::String16>* _aidl_return) {
+        (void)uid;
+        // Brillo doesn't currently have installable packages.
+        if (_aidl_return) {
+            _aidl_return->clear();
+        }
+        return binder::Status::ok();
+    }
+
+    ::android::binder::Status isRuntimePermission(
+            const ::android::String16& permission, bool* _aidl_return) {
+        (void)permission;
+        // Brillo doesn't currently have runtime permissions.
+        *_aidl_return = false;
+        return binder::Status::ok();
+    }
+};
+
+}  // namespace android
+
+int main() {
+    base::AtExitManager atExitManager;
+    brillo::InitLog(brillo::kLogToSyslog);
+    // Register the service with servicemanager.
+    android::status_t status = android::defaultServiceManager()->addService(
+            serviceName, new android::PermissionService());
+    CHECK(status == android::OK) << "Failed to get IPermissionController "
+                                    "binder from servicemanager.";
+
+    // Create a message loop.
+    base::MessageLoopForIO messageLoopForIo;
+    brillo::BaseMessageLoop messageLoop{&messageLoopForIo};
+
+    // Initialize a binder watcher.
+    brillo::BinderWatcher watcher(&messageLoop);
+    watcher.Init();
+
+    // Run the message loop.
+    messageLoop.Run();
+}
diff --git a/services/nativeperms/nativeperms.rc b/services/nativeperms/nativeperms.rc
new file mode 100644
index 0000000..704c0a2
--- /dev/null
+++ b/services/nativeperms/nativeperms.rc
@@ -0,0 +1,4 @@
+service nativeperms /system/bin/nativeperms
+    class main
+    user system
+    group system
diff --git a/services/schedulerservice/Android.bp b/services/schedulerservice/Android.bp
index 73802db..0227164 100644
--- a/services/schedulerservice/Android.bp
+++ b/services/schedulerservice/Android.bp
@@ -6,6 +6,8 @@
     cflags: ["-Wall", "-Werror"],
     shared_libs: [
         "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
         "libmediautils",
         "liblog",
         "libutils",
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index 1c9a4af..33a2747 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -45,6 +45,8 @@
         "libcrypto",
         "libbase",
         "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
         "libfmq",
         "android.hardware.sensors@1.0",
         "android.hardware.sensors@2.0",
diff --git a/services/sensorservice/OWNERS b/services/sensorservice/OWNERS
index 90c2330..81099e8 100644
--- a/services/sensorservice/OWNERS
+++ b/services/sensorservice/OWNERS
@@ -1,3 +1,3 @@
 arthuri@google.com
 bduddie@google.com
-stange@google.com
+bstack@google.com
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 14ed73d..090a0ce 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -208,12 +208,6 @@
                 registerSensor(new RotationVectorSensor(), !needRotationVector, true);
                 registerSensor(new OrientationSensor(), !needRotationVector, true);
 
-                bool needLinearAcceleration =
-                        (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) != 0;
-
-                registerSensor(new LinearAccelerationSensor(list, count),
-                               !needLinearAcceleration, true);
-
                 // virtual debugging sensors are not for user
                 registerSensor( new CorrectedGyroSensor(list, count), true, true);
                 registerSensor( new GyroDriftSensor(), true, true);
@@ -223,6 +217,11 @@
                 bool needGravitySensor = (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) != 0;
                 registerSensor(new GravitySensor(list, count), !needGravitySensor, true);
 
+                bool needLinearAcceleration =
+                        (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) != 0;
+                registerSensor(new LinearAccelerationSensor(list, count),
+                               !needLinearAcceleration, true);
+
                 bool needGameRotationVector =
                         (virtualSensorsNeeds & (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR)) != 0;
                 registerSensor(new GameRotationVectorSensor(), !needGameRotationVector, true);
diff --git a/services/sensorservice/hidl/Android.bp b/services/sensorservice/hidl/Android.bp
index d0c83d6..02c13fa 100644
--- a/services/sensorservice/hidl/Android.bp
+++ b/services/sensorservice/hidl/Android.bp
@@ -13,6 +13,8 @@
     shared_libs: [
         "libbase",
         "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
         "libutils",
         "libsensor",
         "android.frameworks.sensorservice@1.0",
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index cda982a..501d176 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -43,6 +43,8 @@
         "libgui",
         "libhardware",
         "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
         "liblayers_proto",
         "liblog",
         "libnativewindow",
@@ -83,6 +85,8 @@
         "android.hardware.graphics.composer@2.3",
         "android.hardware.power@1.3",
         "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
     ],
 }
 
@@ -96,10 +100,6 @@
     lto: {
         thin: true,
     },
-    // TODO(b/131771163): Fix broken fuzzer support with LTO.
-    sanitize: {
-        fuzzer: false,
-    },
 }
 
 cc_library_headers {
@@ -183,6 +183,9 @@
     cflags: [
         "-DLOG_TAG=\"SurfaceFlinger\"",
     ],
+    whole_static_libs: [
+        "libsigchain",
+    ],
     shared_libs: [
         "android.frameworks.displayservice@1.0",
         "android.hardware.configstore-utils",
@@ -193,6 +196,7 @@
         "libcutils",
         "libdisplayservicehidl",
         "libhidlbase",
+        "libhidltransport",
         "libinput",
         "liblayers_proto",
         "liblog",
@@ -241,6 +245,8 @@
         "android.hardware.configstore@1.1",
         "android.hardware.graphics.common@1.2",
         "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
         "libui",
         "libutils",
         "liblog",
@@ -251,6 +257,8 @@
     export_shared_lib_headers: [
         "android.hardware.graphics.common@1.2",
         "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
     ],
     export_static_lib_headers: [
         "SurfaceFlingerProperties",
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index cbb9d65..eb1bf66 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -243,9 +243,8 @@
     bool sidebandStreamChanged = true;
     if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false)) {
         // mSidebandStreamChanged was changed to false
-        mSidebandStream = mConsumer->getSidebandStream();
         auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
-        layerCompositionState.sidebandStream = mSidebandStream;
+        layerCompositionState.sidebandStream = mConsumer->getSidebandStream();
         if (layerCompositionState.sidebandStream != nullptr) {
             setTransactionFlags(eTransactionNeeded);
             mFlinger->setTransactionFlags(eTraversalNeeded);
@@ -462,6 +461,7 @@
             status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
             if (result != NO_ERROR) {
                 ALOGE("[%s] Timed out waiting on callback", mName.string());
+                break;
             }
         }
 
@@ -496,6 +496,7 @@
             status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
             if (result != NO_ERROR) {
                 ALOGE("[%s] Timed out waiting on callback", mName.string());
+                break;
             }
         }
 
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index 1c31ab9..6f076ad 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -118,13 +118,6 @@
         //
         // You can either "make dist tests" before flashing, or set this
         // option to false temporarily.
-
-
-        // FIXME: ASAN build is broken for a while, but was not discovered
-        // since new PM silently suppressed ASAN. Temporarily turn off ASAN
-        // to unblock the compiler upgrade process.
-        // address: true,
-        // http://b/139747256
-        address: false,
+        address: true,
     },
 }
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 5700d72..4a13bfb 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -272,17 +272,13 @@
         scissor = displayBounds;
     }
 
-    uint32_t transformOrientation;
-
     if (isPrimary()) {
         sPrimaryDisplayOrientation = displayStateOrientationToTransformOrientation(orientation);
-        transformOrientation = displayStateOrientationToTransformOrientation(
-                (orientation + mDisplayInstallOrientation) % (DisplayState::eOrientation270 + 1));
-    } else {
-        transformOrientation = displayStateOrientationToTransformOrientation(orientation);
     }
 
-    getCompositionDisplay()->setProjection(globalTransform, transformOrientation,
+    getCompositionDisplay()->setProjection(globalTransform,
+                                           displayStateOrientationToTransformOrientation(
+                                                   orientation),
                                            frame, viewport, scissor, needsFiltering);
 }
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3e6dded..44f3eae 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -153,6 +153,7 @@
     mRemoteSyncPoints.clear();
 
     {
+        Mutex::Autolock pendingStateLock(mPendingStateMutex);
         for (State pendingState : mPendingStates) {
             pendingState.barrierLayer_legacy = nullptr;
         }
@@ -906,7 +907,6 @@
 
     // Commit the transaction
     commitTransaction(c);
-    mPendingStatesSnapshot = mPendingStates;
     mCurrentState.callbackHandles = {};
     return flags;
 }
@@ -1874,61 +1874,14 @@
     setTransactionFlags(eTransactionNeeded);
 }
 
-void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) const {
-    ui::Transform transform = getTransform();
-
-    if (traceFlags & SurfaceTracing::TRACE_CRITICAL) {
-        for (const auto& pendingState : mPendingStatesSnapshot) {
-            auto barrierLayer = pendingState.barrierLayer_legacy.promote();
-            if (barrierLayer != nullptr) {
-                BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer();
-                barrierLayerProto->set_id(barrierLayer->sequence);
-                barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy);
-            }
-        }
-
-        auto buffer = mActiveBuffer;
-        if (buffer != nullptr) {
-            LayerProtoHelper::writeToProto(buffer,
-                                           [&]() { return layerInfo->mutable_active_buffer(); });
-            LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform),
-                                           layerInfo->mutable_buffer_transform());
-        }
-        layerInfo->set_invalidate(contentDirty);
-        layerInfo->set_is_protected(isProtected());
-        layerInfo->set_dataspace(
-                dataspaceDetails(static_cast<android_dataspace>(mCurrentDataSpace)));
-        layerInfo->set_queued_frames(getQueuedFrameCount());
-        layerInfo->set_refresh_pending(isBufferLatched());
-        layerInfo->set_curr_frame(mCurrentFrameNumber);
-        layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
-
-        layerInfo->set_corner_radius(getRoundedCornerState().radius);
-        LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform());
-        LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
-                                               [&]() { return layerInfo->mutable_position(); });
-        LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
-        LayerProtoHelper::writeToProto(visibleRegion,
-                                       [&]() { return layerInfo->mutable_visible_region(); });
-        LayerProtoHelper::writeToProto(surfaceDamageRegion,
-                                       [&]() { return layerInfo->mutable_damage_region(); });
-    }
-
-    if (traceFlags & SurfaceTracing::TRACE_EXTRA) {
-        LayerProtoHelper::writeToProto(mSourceBounds,
-                                       [&]() { return layerInfo->mutable_source_bounds(); });
-        LayerProtoHelper::writeToProto(mScreenBounds,
-                                       [&]() { return layerInfo->mutable_screen_bounds(); });
-    }
-}
-
-void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet,
-                                    uint32_t traceFlags) const {
+void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet,
+                         uint32_t traceFlags) {
     const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
     const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
     const State& state = useDrawing ? mDrawingState : mCurrentState;
 
     ui::Transform requestedTransform = state.active_legacy.transform;
+    ui::Transform transform = getTransform();
 
     if (traceFlags & SurfaceTracing::TRACE_CRITICAL) {
         layerInfo->set_id(sequence);
@@ -1948,10 +1901,17 @@
 
         LayerProtoHelper::writeToProto(state.activeTransparentRegion_legacy,
                                        [&]() { return layerInfo->mutable_transparent_region(); });
+        LayerProtoHelper::writeToProto(visibleRegion,
+                                       [&]() { return layerInfo->mutable_visible_region(); });
+        LayerProtoHelper::writeToProto(surfaceDamageRegion,
+                                       [&]() { return layerInfo->mutable_damage_region(); });
 
         layerInfo->set_layer_stack(getLayerStack());
         layerInfo->set_z(state.z);
 
+        LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
+                                               [&]() { return layerInfo->mutable_position(); });
+
         LayerProtoHelper::writePositionToProto(requestedTransform.tx(), requestedTransform.ty(),
                                                [&]() {
                                                    return layerInfo->mutable_requested_position();
@@ -1962,9 +1922,15 @@
 
         LayerProtoHelper::writeToProto(state.crop_legacy,
                                        [&]() { return layerInfo->mutable_crop(); });
+        layerInfo->set_corner_radius(getRoundedCornerState().radius);
 
         layerInfo->set_is_opaque(isOpaque(state));
+        layerInfo->set_invalidate(contentDirty);
+        layerInfo->set_is_protected(isProtected());
 
+        // XXX (b/79210409) mCurrentDataSpace is not protected
+        layerInfo->set_dataspace(
+                dataspaceDetails(static_cast<android_dataspace>(mCurrentDataSpace)));
 
         layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat()));
         LayerProtoHelper::writeToProto(getColor(), [&]() { return layerInfo->mutable_color(); });
@@ -1972,6 +1938,7 @@
                                        [&]() { return layerInfo->mutable_requested_color(); });
         layerInfo->set_flags(state.flags);
 
+        LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform());
         LayerProtoHelper::writeToProto(requestedTransform,
                                        layerInfo->mutable_requested_transform());
 
@@ -1988,6 +1955,29 @@
         } else {
             layerInfo->set_z_order_relative_of(-1);
         }
+
+        auto buffer = mActiveBuffer;
+        if (buffer != nullptr) {
+            LayerProtoHelper::writeToProto(buffer,
+                                           [&]() { return layerInfo->mutable_active_buffer(); });
+            LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform),
+                                           layerInfo->mutable_buffer_transform());
+        }
+
+        layerInfo->set_queued_frames(getQueuedFrameCount());
+        layerInfo->set_refresh_pending(isBufferLatched());
+        layerInfo->set_curr_frame(mCurrentFrameNumber);
+        layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
+
+        for (const auto& pendingState : mPendingStates) {
+            auto barrierLayer = pendingState.barrierLayer_legacy.promote();
+            if (barrierLayer != nullptr) {
+                BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer();
+                barrierLayerProto->set_id(barrierLayer->sequence);
+                barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy);
+            }
+        }
+        LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
     }
 
     if (traceFlags & SurfaceTracing::TRACE_INPUT) {
@@ -2000,19 +1990,23 @@
         for (const auto& entry : state.metadata.mMap) {
             (*protoMap)[entry.first] = std::string(entry.second.cbegin(), entry.second.cend());
         }
+        LayerProtoHelper::writeToProto(mEffectiveTransform,
+                                       layerInfo->mutable_effective_transform());
+        LayerProtoHelper::writeToProto(mSourceBounds,
+                                       [&]() { return layerInfo->mutable_source_bounds(); });
+        LayerProtoHelper::writeToProto(mScreenBounds,
+                                       [&]() { return layerInfo->mutable_screen_bounds(); });
     }
 }
 
-void Layer::writeToProtoCompositionState(LayerProto* layerInfo,
-                                         const sp<DisplayDevice>& displayDevice,
-                                         uint32_t traceFlags) const {
+void Layer::writeToProto(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice,
+                         uint32_t traceFlags) {
     auto outputLayer = findOutputLayerForDisplay(displayDevice);
     if (!outputLayer) {
         return;
     }
 
-    writeToProtoDrawingState(layerInfo, traceFlags);
-    writeToProtoCommonState(layerInfo, LayerVector::StateSet::Drawing, traceFlags);
+    writeToProto(layerInfo, LayerVector::StateSet::Drawing, traceFlags);
 
     const auto& compositionState = outputLayer->getState();
 
@@ -2030,12 +2024,26 @@
             static_cast<int32_t>(compositionState.hwc ? (*compositionState.hwc).hwcCompositionType
                                                       : Hwc2::IComposerClient::Composition::CLIENT);
     layerInfo->set_hwc_composition_type(compositionType);
+
+    if (std::strcmp(getTypeId(), "BufferLayer") == 0 &&
+        static_cast<BufferLayer*>(this)->isProtected()) {
+        layerInfo->set_is_protected(true);
+    } else {
+        layerInfo->set_is_protected(false);
+    }
 }
 
 bool Layer::isRemovedFromCurrentState() const  {
     return mRemovedFromCurrentState;
 }
 
+// Debug helper for b/137560795
+#define INT32_MIGHT_OVERFLOW(n) (((n) >= INT32_MAX / 2) || ((n) <= INT32_MIN / 2))
+
+#define RECT_BOUNDS_INVALID(rect)                                               \
+    (INT32_MIGHT_OVERFLOW((rect).left) || INT32_MIGHT_OVERFLOW((rect).right) || \
+     INT32_MIGHT_OVERFLOW((rect).bottom) || INT32_MIGHT_OVERFLOW((rect).top))
+
 InputWindowInfo Layer::fillInputInfo() {
     InputWindowInfo info = mDrawingState.inputInfo;
 
@@ -2046,14 +2054,14 @@
     ui::Transform t = getTransform();
     const float xScale = t.sx();
     const float yScale = t.sy();
-    int32_t xSurfaceInset = info.surfaceInset;
-    int32_t ySurfaceInset = info.surfaceInset;
+    float xSurfaceInset = info.surfaceInset;
+    float ySurfaceInset = info.surfaceInset;
     if (xScale != 1.0f || yScale != 1.0f) {
-        info.windowXScale *= (xScale != 0.0f) ? 1.0f / xScale : 0.0f;
-        info.windowYScale *= (yScale != 0.0f) ? 1.0f / yScale : 0.0f;
+        info.windowXScale *= 1.0f / xScale;
+        info.windowYScale *= 1.0f / yScale;
         info.touchableRegion.scaleSelf(xScale, yScale);
-        xSurfaceInset = std::round(xSurfaceInset * xScale);
-        ySurfaceInset = std::round(ySurfaceInset * yScale);
+        xSurfaceInset *= xScale;
+        ySurfaceInset *= yScale;
     }
 
     // Transform layer size to screen space and inset it by surface insets.
@@ -2066,10 +2074,25 @@
     }
     layerBounds = t.transform(layerBounds);
 
-    // clamp inset to layer bounds
-    xSurfaceInset = (xSurfaceInset >= 0) ? std::min(xSurfaceInset, layerBounds.getWidth() / 2) : 0;
-    ySurfaceInset = (ySurfaceInset >= 0) ? std::min(ySurfaceInset, layerBounds.getHeight() / 2) : 0;
+    // debug check for b/137560795
+    {
+        if (RECT_BOUNDS_INVALID(layerBounds)) {
+            ALOGE("layer %s bounds are invalid (%" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32
+                  ")",
+                  mName.c_str(), layerBounds.left, layerBounds.top, layerBounds.right,
+                  layerBounds.bottom);
+            std::string out;
+            getTransform().dump(out, "Transform");
+            ALOGE("%s", out.c_str());
+            layerBounds.left = layerBounds.top = layerBounds.right = layerBounds.bottom = 0;
+        }
 
+        if (INT32_MIGHT_OVERFLOW(xSurfaceInset) || INT32_MIGHT_OVERFLOW(ySurfaceInset)) {
+            ALOGE("layer %s surface inset are invalid (%" PRIi32 ", %" PRIi32 ")", mName.c_str(),
+                  int32_t(xSurfaceInset), int32_t(ySurfaceInset));
+            xSurfaceInset = ySurfaceInset = 0;
+        }
+    }
     layerBounds.inset(xSurfaceInset, ySurfaceInset, xSurfaceInset, ySurfaceInset);
 
     // Input coordinate should match the layer bounds.
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3b4d873..b46eb11 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -437,21 +437,11 @@
 
     bool isRemovedFromCurrentState() const;
 
-    // Write states that are modified by the main thread. This includes drawing
-    // state as well as buffer data. This should be called in the main or tracing
-    // thread.
-    void writeToProtoDrawingState(LayerProto* layerInfo,
-                                  uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
-    // Write states that are modified by the main thread. This includes drawing
-    // state as well as buffer data and composition data for layers on the specified
-    // display. This should be called in the main or tracing thread.
-    void writeToProtoCompositionState(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice,
-                                      uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
-    // Write drawing or current state. If writing current state, the caller should hold the
-    // external mStateLock. If writing drawing state, this function should be called on the
-    // main or tracing thread.
-    void writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet,
-                                 uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
+    void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet,
+                      uint32_t traceFlags = SurfaceTracing::TRACE_ALL);
+
+    void writeToProto(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice,
+                      uint32_t traceFlags = SurfaceTracing::TRACE_ALL);
 
     virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; }
     virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; }
@@ -841,15 +831,13 @@
 
     bool mPrimaryDisplayOnly = false;
 
-    // These are only accessed by the main thread or the tracing thread.
-    State mDrawingState;
-    // Store a copy of the pending state so that the drawing thread can access the
-    // states without a lock.
-    Vector<State> mPendingStatesSnapshot;
-
-    // these are protected by an external lock (mStateLock)
+    // these are protected by an external lock
     State mCurrentState;
+    State mDrawingState;
     std::atomic<uint32_t> mTransactionFlags{0};
+
+    // Accessed from main thread and binder threads
+    Mutex mPendingStateMutex;
     Vector<State> mPendingStates;
 
     // Timestamp history for UIAutomation. Thread safe.
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 07fdead..80da154 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -200,9 +200,10 @@
 
 void RegionSamplingThread::addListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
                                        const sp<IRegionSamplingListener>& listener) {
-    wp<Layer> stopLayer = stopLayerHandle != nullptr
-            ? static_cast<Layer::Handle*>(stopLayerHandle.get())->owner
-            : nullptr;
+    wp<Layer> stopLayer;
+    if (stopLayerHandle != nullptr && stopLayerHandle->localBinder() != nullptr) {
+        stopLayer = static_cast<Layer::Handle*>(stopLayerHandle.get())->owner;
+    }
 
     sp<IBinder> asBinder = IInterface::asBinder(listener);
     asBinder->linkToDeath(this);
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
index 8a2604f..9fa2bbc 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -96,7 +96,6 @@
     highFpsOffsets.late = {RefreshRateType::PERFORMANCE, highFpsLateSfOffsetNs,
                            highFpsLateAppOffsetNs};
 
-    mOffsets.insert({RefreshRateType::POWER_SAVING, defaultOffsets});
     mOffsets.insert({RefreshRateType::DEFAULT, defaultOffsets});
     mOffsets.insert({RefreshRateType::PERFORMANCE, highFpsOffsets});
 
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index d730058..d813708 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -34,10 +34,9 @@
  */
 class RefreshRateConfigs {
 public:
-    // Enum to indicate which vsync rate to run at. Power saving is intended to be the lowest
-    // (eg. when the screen is in AOD mode or off), default is the old 60Hz, and performance
+    // Enum to indicate which vsync rate to run at. Default is the old 60Hz, and performance
     // is the new 90Hz. Eventually we want to have a way for vendors to map these in the configs.
-    enum class RefreshRateType { POWER_SAVING, DEFAULT, PERFORMANCE };
+    enum class RefreshRateType { DEFAULT, PERFORMANCE };
 
     struct RefreshRate {
         // This config ID corresponds to the position of the config in the vector that is stored
@@ -47,26 +46,57 @@
         std::string name;
         // Refresh rate in frames per second, rounded to the nearest integer.
         uint32_t fps = 0;
-        // config Id (returned from HWC2::Display::Config::getId())
-        hwc2_config_t id;
+        // Vsync period in nanoseconds.
+        nsecs_t vsyncPeriod;
+        // Hwc config Id (returned from HWC2::Display::Config::getId())
+        hwc2_config_t hwcId;
     };
 
+    // Returns true if this device is doing refresh rate switching. This won't change at runtime.
+    bool refreshRateSwitchingSupported() const { return mRefreshRateSwitchingSupported; }
+
+    // Returns the refresh rate map. This map won't be modified at runtime, so it's safe to access
+    // from multiple threads. This can only be called if refreshRateSwitching() returns true.
     // TODO(b/122916473): Get this information from configs prepared by vendors, instead of
     // baking them in.
-    const std::map<RefreshRateType, std::shared_ptr<RefreshRate>>& getRefreshRates() const {
-        return mRefreshRates;
-    }
-    std::shared_ptr<RefreshRate> getRefreshRate(RefreshRateType type) const {
-        const auto& refreshRate = mRefreshRates.find(type);
-        if (refreshRate != mRefreshRates.end()) {
-            return refreshRate->second;
-        }
-        return nullptr;
+    const std::map<RefreshRateType, RefreshRate>& getRefreshRateMap() const {
+        LOG_ALWAYS_FATAL_IF(!mRefreshRateSwitchingSupported);
+        return mRefreshRateMap;
     }
 
-    RefreshRateType getRefreshRateType(hwc2_config_t id) const {
-        for (const auto& [type, refreshRate] : mRefreshRates) {
-            if (refreshRate->id == id) {
+    const RefreshRate& getRefreshRateFromType(RefreshRateType type) const {
+        if (!mRefreshRateSwitchingSupported) {
+            return getCurrentRefreshRate().second;
+        } else {
+            auto refreshRate = mRefreshRateMap.find(type);
+            LOG_ALWAYS_FATAL_IF(refreshRate == mRefreshRateMap.end());
+            return refreshRate->second;
+        }
+    }
+
+    std::pair<RefreshRateType, const RefreshRate&> getCurrentRefreshRate() const {
+        int currentConfig = mCurrentConfig;
+        if (mRefreshRateSwitchingSupported) {
+            for (const auto& [type, refresh] : mRefreshRateMap) {
+                if (refresh.configId == currentConfig) {
+                    return {type, refresh};
+                }
+            }
+            LOG_ALWAYS_FATAL();
+        }
+        return {RefreshRateType::DEFAULT, mRefreshRates[currentConfig]};
+    }
+
+    const RefreshRate& getRefreshRateFromConfigId(int configId) const {
+        LOG_ALWAYS_FATAL_IF(configId >= mRefreshRates.size());
+        return mRefreshRates[configId];
+    }
+
+    RefreshRateType getRefreshRateTypeFromHwcConfigId(hwc2_config_t hwcId) const {
+        if (!mRefreshRateSwitchingSupported) return RefreshRateType::DEFAULT;
+
+        for (const auto& [type, refreshRate] : mRefreshRateMap) {
+            if (refreshRate.hwcId == hwcId) {
                 return type;
             }
         }
@@ -74,64 +104,102 @@
         return RefreshRateType::DEFAULT;
     }
 
-    void populate(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
-        mRefreshRates.clear();
+    void setCurrentConfig(int config) {
+        LOG_ALWAYS_FATAL_IF(config >= mRefreshRates.size());
+        mCurrentConfig = config;
+    }
 
-        // This is the rate that HWC encapsulates right now when the device is in DOZE mode.
-        mRefreshRates.emplace(RefreshRateType::POWER_SAVING,
-                              std::make_shared<RefreshRate>(
-                                      RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0,
-                                                  HWC2_SCREEN_OFF_CONFIG_ID}));
+    struct InputConfig {
+        hwc2_config_t hwcId = 0;
+        nsecs_t vsyncPeriod = 0;
+    };
 
-        if (configs.size() < 1) {
-            ALOGE("Device does not have valid configs. Config size is 0.");
-            return;
+    RefreshRateConfigs(bool refreshRateSwitching, const std::vector<InputConfig>& configs,
+                       int currentConfig) {
+        init(refreshRateSwitching, configs, currentConfig);
+    }
+
+    RefreshRateConfigs(bool refreshRateSwitching,
+                       const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
+                       int currentConfig) {
+        std::vector<InputConfig> inputConfigs;
+        for (const auto& config : configs) {
+            inputConfigs.push_back({config->getId(), config->getVsyncPeriod()});
         }
-
-        // Create a map between config index and vsync period. This is all the info we need
-        // from the configs.
-        std::vector<std::pair<int, nsecs_t>> configIdToVsyncPeriod;
-        for (int i = 0; i < configs.size(); ++i) {
-            configIdToVsyncPeriod.emplace_back(i, configs.at(i)->getVsyncPeriod());
-        }
-
-        std::sort(configIdToVsyncPeriod.begin(), configIdToVsyncPeriod.end(),
-                  [](const std::pair<int, nsecs_t>& a, const std::pair<int, nsecs_t>& b) {
-                      return a.second > b.second;
-                  });
-
-        // When the configs are ordered by the resync rate. We assume that the first one is DEFAULT.
-        nsecs_t vsyncPeriod = configIdToVsyncPeriod[0].second;
-        if (vsyncPeriod != 0) {
-            const float fps = 1e9 / vsyncPeriod;
-            const int configId = configIdToVsyncPeriod[0].first;
-            mRefreshRates.emplace(RefreshRateType::DEFAULT,
-                                  std::make_shared<RefreshRate>(
-                                          RefreshRate{configId, base::StringPrintf("%2.ffps", fps),
-                                                      static_cast<uint32_t>(fps),
-                                                      configs.at(configId)->getId()}));
-        }
-
-        if (configs.size() < 2) {
-            return;
-        }
-
-        // When the configs are ordered by the resync rate. We assume that the second one is
-        // PERFORMANCE, eg. the higher rate.
-        vsyncPeriod = configIdToVsyncPeriod[1].second;
-        if (vsyncPeriod != 0) {
-            const float fps = 1e9 / vsyncPeriod;
-            const int configId = configIdToVsyncPeriod[1].first;
-            mRefreshRates.emplace(RefreshRateType::PERFORMANCE,
-                                  std::make_shared<RefreshRate>(
-                                          RefreshRate{configId, base::StringPrintf("%2.ffps", fps),
-                                                      static_cast<uint32_t>(fps),
-                                                      configs.at(configId)->getId()}));
-        }
+        init(refreshRateSwitching, inputConfigs, currentConfig);
     }
 
 private:
-    std::map<RefreshRateType, std::shared_ptr<RefreshRate>> mRefreshRates;
+    void init(bool refreshRateSwitching, const std::vector<InputConfig>& configs,
+              int currentConfig) {
+        mRefreshRateSwitchingSupported = refreshRateSwitching;
+        LOG_ALWAYS_FATAL_IF(configs.empty());
+        LOG_ALWAYS_FATAL_IF(currentConfig >= configs.size());
+        mCurrentConfig = currentConfig;
+
+        auto buildRefreshRate = [&](int configId) -> RefreshRate {
+            const nsecs_t vsyncPeriod = configs[configId].vsyncPeriod;
+            const float fps = 1e9 / vsyncPeriod;
+            return {configId, base::StringPrintf("%2.ffps", fps), static_cast<uint32_t>(fps),
+                    vsyncPeriod, configs[configId].hwcId};
+        };
+
+        for (int i = 0; i < configs.size(); ++i) {
+            mRefreshRates.push_back(buildRefreshRate(i));
+        }
+
+        if (!mRefreshRateSwitchingSupported) return;
+
+        auto findDefaultAndPerfConfigs = [&]() -> std::optional<std::pair<int, int>> {
+            if (configs.size() < 2) {
+                return {};
+            }
+
+            std::vector<const RefreshRate*> sortedRefreshRates;
+            for (const auto& refreshRate : mRefreshRates) {
+                sortedRefreshRates.push_back(&refreshRate);
+            }
+            std::sort(sortedRefreshRates.begin(), sortedRefreshRates.end(),
+                      [](const RefreshRate* refreshRate1, const RefreshRate* refreshRate2) {
+                          return refreshRate1->vsyncPeriod > refreshRate2->vsyncPeriod;
+                      });
+
+            // When the configs are ordered by the resync rate, we assume that
+            // the first one is DEFAULT and the second one is PERFORMANCE,
+            // i.e. the higher rate.
+            if (sortedRefreshRates[0]->vsyncPeriod == 0 ||
+                sortedRefreshRates[1]->vsyncPeriod == 0) {
+                return {};
+            }
+
+            return std::pair<int, int>(sortedRefreshRates[0]->configId,
+                                       sortedRefreshRates[1]->configId);
+        };
+
+        auto defaultAndPerfConfigs = findDefaultAndPerfConfigs();
+        if (!defaultAndPerfConfigs) {
+            mRefreshRateSwitchingSupported = false;
+            return;
+        }
+
+        mRefreshRateMap[RefreshRateType::DEFAULT] = mRefreshRates[defaultAndPerfConfigs->first];
+        mRefreshRateMap[RefreshRateType::PERFORMANCE] =
+                mRefreshRates[defaultAndPerfConfigs->second];
+    }
+
+    // Whether this device is doing refresh rate switching or not. This must not change after this
+    // object is initialized.
+    bool mRefreshRateSwitchingSupported;
+    // The list of refresh rates, indexed by display config ID. This must not change after this
+    // object is initialized.
+    std::vector<RefreshRate> mRefreshRates;
+    // The mapping of refresh rate type to RefreshRate. This must not change after this object is
+    // initialized.
+    std::map<RefreshRateType, RefreshRate> mRefreshRateMap;
+    // The ID of the current config. This will change at runtime. This is set by SurfaceFlinger on
+    // the main thread, and read by the Scheduler (and other objects) on other threads, so it's
+    // atomic.
+    std::atomic<int> mCurrentConfig;
 };
 
 } // namespace scheduler
diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h
index 7e7c630..947eb08 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateStats.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h
@@ -41,21 +41,18 @@
     static constexpr int64_t MS_PER_DAY = 24 * MS_PER_HOUR;
 
 public:
-    RefreshRateStats(const RefreshRateConfigs& refreshRateConfigs, TimeStats& timeStats)
-          : mRefreshRateConfigs(refreshRateConfigs), mTimeStats(timeStats) {}
+    RefreshRateStats(const RefreshRateConfigs& refreshRateConfigs, TimeStats& timeStats,
+                     int currentConfigMode, int currentPowerMode)
+          : mRefreshRateConfigs(refreshRateConfigs),
+            mTimeStats(timeStats),
+            mCurrentConfigMode(currentConfigMode),
+            mCurrentPowerMode(currentPowerMode) {}
 
-    // Sets power mode. We only collect the information when the power mode is not
-    // HWC_POWER_MODE_NORMAL. When power mode is HWC_POWER_MODE_NORMAL, we collect the stats based
-    // on config mode.
+    // Sets power mode.
     void setPowerMode(int mode) {
         if (mCurrentPowerMode == mode) {
             return;
         }
-        // If power mode is normal, the time is going to be recorded under config modes.
-        if (mode == HWC_POWER_MODE_NORMAL) {
-            mCurrentPowerMode = mode;
-            return;
-        }
         flushTime();
         mCurrentPowerMode = mode;
     }
@@ -79,16 +76,15 @@
         flushTime();
 
         std::unordered_map<std::string, int64_t> totalTime;
-        for (const auto& [type, config] : mRefreshRateConfigs.getRefreshRates()) {
-            int64_t totalTimeForConfig = 0;
-            if (!config) {
-                continue;
-            }
-            if (mConfigModesTotalTime.find(config->configId) != mConfigModesTotalTime.end()) {
-                totalTimeForConfig = mConfigModesTotalTime.at(config->configId);
-            }
-            totalTime[config->name] = totalTimeForConfig;
+        // Multiple configs may map to the same name, e.g. "60fps". Add the
+        // times for such configs together.
+        for (const auto& [config, time] : mConfigModesTotalTime) {
+            totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(config).name] = 0;
         }
+        for (const auto& [config, time] : mConfigModesTotalTime) {
+            totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(config).name] += time;
+        }
+        totalTime["ScreenOff"] = mScreenOffTime;
         return totalTime;
     }
 
@@ -104,32 +100,26 @@
     }
 
 private:
-    void flushTime() {
-        // Normal power mode is counted under different config modes.
-        if (mCurrentPowerMode == HWC_POWER_MODE_NORMAL) {
-            flushTimeForMode(mCurrentConfigMode);
-        } else {
-            flushTimeForMode(SCREEN_OFF_CONFIG_ID);
-        }
-    }
-
     // Calculates the time that passed in ms between the last time we recorded time and the time
     // this method was called.
-    void flushTimeForMode(int mode) {
+    void flushTime() {
         nsecs_t currentTime = systemTime();
         nsecs_t timeElapsed = currentTime - mPreviousRecordedTime;
         int64_t timeElapsedMs = ns2ms(timeElapsed);
         mPreviousRecordedTime = currentTime;
 
-        mConfigModesTotalTime[mode] += timeElapsedMs;
-        for (const auto& [type, config] : mRefreshRateConfigs.getRefreshRates()) {
-            if (!config) {
-                continue;
+        uint32_t fps = 0;
+        if (mCurrentPowerMode == HWC_POWER_MODE_NORMAL) {
+            // Normal power mode is counted under different config modes.
+            if (mConfigModesTotalTime.find(mCurrentConfigMode) == mConfigModesTotalTime.end()) {
+                mConfigModesTotalTime[mCurrentConfigMode] = 0;
             }
-            if (config->configId == mode) {
-                mTimeStats.recordRefreshRate(config->fps, timeElapsed);
-            }
+            mConfigModesTotalTime[mCurrentConfigMode] += timeElapsedMs;
+            fps = mRefreshRateConfigs.getRefreshRateFromConfigId(mCurrentConfigMode).fps;
+        } else {
+            mScreenOffTime += timeElapsedMs;
         }
+        mTimeStats.recordRefreshRate(fps, timeElapsed);
     }
 
     // Formats the time in milliseconds into easy to read format.
@@ -149,10 +139,11 @@
     // Aggregate refresh rate statistics for telemetry.
     TimeStats& mTimeStats;
 
-    int64_t mCurrentConfigMode = SCREEN_OFF_CONFIG_ID;
-    int32_t mCurrentPowerMode = HWC_POWER_MODE_OFF;
+    int mCurrentConfigMode;
+    int32_t mCurrentPowerMode;
 
-    std::unordered_map<int /* power mode */, int64_t /* duration in ms */> mConfigModesTotalTime;
+    std::unordered_map<int /* config */, int64_t /* duration in ms */> mConfigModesTotalTime;
+    int64_t mScreenOffTime = 0;
 
     nsecs_t mPreviousRecordedTime = systemTime();
 };
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 8da5612..0b43378 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -133,7 +133,6 @@
 
 sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
         const char* connectionName, nsecs_t phaseOffsetNs, nsecs_t offsetThresholdForNextVsync,
-        ResyncCallback resyncCallback,
         impl::EventThread::InterceptVSyncsCallback interceptCallback) {
     const int64_t id = sNextId++;
     ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
@@ -143,8 +142,7 @@
                             offsetThresholdForNextVsync, std::move(interceptCallback));
 
     auto eventThreadConnection =
-            createConnectionInternal(eventThread.get(), std::move(resyncCallback),
-                                     ISurfaceComposer::eConfigChangedSuppress);
+            createConnectionInternal(eventThread.get(), ISurfaceComposer::eConfigChangedSuppress);
     mConnections.emplace(id,
                          std::make_unique<Connection>(new ConnectionHandle(id),
                                                       eventThreadConnection,
@@ -164,17 +162,15 @@
 }
 
 sp<EventThreadConnection> Scheduler::createConnectionInternal(
-        EventThread* eventThread, ResyncCallback&& resyncCallback,
-        ISurfaceComposer::ConfigChanged configChanged) {
-    return eventThread->createEventConnection(std::move(resyncCallback), configChanged);
+        EventThread* eventThread, ISurfaceComposer::ConfigChanged configChanged) {
+    return eventThread->createEventConnection([&] { resync(); }, configChanged);
 }
 
 sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
-        const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback,
+        const sp<Scheduler::ConnectionHandle>& handle,
         ISurfaceComposer::ConfigChanged configChanged) {
     RETURN_VALUE_IF_INVALID(nullptr);
-    return createConnectionInternal(mConnections[handle->id]->thread.get(),
-                                    std::move(resyncCallback), configChanged);
+    return createConnectionInternal(mConnections[handle->id]->thread.get(), configChanged);
 }
 
 EventThread* Scheduler::getEventThread(const sp<Scheduler::ConnectionHandle>& handle) {
@@ -264,23 +260,15 @@
     setVsyncPeriod(period);
 }
 
-ResyncCallback Scheduler::makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod) {
-    std::weak_ptr<VsyncState> ptr = mPrimaryVsyncState;
-    return [ptr, getVsyncPeriod = std::move(getVsyncPeriod)]() {
-        if (const auto vsync = ptr.lock()) {
-            vsync->resync(getVsyncPeriod);
-        }
-    };
-}
-
-void Scheduler::VsyncState::resync(const GetVsyncPeriod& getVsyncPeriod) {
+void Scheduler::resync() {
     static constexpr nsecs_t kIgnoreDelay = ms2ns(750);
 
     const nsecs_t now = systemTime();
-    const nsecs_t last = lastResyncTime.exchange(now);
+    const nsecs_t last = mLastResyncTime.exchange(now);
 
     if (now - last > kIgnoreDelay) {
-        scheduler.resyncToHardwareVsync(false, getVsyncPeriod());
+        resyncToHardwareVsync(false,
+                              mRefreshRateConfigs.getCurrentRefreshRate().second.vsyncPeriod);
     }
 }
 
@@ -338,15 +326,19 @@
 
 std::unique_ptr<scheduler::LayerHistory::LayerHandle> Scheduler::registerLayer(
         std::string const& name, int windowType) {
-    RefreshRateType refreshRateType = (windowType == InputWindowInfo::TYPE_WALLPAPER)
-            ? RefreshRateType::DEFAULT
-            : RefreshRateType::PERFORMANCE;
-
-    const auto refreshRate = mRefreshRateConfigs.getRefreshRate(refreshRateType);
-    const uint32_t performanceFps = (refreshRate) ? refreshRate->fps : 0;
-
-    const auto defaultRefreshRate = mRefreshRateConfigs.getRefreshRate(RefreshRateType::DEFAULT);
-    const uint32_t defaultFps = (defaultRefreshRate) ? defaultRefreshRate->fps : 0;
+    uint32_t defaultFps, performanceFps;
+    if (mRefreshRateConfigs.refreshRateSwitchingSupported()) {
+        defaultFps = mRefreshRateConfigs.getRefreshRateFromType(RefreshRateType::DEFAULT).fps;
+        performanceFps =
+                mRefreshRateConfigs
+                        .getRefreshRateFromType((windowType == InputWindowInfo::TYPE_WALLPAPER)
+                                                        ? RefreshRateType::DEFAULT
+                                                        : RefreshRateType::PERFORMANCE)
+                        .fps;
+    } else {
+        defaultFps = mRefreshRateConfigs.getCurrentRefreshRate().second.fps;
+        performanceFps = defaultFps;
+    }
     return mLayerHistory.createLayer(name, defaultFps, performanceFps);
 }
 
@@ -398,17 +390,6 @@
     mChangeRefreshRateCallback = changeRefreshRateCallback;
 }
 
-void Scheduler::setGetCurrentRefreshRateTypeCallback(
-        const GetCurrentRefreshRateTypeCallback&& getCurrentRefreshRateTypeCallback) {
-    std::lock_guard<std::mutex> lock(mCallbackLock);
-    mGetCurrentRefreshRateTypeCallback = getCurrentRefreshRateTypeCallback;
-}
-
-void Scheduler::setGetVsyncPeriodCallback(const GetVsyncPeriod&& getVsyncPeriod) {
-    std::lock_guard<std::mutex> lock(mCallbackLock);
-    mGetVsyncPeriod = getVsyncPeriod;
-}
-
 void Scheduler::updateFrameSkipping(const int64_t skipCount) {
     ATRACE_INT("FrameSkipCount", skipCount);
     if (mSkipCount != skipCount) {
@@ -460,14 +441,12 @@
 
 void Scheduler::resetKernelTimerCallback() {
     ATRACE_INT("ExpiredKernelIdleTimer", 0);
-    std::lock_guard<std::mutex> lock(mCallbackLock);
-    if (mGetVsyncPeriod && mGetCurrentRefreshRateTypeCallback) {
+    const auto refreshRate = mRefreshRateConfigs.getCurrentRefreshRate();
+    if (refreshRate.first == RefreshRateType::PERFORMANCE) {
         // If we're not in performance mode then the kernel timer shouldn't do
         // anything, as the refresh rate during DPU power collapse will be the
         // same.
-        if (mGetCurrentRefreshRateTypeCallback() == Scheduler::RefreshRateType::PERFORMANCE) {
-            resyncToHardwareVsync(true, mGetVsyncPeriod());
-        }
+        resyncToHardwareVsync(true, refreshRate.second.vsyncPeriod);
     }
 }
 
@@ -497,15 +476,13 @@
 }
 
 void Scheduler::expiredKernelTimerCallback() {
-    std::lock_guard<std::mutex> lock(mCallbackLock);
     ATRACE_INT("ExpiredKernelIdleTimer", 1);
-    if (mGetCurrentRefreshRateTypeCallback) {
-        if (mGetCurrentRefreshRateTypeCallback() != Scheduler::RefreshRateType::PERFORMANCE) {
-            // Disable HW Vsync if the timer expired, as we don't need it
-            // enabled if we're not pushing frames, and if we're in PERFORMANCE
-            // mode then we'll need to re-update the DispSync model anyways.
-            disableHardwareVsync(false);
-        }
+    const auto refreshRate = mRefreshRateConfigs.getCurrentRefreshRate();
+    if (refreshRate.first != RefreshRateType::PERFORMANCE) {
+        // Disable HW Vsync if the timer expired, as we don't need it
+        // enabled if we're not pushing frames, and if we're in PERFORMANCE
+        // mode then we'll need to re-update the DispSync model anyways.
+        disableHardwareVsync(false);
     }
 }
 
@@ -540,6 +517,10 @@
 }
 
 Scheduler::RefreshRateType Scheduler::calculateRefreshRateType() {
+    if (!mRefreshRateConfigs.refreshRateSwitchingSupported()) {
+        return RefreshRateType::DEFAULT;
+    }
+
     // HDR content is not supported on PERFORMANCE mode
     if (mForceHDRContentToDefaultRefreshRate && mIsHDRContent) {
         return RefreshRateType::DEFAULT;
@@ -567,16 +548,12 @@
     }
 
     // Content detection is on, find the appropriate refresh rate with minimal error
-    auto begin = mRefreshRateConfigs.getRefreshRates().cbegin();
+    auto begin = mRefreshRateConfigs.getRefreshRateMap().cbegin();
 
-    // Skip POWER_SAVING config as it is not a real config
-    if (begin->first == RefreshRateType::POWER_SAVING) {
-        ++begin;
-    }
-    auto iter = min_element(begin, mRefreshRateConfigs.getRefreshRates().cend(),
+    auto iter = min_element(begin, mRefreshRateConfigs.getRefreshRateMap().cend(),
                             [rate = mContentRefreshRate](const auto& l, const auto& r) -> bool {
-                                return std::abs(l.second->fps - static_cast<float>(rate)) <
-                                        std::abs(r.second->fps - static_cast<float>(rate));
+                                return std::abs(l.second.fps - static_cast<float>(rate)) <
+                                        std::abs(r.second.fps - static_cast<float>(rate));
                             });
     RefreshRateType currRefreshRateType = iter->first;
 
@@ -584,11 +561,11 @@
     // 90Hz config. However we should still prefer a lower refresh rate if the content doesn't
     // align well with both
     constexpr float MARGIN = 0.05f;
-    float ratio = mRefreshRateConfigs.getRefreshRate(currRefreshRateType)->fps /
+    float ratio = mRefreshRateConfigs.getRefreshRateFromType(currRefreshRateType).fps /
             float(mContentRefreshRate);
     if (std::abs(std::round(ratio) - ratio) > MARGIN) {
-        while (iter != mRefreshRateConfigs.getRefreshRates().cend()) {
-            ratio = iter->second->fps / float(mContentRefreshRate);
+        while (iter != mRefreshRateConfigs.getRefreshRateMap().cend()) {
+            ratio = iter->second.fps / float(mContentRefreshRate);
 
             if (std::abs(std::round(ratio) - ratio) <= MARGIN) {
                 currRefreshRateType = iter->first;
@@ -601,6 +578,11 @@
     return currRefreshRateType;
 }
 
+Scheduler::RefreshRateType Scheduler::getPreferredRefreshRateType() {
+    std::lock_guard<std::mutex> lock(mFeatureStateLock);
+    return mRefreshRateType;
+}
+
 void Scheduler::changeRefreshRate(RefreshRateType refreshRateType, ConfigEvent configEvent) {
     std::lock_guard<std::mutex> lock(mCallbackLock);
     if (mChangeRefreshRateCallback) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 5d8bb4c..4b21dad 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -49,9 +49,7 @@
     }
 
     using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
-    using GetCurrentRefreshRateTypeCallback = std::function<RefreshRateType()>;
     using ChangeRefreshRateCallback = std::function<void(RefreshRateType, ConfigEvent)>;
-    using GetVsyncPeriod = std::function<nsecs_t()>;
 
     // Enum to indicate whether to start the transaction early, or at vsync time.
     enum class TransactionStart { EARLY, NORMAL };
@@ -81,16 +79,6 @@
         const std::unique_ptr<EventThread> thread;
     };
 
-    // Stores per-display state about VSYNC.
-    struct VsyncState {
-        explicit VsyncState(Scheduler& scheduler) : scheduler(scheduler) {}
-
-        void resync(const GetVsyncPeriod&);
-
-        Scheduler& scheduler;
-        std::atomic<nsecs_t> lastResyncTime = 0;
-    };
-
     explicit Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
                        const scheduler::RefreshRateConfigs& refreshRateConfig);
 
@@ -98,12 +86,11 @@
 
     /** Creates an EventThread connection. */
     sp<ConnectionHandle> createConnection(const char* connectionName, nsecs_t phaseOffsetNs,
-                                          nsecs_t offsetThresholdForNextVsync, ResyncCallback,
+                                          nsecs_t offsetThresholdForNextVsync,
                                           impl::EventThread::InterceptVSyncsCallback);
 
     sp<IDisplayEventConnection> createDisplayEventConnection(
-            const sp<ConnectionHandle>& handle, ResyncCallback,
-            ISurfaceComposer::ConfigChanged configChanged);
+            const sp<ConnectionHandle>& handle, ISurfaceComposer::ConfigChanged configChanged);
 
     // Getter methods.
     EventThread* getEventThread(const sp<ConnectionHandle>& handle);
@@ -143,8 +130,7 @@
     // no-op.
     // The period is the vsync period from the current display configuration.
     void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
-    // Creates a callback for resyncing.
-    ResyncCallback makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod);
+    void resync();
     void setRefreshSkipCount(int count);
     // Passes a vsync sample to DispSync. periodFlushed will be true if
     // DispSync detected that the vsync period changed, and false otherwise.
@@ -167,9 +153,6 @@
     void updateFpsBasedOnContent();
     // Callback that gets invoked when Scheduler wants to change the refresh rate.
     void setChangeRefreshRateCallback(const ChangeRefreshRateCallback&& changeRefreshRateCallback);
-    void setGetCurrentRefreshRateTypeCallback(
-            const GetCurrentRefreshRateTypeCallback&& getCurrentRefreshRateType);
-    void setGetVsyncPeriodCallback(const GetVsyncPeriod&& getVsyncPeriod);
 
     // Returns whether idle timer is enabled or not
     bool isIdleTimerEnabled() { return mSetIdleTimerMs > 0; }
@@ -189,6 +172,9 @@
     // calls DispSync::dump() on primary disp sync
     void dumpPrimaryDispSync(std::string& result) const;
 
+    // Get the appropriate refresh type for current conditions.
+    RefreshRateType getPreferredRefreshRateType();
+
 protected:
     virtual std::unique_ptr<EventThread> makeEventThread(
             const char* connectionName, DispSync* dispSync, nsecs_t phaseOffsetNs,
@@ -206,7 +192,7 @@
     enum class DisplayPowerTimerState { EXPIRED, RESET };
 
     // Creates a connection on the given EventThread and forwards the given callbacks.
-    sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&,
+    sp<EventThreadConnection> createConnectionInternal(EventThread*,
                                                        ISurfaceComposer::ConfigChanged);
 
     nsecs_t calculateAverage() const;
@@ -261,7 +247,8 @@
     std::mutex mHWVsyncLock;
     bool mPrimaryHWVsyncEnabled GUARDED_BY(mHWVsyncLock);
     bool mHWVsyncAvailable GUARDED_BY(mHWVsyncLock);
-    const std::shared_ptr<VsyncState> mPrimaryVsyncState{std::make_shared<VsyncState>(*this)};
+
+    std::atomic<nsecs_t> mLastResyncTime = 0;
 
     std::unique_ptr<DispSync> mPrimaryDispSync;
     std::unique_ptr<EventControlThread> mEventControlThread;
@@ -297,9 +284,7 @@
     std::unique_ptr<scheduler::IdleTimer> mDisplayPowerTimer;
 
     std::mutex mCallbackLock;
-    GetCurrentRefreshRateTypeCallback mGetCurrentRefreshRateTypeCallback GUARDED_BY(mCallbackLock);
     ChangeRefreshRateCallback mChangeRefreshRateCallback GUARDED_BY(mCallbackLock);
-    GetVsyncPeriod mGetVsyncPeriod GUARDED_BY(mCallbackLock);
 
     // In order to make sure that the features don't override themselves, we need a state machine
     // to keep track which feature requested the config change.
diff --git a/services/surfaceflinger/Scheduler/SchedulerUtils.h b/services/surfaceflinger/Scheduler/SchedulerUtils.h
index ac10f83..f193553 100644
--- a/services/surfaceflinger/Scheduler/SchedulerUtils.h
+++ b/services/surfaceflinger/Scheduler/SchedulerUtils.h
@@ -30,12 +30,6 @@
 // about layers.
 static constexpr size_t ARRAY_SIZE = 30;
 
-// This number is used to have a place holder for when the screen is not NORMAL/ON. Currently
-// the config is not visible to SF, and is completely maintained by HWC. However, we would
-// still like to keep track of time when the device is in this config.
-static constexpr int SCREEN_OFF_CONFIG_ID = -1;
-static constexpr uint32_t HWC2_SCREEN_OFF_CONFIG_ID = 0xffffffff;
-
 // This number is used when we try to determine how long do we keep layer information around
 // before we remove it. It is also used to determine how long the layer stays relevant.
 // This time period captures infrequent updates when playing YouTube video with static image,
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 200da2e..fd7f128 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -540,9 +540,9 @@
 
     // wait patiently for the window manager death
     const String16 name("window");
-    mWindowManager = defaultServiceManager()->getService(name);
-    if (mWindowManager != 0) {
-        mWindowManager->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
+    sp<IBinder> window(defaultServiceManager()->getService(name));
+    if (window != 0) {
+        window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
     }
     sp<IBinder> input(defaultServiceManager()->getService(
             String16("inputflinger")));
@@ -569,14 +569,16 @@
         readPersistentProperties();
         mBootStage = BootStage::FINISHED;
 
-        // set the refresh rate according to the policy
-        const auto& performanceRefreshRate =
-                mRefreshRateConfigs.getRefreshRate(RefreshRateType::PERFORMANCE);
+        if (mRefreshRateConfigs->refreshRateSwitchingSupported()) {
+            // set the refresh rate according to the policy
+            const auto& performanceRefreshRate =
+                    mRefreshRateConfigs->getRefreshRateFromType(RefreshRateType::PERFORMANCE);
 
-        if (performanceRefreshRate && isDisplayConfigAllowed(performanceRefreshRate->configId)) {
-            setRefreshRateTo(RefreshRateType::PERFORMANCE, Scheduler::ConfigEvent::None);
-        } else {
-            setRefreshRateTo(RefreshRateType::DEFAULT, Scheduler::ConfigEvent::None);
+            if (isDisplayConfigAllowed(performanceRefreshRate.configId)) {
+                setRefreshRateTo(RefreshRateType::PERFORMANCE, Scheduler::ConfigEvent::None);
+            } else {
+                setRefreshRateTo(RefreshRateType::DEFAULT, Scheduler::ConfigEvent::None);
+            }
         }
     }));
 }
@@ -619,32 +621,6 @@
     ALOGI("Phase offset NS: %" PRId64 "", mPhaseOffsets->getCurrentAppOffset());
 
     Mutex::Autolock _l(mStateLock);
-    // start the EventThread
-    mScheduler =
-            getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
-                                         mRefreshRateConfigs);
-    auto resyncCallback =
-            mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
-
-    mAppConnectionHandle =
-            mScheduler->createConnection("app", mVsyncModulator.getOffsets().app,
-                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
-                                         resyncCallback,
-                                         impl::EventThread::InterceptVSyncsCallback());
-    mSfConnectionHandle =
-            mScheduler->createConnection("sf", mVsyncModulator.getOffsets().sf,
-                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
-                                         resyncCallback, [this](nsecs_t timestamp) {
-                                             mInterceptor->saveVSyncEvent(timestamp);
-                                         });
-
-    mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
-    mVsyncModulator.setSchedulerAndHandles(mScheduler.get(), mAppConnectionHandle.get(),
-                                           mSfConnectionHandle.get());
-
-    mRegionSamplingThread =
-            new RegionSamplingThread(*this, *mScheduler,
-                                     RegionSamplingThread::EnvironmentTimingTunables());
 
     // Get a RenderEngine for the given display / config (can't fail)
     int32_t renderEngineFeature = 0;
@@ -715,37 +691,6 @@
         ALOGE("Run StartPropertySetThread failed!");
     }
 
-    mScheduler->setChangeRefreshRateCallback(
-            [this](RefreshRateType type, Scheduler::ConfigEvent event) {
-                Mutex::Autolock lock(mStateLock);
-                setRefreshRateTo(type, event);
-            });
-    mScheduler->setGetCurrentRefreshRateTypeCallback([this] {
-        Mutex::Autolock lock(mStateLock);
-        const auto display = getDefaultDisplayDeviceLocked();
-        if (!display) {
-            // If we don't have a default display the fallback to the default
-            // refresh rate type
-            return RefreshRateType::DEFAULT;
-        }
-
-        const int configId = display->getActiveConfig();
-        for (const auto& [type, refresh] : mRefreshRateConfigs.getRefreshRates()) {
-            if (refresh && refresh->configId == configId) {
-                return type;
-            }
-        }
-        // This should never happen, but just gracefully fallback to default.
-        return RefreshRateType::DEFAULT;
-    });
-    mScheduler->setGetVsyncPeriodCallback([this] {
-        Mutex::Autolock lock(mStateLock);
-        return getVsyncPeriod();
-    });
-
-    mRefreshRateConfigs.populate(getHwComposer().getConfigs(*display->getId()));
-    mRefreshRateStats.setConfigMode(getHwComposer().getActiveConfigIndex(*display->getId()));
-
     ALOGV("Done initializing");
 }
 
@@ -899,7 +844,8 @@
         info.xdpi = xdpi;
         info.ydpi = ydpi;
         info.fps = 1e9 / hwConfig->getVsyncPeriod();
-        const auto refreshRateType = mRefreshRateConfigs.getRefreshRateType(hwConfig->getId());
+        const auto refreshRateType =
+                mRefreshRateConfigs->getRefreshRateTypeFromHwcConfigId(hwConfig->getId());
         const auto offset = mPhaseOffsets->getOffsetsForRefreshRate(refreshRateType);
         info.appVsyncOffset = offset.late.app;
 
@@ -1001,7 +947,8 @@
     }
 
     std::lock_guard<std::mutex> lock(mActiveConfigLock);
-    mRefreshRateStats.setConfigMode(mUpcomingActiveConfig.configId);
+    mRefreshRateConfigs->setCurrentConfig(mUpcomingActiveConfig.configId);
+    mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId);
 
     display->setActiveConfig(mUpcomingActiveConfig.configId);
 
@@ -1280,9 +1227,6 @@
             return;
         }
 
-        auto resyncCallback =
-                mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
-
         // TODO(b/128863962): Part of the Injector should be refactored, so that it
         // can be passed to Scheduler.
         if (enable) {
@@ -1294,11 +1238,11 @@
                                            impl::EventThread::InterceptVSyncsCallback(),
                                            "injEventThread");
             }
-            mEventQueue->setEventThread(mInjectorEventThread.get(), std::move(resyncCallback));
+            mEventQueue->setEventThread(mInjectorEventThread.get(), [&] { mScheduler->resync(); });
         } else {
             ALOGV("VSync Injections disabled");
             mEventQueue->setEventThread(mScheduler->getEventThread(mSfConnectionHandle),
-                                        std::move(resyncCallback));
+                                        [&] { mScheduler->resync(); });
         }
 
         mInjectVSyncs = enable;
@@ -1409,16 +1353,10 @@
 
 sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
         ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposer::ConfigChanged configChanged) {
-    auto resyncCallback = mScheduler->makeResyncCallback([this] {
-        Mutex::Autolock lock(mStateLock);
-        return getVsyncPeriod();
-    });
-
     const auto& handle =
             vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;
 
-    return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback),
-                                                    configChanged);
+    return mScheduler->createDisplayEventConnection(handle, configChanged);
 }
 
 // ----------------------------------------------------------------------------
@@ -1515,13 +1453,8 @@
     ATRACE_CALL();
 
     // Don't do any updating if the current fps is the same as the new one.
-    const auto& refreshRateConfig = mRefreshRateConfigs.getRefreshRate(refreshRate);
-    if (!refreshRateConfig) {
-        ALOGV("Skipping refresh rate change request for unsupported rate.");
-        return;
-    }
-
-    const int desiredConfigId = refreshRateConfig->configId;
+    const auto& refreshRateConfig = mRefreshRateConfigs->getRefreshRateFromType(refreshRate);
+    const int desiredConfigId = refreshRateConfig.configId;
 
     if (!isDisplayConfigAllowed(desiredConfigId)) {
         ALOGV("Skipping config %d as it is not part of allowed configs", desiredConfigId);
@@ -1851,12 +1784,6 @@
     mVsyncModulator.onRefreshed(mHadClientComposition);
 
     mLayersWithQueuedFrames.clear();
-    if (mVisibleRegionsDirty) {
-        mVisibleRegionsDirty = false;
-        if (mTracingEnabled) {
-            mTracing.notify("visibleRegionsDirty");
-        }
-    }
 }
 
 
@@ -1866,6 +1793,9 @@
 
     if (mVisibleRegionsDirty) {
         computeLayerBounds();
+        if (mTracingEnabled) {
+            mTracing.notify("visibleRegionsDirty");
+        }
     }
 
     for (auto& layer : mLayersPendingRefresh) {
@@ -2272,6 +2202,7 @@
     // rebuild the visible layer list per screen
     if (CC_UNLIKELY(mVisibleRegionsDirty)) {
         ATRACE_NAME("rebuildLayerStacks VR Dirty");
+        mVisibleRegionsDirty = false;
         invalidateHwcGeometry();
 
         for (const auto& pair : mDisplays) {
@@ -2628,6 +2559,9 @@
         if (event.connection == HWC2::Connection::Connected) {
             if (!mPhysicalDisplayTokens.count(info->id)) {
                 ALOGV("Creating display %s", to_string(info->id).c_str());
+                if (event.hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
+                    initScheduler(info->id);
+                }
                 mPhysicalDisplayTokens[info->id] = new BBinder();
                 DisplayDeviceState state;
                 state.displayId = info->id;
@@ -3028,7 +2962,7 @@
         setInputWindowsFinished();
     }
 
-    executeInputWindowCommands();
+    mInputWindowCommands.clear();
 }
 
 void SurfaceFlinger::updateInputWindowInfo() {
@@ -3052,19 +2986,6 @@
     mPendingInputWindowCommands.clear();
 }
 
-void SurfaceFlinger::executeInputWindowCommands() {
-    for (const auto& transferTouchFocusCommand : mInputWindowCommands.transferTouchFocusCommands) {
-        if (transferTouchFocusCommand.fromToken != nullptr &&
-            transferTouchFocusCommand.toToken != nullptr &&
-            transferTouchFocusCommand.fromToken != transferTouchFocusCommand.toToken) {
-            mInputFlinger->transferTouchFocus(transferTouchFocusCommand.fromToken,
-                                              transferTouchFocusCommand.toToken);
-        }
-    }
-
-    mInputWindowCommands.clear();
-}
-
 void SurfaceFlinger::updateCursorAsync()
 {
     for (const auto& [token, display] : mDisplays) {
@@ -3086,6 +3007,55 @@
     layer->releasePendingBuffer(systemTime());
 }
 
+void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) {
+    if (mScheduler) {
+        // In practice it's not allowed to hotplug in/out the primary display once it's been
+        // connected during startup, but some tests do it, so just warn and return.
+        ALOGW("Can't re-init scheduler");
+        return;
+    }
+
+    int currentConfig = getHwComposer().getActiveConfigIndex(primaryDisplayId);
+    mRefreshRateConfigs =
+            std::make_unique<scheduler::RefreshRateConfigs>(refresh_rate_switching(false),
+                                                            getHwComposer().getConfigs(
+                                                                    primaryDisplayId),
+                                                            currentConfig);
+    mRefreshRateStats =
+            std::make_unique<scheduler::RefreshRateStats>(*mRefreshRateConfigs, *mTimeStats,
+                                                          currentConfig, HWC_POWER_MODE_OFF);
+    mRefreshRateStats->setConfigMode(currentConfig);
+
+    // start the EventThread
+    mScheduler =
+            getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
+                                         *mRefreshRateConfigs);
+    mAppConnectionHandle =
+            mScheduler->createConnection("app", mVsyncModulator.getOffsets().app,
+                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
+                                         impl::EventThread::InterceptVSyncsCallback());
+    mSfConnectionHandle =
+            mScheduler->createConnection("sf", mVsyncModulator.getOffsets().sf,
+                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
+                                         [this](nsecs_t timestamp) {
+                                             mInterceptor->saveVSyncEvent(timestamp);
+                                         });
+
+    mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
+    mVsyncModulator.setSchedulerAndHandles(mScheduler.get(), mAppConnectionHandle.get(),
+                                           mSfConnectionHandle.get());
+
+    mRegionSamplingThread =
+            new RegionSamplingThread(*this, *mScheduler,
+                                     RegionSamplingThread::EnvironmentTimingTunables());
+
+    mScheduler->setChangeRefreshRateCallback(
+            [this](RefreshRateType type, Scheduler::ConfigEvent event) {
+                Mutex::Autolock lock(mStateLock);
+                setRefreshRateTo(type, event);
+            });
+}
+
 void SurfaceFlinger::commitTransaction()
 {
     if (!mLayersPendingRemoval.isEmpty()) {
@@ -4598,7 +4568,7 @@
 
     if (display->isPrimary()) {
         mTimeStats->setPowerMode(mode);
-        mRefreshRateStats.setPowerMode(mode);
+        mRefreshRateStats->setPowerMode(mode);
         mScheduler->setDisplayPowerState(mode == HWC_POWER_MODE_NORMAL);
     }
 
@@ -4671,22 +4641,18 @@
 
         if (const auto it = dumpers.find(flag); it != dumpers.end()) {
             (it->second)(args, asProto, result);
-        } else if (!asProto) {
-            dumpAllLocked(args, result);
+        } else {
+            if (asProto) {
+                LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
+                result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize());
+            } else {
+                dumpAllLocked(args, result);
+            }
         }
 
         if (locked) {
             mStateLock.unlock();
         }
-
-        LayersProto layersProto = dumpProtoFromMainThread();
-        if (asProto) {
-            result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize());
-        } else {
-            auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
-            result.append(LayerProtoParser::layerTreeToString(layerTree));
-            result.append("\n");
-        }
     }
     write(fd, result.c_str(), result.size());
     return NO_ERROR;
@@ -4770,15 +4736,14 @@
                   mUseSmart90ForVideo ? "on" : "off");
     StringAppendF(&result, "Allowed Display Configs: ");
     for (int32_t configId : mAllowedDisplayConfigs) {
-        for (auto refresh : mRefreshRateConfigs.getRefreshRates()) {
-            if (refresh.second && refresh.second->configId == configId) {
-                StringAppendF(&result, "%dHz, ", refresh.second->fps);
-            }
-        }
+        StringAppendF(&result, "%" PRIu32 " Hz, ",
+                      mRefreshRateConfigs->getRefreshRateFromConfigId(configId).fps);
     }
     StringAppendF(&result, "(config override by backdoor: %s)\n\n",
                   mDebugDisplayConfigSetByBackdoor ? "yes" : "no");
     mScheduler->dump(mAppConnectionHandle, result);
+    StringAppendF(&result, "+  Refresh rate switching: %s\n",
+                  mRefreshRateConfigs->refreshRateSwitchingSupported() ? "on" : "off");
 }
 
 void SurfaceFlinger::dumpStaticScreenStats(std::string& result) const {
@@ -4929,23 +4894,19 @@
     result.append("\n");
 }
 
-LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const {
+LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet,
+                                          uint32_t traceFlags) const {
     LayersProto layersProto;
-    mDrawingState.traverseInZOrder([&](Layer* layer) {
+    const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
+    const State& state = useDrawing ? mDrawingState : mCurrentState;
+    state.traverseInZOrder([&](Layer* layer) {
         LayerProto* layerProto = layersProto.add_layers();
-        layer->writeToProtoDrawingState(layerProto, traceFlags);
-        layer->writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags);
+        layer->writeToProto(layerProto, stateSet, traceFlags);
     });
 
     return layersProto;
 }
 
-LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) {
-    LayersProto layersProto;
-    postMessageSync(new LambdaMessage([&]() { layersProto = dumpDrawingStateProto(traceFlags); }));
-    return layersProto;
-}
-
 LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(
         const sp<DisplayDevice>& displayDevice) const {
     LayersProto layersProto;
@@ -4966,7 +4927,7 @@
     mDrawingState.traverseInZOrder([&](Layer* layer) {
         if (!layer->visibleRegion.isEmpty() && !display->getOutputLayersOrderedByZ().empty()) {
             LayerProto* layerProto = layersProto.add_layers();
-            layer->writeToProtoCompositionState(layerProto, displayDevice);
+            layer->writeToProto(layerProto, displayDevice);
         }
     });
 
@@ -5031,6 +4992,13 @@
     colorizer.reset(result);
 
     {
+        LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
+        auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
+        result.append(LayerProtoParser::layerTreeToString(layerTree));
+        result.append("\n");
+    }
+
+    {
         StringAppendF(&result, "Composition layers\n");
         mDrawingState.traverseInZOrder([&](Layer* layer) {
             auto compositionLayer = layer->getCompositionLayer();
@@ -5140,7 +5108,7 @@
     result.append("\nScheduler state:\n");
     result.append(mScheduler->doDump() + "\n");
     StringAppendF(&result, "+  Smart video mode: %s\n\n", mUseSmart90ForVideo ? "on" : "off");
-    result.append(mRefreshRateStats.doDump() + "\n");
+    result.append(mRefreshRateStats->doDump() + "\n");
 
     result.append(mTimeStats->miniDump());
     result.append("\n");
@@ -5611,7 +5579,8 @@
             case 1034: {
                 // TODO(b/129297325): expose this via developer menu option
                 n = data.readInt32();
-                if (n && !mRefreshRateOverlay) {
+                if (n && !mRefreshRateOverlay &&
+                    mRefreshRateConfigs->refreshRateSwitchingSupported()) {
                     RefreshRateType type;
                     {
                         std::lock_guard<std::mutex> lock(mActiveConfigLock);
@@ -6210,15 +6179,28 @@
     mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value,
                                 display->getActiveConfig());
 
-    // Set the highest allowed config by iterating backwards on available refresh rates
-    const auto& refreshRates = mRefreshRateConfigs.getRefreshRates();
-    for (auto iter = refreshRates.crbegin(); iter != refreshRates.crend(); ++iter) {
-        if (iter->second && isDisplayConfigAllowed(iter->second->configId)) {
-            ALOGV("switching to config %d", iter->second->configId);
-            setDesiredActiveConfig(
-                    {iter->first, iter->second->configId, Scheduler::ConfigEvent::Changed});
-            break;
+    if (mRefreshRateConfigs->refreshRateSwitchingSupported()) {
+        const auto& type = mScheduler->getPreferredRefreshRateType();
+        const auto& config = mRefreshRateConfigs->getRefreshRateFromType(type);
+        if (isDisplayConfigAllowed(config.configId)) {
+            ALOGV("switching to Scheduler preferred config %d", config.configId);
+            setDesiredActiveConfig({type, config.configId, Scheduler::ConfigEvent::Changed});
+        } else {
+            // Set the highest allowed config by iterating backwards on available refresh rates
+            const auto& refreshRates = mRefreshRateConfigs->getRefreshRateMap();
+            for (auto iter = refreshRates.crbegin(); iter != refreshRates.crend(); ++iter) {
+                if (isDisplayConfigAllowed(iter->second.configId)) {
+                    ALOGV("switching to allowed config %d", iter->second.configId);
+                    setDesiredActiveConfig(
+                            {iter->first, iter->second.configId, Scheduler::ConfigEvent::Changed});
+                    break;
+                }
+            }
         }
+    } else if (!isDisplayConfigAllowed(display->getActiveConfig())) {
+        ALOGV("switching to config %d", allowedConfigs[0]);
+        setDesiredActiveConfig(
+                {RefreshRateType::DEFAULT, allowedConfigs[0], Scheduler::ConfigEvent::Changed});
     }
 }
 
@@ -6235,7 +6217,7 @@
         return NO_ERROR;
     }
 
-    postMessageSync(new LambdaMessage([&]() NO_THREAD_SAFETY_ANALYSIS {
+    postMessageSync(new LambdaMessage([&]() {
         const auto display = getDisplayDeviceLocked(displayToken);
         if (!display) {
             ALOGE("Attempt to set allowed display configs for invalid display token %p",
@@ -6243,6 +6225,7 @@
         } else if (display->isVirtual()) {
             ALOGW("Attempt to set allowed display configs for virtual display");
         } else {
+            Mutex::Autolock lock(mStateLock);
             setAllowedDisplayConfigsInternal(display, allowedConfigs);
         }
     }));
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5778be6..a22d6fc 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -263,8 +263,7 @@
     status_t postMessageAsync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0);
 
     // post a synchronous message to the main thread
-    status_t postMessageSync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0)
-            EXCLUDES(mStateLock);
+    status_t postMessageSync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0);
 
     // force full composition on all displays
     void repaintEverything();
@@ -554,9 +553,9 @@
     void updateInputFlinger();
     void updateInputWindowInfo();
     void commitInputWindowCommands() REQUIRES(mStateLock);
-    void executeInputWindowCommands();
     void setInputWindowsFinished();
     void updateCursorAsync();
+    void initScheduler(DisplayId primaryDisplayId);
 
     /* handlePageFlip - latch a new buffer if available and compute the dirty
      * region. Returns whether a new buffer has been latched, i.e., whether it
@@ -901,9 +900,8 @@
     void dumpBufferingStats(std::string& result) const;
     void dumpDisplayIdentificationData(std::string& result) const;
     void dumpWideColorInfo(std::string& result) const;
-    LayersProto dumpDrawingStateProto(uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
-    LayersProto dumpProtoFromMainThread(uint32_t traceFlags = SurfaceTracing::TRACE_ALL)
-            EXCLUDES(mStateLock);
+    LayersProto dumpProtoInfo(LayerVector::StateSet stateSet,
+                              uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
     void withTracingLock(std::function<void()> operation) REQUIRES(mStateLock);
     LayersProto dumpVisibleLayersProtoInfo(const sp<DisplayDevice>& display) const;
 
@@ -1104,9 +1102,6 @@
     // either AID_GRAPHICS or AID_SYSTEM.
     status_t CheckTransactCodeCredentials(uint32_t code);
 
-    // to linkToDeath
-    sp<IBinder> mWindowManager;
-
     std::unique_ptr<dvr::VrFlinger> mVrFlinger;
     std::atomic<bool> mVrFlingerRequestsDisplay = false;
     static bool useVrFlinger;
@@ -1138,8 +1133,8 @@
     sp<Scheduler::ConnectionHandle> mAppConnectionHandle;
     sp<Scheduler::ConnectionHandle> mSfConnectionHandle;
 
-    scheduler::RefreshRateConfigs mRefreshRateConfigs;
-    scheduler::RefreshRateStats mRefreshRateStats{mRefreshRateConfigs, *mTimeStats};
+    std::unique_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;
+    std::unique_ptr<scheduler::RefreshRateStats> mRefreshRateStats;
 
     // All configs are allowed if the set is empty.
     using DisplayConfigs = std::set<int32_t>;
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp
index 768074a..b4716eb 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -226,6 +226,14 @@
     return static_cast<int64_t>(defaultValue);
 }
 
+bool refresh_rate_switching(bool defaultValue) {
+    auto temp = SurfaceFlingerProperties::refresh_rate_switching();
+    if (temp.has_value()) {
+        return *temp;
+    }
+    return defaultValue;
+}
+
 int32_t set_idle_timer_ms(int32_t defaultValue) {
     auto temp = SurfaceFlingerProperties::set_idle_timer_ms();
     if (temp.has_value()) {
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h
index 5f88322..e394cca 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -73,6 +73,8 @@
 int64_t color_space_agnostic_dataspace(
         android::hardware::graphics::common::V1_2::Dataspace defaultValue);
 
+bool refresh_rate_switching(bool defaultValue);
+
 int32_t set_idle_timer_ms(int32_t defaultValue);
 
 int32_t set_touch_timer_ms(int32_t defaultValue);
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index 9053f2c..c4ab066 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -162,7 +162,7 @@
     LayersTraceProto entry;
     entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
     entry.set_where(where);
-    LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags));
+    LayersProto layers(mFlinger.dumpProtoInfo(LayerVector::StateSet::Drawing, mTraceFlags));
     entry.mutable_layers()->Swap(&layers);
 
     return entry;
diff --git a/services/surfaceflinger/TimeStats/OWNERS b/services/surfaceflinger/TimeStats/OWNERS
index 1441f91..ac02d12 100644
--- a/services/surfaceflinger/TimeStats/OWNERS
+++ b/services/surfaceflinger/TimeStats/OWNERS
@@ -1,2 +1 @@
-alecmouri@google.com
-zzyiwei@google.com
+zzyiwei@google.com
\ No newline at end of file
diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp
index d03cb7b..cb368b0 100644
--- a/services/surfaceflinger/layerproto/Android.bp
+++ b/services/surfaceflinger/layerproto/Android.bp
@@ -43,7 +43,7 @@
         type: "nano",
     },
     srcs: ["*.proto"],
-    sdk_version: "core_platform",
+    no_framework_libs: true,
     target: {
         android: {
             jarjar_rules: "jarjar-rules.txt",
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index 56ab4e3..000f21c 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -15,7 +15,7 @@
 module: "android.sysprop.SurfaceFlingerProperties"
 owner: Platform
 
-# The following two propertiess define (respectively):
+# The following two properties define (respectively):
 #
 # - The phase offset between hardware vsync and when apps are woken up by the
 #   Choreographer callback
@@ -36,7 +36,7 @@
 prop {
     api_name: "vsync_event_phase_offset_ns"
     type: Long
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.vsync_event_phase_offset_ns"
 }
@@ -44,7 +44,7 @@
 prop {
     api_name: "vsync_sf_event_phase_offset_ns"
     type: Long
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.vsync_sf_event_phase_offset_ns"
 }
@@ -53,7 +53,7 @@
 prop {
     api_name: "use_context_priority"
     type: Boolean
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.use_context_priority"
 }
@@ -62,7 +62,7 @@
 prop {
     api_name: "max_frame_buffer_acquired_buffers"
     type: Long
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers"
 }
@@ -80,7 +80,7 @@
 prop {
     api_name: "has_wide_color_display"
     type: Boolean
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.has_wide_color_display"
 }
@@ -90,7 +90,7 @@
 prop {
     api_name: "running_without_sync_framework"
     type: Boolean
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.running_without_sync_framework"
 }
@@ -108,7 +108,7 @@
 prop {
     api_name: "has_HDR_display"
     type: Boolean
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.has_HDR_display"
 }
@@ -117,7 +117,7 @@
 prop {
     api_name: "present_time_offset_from_vsync_ns"
     type: Long
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.present_time_offset_from_vsync_ns"
 }
@@ -129,7 +129,7 @@
 prop {
     api_name: "force_hwc_copy_for_virtual_displays"
     type: Boolean
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays"
 }
@@ -139,7 +139,7 @@
 prop {
     api_name: "max_virtual_display_dimension"
     type: Long
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.max_virtual_display_dimension"
 }
@@ -151,7 +151,7 @@
 prop {
     api_name: "use_vr_flinger"
     type: Boolean
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.use_vr_flinger"
 }
@@ -161,7 +161,7 @@
 prop {
     api_name: "start_graphics_allocator_service"
     type: Boolean
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.start_graphics_allocator_service"
 }
@@ -171,7 +171,7 @@
     api_name: "primary_display_orientation"
     type: Enum
     enum_values: "ORIENTATION_0|ORIENTATION_90|ORIENTATION_180|ORIENTATION_270"
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.primary_display_orientation"
 }
@@ -182,7 +182,7 @@
 prop {
     api_name: "use_color_management"
     type: Boolean
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.use_color_management"
 }
@@ -209,7 +209,7 @@
 prop {
     api_name: "default_composition_dataspace"
     type: Long
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.default_composition_dataspace"
 }
@@ -220,7 +220,7 @@
 prop {
     api_name: "default_composition_pixel_format"
     type: Integer
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.default_composition_pixel_format"
 }
@@ -235,7 +235,7 @@
 prop {
     api_name: "wcg_composition_dataspace"
     type: Long
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.wcg_composition_dataspace"
 }
@@ -246,7 +246,7 @@
 prop {
     api_name: "wcg_composition_pixel_format"
     type: Integer
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.wcg_composition_pixel_format"
 }
@@ -272,7 +272,7 @@
 prop {
     api_name: "display_primary_red"
     type: DoubleList
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.display_primary_red"
 }
@@ -280,7 +280,7 @@
 prop {
     api_name: "display_primary_green"
     type: DoubleList
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.display_primary_green"
 }
@@ -288,7 +288,7 @@
 prop {
     api_name: "display_primary_blue"
     type: DoubleList
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.display_primary_blue"
 }
@@ -296,18 +296,30 @@
 prop {
     api_name: "display_primary_white"
     type: DoubleList
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.display_primary_white"
 }
 
+# refreshRateSwitching indicates whether SurfaceFlinger should use refresh rate
+# switching on the device, e.g. to switch between 60 and 90 Hz. The settings
+# below that are related to refresh rate switching will only have an effect if
+# refresh_rate_switching is enabled.
+prop {
+    api_name: "refresh_rate_switching"
+    type: Boolean
+    scope: System
+    access: Readonly
+    prop_name: "ro.surface_flinger.refresh_rate_switching"
+}
+
 # setIdleTimerMs indicates what is considered a timeout in milliseconds for Scheduler. This value is
 # used by the Scheduler to trigger inactivity callbacks that will switch the display to a lower
 # refresh rate. Setting this property to 0 means there is no timer.
 prop {
     api_name: "set_idle_timer_ms"
     type: Integer
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.set_idle_timer_ms"
 }
@@ -318,7 +330,7 @@
 prop {
     api_name: "set_touch_timer_ms"
     type: Integer
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.set_touch_timer_ms"
 }
@@ -340,7 +352,7 @@
 prop {
     api_name: "use_smart_90_for_video"
     type: Boolean
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.use_smart_90_for_video"
 }
@@ -348,7 +360,7 @@
 prop {
     api_name: "enable_protected_contents"
     type: Boolean
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.protected_contents"
 }
@@ -358,7 +370,7 @@
 prop {
     api_name: "support_kernel_idle_timer"
     type: Boolean
-    scope: Public
+    scope: System
     access: Readonly
     prop_name: "ro.surface_flinger.support_kernel_idle_timer"
 }
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
deleted file mode 100644
index b66e56e..0000000
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
+++ /dev/null
@@ -1,138 +0,0 @@
-props {
-  module: "android.sysprop.SurfaceFlingerProperties"
-  prop {
-    api_name: "color_space_agnostic_dataspace"
-    type: Long
-    prop_name: "ro.surface_flinger.color_space_agnostic_dataspace"
-  }
-  prop {
-    api_name: "default_composition_dataspace"
-    type: Long
-    prop_name: "ro.surface_flinger.default_composition_dataspace"
-  }
-  prop {
-    api_name: "default_composition_pixel_format"
-    type: Integer
-    prop_name: "ro.surface_flinger.default_composition_pixel_format"
-  }
-  prop {
-    api_name: "display_primary_blue"
-    type: DoubleList
-    prop_name: "ro.surface_flinger.display_primary_blue"
-  }
-  prop {
-    api_name: "display_primary_green"
-    type: DoubleList
-    prop_name: "ro.surface_flinger.display_primary_green"
-  }
-  prop {
-    api_name: "display_primary_red"
-    type: DoubleList
-    prop_name: "ro.surface_flinger.display_primary_red"
-  }
-  prop {
-    api_name: "display_primary_white"
-    type: DoubleList
-    prop_name: "ro.surface_flinger.display_primary_white"
-  }
-  prop {
-    api_name: "enable_protected_contents"
-    prop_name: "ro.surface_flinger.protected_contents"
-  }
-  prop {
-    api_name: "force_hwc_copy_for_virtual_displays"
-    prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays"
-  }
-  prop {
-    api_name: "has_HDR_display"
-    prop_name: "ro.surface_flinger.has_HDR_display"
-  }
-  prop {
-    api_name: "has_wide_color_display"
-    prop_name: "ro.surface_flinger.has_wide_color_display"
-  }
-  prop {
-    api_name: "max_frame_buffer_acquired_buffers"
-    type: Long
-    prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers"
-  }
-  prop {
-    api_name: "max_virtual_display_dimension"
-    type: Long
-    prop_name: "ro.surface_flinger.max_virtual_display_dimension"
-  }
-  prop {
-    api_name: "present_time_offset_from_vsync_ns"
-    type: Long
-    prop_name: "ro.surface_flinger.present_time_offset_from_vsync_ns"
-  }
-  prop {
-    api_name: "primary_display_orientation"
-    type: Enum
-    prop_name: "ro.surface_flinger.primary_display_orientation"
-    enum_values: "ORIENTATION_0|ORIENTATION_90|ORIENTATION_180|ORIENTATION_270"
-  }
-  prop {
-    api_name: "running_without_sync_framework"
-    prop_name: "ro.surface_flinger.running_without_sync_framework"
-  }
-  prop {
-    api_name: "set_display_power_timer_ms"
-    type: Integer
-    prop_name: "ro.surface_flinger.set_display_power_timer_ms"
-  }
-  prop {
-    api_name: "set_idle_timer_ms"
-    type: Integer
-    prop_name: "ro.surface_flinger.set_idle_timer_ms"
-  }
-  prop {
-    api_name: "set_touch_timer_ms"
-    type: Integer
-    prop_name: "ro.surface_flinger.set_touch_timer_ms"
-  }
-  prop {
-    api_name: "start_graphics_allocator_service"
-    prop_name: "ro.surface_flinger.start_graphics_allocator_service"
-  }
-  prop {
-    api_name: "support_kernel_idle_timer"
-    prop_name: "ro.surface_flinger.support_kernel_idle_timer"
-  }
-  prop {
-    api_name: "use_color_management"
-    prop_name: "ro.surface_flinger.use_color_management"
-  }
-  prop {
-    api_name: "use_context_priority"
-    prop_name: "ro.surface_flinger.use_context_priority"
-  }
-  prop {
-    api_name: "use_smart_90_for_video"
-    prop_name: "ro.surface_flinger.use_smart_90_for_video"
-  }
-  prop {
-    api_name: "use_vr_flinger"
-    prop_name: "ro.surface_flinger.use_vr_flinger"
-  }
-  prop {
-    api_name: "vsync_event_phase_offset_ns"
-    type: Long
-    prop_name: "ro.surface_flinger.vsync_event_phase_offset_ns"
-  }
-  prop {
-    api_name: "vsync_sf_event_phase_offset_ns"
-    type: Long
-    prop_name: "ro.surface_flinger.vsync_sf_event_phase_offset_ns"
-  }
-  prop {
-    api_name: "wcg_composition_dataspace"
-    type: Long
-    prop_name: "ro.surface_flinger.wcg_composition_dataspace"
-  }
-  prop {
-    api_name: "wcg_composition_pixel_format"
-    type: Integer
-    prop_name: "ro.surface_flinger.wcg_composition_pixel_format"
-  }
-}
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-latest.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-latest.txt
deleted file mode 100644
index b66e56e..0000000
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-latest.txt
+++ /dev/null
@@ -1,138 +0,0 @@
-props {
-  module: "android.sysprop.SurfaceFlingerProperties"
-  prop {
-    api_name: "color_space_agnostic_dataspace"
-    type: Long
-    prop_name: "ro.surface_flinger.color_space_agnostic_dataspace"
-  }
-  prop {
-    api_name: "default_composition_dataspace"
-    type: Long
-    prop_name: "ro.surface_flinger.default_composition_dataspace"
-  }
-  prop {
-    api_name: "default_composition_pixel_format"
-    type: Integer
-    prop_name: "ro.surface_flinger.default_composition_pixel_format"
-  }
-  prop {
-    api_name: "display_primary_blue"
-    type: DoubleList
-    prop_name: "ro.surface_flinger.display_primary_blue"
-  }
-  prop {
-    api_name: "display_primary_green"
-    type: DoubleList
-    prop_name: "ro.surface_flinger.display_primary_green"
-  }
-  prop {
-    api_name: "display_primary_red"
-    type: DoubleList
-    prop_name: "ro.surface_flinger.display_primary_red"
-  }
-  prop {
-    api_name: "display_primary_white"
-    type: DoubleList
-    prop_name: "ro.surface_flinger.display_primary_white"
-  }
-  prop {
-    api_name: "enable_protected_contents"
-    prop_name: "ro.surface_flinger.protected_contents"
-  }
-  prop {
-    api_name: "force_hwc_copy_for_virtual_displays"
-    prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays"
-  }
-  prop {
-    api_name: "has_HDR_display"
-    prop_name: "ro.surface_flinger.has_HDR_display"
-  }
-  prop {
-    api_name: "has_wide_color_display"
-    prop_name: "ro.surface_flinger.has_wide_color_display"
-  }
-  prop {
-    api_name: "max_frame_buffer_acquired_buffers"
-    type: Long
-    prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers"
-  }
-  prop {
-    api_name: "max_virtual_display_dimension"
-    type: Long
-    prop_name: "ro.surface_flinger.max_virtual_display_dimension"
-  }
-  prop {
-    api_name: "present_time_offset_from_vsync_ns"
-    type: Long
-    prop_name: "ro.surface_flinger.present_time_offset_from_vsync_ns"
-  }
-  prop {
-    api_name: "primary_display_orientation"
-    type: Enum
-    prop_name: "ro.surface_flinger.primary_display_orientation"
-    enum_values: "ORIENTATION_0|ORIENTATION_90|ORIENTATION_180|ORIENTATION_270"
-  }
-  prop {
-    api_name: "running_without_sync_framework"
-    prop_name: "ro.surface_flinger.running_without_sync_framework"
-  }
-  prop {
-    api_name: "set_display_power_timer_ms"
-    type: Integer
-    prop_name: "ro.surface_flinger.set_display_power_timer_ms"
-  }
-  prop {
-    api_name: "set_idle_timer_ms"
-    type: Integer
-    prop_name: "ro.surface_flinger.set_idle_timer_ms"
-  }
-  prop {
-    api_name: "set_touch_timer_ms"
-    type: Integer
-    prop_name: "ro.surface_flinger.set_touch_timer_ms"
-  }
-  prop {
-    api_name: "start_graphics_allocator_service"
-    prop_name: "ro.surface_flinger.start_graphics_allocator_service"
-  }
-  prop {
-    api_name: "support_kernel_idle_timer"
-    prop_name: "ro.surface_flinger.support_kernel_idle_timer"
-  }
-  prop {
-    api_name: "use_color_management"
-    prop_name: "ro.surface_flinger.use_color_management"
-  }
-  prop {
-    api_name: "use_context_priority"
-    prop_name: "ro.surface_flinger.use_context_priority"
-  }
-  prop {
-    api_name: "use_smart_90_for_video"
-    prop_name: "ro.surface_flinger.use_smart_90_for_video"
-  }
-  prop {
-    api_name: "use_vr_flinger"
-    prop_name: "ro.surface_flinger.use_vr_flinger"
-  }
-  prop {
-    api_name: "vsync_event_phase_offset_ns"
-    type: Long
-    prop_name: "ro.surface_flinger.vsync_event_phase_offset_ns"
-  }
-  prop {
-    api_name: "vsync_sf_event_phase_offset_ns"
-    type: Long
-    prop_name: "ro.surface_flinger.vsync_sf_event_phase_offset_ns"
-  }
-  prop {
-    api_name: "wcg_composition_dataspace"
-    type: Long
-    prop_name: "ro.surface_flinger.wcg_composition_dataspace"
-  }
-  prop {
-    api_name: "wcg_composition_pixel_format"
-    type: Integer
-    prop_name: "ro.surface_flinger.wcg_composition_pixel_format"
-  }
-}
diff --git a/services/surfaceflinger/sysprop/api/current.txt b/services/surfaceflinger/sysprop/api/current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/removed.txt b/services/surfaceflinger/sysprop/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/system-current.txt b/services/surfaceflinger/sysprop/api/system-current.txt
new file mode 100644
index 0000000..2e804c8
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/system-current.txt
@@ -0,0 +1,46 @@
+// Signature format: 2.0
+package android.sysprop {
+
+  public final class SurfaceFlingerProperties {
+    method public static java.util.Optional<java.lang.Long> color_space_agnostic_dataspace();
+    method public static java.util.Optional<java.lang.Long> default_composition_dataspace();
+    method public static java.util.Optional<java.lang.Integer> default_composition_pixel_format();
+    method public static java.util.List<java.lang.Double> display_primary_blue();
+    method public static java.util.List<java.lang.Double> display_primary_green();
+    method public static java.util.List<java.lang.Double> display_primary_red();
+    method public static java.util.List<java.lang.Double> display_primary_white();
+    method public static java.util.Optional<java.lang.Boolean> enable_protected_contents();
+    method public static java.util.Optional<java.lang.Boolean> force_hwc_copy_for_virtual_displays();
+    method public static java.util.Optional<java.lang.Boolean> has_HDR_display();
+    method public static java.util.Optional<java.lang.Boolean> has_wide_color_display();
+    method public static java.util.Optional<java.lang.Long> max_frame_buffer_acquired_buffers();
+    method public static java.util.Optional<java.lang.Long> max_virtual_display_dimension();
+    method public static java.util.Optional<java.lang.Long> present_time_offset_from_vsync_ns();
+    method public static java.util.Optional<android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values> primary_display_orientation();
+    method public static java.util.Optional<java.lang.Boolean> refresh_rate_switching();
+    method public static java.util.Optional<java.lang.Boolean> running_without_sync_framework();
+    method public static java.util.Optional<java.lang.Integer> set_display_power_timer_ms();
+    method public static java.util.Optional<java.lang.Integer> set_idle_timer_ms();
+    method public static java.util.Optional<java.lang.Integer> set_touch_timer_ms();
+    method public static java.util.Optional<java.lang.Boolean> start_graphics_allocator_service();
+    method public static java.util.Optional<java.lang.Boolean> support_kernel_idle_timer();
+    method public static java.util.Optional<java.lang.Boolean> use_color_management();
+    method public static java.util.Optional<java.lang.Boolean> use_context_priority();
+    method public static java.util.Optional<java.lang.Boolean> use_smart_90_for_video();
+    method public static java.util.Optional<java.lang.Boolean> use_vr_flinger();
+    method public static java.util.Optional<java.lang.Long> vsync_event_phase_offset_ns();
+    method public static java.util.Optional<java.lang.Long> vsync_sf_event_phase_offset_ns();
+    method public static java.util.Optional<java.lang.Long> wcg_composition_dataspace();
+    method public static java.util.Optional<java.lang.Integer> wcg_composition_pixel_format();
+  }
+
+  public enum SurfaceFlingerProperties.primary_display_orientation_values {
+    method public String getPropValue();
+    enum_constant public static final android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values ORIENTATION_0;
+    enum_constant public static final android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values ORIENTATION_180;
+    enum_constant public static final android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values ORIENTATION_270;
+    enum_constant public static final android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values ORIENTATION_90;
+  }
+
+}
+
diff --git a/services/surfaceflinger/sysprop/api/system-removed.txt b/services/surfaceflinger/sysprop/api/system-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/system-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/test-current.txt b/services/surfaceflinger/sysprop/api/test-current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/test-current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/test-removed.txt b/services/surfaceflinger/sysprop/api/test-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/test-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 2feff45..a2c0611 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -20,6 +20,8 @@
         "libgui",
         "libhardware",
         "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
         "liblayers_proto",
         "liblog",
         "libnativewindow",
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index a892a2a..f9e0b64 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -54,11 +54,10 @@
 namespace {
 
 // Mock test helpers
-using ::testing::_;
-using ::testing::DoAll;
 using ::testing::Invoke;
 using ::testing::Return;
 using ::testing::SetArgPointee;
+using ::testing::_;
 
 using Transaction = SurfaceComposerClient::Transaction;
 
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 4f8ed1a..349dd3f 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -125,7 +125,17 @@
     }
 
     void setupScheduler() {
-        mScheduler = new TestableScheduler(mFlinger.mutableRefreshRateConfigs());
+        std::vector<scheduler::RefreshRateConfigs::InputConfig> configs{{/*hwcId=*/0, 16666667}};
+        mFlinger.mutableRefreshRateConfigs() =
+                std::make_unique<scheduler::RefreshRateConfigs>(/*refreshRateSwitching=*/false,
+                                                                configs,
+                                                                /*currentConfig=*/0);
+        mFlinger.mutableRefreshRateStats() =
+                std::make_unique<scheduler::RefreshRateStats>(*mFlinger.mutableRefreshRateConfigs(),
+                                                              *mFlinger.mutableTimeStats(),
+                                                              /*currentConfig=*/0,
+                                                              /*powerMode=*/HWC_POWER_MODE_OFF);
+        mScheduler = new TestableScheduler(*mFlinger.mutableRefreshRateConfigs());
         mScheduler->mutableEventControlThread().reset(mEventControlThread);
         mScheduler->mutablePrimaryDispSync().reset(mPrimaryDispSync);
         EXPECT_CALL(*mEventThread.get(), registerDisplayEventConnection(_));
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 5f58e7d..f40996e 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -29,6 +29,7 @@
 #include <ui/DebugUtils.h>
 
 #include "DisplayIdentificationTest.h"
+#include "Scheduler/RefreshRateConfigs.h"
 #include "TestableScheduler.h"
 #include "TestableSurfaceFlinger.h"
 #include "mock/DisplayHardware/MockComposer.h"
@@ -179,7 +180,16 @@
 }
 
 void DisplayTransactionTest::setupScheduler() {
-    mScheduler = new TestableScheduler(mFlinger.mutableRefreshRateConfigs());
+    std::vector<scheduler::RefreshRateConfigs::InputConfig> configs{{/*hwcId=*/0, 16666667}};
+    mFlinger.mutableRefreshRateConfigs() =
+            std::make_unique<scheduler::RefreshRateConfigs>(/*refreshRateSwitching=*/false, configs,
+                                                            /*currentConfig=*/0);
+    mFlinger.mutableRefreshRateStats() =
+            std::make_unique<scheduler::RefreshRateStats>(*mFlinger.mutableRefreshRateConfigs(),
+                                                          *mFlinger.mutableTimeStats(),
+                                                          /*currentConfig=*/0,
+                                                          /*powerMode=*/HWC_POWER_MODE_OFF);
+    mScheduler = new TestableScheduler(*mFlinger.mutableRefreshRateConfigs());
     mScheduler->mutableEventControlThread().reset(mEventControlThread);
     mScheduler->mutablePrimaryDispSync().reset(mPrimaryDispSync);
     EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_));
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 5067fe8..f315a8a 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -23,7 +23,6 @@
 
 #include "DisplayHardware/HWC2.h"
 #include "Scheduler/RefreshRateConfigs.h"
-#include "mock/DisplayHardware/MockDisplay.h"
 
 using namespace std::chrono_literals;
 using testing::_;
@@ -50,9 +49,8 @@
         ASSERT_EQ(left.configId, right.configId);
         ASSERT_EQ(left.name, right.name);
         ASSERT_EQ(left.fps, right.fps);
+        ASSERT_EQ(left.vsyncPeriod, right.vsyncPeriod);
     }
-
-    RefreshRateConfigs mConfigs;
 };
 
 RefreshRateConfigsTest::RefreshRateConfigsTest() {
@@ -71,101 +69,39 @@
 /* ------------------------------------------------------------------------
  * Test cases
  */
-TEST_F(RefreshRateConfigsTest, zeroDeviceConfigs_storesPowerSavingConfig) {
-    std::vector<std::shared_ptr<const HWC2::Display::Config>> displayConfigs;
-    mConfigs.populate(displayConfigs);
-
-    // We always store a configuration for screen off.
-    const auto& rates = mConfigs.getRefreshRates();
-    ASSERT_EQ(1, rates.size());
-    const auto& powerSavingRate = rates.find(RefreshRateType::POWER_SAVING);
-    ASSERT_NE(rates.end(), powerSavingRate);
-    ASSERT_EQ(rates.end(), rates.find(RefreshRateType::PERFORMANCE));
-    ASSERT_EQ(rates.end(), rates.find(RefreshRateType::DEFAULT));
-
-    RefreshRate expectedConfig =
-            RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0, HWC2_SCREEN_OFF_CONFIG_ID};
-    assertRatesEqual(expectedConfig, *powerSavingRate->second);
-
-    ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
-    assertRatesEqual(expectedConfig, *mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
-    ASSERT_FALSE(mConfigs.getRefreshRate(RefreshRateType::PERFORMANCE));
-    ASSERT_FALSE(mConfigs.getRefreshRate(RefreshRateType::DEFAULT));
-
-    // Sanity check that getRefreshRate() does not modify the underlying configs.
-    ASSERT_EQ(1, mConfigs.getRefreshRates().size());
+TEST_F(RefreshRateConfigsTest, oneDeviceConfig_isRejected) {
+    std::vector<RefreshRateConfigs::InputConfig> configs{{HWC2_CONFIG_ID_60, VSYNC_60}};
+    auto refreshRateConfigs =
+            std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+                                                 /*currentConfig=*/0);
+    ASSERT_FALSE(refreshRateConfigs->refreshRateSwitchingSupported());
 }
 
-TEST_F(RefreshRateConfigsTest, oneDeviceConfig_storesDefaultConfig) {
-    auto display = new Hwc2::mock::Display();
-    std::vector<std::shared_ptr<const HWC2::Display::Config>> displayConfigs;
-    auto config60 = HWC2::Display::Config::Builder(*display, CONFIG_ID_60);
-    config60.setVsyncPeriod(VSYNC_60);
-    displayConfigs.push_back(config60.build());
-    mConfigs.populate(displayConfigs);
+TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap) {
+    std::vector<RefreshRateConfigs::InputConfig> configs{{HWC2_CONFIG_ID_60, VSYNC_60},
+                                                         {HWC2_CONFIG_ID_90, VSYNC_90}};
+    auto refreshRateConfigs =
+            std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+                                                 /*currentConfig=*/0);
 
-    const auto& rates = mConfigs.getRefreshRates();
+    ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
+    const auto& rates = refreshRateConfigs->getRefreshRateMap();
     ASSERT_EQ(2, rates.size());
-    const auto& powerSavingRate = rates.find(RefreshRateType::POWER_SAVING);
-    const auto& defaultRate = rates.find(RefreshRateType::DEFAULT);
-    ASSERT_NE(rates.end(), powerSavingRate);
-    ASSERT_NE(rates.end(), defaultRate);
-    ASSERT_EQ(rates.end(), rates.find(RefreshRateType::PERFORMANCE));
-
-    RefreshRate expectedPowerSavingConfig =
-            RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0, HWC2_SCREEN_OFF_CONFIG_ID};
-    assertRatesEqual(expectedPowerSavingConfig, *powerSavingRate->second);
-    RefreshRate expectedDefaultConfig = RefreshRate{CONFIG_ID_60, "60fps", 60, HWC2_CONFIG_ID_60};
-    assertRatesEqual(expectedDefaultConfig, *defaultRate->second);
-
-    ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
-    assertRatesEqual(expectedPowerSavingConfig,
-                     *mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
-    ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::DEFAULT));
-    assertRatesEqual(expectedDefaultConfig, *mConfigs.getRefreshRate(RefreshRateType::DEFAULT));
-    ASSERT_FALSE(mConfigs.getRefreshRate(RefreshRateType::PERFORMANCE));
-
-    // Sanity check that getRefreshRate() does not modify the underlying configs.
-    ASSERT_EQ(2, mConfigs.getRefreshRates().size());
-}
-
-TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesPerformanceConfig) {
-    auto display = new Hwc2::mock::Display();
-    std::vector<std::shared_ptr<const HWC2::Display::Config>> displayConfigs;
-    auto config60 = HWC2::Display::Config::Builder(*display, CONFIG_ID_60);
-    config60.setVsyncPeriod(VSYNC_60);
-    displayConfigs.push_back(config60.build());
-    auto config90 = HWC2::Display::Config::Builder(*display, CONFIG_ID_90);
-    config90.setVsyncPeriod(VSYNC_90);
-    displayConfigs.push_back(config90.build());
-    mConfigs.populate(displayConfigs);
-
-    const auto& rates = mConfigs.getRefreshRates();
-    ASSERT_EQ(3, rates.size());
-    const auto& powerSavingRate = rates.find(RefreshRateType::POWER_SAVING);
     const auto& defaultRate = rates.find(RefreshRateType::DEFAULT);
     const auto& performanceRate = rates.find(RefreshRateType::PERFORMANCE);
-    ASSERT_NE(rates.end(), powerSavingRate);
     ASSERT_NE(rates.end(), defaultRate);
     ASSERT_NE(rates.end(), performanceRate);
 
-    RefreshRate expectedPowerSavingConfig =
-            RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0, HWC2_SCREEN_OFF_CONFIG_ID};
-    assertRatesEqual(expectedPowerSavingConfig, *powerSavingRate->second);
-    RefreshRate expectedDefaultConfig = RefreshRate{CONFIG_ID_60, "60fps", 60, HWC2_CONFIG_ID_60};
-    assertRatesEqual(expectedDefaultConfig, *defaultRate->second);
-    RefreshRate expectedPerformanceConfig =
-            RefreshRate{CONFIG_ID_90, "90fps", 90, HWC2_CONFIG_ID_90};
-    assertRatesEqual(expectedPerformanceConfig, *performanceRate->second);
+    RefreshRate expectedDefaultConfig = {CONFIG_ID_60, "60fps", 60, VSYNC_60, HWC2_CONFIG_ID_60};
+    assertRatesEqual(expectedDefaultConfig, defaultRate->second);
+    RefreshRate expectedPerformanceConfig = {CONFIG_ID_90, "90fps", 90, VSYNC_90,
+                                             HWC2_CONFIG_ID_90};
+    assertRatesEqual(expectedPerformanceConfig, performanceRate->second);
 
-    ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
-    assertRatesEqual(expectedPowerSavingConfig,
-                     *mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
-    ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::DEFAULT));
-    assertRatesEqual(expectedDefaultConfig, *mConfigs.getRefreshRate(RefreshRateType::DEFAULT));
-    ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::PERFORMANCE));
+    assertRatesEqual(expectedDefaultConfig,
+                     refreshRateConfigs->getRefreshRateFromType(RefreshRateType::DEFAULT));
     assertRatesEqual(expectedPerformanceConfig,
-                     *mConfigs.getRefreshRate(RefreshRateType::PERFORMANCE));
+                     refreshRateConfigs->getRefreshRateFromType(RefreshRateType::PERFORMANCE));
 }
 } // namespace
 } // namespace scheduler
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
index 411ec61..cec0b32 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
@@ -22,7 +22,6 @@
 #include <thread>
 
 #include "Scheduler/RefreshRateStats.h"
-#include "mock/DisplayHardware/MockDisplay.h"
 #include "mock/MockTimeStats.h"
 
 using namespace std::chrono_literals;
@@ -42,9 +41,18 @@
     RefreshRateStatsTest();
     ~RefreshRateStatsTest();
 
+    void init(const std::vector<RefreshRateConfigs::InputConfig>& configs) {
+        mRefreshRateConfigs = std::make_unique<RefreshRateConfigs>(
+                /*refreshRateSwitching=*/true, configs, /*currentConfig=*/0);
+        mRefreshRateStats =
+                std::make_unique<RefreshRateStats>(*mRefreshRateConfigs, mTimeStats,
+                                                   /*currentConfig=*/0,
+                                                   /*currentPowerMode=*/HWC_POWER_MODE_OFF);
+    }
+
     mock::TimeStats mTimeStats;
-    RefreshRateConfigs mRefreshRateConfigs;
-    RefreshRateStats mRefreshRateStats{mRefreshRateConfigs, mTimeStats};
+    std::unique_ptr<RefreshRateConfigs> mRefreshRateConfigs;
+    std::unique_ptr<RefreshRateStats> mRefreshRateStats;
 };
 
 RefreshRateStatsTest::RefreshRateStatsTest() {
@@ -63,63 +71,46 @@
 /* ------------------------------------------------------------------------
  * Test cases
  */
-TEST_F(RefreshRateStatsTest, canCreateAndDestroyTest) {
-    std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
-    mRefreshRateConfigs.populate(configs);
-
-    // There is one default config, so the refresh rates should have one item.
-    EXPECT_EQ(1, mRefreshRateStats.getTotalTimes().size());
-}
-
 TEST_F(RefreshRateStatsTest, oneConfigTest) {
-    auto display = new Hwc2::mock::Display();
-
-    auto config = HWC2::Display::Config::Builder(*display, CONFIG_ID_90);
-    config.setVsyncPeriod(VSYNC_90);
-    std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
-    configs.push_back(config.build());
-
-    mRefreshRateConfigs.populate(configs);
+    init({{CONFIG_ID_90, VSYNC_90}});
 
     EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
     EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1));
 
-    std::unordered_map<std::string, int64_t> times = mRefreshRateStats.getTotalTimes();
-    EXPECT_EQ(2, times.size());
+    std::unordered_map<std::string, int64_t> times = mRefreshRateStats->getTotalTimes();
+    ASSERT_EQ(1, times.size());
     EXPECT_NE(0u, times.count("ScreenOff"));
-    EXPECT_EQ(1u, times.count("90fps"));
-    EXPECT_EQ(0, times["90fps"]);
     // Setting up tests on mobile harness can be flaky with time passing, so testing for
     // exact time changes can result in flaxy numbers. To avoid that remember old
     // numbers to make sure the correct values are increasing in the next test.
     int screenOff = times["ScreenOff"];
-    int ninety = times["90fps"];
 
     // Screen is off by default.
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats.getTotalTimes();
+    times = mRefreshRateStats->getTotalTimes();
     EXPECT_LT(screenOff, times["ScreenOff"]);
-    EXPECT_EQ(0, times["90fps"]);
+    EXPECT_EQ(0u, times.count("90fps"));
 
-    mRefreshRateStats.setConfigMode(CONFIG_ID_90);
-    mRefreshRateStats.setPowerMode(HWC_POWER_MODE_NORMAL);
-    screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
+    mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+    mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+    screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats.getTotalTimes();
+    times = mRefreshRateStats->getTotalTimes();
     EXPECT_EQ(screenOff, times["ScreenOff"]);
-    EXPECT_LT(ninety, times["90fps"]);
+    ASSERT_EQ(1u, times.count("90fps"));
+    EXPECT_LT(0, times["90fps"]);
 
-    mRefreshRateStats.setPowerMode(HWC_POWER_MODE_DOZE);
-    ninety = mRefreshRateStats.getTotalTimes()["90fps"];
+    mRefreshRateStats->setPowerMode(HWC_POWER_MODE_DOZE);
+    int ninety = mRefreshRateStats->getTotalTimes()["90fps"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats.getTotalTimes();
+    times = mRefreshRateStats->getTotalTimes();
     EXPECT_LT(screenOff, times["ScreenOff"]);
     EXPECT_EQ(ninety, times["90fps"]);
 
-    mRefreshRateStats.setConfigMode(CONFIG_ID_90);
-    screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
+    mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+    screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats.getTotalTimes();
+    times = mRefreshRateStats->getTotalTimes();
     // Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config
     // does not update refresh rates that come from the config.
     EXPECT_LT(screenOff, times["ScreenOff"]);
@@ -127,93 +118,75 @@
 }
 
 TEST_F(RefreshRateStatsTest, twoConfigsTest) {
-    auto display = new Hwc2::mock::Display();
-
-    auto config90 = HWC2::Display::Config::Builder(*display, CONFIG_ID_90);
-    config90.setVsyncPeriod(VSYNC_90);
-    std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
-    configs.push_back(config90.build());
-
-    auto config60 = HWC2::Display::Config::Builder(*display, CONFIG_ID_60);
-    config60.setVsyncPeriod(VSYNC_60);
-    configs.push_back(config60.build());
-
-    mRefreshRateConfigs.populate(configs);
+    init({{CONFIG_ID_90, VSYNC_90}, {CONFIG_ID_60, VSYNC_60}});
 
     EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
     EXPECT_CALL(mTimeStats, recordRefreshRate(60, _)).Times(AtLeast(1));
     EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1));
 
-    std::unordered_map<std::string, int64_t> times = mRefreshRateStats.getTotalTimes();
-    EXPECT_EQ(3, times.size());
+    std::unordered_map<std::string, int64_t> times = mRefreshRateStats->getTotalTimes();
+    ASSERT_EQ(1, times.size());
     EXPECT_NE(0u, times.count("ScreenOff"));
-    EXPECT_EQ(1u, times.count("60fps"));
-    EXPECT_EQ(0, times["60fps"]);
-    EXPECT_EQ(1u, times.count("90fps"));
-    EXPECT_EQ(0, times["90fps"]);
     // Setting up tests on mobile harness can be flaky with time passing, so testing for
     // exact time changes can result in flaxy numbers. To avoid that remember old
     // numbers to make sure the correct values are increasing in the next test.
     int screenOff = times["ScreenOff"];
-    int sixty = times["60fps"];
-    int ninety = times["90fps"];
 
     // Screen is off by default.
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats.getTotalTimes();
+    times = mRefreshRateStats->getTotalTimes();
     EXPECT_LT(screenOff, times["ScreenOff"]);
-    EXPECT_EQ(sixty, times["60fps"]);
-    EXPECT_EQ(ninety, times["90fps"]);
 
-    mRefreshRateStats.setConfigMode(CONFIG_ID_90);
-    mRefreshRateStats.setPowerMode(HWC_POWER_MODE_NORMAL);
-    screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
+    mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+    mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+    screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats.getTotalTimes();
+    times = mRefreshRateStats->getTotalTimes();
     EXPECT_EQ(screenOff, times["ScreenOff"]);
-    EXPECT_EQ(sixty, times["60fps"]);
-    EXPECT_LT(ninety, times["90fps"]);
+    ASSERT_EQ(1u, times.count("90fps"));
+    EXPECT_LT(0, times["90fps"]);
 
     // When power mode is normal, time for configs updates.
-    mRefreshRateStats.setConfigMode(CONFIG_ID_60);
-    ninety = mRefreshRateStats.getTotalTimes()["90fps"];
+    mRefreshRateStats->setConfigMode(CONFIG_ID_60);
+    int ninety = mRefreshRateStats->getTotalTimes()["90fps"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats.getTotalTimes();
+    times = mRefreshRateStats->getTotalTimes();
     EXPECT_EQ(screenOff, times["ScreenOff"]);
     EXPECT_EQ(ninety, times["90fps"]);
-    EXPECT_LT(sixty, times["60fps"]);
+    ASSERT_EQ(1u, times.count("60fps"));
+    EXPECT_LT(0, times["60fps"]);
 
-    mRefreshRateStats.setConfigMode(CONFIG_ID_90);
-    sixty = mRefreshRateStats.getTotalTimes()["60fps"];
+    mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+    int sixty = mRefreshRateStats->getTotalTimes()["60fps"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats.getTotalTimes();
+    times = mRefreshRateStats->getTotalTimes();
     EXPECT_EQ(screenOff, times["ScreenOff"]);
     EXPECT_LT(ninety, times["90fps"]);
     EXPECT_EQ(sixty, times["60fps"]);
 
-    mRefreshRateStats.setConfigMode(CONFIG_ID_60);
-    ninety = mRefreshRateStats.getTotalTimes()["90fps"];
+    mRefreshRateStats->setConfigMode(CONFIG_ID_60);
+    ninety = mRefreshRateStats->getTotalTimes()["90fps"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats.getTotalTimes();
+    times = mRefreshRateStats->getTotalTimes();
     EXPECT_EQ(screenOff, times["ScreenOff"]);
     EXPECT_EQ(ninety, times["90fps"]);
     EXPECT_LT(sixty, times["60fps"]);
 
     // Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config
     // does not update refresh rates that come from the config.
-    mRefreshRateStats.setPowerMode(HWC_POWER_MODE_DOZE);
-    mRefreshRateStats.setConfigMode(CONFIG_ID_90);
-    sixty = mRefreshRateStats.getTotalTimes()["60fps"];
+    mRefreshRateStats->setPowerMode(HWC_POWER_MODE_DOZE);
+    mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+    sixty = mRefreshRateStats->getTotalTimes()["60fps"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats.getTotalTimes();
+    times = mRefreshRateStats->getTotalTimes();
     EXPECT_LT(screenOff, times["ScreenOff"]);
     EXPECT_EQ(ninety, times["90fps"]);
     EXPECT_EQ(sixty, times["60fps"]);
 
-    mRefreshRateStats.setConfigMode(CONFIG_ID_60);
-    screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
+    mRefreshRateStats->setConfigMode(CONFIG_ID_60);
+    screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats.getTotalTimes();
+    times = mRefreshRateStats->getTotalTimes();
     EXPECT_LT(screenOff, times["ScreenOff"]);
     EXPECT_EQ(ninety, times["90fps"]);
     EXPECT_EQ(sixty, times["60fps"]);
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 740115e..571fdfd 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -3,13 +3,13 @@
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
-
 #include <log/log.h>
 
 #include <mutex>
 
 #include "Scheduler/EventControlThread.h"
 #include "Scheduler/EventThread.h"
+#include "Scheduler/RefreshRateConfigs.h"
 #include "Scheduler/Scheduler.h"
 #include "mock/MockEventThread.h"
 
@@ -34,7 +34,7 @@
         MOCK_METHOD0(requestNextVsync, void());
     };
 
-    scheduler::RefreshRateConfigs mRefreshRateConfigs;
+    std::unique_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;
 
     /**
      * This mock Scheduler class uses implementation of mock::EventThread but keeps everything else
@@ -73,9 +73,14 @@
             ::testing::UnitTest::GetInstance()->current_test_info();
     ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
 
+    std::vector<scheduler::RefreshRateConfigs::InputConfig> configs{{/*hwcId=*/0, 16666667}};
+    mRefreshRateConfigs =
+            std::make_unique<scheduler::RefreshRateConfigs>(/*refreshRateSwitching=*/false, configs,
+                                                            /*currentConfig=*/0);
+
     std::unique_ptr<mock::EventThread> eventThread = std::make_unique<mock::EventThread>();
     mEventThread = eventThread.get();
-    mScheduler = std::make_unique<MockScheduler>(mRefreshRateConfigs, std::move(eventThread));
+    mScheduler = std::make_unique<MockScheduler>(*mRefreshRateConfigs, std::move(eventThread));
     EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
 
     mEventThreadConnection = new MockEventThreadConnection(mEventThread);
@@ -85,7 +90,7 @@
     EXPECT_CALL(*mEventThread, createEventConnection(_, _))
             .WillRepeatedly(Return(mEventThreadConnection));
 
-    mConnectionHandle = mScheduler->createConnection("appConnection", 16, 16, ResyncCallback(),
+    mConnectionHandle = mScheduler->createConnection("appConnection", 16, 16,
                                                      impl::EventThread::InterceptVSyncsCallback());
     EXPECT_TRUE(mConnectionHandle != nullptr);
 }
@@ -107,7 +112,7 @@
     sp<IDisplayEventConnection> returnedValue;
     ASSERT_NO_FATAL_FAILURE(
             returnedValue =
-                    mScheduler->createDisplayEventConnection(nullptr, ResyncCallback(),
+                    mScheduler->createDisplayEventConnection(nullptr,
                                                              ISurfaceComposer::
                                                                      eConfigChangedSuppress));
     EXPECT_TRUE(returnedValue == nullptr);
@@ -130,7 +135,7 @@
     sp<IDisplayEventConnection> returnedValue;
     ASSERT_NO_FATAL_FAILURE(
             returnedValue =
-                    mScheduler->createDisplayEventConnection(connectionHandle, ResyncCallback(),
+                    mScheduler->createDisplayEventConnection(connectionHandle,
                                                              ISurfaceComposer::
                                                                      eConfigChangedSuppress));
     EXPECT_TRUE(returnedValue == nullptr);
@@ -161,7 +166,7 @@
     sp<IDisplayEventConnection> returnedValue;
     ASSERT_NO_FATAL_FAILURE(
             returnedValue =
-                    mScheduler->createDisplayEventConnection(mConnectionHandle, ResyncCallback(),
+                    mScheduler->createDisplayEventConnection(mConnectionHandle,
                                                              ISurfaceComposer::
                                                                      eConfigChangedSuppress));
     EXPECT_TRUE(returnedValue != nullptr);
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 64d34ee..1c1b020 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -32,11 +32,11 @@
 #include "Layer.h"
 #include "NativeWindowSurface.h"
 #include "Scheduler/MessageQueue.h"
+#include "Scheduler/RefreshRateConfigs.h"
 #include "StartPropertySetThread.h"
 #include "SurfaceFlinger.h"
 #include "SurfaceFlingerFactory.h"
 #include "SurfaceInterceptor.h"
-
 #include "TimeStats/TimeStats.h"
 
 namespace android {
@@ -342,6 +342,8 @@
     auto& mutableAppConnectionHandle() { return mFlinger->mAppConnectionHandle; }
     auto& mutableSfConnectionHandle() { return mFlinger->mSfConnectionHandle; }
     auto& mutableRefreshRateConfigs() { return mFlinger->mRefreshRateConfigs; }
+    auto& mutableRefreshRateStats() { return mFlinger->mRefreshRateStats; }
+    auto& mutableTimeStats() { return mFlinger->mTimeStats; }
 
     ~TestableSurfaceFlinger() {
         // All these pointer and container clears help ensure that GMock does
diff --git a/services/surfaceflinger/version-script32.txt b/services/surfaceflinger/version-script32.txt
new file mode 100644
index 0000000..2340785
--- /dev/null
+++ b/services/surfaceflinger/version-script32.txt
@@ -0,0 +1,12 @@
+{
+global:
+  EnsureFrontOfChain;
+  AddSpecialSignalHandlerFn;
+  RemoveSpecialSignalHandlerFn;
+  bsd_signal;
+  sigaction;
+  signal;
+  sigprocmask;
+local:
+  *;
+};
diff --git a/services/surfaceflinger/version-script64.txt b/services/surfaceflinger/version-script64.txt
new file mode 100644
index 0000000..acf3630
--- /dev/null
+++ b/services/surfaceflinger/version-script64.txt
@@ -0,0 +1,11 @@
+{
+global:
+  EnsureFrontOfChain;
+  AddSpecialSignalHandlerFn;
+  RemoveSpecialSignalHandlerFn;
+  sigaction;
+  signal;
+  sigprocmask;
+local:
+  *;
+};
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index c202b5c..4c34b93 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -1,151 +1,180 @@
 cc_library_shared {
-    name: "libvr_hwc-hal",
+  name: "libvr_hwc-hal",
 
-    srcs: [
-        "impl/vr_hwc.cpp",
-        "impl/vr_composer_client.cpp",
-    ],
+  srcs: [
+    "impl/vr_hwc.cpp",
+    "impl/vr_composer_client.cpp",
+  ],
 
-    static_libs: [
-        "libbroadcastring",
-        "libdisplay",
-    ],
+  static_libs: [
+    "libbroadcastring",
+    "libdisplay",
+  ],
 
-    shared_libs: [
-        "android.frameworks.vr.composer@1.0",
-        "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@3.0",
-        "libbase",
-        "libbufferhubqueue",
-        "libbinder",
-        "libcutils",
-        "libfmq",
-        "libhardware",
-        "libhidlbase",
-        "liblog",
-        "libsync",
-        "libui",
-        "libutils",
-        "libpdx_default_transport",
-    ],
+  shared_libs: [
+    "android.frameworks.vr.composer@1.0",
+    "android.hardware.graphics.composer@2.1",
+    "android.hardware.graphics.mapper@2.0",
+    "android.hardware.graphics.mapper@3.0",
+    "libbase",
+    "libbufferhubqueue",
+    "libbinder",
+    "libcutils",
+    "libfmq",
+    "libhardware",
+    "libhidlbase",
+    "libhidltransport",
+    "liblog",
+    "libsync",
+    "libui",
+    "libutils",
+    "libpdx_default_transport",
+  ],
 
-    header_libs: [
-        "android.hardware.graphics.composer@2.1-command-buffer",
-        "android.hardware.graphics.composer@2.1-hal",
-    ],
+  header_libs: [
+    "android.hardware.graphics.composer@2.1-command-buffer",
+    "android.hardware.graphics.composer@2.1-hal",
+  ],
 
-    export_header_lib_headers: [
-        "android.hardware.graphics.composer@2.1-hal",
-    ],
+  export_header_lib_headers: [
+    "android.hardware.graphics.composer@2.1-hal",
+  ],
 
-    export_static_lib_headers: [
-        "libdisplay",
-    ],
+  export_static_lib_headers: [
+    "libdisplay",
+  ],
 
-    export_shared_lib_headers: [
-        "android.frameworks.vr.composer@1.0",
-        "android.hardware.graphics.composer@2.1",
-    ],
+  export_shared_lib_headers: [
+    "android.frameworks.vr.composer@1.0",
+    "android.hardware.graphics.composer@2.1",
+  ],
 
-    export_include_dirs: ["."],
+  export_include_dirs: ["."],
 
-    cflags: [
-        "-DLOG_TAG=\"vr_hwc\"",
-        "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
-        "-Wall",
-        "-Werror",
-        "-Wno-error=unused-private-field",
-        // Warnings in vr_hwc.cpp to be fixed after sync of goog/master.
-        "-Wno-sign-compare",
-        "-Wno-unused-parameter",
-    ],
+  cflags: [
+    "-DLOG_TAG=\"vr_hwc\"",
+    "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
+    "-Wall",
+    "-Werror",
+    "-Wno-error=unused-private-field",
+    // Warnings in vr_hwc.cpp to be fixed after sync of goog/master.
+    "-Wno-sign-compare",
+    "-Wno-unused-parameter",
+  ],
 
 }
 
 cc_library_static {
-    name: "libvr_hwc-impl",
-    srcs: [
-        "vr_composer.cpp",
-    ],
-    static_libs: [
-        "libvr_hwc-binder",
-    ],
-    shared_libs: [
-        "libbase",
-        "libbinder",
-        "liblog",
-        "libui",
-        "libutils",
-        "libvr_hwc-hal",
-    ],
-    export_shared_lib_headers: [
-        "libvr_hwc-hal",
-    ],
-    cflags: [
-        "-DLOG_TAG=\"vr_hwc\"",
-        "-Wall",
-        "-Werror",
-    ],
+  name: "libvr_hwc-binder",
+  srcs: [
+    "aidl/android/dvr/IVrComposer.aidl",
+    "aidl/android/dvr/IVrComposerCallback.aidl",
+    "aidl/android/dvr/parcelable_composer_frame.cpp",
+    "aidl/android/dvr/parcelable_composer_layer.cpp",
+    "aidl/android/dvr/parcelable_unique_fd.cpp",
+  ],
+  aidl: {
+    include_dirs: ["frameworks/native/services/vr/hardware_composer/aidl"],
+    export_aidl_headers: true,
+  },
+  export_include_dirs: ["aidl"],
+
+  cflags: [
+    "-Wall",
+    "-Werror",
+  ],
+
+  shared_libs: [
+    "libbinder",
+    "libui",
+    "libutils",
+    "libvr_hwc-hal",
+  ],
+}
+
+cc_library_static {
+  name: "libvr_hwc-impl",
+  srcs: [
+    "vr_composer.cpp",
+  ],
+  static_libs: [
+    "libvr_hwc-binder",
+  ],
+  shared_libs: [
+    "libbase",
+    "libbinder",
+    "liblog",
+    "libui",
+    "libutils",
+    "libvr_hwc-hal",
+  ],
+  export_shared_lib_headers: [
+    "libvr_hwc-hal",
+  ],
+  cflags: [
+    "-DLOG_TAG=\"vr_hwc\"",
+    "-Wall",
+    "-Werror",
+  ],
 }
 
 cc_binary {
-    name: "vr_hwc",
-    vintf_fragments: ["manifest_vr_hwc.xml"],
-    srcs: [
-        "vr_hardware_composer_service.cpp",
-    ],
-    static_libs: [
-        "libvr_hwc-impl",
-        // NOTE: This needs to be included after the *-impl lib otherwise the
-        // symbols in the *-binder library get optimized out.
-        "libvr_hwc-binder",
-    ],
-    shared_libs: [
-        "android.frameworks.vr.composer@1.0",
-        "android.hardware.graphics.composer@2.1",
-        "libbase",
-        "libbinder",
-        "liblog",
-        "libhardware",
-        "libhidlbase",
-        "libui",
-        "libutils",
-        "libvr_hwc-hal",
-    ],
-    cflags: [
-        "-DLOG_TAG=\"vr_hwc\"",
-        "-Wall",
-        "-Werror",
-    ],
-    init_rc: [
-        "vr_hwc.rc",
-    ],
+  name: "vr_hwc",
+  vintf_fragments: ["manifest_vr_hwc.xml"],
+  srcs: [
+    "vr_hardware_composer_service.cpp"
+  ],
+  static_libs: [
+    "libvr_hwc-impl",
+    // NOTE: This needs to be included after the *-impl lib otherwise the
+    // symbols in the *-binder library get optimized out.
+    "libvr_hwc-binder",
+  ],
+  shared_libs: [
+    "android.frameworks.vr.composer@1.0",
+    "android.hardware.graphics.composer@2.1",
+    "libbase",
+    "libbinder",
+    "liblog",
+    "libhardware",
+    "libhidlbase",
+    "libui",
+    "libutils",
+    "libvr_hwc-hal",
+  ],
+  cflags: [
+    "-DLOG_TAG=\"vr_hwc\"",
+    "-Wall",
+    "-Werror",
+  ],
+  init_rc: [
+    "vr_hwc.rc",
+  ],
 }
 
 cc_test {
-    name: "vr_hwc_test",
-    gtest: true,
-    srcs: ["tests/vr_composer_test.cpp"],
-    static_libs: [
-        "libgtest",
-        "libvr_hwc-impl",
-        // NOTE: This needs to be included after the *-impl lib otherwise the
-        // symbols in the *-binder library get optimized out.
-        "libvr_hwc-binder",
-    ],
-    cflags: [
-        "-Wall",
-        "-Werror",
-        // warnings in vr_composer_test.cpp to be fixed after merge of goog/master
-        "-Wno-sign-compare",
-        "-Wno-unused-parameter",
-    ],
-    shared_libs: [
-        "libbase",
-        "libbinder",
-        "liblog",
-        "libui",
-        "libutils",
-    ],
+  name: "vr_hwc_test",
+  gtest: true,
+  srcs: ["tests/vr_composer_test.cpp"],
+  static_libs: [
+    "libgtest",
+    "libvr_hwc-impl",
+    // NOTE: This needs to be included after the *-impl lib otherwise the
+    // symbols in the *-binder library get optimized out.
+    "libvr_hwc-binder",
+  ],
+  cflags: [
+    "-Wall",
+    "-Werror",
+    // warnings in vr_composer_test.cpp to be fixed after merge of goog/master
+    "-Wno-sign-compare",
+    "-Wno-unused-parameter",
+  ],
+  shared_libs: [
+    "libbase",
+    "libbinder",
+    "liblog",
+    "libui",
+    "libutils",
+  ],
 }
diff --git a/services/vr/hardware_composer/aidl/Android.bp b/services/vr/hardware_composer/aidl/Android.bp
deleted file mode 100644
index a1d5392..0000000
--- a/services/vr/hardware_composer/aidl/Android.bp
+++ /dev/null
@@ -1,27 +0,0 @@
-cc_library_static {
-    name: "libvr_hwc-binder",
-    srcs: [
-        "android/dvr/IVrComposer.aidl",
-        "android/dvr/IVrComposerCallback.aidl",
-        "android/dvr/parcelable_composer_frame.cpp",
-        "android/dvr/parcelable_composer_layer.cpp",
-        "android/dvr/parcelable_unique_fd.cpp",
-    ],
-    aidl: {
-        local_include_dirs: ["."],
-        export_aidl_headers: true,
-    },
-    export_include_dirs: ["."],
-
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-
-    shared_libs: [
-        "libbinder",
-        "libui",
-        "libutils",
-        "libvr_hwc-hal",
-    ],
-}
diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp
index dcaa663..131a306 100644
--- a/services/vr/virtual_touchpad/Android.bp
+++ b/services/vr/virtual_touchpad/Android.bp
@@ -62,7 +62,7 @@
 service_src = [
     "main.cpp",
     "VirtualTouchpadService.cpp",
-    ":virtualtouchpad_aidl",
+    "aidl/android/dvr/IVirtualTouchpadService.aidl",
 ]
 
 service_static_libs = [
@@ -99,7 +99,7 @@
 client_src = [
     "VirtualTouchpadClient.cpp",
     "DvrVirtualTouchpadClient.cpp",
-    ":virtualtouchpad_aidl",
+    "aidl/android/dvr/IVirtualTouchpadService.aidl",
 ]
 
 client_shared_libs = [
@@ -122,9 +122,3 @@
     name: "libvirtualtouchpadclient",
     export_include_dirs: ["include"],
 }
-
-filegroup {
-    name: "virtualtouchpad_aidl",
-    srcs: ["aidl/android/dvr/IVirtualTouchpadService.aidl"],
-    path: "aidl",
-}
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 4d6b2be..993b751 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -41,13 +41,11 @@
         "-DVK_NO_PROTOTYPES",
         "-fvisibility=hidden",
         "-fstrict-aliasing",
-        "-Wextra",
+        "-Weverything",
         "-Werror",
         "-Wno-padded",
-        "-Wno-sign-compare",
         "-Wno-switch-enum",
-        "-Wno-unused-variable",
-        "-Wno-unused-function",
+        "-Wno-undef",
 
         // Have clang emit complete debug_info.
         "-fstandalone-debug",
@@ -89,6 +87,7 @@
         "libbase",
         "libdl_android",
         "libhidlbase",
+        "libhidltransport",
         "liblog",
         "libui",
         "libgraphicsenv",
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 3d56656..c3b5523 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -124,7 +124,7 @@
     };
 
     void AddImplicitLayers() {
-        if (!is_instance_ || !driver::Debuggable())
+        if (!is_instance_)
             return;
 
         GetLayersFromSettings();
@@ -370,7 +370,8 @@
 
    private:
     bool EnableDebugCallback() const {
-        return (is_instance_ && driver::Debuggable() &&
+        return (is_instance_ &&
+                android::GraphicsEnv::getInstance().isDebuggable() &&
                 property_get_bool("debug.vulkan.enable_callback", false));
     }
 
@@ -519,11 +520,7 @@
       get_device_proc_addr_(nullptr),
       driver_extensions_(nullptr),
       driver_extension_count_(0) {
-    // advertise the loader supported core Vulkan API version at vulkan::api
-    for (uint32_t i = driver::ProcHook::EXTENSION_CORE_1_0;
-         i != driver::ProcHook::EXTENSION_COUNT; ++i) {
-        enabled_extensions_.set(i);
-    }
+    enabled_extensions_.set(driver::ProcHook::EXTENSION_CORE);
 }
 
 LayerChain::~LayerChain() {
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
index a5a0405..bdd3573 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -765,19 +765,6 @@
 {{end}}
 
 
-
-{{/*
-------------------------------------------------------------------------------
-  Emits the ProcHook enum for core Vulkan API verions.
-------------------------------------------------------------------------------
-*/}}
-{{define "driver.GetProcHookEnum"}}
-  {{if GetAnnotation $ "vulkan1_1"}}ProcHook::EXTENSION_CORE_1_1
-  {{else}}ProcHook::EXTENSION_CORE_1_0
-  {{end}}
-{{end}}
-
-
 {{/*
 ------------------------------------------------------------------------------
   Emits true if a function needs a ProcHook stub.
@@ -791,8 +778,6 @@
     {{if $ext}}
       {{if not (Macro "IsExtensionInternal" $ext)}}true{{end}}
     {{end}}
-
-    {{if GetAnnotation $ "vulkan1_1"}}true{{end}}
   {{end}}
 {{end}}
 
@@ -816,8 +801,7 @@
           {{TrimPrefix "VK_" $e}},
         {{end}}

-        EXTENSION_CORE_1_0,
-        EXTENSION_CORE_1_1,
+        EXTENSION_CORE, // valid bit
         EXTENSION_COUNT,
         EXTENSION_UNKNOWN,
       };
@@ -854,21 +838,14 @@
   {{AssertType $ "Function"}}
 
   {{if (Macro "driver.NeedProcHookStub" $)}}
-    {{$ext_name := Strings ("")}}
-    {{$ext_hook := Strings ("")}}
     {{$ext := GetAnnotation $ "extension"}}
-    {{if $ext}}
-      {{$ext_name = index $ext.Arguments 0}}
-      {{$ext_hook = Strings ("ProcHook::") (Macro "BaseName" $ext)}}
-    {{else}}
-      {{$ext_name = Strings ("VK_VERSION_1_0")}}
-      {{$ext_hook = (Macro "driver.GetProcHookEnum" $)}}
-    {{end}}
+    {{$ext_name := index $ext.Arguments 0}}
 
     {{$base := (Macro "BaseName" $)}}
 
     VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) {
       {{$p0 := index $.CallParameters 0}}
+      {{$ext_hook := Strings ("ProcHook::") (Macro "BaseName" $ext)}}
 
       if (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) {
         {{if not (IsVoid $.Return.Type)}}return §{{end}}
@@ -901,7 +878,7 @@
   {
     "{{$.Name}}",
     ProcHook::GLOBAL,
-    {{Macro "driver.GetProcHookEnum" $}},
+    ProcHook::EXTENSION_CORE,
     reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
     nullptr,
   },
@@ -934,7 +911,7 @@
         nullptr,
       {{end}}
     {{else}}
-      {{Macro "driver.GetProcHookEnum" $}},
+      ProcHook::EXTENSION_CORE,
       reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
       nullptr,
     {{end}}
@@ -957,23 +934,18 @@
     ProcHook::DEVICE,
 
     {{$ext := GetAnnotation $ "extension"}}
-    {{if or $ext (GetAnnotation $ "vulkan1_1")}}
-      {{if $ext}}
-        ProcHook::{{Macro "BaseName" $ext}},
-        {{if Macro "IsExtensionInternal" $ext}}
-          nullptr,
-          nullptr,
-        {{else}}
-          reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
-          reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
-        {{end}}
+    {{if $ext}}
+      ProcHook::{{Macro "BaseName" $ext}},
+
+      {{if (Macro "IsExtensionInternal" $ext)}}
+        nullptr,
+        nullptr,
       {{else}}
-        {{Macro "driver.GetProcHookEnum" $}},
         reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
         reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
       {{end}}
     {{else}}
-      {{Macro "driver.GetProcHookEnum" $}},
+      ProcHook::EXTENSION_CORE,
       reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
       nullptr,
     {{end}}
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 7477351..8ea0980 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -24,10 +24,7 @@
 #include <dlfcn.h>
 #include <algorithm>
 #include <array>
-#include <climits>
 #include <new>
-#include <sstream>
-#include <string>
 
 #include <log/log.h>
 
@@ -107,7 +104,6 @@
 
     VkResult Validate();
     void DowngradeApiVersion();
-    void UpgradeDeviceCoreApiVersion(uint32_t api_version);
 
     const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
     const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
@@ -156,12 +152,15 @@
 Hal Hal::hal_;
 
 void* LoadLibrary(const android_dlextinfo& dlextinfo,
-                  const std::string_view subname) {
+                  const char* subname,
+                  int subname_len) {
     ATRACE_CALL();
 
-    std::stringstream ss;
-    ss << "vulkan." << subname << ".so";
-    return android_dlopen_ext(ss.str().c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+    const char kLibFormat[] = "vulkan.%*s.so";
+    char* name = static_cast<char*>(
+        alloca(sizeof(kLibFormat) + static_cast<size_t>(subname_len)));
+    sprintf(name, kLibFormat, subname_len, subname);
+    return android_dlopen_ext(name, RTLD_LOCAL | RTLD_NOW, &dlextinfo);
 }
 
 const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
@@ -181,9 +180,8 @@
     char prop[PROPERTY_VALUE_MAX];
     for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
         int prop_len = property_get(key, prop, nullptr);
-        if (prop_len > 0 && prop_len <= UINT_MAX) {
-            std::string_view lib_name(prop, static_cast<unsigned int>(prop_len));
-            so = LoadLibrary(dlextinfo, lib_name);
+        if (prop_len > 0) {
+            so = LoadLibrary(dlextinfo, prop, prop_len);
             if (so)
                 break;
         }
@@ -335,12 +333,8 @@
       physical_dev_(VK_NULL_HANDLE),
       instance_info_(create_info),
       extension_filter_() {
-    // instance core versions need to match the loader api version
-    for (uint32_t i = ProcHook::EXTENSION_CORE_1_0;
-         i != ProcHook::EXTENSION_COUNT; ++i) {
-        hook_extensions_.set(i);
-        hal_extensions_.set(i);
-    }
+    hook_extensions_.set(ProcHook::EXTENSION_CORE);
+    hal_extensions_.set(ProcHook::EXTENSION_CORE);
 }
 
 CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
@@ -351,9 +345,8 @@
       physical_dev_(physical_dev),
       dev_info_(create_info),
       extension_filter_() {
-    // initialize with baseline core API version
-    hook_extensions_.set(ProcHook::EXTENSION_CORE_1_0);
-    hal_extensions_.set(ProcHook::EXTENSION_CORE_1_0);
+    hook_extensions_.set(ProcHook::EXTENSION_CORE);
+    hal_extensions_.set(ProcHook::EXTENSION_CORE);
 }
 
 CreateInfoWrapper::~CreateInfoWrapper() {
@@ -552,8 +545,7 @@
             case ProcHook::ANDROID_external_memory_android_hardware_buffer:
             case ProcHook::ANDROID_native_buffer:
             case ProcHook::GOOGLE_display_timing:
-            case ProcHook::EXTENSION_CORE_1_0:
-            case ProcHook::EXTENSION_CORE_1_1:
+            case ProcHook::EXTENSION_CORE:
             case ProcHook::EXTENSION_COUNT:
                 // Device and meta extensions. If we ever get here it's a bug in
                 // our code. But enumerating them lets us avoid having a default
@@ -601,8 +593,7 @@
             case ProcHook::EXT_debug_report:
             case ProcHook::EXT_swapchain_colorspace:
             case ProcHook::ANDROID_native_buffer:
-            case ProcHook::EXTENSION_CORE_1_0:
-            case ProcHook::EXTENSION_CORE_1_1:
+            case ProcHook::EXTENSION_CORE:
             case ProcHook::EXTENSION_COUNT:
                 // Instance and meta extensions. If we ever get here it's a bug
                 // in our code. But enumerating them lets us avoid having a
@@ -650,28 +641,6 @@
     }
 }
 
-void CreateInfoWrapper::UpgradeDeviceCoreApiVersion(uint32_t api_version) {
-    ALOG_ASSERT(!is_instance_, "Device only API called by instance wrapper.");
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wold-style-cast"
-    api_version ^= VK_VERSION_PATCH(api_version);
-#pragma clang diagnostic pop
-    // cap the API version to the loader supported highest version
-    if (api_version > VK_API_VERSION_1_1)
-        api_version = VK_API_VERSION_1_1;
-    switch (api_version) {
-        case VK_API_VERSION_1_1:
-            hook_extensions_.set(ProcHook::EXTENSION_CORE_1_1);
-            hal_extensions_.set(ProcHook::EXTENSION_CORE_1_1);
-            [[clang::fallthrough]];
-        case VK_API_VERSION_1_0:
-            break;
-        default:
-            ALOGD("Unknown upgrade API version[%u]", api_version);
-            break;
-    }
-}
-
 VKAPI_ATTR void* DefaultAllocate(void*,
                                  size_t size,
                                  size_t alignment,
@@ -755,10 +724,6 @@
 
 }  // anonymous namespace
 
-bool Debuggable() {
-    return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
-}
-
 bool OpenHAL() {
     return Hal::Open();
 }
@@ -807,7 +772,7 @@
                        : nullptr;
             break;
         case ProcHook::DEVICE:
-            proc = (hook->extension == ProcHook::EXTENSION_CORE_1_0)
+            proc = (hook->extension == ProcHook::EXTENSION_CORE)
                        ? hook->proc
                        : hook->checked_proc;
             break;
@@ -1155,13 +1120,6 @@
     if (!data)
         return VK_ERROR_OUT_OF_HOST_MEMORY;
 
-    VkPhysicalDeviceProperties properties;
-    ATRACE_BEGIN("driver.GetPhysicalDeviceProperties");
-    instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
-                                                     &properties);
-    ATRACE_END();
-
-    wrapper.UpgradeDeviceCoreApiVersion(properties.apiVersion);
     data->hook_extensions |= wrapper.GetHookExtensions();
 
     // call into the driver
@@ -1206,6 +1164,12 @@
         return VK_ERROR_INCOMPATIBLE_DRIVER;
     }
 
+    VkPhysicalDeviceProperties properties;
+    ATRACE_BEGIN("driver.GetPhysicalDeviceProperties");
+    instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
+                                                     &properties);
+    ATRACE_END();
+
     if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) {
         // Log that the app is hitting software Vulkan implementation
         android::GraphicsEnv::getInstance().setTargetStats(
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
index 047a27a..075a15b 100644
--- a/vulkan/libvulkan/driver.h
+++ b/vulkan/libvulkan/driver.h
@@ -67,7 +67,9 @@
         : opaque_api_data(),
           allocator(alloc),
           driver(),
-          get_device_proc_addr(nullptr) {}
+          get_device_proc_addr(nullptr) {
+        hook_extensions.set(ProcHook::EXTENSION_CORE);
+    }
 
     api::InstanceData opaque_api_data;
 
@@ -87,7 +89,9 @@
         : opaque_api_data(),
           allocator(alloc),
           debug_report_callbacks(debug_report_callbacks_),
-          driver() {}
+          driver() {
+        hook_extensions.set(ProcHook::EXTENSION_CORE);
+    }
 
     api::DeviceData opaque_api_data;
 
@@ -101,7 +105,6 @@
     uint32_t driver_version;
 };
 
-bool Debuggable();
 bool OpenHAL();
 const VkAllocationCallbacks& GetDefaultAllocator();
 
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index aa31735..574c327 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -31,23 +31,6 @@
 
 // clang-format off
 
-VKAPI_ATTR VkResult checkedBindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
-    if (GetData(device).hook_extensions[ProcHook::EXTENSION_CORE_1_1]) {
-        return BindImageMemory2(device, bindInfoCount, pBindInfos);
-    } else {
-        Logger(device).Err(device, "VK_VERSION_1_0 not enabled. vkBindImageMemory2 not executed.");
-        return VK_SUCCESS;
-    }
-}
-
-VKAPI_ATTR void checkedGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
-    if (GetData(device).hook_extensions[ProcHook::EXTENSION_CORE_1_1]) {
-        GetDeviceQueue2(device, pQueueInfo, pQueue);
-    } else {
-        Logger(device).Err(device, "VK_VERSION_1_0 not enabled. vkGetDeviceQueue2 not executed.");
-    }
-}
-
 VKAPI_ATTR VkResult checkedCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain) {
     if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
         return CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
@@ -191,16 +174,16 @@
     {
         "vkAllocateCommandBuffers",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE_1_0,
+        ProcHook::EXTENSION_CORE,
         reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers),
         nullptr,
     },
     {
         "vkBindImageMemory2",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE_1_1,
+        ProcHook::EXTENSION_CORE,
         reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory2),
-        reinterpret_cast<PFN_vkVoidFunction>(checkedBindImageMemory2),
+        nullptr,
     },
     {
         "vkBindImageMemory2KHR",
@@ -226,14 +209,14 @@
     {
         "vkCreateDevice",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE_1_0,
+        ProcHook::EXTENSION_CORE,
         reinterpret_cast<PFN_vkVoidFunction>(CreateDevice),
         nullptr,
     },
     {
         "vkCreateInstance",
         ProcHook::GLOBAL,
-        ProcHook::EXTENSION_CORE_1_0,
+        ProcHook::EXTENSION_CORE,
         reinterpret_cast<PFN_vkVoidFunction>(CreateInstance),
         nullptr,
     },
@@ -261,14 +244,14 @@
     {
         "vkDestroyDevice",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE_1_0,
+        ProcHook::EXTENSION_CORE,
         reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice),
         nullptr,
     },
     {
         "vkDestroyInstance",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE_1_0,
+        ProcHook::EXTENSION_CORE,
         reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance),
         nullptr,
     },
@@ -289,28 +272,28 @@
     {
         "vkEnumerateDeviceExtensionProperties",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE_1_0,
+        ProcHook::EXTENSION_CORE,
         reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties),
         nullptr,
     },
     {
         "vkEnumerateInstanceExtensionProperties",
         ProcHook::GLOBAL,
-        ProcHook::EXTENSION_CORE_1_0,
+        ProcHook::EXTENSION_CORE,
         reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties),
         nullptr,
     },
     {
         "vkEnumeratePhysicalDeviceGroups",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE_1_1,
+        ProcHook::EXTENSION_CORE,
         reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDeviceGroups),
         nullptr,
     },
     {
         "vkEnumeratePhysicalDevices",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE_1_0,
+        ProcHook::EXTENSION_CORE,
         reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices),
         nullptr,
     },
@@ -331,28 +314,28 @@
     {
         "vkGetDeviceProcAddr",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE_1_0,
+        ProcHook::EXTENSION_CORE,
         reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr),
         nullptr,
     },
     {
         "vkGetDeviceQueue",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE_1_0,
+        ProcHook::EXTENSION_CORE,
         reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue),
         nullptr,
     },
     {
         "vkGetDeviceQueue2",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE_1_1,
+        ProcHook::EXTENSION_CORE,
         reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue2),
-        reinterpret_cast<PFN_vkVoidFunction>(checkedGetDeviceQueue2),
+        nullptr,
     },
     {
         "vkGetInstanceProcAddr",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE_1_0,
+        ProcHook::EXTENSION_CORE,
         reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr),
         nullptr,
     },
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 831efb7..3faf6c0 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -48,8 +48,7 @@
         ANDROID_external_memory_android_hardware_buffer,
         KHR_bind_memory2,
 
-        EXTENSION_CORE_1_0,
-        EXTENSION_CORE_1_1,
+        EXTENSION_CORE,  // valid bit
         EXTENSION_COUNT,
         EXTENSION_UNKNOWN,
     };
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index dd91739..691f3b0 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -24,7 +24,6 @@
 #include <string.h>
 #include <sys/prctl.h>
 
-#include <memory>
 #include <mutex>
 #include <string>
 #include <vector>
@@ -102,7 +101,9 @@
     bool EnumerateLayers(size_t library_idx,
                          std::vector<Layer>& instance_layers) const;
 
-    void* GetGPA(const Layer& layer, const std::string_view gpa_name) const;
+    void* GetGPA(const Layer& layer,
+                 const char* gpa_name,
+                 size_t gpa_name_len) const;
 
     const std::string GetFilename() { return filename_; }
 
@@ -225,10 +226,17 @@
     }
 
     // get layer properties
-    auto properties = std::make_unique<VkLayerProperties[]>(num_instance_layers + num_device_layers);
+    VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca(
+        (num_instance_layers + num_device_layers) * sizeof(VkLayerProperties)));
+    result = enumerate_instance_layers(&num_instance_layers, properties);
+    if (result != VK_SUCCESS) {
+        ALOGE("vkEnumerateInstanceLayerProperties failed for library '%s': %d",
+              path_.c_str(), result);
+        return false;
+    }
     if (num_device_layers > 0) {
         result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
-                                         properties.get() + num_instance_layers);
+                                         properties + num_instance_layers);
         if (result != VK_SUCCESS) {
             ALOGE(
                 "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
@@ -313,11 +321,21 @@
     return true;
 }
 
-void* LayerLibrary::GetGPA(const Layer& layer, const std::string_view gpa_name) const {
-    std::string layer_name { layer.properties.layerName };
-    if (void* gpa = GetTrampoline((layer_name.append(gpa_name).c_str())))
-        return gpa;
-    return GetTrampoline((std::string {"vk"}.append(gpa_name)).c_str());
+void* LayerLibrary::GetGPA(const Layer& layer,
+                           const char* gpa_name,
+                           size_t gpa_name_len) const {
+    void* gpa;
+    size_t layer_name_len =
+        std::max(size_t{2}, strlen(layer.properties.layerName));
+    char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
+    strcpy(name, layer.properties.layerName);
+    strcpy(name + layer_name_len, gpa_name);
+    if (!(gpa = GetTrampoline(name))) {
+        strcpy(name, "vk");
+        strcpy(name + 2, gpa_name);
+        gpa = GetTrampoline(name);
+    }
+    return gpa;
 }
 
 // ----------------------------------------------------------------------------
@@ -370,8 +388,9 @@
         return;
     }
     std::string prefix(dir_in_zip + "/");
+    const ZipString prefix_str(prefix.c_str());
     void* iter_cookie = nullptr;
-    if ((err = StartIteration(zip, &iter_cookie, prefix, "")) != 0) {
+    if ((err = StartIteration(zip, &iter_cookie, &prefix_str, nullptr)) != 0) {
         ALOGE("failed to iterate entries in apk '%s': %d", zipname.c_str(),
               err);
         CloseArchive(zip);
@@ -380,9 +399,11 @@
     ALOGD("searching for layers in '%s!/%s'", zipname.c_str(),
           dir_in_zip.c_str());
     ZipEntry entry;
-    std::string name;
+    ZipString name;
     while (Next(iter_cookie, &entry, &name) == 0) {
-        std::string filename(name.substr(prefix.length()));
+        std::string filename(
+            reinterpret_cast<const char*>(name.name) + prefix.length(),
+            name.name_length - prefix.length());
         // only enumerate direct entries of the directory, not subdirectories
         if (filename.find('/') != filename.npos)
             continue;
@@ -452,9 +473,10 @@
 }
 
 void* GetLayerGetProcAddr(const Layer& layer,
-                          const std::string_view gpa_name) {
+                          const char* gpa_name,
+                          size_t gpa_name_len) {
     const LayerLibrary& library = g_layer_libraries[layer.library_idx];
-    return library.GetGPA(layer, gpa_name);
+    return library.GetGPA(layer, gpa_name, gpa_name_len);
 }
 
 }  // anonymous namespace
@@ -462,8 +484,7 @@
 void DiscoverLayers() {
     ATRACE_CALL();
 
-    if (property_get_bool("ro.debuggable", false) &&
-        prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
+    if (android::GraphicsEnv::getInstance().isDebuggable()) {
         DiscoverLayersInPathList(kSystemLayerLibraryDir);
     }
     if (!android::GraphicsEnv::getInstance().getLayerPaths().empty())
@@ -537,13 +558,13 @@
 
 PFN_vkGetInstanceProcAddr LayerRef::GetGetInstanceProcAddr() const {
     return layer_ ? reinterpret_cast<PFN_vkGetInstanceProcAddr>(
-                        GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr"))
+                        GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr", 19))
                   : nullptr;
 }
 
 PFN_vkGetDeviceProcAddr LayerRef::GetGetDeviceProcAddr() const {
     return layer_ ? reinterpret_cast<PFN_vkGetDeviceProcAddr>(
-                        GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr"))
+                        GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr", 17))
                   : nullptr;
 }
 
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index fbf6d0d..a8949d3 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -718,6 +718,8 @@
         {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
         {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
         {VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
+        {VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
+        {VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
     };
     const uint32_t kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
     uint32_t total_num_formats = kNumFormats;
@@ -1278,7 +1280,6 @@
     VkImageCreateInfo image_create = {
         .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
         .pNext = &image_native_buffer,
-        .flags = createProtectedSwapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
         .imageType = VK_IMAGE_TYPE_2D,
         .format = create_info->imageFormat,
         .extent = {0, 0, 1},
@@ -1287,6 +1288,7 @@
         .samples = VK_SAMPLE_COUNT_1_BIT,
         .tiling = VK_IMAGE_TILING_OPTIMAL,
         .usage = create_info->imageUsage,
+        .flags = createProtectedSwapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
         .sharingMode = create_info->imageSharingMode,
         .queueFamilyIndexCount = create_info->queueFamilyIndexCount,
         .pQueueFamilyIndices = create_info->pQueueFamilyIndices,
@@ -1379,7 +1381,7 @@
     bool active = swapchain->surface.swapchain_handle == swapchain_handle;
     ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
 
-    if (window && swapchain->frame_timestamps_enabled) {
+    if (swapchain->frame_timestamps_enabled) {
         native_window_enable_frame_timestamps(window, false);
     }
     for (uint32_t i = 0; i < swapchain->num_images; i++)
diff --git a/vulkan/nulldrv/Android.bp b/vulkan/nulldrv/Android.bp
index ba02504..dedf419 100644
--- a/vulkan/nulldrv/Android.bp
+++ b/vulkan/nulldrv/Android.bp
@@ -23,11 +23,18 @@
         "-fvisibility=hidden",
         "-fstrict-aliasing",
         "-DLOG_TAG=\"vknulldrv\"",
-        "-Wextra",
+        "-Weverything",
         "-Werror",
+        "-Wno-padded",
+        "-Wno-undef",
+        "-Wno-zero-length-array",
 
         "-DLOG_NDEBUG=0",
     ],
+    cppflags: [
+        "-Wno-c++98-compat-pedantic",
+        "-Wno-c99-extensions",
+    ],
 
     srcs: [
         "null_driver.cpp",
diff --git a/vulkan/tools/Android.bp b/vulkan/tools/Android.bp
index 91d64fe..2514094 100644
--- a/vulkan/tools/Android.bp
+++ b/vulkan/tools/Android.bp
@@ -22,8 +22,16 @@
 
         "-DLOG_TAG=\"vkinfo\"",
 
-        "-Wextra",
+        "-Weverything",
         "-Werror",
+        "-Wno-padded",
+        "-Wno-undef",
+        "-Wno-switch-enum",
+    ],
+    cppflags: [
+        "-Wno-c++98-compat-pedantic",
+        "-Wno-c99-extensions",
+        "-Wno-old-style-cast",
     ],
 
     srcs: ["vkinfo.cpp"],
diff --git a/vulkan/tools/vkinfo.cpp b/vulkan/tools/vkinfo.cpp
index f9e4916..89bc926 100644
--- a/vulkan/tools/vkinfo.cpp
+++ b/vulkan/tools/vkinfo.cpp
@@ -195,10 +195,10 @@
         .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
         .queueCreateInfoCount = 1,
         .pQueueCreateInfos = &queue_create_info,
-        .enabledLayerCount = (options.validate) ? num_layers : 0,
-        .ppEnabledLayerNames = kValidationLayers,
         .enabledExtensionCount = num_extensions,
         .ppEnabledExtensionNames = extensions,
+        .enabledLayerCount = (options.validate) ? num_layers : 0,
+        .ppEnabledLayerNames = kValidationLayers,
         .pEnabledFeatures = &info.features,
     };
     result = vkCreateDevice(gpu, &create_info, nullptr, &device);
@@ -272,10 +272,10 @@
     const VkInstanceCreateInfo create_info = {
         .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
         .pApplicationInfo = &application_info,
-        .enabledLayerCount = (options.validate) ? num_layers : 0,
-        .ppEnabledLayerNames = kValidationLayers,
         .enabledExtensionCount = num_extensions,
         .ppEnabledExtensionNames = extensions,
+        .enabledLayerCount = (options.validate) ? num_layers : 0,
+        .ppEnabledLayerNames = kValidationLayers,
     };
     VkInstance instance;
     result = vkCreateInstance(&create_info, nullptr, &instance);