Loading services/surfaceflinger/SurfaceFlinger.cpp +119 −111 Original line number Diff line number Diff line Loading @@ -125,6 +125,19 @@ #include "android-base/parseint.h" #include "android-base/stringprintf.h" #define MAIN_THREAD ACQUIRE(mStateLock) RELEASE(mStateLock) #define ON_MAIN_THREAD(expr) \ [&] { \ LOG_FATAL_IF(std::this_thread::get_id() != mMainThreadId); \ UnnecessaryLock lock(mStateLock); \ return (expr); \ }() #undef NO_THREAD_SAFETY_ANALYSIS #define NO_THREAD_SAFETY_ANALYSIS \ _Pragma("GCC error \"Prefer MAIN_THREAD macros or {Conditional,Timed,Unnecessary}Lock.\"") namespace android { using namespace std::string_literals; Loading Loading @@ -173,12 +186,12 @@ bool isWideColorMode(const ColorMode colorMode) { #pragma clang diagnostic pop template <typename Mutex> struct ConditionalLockGuard { ConditionalLockGuard(Mutex& mutex, bool lock) : mutex(mutex), lock(lock) { struct SCOPED_CAPABILITY ConditionalLockGuard { ConditionalLockGuard(Mutex& mutex, bool lock) ACQUIRE(mutex) : mutex(mutex), lock(lock) { if (lock) mutex.lock(); } ~ConditionalLockGuard() { ~ConditionalLockGuard() RELEASE() { if (lock) mutex.unlock(); } Loading @@ -188,6 +201,27 @@ struct ConditionalLockGuard { using ConditionalLock = ConditionalLockGuard<Mutex>; struct SCOPED_CAPABILITY TimedLock { TimedLock(Mutex& mutex, nsecs_t timeout, const char* whence) ACQUIRE(mutex) : mutex(mutex), status(mutex.timedLock(timeout)) { ALOGE_IF(!locked(), "%s timed out locking: %s (%d)", whence, strerror(-status), status); } ~TimedLock() RELEASE() { if (locked()) mutex.unlock(); } bool locked() const { return status == NO_ERROR; } Mutex& mutex; const status_t status; }; struct SCOPED_CAPABILITY UnnecessaryLock { explicit UnnecessaryLock(Mutex& mutex) ACQUIRE(mutex) {} ~UnnecessaryLock() RELEASE() {} }; // TODO(b/141333600): Consolidate with HWC2::Display::Config::Builder::getDefaultDensity. constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV; Loading Loading @@ -991,7 +1025,7 @@ status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mo } auto future = schedule([=]() -> status_t { const auto display = getDisplayDeviceLocked(displayToken); const auto display = ON_MAIN_THREAD(getDisplayDeviceLocked(displayToken)); if (!display) { ALOGE("Attempt to set allowed display configs for invalid display token %p", displayToken.get()); Loading Loading @@ -1176,7 +1210,7 @@ ColorMode SurfaceFlinger::getActiveColorMode(const sp<IBinder>& displayToken) { } status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, ColorMode mode) { schedule([=] { schedule([=]() MAIN_THREAD { Vector<ColorMode> modes; getDisplayColorModes(displayToken, &modes); bool exists = std::find(std::begin(modes), std::end(modes), mode) != std::end(modes); Loading Loading @@ -1222,7 +1256,7 @@ status_t SurfaceFlinger::getAutoLowLatencyModeSupport(const sp<IBinder>& display } void SurfaceFlinger::setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on) { static_cast<void>(schedule([=] { static_cast<void>(schedule([=]() MAIN_THREAD { if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) { getHwComposer().setAutoLowLatencyMode(*displayId, on); } else { Loading Loading @@ -1253,7 +1287,7 @@ status_t SurfaceFlinger::getGameContentTypeSupport(const sp<IBinder>& displayTok } void SurfaceFlinger::setGameContentType(const sp<IBinder>& displayToken, bool on) { static_cast<void>(schedule([=] { static_cast<void>(schedule([=]() MAIN_THREAD { if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) { const auto type = on ? hal::ContentType::GAME : hal::ContentType::NONE; getHwComposer().setContentType(*displayId, type); Loading Loading @@ -1343,7 +1377,7 @@ status_t SurfaceFlinger::getDisplayedContentSamplingAttributes(const sp<IBinder> status_t SurfaceFlinger::setDisplayContentSamplingEnabled(const sp<IBinder>& displayToken, bool enable, uint8_t componentMask, uint64_t maxFrames) { return schedule([=]() -> status_t { return schedule([=]() MAIN_THREAD -> status_t { if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) { return getHwComposer().setDisplayContentSamplingEnabled(*displayId, enable, componentMask, Loading Loading @@ -1412,13 +1446,9 @@ status_t SurfaceFlinger::injectVSync(nsecs_t when) { return mScheduler->injectVSync(when, calculateExpectedPresentTime(when)) ? NO_ERROR : BAD_VALUE; } status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const NO_THREAD_SAFETY_ANALYSIS { // Try to acquire a lock for 1s, fail gracefully const status_t err = mStateLock.timedLock(s2ns(1)); const bool locked = (err == NO_ERROR); if (!locked) { ALOGE("LayerDebugInfo: SurfaceFlinger unresponsive (%s [%d]) - exit", strerror(-err), err); status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const { TimedLock lock(mStateLock, s2ns(1), __FUNCTION__); if (!lock.locked()) { return TIMED_OUT; } Loading @@ -1427,7 +1457,6 @@ status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayer mCurrentState.traverseInZOrder( [&](Layer* layer) { outLayers->push_back(layer->getLayerDebugInfo(display.get())); }); mStateLock.unlock(); return NO_ERROR; } Loading Loading @@ -1484,7 +1513,7 @@ status_t SurfaceFlinger::setDisplayBrightness(const sp<IBinder>& displayToken, f return BAD_VALUE; } return promise::chain(schedule([=] { return promise::chain(schedule([=]() MAIN_THREAD { if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) { return getHwComposer().setDisplayBrightness(*displayId, brightness); } else { Loading Loading @@ -1597,7 +1626,7 @@ void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate, } void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId, hal::Connection connection) NO_THREAD_SAFETY_ANALYSIS { hal::Connection connection) { ALOGV("%s(%d, %" PRIu64 ", %s)", __FUNCTION__, sequenceId, hwcDisplayId, connection == hal::Connection::CONNECTED ? "connected" : "disconnected"); Loading Loading @@ -1650,8 +1679,7 @@ void SurfaceFlinger::setPrimaryVsyncEnabled(bool enabled) { // Enable / Disable HWVsync from the main thread to avoid race conditions with // display power state. static_cast<void>( schedule([=]() NO_THREAD_SAFETY_ANALYSIS { setPrimaryVsyncEnabledInternal(enabled); })); static_cast<void>(schedule([=]() MAIN_THREAD { setPrimaryVsyncEnabledInternal(enabled); })); } void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) { Loading @@ -1667,7 +1695,6 @@ void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) { } } // Note: it is assumed the caller holds |mStateLock| when this is called void SurfaceFlinger::resetDisplayState() { mScheduler->disableHardwareVsync(true); // Clear the drawing state so that the logic inside of Loading Loading @@ -1760,7 +1787,7 @@ void SurfaceFlinger::updateVrFlinger() { setTransactionFlags(eDisplayTransactionNeeded); } sp<Fence> SurfaceFlinger::previousFrameFence() NO_THREAD_SAFETY_ANALYSIS { sp<Fence> SurfaceFlinger::previousFrameFence() { // We are storing the last 2 present fences. If sf's phase offset is to be // woken up before the actual vsync but targeting the next vsync, we need to check // fence N-2 Loading @@ -1768,7 +1795,7 @@ sp<Fence> SurfaceFlinger::previousFrameFence() NO_THREAD_SAFETY_ANALYSIS { : mPreviousPresentFences[1]; } bool SurfaceFlinger::previousFramePending(int graceTimeMs) NO_THREAD_SAFETY_ANALYSIS { bool SurfaceFlinger::previousFramePending(int graceTimeMs) { ATRACE_CALL(); const sp<Fence>& fence = previousFrameFence(); Loading @@ -1782,7 +1809,7 @@ bool SurfaceFlinger::previousFramePending(int graceTimeMs) NO_THREAD_SAFETY_ANAL return status == -ETIME; } nsecs_t SurfaceFlinger::previousFramePresentTime() NO_THREAD_SAFETY_ANALYSIS { nsecs_t SurfaceFlinger::previousFramePresentTime() { const sp<Fence>& fence = previousFrameFence(); if (fence == Fence::NO_FENCE) { Loading @@ -1800,8 +1827,7 @@ nsecs_t SurfaceFlinger::calculateExpectedPresentTime(nsecs_t now) const { return mVSyncModulator->getOffsets().sf > 0 ? presentTime : presentTime + stats.vsyncPeriod; } void SurfaceFlinger::onMessageReceived(int32_t what, nsecs_t expectedVSyncTime) NO_THREAD_SAFETY_ANALYSIS { void SurfaceFlinger::onMessageReceived(int32_t what, nsecs_t expectedVSyncTime) { ATRACE_CALL(); switch (what) { case MessageQueue::INVALIDATE: { Loading @@ -1815,7 +1841,7 @@ void SurfaceFlinger::onMessageReceived(int32_t what, } } void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) NO_THREAD_SAFETY_ANALYSIS { void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) { ATRACE_CALL(); const nsecs_t frameStart = systemTime(); Loading Loading @@ -1888,7 +1914,7 @@ void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) NO_THREAD_SA // We received the present fence from the HWC, so we assume it successfully updated // the config, hence we update SF. mSetActiveConfigPending = false; setActiveConfigInternal(); ON_MAIN_THREAD(setActiveConfigInternal()); } if (framePending && mPropagateBackpressure) { Loading @@ -1907,12 +1933,12 @@ void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) NO_THREAD_SA std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count(); // If we're in a user build then don't push any atoms if (!mIsUserBuild && mMissedFrameJankCount > 0) { const auto displayDevice = getDefaultDisplayDeviceLocked(); const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); // Only report jank when the display is on, as displays in DOZE // power mode may operate at a different frame rate than is // reported in their config, which causes noticeable (but less // severe) jank. if (displayDevice && displayDevice->getPowerMode() == hal::PowerMode::ON) { if (display && display->getPowerMode() == hal::PowerMode::ON) { const nsecs_t currentTime = systemTime(); const nsecs_t jankDuration = currentTime - mMissedFrameJankStart; if (jankDuration > kMinJankyDuration && jankDuration < kMaxJankyDuration) { Loading Loading @@ -1969,7 +1995,7 @@ void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) NO_THREAD_SA mScheduler->chooseRefreshRateForContent(); } performSetActiveConfig(); ON_MAIN_THREAD(performSetActiveConfig()); updateCursorAsync(); updateInputFlinger(); Loading Loading @@ -2018,8 +2044,9 @@ void SurfaceFlinger::onMessageRefresh() { mRefreshPending = false; compositionengine::CompositionRefreshArgs refreshArgs; refreshArgs.outputs.reserve(mDisplays.size()); for (const auto& [_, display] : mDisplays) { const auto& displays = ON_MAIN_THREAD(mDisplays); refreshArgs.outputs.reserve(displays.size()); for (const auto& [_, display] : displays) { refreshArgs.outputs.push_back(display->getCompositionDisplay()); } mDrawingState.traverseInZOrder([&refreshArgs](Layer* layer) { Loading Loading @@ -2074,21 +2101,18 @@ void SurfaceFlinger::onMessageRefresh() { const bool prevFrameHadDeviceComposition = mHadDeviceComposition; mHadClientComposition = std::any_of(mDisplays.cbegin(), mDisplays.cend(), [](const auto& tokenDisplayPair) { auto& displayDevice = tokenDisplayPair.second; return displayDevice->getCompositionDisplay()->getState().usesClientComposition && !displayDevice->getCompositionDisplay()->getState().reusedClientComposition; mHadClientComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) { const auto& state = pair.second->getCompositionDisplay()->getState(); return state.usesClientComposition && !state.reusedClientComposition; }); mHadDeviceComposition = std::any_of(mDisplays.cbegin(), mDisplays.cend(), [](const auto& tokenDisplayPair) { auto& displayDevice = tokenDisplayPair.second; return displayDevice->getCompositionDisplay()->getState().usesDeviceComposition; mHadDeviceComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) { const auto& state = pair.second->getCompositionDisplay()->getState(); return state.usesDeviceComposition; }); mReusedClientComposition = std::any_of(mDisplays.cbegin(), mDisplays.cend(), [](const auto& tokenDisplayPair) { auto& displayDevice = tokenDisplayPair.second; return displayDevice->getCompositionDisplay()->getState().reusedClientComposition; std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) { const auto& state = pair.second->getCompositionDisplay()->getState(); return state.reusedClientComposition; }); // Only report a strategy change if we move in and out of composition with hw overlays Loading Loading @@ -2194,14 +2218,14 @@ void SurfaceFlinger::postComposition() for (auto& layer : mLayersWithQueuedFrames) { layer->releasePendingBuffer(dequeueReadyTime); } // |mStateLock| not needed as we are on the main thread const auto displayDevice = getDefaultDisplayDeviceLocked(); const auto* display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()).get(); getBE().mGlCompositionDoneTimeline.updateSignalTimes(); std::shared_ptr<FenceTime> glCompositionDoneFenceTime; if (displayDevice && displayDevice->getCompositionDisplay()->getState().usesClientComposition) { if (display && display->getCompositionDisplay()->getState().usesClientComposition) { glCompositionDoneFenceTime = std::make_shared<FenceTime>(displayDevice->getCompositionDisplay() std::make_shared<FenceTime>(display->getCompositionDisplay() ->getRenderSurface() ->getClientTargetAcquireFence()); getBE().mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime); Loading @@ -2211,9 +2235,8 @@ void SurfaceFlinger::postComposition() getBE().mDisplayTimeline.updateSignalTimes(); mPreviousPresentFences[1] = mPreviousPresentFences[0]; mPreviousPresentFences[0] = displayDevice ? getHwComposer().getPresentFence(*displayDevice->getId()) : Fence::NO_FENCE; mPreviousPresentFences[0] = display ? getHwComposer().getPresentFence(*display->getId()) : Fence::NO_FENCE; auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFences[0]); getBE().mDisplayTimeline.push(presentFenceTime); Loading @@ -2232,8 +2255,7 @@ void SurfaceFlinger::postComposition() } mDrawingState.traverse([&](Layer* layer) { const bool frameLatched = layer->onPostComposition(displayDevice.get(), glCompositionDoneFenceTime, const bool frameLatched = layer->onPostComposition(display, glCompositionDoneFenceTime, presentFenceTime, compositorTiming); if (frameLatched) { recordBufferingStats(layer->getName(), layer->getOccupancyHistory(false)); Loading @@ -2243,14 +2265,15 @@ void SurfaceFlinger::postComposition() mTransactionCompletedThread.addPresentFence(mPreviousPresentFences[0]); mTransactionCompletedThread.sendCallbacks(); if (displayDevice && displayDevice->isPrimary() && displayDevice->getPowerMode() == hal::PowerMode::ON && presentFenceTime->isValid()) { if (display && display->isPrimary() && display->getPowerMode() == hal::PowerMode::ON && presentFenceTime->isValid()) { mScheduler->addPresentFence(presentFenceTime); } const bool isDisplayConnected = display && getHwComposer().isConnected(*display->getId()); if (!hasSyncFramework) { if (displayDevice && getHwComposer().isConnected(*displayDevice->getId()) && displayDevice->isPoweredOn()) { if (isDisplayConnected && display->isPoweredOn()) { mScheduler->enableHardwareVsync(); } } Loading @@ -2261,11 +2284,10 @@ void SurfaceFlinger::postComposition() if (presentFenceTime->isValid()) { mAnimFrameTracker.setActualPresentFence( std::move(presentFenceTime)); } else if (displayDevice && getHwComposer().isConnected(*displayDevice->getId())) { } else if (isDisplayConnected) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(*displayDevice->getId()); const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(*display->getId()); mAnimFrameTracker.setActualPresentTime(presentTime); } mAnimFrameTracker.advanceFrame(); Loading @@ -2286,8 +2308,7 @@ void SurfaceFlinger::postComposition() const size_t appConnections = mScheduler->getEventThreadConnectionCount(mAppConnectionHandle); mTimeStats->recordDisplayEventConnectionCount(sfConnections + appConnections); if (displayDevice && getHwComposer().isConnected(*displayDevice->getId()) && !displayDevice->isPoweredOn()) { if (isDisplayConnected && !display->isPoweredOn()) { return; } Loading Loading @@ -2343,7 +2364,7 @@ FloatRect SurfaceFlinger::getLayerClipBoundsForDisplay(const DisplayDevice& disp } void SurfaceFlinger::computeLayerBounds() { for (const auto& pair : mDisplays) { for (const auto& pair : ON_MAIN_THREAD(mDisplays)) { const auto& displayDevice = pair.second; const auto display = displayDevice->getCompositionDisplay(); for (const auto& layer : mDrawingState.layersSortedByZ) { Loading @@ -2358,10 +2379,8 @@ void SurfaceFlinger::computeLayerBounds() { } } void SurfaceFlinger::postFrame() { // |mStateLock| not needed as we are on the main thread const auto display = getDefaultDisplayDeviceLocked(); void SurfaceFlinger::postFrame() { const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); if (display && getHwComposer().isConnected(*display->getId())) { uint32_t flipCount = display->getPageFlipCount(); if (flipCount % LOG_FRAME_STATS_PERIOD == 0) { Loading Loading @@ -2789,7 +2808,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) sp<const DisplayDevice> hintDisplay; uint32_t currentlayerStack = 0; bool first = true; mCurrentState.traverse([&](Layer* layer) { mCurrentState.traverse([&](Layer* layer) REQUIRES(mStateLock) { // NOTE: we rely on the fact that layers are sorted by // layerStack first (so we don't have to traverse the list // of displays for every layer). Loading Loading @@ -2902,10 +2921,9 @@ void SurfaceFlinger::commitInputWindowCommands() { mPendingInputWindowCommands.clear(); } void SurfaceFlinger::updateCursorAsync() { void SurfaceFlinger::updateCursorAsync() { compositionengine::CompositionRefreshArgs refreshArgs; for (const auto& [_, display] : mDisplays) { for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) { if (display->getId()) { refreshArgs.outputs.push_back(display->getCompositionDisplay()); } Loading @@ -2915,7 +2933,7 @@ void SurfaceFlinger::updateCursorAsync() } void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate, Scheduler::ConfigEvent event) NO_THREAD_SAFETY_ANALYSIS { Scheduler::ConfigEvent event) { // If this is called from the main thread mStateLock must be locked before // Currently the only way to call this function from the main thread is from // Sheduler::chooseRefreshRateForContent Loading Loading @@ -3041,7 +3059,7 @@ void SurfaceFlinger::commitOffscreenLayers() { } void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) { for (const auto& [token, displayDevice] : mDisplays) { for (const auto& [token, displayDevice] : ON_MAIN_THREAD(mDisplays)) { auto display = displayDevice->getCompositionDisplay(); if (display->belongsInOutput(layer->getLayerStack(), layer->getPrimaryDisplayOnly())) { display->editState().dirtyRegion.orSelf(dirty); Loading Loading @@ -4137,7 +4155,7 @@ void SurfaceFlinger::onInitializeDisplays() { void SurfaceFlinger::initializeDisplays() { // Async since we may be called from the main thread. static_cast<void>(schedule([this]() NO_THREAD_SAFETY_ANALYSIS { onInitializeDisplays(); })); static_cast<void>(schedule([this]() MAIN_THREAD { onInitializeDisplays(); })); } void SurfaceFlinger::setVsyncEnabledInHWC(DisplayId displayId, hal::Vsync enabled) { Loading Loading @@ -4228,7 +4246,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: } void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) { schedule([=]() NO_THREAD_SAFETY_ANALYSIS { schedule([=]() MAIN_THREAD { const auto display = getDisplayDeviceLocked(displayToken); if (!display) { ALOGE("Attempt to set power mode %d for invalid display token %p", mode, Loading @@ -4241,8 +4259,7 @@ void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) { }).wait(); } status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) NO_THREAD_SAFETY_ANALYSIS { status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { std::string result; IPCThreadState* ipc = IPCThreadState::self(); Loading @@ -4254,18 +4271,6 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, StringAppendF(&result, "Permission Denial: can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid); } else { // Try to get the main lock, but give up after one second // (this would indicate SF is stuck, but we want to be able to // print something in dumpsys). status_t err = mStateLock.timedLock(s2ns(1)); bool locked = (err == NO_ERROR); if (!locked) { StringAppendF(&result, "SurfaceFlinger appears to be unresponsive (%s [%d]), dumping anyways " "(no locks held)\n", strerror(-err), err); } static const std::unordered_map<std::string, Dumper> dumpers = { {"--display-id"s, dumper(&SurfaceFlinger::dumpDisplayIdentificationData)}, {"--dispsync"s, Loading @@ -4283,18 +4288,23 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, const auto flag = args.empty() ? ""s : std::string(String8(args[0])); const auto it = dumpers.find(flag); if (it != dumpers.end()) { bool dumpLayers = true; { TimedLock lock(mStateLock, s2ns(1), __FUNCTION__); if (!lock.locked()) { StringAppendF(&result, "Dumping without lock after timeout: %s (%d)\n", strerror(-lock.status), lock.status); } if (const auto it = dumpers.find(flag); it != dumpers.end()) { (it->second)(args, asProto, result); dumpLayers = false; } else if (!asProto) { dumpAllLocked(args, result); } if (locked) { mStateLock.unlock(); } if (it == dumpers.end()) { if (dumpLayers) { const LayersProto layersProto = dumpProtoFromMainThread(); if (asProto) { result.append(layersProto.SerializeAsString()); Loading Loading @@ -4568,7 +4578,7 @@ void SurfaceFlinger::dumpWideColorInfo(std::string& result) const { LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { // If context is SurfaceTracing thread, mTracingLock blocks display transactions on main thread. const auto display = getDefaultDisplayDeviceLocked(); const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); LayersProto layersProto; for (const sp<Layer>& layer : mDrawingState.layersSortedByZ) { Loading Loading @@ -5404,7 +5414,7 @@ status_t SurfaceFlinger::setSchedFifo(bool enabled) { return NO_ERROR; } const sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) { sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) { const sp<IBinder> displayToken = getPhysicalDisplayTokenLocked(DisplayId{displayOrLayerStack}); if (displayToken) { return getDisplayDeviceLocked(displayToken); Loading @@ -5414,7 +5424,7 @@ const sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t disp return getDisplayByLayerStack(displayOrLayerStack); } const sp<DisplayDevice> SurfaceFlinger::getDisplayByLayerStack(uint64_t layerStack) { sp<DisplayDevice> SurfaceFlinger::getDisplayByLayerStack(uint64_t layerStack) { for (const auto& [token, display] : mDisplays) { if (display->getLayerStack() == layerStack) { return display; Loading Loading @@ -5989,7 +5999,7 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecs(const sp<IBinder>& display } auto future = schedule([=]() -> status_t { const auto display = getDisplayDeviceLocked(displayToken); const auto display = ON_MAIN_THREAD(getDisplayDeviceLocked(displayToken)); if (!display) { ALOGE("Attempt to set desired display configs for invalid display token %p", displayToken.get()); Loading Loading @@ -6144,7 +6154,7 @@ status_t SurfaceFlinger::setFrameRate(const sp<IGraphicBufferProducer>& surface, return BAD_VALUE; } static_cast<void>(schedule([=]() NO_THREAD_SAFETY_ANALYSIS { static_cast<void>(schedule([=] { Mutex::Autolock lock(mStateLock); if (authenticateSurfaceTextureLocked(surface)) { sp<Layer> layer = (static_cast<MonitoredProducer*>(surface.get()))->getLayer(); Loading Loading @@ -6173,8 +6183,7 @@ status_t SurfaceFlinger::acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) sp<IBinder> token; if (mFrameRateFlexibilityTokenCount == 0) { // |mStateLock| not needed as we are on the main thread const auto display = getDefaultDisplayDeviceLocked(); const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); // This is a little racy, but not in a way that hurts anything. As we grab the // defaultConfig from the display manager policy, we could be setting a new display Loading Loading @@ -6224,8 +6233,7 @@ void SurfaceFlinger::onFrameRateFlexibilityTokenReleased() { mFrameRateFlexibilityTokenCount--; ALOGD("Frame rate flexibility token released. count=%d", mFrameRateFlexibilityTokenCount); if (mFrameRateFlexibilityTokenCount == 0) { // |mStateLock| not needed as we are on the main thread const auto display = getDefaultDisplayDeviceLocked(); const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); constexpr bool kOverridePolicy = true; status_t result = setDesiredDisplayConfigSpecsInternal(display, {}, kOverridePolicy); LOG_ALWAYS_FATAL_IF(result < 0, "Failed releasing frame rate flexibility token"); Loading services/surfaceflinger/SurfaceFlinger.h +29 −31 File changed.Preview size limit exceeded, changes collapsed. Show changes services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +2 −2 Original line number Diff line number Diff line Loading @@ -289,14 +289,14 @@ public: return mFlinger->destroyDisplay(displayToken); } auto resetDisplayState() { return mFlinger->resetDisplayState(); } auto resetDisplayState() NO_THREAD_SAFETY_ANALYSIS { return mFlinger->resetDisplayState(); } auto setupNewDisplayDeviceInternal( const wp<IBinder>& displayToken, std::shared_ptr<compositionengine::Display> compositionDisplay, const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) { const sp<IGraphicBufferProducer>& producer) NO_THREAD_SAFETY_ANALYSIS { return mFlinger->setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state, dispSurface, producer); } Loading Loading
services/surfaceflinger/SurfaceFlinger.cpp +119 −111 Original line number Diff line number Diff line Loading @@ -125,6 +125,19 @@ #include "android-base/parseint.h" #include "android-base/stringprintf.h" #define MAIN_THREAD ACQUIRE(mStateLock) RELEASE(mStateLock) #define ON_MAIN_THREAD(expr) \ [&] { \ LOG_FATAL_IF(std::this_thread::get_id() != mMainThreadId); \ UnnecessaryLock lock(mStateLock); \ return (expr); \ }() #undef NO_THREAD_SAFETY_ANALYSIS #define NO_THREAD_SAFETY_ANALYSIS \ _Pragma("GCC error \"Prefer MAIN_THREAD macros or {Conditional,Timed,Unnecessary}Lock.\"") namespace android { using namespace std::string_literals; Loading Loading @@ -173,12 +186,12 @@ bool isWideColorMode(const ColorMode colorMode) { #pragma clang diagnostic pop template <typename Mutex> struct ConditionalLockGuard { ConditionalLockGuard(Mutex& mutex, bool lock) : mutex(mutex), lock(lock) { struct SCOPED_CAPABILITY ConditionalLockGuard { ConditionalLockGuard(Mutex& mutex, bool lock) ACQUIRE(mutex) : mutex(mutex), lock(lock) { if (lock) mutex.lock(); } ~ConditionalLockGuard() { ~ConditionalLockGuard() RELEASE() { if (lock) mutex.unlock(); } Loading @@ -188,6 +201,27 @@ struct ConditionalLockGuard { using ConditionalLock = ConditionalLockGuard<Mutex>; struct SCOPED_CAPABILITY TimedLock { TimedLock(Mutex& mutex, nsecs_t timeout, const char* whence) ACQUIRE(mutex) : mutex(mutex), status(mutex.timedLock(timeout)) { ALOGE_IF(!locked(), "%s timed out locking: %s (%d)", whence, strerror(-status), status); } ~TimedLock() RELEASE() { if (locked()) mutex.unlock(); } bool locked() const { return status == NO_ERROR; } Mutex& mutex; const status_t status; }; struct SCOPED_CAPABILITY UnnecessaryLock { explicit UnnecessaryLock(Mutex& mutex) ACQUIRE(mutex) {} ~UnnecessaryLock() RELEASE() {} }; // TODO(b/141333600): Consolidate with HWC2::Display::Config::Builder::getDefaultDensity. constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV; Loading Loading @@ -991,7 +1025,7 @@ status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mo } auto future = schedule([=]() -> status_t { const auto display = getDisplayDeviceLocked(displayToken); const auto display = ON_MAIN_THREAD(getDisplayDeviceLocked(displayToken)); if (!display) { ALOGE("Attempt to set allowed display configs for invalid display token %p", displayToken.get()); Loading Loading @@ -1176,7 +1210,7 @@ ColorMode SurfaceFlinger::getActiveColorMode(const sp<IBinder>& displayToken) { } status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, ColorMode mode) { schedule([=] { schedule([=]() MAIN_THREAD { Vector<ColorMode> modes; getDisplayColorModes(displayToken, &modes); bool exists = std::find(std::begin(modes), std::end(modes), mode) != std::end(modes); Loading Loading @@ -1222,7 +1256,7 @@ status_t SurfaceFlinger::getAutoLowLatencyModeSupport(const sp<IBinder>& display } void SurfaceFlinger::setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on) { static_cast<void>(schedule([=] { static_cast<void>(schedule([=]() MAIN_THREAD { if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) { getHwComposer().setAutoLowLatencyMode(*displayId, on); } else { Loading Loading @@ -1253,7 +1287,7 @@ status_t SurfaceFlinger::getGameContentTypeSupport(const sp<IBinder>& displayTok } void SurfaceFlinger::setGameContentType(const sp<IBinder>& displayToken, bool on) { static_cast<void>(schedule([=] { static_cast<void>(schedule([=]() MAIN_THREAD { if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) { const auto type = on ? hal::ContentType::GAME : hal::ContentType::NONE; getHwComposer().setContentType(*displayId, type); Loading Loading @@ -1343,7 +1377,7 @@ status_t SurfaceFlinger::getDisplayedContentSamplingAttributes(const sp<IBinder> status_t SurfaceFlinger::setDisplayContentSamplingEnabled(const sp<IBinder>& displayToken, bool enable, uint8_t componentMask, uint64_t maxFrames) { return schedule([=]() -> status_t { return schedule([=]() MAIN_THREAD -> status_t { if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) { return getHwComposer().setDisplayContentSamplingEnabled(*displayId, enable, componentMask, Loading Loading @@ -1412,13 +1446,9 @@ status_t SurfaceFlinger::injectVSync(nsecs_t when) { return mScheduler->injectVSync(when, calculateExpectedPresentTime(when)) ? NO_ERROR : BAD_VALUE; } status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const NO_THREAD_SAFETY_ANALYSIS { // Try to acquire a lock for 1s, fail gracefully const status_t err = mStateLock.timedLock(s2ns(1)); const bool locked = (err == NO_ERROR); if (!locked) { ALOGE("LayerDebugInfo: SurfaceFlinger unresponsive (%s [%d]) - exit", strerror(-err), err); status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const { TimedLock lock(mStateLock, s2ns(1), __FUNCTION__); if (!lock.locked()) { return TIMED_OUT; } Loading @@ -1427,7 +1457,6 @@ status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayer mCurrentState.traverseInZOrder( [&](Layer* layer) { outLayers->push_back(layer->getLayerDebugInfo(display.get())); }); mStateLock.unlock(); return NO_ERROR; } Loading Loading @@ -1484,7 +1513,7 @@ status_t SurfaceFlinger::setDisplayBrightness(const sp<IBinder>& displayToken, f return BAD_VALUE; } return promise::chain(schedule([=] { return promise::chain(schedule([=]() MAIN_THREAD { if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) { return getHwComposer().setDisplayBrightness(*displayId, brightness); } else { Loading Loading @@ -1597,7 +1626,7 @@ void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate, } void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId, hal::Connection connection) NO_THREAD_SAFETY_ANALYSIS { hal::Connection connection) { ALOGV("%s(%d, %" PRIu64 ", %s)", __FUNCTION__, sequenceId, hwcDisplayId, connection == hal::Connection::CONNECTED ? "connected" : "disconnected"); Loading Loading @@ -1650,8 +1679,7 @@ void SurfaceFlinger::setPrimaryVsyncEnabled(bool enabled) { // Enable / Disable HWVsync from the main thread to avoid race conditions with // display power state. static_cast<void>( schedule([=]() NO_THREAD_SAFETY_ANALYSIS { setPrimaryVsyncEnabledInternal(enabled); })); static_cast<void>(schedule([=]() MAIN_THREAD { setPrimaryVsyncEnabledInternal(enabled); })); } void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) { Loading @@ -1667,7 +1695,6 @@ void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) { } } // Note: it is assumed the caller holds |mStateLock| when this is called void SurfaceFlinger::resetDisplayState() { mScheduler->disableHardwareVsync(true); // Clear the drawing state so that the logic inside of Loading Loading @@ -1760,7 +1787,7 @@ void SurfaceFlinger::updateVrFlinger() { setTransactionFlags(eDisplayTransactionNeeded); } sp<Fence> SurfaceFlinger::previousFrameFence() NO_THREAD_SAFETY_ANALYSIS { sp<Fence> SurfaceFlinger::previousFrameFence() { // We are storing the last 2 present fences. If sf's phase offset is to be // woken up before the actual vsync but targeting the next vsync, we need to check // fence N-2 Loading @@ -1768,7 +1795,7 @@ sp<Fence> SurfaceFlinger::previousFrameFence() NO_THREAD_SAFETY_ANALYSIS { : mPreviousPresentFences[1]; } bool SurfaceFlinger::previousFramePending(int graceTimeMs) NO_THREAD_SAFETY_ANALYSIS { bool SurfaceFlinger::previousFramePending(int graceTimeMs) { ATRACE_CALL(); const sp<Fence>& fence = previousFrameFence(); Loading @@ -1782,7 +1809,7 @@ bool SurfaceFlinger::previousFramePending(int graceTimeMs) NO_THREAD_SAFETY_ANAL return status == -ETIME; } nsecs_t SurfaceFlinger::previousFramePresentTime() NO_THREAD_SAFETY_ANALYSIS { nsecs_t SurfaceFlinger::previousFramePresentTime() { const sp<Fence>& fence = previousFrameFence(); if (fence == Fence::NO_FENCE) { Loading @@ -1800,8 +1827,7 @@ nsecs_t SurfaceFlinger::calculateExpectedPresentTime(nsecs_t now) const { return mVSyncModulator->getOffsets().sf > 0 ? presentTime : presentTime + stats.vsyncPeriod; } void SurfaceFlinger::onMessageReceived(int32_t what, nsecs_t expectedVSyncTime) NO_THREAD_SAFETY_ANALYSIS { void SurfaceFlinger::onMessageReceived(int32_t what, nsecs_t expectedVSyncTime) { ATRACE_CALL(); switch (what) { case MessageQueue::INVALIDATE: { Loading @@ -1815,7 +1841,7 @@ void SurfaceFlinger::onMessageReceived(int32_t what, } } void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) NO_THREAD_SAFETY_ANALYSIS { void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) { ATRACE_CALL(); const nsecs_t frameStart = systemTime(); Loading Loading @@ -1888,7 +1914,7 @@ void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) NO_THREAD_SA // We received the present fence from the HWC, so we assume it successfully updated // the config, hence we update SF. mSetActiveConfigPending = false; setActiveConfigInternal(); ON_MAIN_THREAD(setActiveConfigInternal()); } if (framePending && mPropagateBackpressure) { Loading @@ -1907,12 +1933,12 @@ void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) NO_THREAD_SA std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count(); // If we're in a user build then don't push any atoms if (!mIsUserBuild && mMissedFrameJankCount > 0) { const auto displayDevice = getDefaultDisplayDeviceLocked(); const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); // Only report jank when the display is on, as displays in DOZE // power mode may operate at a different frame rate than is // reported in their config, which causes noticeable (but less // severe) jank. if (displayDevice && displayDevice->getPowerMode() == hal::PowerMode::ON) { if (display && display->getPowerMode() == hal::PowerMode::ON) { const nsecs_t currentTime = systemTime(); const nsecs_t jankDuration = currentTime - mMissedFrameJankStart; if (jankDuration > kMinJankyDuration && jankDuration < kMaxJankyDuration) { Loading Loading @@ -1969,7 +1995,7 @@ void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) NO_THREAD_SA mScheduler->chooseRefreshRateForContent(); } performSetActiveConfig(); ON_MAIN_THREAD(performSetActiveConfig()); updateCursorAsync(); updateInputFlinger(); Loading Loading @@ -2018,8 +2044,9 @@ void SurfaceFlinger::onMessageRefresh() { mRefreshPending = false; compositionengine::CompositionRefreshArgs refreshArgs; refreshArgs.outputs.reserve(mDisplays.size()); for (const auto& [_, display] : mDisplays) { const auto& displays = ON_MAIN_THREAD(mDisplays); refreshArgs.outputs.reserve(displays.size()); for (const auto& [_, display] : displays) { refreshArgs.outputs.push_back(display->getCompositionDisplay()); } mDrawingState.traverseInZOrder([&refreshArgs](Layer* layer) { Loading Loading @@ -2074,21 +2101,18 @@ void SurfaceFlinger::onMessageRefresh() { const bool prevFrameHadDeviceComposition = mHadDeviceComposition; mHadClientComposition = std::any_of(mDisplays.cbegin(), mDisplays.cend(), [](const auto& tokenDisplayPair) { auto& displayDevice = tokenDisplayPair.second; return displayDevice->getCompositionDisplay()->getState().usesClientComposition && !displayDevice->getCompositionDisplay()->getState().reusedClientComposition; mHadClientComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) { const auto& state = pair.second->getCompositionDisplay()->getState(); return state.usesClientComposition && !state.reusedClientComposition; }); mHadDeviceComposition = std::any_of(mDisplays.cbegin(), mDisplays.cend(), [](const auto& tokenDisplayPair) { auto& displayDevice = tokenDisplayPair.second; return displayDevice->getCompositionDisplay()->getState().usesDeviceComposition; mHadDeviceComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) { const auto& state = pair.second->getCompositionDisplay()->getState(); return state.usesDeviceComposition; }); mReusedClientComposition = std::any_of(mDisplays.cbegin(), mDisplays.cend(), [](const auto& tokenDisplayPair) { auto& displayDevice = tokenDisplayPair.second; return displayDevice->getCompositionDisplay()->getState().reusedClientComposition; std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) { const auto& state = pair.second->getCompositionDisplay()->getState(); return state.reusedClientComposition; }); // Only report a strategy change if we move in and out of composition with hw overlays Loading Loading @@ -2194,14 +2218,14 @@ void SurfaceFlinger::postComposition() for (auto& layer : mLayersWithQueuedFrames) { layer->releasePendingBuffer(dequeueReadyTime); } // |mStateLock| not needed as we are on the main thread const auto displayDevice = getDefaultDisplayDeviceLocked(); const auto* display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()).get(); getBE().mGlCompositionDoneTimeline.updateSignalTimes(); std::shared_ptr<FenceTime> glCompositionDoneFenceTime; if (displayDevice && displayDevice->getCompositionDisplay()->getState().usesClientComposition) { if (display && display->getCompositionDisplay()->getState().usesClientComposition) { glCompositionDoneFenceTime = std::make_shared<FenceTime>(displayDevice->getCompositionDisplay() std::make_shared<FenceTime>(display->getCompositionDisplay() ->getRenderSurface() ->getClientTargetAcquireFence()); getBE().mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime); Loading @@ -2211,9 +2235,8 @@ void SurfaceFlinger::postComposition() getBE().mDisplayTimeline.updateSignalTimes(); mPreviousPresentFences[1] = mPreviousPresentFences[0]; mPreviousPresentFences[0] = displayDevice ? getHwComposer().getPresentFence(*displayDevice->getId()) : Fence::NO_FENCE; mPreviousPresentFences[0] = display ? getHwComposer().getPresentFence(*display->getId()) : Fence::NO_FENCE; auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFences[0]); getBE().mDisplayTimeline.push(presentFenceTime); Loading @@ -2232,8 +2255,7 @@ void SurfaceFlinger::postComposition() } mDrawingState.traverse([&](Layer* layer) { const bool frameLatched = layer->onPostComposition(displayDevice.get(), glCompositionDoneFenceTime, const bool frameLatched = layer->onPostComposition(display, glCompositionDoneFenceTime, presentFenceTime, compositorTiming); if (frameLatched) { recordBufferingStats(layer->getName(), layer->getOccupancyHistory(false)); Loading @@ -2243,14 +2265,15 @@ void SurfaceFlinger::postComposition() mTransactionCompletedThread.addPresentFence(mPreviousPresentFences[0]); mTransactionCompletedThread.sendCallbacks(); if (displayDevice && displayDevice->isPrimary() && displayDevice->getPowerMode() == hal::PowerMode::ON && presentFenceTime->isValid()) { if (display && display->isPrimary() && display->getPowerMode() == hal::PowerMode::ON && presentFenceTime->isValid()) { mScheduler->addPresentFence(presentFenceTime); } const bool isDisplayConnected = display && getHwComposer().isConnected(*display->getId()); if (!hasSyncFramework) { if (displayDevice && getHwComposer().isConnected(*displayDevice->getId()) && displayDevice->isPoweredOn()) { if (isDisplayConnected && display->isPoweredOn()) { mScheduler->enableHardwareVsync(); } } Loading @@ -2261,11 +2284,10 @@ void SurfaceFlinger::postComposition() if (presentFenceTime->isValid()) { mAnimFrameTracker.setActualPresentFence( std::move(presentFenceTime)); } else if (displayDevice && getHwComposer().isConnected(*displayDevice->getId())) { } else if (isDisplayConnected) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(*displayDevice->getId()); const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(*display->getId()); mAnimFrameTracker.setActualPresentTime(presentTime); } mAnimFrameTracker.advanceFrame(); Loading @@ -2286,8 +2308,7 @@ void SurfaceFlinger::postComposition() const size_t appConnections = mScheduler->getEventThreadConnectionCount(mAppConnectionHandle); mTimeStats->recordDisplayEventConnectionCount(sfConnections + appConnections); if (displayDevice && getHwComposer().isConnected(*displayDevice->getId()) && !displayDevice->isPoweredOn()) { if (isDisplayConnected && !display->isPoweredOn()) { return; } Loading Loading @@ -2343,7 +2364,7 @@ FloatRect SurfaceFlinger::getLayerClipBoundsForDisplay(const DisplayDevice& disp } void SurfaceFlinger::computeLayerBounds() { for (const auto& pair : mDisplays) { for (const auto& pair : ON_MAIN_THREAD(mDisplays)) { const auto& displayDevice = pair.second; const auto display = displayDevice->getCompositionDisplay(); for (const auto& layer : mDrawingState.layersSortedByZ) { Loading @@ -2358,10 +2379,8 @@ void SurfaceFlinger::computeLayerBounds() { } } void SurfaceFlinger::postFrame() { // |mStateLock| not needed as we are on the main thread const auto display = getDefaultDisplayDeviceLocked(); void SurfaceFlinger::postFrame() { const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); if (display && getHwComposer().isConnected(*display->getId())) { uint32_t flipCount = display->getPageFlipCount(); if (flipCount % LOG_FRAME_STATS_PERIOD == 0) { Loading Loading @@ -2789,7 +2808,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) sp<const DisplayDevice> hintDisplay; uint32_t currentlayerStack = 0; bool first = true; mCurrentState.traverse([&](Layer* layer) { mCurrentState.traverse([&](Layer* layer) REQUIRES(mStateLock) { // NOTE: we rely on the fact that layers are sorted by // layerStack first (so we don't have to traverse the list // of displays for every layer). Loading Loading @@ -2902,10 +2921,9 @@ void SurfaceFlinger::commitInputWindowCommands() { mPendingInputWindowCommands.clear(); } void SurfaceFlinger::updateCursorAsync() { void SurfaceFlinger::updateCursorAsync() { compositionengine::CompositionRefreshArgs refreshArgs; for (const auto& [_, display] : mDisplays) { for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) { if (display->getId()) { refreshArgs.outputs.push_back(display->getCompositionDisplay()); } Loading @@ -2915,7 +2933,7 @@ void SurfaceFlinger::updateCursorAsync() } void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate, Scheduler::ConfigEvent event) NO_THREAD_SAFETY_ANALYSIS { Scheduler::ConfigEvent event) { // If this is called from the main thread mStateLock must be locked before // Currently the only way to call this function from the main thread is from // Sheduler::chooseRefreshRateForContent Loading Loading @@ -3041,7 +3059,7 @@ void SurfaceFlinger::commitOffscreenLayers() { } void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) { for (const auto& [token, displayDevice] : mDisplays) { for (const auto& [token, displayDevice] : ON_MAIN_THREAD(mDisplays)) { auto display = displayDevice->getCompositionDisplay(); if (display->belongsInOutput(layer->getLayerStack(), layer->getPrimaryDisplayOnly())) { display->editState().dirtyRegion.orSelf(dirty); Loading Loading @@ -4137,7 +4155,7 @@ void SurfaceFlinger::onInitializeDisplays() { void SurfaceFlinger::initializeDisplays() { // Async since we may be called from the main thread. static_cast<void>(schedule([this]() NO_THREAD_SAFETY_ANALYSIS { onInitializeDisplays(); })); static_cast<void>(schedule([this]() MAIN_THREAD { onInitializeDisplays(); })); } void SurfaceFlinger::setVsyncEnabledInHWC(DisplayId displayId, hal::Vsync enabled) { Loading Loading @@ -4228,7 +4246,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: } void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) { schedule([=]() NO_THREAD_SAFETY_ANALYSIS { schedule([=]() MAIN_THREAD { const auto display = getDisplayDeviceLocked(displayToken); if (!display) { ALOGE("Attempt to set power mode %d for invalid display token %p", mode, Loading @@ -4241,8 +4259,7 @@ void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) { }).wait(); } status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) NO_THREAD_SAFETY_ANALYSIS { status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { std::string result; IPCThreadState* ipc = IPCThreadState::self(); Loading @@ -4254,18 +4271,6 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, StringAppendF(&result, "Permission Denial: can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid); } else { // Try to get the main lock, but give up after one second // (this would indicate SF is stuck, but we want to be able to // print something in dumpsys). status_t err = mStateLock.timedLock(s2ns(1)); bool locked = (err == NO_ERROR); if (!locked) { StringAppendF(&result, "SurfaceFlinger appears to be unresponsive (%s [%d]), dumping anyways " "(no locks held)\n", strerror(-err), err); } static const std::unordered_map<std::string, Dumper> dumpers = { {"--display-id"s, dumper(&SurfaceFlinger::dumpDisplayIdentificationData)}, {"--dispsync"s, Loading @@ -4283,18 +4288,23 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, const auto flag = args.empty() ? ""s : std::string(String8(args[0])); const auto it = dumpers.find(flag); if (it != dumpers.end()) { bool dumpLayers = true; { TimedLock lock(mStateLock, s2ns(1), __FUNCTION__); if (!lock.locked()) { StringAppendF(&result, "Dumping without lock after timeout: %s (%d)\n", strerror(-lock.status), lock.status); } if (const auto it = dumpers.find(flag); it != dumpers.end()) { (it->second)(args, asProto, result); dumpLayers = false; } else if (!asProto) { dumpAllLocked(args, result); } if (locked) { mStateLock.unlock(); } if (it == dumpers.end()) { if (dumpLayers) { const LayersProto layersProto = dumpProtoFromMainThread(); if (asProto) { result.append(layersProto.SerializeAsString()); Loading Loading @@ -4568,7 +4578,7 @@ void SurfaceFlinger::dumpWideColorInfo(std::string& result) const { LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { // If context is SurfaceTracing thread, mTracingLock blocks display transactions on main thread. const auto display = getDefaultDisplayDeviceLocked(); const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); LayersProto layersProto; for (const sp<Layer>& layer : mDrawingState.layersSortedByZ) { Loading Loading @@ -5404,7 +5414,7 @@ status_t SurfaceFlinger::setSchedFifo(bool enabled) { return NO_ERROR; } const sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) { sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) { const sp<IBinder> displayToken = getPhysicalDisplayTokenLocked(DisplayId{displayOrLayerStack}); if (displayToken) { return getDisplayDeviceLocked(displayToken); Loading @@ -5414,7 +5424,7 @@ const sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t disp return getDisplayByLayerStack(displayOrLayerStack); } const sp<DisplayDevice> SurfaceFlinger::getDisplayByLayerStack(uint64_t layerStack) { sp<DisplayDevice> SurfaceFlinger::getDisplayByLayerStack(uint64_t layerStack) { for (const auto& [token, display] : mDisplays) { if (display->getLayerStack() == layerStack) { return display; Loading Loading @@ -5989,7 +5999,7 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecs(const sp<IBinder>& display } auto future = schedule([=]() -> status_t { const auto display = getDisplayDeviceLocked(displayToken); const auto display = ON_MAIN_THREAD(getDisplayDeviceLocked(displayToken)); if (!display) { ALOGE("Attempt to set desired display configs for invalid display token %p", displayToken.get()); Loading Loading @@ -6144,7 +6154,7 @@ status_t SurfaceFlinger::setFrameRate(const sp<IGraphicBufferProducer>& surface, return BAD_VALUE; } static_cast<void>(schedule([=]() NO_THREAD_SAFETY_ANALYSIS { static_cast<void>(schedule([=] { Mutex::Autolock lock(mStateLock); if (authenticateSurfaceTextureLocked(surface)) { sp<Layer> layer = (static_cast<MonitoredProducer*>(surface.get()))->getLayer(); Loading Loading @@ -6173,8 +6183,7 @@ status_t SurfaceFlinger::acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) sp<IBinder> token; if (mFrameRateFlexibilityTokenCount == 0) { // |mStateLock| not needed as we are on the main thread const auto display = getDefaultDisplayDeviceLocked(); const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); // This is a little racy, but not in a way that hurts anything. As we grab the // defaultConfig from the display manager policy, we could be setting a new display Loading Loading @@ -6224,8 +6233,7 @@ void SurfaceFlinger::onFrameRateFlexibilityTokenReleased() { mFrameRateFlexibilityTokenCount--; ALOGD("Frame rate flexibility token released. count=%d", mFrameRateFlexibilityTokenCount); if (mFrameRateFlexibilityTokenCount == 0) { // |mStateLock| not needed as we are on the main thread const auto display = getDefaultDisplayDeviceLocked(); const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); constexpr bool kOverridePolicy = true; status_t result = setDesiredDisplayConfigSpecsInternal(display, {}, kOverridePolicy); LOG_ALWAYS_FATAL_IF(result < 0, "Failed releasing frame rate flexibility token"); Loading
services/surfaceflinger/SurfaceFlinger.h +29 −31 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +2 −2 Original line number Diff line number Diff line Loading @@ -289,14 +289,14 @@ public: return mFlinger->destroyDisplay(displayToken); } auto resetDisplayState() { return mFlinger->resetDisplayState(); } auto resetDisplayState() NO_THREAD_SAFETY_ANALYSIS { return mFlinger->resetDisplayState(); } auto setupNewDisplayDeviceInternal( const wp<IBinder>& displayToken, std::shared_ptr<compositionengine::Display> compositionDisplay, const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) { const sp<IGraphicBufferProducer>& producer) NO_THREAD_SAFETY_ANALYSIS { return mFlinger->setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state, dispSurface, producer); } Loading