Merge "SyncPointerCapture (8/n): Add doc for Pointer Capture in InputFlinger"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index cbb74b3..afa0b4d 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2864,31 +2864,23 @@
     // duration is logged into MYLOG instead.
     PrintHeader();
 
-    // TODO(b/158737089) reduce code repetition in if branches
-    if (options_->telephony_only) {
-        MaybeTakeEarlyScreenshot();
-        onUiIntensiveBugreportDumpsFinished(calling_uid);
-        MaybeCheckUserConsent(calling_uid, calling_package);
-        DumpstateTelephonyOnly(calling_package);
-    } else if (options_->wifi_only) {
-        MaybeTakeEarlyScreenshot();
-        onUiIntensiveBugreportDumpsFinished(calling_uid);
-        MaybeCheckUserConsent(calling_uid, calling_package);
-        DumpstateWifiOnly();
-    } else if (options_->limited_only) {
-        MaybeTakeEarlyScreenshot();
-        onUiIntensiveBugreportDumpsFinished(calling_uid);
-        MaybeCheckUserConsent(calling_uid, calling_package);
-        DumpstateLimitedOnly();
-    } else {
+    bool is_dumpstate_restricted = options_->telephony_only
+                                   || options_->wifi_only
+                                   || options_->limited_only;
+    if (!is_dumpstate_restricted) {
         // Invoke critical dumpsys first to preserve system state, before doing anything else.
         RunDumpsysCritical();
-
-        // Take screenshot and get consent only after critical dumpsys has finished.
-        MaybeTakeEarlyScreenshot();
-        onUiIntensiveBugreportDumpsFinished(calling_uid);
-        MaybeCheckUserConsent(calling_uid, calling_package);
-
+    }
+    MaybeTakeEarlyScreenshot();
+    onUiIntensiveBugreportDumpsFinished(calling_uid);
+    MaybeCheckUserConsent(calling_uid, calling_package);
+    if (options_->telephony_only) {
+        DumpstateTelephonyOnly(calling_package);
+    } else if (options_->wifi_only) {
+        DumpstateWifiOnly();
+    } else if (options_->limited_only) {
+        DumpstateLimitedOnly();
+    } else {
         // Dump state for the default case. This also drops root.
         RunStatus s = DumpstateDefaultAfterCritical();
         if (s != RunStatus::OK) {
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index b821578..818804a 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -398,6 +398,10 @@
         PLOG(ERROR) << "Failed to prepare " << profile_dir;
         return false;
     }
+    if (selinux_android_restorecon(profile_dir.c_str(), 0)) {
+        PLOG(ERROR) << "Failed to restorecon " << profile_dir;
+        return false;
+    }
 
     const std::string ref_profile_path =
             create_primary_reference_profile_package_dir_path(packageName);
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 594880a..65fc46e 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1818,10 +1818,13 @@
 
     pid_t pid = fork();
     if (pid == 0) {
+        // Need to set schedpolicy before dropping privileges
+        // for cgroup migration. See details at b/175178520.
+        SetDex2OatScheduling(boot_complete);
+
         /* child -- drop privileges before continuing */
         drop_capabilities(uid);
 
-        SetDex2OatScheduling(boot_complete);
         if (flock(out_oat.fd(), LOCK_EX | LOCK_NB) != 0) {
             PLOG(ERROR) << "flock(" << out_oat.path() << ") failed";
             _exit(DexoptReturnCodes::kFlock);
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index 1994e56..0cbb80f 100644
--- a/cmds/lshal/Android.bp
+++ b/cmds/lshal/Android.bp
@@ -16,6 +16,7 @@
     name: "liblshal",
     shared_libs: [
         "libbase",
+        "libbinderdebug",
         "libcutils",
         "libutils",
         "libhidlbase",
@@ -47,6 +48,7 @@
     name: "lshal_defaults",
     shared_libs: [
         "libbase",
+        "libbinderdebug",
         "libcutils",
         "libutils",
         "libhidlbase",
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 92958d9..22268ac 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -29,7 +29,6 @@
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
-#include <android-base/parseint.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <hidl-hash/Hash.h>
 #include <hidl-util/FQName.h>
@@ -203,97 +202,14 @@
             lshal::getVintfInfo(getFrameworkMatrix(), fqInstance, ta, FRAMEWORK_MATRIX);
 }
 
-static bool scanBinderContext(pid_t pid,
-        const std::string &contextName,
-        std::function<void(const std::string&)> eachLine) {
-    std::ifstream ifs("/dev/binderfs/binder_logs/proc/" + std::to_string(pid));
-    if (!ifs.is_open()) {
-        ifs.open("/d/binder/proc/" + std::to_string(pid));
-        if (!ifs.is_open()) {
-            return false;
-        }
-    }
-
-    static const std::regex kContextLine("^context (\\w+)$");
-
-    bool isDesiredContext = false;
-    std::string line;
-    std::smatch match;
-    while(getline(ifs, line)) {
-        if (std::regex_search(line, match, kContextLine)) {
-            isDesiredContext = match.str(1) == contextName;
-            continue;
-        }
-
-        if (!isDesiredContext) {
-            continue;
-        }
-
-        eachLine(line);
-    }
-    return true;
-}
-
 bool ListCommand::getPidInfo(
-        pid_t serverPid, PidInfo *pidInfo) const {
-    static const std::regex kReferencePrefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+");
-    static const std::regex kThreadPrefix("^\\s*thread \\d+:\\s+l\\s+(\\d)(\\d)");
-
-    std::smatch match;
-    return scanBinderContext(serverPid, "hwbinder", [&](const std::string& line) {
-        if (std::regex_search(line, match, kReferencePrefix)) {
-            const std::string &ptrString = "0x" + match.str(2); // use number after c
-            uint64_t ptr;
-            if (!::android::base::ParseUint(ptrString.c_str(), &ptr)) {
-                // Should not reach here, but just be tolerant.
-                err() << "Could not parse number " << ptrString << std::endl;
-                return;
-            }
-            const std::string proc = " proc ";
-            auto pos = line.rfind(proc);
-            if (pos != std::string::npos) {
-                for (const std::string &pidStr : split(line.substr(pos + proc.size()), ' ')) {
-                    int32_t pid;
-                    if (!::android::base::ParseInt(pidStr, &pid)) {
-                        err() << "Could not parse number " << pidStr << std::endl;
-                        return;
-                    }
-                    pidInfo->refPids[ptr].push_back(pid);
-                }
-            }
-
-            return;
-        }
-
-        if (std::regex_search(line, match, kThreadPrefix)) {
-            // "1" is waiting in binder driver
-            // "2" is poll. It's impossible to tell if these are in use.
-            //     and HIDL default code doesn't use it.
-            bool isInUse = match.str(1) != "1";
-            // "0" is a thread that has called into binder
-            // "1" is looper thread
-            // "2" is main looper thread
-            bool isHwbinderThread = match.str(2) != "0";
-
-            if (!isHwbinderThread) {
-                return;
-            }
-
-            if (isInUse) {
-                pidInfo->threadUsage++;
-            }
-
-            pidInfo->threadCount++;
-            return;
-        }
-
-        // not reference or thread line
-        return;
-    });
+        pid_t serverPid, BinderPidInfo *pidInfo) const {
+    const auto& status = getBinderPidInfo(BinderDebugContext::HWBINDER, serverPid, pidInfo);
+    return status == OK;
 }
 
-const PidInfo* ListCommand::getPidInfoCached(pid_t serverPid) {
-    auto pair = mCachedPidInfos.insert({serverPid, PidInfo{}});
+const BinderPidInfo* ListCommand::getPidInfoCached(pid_t serverPid) {
+    auto pair = mCachedPidInfos.insert({serverPid, BinderPidInfo{}});
     if (pair.second /* did insertion take place? */) {
         if (!getPidInfo(serverPid, &pair.first->second)) {
             return nullptr;
@@ -727,7 +643,7 @@
         entry->arch = fromBaseArchitecture(debugInfo.arch);
 
         if (debugInfo.pid != NO_PID) {
-            const PidInfo* pidInfo = getPidInfoCached(debugInfo.pid);
+            const BinderPidInfo* pidInfo = getPidInfoCached(debugInfo.pid);
             if (pidInfo == nullptr) {
                 handleError(IO_ERROR,
                             "no information for PID " + std::to_string(debugInfo.pid) +
diff --git a/cmds/lshal/ListCommand.h b/cmds/lshal/ListCommand.h
index 412aadd..561f9cb 100644
--- a/cmds/lshal/ListCommand.h
+++ b/cmds/lshal/ListCommand.h
@@ -25,6 +25,7 @@
 
 #include <android-base/macros.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
+#include <binderdebug/BinderDebug.h>
 #include <hidl-util/FqInstance.h>
 #include <vintf/HalManifest.h>
 #include <vintf/VintfObject.h>
@@ -40,12 +41,6 @@
 
 class Lshal;
 
-struct PidInfo {
-    std::map<uint64_t, Pids> refPids; // pids that are referenced
-    uint32_t threadUsage; // number of threads in use
-    uint32_t threadCount; // number of threads total
-};
-
 enum class HalType {
     BINDERIZED_SERVICES = 0,
     PASSTHROUGH_CLIENTS,
@@ -110,9 +105,9 @@
     // Get relevant information for a PID by parsing files under
     // /dev/binderfs/binder_logs or /d/binder.
     // It is a virtual member function so that it can be mocked.
-    virtual bool getPidInfo(pid_t serverPid, PidInfo *info) const;
+    virtual bool getPidInfo(pid_t serverPid, BinderPidInfo *info) const;
     // Retrieve from mCachedPidInfos and call getPidInfo if necessary.
-    const PidInfo* getPidInfoCached(pid_t serverPid);
+    const BinderPidInfo* getPidInfoCached(pid_t serverPid);
 
     void dumpTable(const NullableOStream<std::ostream>& out) const;
     void dumpVintf(const NullableOStream<std::ostream>& out) const;
@@ -191,7 +186,7 @@
     std::map<pid_t, std::string> mCmdlines;
 
     // Cache for getPidInfo.
-    std::map<pid_t, PidInfo> mCachedPidInfos;
+    std::map<pid_t, BinderPidInfo> mCachedPidInfos;
 
     // Cache for getPartition.
     std::map<pid_t, Partition> mPartitions;
diff --git a/cmds/lshal/TableEntry.h b/cmds/lshal/TableEntry.h
index 3c36813..476aa04 100644
--- a/cmds/lshal/TableEntry.h
+++ b/cmds/lshal/TableEntry.h
@@ -32,7 +32,7 @@
 namespace lshal {
 
 using android::procpartition::Partition;
-using Pids = std::vector<int32_t>;
+using Pids = std::vector<pid_t>;
 
 enum class TableColumnType : unsigned int {
     INTERFACE_NAME = 0,
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index ba6cdf1..b6ff28d 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -233,12 +233,12 @@
         return ListCommand::dumpVintf(out);
     }
     void internalPostprocess() { ListCommand::postprocess(); }
-    const PidInfo* getPidInfoCached(pid_t serverPid) {
+    const BinderPidInfo* getPidInfoCached(pid_t serverPid) {
         return ListCommand::getPidInfoCached(serverPid);
     }
 
     MOCK_METHOD0(postprocess, void());
-    MOCK_CONST_METHOD2(getPidInfo, bool(pid_t, PidInfo*));
+    MOCK_CONST_METHOD2(getPidInfo, bool(pid_t, BinderPidInfo*));
     MOCK_CONST_METHOD1(parseCmdline, std::string(pid_t));
     MOCK_METHOD1(getPartition, Partition(pid_t));
 
@@ -299,8 +299,8 @@
 static std::vector<pid_t> getClients(pid_t serverId) {
     return {serverId + 1, serverId + 3};
 }
-static PidInfo getPidInfoFromId(pid_t serverId) {
-    PidInfo info;
+static BinderPidInfo getPidInfoFromId(pid_t serverId) {
+    BinderPidInfo info;
     info.refPids[getPtr(serverId)] = getClients(serverId);
     info.threadUsage = 10 + serverId;
     info.threadCount = 20 + serverId;
@@ -363,7 +363,7 @@
     void initMockList() {
         mockList = std::make_unique<NiceMock<MockListCommand>>(lshal.get());
         ON_CALL(*mockList, getPidInfo(_,_)).WillByDefault(Invoke(
-            [](pid_t serverPid, PidInfo* info) {
+            [](pid_t serverPid, BinderPidInfo* info) {
                 *info = getPidInfoFromId(serverPid);
                 return true;
             }));
diff --git a/data/etc/android.software.opengles.deqp.level-2020-03-01.xml b/data/etc/android.software.opengles.deqp.level-2020-03-01.xml
new file mode 100644
index 0000000..f11e0bb
--- /dev/null
+++ b/data/etc/android.software.opengles.deqp.level-2020-03-01.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This is the standard feature indicating that the device passes OpenGL ES
+     dEQP tests associated with date 2020-03-01 (0x07E40301). -->
+<permissions>
+    <feature name="android.software.opengles.deqp.level" version="132383489" />
+</permissions>
diff --git a/data/etc/android.software.opengles.deqp.level-2021-03-01.xml b/data/etc/android.software.opengles.deqp.level-2021-03-01.xml
new file mode 100644
index 0000000..b60697d
--- /dev/null
+++ b/data/etc/android.software.opengles.deqp.level-2021-03-01.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This is the standard feature indicating that the device passes OpenGL ES
+     dEQP tests associated with date 2021-03-01 (0x07E50301). -->
+<permissions>
+    <feature name="android.software.opengles.deqp.level" version="132449025" />
+</permissions>
diff --git a/data/etc/android.software.vulkan.deqp.level-2019-03-01.xml b/data/etc/android.software.vulkan.deqp.level-2019-03-01.xml
index 9c67d4a..d3ad45a 100644
--- a/data/etc/android.software.vulkan.deqp.level-2019-03-01.xml
+++ b/data/etc/android.software.vulkan.deqp.level-2019-03-01.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 
-<!-- This is the standard feature indicating that the device passes Vulkan deQP
+<!-- This is the standard feature indicating that the device passes Vulkan dEQP
      tests associated with date 2019-03-01 (0x07E30301). -->
 <permissions>
     <feature name="android.software.vulkan.deqp.level" version="132317953" />
diff --git a/data/etc/android.software.vulkan.deqp.level-2020-03-01.xml b/data/etc/android.software.vulkan.deqp.level-2020-03-01.xml
index 19b269b..84ba389 100644
--- a/data/etc/android.software.vulkan.deqp.level-2020-03-01.xml
+++ b/data/etc/android.software.vulkan.deqp.level-2020-03-01.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 
-<!-- This is the standard feature indicating that the device passes Vulkan deQP
+<!-- This is the standard feature indicating that the device passes Vulkan dEQP
      tests associated with date 2020-03-01 (0x07E40301). -->
 <permissions>
     <feature name="android.software.vulkan.deqp.level" version="132383489" />
diff --git a/data/etc/android.software.vulkan.deqp.level-2021-03-01.xml b/data/etc/android.software.vulkan.deqp.level-2021-03-01.xml
new file mode 100644
index 0000000..ae26269
--- /dev/null
+++ b/data/etc/android.software.vulkan.deqp.level-2021-03-01.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This is the standard feature indicating that the device passes Vulkan dEQP
+     tests associated with date 2021-03-01 (0x07E50301). -->
+<permissions>
+    <feature name="android.software.vulkan.deqp.level" version="132449025" />
+</permissions>
diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h
index b90d57e..5e40ca7 100644
--- a/include/input/DisplayViewport.h
+++ b/include/input/DisplayViewport.h
@@ -119,7 +119,7 @@
         physicalBottom = height;
         deviceWidth = width;
         deviceHeight = height;
-        isActive = false;
+        isActive = true;
         uniqueId.clear();
         physicalPort = std::nullopt;
         type = ViewportType::INTERNAL;
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 90feedd..7c3ba3f 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -183,6 +183,14 @@
     ],
     tidy_checks_as_errors: [
         "*",
+        "-clang-analyzer-core.CallAndMessage",
+        "-clang-analyzer-core.uninitialized.Assign",
+        "-clang-analyzer-unix.Malloc,",
+        "-clang-analyzer-deadcode.DeadStores",
+        "-clang-analyzer-optin.cplusplus.UninitializedObject",
+        "-misc-no-recursion",
+        "-misc-redundant-expression",
+        "-misc-unused-using-decls",
     ],
 }
 
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index d4c7acf..7d01e0b 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -1248,10 +1248,22 @@
                 constexpr uint32_t kForwardReplyFlags = TF_CLEAR_BUF;
                 sendReply(reply, (tr.flags & kForwardReplyFlags));
             } else {
-                if (error != OK || reply.dataSize() != 0) {
-                    alog << "oneway function results will be dropped but finished with status "
-                         << statusToString(error)
-                         << " and parcel size " << reply.dataSize() << endl;
+                if (error != OK) {
+                    alog << "oneway function results for code " << tr.code
+                         << " on binder at "
+                         << reinterpret_cast<void*>(tr.target.ptr)
+                         << " will be dropped but finished with status "
+                         << statusToString(error);
+
+                    // ideally we could log this even when error == OK, but it
+                    // causes too much logspam because some manually-written
+                    // interfaces have clients that call methods which always
+                    // write results, sometimes as oneway methods.
+                    if (reply.dataSize() != 0) {
+                         alog << " and reply parcel size " << reply.dataSize();
+                    }
+
+                    alog << endl;
                 }
                 LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
             }
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index 35c697e..f1085cf 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -136,7 +136,9 @@
         OP_PHONE_CALL_MICROPHONE = 100,
         OP_PHONE_CALL_CAMERA = 101,
         OP_RECORD_AUDIO_HOTWORD = 102,
-        _NUM_OP = 103
+        // Ops 103-105 are currently unused in native, and intentionally omitted
+        OP_RECORD_AUDIO_OUTPUT = 106,
+        _NUM_OP = 107
     };
 
     AppOpsManager();
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index a57beee..bdb74dc 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -105,6 +105,14 @@
     ],
     tidy_checks_as_errors: [
         "*",
+        "-clang-analyzer-core.CallAndMessage",
+        "-clang-analyzer-core.uninitialized.Assign",
+        "-clang-analyzer-unix.Malloc,",
+        "-clang-analyzer-deadcode.DeadStores",
+        "-clang-analyzer-optin.cplusplus.UninitializedObject",
+        "-misc-no-recursion",
+        "-misc-redundant-expression",
+        "-misc-unused-using-decls",
     ],
 }
 
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 0f7d159..a5261e5 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -404,6 +404,13 @@
     EXPECT_EQ(NO_ERROR, ret);
 }
 
+TEST_F(BinderLibTest, NopTransactionOneway) {
+    status_t ret;
+    Parcel data, reply;
+    ret = m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply, TF_ONE_WAY);
+    EXPECT_EQ(NO_ERROR, ret);
+}
+
 TEST_F(BinderLibTest, NopTransactionClear) {
     status_t ret;
     Parcel data, reply;
@@ -1182,9 +1189,6 @@
         virtual status_t onTransact(uint32_t code,
                                     const Parcel& data, Parcel* reply,
                                     uint32_t flags = 0) {
-            //printf("%s: code %d\n", __func__, code);
-            (void)flags;
-
             if (getuid() != (uid_t)IPCThreadState::self()->getCallingUid()) {
                 return PERMISSION_DENIED;
             }
@@ -1258,8 +1262,12 @@
                 return NO_ERROR;
             case BINDER_LIB_TEST_NOP_TRANSACTION_WAIT:
                 usleep(5000);
-                return NO_ERROR;
+                [[fallthrough]];
             case BINDER_LIB_TEST_NOP_TRANSACTION:
+                // oneway error codes should be ignored
+                if (flags & TF_ONE_WAY) {
+                    return UNKNOWN_ERROR;
+                }
                 return NO_ERROR;
             case BINDER_LIB_TEST_DELAYED_CALL_BACK: {
                 // Note: this transaction is only designed for use with a
diff --git a/libs/binderdebug/Android.bp b/libs/binderdebug/Android.bp
new file mode 100644
index 0000000..343246a
--- /dev/null
+++ b/libs/binderdebug/Android.bp
@@ -0,0 +1,28 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library {
+    name: "libbinderdebug",
+    vendor_available: true,
+    shared_libs: [
+        "libbase",
+        "libbinder",
+    ],
+    srcs: [
+        "BinderDebug.cpp",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
+}
diff --git a/libs/binderdebug/BinderDebug.cpp b/libs/binderdebug/BinderDebug.cpp
new file mode 100644
index 0000000..b435dba
--- /dev/null
+++ b/libs/binderdebug/BinderDebug.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+#include <binder/Binder.h>
+#include <sys/types.h>
+#include <fstream>
+#include <regex>
+
+#include <binderdebug/BinderDebug.h>
+
+namespace android {
+
+static std::string contextToString(BinderDebugContext context) {
+    switch (context) {
+        case BinderDebugContext::BINDER:
+            return "binder";
+        case BinderDebugContext::HWBINDER:
+            return "hwbinder";
+        case BinderDebugContext::VNDBINDER:
+            return "vndbinder";
+        default:
+            return std::string();
+    }
+}
+
+static status_t scanBinderContext(pid_t pid, const std::string& contextName,
+                                  std::function<void(const std::string&)> eachLine) {
+    std::ifstream ifs("/dev/binderfs/binder_logs/proc/" + std::to_string(pid));
+    if (!ifs.is_open()) {
+        ifs.open("/d/binder/proc/" + std::to_string(pid));
+        if (!ifs.is_open()) {
+            return -errno;
+        }
+    }
+    static const std::regex kContextLine("^context (\\w+)$");
+
+    bool isDesiredContext = false;
+    std::string line;
+    std::smatch match;
+    while (getline(ifs, line)) {
+        if (std::regex_search(line, match, kContextLine)) {
+            isDesiredContext = match.str(1) == contextName;
+            continue;
+        }
+        if (!isDesiredContext) {
+            continue;
+        }
+        eachLine(line);
+    }
+    return OK;
+}
+
+status_t getBinderPidInfo(BinderDebugContext context, pid_t pid, BinderPidInfo* pidInfo) {
+    std::smatch match;
+    static const std::regex kReferencePrefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+");
+    static const std::regex kThreadPrefix("^\\s*thread \\d+:\\s+l\\s+(\\d)(\\d)");
+    std::string contextStr = contextToString(context);
+    status_t ret = scanBinderContext(pid, contextStr, [&](const std::string& line) {
+        if (std::regex_search(line, match, kReferencePrefix)) {
+            const std::string& ptrString = "0x" + match.str(2); // use number after c
+            uint64_t ptr;
+            if (!::android::base::ParseUint(ptrString.c_str(), &ptr)) {
+                // Should not reach here, but just be tolerant.
+                return;
+            }
+            const std::string proc = " proc ";
+            auto pos = line.rfind(proc);
+            if (pos != std::string::npos) {
+                for (const std::string& pidStr : base::Split(line.substr(pos + proc.size()), " ")) {
+                    int32_t pid;
+                    if (!::android::base::ParseInt(pidStr, &pid)) {
+                        return;
+                    }
+                    pidInfo->refPids[ptr].push_back(pid);
+                }
+            }
+
+            return;
+        }
+        if (std::regex_search(line, match, kThreadPrefix)) {
+            // "1" is waiting in binder driver
+            // "2" is poll. It's impossible to tell if these are in use.
+            //     and HIDL default code doesn't use it.
+            bool isInUse = match.str(1) != "1";
+            // "0" is a thread that has called into binder
+            // "1" is looper thread
+            // "2" is main looper thread
+            bool isBinderThread = match.str(2) != "0";
+            if (!isBinderThread) {
+                return;
+            }
+            if (isInUse) {
+                pidInfo->threadUsage++;
+            }
+
+            pidInfo->threadCount++;
+            return;
+        }
+        return;
+    });
+    return ret;
+}
+
+} // namespace  android
diff --git a/libs/binderdebug/TEST_MAPPING b/libs/binderdebug/TEST_MAPPING
new file mode 100644
index 0000000..2f3353e
--- /dev/null
+++ b/libs/binderdebug/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "libbinderdebug_test"
+    }
+  ]
+}
diff --git a/libs/binderdebug/include/binderdebug/BinderDebug.h b/libs/binderdebug/include/binderdebug/BinderDebug.h
new file mode 100644
index 0000000..14a0ef3
--- /dev/null
+++ b/libs/binderdebug/include/binderdebug/BinderDebug.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 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 <map>
+#include <vector>
+
+namespace android {
+
+struct BinderPidInfo {
+    std::map<uint64_t, std::vector<pid_t>> refPids; // cookie -> processes which hold binder
+    uint32_t threadUsage;                           // number of threads in use
+    uint32_t threadCount;                           // number of threads total
+};
+
+enum class BinderDebugContext {
+    BINDER,
+    HWBINDER,
+    VNDBINDER,
+};
+
+status_t getBinderPidInfo(BinderDebugContext context, pid_t pid, BinderPidInfo* pidInfo);
+
+} // namespace  android
diff --git a/libs/binderdebug/tests/Android.bp b/libs/binderdebug/tests/Android.bp
new file mode 100644
index 0000000..4c06b1d
--- /dev/null
+++ b/libs/binderdebug/tests/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2020 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_test {
+    name: "libbinderdebug_test",
+    test_suites: ["general-tests"],
+    srcs: [
+        "binderdebug_test.cpp",
+        "android/binderdebug/test/IControl.aidl",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libutils",
+    ],
+    static_libs: ["libbinderdebug"],
+    cflags: ["-Wall", "-Werror"],
+    require_root: true,
+}
diff --git a/libs/binderdebug/tests/android/binderdebug/test/IControl.aidl b/libs/binderdebug/tests/android/binderdebug/test/IControl.aidl
new file mode 100644
index 0000000..8efeb63
--- /dev/null
+++ b/libs/binderdebug/tests/android/binderdebug/test/IControl.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.binderdebug.test;
+
+interface IControl {
+    // Notifies the service to continue execution
+    void Continue();
+}
diff --git a/libs/binderdebug/tests/binderdebug_test.cpp b/libs/binderdebug/tests/binderdebug_test.cpp
new file mode 100644
index 0000000..ea799c0
--- /dev/null
+++ b/libs/binderdebug/tests/binderdebug_test.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/Binder.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <binder/IPCThreadState.h>
+#include <binderdebug/BinderDebug.h>
+#include <gtest/gtest.h>
+#include <semaphore.h>
+#include <thread>
+
+#include <android/binderdebug/test/BnControl.h>
+#include <android/binderdebug/test/IControl.h>
+
+namespace android {
+namespace binderdebug {
+namespace test {
+
+class Control : public BnControl {
+public:
+    Control() {sem_init(&s, 1, 0);};
+    ::android::binder::Status Continue() override;
+    sem_t s;
+};
+
+::android::binder::Status Control::Continue() {
+    IPCThreadState::self()->flushCommands();
+    sem_post(&s);
+    return binder::Status::ok();
+}
+
+TEST(BinderDebugTests, BinderPid) {
+    BinderPidInfo pidInfo;
+    const auto& status = getBinderPidInfo(BinderDebugContext::BINDER, getpid(), &pidInfo);
+    ASSERT_EQ(status, OK);
+    // There should be one referenced PID for servicemanager
+    EXPECT_TRUE(!pidInfo.refPids.empty());
+}
+
+TEST(BinderDebugTests, BinderThreads) {
+    BinderPidInfo pidInfo;
+    const auto& status = getBinderPidInfo(BinderDebugContext::BINDER, getpid(), &pidInfo);
+    ASSERT_EQ(status, OK);
+    EXPECT_TRUE(pidInfo.threadUsage <= pidInfo.threadCount);
+    // The second looper thread can sometimes take longer to spawn.
+    EXPECT_GE(pidInfo.threadCount, 1);
+}
+
+extern "C" {
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+
+    // Create a child/client process to call into the main process so we can ensure
+    // looper thread has been registered before attempting to get the BinderPidInfo
+    pid_t pid = fork();
+    if (pid == 0) {
+        sp<IBinder> binder = android::defaultServiceManager()->getService(String16("binderdebug"));
+        sp<IControl> service;
+        if (binder != nullptr) {
+            service = android::interface_cast<IControl>(binder);
+        }
+        service->Continue();
+        exit(0);
+    }
+    sp<Control> iface = new Control;
+    android::defaultServiceManager()->addService(String16("binderdebug"), iface);
+    android::ProcessState::self()->setThreadPoolMaxThreadCount(8);
+    ProcessState::self()->startThreadPool();
+    sem_wait(&iface->s);
+
+    return RUN_ALL_TESTS();
+}
+} // extern "C"
+} // namespace  test
+} // namespace  binderdebug
+} // namespace  android
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index b9ab561..bf0386f 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -42,6 +42,10 @@
 // Macros to include adapter info in log messages
 #define BQA_LOGV(x, ...) \
     ALOGV("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
+// enable logs for a single layer
+//#define BQA_LOGV(x, ...) \
+//    ALOGV_IF((strstr(mName.c_str(), "SurfaceView") != nullptr), "[%s](f:%u,a:%u) " x, \
+//              mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
 #define BQA_LOGE(x, ...) \
     ALOGE("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
 
@@ -123,7 +127,7 @@
         mProducer->setMaxDequeuedBufferCount(2);
     }
     mBufferItemConsumer =
-        new BLASTBufferItemConsumer(mConsumer, GraphicBuffer::USAGE_HW_COMPOSER, 1, true);
+        new BLASTBufferItemConsumer(mConsumer, GraphicBuffer::USAGE_HW_COMPOSER, 1, false);
     static int32_t id = 0;
     auto consumerName = mName + "(BLAST Consumer)" + std::to_string(id);
     id++;
@@ -248,7 +252,8 @@
 
     BufferItem bufferItem;
 
-    status_t status = mBufferItemConsumer->acquireBuffer(&bufferItem, -1, false);
+    status_t status =
+            mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false);
     if (status != OK) {
         BQA_LOGE("Failed to acquire a buffer, err=%s", statusToString(status).c_str());
         return;
@@ -289,6 +294,9 @@
     mLastBufferScalingMode = bufferItem.mScalingMode;
 
     t->setBuffer(mSurfaceControl, buffer);
+    t->setDataspace(mSurfaceControl, static_cast<ui::Dataspace>(bufferItem.mDataSpace));
+    t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata);
+    t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage);
     t->setAcquireFence(mSurfaceControl,
                        bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE);
     t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index e46a415..405658b 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -1230,6 +1230,21 @@
 
         return remote()->transact(BnSurfaceComposer::ADD_TRANSACTION_TRACE_LISTENER, data, &reply);
     }
+
+    /**
+     * Get priority of the RenderEngine in surface flinger.
+     */
+    virtual int getGPUContextPriority() {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        status_t err =
+                remote()->transact(BnSurfaceComposer::GET_GPU_CONTEXT_PRIORITY, data, &reply);
+        if (err != NO_ERROR) {
+            ALOGE("getGPUContextPriority failed to read data:  %s (%d)", strerror(-err), err);
+            return 0;
+        }
+        return reply.readInt32();
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -2094,6 +2109,12 @@
 
             return addTransactionTraceListener(listener);
         }
+        case GET_GPU_CONTEXT_PRIORITY: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            int priority = getGPUContextPriority();
+            SAFE_PARCEL(reply->writeInt32, priority);
+            return NO_ERROR;
+        }
         default: {
             return BBinder::onTransact(code, data, reply, flags);
         }
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 9ed7d1c..0d370d3 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1988,6 +1988,10 @@
                                                                           lightRadius);
 }
 
+int SurfaceComposerClient::getGPUContextPriority() {
+    return ComposerService::getComposerService()->getGPUContextPriority();
+}
+
 // ----------------------------------------------------------------------------
 
 status_t ScreenshotClient::captureDisplay(const DisplayCaptureArgs& captureArgs,
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 86e3a25..7d25d61 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -504,6 +504,11 @@
      */
     virtual status_t addTransactionTraceListener(
             const sp<gui::ITransactionTraceListener>& listener) = 0;
+
+    /**
+     * Gets priority of the RenderEngine in SurfaceFlinger.
+     */
+    virtual int getGPUContextPriority() = 0;
 };
 
 // ----------------------------------------------------------------------------
@@ -565,6 +570,7 @@
         ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN,
         SET_FRAME_TIMELINE_VSYNC,
         ADD_TRANSACTION_TRACE_LISTENER,
+        GET_GPU_CONTEXT_PRIORITY,
         // Always append new enum to the end.
     };
 
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index f1845ee..3ee4a39 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -185,6 +185,11 @@
     static bool getProtectedContentSupport();
 
     /**
+     * Gets the context priority of surface flinger's render engine.
+     */
+    static int getGPUContextPriority();
+
+    /**
      * Uncaches a buffer in ISurfaceComposer. It must be uncached via a transaction so that it is
      * in order with other transactions that use buffers.
      */
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index c39b0b5..c75c46c 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -95,6 +95,15 @@
         return std::make_unique<InputSurface>(surfaceControl, width, height);
     }
 
+    static std::unique_ptr<InputSurface> makeBlastInputSurface(const sp<SurfaceComposerClient> &scc,
+                                                               int width, int height) {
+        sp<SurfaceControl> surfaceControl =
+                scc->createSurface(String8("Test Buffer Surface"), width, height,
+                                   PIXEL_FORMAT_RGBA_8888,
+                                   ISurfaceComposerClient::eFXSurfaceBufferState);
+        return std::make_unique<InputSurface>(surfaceControl, width, height);
+    }
+
     static std::unique_ptr<InputSurface> makeContainerInputSurface(
             const sp<SurfaceComposerClient> &scc, int width, int height) {
         sp<SurfaceControl> surfaceControl =
@@ -180,13 +189,13 @@
         t.apply(true);
     }
 
-    void showAt(int x, int y) {
+    void showAt(int x, int y, Rect crop = Rect(0, 0, 100, 100)) {
         SurfaceComposerClient::Transaction t;
         t.show(mSurfaceControl);
         t.setInputWindowInfo(mSurfaceControl, mInputInfo);
         t.setLayer(mSurfaceControl, LAYER_BASE);
         t.setPosition(mSurfaceControl, x, y);
-        t.setCrop_legacy(mSurfaceControl, Rect(0, 0, 100, 100));
+        t.setCrop_legacy(mSurfaceControl, crop);
         t.setAlpha(mSurfaceControl, 1);
         t.apply(true);
     }
@@ -684,4 +693,34 @@
     surface->expectTap(1, 10);
 }
 
+TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_bql) {
+    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+
+    std::unique_ptr<InputSurface> bufferSurface =
+            InputSurface::makeBufferInputSurface(mComposerClient, 0, 0);
+    bufferSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE;
+    bufferSurface->mInputInfo.ownerUid = 22222;
+
+    surface->showAt(10, 10);
+    bufferSurface->showAt(50, 50, Rect::EMPTY_RECT);
+
+    injectTap(11, 11);
+    surface->expectTap(1, 1);
+}
+
+TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_blast) {
+    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+
+    std::unique_ptr<InputSurface> bufferSurface =
+            InputSurface::makeBlastInputSurface(mComposerClient, 0, 0);
+    bufferSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE;
+    bufferSurface->mInputInfo.ownerUid = 22222;
+
+    surface->showAt(10, 10);
+    bufferSurface->showAt(50, 50, Rect::EMPTY_RECT);
+
+    injectTap(11, 11);
+    surface->expectTap(1, 1);
+}
+
 } // namespace android::test
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index ce3afa2..7761db8 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -887,6 +887,8 @@
         return NO_ERROR;
     }
 
+    int getGPUContextPriority() override { return 0; };
+
 protected:
     IBinder* onAsBinder() override { return nullptr; }
 
diff --git a/libs/renderengine/gl/ProgramCache.cpp b/libs/renderengine/gl/ProgramCache.cpp
index 7fc0499..5ff9240 100644
--- a/libs/renderengine/gl/ProgramCache.cpp
+++ b/libs/renderengine/gl/ProgramCache.cpp
@@ -740,15 +740,6 @@
         if (needs.isOpaque()) {
             fs << "gl_FragColor.a = 1.0;";
         }
-        if (needs.hasAlpha()) {
-            // modulate the current alpha value with alpha set
-            if (needs.isPremultiplied()) {
-                // ... and the color too if we're premultiplied
-                fs << "gl_FragColor *= color.a;";
-            } else {
-                fs << "gl_FragColor.a *= color.a;";
-            }
-        }
     }
 
     if (needs.hasTransformMatrix() || (needs.getInputTF() != needs.getOutputTF()) ||
@@ -768,6 +759,23 @@
         }
     }
 
