Merge "SurfaceFlinger: missing configChanged event on idle" into rvc-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index d4c1616..942c16c 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1367,13 +1367,11 @@
     printf("\n");
 }
 
-static void DumpstateArcOnly() {
+static void DumpstateLimitedOnly() {
     // Trimmed-down version of dumpstate to only include a whitelisted
     // set of logs (system log, event log, and system server / system app
-    // crashes, and ARC networking logs). See b/136273873 and b/138459828
-    // for context. New sections must be first approved by Chrome OS Privacy
-    // and then added to server side cros monitoring PII scrubber before adding
-    // them here. See cl/312126645 for an example.
+    // crashes, and networking logs). See b/136273873 and b/138459828
+    // for context.
     DurationReporter duration_reporter("DUMPSTATE");
     unsigned long timeout_ms;
     // calculate timeout
@@ -1391,11 +1389,6 @@
     printf("== Networking Service\n");
     printf("========================================================\n");
 
-    // ARC networking service implements dumpsys by reusing the 'wifi' service name.
-    // The top-level handler is implemented in handleDump() in
-    // vendor/google_arc/libs/arc-services/src/com/android/server/arc/net/ArcNetworkService.java.
-    // It outputs a subset of Android system server state relevant for debugging ARC
-    // connectivity issues, in a PII-free manner. See b/147270970.
     RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
                CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
 
@@ -2100,7 +2093,7 @@
 static void ShowUsage() {
     fprintf(stderr,
             "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-d] [-p] "
-            "[-z] [-s] [-S] [-q] [-P] [-R] [-A] [-V version]\n"
+            "[-z] [-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
             "  -h: display this help message\n"
             "  -b: play sound file instead of vibrate, at beginning of job\n"
             "  -e: play sound file instead of vibrate, at end of job\n"
@@ -2113,7 +2106,7 @@
             "  -P: send broadcast when started and do progress updates\n"
             "  -R: take bugreport in remote mode (requires -z and -d, shouldn't be used with -P)\n"
             "  -w: start binder service and make it wait for a call to startBugreport\n"
-            "  -A: output limited information that is safe for submission in ARC++ bugreports\n"
+            "  -L: output limited information that is safe for submission in feedback reports\n"
             "  -v: prints the dumpstate header and exit\n");
 }
 
@@ -2359,12 +2352,12 @@
         "do_zip_file: %d do_vibrate: %d use_socket: %d use_control_socket: %d do_screenshot: %d "
         "is_remote_mode: %d show_header_only: %d do_start_service: %d telephony_only: %d "
         "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s dumpstate_hal_mode: %s "
-        "arc_only: %d args: %s\n",
+        "limited_only: %d args: %s\n",
         options.do_zip_file, options.do_vibrate, options.use_socket, options.use_control_socket,
         options.do_screenshot, options.is_remote_mode, options.show_header_only,
         options.do_start_service, options.telephony_only, options.wifi_only,
         options.do_progress_updates, options.bugreport_fd.get(), options.bugreport_mode.c_str(),
-        toString(options.dumpstate_hal_mode).c_str(), options.arc_only, options.args.c_str());
+        toString(options.dumpstate_hal_mode).c_str(), options.limited_only, options.args.c_str());
 }
 
 void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
@@ -2386,7 +2379,7 @@
 Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
     RunStatus status = RunStatus::OK;
     int c;
