Merge "Change severity of "No local sync point found" logs"
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 5076ae6..f583c9b 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -450,6 +450,20 @@
             AddArg("--boot-image-merge");
         }
 
+        uint32_t min_new_classes_percent_change = ::android::base::GetUintProperty<uint32_t>(
+            "dalvik.vm.bgdexopt.new-classes-percent", /*default*/-1);
+        if (min_new_classes_percent_change >= 0 && min_new_classes_percent_change <= 100) {
+          AddArg("--min-new-classes-percent-change=" +
+                 std::to_string(min_new_classes_percent_change));
+        }
+
+        uint32_t min_new_methods_percent_change = ::android::base::GetUintProperty<uint32_t>(
+            "dalvik.vm.bgdexopt.new-methods-percent", /*default*/-1);
+        if (min_new_methods_percent_change >=0 && min_new_methods_percent_change <= 100) {
+          AddArg("--min-new-methods-percent-change=" +
+                 std::to_string(min_new_methods_percent_change));
+        }
+
         // Do not add after dex2oat_flags, they should override others for debugging.
         PrepareArgs(profman_bin);
     }
diff --git a/data/etc/cec_config.xml b/data/etc/cec_config.xml
index 8e78ad7..5defb2f 100644
--- a/data/etc/cec_config.xml
+++ b/data/etc/cec_config.xml
@@ -9,6 +9,15 @@
     </allowed-values>
     <default-value int-value="1" />
   </setting>
+  <setting name="hdmi_cec_version"
+           value-type="int"
+           user-configurable="true">
+    <allowed-values>
+      <value int-value="0x05" />
+      <value int-value="0x06" />
+    </allowed-values>
+    <default-value int-value="0x05" />
+  </setting>
   <setting name="send_standby_on_sleep"
            value-type="string"
            user-configurable="true">
diff --git a/include/android/permission_manager.h b/include/android/permission_manager.h
new file mode 100644
index 0000000..7817126
--- /dev/null
+++ b/include/android/permission_manager.h
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_PERMISSION_MANAGER_H
+#define ANDROID_PERMISSION_MANAGER_H
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+/**
+ * Permission check results.
+ *
+ * Introduced in API 31.
+ */
+enum {
+    /**
+     * This is returned by APermissionManager_checkPermission()
+     * if the permission has been granted to the given package.
+     */
+    PERMISSION_MANAGER_PERMISSION_GRANTED = 0,
+    /**
+     * This is returned by APermissionManager_checkPermission()
+     * if the permission has not been granted to the given package.
+     */
+    PERMISSION_MANAGER_PERMISSION_DENIED = -1,
+};
+
+/**
+ * Permission check return status values.
+ *
+ * Introduced in API 31.
+ */
+enum {
+    /**
+     * This is returned if the permission check completed without errors.
+     * The output result is valid and contains one of {PERMISSION_MANAGER_PERMISSION_GRANTED,
+     * PERMISSION_MANAGER_PERMISSION_DENIED}.
+     */
+    PERMISSION_MANAGER_STATUS_OK = 0,
+    /**
+     * This is returned if the permission check encountered an unspecified error.
+     * The output result is unmodified.
+     */
+    PERMISSION_MANAGER_STATUS_ERROR_UNKNOWN = -1,
+    /**
+     * This is returned if the permission check failed because the service is
+     * unavailable. The output result is unmodified.
+     */
+    PERMISSION_MANAGER_STATUS_SERVICE_UNAVAILABLE = -2,
+};
+
+#if __ANDROID_API__ >= 31
+
+/**
+ * Checks whether the package with the given pid/uid has been granted a permission.
+ *
+ * Note that the Java API of Context#checkPermission() is usually faster due to caching,
+ * thus is preferred over this API wherever possible.
+ *
+ * @param permission the permission to be checked.
+ * @param pid the process id of the package to be checked.
+ * @param uid the uid of the package to be checked.
+ * @param outResult output of the permission check result.
+ *
+ * @return error codes if any error happened during the check.
+ */
+int32_t APermissionManager_checkPermission(const char* permission,
+                                           pid_t pid,
+                                           uid_t uid,
+                                           int32_t* outResult) __INTRODUCED_IN(31);
+
+#endif // __ANDROID_API__ >= 31
+
+__END_DECLS
+
+#endif  // ANDROID_PERMISSION_MANAGER_H
diff --git a/libs/binder/ActivityManager.cpp b/libs/binder/ActivityManager.cpp
index 5e4c98f..727ea60 100644
--- a/libs/binder/ActivityManager.cpp
+++ b/libs/binder/ActivityManager.cpp
@@ -17,6 +17,7 @@
 #include <mutex>
 #include <unistd.h>
 
+#include <android/permission_manager.h>
 #include <binder/ActivityManager.h>
 #include <binder/Binder.h>
 #include <binder/IServiceManager.h>
@@ -98,6 +99,18 @@
     return PROCESS_STATE_UNKNOWN;
 }
 
+status_t ActivityManager::checkPermission(const String16& permission,
+                                     const pid_t pid,
+                                     const uid_t uid,
+                                     int32_t* outResult) {
+    sp<IActivityManager> service = getService();
+    if (service != nullptr) {
+        return service->checkPermission(permission, pid, uid, outResult);
+    }
+    // ActivityManagerService appears dead. Return usual error code for dead service.
+    return DEAD_OBJECT;
+}
+
 status_t ActivityManager::linkToDeath(const sp<IBinder::DeathRecipient>& recipient) {
     sp<IActivityManager> service = getService();
     if (service != nullptr) {
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index e6071a0..26b997e 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -112,7 +112,9 @@
         "Stability.cpp",
         "Status.cpp",
         "TextOutput.cpp",
+        "Utils.cpp",
         ":libbinder_aidl",
+        ":activity_manager_procstate_aidl",
     ],
 
     target: {
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 6ca3b16..f2d223d 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -173,6 +173,10 @@
 {
     data.setDataPosition(0);
 
+    if (reply != nullptr && (flags & FLAG_CLEAR_BUF)) {
+        reply->markSensitive();
+    }
+
     status_t err = NO_ERROR;
     switch (code) {
         case PING_TRANSACTION:
diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp
index 1eb5363..e9f5aae 100644
--- a/libs/binder/IActivityManager.cpp
+++ b/libs/binder/IActivityManager.cpp
@@ -17,9 +17,11 @@
 #include <unistd.h>
 #include <fcntl.h>
 
+#include <android/permission_manager.h>
 #include <binder/ActivityManager.h>
 #include <binder/IActivityManager.h>
 #include <binder/Parcel.h>
+#include <utils/Errors.h>
 
 namespace android {
 
@@ -104,6 +106,23 @@
         }
         return reply.readInt32();
     }
+
+    virtual status_t checkPermission(const String16& permission,
+                                    const pid_t pid,
+                                    const uid_t uid,
+                                    int32_t* outResult) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IActivityManager::getInterfaceDescriptor());
+        data.writeString16(permission);
+        data.writeInt32(pid);
+        data.writeInt32(uid);
+        status_t err = remote()->transact(CHECK_PERMISSION_TRANSACTION, data, &reply);
+        if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) {
+            return err;
+        }
+        *outResult = reply.readInt32();
+        return NO_ERROR;
+    }
 };
 
 // ------------------------------------------------------------------------------------
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 05fcc2b..a3a2f87 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -1244,7 +1244,9 @@
             if ((tr.flags & TF_ONE_WAY) == 0) {
                 LOG_ONEWAY("Sending reply to %d!", mCallingPid);
                 if (error < NO_ERROR) reply.setError(error);
-                sendReply(reply, 0);
+
+                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 "
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index ddd9f9b..58df52d 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -49,6 +49,7 @@
 
 #include <private/binder/binder_module.h>
 #include "Static.h"
+#include "Utils.h"
 
 #define LOG_REFS(...)
 //#define LOG_REFS(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
@@ -502,6 +503,11 @@
     return mHasFds;
 }
 
