diff options
27 files changed, 289 insertions, 81 deletions
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp index 26c2a0d802..a00459d352 100644 --- a/libs/dumputils/dump_utils.cpp +++ b/libs/dumputils/dump_utils.cpp @@ -110,13 +110,15 @@ std::set<int> get_interesting_hal_pids() { } bool IsZygote(int pid) { - static const std::string kZygotePrefix = "zygote"; - std::string cmdline; if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid), &cmdline)) { return true; } - return (cmdline.find(kZygotePrefix) == 0); + // cmdline has embedded nulls; only consider argv[0]. + cmdline = std::string(cmdline.c_str()); + + return cmdline == "zygote" || cmdline == "zygote64" || cmdline == "usap32" || + cmdline == "usap64"; } diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 4372e16a1f..6c9d81ab57 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -955,6 +955,27 @@ public: } return NO_ERROR; } + + virtual status_t notifyPowerHint(int32_t hintId) { + Parcel data, reply; + status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (error != NO_ERROR) { + ALOGE("notifyPowerHint: failed to write interface token: %d", error); + return error; + } + error = data.writeInt32(hintId); + if (error != NO_ERROR) { + ALOGE("notifyPowerHint: failed to write hintId: %d", error); + return error; + } + error = remote()->transact(BnSurfaceComposer::NOTIFY_POWER_HINT, data, &reply, + IBinder::FLAG_ONEWAY); + if (error != NO_ERROR) { + ALOGE("notifyPowerHint: failed to transact: %d", error); + return error; + } + return NO_ERROR; + } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -1556,6 +1577,16 @@ status_t BnSurfaceComposer::onTransact( } return setDisplayBrightness(displayToken, brightness); } + case NOTIFY_POWER_HINT: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + int32_t hintId; + status_t error = data.readInt32(&hintId); + if (error != NO_ERROR) { + ALOGE("notifyPowerHint: failed to read hintId: %d", error); + return error; + } + return notifyPowerHint(hintId); + } default: { return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 075bb52e3c..6066421faf 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -245,6 +245,7 @@ void layer_state_t::merge(const layer_state_t& other) { } if (other.what & eLayerChanged) { what |= eLayerChanged; + what &= ~eRelativeLayerChanged; z = other.z; } if (other.what & eSizeChanged) { @@ -303,6 +304,7 @@ void layer_state_t::merge(const layer_state_t& other) { } if (other.what & eRelativeLayerChanged) { what |= eRelativeLayerChanged; + what &= ~eLayerChanged; z = other.z; relativeLayerHandle = other.relativeLayerHandle; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 5d4367d7f4..d6f88fc7a4 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -611,6 +611,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer return *this; } s->what |= layer_state_t::eLayerChanged; + s->what &= ~layer_state_t::eRelativeLayerChanged; s->z = z; registerSurfaceControlForCallback(sc); @@ -624,6 +625,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setRelat mStatus = BAD_INDEX; } s->what |= layer_state_t::eRelativeLayerChanged; + s->what &= ~layer_state_t::eLayerChanged; s->relativeLayerHandle = relativeTo; s->z = z; @@ -1543,6 +1545,10 @@ status_t SurfaceComposerClient::setDisplayBrightness(const sp<IBinder>& displayT return ComposerService::getComposerService()->setDisplayBrightness(displayToken, brightness); } +status_t SurfaceComposerClient::notifyPowerHint(int32_t hintId) { + return ComposerService::getComposerService()->notifyPowerHint(hintId); +} + // ---------------------------------------------------------------------------- status_t ScreenshotClient::capture(const sp<IBinder>& display, const ui::Dataspace reqDataSpace, diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index fd67754d05..e2f77365b3 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -425,6 +425,16 @@ public: */ virtual status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) const = 0; + + /* + * Sends a power hint to the composer. This function is asynchronous. + * + * hintId + * hint id according to android::hardware::power::V1_0::PowerHint + * + * Returns NO_ERROR upon success. + */ + virtual status_t notifyPowerHint(int32_t hintId) = 0; }; // ---------------------------------------------------------------------------- @@ -477,6 +487,7 @@ public: GET_DISPLAY_BRIGHTNESS_SUPPORT, SET_DISPLAY_BRIGHTNESS, CAPTURE_SCREEN_BY_ID, + NOTIFY_POWER_HINT, // Always append new enum to the end. }; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index a038838608..0e17c7b015 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -201,6 +201,16 @@ public: */ static status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness); + /* + * Sends a power hint to the composer. This function is asynchronous. + * + * hintId + * hint id according to android::hardware::power::V1_0::PowerHint + * + * Returns NO_ERROR upon success. + */ + static status_t notifyPowerHint(int32_t hintId); + // ------------------------------------------------------------------------ // surface creation / destruction diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index db97faed02..960cf1846e 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -704,6 +704,7 @@ public: std::vector<int32_t>* /*outAllowedConfigs*/) override { return NO_ERROR; } + status_t notifyPowerHint(int32_t /*hintId*/) override { return NO_ERROR; } protected: IBinder* onAsBinder() override { return nullptr; } diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index fa1e2329cd..c11b88eac2 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -1550,7 +1550,8 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection, if (err == NO_ERROR) { connection->updateLooperRegistration(mLooper); - if (sensor->getSensor().getRequiredPermission().size() > 0) { + if (sensor->getSensor().getRequiredPermission().size() > 0 && + sensor->getSensor().getRequiredAppOp() >= 0) { connection->mHandleToAppOp[handle] = sensor->getSensor().getRequiredAppOp(); } diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index a6c7e6ce65..05bad4ddd8 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -107,10 +107,8 @@ DisplayEventReceiver::Event makeConfigChanged(PhysicalDisplayId displayId, int32 } // namespace EventThreadConnection::EventThreadConnection(EventThread* eventThread, - ResyncCallback resyncCallback, - ResetIdleTimerCallback resetIdleTimerCallback) + ResyncCallback resyncCallback) : resyncCallback(std::move(resyncCallback)), - resetIdleTimerCallback(std::move(resetIdleTimerCallback)), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {} @@ -136,12 +134,7 @@ status_t EventThreadConnection::setVsyncRate(uint32_t rate) { void EventThreadConnection::requestNextVsync() { ATRACE_NAME("requestNextVsync"); - mEventThread->requestNextVsync(this, true); -} - -void EventThreadConnection::requestNextVsyncForHWC() { - ATRACE_NAME("requestNextVsyncForHWC"); - mEventThread->requestNextVsync(this, false); + mEventThread->requestNextVsync(this); } status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) { @@ -210,10 +203,8 @@ void EventThread::setPhaseOffset(nsecs_t phaseOffset) { mVSyncSource->setPhaseOffset(phaseOffset); } -sp<EventThreadConnection> EventThread::createEventConnection( - ResyncCallback resyncCallback, ResetIdleTimerCallback resetIdleTimerCallback) const { - return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback), - std::move(resetIdleTimerCallback)); +sp<EventThreadConnection> EventThread::createEventConnection(ResyncCallback resyncCallback) const { + return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback)); } status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) { @@ -255,12 +246,7 @@ void EventThread::setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& c } } -void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection, bool reset) { - if (connection->resetIdleTimerCallback && reset) { - ATRACE_NAME("resetIdleTimer"); - connection->resetIdleTimerCallback(); - } - +void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) { if (connection->resyncCallback) { connection->resyncCallback(); } diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h index 7107d6388a..61530c62e5 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -45,7 +45,6 @@ class SurfaceFlinger; // --------------------------------------------------------------------------- using ResyncCallback = std::function<void()>; -using ResetIdleTimerCallback = std::function<void()>; enum class VSyncRequest { None = -1, @@ -70,7 +69,7 @@ public: class EventThreadConnection : public BnDisplayEventConnection { public: - EventThreadConnection(EventThread*, ResyncCallback, ResetIdleTimerCallback); + EventThreadConnection(EventThread*, ResyncCallback); virtual ~EventThreadConnection(); virtual status_t postEvent(const DisplayEventReceiver::Event& event); @@ -78,13 +77,9 @@ public: status_t stealReceiveChannel(gui::BitTube* outChannel) override; status_t setVsyncRate(uint32_t rate) override; void requestNextVsync() override; // asynchronous - // Requesting Vsync for HWC does not reset the idle timer, since HWC requires a refresh - // in order to update the configs. - void requestNextVsyncForHWC(); // Called in response to requestNextVsync. const ResyncCallback resyncCallback; - const ResetIdleTimerCallback resetIdleTimerCallback; VSyncRequest vsyncRequest = VSyncRequest::None; @@ -98,8 +93,7 @@ class EventThread { public: virtual ~EventThread(); - virtual sp<EventThreadConnection> createEventConnection(ResyncCallback, - ResetIdleTimerCallback) const = 0; + virtual sp<EventThreadConnection> createEventConnection(ResyncCallback) const = 0; // called before the screen is turned off from main thread virtual void onScreenReleased() = 0; @@ -120,8 +114,7 @@ public: const sp<EventThreadConnection>& connection) = 0; virtual void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) = 0; // Requests the next vsync. If resetIdleTimer is set to true, it resets the idle timer. - virtual void requestNextVsync(const sp<EventThreadConnection>& connection, - bool resetIdleTimer) = 0; + virtual void requestNextVsync(const sp<EventThreadConnection>& connection) = 0; }; namespace impl { @@ -135,13 +128,11 @@ public: EventThread(std::unique_ptr<VSyncSource>, InterceptVSyncsCallback, const char* threadName); ~EventThread(); - sp<EventThreadConnection> createEventConnection(ResyncCallback, - ResetIdleTimerCallback) const override; + sp<EventThreadConnection> createEventConnection(ResyncCallback) const override; status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override; void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) override; - void requestNextVsync(const sp<EventThreadConnection>& connection, - bool resetIdleTimer) override; + void requestNextVsync(const sp<EventThreadConnection>& connection) override; // called before the screen is turned off from main thread void onScreenReleased() override; diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp index 1f18ead91a..baf900df52 100644 --- a/services/surfaceflinger/Scheduler/MessageQueue.cpp +++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp @@ -96,8 +96,7 @@ void MessageQueue::setEventThread(android::EventThread* eventThread, } mEventThread = eventThread; - mEvents = - eventThread->createEventConnection(std::move(resyncCallback), ResetIdleTimerCallback()); + mEvents = eventThread->createEventConnection(std::move(resyncCallback)); mEvents->stealReceiveChannel(&mEventTube); mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver, this); @@ -150,10 +149,6 @@ void MessageQueue::invalidate() { mEvents->requestNextVsync(); } -void MessageQueue::invalidateForHWC() { - mEvents->requestNextVsyncForHWC(); -} - void MessageQueue::refresh() { mHandler->dispatchRefresh(); } diff --git a/services/surfaceflinger/Scheduler/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h index 245a8ace88..0b2206d2af 100644 --- a/services/surfaceflinger/Scheduler/MessageQueue.h +++ b/services/surfaceflinger/Scheduler/MessageQueue.h @@ -91,7 +91,6 @@ public: virtual void waitMessage() = 0; virtual status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime = 0) = 0; virtual void invalidate() = 0; - virtual void invalidateForHWC() = 0; virtual void refresh() = 0; }; @@ -136,8 +135,6 @@ public: // sends INVALIDATE message at next VSYNC void invalidate() override; - // sends INVALIDATE message at next VSYNC, without resetting the idle timer in the Scheduler - void invalidateForHWC(); // sends REFRESH message at next VSYNC void refresh() override; }; diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 3f9a88df75..513436a270 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -75,6 +75,8 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function, mSetIdleTimerMs = set_idle_timer_ms(0); mSupportKernelTimer = support_kernel_idle_timer(false); + mSetTouchTimerMs = set_touch_timer_ms(0); + char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.set_idle_timer_ms", value, "0"); int int_value = atoi(value); @@ -99,10 +101,20 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function, } mIdleTimer->start(); } + + if (mSetTouchTimerMs > 0) { + // Touch events are coming to SF every 100ms, so the timer needs to be higher than that + mTouchTimer = + std::make_unique<scheduler::IdleTimer>(std::chrono::milliseconds(mSetTouchTimerMs), + [this] { resetTouchTimerCallback(); }, + [this] { expiredTouchTimerCallback(); }); + mTouchTimer->start(); + } } Scheduler::~Scheduler() { // Ensure the IdleTimer thread is joined before we start destroying state. + mTouchTimer.reset(); mIdleTimer.reset(); } @@ -136,8 +148,7 @@ std::unique_ptr<EventThread> Scheduler::makeEventThread( sp<EventThreadConnection> Scheduler::createConnectionInternal(EventThread* eventThread, ResyncCallback&& resyncCallback) { - return eventThread->createEventConnection(std::move(resyncCallback), - [this] { resetIdleTimer(); }); + return eventThread->createEventConnection(std::move(resyncCallback)); } sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection( @@ -385,6 +396,16 @@ void Scheduler::resetIdleTimer() { } } +void Scheduler::notifyTouchEvent() { + if (mTouchTimer) { + mTouchTimer->reset(); + } + + if (mSupportKernelTimer) { + resetIdleTimer(); + } +} + void Scheduler::resetTimerCallback() { timerChangeRefreshRate(IdleTimerState::RESET); ATRACE_INT("ExpiredIdleTimer", 0); @@ -403,6 +424,18 @@ void Scheduler::expiredTimerCallback() { ATRACE_INT("ExpiredIdleTimer", 1); } +void Scheduler::resetTouchTimerCallback() { + // We do not notify the applications about config changes when idle timer is reset. + touchChangeRefreshRate(TouchState::ACTIVE); + ATRACE_INT("TouchState", 1); +} + +void Scheduler::expiredTouchTimerCallback() { + // We do not notify the applications about config changes when idle timer expires. + touchChangeRefreshRate(TouchState::INACTIVE); + ATRACE_INT("TouchState", 0); +} + void Scheduler::expiredKernelTimerCallback() { ATRACE_INT("ExpiredKernelIdleTimer", 1); // Disable HW Vsync if the timer expired, as we don't need it @@ -413,6 +446,7 @@ void Scheduler::expiredKernelTimerCallback() { std::string Scheduler::doDump() { std::ostringstream stream; stream << "+ Idle timer interval: " << mSetIdleTimerMs << " ms" << std::endl; + stream << "+ Touch timer interval: " << mSetTouchTimerMs << " ms" << std::endl; return stream.str(); } @@ -433,17 +467,44 @@ void Scheduler::timerChangeRefreshRate(IdleTimerState idleTimerState) { changeRefreshRate(newRefreshRateType, ConfigEvent::None); } -Scheduler::RefreshRateType Scheduler::calculateRefreshRateType() { - // First check if timer has expired as it means there is no new content on the screen - if (mCurrentIdleTimerState == IdleTimerState::EXPIRED) { - return RefreshRateType::DEFAULT; +void Scheduler::touchChangeRefreshRate(TouchState touchState) { + ConfigEvent event = ConfigEvent::None; + RefreshRateType newRefreshRateType; + { + std::lock_guard<std::mutex> lock(mFeatureStateLock); + if (mCurrentTouchState == touchState) { + return; + } + mCurrentTouchState = touchState; + newRefreshRateType = calculateRefreshRateType(); + if (mRefreshRateType == newRefreshRateType) { + return; + } + mRefreshRateType = newRefreshRateType; + // Send an event in case that content detection is on as touch has a higher priority + if (mCurrentContentFeatureState == ContentFeatureState::CONTENT_DETECTION_ON) { + event = ConfigEvent::Changed; + } } + changeRefreshRate(newRefreshRateType, event); +} +Scheduler::RefreshRateType Scheduler::calculateRefreshRateType() { // HDR content is not supported on PERFORMANCE mode if (mForceHDRContentToDefaultRefreshRate && mIsHDRContent) { return RefreshRateType::DEFAULT; } + // As long as touch is active we want to be in performance mode + if (mCurrentTouchState == TouchState::ACTIVE) { + return RefreshRateType::PERFORMANCE; + } + + // If timer has expired as it means there is no new content on the screen + if (mCurrentIdleTimerState == IdleTimerState::EXPIRED) { + return RefreshRateType::DEFAULT; + } + // If content detection is off we choose performance as we don't know the content fps if (mCurrentContentFeatureState == ContentFeatureState::CONTENT_DETECTION_OFF) { return RefreshRateType::PERFORMANCE; diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 7c8adf0036..96d4bd5214 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -165,6 +165,12 @@ public: // Returns whether idle timer is enabled or not bool isIdleTimerEnabled() { return mSetIdleTimerMs > 0; } + // Function that resets the idle timer. + void resetIdleTimer(); + + // Function that resets the touch timer. + void notifyTouchEvent(); + // Returns relevant information about Scheduler for dumpsys purposes. std::string doDump(); @@ -183,14 +189,14 @@ private: // to keep track which feature requested the config change. enum class ContentFeatureState { CONTENT_DETECTION_ON, CONTENT_DETECTION_OFF }; enum class IdleTimerState { EXPIRED, RESET }; + enum class TouchState { INACTIVE, ACTIVE }; // Creates a connection on the given EventThread and forwards the given callbacks. sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&); nsecs_t calculateAverage() const; void updateFrameSkipping(const int64_t skipCount); - // Function that resets the idle timer. - void resetIdleTimer(); + // Function that is called when the timer resets. void resetTimerCallback(); // Function that is called when the timer expires. @@ -203,10 +209,16 @@ private: // driver timeout in the kernel. This disables hardware vsync when we move // into idle. void expiredKernelTimerCallback(); + // Function that is called when the touch timer resets. + void resetTouchTimerCallback(); + // Function that is called when the touch timer expires. + void expiredTouchTimerCallback(); // Sets vsync period. void setVsyncPeriod(const nsecs_t period); // Idle timer feature's function to change the refresh rate. void timerChangeRefreshRate(IdleTimerState idleTimerState); + // Touch timer feature's function to change the refresh rate. + void touchChangeRefreshRate(TouchState touchState); // Calculate the new refresh rate type RefreshRateType calculateRefreshRateType() REQUIRES(mFeatureStateLock); // Acquires a lock and calls the ChangeRefreshRateCallback() with given parameters. @@ -258,6 +270,10 @@ private: // timer. bool mSupportKernelTimer; + // Timer used to monitor touch events. + int64_t mSetTouchTimerMs = 0; + std::unique_ptr<scheduler::IdleTimer> mTouchTimer; + std::mutex mCallbackLock; ChangeRefreshRateCallback mChangeRefreshRateCallback GUARDED_BY(mCallbackLock); GetVsyncPeriod mGetVsyncPeriod GUARDED_BY(mCallbackLock); @@ -268,6 +284,7 @@ private: ContentFeatureState mCurrentContentFeatureState GUARDED_BY(mFeatureStateLock) = ContentFeatureState::CONTENT_DETECTION_OFF; IdleTimerState mCurrentIdleTimerState GUARDED_BY(mFeatureStateLock) = IdleTimerState::RESET; + TouchState mCurrentTouchState GUARDED_BY(mFeatureStateLock) = TouchState::INACTIVE; uint32_t mContentRefreshRate GUARDED_BY(mFeatureStateLock); RefreshRateType mRefreshRateType GUARDED_BY(mFeatureStateLock); bool mIsHDRContent GUARDED_BY(mFeatureStateLock) = false; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 3f2240ee57..dd75868443 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -113,6 +113,7 @@ #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> #include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h> #include <android/hardware/configstore/1.1/types.h> +#include <android/hardware/power/1.0/IPower.h> #include <configstore/Utils.h> #include <layerproto/LayerProtoParser.h> @@ -124,6 +125,7 @@ using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; using namespace android::sysprop; +using android::hardware::power::V1_0::PowerHint; using base::StringAppendF; using ui::ColorMode; using ui::Dataspace; @@ -985,7 +987,7 @@ bool SurfaceFlinger::performSetActiveConfig() { if (mCheckPendingFence) { if (previousFrameMissed()) { // fence has not signaled yet. wait for the next invalidate - mEventQueue->invalidateForHWC(); + mEventQueue->invalidate(); return true; } @@ -1036,7 +1038,7 @@ bool SurfaceFlinger::performSetActiveConfig() { // we need to submit an empty frame to HWC to start the process mCheckPendingFence = true; - mEventQueue->invalidateForHWC(); + mEventQueue->invalidate(); return false; } @@ -1047,6 +1049,7 @@ status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& displayToken, } std::vector<ColorMode> modes; + bool isInternalDisplay = false; { ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId); @@ -1056,9 +1059,20 @@ status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& displayToken, } modes = getHwComposer().getColorModes(*displayId); + isInternalDisplay = displayId == getInternalDisplayIdLocked(); } outColorModes->clear(); - std::copy(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes)); + + // If it's built-in display and the configuration claims it's not wide color capable, + // filter out all wide color modes. The typical reason why this happens is that the + // hardware is not good enough to support GPU composition of wide color, and thus the + // OEMs choose to disable this capability. + if (isInternalDisplay && !hasWideColorDisplay) { + std::remove_copy_if(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes), + isWideColorMode); + } else { + std::copy(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes)); + } return NO_ERROR; } @@ -1205,6 +1219,13 @@ status_t SurfaceFlinger::isWideColorDisplay(const sp<IBinder>& displayToken, if (!display) { return BAD_VALUE; } + + // Use hasWideColorDisplay to override built-in display. + const auto displayId = display->getId(); + if (displayId && displayId == getInternalDisplayIdLocked()) { + *outIsWideColorDisplay = hasWideColorDisplay; + return NO_ERROR; + } *outIsWideColorDisplay = display->hasWideColorGamut(); return NO_ERROR; } @@ -1332,6 +1353,16 @@ status_t SurfaceFlinger::setDisplayBrightness(const sp<IBinder>& displayToken, return getHwComposer().setDisplayBrightness(*displayId, brightness); } +status_t SurfaceFlinger::notifyPowerHint(int32_t hintId) { + PowerHint powerHint = static_cast<PowerHint>(hintId); + + if (powerHint == PowerHint::INTERACTION) { + mScheduler->notifyTouchEvent(); + } + + return NO_ERROR; +} + // ---------------------------------------------------------------------------- sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection( @@ -1354,10 +1385,12 @@ void SurfaceFlinger::waitForEvent() { } void SurfaceFlinger::signalTransaction() { + mScheduler->resetIdleTimer(); mEventQueue->invalidate(); } void SurfaceFlinger::signalLayerUpdate() { + mScheduler->resetIdleTimer(); mEventQueue->invalidate(); } @@ -4732,7 +4765,7 @@ void SurfaceFlinger::dumpDisplayIdentificationData(std::string& result) const { } void SurfaceFlinger::dumpWideColorInfo(std::string& result) const { - StringAppendF(&result, "Device has wide color display: %d\n", hasWideColorDisplay); + StringAppendF(&result, "Device has wide color built-in display: %d\n", hasWideColorDisplay); StringAppendF(&result, "Device uses color management: %d\n", useColorManagement); StringAppendF(&result, "DisplayColorSetting: %s\n", decodeDisplayColorSetting(mDisplayColorSetting).c_str()); @@ -5034,7 +5067,8 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case SET_POWER_MODE: case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES: case SET_DISPLAY_CONTENT_SAMPLING_ENABLED: - case GET_DISPLAYED_CONTENT_SAMPLE: { + case GET_DISPLAYED_CONTENT_SAMPLE: + case NOTIFY_POWER_HINT: { if (!callingThreadHasUnscopedSurfaceFlingerAccess()) { IPCThreadState* ipc = IPCThreadState::self(); ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d", @@ -5473,7 +5507,7 @@ void SurfaceFlinger::repaintEverything() { void SurfaceFlinger::repaintEverythingForHWC() { mRepaintEverything = true; - mEventQueue->invalidateForHWC(); + mEventQueue->invalidate(); } // A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d9de07b359..ddfe88c928 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -460,6 +460,7 @@ private: status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken, bool* outSupport) const override; status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) const override; + status_t notifyPowerHint(int32_t hintId) override; /* ------------------------------------------------------------------------ * DeathRecipient interface diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp index c43d095341..4f352ff9db 100644 --- a/services/surfaceflinger/SurfaceFlingerProperties.cpp +++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp @@ -230,6 +230,14 @@ int32_t set_idle_timer_ms(int32_t defaultValue) { return defaultValue; } +int32_t set_touch_timer_ms(int32_t defaultValue) { + auto temp = SurfaceFlingerProperties::set_touch_timer_ms(); + if (temp.has_value()) { + return *temp; + } + return defaultValue; +} + bool use_smart_90_for_video(bool defaultValue) { auto temp = SurfaceFlingerProperties::use_smart_90_for_video(); if (temp.has_value()) { diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h index d772fa84a3..1964ccd582 100644 --- a/services/surfaceflinger/SurfaceFlingerProperties.h +++ b/services/surfaceflinger/SurfaceFlingerProperties.h @@ -72,6 +72,8 @@ int32_t wcg_composition_pixel_format( int32_t set_idle_timer_ms(int32_t defaultValue); +int32_t set_touch_timer_ms(int32_t defaultValue); + bool use_smart_90_for_video(bool defaultValue); bool enable_protected_contents(bool defaultValue); diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop index bd8aacdff6..decabd5e88 100644 --- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop +++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop @@ -298,6 +298,17 @@ prop { prop_name: "ro.surface_flinger.set_idle_timer_ms" } +# setTouchTimerMs indicates what is considered a timeout in milliseconds for Scheduler. +# This value is used by the Scheduler to trigger touch inactivity callbacks that will switch the +# display to a lower refresh rate. Setting this property to 0 means there is no timer. +prop { + api_name: "set_touch_timer_ms" + type: Integer + scope: System + access: Readonly + prop_name: "ro.surface_flinger.set_touch_timer_ms" +} + # useSmart90ForVideo indicates whether Scheduler should detect content FPS, and try to adjust the # screen refresh rate based on that. prop { diff --git a/services/surfaceflinger/sysprop/api/system-current.txt b/services/surfaceflinger/sysprop/api/system-current.txt index dd5dbe04b3..6ae3ac15ee 100644 --- a/services/surfaceflinger/sysprop/api/system-current.txt +++ b/services/surfaceflinger/sysprop/api/system-current.txt @@ -18,6 +18,7 @@ package android.sysprop { method public static java.util.Optional<android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values> primary_display_orientation(); method public static java.util.Optional<java.lang.Boolean> running_without_sync_framework(); method public static java.util.Optional<java.lang.Integer> set_idle_timer_ms(); + method public static java.util.Optional<java.lang.Integer> set_touch_timer_ms(); method public static java.util.Optional<java.lang.Boolean> start_graphics_allocator_service(); method public static java.util.Optional<java.lang.Boolean> support_kernel_idle_timer(); method public static java.util.Optional<java.lang.Boolean> use_color_management(); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index d03c25df70..ec1ac4b229 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -1056,6 +1056,53 @@ TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) { screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); } +TEST_P(LayerTypeTransactionTest, SetLayerAndRelative) { + sp<SurfaceControl> parent = + LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor); + + sp<SurfaceControl> childLayer; + ASSERT_NO_FATAL_FAILURE( + childLayer = LayerTransactionTest::createLayer("childLayer", 0 /* buffer width */, + 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor, + parent.get())); + Transaction() + .setColor(childLayer, half3{1.0f, 0.0f, 0.0f}) + .setColor(parent, half3{0.0f, 0.0f, 0.0f}) + .show(childLayer) + .show(parent) + .setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight)) + .setCrop_legacy(childLayer, Rect(0, 0, 20, 30)) + .apply(); + + Transaction() + .setRelativeLayer(childLayer, parent->getHandle(), -1) + .setLayer(childLayer, 1) + .apply(); + + { + SCOPED_TRACE("setLayer above"); + // Set layer should get applied and place the child above. + std::unique_ptr<ScreenCapture> screenshot; + ScreenCapture::captureScreen(&screenshot); + screenshot->expectColor(Rect(0, 0, 20, 30), Color::RED); + } + + Transaction() + .setLayer(childLayer, 1) + .setRelativeLayer(childLayer, parent->getHandle(), -1) + .apply(); + + { + SCOPED_TRACE("setRelative below"); + // Set relative layer should get applied and place the child below. + std::unique_ptr<ScreenCapture> screenshot; + ScreenCapture::captureScreen(&screenshot); + screenshot->expectColor(Rect(0, 0, 20, 30), Color::BLACK); + } +} + void LayerRenderTypeTransactionTest::setRelativeZGroupHelper(uint32_t layerType) { sp<SurfaceControl> layerR; sp<SurfaceControl> layerG; diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp index 83a92c8691..ea908a9018 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -55,10 +55,8 @@ protected: class MockEventThreadConnection : public EventThreadConnection { public: MockEventThreadConnection(android::impl::EventThread* eventThread, - ResyncCallback&& resyncCallback, - ResetIdleTimerCallback&& resetIdleTimerCallback) - : EventThreadConnection(eventThread, std::move(resyncCallback), - std::move(resetIdleTimerCallback)) {} + ResyncCallback&& resyncCallback) + : EventThreadConnection(eventThread, std::move(resyncCallback)) {} MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event)); }; @@ -88,7 +86,6 @@ protected: AsyncCallRecorder<void (*)(VSyncSource::Callback*)> mVSyncSetCallbackCallRecorder; AsyncCallRecorder<void (*)(nsecs_t)> mVSyncSetPhaseOffsetCallRecorder; AsyncCallRecorder<void (*)()> mResyncCallRecorder; - AsyncCallRecorder<void (*)()> mResetIdleTimerCallRecorder; AsyncCallRecorder<void (*)(nsecs_t)> mInterceptVSyncCallRecorder; ConnectionEventRecorder mConnectionEventCallRecorder{0}; @@ -143,8 +140,7 @@ void EventThreadTest::createThread() { sp<EventThreadTest::MockEventThreadConnection> EventThreadTest::createConnection( ConnectionEventRecorder& recorder) { sp<MockEventThreadConnection> connection = - new MockEventThreadConnection(mThread.get(), mResyncCallRecorder.getInvocable(), - mResetIdleTimerCallRecorder.getInvocable()); + new MockEventThreadConnection(mThread.get(), mResyncCallRecorder.getInvocable()); EXPECT_CALL(*connection, postEvent(_)).WillRepeatedly(Invoke(recorder.getInvocable())); return connection; } @@ -225,7 +221,6 @@ TEST_F(EventThreadTest, canCreateAndDestroyThreadWithNoEventsSent) { EXPECT_FALSE(mVSyncSetCallbackCallRecorder.waitForCall(0us).has_value()); EXPECT_FALSE(mVSyncSetPhaseOffsetCallRecorder.waitForCall(0us).has_value()); EXPECT_FALSE(mResyncCallRecorder.waitForCall(0us).has_value()); - EXPECT_FALSE(mResetIdleTimerCallRecorder.waitForCall(0us).has_value()); EXPECT_FALSE(mInterceptVSyncCallRecorder.waitForCall(0us).has_value()); EXPECT_FALSE(mConnectionEventCallRecorder.waitForCall(0us).has_value()); } @@ -235,7 +230,7 @@ TEST_F(EventThreadTest, vsyncRequestIsIgnoredIfDisplayIsDisconnected) { expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, false); // Signal that we want the next vsync event to be posted to the connection. - mThread->requestNextVsync(mConnection, false); + mThread->requestNextVsync(mConnection); // EventThread should not enable vsync callbacks. EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value()); @@ -243,10 +238,9 @@ TEST_F(EventThreadTest, vsyncRequestIsIgnoredIfDisplayIsDisconnected) { TEST_F(EventThreadTest, requestNextVsyncPostsASingleVSyncEventToTheConnection) { // Signal that we want the next vsync event to be posted to the connection - mThread->requestNextVsync(mConnection, true); + mThread->requestNextVsync(mConnection); - // EventThread should immediately reset the idle timer and request a resync. - EXPECT_TRUE(mResetIdleTimerCallRecorder.waitForCall().has_value()); + // EventThread should immediately request a resync. EXPECT_TRUE(mResyncCallRecorder.waitForCall().has_value()); // EventThread should enable vsync callbacks. diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index b960bdf3fd..1f8b11180b 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -25,7 +25,7 @@ protected: class MockEventThreadConnection : public android::EventThreadConnection { public: explicit MockEventThreadConnection(EventThread* eventThread) - : EventThreadConnection(eventThread, ResyncCallback(), ResetIdleTimerCallback()) {} + : EventThreadConnection(eventThread, ResyncCallback()) {} ~MockEventThreadConnection() = default; MOCK_METHOD1(stealReceiveChannel, status_t(gui::BitTube* outChannel)); @@ -81,7 +81,7 @@ SchedulerTest::SchedulerTest() { // createConnection call to scheduler makes a createEventConnection call to EventThread. Make // sure that call gets executed and returns an EventThread::Connection object. - EXPECT_CALL(*mEventThread, createEventConnection(_, _)) + EXPECT_CALL(*mEventThread, createEventConnection(_)) .WillRepeatedly(Return(mEventThreadConnection)); mConnectionHandle = mScheduler->createConnection("appConnection", 16, ResyncCallback(), diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index 1c397d8443..c3d2b8de4f 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -34,8 +34,7 @@ public: // Scheduler::Connection. This allows plugging in mock::EventThread. sp<Scheduler::ConnectionHandle> addConnection(std::unique_ptr<EventThread> eventThread) { sp<EventThreadConnection> eventThreadConnection = - new EventThreadConnection(eventThread.get(), ResyncCallback(), - ResetIdleTimerCallback()); + new EventThreadConnection(eventThread.get(), ResyncCallback()); const int64_t id = sNextId++; mConnections.emplace(id, std::make_unique<Scheduler::Connection>(new ConnectionHandle(id), diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h index cb4a300611..5b5f8e7fab 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h +++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h @@ -28,8 +28,7 @@ public: EventThread(); ~EventThread() override; - MOCK_CONST_METHOD2(createEventConnection, - sp<EventThreadConnection>(ResyncCallback, ResetIdleTimerCallback)); + MOCK_CONST_METHOD1(createEventConnection, sp<EventThreadConnection>(ResyncCallback)); MOCK_METHOD0(onScreenReleased, void()); MOCK_METHOD0(onScreenAcquired, void()); MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool)); @@ -39,7 +38,7 @@ public: MOCK_METHOD1(registerDisplayEventConnection, status_t(const sp<android::EventThreadConnection> &)); MOCK_METHOD2(setVsyncRate, void(uint32_t, const sp<android::EventThreadConnection> &)); - MOCK_METHOD2(requestNextVsync, void(const sp<android::EventThreadConnection> &, bool)); + MOCK_METHOD1(requestNextVsync, void(const sp<android::EventThreadConnection> &)); MOCK_METHOD1(pauseVsyncCallback, void(bool)); }; diff --git a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h index e22d3e8ab2..1b1c1a7990 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h +++ b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h @@ -35,7 +35,6 @@ public: MOCK_METHOD0(waitMessage, void()); MOCK_METHOD2(postMessage, status_t(const sp<MessageBase>&, nsecs_t)); MOCK_METHOD0(invalidate, void()); - MOCK_METHOD0(invalidateForHWC, void()); MOCK_METHOD0(refresh, void()); }; diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp index a22f60e330..e5f40aa84a 100644 --- a/vulkan/libvulkan/swapchain.cpp +++ b/vulkan/libvulkan/swapchain.cpp @@ -1171,7 +1171,9 @@ VkResult CreateSwapchainKHR(VkDevice device, } uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value); uint32_t num_images = - (create_info->minImageCount - 1) + min_undequeued_buffers; + (swap_interval ? create_info->minImageCount + : std::max(3u, create_info->minImageCount)) - + 1 + min_undequeued_buffers; // Lower layer insists that we have at least two buffers. This is wasteful // and we'd like to relax it in the shared case, but not all the pieces are |