Merge "Add a service-unique ID to BufferNode"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 1855d26..6a9007c 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -34,23 +34,21 @@
 # made today requires touching the same file, just copy the old
 # touch step and add it to the end of the list.
 #
-# *****************************************************************
-# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THE BANNER
-# *****************************************************************
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
 
 # For example:
 #$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
 #$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
 #$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
 #$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
 $(call add-clean-step, find $(PRODUCT_OUT) -type f -name "libdvr.so" -print0 | xargs -0 rm -f)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libdvr_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libdvr_intermediates)
 $(call add-clean-step, find $(PRODUCT_OUT) -type f -name "libgui*" -print0 | xargs -0 rm -f)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libgui_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libgui_intermediates)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/thermalserviced)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/thermalservice.rc)
-# ******************************************************************
-# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
-# ******************************************************************
+$(call add-clean-step, find $(PRODUCT_OUT) -type f -name "gpuservice*" -print0 | xargs -0 rm -f)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/gpuservice_intermediates)
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index d6ca0bf..4459cef 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -97,6 +97,14 @@
     chmod 0666 /sys/kernel/tracing/events/kmem/ion_heap_grow/enable
     chmod 0666 /sys/kernel/debug/tracing/events/kmem/ion_heap_shrink/enable
     chmod 0666 /sys/kernel/tracing/events/kmem/ion_heap_shrink/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/signal/signal_generate/enable
+    chmod 0666 /sys/kernel/tracing/events/signal/signal_generate/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/signal/signal_deliver/enable
+    chmod 0666 /sys/kernel/tracing/events/signal/signal_deliver/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/mm_event/mm_event_record/enable
+    chmod 0666 /sys/kernel/tracing/events/mm_event/mm_event_record/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/lowmemorykiller/lowmemory_kill/enable
+    chmod 0666 /sys/kernel/tracing/events/lowmemorykiller/lowmemory_kill/enable
 
     # disk
     chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block/enable
diff --git a/cmds/bugreportz/Android.bp b/cmds/bugreportz/Android.bp
new file mode 100644
index 0000000..924a3a3
--- /dev/null
+++ b/cmds/bugreportz/Android.bp
@@ -0,0 +1,44 @@
+// bugreportz
+// ==========
+cc_binary {
+    name: "bugreportz",
+
+    srcs: [
+        "bugreportz.cpp",
+        "main.cpp",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+    ],
+}
+
+// bugreportz_test
+// ===============
+cc_test {
+    name: "bugreportz_test",
+    test_suites: ["device-tests"],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    srcs: [
+        "bugreportz.cpp",
+        "bugreportz_test.cpp",
+    ],
+
+    static_libs: ["libgmock"],
+
+    shared_libs: [
+        "libbase",
+        "libutils",
+    ],
+}
diff --git a/cmds/bugreportz/Android.mk b/cmds/bugreportz/Android.mk
deleted file mode 100644
index 10dda56..0000000
--- a/cmds/bugreportz/Android.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# bugreportz
-# ==========
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-   bugreportz.cpp \
-   main.cpp \
-
-LOCAL_MODULE:= bugreportz
-
-LOCAL_CFLAGS := -Werror -Wall
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libcutils \
-
-include $(BUILD_EXECUTABLE)
-
-# bugreportz_test
-# ===============
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := bugreportz_test
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -Werror -Wall
-
-LOCAL_SRC_FILES := \
-    bugreportz.cpp \
-    bugreportz_test.cpp \
-
-LOCAL_STATIC_LIBRARIES := \
-    libgmock \
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libutils \
-
-include $(BUILD_NATIVE_TEST)
diff --git a/cmds/cmd/Android.bp b/cmds/cmd/Android.bp
new file mode 100644
index 0000000..d91184a
--- /dev/null
+++ b/cmds/cmd/Android.bp
@@ -0,0 +1,18 @@
+cc_binary {
+    name: "cmd",
+
+    srcs: ["cmd.cpp"],
+
+    shared_libs: [
+        "libutils",
+        "liblog",
+        "libselinux",
+        "libbinder",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-DXP_UNIX",
+    ],
+}
diff --git a/cmds/cmd/Android.mk b/cmds/cmd/Android.mk
deleted file mode 100644
index 4868555..0000000
--- a/cmds/cmd/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	cmd.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libutils \
-	liblog \
-    libselinux \
-	libbinder
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_C_INCLUDES += \
-    $(JNI_H_INCLUDE)
-
-ifeq ($(TARGET_OS),linux)
-	LOCAL_CFLAGS += -DXP_UNIX
-	#LOCAL_SHARED_LIBRARIES += librt
-endif
-
-LOCAL_MODULE:= cmd
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 71658d8..0ee6c3a 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -24,10 +24,31 @@
 
 #include "DumpstateInternal.h"
 
+using android::base::StringPrintf;
+
 namespace android {
 namespace os {
 
 namespace {
+
+static binder::Status exception(uint32_t code, const std::string& msg) {
+    MYLOGE("%s (%d) ", msg.c_str(), code);
+    return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
+}
+
+static binder::Status error(uint32_t code, const std::string& msg) {
+    MYLOGE("%s (%d) ", msg.c_str(), code);
+    return binder::Status::fromServiceSpecificError(code, String8(msg.c_str()));
+}
+
+static void* callAndNotify(void* data) {
+    Dumpstate& ds = *static_cast<Dumpstate*>(data);
+    // TODO(111441001): Return status on listener.
+    ds.Run();
+    MYLOGE("Finished Run()\n");
+    return nullptr;
+}
+
 class DumpstateToken : public BnDumpstateToken {};
 }
 
@@ -77,10 +98,30 @@
     return binder::Status::ok();
 }
 
-binder::Status DumpstateService::startBugreport(int, const sp<IDumpstateListener>&,
-                                                const DumpstateOptions&, int32_t* returned_id) {
-    // TODO: fork to handle the bugreport request and return the process id or a request id here.
+binder::Status DumpstateService::startBugreport(int, int bugreport_mode, int32_t* returned_id) {
+    // TODO(111441001): return a request id here.
     *returned_id = -1;
+    MYLOGI("startBugreport() with mode: %d\n", bugreport_mode);
+
+    if (bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_FULL &&
+        bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE &&
+        bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_REMOTE &&
+        bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_WEAR &&
+        bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_TELEPHONY &&
+        bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_WIFI) {
+        return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
+                         StringPrintf("Invalid bugreport mode: %d", bugreport_mode));
+    }
+
+    std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
+    options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode));
+    ds_.SetOptions(std::move(options));
+
+    pthread_t thread;
+    status_t err = pthread_create(&thread, nullptr, callAndNotify, &ds_);
+    if (err != 0) {
+        return error(err, "Could not create a background thread.");
+    }
     return binder::Status::ok();
 }
 
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index 131aff3..58095b3 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -41,8 +41,7 @@
                                bool getSectionDetails,
                                sp<IDumpstateToken>* returned_token) override;
 
-    binder::Status startBugreport(int fd, const sp<IDumpstateListener>& listener,
-                                  const DumpstateOptions& options, int32_t* returned_id) override;
+    binder::Status startBugreport(int fd, int bugreport_mode, int32_t* returned_id) override;
 
   private:
     Dumpstate& ds_;
diff --git a/cmds/dumpstate/DumpstateUtil.cpp b/cmds/dumpstate/DumpstateUtil.cpp
index 600a500..97c8ae2 100644
--- a/cmds/dumpstate/DumpstateUtil.cpp
+++ b/cmds/dumpstate/DumpstateUtil.cpp
@@ -101,13 +101,16 @@
 }
 
 CommandOptions::CommandOptionsBuilder& CommandOptions::CommandOptionsBuilder::AsRoot() {
-    values.account_mode_ = SU_ROOT;
+    if (!PropertiesHelper::IsUnroot()) {
+        values.account_mode_ = SU_ROOT;
+    }
     return *this;
 }
 
 CommandOptions::CommandOptionsBuilder& CommandOptions::CommandOptionsBuilder::AsRootIfAvailable() {
-    if (!PropertiesHelper::IsUserBuild())
-        values.account_mode_ = SU_ROOT;
+    if (!PropertiesHelper::IsUserBuild()) {
+        return AsRoot();
+    }
     return *this;
 }
 
@@ -176,6 +179,7 @@
 
 std::string PropertiesHelper::build_type_ = "";
 int PropertiesHelper::dry_run_ = -1;
+int PropertiesHelper::unroot_ = -1;
 
 bool PropertiesHelper::IsUserBuild() {
     if (build_type_.empty()) {
@@ -191,6 +195,13 @@
     return dry_run_ == 1;
 }
 
+bool PropertiesHelper::IsUnroot() {
+    if (unroot_ == -1) {
+        unroot_ = android::base::GetBoolProperty("dumpstate.unroot", false) ? 1 : 0;
+    }
+    return unroot_ == 1;
+}
+
 int DumpFileToFd(int out_fd, const std::string& title, const std::string& path) {
     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
     if (fd.get() < 0) {
diff --git a/cmds/dumpstate/DumpstateUtil.h b/cmds/dumpstate/DumpstateUtil.h
index 8342099..d69ffbf 100644
--- a/cmds/dumpstate/DumpstateUtil.h
+++ b/cmds/dumpstate/DumpstateUtil.h
@@ -97,9 +97,16 @@
       public:
         /* Sets the command to always run, even on `dry-run` mode. */
         CommandOptionsBuilder& Always();
-        /* Sets the command's PrivilegeMode as `SU_ROOT` */
+        /*
+         * Sets the command's PrivilegeMode as `SU_ROOT` unless overridden by system property
+         * 'dumpstate.unroot'.
+         */
         CommandOptionsBuilder& AsRoot();
-        /* If !IsUserBuild(), sets the command's PrivilegeMode as `SU_ROOT` */
+        /*
+         * Runs AsRoot() on userdebug builds. No-op on user builds since 'su' is
+         * not available. This is used for commands that return some useful information even
+         * when run as shell.
+         */
         CommandOptionsBuilder& AsRootIfAvailable();
         /* Sets the command's PrivilegeMode as `DROP_ROOT` */
         CommandOptionsBuilder& DropRoot();
@@ -162,9 +169,17 @@
      */
     static bool IsDryRun();
 
+    /**
+     * Checks whether root availability should be overridden.
+     *
+     * Useful to verify how dumpstate would work in a device with an user build.
+     */
+    static bool IsUnroot();
+
   private:
     static std::string build_type_;
     static int dry_run_;
+    static int unroot_;
 };
 
 /*
diff --git a/cmds/dumpstate/README.md b/cmds/dumpstate/README.md
index 0302ea5..d5b2953 100644
--- a/cmds/dumpstate/README.md
+++ b/cmds/dumpstate/README.md
@@ -28,22 +28,22 @@
 
 ## To build, deploy, and run unit tests
 
-First create `/data/nativetest`:
+First create `/data/nativetest64`:
 
 ```
-adb shell mkdir /data/nativetest
+adb shell mkdir /data/nativetest64
 ```
 
 Then run:
 
 ```
-mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest/dumpstate_test* /data/nativetest && adb shell /data/nativetest/dumpstate_test/dumpstate_test
+mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest64/dumpstate_test* /data/nativetest64 && adb shell /data/nativetest/dumpstate_test/dumpstate_test
 ```
 
 And to run just one test (for example, `DumpstateTest.RunCommandNoArgs`):
 
 ```
-mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest/dumpstate_test* /data/nativetest && adb shell /data/nativetest/dumpstate_test/dumpstate_test --gtest_filter=DumpstateTest.RunCommandNoArgs
+mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest64/dumpstate_test* /data/nativetest64 && adb shell /data/nativetest/dumpstate_test/dumpstate_test --gtest_filter=DumpstateTest.RunCommandNoArgs
 ```
 
 ## To take quick bugreports
@@ -52,6 +52,12 @@
 adb shell setprop dumpstate.dry_run true
 ```
 
+## To emulate a device with user build
+
+```
+adb shell setprop dumpstate.unroot true
+```
+
 ## To change the `dumpstate` version
 
 ```
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index 68a4f21..9e59f58 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -39,10 +39,27 @@
     IDumpstateToken setListener(@utf8InCpp String name, IDumpstateListener listener,
                                 boolean getSectionDetails);
 
+    // These modes encapsulate a set of run time options for generating bugreports.
+    // A zipped bugreport; default mode.
+    const int BUGREPORT_MODE_FULL = 0;
+
+    // Interactive bugreport, i.e. triggered by the user.
+    const int BUGREPORT_MODE_INTERACTIVE = 1;
+
+    // Remote bugreport triggered by DevicePolicyManager, for e.g.
+    const int BUGREPORT_MODE_REMOTE = 2;
+
+    // Bugreport triggered on a wear device.
+    const int BUGREPORT_MODE_WEAR = 3;
+
+    // Bugreport limited to only telephony info.
+    const int BUGREPORT_MODE_TELEPHONY = 4;
+
+    // Bugreport limited to only wifi info.
+    const int BUGREPORT_MODE_WIFI = 5;
+
     /*
-     * Starts a bugreport in a child process.
-     *
-     * Returns an identifier of the bugreport process running in the background.
+     * Starts a bugreport in the background.
      */
-    int startBugreport(int fd, IDumpstateListener listener, in DumpstateOptions options);
+    int startBugreport(int fd, int bugreportMode);
 }
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 904c0e9..72d1de9 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1917,7 +1917,7 @@
             am_args.push_back("android.intent.extra.SCREENSHOT");
             am_args.push_back(ds.screenshot_path_);
         }
-        if (ds.options_->notification_title.empty()) {
+        if (!ds.options_->notification_title.empty()) {
             am_args.push_back("--es");
             am_args.push_back("android.intent.extra.TITLE");
             am_args.push_back(ds.options_->notification_title);
@@ -1940,44 +1940,103 @@
     }
 }
 
-// TODO: Move away from system properties when we have options passed via binder calls.
-/* Sets runtime options from the system properties and then clears those properties. */
-static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
-    options->extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
-    if (!options->extra_options.empty()) {
-        // Framework uses a system property to override some command-line args.
-        // Currently, it contains the type of the requested bugreport.
-        if (options->extra_options == "bugreportplus") {
+static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
+    switch (mode) {
+        case Dumpstate::BugreportMode::BUGREPORT_FULL:
+            return "BUGREPORT_FULL";
+        case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
+            return "BUGREPORT_INTERACTIVE";
+        case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
+            return "BUGREPORT_REMOTE";
+        case Dumpstate::BugreportMode::BUGREPORT_WEAR:
+            return "BUGREPORT_WEAR";
+        case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
+            return "BUGREPORT_TELEPHONY";
+        case Dumpstate::BugreportMode::BUGREPORT_WIFI:
+            return "BUGREPORT_WIFI";
+    }
+}
+
+static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options) {
+    switch (mode) {
+        case Dumpstate::BugreportMode::BUGREPORT_FULL:
+            options->do_broadcast = true;
+            options->do_fb = true;
+            break;
+        case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
             // Currently, the dumpstate binder is only used by Shell to update progress.
             options->do_start_service = true;
             options->do_progress_updates = true;
             options->do_fb = false;
-        } else if (options->extra_options == "bugreportremote") {
+            options->do_broadcast = true;
+            break;
+        case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
             options->do_vibrate = false;
             options->is_remote_mode = true;
             options->do_fb = false;
-        } else if (options->extra_options == "bugreportwear") {
+            options->do_broadcast = true;
+            break;
+        case Dumpstate::BugreportMode::BUGREPORT_WEAR:
             options->do_start_service = true;
             options->do_progress_updates = true;
             options->do_zip_file = true;
-        } else if (options->extra_options == "bugreporttelephony") {
+            options->do_fb = true;
+            options->do_broadcast = true;
+            break;
+        case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
             options->telephony_only = true;
-        } else if (options->extra_options == "bugreportwifi") {
+            options->do_fb = true;
+            options->do_broadcast = true;
+            break;
+        case Dumpstate::BugreportMode::BUGREPORT_WIFI:
             options->wifi_only = true;
             options->do_zip_file = true;
+            options->do_fb = true;
+            options->do_broadcast = true;
+            break;
+    }
+}
+
+static Dumpstate::BugreportMode getBugreportModeFromProperty() {
+    // If the system property is not set, it's assumed to be a full bugreport.
+    Dumpstate::BugreportMode mode = Dumpstate::BugreportMode::BUGREPORT_FULL;
+
+    std::string extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
+    if (!extra_options.empty()) {
+        // Framework uses a system property to override some command-line args.
+        // Currently, it contains the type of the requested bugreport.
+        if (extra_options == "bugreportplus") {
+            mode = Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE;
+        } else if (extra_options == "bugreportremote") {
+            mode = Dumpstate::BugreportMode::BUGREPORT_REMOTE;
+        } else if (extra_options == "bugreportwear") {
+            mode = Dumpstate::BugreportMode::BUGREPORT_WEAR;
+        } else if (extra_options == "bugreporttelephony") {
+            mode = Dumpstate::BugreportMode::BUGREPORT_TELEPHONY;
+        } else if (extra_options == "bugreportwifi") {
+            mode = Dumpstate::BugreportMode::BUGREPORT_WIFI;
         } else {
-            MYLOGE("Unknown extra option: %s\n", options->extra_options.c_str());
+            MYLOGE("Unknown extra option: %s\n", extra_options.c_str());
         }
         // Reset the property
         android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
     }
+    return mode;
+}
+
+// TODO: Move away from system properties when we have options passed via binder calls.
+/* Sets runtime options from the system properties and then clears those properties. */
+static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
+    Dumpstate::BugreportMode mode = getBugreportModeFromProperty();
+    SetOptionsFromMode(mode, options);
 
     options->notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
     if (!options->notification_title.empty()) {
         // Reset the property
         android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
 
-        options->extra_options = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
+        options->notification_description =
+            android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
         if (!options->notification_description.empty()) {
             // Reset the property
             android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
@@ -1987,6 +2046,40 @@
     }
 }
 
+static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
+    MYLOGI("do_zip_file: %d\n", options.do_zip_file);
+    MYLOGI("do_add_date: %d\n", options.do_add_date);
+    MYLOGI("do_vibrate: %d\n", options.do_vibrate);
+    MYLOGI("use_socket: %d\n", options.use_socket);
+    MYLOGI("use_control_socket: %d\n", options.use_control_socket);
+    MYLOGI("do_fb: %d\n", options.do_fb);
+    MYLOGI("do_broadcast: %d\n", options.do_broadcast);
+    MYLOGI("is_remote_mode: %d\n", options.is_remote_mode);
+    MYLOGI("show_header_only: %d\n", options.show_header_only);
+    MYLOGI("do_start_service: %d\n", options.do_start_service);
+    MYLOGI("telephony_only: %d\n", options.telephony_only);
+    MYLOGI("wifi_only: %d\n", options.wifi_only);
+    MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
+    MYLOGI("use_outfile: %s\n", options.use_outfile.c_str());
+    MYLOGI("extra_options: %s\n", options.extra_options.c_str());
+    MYLOGI("args: %s\n", options.args.c_str());
+    MYLOGI("notification_title: %s\n", options.notification_title.c_str());
+    MYLOGI("notification_description: %s\n", options.notification_description.c_str());
+}
+
+void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode) {
+    // In the new API world, date is always added; output is always a zip file.
+    // TODO(111441001): remove these options once they are obsolete.
+    do_add_date = true;
+    do_zip_file = true;
+
+    // STOPSHIP b/111441001: Remove hardcoded output file path; accept fd.
+    use_outfile = "/data/user_de/0/com.android.shell/files/bugreports/bugreport";
+
+    extra_options = ModeToString(bugreport_mode);
+    SetOptionsFromMode(bugreport_mode, this);
+}
+
 Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
     RunStatus status = RunStatus::OK;
     int c;
@@ -2051,11 +2144,16 @@
     return true;
 }
 