+void Parcel::markSensitive() const
+{
+    mDeallocZero = true;
+}
+
 void Parcel::updateWorkSourceRequestHeaderPosition() const {
     // Only update the request headers once. We only want to point
     // to the first headers read/written.
@@ -1068,6 +1074,7 @@
 {
     if (str == nullptr) return writeInt32(-1);
 
+    // NOTE: Keep this logic in sync with android_os_Parcel.cpp
     status_t err = writeInt32(len);
     if (err == NO_ERROR) {
         uint8_t* data = (uint8_t*)writeInplace(len+sizeof(char));
@@ -1108,6 +1115,7 @@
 {
     if (str == nullptr) return writeInt32(-1);
 
+    // NOTE: Keep this logic in sync with android_os_Parcel.cpp
     status_t err = writeInt32(len);
     if (err == NO_ERROR) {
         len *= sizeof(char16_t);
@@ -1906,17 +1914,6 @@
 
 #endif
 
-status_t Parcel::readIntPtr(intptr_t *pArg) const
-{
-    return readAligned(pArg);
-}
-
-
-intptr_t Parcel::readIntPtr() const
-{
-    return readAligned<intptr_t>();
-}
-
 status_t Parcel::readBool(bool *pArg) const
 {
     int32_t tmp = 0;
@@ -2625,6 +2622,9 @@
             LOG_ALLOC("Parcel %p: freeing with %zu capacity", this, mDataCapacity);
             gParcelGlobalAllocSize -= mDataCapacity;
             gParcelGlobalAllocCount--;
+            if (mDeallocZero) {
+                zeroMemory(mData, mDataSize);
+            }
             free(mData);
         }
         if (mObjects) free(mObjects);
@@ -2647,6 +2647,21 @@
             : continueWrite(std::max(newSize, (size_t) 128));
 }
 
+static uint8_t* reallocZeroFree(uint8_t* data, size_t oldCapacity, size_t newCapacity, bool zero) {
+    if (!zero) {
+        return (uint8_t*)realloc(data, newCapacity);
+    }
+    uint8_t* newData = (uint8_t*)malloc(newCapacity);
+    if (!newData) {
+        return nullptr;
+    }
+
+    memcpy(newData, data, std::min(oldCapacity, newCapacity));
+    zeroMemory(data, oldCapacity);
+    free(data);
+    return newData;
+}
+
 status_t Parcel::restartWrite(size_t desired)
 {
     if (desired > INT32_MAX) {
@@ -2660,7 +2675,7 @@
         return continueWrite(desired);
     }
 
-    uint8_t* data = (uint8_t*)realloc(mData, desired);
+    uint8_t* data = reallocZeroFree(mData, mDataCapacity, desired, mDeallocZero);
     if (!data && desired > mDataCapacity) {
         mError = NO_MEMORY;
         return NO_MEMORY;
@@ -2811,7 +2826,7 @@
 
         // We own the data, so we can just do a realloc().
         if (desired > mDataCapacity) {
-            uint8_t* data = (uint8_t*)realloc(mData, desired);
+            uint8_t* data = reallocZeroFree(mData, mDataCapacity, desired, mDeallocZero);
             if (data) {
                 LOG_ALLOC("Parcel %p: continue from %zu to %zu capacity", this, mDataCapacity,
                         desired);
@@ -2879,6 +2894,7 @@
     mHasFds = false;
     mFdsKnown = true;
     mAllowFds = true;
+    mDeallocZero = false;
     mOwner = nullptr;
     mOpenAshmemSize = 0;
     mWorkSourceRequestHeaderPosition = 0;
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index c232283..61a611d 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -16,6 +16,13 @@
       "name": "binderTextOutputTest"
     },
     {
+      "name": "binderParcelTest"
+    },
+    {
+      "name": "binderParcelTest",
+      "host": true
+    },
+    {
       "name": "binderLibTest"
     },
     {
diff --git a/libs/binder/Utils.cpp b/libs/binder/Utils.cpp
new file mode 100644
index 0000000..90a4502
--- /dev/null
+++ b/libs/binder/Utils.cpp
@@ -0,0 +1,27 @@
+/*
+ * 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 "Utils.h"
+
+#include <string.h>
+
+namespace android {
+
+void zeroMemory(uint8_t* data, size_t size) {
+    memset(data, 0, size);
+}
+
+}   // namespace android
diff --git a/libs/binder/Utils.h b/libs/binder/Utils.h
new file mode 100644
index 0000000..f94b158
--- /dev/null
+++ b/libs/binder/Utils.h
@@ -0,0 +1,25 @@
+/*
+ * 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 <cstdint>
+#include <stddef.h>
+
+namespace android {
+
+// avoid optimizations
+void zeroMemory(uint8_t* data, size_t size);
+
+}   // namespace android
diff --git a/libs/binder/include/binder/ActivityManager.h b/libs/binder/include/binder/ActivityManager.h
index 9108e31..0240858 100644
--- a/libs/binder/include/binder/ActivityManager.h
+++ b/libs/binder/include/binder/ActivityManager.h
@@ -14,18 +14,21 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_ACTIVITY_MANAGER_H
-#define ANDROID_ACTIVITY_MANAGER_H
+#pragma once
 
 #ifndef __ANDROID_VNDK__
 
 #include <binder/IActivityManager.h>
+#include <android/app/ProcessStateEnum.h>
 
 #include <utils/threads.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
 
+#define DECLARE_PROCESS_STATE(name) \
+    PROCESS_STATE_##name = (int32_t) app::ProcessStateEnum::name
+
 class ActivityManager
 {
 public:
@@ -41,30 +44,31 @@
         UID_OBSERVER_ACTIVE = 1<<3
     };
 
+    // PROCESS_STATE_* must come from frameworks/base/core/java/android/app/ProcessStateEnum.aidl.
+    // This is to make sure that Java side uses the same values as native.
     enum {
-        PROCESS_STATE_UNKNOWN = -1,
-        PROCESS_STATE_PERSISTENT = 0,
-        PROCESS_STATE_PERSISTENT_UI = 1,
-        PROCESS_STATE_TOP = 2,
-        PROCESS_STATE_FOREGROUND_SERVICE_LOCATION = 3,
-        PROCESS_STATE_BOUND_TOP = 4,
-        PROCESS_STATE_FOREGROUND_SERVICE = 5,
-        PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 6,
-        PROCESS_STATE_IMPORTANT_FOREGROUND = 7,
-        PROCESS_STATE_IMPORTANT_BACKGROUND = 8,
-        PROCESS_STATE_TRANSIENT_BACKGROUND = 9,
-        PROCESS_STATE_BACKUP = 10,
-        PROCESS_STATE_SERVICE = 11,
-        PROCESS_STATE_RECEIVER = 12,
-        PROCESS_STATE_TOP_SLEEPING = 13,
-        PROCESS_STATE_HEAVY_WEIGHT = 14,
-        PROCESS_STATE_HOME = 15,
-        PROCESS_STATE_LAST_ACTIVITY = 16,
-        PROCESS_STATE_CACHED_ACTIVITY = 17,
-        PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 18,
-        PROCESS_STATE_CACHED_RECENT = 19,
-        PROCESS_STATE_CACHED_EMPTY = 20,
-        PROCESS_STATE_NONEXISTENT = 21,
+        DECLARE_PROCESS_STATE(UNKNOWN),
+        DECLARE_PROCESS_STATE(PERSISTENT),
+        DECLARE_PROCESS_STATE(PERSISTENT_UI),
+        DECLARE_PROCESS_STATE(TOP),
+        DECLARE_PROCESS_STATE(BOUND_TOP),
+        DECLARE_PROCESS_STATE(FOREGROUND_SERVICE),
+        DECLARE_PROCESS_STATE(BOUND_FOREGROUND_SERVICE),
+        DECLARE_PROCESS_STATE(IMPORTANT_FOREGROUND),
+        DECLARE_PROCESS_STATE(IMPORTANT_BACKGROUND),
+        DECLARE_PROCESS_STATE(TRANSIENT_BACKGROUND),
+        DECLARE_PROCESS_STATE(BACKUP),
+        DECLARE_PROCESS_STATE(SERVICE),
+        DECLARE_PROCESS_STATE(RECEIVER),
+        DECLARE_PROCESS_STATE(TOP_SLEEPING),
+        DECLARE_PROCESS_STATE(HEAVY_WEIGHT),
+        DECLARE_PROCESS_STATE(HOME),
+        DECLARE_PROCESS_STATE(LAST_ACTIVITY),
+        DECLARE_PROCESS_STATE(CACHED_ACTIVITY),
+        DECLARE_PROCESS_STATE(CACHED_ACTIVITY_CLIENT),
+        DECLARE_PROCESS_STATE(CACHED_RECENT),
+        DECLARE_PROCESS_STATE(CACHED_EMPTY),
+        DECLARE_PROCESS_STATE(NONEXISTENT),
     };
 
     ActivityManager();
@@ -77,9 +81,9 @@
     void unregisterUidObserver(const sp<IUidObserver>& observer);
     bool isUidActive(const uid_t uid, const String16& callingPackage);
     int getUidProcessState(const uid_t uid, const String16& callingPackage);
+    status_t checkPermission(const String16& permission, const pid_t pid, const uid_t uid, int32_t* outResult);
 
-
-  status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient);
+    status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient);
     status_t unlinkToDeath(const sp<IBinder::DeathRecipient>& recipient);
 
 private:
@@ -94,5 +98,3 @@
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
 #endif // __ANDROID_VNDK__
-
-#endif // ANDROID_ACTIVITY_MANAGER_H
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index 233f12a..35c697e 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_APP_OPS_MANAGER_H
-#define ANDROID_APP_OPS_MANAGER_H
+#pragma once
 
 #include <binder/IAppOpsService.h>
 
@@ -179,5 +178,3 @@
 } // namespace android
 
 // ---------------------------------------------------------------------------
-
-#endif // ANDROID_APP_OPS_MANAGER_H
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index f3fea16..d6da397 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_BINDER_H
-#define ANDROID_BINDER_H
+#pragma once
 
 #include <atomic>
 #include <stdint.h>
@@ -142,5 +141,3 @@
 } // namespace android
 
 // ---------------------------------------------------------------------------
-
-#endif // ANDROID_BINDER_H
diff --git a/libs/binder/include/binder/BinderService.h b/libs/binder/include/binder/BinderService.h
index c17ae6f..5776f3c 100644
--- a/libs/binder/include/binder/BinderService.h
+++ b/libs/binder/include/binder/BinderService.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_BINDER_SERVICE_H
-#define ANDROID_BINDER_SERVICE_H
+#pragma once
 
 #include <stdint.h>
 
@@ -64,4 +63,3 @@
 
 } // namespace android
 // ---------------------------------------------------------------------------
-#endif // ANDROID_BINDER_SERVICE_H
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 378a911..64d0657 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_BPBINDER_H
-#define ANDROID_BPBINDER_H
+#pragma once
 
 #include <binder/IBinder.h>
 #include <utils/KeyedVector.h>
@@ -153,5 +152,3 @@
 } // namespace android
 
 // ---------------------------------------------------------------------------
-
-#endif // ANDROID_BPBINDER_H
diff --git a/libs/binder/include/binder/Debug.h b/libs/binder/include/binder/Debug.h
index 324e5c1..ac71e00 100644
--- a/libs/binder/include/binder/Debug.h
+++ b/libs/binder/include/binder/Debug.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_BINDER_DEBUG_H
-#define ANDROID_BINDER_DEBUG_H
+#pragma once
 
 #include <stdint.h>
 #include <sys/cdefs.h>
@@ -45,5 +44,3 @@
 
 // ---------------------------------------------------------------------------
 } // namespace android
-
-#endif // ANDROID_BINDER_DEBUG_H
diff --git a/libs/binder/include/binder/Enums.h b/libs/binder/include/binder/Enums.h
index aec6f70..c6803bd 100644
--- a/libs/binder/include/binder/Enums.h
+++ b/libs/binder/include/binder/Enums.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 #pragma once
 
 #include <iterator>
@@ -38,4 +39,4 @@
     constexpr auto end() const { return std::end(internal::enum_values<EnumType>); }
 };
 
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/libs/binder/include/binder/IActivityManager.h b/libs/binder/include/binder/IActivityManager.h
index e0248f6..e2081ff 100644
--- a/libs/binder/include/binder/IActivityManager.h
+++ b/libs/binder/include/binder/IActivityManager.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_IACTIVITY_MANAGER_H
-#define ANDROID_IACTIVITY_MANAGER_H
+#pragma once
 
 #ifndef __ANDROID_VNDK__
 
@@ -39,13 +38,18 @@
     virtual void unregisterUidObserver(const sp<IUidObserver>& observer) = 0;
     virtual bool isUidActive(const uid_t uid, const String16& callingPackage) = 0;
     virtual int32_t getUidProcessState(const uid_t uid, const String16& callingPackage) = 0;
+    virtual status_t checkPermission(const String16& permission,
+                                    const pid_t pid,
+                                    const uid_t uid,
+                                    int32_t* outResult) = 0;
 
     enum {
         OPEN_CONTENT_URI_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
         REGISTER_UID_OBSERVER_TRANSACTION,
         UNREGISTER_UID_OBSERVER_TRANSACTION,
         IS_UID_ACTIVE_TRANSACTION,
-        GET_UID_PROCESS_STATE_TRANSACTION
+        GET_UID_PROCESS_STATE_TRANSACTION,
+        CHECK_PERMISSION_TRANSACTION,
     };
 };
 
@@ -56,5 +60,3 @@
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
 #endif // __ANDROID_VNDK__
-
-#endif // ANDROID_IACTIVITY_MANAGER_H
diff --git a/libs/binder/include/binder/IAppOpsCallback.h b/libs/binder/include/binder/IAppOpsCallback.h
index 7664260..eb76f57 100644
--- a/libs/binder/include/binder/IAppOpsCallback.h
+++ b/libs/binder/include/binder/IAppOpsCallback.h
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-//
-#ifndef ANDROID_IAPP_OPS_CALLBACK_H
-#define ANDROID_IAPP_OPS_CALLBACK_H
+#pragma once
 
 #ifndef __ANDROID_VNDK__
 
@@ -57,6 +55,3 @@
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
 #endif // __ANDROID_VNDK__
-
-#endif // ANDROID_IAPP_OPS_CALLBACK_H
-
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h
index de7d12f..22f056b 100644
--- a/libs/binder/include/binder/IAppOpsService.h
+++ b/libs/binder/include/binder/IAppOpsService.h
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-//
-#ifndef ANDROID_IAPP_OPS_SERVICE_H
-#define ANDROID_IAPP_OPS_SERVICE_H
+#pragma once
 
 #include <binder/IAppOpsCallback.h>
 #include <binder/IInterface.h>
@@ -90,5 +88,3 @@
 // ----------------------------------------------------------------------
 
 } // namespace android
-
-#endif // ANDROID_IAPP_OPS_SERVICE_H
diff --git a/libs/binder/include/binder/IBatteryStats.h b/libs/binder/include/binder/IBatteryStats.h
index b786f89..6defc7f 100644
--- a/libs/binder/include/binder/IBatteryStats.h
+++ b/libs/binder/include/binder/IBatteryStats.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_IBATTERYSTATS_H
-#define ANDROID_IBATTERYSTATS_H
+#pragma once
 
 #ifndef __ANDROID_VNDK__
 
@@ -82,5 +81,3 @@
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
 #endif // __ANDROID_VNDK__
-
-#endif // ANDROID_IBATTERYSTATS_H
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index eea0e89..c8fb448 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_IBINDER_H
-#define ANDROID_IBINDER_H
+#pragma once
 
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
@@ -64,6 +63,10 @@
         // Corresponds to TF_ONE_WAY -- an asynchronous call.
         FLAG_ONEWAY             = 0x00000001,
 
+        // Corresponds to TF_CLEAR_BUF -- clear transaction buffers after call
+        // is made
+        FLAG_CLEAR_BUF          = 0x00000020,
+
         // Private userspace flag for transaction which is being requested from
         // a vendor context.
         FLAG_PRIVATE_VENDOR     = 0x10000000,
@@ -253,5 +256,3 @@
 } // namespace android
 
 // ---------------------------------------------------------------------------
-
-#endif // ANDROID_IBINDER_H
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index 468cc16..988508e 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-//
-#ifndef ANDROID_IINTERFACE_H
-#define ANDROID_IINTERFACE_H
+#pragma once
 
 #include <binder/Binder.h>
 
@@ -331,5 +329,3 @@
 
 } // namespace internal
 } // namespace android
-
-#endif // ANDROID_IINTERFACE_H
diff --git a/libs/binder/include/binder/IMediaResourceMonitor.h b/libs/binder/include/binder/IMediaResourceMonitor.h
index da2b7cf..ac4b4ca 100644
--- a/libs/binder/include/binder/IMediaResourceMonitor.h
+++ b/libs/binder/include/binder/IMediaResourceMonitor.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_I_MEDIA_RESOURCE_MONITOR_H
-#define ANDROID_I_MEDIA_RESOURCE_MONITOR_H
+#pragma once
 
 #ifndef __ANDROID_VNDK__
 
@@ -57,5 +56,3 @@
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
 #endif // __ANDROID_VNDK__
-
-#endif // ANDROID_I_MEDIA_RESOURCE_MONITOR_H
diff --git a/libs/binder/include/binder/IMemory.h b/libs/binder/include/binder/IMemory.h
index 1a36eb0..d8b7ec1 100644
--- a/libs/binder/include/binder/IMemory.h
+++ b/libs/binder/include/binder/IMemory.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_IMEMORY_H
-#define ANDROID_IMEMORY_H
+#pragma once
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -124,5 +123,3 @@
 // ----------------------------------------------------------------------------
 
 } // namespace android
-
-#endif // ANDROID_IMEMORY_H
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 49ef253..a3712c9 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_IPC_THREAD_STATE_H
-#define ANDROID_IPC_THREAD_STATE_H
+#pragma once
 
 #include <utils/Errors.h>
 #include <binder/Parcel.h>
@@ -214,5 +213,3 @@
 } // namespace android
 
 // ---------------------------------------------------------------------------
-
-#endif // ANDROID_IPC_THREAD_STATE_H
diff --git a/libs/binder/include/binder/IPermissionController.h b/libs/binder/include/binder/IPermissionController.h
index 4b66df8..a4f93d9 100644
--- a/libs/binder/include/binder/IPermissionController.h
+++ b/libs/binder/include/binder/IPermissionController.h
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-//
-#ifndef ANDROID_IPERMISSION_CONTROLLER_H
-#define ANDROID_IPERMISSION_CONTROLLER_H
+#pragma once
 
 #ifndef __ANDROID_VNDK__
 
@@ -70,6 +68,3 @@
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
 #endif // __ANDROID_VNDK__
-
-#endif // ANDROID_IPERMISSION_CONTROLLER_H
-
diff --git a/libs/binder/include/binder/IProcessInfoService.h b/libs/binder/include/binder/IProcessInfoService.h
index ca30ad3..622f231 100644
--- a/libs/binder/include/binder/IProcessInfoService.h
+++ b/libs/binder/include/binder/IProcessInfoService.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_I_PROCESS_INFO_SERVICE_H
-#define ANDROID_I_PROCESS_INFO_SERVICE_H
+#pragma once
 
 #ifndef __ANDROID_VNDK__
 
@@ -51,5 +50,3 @@
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
 #endif // __ANDROID_VNDK__
-
-#endif // ANDROID_I_PROCESS_INFO_SERVICE_H
diff --git a/libs/binder/include/binder/IResultReceiver.h b/libs/binder/include/binder/IResultReceiver.h
index 70e99e7..5434445 100644
--- a/libs/binder/include/binder/IResultReceiver.h
+++ b/libs/binder/include/binder/IResultReceiver.h
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-//
-#ifndef ANDROID_IRESULT_RECEIVER_H
-#define ANDROID_IRESULT_RECEIVER_H
+#pragma once
 
 #include <binder/IInterface.h>
 
@@ -51,6 +49,3 @@
 // ----------------------------------------------------------------------
 
 } // namespace android
-
-#endif // ANDROID_IRESULT_RECEIVER_H
-
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 3c5ccc1..5f0d056 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-//
-#ifndef ANDROID_ISERVICE_MANAGER_H
-#define ANDROID_ISERVICE_MANAGER_H
+#pragma once
 
 #include <binder/IInterface.h>
 #include <utils/Vector.h>
@@ -164,6 +162,3 @@
 bool checkPermission(const String16& permission, pid_t pid, uid_t uid);
 
 } // namespace android
-
-#endif // ANDROID_ISERVICE_MANAGER_H
-
diff --git a/libs/binder/include/binder/IShellCallback.h b/libs/binder/include/binder/IShellCallback.h
index b7ab6ea..17e34db 100644
--- a/libs/binder/include/binder/IShellCallback.h
+++ b/libs/binder/include/binder/IShellCallback.h
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-//
-#ifndef ANDROID_ISHELL_CALLBACK_H
-#define ANDROID_ISHELL_CALLBACK_H
+#pragma once
 
 #include <binder/IInterface.h>
 
@@ -52,6 +50,3 @@
 // ----------------------------------------------------------------------
 
 } // namespace android
-
-#endif // ANDROID_ISHELL_CALLBACK_H
-
diff --git a/libs/binder/include/binder/IUidObserver.h b/libs/binder/include/binder/IUidObserver.h
index d070390..9291c0b 100644
--- a/libs/binder/include/binder/IUidObserver.h
+++ b/libs/binder/include/binder/IUidObserver.h
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-//
-#ifndef ANDROID_IUID_OBSERVER_H
-#define ANDROID_IUID_OBSERVER_H
+#pragma once
 
 #ifndef __ANDROID_VNDK__
 
@@ -64,5 +62,3 @@
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
 #endif // __ANDROID_VNDK__
-
-#endif // ANDROID_IUID_OBSERVER_H
diff --git a/libs/binder/include/binder/IpPrefix.h b/libs/binder/include/binder/IpPrefix.h
index c7e7a50..c1cd3c2 100644
--- a/libs/binder/include/binder/IpPrefix.h
+++ b/libs/binder/include/binder/IpPrefix.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_IP_PREFIX_H
-#define ANDROID_IP_PREFIX_H
+#pragma once
 
 #ifndef __ANDROID_VNDK__
 
@@ -90,5 +89,3 @@
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
 #endif // __ANDROID_VNDK__
-
-#endif  // ANDROID_IP_PREFIX_H
diff --git a/libs/binder/include/binder/MemoryBase.h b/libs/binder/include/binder/MemoryBase.h
index 4dd3638..61a029c 100644
--- a/libs/binder/include/binder/MemoryBase.h
+++ b/libs/binder/include/binder/MemoryBase.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_MEMORY_BASE_H
-#define ANDROID_MEMORY_BASE_H
+#pragma once
 
 #include <stdlib.h>
 #include <stdint.h>
@@ -47,5 +46,3 @@
 
 // ---------------------------------------------------------------------------
 } // namespace android
-
-#endif // ANDROID_MEMORY_BASE_H
diff --git a/libs/binder/include/binder/MemoryDealer.h b/libs/binder/include/binder/MemoryDealer.h
index 6c1c412..e727772 100644
--- a/libs/binder/include/binder/MemoryDealer.h
+++ b/libs/binder/include/binder/MemoryDealer.h
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_MEMORY_DEALER_H
-#define ANDROID_MEMORY_DEALER_H
-
+#pragma once
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -60,5 +58,3 @@
 
 // ----------------------------------------------------------------------------
 } // namespace android
-
-#endif // ANDROID_MEMORY_DEALER_H
diff --git a/libs/binder/include/binder/MemoryHeapBase.h b/libs/binder/include/binder/MemoryHeapBase.h
index 0ece121..dd76943 100644
--- a/libs/binder/include/binder/MemoryHeapBase.h
+++ b/libs/binder/include/binder/MemoryHeapBase.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_MEMORY_HEAP_BASE_H
-#define ANDROID_MEMORY_HEAP_BASE_H
+#pragma once
 
 #include <stdlib.h>
 #include <stdint.h>
@@ -93,5 +92,3 @@
 
 // ---------------------------------------------------------------------------
 } // namespace android
-
-#endif // ANDROID_MEMORY_HEAP_BASE_H
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index fbfd6c5..138d957 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_PARCEL_H
-#define ANDROID_PARCEL_H
+#pragma once
 
 #include <map> // for legacy reasons
 #include <string>
@@ -84,6 +83,13 @@
 
     bool                hasFileDescriptors() const;
 
+    // Zeros data when reallocating. Other mitigations may be added
+    // in the future.
+    //
+    // WARNING: some read methods may make additional copies of data.
+    // In order to verify this, heap dumps should be used.
+    void                markSensitive() const;
+
     // Writes the RPC header.
     status_t            writeInterfaceToken(const String16& interface);
     status_t            writeInterfaceToken(const char16_t* str, size_t len);
@@ -297,8 +303,6 @@
     status_t            readFloat(float *pArg) const;
     double              readDouble() const;
     status_t            readDouble(double *pArg) const;
-    intptr_t            readIntPtr() const;
-    status_t            readIntPtr(intptr_t *pArg) const;
     bool                readBool() const;
     status_t            readBool(bool *pArg) const;
     char16_t            readChar() const;
@@ -600,6 +604,10 @@
     mutable bool        mHasFds;
     bool                mAllowFds;
 
+    // if this parcelable is involved in a secure transaction, force the
+    // data to be overridden with zero when deallocated
+    mutable bool        mDeallocZero;
+
     release_func        mOwner;
     void*               mOwnerCookie;
 
@@ -1328,5 +1336,3 @@
 } // namespace android
 
 // ---------------------------------------------------------------------------
-
-#endif // ANDROID_PARCEL_H
diff --git a/libs/binder/include/binder/ParcelFileDescriptor.h b/libs/binder/include/binder/ParcelFileDescriptor.h
index 71e1d3c..4ba6ba8 100644
--- a/libs/binder/include/binder/ParcelFileDescriptor.h
+++ b/libs/binder/include/binder/ParcelFileDescriptor.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_PARCEL_FILE_DESCRIPTOR_H_
-#define ANDROID_PARCEL_FILE_DESCRIPTOR_H_
+#pragma once
 
 #include <android-base/unique_fd.h>
 #include <binder/Parcel.h>
@@ -67,5 +66,3 @@
 
 } // namespace os
 } // namespace android
-
-#endif // ANDROID_OS_PARCEL_FILE_DESCRIPTOR_H_
diff --git a/libs/binder/include/binder/Parcelable.h b/libs/binder/include/binder/Parcelable.h
index a6e610c..2c652be 100644
--- a/libs/binder/include/binder/Parcelable.h
+++ b/libs/binder/include/binder/Parcelable.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_PARCELABLE_H
-#define ANDROID_PARCELABLE_H
+#pragma once
 
 #include <vector>
 
@@ -74,5 +73,3 @@
 #endif
 
 }  // namespace android
-
-#endif // ANDROID_PARCELABLE_H
diff --git a/libs/binder/include/binder/PermissionCache.h b/libs/binder/include/binder/PermissionCache.h
index c258215..835a3a8 100644
--- a/libs/binder/include/binder/PermissionCache.h
+++ b/libs/binder/include/binder/PermissionCache.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef BINDER_PERMISSION_H
-#define BINDER_PERMISSION_H
+#pragma once
 
 #ifndef __ANDROID_VNDK__
 
@@ -82,5 +81,3 @@
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
 #endif // __ANDROID_VNDK__
-
-#endif /* BINDER_PERMISSION_H */
diff --git a/libs/binder/include/binder/PermissionController.h b/libs/binder/include/binder/PermissionController.h
index 4db522a..e658574 100644
--- a/libs/binder/include/binder/PermissionController.h
+++ b/libs/binder/include/binder/PermissionController.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_PERMISSION_CONTROLLER_H
-#define ANDROID_PERMISSION_CONTROLLER_H
+#pragma once
 
 #ifndef __ANDROID_VNDK__
 
@@ -65,5 +64,3 @@
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
 #endif // __ANDROID_VNDK__
-
-#endif // ANDROID_PERMISSION_CONTROLLER_H
diff --git a/libs/binder/include/binder/PersistableBundle.h b/libs/binder/include/binder/PersistableBundle.h
index 322fef9..4517cf2 100644
--- a/libs/binder/include/binder/PersistableBundle.h
+++ b/libs/binder/include/binder/PersistableBundle.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_PERSISTABLE_BUNDLE_H
-#define ANDROID_PERSISTABLE_BUNDLE_H
+#pragma once
 
 #include <map>
 #include <set>
@@ -128,5 +127,3 @@
 }  // namespace os
 
 }  // namespace android
-
-#endif  // ANDROID_PERSISTABLE_BUNDLE_H
diff --git a/libs/binder/include/binder/ProcessInfoService.h b/libs/binder/include/binder/ProcessInfoService.h
index 6bfd1bc..6b3b5ce 100644
--- a/libs/binder/include/binder/ProcessInfoService.h
+++ b/libs/binder/include/binder/ProcessInfoService.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_PROCESS_INFO_SERVICE_H
-#define ANDROID_PROCESS_INFO_SERVICE_H
+#pragma once
 
 #ifndef __ANDROID_VNDK__
 
@@ -83,6 +82,3 @@
 #else // __ANDROID_VNDK__
 #error "This header is not visible to vendors"
 #endif // __ANDROID_VNDK__
-
-#endif // ANDROID_PROCESS_INFO_SERVICE_H
-
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index efb95f4..46457cd 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_PROCESS_STATE_H
-#define ANDROID_PROCESS_STATE_H
+#pragma once
 
 #include <binder/IBinder.h>
 #include <utils/KeyedVector.h>
@@ -132,5 +131,3 @@
 } // namespace android
 
 // ---------------------------------------------------------------------------
-
-#endif // ANDROID_PROCESS_STATE_H
diff --git a/libs/binder/include/binder/TextOutput.h b/libs/binder/include/binder/TextOutput.h
index c7e1e14..bf9c92b 100644
--- a/libs/binder/include/binder/TextOutput.h
+++ b/libs/binder/include/binder/TextOutput.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_TEXTOUTPUT_H
-#define ANDROID_TEXTOUTPUT_H
+#pragma once
 
 #include <utils/Errors.h>
 #include <utils/String8.h>
@@ -206,5 +205,3 @@
 
 // ---------------------------------------------------------------------------
 } // namespace android
-
-#endif // ANDROID_TEXTOUTPUT_H
diff --git a/libs/binder/include/private/binder/binder_module.h b/libs/binder/include/private/binder/binder_module.h
index 7be8f7b..0fe7f5b 100644
--- a/libs/binder/include/private/binder/binder_module.h
+++ b/libs/binder/include/private/binder/binder_module.h
@@ -88,7 +88,9 @@
 };
 #endif //BINDER_GET_FROZEN_INFO
 
-
+enum transaction_flags_ext {
+    TF_CLEAR_BUF = 0x20, /* clear buffer on txn complete */
+};
 
 #ifdef __cplusplus
 }   // namespace android
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 4610ba9..b927f6f 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#include <android/binder_context.h>
 #include <android/binder_ibinder.h>
 #include <android/binder_ibinder_platform.h>
+#include <android/binder_libbinder.h>
 #include "ibinder_internal.h"
 
 #include <android/binder_stability.h>
@@ -611,7 +611,7 @@
         return STATUS_UNKNOWN_TRANSACTION;
     }
 
-    constexpr binder_flags_t kAllFlags = FLAG_PRIVATE_VENDOR | FLAG_ONEWAY;
+    constexpr binder_flags_t kAllFlags = FLAG_PRIVATE_VENDOR | FLAG_ONEWAY | FLAG_CLEAR_BUF;
     if ((flags & ~kAllFlags) != 0) {
         LOG(ERROR) << __func__ << ": Unrecognized flags sent: " << flags;
         return STATUS_BAD_VALUE;
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 33763d5..ce3d1db 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -43,7 +43,6 @@
 
 #if __ANDROID_API__ >= 29
 
-// Also see TF_* in kernel's binder.h
 typedef uint32_t binder_flags_t;
 enum {
     /**
diff --git a/libs/binder/ndk/include_platform/android/binder_context.h b/libs/binder/ndk/include_platform/android/binder_context.h
deleted file mode 100644
index a99d555..0000000
--- a/libs/binder/ndk/include_platform/android/binder_context.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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 <android/binder_ibinder.h>
-
-__BEGIN_DECLS
-
-/**
- * Makes calls to AIBinder_getCallingSid work if the kernel supports it. This
- * must be called on a local binder server before it is sent out to any othe
- * process. If this is a remote binder, it will abort. If the kernel doesn't
- * support this feature, you'll always get null from AIBinder_getCallingSid.
- *
- * \param binder local server binder to request security contexts on
- */
-__attribute__((weak)) void AIBinder_setRequestingSid(AIBinder* binder, bool requestingSid)
-        __INTRODUCED_IN(31);
-
-/**
- * Returns the selinux context of the callee.
- *
- * In order for this to work, the following conditions must be met:
- * - The kernel must be new enough to support this feature.
- * - The server must have called AIBinder_setRequestingSid.
- * - The callee must be a remote process.
- *
- * \return security context or null if unavailable. The lifetime of this context
- * is the lifetime of the transaction.
- */
-__attribute__((weak, warn_unused_result)) const char* AIBinder_getCallingSid() __INTRODUCED_IN(31);
-
-__END_DECLS
diff --git a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
index 2af65cf..e315c79 100644
--- a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
+++ b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
@@ -16,39 +16,43 @@
 
 #pragma once
 
-// binder_context.h used to be part of this header and is included for backwards
-// compatibility.
-#include <android/binder_context.h>
-
-#if !defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__)
-
 #include <android/binder_ibinder.h>
-#include <binder/IBinder.h>
+
+__BEGIN_DECLS
+
+// platform values for binder_flags_t
+enum {
+    /**
+     * The transaction and reply will be cleared by the kernel in read-only
+     * binder buffers storing transactions.
+     *
+     * Introduced in API level 31.
+     */
+    FLAG_CLEAR_BUF = 0x20,
+};
 
 /**
- * Get libbinder version of binder from AIBinder.
+ * Makes calls to AIBinder_getCallingSid work if the kernel supports it. This
+ * must be called on a local binder server before it is sent out to any othe
+ * process. If this is a remote binder, it will abort. If the kernel doesn't
+ * support this feature, you'll always get null from AIBinder_getCallingSid.
  *
- * WARNING: function calls to a local object on the other side of this function
- * will parcel. When converting between binders, keep in mind it is not as
- * efficient as a direct function call.
- *
- * \param binder binder with ownership retained by the client
- * \return platform binder object
+ * \param binder local server binder to request security contexts on
  */
-android::sp<android::IBinder> AIBinder_toPlatformBinder(AIBinder* binder);
+__attribute__((weak)) void AIBinder_setRequestingSid(AIBinder* binder, bool requestingSid)
+        __INTRODUCED_IN(31);
 
 /**
- * Get libbinder_ndk version of binder from platform binder.
+ * Returns the selinux context of the callee.
  *
- * WARNING: function calls to a local object on the other side of this function
- * will parcel. When converting between binders, keep in mind it is not as
- * efficient as a direct function call.
+ * In order for this to work, the following conditions must be met:
+ * - The kernel must be new enough to support this feature.
+ * - The server must have called AIBinder_setRequestingSid.
+ * - The callee must be a remote process.
  *
- * \param binder platform binder which may be from anywhere (doesn't have to be
- * created with libbinder_ndK)
- * \return binder with one reference count of ownership given to the client. See
- * AIBinder_decStrong
+ * \return security context or null if unavailable. The lifetime of this context
+ * is the lifetime of the transaction.
  */
-AIBinder* AIBinder_fromPlatformBinder(const android::sp<android::IBinder>& binder);
+__attribute__((weak, warn_unused_result)) const char* AIBinder_getCallingSid() __INTRODUCED_IN(31);
 
-#endif
+__END_DECLS
diff --git a/libs/binder/ndk/include_platform/android/binder_libbinder.h b/libs/binder/ndk/include_platform/android/binder_libbinder.h
new file mode 100644
index 0000000..f0c00e8
--- /dev/null
+++ b/libs/binder/ndk/include_platform/android/binder_libbinder.h
@@ -0,0 +1,50 @@
+/*
+ * 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
+
+#if !defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__)
+
+#include <android/binder_ibinder.h>
+#include <binder/IBinder.h>
+
+/**
+ * Get libbinder version of binder from AIBinder.
+ *
+ * WARNING: function calls to a local object on the other side of this function
+ * will parcel. When converting between binders, keep in mind it is not as
+ * efficient as a direct function call.
+ *
+ * \param binder binder with ownership retained by the client
+ * \return platform binder object
+ */
+android::sp<android::IBinder> AIBinder_toPlatformBinder(AIBinder* binder);
+
+/**
+ * Get libbinder_ndk version of binder from platform binder.
+ *
+ * WARNING: function calls to a local object on the other side of this function
+ * will parcel. When converting between binders, keep in mind it is not as
+ * efficient as a direct function call.
+ *
+ * \param binder platform binder which may be from anywhere (doesn't have to be
+ * created with libbinder_ndK)
+ * \return binder with one reference count of ownership given to the client. See
+ * AIBinder_decStrong
+ */
+AIBinder* AIBinder_fromPlatformBinder(const android::sp<android::IBinder>& binder);
+
+#endif
diff --git a/libs/binder/ndk/include_platform/android/binder_parcel_platform.h b/libs/binder/ndk/include_platform/android/binder_parcel_platform.h
index 114a781..d54c1a1 100644
--- a/libs/binder/ndk/include_platform/android/binder_parcel_platform.h
+++ b/libs/binder/ndk/include_platform/android/binder_parcel_platform.h
@@ -33,4 +33,15 @@
  */
 bool AParcel_getAllowFds(const AParcel*);
 
+/**
+ * Data written to the parcel will be zero'd before being deleted or realloced.
+ *
+ * The main use of this is marking a parcel that will be used in a transaction
+ * with FLAG_CLEAR_BUF. When FLAG_CLEAR_BUF is used, the reply parcel will
+ * automatically be marked as sensitive when it is created.
+ *
+ * \param parcel The parcel to clear associated data from.
+ */
+void AParcel_markSensitive(const AParcel* parcel);
+
 __END_DECLS
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 947cc98..6962f86 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -121,15 +121,16 @@
     AServiceManager_registerLazyService; # llndk
     AServiceManager_waitForService; # apex llndk
 
-    AParcel_reset;
-    AParcel_getDataSize;
     AParcel_appendFrom;
     AParcel_create;
+    AParcel_getDataSize;
+    AParcel_reset;
 };
 
 LIBBINDER_NDK_PLATFORM {
   global:
     AParcel_getAllowFds;
+    AParcel_markSensitive;
     extern "C++" {
         AIBinder_fromPlatformBinder*;
         AIBinder_toPlatformBinder*;
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index 2f95318..3e3eda1 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -226,6 +226,10 @@
     return parcel->get()->dataPosition();
 }
 
+void AParcel_markSensitive(const AParcel* parcel) {
+    return parcel->get()->markSensitive();
+}
+
 binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) {
     sp<IBinder> writeBinder = binder != nullptr ? binder->getBinder() : nullptr;
     return parcel->get()->writeStrongBinder(writeBinder);
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 160b9f2..f84d9d3 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -18,9 +18,9 @@
 #include <aidl/BnBinderNdkUnitTest.h>
 #include <aidl/BnEmpty.h>
 #include <android-base/logging.h>
-#include <android/binder_context.h>
 #include <android/binder_ibinder_jni.h>
 #include <android/binder_ibinder_platform.h>
+#include <android/binder_libbinder.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 #include <gtest/gtest.h>
diff --git a/libs/binder/parcel_fuzzer/binder.cpp b/libs/binder/parcel_fuzzer/binder.cpp
index e5c6333..a94f06f 100644
--- a/libs/binder/parcel_fuzzer/binder.cpp
+++ b/libs/binder/parcel_fuzzer/binder.cpp
@@ -130,7 +130,6 @@
     PARCEL_READ_OPT_STATUS(uint64_t, readUint64),
     PARCEL_READ_OPT_STATUS(float, readFloat),
     PARCEL_READ_OPT_STATUS(double, readDouble),
-    PARCEL_READ_OPT_STATUS(intptr_t, readIntPtr),
     PARCEL_READ_OPT_STATUS(bool, readBool),
     PARCEL_READ_OPT_STATUS(char16_t, readChar),
     PARCEL_READ_OPT_STATUS(int8_t, readByte),
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index 6d0a369..037ee95 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -33,8 +33,7 @@
 
 /// Additional operation flags.
 ///
-/// Can be either 0 for a normal RPC, or [`IBinder::FLAG_ONEWAY`] for a
-/// one-way RPC.
+/// `IBinder::FLAG_*` values.
 pub type TransactionFlags = u32;
 
 /// Super-trait for Binder interfaces.
@@ -91,6 +90,8 @@
 
     /// Corresponds to TF_ONE_WAY -- an asynchronous call.
     const FLAG_ONEWAY: TransactionFlags = sys::FLAG_ONEWAY;
+    /// Corresponds to TF_CLEAR_BUF -- clear transaction buffers after call is made.
+    const FLAG_CLEAR_BUF: TransactionFlags = sys::FLAG_CLEAR_BUF;
 
     /// Is this object still alive?
     fn is_binder_alive(&self) -> bool;
diff --git a/libs/binder/rust/src/parcel.rs b/libs/binder/rust/src/parcel.rs
index 2c1e5a4..6c34824 100644
--- a/libs/binder/rust/src/parcel.rs
+++ b/libs/binder/rust/src/parcel.rs
@@ -100,6 +100,14 @@
 
 // Data serialization methods
 impl Parcel {
+    /// Data written to parcelable is zero'd before being deleted or reallocated.
+    pub fn mark_sensitive(&mut self) {
+        unsafe {
+            // Safety: guaranteed to have a parcel object, and this method never fails
+            sys::AParcel_markSensitive(self.as_native())
+        }
+    }
+
     /// Write a type that implements [`Serialize`] to the `Parcel`.
     pub fn write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> Result<()> {
         parcelable.serialize(self)
diff --git a/libs/binder/rust/sys/BinderBindings.hpp b/libs/binder/rust/sys/BinderBindings.hpp
index 303f4a5..ef142b5 100644
--- a/libs/binder/rust/sys/BinderBindings.hpp
+++ b/libs/binder/rust/sys/BinderBindings.hpp
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-#include <android/binder_context.h>
 #include <android/binder_ibinder.h>
+#include <android/binder_ibinder_platform.h>
 #include <android/binder_manager.h>
 #include <android/binder_parcel.h>
+#include <android/binder_parcel_platform.h>
 #include <android/binder_process.h>
 #include <android/binder_shell.h>
 #include <android/binder_status.h>
@@ -78,6 +79,7 @@
 
 enum {
     FLAG_ONEWAY = FLAG_ONEWAY,
+    FLAG_CLEAR_BUF = FLAG_CLEAR_BUF,
 };
 
 } // namespace consts
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index a03835b..87f1d45 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -60,6 +60,23 @@
     require_root: true,
 }
 
+// unit test only, which can run on host and doesn't use /dev/binder
+cc_test {
+    name: "binderParcelTest",
+    host_supported: true,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+    srcs: ["binderParcelTest.cpp"],
+    shared_libs: [
+        "libbinder",
+        "libutils",
+    ],
+    test_suites: ["general-tests"],
+}
+
 cc_test {
     name: "binderLibTest",
     defaults: ["binder_test_defaults"],
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 98f0868..ad4729d 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -402,6 +402,14 @@
     EXPECT_EQ(NO_ERROR, ret);
 }
 
+TEST_F(BinderLibTest, NopTransactionClear) {
+    status_t ret;
+    Parcel data, reply;
+    // make sure it accepts the transaction flag
+    ret = m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply, TF_CLEAR_BUF);
+    EXPECT_EQ(NO_ERROR, ret);
+}
+
 TEST_F(BinderLibTest, Freeze) {
     status_t ret;
     Parcel data, reply, replypid;
diff --git a/libs/binder/tests/binderParcelTest.cpp b/libs/binder/tests/binderParcelTest.cpp
new file mode 100644
index 0000000..1764228
--- /dev/null
+++ b/libs/binder/tests/binderParcelTest.cpp
@@ -0,0 +1,114 @@
+/*
+ * 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/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <gtest/gtest.h>
+
+using android::IPCThreadState;
+using android::OK;
+using android::Parcel;
+using android::String16;
+using android::String8;
+using android::status_t;
+
+// Tests a second operation results in a parcel at the same location as it
+// started.
+void parcelOpSameLength(const std::function<void(Parcel*)>& a, const std::function<void(Parcel*)>& b) {
+    Parcel p;
+    a(&p);
+    size_t end = p.dataPosition();
+    p.setDataPosition(0);
+    b(&p);
+    EXPECT_EQ(end, p.dataPosition());
+}
+
+TEST(Parcel, InverseInterfaceToken) {
+    const String16 token = String16("asdf");
+    parcelOpSameLength([&] (Parcel* p) {
+        p->writeInterfaceToken(token);
+    }, [&] (Parcel* p) {
+        EXPECT_TRUE(p->enforceInterface(token, IPCThreadState::self()));
+    });
+}
+
+TEST(Parcel, Utf8FromUtf16Read) {
+    const char* token = "asdf";
+    parcelOpSameLength([&] (Parcel* p) {
+        p->writeString16(String16(token));
+    }, [&] (Parcel* p) {
+        std::string s;
+        EXPECT_EQ(OK, p->readUtf8FromUtf16(&s));
+        EXPECT_EQ(token, s);
+    });
+}
+
+TEST(Parcel, Utf8AsUtf16Write) {
+    std::string token = "asdf";
+    parcelOpSameLength([&] (Parcel* p) {
+        p->writeUtf8AsUtf16(token);
+    }, [&] (Parcel* p) {
+        String16 s;
+        EXPECT_EQ(OK, p->readString16(&s));
+        EXPECT_EQ(s, String16(token.c_str()));
+    });
+}
+
+template <typename T>
+using readFunc = status_t (Parcel::*)(T* out) const;
+template <typename T>
+using writeFunc = status_t (Parcel::*)(const T& in);
+template <typename T>
+using copyWriteFunc = status_t (Parcel::*)(T in);
+
+template <typename T, typename WRITE_FUNC>
+void readWriteInverse(std::vector<T>&& ts, readFunc<T> r, WRITE_FUNC w) {
+    for (const T& value : ts) {
+        parcelOpSameLength([&] (Parcel* p) {
+            (*p.*w)(value);
+        }, [&] (Parcel* p) {
+            T outValue;
+            EXPECT_EQ(OK, (*p.*r)(&outValue));
+            EXPECT_EQ(value, outValue);
+        });
+    }
+}
+
+template <typename T>
+void readWriteInverse(std::vector<T>&& ts, readFunc<T> r, writeFunc<T> w) {
+    readWriteInverse<T, writeFunc<T>>(std::move(ts), r, w);
+}
+template <typename T>
+void readWriteInverse(std::vector<T>&& ts, readFunc<T> r, copyWriteFunc<T> w) {
+    readWriteInverse<T, copyWriteFunc<T>>(std::move(ts), r, w);
+}
+
+#define TEST_READ_WRITE_INVERSE(type, name, ...) \
+    TEST(Parcel, Inverse##name) { \
+        readWriteInverse<type>(__VA_ARGS__, &Parcel::read##name, &Parcel::write##name); \
+    }
+
+TEST_READ_WRITE_INVERSE(int32_t, Int32, {-2, -1, 0, 1, 2});
+TEST_READ_WRITE_INVERSE(uint32_t, Uint32, {0, 1, 2});
+TEST_READ_WRITE_INVERSE(int64_t, Int64, {-2, -1, 0, 1, 2});
+TEST_READ_WRITE_INVERSE(uint64_t, Uint64, {0, 1, 2});
+TEST_READ_WRITE_INVERSE(float, Float, {-1.0f, 0.0f, 3.14f});
+TEST_READ_WRITE_INVERSE(double, Double, {-1.0, 0.0, 3.14});
+TEST_READ_WRITE_INVERSE(bool, Bool, {true, false});
+TEST_READ_WRITE_INVERSE(char16_t, Char, {u'a', u'\0'});
+TEST_READ_WRITE_INVERSE(int8_t, Byte, {-1, 0, 1});
+TEST_READ_WRITE_INVERSE(String8, String8, {String8(), String8("a"), String8("asdf")});
+TEST_READ_WRITE_INVERSE(String16, String16, {String16(), String16("a"), String16("asdf")});
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index 9299721..f3559fa 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -123,6 +123,7 @@
                 .apply();
 
         mCaptureArgs.displayToken = mDisplayToken;
+        mCaptureArgs.dataspace = ui::Dataspace::V0_SRGB;
     }
 
     void setUpProducer(BLASTBufferQueueHelper adapter, sp<IGraphicBufferProducer>& producer) {
@@ -181,6 +182,7 @@
         for (uint32_t row = 0; row < height; row++) {
             for (uint32_t col = 0; col < width; col++) {
                 uint8_t* pixel = (uint8_t*)(bufData + (row * stride) + col);
+                ASSERT_NE(nullptr, pixel);
                 bool inRegion;
                 if (!outsideRegion) {
                     inRegion = row >= region.top + border && row < region.bottom - border &&
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 483f171..c39b0b5 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -153,6 +153,24 @@
         EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS);
     }
 
+    void expectTapWithFlag(int x, int y, int32_t flags) {
+        InputEvent *ev = consumeEvent();
+        ASSERT_NE(ev, nullptr);
+        ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType());
+        MotionEvent *mev = static_cast<MotionEvent *>(ev);
+        EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction());
+        EXPECT_EQ(x, mev->getX(0));
+        EXPECT_EQ(y, mev->getY(0));
+        EXPECT_EQ(flags, mev->getFlags() & flags);
+
+        ev = consumeEvent();
+        ASSERT_NE(ev, nullptr);
+        ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType());
+        mev = static_cast<MotionEvent *>(ev);
+        EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction());
+        EXPECT_EQ(flags, mev->getFlags() & flags);
+    }
+
     ~InputSurface() { mInputFlinger->removeInputChannel(mClientChannel->getConnectionToken()); }
 
     void doTransaction(std::function<void(SurfaceComposerClient::Transaction&,
@@ -602,4 +620,68 @@
     surface->expectTap(5, 10);
 }
 
+TEST_F(InputSurfacesTest, touch_flag_obscured) {
+    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+    surface->showAt(100, 100);
+
+    // Add non touchable window to fully cover touchable window. Window behind gets touch, but
+    // with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED
+    std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100);
+    nonTouchableSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE;
+    nonTouchableSurface->mInputInfo.ownerUid = 22222;
+    nonTouchableSurface->showAt(100, 100);
+
+    injectTap(190, 199);
+    surface->expectTapWithFlag(90, 99, AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED);
+}
+
+TEST_F(InputSurfacesTest, touch_flag_partially_obscured_with_crop) {
+    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+    surface->showAt(100, 100);
+
+    // Add non touchable window to cover touchable window, but parent is cropped to not cover area
+    // that will be tapped. Window behind gets touch, but with flag
+    // AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED
+    std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100);
+    std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100);
+    nonTouchableSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE;
+    parentSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE;
+    nonTouchableSurface->mInputInfo.ownerUid = 22222;
+    parentSurface->mInputInfo.ownerUid = 22222;
+    nonTouchableSurface->showAt(0, 0);
+    parentSurface->showAt(100, 100);
+
+    nonTouchableSurface->doTransaction([&](auto &t, auto &sc) {
+        t.setCrop_legacy(parentSurface->mSurfaceControl, Rect(0, 0, 50, 50));
+        t.reparent(sc, parentSurface->mSurfaceControl);
+    });
+
+    injectTap(190, 199);
+    surface->expectTapWithFlag(90, 99, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
+}
+
+TEST_F(InputSurfacesTest, touch_not_obscured_with_crop) {
+    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+    surface->showAt(100, 100);
+
+    // Add non touchable window to cover touchable window, but parent is cropped to avoid covering
+    // the touchable window. Window behind gets touch with no obscured flags.
+    std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100);
+    std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100);
+    nonTouchableSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE;
+    parentSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE;
+    nonTouchableSurface->mInputInfo.ownerUid = 22222;
+    parentSurface->mInputInfo.ownerUid = 22222;
+    nonTouchableSurface->showAt(0, 0);
+    parentSurface->showAt(50, 50);
+
+    nonTouchableSurface->doTransaction([&](auto &t, auto &sc) {
+        t.setCrop_legacy(parentSurface->mSurfaceControl, Rect(0, 0, 50, 50));
+        t.reparent(sc, parentSurface->mSurfaceControl);
+    });
+
+    injectTap(101, 110);
+    surface->expectTap(1, 10);
+}
+
 } // namespace android::test
diff --git a/libs/gui/view/Surface.cpp b/libs/gui/view/Surface.cpp
index 3e49de6..1bfe462 100644
--- a/libs/gui/view/Surface.cpp
+++ b/libs/gui/view/Surface.cpp
@@ -75,13 +75,9 @@
 }
 
 String16 Surface::readMaybeEmptyString16(const Parcel* parcel) {
-    size_t len;
-    const char16_t* str = parcel->readString16Inplace(&len);
-    if (str != nullptr) {
-        return String16(str, len);
-    } else {
-        return String16();
-    }
+    std::optional<String16> str;
+    parcel->readString16(&str);
+    return str.value_or(String16());
 }
 
 } // namespace view
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index eb967ce..cd7f37b 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -78,6 +78,7 @@
         "skia/SkiaRenderEngine.cpp",
         "skia/SkiaGLRenderEngine.cpp",
         "skia/filters/BlurFilter.cpp",
+        "skia/filters/LinearEffect.cpp",
     ],
 }
 
diff --git a/libs/renderengine/Description.cpp b/libs/renderengine/Description.cpp
index b9cea10..245c9e1 100644
--- a/libs/renderengine/Description.cpp
+++ b/libs/renderengine/Description.cpp
@@ -52,5 +52,10 @@
     return colorMatrix != identity;
 }
 
+bool Description::hasDisplayColorMatrix() const {
+    const mat4 identity;
+    return displayColorMatrix != identity;
+}
+
 } // namespace renderengine
 } // namespace android
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 13577f7..be83ebc 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -1121,6 +1121,7 @@
 
     setOutputDataSpace(display.outputDataspace);
     setDisplayMaxLuminance(display.maxLuminance);
+    setDisplayColorTransform(display.colorTransform);
 
     const mat4 projectionMatrix =
             ui::Transform(display.orientation).asMatrix4() * mState.projectionMatrix;
@@ -1189,7 +1190,7 @@
         position[3] = vec2(bounds.right, bounds.top);
 
         setupLayerCropping(*layer, mesh);
-        setColorTransform(display.colorTransform * layer->colorTransform);
+        setColorTransform(layer->colorTransform);
 
         bool usePremultipliedAlpha = true;
         bool disableTexture = true;
@@ -1351,6 +1352,10 @@
     mState.colorMatrix = colorTransform;
 }
 
+void GLESRenderEngine::setDisplayColorTransform(const mat4& colorTransform) {
+    mState.displayColorMatrix = colorTransform;
+}
+
 void GLESRenderEngine::disableTexturing() {
     mState.textureEnabled = false;
 }
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 1779994..c0449a1 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -168,6 +168,7 @@
     void setupLayerTexturing(const Texture& texture);
     void setupFillWithColor(float r, float g, float b, float a);
     void setColorTransform(const mat4& colorTransform);
+    void setDisplayColorTransform(const mat4& colorTransform);
     void disableTexturing();
     void disableBlending();
     void setupCornerRadiusCropSize(float width, float height);
diff --git a/libs/renderengine/gl/Program.cpp b/libs/renderengine/gl/Program.cpp
index f4fbf35..a172c56 100644
--- a/libs/renderengine/gl/Program.cpp
+++ b/libs/renderengine/gl/Program.cpp
@@ -66,6 +66,7 @@
         mTextureMatrixLoc = glGetUniformLocation(programId, "texture");
         mSamplerLoc = glGetUniformLocation(programId, "sampler");
         mColorLoc = glGetUniformLocation(programId, "color");
+        mDisplayColorMatrixLoc = glGetUniformLocation(programId, "displayColorMatrix");
         mDisplayMaxLuminanceLoc = glGetUniformLocation(programId, "displayMaxLuminance");
         mMaxMasteringLuminanceLoc = glGetUniformLocation(programId, "maxMasteringLuminance");
         mMaxContentLuminanceLoc = glGetUniformLocation(programId, "maxContentLuminance");
@@ -129,6 +130,9 @@
         const float color[4] = {desc.color.r, desc.color.g, desc.color.b, desc.color.a};
         glUniform4fv(mColorLoc, 1, color);
     }
+    if (mDisplayColorMatrixLoc >= 0) {
+        glUniformMatrix4fv(mDisplayColorMatrixLoc, 1, GL_FALSE, desc.displayColorMatrix.asArray());
+    }
     if (mInputTransformMatrixLoc >= 0) {
         mat4 inputTransformMatrix = desc.inputTransformMatrix;
         glUniformMatrix4fv(mInputTransformMatrixLoc, 1, GL_FALSE, inputTransformMatrix.asArray());
diff --git a/libs/renderengine/gl/Program.h b/libs/renderengine/gl/Program.h
index fc3755e..4292645 100644
--- a/libs/renderengine/gl/Program.h
+++ b/libs/renderengine/gl/Program.h
@@ -104,6 +104,7 @@
     /* location of transform matrix */
     GLint mInputTransformMatrixLoc;
     GLint mOutputTransformMatrixLoc;
+    GLint mDisplayColorMatrixLoc;
 
     /* location of corner radius uniform */
     GLint mCornerRadiusLoc;
diff --git a/libs/renderengine/gl/ProgramCache.cpp b/libs/renderengine/gl/ProgramCache.cpp
index 3ae35ec..7fc0499 100644
--- a/libs/renderengine/gl/ProgramCache.cpp
+++ b/libs/renderengine/gl/ProgramCache.cpp
@@ -180,6 +180,9 @@
                  description.hasOutputTransformMatrix() || description.hasColorMatrix()
                          ? Key::OUTPUT_TRANSFORM_MATRIX_ON
                          : Key::OUTPUT_TRANSFORM_MATRIX_OFF)
+            .set(Key::Key::DISPLAY_COLOR_TRANSFORM_MATRIX_MASK,
+                 description.hasDisplayColorMatrix() ? Key::DISPLAY_COLOR_TRANSFORM_MATRIX_ON
+                                                     : Key::DISPLAY_COLOR_TRANSFORM_MATRIX_OFF)
             .set(Key::ROUNDED_CORNERS_MASK,
                  description.cornerRadius > 0 ? Key::ROUNDED_CORNERS_ON : Key::ROUNDED_CORNERS_OFF)
             .set(Key::SHADOW_MASK, description.drawShadows ? Key::SHADOW_ON : Key::SHADOW_OFF);
@@ -661,7 +664,8 @@
             )__SHADER__";
     }
 