+    /*
+     * Whether applying layer alpha before or after color transform doesn't matter,
+     * as long as we can undo premultiplication. But we cannot un-premultiply
+     * for color transform if the layer alpha = 0, e.g. 0 / (0 + 0.0019) = 0.
+     */
+    if (!needs.drawShadows()) {
+        if (needs.hasAlpha()) {
+            // modulate the current alpha value with alpha set
+            if (needs.isPremultiplied()) {
+                // ... and the color too if we're premultiplied
+                fs << "gl_FragColor *= color.a;";
+            } else {
+                fs << "gl_FragColor.a *= color.a;";
+            }
+        }
+    }
+
     if (needs.hasRoundedCorners()) {
         if (needs.isPremultiplied()) {
             fs << "gl_FragColor *= vec4(applyCornerRadius(outCropCoords));";
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 4e9c5af..ee0a70a 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -587,6 +587,10 @@
             if (!texMatrix.invert(&matrix)) {
                 matrix = texMatrix;
             }
+            // The shader does not respect the translation, so we add it to the texture
+            // transform for the SkImage. This will make sure that the correct layer contents
+            // are drawn in the correct part of the screen.
+            matrix.postTranslate(layer->geometry.boundaries.left, layer->geometry.boundaries.top);
 
             sk_sp<SkShader> shader;
 
@@ -596,7 +600,7 @@
                                                    {SkFilterMode::kLinear, SkMipmapMode::kNone}),
                                            &matrix);
             } else {
-                shader = image->makeShader(matrix);
+                shader = image->makeShader(SkSamplingOptions(), matrix);
             }
 
             if (mUseColorManagement &&
@@ -649,12 +653,11 @@
             drawShadow(canvas, rect, layer->geometry.roundedCornersRadius, layer->shadow);
         }
 