-Dumpstate::RunStatus Dumpstate::RunWithOptions(std::unique_ptr<DumpOptions> options) {
-    if (!options->ValidateOptions()) {
+void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
+    options_ = std::move(options);
+}
+
+Dumpstate::RunStatus Dumpstate::Run() {
+    if (!options_->ValidateOptions()) {
+        MYLOGE("Invalid options specified\n");
+        LogDumpOptions(*options_);
         return RunStatus::INVALID_INPUT;
     }
-    options_ = std::move(options);
     /* set as high priority, and protect from OOM killer */
     setpriority(PRIO_PROCESS, 0, -20);
 
@@ -2277,7 +2375,8 @@
     std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
     Dumpstate::RunStatus status = options->Initialize(argc, argv);
     if (status == Dumpstate::RunStatus::OK) {
-        status = ds.RunWithOptions(std::move(options));
+        ds.SetOptions(std::move(options));
+        status = ds.Run();
     }
 
     switch (status) {
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index c2f7f6a..5e7f71d 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -27,6 +27,7 @@
 
 #include <android-base/macros.h>
 #include <android-base/unique_fd.h>
+#include <android/os/IDumpstate.h>
 #include <android/os/IDumpstateListener.h>
 #include <utils/StrongPointer.h>
 #include <ziparchive/zip_writer.h>
@@ -42,6 +43,9 @@
 // TODO: and then remove explicitly android::os::dumpstate:: prefixes
 namespace android {
 namespace os {
+
+struct DumpstateOptions;
+
 namespace dumpstate {
 
 class DumpstateTest;
@@ -185,6 +189,16 @@
   public:
     enum RunStatus { OK, HELP, INVALID_INPUT, ERROR };
 
+    // The mode under which the bugreport should be run. Each mode encapsulates a few options.
+    enum BugreportMode {
+        BUGREPORT_FULL = android::os::IDumpstate::BUGREPORT_MODE_FULL,
+        BUGREPORT_INTERACTIVE = android::os::IDumpstate::BUGREPORT_MODE_INTERACTIVE,
+        BUGREPORT_REMOTE = android::os::IDumpstate::BUGREPORT_MODE_REMOTE,
+        BUGREPORT_WEAR = android::os::IDumpstate::BUGREPORT_MODE_WEAR,
+        BUGREPORT_TELEPHONY = android::os::IDumpstate::BUGREPORT_MODE_TELEPHONY,
+        BUGREPORT_WIFI = android::os::IDumpstate::BUGREPORT_MODE_WIFI
+    };
+
     static android::os::dumpstate::CommandOptions DEFAULT_DUMPSYS;
 
     static Dumpstate& GetInstance();
@@ -294,8 +308,11 @@
 
     struct DumpOptions;
 
-    /* Main entry point for running a complete bugreport. Takes ownership of options. */
-    RunStatus RunWithOptions(std::unique_ptr<DumpOptions> options);
+    /* Main entry point for running a complete bugreport. */
+    RunStatus Run();
+
+    /* Sets runtime options. */
+    void SetOptions(std::unique_ptr<DumpOptions> options);
 
     // TODO: add other options from DumpState.
     /*
@@ -317,6 +334,7 @@
         // Whether progress updates should be published.
         bool do_progress_updates = false;
         std::string use_outfile;
+        // TODO: rename to MODE.
         // Extra options passed as system property.
         std::string extra_options;
         // Command-line arguments as string
@@ -328,6 +346,9 @@
         /* Initializes options from commandline arguments and system properties. */
         RunStatus Initialize(int argc, char* argv[]);
 
+        /* Initializes options from the requested mode. */
+        void Initialize(BugreportMode bugreport_mode);
+
         /* Returns true if the options set so far are consistent. */
         bool ValidateOptions() const;
     };
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index b675c51..9ca894d 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -85,6 +85,10 @@
         PropertiesHelper::build_type_ = build_type;
     }
 
+    void SetUnroot(bool unroot) const {
+        PropertiesHelper::unroot_ = unroot;
+    }
+
     bool IsStandalone() const {
         return calls_ == 1;
     }
@@ -155,10 +159,11 @@
     };
     // clang-format on
 
-    Dumpstate::DumpOptions options;
     Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
 
     EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+
+    // These correspond to bugreport_mode = full, because that's the default.
     EXPECT_FALSE(options_.do_add_date);
     EXPECT_FALSE(options_.do_zip_file);
     EXPECT_EQ("", options_.use_outfile);
@@ -166,10 +171,10 @@
     EXPECT_FALSE(options_.use_control_socket);
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_TRUE(options_.do_vibrate);
-    EXPECT_FALSE(options_.do_fb);
+    EXPECT_TRUE(options_.do_fb);
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
-    EXPECT_FALSE(options_.do_broadcast);
+    EXPECT_TRUE(options_.do_broadcast);
 }
 
 TEST_F(DumpOptionsTest, InitializePartial1) {
@@ -198,10 +203,10 @@
     // Other options retain default values
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_TRUE(options_.do_vibrate);
-    EXPECT_FALSE(options_.do_fb);
+    EXPECT_TRUE(options_.do_fb);
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
-    EXPECT_FALSE(options_.do_broadcast);
+    EXPECT_TRUE(options_.do_broadcast);
 }
 
 TEST_F(DumpOptionsTest, InitializePartial2) {
@@ -650,6 +655,32 @@
     EXPECT_THAT(err, StrEq("stderr\n"));
 }
 
+TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild_withUnroot) {
+    if (!IsStandalone()) {
+        // TODO: temporarily disabled because it might cause other tests to fail after dropping
+        // to Shell - need to refactor tests to avoid this problem)
+        MYLOGE(
+            "Skipping DumpstateTest.RunCommandAsRootNonUserBuild_withUnroot() "
+            "on test suite\n")
+        return;
+    }
+    if (PropertiesHelper::IsUserBuild()) {
+        ALOGI("Skipping RunCommandAsRootNonUserBuild_withUnroot on user builds\n");
+        return;
+    }
+
+    // Same test as above, but with unroot property set, which will override su availability.
+    SetUnroot(true);
+    DropRoot();
+
+    EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
+                            CommandOptions::WithTimeout(1).AsRoot().Build()));
+
+    // AsRoot is ineffective.
+    EXPECT_THAT(out, StrEq("2000\nstdout\n"));
+    EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
+}
+
 TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnUserBuild) {
     if (!IsStandalone()) {
         // TODO: temporarily disabled because it might cause other tests to fail after dropping
@@ -692,6 +723,32 @@
     EXPECT_THAT(err, StrEq("stderr\n"));
 }
 
+TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild_withUnroot) {
+    if (!IsStandalone()) {
+        // TODO: temporarily disabled because it might cause other tests to fail after dropping
+        // to Shell - need to refactor tests to avoid this problem)
+        MYLOGE(
+            "Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild_withUnroot() "
+            "on test suite\n")
+        return;
+    }
+    if (PropertiesHelper::IsUserBuild()) {
+        ALOGI("Skipping RunCommandAsRootIfAvailableOnDebugBuild_withUnroot on user builds\n");
+        return;
+    }
+    // Same test as above, but with unroot property set, which will override su availability.
+    SetUnroot(true);
+
+    DropRoot();
+
+    EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
+                            CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
+
+    // It's a userdebug build, so "su root" should be available, but unroot=true overrides it.
+    EXPECT_THAT(out, StrEq("2000\nstdout\n"));
+    EXPECT_THAT(err, StrEq("stderr\n"));
+}
+
 TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) {
     EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
     EXPECT_THAT(out,
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 4ad5c4b..6cbb691 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -82,8 +82,12 @@
 
 CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
 
+// TODO(111441001): Default DumpOptions to sensible values.
 Dumpstate::Dumpstate(const std::string& version)
-    : pid_(getpid()), version_(version), now_(time(nullptr)) {
+    : pid_(getpid()),
+      options_(new Dumpstate::DumpOptions()),
+      version_(version),
+      now_(time(nullptr)) {
 }
 
 Dumpstate& Dumpstate::GetInstance() {
diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h
index 11bb721..1ef8986 100644
--- a/include/input/IInputFlinger.h
+++ b/include/input/IInputFlinger.h
@@ -22,6 +22,9 @@
 
 #include <binder/IInterface.h>
 
+#include <utils/Vector.h>
+#include <input/InputWindow.h>
+
 namespace android {
 
 /*
@@ -31,6 +34,8 @@
 class IInputFlinger : public IInterface {
 public:
     DECLARE_META_INTERFACE(InputFlinger)
+
+    virtual void setInputWindows(const Vector<InputWindowInfo>& inputHandles) = 0;
 };
 
 
@@ -40,7 +45,7 @@
 class BnInputFlinger : public BnInterface<IInputFlinger> {
 public:
     enum {
-        DO_SOMETHING_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+        SET_INPUT_WINDOWS_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
     };
 
     virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/include/input/Input.h b/include/input/Input.h
index 819a89f..d35354b 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -17,6 +17,8 @@
 #ifndef _LIBINPUT_INPUT_H
 #define _LIBINPUT_INPUT_H
 
+#pragma GCC system_header
+
 /**
  * Native input event structures.
  */
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 4782c9b..d906db3 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -17,6 +17,8 @@
 #ifndef _LIBINPUT_INPUT_TRANSPORT_H
 #define _LIBINPUT_INPUT_TRANSPORT_H
 
+#pragma GCC system_header
+
 /**
  * Native input transport.
  *
@@ -29,6 +31,7 @@
 
 #include <string>
 
+#include <binder/IBinder.h>
 #include <input/Input.h>
 #include <utils/Errors.h>
 #include <utils/Timers.h>
@@ -188,11 +191,16 @@
     status_t write(Parcel& out) const;
     status_t read(const Parcel& from);
 
+    sp<IBinder> getToken() const;
+    void setToken(const sp<IBinder>& token);
+
 private:
     void setFd(int fd);
 
     std::string mName;
     int mFd = -1;
+
+    sp<IBinder> mToken = nullptr;
 };
 
 /*
diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h
index 7c284dd..9e3d334 100644
--- a/include/input/InputWindow.h
+++ b/include/input/InputWindow.h
@@ -33,6 +33,9 @@
  * Describes the properties of a window that can receive input.
  */
 struct InputWindowInfo {
+    InputWindowInfo() = default;
+    InputWindowInfo(const Parcel& from);
+
     // Window flags from WindowManager.LayoutParams
     enum {
         FLAG_ALLOW_LOCK_WHILE_SCREEN_ON     = 0x00000001,
@@ -168,17 +171,17 @@
     const sp<InputApplicationHandle> inputApplicationHandle;
 
     inline const InputWindowInfo* getInfo() const {
-        return mInfo;
+        return &mInfo;
     }
 
     sp<InputChannel> getInputChannel() const;
 
     inline std::string getName() const {
-        return mInfo ? mInfo->name : "<invalid>";
+        return mInfo.inputChannel ? mInfo.name : "<invalid>";
     }
 
     inline nsecs_t getDispatchingTimeout(nsecs_t defaultValue) const {
-        return mInfo ? mInfo->dispatchingTimeout : defaultValue;
+        return mInfo.inputChannel? mInfo.dispatchingTimeout : defaultValue;
     }
 
     /**
@@ -193,16 +196,16 @@
     virtual bool updateInfo() = 0;
 
     /**
-     * Releases the storage used by the associated information when it is
+     * Releases the channel used by the associated information when it is
      * no longer needed.
      */
-    void releaseInfo();
+    void releaseChannel();
 
 protected:
     explicit InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle);
     virtual ~InputWindowHandle();
 
-    InputWindowInfo* mInfo;
+    InputWindowInfo mInfo;
 };
 
 } // namespace android
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 7a47724..f0c21f5 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -387,23 +387,28 @@
     return mStrictModePolicy;
 }
 
-uid_t IPCThreadState::setWorkSource(uid_t uid)
+int64_t IPCThreadState::setCallingWorkSourceUid(uid_t uid)
 {
-    uid_t returnValue = mWorkSource;
+    // Note: we currently only use half of the int64. We return an int64 for extensibility.
+    int64_t token = mWorkSource;
     mWorkSource = uid;
-    return returnValue;
+    return token;
 }
 
-uid_t IPCThreadState::getWorkSource() const
+uid_t IPCThreadState::getCallingWorkSourceUid() const
 {
     return mWorkSource;
 }
 
-uid_t IPCThreadState::clearWorkSource()
+int64_t IPCThreadState::clearCallingWorkSource()
 {
-    uid_t returnValue = mWorkSource;
-    mWorkSource = kUnsetWorkSource;
-    return returnValue;
+    return setCallingWorkSourceUid(kUnsetWorkSource);
+}
+
+void IPCThreadState::restoreCallingWorkSource(int64_t token)
+{
+    uid_t uid = (int)token;
+    setCallingWorkSourceUid(uid);
 }
 
 void IPCThreadState::setLastTransactionBinderFlags(int32_t flags)
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index bc1a71c..643f428 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -601,7 +601,7 @@
 {
     writeInt32(IPCThreadState::self()->getStrictModePolicy() |
                STRICT_MODE_PENALTY_GATHER);
-    writeInt32(IPCThreadState::self()->getWorkSource());
+    writeInt32(IPCThreadState::self()->getCallingWorkSourceUid());
     // currently the interface identification token is just its name as a string
     return writeString16(interface);
 }
@@ -631,7 +631,7 @@
     }
     // WorkSource.
     int32_t workSource = readInt32();
-    threadState->setWorkSource(workSource);
+    threadState->setCallingWorkSourceUid(workSource);
     // Interface descriptor.
     const String16 str(readString16());
     if (str == interface) {
@@ -2245,8 +2245,30 @@
     int32_t hasComm = readInt32();
     int fd = readFileDescriptor();
     if (hasComm != 0) {
-        // skip
-        readFileDescriptor();
+        // detach (owned by the binder driver)
+        int comm = readFileDescriptor();
+
+        // warning: this must be kept in sync with:
+        // frameworks/base/core/java/android/os/ParcelFileDescriptor.java
+        enum ParcelFileDescriptorStatus {
+            DETACHED = 2,
+        };
+
+#if BYTE_ORDER == BIG_ENDIAN
+        const int32_t message = ParcelFileDescriptorStatus::DETACHED;
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN
+        const int32_t message = __builtin_bswap32(ParcelFileDescriptorStatus::DETACHED);
+#endif
+
+        ssize_t written = TEMP_FAILURE_RETRY(
+            ::write(comm, &message, sizeof(message)));
+
+        if (written == -1 || written != sizeof(message)) {
+            ALOGW("Failed to detach ParcelFileDescriptor written: %zd err: %s",
+                written, strerror(errno));
+            return BAD_TYPE;
+        }
     }
     return fd;
 }
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 5888e14..de126d5 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -47,12 +47,14 @@
             void                setStrictModePolicy(int32_t policy);
             int32_t             getStrictModePolicy() const;
 
-            // See Binder#setThreadWorkSource in Binder.java.
-            uid_t               setWorkSource(uid_t uid);
-            // See Binder#getThreadWorkSource in Binder.java.
-            uid_t               getWorkSource() const;
-            // See Binder#clearThreadWorkSource in Binder.java.
-            uid_t               clearWorkSource();
+            // See Binder#setCallingWorkSourceUid in Binder.java.
+            int64_t             setCallingWorkSourceUid(uid_t uid);
+            // See Binder#getCallingWorkSourceUid in Binder.java.
+            uid_t               getCallingWorkSourceUid() const;
+            // See Binder#clearCallingWorkSource in Binder.java.
+            int64_t             clearCallingWorkSource();
+            // See Binder#restoreCallingWorkSource in Binder.java.
+            void                restoreCallingWorkSource(int64_t token);
 
             void                setLastTransactionBinderFlags(int32_t flags);
             int32_t             getLastTransactionBinderFlags() const;
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index d16502f..14ce4cb 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -39,6 +39,8 @@
         "libutils",
     ],
 
+    cpp_std: "c++17",
+
     version_script: "libbinder_ndk.map.txt",
 }
 
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index f3fb9c3..f9c8c8a 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -22,6 +22,7 @@
 #include "status_internal.h"
 
 #include <android-base/logging.h>
+#include <binder/IPCThreadState.h>
 
 using DeathRecipient = ::android::IBinder::DeathRecipient;
 
@@ -346,6 +347,14 @@
     return recipient->unlinkToDeath(binder, cookie);
 }
 
+uid_t AIBinder_getCallingUid() {
+    return ::android::IPCThreadState::self()->getCallingUid();
+}
+
+pid_t AIBinder_getCallingPid() {
+    return ::android::IPCThreadState::self()->getCallingPid();
+}
+
 void AIBinder_incStrong(AIBinder* binder) {
     if (binder == nullptr) {
         LOG(ERROR) << __func__ << ": on null binder";
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 5c26039..e2c0cfa 100644
--- a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -198,6 +198,11 @@
      * See AStatus_isOk.
      */
     bool isOk() { return get() != nullptr && AStatus_isOk(get()); }
+
+    /**
+     * Convenience method for okay status.
+     */
+    static ScopedAStatus ok() { return ScopedAStatus(AStatus_newOk()); }
 };
 
 /**
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index d711ad8..9c6c55e 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -28,6 +28,7 @@
 
 #include <stdint.h>
 #include <sys/cdefs.h>
+#include <sys/types.h>
 
 #include <android/binder_parcel.h>
 #include <android/binder_status.h>
@@ -270,6 +271,31 @@
                                        void* cookie) __INTRODUCED_IN(29);
 
 /**
+ * This returns the calling UID assuming that this thread is called from a thread that is processing
+ * a binder transaction (for instance, in the implementation of AIBinder_Class_onTransact).
+ *
+ * This can be used with higher-level system services to determine the caller's identity and check
+ * permissions.
+ *
+ * \return calling uid or the current process's UID if this thread isn't processing a transaction.
+ */
+uid_t AIBinder_getCallingUid();
+
+/**
+ * This returns the calling PID assuming that this thread is called from a thread that is processing
+ * a binder transaction (for instance, in the implementation of AIBinder_Class_onTransact).
+ *
+ * This can be used with higher-level system services to determine the caller's identity and check
+ * permissions. However, when doing this, one should be aware of possible TOCTOU problems when the
+ * calling process dies and is replaced with another process with elevated permissions and the same
+ * PID.
+ *
+ * \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();
+
+/**
  * This can only be called if a strong reference to this object already exists in process.
  *
  * \param binder the binder object to add a refcount to.
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index 4ee1b67..3594349 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -55,9 +55,9 @@
 
 /**
  * This is called to allocate a buffer for a C-style string (null-terminated). The returned buffer
- * should be at least length bytes. This includes space for a null terminator. length will always be
- * strictly less than or equal to the maximum size that can be held in a size_t and will always be
- * greater than 0.
+ * should be at least length bytes. This includes space for a null terminator. For a string, length
+ * will always be strictly less than or equal to the maximum size that can be held in a size_t and
+ * will always be greater than 0. However, if a 'null' string is being read, length will be -1.
  *
  * See also AParcel_readString.
  *
@@ -65,31 +65,35 @@
  *
  * \param stringData some external representation of a string
  * \param length the length of the buffer needed to fill (including the null-terminator)
+ * \param buffer a buffer of size 'length' or null if allocation failed.
  *
- * \return a buffer of size 'length' or null if allocation failed.
+ * \return true if the allocation succeeded, false otherwise. If length is -1, a true return here
+ * means that a 'null' value (or equivalent) was successfully stored.
  */
-typedef char* (*AParcel_stringAllocator)(void* stringData, size_t length);
+typedef bool (*AParcel_stringAllocator)(void* stringData, int32_t length, char** buffer);
 
 /**
- * This is called to allocate an array of size 'length'.
+ * This is called to allocate an array of size 'length'. If length is -1, then a 'null' array (or
+ * equivalent) should be created.
  *
  * See also AParcel_readStringArray
  *
  * \param arrayData some external representation of an array
  * \param length the length to allocate this array to
  *
- * \return true if allocation succeeded
+ * \return true if allocation succeeded. If length is -1, a true return here means that a 'null'
+ * value (or equivalent) was successfully stored.
  */
-typedef bool (*AParcel_stringArrayAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_stringArrayAllocator)(void* arrayData, int32_t length);
 
 /**
  * This is called to allocate a string inside of an array that was allocated by an
  * AParcel_stringArrayAllocator.
  *
  * The index returned will always be within the range [0, length of arrayData). The returned buffer
- * should be at least length bytes. This includes space for a null-terminator. length will always be
- * strictly less than or equal to the maximum size that can be held in a size_t and will always be
- * greater than 0.
+ * should be at least length bytes. This includes space for a null-terminator. For a string, length
+ * will always be strictly less than or equal to the maximum size that can be held in a size_t and
+ * will always be greater than 0. However, if a 'null' string is being read, length will be -1.
  *
  * See also AParcel_readStringArray
  *
@@ -97,10 +101,13 @@
  * \param index the index at which a string should be allocated.
  * \param length the length of the string to be allocated at this index. See also
  * AParcel_stringAllocator. This includes the length required for a null-terminator.
+ * \param buffer a buffer of size 'length' or null if allocation failed.
  *
- * \return a buffer of size 'length' or null if allocation failed.
+ * \return true if the allocation succeeded, false otherwise. If length is -1, a true return here
+ * means that a 'null' value (or equivalent) was successfully stored.
  */
-typedef char* (*AParcel_stringArrayElementAllocator)(void* arrayData, size_t index, size_t length);
+typedef bool (*AParcel_stringArrayElementAllocator)(void* arrayData, size_t index, int32_t length,
+                                                    char** buffer);
 
 /**
  * This returns the length and buffer of an array at a specific index in an arrayData object.
@@ -110,10 +117,11 @@
  * \param arrayData some external representation of an array.
  * \param index the index at which a string should be allocated.
  * \param outLength an out parameter for the length of the string at the specified index. This
- * should not include the length for a null-terminator if there is one.
+ * should not include the length for a null-terminator if there is one. If the object at this index
+ * is 'null', then this should be set to -1.
  *
  * \param a buffer of size outLength or more representing the string at the provided index. This is
- * not required to be null-terminated.
+ * not required to be null-terminated. If the object at index is null, then this should be null.
  */
 typedef const char* (*AParcel_stringArrayElementGetter)(const void* arrayData, size_t index,
                                                         size_t* outLength);
@@ -124,109 +132,127 @@
  *
  * The implementation of this function should allocate a contiguous array of size 'length' and
  * return that underlying buffer to be filled out. If there is an error or length is 0, null may be
- * returned.
+ * returned. If length is -1, this should allocate some representation of a null array.
  *
  * See also AParcel_readInt32Array
  *
  * \param arrayData some external representation of an array of int32_t.
  * \param length the length to allocate arrayData to.
+ * \param outBuffer a buffer of int32_t of size 'length' (if length is >= 0, if length is 0, this
+ * may be nullptr).
  *
- * \return a buffer of int32_t of size 'length'.
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
  */
-typedef int32_t* (*AParcel_int32ArrayAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_int32ArrayAllocator)(void* arrayData, int32_t length, int32_t** outBuffer);
 
 /**
  * This is called to get the underlying data from an arrayData object.
  *
  * The implementation of this function should allocate a contiguous array of size 'length' and
  * return that underlying buffer to be filled out. If there is an error or length is 0, null may be
- * returned.
+ * returned. If length is -1, this should allocate some representation of a null array.
  *
  * See also AParcel_readUint32Array
  *
  * \param arrayData some external representation of an array of uint32_t.
  * \param length the length to allocate arrayData to.
+ * \param outBuffer a buffer of uint32_t of size 'length' (if length is >= 0, if length is 0, this
+ * may be nullptr).
  *
- * \return a buffer of uint32_t of size 'length'.
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
  */
-typedef uint32_t* (*AParcel_uint32ArrayAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_uint32ArrayAllocator)(void* arrayData, int32_t length, uint32_t** outBuffer);
 
 /**
  * This is called to get the underlying data from an arrayData object.
  *
  * The implementation of this function should allocate a contiguous array of size 'length' and
  * return that underlying buffer to be filled out. If there is an error or length is 0, null may be
- * returned.
+ * returned. If length is -1, this should allocate some representation of a null array.
  *
  * See also AParcel_readInt64Array
  *
  * \param arrayData some external representation of an array of int64_t.
  * \param length the length to allocate arrayData to.
+ * \param outBuffer a buffer of int64_t of size 'length' (if length is >= 0, if length is 0, this
+ * may be nullptr).
  *
- * \return a buffer of int64_t of size 'length'.
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
  */
-typedef int64_t* (*AParcel_int64ArrayAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_int64ArrayAllocator)(void* arrayData, int32_t length, int64_t** outBuffer);
 
 /**
  * This is called to get the underlying data from an arrayData object.
  *
  * The implementation of this function should allocate a contiguous array of size 'length' and
  * return that underlying buffer to be filled out. If there is an error or length is 0, null may be
- * returned.
+ * returned. If length is -1, this should allocate some representation of a null array.
  *
  * See also AParcel_readUint64Array
  *
  * \param arrayData some external representation of an array of uint64_t.
  * \param length the length to allocate arrayData to.
+ * \param outBuffer a buffer of uint64_t of size 'length' (if length is >= 0, if length is 0, this
+ * may be nullptr).
  *
- * \return a buffer of uint64_t of size 'length'.
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
  */
-typedef uint64_t* (*AParcel_uint64ArrayAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_uint64ArrayAllocator)(void* arrayData, int32_t length, uint64_t** outBuffer);
 
 /**
  * This is called to get the underlying data from an arrayData object.
  *
  * The implementation of this function should allocate a contiguous array of size 'length' and
  * return that underlying buffer to be filled out. If there is an error or length is 0, null may be
- * returned.
+ * returned. If length is -1, this should allocate some representation of a null array.
  *
  * See also AParcel_readFloatArray
  *
  * \param arrayData some external representation of an array of float.
  * \param length the length to allocate arrayData to.
+ * \param outBuffer a buffer of float of size 'length' (if length is >= 0, if length is 0, this may
+ * be nullptr).
  *
- * \return a buffer of float of size 'length'.
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
  */
-typedef float* (*AParcel_floatArrayAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_floatArrayAllocator)(void* arrayData, int32_t length, float** outBuffer);
 
 /**
  * This is called to get the underlying data from an arrayData object.
  *
  * The implementation of this function should allocate a contiguous array of size 'length' and
  * return that underlying buffer to be filled out. If there is an error or length is 0, null may be
- * returned.
+ * returned. If length is -1, this should allocate some representation of a null array.
  *
  * See also AParcel_readDoubleArray
  *
  * \param arrayData some external representation of an array of double.
  * \param length the length to allocate arrayData to.
+ * \param outBuffer a buffer of double of size 'length' (if length is >= 0, if length is 0, this may
+ * be nullptr).
  *
- * \return a buffer of double of size 'length'.
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
  */
-typedef double* (*AParcel_doubleArrayAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_doubleArrayAllocator)(void* arrayData, int32_t length, double** outBuffer);
 
 /**
  * This allocates an array of size 'length' inside of arrayData and returns whether or not there was
- * a success.
+ * a success. If length is -1, then this should allocate some representation of a null array.
  *
  * See also AParcel_readBoolArray
  *
  * \param arrayData some external representation of an array of bool.
- * \param length the length to allocate arrayData to.
+ * \param length the length to allocate arrayData to (or -1 if this represents a null array).
  *
  * \return whether the allocation succeeded.
  */
-typedef bool (*AParcel_boolArrayAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_boolArrayAllocator)(void* arrayData, int32_t length);
 
 /**
  * This is called to get the underlying data from an arrayData object at index.
@@ -256,32 +282,38 @@
  *
  * The implementation of this function should allocate a contiguous array of size 'length' and
  * return that underlying buffer to be filled out. If there is an error or length is 0, null may be
- * returned.
+ * returned. If length is -1, this should allocate some representation of a null array.
  *
  * See also AParcel_readCharArray
  *
  * \param arrayData some external representation of an array of char16_t.
  * \param length the length to allocate arrayData to.
+ * \param outBuffer a buffer of char16_t of size 'length' (if length is >= 0, if length is 0, this
+ * may be nullptr).
  *
- * \return a buffer of char16_t of size 'length'.
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
  */
-typedef char16_t* (*AParcel_charArrayAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_charArrayAllocator)(void* arrayData, int32_t length, char16_t** outBuffer);
 
 /**
  * This is called to get the underlying data from an arrayData object.
  *
  * The implementation of this function should allocate a contiguous array of size 'length' and
  * return that underlying buffer to be filled out. If there is an error or length is 0, null may be
- * returned.
+ * returned. If length is -1, this should allocate some representation of a null array.
  *
  * See also AParcel_readByteArray
  *
  * \param arrayData some external representation of an array of int8_t.
  * \param length the length to allocate arrayData to.
+ * \param outBuffer a buffer of int8_t of size 'length' (if length is >= 0, if length is 0, this may
+ * be nullptr).
  *
- * \return a buffer of int8_t of size 'length'.
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
  */
-typedef int8_t* (*AParcel_byteArrayAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_byteArrayAllocator)(void* arrayData, int32_t length, int8_t** outBuffer);
 
 // @END-PRIMITIVE-VECTOR-GETTERS
 
@@ -297,12 +329,11 @@
 binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) __INTRODUCED_IN(29);
 
 /**
- * Reads an AIBinder from the next location in a non-null parcel. This will fail if the binder is
- * non-null. One strong ref-count of ownership is passed to the caller of this function.
+ * 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.
  *
  * \param parcel the parcel to read from.
- * \param binder the out parameter for what is read from the parcel. This will not be null on
- * success.
+ * \param binder the out parameter for what is read from the parcel. This may be null.
  *
  * \return STATUS_OK on successful write.
  */