-    if (needs.hasTransformMatrix() || (needs.getInputTF() != needs.getOutputTF())) {
+    if (needs.hasTransformMatrix() || (needs.getInputTF() != needs.getOutputTF()) ||
+        needs.hasDisplayColorMatrix()) {
         if (needs.needsToneMapping()) {
             fs << "uniform float displayMaxLuminance;";
             fs << "uniform float maxMasteringLuminance;";
@@ -700,6 +704,21 @@
             )__SHADER__";
         }
 
+        if (needs.hasDisplayColorMatrix()) {
+            fs << "uniform mat4 displayColorMatrix;";
+            fs << R"__SHADER__(
+                highp vec3 DisplayColorMatrix(const highp vec3 color) {
+                    return clamp(vec3(displayColorMatrix * vec4(color, 1.0)), 0.0, 1.0);
+                }
+            )__SHADER__";
+        } else {
+            fs << R"__SHADER__(
+                highp vec3 DisplayColorMatrix(const highp vec3 color) {
+                    return color;
+                }
+            )__SHADER__";
+        }
+
         generateEOTF(fs, needs);
         generateOOTF(fs, needs);
         generateOETF(fs, needs);
@@ -732,14 +751,17 @@
         }
     }
 
-    if (needs.hasTransformMatrix() || (needs.getInputTF() != needs.getOutputTF())) {
+    if (needs.hasTransformMatrix() || (needs.getInputTF() != needs.getOutputTF()) ||
+        needs.hasDisplayColorMatrix()) {
         if (!needs.isOpaque() && needs.isPremultiplied()) {
             // un-premultiply if needed before linearization
             // avoid divide by 0 by adding 0.5/256 to the alpha channel
             fs << "gl_FragColor.rgb = gl_FragColor.rgb / (gl_FragColor.a + 0.0019);";
         }
         fs << "gl_FragColor.rgb = "
-              "OETF(OutputTransform(OOTF(InputTransform(EOTF(gl_FragColor.rgb)))));";
+              "DisplayColorMatrix(OETF(OutputTransform(OOTF(InputTransform(EOTF(gl_FragColor.rgb)))"
+              ")));";
+
         if (!needs.isOpaque() && needs.isPremultiplied()) {
             // and re-premultiply if needed after gamma correction
             fs << "gl_FragColor.rgb = gl_FragColor.rgb * (gl_FragColor.a + 0.0019);";
diff --git a/libs/renderengine/gl/ProgramCache.h b/libs/renderengine/gl/ProgramCache.h
index 901e631..37bb651 100644
--- a/libs/renderengine/gl/ProgramCache.h
+++ b/libs/renderengine/gl/ProgramCache.h
@@ -117,6 +117,11 @@
             SHADOW_MASK = 1 << SHADOW_SHIFT,
             SHADOW_OFF = 0 << SHADOW_SHIFT,
             SHADOW_ON = 1 << SHADOW_SHIFT,
+
+            DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT = 14,
+            DISPLAY_COLOR_TRANSFORM_MATRIX_MASK = 1 << DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT,
+            DISPLAY_COLOR_TRANSFORM_MATRIX_OFF = 0 << DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT,
+            DISPLAY_COLOR_TRANSFORM_MATRIX_ON = 1 << DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT,
         };
 
         inline Key() : mKey(0) {}
@@ -143,6 +148,10 @@
         inline bool hasOutputTransformMatrix() const {
             return (mKey & OUTPUT_TRANSFORM_MATRIX_MASK) == OUTPUT_TRANSFORM_MATRIX_ON;
         }
+        inline bool hasDisplayColorMatrix() const {
+            return (mKey & DISPLAY_COLOR_TRANSFORM_MATRIX_MASK) ==
+                    DISPLAY_COLOR_TRANSFORM_MATRIX_ON;
+        }
         inline bool hasTransformMatrix() const {
             return hasInputTransformMatrix() || hasOutputTransformMatrix();
         }
diff --git a/libs/renderengine/include/renderengine/private/Description.h b/libs/renderengine/include/renderengine/private/Description.h
index a62161a..fa6ec10 100644
--- a/libs/renderengine/include/renderengine/private/Description.h
+++ b/libs/renderengine/include/renderengine/private/Description.h
@@ -44,6 +44,7 @@
     bool hasInputTransformMatrix() const;
     bool hasOutputTransformMatrix() const;
     bool hasColorMatrix() const;
+    bool hasDisplayColorMatrix() const;
 
     // whether textures are premultiplied
     bool isPremultipliedAlpha = false;
@@ -79,6 +80,8 @@
 
     // The color matrix will be applied in linear space right before OETF.
     mat4 colorMatrix;
+    // The display color matrix will be applied in gamma space after OETF
+    mat4 displayColorMatrix;
     mat4 inputTransformMatrix;
     mat4 outputTransformMatrix;
 
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 03c8e80..1f25fbf 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -16,6 +16,9 @@
 
 //#define LOG_NDEBUG 0
 #include <cstdint>
+
+#include "SkImageInfo.h"
+#include "system/graphics-base-v1.0.h"
 #undef LOG_TAG
 #define LOG_TAG "RenderEngine"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
@@ -50,6 +53,7 @@
 #include "../gl/GLExtensions.h"
 #include "SkiaGLRenderEngine.h"
 #include "filters/BlurFilter.h"
+#include "filters/LinearEffect.h"
 
 extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 
@@ -411,6 +415,32 @@
                          matrix[3][3], 0);
 }
 
