Merge "RE: Add a test verifying we've compiled a min no of shaders" into tm-dev
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 397d432..b4aa88e 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -2976,13 +2976,15 @@
 // Dumps the contents of a profile file, using pkgname's dex files for pretty
 // printing the result.
 binder::Status InstalldNativeService::dumpProfiles(int32_t uid, const std::string& packageName,
-        const std::string& profileName, const std::string& codePath, bool* _aidl_return) {
+                                                   const std::string& profileName,
+                                                   const std::string& codePath,
+                                                   bool dumpClassesAndMethods, bool* _aidl_return) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
     CHECK_ARGUMENT_PATH(codePath);
     LOCK_PACKAGE();
 
-    *_aidl_return = dump_profiles(uid, packageName, profileName, codePath);
+    *_aidl_return = dump_profiles(uid, packageName, profileName, codePath, dumpClassesAndMethods);
     return ok();
 }
 
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 0432222..521afc3 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -134,7 +134,8 @@
     binder::Status mergeProfiles(int32_t uid, const std::string& packageName,
             const std::string& profileName, int* _aidl_return);
     binder::Status dumpProfiles(int32_t uid, const std::string& packageName,
-            const std::string& profileName, const std::string& codePath, bool* _aidl_return);
+                                const std::string& profileName, const std::string& codePath,
+                                bool dumpClassesAndMethods, bool* _aidl_return);
     binder::Status copySystemProfile(const std::string& systemProfile,
             int32_t uid, const std::string& packageName, const std::string& profileName,
             bool* _aidl_return);
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index db03411..9ad853b 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -77,7 +77,7 @@
 
     int mergeProfiles(int uid, @utf8InCpp String packageName, @utf8InCpp String profileName);
     boolean dumpProfiles(int uid, @utf8InCpp String packageName, @utf8InCpp String  profileName,
-            @utf8InCpp String codePath);
+            @utf8InCpp String codePath, boolean dumpClassesAndMethods);
     boolean copySystemProfile(@utf8InCpp String systemProfile, int uid,
             @utf8InCpp String packageName, @utf8InCpp String profileName);
     void clearAppProfiles(@utf8InCpp String packageName, @utf8InCpp String profileName);
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 894c7d3..ebb7891 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -624,12 +624,15 @@
                   /*for_boot_image*/false);
     }
 