+        // Push the clipRRect onto the clip stack. Draw the image. Pop the clip.
         if (layer->geometry.roundedCornersRadius > 0) {
-            canvas->drawRRect(getRoundedRect(layer), paint);
-        } else {
-            canvas->drawRect(dest, paint);
+            canvas->clipRRect(getRoundedRect(layer), true);
         }
-
+        canvas->drawRect(dest, paint);
         canvas->restore();
     }
     canvas->restore();
@@ -698,7 +701,7 @@
 }
 
 inline SkRRect SkiaGLRenderEngine::getRoundedRect(const LayerSettings* layer) {
-    const auto rect = getSkRect(layer->geometry.boundaries);
+    const auto rect = getSkRect(layer->geometry.roundedCornersCrop);
     const auto cornerRadius = layer->geometry.roundedCornersRadius;
     return SkRRect::MakeRectXY(rect, cornerRadius, cornerRadius);
 }
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index e825742..d9dfd8c 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -406,6 +406,12 @@
     void fillBufferColorTransform();
 
     template <typename SourceVariant>
+    void fillBufferWithColorTransformZeroLayerAlpha();
+
+    template <typename SourceVariant>
+    void fillBufferColorTransformZeroLayerAlpha();
+
+    template <typename SourceVariant>
     void fillRedBufferWithRoundedCorners();
 
     template <typename SourceVariant>