+static bool needsToneMapping(ui::Dataspace sourceDataspace, ui::Dataspace destinationDataspace) {
+    int64_t sourceTransfer = sourceDataspace & HAL_DATASPACE_TRANSFER_MASK;
+    int64_t destTransfer = destinationDataspace & HAL_DATASPACE_TRANSFER_MASK;
+
+    // Treat unsupported dataspaces as srgb
+    if (destTransfer != HAL_DATASPACE_TRANSFER_LINEAR &&
+        destTransfer != HAL_DATASPACE_TRANSFER_HLG &&
+        destTransfer != HAL_DATASPACE_TRANSFER_ST2084) {
+        destTransfer = HAL_DATASPACE_TRANSFER_SRGB;
+    }
+
+    if (sourceTransfer != HAL_DATASPACE_TRANSFER_LINEAR &&
+        sourceTransfer != HAL_DATASPACE_TRANSFER_HLG &&
+        sourceTransfer != HAL_DATASPACE_TRANSFER_ST2084) {
+        sourceTransfer = HAL_DATASPACE_TRANSFER_SRGB;
+    }
+
+    const bool isSourceLinear = sourceTransfer == HAL_DATASPACE_TRANSFER_LINEAR;
+    const bool isSourceSRGB = sourceTransfer == HAL_DATASPACE_TRANSFER_SRGB;
+    const bool isDestLinear = destTransfer == HAL_DATASPACE_TRANSFER_LINEAR;
+    const bool isDestSRGB = destTransfer == HAL_DATASPACE_TRANSFER_SRGB;
+
+    return !(isSourceLinear && isDestSRGB) && !(isSourceSRGB && isDestLinear) &&
+            sourceTransfer != destTransfer;
+}
+
 void SkiaGLRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) {
     std::lock_guard<std::mutex> lock(mRenderingMutex);
     mImageCache.erase(bufferId);
@@ -482,7 +512,8 @@
     // displays might have different scaling when compared to the physical screen.
 
     canvas->clipRect(getSkRect(display.physicalDisplay));
-    canvas->translate(display.physicalDisplay.left, display.physicalDisplay.top);
+    SkMatrix screenTransform;
+    screenTransform.setTranslate(display.physicalDisplay.left, display.physicalDisplay.top);
 
     const auto clipWidth = display.clip.width();
     const auto clipHeight = display.clip.height();
@@ -496,25 +527,28 @@
             static_cast<SkScalar>(rotatedClipWidth);
     const auto scaleY = static_cast<SkScalar>(display.physicalDisplay.height()) /
             static_cast<SkScalar>(rotatedClipHeight);
-    canvas->scale(scaleX, scaleY);
+    screenTransform.preScale(scaleX, scaleY);
 
     // Canvas rotation is done by centering the clip window at the origin, rotating, translating
     // back so that the top left corner of the clip is at (0, 0).
-    canvas->translate(rotatedClipWidth / 2, rotatedClipHeight / 2);
-    canvas->rotate(toDegrees(display.orientation));
-    canvas->translate(-clipWidth / 2, -clipHeight / 2);
-    canvas->translate(-display.clip.left, -display.clip.top);
+    screenTransform.preTranslate(rotatedClipWidth / 2, rotatedClipHeight / 2);
+    screenTransform.preRotate(toDegrees(display.orientation));
+    screenTransform.preTranslate(-clipWidth / 2, -clipHeight / 2);
+    screenTransform.preTranslate(-display.clip.left, -display.clip.top);
     for (const auto& layer : layers) {
+        const SkMatrix drawTransform = getDrawTransform(layer, screenTransform);
+
         SkPaint paint;
         const auto& bounds = layer->geometry.boundaries;
         const auto dest = getSkRect(bounds);
         std::unordered_map<uint32_t, sk_sp<SkSurface>> cachedBlurs;
 
         if (mBlurFilter) {
+            const auto layerRect = drawTransform.mapRect(dest);
             if (layer->backgroundBlurRadius > 0) {
                 ATRACE_NAME("BackgroundBlur");
                 auto blurredSurface =
-                        mBlurFilter->draw(canvas, surface, layer->backgroundBlurRadius);
+                        mBlurFilter->draw(canvas, surface, layer->backgroundBlurRadius, layerRect);
                 cachedBlurs[layer->backgroundBlurRadius] = blurredSurface;
             }
             if (layer->blurRegions.size() > 0) {
@@ -523,7 +557,8 @@
                         continue;
                     }
                     ATRACE_NAME("BlurRegion");
-                    auto blurredSurface = mBlurFilter->generate(canvas, surface, region.blurRadius);
+                    auto blurredSurface =
+                            mBlurFilter->generate(canvas, surface, region.blurRadius, layerRect);
                     cachedBlurs[region.blurRadius] = blurredSurface;
                 }
             }
@@ -539,14 +574,20 @@
             if (iter != mImageCache.end()) {
                 image = iter->second;
             } else {
-                image = SkImage::MakeFromAHardwareBuffer(item.buffer->toAHardwareBuffer(),
-                                                         item.usePremultipliedAlpha
-                                                                 ? kPremul_SkAlphaType
-                                                                 : kUnpremul_SkAlphaType,
-                                                         mUseColorManagement
-                                                                 ? toColorSpace(
-                                                                           layer->sourceDataspace)
-                                                                 : SkColorSpace::MakeSRGB());
+                image = SkImage::MakeFromAHardwareBuffer(
+                        item.buffer->toAHardwareBuffer(),
+                        item.isOpaque ? kOpaque_SkAlphaType
+                                      : (item.usePremultipliedAlpha ? kPremul_SkAlphaType
+                                                                    : kUnpremul_SkAlphaType),
+                        mUseColorManagement
+                                ? (needsToneMapping(layer->sourceDataspace, display.outputDataspace)
+                                           // If we need to map to linear space, then
+                                           // mark the source image with the same
+                                           // colorspace as the destination surface so
+                                           // that Skia's color management is a no-op.
+                                           ? toColorSpace(display.outputDataspace)
+                                           : toColorSpace(layer->sourceDataspace))
+                                : SkColorSpace::MakeSRGB());
                 mImageCache.insert({item.buffer->getId(), image});
             }
 
@@ -560,6 +601,10 @@
             }
 
             auto texMatrix = getSkM44(item.textureTransform).asM33();
