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)));