@@ -765,6 +771,36 @@
 }
 
 template <typename SourceVariant>
+void RenderEngineTest::fillBufferWithColorTransformZeroLayerAlpha() {
+    renderengine::DisplaySettings settings;
+    settings.physicalDisplay = fullscreenRect();
+    settings.clip = Rect(1, 1);
+
+    std::vector<const renderengine::LayerSettings*> layers;
+
+    renderengine::LayerSettings layer;
+    layer.geometry.boundaries = Rect(1, 1).toFloatRect();
+    SourceVariant::fillColor(layer, 0.5f, 0.25f, 0.125f, this);
+    layer.alpha = 0;
+
+    // construct a fake color matrix
+    // simple inverse color
+    settings.colorTransform = mat4(-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 1, 1, 1, 1);
+
+    layer.geometry.boundaries = Rect(1, 1).toFloatRect();
+
+    layers.push_back(&layer);
+
+    invokeDraw(settings, layers, mBuffer);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferColorTransformZeroLayerAlpha() {
+    fillBufferWithColorTransformZeroLayerAlpha<SourceVariant>();
+    expectBufferColor(fullscreenRect(), 0, 0, 0, 0);
+}
+
+template <typename SourceVariant>
 void RenderEngineTest::fillRedBufferWithRoundedCorners() {
     renderengine::DisplaySettings settings;
     settings.physicalDisplay = fullscreenRect();
@@ -1240,6 +1276,13 @@
     fillBufferWithRoundedCorners<ColorSourceVariant>();
 }
 
+TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransformZeroLayerAlpha_colorSource) {
+    const auto& renderEngineFactory = GetParam();
+    mRE = renderEngineFactory->createRenderEngine();
+
+    fillBufferColorTransformZeroLayerAlpha<ColorSourceVariant>();
+}
+
 TEST_P(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_colorSource) {
     const auto& renderEngineFactory = GetParam();
     mRE = renderEngineFactory->createRenderEngine();
@@ -1337,6 +1380,12 @@
 
     fillBufferWithRoundedCorners<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
+TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransformZeroLayerAlpha_opaqueBufferSource) {
+    const auto& renderEngineFactory = GetParam();
+    mRE = renderEngineFactory->createRenderEngine();
+
+    fillBufferColorTransformZeroLayerAlpha<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_opaqueBufferSource) {
     const auto& renderEngineFactory = GetParam();
@@ -1436,6 +1485,13 @@
     fillBufferWithRoundedCorners<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
+TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransformZeroLayerAlpha_bufferSource) {
+    const auto& renderEngineFactory = GetParam();
+    mRE = renderEngineFactory->createRenderEngine();
+
+    fillBufferColorTransformZeroLayerAlpha<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
 TEST_P(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_bufferSource) {
     const auto& renderEngineFactory = GetParam();
     mRE = renderEngineFactory->createRenderEngine();
@@ -1735,6 +1791,56 @@
     EXPECT_TRUE(mRE->isTextureNameKnownForTesting(texName));
 }
 
+TEST_P(RenderEngineTest, testRoundedCornersCrop) {
+    const auto& renderEngineFactory = GetParam();
+    mRE = renderEngineFactory->createRenderEngine();
+
+    renderengine::DisplaySettings settings;
+    settings.physicalDisplay = fullscreenRect();
+    settings.clip = fullscreenRect();
+    settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
+
+    std::vector<const renderengine::LayerSettings*> layers;
+
+    renderengine::LayerSettings redLayer;
+    redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
+    redLayer.geometry.boundaries = fullscreenRect().toFloatRect();
+    redLayer.geometry.roundedCornersRadius = 5.0f;
+    redLayer.geometry.roundedCornersCrop = fullscreenRect().toFloatRect();
+    // Red background.
+    redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f);
+    redLayer.alpha = 1.0f;
+
+    layers.push_back(&redLayer);
+
+    // Green layer with 1/3 size.
+    renderengine::LayerSettings greenLayer;
+    greenLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
+    greenLayer.geometry.boundaries = fullscreenRect().toFloatRect();
+    greenLayer.geometry.roundedCornersRadius = 5.0f;
+    // Bottom right corner is not going to be rounded.
+    greenLayer.geometry.roundedCornersCrop =
+            Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3, DEFAULT_DISPLAY_HEIGHT,
+                 DEFAULT_DISPLAY_HEIGHT)
+                    .toFloatRect();
+    greenLayer.source.solidColor = half3(0.0f, 1.0f, 0.0f);
+    greenLayer.alpha = 1.0f;
+
+    layers.push_back(&greenLayer);
+
+    invokeDraw(settings, layers, mBuffer);
+
+    // Corners should be ignored...
+    // Screen size: width is 128, height is 256.
+    expectBufferColor(Rect(0, 0, 1, 1), 0, 0, 0, 0);
+    expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH - 1, 0, DEFAULT_DISPLAY_WIDTH, 1), 0, 0, 0, 0);
+    expectBufferColor(Rect(0, DEFAULT_DISPLAY_HEIGHT - 1, 1, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 0);
+    // Bottom right corner is kept out of the clipping, and it's green.
+    expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH - 1, DEFAULT_DISPLAY_HEIGHT - 1,
+                           DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+                      0, 255, 0, 255);
+}
+
 } // namespace android
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/libs/sensorprivacy/OWNERS b/libs/sensorprivacy/OWNERS
new file mode 100644
index 0000000..be955f5
--- /dev/null
+++ b/libs/sensorprivacy/OWNERS
@@ -0,0 +1,3 @@
+cbrubaker@google.com
+evanseverson@google.com
+mpgroover@google.com
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index b620e2d..ce12c27 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -647,6 +647,13 @@
         return;
     }
 