@@ -310,26 +341,13 @@
         __INTRODUCED_IN(29);
 
 /**
- * Reads an AIBinder from the next location in a non-null parcel. This may read a null. One strong
- * ref-count of ownership is passed to the caller of this function.
- *
- * \param parcel the parcel to read from.
- * \param binder the out parameter for what is read from the parcel. This may be null even on
- * success.
- *
- * \return STATUS_OK on successful write.
- */
-binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder)
-        __INTRODUCED_IN(29);
-
-/**
  * Writes a file descriptor to the next location in a non-null parcel. This does not take ownership
  * of fd.
  *
  * This corresponds to the SDK's android.os.ParcelFileDescriptor.
  *
  * \param parcel the parcel to write to.
- * \param fd the value to write to the parcel.
+ * \param fd the value to write to the parcel (-1 to represent a null ParcelFileDescriptor).
  *
  * \return STATUS_OK on successful write.
  */
@@ -343,7 +361,8 @@
  * This corresponds to the SDK's android.os.ParcelFileDescriptor.
  *
  * \param parcel the parcel to read from.
- * \param binder the out parameter for what is read from the parcel.
+ * \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.
  */
@@ -381,13 +400,15 @@
 /**
  * Writes utf-8 string value to the next location in a non-null parcel.
  *
+ * If length is -1, and string is nullptr, this will write a 'null' string to the parcel.
+ *
  * \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.
  *
  * \return STATUS_OK on successful write.
  */
-binder_status_t AParcel_writeString(AParcel* parcel, const char* string, size_t length)
+binder_status_t AParcel_writeString(AParcel* parcel, const char* string, int32_t length)
         __INTRODUCED_IN(29);
 
 /**
@@ -395,7 +416,8 @@
  *
  * Data is passed to the string allocator once the string size is known. This size includes the
  * space for the null-terminator of this string. This allocator returns a buffer which is used as
- * the output buffer from this read.
+ * the output buffer from this read. If there is a 'null' string on the binder buffer, the allocator
+ * will be called with length -1.
  *
  * \param parcel the parcel to read from.
  * \param stringData some external representation of a string.
@@ -411,7 +433,8 @@
  *
  * length is the length of the array. AParcel_stringArrayElementGetter will be called for all
  * indices in range [0, length) with the arrayData provided here. The string length and buffer
- * returned from this function will be used to fill out the data from the parcel.
+ * 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.
  *
  * \param parcel the parcel to write to.
  * \param arrayData some external representation of an array.
@@ -421,7 +444,7 @@
  *
  * \return STATUS_OK on successful write.
  */
-binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, size_t length,
+binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, int32_t length,
                                          AParcel_stringArrayElementGetter getter)
         __INTRODUCED_IN(29);
 
@@ -432,7 +455,8 @@
  * length is the length of the array to be read from the parcel. Then, for each index i in [0,
  * length), AParcel_stringArrayElementAllocator will be called with the length of the string to be
  * read from the parcel. The resultant buffer from each of these calls will be filled according to
- * the contents of the string that is read.
+ * 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.
  *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
@@ -633,72 +657,72 @@
  * Writes an array of int32_t to the next location in a non-null parcel.
  *
  * \param parcel the parcel to write to.
- * \param arrayData an array of size 'length'.
- * \param length the length of arrayData.
+ * \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.
  *
  * \return STATUS_OK on successful write.
  */
-binder_status_t AParcel_writeInt32Array(AParcel* parcel, const int32_t* arrayData, size_t length)
+binder_status_t AParcel_writeInt32Array(AParcel* parcel, const int32_t* arrayData, int32_t length)
         __INTRODUCED_IN(29);
 
 /**
  * Writes an array of uint32_t to the next location in a non-null parcel.
  *
  * \param parcel the parcel to write to.
- * \param arrayData an array of size 'length'.
- * \param length the length of arrayData.
+ * \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.
  *
  * \return STATUS_OK on successful write.
  */
-binder_status_t AParcel_writeUint32Array(AParcel* parcel, const uint32_t* arrayData, size_t length)
+binder_status_t AParcel_writeUint32Array(AParcel* parcel, const uint32_t* arrayData, int32_t length)
         __INTRODUCED_IN(29);
 
 /**
  * Writes an array of int64_t to the next location in a non-null parcel.
  *
  * \param parcel the parcel to write to.
- * \param arrayData an array of size 'length'.
- * \param length the length of arrayData.
+ * \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.
  *
  * \return STATUS_OK on successful write.
  */
-binder_status_t AParcel_writeInt64Array(AParcel* parcel, const int64_t* arrayData, size_t length)
+binder_status_t AParcel_writeInt64Array(AParcel* parcel, const int64_t* arrayData, int32_t length)
         __INTRODUCED_IN(29);
 
 /**
  * Writes an array of uint64_t to the next location in a non-null parcel.
  *
  * \param parcel the parcel to write to.
- * \param arrayData an array of size 'length'.
- * \param length the length of arrayData.
+ * \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.
  *
  * \return STATUS_OK on successful write.
  */
-binder_status_t AParcel_writeUint64Array(AParcel* parcel, const uint64_t* arrayData, size_t length)
+binder_status_t AParcel_writeUint64Array(AParcel* parcel, const uint64_t* arrayData, int32_t length)
         __INTRODUCED_IN(29);
 
 /**
  * Writes an array of float to the next location in a non-null parcel.
  *
  * \param parcel the parcel to write to.
- * \param arrayData an array of size 'length'.
- * \param length the length of arrayData.
+ * \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.
  *
  * \return STATUS_OK on successful write.
  */
-binder_status_t AParcel_writeFloatArray(AParcel* parcel, const float* arrayData, size_t length)
+binder_status_t AParcel_writeFloatArray(AParcel* parcel, const float* arrayData, int32_t length)
         __INTRODUCED_IN(29);
 
 /**
  * Writes an array of double to the next location in a non-null parcel.
  *
  * \param parcel the parcel to write to.
- * \param arrayData an array of size 'length'.
- * \param length the length of arrayData.
+ * \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.
  *
  * \return STATUS_OK on successful write.
  */
-binder_status_t AParcel_writeDoubleArray(AParcel* parcel, const double* arrayData, size_t length)
+binder_status_t AParcel_writeDoubleArray(AParcel* parcel, const double* arrayData, int32_t length)
         __INTRODUCED_IN(29);
 
 /**
@@ -709,36 +733,36 @@
  *
  * \param parcel the parcel to write to.
  * \param arrayData some external representation of an array.
- * \param length the length of arrayData.
+ * \param length the length of arrayData (or -1 if this represents a null array).
  * \param getter the callback to retrieve data at specific locations in the array.
  *
  * \return STATUS_OK on successful write.
  */
-binder_status_t AParcel_writeBoolArray(AParcel* parcel, const void* arrayData, size_t length,
+binder_status_t AParcel_writeBoolArray(AParcel* parcel, const void* arrayData, int32_t length,
                                        AParcel_boolArrayGetter getter) __INTRODUCED_IN(29);
 
 /**
  * Writes an array of char16_t to the next location in a non-null parcel.
  *
  * \param parcel the parcel to write to.
- * \param arrayData an array of size 'length'.
- * \param length the length of arrayData.
+ * \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.
  *
  * \return STATUS_OK on successful write.
  */
-binder_status_t AParcel_writeCharArray(AParcel* parcel, const char16_t* arrayData, size_t length)
+binder_status_t AParcel_writeCharArray(AParcel* parcel, const char16_t* arrayData, int32_t length)
         __INTRODUCED_IN(29);
 
 /**
  * Writes an array of int8_t to the next location in a non-null parcel.
  *
  * \param parcel the parcel to write to.
- * \param arrayData an array of size 'length'.
- * \param length the length of arrayData.
+ * \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.
  *
  * \return STATUS_OK on successful write.
  */
-binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* arrayData, size_t length)
+binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* arrayData, int32_t length)
         __INTRODUCED_IN(29);
 
 /**
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
index 2ccbe5a..f99c3a9 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
@@ -26,8 +26,10 @@
 
 #pragma once
 
+#include <android/binder_auto_utils.h>
 #include <android/binder_parcel.h>
 
+#include <optional>
 #include <string>
 #include <vector>
 
@@ -37,12 +39,37 @@
  * This retrieves and allocates a vector to size 'length' and returns the underlying buffer.
  */
 template <typename T>
-static inline T* AParcel_stdVectorAllocator(void* vectorData, size_t length) {
+static inline bool AParcel_stdVectorAllocator(void* vectorData, int32_t length, T** outBuffer) {
+    if (length < 0) return false;
+
     std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
-    if (length > vec->max_size()) return nullptr;
+    if (length > vec->max_size()) return false;
 
     vec->resize(length);
-    return vec->data();
+    *outBuffer = vec->data();
+    return true;
+}
+
+/**
+ * This retrieves and allocates a vector to size 'length' and returns the underlying buffer.
+ */
+template <typename T>
+static inline bool AParcel_nullableStdVectorAllocator(void* vectorData, int32_t length,
+                                                      T** outBuffer) {
+    std::optional<std::vector<T>>* vec = static_cast<std::optional<std::vector<T>>*>(vectorData);
+
+    if (length < 0) {
+        *vec = std::nullopt;
+        return true;
+    }
+
+    *vec = std::optional<std::vector<T>>(std::vector<T>{});
+
+    if (length > (*vec)->max_size()) return false;
+    (*vec)->resize(length);
+
+    *outBuffer = (*vec)->data();
+    return true;
 }
 
 /**
@@ -50,13 +77,16 @@
  *
  * See also AParcel_stdVectorAllocator. Types used with this allocator have their sizes defined
  * externally with respect to the NDK, and that size information is not passed into the NDK.
- * Instead, it is used in cases where callbacks are used.
+ * Instead, it is used in cases where callbacks are used. Note that when this allocator is used,
+ * null arrays are not supported.
  *
  * See AParcel_readVector(const AParcel* parcel, std::vector<bool>)
  * See AParcel_readVector(const AParcel* parcel, std::vector<std::string>)
  */
 template <typename T>
-static inline bool AParcel_stdVectorExternalAllocator(void* vectorData, size_t length) {
+static inline bool AParcel_stdVectorExternalAllocator(void* vectorData, int32_t length) {
+    if (length < 0) return false;
+
     std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
     if (length > vec->max_size()) return false;
 
@@ -65,6 +95,34 @@
 }
 
 /**
+ * This allocates a vector to size 'length' and returns whether the allocation is successful.
+ *
+ * See also AParcel_stdVectorAllocator. Types used with this allocator have their sizes defined
+ * externally with respect to the NDK, and that size information is not passed into the NDK.
+ * Instead, it is used in cases where callbacks are used. Note, when this allocator is used,
+ * the vector itself can be nullable.
+ *
+ * See AParcel_readVector(const AParcel* parcel,
+ * std::optional<std::vector<std::optional<std::string>>>)
+ */
+template <typename T>
+static inline bool AParcel_nullableStdVectorExternalAllocator(void* vectorData, int32_t length) {
+    std::optional<std::vector<T>>* vec = static_cast<std::optional<std::vector<T>>*>(vectorData);
+
+    if (length < 0) {
+        *vec = std::nullopt;
+        return true;
+    }
+
+    *vec = std::optional<std::vector<T>>(std::vector<T>{});
+
+    if (length > (*vec)->max_size()) return false;
+    (*vec)->resize(length);
+
+    return true;
+}
+
+/**
  * This retrieves the underlying value in a vector which may not be contiguous at index from a
  * corresponding vectorData.
  */
@@ -84,166 +142,156 @@
     (*vec)[index] = value;
 }
 
-// @START
 /**
- * Writes a vector of int32_t to the next location in a non-null parcel.
+ * This sets the underlying value in a corresponding vectorData which may not be contiguous at
+ * index.
  */
-inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int32_t>& vec) {
-    return AParcel_writeInt32Array(parcel, vec.data(), vec.size());
+template <typename T>
+static inline void AParcel_nullableStdVectorSetter(void* vectorData, size_t index, T value) {
+    std::optional<std::vector<T>>* vec = static_cast<std::optional<std::vector<T>>*>(vectorData);
+    vec->value()[index] = value;
 }
 
 /**
- * Reads a vector of int32_t from the next location in a non-null parcel.
+ * Convenience method to write a nullable strong binder.
  */
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int32_t>* vec) {
-    void* vectorData = static_cast<void*>(vec);
-    return AParcel_readInt32Array(parcel, vectorData, AParcel_stdVectorAllocator<int32_t>);
+static inline binder_status_t AParcel_writeNullableStrongBinder(AParcel* parcel,
+                                                                const SpAIBinder& binder) {
+    return AParcel_writeStrongBinder(parcel, binder.get());
 }
 
 /**
- * Writes a vector of uint32_t to the next location in a non-null parcel.
+ * Convenience method to read a nullable strong binder.
  */
-inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint32_t>& vec) {
-    return AParcel_writeUint32Array(parcel, vec.data(), vec.size());
+static inline binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel,
+                                                               SpAIBinder* binder) {
+    AIBinder* readBinder;
+    binder_status_t status = AParcel_readStrongBinder(parcel, &readBinder);
+    if (status == STATUS_OK) {
+        binder->set(readBinder);
+    }
+    return status;
 }
 
 /**
- * Reads a vector of uint32_t from the next location in a non-null parcel.
+ * Convenience method to write a strong binder but return an error if it is null.
  */
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint32_t>* vec) {
-    void* vectorData = static_cast<void*>(vec);
-    return AParcel_readUint32Array(parcel, vectorData, AParcel_stdVectorAllocator<uint32_t>);
+static inline binder_status_t AParcel_writeRequiredStrongBinder(AParcel* parcel,
+                                                                const SpAIBinder& binder) {
+    if (binder.get() == nullptr) {
+        return STATUS_UNEXPECTED_NULL;
+    }
+    return AParcel_writeStrongBinder(parcel, binder.get());
 }
 
 /**
- * Writes a vector of int64_t to the next location in a non-null parcel.
+ * Convenience method to read a strong binder but return an error if it is null.
  */
-inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int64_t>& vec) {
-    return AParcel_writeInt64Array(parcel, vec.data(), vec.size());
+static inline binder_status_t AParcel_readRequiredStrongBinder(const AParcel* parcel,
+                                                               SpAIBinder* binder) {
+    AIBinder* readBinder;
+    binder_status_t ret = AParcel_readStrongBinder(parcel, &readBinder);
+    if (ret == STATUS_OK) {
+        if (readBinder == nullptr) {
+            return STATUS_UNEXPECTED_NULL;
+        }
+
+        binder->set(readBinder);
+    }
+    return ret;
 }
 
 /**
- * Reads a vector of int64_t from the next location in a non-null parcel.
+ * Convenience method to write a ParcelFileDescriptor where -1 represents a null value.
  */
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int64_t>* vec) {
-    void* vectorData = static_cast<void*>(vec);
-    return AParcel_readInt64Array(parcel, vectorData, AParcel_stdVectorAllocator<int64_t>);
+static inline binder_status_t AParcel_writeNullableParcelFileDescriptor(
+        AParcel* parcel, const ScopedFileDescriptor& fd) {
+    return AParcel_writeParcelFileDescriptor(parcel, fd.get());
 }
 
 /**
- * Writes a vector of uint64_t to the next location in a non-null parcel.
+ * Convenience method to read a ParcelFileDescriptor where -1 represents a null value.
  */
-inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint64_t>& vec) {
-    return AParcel_writeUint64Array(parcel, vec.data(), vec.size());
+static inline binder_status_t AParcel_readNullableParcelFileDescriptor(const AParcel* parcel,
+                                                                       ScopedFileDescriptor* fd) {
+    int readFd;
+    binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd);
+    if (status == STATUS_OK) {
+        fd->set(readFd);
+    }
+    return status;
 }
 
 /**
- * Reads a vector of uint64_t from the next location in a non-null parcel.
+ * Convenience method to write a valid ParcelFileDescriptor.
  */
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint64_t>* vec) {
-    void* vectorData = static_cast<void*>(vec);
-    return AParcel_readUint64Array(parcel, vectorData, AParcel_stdVectorAllocator<uint64_t>);
+static inline binder_status_t AParcel_writeRequiredParcelFileDescriptor(
+        AParcel* parcel, const ScopedFileDescriptor& fd) {
+    if (fd.get() < 0) {
+        return STATUS_UNEXPECTED_NULL;
+    }
+    return AParcel_writeParcelFileDescriptor(parcel, fd.get());
 }
 
 /**
- * Writes a vector of float to the next location in a non-null parcel.
+ * Convenience method to read a valid ParcelFileDescriptor.
  */
-inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<float>& vec) {
-    return AParcel_writeFloatArray(parcel, vec.data(), vec.size());
+static inline binder_status_t AParcel_readRequiredParcelFileDescriptor(const AParcel* parcel,
+                                                                       ScopedFileDescriptor* fd) {
+    int readFd;
+    binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd);
+    if (status == STATUS_OK) {
+        if (readFd < 0) {
+            return STATUS_UNEXPECTED_NULL;
+        }
+        fd->set(readFd);
+    }
+    return status;
 }
 
 /**
- * Reads a vector of float from the next location in a non-null parcel.
- */
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<float>* vec) {
-    void* vectorData = static_cast<void*>(vec);
-    return AParcel_readFloatArray(parcel, vectorData, AParcel_stdVectorAllocator<float>);
-}
-
-/**
- * Writes a vector of double to the next location in a non-null parcel.
- */
-inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<double>& vec) {
-    return AParcel_writeDoubleArray(parcel, vec.data(), vec.size());
-}
-
-/**
- * Reads a vector of double from the next location in a non-null parcel.
- */
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<double>* vec) {
-    void* vectorData = static_cast<void*>(vec);
-    return AParcel_readDoubleArray(parcel, vectorData, AParcel_stdVectorAllocator<double>);
-}
-
-/**
- * Writes a vector of bool to the next location in a non-null parcel.
- */
-inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<bool>& vec) {
-    return AParcel_writeBoolArray(parcel, static_cast<const void*>(&vec), vec.size(),
-                                  AParcel_stdVectorGetter<bool>);
-}
-
-/**
- * Reads a vector of bool from the next location in a non-null parcel.
- */
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<bool>* vec) {
-    void* vectorData = static_cast<void*>(vec);
-    return AParcel_readBoolArray(parcel, vectorData, AParcel_stdVectorExternalAllocator<bool>,
-                                 AParcel_stdVectorSetter<bool>);
-}
-
-/**
- * Writes a vector of char16_t to the next location in a non-null parcel.
- */
-inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<char16_t>& vec) {
-    return AParcel_writeCharArray(parcel, vec.data(), vec.size());
-}
-
-/**
- * Reads a vector of char16_t from the next location in a non-null parcel.
- */
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<char16_t>* vec) {
-    void* vectorData = static_cast<void*>(vec);
-    return AParcel_readCharArray(parcel, vectorData, AParcel_stdVectorAllocator<char16_t>);
-}
-
-/**
- * Writes a vector of int8_t to the next location in a non-null parcel.
- */
-inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int8_t>& vec) {
-    return AParcel_writeByteArray(parcel, vec.data(), vec.size());
-}
-
-/**
- * Reads a vector of int8_t from the next location in a non-null parcel.
- */
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int8_t>* vec) {
-    void* vectorData = static_cast<void*>(vec);
-    return AParcel_readByteArray(parcel, vectorData, AParcel_stdVectorAllocator<int8_t>);
-}
-
-// @END
-
-/**
  * Allocates a std::string to length and returns the underlying buffer. For use with
  * AParcel_readString. See use below in AParcel_readString(const AParcel*, std::string*).
  */