-    while ((c = getopt(argc, argv, "dho:svqzpAPBRSV:w")) != -1) {
+    while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
         switch (c) {
             // clang-format off
             case 'd': do_add_date = true;            break;
@@ -2398,7 +2391,7 @@
             case 'p': do_screenshot = true;          break;
             case 'P': do_progress_updates = true;    break;
             case 'R': is_remote_mode = true;         break;
-            case 'A': arc_only = true;               break;
+            case 'L': limited_only = true;           break;
             case 'V':                                break;  // compatibility no-op
             case 'w':
                 // This was already processed
@@ -2683,7 +2676,7 @@
     // duration is logged into MYLOG instead.
     PrintHeader();
 
-    // TODO(nandana) reduce code repetition in if branches
+    // TODO(b/158737089) reduce code repetition in if branches
     if (options_->telephony_only) {
         MaybeTakeEarlyScreenshot();
         onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
@@ -2695,11 +2688,11 @@
         onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
         MaybeCheckUserConsent(calling_uid, calling_package);
         DumpstateWifiOnly();
-    } else if (options_->arc_only) {
+    } else if (options_->limited_only) {
         MaybeTakeEarlyScreenshot();
         onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
         MaybeCheckUserConsent(calling_uid, calling_package);
-        DumpstateArcOnly();
+        DumpstateLimitedOnly();
     } else {
         // Invoke critical dumpsys first to preserve system state, before doing anything else.
         RunDumpsysCritical();
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index c8c9f45..dc0848a 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -378,7 +378,7 @@
         bool telephony_only = false;
         bool wifi_only = false;
         // Trimmed-down version of dumpstate to only include whitelisted logs.
-        bool arc_only = false;
+        bool limited_only = false;
         // Whether progress updates should be published.
         bool do_progress_updates = false;
         // The mode we'll use when calling IDumpstateDevice::dumpstateBoard.
diff --git a/cmds/dumpstate/main.cpp b/cmds/dumpstate/main.cpp
index f1342a5..ec89c0d 100644
--- a/cmds/dumpstate/main.cpp
+++ b/cmds/dumpstate/main.cpp
@@ -30,7 +30,7 @@
     bool do_wait = false;
     int c;
     // Keep flags in sync with Dumpstate::DumpOptions::Initialize.
-    while ((c = getopt(argc, argv, "dho:svqzpAPBRSV:w")) != -1 && !do_wait) {
+    while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1 && !do_wait) {
         switch (c) {
             case 'w':
                 do_wait = true;
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 7078521..e94e51c 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -179,7 +179,7 @@
     EXPECT_FALSE(options_.do_screenshot);
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
-    EXPECT_FALSE(options_.arc_only);
+    EXPECT_FALSE(options_.limited_only);
     EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
 }
 
@@ -207,7 +207,7 @@
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
     EXPECT_FALSE(options_.use_socket);
-    EXPECT_FALSE(options_.arc_only);
+    EXPECT_FALSE(options_.limited_only);
     EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
 }
 
@@ -233,7 +233,7 @@
     EXPECT_FALSE(options_.do_screenshot);
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
-    EXPECT_FALSE(options_.arc_only);
+    EXPECT_FALSE(options_.limited_only);
     EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
 }
 
@@ -252,7 +252,7 @@
     EXPECT_FALSE(options_.is_remote_mode);
     EXPECT_FALSE(options_.use_socket);
     EXPECT_FALSE(options_.do_start_service);
-    EXPECT_FALSE(options_.arc_only);
+    EXPECT_FALSE(options_.limited_only);
 }
 
 TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) {
@@ -270,7 +270,7 @@
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_FALSE(options_.is_remote_mode);
     EXPECT_FALSE(options_.use_socket);
-    EXPECT_FALSE(options_.arc_only);
+    EXPECT_FALSE(options_.limited_only);
 }
 
 TEST_F(DumpOptionsTest, InitializeRemoteBugReport) {
@@ -287,7 +287,7 @@
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.use_socket);
-    EXPECT_FALSE(options_.arc_only);
+    EXPECT_FALSE(options_.limited_only);
 }
 
 TEST_F(DumpOptionsTest, InitializeWearBugReport) {
@@ -305,7 +305,7 @@
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_FALSE(options_.is_remote_mode);
     EXPECT_FALSE(options_.use_socket);
-    EXPECT_FALSE(options_.arc_only);
+    EXPECT_FALSE(options_.limited_only);
 }
 
 TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) {
@@ -323,7 +323,7 @@
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_FALSE(options_.is_remote_mode);
     EXPECT_FALSE(options_.use_socket);
-    EXPECT_FALSE(options_.arc_only);
+    EXPECT_FALSE(options_.limited_only);
 }
 
 TEST_F(DumpOptionsTest, InitializeWifiBugReport) {
@@ -341,10 +341,10 @@
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
     EXPECT_FALSE(options_.use_socket);
-    EXPECT_FALSE(options_.arc_only);
+    EXPECT_FALSE(options_.limited_only);
 }
 