+    if (!newViewport->isActive) {
+        ALOGI("Disabling %s (device %i) because the associated viewport is not active",
+              getDeviceName().c_str(), getDeviceId());
+        mDeviceMode = DeviceMode::DISABLED;
+        return;
+    }
+
     // Raw width and height in the natural orientation.
     int32_t rawWidth = mRawPointerAxes.getRawWidth();
     int32_t rawHeight = mRawPointerAxes.getRawHeight();
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index cd61750..c26a389 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -224,10 +224,11 @@
     }
 
     void addDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
-            const std::string& uniqueId, std::optional<uint8_t> physicalPort,
-            ViewportType viewportType) {
-        const DisplayViewport viewport = createDisplayViewport(displayId, width, height,
-                orientation, uniqueId, physicalPort, viewportType);
+                            bool isActive, const std::string& uniqueId,
+                            std::optional<uint8_t> physicalPort, ViewportType viewportType) {
+        const DisplayViewport viewport =
+                createDisplayViewport(displayId, width, height, orientation, isActive, uniqueId,
+                                      physicalPort, viewportType);
         mViewports.push_back(viewport);
         mConfig.setDisplayViewports(mViewports);
     }
@@ -295,8 +296,9 @@
 
 private:
     DisplayViewport createDisplayViewport(int32_t displayId, int32_t width, int32_t height,
-            int32_t orientation, const std::string& uniqueId, std::optional<uint8_t> physicalPort,
-            ViewportType type) {
+                                          int32_t orientation, bool isActive,
+                                          const std::string& uniqueId,
+                                          std::optional<uint8_t> physicalPort, ViewportType type) {
         bool isRotated = (orientation == DISPLAY_ORIENTATION_90
                 || orientation == DISPLAY_ORIENTATION_270);
         DisplayViewport v;
@@ -312,6 +314,7 @@
         v.physicalBottom = isRotated ? width : height;
         v.deviceWidth = isRotated ? height : width;
         v.deviceHeight = isRotated ? width : height;
+        v.isActive = isActive;
         v.uniqueId = uniqueId;
         v.physicalPort = physicalPort;
         v.type = type;
@@ -1117,7 +1120,7 @@
 
     // Add an internal viewport, then clear it
     mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
-                                    DISPLAY_ORIENTATION_0, uniqueId, NO_PORT,
+                                    DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId, NO_PORT,
                                     ViewportType::INTERNAL);
 
     // Check matching by uniqueId