+
+            // b/171404534, scale to fix the layer
+            matrix.postScale(bounds.getWidth() / bufferWidth, bounds.getHeight() / bufferHeight);
+
             // textureTansform was intended to be passed directly into a shader, so when
             // building the total matrix with the textureTransform we need to first
             // normalize it, then apply the textureTransform, then scale back up.
@@ -590,7 +635,22 @@
 
             matrix.postConcat(texMatrix);
             matrix.postScale(rotatedBufferWidth, rotatedBufferHeight);
-            paint.setShader(image->makeShader(matrix));
+            sk_sp<SkShader> shader = image->makeShader(matrix);
+
+            if (mUseColorManagement &&
+                needsToneMapping(layer->sourceDataspace, display.outputDataspace)) {
+                LinearEffect effect = LinearEffect{.inputDataspace = layer->sourceDataspace,
+                                                   .outputDataspace = display.outputDataspace,
+                                                   .undoPremultipliedAlpha = !item.isOpaque &&
+                                                           item.usePremultipliedAlpha};
+                sk_sp<SkRuntimeEffect> runtimeEffect = buildRuntimeEffect(effect);
+                paint.setShader(createLinearEffectShader(shader, effect, runtimeEffect,
+                                                         display.maxLuminance,
+                                                         layer->source.buffer.maxMasteringLuminance,
+                                                         layer->source.buffer.maxContentLuminance));
+            } else {
+                paint.setShader(shader);
+            }
         } else {
             ATRACE_NAME("DrawColor");
             const auto color = layer->source.solidColor;
@@ -603,9 +663,8 @@
 
         paint.setColorFilter(SkColorFilters::Matrix(toSkColorMatrix(display.colorTransform)));
 
-        // Layers have a local transform matrix that should be applied to them.
         canvas->save();
-        canvas->concat(getSkM44(layer->geometry.positionTransform));
+        canvas->concat(drawTransform);
 
         for (const auto effectRegion : layer->blurRegions) {
             drawBlurRegion(canvas, effectRegion, dest, cachedBlurs[effectRegion.blurRadius]);
@@ -682,6 +741,13 @@
                  matrix[0][3], matrix[1][3], matrix[2][3], matrix[3][3]);
 }
 
+inline SkMatrix SkiaGLRenderEngine::getDrawTransform(const LayerSettings* layer,
+                                                     const SkMatrix& screenTransform) {
+    // Layers have a local transform matrix that should be applied to them.
+    const auto layerTransform = getSkM44(layer->geometry.positionTransform).asM33();
+    return SkMatrix::Concat(screenTransform, layerTransform);
+}
+
 inline SkPoint3 SkiaGLRenderEngine::getSkPoint3(const vec3& vector) {
     return SkPoint3::Make(vector.x, vector.y, vector.z);
 }
@@ -817,4 +883,4 @@
 
 } // namespace skia
 } // namespace renderengine
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index 0143445..c65e431 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -69,6 +69,7 @@
     inline SkRRect getRoundedRect(const LayerSettings* layer);
     inline SkColor getSkColor(const vec4& color);
     inline SkM44 getSkM44(const mat4& matrix);
+    inline SkMatrix getDrawTransform(const LayerSettings* layer, const SkMatrix& screenTransform);
     inline SkPoint3 getSkPoint3(const vec3& vector);
 
     base::unique_fd flush();
@@ -107,4 +108,4 @@
 } // namespace renderengine
 } // namespace android
 
-#endif /* SF_GLESRENDERENGINE_H_ */
\ No newline at end of file
+#endif /* SF_GLESRENDERENGINE_H_ */
diff --git a/libs/renderengine/skia/filters/BlurFilter.cpp b/libs/renderengine/skia/filters/BlurFilter.cpp
index f6a316f..dfb306f 100644
--- a/libs/renderengine/skia/filters/BlurFilter.cpp
+++ b/libs/renderengine/skia/filters/BlurFilter.cpp
@@ -56,7 +56,7 @@
 }
 
 sk_sp<SkSurface> BlurFilter::generate(SkCanvas* canvas, const sk_sp<SkSurface> input,
-                                      const uint32_t blurRadius) const {
+                                      const uint32_t blurRadius, SkRect rect) const {
     ATRACE_CALL();
 
     // Kawase is an approximation of Gaussian, but it behaves differently from it.
@@ -68,6 +68,9 @@
 
     SkImageInfo scaledInfo = SkImageInfo::MakeN32Premul((float)input->width() * kInputScale,
                                                         (float)input->height() * kInputScale);
+
+    SkRect scaledRect = {rect.fLeft * kInputScale, rect.fTop * kInputScale,
+                         rect.fRight * kInputScale, rect.fBottom * kInputScale};
     auto drawSurface = canvas->makeSurface(scaledInfo);
 
     const float stepX = radiusByPasses;
@@ -88,7 +91,9 @@
         SkPaint paint;
         paint.setShader(blurBuilder.makeShader(nullptr, false));
         paint.setFilterQuality(kLow_SkFilterQuality);
-        drawSurface->getCanvas()->drawIRect(scaledInfo.bounds(), paint);
+
+        drawSurface->getCanvas()->drawRect(scaledRect, paint);
+
         blurBuilder.child("input") = nullptr;
     }
 