-static inline char* AParcel_stdStringAllocator(void* stringData, size_t length) {
+static inline bool AParcel_stdStringAllocator(void* stringData, int32_t length, char** buffer) {
+    if (length <= 0) return false;
+
     std::string* str = static_cast<std::string*>(stringData);
     str->resize(length - 1);
-    return &(*str)[0];
+    *buffer = &(*str)[0];
+    return true;
 }
 
 /**
- * Allocates a std::string inside of a std::vector<std::string> at index index to size 'length'.
+ * Allocates a string in a std::optional<std::string> to size 'length' (or to std::nullopt when
+ * length is -1) and returns the underlying buffer. For use with AParcel_readString. See use below
+ * in AParcel_readString(const AParcel*, std::optional<std::string>*).
  */
-static inline char* AParcel_stdVectorStringElementAllocator(void* vectorData, size_t index,
-                                                            size_t length) {
-    std::vector<std::string>* vec = static_cast<std::vector<std::string>*>(vectorData);
+static inline bool AParcel_nullableStdStringAllocator(void* stringData, int32_t length,
+                                                      char** buffer) {
+    if (length == 0) return false;
 
+    std::optional<std::string>* str = static_cast<std::optional<std::string>*>(stringData);
+
+    if (length < 0) {
+        *str = std::nullopt;
+        return true;
+    }
+
+    *str = std::optional<std::string>(std::string{});
+    (*str)->resize(length - 1);
+    *buffer = &(**str)[0];
+    return true;
+}
+
+/**
+ * Allocates a std::string inside of a std::vector<std::string> at index 'index' to size 'length'.
+ */
+static inline bool AParcel_stdVectorStringElementAllocator(void* vectorData, size_t index,
+                                                           int32_t length, char** buffer) {
+    std::vector<std::string>* vec = static_cast<std::vector<std::string>*>(vectorData);
     std::string& element = vec->at(index);
-    element.resize(length - 1);
-    return &element[0];
+    return AParcel_stdStringAllocator(static_cast<void*>(&element), length, buffer);
 }
 
 /**
@@ -253,7 +301,6 @@
 static inline const char* AParcel_stdVectorStringElementGetter(const void* vectorData, size_t index,
                                                                size_t* outLength) {
     const std::vector<std::string>* vec = static_cast<const std::vector<std::string>*>(vectorData);
-
     const std::string& element = vec->at(index);
 
     *outLength = element.size();
@@ -261,6 +308,40 @@
 }
 
 /**
+ * Allocates a string in a std::optional<std::string> inside of a
+ * std::optional<std::vector<std::optional<std::string>>> at index 'index' to size 'length' (or to
+ * std::nullopt when length is -1).
+ */
+static inline bool AParcel_nullableStdVectorStringElementAllocator(void* vectorData, size_t index,
+                                                                   int32_t length, char** buffer) {
+    std::optional<std::vector<std::optional<std::string>>>* vec =
+            static_cast<std::optional<std::vector<std::optional<std::string>>>*>(vectorData);
+    std::optional<std::string>& element = vec->value().at(index);
+    return AParcel_nullableStdStringAllocator(static_cast<void*>(&element), length, buffer);
+}
+
+/**
+ * This gets the length and buffer of a std::optional<std::string> inside of a
+ * std::vector<std::string> at index index. If the string is null, then it returns null and a length
+ * of -1.
+ */
+static inline const char* AParcel_nullableStdVectorStringElementGetter(const void* vectorData,
+                                                                       size_t index,
+                                                                       size_t* outLength) {
+    const std::optional<std::vector<std::optional<std::string>>>* vec =
+            static_cast<const std::optional<std::vector<std::optional<std::string>>>*>(vectorData);
+    const std::optional<std::string>& element = vec->value().at(index);
+
+    if (!element) {
+        *outLength = -1;
+        return nullptr;
+    }
+
+    *outLength = element->size();
+    return element->c_str();
+}
+
+/**
  * Convenience API for writing a std::string.
  */
 static inline binder_status_t AParcel_writeString(AParcel* parcel, const std::string& str) {
@@ -276,6 +357,27 @@
 }
 
 /**
+ * Convenience API for writing a std::optional<std::string>.
+ */
+static inline binder_status_t AParcel_writeString(AParcel* parcel,
+                                                  const std::optional<std::string>& str) {
+    if (!str) {
+        return AParcel_writeString(parcel, nullptr, -1);
+    }
+
+    return AParcel_writeString(parcel, str->c_str(), str->size());
+}
+
+/**
+ * Convenience API for reading a std::optional<std::string>.
+ */
+static inline binder_status_t AParcel_readString(const AParcel* parcel,
+                                                 std::optional<std::string>* str) {
+    void* stringData = static_cast<void*>(str);
+    return AParcel_readString(parcel, stringData, AParcel_nullableStdStringAllocator);
+}
+
+/**
  * Convenience API for writing a std::vector<std::string>
  */
 static inline binder_status_t AParcel_writeVector(AParcel* parcel,
@@ -297,6 +399,334 @@
 }
 
 /**
+ * Convenience API for writing a std::optional<std::vector<std::optional<std::string>>>
+ */
+static inline binder_status_t AParcel_writeVector(
+        AParcel* parcel, const std::optional<std::vector<std::optional<std::string>>>& vec) {
+    const void* vectorData = static_cast<const void*>(&vec);
+    return AParcel_writeStringArray(parcel, vectorData, (vec ? vec->size() : -1),
+                                    AParcel_nullableStdVectorStringElementGetter);
+}
+
+/**
+ * Convenience API for reading a std::optional<std::vector<std::optional<std::string>>>
+ */
+static inline binder_status_t AParcel_readVector(
+        const AParcel* parcel, std::optional<std::vector<std::optional<std::string>>>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readStringArray(
+            parcel, vectorData,
+            AParcel_nullableStdVectorExternalAllocator<std::optional<std::string>>,
+            AParcel_nullableStdVectorStringElementAllocator);
+}
+
+// @START
+/**
+ * Writes a vector of int32_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int32_t>& vec) {
+    return AParcel_writeInt32Array(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Writes an optional vector of int32_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+                                           const std::optional<std::vector<int32_t>>& vec) {
+    if (!vec) return AParcel_writeInt32Array(parcel, nullptr, -1);
+    return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of int32_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int32_t>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readInt32Array(parcel, vectorData, AParcel_stdVectorAllocator<int32_t>);
+}
+
+/**
+ * Reads an optional vector of int32_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+                                          std::optional<std::vector<int32_t>>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readInt32Array(parcel, vectorData, AParcel_nullableStdVectorAllocator<int32_t>);
+}
+
+/**
+ * Writes a vector of uint32_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint32_t>& vec) {
+    return AParcel_writeUint32Array(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Writes an optional vector of uint32_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+                                           const std::optional<std::vector<uint32_t>>& vec) {
+    if (!vec) return AParcel_writeUint32Array(parcel, nullptr, -1);
+    return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of uint32_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint32_t>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readUint32Array(parcel, vectorData, AParcel_stdVectorAllocator<uint32_t>);
+}
+
+/**
+ * Reads an optional vector of uint32_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+                                          std::optional<std::vector<uint32_t>>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readUint32Array(parcel, vectorData,
+                                   AParcel_nullableStdVectorAllocator<uint32_t>);
+}
+
+/**
+ * Writes a vector of int64_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int64_t>& vec) {
+    return AParcel_writeInt64Array(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Writes an optional vector of int64_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+                                           const std::optional<std::vector<int64_t>>& vec) {
+    if (!vec) return AParcel_writeInt64Array(parcel, nullptr, -1);
+    return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of int64_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int64_t>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readInt64Array(parcel, vectorData, AParcel_stdVectorAllocator<int64_t>);
+}
+
+/**
+ * Reads an optional vector of int64_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+                                          std::optional<std::vector<int64_t>>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readInt64Array(parcel, vectorData, AParcel_nullableStdVectorAllocator<int64_t>);
+}
+
+/**
+ * Writes a vector of uint64_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint64_t>& vec) {
+    return AParcel_writeUint64Array(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Writes an optional vector of uint64_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+                                           const std::optional<std::vector<uint64_t>>& vec) {
+    if (!vec) return AParcel_writeUint64Array(parcel, nullptr, -1);
+    return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of uint64_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint64_t>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readUint64Array(parcel, vectorData, AParcel_stdVectorAllocator<uint64_t>);
+}
+
+/**
+ * Reads an optional vector of uint64_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+                                          std::optional<std::vector<uint64_t>>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readUint64Array(parcel, vectorData,
+                                   AParcel_nullableStdVectorAllocator<uint64_t>);
+}
+
+/**
+ * Writes a vector of float to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<float>& vec) {
+    return AParcel_writeFloatArray(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Writes an optional vector of float to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+                                           const std::optional<std::vector<float>>& vec) {
+    if (!vec) return AParcel_writeFloatArray(parcel, nullptr, -1);
+    return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of float from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<float>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readFloatArray(parcel, vectorData, AParcel_stdVectorAllocator<float>);
+}
+
+/**
+ * Reads an optional vector of float from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+                                          std::optional<std::vector<float>>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readFloatArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<float>);
+}
+
+/**
+ * Writes a vector of double to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<double>& vec) {
+    return AParcel_writeDoubleArray(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Writes an optional vector of double to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+                                           const std::optional<std::vector<double>>& vec) {
+    if (!vec) return AParcel_writeDoubleArray(parcel, nullptr, -1);
+    return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of double from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<double>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readDoubleArray(parcel, vectorData, AParcel_stdVectorAllocator<double>);
+}
+
+/**
+ * Reads an optional vector of double from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+                                          std::optional<std::vector<double>>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readDoubleArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<double>);
+}
+
+/**
+ * Writes a vector of bool to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<bool>& vec) {
+    return AParcel_writeBoolArray(parcel, static_cast<const void*>(&vec), vec.size(),
+                                  AParcel_stdVectorGetter<bool>);
+}
+
+/**
+ * Writes an optional vector of bool to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+                                           const std::optional<std::vector<bool>>& vec) {
+    if (!vec) return AParcel_writeBoolArray(parcel, nullptr, -1, AParcel_stdVectorGetter<bool>);
+    return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of bool from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<bool>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readBoolArray(parcel, vectorData, AParcel_stdVectorExternalAllocator<bool>,
+                                 AParcel_stdVectorSetter<bool>);
+}
+
+/**
+ * Reads an optional vector of bool from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+                                          std::optional<std::vector<bool>>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readBoolArray(parcel, vectorData,
+                                 AParcel_nullableStdVectorExternalAllocator<bool>,
+                                 AParcel_nullableStdVectorSetter<bool>);
+}
+
+/**
+ * Writes a vector of char16_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<char16_t>& vec) {
+    return AParcel_writeCharArray(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Writes an optional vector of char16_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+                                           const std::optional<std::vector<char16_t>>& vec) {
+    if (!vec) return AParcel_writeCharArray(parcel, nullptr, -1);
+    return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of char16_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<char16_t>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readCharArray(parcel, vectorData, AParcel_stdVectorAllocator<char16_t>);
+}
+
+/**
+ * Reads an optional vector of char16_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+                                          std::optional<std::vector<char16_t>>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readCharArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<char16_t>);
+}
+
+/**
+ * Writes a vector of int8_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int8_t>& vec) {
+    return AParcel_writeByteArray(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Writes an optional vector of int8_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+                                           const std::optional<std::vector<int8_t>>& vec) {
+    if (!vec) return AParcel_writeByteArray(parcel, nullptr, -1);
+    return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of int8_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int8_t>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readByteArray(parcel, vectorData, AParcel_stdVectorAllocator<int8_t>);
+}
+
+/**
+ * Reads an optional vector of int8_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+                                          std::optional<std::vector<int8_t>>* vec) {
+    void* vectorData = static_cast<void*>(vec);
+    return AParcel_readByteArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<int8_t>);
+}
+
+// @END
+
+/**
  * Convenience API for writing the size of a vector.
  */
 template <typename T>
@@ -309,6 +739,23 @@
 }
 
 /**
+ * Convenience API for writing the size of a vector.
+ */
+template <typename T>
+static inline binder_status_t AParcel_writeVectorSize(AParcel* parcel,
+                                                      const std::optional<std::vector<T>>& vec) {
+    if (!vec) {
+        return AParcel_writeInt32(parcel, -1);
+    }
+
+    if (vec->size() > INT32_MAX) {
+        return STATUS_BAD_VALUE;
+    }
+
+    return AParcel_writeInt32(parcel, static_cast<int32_t>(vec->size()));
+}
+
+/**
  * Convenience API for resizing a vector.
  */
 template <typename T>
@@ -323,6 +770,28 @@
     return STATUS_OK;
 }
 
+/**
+ * Convenience API for resizing a vector.
+ */
+template <typename T>
+static inline binder_status_t AParcel_resizeVector(const AParcel* parcel,
+                                                   std::optional<std::vector<T>>* vec) {
+    int32_t size;
+    binder_status_t err = AParcel_readInt32(parcel, &size);
+
+    if (err != STATUS_OK) return err;
+    if (size < -1) return STATUS_UNEXPECTED_NULL;
+
+    if (size == -1) {
+        *vec = std::nullopt;
+        return STATUS_OK;
+    }
+
+    *vec = std::optional<std::vector<T>>(std::vector<T>{});
+    (*vec)->resize(static_cast<size_t>(size));
+    return STATUS_OK;
+}
+
 }  // namespace ndk
 
 /** @} */
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index d2c1a3d..41df90b 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -7,6 +7,8 @@
     AIBinder_debugGetRefCount;
     AIBinder_decStrong;
     AIBinder_fromJavaBinder;
+    AIBinder_getCallingPid;
+    AIBinder_getCallingUid;
     AIBinder_getClass;
     AIBinder_getUserData;
     AIBinder_incStrong;
@@ -37,7 +39,6 @@
     AParcel_readInt32Array;
     AParcel_readInt64;
     AParcel_readInt64Array;
-    AParcel_readNullableStrongBinder;
     AParcel_readParcelFileDescriptor;
     AParcel_readStatusHeader;
     AParcel_readString;
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index 8e5b477..3c32100 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -36,28 +36,46 @@
 using ::android::os::ParcelFileDescriptor;
 
 template <typename T>
-using ContiguousArrayAllocator = T* (*)(void* arrayData, size_t length);
+using ContiguousArrayAllocator = bool (*)(void* arrayData, int32_t length, T** outBuffer);
 
 template <typename T>
-using ArrayAllocator = bool (*)(void* arrayData, size_t length);
+using ArrayAllocator = bool (*)(void* arrayData, int32_t length);
 template <typename T>
 using ArrayGetter = T (*)(const void* arrayData, size_t index);
 template <typename T>
 using ArraySetter = void (*)(void* arrayData, size_t index, T value);
 