-TEST_F(DumpOptionsTest, InitializeArcOnlyBugreport) {
+TEST_F(DumpOptionsTest, InitializeLimitedOnlyBugreport) {
     // clang-format off
     char* argv[] = {
         const_cast<char*>("dumpstatez"),
@@ -352,7 +352,7 @@
         const_cast<char*>("-d"),
         const_cast<char*>("-z"),
         const_cast<char*>("-q"),
-        const_cast<char*>("-A")
+        const_cast<char*>("-L")
     };
     // clang-format on
 
@@ -363,7 +363,7 @@
     EXPECT_TRUE(options_.do_zip_file);
     EXPECT_TRUE(options_.use_control_socket);
     EXPECT_FALSE(options_.do_vibrate);
-    EXPECT_TRUE(options_.arc_only);
+    EXPECT_TRUE(options_.limited_only);
 
     // Other options retain default values
     EXPECT_FALSE(options_.show_header_only);
@@ -400,7 +400,7 @@
     EXPECT_FALSE(options_.is_remote_mode);
     EXPECT_FALSE(options_.use_socket);
     EXPECT_FALSE(options_.wifi_only);
-    EXPECT_FALSE(options_.arc_only);
+    EXPECT_FALSE(options_.limited_only);
 }
 
 TEST_F(DumpOptionsTest, InitializePartial1) {
@@ -430,7 +430,7 @@
     EXPECT_FALSE(options_.do_screenshot);
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
-    EXPECT_FALSE(options_.arc_only);
+    EXPECT_FALSE(options_.limited_only);
     EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
 }
 
@@ -460,7 +460,7 @@
     EXPECT_FALSE(options_.do_zip_file);
     EXPECT_FALSE(options_.use_socket);
     EXPECT_FALSE(options_.use_control_socket);
-    EXPECT_FALSE(options_.arc_only);
+    EXPECT_FALSE(options_.limited_only);
     EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
 }
 
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 2a27a9a..e62a61f 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -691,8 +691,7 @@
         return result;
     }
 
-    virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const
-    {
+    virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) {
         if (!outLayers) {
             return UNEXPECTED_NULL;
         }
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 0d33b3f..b49fa1b 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -354,7 +354,7 @@
      *
      * Requires the ACCESS_SURFACE_FLINGER permission.
      */
-    virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const = 0;
+    virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) = 0;
 
     virtual status_t getColorManagement(bool* outGetColorManagement) const = 0;
 
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index a1d12a5..c2b4ef9 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -785,7 +785,7 @@
         return NO_ERROR;
     }
     status_t injectVSync(nsecs_t /*when*/) override { return NO_ERROR; }
-    status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* /*layers*/) const override {
+    status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* /*layers*/) override {
         return NO_ERROR;
     }
     status_t getCompositionPreference(
diff --git a/services/automotive/display/android.frameworks.automotive.display@1.0-service.rc b/services/automotive/display/android.frameworks.automotive.display@1.0-service.rc
index ffb7b5e..5c7f344 100644
--- a/services/automotive/display/android.frameworks.automotive.display@1.0-service.rc
+++ b/services/automotive/display/android.frameworks.automotive.display@1.0-service.rc
@@ -2,4 +2,3 @@
     class hal
     user graphics
     group automotive_evs
-    disabled  # will not automatically start with its class; must be explicitly started.
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index e6e3347..8dddd6d 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -3640,7 +3640,8 @@
             continue;
         }
 