-    void SetupDump(const std::vector<unique_fd>& profiles_fd,
-                   const unique_fd& reference_profile_fd,
+    void SetupDump(const std::vector<unique_fd>& profiles_fd, const unique_fd& reference_profile_fd,
                    const std::vector<std::string>& dex_locations,
-                   const std::vector<unique_fd>& apk_fds,
+                   const std::vector<unique_fd>& apk_fds, bool dump_classes_and_methods,
                    const unique_fd& output_fd) {
-        AddArg("--dump-only");
+        if (dump_classes_and_methods) {
+            AddArg("--dump-classes-and-methods");
+        } else {
+            AddArg("--dump-only");
+        }
         AddArg(StringPrintf("--dump-output-to-fd=%d", output_fd.get()));
         SetupArgs(profiles_fd,
                   reference_profile_fd,
@@ -772,7 +775,7 @@
 }
 
 bool dump_profiles(int32_t uid, const std::string& pkgname, const std::string& profile_name,
-        const std::string& code_path) {
+                   const std::string& code_path, bool dump_classes_and_methods) {
     std::vector<unique_fd> profile_fds;
     unique_fd reference_profile_fd;
     std::string out_file_name = StringPrintf("/data/misc/profman/%s-%s.txt",
@@ -808,7 +811,8 @@
 
 
     RunProfman profman_dump;
-    profman_dump.SetupDump(profile_fds, reference_profile_fd, dex_locations, apk_fds, output_fd);
+    profman_dump.SetupDump(profile_fds, reference_profile_fd, dex_locations, apk_fds,
+                           dump_classes_and_methods, output_fd);
     pid_t pid = fork();
     if (pid == 0) {
         /* child -- drop privileges before continuing */
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index f7af929..5cf402c 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -88,10 +88,8 @@
                              const std::string& profile_name,
                              const std::string& classpath);
 
-bool dump_profiles(int32_t uid,
-                   const std::string& pkgname,
-                   const std::string& profile_name,
-                   const std::string& code_path);
+bool dump_profiles(int32_t uid, const std::string& pkgname, const std::string& profile_name,
+                   const std::string& code_path, bool dump_classes_and_methods);
 
 bool copy_system_profile(const std::string& system_profile,
                          uid_t packageUid,
diff --git a/include/android/input.h b/include/android/input.h
index fb5e204..38b27bc 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -810,7 +810,7 @@
 /**
  * Constants that identify different gesture classification types.
  */
-enum {
+enum AMotionClassification : uint32_t {
     /**
      * Classification constant: None.
      *
@@ -820,7 +820,8 @@
     /**
      * Classification constant: Ambiguous gesture.
      *
-     * The user's intent with respect to the current event stream is not yet determined.
+     * The user's intent with respect to the current event stream is not yet determined. Events
+     * starting in AMBIGUOUS_GESTURE will eventually resolve into either DEEP_PRESS or NONE.
      * Gestural actions, such as scrolling, should be inhibited until the classification resolves
      * to another value or the event stream ends.
      */
@@ -1357,8 +1358,17 @@
  * Get the action button for the motion event. Returns a valid action button when the
  * event is associated with a button press or button release action. For other actions
  * the return value is undefined.
+ *
+ * @see #AMOTION_EVENT_BUTTON_PRIMARY
+ * @see #AMOTION_EVENT_BUTTON_SECONDARY
+ * @see #AMOTION_EVENT_BUTTON_TERTIARY
+ * @see #AMOTION_EVENT_BUTTON_BACK
+ * @see #AMOTION_EVENT_BUTTON_FORWARD
+ * @see #AMOTION_EVENT_BUTTON_STYLUS_PRIMARY
+ * @see #AMOTION_EVENT_BUTTON_STYLUS_SECONDARY
  */
-int32_t AMotionEvent_getActionButton(const AInputEvent* motion_event);
+int32_t AMotionEvent_getActionButton(const AInputEvent* motion_event)
+        __INTRODUCED_IN(__ANDROID_API_T__);
 
 /**
  * Returns the classification for the current gesture.
@@ -1368,7 +1378,8 @@
  * @see #AMOTION_EVENT_CLASSIFICATION_AMBIGUOUS_GESTURE
  * @see #AMOTION_EVENT_CLASSIFICATION_DEEP_PRESS
 */
-int32_t AMotionEvent_getClassification(const AInputEvent* motion_event);
+int32_t AMotionEvent_getClassification(const AInputEvent* motion_event)
+        __INTRODUCED_IN(__ANDROID_API_T__);
 
 /**
  * Creates a native AInputEvent* object that is a copy of the specified Java
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index 1bc8464..a579442 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -35,9 +35,9 @@
 class RpcTransport;
 class FdTrigger;
 
-constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_NEXT = 0;
+constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_NEXT = 1;
 constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL = 0xF0000000;
-constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION = RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL;
+constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION = 0;
 
 /**
  * This represents a session (group of connections) between a client
diff --git a/libs/binder/tests/binderRpcWireProtocolTest.cpp b/libs/binder/tests/binderRpcWireProtocolTest.cpp
index a807afa..4fcf42d 100644
--- a/libs/binder/tests/binderRpcWireProtocolTest.cpp
+++ b/libs/binder/tests/binderRpcWireProtocolTest.cpp
@@ -237,8 +237,9 @@
     checkRepr(kCurrentRepr, RPC_WIRE_PROTOCOL_VERSION);
 }
 
-static_assert(RPC_WIRE_PROTOCOL_VERSION == RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL,
-              "you better update this test!");
+static_assert(RPC_WIRE_PROTOCOL_VERSION == 0,
+              "If the binder wire protocol is updated, this test should test additional versions. "
+              "The binder wire protocol should only be updated on upstream AOSP.");
 
 TEST(RpcWire, ReleaseBranchHasFrozenRpcWireProtocol) {
     if (RPC_WIRE_PROTOCOL_VERSION == RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL) {
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 1d4fc1f..5d7874a 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -103,9 +103,6 @@
 
             sanitize: {
                 misc_undefined: ["integer"],
-                diag: {
-                    misc_undefined: ["integer"],
-                },
             },
         },
         host: {
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 99d3932..a4cee8f 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -292,6 +292,8 @@
 void SkiaGLRenderEngine::SkSLCacheMonitor::store(const SkData& key, const SkData& data,
                                                  const SkString& description) {
     mShadersCachedSinceLastCall++;
+    mTotalShadersCompiled++;
+    ATRACE_FORMAT("SF cache: %i shaders", mTotalShadersCompiled);
 }
 
 int SkiaGLRenderEngine::reportShadersCompiled() {
@@ -1184,11 +1186,15 @@
                 static constexpr float kInverseGamma22 = 1.f / 2.2f;
                 const auto gammaCorrectedDimmingRatio =
                         std::pow(layerDimmingRatio, kInverseGamma22);
-                const auto dimmingMatrix =
+                auto dimmingMatrix =
                         mat4::scale(vec4(gammaCorrectedDimmingRatio, gammaCorrectedDimmingRatio,
                                          gammaCorrectedDimmingRatio, 1.f));
-                paint.setColorFilter(SkColorFilters::Matrix(
-                        toSkColorMatrix(display.colorTransform * dimmingMatrix)));
+
+                const auto colorFilter =
+                        SkColorFilters::Matrix(toSkColorMatrix(std::move(dimmingMatrix)));
+                paint.setColorFilter(displayColorTransform
+                                             ? displayColorTransform->makeComposed(colorFilter)
+                                             : colorFilter);
             } else {
                 paint.setColorFilter(displayColorTransform);
             }
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index bef2cd0..5ef9944 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -181,6 +181,7 @@
 
     private:
         int mShadersCachedSinceLastCall = 0;
+        int mTotalShadersCompiled = 0;
     };
 
     SkSLCacheMonitor mSkSLCacheMonitor;
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index ddcd208..7c70a74 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -91,6 +91,14 @@
                 sign(linear.b) * OETF_sRGB(linear.b));
 }
 
+// clang-format off
+// Converts red channels to green channels, and zeroes out an existing green channel.
+static const auto kRemoveGreenAndMoveRedToGreenMat4 = mat4(0, 1, 0, 0,
+                                                           0, 0, 0, 0,
+                                                           0, 0, 1, 0,
+                                                           0, 0, 0, 1);
+// clang-format on
+
 } // namespace
 
 class RenderEngineFactory {
@@ -2557,6 +2565,133 @@
     expectBufferColor(Rect(2, 0, 3, 1), 122, 0, 0, 255, 1);
 }
 
+TEST_P(RenderEngineTest, testDimming_inGammaSpace_withDisplayColorTransform) {
+    if (GetParam()->type() == renderengine::RenderEngine::RenderEngineType::GLES) {
+        GTEST_SKIP();
+    }
+    initializeRenderEngine();
+
+    const ui::Dataspace dataspace = static_cast<ui::Dataspace>(ui::Dataspace::STANDARD_BT709 |
+                                                               ui::Dataspace::TRANSFER_GAMMA2_2 |
+                                                               ui::Dataspace::RANGE_FULL);
+
+    const auto displayRect = Rect(3, 1);
+    const renderengine::DisplaySettings display{
+            .physicalDisplay = displayRect,
+            .clip = displayRect,
+            .outputDataspace = dataspace,
+            .colorTransform = kRemoveGreenAndMoveRedToGreenMat4,
+            .targetLuminanceNits = 1000.f,
+            .dimmingStage = aidl::android::hardware::graphics::composer3::DimmingStage::GAMMA_OETF,
+    };
+
+    const auto greenBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 255, 0, 255));
+    const auto blueBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 0, 255, 255));
+    const auto redBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(255, 0, 0, 255));
+
+    const renderengine::LayerSettings greenLayer{
+            .geometry.boundaries = FloatRect(0.f, 0.f, 1.f, 1.f),
+            .source =
+                    renderengine::PixelSource{
+                            .buffer =
+                                    renderengine::Buffer{
+                                            .buffer = greenBuffer,
+                                            .usePremultipliedAlpha = true,
+                                    },
+                    },
+            .alpha = 1.0f,
+            .sourceDataspace = dataspace,
+            .whitePointNits = 200.f,
+    };
+
+    const renderengine::LayerSettings redLayer{
+            .geometry.boundaries = FloatRect(1.f, 0.f, 2.f, 1.f),
+            .source =
+                    renderengine::PixelSource{
+                            .buffer =
+                                    renderengine::Buffer{
+                                            .buffer = redBuffer,
+                                            .usePremultipliedAlpha = true,
+                                    },
+                    },
+            .alpha = 1.0f,
+            .sourceDataspace = dataspace,
+            // When the white point is not set for a layer, just ignore it and treat it as the same
+            // as the max layer
+            .whitePointNits = -1.f,
+    };
+
+    std::vector<renderengine::LayerSettings> layers{greenLayer, redLayer};
+    invokeDraw(display, layers);
+
+    expectBufferColor(Rect(1, 1), 0, 0, 0, 255, 1);
+    expectBufferColor(Rect(1, 0, 2, 1), 0, 122, 0, 255, 1);
+}
+
+TEST_P(RenderEngineTest, testDimming_inGammaSpace_withDisplayColorTransform_deviceHandles) {
+    if (GetParam()->type() == renderengine::RenderEngine::RenderEngineType::GLES) {
+        GTEST_SKIP();
+    }
+    initializeRenderEngine();
+
+    const ui::Dataspace dataspace = static_cast<ui::Dataspace>(ui::Dataspace::STANDARD_BT709 |
+                                                               ui::Dataspace::TRANSFER_GAMMA2_2 |
+                                                               ui::Dataspace::RANGE_FULL);
+
+    const auto displayRect = Rect(3, 1);
+    const renderengine::DisplaySettings display{
+            .physicalDisplay = displayRect,
+            .clip = displayRect,
+            .outputDataspace = dataspace,
+            .colorTransform = kRemoveGreenAndMoveRedToGreenMat4,
+            .deviceHandlesColorTransform = true,
+            .targetLuminanceNits = 1000.f,
+            .dimmingStage = aidl::android::hardware::graphics::composer3::DimmingStage::GAMMA_OETF,
+    };
+
+    const auto greenBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 255, 0, 255));
+    const auto blueBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 0, 255, 255));
+    const auto redBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(255, 0, 0, 255));
+
+    const renderengine::LayerSettings greenLayer{
+            .geometry.boundaries = FloatRect(0.f, 0.f, 1.f, 1.f),
+            .source =
+                    renderengine::PixelSource{
+                            .buffer =
+                                    renderengine::Buffer{
+                                            .buffer = greenBuffer,
+                                            .usePremultipliedAlpha = true,
+                                    },
+                    },
+            .alpha = 1.0f,
+            .sourceDataspace = dataspace,
+            .whitePointNits = 200.f,
+    };
+
+    const renderengine::LayerSettings redLayer{
+            .geometry.boundaries = FloatRect(1.f, 0.f, 2.f, 1.f),
+            .source =
+                    renderengine::PixelSource{
+                            .buffer =
+                                    renderengine::Buffer{
+                                            .buffer = redBuffer,
+                                            .usePremultipliedAlpha = true,
+                                    },
+                    },
+            .alpha = 1.0f,
+            .sourceDataspace = dataspace,
+            // When the white point is not set for a layer, just ignore it and treat it as the same
+            // as the max layer
+            .whitePointNits = -1.f,
+    };
+
+    std::vector<renderengine::LayerSettings> layers{greenLayer, redLayer};
+    invokeDraw(display, layers);
+
+    expectBufferColor(Rect(1, 1), 0, 122, 0, 255, 1);
+    expectBufferColor(Rect(1, 0, 2, 1), 122, 0, 0, 255, 1);
+}
+
 TEST_P(RenderEngineTest, testDimming_withoutTargetLuminance) {
     initializeRenderEngine();
     if (GetParam()->type() == renderengine::RenderEngine::RenderEngineType::GLES) {
@@ -2796,10 +2931,7 @@
             // pure red to pure green. That will occur when the R8 buffer is
             // 255. When the R8 buffer is 0, it will still change to black, as
             // with r8_behaves_as_mask.
-            .colorTransform = mat4(0, 1, 0, 0,
-                                   0, 0, 0, 0,
-                                   0, 0, 1, 0,
-                                   0, 0, 0, 1),
+            .colorTransform = kRemoveGreenAndMoveRedToGreenMat4,
             .deviceHandlesColorTransform = false,
     };
 
diff --git a/libs/ui/DeviceProductInfo.cpp b/libs/ui/DeviceProductInfo.cpp
index 4d6ce43..04d9d3c 100644
--- a/libs/ui/DeviceProductInfo.cpp
+++ b/libs/ui/DeviceProductInfo.cpp
@@ -57,7 +57,7 @@
 }
 
 void DeviceProductInfo::dump(std::string& result) const {
-    StringAppendF(&result, "{name=%s, ", name.c_str());
+    StringAppendF(&result, "{name=\"%s\", ", name.c_str());
     StringAppendF(&result, "manufacturerPnpId=%s, ", manufacturerPnpId.data());
     StringAppendF(&result, "productId=%s, ", productId.c_str());
 
diff --git a/libs/ui/Gralloc4.cpp b/libs/ui/Gralloc4.cpp
index 4f950b8..f6ab7b2 100644
--- a/libs/ui/Gralloc4.cpp
+++ b/libs/ui/Gralloc4.cpp
@@ -1245,8 +1245,9 @@
         } else {
             if (importBuffers) {
                 for (uint32_t i = 0; i < bufferCount; i++) {
-                    error = mMapper.importBuffer(makeFromAidl(result.buffers[i]),
-                                                 &outBufferHandles[i]);
+                    auto handle = makeFromAidl(result.buffers[i]);
+                    error = mMapper.importBuffer(handle, &outBufferHandles[i]);
+                    native_handle_delete(handle);
                     if (error != NO_ERROR) {
                         for (uint32_t j = 0; j < i; j++) {
                             mMapper.freeBuffer(outBufferHandles[j]);
diff --git a/libs/vr/libbroadcastring/Android.bp b/libs/vr/libbroadcastring/Android.bp
index d4538f1..fa449ae 100644
--- a/libs/vr/libbroadcastring/Android.bp
+++ b/libs/vr/libbroadcastring/Android.bp
@@ -9,7 +9,7 @@
 
 cc_library_static {
     name: "libbroadcastring",
-    clang: true,
+
     cflags: [
         "-Wall",
         "-Wextra",
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index c1934ff..637b1cb 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -1657,9 +1657,8 @@
 
         dispatchPointerUsage(when, readTime, policyFlags, pointerUsage);
     } else {
-        updateTouchSpots();
-
         if (!mCurrentMotionAborted) {
+            updateTouchSpots();
             dispatchButtonRelease(when, readTime, policyFlags);
             dispatchHoverExit(when, readTime, policyFlags);
             dispatchTouches(when, readTime, policyFlags);
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/ProjectionSpace.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/ProjectionSpace.h
index a63145a..49013e0 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/ProjectionSpace.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/ProjectionSpace.h
@@ -120,16 +120,16 @@
 
 } // namespace compositionengine
 
-inline std::string to_string(const android::compositionengine::ProjectionSpace& space) {
-    return android::base::
-            StringPrintf("ProjectionSpace(bounds = %s, content = %s, orientation = %s)",
-                         to_string(space.getBoundsAsRect()).c_str(),
-                         to_string(space.getContent()).c_str(), toCString(space.getOrientation()));
+inline std::string to_string(const compositionengine::ProjectionSpace& space) {
+    return base::StringPrintf("ProjectionSpace{bounds=%s, content=%s, orientation=%s}",
+                              to_string(space.getBoundsAsRect()).c_str(),
+                              to_string(space.getContent()).c_str(),
+                              toCString(space.getOrientation()));
 }
 
 // Defining PrintTo helps with Google Tests.
-inline void PrintTo(const android::compositionengine::ProjectionSpace& space, ::std::ostream* os) {
+inline void PrintTo(const compositionengine::ProjectionSpace& space, std::ostream* os) {
     *os << to_string(space);
 }
 
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
index 5fa0d67..61be983 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
@@ -155,6 +155,8 @@
         SUCCESS = 1,
         // Composition strategy prediction failed for this frame.
         FAIL = 2,
+
+        ftl_last = FAIL
     };
 
     CompositionStrategyPredictionState strategyPrediction =
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
index d64d676..ecd432f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -60,7 +60,7 @@
     std::vector<LayerFE::LayerSettings> getOverrideCompositionList() const override;
 
     void dump(std::string&) const override;
-    virtual FloatRect calculateOutputSourceCrop() const;
+    virtual FloatRect calculateOutputSourceCrop(uint32_t internalDisplayRotationFlags) const;
     virtual Rect calculateOutputDisplayFrame() const;
     virtual uint32_t calculateOutputRelativeBufferTransform(
             uint32_t internalDisplayRotationFlags) const;
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index f545886..b79b46b 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -131,15 +131,11 @@
 }
 
 void Display::dump(std::string& out) const {
-    using android::base::StringAppendF;
+    const char* const type = isVirtual() ? "virtual" : "physical";
+    base::StringAppendF(&out, "Display %s (%s, \"%s\")", to_string(mId).c_str(), type,
+                        getName().c_str());
 
-    StringAppendF(&out, "   Composition Display State: [\"%s\"]", getName().c_str());
-
-    out.append("\n   ");
-    dumpVal(out, "isVirtual", isVirtual());
-    dumpVal(out, "DisplayId", to_string(mId));
-    out.append("\n");
-
+    out.append("\n   Composition Display State:\n");
     Output::dumpBase(out);
 }
 
diff --git a/services/surfaceflinger/CompositionEngine/src/DumpHelpers.cpp b/services/surfaceflinger/CompositionEngine/src/DumpHelpers.cpp
index 01c368d..290c710 100644
--- a/services/surfaceflinger/CompositionEngine/src/DumpHelpers.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/DumpHelpers.cpp
@@ -89,7 +89,6 @@
 
 void dumpVal(std::string& out, const char* name, const ui::Transform& transform) {
     transform.dump(out, name);
-    out.append(" ");
 }
 
 void dumpVal(std::string& out, const char* name, const mat4& tr) {
@@ -99,7 +98,7 @@
                   "[%0.3f,%0.3f,%0.3f,%0.3f]"
                   "[%0.3f,%0.3f,%0.3f,%0.3f]"
                   "[%0.3f,%0.3f,%0.3f,%0.3f]"
-                  "[%0.3f,%0.3f,%0.3f,%0.3f]]",
+                  "[%0.3f,%0.3f,%0.3f,%0.3f]] ",
                   name,
                   tr[0][0], tr[1][0], tr[2][0], tr[3][0],
                   tr[0][1], tr[1][1], tr[2][1], tr[3][1],
@@ -109,9 +108,9 @@
 }
 
 void dumpVal(std::string& out, const char* name, const StretchEffect& effect) {
-    StringAppendF(&out, "%s={ width =%f, height = %f, vec=(%f, %f), max=(%f, %f) } ", name,
-                  effect.width, effect.height,
-                  effect.vectorX, effect.vectorY, effect.maxAmountX, effect.maxAmountY);
+    StringAppendF(&out, "%s={width=%f, height=%f, vec=(%f, %f), max=(%f, %f)} ", name, effect.width,
+                  effect.height, effect.vectorX, effect.vectorY, effect.maxAmountX,
+                  effect.maxAmountY);
 }
 
 } // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 004e071..ec86731 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -294,17 +294,15 @@
 }
 
 void Output::dump(std::string& out) const {
-    using android::base::StringAppendF;
-
-    StringAppendF(&out, "   Composition Output State: [\"%s\"]", mName.c_str());
-
-    out.append("\n   ");
+    base::StringAppendF(&out, "Output \"%s\"", mName.c_str());
+    out.append("\n   Composition Output State:\n");
 
     dumpBase(out);
 }
 
 void Output::dumpBase(std::string& out) const {
     dumpState(out);
+    out += '\n';
 
     if (mDisplayColorProfile) {
         mDisplayColorProfile->dump(out);
@@ -312,13 +310,15 @@
         out.append("    No display color profile!\n");
     }
 
+    out += '\n';
+
     if (mRenderSurface) {
         mRenderSurface->dump(out);
     } else {
         out.append("    No render surface!\n");
     }
 
-    android::base::StringAppendF(&out, "\n   %zu Layers\n", getOutputLayerCount());
+    base::StringAppendF(&out, "\n   %zu Layers\n", getOutputLayerCount());
     for (const auto* outputLayer : getOutputLayersOrderedByZ()) {
         if (!outputLayer) {
             continue;
@@ -329,7 +329,7 @@
 
 void Output::dumpPlannerInfo(const Vector<String16>& args, std::string& out) const {
     if (!mPlanner) {
-        base::StringAppendF(&out, "Planner is disabled\n");
+        out.append("Planner is disabled\n");
         return;
     }
     base::StringAppendF(&out, "Planner info for display [%s]\n", mName.c_str());
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
index 7188281..3b85e3b 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
@@ -14,40 +14,30 @@
  * limitations under the License.
  */
 
+#include <ftl/enum.h>
+
 #include <compositionengine/impl/DumpHelpers.h>
 #include <compositionengine/impl/OutputCompositionState.h>
 
 namespace android::compositionengine::impl {
-using CompositionStrategyPredictionState =
-        OutputCompositionState::CompositionStrategyPredictionState;
-
-std::string toString(CompositionStrategyPredictionState state) {
-    switch (state) {
-        case CompositionStrategyPredictionState::DISABLED:
-            return "Disabled";
-        case CompositionStrategyPredictionState::SUCCESS:
-            return "Success";
-        case CompositionStrategyPredictionState::FAIL:
-            return "Fail";
-    }
-}
 
 void OutputCompositionState::dump(std::string& out) const {
     out.append("   ");
     dumpVal(out, "isEnabled", isEnabled);
     dumpVal(out, "isSecure", isSecure);
-
-    dumpVal(out, "usesClientComposition", usesClientComposition);
     dumpVal(out, "usesDeviceComposition", usesDeviceComposition);
+
+    out.append("\n   ");
+    dumpVal(out, "usesClientComposition", usesClientComposition);
     dumpVal(out, "flipClientTarget", flipClientTarget);
     dumpVal(out, "reusedClientComposition", reusedClientComposition);
-    dumpVal(out, "layerFilter", layerFilter);
 
     out.append("\n   ");
-
+    dumpVal(out, "layerFilter", layerFilter);
+    out.append("\n   ");
     dumpVal(out, "transform", transform);
 
-    out.append("\n   ");
+    out.append("   "); // ui::Transform::dump appends EOL.
     dumpVal(out, "layerStackSpace", to_string(layerStackSpace));
     out.append("\n   ");
     dumpVal(out, "framebufferSpace", to_string(framebufferSpace));
@@ -59,19 +49,24 @@
     dumpVal(out, "needsFiltering", needsFiltering);
 
     out.append("\n   ");
-
     dumpVal(out, "colorMode", toString(colorMode), colorMode);
     dumpVal(out, "renderIntent", toString(renderIntent), renderIntent);
     dumpVal(out, "dataspace", toString(dataspace), dataspace);
+    dumpVal(out, "targetDataspace", toString(targetDataspace), targetDataspace);
+
+    out.append("\n   ");
     dumpVal(out, "colorTransformMatrix", colorTransformMatrix);
-    dumpVal(out, "target dataspace", toString(targetDataspace), targetDataspace);
+
+    out.append("\n   ");
     dumpVal(out, "displayBrightnessNits", displayBrightnessNits);
     dumpVal(out, "sdrWhitePointNits", sdrWhitePointNits);
     dumpVal(out, "clientTargetBrightness", clientTargetBrightness);
     dumpVal(out, "displayBrightness", displayBrightness);
-    dumpVal(out, "compositionStrategyPredictionState", toString(strategyPrediction));
 
-    out.append("\n");
+    out.append("\n   ");
+    dumpVal(out, "compositionStrategyPredictionState", ftl::enum_string(strategyPrediction));
+
+    out += '\n';
 }
 
 } // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 3289d55..744561c 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -106,9 +106,8 @@
     return activeCrop;
 }
 
-FloatRect OutputLayer::calculateOutputSourceCrop() const {
+FloatRect OutputLayer::calculateOutputSourceCrop(uint32_t internalDisplayRotationFlags) const {
     const auto& layerState = *getLayerFE().getCompositionState();
-    const auto& outputState = getOutput().getState();
 
     if (!layerState.geomUsesSourceCrop) {
         return {};
@@ -140,8 +139,7 @@
          * the code below applies the primary display's inverse transform to the
          * buffer
          */
-        uint32_t invTransformOrient =
-                ui::Transform::toRotationFlags(outputState.displaySpace.getOrientation());
+        uint32_t invTransformOrient = internalDisplayRotationFlags;
         // calculate the inverse transform
         if (invTransformOrient & HAL_TRANSFORM_ROT_90) {
             invTransformOrient ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
@@ -304,7 +302,7 @@
         state.forceClientComposition = false;
 
         state.displayFrame = calculateOutputDisplayFrame();
-        state.sourceCrop = calculateOutputSourceCrop();
+        state.sourceCrop = calculateOutputSourceCrop(internalDisplayRotationFlags);
         state.bufferTransform = static_cast<Hwc2::Transform>(
                 calculateOutputRelativeBufferTransform(internalDisplayRotationFlags));
 
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index ceee48c..f96570a 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -169,7 +169,7 @@
     FloatRect calculateOutputSourceCrop() {
         mLayerFEState.geomInverseLayerTransform = mLayerFEState.geomLayerTransform.inverse();
 
-        return mOutputLayer.calculateOutputSourceCrop();
+        return mOutputLayer.calculateOutputSourceCrop(ui::Transform::RotationFlags::ROT_0);
     }
 };
 
@@ -533,7 +533,7 @@
                                                     sp<compositionengine::LayerFE> layerFE)
           : mOutput(output), mLayerFE(layerFE) {}
     // Mock everything called by updateCompositionState to simplify testing it.
-    MOCK_CONST_METHOD0(calculateOutputSourceCrop, FloatRect());
+    MOCK_CONST_METHOD1(calculateOutputSourceCrop, FloatRect(uint32_t));
     MOCK_CONST_METHOD0(calculateOutputDisplayFrame, Rect());
     MOCK_CONST_METHOD1(calculateOutputRelativeBufferTransform, uint32_t(uint32_t));
 
@@ -563,7 +563,8 @@
     ~OutputLayerUpdateCompositionStateTest() = default;
 
     void setupGeometryChildCallValues(ui::Transform::RotationFlags internalDisplayRotationFlags) {
-        EXPECT_CALL(mOutputLayer, calculateOutputSourceCrop()).WillOnce(Return(kSourceCrop));
+        EXPECT_CALL(mOutputLayer, calculateOutputSourceCrop(internalDisplayRotationFlags))
+                .WillOnce(Return(kSourceCrop));
         EXPECT_CALL(mOutputLayer, calculateOutputDisplayFrame()).WillOnce(Return(kDisplayFrame));
         EXPECT_CALL(mOutputLayer,
                     calculateOutputRelativeBufferTransform(internalDisplayRotationFlags))
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 65e7a7f..52529d6 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -24,7 +24,6 @@
 
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include <android-base/stringprintf.h>
 #include <compositionengine/CompositionEngine.h>
 #include <compositionengine/Display.h>
 #include <compositionengine/DisplayColorProfile.h>
@@ -49,8 +48,6 @@
 
 namespace hal = hardware::graphics::composer::hal;
 
-using android::base::StringAppendF;
-
 ui::Transform::RotationFlags DisplayDevice::sPrimaryDisplayRotationFlags = ui::Transform::ROT_0;
 
 DisplayDeviceCreationArgs::DisplayDeviceCreationArgs(
@@ -342,38 +339,40 @@
 }
 
 std::string DisplayDevice::getDebugName() const {
-    const char* type = "virtual";
+    using namespace std::string_literals;
+
+    std::string name = "Display "s + to_string(getId()) + " ("s;
+
     if (mConnectionType) {
-        type = isInternal() ? "internal" : "external";
+        name += isInternal() ? "internal"s : "external"s;
+    } else {
+        name += "virtual"s;
     }
 
-    return base::StringPrintf("DisplayDevice{%s, %s%s, \"%s\"}", to_string(getId()).c_str(), type,
-                              isPrimary() ? ", primary" : "", mDisplayName.c_str());
+    if (isPrimary()) {
+        name += ", primary"s;
+    }
+
+    return name + ", \""s + mDisplayName + "\")"s;
 }
 
 void DisplayDevice::dump(std::string& result) const {
-    StringAppendF(&result, "+ %s\n", getDebugName().c_str());
-    StringAppendF(&result, "   powerMode=%s (%d)\n", to_string(mPowerMode).c_str(),
-                  static_cast<int32_t>(mPowerMode));
-    const auto activeMode = getActiveMode();
-    StringAppendF(&result, "   activeMode=%s\n",
-                  activeMode ? to_string(*activeMode).c_str() : "none");
+    using namespace std::string_literals;
 
-    result.append("   supportedModes=\n");
-    for (const auto& [id, mode] : mSupportedModes) {
-        result.append("      ");
-        result.append(to_string(*mode));
-        result.push_back('\n');
+    result += getDebugName();
+
+    if (!isVirtual()) {
+        result += "\n   deviceProductInfo="s;
+        if (mDeviceProductInfo) {
+            mDeviceProductInfo->dump(result);
+        } else {
+            result += "{}"s;
+        }
     }
 
-    StringAppendF(&result, "   deviceProductInfo=");
-    if (mDeviceProductInfo) {
-        mDeviceProductInfo->dump(result);
-    } else {
-        result.append("{}");
-    }
-    result.append("\n");
-    getCompositionDisplay()->dump(result);
+    result += "\n   powerMode="s;
+    result += to_string(mPowerMode);
+    result += '\n';
 
     if (mRefreshRateConfigs) {
         mRefreshRateConfigs->dump(result);
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 8d685cf..eb14933 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -44,18 +44,10 @@
 #include "HWComposer.h"
 #include "../SurfaceFlinger.h"
 
-// ----------------------------------------------------------------------------
 namespace android {
-// ----------------------------------------------------------------------------
 
 using ui::Dataspace;
 
-/*
- * This implements the (main) framebuffer management. This class is used
- * mostly by SurfaceFlinger, but also by command line GL application.
- *
- */
-
 FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
                                        const sp<IGraphicBufferConsumer>& consumer,
                                        const ui::Size& size, const ui::Size& maxSize)
@@ -205,14 +197,14 @@
 
 void FramebufferSurface::dumpAsString(String8& result) const {
     Mutex::Autolock lock(mMutex);
-    result.appendFormat("  FramebufferSurface: dataspace: %s(%d)\n",
+    result.append("   FramebufferSurface\n");
+    result.appendFormat("      mDataSpace=%s (%d)\n",
                         dataspaceDetails(static_cast<android_dataspace>(mDataSpace)).c_str(),
                         mDataSpace);
-    ConsumerBase::dumpLocked(result, "   ");
+    ConsumerBase::dumpLocked(result, "      ");
 }
 
-void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const
-{
+void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const {
     ConsumerBase::dumpLocked(result, prefix);
 }
 
@@ -220,9 +212,7 @@
     return mCurrentFence;
 }
 
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
+} // namespace android
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 670233a..79e4c75 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -376,11 +376,6 @@
     }
 
     ATRACE_CALL();
-    if (displayData.powerMode == hal::PowerMode::DOZE && enabled == hal::Vsync::ENABLE) {
-        ALOGV("%s will not enable vsync for display %s due to power mode %s", __FUNCTION__,
-              to_string(displayId).c_str(), to_string(displayData.powerMode).c_str());
-        return;
-    }
     auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
     RETURN_IF_HWC_ERROR(error, displayId);
 
@@ -557,7 +552,6 @@
         setVsyncEnabled(displayId, hal::Vsync::DISABLE);
     }
 
-    mDisplayData[displayId].powerMode = mode;
     const auto& displayData = mDisplayData[displayId];
     auto& hwcDisplay = displayData.hwcDisplay;
     switch (mode) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 8d67589..7dc10ea 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -462,8 +462,6 @@
         std::mutex vsyncEnabledLock;
         hal::Vsync vsyncEnabled GUARDED_BY(vsyncEnabledLock) = hal::Vsync::DISABLE;
 
-        hal::PowerMode powerMode = hal::PowerMode::ON;
-
         nsecs_t lastHwVsync = 0;
     };
 
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index cbafdd3..659efd8 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -564,6 +564,7 @@
         if (!wrapper->shouldReconnectHAL()) {
             return wrapper;
         }
+        ALOGD("Reconnecting Power HAL");
         sHalWrapper = nullptr;
     }
 
@@ -576,7 +577,9 @@
     // If that didn't succeed, attempt to connect to the HIDL Power HAL
     if (sHalWrapper == nullptr) {
         sHalWrapper = HidlPowerHalWrapper::connect();
-    } else { // if AIDL, pass on any existing hint session values
+    } else {
+        ALOGD("Successfully connecting AIDL Power HAL");
+        // if AIDL, pass on any existing hint session values
         // thread ids always safe to set
         sHalWrapper->setPowerHintSessionThreadIds(oldPowerHintSessionThreadIds);
         // only set duration and start if duration is defined
diff --git a/services/surfaceflinger/FlagManager.cpp b/services/surfaceflinger/FlagManager.cpp
index bd3cf74..f8ad8f6 100644
--- a/services/surfaceflinger/FlagManager.cpp
+++ b/services/surfaceflinger/FlagManager.cpp
@@ -96,7 +96,8 @@
 }
 
 bool FlagManager::use_adpf_cpu_hint() const {
-    std::optional<bool> sysPropVal = std::nullopt;
+    std::optional<bool> sysPropVal =
+            doParse<bool>(base::GetProperty("debug.sf.enable_adpf_cpu_hint", "").c_str());
     return getValue("AdpfFeature__adpf_cpu_hint", sysPropVal, false);
 }
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index d8a5601..3a92ca4 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2664,6 +2664,18 @@
     mDrawingState.callbackHandles = {};
 }
 
+bool Layer::setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles) {
+    if (handles.empty()) {
+        return false;
+    }
+
+    for (const auto& handle : handles) {
+        mFlinger->getTransactionCallbackInvoker().registerUnpresentedCallbackHandle(handle);
+    }
+
+    return true;
+}
+
 // ---------------------------------------------------------------------------
 
 std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 565a6ff..ecea744 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -431,9 +431,7 @@
     virtual bool setApi(int32_t /*api*/) { return false; };
     virtual bool setSidebandStream(const sp<NativeHandle>& /*sidebandStream*/) { return false; };
     virtual bool setTransactionCompletedListeners(
-            const std::vector<sp<CallbackHandle>>& /*handles*/) {
-        return false;
-    };
+            const std::vector<sp<CallbackHandle>>& /*handles*/);
     virtual bool addFrameEvent(const sp<Fence>& /*acquireFence*/, nsecs_t /*postedTime*/,
                                nsecs_t /*requestedPresentTime*/) {
         return false;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 3226f22..ca83496 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -133,9 +133,9 @@
 } // namespace
 
 std::string RefreshRateConfigs::Policy::toString() const {
-    return base::StringPrintf("default mode ID: %d, allowGroupSwitching = %d"
-                              ", primary range: %s, app request range: %s",
-                              defaultMode.value(), allowGroupSwitching,
+    return base::StringPrintf("{defaultModeId=%d, allowGroupSwitching=%s"
+                              ", primaryRange=%s, appRequestRange=%s}",
+                              defaultMode.value(), allowGroupSwitching ? "true" : "false",
                               to_string(primaryRange).c_str(), to_string(appRequestRange).c_str());
 }
 
@@ -922,41 +922,46 @@
 }
 
 void RefreshRateConfigs::dump(std::string& result) const {
+    using namespace std::string_literals;
+
     std::lock_guard lock(mLock);
-    base::StringAppendF(&result, "DesiredDisplayModeSpecs (DisplayManager): %s\n\n",
-                        mDisplayManagerPolicy.toString().c_str());
-    scheduler::RefreshRateConfigs::Policy currentPolicy = *getCurrentPolicyLocked();
-    if (mOverridePolicy && currentPolicy != mDisplayManagerPolicy) {
-        base::StringAppendF(&result, "DesiredDisplayModeSpecs (Override): %s\n\n",
-                            currentPolicy.toString().c_str());
-    }
 
-    base::StringAppendF(&result, "Active mode: %s\n", to_string(*mActiveModeIt->second).c_str());
+    const auto activeModeId = mActiveModeIt->first;
+    result += "   activeModeId="s;
+    result += std::to_string(activeModeId.value());
 
-    result.append("Display modes:\n");
+    result += "\n   displayModes=\n"s;
     for (const auto& [id, mode] : mDisplayModes) {
-        result.push_back('\t');
-        result.append(to_string(*mode));
-        result.push_back('\n');
+        result += "      "s;
+        result += to_string(*mode);
+        result += '\n';
     }
 
-    base::StringAppendF(&result, "Supports Frame Rate Override By Content: %s\n",
-                        mSupportsFrameRateOverrideByContent ? "yes" : "no");
+    base::StringAppendF(&result, "   displayManagerPolicy=%s\n",
+                        mDisplayManagerPolicy.toString().c_str());
 
-    result.append("Idle timer: ");
-    if (const auto controller = mConfig.kernelIdleTimerController) {
-        base::StringAppendF(&result, "(kernel via %s) ", ftl::enum_string(*controller).c_str());
-    } else {
-        result.append("(platform) ");
+    if (const Policy& currentPolicy = *getCurrentPolicyLocked();
+        mOverridePolicy && currentPolicy != mDisplayManagerPolicy) {
+        base::StringAppendF(&result, "   overridePolicy=%s\n", currentPolicy.toString().c_str());
     }
 
+    base::StringAppendF(&result, "   supportsFrameRateOverrideByContent=%s\n",
+                        mSupportsFrameRateOverrideByContent ? "true" : "false");
+
+    result += "   idleTimer="s;
     if (mIdleTimer) {
-        result.append(mIdleTimer->dump());
+        result += mIdleTimer->dump();
     } else {
-        result.append("off");
+        result += "off"s;
     }
 
-    result.append("\n\n");
+    if (const auto controller = mConfig.kernelIdleTimerController) {
+        base::StringAppendF(&result, " (kernel via %s)", ftl::enum_string(*controller).c_str());
+    } else {
+        result += " (platform)"s;
+    }
+
+    result += '\n';
 }
 
 std::chrono::milliseconds RefreshRateConfigs::getIdleTimerTimeout() {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ccd218d..d39176b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -583,14 +583,8 @@
 std::vector<PhysicalDisplayId> SurfaceFlinger::getPhysicalDisplayIdsLocked() const {
     std::vector<PhysicalDisplayId> displayIds;
     displayIds.reserve(mPhysicalDisplayTokens.size());
-    const auto defaultDisplayId = [this]() REQUIRES(mStateLock) {
-        if (const auto display = getDefaultDisplayDeviceLocked()) {
-            return display->getPhysicalId();
-        }
 
-        // fallback to the internal display id if the active display is unknown
-        return getInternalDisplayIdLocked();
-    }();
+    const auto defaultDisplayId = getDefaultDisplayDeviceLocked()->getPhysicalId();
     displayIds.push_back(defaultDisplayId);
 
     for (const auto& [id, token] : mPhysicalDisplayTokens) {
@@ -604,7 +598,7 @@
 
 status_t SurfaceFlinger::getPrimaryPhysicalDisplayId(PhysicalDisplayId* id) const {
     Mutex::Autolock lock(mStateLock);
-    *id = getInternalDisplayIdLocked();
+    *id = getPrimaryDisplayIdLocked();
     return NO_ERROR;
 }
 
@@ -681,8 +675,12 @@
 
         readPersistentProperties();
         mPowerAdvisor->onBootFinished();
-        mPowerAdvisor->enablePowerHint(mFlagManager.use_adpf_cpu_hint());
-        if (mPowerAdvisor->usePowerHintSession()) {
+        const bool powerHintEnabled = mFlagManager.use_adpf_cpu_hint();
+        mPowerAdvisor->enablePowerHint(powerHintEnabled);
+        const bool powerHintUsed = mPowerAdvisor->usePowerHintSession();
+        ALOGD("Power hint is %s",
+              powerHintUsed ? "supported" : (powerHintEnabled ? "unsupported" : "disabled"));
+        if (powerHintUsed) {
             std::optional<pid_t> renderEngineTid = getRenderEngine().getRenderEngineTid();
             std::vector<int32_t> tidList;
             tidList.emplace_back(gettid());
@@ -1315,17 +1313,25 @@
 }
 
 status_t SurfaceFlinger::getDisplayNativePrimaries(const sp<IBinder>& displayToken,
-                                                   ui::DisplayPrimaries &primaries) {
+                                                   ui::DisplayPrimaries& primaries) {
     if (!displayToken) {
         return BAD_VALUE;
     }
 
-    // Currently we only support this API for a single internal display.
-    if (getInternalDisplayToken() != displayToken) {
+    Mutex::Autolock lock(mStateLock);
+
+    const auto display = getDisplayDeviceLocked(displayToken);
+    if (!display) {
         return NAME_NOT_FOUND;
     }
 
-    memcpy(&primaries, &mInternalDisplayPrimaries, sizeof(ui::DisplayPrimaries));
+    const auto connectionType = display->getConnectionType();
+    if (connectionType != ui::DisplayConnectionType::Internal) {
+        return INVALID_OPERATION;
+    }
+
+    // TODO(b/229846990): For now, assume that all internal displays have the same primaries.
+    primaries = mInternalDisplayPrimaries;
     return NO_ERROR;
 }
 
@@ -2826,7 +2832,7 @@
     }
 
     if (const auto id = PhysicalDisplayId::tryCast(compositionDisplay->getId())) {
-        creationArgs.isPrimary = id == getInternalDisplayIdLocked();
+        creationArgs.isPrimary = id == getPrimaryDisplayIdLocked();
 
         if (useColorManagement) {
             std::vector<ColorMode> modes = getHwComposer().getColorModes(*id);
@@ -4945,7 +4951,9 @@
                       pid, uid);
     } else {
         static const std::unordered_map<std::string, Dumper> dumpers = {
+                {"--comp-displays"s, dumper(&SurfaceFlinger::dumpCompositionDisplays)},
                 {"--display-id"s, dumper(&SurfaceFlinger::dumpDisplayIdentificationData)},
+                {"--displays"s, dumper(&SurfaceFlinger::dumpDisplays)},
                 {"--dispsync"s, dumper([this](std::string& s) { mScheduler->dumpVsync(s); })},
                 {"--edid"s, argsDumper(&SurfaceFlinger::dumpRawDisplayIdentificationData)},
                 {"--frame-events"s, dumper(&SurfaceFlinger::dumpFrameEventsLocked)},
@@ -5122,6 +5130,20 @@
         [&] (Layer* layer) { layer->dumpFrameEvents(result); });
 }
 
+void SurfaceFlinger::dumpCompositionDisplays(std::string& result) const {
+    for (const auto& [token, display] : mDisplays) {
+        display->getCompositionDisplay()->dump(result);
+        result += '\n';
+    }
+}
+
+void SurfaceFlinger::dumpDisplays(std::string& result) const {
+    for (const auto& [token, display] : mDisplays) {
+        display->dump(result);
+        result += '\n';
+    }
+}
+
 void SurfaceFlinger::dumpDisplayIdentificationData(std::string& result) const {
     for (const auto& [token, display] : mDisplays) {
         const auto displayId = PhysicalDisplayId::tryCast(display->getId());
@@ -5330,21 +5352,12 @@
         });
     }
 
-    /*
-     * Dump Display state
-     */
-
     colorizer.bold(result);
     StringAppendF(&result, "Displays (%zu entries)\n", mDisplays.size());
     colorizer.reset(result);
-    for (const auto& [token, display] : mDisplays) {
-        display->dump(result);
-    }
-    result.append("\n");
-
-    /*
-     * Dump CompositionEngine state
-     */
+    dumpDisplays(result);
+    dumpCompositionDisplays(result);
+    result.push_back('\n');
 
     mCompositionEngine->dump(result);
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 011aaef..74e0407 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -525,19 +525,6 @@
     bool callingThreadHasUnscopedSurfaceFlingerAccess(bool usePermissionCache = true)
             EXCLUDES(mStateLock);
 
-    // the following two methods are moved from ISurfaceComposer.h
-    // TODO(b/74619554): Remove this stopgap once the framework is display-agnostic.
-    std::optional<PhysicalDisplayId> getInternalDisplayId() const {
-        const auto displayIds = getPhysicalDisplayIds();
-        return displayIds.empty() ? std::nullopt : std::make_optional(displayIds.front());
-    }
-
-    // TODO(b/74619554): Remove this stopgap once the framework is display-agnostic.
-    sp<IBinder> getInternalDisplayToken() const {
-        const auto displayId = getInternalDisplayId();
-        return displayId ? getPhysicalDisplayToken(*displayId) : nullptr;
-    }
-
     // Implements ISurfaceComposer
     sp<ISurfaceComposerClient> createConnection() override;
     sp<IBinder> createDisplay(const String8& displayName, bool secure);
@@ -922,6 +909,13 @@
         return nullptr;
     }
 
+    sp<const DisplayDevice> getDisplayDeviceLocked(DisplayId id) const REQUIRES(mStateLock) {
+        // TODO(b/182939859): Replace tokens with IDs for display lookup.
+        return findDisplay([id](const auto& display) { return display.getId() == id; });
+    }
+
+    // Returns the primary display or (for foldables) the active display, assuming that the inner
+    // and outer displays have mutually exclusive power states.
     sp<const DisplayDevice> getDefaultDisplayDeviceLocked() const REQUIRES(mStateLock) {
         return const_cast<SurfaceFlinger*>(this)->getDefaultDisplayDeviceLocked();
     }
@@ -930,12 +924,9 @@
         if (const auto display = getDisplayDeviceLocked(mActiveDisplayToken)) {
             return display;
         }
-        // The active display is outdated, fall back to the internal display
+        // The active display is outdated, so fall back to the primary display.
         mActiveDisplayToken.clear();
-        if (const auto token = getInternalDisplayTokenLocked()) {
-            return getDisplayDeviceLocked(token);
-        }
-        return nullptr;
+        return getDisplayDeviceLocked(getPrimaryDisplayTokenLocked());
     }
 
     sp<const DisplayDevice> getDefaultDisplayDevice() const EXCLUDES(mStateLock) {
@@ -952,11 +943,6 @@
         return it == mDisplays.end() ? nullptr : it->second;
     }
 
-    sp<const DisplayDevice> getDisplayDeviceLocked(DisplayId id) const REQUIRES(mStateLock) {
-        // TODO(b/182939859): Replace tokens with IDs for display lookup.
-        return findDisplay([id](const auto& display) { return display.getId() == id; });
-    }
-
     std::vector<PhysicalDisplayId> getPhysicalDisplayIdsLocked() const REQUIRES(mStateLock);
 
     // mark a region of a layer stack dirty. this updates the dirty
@@ -1066,18 +1052,17 @@
         return {};
     }
 
-    // TODO(b/182939859): SF conflates the primary (a.k.a. default) display with the first display
-    // connected at boot, which is typically internal. (Theoretically, it must be internal because
-    // SF does not support disconnecting it, though in practice HWC may circumvent this limitation.)
+    // Returns the first display connected at boot.
     //
-    // SF inherits getInternalDisplayToken and getInternalDisplayId from ISurfaceComposer, so these
-    // locked counterparts are named consistently. Once SF supports headless mode and can designate
-    // any display as primary, the "internal" misnomer will be phased out.
-    sp<IBinder> getInternalDisplayTokenLocked() const REQUIRES(mStateLock) {
-        return getPhysicalDisplayTokenLocked(getInternalDisplayIdLocked());
+    // TODO(b/229851933): SF conflates the primary display with the first display connected at boot,
+    // which typically has DisplayConnectionType::Internal. (Theoretically, it must be an internal
+    // display because SF does not support disconnecting it, though in practice HWC may circumvent
+    // this limitation.)
+    sp<IBinder> getPrimaryDisplayTokenLocked() const REQUIRES(mStateLock) {
+        return getPhysicalDisplayTokenLocked(getPrimaryDisplayIdLocked());
     }
 
-    PhysicalDisplayId getInternalDisplayIdLocked() const REQUIRES(mStateLock) {
+    PhysicalDisplayId getPrimaryDisplayIdLocked() const REQUIRES(mStateLock) {
         return getHwComposer().getPrimaryDisplayId();
     }
 
@@ -1109,9 +1094,13 @@
     void dumpStaticScreenStats(std::string& result) const;
     // Not const because each Layer needs to query Fences and cache timestamps.
     void dumpFrameEventsLocked(std::string& result);
+
+    void dumpCompositionDisplays(std::string& result) const REQUIRES(mStateLock);
+    void dumpDisplays(std::string& result) const REQUIRES(mStateLock);
     void dumpDisplayIdentificationData(std::string& result) const REQUIRES(mStateLock);
     void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const;
     void dumpWideColorInfo(std::string& result) const REQUIRES(mStateLock);
+
     LayersProto dumpDrawingStateProto(uint32_t traceFlags) const;
     void dumpOffscreenLayersProto(LayersProto& layersProto,
                                   uint32_t traceFlags = LayerTracing::TRACE_ALL) const;
diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp
index 8a2305b..219db8c 100644
--- a/services/surfaceflinger/tests/LayerCallback_test.cpp
+++ b/services/surfaceflinger/tests/LayerCallback_test.cpp
@@ -55,24 +55,34 @@
         return createLayer(mClient, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState);
     }
 
+    static int fillBuffer(Transaction& transaction, const sp<SurfaceControl>& layer,
+                          bool setBuffer = true, bool setBackgroundColor = false) {
+        sp<GraphicBuffer> buffer;
+        sp<Fence> fence;
+        if (setBuffer) {
+            int err = getBuffer(&buffer, &fence);
+            if (err != NO_ERROR) {
+                return err;
+            }
+
+            transaction.setBuffer(layer, buffer, fence);
+        }
+
+        if (setBackgroundColor) {
+            transaction.setBackgroundColor(layer, /*color*/ half3(1.0f, 0, 0), /*alpha*/ 1.0f,
+                                           ui::Dataspace::UNKNOWN);
+        }
+
+        return NO_ERROR;
+    }
+
     static int fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper,
                                const sp<SurfaceControl>& layer = nullptr, bool setBuffer = true,
                                bool setBackgroundColor = false) {
         if (layer) {
-            sp<GraphicBuffer> buffer;
-            sp<Fence> fence;
-            if (setBuffer) {
-                int err = getBuffer(&buffer, &fence);
-                if (err != NO_ERROR) {
-                    return err;
-                }
-
-                transaction.setBuffer(layer, buffer, fence);
-            }
-
-            if (setBackgroundColor) {
-                transaction.setBackgroundColor(layer, /*color*/ half3(1.0f, 0, 0), /*alpha*/ 1.0f,
-                                               ui::Dataspace::UNKNOWN);
+            int err = fillBuffer(transaction, layer, setBuffer, setBackgroundColor);
+            if (err != NO_ERROR) {
+                return err;
             }
         }
 
@@ -1115,7 +1125,7 @@
     Transaction transaction;
     CallbackHelper callback;
     int err = fillTransaction(transaction, &callback, layer, true);
-    err |= fillTransaction(transaction, &callback, offscreenLayer, true);
+    err |= fillBuffer(transaction, offscreenLayer);
     if (err) {
         GTEST_SUCCEED() << "test not supported";
         return;
@@ -1129,5 +1139,86 @@
     committedSc.insert(layer);
     committedSc.insert(offscreenLayer);
     EXPECT_NO_FATAL_FAILURE(waitForCommitCallback(callback, committedSc));
+
+    ExpectedResult expected;
+    expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+    expected.addSurface(ExpectedResult::Transaction::PRESENTED, offscreenLayer);
+    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
 }
+
+TEST_F(LayerCallbackTest, TransactionCommittedCallback_BSL) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+    Transaction transaction;
+    CallbackHelper callback;
+    int err = fillTransaction(transaction, &callback, layer, true);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    transaction.addTransactionCommittedCallback(callback.function, callback.getContext()).apply();
+    std::unordered_set<sp<SurfaceControl>, SCHash> committedSc;
+    committedSc.insert(layer);
+    EXPECT_NO_FATAL_FAILURE(waitForCommitCallback(callback, committedSc));
+    ExpectedResult expected;
+    expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
+TEST_F(LayerCallbackTest, TransactionCommittedCallback_EffectLayer) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createColorLayer("ColorLayer", Color::RED));
+
+    Transaction transaction;
+    CallbackHelper callback;
+    int err = fillTransaction(transaction, &callback);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    transaction.addTransactionCommittedCallback(callback.function, callback.getContext()).apply();
+    std::unordered_set<sp<SurfaceControl>, SCHash> committedSc;
+    EXPECT_NO_FATAL_FAILURE(waitForCommitCallback(callback, committedSc));
+
+    ExpectedResult expected;
+    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
+TEST_F(LayerCallbackTest, TransactionCommittedCallback_ContainerLayer) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer(mClient, "Container Layer", 0, 0,
+                                                ISurfaceComposerClient::eFXSurfaceContainer));
+
+    Transaction transaction;
+    CallbackHelper callback;
+    int err = fillTransaction(transaction, &callback);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    transaction.addTransactionCommittedCallback(callback.function, callback.getContext()).apply();
+    std::unordered_set<sp<SurfaceControl>, SCHash> committedSc;
+    EXPECT_NO_FATAL_FAILURE(waitForCommitCallback(callback, committedSc));
+
+    ExpectedResult expected;
+    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
+TEST_F(LayerCallbackTest, TransactionCommittedCallback_NoLayer) {
+    Transaction transaction;
+    CallbackHelper callback;
+    int err = fillTransaction(transaction, &callback);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    transaction.addTransactionCommittedCallback(callback.function, callback.getContext()).apply();
+    std::unordered_set<sp<SurfaceControl>, SCHash> committedSc;
+    EXPECT_NO_FATAL_FAILURE(waitForCommitCallback(callback, committedSc));
+
+    ExpectedResult expected;
+    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_PowerHintTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_PowerHintTest.cpp
index 0a157c4..8de9e4b 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_PowerHintTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_PowerHintTest.cpp
@@ -130,8 +130,7 @@
     ON_CALL(*mPowerAdvisor, usePowerHintSession()).WillByDefault(Return(true));
 
     const std::chrono::nanoseconds mockVsyncPeriod = 15ms;
-    const std::chrono::nanoseconds expectedTargetTime = 14ms;
-    EXPECT_CALL(*mPowerAdvisor, setTargetWorkDuration(Gt(expectedTargetTime.count()))).Times(1);
+    EXPECT_CALL(*mPowerAdvisor, setTargetWorkDuration(_)).Times(1);
 
     const nsecs_t now = systemTime();
     const std::chrono::nanoseconds mockHwcRunTime = 20ms;