@@ -1148,20 +1151,20 @@
 
     // Add an internal viewport
     mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
-                                    DISPLAY_ORIENTATION_0, internalUniqueId, NO_PORT,
-                                    ViewportType::INTERNAL);
+                                    DISPLAY_ORIENTATION_0, true /*isActive*/, internalUniqueId,
+                                    NO_PORT, ViewportType::INTERNAL);
     // Add an external viewport
     mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
-                                    DISPLAY_ORIENTATION_0, externalUniqueId, NO_PORT,
-                                    ViewportType::EXTERNAL);
+                                    DISPLAY_ORIENTATION_0, true /*isActive*/, externalUniqueId,
+                                    NO_PORT, ViewportType::EXTERNAL);
     // Add an virtual viewport
     mFakePolicy->addDisplayViewport(virtualDisplayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT,
-                                    DISPLAY_ORIENTATION_0, virtualUniqueId1, NO_PORT,
-                                    ViewportType::VIRTUAL);
+                                    DISPLAY_ORIENTATION_0, true /*isActive*/, virtualUniqueId1,
+                                    NO_PORT, ViewportType::VIRTUAL);
     // Add another virtual viewport
     mFakePolicy->addDisplayViewport(virtualDisplayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT,
-                                    DISPLAY_ORIENTATION_0, virtualUniqueId2, NO_PORT,
-                                    ViewportType::VIRTUAL);
+                                    DISPLAY_ORIENTATION_0, true /*isActive*/, virtualUniqueId2,
+                                    NO_PORT, ViewportType::VIRTUAL);
 
     // Check matching by type for internal
     std::optional<DisplayViewport> internalViewport =
@@ -1210,10 +1213,12 @@
         mFakePolicy->clearViewports();
         // Add a viewport
         mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            DISPLAY_ORIENTATION_0, uniqueId1, NO_PORT, type);
+                                        DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId1,
+                                        NO_PORT, type);
         // Add another viewport
         mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            DISPLAY_ORIENTATION_0, uniqueId2, NO_PORT, type);
+                                        DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId2,
+                                        NO_PORT, type);
 
         // Check that correct display viewport was returned by comparing the display IDs.
         std::optional<DisplayViewport> viewport1 =
@@ -1253,10 +1258,10 @@
     // Add the default display first and ensure it gets returned.
     mFakePolicy->clearViewports();
     mFakePolicy->addDisplayViewport(ADISPLAY_ID_DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
-                                    DISPLAY_ORIENTATION_0, uniqueId1, NO_PORT,
+                                    DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId1, NO_PORT,
                                     ViewportType::INTERNAL);
     mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
-                                    DISPLAY_ORIENTATION_0, uniqueId2, NO_PORT,
+                                    DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId2, NO_PORT,
                                     ViewportType::INTERNAL);
 
     std::optional<DisplayViewport> viewport =
@@ -1268,10 +1273,10 @@
     // Add the default display second to make sure order doesn't matter.
     mFakePolicy->clearViewports();
     mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
-                                    DISPLAY_ORIENTATION_0, uniqueId2, NO_PORT,
+                                    DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId2, NO_PORT,
                                     ViewportType::INTERNAL);
     mFakePolicy->addDisplayViewport(ADISPLAY_ID_DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
-                                    DISPLAY_ORIENTATION_0, uniqueId1, NO_PORT,
+                                    DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId1, NO_PORT,
                                     ViewportType::INTERNAL);
 
     viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
@@ -1296,10 +1301,12 @@
     mFakePolicy->clearViewports();
     // Add a viewport that's associated with some display port that's not of interest.
     mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            DISPLAY_ORIENTATION_0, uniqueId1, hdmi3, type);
+                                    DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId1, hdmi3,
+                                    type);
     // Add another viewport, connected to HDMI1 port
     mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            DISPLAY_ORIENTATION_0, uniqueId2, hdmi1, type);