-        if (oldHandlesById.find(handle->getId()) != oldHandlesById.end()) {
+        if ((oldHandlesById.find(handle->getId()) != oldHandlesById.end()) &&
+                (oldHandlesById.at(handle->getId())->getToken() == handle->getToken())) {
             const sp<InputWindowHandle>& oldHandle = oldHandlesById.at(handle->getId());
             oldHandle->updateFrom(handle);
             newHandles.push_back(oldHandle);
diff --git a/services/sensorservice/SensorDeviceUtils.h b/services/sensorservice/SensorDeviceUtils.h
index d7e621c..c232f0b 100644
--- a/services/sensorservice/SensorDeviceUtils.h
+++ b/services/sensorservice/SensorDeviceUtils.h
@@ -36,7 +36,7 @@
     // Increase the value of the sensor's nominal resolution to ensure that
     // sensor accuracy improvements, like runtime calibration, are not masked
     // during requantization.
-    double incRes = 0.25 * resolution;
+    double incRes = 0.125 * resolution;
     *value = round(static_cast<double>(*value) / incRes) * incRes;
 }
 
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 97ffe6f..0e69f60 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -148,6 +148,11 @@
     virtual status_t updateActiveBuffer() = 0;
     virtual status_t updateFrameNumber(nsecs_t latchTime) = 0;
 
+    // We generate InputWindowHandles for all buffered layers regardless of whether they
+    // have an InputChannel. This is to enable the InputDispatcher to do PID based occlusion
+    // detection.
+    bool needsInputInfo() const override { return true; }
+
 protected:
     struct BufferInfo {
         nsecs_t mDesiredPresentTime;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 4f8fc41..790f2ec 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -33,7 +33,6 @@
 #include <renderengine/Image.h>
 
 #include "EffectLayer.h"
-#include "FrameTracer/FrameTracer.h"
 #include "TimeStats/TimeStats.h"
 
 namespace android {
@@ -98,9 +97,6 @@
 
     // Prevent tracing the same release multiple times.
     if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) {
-        mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber,
-                                           std::make_shared<FenceTime>(releaseFence),
-                                           FrameTracer::FrameEvent::RELEASE_FENCE);
         mPreviousReleasedFrameNumber = mPreviousFrameNumber;
     }
 }
@@ -277,9 +273,6 @@
     const int32_t layerId = getSequence();
     mFlinger->mTimeStats->setPostTime(layerId, mCurrentState.frameNumber, getName().c_str(),
                                       postTime);
-    mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str());
-    mFlinger->mFrameTracer->traceTimestamp(layerId, buffer->getId(), mCurrentState.frameNumber,
-                                           postTime, FrameTracer::FrameEvent::POST);
     desiredPresentTime = desiredPresentTime <= 0 ? 0 : desiredPresentTime;
     mCurrentState.desiredPresentTime = desiredPresentTime;
 
@@ -580,20 +573,13 @@
         status_t err = bindTextureImage();
         if (err != NO_ERROR) {
             mFlinger->mTimeStats->onDestroy(layerId);
-            mFlinger->mFrameTracer->onDestroy(layerId);
             return BAD_VALUE;
         }
     }
 
-    const uint64_t bufferID = getCurrentBufferId();
     mFlinger->mTimeStats->setAcquireFence(layerId, mDrawingState.frameNumber,
-                                          mBufferInfo.mFenceTime);
-    mFlinger->mFrameTracer->traceFence(layerId, bufferID, mDrawingState.frameNumber,
-                                       mBufferInfo.mFenceTime,
-                                       FrameTracer::FrameEvent::ACQUIRE_FENCE);
+                                          std::make_shared<FenceTime>(mDrawingState.acquireFence));
     mFlinger->mTimeStats->setLatchTime(layerId, mDrawingState.frameNumber, latchTime);
-    mFlinger->mFrameTracer->traceTimestamp(layerId, bufferID, mDrawingState.frameNumber, latchTime,
-                                           FrameTracer::FrameEvent::LATCH);
 
     mCurrentStateModified = false;
 
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index af76b81..8ac0561 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -208,13 +208,17 @@
         *outVsyncPeriod = static_cast<nsecs_t>(vsyncPeriodNanos);
     } else {
         // Get the default vsync period
-        HWConfigId configId = 0;
-        auto intError_2_1 = mComposer.getActiveConfig(mId, &configId);
-        error = static_cast<Error>(intError_2_1);
-        if (error == Error::NONE) {
-            auto config = mConfigs.at(configId);
-            *outVsyncPeriod = config->getVsyncPeriod();
+        std::shared_ptr<const Display::Config> config;
+        error = getActiveConfig(&config);
+        if (error != Error::NONE) {
+            return error;
         }
+        if (!config) {
+            // HWC has updated the display modes and hasn't notified us yet.
+            return Error::BAD_CONFIG;
+        }
+
+        *outVsyncPeriod = config->getVsyncPeriod();
     }
 
     return error;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index dcc213f..3255aac 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -229,13 +229,23 @@
     mFlinger->markLayerPendingRemovalLocked(this);
 }
 