@@ -110,7 +115,8 @@
             SkPaint paint;
             paint.setShader(blurBuilder.makeShader(nullptr, false));
             paint.setFilterQuality(kLow_SkFilterQuality);
-            drawSurface->getCanvas()->drawIRect(scaledInfo.bounds(), paint);
+
+            drawSurface->getCanvas()->drawRect(scaledRect, paint);
 
             // Swap buffers for next iteration
             const auto tmp = drawSurface;
@@ -125,16 +131,18 @@
 }
 
 sk_sp<SkSurface> BlurFilter::draw(SkCanvas* canvas, const sk_sp<SkSurface> input,
-                                  const uint32_t blurRadius) const {
+                                  const uint32_t blurRadius, SkRect rect) const {
     ATRACE_CALL();
-    auto surface = generate(canvas, input, blurRadius);
+    sk_sp<SkSurface> surface = generate(canvas, input, blurRadius, rect);
+    const auto image = surface->makeImageSnapshot();
 
     SkPaint paint;
-    const auto image = surface->makeImageSnapshot();
     paint.setShader(image->makeShader(SkMatrix::MakeScale(kInverseInputScale)));
     paint.setFilterQuality(kLow_SkFilterQuality);
     paint.setAlpha(std::min(1.0f, (float)blurRadius / kMaxCrossFadeRadius) * 255);
-    canvas->drawIRect(SkIRect::MakeWH(input->width(), input->height()), paint);
+
+    canvas->drawRect(rect, paint);
+
     return surface;
 }
 
@@ -146,4 +154,4 @@
 
 } // namespace skia
 } // namespace renderengine
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/libs/renderengine/skia/filters/BlurFilter.h b/libs/renderengine/skia/filters/BlurFilter.h
index 6f973d7..c0a92f6 100644
--- a/libs/renderengine/skia/filters/BlurFilter.h
+++ b/libs/renderengine/skia/filters/BlurFilter.h
@@ -48,11 +48,11 @@
     virtual ~BlurFilter(){};
 
     // Execute blur, saving it to a texture
-    sk_sp<SkSurface> generate(SkCanvas* canvas, const sk_sp<SkSurface> input,
-                              const uint32_t radius) const;
+    sk_sp<SkSurface> generate(SkCanvas* canvas, const sk_sp<SkSurface> input, const uint32_t radius,
+                              SkRect rect) const;
     // Same as generate but also drawing to the screen
-    sk_sp<SkSurface> draw(SkCanvas* canvas, const sk_sp<SkSurface> input,
-                          const uint32_t radius) const;
+    sk_sp<SkSurface> draw(SkCanvas* canvas, const sk_sp<SkSurface> input, const uint32_t radius,
+                          SkRect rect) const;
     // Returns a matrix that should be applied to the blur shader
     SkMatrix getShaderMatrix(const SkMatrix& transformMatrix) const;
 
diff --git a/libs/renderengine/skia/filters/LinearEffect.cpp b/libs/renderengine/skia/filters/LinearEffect.cpp
new file mode 100644
index 0000000..376abdf
--- /dev/null
+++ b/libs/renderengine/skia/filters/LinearEffect.cpp
@@ -0,0 +1,308 @@
+/*
+ * 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.
+ */
+
+#include "LinearEffect.h"
+
+#include <SkString.h>
+
+#include <optional>
+
+#include "log/log.h"
+#include "math/mat4.h"
+#include "ui/ColorSpace.h"
+
+namespace android {
+namespace renderengine {
+namespace skia {
+
+static void generateEOTF(ui::Dataspace dataspace, SkString& shader) {
+    switch (dataspace & HAL_DATASPACE_TRANSFER_MASK) {
+        case HAL_DATASPACE_TRANSFER_ST2084:
+            shader.append(R"(
+
+                float3 EOTF(float3 color) {
+                    float m1 = (2610.0 / 4096.0) / 4.0;
+                    float m2 = (2523.0 / 4096.0) * 128.0;
+                    float c1 = (3424.0 / 4096.0);
+                    float c2 = (2413.0 / 4096.0) * 32.0;
+                    float c3 = (2392.0 / 4096.0) * 32.0;
+
+                    float3 tmp = pow(clamp(color, 0.0, 1.0), 1.0 / float3(m2));
+                    tmp = max(tmp - c1, 0.0) / (c2 - c3 * tmp);
+                    return pow(tmp, 1.0 / float3(m1));
+                }
+            )");
+            break;
+        default:
+            shader.append(R"(
+
+                float EOTF_sRGB(float srgb) {
+                    return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4);
+                }
+
+                float3 EOTF_sRGB(float3 srgb) {
+                    return float3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
+                }
+
+                float3 EOTF(float3 srgb) {
+                    return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
+                }
+            )");
+            break;
+    }
+}
+
+static void generateXYZTransforms(SkString& shader) {
+    shader.append(R"(
+        uniform float4x4 in_rgbToXyz;
+        uniform float4x4 in_xyzToRgb;
+        float3 ToXYZ(float3 rgb) {
+            return clamp((in_rgbToXyz * float4(rgb, 1.0)).rgb, 0.0, 1.0);
+        }
+
+        float3 ToRGB(float3 xyz) {
+            return clamp((in_xyzToRgb * float4(xyz, 1.0)).rgb, 0.0, 1.0);
+        }
+    )");
+}
+
+static void generateOOTF(ui::Dataspace inputDataspace, ui::Dataspace outputDataspace,
+                         SkString& shader) {
+    shader.append(R"(
+            uniform float in_displayMaxLuminance;
+            uniform float in_inputMaxLuminance;
+            uniform float in_maxContentLuminance;
+        )");
+    switch (inputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
+        case HAL_DATASPACE_TRANSFER_ST2084:
+            shader.append(R"(
+                    float3 ScaleLuminance(float3 xyz) {
+                        return xyz * 10000.0;
+                    }
+                )");
+
+            switch (outputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
+                default:
+                    shader.append(R"(
+                            float3 ToneMap(float3 xyz) {
+                                float maxInLumi = in_inputMaxLuminance;
+                                float maxOutLumi = in_displayMaxLuminance;
+
+                                float nits = xyz.y;
+
+                                // clamp to max input luminance
+                                nits = clamp(nits, 0.0, maxInLumi);
+
+                                // scale [0.0, maxInLumi] to [0.0, maxOutLumi]
+                                if (maxInLumi <= maxOutLumi) {
+                                    return xyz * (maxOutLumi / maxInLumi);
+                                } else {
+                                    // three control points
+                                    const float x0 = 10.0;
+                                    const float y0 = 17.0;
+                                    float x1 = maxOutLumi * 0.75;
+                                    float y1 = x1;
+                                    float x2 = x1 + (maxInLumi - x1) / 2.0;
+                                    float y2 = y1 + (maxOutLumi - y1) * 0.75;
+
+                                    // horizontal distances between the last three control points
+                                    float h12 = x2 - x1;
+                                    float h23 = maxInLumi - x2;
+                                    // tangents at the last three control points
+                                    float m1 = (y2 - y1) / h12;
+                                    float m3 = (maxOutLumi - y2) / h23;
+                                    float m2 = (m1 + m3) / 2.0;
+
+                                    if (nits < x0) {
+                                        // scale [0.0, x0] to [0.0, y0] linearly
+                                        float slope = y0 / x0;
+                                        return xyz * slope;
+                                    } else if (nits < x1) {
+                                        // scale [x0, x1] to [y0, y1] linearly
+                                        float slope = (y1 - y0) / (x1 - x0);
+                                        nits = y0 + (nits - x0) * slope;
+                                    } else if (nits < x2) {
+                                        // scale [x1, x2] to [y1, y2] using Hermite interp
+                                        float t = (nits - x1) / h12;
+                                        nits = (y1 * (1.0 + 2.0 * t) + h12 * m1 * t) * (1.0 - t) * (1.0 - t) +
+                                                (y2 * (3.0 - 2.0 * t) + h12 * m2 * (t - 1.0)) * t * t;
+                                    } else {
+                                        // scale [x2, maxInLumi] to [y2, maxOutLumi] using Hermite interp
+                                        float t = (nits - x2) / h23;
+                                        nits = (y2 * (1.0 + 2.0 * t) + h23 * m2 * t) * (1.0 - t) * (1.0 - t) +
+                                                (maxOutLumi * (3.0 - 2.0 * t) + h23 * m3 * (t - 1.0)) * t * t;
+                                    }
+                                }
+
+                                // color.y is greater than x0 and is thus non-zero
+                                return xyz * (nits / xyz.y);
+                            }
+                        )");
+                    break;
+            }
+            break;
+        default:
+            shader.append(R"(
+                    float3 ScaleLuminance(float3 xyz) {
+                        return xyz * in_displayMaxLuminance;
+                    }
+
+                    float3 ToneMap(float3 xyz) {
+                        return xyz;
+                    }
+                )");
+            break;
+    }
+
+    switch (outputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
+        case HAL_DATASPACE_TRANSFER_ST2084:
+            shader.append(R"(
+                    float3 NormalizeLuminance(float3 xyz) {
+                        return xyz / 10000.0;
+                    }
+                )");
+            break;
+        default:
+            shader.append(R"(
+                    float3 NormalizeLuminance(float3 xyz) {
+                        return xyz / in_displayMaxLuminance;
+                    }
+                )");
+            break;
+    }
+
+    shader.append(R"(
+            float3 OOTF(float3 xyz) {
+                return NormalizeLuminance(ToneMap(ScaleLuminance(xyz)));
+            }
+        )");
+}
+
+static void generateOETF(ui::Dataspace dataspace, SkString& shader) {
+    switch (dataspace & HAL_DATASPACE_TRANSFER_MASK) {
+        case HAL_DATASPACE_TRANSFER_ST2084:
+            shader.append(R"(
+
+                float3 OETF(float3 xyz) {
+                    float m1 = (2610.0 / 4096.0) / 4.0;
+                    float m2 = (2523.0 / 4096.0) * 128.0;
+                    float c1 = (3424.0 / 4096.0);
+                    float c2 = (2413.0 / 4096.0) * 32.0;
+                    float c3 = (2392.0 / 4096.0) * 32.0;
+
+                    float3 tmp = pow(xyz, float3(m1));
+                    tmp = (c1 + c2 * tmp) / (1.0 + c3 * tmp);
+                    return pow(tmp, float3(m2));
+                }
+            )");
+            break;
+        default:
+            shader.append(R"(
+                float OETF_sRGB(float linear) {
+                    return linear <= 0.0031308 ?
+                            linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055;
+                }
+
+                float3 OETF_sRGB(float3 linear) {
+                    return float3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
+                }
+
+                float3 OETF(float3 linear) {
+                    return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
+                }
+            )");
+            break;
+    }
+}
+
+static void generateEffectiveOOTF(bool undoPremultipliedAlpha, SkString& shader) {
+    shader.append(R"(
+        in shader input;
+        half4 main(float2 xy) {
+            float4 c = float4(sample(input, xy));
+    )");
+    if (undoPremultipliedAlpha) {
+        shader.append(R"(
+            c.rgb = c.rgb / (c.a + 0.0019);
+        )");
+    }
+    shader.append(R"(
+        c.rgb = OETF(ToRGB(OOTF(ToXYZ(EOTF(c.rgb)))));
+    )");
+    if (undoPremultipliedAlpha) {
+        shader.append(R"(
+            c.rgb = c.rgb * (c.a + 0.0019);
+        )");
+    }
+    shader.append(R"(
+            return c;
+        }
+    )");
+}
+static ColorSpace toColorSpace(ui::Dataspace dataspace) {
+    switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
+        case HAL_DATASPACE_STANDARD_BT709:
+            return ColorSpace::sRGB();
+            break;
+        case HAL_DATASPACE_STANDARD_DCI_P3:
+            return ColorSpace::DisplayP3();
+            break;
+        case HAL_DATASPACE_STANDARD_BT2020:
+            return ColorSpace::BT2020();
+            break;
+        default:
+            return ColorSpace::sRGB();
+            break;
+    }
+}
+
+sk_sp<SkRuntimeEffect> buildRuntimeEffect(const LinearEffect& linearEffect) {
+    SkString shaderString;
+    generateEOTF(linearEffect.inputDataspace, shaderString);
+    generateXYZTransforms(shaderString);
+    generateOOTF(linearEffect.inputDataspace, linearEffect.outputDataspace, shaderString);
+    generateOETF(linearEffect.outputDataspace, shaderString);
+    generateEffectiveOOTF(linearEffect.undoPremultipliedAlpha, shaderString);
+
+    auto [shader, error] = SkRuntimeEffect::Make(shaderString);
+    if (!shader) {
+        LOG_ALWAYS_FATAL("LinearColorFilter construction error: %s", error.c_str());
+    }
+    return shader;
+}
+
+sk_sp<SkShader> createLinearEffectShader(sk_sp<SkShader> shader, const LinearEffect& linearEffect,
+                                         sk_sp<SkRuntimeEffect> runtimeEffect,
+                                         float maxDisplayLuminance, float maxMasteringLuminance,
+                                         float maxContentLuminance) {
+    SkRuntimeShaderBuilder effectBuilder(runtimeEffect);
+
+    effectBuilder.child("input") = shader;
+
+    ColorSpace inputColorSpace = toColorSpace(linearEffect.inputDataspace);
+    ColorSpace outputColorSpace = toColorSpace(linearEffect.outputDataspace);
+
+    effectBuilder.uniform("in_rgbToXyz") = mat4(inputColorSpace.getRGBtoXYZ());
+    effectBuilder.uniform("in_xyzToRgb") = mat4(outputColorSpace.getXYZtoRGB());
+    effectBuilder.uniform("in_displayMaxLuminance") = maxDisplayLuminance;
+    effectBuilder.uniform("in_inputMaxLuminance") =
+            std::min(maxMasteringLuminance, maxContentLuminance);
+    return effectBuilder.makeShader(nullptr, false);
+}
+
+} // namespace skia
+} // namespace renderengine
+} // namespace android
\ No newline at end of file
diff --git a/libs/renderengine/skia/filters/LinearEffect.h b/libs/renderengine/skia/filters/LinearEffect.h
new file mode 100644
index 0000000..2615669
--- /dev/null
+++ b/libs/renderengine/skia/filters/LinearEffect.h
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <optional>
+
+#include "SkColorMatrix.h"
+#include "SkRuntimeEffect.h"
+#include "SkShader.h"
+#include "ui/GraphicTypes.h"
+
+namespace android {
+namespace renderengine {
+namespace skia {
+
+/**
+ * Arguments for creating an effect that applies color transformations in linear XYZ space.
+ * A linear effect is decomposed into the following steps when operating on an image:
+ * 1. Electrical-Optical Transfer Function (EOTF) maps the input RGB signal into the intended
+ * relative display brightness of the scene in nits for each RGB channel
+ * 2. Transformation matrix from linear RGB brightness to linear XYZ, to operate on display
+ * luminance.
+ * 3. Opto-Optical Transfer Function (OOTF) applies a "rendering intent". This can include tone
+ * mapping to display SDR content alongside HDR content, or any number of subjective transformations
+ * 4. Transformation matrix from linear XYZ back to linear RGB brightness.
+ * 5. Opto-Electronic Transfer Function (OETF) maps the display brightness of the scene back to
+ * output RGB colors.
+ *
+ * For further reading, consult the recommendation in ITU-R BT.2390-4:
+ * https://www.itu.int/dms_pub/itu-r/opb/rep/R-REP-BT.2390-4-2018-PDF-E.pdf
+ *
+ * Skia normally attempts to do its own simple tone mapping, i.e., the working color space is
+ * intended to be the output surface. However, Skia does not support complex tone mapping such as
+ * polynomial interpolation. As such, this filter assumes that tone mapping has not yet been applied
+ * to the source colors. so that the tone mapping process is only applied once by this effect. Tone
+ * mapping is applied when presenting HDR content (content with HLG or PQ transfer functions)
+ * alongside other content, whereby maximum input luminance is mapped to maximum output luminance
+ * and intermediate values are interpolated.
+ */
+struct LinearEffect {
+    // Input dataspace of the source colors.
+    const ui::Dataspace inputDataspace = ui::Dataspace::SRGB;
+
+    // Working dataspace for the output surface, for conversion from linear space.
+    const ui::Dataspace outputDataspace = ui::Dataspace::SRGB;
+
+    // Sets whether alpha premultiplication must be undone.
+    // This is required if the source colors use premultiplied alpha and is not opaque.
+    const bool undoPremultipliedAlpha = false;
+};
+
+sk_sp<SkRuntimeEffect> buildRuntimeEffect(const LinearEffect& linearEffect);
+
+// Generates a shader resulting from applying the a linear effect created from
+// LinearEffectARgs::buildEffect to an inputShader. We also provide additional HDR metadata upon
+// creating the shader:
+// * The max display luminance is the max luminance of the physical display in nits
+// * The max mastering luminance is provided as the max luminance from the SMPTE 2086
+// standard.
+// * The max content luminance is provided as the max light level from the CTA 861.3
+// standard.
+sk_sp<SkShader> createLinearEffectShader(sk_sp<SkShader> inputShader,
+                                         const LinearEffect& linearEffect,
+                                         sk_sp<SkRuntimeEffect> runtimeEffect,
+                                         float maxDisplayLuminance, float maxMasteringLuminance,
+                                         float maxContentLuminance);
+} // namespace skia
+} // namespace renderengine
+} // namespace android
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index d795616..d20fcc4 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -39,7 +39,7 @@
 
 struct RenderEngineTest : public ::testing::Test {
     static void SetUpTestSuite() {
-        sRE = renderengine::gl::GLESRenderEngine::create(
+        renderengine::RenderEngineCreationArgs reCreationArgs =
                 renderengine::RenderEngineCreationArgs::Builder()
                         .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
                         .setImageCacheSize(1)
@@ -49,13 +49,18 @@
                         .setSupportsBackgroundBlur(true)
                         .setContextPriority(renderengine::RenderEngine::ContextPriority::MEDIUM)
                         .setRenderEngineType(renderengine::RenderEngine::RenderEngineType::GLES)
-                        .build());
+                        .build();
+        sRE = renderengine::gl::GLESRenderEngine::create(reCreationArgs);
+
+        reCreationArgs.useColorManagement = true;
+        sRECM = renderengine::gl::GLESRenderEngine::create(reCreationArgs);
     }
 
     static void TearDownTestSuite() {
         // The ordering here is important - sCurrentBuffer must live longer
         // than RenderEngine to avoid a null reference on tear-down.
         sRE = nullptr;
+        sRECM = nullptr;
         sCurrentBuffer = nullptr;
     }
 
@@ -85,6 +90,9 @@
             sRE->deleteTextures(1, &texName);
             EXPECT_FALSE(sRE->isTextureNameKnownForTesting(texName));
         }