-template <typename T>
-binder_status_t WriteArray(AParcel* parcel, const T* array, size_t length) {
-    if (length > std::numeric_limits<int32_t>::max()) return STATUS_BAD_VALUE;
+binder_status_t WriteAndValidateArraySize(AParcel* parcel, bool isNullArray, int32_t length) {
+    // only -1 can be used to represent a null array
+    if (length < -1) return STATUS_BAD_VALUE;
+
+    if (!isNullArray && length < 0) {
+        LOG(ERROR) << __func__ << ": null array must be used with length == -1.";
+        return STATUS_BAD_VALUE;
+    }
+    if (isNullArray && length > 0) {
+        LOG(ERROR) << __func__ << ": null buffer cannot be for size " << length << " array.";
+        return STATUS_BAD_VALUE;
+    }
 
     Parcel* rawParcel = parcel->get();
 
     status_t status = rawParcel->writeInt32(static_cast<int32_t>(length));
     if (status != STATUS_OK) return PruneStatusT(status);
 
+    return STATUS_OK;
+}
+
+template <typename T>
+binder_status_t WriteArray(AParcel* parcel, const T* array, int32_t length) {
+    binder_status_t status = WriteAndValidateArraySize(parcel, array == nullptr, length);
+    if (status != STATUS_OK) return status;
+    if (length <= 0) return STATUS_OK;
+
     int32_t size = 0;
     if (__builtin_smul_overflow(sizeof(T), length, &size)) return STATUS_NO_MEMORY;
 
-    void* const data = rawParcel->writeInplace(size);
+    void* const data = parcel->get()->writeInplace(size);
     if (data == nullptr) return STATUS_NO_MEMORY;
 
     memcpy(data, array, size);
@@ -67,17 +85,16 @@
 
 // Each element in a char16_t array is converted to an int32_t (not packed).
 template <>
-binder_status_t WriteArray<char16_t>(AParcel* parcel, const char16_t* array, size_t length) {
-    if (length > std::numeric_limits<int32_t>::max()) return STATUS_BAD_VALUE;
-
-    Parcel* rawParcel = parcel->get();
-
-    status_t status = rawParcel->writeInt32(static_cast<int32_t>(length));
-    if (status != STATUS_OK) return PruneStatusT(status);
+binder_status_t WriteArray<char16_t>(AParcel* parcel, const char16_t* array, int32_t length) {
+    binder_status_t status = WriteAndValidateArraySize(parcel, array == nullptr, length);
+    if (status != STATUS_OK) return status;
+    if (length <= 0) return STATUS_OK;
 
     int32_t size = 0;
     if (__builtin_smul_overflow(sizeof(char16_t), length, &size)) return STATUS_NO_MEMORY;
 
+    Parcel* rawParcel = parcel->get();
+
     for (int32_t i = 0; i < length; i++) {
         status = rawParcel->writeChar(array[i]);
 
@@ -96,10 +113,12 @@
     status_t status = rawParcel->readInt32(&length);
 
     if (status != STATUS_OK) return PruneStatusT(status);
-    if (length < 0) return STATUS_UNEXPECTED_NULL;
+    if (length < -1) return STATUS_BAD_VALUE;
 
-    T* array = allocator(arrayData, length);
-    if (length == 0) return STATUS_OK;
+    T* array;
+    if (!allocator(arrayData, length, &array)) return STATUS_NO_MEMORY;
+
+    if (length <= 0) return STATUS_OK;
     if (array == nullptr) return STATUS_NO_MEMORY;
 
     int32_t size = 0;
@@ -123,10 +142,12 @@
     status_t status = rawParcel->readInt32(&length);
 
     if (status != STATUS_OK) return PruneStatusT(status);
-    if (length < 0) return STATUS_UNEXPECTED_NULL;
+    if (length < -1) return STATUS_BAD_VALUE;
 
-    char16_t* array = allocator(arrayData, length);
-    if (length == 0) return STATUS_OK;
+    char16_t* array;
+    if (!allocator(arrayData, length, &array)) return STATUS_NO_MEMORY;
+
+    if (length <= 0) return STATUS_OK;
     if (array == nullptr) return STATUS_NO_MEMORY;
 
     int32_t size = 0;
@@ -142,15 +163,16 @@
 }
 
 template <typename T>
-binder_status_t WriteArray(AParcel* parcel, const void* arrayData, size_t length,
+binder_status_t WriteArray(AParcel* parcel, const void* arrayData, int32_t length,
                            ArrayGetter<T> getter, status_t (Parcel::*write)(T)) {
-    if (length > std::numeric_limits<int32_t>::max()) return STATUS_BAD_VALUE;
+    // we have no clue if arrayData represents a null object or not, we can only infer from length
+    bool arrayIsNull = length < 0;
+    binder_status_t status = WriteAndValidateArraySize(parcel, arrayIsNull, length);
+    if (status != STATUS_OK) return status;
+    if (length <= 0) return STATUS_OK;
 
     Parcel* rawParcel = parcel->get();
 
-    status_t status = rawParcel->writeInt32(static_cast<int32_t>(length));
-    if (status != STATUS_OK) return PruneStatusT(status);
-
     for (size_t i = 0; i < length; i++) {
         status = (rawParcel->*write)(getter(arrayData, i));
 
@@ -169,10 +191,12 @@
     status_t status = rawParcel->readInt32(&length);
 
     if (status != STATUS_OK) return PruneStatusT(status);
-    if (length < 0) return STATUS_UNEXPECTED_NULL;
+    if (length < -1) return STATUS_BAD_VALUE;
 
     if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
 
+    if (length <= 0) return STATUS_OK;
+
     for (size_t i = 0; i < length; i++) {
         T readTarget;
         status = (rawParcel->*read)(&readTarget);
@@ -194,17 +218,6 @@
 }
 binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder) {
     sp<IBinder> readBinder = nullptr;
-    status_t status = parcel->get()->readStrongBinder(&readBinder);
-    if (status != STATUS_OK) {
-        return PruneStatusT(status);
-    }
-    sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(readBinder);
-    AIBinder_incStrong(ret.get());
-    *binder = ret.get();
-    return PruneStatusT(status);
-}
-binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder) {
-    sp<IBinder> readBinder = nullptr;
     status_t status = parcel->get()->readNullableStrongBinder(&readBinder);
     if (status != STATUS_OK) {
         return PruneStatusT(status);
@@ -216,23 +229,39 @@
 }
 
 binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd) {
-    ParcelFileDescriptor parcelFd((unique_fd(fd)));
+    std::unique_ptr<ParcelFileDescriptor> parcelFd;
 
-    status_t status = parcel->get()->writeParcelable(parcelFd);
+    if (fd < 0) {
+        if (fd != -1) {
+            return STATUS_UNKNOWN_ERROR;
+        }
+        // parcelFd = nullptr
+    } else {  // fd >= 0
+        parcelFd = std::make_unique<ParcelFileDescriptor>(unique_fd(fd));
+    }
+
+    status_t status = parcel->get()->writeNullableParcelable(parcelFd);
 
     // ownership is retained by caller
-    (void)parcelFd.release().release();
+    if (parcelFd != nullptr) {
+        (void)parcelFd->release().release();
+    }
 
     return PruneStatusT(status);
 }
 
 binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd) {
-    ParcelFileDescriptor parcelFd;
-    // status_t status = parcelFd.readFromParcel(parcel->get());
+    std::unique_ptr<ParcelFileDescriptor> parcelFd;
+
     status_t status = parcel->get()->readParcelable(&parcelFd);
     if (status != STATUS_OK) return PruneStatusT(status);
 
-    *fd = parcelFd.release().release();
+    if (parcelFd) {
+        *fd = parcelFd->release().release();
+    } else {
+        *fd = -1;
+    }
+
     return STATUS_OK;
 }
 
@@ -248,9 +277,23 @@
     return PruneStatusT(ret);
 }
 
-binder_status_t AParcel_writeString(AParcel* parcel, const char* string, size_t length) {
-    const uint8_t* str8 = (uint8_t*)string;
+binder_status_t AParcel_writeString(AParcel* parcel, const char* string, int32_t length) {
+    if (string == nullptr) {
+        if (length != -1) {
+            LOG(WARNING) << __func__ << ": null string must be used with length == -1.";
+            return STATUS_BAD_VALUE;
+        }
 
+        status_t err = parcel->get()->writeInt32(-1);
+        return PruneStatusT(err);
+    }
+
+    if (length < 0) {
+        LOG(WARNING) << __func__ << ": Negative string length: " << length;
+        return STATUS_BAD_VALUE;
+    }
+
+    const uint8_t* str8 = (uint8_t*)string;
     const ssize_t len16 = utf8_to_utf16_length(str8, length);
 
     if (len16 < 0 || len16 >= std::numeric_limits<int32_t>::max()) {
@@ -279,7 +322,10 @@
     const char16_t* str16 = parcel->get()->readString16Inplace(&len16);
 
     if (str16 == nullptr) {
-        LOG(WARNING) << __func__ << ": Failed to read string in place.";
+        if (allocator(stringData, -1, nullptr)) {
+            return STATUS_OK;
+        }
+
         return STATUS_UNEXPECTED_NULL;
     }
 
@@ -296,9 +342,10 @@
         return STATUS_BAD_VALUE;
     }
 
-    char* str8 = allocator(stringData, len8);
+    char* str8;
+    bool success = allocator(stringData, len8, &str8);
 
-    if (str8 == nullptr) {
+    if (!success || str8 == nullptr) {
         LOG(WARNING) << __func__ << ": AParcel_stringAllocator failed to allocate.";
         return STATUS_NO_MEMORY;
     }
@@ -308,19 +355,18 @@
     return STATUS_OK;
 }
 
-binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, size_t length,
+binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, int32_t length,
                                          AParcel_stringArrayElementGetter getter) {
-    if (length > std::numeric_limits<int32_t>::max()) return STATUS_BAD_VALUE;
-
-    Parcel* rawParcel = parcel->get();
-
-    status_t status = rawParcel->writeInt32(static_cast<int32_t>(length));
-    if (status != STATUS_OK) return PruneStatusT(status);
+    // we have no clue if arrayData represents a null object or not, we can only infer from length
+    bool arrayIsNull = length < 0;
+    binder_status_t status = WriteAndValidateArraySize(parcel, arrayIsNull, length);
+    if (status != STATUS_OK) return status;
+    if (length <= 0) return STATUS_OK;
 
     for (size_t i = 0; i < length; i++) {
         size_t length = 0;
         const char* str = getter(arrayData, i, &length);
-        if (str == nullptr) return STATUS_BAD_VALUE;
+        if (str == nullptr && length != -1) return STATUS_BAD_VALUE;
 
         binder_status_t status = AParcel_writeString(parcel, str, length);
         if (status != STATUS_OK) return status;
@@ -336,10 +382,10 @@
     size_t index;     // index into the string array
     AParcel_stringArrayElementAllocator elementAllocator;
 
-    static char* Allocator(void* stringData, size_t length) {
+    static bool Allocator(void* stringData, int32_t length, char** buffer) {
         StringArrayElementAllocationAdapter* adapter =
                 static_cast<StringArrayElementAllocationAdapter*>(stringData);
-        return adapter->elementAllocator(adapter->arrayData, adapter->index, length);
+        return adapter->elementAllocator(adapter->arrayData, adapter->index, length, buffer);
     }
 };
 
@@ -352,10 +398,12 @@
     status_t status = rawParcel->readInt32(&length);
 
     if (status != STATUS_OK) return PruneStatusT(status);
-    if (length < 0) return STATUS_UNEXPECTED_NULL;
+    if (length < -1) return STATUS_BAD_VALUE;
 
     if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
 
+    if (length == -1) return STATUS_OK;  // null string array
+
     StringArrayElementAllocationAdapter adapter{
             .arrayData = arrayData,
             .index = 0,
@@ -363,8 +411,10 @@
     };
 
     for (; adapter.index < length; adapter.index++) {
-        AParcel_readString(parcel, static_cast<void*>(&adapter),
-                           StringArrayElementAllocationAdapter::Allocator);
+        binder_status_t status = AParcel_readString(parcel, static_cast<void*>(&adapter),
+                                                    StringArrayElementAllocationAdapter::Allocator);
+
+        if (status != STATUS_OK) return status;
     }
 
     return STATUS_OK;
@@ -463,42 +513,42 @@
     return PruneStatusT(status);
 }
 
-binder_status_t AParcel_writeInt32Array(AParcel* parcel, const int32_t* arrayData, size_t length) {
+binder_status_t AParcel_writeInt32Array(AParcel* parcel, const int32_t* arrayData, int32_t length) {
     return WriteArray<int32_t>(parcel, arrayData, length);
 }
 
 binder_status_t AParcel_writeUint32Array(AParcel* parcel, const uint32_t* arrayData,
-                                         size_t length) {
+                                         int32_t length) {
     return WriteArray<uint32_t>(parcel, arrayData, length);
 }
 
-binder_status_t AParcel_writeInt64Array(AParcel* parcel, const int64_t* arrayData, size_t length) {
+binder_status_t AParcel_writeInt64Array(AParcel* parcel, const int64_t* arrayData, int32_t length) {
     return WriteArray<int64_t>(parcel, arrayData, length);
 }
 
 binder_status_t AParcel_writeUint64Array(AParcel* parcel, const uint64_t* arrayData,
-                                         size_t length) {
+                                         int32_t length) {
     return WriteArray<uint64_t>(parcel, arrayData, length);
 }
 
-binder_status_t AParcel_writeFloatArray(AParcel* parcel, const float* arrayData, size_t length) {
+binder_status_t AParcel_writeFloatArray(AParcel* parcel, const float* arrayData, int32_t length) {
     return WriteArray<float>(parcel, arrayData, length);
 }
 
-binder_status_t AParcel_writeDoubleArray(AParcel* parcel, const double* arrayData, size_t length) {
+binder_status_t AParcel_writeDoubleArray(AParcel* parcel, const double* arrayData, int32_t length) {
     return WriteArray<double>(parcel, arrayData, length);
 }
 
-binder_status_t AParcel_writeBoolArray(AParcel* parcel, const void* arrayData, size_t length,
+binder_status_t AParcel_writeBoolArray(AParcel* parcel, const void* arrayData, int32_t length,
                                        AParcel_boolArrayGetter getter) {
     return WriteArray<bool>(parcel, arrayData, length, getter, &Parcel::writeBool);
 }
 
-binder_status_t AParcel_writeCharArray(AParcel* parcel, const char16_t* arrayData, size_t length) {
+binder_status_t AParcel_writeCharArray(AParcel* parcel, const char16_t* arrayData, int32_t length) {
     return WriteArray<char16_t>(parcel, arrayData, length);
 }
 
-binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* arrayData, size_t length) {
+binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* arrayData, int32_t length) {
     return WriteArray<int8_t>(parcel, arrayData, length);
 }
 
diff --git a/libs/binder/ndk/scripts/gen_parcel_helper.py b/libs/binder/ndk/scripts/gen_parcel_helper.py
index bb76254..8f587d2 100755
--- a/libs/binder/ndk/scripts/gen_parcel_helper.py
+++ b/libs/binder/ndk/scripts/gen_parcel_helper.py
@@ -99,8 +99,8 @@
     for pretty, cpp in data_types:
         nca = pretty in non_contiguously_addressable
 
-        arg_types = "const " + cpp + "* arrayData, size_t length"
-        if nca: arg_types = "const void* arrayData, size_t length, AParcel_" + pretty.lower() + "ArrayGetter getter"
+        arg_types = "const " + cpp + "* arrayData, int32_t length"
+        if nca: arg_types = "const void* arrayData, int32_t length, AParcel_" + pretty.lower() + "ArrayGetter getter"
         args = "arrayData, length"
         if nca: args = "arrayData, length, getter, &Parcel::write" + pretty
 
@@ -114,11 +114,11 @@
         header += " * \\param parcel the parcel to write to.\n"
         if nca:
             header += " * \\param arrayData some external representation of an array.\n"
-            header += " * \\param length the length of arrayData.\n"
+            header += " * \\param length the length of arrayData (or -1 if this represents a null array).\n"
             header += " * \\param getter the callback to retrieve data at specific locations in the array.\n"
         else:
-            header += " * \\param arrayData an array of size 'length'.\n"
-            header += " * \\param length the length of arrayData.\n"
+            header += " * \\param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).\n"
+            header += " * \\param length the length of arrayData or -1 if this represents a null array.\n"
         header += " *\n"
         header += " * \\return STATUS_OK on successful write.\n"
         header += " */\n"
@@ -139,16 +139,16 @@
         if nca:
             pre_header += "/**\n"
             pre_header += " * This allocates an array of size 'length' inside of arrayData and returns whether or not there was "
-            pre_header += "a success.\n"
+            pre_header += "a success. If length is -1, then this should allocate some representation of a null array.\n"
             pre_header += " *\n"
             pre_header += " * See also " + read_func + "\n"
             pre_header += " *\n"
             pre_header += " * \\param arrayData some external representation of an array of " + cpp + ".\n"
-            pre_header += " * \\param length the length to allocate arrayData to.\n"
+            pre_header += " * \\param length the length to allocate arrayData to (or -1 if this represents a null array).\n"
             pre_header += " *\n"
             pre_header += " * \\return whether the allocation succeeded.\n"
             pre_header += " */\n"
-            pre_header += "typedef bool (*" + allocator_type + ")(void* arrayData, size_t length);\n\n"
+            pre_header += "typedef bool (*" + allocator_type + ")(void* arrayData, int32_t length);\n\n"
 
             pre_header += "/**\n"
             pre_header += " * This is called to get the underlying data from an arrayData object at index.\n"
@@ -178,16 +178,18 @@
             pre_header += " *\n"
             pre_header += " * The implementation of this function should allocate a contiguous array of size 'length' and "
             pre_header += "return that underlying buffer to be filled out. If there is an error or length is 0, null may be "
-            pre_header += "returned.\n"
+            pre_header += "returned. If length is -1, this should allocate some representation of a null array.\n"
             pre_header += " *\n"
             pre_header += " * See also " + read_func + "\n"
             pre_header += " *\n"
             pre_header += " * \\param arrayData some external representation of an array of " + cpp + ".\n"
             pre_header += " * \\param length the length to allocate arrayData to.\n"
+            pre_header += " * \\param outBuffer a buffer of " + cpp + " of size 'length' (if length is >= 0, if length is 0, "
+            pre_header += "this may be nullptr).\n"
             pre_header += " *\n"
-            pre_header += " * \\return a buffer of " + cpp + " of size 'length'.\n"
+            pre_header += " * \\return whether or not the allocation was successful (or whether a null array is represented when length is -1).\n"
             pre_header += " */\n"
-            pre_header += "typedef " + cpp + "* (*" + allocator_type + ")(void* arrayData, size_t length);\n\n"
+            pre_header += "typedef bool (*" + allocator_type + ")(void* arrayData, int32_t length, " + cpp + "** outBuffer);\n\n"
 
         read_array_args = [("const AParcel*", "parcel")]
         read_array_args += [("void*", "arrayData")]
@@ -232,6 +234,16 @@
         cpp_helper += "}\n\n"
 
         cpp_helper += "/**\n"
+        cpp_helper += " * Writes an optional vector of " + cpp + " to the next location in a non-null parcel.\n"
+        cpp_helper += " */\n"
+        cpp_helper += "inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::optional<std::vector<" + cpp + ">>& vec) {\n"
+        extra_args = ""
+        if nca: extra_args = ", AParcel_stdVectorGetter<" + cpp + ">"
+        cpp_helper += "    if (!vec) return AParcel_write" + pretty + "Array(parcel, nullptr, -1" + extra_args + ");\n"
+        cpp_helper += "    return AParcel_writeVector(parcel, *vec);\n"
+        cpp_helper += "}\n\n"
+
+        cpp_helper += "/**\n"
         cpp_helper += " * Reads a vector of " + cpp + " from the next location in a non-null parcel.\n"
         cpp_helper += " */\n"
         cpp_helper += "inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<" + cpp + ">* vec) {\n"
@@ -247,6 +259,22 @@
         cpp_helper += "    return AParcel_read" + pretty + "Array(" + ", ".join(read_args) + ");\n"
         cpp_helper += "}\n\n"
 
+        cpp_helper += "/**\n"
+        cpp_helper += " * Reads an optional vector of " + cpp + " from the next location in a non-null parcel.\n"
+        cpp_helper += " */\n"
+        cpp_helper += "inline binder_status_t AParcel_readVector(const AParcel* parcel, std::optional<std::vector<" + cpp + ">>* vec) {\n"
+        cpp_helper += "    void* vectorData = static_cast<void*>(vec);\n"
+        read_args = []
+        read_args += ["parcel"]
+        read_args += ["vectorData"]
+        if nca:
+            read_args += ["AParcel_nullableStdVectorExternalAllocator<bool>"]
+            read_args += ["AParcel_nullableStdVectorSetter<" + cpp + ">"]
+        else:
+            read_args += ["AParcel_nullableStdVectorAllocator<" + cpp + ">"]
+        cpp_helper += "    return AParcel_read" + pretty + "Array(" + ", ".join(read_args) + ");\n"
+        cpp_helper += "}\n\n"
+
     replaceFileTags(ROOT + "include_ndk/android/binder_parcel.h", pre_header, "START-PRIMITIVE-VECTOR-GETTERS", "END-PRIMITIVE-VECTOR-GETTERS")
     replaceFileTags(ROOT + "include_ndk/android/binder_parcel.h", header, "START-PRIMITIVE-READ-WRITE", "END-PRIMITIVE-READ-WRITE")
     replaceFileTags(ROOT + "parcel.cpp", source, "START", "END")
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index b29b6e7..67481cf 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -22,6 +22,7 @@
     strip: {
         none: true,
     },
+    cpp_std: "c++17",
     cflags: [
         "-O0",
         "-g",
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 7bcfffd..22c1bad 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -953,7 +953,7 @@
 {
     status_t ret;
     Parcel data, reply;
-    uid_t previousWorkSource = IPCThreadState::self()->setWorkSource(100);
+    int64_t previousWorkSource = IPCThreadState::self()->setCallingWorkSourceUid(100);
     data.writeInterfaceToken(binderLibTestServiceName);
     ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply);
     EXPECT_EQ(100, reply.readInt32());
@@ -966,8 +966,8 @@
     status_t ret;
     Parcel data, reply;
 
-    IPCThreadState::self()->setWorkSource(100);
-    uid_t previousWorkSource = IPCThreadState::self()->clearWorkSource();
+    IPCThreadState::self()->setCallingWorkSourceUid(100);
+    int64_t previousWorkSource = IPCThreadState::self()->clearCallingWorkSource();
     data.writeInterfaceToken(binderLibTestServiceName);
     ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply);
 
@@ -976,6 +976,22 @@
     EXPECT_EQ(NO_ERROR, ret);
 }
 
+TEST_F(BinderLibTest, WorkSourceRestored)
+{
+    status_t ret;
+    Parcel data, reply;
+
+    IPCThreadState::self()->setCallingWorkSourceUid(100);
+    int64_t token = IPCThreadState::self()->clearCallingWorkSource();
+    IPCThreadState::self()->restoreCallingWorkSource(token);
+
+    data.writeInterfaceToken(binderLibTestServiceName);
+    ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply);
+
+    EXPECT_EQ(100, reply.readInt32());
+    EXPECT_EQ(NO_ERROR, ret);
+}
+
 class BinderLibTestService : public BBinder
 {
     public:
@@ -1276,7 +1292,7 @@
             }
             case BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION: {
                 data.enforceInterface(binderLibTestServiceName);
-                reply->writeInt32(IPCThreadState::self()->getWorkSource());
+                reply->writeInt32(IPCThreadState::self()->getCallingWorkSourceUid());
                 return NO_ERROR;
             }
             default:
diff --git a/libs/binder/tests/binderValueTypeTest.cpp b/libs/binder/tests/binderValueTypeTest.cpp
index c8f4697..15949d4 100644
--- a/libs/binder/tests/binderValueTypeTest.cpp
+++ b/libs/binder/tests/binderValueTypeTest.cpp
@@ -22,7 +22,6 @@
 #include <vector>
 
 #include "android-base/file.h"
-#include "android-base/test_utils.h"
 #include <gtest/gtest.h>
 
 #include <binder/Parcel.h>
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 7677c3a..127fcd6 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -135,6 +135,7 @@
         "libutils",
         "libnativewindow",
         "liblog",
+        "libinput",
         "libhidlbase",
         "libhidltransport",
         "android.hidl.token@1.0-utils",
@@ -146,7 +147,7 @@
     // bufferhub is not used when building libgui for vendors
     target: {
         vendor: {
-            cflags: ["-DNO_BUFFERHUB"],
+            cflags: ["-DNO_BUFFERHUB", "-DNO_INPUT"],
             exclude_srcs: [
                 "BufferHubConsumer.cpp",
                 "BufferHubProducer.cpp",
@@ -155,6 +156,7 @@
                 "libbufferhub",
                 "libbufferhubqueue",
                 "libpdx_default_transport",
+                "libinput"
             ],
         },
     },
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 7b71b39..9f30060 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -50,6 +50,9 @@
     output.writeFloat(color.r);
     output.writeFloat(color.g);
     output.writeFloat(color.b);
+#ifndef NO_INPUT
+    inputInfo.write(output);
+#endif
     output.write(transparentRegion);
     output.writeUint32(transform);
     output.writeBool(transformToDisplayInverse);
@@ -120,6 +123,11 @@
     color.r = input.readFloat();
     color.g = input.readFloat();
     color.b = input.readFloat();
+
+#ifndef NO_INPUT
+    inputInfo = InputWindowInfo::read(input);
+#endif
+
     input.read(transparentRegion);
     transform = input.readUint32();
     transformToDisplayInverse = input.readBool();
@@ -343,6 +351,13 @@
         listenerCallbacks = other.listenerCallbacks;
     }
 
+#ifndef NO_INPUT
+    if (other.what & eInputInfoChanged) {
+        what |= eInputInfoChanged;
+        inputInfo = other.inputInfo;
+    }
+#endif
+
     if ((other.what & what) != other.what) {
         ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
               "other.what=0x%X what=0x%X",
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index e10bda4..87c6f27 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -42,6 +42,10 @@
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 
+#ifndef NO_INPUT
+#include <input/InputWindow.h>
+#endif
+
 #include <private/gui/ComposerService.h>
 
 namespace android {
@@ -759,6 +763,21 @@
     return *this;
 }
 
+#ifndef NO_INPUT
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo(
+        const sp<SurfaceControl>& sc,
+        const InputWindowInfo& info) {
+    layer_state_t* s = getLayerState(sc);
+    if (!s) {
+        mStatus = BAD_INDEX;
+        return *this;
+    }
+    s->inputInfo = info;
+    s->what |= layer_state_t::eInputInfoChanged;
+    return *this;
+}
+#endif
+
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::destroySurface(
         const sp<SurfaceControl>& sc) {
     layer_state_t* s = getLayerState(sc);
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index ddbac7b..cdb2309 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -25,6 +25,11 @@
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/ITransactionCompletedListener.h>
 #include <math/mat4.h>
+
+#ifndef NO_INPUT
+#include <input/InputWindow.h>
+#endif
+
 #include <math/vec3.h>
 #include <ui/GraphicTypes.h>
 #include <ui/Rect.h>
@@ -76,6 +81,7 @@
         eSidebandStreamChanged = 0x08000000,
         eColorTransformChanged = 0x10000000,
         eListenerCallbacksChanged = 0x20000000,
+        eInputInfoChanged = 0x40000000,
     };
 
     layer_state_t()
@@ -158,6 +164,9 @@
     mat4 colorTransform;
 
     std::vector<ListenerCallbacks> listenerCallbacks;
+#ifndef NO_INPUT
+    InputWindowInfo inputInfo;
+#endif
 };
 
 struct ComposerState {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 1cafb77..10c27b1 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -330,6 +330,10 @@
         // freezing the total geometry of a surface until a resize is completed.
         Transaction& setGeometryAppliesWithResize(const sp<SurfaceControl>& sc);
 
+#ifndef NO_INPUT
+        Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const InputWindowInfo& info);
+#endif
+
         Transaction& destroySurface(const sp<SurfaceControl>& sc);
 
         // Set a color transform matrix on the given layer on the built-in display.
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 72558a6..8cb8649 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -43,12 +43,12 @@
     target: {
         android: {
             srcs: [
-                "IInputFlinger.cpp",
                 "InputTransport.cpp",
                 "VelocityControl.cpp",
                 "VelocityTracker.cpp",
                 "InputApplication.cpp",
-                "InputWindow.cpp"
+                "InputWindow.cpp",
+                "IInputFlinger.cpp"
             ],
 
             shared_libs: [
diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp
index 003e73d..47a2c0c 100644
--- a/libs/input/IInputFlinger.cpp
+++ b/libs/input/IInputFlinger.cpp
@@ -23,7 +23,6 @@
 
 #include <input/IInputFlinger.h>
 
-
 namespace android {
 
 class BpInputFlinger : public BpInterface<IInputFlinger> {
@@ -31,23 +30,35 @@
     explicit BpInputFlinger(const sp<IBinder>& impl) :
             BpInterface<IInputFlinger>(impl) { }
 
-    virtual status_t doSomething() {
+    virtual void setInputWindows(const Vector<InputWindowInfo>& inputInfo) {
         Parcel data, reply;
         data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
-        remote()->transact(BnInputFlinger::DO_SOMETHING_TRANSACTION, data, &reply);
-        return reply.readInt32();
+
+        data.writeUint32(static_cast<uint32_t>(inputInfo.size()));
+        for (const auto& info : inputInfo) {
+            info.write(data);
+        }
+        remote()->transact(BnInputFlinger::SET_INPUT_WINDOWS_TRANSACTION, data, &reply);
     }
 };
 
 IMPLEMENT_META_INTERFACE(InputFlinger, "android.input.IInputFlinger");
 
-
 status_t BnInputFlinger::onTransact(
         uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
     switch(code) {
-    case DO_SOMETHING_TRANSACTION: {
+    case SET_INPUT_WINDOWS_TRANSACTION: {
         CHECK_INTERFACE(IInputFlinger, data, reply);
-        reply->writeInt32(0);
+        size_t count = data.readUint32();
+        if (count > data.dataSize()) {
+            return BAD_VALUE;
+        }
+        Vector<InputWindowInfo> handles;
+        handles.setCapacity(count);
+        for (size_t i = 0; i < count; i++) {
+            handles.add(InputWindowInfo(data));
+        }
+        setInputWindows(handles);
         break;
     }
     default:
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 32444f9..e93f3a4 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -247,6 +247,10 @@
     if (s != OK) {
         return s;
     }
+    s = out.writeStrongBinder(mToken);
+    if (s != OK) {
+        return s;
+    }
 
     s = out.writeDupFileDescriptor(getFd());
 
@@ -255,6 +259,7 @@
 
 status_t InputChannel::read(const Parcel& from) {
     mName = from.readString8();
+    mToken = from.readStrongBinder();
 
     int rawFd = from.readFileDescriptor();
     setFd(::dup(rawFd));
@@ -266,6 +271,17 @@
     return OK;
 }
 
+sp<IBinder> InputChannel::getToken() const {
+    return mToken;
+}
+
+void InputChannel::setToken(const sp<IBinder>& token) {
+    if (mToken != nullptr) {
+        ALOGE("Assigning InputChannel (%s) a second handle?", mName.c_str());
+    }
+    mToken = token;
+}
+
 // --- InputPublisher ---
 
 InputPublisher::InputPublisher(const sp<InputChannel>& channel) :
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
index f94faba..f82437e 100644
--- a/libs/input/InputWindow.cpp
+++ b/libs/input/InputWindow.cpp
@@ -135,25 +135,25 @@
     return ret;
 }
 
+InputWindowInfo::InputWindowInfo(const Parcel& from) {
+    *this = read(from);
+}
+
 // --- InputWindowHandle ---
 
 InputWindowHandle::InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
-    inputApplicationHandle(inputApplicationHandle), mInfo(nullptr) {
+    inputApplicationHandle(inputApplicationHandle) {
 }
 
 InputWindowHandle::~InputWindowHandle() {
-    delete mInfo;
 }
 
-void InputWindowHandle::releaseInfo() {
-    if (mInfo) {
-        delete mInfo;
-        mInfo = nullptr;
-    }
+void InputWindowHandle::releaseChannel() {
+    mInfo.inputChannel.clear();
 }
 
 sp<InputChannel> InputWindowHandle::getInputChannel() const {
-    return mInfo ? mInfo->inputChannel : nullptr;
+    return mInfo.inputChannel;
 }
 
 } // namespace android
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index beaf9ee..7efc8bd 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -50,6 +50,7 @@
         "gl/GLExtensions.cpp",
         "gl/GLFramebuffer.cpp",
         "gl/GLImage.cpp",
+        "gl/GLSurface.cpp",
         "gl/Program.cpp",
         "gl/ProgramCache.cpp",
     ],
diff --git a/libs/renderengine/gl/GLES20RenderEngine.cpp b/libs/renderengine/gl/GLES20RenderEngine.cpp
index d35762d..70a4322 100644
--- a/libs/renderengine/gl/GLES20RenderEngine.cpp
+++ b/libs/renderengine/gl/GLES20RenderEngine.cpp
@@ -41,6 +41,7 @@
 #include "GLExtensions.h"
 #include "GLFramebuffer.h"
 #include "GLImage.h"
+#include "GLSurface.h"
 #include "Program.h"
 #include "ProgramCache.h"
 
@@ -274,8 +275,6 @@
 
     // now figure out what version of GL did we actually get
     // NOTE: a dummy surface is not needed if KHR_create_context is supported
-    // TODO(alecmouri): don't create this surface if EGL_KHR_surfaceless_context
-    // is supported.
 
     EGLConfig dummyConfig = config;
     if (dummyConfig == EGL_NO_CONFIG) {
@@ -302,10 +301,10 @@
             break;
         case GLES_VERSION_2_0:
         case GLES_VERSION_3_0:
-            engine = std::make_unique<GLES20RenderEngine>(featureFlags, display, config, ctxt,
-                                                          dummy);
+            engine = std::make_unique<GLES20RenderEngine>(featureFlags);
             break;
     }
+    engine->setEGLHandles(display, config, ctxt);
 
     ALOGI("OpenGL ES informations:");
     ALOGI("vendor    : %s", extensions.getVendor());
@@ -315,6 +314,9 @@
     ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize());
     ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims());
 
+    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglDestroySurface(display, dummy);
+
     return engine;
 }
 
@@ -357,13 +359,11 @@
     return config;
 }
 
-GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags, EGLDisplay display, EGLConfig config,
-                                       EGLContext ctxt, EGLSurface dummy)
+GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags)
       : renderengine::impl::RenderEngine(featureFlags),
-        mEGLDisplay(display),
-        mEGLConfig(config),
-        mEGLContext(ctxt),
-        mDummySurface(dummy),
+        mEGLDisplay(EGL_NO_DISPLAY),
+        mEGLConfig(nullptr),
+        mEGLContext(EGL_NO_CONTEXT),
         mVpWidth(0),
         mVpHeight(0),
         mUseColorManagement(featureFlags & USE_COLOR_MANAGEMENT) {
@@ -422,6 +422,10 @@
     return std::make_unique<GLFramebuffer>(*this);
 }
 
+std::unique_ptr<Surface> GLES20RenderEngine::createSurface() {
+    return std::make_unique<GLSurface>(*this);
+}
+
 std::unique_ptr<Image> GLES20RenderEngine::createImage() {
     return std::make_unique<GLImage>(*this);
 }
@@ -434,6 +438,31 @@
     return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext();
 }
 
+bool GLES20RenderEngine::setCurrentSurface(const Surface& surface) {
+    // Surface is an abstract interface. GLES20RenderEngine only ever
+    // creates GLSurface's, so it is safe to just cast to the actual
+    // type.
+    bool success = true;
+    const GLSurface& glSurface = static_cast<const GLSurface&>(surface);
+    EGLSurface eglSurface = glSurface.getEGLSurface();
+    if (eglSurface != eglGetCurrentSurface(EGL_DRAW)) {
+        success = eglMakeCurrent(mEGLDisplay, eglSurface, eglSurface, mEGLContext) == EGL_TRUE;
+        if (success && glSurface.getAsync()) {
+            eglSwapInterval(mEGLDisplay, 0);
+        }
+        if (success) {
+            mSurfaceHeight = glSurface.getHeight();
+        }
+    }
+
+    return success;
+}
+
+void GLES20RenderEngine::resetCurrentSurface() {
+    eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    mSurfaceHeight = 0;
+}
+
 base::unique_fd GLES20RenderEngine::flush() {
     if (!GLExtensions::getInstance().hasNativeFenceSync()) {
         return base::unique_fd();
@@ -547,7 +576,7 @@
 
 void GLES20RenderEngine::setScissor(const Rect& region) {
     // Invert y-coordinate to map to GL-space.
-    int32_t canvasHeight = mFboHeight;
+    int32_t canvasHeight = mRenderToFbo ? mFboHeight : mSurfaceHeight;
     int32_t glBottom = canvasHeight - region.bottom;
 
     glScissor(region.left, glBottom, region.getWidth(), region.getHeight());
@@ -590,6 +619,7 @@
     glBindFramebuffer(GL_FRAMEBUFFER, framebufferName);
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureName, 0);
 
+    mRenderToFbo = true;
     mFboHeight = glFramebuffer->getBufferHeight();
 
     uint32_t glStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -601,10 +631,17 @@
 }
 
 void GLES20RenderEngine::unbindFrameBuffer(Framebuffer* /* framebuffer */) {
+    mRenderToFbo = false;
     mFboHeight = 0;
 
     // back to main framebuffer
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+    // Workaround for b/77935566 to force the EGL driver to release the
+    // screenshot buffer
+    setScissor(Rect::EMPTY_RECT);
+    clearWithColor(0.0, 0.0, 0.0, 0.0);
+    disableScissor();
 }
 
 void GLES20RenderEngine::checkErrors() const {
@@ -629,7 +666,9 @@
     int32_t r = sourceCrop.right;
     int32_t b = sourceCrop.bottom;
     int32_t t = sourceCrop.top;
-    std::swap(t, b);
+    if (mRenderToFbo) {
+        std::swap(t, b);
+    }
     mat4 m = mat4::ortho(l, r, b, t, 0, 1);
 
     // Apply custom rotation to the projection.
@@ -935,6 +974,12 @@
     return (isInputHdrDataSpace || isOutputHdrDataSpace) && inputTransfer != outputTransfer;
 }
 
+void GLES20RenderEngine::setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt) {
+    mEGLDisplay = display;
+    mEGLConfig = config;
+    mEGLContext = ctxt;
+}
+
 } // namespace gl
 } // namespace renderengine
 } // namespace android
diff --git a/libs/renderengine/gl/GLES20RenderEngine.h b/libs/renderengine/gl/GLES20RenderEngine.h
index 6c50938..148df2f 100644
--- a/libs/renderengine/gl/GLES20RenderEngine.h
+++ b/libs/renderengine/gl/GLES20RenderEngine.h
@@ -40,21 +40,24 @@
 namespace gl {
 
 class GLImage;
+class GLSurface;
 
 class GLES20RenderEngine : public impl::RenderEngine {
 public:
     static std::unique_ptr<GLES20RenderEngine> create(int hwcFormat, uint32_t featureFlags);
     static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
 
-    GLES20RenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag
-                       EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy);
+    GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag
     ~GLES20RenderEngine() override;
 
     std::unique_ptr<Framebuffer> createFramebuffer() override;
+    std::unique_ptr<Surface> createSurface() override;
     std::unique_ptr<Image> createImage() override;
 
     void primeCache() const override;
     bool isCurrent() const override;
+    bool setCurrentSurface(const Surface& surface) override;
+    void resetCurrentSurface() override;
     base::unique_fd flush() override;
     bool finish() override;
     bool waitFence(base::unique_fd fenceFd) override;
@@ -117,12 +120,11 @@
     // with PQ or HLG transfer function.
     bool isHdrDataSpace(const ui::Dataspace dataSpace) const;
     bool needsXYZTransformMatrix() const;
-    void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy);
+    void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt);
 
     EGLDisplay mEGLDisplay;
     EGLConfig mEGLConfig;
     EGLContext mEGLContext;
-    EGLSurface mDummySurface;
     GLuint mProtectedTexName;
     GLint mMaxViewportDims[2];
     GLint mMaxTextureSize;
@@ -143,6 +145,8 @@
     mat4 mBt2020ToSrgb;
     mat4 mBt2020ToDisplayP3;
 
+    bool mRenderToFbo = false;
+    int32_t mSurfaceHeight = 0;
     int32_t mFboHeight = 0;
 
     // Current dataspace of layer being rendered
diff --git a/libs/renderengine/gl/GLSurface.cpp b/libs/renderengine/gl/GLSurface.cpp
new file mode 100644
index 0000000..2d694e9
--- /dev/null
+++ b/libs/renderengine/gl/GLSurface.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright 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 "GLSurface.h"
+
+#include <android/native_window.h>
+#include <log/log.h>
+#include <ui/PixelFormat.h>
+#include "GLES20RenderEngine.h"
+
+namespace android {
+namespace renderengine {
+namespace gl {
+
+GLSurface::GLSurface(const GLES20RenderEngine& engine)
+      : mEGLDisplay(engine.getEGLDisplay()), mEGLConfig(engine.getEGLConfig()) {
+    // RE does not assume any config when EGL_KHR_no_config_context is supported
+    if (mEGLConfig == EGL_NO_CONFIG_KHR) {
+        mEGLConfig =
+                GLES20RenderEngine::chooseEglConfig(mEGLDisplay, PIXEL_FORMAT_RGBA_8888, false);
+    }
+}
+
+GLSurface::~GLSurface() {
+    setNativeWindow(nullptr);
+}
+
+void GLSurface::setNativeWindow(ANativeWindow* window) {
+    if (mEGLSurface != EGL_NO_SURFACE) {
+        eglDestroySurface(mEGLDisplay, mEGLSurface);
+        mEGLSurface = EGL_NO_SURFACE;
+        mSurfaceWidth = 0;
+        mSurfaceHeight = 0;
+    }
+
+    mWindow = window;
+    if (mWindow) {
+        mEGLSurface = eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mWindow, nullptr);
+        mSurfaceWidth = ANativeWindow_getWidth(window);
+        mSurfaceHeight = ANativeWindow_getHeight(window);
+    }
+}
+
+void GLSurface::swapBuffers() const {
+    if (!eglSwapBuffers(mEGLDisplay, mEGLSurface)) {
+        EGLint error = eglGetError();
+
+        const char format[] = "eglSwapBuffers(%p, %p) failed with 0x%08x";
+        if (mCritical || error == EGL_CONTEXT_LOST) {
+            LOG_ALWAYS_FATAL(format, mEGLDisplay, mEGLSurface, error);
+        } else {
+            ALOGE(format, mEGLDisplay, mEGLSurface, error);
+        }
+    }
+}
+
+EGLint GLSurface::queryConfig(EGLint attrib) const {
+    EGLint value;
+    if (!eglGetConfigAttrib(mEGLDisplay, mEGLConfig, attrib, &value)) {
+        value = 0;
+    }
+
+    return value;
+}
+
+int32_t GLSurface::queryRedSize() const {
+    return queryConfig(EGL_RED_SIZE);
+}
+
+int32_t GLSurface::queryGreenSize() const {
+    return queryConfig(EGL_GREEN_SIZE);
+}
+
+int32_t GLSurface::queryBlueSize() const {
+    return queryConfig(EGL_BLUE_SIZE);
+}
+
+int32_t GLSurface::queryAlphaSize() const {
+    return queryConfig(EGL_ALPHA_SIZE);
+}
+
+int32_t GLSurface::getWidth() const {
+    return mSurfaceWidth;
+}
+
+int32_t GLSurface::getHeight() const {
+    return mSurfaceHeight;
+}
+
+} // namespace gl
+} // namespace renderengine
+} // namespace android
diff --git a/libs/renderengine/gl/GLSurface.h b/libs/renderengine/gl/GLSurface.h
new file mode 100644
index 0000000..092d371
--- /dev/null
+++ b/libs/renderengine/gl/GLSurface.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include <EGL/egl.h>
+#include <android-base/macros.h>
+#include <renderengine/Surface.h>
+
+struct ANativeWindow;
+
+namespace android {
+namespace renderengine {
+namespace gl {
+
+class GLES20RenderEngine;
+
+class GLSurface final : public renderengine::Surface {
+public:
+    GLSurface(const GLES20RenderEngine& engine);
+    ~GLSurface() override;
+
+    // renderengine::Surface implementation
+    void setCritical(bool enable) override { mCritical = enable; }
+    void setAsync(bool enable) override { mAsync = enable; }
+
+    void setNativeWindow(ANativeWindow* window) override;
+    void swapBuffers() const override;
+
+    int32_t queryRedSize() const override;
+    int32_t queryGreenSize() const override;
+    int32_t queryBlueSize() const override;
+    int32_t queryAlphaSize() const override;
+
+    bool getAsync() const { return mAsync; }
+    EGLSurface getEGLSurface() const { return mEGLSurface; }
+
+    int32_t getWidth() const override;
+    int32_t getHeight() const override;
+
+private:
+    EGLint queryConfig(EGLint attrib) const;
+
+    EGLDisplay mEGLDisplay;
+    EGLConfig mEGLConfig;
+
+    bool mCritical = false;
+    bool mAsync = false;
+
+    int32_t mSurfaceWidth = 0;
+    int32_t mSurfaceHeight = 0;
+
+    ANativeWindow* mWindow = nullptr;
+    EGLSurface mEGLSurface = EGL_NO_SURFACE;
+
+    DISALLOW_COPY_AND_ASSIGN(GLSurface);
+};
+
+} // namespace gl
+} // namespace renderengine
+} // namespace android
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index 22891c4..becb3c3 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -48,6 +48,7 @@
 class BindNativeBufferAsFramebuffer;
 class Image;
 class Mesh;
+class Surface;
 class Texture;
 
 namespace impl {
@@ -71,6 +72,7 @@
     // used to support legacy behavior.
 
     virtual std::unique_ptr<Framebuffer> createFramebuffer() = 0;
+    virtual std::unique_ptr<Surface> createSurface() = 0;
     virtual std::unique_ptr<Image> createImage() = 0;
 
     virtual void primeCache() const = 0;
@@ -82,6 +84,8 @@
     virtual bool useWaitSync() const = 0;
 
     virtual bool isCurrent() const = 0;
+    virtual bool setCurrentSurface(const Surface& surface) = 0;
+    virtual void resetCurrentSurface() = 0;
 
     // helpers
     // flush submits RenderEngine command stream for execution and returns a
diff --git a/libs/renderengine/include/renderengine/Surface.h b/libs/renderengine/include/renderengine/Surface.h
new file mode 100644
index 0000000..ba7331d
--- /dev/null
+++ b/libs/renderengine/include/renderengine/Surface.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+struct ANativeWindow;
+
+namespace android {
+namespace renderengine {
+
+class Surface {
+public:
+    virtual ~Surface() = default;
+
+    virtual void setCritical(bool enable) = 0;
+    virtual void setAsync(bool enable) = 0;
+
+    virtual void setNativeWindow(ANativeWindow* window) = 0;
+    virtual void swapBuffers() const = 0;
+
+    virtual int32_t queryRedSize() const = 0;
+    virtual int32_t queryGreenSize() const = 0;
+    virtual int32_t queryBlueSize() const = 0;
+    virtual int32_t queryAlphaSize() const = 0;
+
+    virtual int32_t getWidth() const = 0;
+    virtual int32_t getHeight() const = 0;
+};
+
+} // namespace renderengine
+} // namespace android
diff --git a/opengl/include/EGL/Platform.h b/opengl/include/EGL/Platform.h
index 624d31f..f2b501c 100644
--- a/opengl/include/EGL/Platform.h
+++ b/opengl/include/EGL/Platform.h
@@ -36,6 +36,7 @@
 namespace angle
 {
 struct WorkaroundsD3D;
+struct FeaturesVk;
 using TraceEventHandle = uint64_t;
 using EGLDisplayType   = void *;
 struct PlatformMethods;
@@ -233,6 +234,13 @@
 {
 }
 
+using OverrideFeaturesVkFunc = void (*)(PlatformMethods *platform,
+                                        angle::FeaturesVk *workaroundsVulkan);
+inline void DefaultOverrideFeaturesVk(PlatformMethods *platform,
+                                      angle::FeaturesVk *workaroundsVulkan)
+{
+}
+
 // Callback on a successful program link with the program binary. Can be used to store
 // shaders to disk. Keys are a 160-bit SHA-1 hash.
 using ProgramKeyType   = std::array<uint8_t, 20>;
@@ -262,6 +270,7 @@
     OP(histogramSparse, HistogramSparse)                         \
     OP(histogramBoolean, HistogramBoolean)                       \
     OP(overrideWorkaroundsD3D, OverrideWorkaroundsD3D)           \
+    OP(overrideFeaturesVk, OverrideFeaturesVk)                   \
     OP(cacheProgram, CacheProgram)
 
 #define ANGLE_PLATFORM_METHOD_DEF(Name, CapsName) CapsName##Func Name = Default##CapsName;
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index e4ca6bc..150896c 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -62,7 +62,7 @@
     status_t cmd_vkjson(int out, int err);
 }
 
-const char* const GpuService::SERVICE_NAME = "gpuservice";
+const char* const GpuService::SERVICE_NAME = "gpu";
 
 GpuService::GpuService() = default;
 
diff --git a/services/gpuservice/gpuservice.rc b/services/gpuservice/gpuservice.rc
index d23cf46..65a5c27 100644
--- a/services/gpuservice/gpuservice.rc
+++ b/services/gpuservice/gpuservice.rc
@@ -1,4 +1,4 @@
-service gpuservice /system/bin/gpuservice
+service gpu /system/bin/gpuservice
     class core
     user gpu_service
     group graphics
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 9a65452..7812cb2 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -35,6 +35,7 @@
         "libutils",
         "libui",
         "libhardware_legacy",
+        "libutils"
     ],
 
     cflags: [
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 2e984d9..0c9e04b 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -58,6 +58,7 @@
 #include <utils/Trace.h>
 #include <powermanager/PowerManager.h>
 #include <ui/Region.h>
+#include <binder/Binder.h>
 
 #define INDENT "  "
 #define INDENT2 "    "
@@ -818,7 +819,7 @@
             sp<InputWindowHandle> focusedWindowHandle =
                     getValueByKey(mFocusedWindowHandlesByDisplay, getTargetDisplayId(entry));
             if (focusedWindowHandle != nullptr) {
-                commandEntry->inputWindowHandle = focusedWindowHandle;
+                commandEntry->inputChannel = focusedWindowHandle->getInputChannel();
             }
             commandEntry->keyEntry = entry;
             entry->refCount += 1;
@@ -1064,6 +1065,13 @@
     }
 }
 
+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) {
@@ -1078,17 +1086,10 @@
             ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
             if (connectionIndex >= 0) {
                 sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
-                sp<InputWindowHandle> windowHandle = connection->inputWindowHandle;
+                sp<IBinder> token = connection->inputChannel->getToken();
 
-                if (windowHandle != nullptr) {
-                    const InputWindowInfo* info = windowHandle->getInfo();
-                    if (info) {
-                        ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(info->displayId);
-                        if (stateIndex >= 0) {
-                            mTouchStatesByDisplay.editValueAt(stateIndex).removeWindow(
-                                    windowHandle);
-                        }
-                    }
+                if (token != nullptr) {
+                    removeWindowByTokenLocked(token);
                 }
 
                 if (connection->status == Connection::STATUS_NORMAL) {
@@ -1168,7 +1169,8 @@
             goto Unresponsive;
         }
 
-        ALOGI("Dropping event because there is no focused window or focused application.");
+        ALOGI("Dropping event because there is no focused window or focused application in display "
+                "%" PRId32 ".", displayId);
         injectionResult = INPUT_EVENT_INJECTION_FAILED;
         goto Failed;
     }
@@ -1254,7 +1256,8 @@
         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.");
+            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;
@@ -1270,7 +1273,8 @@
         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.");
+        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;
@@ -1335,7 +1339,8 @@
             // Try to assign the pointer to the first foreground window we find, if there is one.
             newTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle();
             if (newTouchedWindowHandle == nullptr) {
-                ALOGI("Dropping event because there is no touchable window at (%d, %d).", x, y);
+                ALOGI("Dropping event because there is no touchable window at (%d, %d) in display "
+                        "%" PRId32 ".", x, y, displayId);
                 injectionResult = INPUT_EVENT_INJECTION_FAILED;
                 goto Failed;
             }
@@ -1373,7 +1378,7 @@
         if (! mTempTouchState.down) {
 #if DEBUG_FOCUS
             ALOGD("Dropping event because the pointer is not down or we previously "
-                    "dropped the pointer down event.");
+                    "dropped the pointer down event in display %" PRId32, displayId);
 #endif
             injectionResult = INPUT_EVENT_INJECTION_FAILED;
             goto Failed;
@@ -1393,9 +1398,10 @@
             if (oldTouchedWindowHandle != newTouchedWindowHandle
                     && newTouchedWindowHandle != nullptr) {
 #if DEBUG_FOCUS
-                ALOGD("Touch is slipping out of window %s into window %s.",
+                ALOGD("Touch is slipping out of window %s into window %s in display %" PRId32,
                         oldTouchedWindowHandle->getName().c_str(),
-                        newTouchedWindowHandle->getName().c_str());
+                        newTouchedWindowHandle->getName().c_str(),
+                        displayId);
 #endif
                 // Make a slippery exit from the old window.
                 mTempTouchState.addOrUpdateWindow(oldTouchedWindowHandle,
@@ -1464,7 +1470,8 @@
         }
         if (! haveForegroundWindow) {
 #if DEBUG_FOCUS
-            ALOGD("Dropping event because there is no touched foreground window to receive it.");
+            ALOGD("Dropping event because there is no touched foreground window in display %" PRId32
+                    " to receive it.", displayId);
 #endif
             injectionResult = INPUT_EVENT_INJECTION_FAILED;
             goto Failed;
@@ -1689,7 +1696,7 @@
     } else {
         // If there is no monitor channel registered or all monitor channel unregistered,
         // the display can't detect the extra system gesture by a copy of input events.
-        ALOGW("There is no monitor channel found in display=%" PRId32, displayId);
+        ALOGW("There is no monitor channel found in display %" PRId32, displayId);
     }
 }
 
@@ -3011,11 +3018,13 @@
         const Vector<sp<InputWindowHandle>> windowHandles = it.second;
         size_t numWindows = windowHandles.size();
         for (size_t i = 0; i < numWindows; i++) {
-            if (windowHandles.itemAt(i) == windowHandle) {
+            if (windowHandles.itemAt(i)->getInputChannel()->getToken()
+                    == windowHandle->getInputChannel()->getToken()) {
                 if (windowHandle->getInfo()->displayId != it.first) {
-                    ALOGE("Found window %s in display %d, but it should belong to display %d",
-                        windowHandle->getName().c_str(), it.first,
-                        windowHandle->getInfo()->displayId);
+                    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;
             }
@@ -3034,7 +3043,7 @@
 void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle>>& inputWindowHandles,
         int32_t displayId) {
 #if DEBUG_FOCUS
-    ALOGD("setInputWindows");
+    ALOGD("setInputWindows displayId=%" PRId32, displayId);
 #endif
     { // acquire lock
         AutoMutex _l(mLock);
@@ -3085,8 +3094,8 @@
         if (oldFocusedWindowHandle != newFocusedWindowHandle) {
             if (oldFocusedWindowHandle != nullptr) {
 #if DEBUG_FOCUS
-                ALOGD("Focus left window: %s",
-                        oldFocusedWindowHandle->getName().c_str());
+                ALOGD("Focus left window: %s in display %" PRId32,
+                        oldFocusedWindowHandle->getName().c_str(), displayId);
 #endif
                 sp<InputChannel> focusedInputChannel = oldFocusedWindowHandle->getInputChannel();
                 if (focusedInputChannel != nullptr) {
@@ -3099,8 +3108,8 @@
             }
             if (newFocusedWindowHandle != nullptr) {
 #if DEBUG_FOCUS
-                ALOGD("Focus entered window: %s",
-                        newFocusedWindowHandle->getName().c_str());
+                ALOGD("Focus entered window: %s in display %" PRId32,
+                        newFocusedWindowHandle->getName().c_str(), displayId);
 #endif
                 mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle;
             }
@@ -3113,8 +3122,8 @@
                 TouchedWindow& touchedWindow = state.windows.editItemAt(i);
                 if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
 #if DEBUG_FOCUS
-                    ALOGD("Touched window was removed: %s",
-                            touchedWindow.windowHandle->getName().c_str());
+                    ALOGD("Touched window was removed: %s in display %" PRId32,
+                            touchedWindow.windowHandle->getName().c_str(), displayId);
 #endif
                     sp<InputChannel> touchedInputChannel =
                             touchedWindow.windowHandle->getInputChannel();
@@ -3142,7 +3151,7 @@
 #if DEBUG_FOCUS
                 ALOGD("Window went away: %s", oldWindowHandle->getName().c_str());
 #endif
-                oldWindowHandle->releaseInfo();
+                oldWindowHandle->releaseChannel();
             }
         }
     } // release lock
@@ -3154,7 +3163,7 @@
 void InputDispatcher::setFocusedApplication(
         int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) {
 #if DEBUG_FOCUS
-    ALOGD("setFocusedApplication");
+    ALOGD("setFocusedApplication displayId=%" PRId32, displayId);
 #endif
     { // acquire lock
         AutoMutex _l(mLock);
@@ -3469,7 +3478,7 @@
     if (!mWindowHandlesByDisplay.empty()) {
        for (auto& it : mWindowHandlesByDisplay) {
             const Vector<sp<InputWindowHandle>> windowHandles = it.second;
-            dump += StringPrintf(INDENT "Display: %d\n", it.first);
+            dump += StringPrintf(INDENT "Display: %" PRId32 "\n", it.first);
             if (!windowHandles.isEmpty()) {
                 dump += INDENT2 "Windows:\n";
                 for (size_t i = 0; i < windowHandles.size(); i++) {
@@ -3509,7 +3518,7 @@
     if (!mMonitoringChannelsByDisplay.empty()) {
        for (auto& it : mMonitoringChannelsByDisplay) {
             const Vector<sp<InputChannel>>& monitoringChannels = it.second;
-            dump += INDENT "MonitoringChannels in Display %d:\n";
+            dump += StringPrintf(INDENT "MonitoringChannels in display %" PRId32 ":\n", it.first);
             const size_t numChannels = monitoringChannels.size();
             for (size_t i = 0; i < numChannels; i++) {
                 const sp<InputChannel>& channel = monitoringChannels[i];
@@ -3632,8 +3641,7 @@
             mConfig.keyRepeatTimeout * 0.000001f);
 }
 
-status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
-        const sp<InputWindowHandle>& inputWindowHandle, int32_t displayId) {
+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);
@@ -3642,17 +3650,20 @@
     { // acquire lock
         AutoMutex _l(mLock);
 
+        // If InputWindowHandle is null and displayId is not ADISPLAY_ID_NONE,
+        // treat inputChannel as monitor channel for displayId.
+        bool monitor = inputChannel->getToken() == nullptr && displayId != ADISPLAY_ID_NONE;
+        if (monitor) {
+            inputChannel->setToken(new BBinder());
+        }
+
         if (getConnectionIndexLocked(inputChannel) >= 0) {
             ALOGW("Attempted to register already registered input channel '%s'",
                     inputChannel->getName().c_str());
             return BAD_VALUE;
         }
 
-        // If InputWindowHandle is null and displayId is not ADISPLAY_ID_NONE,
-        // treat inputChannel as monitor channel for displayId.
-        bool monitor = inputWindowHandle == nullptr && displayId != ADISPLAY_ID_NONE;
-
-        sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);
+        sp<Connection> connection = new Connection(inputChannel, monitor);
 
         int fd = inputChannel->getFd();
         mConnectionsByFd.add(fd, connection);
@@ -3737,11 +3748,14 @@
 }
 
 ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
-    ssize_t connectionIndex = mConnectionsByFd.indexOfKey(inputChannel->getFd());
-    if (connectionIndex >= 0) {
-        sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
-        if (connection->inputChannel.get() == inputChannel.get()) {
-            return connectionIndex;
+    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;
         }
     }
 
@@ -3798,7 +3812,7 @@
     CommandEntry* commandEntry = postCommandLocked(
             & InputDispatcher::doNotifyANRLockedInterruptible);
     commandEntry->inputApplicationHandle = applicationHandle;
-    commandEntry->inputWindowHandle = windowHandle;
+    commandEntry->inputChannel = windowHandle != nullptr ? windowHandle->getInputChannel() : nullptr;
     commandEntry->reason = reason;
 }
 
@@ -3818,7 +3832,7 @@
     if (connection->status != Connection::STATUS_ZOMBIE) {
         mLock.unlock();
 
-        mPolicy->notifyInputChannelBroken(connection->inputWindowHandle);
+        mPolicy->notifyInputChannelBroken(connection->inputChannel->getToken());
 
         mLock.lock();
     }
@@ -3829,14 +3843,14 @@
     mLock.unlock();
 
     nsecs_t newTimeout = mPolicy->notifyANR(
-            commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle,
+            commandEntry->inputApplicationHandle,
+            commandEntry->inputChannel ? commandEntry->inputChannel->getToken() : nullptr,
             commandEntry->reason);
 
     mLock.lock();
 
     resumeAfterTargetsNotReadyTimeoutLocked(newTimeout,
-            commandEntry->inputWindowHandle != nullptr
-                    ? commandEntry->inputWindowHandle->getInputChannel() : nullptr);
+            commandEntry->inputChannel);
 }
 
 void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
@@ -3849,7 +3863,9 @@
     mLock.unlock();
 
     android::base::Timer t;
-    nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
+    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",
@@ -3950,7 +3966,7 @@
 
                 mLock.unlock();
 
-                mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
+                mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(),
                         &event, keyEntry->policyFlags, &event);
 
                 mLock.lock();
@@ -3995,7 +4011,7 @@
 
             mLock.unlock();
 
-            bool fallback = mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
+            bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(),
                     &event, keyEntry->policyFlags, &event);
 
             mLock.lock();
@@ -4711,9 +4727,8 @@
 
 // --- InputDispatcher::Connection ---
 
-InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel,
-        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) :
-        status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
+InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel, bool monitor) :
+        status(STATUS_NORMAL), inputChannel(inputChannel),
         monitor(monitor),
         inputPublisher(inputChannel), inputPublisherBlocked(false) {
 }
@@ -4722,8 +4737,8 @@
 }
 
 const std::string InputDispatcher::Connection::getWindowName() const {
-    if (inputWindowHandle != nullptr) {
-        return inputWindowHandle->getName();
+    if (inputChannel != nullptr) {
+        return inputChannel->getName();
     }
     if (monitor) {
         return "monitor";
@@ -4830,6 +4845,15 @@
     }
 }
 
+void InputDispatcher::TouchState::removeWindowByToken(const sp<IBinder>& token) {
+    for (size_t i = 0; i < windows.size(); i++) {
+        if (windows.itemAt(i).windowHandle->getInputChannel()->getToken() == token) {
+            windows.removeAt(i);
+            return;
+        }
+    }
+}
+
 void InputDispatcher::TouchState::filterNonAsIsTouchWindows() {
     for (size_t i = 0 ; i < windows.size(); ) {
         TouchedWindow& window = windows.editItemAt(i);
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 5efb2fa..5016082 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -208,11 +208,11 @@
     /* 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<InputWindowHandle>& inputWindowHandle,
+            const sp<IBinder>& token,
             const std::string& reason) = 0;
 
     /* Notifies the system that an input channel is unrecoverably broken. */
-    virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) = 0;
+    virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0;
 
     /* Gets the input dispatcher configuration. */
     virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0;
@@ -243,12 +243,12 @@
     virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
 
     /* Allows the policy a chance to intercept a key before dispatching. */
-    virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
+    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<InputWindowHandle>& inputWindowHandle,
+    virtual bool dispatchUnhandledKey(const sp<IBinder>& token,
             const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
 
     /* Notifies the policy about switch events.
@@ -352,8 +352,8 @@
      *
      * This method may be called on any thread (usually by the input manager).
      */
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
-            const sp<InputWindowHandle>& inputWindowHandle, int32_t displayId) = 0;
+    virtual status_t registerInputChannel(
+            const sp<InputChannel>& inputChannel, int32_t displayId) = 0;
 
     /* Unregister input channels that will no longer receive input events.
      *
@@ -413,7 +413,7 @@
             const sp<InputChannel>& toChannel);
 
     virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
-            const sp<InputWindowHandle>& inputWindowHandle, int32_t displayId);
+            int32_t displayId);
     virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
 
 private:
@@ -617,11 +617,11 @@
         nsecs_t eventTime;
         KeyEntry* keyEntry;
         sp<InputApplicationHandle> inputApplicationHandle;
-        sp<InputWindowHandle> inputWindowHandle;
         std::string reason;
         int32_t userActivityEventType;
         uint32_t seq;
         bool handled;
+        sp<InputChannel> inputChannel;
     };
 
     // Generic queue implementation.
@@ -834,7 +834,6 @@
 
         Status status;
         sp<InputChannel> inputChannel; // never null
-        sp<InputWindowHandle> inputWindowHandle; // may be null
         bool monitor;
         InputPublisher inputPublisher;
         InputState inputState;
@@ -850,8 +849,7 @@
         // yet received a "finished" response from the application.
         Queue<DispatchEntry> waitQueue;
 
-        explicit Connection(const sp<InputChannel>& inputChannel,
-                const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
+        explicit Connection(const sp<InputChannel>& inputChannel, bool monitor);
 
         inline const std::string getInputChannelName() const { return inputChannel->getName(); }
 
@@ -1007,6 +1005,7 @@
         void addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
                 int32_t targetFlags, BitSet32 pointerIds);
         void removeWindow(const sp<InputWindowHandle>& windowHandle);
+        void removeWindowByToken(const sp<IBinder>& token);
         void filterNonAsIsTouchWindows();
         sp<InputWindowHandle> getFirstForegroundWindowHandle() const;
         bool isSlippery() const;
@@ -1062,6 +1061,9 @@
             const sp<InputApplicationHandle>& applicationHandle,
             const sp<InputWindowHandle>& windowHandle,
             nsecs_t* nextWakeupTime, const char* reason);
+
+    void removeWindowByTokenLocked(const sp<IBinder>& token);
+
     void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
             const sp<InputChannel>& inputChannel);
     nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime);
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 519faa6..40ca6a7 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -21,6 +21,7 @@
 #include "InputManager.h"
 
 #include <log/log.h>
+#include <unordered_map>
 
 namespace android {
 
@@ -90,4 +91,39 @@
     return mDispatcher;
 }
 
+class BinderApplicationHandle : public InputApplicationHandle {
+public:
+    BinderApplicationHandle() = default;
+
+    bool updateInfo() override {
+        return true;
+    }
+};
+
+class BinderWindowHandle : public InputWindowHandle {
+public:
+    BinderWindowHandle(const InputWindowInfo& info) :
+        InputWindowHandle(new BinderApplicationHandle()) {
+
+        mInfo = info;
+    }
+
+    bool updateInfo() override {
+        return true;
+    }
+};
+
+void InputManager::setInputWindows(const Vector<InputWindowInfo>& infos) {
+    std::unordered_map<int32_t, Vector<sp<InputWindowHandle>>> handlesPerDisplay;
+
+    Vector<sp<InputWindowHandle>> handles;
+    for (const auto& info : infos) {
+        handlesPerDisplay.emplace(info.displayId, Vector<sp<InputWindowHandle>>());
+        handlesPerDisplay[info.displayId].add(new BinderWindowHandle(info));
+    }
+    for (auto const& i : handlesPerDisplay) {
+        mDispatcher->setInputWindows(i.second, i.first);
+    }
+}
+
 } // namespace android
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 92e0af2..d0e4cb0 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -27,6 +27,8 @@
 
 #include <input/Input.h>
 #include <input/InputTransport.h>
+
+#include <input/IInputFlinger.h>
 #include <utils/Errors.h>
 #include <utils/Vector.h>
 #include <utils/Timers.h>
@@ -72,7 +74,7 @@
     virtual sp<InputDispatcherInterface> getDispatcher() = 0;
 };
 
-class InputManager : public InputManagerInterface {
+class InputManager : public InputManagerInterface, public BnInputFlinger {
 protected:
     virtual ~InputManager();
 
@@ -93,6 +95,8 @@
     virtual sp<InputReaderInterface> getReader();
     virtual sp<InputDispatcherInterface> getDispatcher();
 
+    virtual void setInputWindows(const Vector<InputWindowInfo>& handles);
+
 private:
     sp<InputReaderInterface> mReader;
     sp<InputReaderThread> mReaderThread;
diff --git a/services/inputflinger/host/Android.bp b/services/inputflinger/host/Android.bp
index 775dbdc..0e48f24 100644
--- a/services/inputflinger/host/Android.bp
+++ b/services/inputflinger/host/Android.bp
@@ -30,6 +30,9 @@
         "libutils",
         "libhardware",
     ],
+    static_libs: [
+        "libarect",
+    ],
 
     cflags: [
         "-Wall",
@@ -54,7 +57,10 @@
     shared_libs: [
         "libbinder",
         "libinputflingerhost",
-        "libutils",
+        "libutils"
+    ],
+    static_libs: [
+        "libarect",
     ],
 
     init_rc: ["inputflinger.rc"],
diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h
index 39e69e5..15ca7b3 100644
--- a/services/inputflinger/host/InputFlinger.h
+++ b/services/inputflinger/host/InputFlinger.h
@@ -39,6 +39,7 @@
     InputFlinger() ANDROID_API;
 
     virtual status_t dump(int fd, const Vector<String16>& args);
+    void setInputWindows(const Vector<InputWindowInfo>&) {}
 
 private:
     virtual ~InputFlinger();
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index a1cd71c..ea42855 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -15,6 +15,7 @@
     ],
     shared_libs: [
         "libbase",
+        "libbinder",
         "libcutils",
         "liblog",
         "libutils",
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index c6eaf9f..e860db5 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -16,6 +16,8 @@
 
 #include "../InputDispatcher.h"
 
+#include <binder/Binder.h>
+
 #include <gtest/gtest.h>
 #include <linux/input.h>
 
@@ -53,12 +55,12 @@
     }
 
     virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
-            const sp<InputWindowHandle>&,
+            const sp<IBinder>&,
             const std::string&) {
         return 0;
     }
 
-    virtual void notifyInputChannelBroken(const sp<InputWindowHandle>&) {
+    virtual void notifyInputChannelBroken(const sp<IBinder>&) {
     }
 
     virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
@@ -75,12 +77,12 @@
     virtual void interceptMotionBeforeQueueing(nsecs_t, uint32_t&) {
     }
 
-    virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>&,
+    virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&,
             const KeyEvent*, uint32_t) {
         return 0;
     }
 
-    virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>&,
+    virtual bool dispatchUnhandledKey(const sp<IBinder>&,
             const KeyEvent*, uint32_t, KeyEvent*) {
         return false;
     }
@@ -336,6 +338,7 @@
             const std::string name, int32_t displayId) :
                 mDispatcher(dispatcher), mName(name), mDisplayId(displayId) {
             InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
+
             mConsumer = new InputConsumer(mClientChannel);
         }
 
@@ -366,34 +369,32 @@
             InputWindowHandle(inputApplicationHandle),
             FakeInputReceiver(dispatcher, name, displayId),
             mFocused(false) {
-            mDispatcher->registerInputChannel(mServerChannel, this, displayId);
+            mServerChannel->setToken(new BBinder());
+            mDispatcher->registerInputChannel(mServerChannel, displayId);
     }
 
     virtual bool updateInfo() {
-        if (!mInfo) {
-            mInfo = new InputWindowInfo();
-        }
-        mInfo->inputChannel = mServerChannel;
-        mInfo->name = mName;
-        mInfo->layoutParamsFlags = 0;
-        mInfo->layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
-        mInfo->dispatchingTimeout = DISPATCHING_TIMEOUT;
-        mInfo->frameLeft = 0;
-        mInfo->frameTop = 0;
-        mInfo->frameRight = WIDTH;
-        mInfo->frameBottom = HEIGHT;
-        mInfo->scaleFactor = 1.0;
-        mInfo->addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
-        mInfo->visible = true;
-        mInfo->canReceiveKeys = true;
-        mInfo->hasFocus = mFocused;
-        mInfo->hasWallpaper = false;
-        mInfo->paused = false;
-        mInfo->layer = 0;
-        mInfo->ownerPid = INJECTOR_PID;
-        mInfo->ownerUid = INJECTOR_UID;
-        mInfo->inputFeatures = 0;
-        mInfo->displayId = mDisplayId;
+        mInfo.inputChannel = mServerChannel;
+        mInfo.name = mName;
+        mInfo.layoutParamsFlags = 0;
+        mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
+        mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
+        mInfo.frameLeft = 0;
+        mInfo.frameTop = 0;
+        mInfo.frameRight = WIDTH;
+        mInfo.frameBottom = HEIGHT;
+        mInfo.scaleFactor = 1.0;
+        mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
+        mInfo.visible = true;
+        mInfo.canReceiveKeys = true;
+        mInfo.hasFocus = mFocused;
+        mInfo.hasWallpaper = false;
+        mInfo.paused = false;
+        mInfo.layer = 0;
+        mInfo.ownerPid = INJECTOR_PID;
+        mInfo.ownerUid = INJECTOR_UID;
+        mInfo.inputFeatures = 0;
+        mInfo.displayId = mDisplayId;
 
         return true;
     }
@@ -529,6 +530,34 @@
     windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
 }
 
+TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
+    sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+
+    sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
+            ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
+            ADISPLAY_ID_DEFAULT);
+
+    windowTop->setFocus();
+
+    Vector<sp<InputWindowHandle>> inputWindowHandles;
+    inputWindowHandles.add(windowTop);
+    inputWindowHandles.add(windowSecond);
+
+    mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
+
+    // Release channel for window is no longer valid.
+    windowTop->releaseChannel();
+
+    // Test inject a motion down, should timeout because of no target channel.
+    ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
+            << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
+
+    // Top window is invalid, so it should not receive any input event.
+    windowTop->assertNoEvents();
+    windowSecond->assertNoEvents();
+}
+
 /* Test InputDispatcher for MultiDisplay */
 class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
 public:
@@ -624,7 +653,7 @@
 public:
     FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
             int32_t displayId) : FakeInputReceiver(dispatcher, name, displayId) {
-        mDispatcher->registerInputChannel(mServerChannel, nullptr, displayId);
+        mDispatcher->registerInputChannel(mServerChannel, displayId);
     }
 };
 
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 9abb040..f168db9 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -184,7 +184,6 @@
         "libhidltransport",
         "liblayers_proto",
         "liblog",
-        "libsync",
         "libtimestats_proto",
         "libutils",
     ],
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index d16febf..5342bcf 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -35,8 +35,6 @@
 #include <gui/Surface.h>
 #include <hardware/gralloc.h>
 #include <renderengine/RenderEngine.h>
-#include <sync/sync.h>
-#include <system/window.h>
 #include <ui/DebugUtils.h>
 #include <ui/DisplayInfo.h>
 #include <ui/PixelFormat.h>
@@ -223,8 +221,8 @@
         mDisplayToken(args.displayToken),
         mId(args.displayId),
         mNativeWindow(args.nativeWindow),
-        mGraphicBuffer(nullptr),
         mDisplaySurface(args.displaySurface),
+        mSurface{std::move(args.renderSurface)},
         mDisplayInstallOrientation(args.displayInstallOrientation),
         mPageFlipCount(0),
         mIsVirtual(args.isVirtual),
@@ -246,6 +244,7 @@
 
     ALOGE_IF(!mNativeWindow, "No native window was set for display");
     ALOGE_IF(!mDisplaySurface, "No display surface was set for display");
+    ALOGE_IF(!mSurface, "No render surface was set for display");
 
     std::vector<Hdr> types = args.hdrCapabilities.getSupportedHdrTypes();
     for (Hdr hdrType : types) {
@@ -285,10 +284,6 @@
     mHdrCapabilities = HdrCapabilities(types, maxLuminance, maxAverageLuminance, minLuminance);
 
     ANativeWindow* const window = mNativeWindow.get();
-
-    int status = native_window_api_connect(mNativeWindow.get(), NATIVE_WINDOW_API_EGL);
-    ALOGE_IF(status != NO_ERROR, "Unable to connect BQ producer: %d", status);
-
     mDisplayWidth = ANativeWindow_getWidth(window);
     mDisplayHeight = ANativeWindow_getHeight(window);
 
@@ -326,6 +321,7 @@
 
 void DisplayDevice::flip() const
 {
+    mFlinger->getRenderEngine().checkErrors();
     mPageFlipCount++;
 }
 
@@ -360,71 +356,9 @@
     return mDisplaySurface->prepareFrame(compositionType);
 }
 
-sp<GraphicBuffer> DisplayDevice::dequeueBuffer() {
-    int fd;
-    ANativeWindowBuffer* buffer;
-
-    status_t res = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fd);
-
-    if (res != NO_ERROR) {
-        ALOGE("ANativeWindow::dequeueBuffer failed for display [%s] with error: %d",
-              getDisplayName().c_str(), res);
-        // Return fast here as we can't do much more - any rendering we do
-        // now will just be wrong.
-        return mGraphicBuffer;
-    }
-
-    ALOGW_IF(mGraphicBuffer != nullptr, "Clobbering a non-null pointer to a buffer [%p].",
-             mGraphicBuffer->getNativeBuffer()->handle);
-    mGraphicBuffer = GraphicBuffer::from(buffer);
-
-    // Block until the buffer is ready
-    // TODO(alecmouri): it's perhaps more appropriate to block renderengine so
-    // that the gl driver can block instead.
-    if (fd >= 0) {
-        sync_wait(fd, -1);
-        close(fd);
-    }
-
-    return mGraphicBuffer;
-}
-
-void DisplayDevice::queueBuffer(HWComposer& hwc) {
+void DisplayDevice::swapBuffers(HWComposer& hwc) const {
     if (hwc.hasClientComposition(mId) || hwc.hasFlipClientTargetRequest(mId)) {
-        // hasFlipClientTargetRequest could return true even if we haven't
-        // dequeued a buffer before. Try dequeueing one if we don't have a
-        // buffer ready.
-        if (mGraphicBuffer == nullptr) {
-            ALOGI("Attempting to queue a client composited buffer without one "
-                  "previously dequeued for display [%s]. Attempting to dequeue "
-                  "a scratch buffer now",
-                  mDisplayName.c_str());
-            // We shouldn't deadlock here, since mGraphicBuffer == nullptr only
-            // after a successful call to queueBuffer, or if dequeueBuffer has
-            // never been called.
-            dequeueBuffer();
-        }
-
-        if (mGraphicBuffer == nullptr) {
-            ALOGE("No buffer is ready for display [%s]", mDisplayName.c_str());
-        } else {
-            int fd = mBufferReady.release();
-
-            status_t res = mNativeWindow->queueBuffer(mNativeWindow.get(),
-                                                      mGraphicBuffer->getNativeBuffer(), fd);
-            if (res != NO_ERROR) {
-                ALOGE("Error when queueing buffer for display [%s]: %d", mDisplayName.c_str(), res);
-                // We risk blocking on dequeueBuffer if the primary display failed
-                // to queue up its buffer, so crash here.
-                if (isPrimary()) {
-                    LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", res);
-                } else {
-                    mNativeWindow->cancelBuffer(mNativeWindow.get(),
-                                                mGraphicBuffer->getNativeBuffer(), fd);
-                }
-            }
-            mGraphicBuffer = nullptr;
-        }
+        mSurface->swapBuffers();
     }
 
     status_t result = mDisplaySurface->advanceFrame();
@@ -433,10 +367,16 @@
     }
 }
 