+sp<Layer> Layer::getRootLayer() {
+    sp<Layer> parent = getParent();
+    if (parent == nullptr) {
+        return this;
+    }
+    return parent->getRootLayer();
+}
+
 void Layer::onRemovedFromCurrentState() {
-    auto layersInTree = getLayersInTree(LayerVector::StateSet::Current);
+    // Use the root layer since we want to maintain the hierarchy for the entire subtree.
+    auto layersInTree = getRootLayer()->getLayersInTree(LayerVector::StateSet::Current);
     std::sort(layersInTree.begin(), layersInTree.end());
-    for (const auto& layer : layersInTree) {
+
+    traverse(LayerVector::StateSet::Current, [&](Layer* layer) {
         layer->removeFromCurrentState();
         layer->removeRelativeZ(layersInTree);
-    }
+    });
 }
 
 void Layer::addToCurrentState() {
@@ -1501,7 +1511,7 @@
     LayerDebugInfo info;
     const State& ds = getDrawingState();
     info.mName = getName();
-    sp<Layer> parent = getParent();
+    sp<Layer> parent = mDrawingParent.promote();
     info.mParentName = parent ? parent->getName() : "none"s;
     info.mType = getType();
     info.mTransparentRegion = ds.activeTransparentRegion_legacy;
@@ -2343,6 +2353,16 @@
 }
 
 InputWindowInfo Layer::fillInputInfo() {
+    if (!hasInputInfo()) {
+        mDrawingState.inputInfo.name = getName();
+        mDrawingState.inputInfo.ownerUid = mCallingUid;
+        mDrawingState.inputInfo.ownerPid = mCallingPid;
+        mDrawingState.inputInfo.inputFeatures =
+            InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL;
+        mDrawingState.inputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL;
+        mDrawingState.inputInfo.displayId = getLayerStack();
+    }
+
     InputWindowInfo info = mDrawingState.inputInfo;
     info.id = sequence;
 
@@ -2424,7 +2444,7 @@
     return mDrawingParent.promote()->getClonedRoot();
 }
 