+        for (uint32_t texName : mTexNamesCM) {
+            sRECM->deleteTextures(1, &texName);
+        }
     }
 
     void writeBufferToFile(const char* basename) {
@@ -253,10 +261,11 @@
 
     void invokeDraw(renderengine::DisplaySettings settings,
                     std::vector<const renderengine::LayerSettings*> layers,
-                    sp<GraphicBuffer> buffer) {
+                    sp<GraphicBuffer> buffer, bool useColorManagement = false) {
         base::unique_fd fence;
-        status_t status =
-                sRE->drawLayers(settings, layers, buffer, true, base::unique_fd(), &fence);
+        status_t status = useColorManagement
+                ? sRECM->drawLayers(settings, layers, buffer, true, base::unique_fd(), &fence)
+                : sRE->drawLayers(settings, layers, buffer, true, base::unique_fd(), &fence);
         sCurrentBuffer = buffer;
 
         int fd = fence.release();
@@ -267,7 +276,11 @@
 
         ASSERT_EQ(NO_ERROR, status);
         if (layers.size() > 0) {
-            ASSERT_TRUE(sRE->isFramebufferImageCachedForTesting(buffer->getId()));
+            if (useColorManagement) {
+                ASSERT_TRUE(sRECM->isFramebufferImageCachedForTesting(buffer->getId()));
+            } else {
+                ASSERT_TRUE(sRE->isFramebufferImageCachedForTesting(buffer->getId()));
+            }
         }
     }
 
@@ -322,12 +335,15 @@
     void fillBufferLayerTransform();
 
     template <typename SourceVariant>
-    void fillBufferWithColorTransform();
+    void fillBufferWithColorTransform(bool useColorManagement = false);
 
     template <typename SourceVariant>
     void fillBufferColorTransform();
 
     template <typename SourceVariant>
+    void fillBufferColorTransformCM();
+
+    template <typename SourceVariant>
     void fillRedBufferWithRoundedCorners();
 
     template <typename SourceVariant>
@@ -366,6 +382,8 @@
     // For now, exercise the GL backend directly so that some caching specifics
     // can be tested without changing the interface.
     static std::unique_ptr<renderengine::gl::GLESRenderEngine> sRE;
+    // renderengine object with Color Management enabled
+    static std::unique_ptr<renderengine::gl::GLESRenderEngine> sRECM;
     // Dumb hack to avoid NPE in the EGL driver: the GraphicBuffer needs to
     // be freed *after* RenderEngine is destroyed, so that the EGL image is
     // destroyed first.
@@ -374,14 +392,17 @@
     sp<GraphicBuffer> mBuffer;
 
     std::vector<uint32_t> mTexNames;
+    std::vector<uint32_t> mTexNamesCM;
 };
 
 std::unique_ptr<renderengine::gl::GLESRenderEngine> RenderEngineTest::sRE = nullptr;
+std::unique_ptr<renderengine::gl::GLESRenderEngine> RenderEngineTest::sRECM = nullptr;
+
 sp<GraphicBuffer> RenderEngineTest::sCurrentBuffer = nullptr;
 
 struct ColorSourceVariant {
     static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b,
-                          RenderEngineTest* /*fixture*/) {
+                          RenderEngineTest* /*fixture*/, bool /*useColorManagement*/ = false) {
         layer.source.solidColor = half3(r, g, b);
     }
 };
@@ -409,11 +430,16 @@
 template <typename OpaquenessVariant>
 struct BufferSourceVariant {
     static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b,
-                          RenderEngineTest* fixture) {
+                          RenderEngineTest* fixture, bool useColorManagement = false) {
         sp<GraphicBuffer> buf = RenderEngineTest::allocateSourceBuffer(1, 1);
         uint32_t texName;
-        fixture->sRE->genTextures(1, &texName);
-        fixture->mTexNames.push_back(texName);
+        if (useColorManagement) {
+            fixture->sRECM->genTextures(1, &texName);
+            fixture->mTexNamesCM.push_back(texName);
+        } else {
+            fixture->sRE->genTextures(1, &texName);
+            fixture->mTexNames.push_back(texName);
+        }
 
         uint8_t* pixels;
         buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
@@ -643,7 +669,7 @@
 }
 
 template <typename SourceVariant>
-void RenderEngineTest::fillBufferWithColorTransform() {
+void RenderEngineTest::fillBufferWithColorTransform(bool useColorManagement) {
     renderengine::DisplaySettings settings;
     settings.physicalDisplay = fullscreenRect();
     settings.clip = Rect(1, 1);
@@ -652,12 +678,12 @@
 
     renderengine::LayerSettings layer;
     layer.geometry.boundaries = Rect(1, 1).toFloatRect();
-    SourceVariant::fillColor(layer, 0.5f, 0.25f, 0.125f, this);
+    SourceVariant::fillColor(layer, 0.5f, 0.25f, 0.125f, this, useColorManagement);
     layer.alpha = 1.0f;
 
     // construct a fake color matrix
     // annihilate green and blue channels
-    settings.colorTransform = mat4::scale(vec4(1, 0, 0, 1));
+    settings.colorTransform = mat4::scale(vec4(0.9f, 0, 0, 1));
     // set red channel to red + green
     layer.colorTransform = mat4(1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
 
@@ -666,13 +692,19 @@
 
     layers.push_back(&layer);
 
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers, mBuffer, useColorManagement);
 }
 
 template <typename SourceVariant>
 void RenderEngineTest::fillBufferColorTransform() {
     fillBufferWithColorTransform<SourceVariant>();
-    expectBufferColor(fullscreenRect(), 191, 0, 0, 255);
+    expectBufferColor(fullscreenRect(), 172, 0, 0, 255, 1);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferColorTransformCM() {
+    fillBufferWithColorTransform<SourceVariant>(true);
+    expectBufferColor(fullscreenRect(), 126, 0, 0, 255, 1);
 }
 
 template <typename SourceVariant>
@@ -1073,7 +1105,11 @@
 }
 
 TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransform_colorSource) {
-    fillBufferLayerTransform<ColorSourceVariant>();
+    fillBufferColorTransform<ColorSourceVariant>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransformCM_colorSource) {
+    fillBufferColorTransformCM<ColorSourceVariant>();
 }
 
 TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_colorSource) {
@@ -1129,7 +1165,11 @@
 }
 
 TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransform_opaqueBufferSource) {
-    fillBufferLayerTransform<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+    fillBufferColorTransform<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransformCM_opaqueBufferSource) {
+    fillBufferColorTransformCM<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
 
 TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_opaqueBufferSource) {
@@ -1185,7 +1225,11 @@
 }
 
 TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransform_bufferSource) {
-    fillBufferLayerTransform<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+    fillBufferColorTransform<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransformCM_bufferSource) {
+    fillBufferColorTransformCM<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
 TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_bufferSource) {
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
index 2b18180..0661709 100644
--- a/services/inputflinger/dispatcher/Entry.h
+++ b/services/inputflinger/dispatcher/Entry.h
@@ -250,7 +250,7 @@
     int32_t userActivityEventType;
     uint32_t seq;
     bool handled;
-    std::shared_ptr<InputChannel> inputChannel;
+    sp<IBinder> connectionToken;
     sp<IBinder> oldToken;
     sp<IBinder> newToken;
     std::string obscuringPackage;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 7191487..e5d208a 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -1230,9 +1230,7 @@
                     &InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
             sp<IBinder> focusedWindowToken =
                     getValueByKey(mFocusedWindowTokenByDisplay, getTargetDisplayId(*entry));
-            if (focusedWindowToken != nullptr) {
-                commandEntry->inputChannel = getInputChannelLocked(focusedWindowToken);
-            }
+            commandEntry->connectionToken = focusedWindowToken;
             commandEntry->keyEntry = entry;
             postCommandLocked(std::move(commandEntry));
             return false; // wait for the command to run
@@ -2272,13 +2270,14 @@
 
 std::string InputDispatcher::dumpWindowForTouchOcclusion(const InputWindowInfo* info,
                                                          bool isTouchedWindow) const {
-    return StringPrintf(INDENT2 "* %stype=%s, package=%s/%" PRId32 ", mode=%s, alpha=%.2f, "
+    return StringPrintf(INDENT2 "* %stype=%s, package=%s/%" PRId32 ", id=%" PRId32
+                                ", mode=%s, alpha=%.2f, "
                                 "frame=[%" PRId32 ",%" PRId32 "][%" PRId32 ",%" PRId32
                                 "], touchableRegion=%s, window={%s}, applicationInfo=%s, "
                                 "flags={%s}, inputFeatures={%s}, hasToken=%s\n",
                         (isTouchedWindow) ? "[TOUCHED] " : "",
                         NamedEnum::string(info->type, "%" PRId32).c_str(),
-                        info->packageName.c_str(), info->ownerUid,
+                        info->packageName.c_str(), info->ownerUid, info->id,
                         toString(info->touchOcclusionMode).c_str(), info->alpha, info->frameLeft,
                         info->frameTop, info->frameRight, info->frameBottom,
                         dumpRegion(info->touchableRegion).c_str(), info->name.c_str(),
@@ -4488,19 +4487,19 @@
                     const sp<InputWindowHandle>& windowHandle = windowHandles[i];
                     const InputWindowInfo* windowInfo = windowHandle->getInfo();
 
-                    dump += StringPrintf(INDENT3 "%zu: name='%s', displayId=%d, "
+                    dump += StringPrintf(INDENT3 "%zu: name='%s', id=%" PRId32 ", displayId=%d, "
                                                  "portalToDisplayId=%d, paused=%s, focusable=%s, "
-                                                 "hasWallpaper=%s, visible=%s, "
+                                                 "hasWallpaper=%s, visible=%s, alpha=%.2f, "
                                                  "flags=%s, type=0x%08x, "
                                                  "frame=[%d,%d][%d,%d], globalScale=%f, "
                                                  "applicationInfo=%s, "
                                                  "touchableRegion=",
-                                         i, windowInfo->name.c_str(), windowInfo->displayId,
-                                         windowInfo->portalToDisplayId,
+                                         i, windowInfo->name.c_str(), windowInfo->id,
+                                         windowInfo->displayId, windowInfo->portalToDisplayId,
                                          toString(windowInfo->paused),
                                          toString(windowInfo->focusable),
                                          toString(windowInfo->hasWallpaper),
-                                         toString(windowInfo->visible),
+                                         toString(windowInfo->visible), windowInfo->alpha,
                                          windowInfo->flags.string().c_str(),
                                          static_cast<int32_t>(windowInfo->type),
                                          windowInfo->frameLeft, windowInfo->frameTop,
@@ -4920,14 +4919,13 @@
                                         connection.inputChannel->getName().c_str(),
                                         ns2ms(currentWait),
                                         oldestEntry->eventEntry->getDescription().c_str());
-
-    updateLastAnrStateLocked(getWindowHandleLocked(connection.inputChannel->getConnectionToken()),
-                             reason);
+    sp<IBinder> connectionToken = connection.inputChannel->getConnectionToken();
+    updateLastAnrStateLocked(getWindowHandleLocked(connectionToken), reason);
 
     std::unique_ptr<CommandEntry> commandEntry =
             std::make_unique<CommandEntry>(&InputDispatcher::doNotifyAnrLockedInterruptible);
     commandEntry->inputApplicationHandle = nullptr;
-    commandEntry->inputChannel = connection.inputChannel;
+    commandEntry->connectionToken = connectionToken;
     commandEntry->reason = std::move(reason);
     postCommandLocked(std::move(commandEntry));
 }
@@ -4941,7 +4939,6 @@
     std::unique_ptr<CommandEntry> commandEntry =
             std::make_unique<CommandEntry>(&InputDispatcher::doNotifyAnrLockedInterruptible);
     commandEntry->inputApplicationHandle = application;
-    commandEntry->inputChannel = nullptr;
     commandEntry->reason = std::move(reason);
     postCommandLocked(std::move(commandEntry));
 }
@@ -5010,10 +5007,8 @@
 }
 
 void InputDispatcher::doNotifyAnrLockedInterruptible(CommandEntry* commandEntry) {
-    sp<IBinder> token =
-            commandEntry->inputChannel ? commandEntry->inputChannel->getConnectionToken() : nullptr;
     mLock.unlock();
-
+    const sp<IBinder>& token = commandEntry->connectionToken;
     const std::chrono::nanoseconds timeoutExtension =
             mPolicy->notifyAnr(commandEntry->inputApplicationHandle, token, commandEntry->reason);
 
@@ -5076,9 +5071,7 @@
     mLock.unlock();
 
     android::base::Timer t;
-    sp<IBinder> token = commandEntry->inputChannel != nullptr
-            ? commandEntry->inputChannel->getConnectionToken()
-            : nullptr;
+    const sp<IBinder>& token = commandEntry->connectionToken;
     nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(token, &event, entry.policyFlags);
     if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
         ALOGW("Excessive delay in interceptKeyBeforeDispatching; took %s ms",
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index ea84835..17f37c3 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -3397,7 +3397,6 @@
 void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, bool down,
                                              bool hovering) {
     int32_t metaState = getContext()->getGlobalMetaState();
-    int32_t displayId = mViewport.displayId;
 
     if (down || hovering) {
         mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER);
@@ -3407,7 +3406,7 @@
     } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
         mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
     }
-    displayId = mPointerController->getDisplayId();
+    int32_t displayId = mPointerController->getDisplayId();
 
     float xCursorPosition;
     float yCursorPosition;
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index dc32003..40471b2 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -198,7 +198,7 @@
     std::condition_variable mNotifyAnr;
     std::chrono::nanoseconds mAnrTimeout = 0ms;
 
-    virtual void notifyConfigurationChanged(nsecs_t when) override {
+    void notifyConfigurationChanged(nsecs_t when) override {
         std::scoped_lock lock(mLock);
         mConfigurationChangedTime = when;
     }
@@ -213,17 +213,17 @@
         return mAnrTimeout;
     }
 
-    virtual void notifyInputChannelBroken(const sp<IBinder>&) override {}
+    void notifyInputChannelBroken(const sp<IBinder>&) override {}
 
-    virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
+    void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
 
-    virtual void notifyUntrustedTouch(const std::string& obscuringPackage) override {}
+    void notifyUntrustedTouch(const std::string& obscuringPackage) override {}
 
-    virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
+    void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
         *outConfig = mConfig;
     }
 
-    virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
+    bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
         std::scoped_lock lock(mLock);
         switch (inputEvent->getType()) {
             case AINPUT_EVENT_TYPE_KEY: {
@@ -241,22 +241,20 @@
         return true;
     }
 
-    virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
+    void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
 
-    virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
+    void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
 
-    virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*,
-                                                  uint32_t) override {
+    nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
         return 0;
     }
 
-    virtual bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t,
-                                      KeyEvent*) override {
+    bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
         return false;
     }
 