+                                    DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId2, hdmi1,
+                                    type);
 
     // Check that correct display viewport was returned by comparing the display ports.
     std::optional<DisplayViewport> hdmi1Viewport = mFakePolicy->getDisplayViewportByPort(hdmi1);
@@ -1703,10 +1710,10 @@
     // Add default and second display.
     mFakePolicy->clearViewports();
     mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
-                                    DISPLAY_ORIENTATION_0, "local:0", NO_PORT,
+                                    DISPLAY_ORIENTATION_0, true /*isActive*/, "local:0", NO_PORT,
                                     ViewportType::INTERNAL);
     mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
-                                    DISPLAY_ORIENTATION_0, "local:1", hdmi1,
+                                    DISPLAY_ORIENTATION_0, true /*isActive*/, "local:1", hdmi1,
                                     ViewportType::EXTERNAL);
     mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
     mReader->loopOnce();
@@ -2000,8 +2007,8 @@
                                       int32_t orientation, const std::string& uniqueId,
                                       std::optional<uint8_t> physicalPort,
                                       ViewportType viewportType) {
-        mFakePolicy->addDisplayViewport(displayId, width, height, orientation, uniqueId,
-                                        physicalPort, viewportType);
+        mFakePolicy->addDisplayViewport(displayId, width, height, orientation, true /*isActive*/,
+                                        uniqueId, physicalPort, viewportType);
         mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
     }
 
@@ -2331,7 +2338,8 @@
 
     // Prepare displays.
     mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
-                                    DISPLAY_ORIENTATION_0, UNIQUE_ID, hdmi, ViewportType::INTERNAL);
+                                    DISPLAY_ORIENTATION_0, true /*isActive*/, UNIQUE_ID, hdmi,
+                                    ViewportType::INTERNAL);
     mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
                        InputReaderConfiguration::CHANGE_DISPLAY_INFO);
     ASSERT_TRUE(mDevice->isEnabled());
@@ -2421,8 +2429,8 @@
     void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
             int32_t orientation, const std::string& uniqueId,
             std::optional<uint8_t> physicalPort, ViewportType viewportType) {
-        mFakePolicy->addDisplayViewport(
-                displayId, width, height, orientation, uniqueId, physicalPort, viewportType);
+        mFakePolicy->addDisplayViewport(displayId, width, height, orientation, true /*isActive*/,
+                                        uniqueId, physicalPort, viewportType);
         configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
     }
 
@@ -4057,7 +4065,8 @@
     constexpr int32_t SECOND_DISPLAY_ID = 1;
     const std::string SECOND_DISPLAY_UNIQUE_ID = "local:1";
     mFakePolicy->addDisplayViewport(SECOND_DISPLAY_ID, 800, 480, DISPLAY_ORIENTATION_0,
-                                    SECOND_DISPLAY_UNIQUE_ID, NO_PORT, ViewportType::EXTERNAL);
+                                    true /*isActive*/, SECOND_DISPLAY_UNIQUE_ID, NO_PORT,
+                                    ViewportType::EXTERNAL);
     mFakePolicy->setDefaultPointerDisplayId(SECOND_DISPLAY_ID);
     configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
 
@@ -7108,6 +7117,26 @@
     ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
 }
 
+/**
+ * When the viewport is not active (isActive=false), the touch mapper should be disabled and the
+ * events should not be delivered to the listener.
+ */
+TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreDropped) {
+    addConfigurationProperty("touch.deviceType", "touchScreen");
+    mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
+                                    DISPLAY_ORIENTATION_0, false /*isActive*/, UNIQUE_ID, NO_PORT,
+                                    ViewportType::INTERNAL);
+    configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+    prepareAxes(POSITION);
+    MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+    NotifyMotionArgs motionArgs;
+    processPosition(mapper, 100, 100);
+    processSync(mapper);
+
+    mFakeListener->assertNotifyMotionWasNotCalled();
+}
+
 TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShowTouches) {
     // Setup the first touch screen device.
     prepareAxes(POSITION | ID | SLOT);
@@ -7708,8 +7737,8 @@
         configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
     }
 