-void DisplayDevice::onPresentDisplayCompleted() {
+void DisplayDevice::onSwapBuffersCompleted() const {
     mDisplaySurface->onFrameCommitted();
 }
 
+bool DisplayDevice::makeCurrent() const {
+    bool success = mFlinger->getRenderEngine().setCurrentSurface(*mSurface);
+    setViewportAndProjection();
+    return success;
+}
+
 void DisplayDevice::setViewportAndProjection() const {
     size_t w = mDisplayWidth;
     size_t h = mDisplayHeight;
@@ -444,13 +384,6 @@
     mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, ui::Transform::ROT_0);
 }
 
-void DisplayDevice::finishBuffer() {
-    mBufferReady = mFlinger->getRenderEngine().flush();
-    if (mBufferReady.get() < 0) {
-        mFlinger->getRenderEngine().finish();
-    }
-}
-
 const sp<Fence>& DisplayDevice::getClientTargetAcquireFence() const {
     return mDisplaySurface->getClientTargetAcquireFence();
 }
@@ -599,8 +532,12 @@
 void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) {
     dirtyRegion.set(getBounds());
 
+    mSurface->setNativeWindow(nullptr);
+
     mDisplaySurface->resizeBuffers(newWidth, newHeight);
 
+    ANativeWindow* const window = mNativeWindow.get();
+    mSurface->setNativeWindow(window);
     mDisplayWidth = newWidth;
     mDisplayHeight = newHeight;
 }