-bool Layer::hasInput() const {
+bool Layer::hasInputInfo() const {
     return mDrawingState.inputInfo.token != nullptr;
 }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3fa935f..068424b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -947,7 +947,17 @@
     void setInputInfo(const InputWindowInfo& info);
 
     InputWindowInfo fillInputInfo();
-    bool hasInput() const;
+    /**
+     * Returns whether this layer has an explicitly set input-info.
+     */
+    bool hasInputInfo() const;
+    /**
+     * Return whether this layer needs an input info. For most layer types
+     * this is only true if they explicitly set an input-info but BufferLayer
+     * overrides this so we can generate input-info for Buffered layers that don't
+     * have them (for input occlusion detection checks).
+     */
+    virtual bool needsInputInfo() const { return hasInputInfo(); }
 
 protected:
     compositionengine::OutputLayer* findOutputLayerForDisplay(const DisplayDevice*) const;
@@ -1088,6 +1098,10 @@
     // Find the root of the cloned hierarchy, this means the first non cloned parent.
     // This will return null if first non cloned parent is not found.
     sp<Layer> getClonedRoot();
+
+    // Finds the top most layer in the hierarchy. This will find the root Layer where the parent is
+    // null.
+    sp<Layer> getRootLayer();
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.cpp b/services/surfaceflinger/Scheduler/VSyncModulator.cpp
index 40a992c..510dc2d 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.cpp
@@ -25,6 +25,7 @@
 #include <cutils/properties.h>
 #include <utils/Trace.h>
 
+#include <chrono>
 #include <cinttypes>
 #include <mutex>
 
@@ -52,6 +53,7 @@
 void VSyncModulator::setTransactionStart(Scheduler::TransactionStart transactionStart) {
     if (transactionStart == Scheduler::TransactionStart::EARLY) {
         mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT_TRANSACTION;
+        mEarlyTxnStartTime = std::chrono::steady_clock::now();
     }
 
     // An early transaction stays an early transaction.
@@ -64,6 +66,7 @@
 }
 
 void VSyncModulator::onTransactionHandled() {
+    mTxnAppliedTime = std::chrono::steady_clock::now();
     if (mTransactionStart == Scheduler::TransactionStart::NORMAL) return;
     mTransactionStart = Scheduler::TransactionStart::NORMAL;
     updateOffsets();
@@ -87,9 +90,16 @@
 
 void VSyncModulator::onRefreshed(bool usedRenderEngine) {
     bool updateOffsetsNeeded = false;
-    if (mRemainingEarlyFrameCount > 0) {
-        mRemainingEarlyFrameCount--;
-        updateOffsetsNeeded = true;
+
+    // Apply a 1ms margin to account for potential data races
+    // This might make us stay in early offsets for one
+    // additional frame but it's better to be conservative here.
+    static const constexpr std::chrono::nanoseconds kMargin = 1ms;
+    if ((mEarlyTxnStartTime.load() + kMargin) < mTxnAppliedTime.load()) {
+        if (mRemainingEarlyFrameCount > 0) {
+            mRemainingEarlyFrameCount--;
+            updateOffsetsNeeded = true;
+        }
     }
     if (usedRenderEngine) {
         mRemainingRenderEngineUsageCount = MIN_EARLY_GL_FRAME_COUNT_TRANSACTION;
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index 704a5d5..d777ef9 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <chrono>
 #include <mutex>
 
 #include "Scheduler.h"
@@ -110,6 +111,8 @@
     std::atomic<bool> mRefreshRateChangePending = false;
     std::atomic<int> mRemainingEarlyFrameCount = 0;
     std::atomic<int> mRemainingRenderEngineUsageCount = 0;
+    std::atomic<std::chrono::steady_clock::time_point> mEarlyTxnStartTime = {};
+    std::atomic<std::chrono::steady_clock::time_point> mTxnAppliedTime = {};
 
     bool mTraceDetailedInfo = false;
 };
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
index 16d102c..c743de0 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
@@ -278,7 +278,9 @@
         return false;
     }
 
-    if (mSupportKernelIdleTimer) {
+    const bool periodIsChanging =
+            mPeriodTransitioningTo && (*mPeriodTransitioningTo != getPeriod());
+    if (mSupportKernelIdleTimer && !periodIsChanging) {
         // Clear out the Composer-provided period and use the allowance logic below
         HwcVsyncPeriod = {};
     }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5ba7839..fbfe448 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1449,17 +1449,14 @@
     return mScheduler->injectVSync(when, calculateExpectedPresentTime(when)) ? NO_ERROR : BAD_VALUE;
 }
 
-status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const {
-    TimedLock lock(mStateLock, s2ns(1), __FUNCTION__);
-    if (!lock.locked()) {
-        return TIMED_OUT;
-    }
-
-    const auto display = getDefaultDisplayDeviceLocked();
+status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) {
     outLayers->clear();
-    mCurrentState.traverseInZOrder(
-            [&](Layer* layer) { outLayers->push_back(layer->getLayerDebugInfo(display.get())); });
-
+    schedule([=] {
+        const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
+        mDrawingState.traverseInZOrder([&](Layer* layer) {
+            outLayers->push_back(layer->getLayerDebugInfo(display.get()));
+        });
+    }).wait();
     return NO_ERROR;
 }
 
@@ -1934,6 +1931,7 @@
     // ...but if it's larger than 1s then we missed the trace cutoff.
     static constexpr nsecs_t kMaxJankyDuration =
             std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
+    nsecs_t jankDurationToUpload = -1;
     // If we're in a user build then don't push any atoms
     if (!mIsUserBuild && mMissedFrameJankCount > 0) {
         const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
@@ -1945,10 +1943,7 @@
             const nsecs_t currentTime = systemTime();
             const nsecs_t jankDuration = currentTime - mMissedFrameJankStart;
             if (jankDuration > kMinJankyDuration && jankDuration < kMaxJankyDuration) {
-                ATRACE_NAME("Jank detected");
-                const int32_t jankyDurationMillis = jankDuration / (1000 * 1000);
-                android::util::stats_write(android::util::DISPLAY_JANK_REPORTED,
-                                           jankyDurationMillis, mMissedFrameJankCount);
+                jankDurationToUpload = jankDuration;
             }
 
             // We either reported a jank event or we missed the trace
@@ -2001,6 +1996,7 @@
 
     refreshNeeded |= mRepaintEverything;
     if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) {
+        mLastJankDuration = jankDurationToUpload;
         // Signal a refresh if a transaction modified the window state,
         // a new buffer was latched, or if HWC has requested a full
         // repaint
@@ -2307,6 +2303,14 @@
     const size_t appConnections = mScheduler->getEventThreadConnectionCount(mAppConnectionHandle);
     mTimeStats->recordDisplayEventConnectionCount(sfConnections + appConnections);
 
+    if (mLastJankDuration > 0) {
+        ATRACE_NAME("Jank detected");
+        const int32_t jankyDurationMillis = mLastJankDuration / (1000 * 1000);
+        android::util::stats_write(android::util::DISPLAY_JANK_REPORTED, jankyDurationMillis,
+                                   mMissedFrameJankCount);
+        mLastJankDuration = -1;
+    }
+
     if (isDisplayConnected && !display->isPoweredOn()) {
         return;
     }
@@ -2904,7 +2908,7 @@
     std::vector<InputWindowInfo> inputHandles;
 
     mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
-        if (layer->hasInput()) {
+        if (layer->needsInputInfo()) {
             // When calculating the screen bounds we ignore the transparent region since it may
             // result in an unwanted offset.
             inputHandles.push_back(layer->fillInputInfo());
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 113b035..e7bfdc7 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -466,7 +466,7 @@
                                 HdrCapabilities* outCapabilities) const override;
     status_t enableVSyncInjections(bool enable) override;
     status_t injectVSync(nsecs_t when) override;
-    status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const override;
+    status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) override;
     status_t getColorManagement(bool* outGetColorManagement) const override;
     status_t getCompositionPreference(ui::Dataspace* outDataspace, ui::PixelFormat* outPixelFormat,
                                       ui::Dataspace* outWideColorGamutDataspace,
@@ -1287,6 +1287,8 @@
     // janky frames there are.
     nsecs_t mMissedFrameJankStart = 0;
     int32_t mMissedFrameJankCount = 0;
+    // Positive if jank should be uploaded in postComposition
+    nsecs_t mLastJankDuration = -1;
 
     int mFrameRateFlexibilityTokenCount = 0;
 
diff --git a/services/surfaceflinger/tests/RelativeZ_test.cpp b/services/surfaceflinger/tests/RelativeZ_test.cpp
index 1180cac..3e0b3c6 100644
--- a/services/surfaceflinger/tests/RelativeZ_test.cpp
+++ b/services/surfaceflinger/tests/RelativeZ_test.cpp
@@ -207,6 +207,71 @@
         sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b);
     }
 }
+
+// Preserve the relative z order when a layer is reparented to a layer that's already offscreen
+TEST_F(RelativeZTest, LayerWithRelativeReparentedToOffscreen) {
+    std::unique_ptr<ScreenCapture> sc;
+
+    Color testLayerColor = {255, 100, 0, 255};
+
+    // Background layer (RED)
+    // Foregroud layer (GREEN)
+    //   child level 1a (testLayerColor) (relative to child level 2b)
+    //   child level 1b (WHITE)
+    //     child level 2a (BLUE)
+    //     child level 2b (BLACK)
+    sp<SurfaceControl> childLevel1a =
+            createColorLayer("child level 1a", testLayerColor, mForegroundLayer.get());
+    sp<SurfaceControl> childLevel1b =
+            createColorLayer("child level 1b", Color::WHITE, mForegroundLayer.get());
+    sp<SurfaceControl> childLevel2a =
+            createColorLayer("child level 2a", Color::BLUE, childLevel1b.get());
+    sp<SurfaceControl> childLevel2b =
+            createColorLayer("child level 2b", Color::BLACK, childLevel1b.get());
+
+    Transaction{}
+            .setRelativeLayer(childLevel1a, childLevel2b->getHandle(), 1)
+            .show(childLevel1a)
+            .show(childLevel1b)
+            .show(childLevel2a)
+            .show(childLevel2b)
+            .apply();
+
+    {
+        // The childLevel1a should be in front of childLevel2b.
+        ScreenCapture::captureScreen(&sc);
+        sc->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), testLayerColor);
+    }
+
+    // Background layer (RED)
+    // Foregroud layer (GREEN)
+    //   child level 1a (testLayerColor) (relative to child level 2b)
+    Transaction{}.reparent(childLevel1b, nullptr).apply();
+
+    // // Background layer (RED)
+    // // Foregroud layer (GREEN)
+    Transaction{}.reparent(childLevel1a, childLevel2a->getHandle()).apply();
+
+    {
+        // The childLevel1a and childLevel1b are no longer on screen
+        ScreenCapture::captureScreen(&sc);
+        sc->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::GREEN);
+    }
+
+    // Background layer (RED)
+    // Foregroud layer (GREEN)
+    //   child level 1b (WHITE)
+    //     child level 2a (BLUE)
+    //       child level 1a (testLayerColor) (relative to child level 2b)
+    //     child level 2b (BLACK)
+    Transaction{}.reparent(childLevel1b, mForegroundLayer->getHandle()).apply();
+
+    {
+        // Nothing should change at this point since relative z info was preserved.
+        ScreenCapture::captureScreen(&sc);
+        sc->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), testLayerColor);
+    }
+}
 } // namespace android
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
index ccbd17f..a972562 100644
--- a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
@@ -672,15 +672,30 @@
                                     kPendingLimit, true /* supportKernelIdleTimer */);
 
     bool periodFlushed = true;