-    void processPositionAndVerify(MultiTouchInputMapper& mapper, int32_t xInside, int32_t yInside,
-                                  int32_t xOutside, int32_t yOutside, int32_t xExpected,
+    void processPositionAndVerify(MultiTouchInputMapper& mapper, int32_t xOutside, int32_t yOutside,
+                                  int32_t xInside, int32_t yInside, int32_t xExpected,
                                   int32_t yExpected) {
         // touch on outside area should not work.
         processPosition(mapper, toRawX(xOutside), toRawY(yOutside));
diff --git a/services/inputflinger/tests/TestInputListener.cpp b/services/inputflinger/tests/TestInputListener.cpp
index 352995c..1050ab8 100644
--- a/services/inputflinger/tests/TestInputListener.cpp
+++ b/services/inputflinger/tests/TestInputListener.cpp
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
+#include "TestInputListener.h"
 
 #include <gtest/gtest.h>
 
-#include "TestInputListener.h"
-
 namespace android {
 
 // --- TestInputListener ---
@@ -28,7 +27,7 @@
       : mEventHappenedTimeout(eventHappenedTimeout),
         mEventDidNotHappenTimeout(eventDidNotHappenTimeout) {}
 
-TestInputListener::~TestInputListener() { }
+TestInputListener::~TestInputListener() {}
 
 void TestInputListener::assertNotifyConfigurationChangedWasCalled(
         NotifyConfigurationChangedArgs* outEventArgs) {
@@ -43,8 +42,7 @@
             "notifyConfigurationChanged() should not be called."));
 }
 
-void TestInputListener::assertNotifyDeviceResetWasCalled(
-        NotifyDeviceResetArgs* outEventArgs) {
+void TestInputListener::assertNotifyDeviceResetWasCalled(NotifyDeviceResetArgs* outEventArgs) {
     ASSERT_NO_FATAL_FAILURE(
             assertCalled<
                     NotifyDeviceResetArgs>(outEventArgs,
@@ -73,7 +71,7 @@
 
 void TestInputListener::assertNotifyMotionWasNotCalled() {
     ASSERT_NO_FATAL_FAILURE(
-            assertNotCalled<NotifySwitchArgs>("notifySwitch() should not be called."));
+            assertNotCalled<NotifyMotionArgs>("notifyMotion() should not be called."));
 }
 
 void TestInputListener::assertNotifySwitchWasCalled(NotifySwitchArgs* outEventArgs) {
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 5cf0460..b6c59cd 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -479,6 +479,10 @@
         return Rect(getActiveWidth(s), getActiveHeight(s));
     }
 
+    if (mBufferInfo.mBuffer == nullptr) {
+        return Rect::INVALID_RECT;
+    }
+
     // if the display frame is not defined, use the parent bounds as the buffer size.
     const auto& p = mDrawingParent.promote();
     if (p != nullptr) {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index b273712..d5b599a 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -819,7 +819,8 @@
             // to be applied as per normal (no synchronization).
             mCurrentState.barrierLayer_legacy = nullptr;
         } else {
-            auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.barrierFrameNumber, this);
+            auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.barrierFrameNumber, this,
+                                                         barrierLayer);
             if (barrierLayer->addSyncPoint(syncPoint)) {
                 std::stringstream ss;
                 ss << "Adding sync point " << mCurrentState.barrierFrameNumber;
@@ -844,7 +845,7 @@
     ATRACE_CALL();
 
     *stateToCommit = mPendingStates[0];
-    mPendingStates.removeAt(0);
+    mPendingStates.pop_front();
     ATRACE_INT(mTransactionName.c_str(), mPendingStates.size());
 }
 
@@ -883,6 +884,7 @@
                 mRemoteSyncPoints.pop_front();
             } else {
                 ATRACE_NAME("!frameIsAvailable");
+                mRemoteSyncPoints.front()->checkTimeoutAndLog();
                 break;
             }
         } else {
@@ -2432,27 +2434,7 @@
     return mRemovedFromCurrentState;
 }
 
-InputWindowInfo Layer::fillInputInfo() {
-    if (!hasInputInfo()) {
-        mDrawingState.inputInfo.name = getName();
-        mDrawingState.inputInfo.ownerUid = mOwnerUid;
-        mDrawingState.inputInfo.ownerPid = mOwnerPid;
-        mDrawingState.inputInfo.inputFeatures = InputWindowInfo::Feature::NO_INPUT_CHANNEL;
-        mDrawingState.inputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL;
-        mDrawingState.inputInfo.displayId = getLayerStack();
-    }
-
-    InputWindowInfo info = mDrawingState.inputInfo;
-    info.id = sequence;
-
-    if (info.displayId == ADISPLAY_ID_NONE) {
-        info.displayId = getLayerStack();
-    }
-
-    ui::Transform t = getTransform();
-    int32_t xSurfaceInset = info.surfaceInset;
-    int32_t ySurfaceInset = info.surfaceInset;
-
+void Layer::fillInputFrameInfo(InputWindowInfo& info) {
     // Transform layer size to screen space and inset it by surface insets.
     // If this is a portal window, set the touchableRegion to the layerBounds.
     Rect layerBounds = info.portalToDisplayId == ADISPLAY_ID_NONE
@@ -2462,6 +2444,20 @@
         layerBounds = getCroppedBufferSize(getDrawingState());
     }
 
+    if (!layerBounds.isValid()) {
+        // If the layer bounds is empty, set the frame to empty and clear the transform
+        info.frameLeft = 0;
+        info.frameTop = 0;
+        info.frameRight = 0;
+        info.frameBottom = 0;
+        info.transform.reset();
+        return;
+    }
+
+    ui::Transform t = getTransform();
+    int32_t xSurfaceInset = info.surfaceInset;
+    int32_t ySurfaceInset = info.surfaceInset;
+
     const float xScale = t.getScaleX();
     const float yScale = t.getScaleY();
     if (xScale != 1.0f || yScale != 1.0f) {
@@ -2528,6 +2524,27 @@
     // Position the touchable region relative to frame screen location and restrict it to frame
     // bounds.
     info.touchableRegion = inputTransform.transform(info.touchableRegion);
+}
+
+InputWindowInfo Layer::fillInputInfo() {
+    if (!hasInputInfo()) {
+        mDrawingState.inputInfo.name = getName();
+        mDrawingState.inputInfo.ownerUid = mOwnerUid;
+        mDrawingState.inputInfo.ownerPid = mOwnerPid;
+        mDrawingState.inputInfo.inputFeatures = InputWindowInfo::Feature::NO_INPUT_CHANNEL;
+        mDrawingState.inputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL;
+        mDrawingState.inputInfo.displayId = getLayerStack();
+    }
+
+    InputWindowInfo info = mDrawingState.inputInfo;
+    info.id = sequence;
+
+    if (info.displayId == ADISPLAY_ID_NONE) {
+        info.displayId = getLayerStack();
+    }
+
+    fillInputFrameInfo(info);
+
     // For compatibility reasons we let layers which can receive input
     // receive input before they have actually submitted a buffer. Because
     // of this we use canReceiveInput instead of isVisible to check the
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index cc47d12..2cfdba3 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -36,6 +36,7 @@
 #include <utils/RefBase.h>
 #include <utils/Timers.h>
 
+#include <chrono>
 #include <cstdint>
 #include <list>
 #include <optional>
@@ -902,12 +903,13 @@
 protected:
     class SyncPoint {
     public:
-        explicit SyncPoint(uint64_t frameNumber, wp<Layer> requestedSyncLayer)
+        explicit SyncPoint(uint64_t frameNumber, wp<Layer> requestedSyncLayer,
+                           wp<Layer> barrierLayer_legacy)
               : mFrameNumber(frameNumber),
                 mFrameIsAvailable(false),
                 mTransactionIsApplied(false),
-                mRequestedSyncLayer(requestedSyncLayer) {}
-
+                mRequestedSyncLayer(requestedSyncLayer),
+                mBarrierLayer_legacy(barrierLayer_legacy) {}
         uint64_t getFrameNumber() const { return mFrameNumber; }
 
         bool frameIsAvailable() const { return mFrameIsAvailable; }
@@ -920,11 +922,42 @@
 
         sp<Layer> getRequestedSyncLayer() { return mRequestedSyncLayer.promote(); }
 
+        sp<Layer> getBarrierLayer() const { return mBarrierLayer_legacy.promote(); }
+
+        bool isTimeout() const {
+            using namespace std::chrono_literals;
+            static constexpr std::chrono::nanoseconds TIMEOUT_THRESHOLD = 1s;
+
+            return std::chrono::steady_clock::now() - mCreateTimeStamp > TIMEOUT_THRESHOLD;
+        }
+
+        void checkTimeoutAndLog() {
+            using namespace std::chrono_literals;
+            static constexpr std::chrono::nanoseconds LOG_PERIOD = 1s;
+
+            if (!frameIsAvailable() && isTimeout()) {
+                const auto now = std::chrono::steady_clock::now();
+                if (now - mLastLogTime > LOG_PERIOD) {
+                    mLastLogTime = now;
+                    sp<Layer> requestedSyncLayer = getRequestedSyncLayer();
+                    sp<Layer> barrierLayer = getBarrierLayer();
+                    ALOGW("[%s] sync point %" PRIu64 " wait timeout %lld for %s",
+                          requestedSyncLayer ? requestedSyncLayer->getDebugName() : "Removed",
+                          mFrameNumber, (now - mCreateTimeStamp).count(),
+                          barrierLayer ? barrierLayer->getDebugName() : "Removed");
+                }
+            }
+        }
+
     private:
         const uint64_t mFrameNumber;
         std::atomic<bool> mFrameIsAvailable;
         std::atomic<bool> mTransactionIsApplied;
         wp<Layer> mRequestedSyncLayer;
+        wp<Layer> mBarrierLayer_legacy;
+        const std::chrono::time_point<std::chrono::steady_clock> mCreateTimeStamp =
+                std::chrono::steady_clock::now();
+        std::chrono::time_point<std::chrono::steady_clock> mLastLogTime;
     };
 
     friend class impl::SurfaceInterceptor;
@@ -1011,12 +1044,12 @@
     State mDrawingState;
     // Store a copy of the pending state so that the drawing thread can access the
     // states without a lock.
-    Vector<State> mPendingStatesSnapshot;
+    std::deque<State> mPendingStatesSnapshot;
 
     // these are protected by an external lock (mStateLock)
     State mCurrentState;
     std::atomic<uint32_t> mTransactionFlags{0};
-    Vector<State> mPendingStates;
+    std::deque<State> mPendingStates;
 
     // Timestamp history for UIAutomation. Thread safe.
     FrameTracker mFrameTracker;
@@ -1114,6 +1147,9 @@
     // null.
     sp<Layer> getRootLayer();
 
+    // Fills in the frame and transform info for the InputWindowInfo
+    void fillInputFrameInfo(InputWindowInfo& info);
+
     // Cached properties computed from drawing state
     // Effective transform taking into account parent transforms and any parent scaling, which is
     // a transform from the current layer coordinate space to display(screen) coordinate space.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e9416d6..786d331 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4910,10 +4910,11 @@
         case CAPTURE_LAYERS:
         case CAPTURE_DISPLAY:
         case SET_DISPLAY_BRIGHTNESS:
-        case SET_FRAME_TIMELINE_VSYNC: {
+        case SET_FRAME_TIMELINE_VSYNC:
+        // This is not sensitive information, so should not require permission control.
+        case GET_GPU_CONTEXT_PRIORITY: {
             return OK;
         }
-
         case ADD_REGION_SAMPLING_LISTENER:
         case REMOVE_REGION_SAMPLING_LISTENER: {
             // codes that require permission check
@@ -6335,6 +6336,13 @@
     return NO_ERROR;
 }
 
+int SurfaceFlinger::getGPUContextPriority() {
+    // TODO(b/168740533): This is a proof of concept. Once REAL time priority is available
+    // in EGL, we can return it in RenderEngine and propagate it to SurfaceFlinger. Until
+    // then return IntentFilter.SYSTEM_HIGH_PRIORITY.
+    return 1000;
+}
+
 } // namespace android
 
 #if defined(__gl_h_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 0509247..2e4d1ce 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -608,6 +608,8 @@
     status_t addTransactionTraceListener(
             const sp<gui::ITransactionTraceListener>& listener) override;
 
+    int getGPUContextPriority() override;
+
     // Implements IBinder::DeathRecipient.
     void binderDied(const wp<IBinder>& who) override;
 
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index 576bba7..497ebd3 100644
--- a/services/surfaceflinger/SurfaceTracing.h
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -85,7 +85,7 @@
     std::unique_ptr<Runner> runner;
 
     struct Config {
-        uint32_t flags = TRACE_CRITICAL | TRACE_INPUT;
+        uint32_t flags = TRACE_CRITICAL | TRACE_INPUT | TRACE_SYNC;
         size_t bufferSize = DEFAULT_BUFFER_SIZE;
     } mConfig;
 
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 030073c..7f05a75 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -388,6 +388,8 @@
         return mFlinger->onTransact(code, data, reply, flags);
     }
 
+    auto getGPUContextPriority() { return mFlinger->getGPUContextPriority(); }
+
     /* ------------------------------------------------------------------------
      * Read-only access to private data to assert post-conditions.
      */