@@ -716,11 +653,12 @@
     ANativeWindow* const window = mNativeWindow.get();
     result.appendFormat("+ %s\n", getDebugName().c_str());
     result.appendFormat("  layerStack=%u, (%4dx%4d), ANativeWindow=%p "
-                        "format=%d, orient=%2d (type=%08x), flips=%u, isSecure=%d, "
-                        "powerMode=%d, activeConfig=%d, numLayers=%zu\n",
+                        "(%d:%d:%d:%d), orient=%2d (type=%08x), "
+                        "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n",
                         mLayerStack, mDisplayWidth, mDisplayHeight, window,
-                        ANativeWindow_getFormat(window), mOrientation, tr.getType(),
-                        getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
+                        mSurface->queryRedSize(), mSurface->queryGreenSize(),
+                        mSurface->queryBlueSize(), mSurface->queryAlphaSize(), mOrientation,
+                        tr.getType(), getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
                         mVisibleLayersSortedByZ.size());
     result.appendFormat("   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
                         "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
@@ -731,9 +669,9 @@
     auto const surface = static_cast<Surface*>(window);
     ui::Dataspace dataspace = surface->getBuffersDataSpace();
     result.appendFormat("   wideColorGamut=%d, hdr10=%d, colorMode=%s, dataspace: %s (%d)\n",
-                        mHasWideColorGamut, mHasHdr10, decodeColorMode(mActiveColorMode).c_str(),
-                        dataspaceDetails(static_cast<android_dataspace>(dataspace)).c_str(),
-                        dataspace);
+                        mHasWideColorGamut, mHasHdr10,
+                        decodeColorMode(mActiveColorMode).c_str(),
+                        dataspaceDetails(static_cast<android_dataspace>(dataspace)).c_str(), dataspace);
 
     String8 surfaceDump;
     mDisplaySurface->dumpAsString(surfaceDump);
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index eb2c5c3..bcd3330 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -24,25 +24,25 @@
 #include <string>
 #include <unordered_map>
 
-#include <android/native_window.h>
 #include <binder/IBinder.h>
 #include <gui/LayerState.h>
 #include <hardware/hwcomposer_defs.h>
 #include <math/mat4.h>
-#include <renderengine/RenderEngine.h>
-#include <system/window.h>
+#include <renderengine/Surface.h>
 #include <ui/GraphicTypes.h>
 #include <ui/HdrCapabilities.h>
 #include <ui/Region.h>
 #include <ui/Transform.h>
-#include <utils/Mutex.h>
 #include <utils/RefBase.h>
+#include <utils/Mutex.h>
 #include <utils/String8.h>
 #include <utils/Timers.h>
 
 #include "DisplayHardware/DisplayIdentification.h"
 #include "RenderArea.h"
 
+struct ANativeWindow;
+
 namespace android {
 
 class DisplaySurface;
@@ -146,13 +146,10 @@
                           ui::Dataspace* outDataspace, ui::ColorMode* outMode,
                           ui::RenderIntent* outIntent) const;
 
-    // Queues the drawn buffer for consumption by HWC.
-    void queueBuffer(HWComposer& hwc);
-    // Allocates a buffer as scratch space for GPU composition
-    sp<GraphicBuffer> dequeueBuffer();
+    void swapBuffers(HWComposer& hwc) const;
 
     // called after h/w composer has completed its set() call
-    void onPresentDisplayCompleted();
+    void onSwapBuffersCompleted() const;
 
     Rect getBounds() const {
         return Rect(mDisplayWidth, mDisplayHeight);
@@ -162,11 +159,7 @@
     void setDisplayName(const std::string& displayName);
     const std::string& getDisplayName() const { return mDisplayName; }
 
-    // Acquires a new buffer for GPU composition.
-    void readyNewBuffer();
-    // Marks the current buffer has finished, so that it can be presented and
-    // swapped out.
-    void finishBuffer();
+    bool makeCurrent() const;
     void setViewportAndProjection() const;
 
     const sp<Fence>& getClientTargetAcquireFence() const;
@@ -211,13 +204,9 @@
 
     // ANativeWindow this display is rendering into
     sp<ANativeWindow> mNativeWindow;
-    // Current buffer that this display can render to.
-    sp<GraphicBuffer> mGraphicBuffer;
     sp<DisplaySurface> mDisplaySurface;
-    // File descriptor indicating that mGraphicBuffer is ready for display, i.e.
-    // that drawing to the buffer is now complete.
-    base::unique_fd mBufferReady;
 
+    std::unique_ptr<renderengine::Surface> mSurface;
     int             mDisplayWidth;
     int             mDisplayHeight;
     const int       mDisplayInstallOrientation;
@@ -337,6 +326,7 @@
     bool isSecure{false};
     sp<ANativeWindow> nativeWindow;
     sp<DisplaySurface> displaySurface;
+    std::unique_ptr<renderengine::Surface> renderSurface;
     int displayInstallOrientation{DisplayState::eOrientationDefault};
     bool hasWideColorGamut{false};
     HdrCapabilities hdrCapabilities;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 5f3fcd6..27d3dc5 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -107,6 +107,8 @@
     mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
     mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight);
     sink->setAsyncMode(true);
+    IGraphicBufferProducer::QueueBufferOutput output;
+    mSource[SOURCE_SCRATCH]->connect(nullptr, NATIVE_WINDOW_API_EGL, false, &output);
 }
 
 VirtualDisplaySurface::~VirtualDisplaySurface() {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e84e21a..35ba391 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -45,7 +45,6 @@
 #include <gui/BufferQueue.h>
 #include <gui/GuiConfig.h>
 #include <gui/IDisplayEventConnection.h>
-#include <gui/IProducerListener.h>
 #include <gui/LayerDebugInfo.h>
 #include <gui/Surface.h>
 #include <renderengine/RenderEngine.h>
@@ -677,6 +676,10 @@
     LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(*display->getId()),
                         "Internal display is disconnected.");
 
+    // make the default display GLContext current so that we can create textures
+    // when creating Layers (which may happens before we render something)
+    display->makeCurrent();
+
     if (useVrFlinger) {
         auto vrFlingerRequestDisplayCallback = [this](bool requestDisplay) {
             // This callback is called from the vr flinger dispatch thread. We
@@ -1406,6 +1409,7 @@
     // mCurrentState and mDrawingState and re-apply all changes when we make the
     // transition.
     mDrawingState.displays.clear();
+    getRenderEngine().resetCurrentSurface();
     mDisplays.clear();
 }
 
@@ -1715,7 +1719,7 @@
             auto& engine(getRenderEngine());
             engine.fillRegionWithColor(dirtyRegion, 1, 0, 1, 1);
 
-            display->queueBuffer(getHwComposer());
+            display->swapBuffers(getHwComposer());
         }
     }
 