-    EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(2);
+    EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(5);
     idleReactor.setIgnorePresentFences(true);
 
-    nsecs_t const newPeriod = 5000;
-    idleReactor.setPeriod(newPeriod);
-
+    // First, set the same period, which should only be confirmed when we receive two
+    // matching callbacks
+    idleReactor.setPeriod(10000);
     EXPECT_TRUE(idleReactor.addResyncSample(0, 0, &periodFlushed));
     EXPECT_FALSE(periodFlushed);
-    EXPECT_FALSE(idleReactor.addResyncSample(newPeriod, 0, &periodFlushed));
+    // Correct period but incorrect timestamp delta
+    EXPECT_TRUE(idleReactor.addResyncSample(0, 10000, &periodFlushed));
+    EXPECT_FALSE(periodFlushed);
+    // Correct period and correct timestamp delta
+    EXPECT_FALSE(idleReactor.addResyncSample(10000, 10000, &periodFlushed));
+    EXPECT_TRUE(periodFlushed);
+
+    // Then, set a new period, which should be confirmed as soon as we receive a callback
+    // reporting the new period
+    nsecs_t const newPeriod = 5000;
+    idleReactor.setPeriod(newPeriod);
+    // Incorrect timestamp delta and period
+    EXPECT_TRUE(idleReactor.addResyncSample(20000, 10000, &periodFlushed));
+    EXPECT_FALSE(periodFlushed);
+    // Incorrect timestamp delta but correct period
+    EXPECT_FALSE(idleReactor.addResyncSample(20000, 5000, &periodFlushed));
     EXPECT_TRUE(periodFlushed);
 
     EXPECT_TRUE(idleReactor.addPresentFence(generateSignalledFenceWithTime(0)));