-    virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
-                              uint32_t policyFlags) override {
+    void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
+                      uint32_t policyFlags) override {
         std::scoped_lock lock(mLock);
         /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
          * essentially a passthrough for notifySwitch.
@@ -264,13 +262,11 @@
         mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
     }
 
-    virtual void pokeUserActivity(nsecs_t, int32_t) override {}
+    void pokeUserActivity(nsecs_t, int32_t) override {}
 
-    virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override {
-        return false;
-    }
+    bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override { return false; }
 
-    virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
+    void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
         std::scoped_lock lock(mLock);
         mOnPointerDownToken = newToken;
     }
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index c0b3d4d..1911a0a 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2495,12 +2495,6 @@
         transformedLayerBounds.bottom = tmp;
     }
 
-    // Input coordinates should be in display coordinate space.
-    info.frameLeft = transformedLayerBounds.left;
-    info.frameTop = transformedLayerBounds.top;
-    info.frameRight = transformedLayerBounds.right;
-    info.frameBottom = transformedLayerBounds.bottom;
-
     // Compute the correct transform to send to input. This will allow it to transform the
     // input coordinates from display space into window space. Therefore, it needs to use the
     // final layer frame to create the inverse transform. Since surface insets are added later,
@@ -2522,6 +2516,16 @@
     inputTransform.set(translation.x, translation.y);
     info.transform = inputTransform.inverse();
 
+    // We need to send the layer bounds cropped to the screenbounds since the layer can be cropped.
+    // The frame should be the area the user sees on screen since it's used for occlusion
+    // detection.
+    Rect screenBounds = Rect{mScreenBounds};
+    transformedLayerBounds.intersect(screenBounds, &transformedLayerBounds);
+    info.frameLeft = transformedLayerBounds.left;
+    info.frameTop = transformedLayerBounds.top;
+    info.frameRight = transformedLayerBounds.right;
+    info.frameBottom = transformedLayerBounds.bottom;
+
     // Position the touchable region relative to frame screen location and restrict it to frame
     // bounds.
     info.touchableRegion = inputTransform.transform(info.touchableRegion);
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index 1343375..47a4f42 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -90,6 +90,7 @@
     {
         std::lock_guard lock(mVsync.mutex);
         mVsync.lastCallbackTime = std::chrono::nanoseconds(vsyncTime);
+        mVsync.mScheduled = false;
     }
     mHandler->dispatchInvalidate(mVsync.tokenManager->generateTokenForPredictions(
                                          {targetWakeupTime, readyTime, vsyncTime}),
@@ -114,6 +115,10 @@
     ATRACE_CALL();
     std::lock_guard lock(mVsync.mutex);
     mVsync.workDuration = workDuration;
+    if (mVsync.mScheduled) {
+        mVsync.registration->schedule({mVsync.workDuration.get().count(), /*readyDuration=*/0,
+                                       mVsync.lastCallbackTime.count()});
+    }
 }
 
 void MessageQueue::waitMessage() {
@@ -147,13 +152,10 @@
     if (mEvents) {
         mEvents->requestNextVsync();
     } else {
-        const auto [workDuration, lastVsyncCallback] = [&] {
-            std::lock_guard lock(mVsync.mutex);
-            std::chrono::nanoseconds mWorkDurationNanos = mVsync.workDuration;
-            return std::make_pair(mWorkDurationNanos.count(), mVsync.lastCallbackTime.count());
-        }();
-
-        mVsync.registration->schedule({workDuration, /*readyDuration=*/0, lastVsyncCallback});
+        std::lock_guard lock(mVsync.mutex);
+        mVsync.mScheduled = true;
+        mVsync.registration->schedule({mVsync.workDuration.get().count(), /*readyDuration=*/0,
+                                       mVsync.lastCallbackTime.count()});
     }
 }
 
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h
index 139b38e..99ce3a6 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.h
+++ b/services/surfaceflinger/Scheduler/MessageQueue.h
@@ -109,6 +109,7 @@
         TracedOrdinal<std::chrono::nanoseconds> workDuration
                 GUARDED_BY(mutex) = {"VsyncWorkDuration-sf", std::chrono::nanoseconds(0)};
         std::chrono::nanoseconds lastCallbackTime GUARDED_BY(mutex) = std::chrono::nanoseconds{0};
+        bool mScheduled GUARDED_BY(mutex) = false;
         TracedOrdinal<int> value = {"VSYNC-sf", 0};
     };
 
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 7d97e72..150f925 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -48,7 +48,7 @@
     }
 }
 
-std::string RefreshRateConfigs::Policy::toString() {
+std::string RefreshRateConfigs::Policy::toString() const {
     return base::StringPrintf("default config ID: %d, allowGroupSwitching = %d"
                               ", primary range: [%.2f %.2f], app request range: [%.2f %.2f]",
                               defaultConfig.value(), allowGroupSwitching, primaryRange.min,
@@ -433,10 +433,12 @@
     // defaultConfig must be a valid config, and within the given refresh rate range.
     auto iter = mRefreshRates.find(policy.defaultConfig);
     if (iter == mRefreshRates.end()) {
+        ALOGE("Default config is not found.");
         return false;
     }
     const RefreshRate& refreshRate = *iter->second;
     if (!refreshRate.inPolicy(policy.primaryRange.min, policy.primaryRange.max)) {
+        ALOGE("Default config is not in the primary range.");
         return false;
     }
     return policy.appRequestRange.min <= policy.primaryRange.min &&
@@ -446,6 +448,7 @@
 status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) {
     std::lock_guard lock(mLock);
     if (!isPolicyValid(policy)) {
+        ALOGE("Invalid refresh rate policy: %s", policy.toString().c_str());
         return BAD_VALUE;
     }
     Policy previousPolicy = *getCurrentPolicyLocked();
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 5cf7d07..8ff92a0 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -166,7 +166,7 @@
         }
 
         bool operator!=(const Policy& other) const { return !(*this == other); }
-        std::string toString();
+        std::string toString() const;
     };
 
     // Return code set*Policy() to indicate the current policy is unchanged.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1119fce..b8b2fbc 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3787,9 +3787,7 @@
     }
     if (what & layer_state_t::eFrameTimelineVsyncChanged) {
         layer->setFrameTimelineVsyncForTransaction(s.frameTimelineVsyncId, postTime);
-    } else {
-        // TODO (b/171252403) We are calling this too much, potentially triggering
-        // unnecessary work
+    } else if (frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) {
         layer->setFrameTimelineVsyncForTransaction(frameTimelineVsyncId, postTime);
     }
     if (what & layer_state_t::eFixedTransformHintChanged) {
@@ -5667,7 +5665,8 @@
         });
     }
 
-    const uint32_t usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE |
+    const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER |
+            GRALLOC_USAGE_HW_TEXTURE |
             (hasProtectedLayer && allowProtected && supportsProtected
                      ? GRALLOC_USAGE_PROTECTED
                      : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
diff --git a/services/surfaceflinger/TEST_MAPPING b/services/surfaceflinger/TEST_MAPPING
index e530ff9..cab33ae 100644
--- a/services/surfaceflinger/TEST_MAPPING
+++ b/services/surfaceflinger/TEST_MAPPING
@@ -5,14 +5,6 @@
     },
     {
       "name": "libcompositionengine_test"
-    },
-    {
-      "name": "SurfaceFlinger_test"
-    }
-  ],
-  "postsubmit": [
-    {
-      "name": "sffakehwc_test"
     }
   ]
 }
diff --git a/services/surfaceflinger/TimeStats/Android.bp b/services/surfaceflinger/TimeStats/Android.bp
index 3901757..0a23da2 100644
--- a/services/surfaceflinger/TimeStats/Android.bp
+++ b/services/surfaceflinger/TimeStats/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libtimestats",
     srcs: [
         "TimeStats.cpp",
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/Android.bp b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
index b937f41..fae4e94 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
+++ b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libtimestats_proto",
     export_include_dirs: ["include"],
 
@@ -30,3 +30,15 @@
         "-Wno-unused-parameter",
     ],
 }
+
+// ====  java host library for timestats proto  ===========================
+// Note timestats is deprecated and is only used for legacy tests
+java_library_host {
+    name: "host-timestats-proto",
+    srcs: [
+        "timestats.proto",
+    ],
+    proto: {
+        type: "full",
+    },
+}
diff --git a/services/surfaceflinger/TracedOrdinal.h b/services/surfaceflinger/TracedOrdinal.h
index 49cf80c..eee4bec 100644
--- a/services/surfaceflinger/TracedOrdinal.h
+++ b/services/surfaceflinger/TracedOrdinal.h
@@ -57,7 +57,9 @@
         trace();
     }
 
-    operator T() const { return mData; }
+    T get() const { return mData; }
+
+    operator T() const { return get(); }
 
     TracedOrdinal& operator=(T other) {
         mData = other;
diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp
index 0a73b23..e2a28a2 100644
--- a/services/surfaceflinger/layerproto/Android.bp
+++ b/services/surfaceflinger/layerproto/Android.bp
@@ -1,5 +1,5 @@
-cc_defaults {
-    name: "liblayers_proto_defaults",
+cc_library {
+    name: "liblayers_proto",
     export_include_dirs: ["include"],
 
     srcs: [
@@ -19,7 +19,7 @@
     proto: {
         export_proto_headers: true,
     },
-    
+
     cppflags: [
         "-Werror",
         "-Wno-unused-parameter",
@@ -35,20 +35,6 @@
     ],
 }
 
-cc_library_shared {
-    name: "liblayers_proto",
-    defaults: [
-        "liblayers_proto_defaults",
-    ],
-}
-
-cc_library_static {
-    name: "liblayers_proto_static",
-    defaults: [
-        "liblayers_proto_defaults",
-    ],
-}
-
 java_library_static {
     name: "layersprotosnano",
     host_supported: true,
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 02b4308..e8b24b4 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -46,7 +46,7 @@
     data: ["SurfaceFlinger_test.filter"],
     static_libs: [
         "libtrace_proto",
-        "liblayers_proto_static",
+        "liblayers_proto",
         "android.hardware.graphics.composer@2.1",
     ],
     shared_libs: [
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 8097a88..18f3745 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -14,7 +14,7 @@
 
 cc_test {
     name: "libsurfaceflinger_unittest",
-    defaults: ["libsurfaceflinger_defaults"],
+    defaults: ["surfaceflinger_defaults"],
     test_suites: ["device-tests"],
     sanitize: {
         // Using the address sanitizer not only helps uncover issues in the code
@@ -94,22 +94,65 @@
         "mock/system/window/MockNativeWindow.cpp",
     ],
     static_libs: [
-        "libgmock",
-        "libcompositionengine",
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.2",
+        "android.hardware.graphics.composer@2.3",
+        "android.hardware.graphics.composer@2.4",
+        "android.hardware.power@1.0",
+        "android.hardware.power@1.1",
+        "android.hardware.power@1.2",
+        "android.hardware.power@1.3",
         "libcompositionengine_mocks",
+        "libcompositionengine",
         "libframetimeline",
+        "libgmock",
         "libgui_mocks",
+        "liblayers_proto",
         "libperfetto_client_experimental",
         "librenderengine_mocks",
+        "librenderengine",
+        "libserviceutils",
+        "libtimestats",
+        "libtimestats_proto",
+        "libtrace_proto",
         "perfetto_trace_protos",
     ],
     shared_libs: [
+        "android.hardware.configstore-utils",
+        "android.hardware.configstore@1.0",
+        "android.hardware.configstore@1.1",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.allocator@3.0",
+        "android.hardware.graphics.common@1.2",
+        "android.hardware.power-cpp",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "libEGL",
+        "libfmq",
+        "libGLESv1_CM",
+        "libGLESv2",
+        "libgui",
+        "libhidlbase",
+        "libinput",
+        "liblog",
+        "libnativewindow",
+        "libprocessgroup",
+        "libprotobuf-cpp-lite",
         "libprotoutil",
+        "libstatslog",
         "libstatssocket",
-        "libtimestats",
-        "libtimestats_proto",
+        "libSurfaceFlingerProp",
+        "libsync",
+        "libui",
+        "libutils",
+        "libstatspull",
     ],
     header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+        "android.hardware.graphics.composer@2.2-command-buffer",
+        "android.hardware.graphics.composer@2.3-command-buffer",
+        "android.hardware.graphics.composer@2.4-command-buffer",
         "libsurfaceflinger_headers",
     ],
 }
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.cpp b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.cpp
index 251ab36..7de1872 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.cpp
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.cpp
@@ -18,6 +18,7 @@
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wconversion"
 
+#define LOG_TAG "MockComposer"
 #include "mock/DisplayHardware/MockComposer.h"
 
 namespace android::Hwc2::mock {
diff --git a/services/vibratorservice/benchmarks/VibratorHalControllerBenchmarks.cpp b/services/vibratorservice/benchmarks/VibratorHalControllerBenchmarks.cpp
index 6589f74..0acff06 100644
--- a/services/vibratorservice/benchmarks/VibratorHalControllerBenchmarks.cpp
+++ b/services/vibratorservice/benchmarks/VibratorHalControllerBenchmarks.cpp
@@ -302,11 +302,13 @@
         }
 
         std::vector<hardware::vibrator::Effect> supported = effectsResult.value();
+        b->ArgNames({"Effect", "Strength"});
+
         if (supported.empty()) {
+            b->Args({static_cast<long>(-1), static_cast<long>(-1)});
             return;
         }
 
-        b->ArgNames({"Effect", "Strength"});
         for (const auto& effect : enum_range<hardware::vibrator::Effect>()) {
             if (std::find(supported.begin(), supported.end(), effect) == supported.end()) {
                 continue;
@@ -318,6 +320,8 @@
     }
 
 protected:
+    bool hasArgs(const State& state) const { return this->getOtherArg(state, 0) >= 0; }
+
     auto getEffect(const State& state) const {
         return static_cast<hardware::vibrator::Effect>(this->getOtherArg(state, 0));
     }
@@ -333,6 +337,9 @@
     if (!hasCapabilities(result, vibrator::Capabilities::ALWAYS_ON_CONTROL, state)) {
         return;
     }
+    if (!hasArgs(state)) {
+        return;
+    }
 
     int32_t id = 1;
     auto effect = getEffect(state);
@@ -354,6 +361,9 @@
     if (!hasCapabilities(result, vibrator::Capabilities::ALWAYS_ON_CONTROL, state)) {
         return;
     }
+    if (!hasArgs(state)) {
+        return;
+    }
 
     int32_t id = 1;
     auto effect = getEffect(state);
@@ -370,6 +380,10 @@
 });
 
 BENCHMARK_WRAPPER(VibratorEffectsBench, performEffect, {
+    if (!hasArgs(state)) {
+        return;
+    }
+
     auto effect = getEffect(state);
     auto strength = getStrength(state);
     auto callback = []() {};
@@ -394,11 +408,13 @@
         }
 
         std::vector<hardware::vibrator::CompositePrimitive> supported = primitivesResult.value();
+        b->ArgNames({"Primitive"});
+
         if (supported.empty()) {
+            b->Args({static_cast<long>(-1)});
             return;
         }
 
-        b->ArgNames({"Primitive"});
         for (const auto& primitive : enum_range<hardware::vibrator::CompositePrimitive>()) {
             if (std::find(supported.begin(), supported.end(), primitive) == supported.end()) {
                 continue;
@@ -411,6 +427,8 @@
     }
 
 protected:
+    bool hasArgs(const State& state) const { return this->getOtherArg(state, 0) >= 0; }
+
     auto getPrimitive(const State& state) const {
         return static_cast<hardware::vibrator::CompositePrimitive>(this->getOtherArg(state, 0));
     }
@@ -422,6 +440,9 @@
     if (!hasCapabilities(result, vibrator::Capabilities::COMPOSE_EFFECTS, state)) {
         return;
     }
+    if (!hasArgs(state)) {
+        return;
+    }
 
     hardware::vibrator::CompositeEffect effect;
     effect.primitive = getPrimitive(state);