@@ -2190,7 +2194,8 @@
         if (displayId) {
             getHwComposer().presentAndGetReleaseFences(*displayId);
         }
-        display->onPresentDisplayCompleted();
+        display->onSwapBuffersCompleted();
+        display->makeCurrent();
         for (auto& layer : display->getVisibleLayersSortedByZ()) {
             sp<Fence> releaseFence = Fence::NO_FENCE;
 
@@ -2337,9 +2342,22 @@
     auto nativeWindow = nativeWindowSurface->getNativeWindow();
     creationArgs.nativeWindow = nativeWindow;
 
+    /*
+     * Create our display's surface
+     */
+    std::unique_ptr<renderengine::Surface> renderSurface = getRenderEngine().createSurface();
+    renderSurface->setCritical(isInternalDisplay);
+    renderSurface->setAsync(state.isVirtual());
+    renderSurface->setNativeWindow(nativeWindow.get());
+    creationArgs.renderSurface = std::move(renderSurface);
+
     // Make sure that composition can never be stalled by a virtual display
     // consumer that isn't processing buffers fast enough. We have to do this
-    // here, in case the display is composed entirely by HWC.
+    // in two places:
+    // * Here, in case the display is composed entirely by HWC.
+    // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
+    //   window's swap interval in eglMakeCurrent, so they'll override the
+    //   interval we set here.
     if (state.isVirtual()) {
         nativeWindow->setSwapInterval(nativeWindow.get(), 0);
     }
@@ -2399,6 +2417,12 @@
                 const auto externalDisplayId = getExternalDisplayId();
 
                 // in drawing state but not in current state
+                // Call makeCurrent() on the primary display so we can
+                // be sure that nothing associated with this display
+                // is current.
+                if (const auto defaultDisplay = getDefaultDisplayDeviceLocked()) {
+                    defaultDisplay->makeCurrent();
+                }
                 if (const auto display = getDisplayDeviceLocked(draw.keyAt(i))) {
                     display->disconnect(getHwComposer());
                 }
@@ -2949,7 +2973,7 @@
     mGeometryInvalid = true;
 }
 
-void SurfaceFlinger::doDisplayComposition(const sp<DisplayDevice>& display,
+void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& display,
                                           const Region& inDirtyRegion) {
     // We only need to actually compose the display if:
     // 1) It is being handled by hardware composer, which may need this to
@@ -2964,10 +2988,10 @@
     if (!doComposeSurfaces(display)) return;
 
     // swap buffers (presentation)
-    display->queueBuffer(getHwComposer());
+    display->swapBuffers(getHwComposer());
 }
 
-bool SurfaceFlinger::doComposeSurfaces(const sp<DisplayDevice>& display) {
+bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& display) {
     ALOGV("doComposeSurfaces");
 
     const Region bounds(display->bounds());
@@ -2980,31 +3004,9 @@
     bool applyColorMatrix = false;
     bool needsEnhancedColorMatrix = false;
 
-    // Framebuffer will live in this scope for GPU composition.
-    std::unique_ptr<renderengine::BindNativeBufferAsFramebuffer> fbo;
-
     if (hasClientComposition) {
         ALOGV("hasClientComposition");
 
-        sp<GraphicBuffer> buf = display->dequeueBuffer();
-
-        if (buf == nullptr) {
-            ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
-                  "client composition for this frame",
-                  display->getDisplayName().c_str());
-            return false;
-        }
-
-        // Bind the framebuffer in this scope.
-        fbo = std::make_unique<renderengine::BindNativeBufferAsFramebuffer>(getRenderEngine(),
-                                                                            buf->getNativeBuffer());
-
-        if (fbo->getStatus() != NO_ERROR) {
-            ALOGW("Binding buffer for display [%s] failed with status: %d",
-                  display->getDisplayName().c_str(), fbo->getStatus());
-            return false;
-        }
-
         Dataspace outputDataspace = Dataspace::UNKNOWN;
         if (display->hasWideColorGamut()) {
             outputDataspace = display->getCompositionDataSpace();
@@ -3033,7 +3035,18 @@
             colorMatrix *= mEnhancedSaturationMatrix;
         }
 
-        display->setViewportAndProjection();
+        if (!display->makeCurrent()) {
+            ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
+                  display->getDisplayName().c_str());
+            getRenderEngine().resetCurrentSurface();
+
+            // |mStateLock| not needed as we are on the main thread
+            const auto defaultDisplay = getDefaultDisplayDeviceLocked();
+            if (!defaultDisplay || !defaultDisplay->makeCurrent()) {
+                ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
+            }
+            return false;
+        }
 
         // Never touch the framebuffer if we don't have any framebuffer layers
         if (hasDeviceComposition) {
@@ -3126,15 +3139,11 @@
         firstLayer = false;
     }
 
-    // Perform some cleanup steps if we used client composition.
-    if (hasClientComposition) {
-        getRenderEngine().setColorTransform(mat4());
-        getBE().mRenderEngine->disableScissor();
-        display->finishBuffer();
-        // Clear out error flags here so that we don't wait until next
-        // composition to log.
-        getRenderEngine().checkErrors();
-    }
+    // Clear color transform matrix at the end of the frame.
+    getRenderEngine().setColorTransform(mat4());
+
+    // disable scissor at the end of the frame
+    getBE().mRenderEngine->disableScissor();
     return true;
 }
 
@@ -3184,19 +3193,15 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer, bool topLevelOnly) {
+status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer) {
     Mutex::Autolock _l(mStateLock);
-    return removeLayerLocked(mStateLock, layer, topLevelOnly);
+    return removeLayerLocked(mStateLock, layer);
 }
 
-status_t SurfaceFlinger::removeLayerLocked(const Mutex& lock, const sp<Layer>& layer,
-                                           bool topLevelOnly) {
+status_t SurfaceFlinger::removeLayerLocked(const Mutex& lock, const sp<Layer>& layer) {
     const auto& p = layer->getParent();
     ssize_t index;
     if (p != nullptr) {
-        if (topLevelOnly) {
-            return NO_ERROR;
-        }
         index = p->removeChild(layer);
     } else {
         index = mCurrentState.layersSortedByZ.remove(layer);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f5218b1..8b389bc 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -592,8 +592,8 @@
     void onHandleDestroyed(const sp<Layer>& layer);
 
     // remove a layer from SurfaceFlinger immediately
-    status_t removeLayer(const sp<Layer>& layer, bool topLevelOnly = false);
-    status_t removeLayerLocked(const Mutex&, const sp<Layer>& layer, bool topLevelOnly = false);
+    status_t removeLayer(const sp<Layer>& layer);
+    status_t removeLayerLocked(const Mutex&, const sp<Layer>& layer);
 
     // add a layer to SurfaceFlinger
     status_t addClientLayer(const sp<Client>& client,
@@ -721,10 +721,10 @@
     void doDebugFlashRegions(const sp<DisplayDevice>& display, bool repaintEverything);
     void doTracing(const char* where);
     void logLayerStats();
-    void doDisplayComposition(const sp<DisplayDevice>& display, const Region& dirtyRegion);
+    void doDisplayComposition(const sp<const DisplayDevice>& display, const Region& dirtyRegion);
 
     // This fails if using GL and the surface has been destroyed.
-    bool doComposeSurfaces(const sp<DisplayDevice>& display);
+    bool doComposeSurfaces(const sp<const DisplayDevice>& display);
 
     void postFramebuffer(const sp<DisplayDevice>& display);
     void postFrame();
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index cfaf495..ab1b252 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -46,7 +46,6 @@
 using testing::AtLeast;
 using testing::ByMove;
 using testing::DoAll;
-using testing::Invoke;
 using testing::IsNull;
 using testing::Mock;
 using testing::NotNull;
@@ -94,10 +93,6 @@
         EXPECT_CALL(*mPrimaryDispSync, computeNextRefresh(0)).WillRepeatedly(Return(0));
         EXPECT_CALL(*mPrimaryDispSync, getPeriod())
                 .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
-        EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
-                .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_WIDTH), Return(0)));
-        EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
-                .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_HEIGHT), Return(0)));
 
         mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
         setupComposer(0);
@@ -144,11 +139,9 @@
     sp<DisplayDevice> mDisplay;
     sp<DisplayDevice> mExternalDisplay;
     sp<mock::DisplaySurface> mDisplaySurface = new mock::DisplaySurface();
+    renderengine::mock::Surface* mRenderSurface = new renderengine::mock::Surface();
     mock::NativeWindow* mNativeWindow = new mock::NativeWindow();
 
-    sp<GraphicBuffer> mBuffer = new GraphicBuffer();
-    ANativeWindowBuffer* mNativeWindowBuffer = mBuffer->getNativeBuffer();
-
     mock::EventThread* mEventThread = new mock::EventThread();
     mock::EventControlThread* mEventControlThread = new mock::EventControlThread();
 
@@ -249,6 +242,8 @@
         test->mDisplay = FakeDisplayDeviceInjector(test->mFlinger, DEFAULT_DISPLAY_ID,
                                                    false /* isVirtual */, true /* isPrimary */)
                                  .setDisplaySurface(test->mDisplaySurface)
+                                 .setRenderSurface(std::unique_ptr<renderengine::Surface>(
+                                         test->mRenderSurface))
                                  .setNativeWindow(test->mNativeWindow)
                                  .setSecure(Derived::IS_SECURE)
                                  .setPowerMode(Derived::INIT_POWER_MODE)
@@ -271,9 +266,13 @@
         EXPECT_CALL(*test->mRenderEngine, checkErrors()).WillRepeatedly(Return());
         EXPECT_CALL(*test->mRenderEngine, isCurrent()).WillRepeatedly(Return(true));
 
-        EXPECT_CALL(*test->mRenderEngine, flush()).WillRepeatedly(Invoke([]() {
-            return base::unique_fd(0);
-        }));
+        EXPECT_CALL(*test->mRenderEngine, setCurrentSurface(Ref(*test->mRenderSurface)))
+                .WillOnce(Return(true));
+        EXPECT_CALL(*test->mRenderEngine,
+                    setViewportAndProjection(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT,
+                                             Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+                                             ui::Transform::ROT_0))
+                .Times(1);
 
         EXPECT_CALL(*test->mDisplaySurface, onFrameCommitted()).Times(1);
         EXPECT_CALL(*test->mDisplaySurface, advanceFrame()).Times(1);
@@ -324,6 +323,8 @@
 
     static void setupHwcCompositionCallExpectations(CompositionTest* test) {
         EXPECT_CALL(*test->mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_HWC)).Times(1);
+
+        EXPECT_CALL(*test->mRenderEngine, disableScissor()).Times(1);
     }
 
     static void setupRECompositionCallExpectations(CompositionTest* test) {
@@ -343,18 +344,12 @@
                     setViewportAndProjection(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT,
                                              Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
                                              ui::Transform::ROT_0))
-                .Times(1);
-        EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(NotNull())).WillOnce(Return(true));
-        EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(IsNull())).WillOnce(Return(true));
-        EXPECT_CALL(*test->mRenderEngine, createFramebuffer())
-                .WillOnce(Return(
-                        ByMove(std::unique_ptr<renderengine::Framebuffer>(test->mReFrameBuffer))));
-        EXPECT_CALL(*test->mRenderEngine, bindFrameBuffer(test->mReFrameBuffer)).Times(1);
-        EXPECT_CALL(*test->mRenderEngine, unbindFrameBuffer(test->mReFrameBuffer)).Times(1);
-        EXPECT_CALL(*test->mNativeWindow, queueBuffer(_, _)).WillOnce(Return(0));
-        EXPECT_CALL(*test->mNativeWindow, dequeueBuffer(_, _))
-                .WillOnce(DoAll(SetArgPointee<0>(test->mNativeWindowBuffer), SetArgPointee<1>(-1),
-                                Return(0)));
+                .Times(1)
+                .RetiresOnSaturation();
+        EXPECT_CALL(*test->mRenderEngine, setCurrentSurface(Ref(*test->mRenderSurface)))
+                .WillOnce(Return(true))
+                .RetiresOnSaturation();
+        EXPECT_CALL(*test->mRenderSurface, swapBuffers()).Times(1);
     }
 
     template <typename Case>
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index ac6a78b..32fce67 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -120,7 +120,6 @@
     mock::EventThread* mEventThread = new mock::EventThread();
     mock::EventControlThread* mEventControlThread = new mock::EventControlThread();
     sp<mock::NativeWindow> mNativeWindow = new mock::NativeWindow();
-    sp<GraphicBuffer> mBuffer = new GraphicBuffer();
 
     // These mocks are created by the test, but are destroyed by SurfaceFlinger
     // by virtue of being stored into a std::unique_ptr. However we still need
@@ -135,6 +134,7 @@
     sp<mock::GraphicBufferConsumer> mConsumer;
     sp<mock::GraphicBufferProducer> mProducer;
     surfaceflinger::mock::NativeWindowSurface* mNativeWindowSurface = nullptr;
+    renderengine::mock::Surface* mRenderSurface = nullptr;
 };
 
 DisplayTransactionTest::DisplayTransactionTest() {
@@ -340,11 +340,26 @@
     static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
         EXPECT_CALL(*test->mNativeWindowSurface, getNativeWindow())
                 .WillOnce(Return(test->mNativeWindow));
+        EXPECT_CALL(*test->mNativeWindow, perform(19)).WillRepeatedly(Return(NO_ERROR));
 
+        // For simplicity, we only expect to create a single render surface for
+        // each test.
+        ASSERT_TRUE(test->mRenderSurface == nullptr);
+        test->mRenderSurface = new renderengine::mock::Surface();
+        EXPECT_CALL(*test->mRenderEngine, createSurface())
+                .WillOnce(Return(ByMove(
+                        std::unique_ptr<renderengine::Surface>(test->mRenderSurface))));
+
+        // Creating a DisplayDevice requires getting default dimensions from the
+        // native window.
         EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
                 .WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0)));
         EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
                 .WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0)));
+
+        EXPECT_CALL(*test->mRenderSurface, setAsync(static_cast<bool>(ASYNC))).Times(1);
+        EXPECT_CALL(*test->mRenderSurface, setCritical(static_cast<bool>(CRITICAL))).Times(1);
+        EXPECT_CALL(*test->mRenderSurface, setNativeWindow(test->mNativeWindow.get())).Times(1);
     }
 
     static void setupFramebufferConsumerBufferQueueCallExpectations(DisplayTransactionTest* test) {
@@ -1055,6 +1070,9 @@
     // The call disable vsyncs
     EXPECT_CALL(*mEventControlThread, setVsyncEnabled(false)).Times(1);
 
+    // The call clears the current render engine surface
+    EXPECT_CALL(*mRenderEngine, resetCurrentSurface());
+
     // The call ends any display resyncs
     EXPECT_CALL(*mPrimaryDispSync, endResync()).Times(1);
 
@@ -1114,7 +1132,6 @@
                 .WillRepeatedly(DoAll(SetArgPointee<1>(1080 /* arbitrary */), Return(0)));
         EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
                 .WillRepeatedly(DoAll(SetArgPointee<1>(1920 /* arbitrary */), Return(0)));
-        EXPECT_CALL(*mNativeWindow, perform(13)).Times(1);
         auto displayDevice = mInjector.inject();
 
         displayDevice->getBestColorMode(mInputDataspace, mInputRenderIntent, &mOutDataspace,
@@ -1708,6 +1725,7 @@
 
     EXPECT_CALL(*surface, setAsyncMode(true)).Times(1);
 
+    EXPECT_CALL(*mProducer, connect(_, _, _, _)).Times(1);
     EXPECT_CALL(*mProducer, disconnect(_, _)).Times(1);
 
     Case::Display::setupHwcVirtualDisplayCreationCallExpectations(this);
@@ -1931,16 +1949,11 @@
     // A display is set up
     auto nativeWindow = new mock::NativeWindow();
     auto displaySurface = new mock::DisplaySurface();
-    sp<GraphicBuffer> buf = new GraphicBuffer();
+    auto renderSurface = new renderengine::mock::Surface();
     auto display = Case::Display::makeFakeExistingDisplayInjector(this);
     display.setNativeWindow(nativeWindow);
     display.setDisplaySurface(displaySurface);
-    // Setup injection expections
-    EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_WIDTH, _))
-            .WillOnce(DoAll(SetArgPointee<1>(oldWidth), Return(0)));
-    EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
-            .WillOnce(DoAll(SetArgPointee<1>(oldHeight), Return(0)));
-    EXPECT_CALL(*nativeWindow, perform(13)).Times(1);
+    display.setRenderSurface(std::unique_ptr<renderengine::Surface>(renderSurface));
     display.inject();
 
     // There is a change to the viewport state
@@ -1952,7 +1965,9 @@
     // --------------------------------------------------------------------
     // Call Expectations
 
+    EXPECT_CALL(*renderSurface, setNativeWindow(nullptr)).Times(1);
     EXPECT_CALL(*displaySurface, resizeBuffers(newWidth, oldHeight)).Times(1);
+    EXPECT_CALL(*renderSurface, setNativeWindow(nativeWindow)).Times(1);
 
     // --------------------------------------------------------------------
     // Invocation
@@ -1973,16 +1988,11 @@
     // A display is set up
     auto nativeWindow = new mock::NativeWindow();
     auto displaySurface = new mock::DisplaySurface();
-    sp<GraphicBuffer> buf = new GraphicBuffer();
+    auto renderSurface = new renderengine::mock::Surface();
     auto display = Case::Display::makeFakeExistingDisplayInjector(this);
     display.setNativeWindow(nativeWindow);
     display.setDisplaySurface(displaySurface);
-    // Setup injection expections
-    EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_WIDTH, _))
-            .WillOnce(DoAll(SetArgPointee<1>(oldWidth), Return(0)));
-    EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
-            .WillOnce(DoAll(SetArgPointee<1>(oldHeight), Return(0)));
-    EXPECT_CALL(*nativeWindow, perform(13)).Times(1);
+    display.setRenderSurface(std::unique_ptr<renderengine::Surface>(renderSurface));
     display.inject();
 
     // There is a change to the viewport state
@@ -1994,7 +2004,9 @@
     // --------------------------------------------------------------------
     // Call Expectations
 
+    EXPECT_CALL(*renderSurface, setNativeWindow(nullptr)).Times(1);
     EXPECT_CALL(*displaySurface, resizeBuffers(oldWidth, newHeight)).Times(1);
+    EXPECT_CALL(*renderSurface, setNativeWindow(nativeWindow)).Times(1);
 
     // --------------------------------------------------------------------
     // Invocation
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 85c835e..a519f1f 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -474,6 +474,11 @@
             return *this;
         }
 
+        auto& setRenderSurface(std::unique_ptr<renderengine::Surface> renderSurface) {
+            mCreationArgs.renderSurface = std::move(renderSurface);
+            return *this;
+        }
+
         auto& setSecure(bool secure) {
             mCreationArgs.isSecure = secure;
             return *this;
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
index fbfbc3f..af54df6 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
@@ -26,6 +26,9 @@
 RenderEngine::RenderEngine() = default;
 RenderEngine::~RenderEngine() = default;
 
+Surface::Surface() = default;
+Surface::~Surface() = default;
+
 Image::Image() = default;
 Image::~Image() = default;
 
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
index 90c3c20..afca63a 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
@@ -23,6 +23,7 @@
 #include <renderengine/LayerSettings.h>
 #include <renderengine/Mesh.h>
 #include <renderengine/RenderEngine.h>
+#include <renderengine/Surface.h>
 #include <renderengine/Texture.h>
 #include <ui/GraphicBuffer.h>
 
@@ -36,12 +37,15 @@
     ~RenderEngine() override;
 
     MOCK_METHOD0(createFramebuffer, std::unique_ptr<Framebuffer>());
+    MOCK_METHOD0(createSurface, std::unique_ptr<renderengine::Surface>());
     MOCK_METHOD0(createImage, std::unique_ptr<renderengine::Image>());
     MOCK_CONST_METHOD0(primeCache, void());
     MOCK_METHOD1(dump, void(String8&));
     MOCK_CONST_METHOD0(useNativeFenceSync, bool());
     MOCK_CONST_METHOD0(useWaitSync, bool());
     MOCK_CONST_METHOD0(isCurrent, bool());
+    MOCK_METHOD1(setCurrentSurface, bool(const renderengine::Surface&));
+    MOCK_METHOD0(resetCurrentSurface, void());
     MOCK_METHOD0(flush, base::unique_fd());
     MOCK_METHOD0(finish, bool());
     MOCK_METHOD1(waitFence, bool(base::unique_fd*));
@@ -78,6 +82,23 @@
                                 ANativeWindowBuffer* const, base::unique_fd*));
 };
 
+class Surface : public renderengine::Surface {
+public:
+    Surface();
+    ~Surface() override;
+
+    MOCK_METHOD1(setCritical, void(bool));
+    MOCK_METHOD1(setAsync, void(bool));
+    MOCK_METHOD1(setNativeWindow, void(ANativeWindow*));
+    MOCK_CONST_METHOD0(swapBuffers, void());
+    MOCK_CONST_METHOD0(queryRedSize, int32_t());
+    MOCK_CONST_METHOD0(queryGreenSize, int32_t());
+    MOCK_CONST_METHOD0(queryBlueSize, int32_t());
+    MOCK_CONST_METHOD0(queryAlphaSize, int32_t());
+    MOCK_CONST_METHOD0(getWidth, int32_t());
+    MOCK_CONST_METHOD0(getHeight, int32_t());
+};
+
 class Image : public renderengine::Image {
 public:
     Image();
diff --git a/services/surfaceflinger/tests/unittests/mock/system/window/MockNativeWindow.h b/services/surfaceflinger/tests/unittests/mock/system/window/MockNativeWindow.h
index 4950a4b..561fd58 100644
--- a/services/surfaceflinger/tests/unittests/mock/system/window/MockNativeWindow.h
+++ b/services/surfaceflinger/tests/unittests/mock/system/window/MockNativeWindow.h
@@ -36,7 +36,6 @@
     MOCK_METHOD1(queueBuffer_DEPRECATED, int(struct ANativeWindowBuffer*));
     MOCK_CONST_METHOD2(query, int(int, int*));
     MOCK_METHOD1(perform, int(int));
-    MOCK_METHOD2(perform, int(int, int));
     MOCK_METHOD1(cancelBuffer_DEPRECATED, int(struct ANativeWindowBuffer*));
     MOCK_METHOD2(dequeueBuffer, int(struct ANativeWindowBuffer**, int*));
     MOCK_METHOD2(queueBuffer, int(struct ANativeWindowBuffer*, int));
diff --git a/services/vr/performanced/Android.bp b/services/vr/performanced/Android.bp
new file mode 100644
index 0000000..20301f6
--- /dev/null
+++ b/services/vr/performanced/Android.bp
@@ -0,0 +1,53 @@
+// 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.
+
+cc_defaults {
+    name: "performanced_defaults",
+    static_libs: [
+        "libperformance",
+        "libvr_manager",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libbase",
+        "libcutils",
+        "liblog",
+        "libutils",
+        "libpdx_default_transport",
+    ],
+}
+
+cc_binary {
+    name: "performanced",
+    defaults: ["performanced_defaults"],
+    srcs: [
+        "cpu_set.cpp",
+        "main.cpp",
+        "performance_service.cpp",
+        "task.cpp",
+    ],
+    cflags: [
+        "-DLOG_TAG=\"performanced\"",
+        "-DTRACE=0",
+        "-Wall",
+        "-Werror",
+    ],
+    init_rc: ["performanced.rc"],
+}
+
+cc_test {
+    name: "performance_service_tests",
+    defaults: ["performanced_defaults"],
+    srcs: ["performance_service_tests.cpp"],
+}
diff --git a/services/vr/performanced/Android.mk b/services/vr/performanced/Android.mk
deleted file mode 100644
index a548ef0..0000000
--- a/services/vr/performanced/Android.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-
-sourceFiles := \
-	cpu_set.cpp \
-	main.cpp \
-	performance_service.cpp \
-	task.cpp
-
-staticLibraries := \
-	libperformance \
-	libvr_manager
-
-sharedLibraries := \
-	libbinder \
-	libbase \
-	libcutils \
-	liblog \
-	libutils \
-	libpdx_default_transport \
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(sourceFiles)
-LOCAL_CFLAGS := -DLOG_TAG=\"performanced\"
-LOCAL_CFLAGS += -DTRACE=0
-LOCAL_CFLAGS += -Wall -Werror
-LOCAL_STATIC_LIBRARIES := $(staticLibraries)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_MODULE := performanced
-LOCAL_INIT_RC := performanced.rc
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := performance_service_tests.cpp
-LOCAL_STATIC_LIBRARIES := $(staticLibraries) libgtest_main
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_MODULE := performance_service_tests
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_NATIVE_TEST)