diff options
29 files changed, 350 insertions, 92 deletions
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp index 08a31c1636..402767a426 100644 --- a/cmds/idlcli/Android.bp +++ b/cmds/idlcli/Android.bp @@ -15,6 +15,7 @@ cc_defaults { name: "idlcli-defaults", shared_libs: [ + "android.hardware.vibrator-ndk_platform", "android.hardware.vibrator@1.0", "android.hardware.vibrator@1.1", "android.hardware.vibrator@1.2", @@ -24,7 +25,6 @@ cc_defaults { "libhidlbase", "liblog", "libutils", - "vintf-vibrator-ndk_platform", ], cflags: [ "-DLOG_TAG=\"idlcli\"", diff --git a/docs/images/camera2/metadata/android.scaler.cropRegion/crop-region-11-ratio.png b/docs/images/camera2/metadata/android.scaler.cropRegion/crop-region-11-ratio.png Binary files differnew file mode 100644 index 0000000000..b6c07656e3 --- /dev/null +++ b/docs/images/camera2/metadata/android.scaler.cropRegion/crop-region-11-ratio.png diff --git a/docs/images/camera2/metadata/android.scaler.cropRegion/crop-region-169-ratio.png b/docs/images/camera2/metadata/android.scaler.cropRegion/crop-region-169-ratio.png Binary files differnew file mode 100644 index 0000000000..4e975e5551 --- /dev/null +++ b/docs/images/camera2/metadata/android.scaler.cropRegion/crop-region-169-ratio.png diff --git a/docs/images/camera2/metadata/android.scaler.cropRegion/crop-region-43-ratio.png b/docs/images/camera2/metadata/android.scaler.cropRegion/crop-region-43-ratio.png Binary files differnew file mode 100644 index 0000000000..a331095df2 --- /dev/null +++ b/docs/images/camera2/metadata/android.scaler.cropRegion/crop-region-43-ratio.png diff --git a/docs/images/camera2/metadata/android.scaler.cropRegion/crop-region-43-square-ratio.png b/docs/images/camera2/metadata/android.scaler.cropRegion/crop-region-43-square-ratio.png Binary files differnew file mode 100644 index 0000000000..41e666854d --- /dev/null +++ b/docs/images/camera2/metadata/android.scaler.cropRegion/crop-region-43-square-ratio.png diff --git a/libs/adbd_auth/adbd_auth.cpp b/libs/adbd_auth/adbd_auth.cpp index 64791098ee..a9c23110c9 100644 --- a/libs/adbd_auth/adbd_auth.cpp +++ b/libs/adbd_auth/adbd_auth.cpp @@ -178,6 +178,10 @@ public: this->callbacks_.key_authorized(arg, id); this->dispatched_prompt_ = std::nullopt; + + // We need to dispatch pending prompts here upon success as well, + // since we might have multiple queued prompts. + DispatchPendingPrompt(); } else if (packet[0] == 'N' && packet[1] == 'O') { CHECK_EQ(2UL, packet.length()); // TODO: Do we want a callback if the key is denied? diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp index 54f383e915..208d729812 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -36,7 +36,10 @@ static const size_t EVENT_BUFFER_SIZE = 100; DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper, ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposer::ConfigChanged configChanged) - : mLooper(looper), mReceiver(vsyncSource, configChanged), mWaitingForVsync(false) { + : mLooper(looper), + mReceiver(vsyncSource, configChanged), + mWaitingForVsync(false), + mConfigChangeFlag(configChanged) { ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this); } @@ -86,6 +89,18 @@ status_t DisplayEventDispatcher::scheduleVsync() { return OK; } +void DisplayEventDispatcher::toggleConfigEvents(ISurfaceComposer::ConfigChanged configChangeFlag) { + if (mConfigChangeFlag == configChangeFlag) { + return; + } + status_t status = mReceiver.toggleConfigEvents(configChangeFlag); + if (status) { + ALOGW("Failed enable config events, status=%d", status); + return; + } + mConfigChangeFlag = configChangeFlag; +} + int DisplayEventDispatcher::handleEvent(int, int events, void*) { if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) { ALOGE("Display event receiver pipe was closed or an error occurred. " @@ -140,7 +155,7 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, break; case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: dispatchConfigChanged(ev.header.timestamp, ev.header.displayId, - ev.config.configId); + ev.config.configId, ev.config.vsyncPeriod); break; default: ALOGW("dispatcher %p ~ ignoring unknown event type %#x", this, ev.header.type); diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp index b8faa2df4c..fd6aaf8b46 100644 --- a/libs/gui/DisplayEventReceiver.cpp +++ b/libs/gui/DisplayEventReceiver.cpp @@ -79,6 +79,14 @@ status_t DisplayEventReceiver::requestNextVsync() { return NO_INIT; } +status_t DisplayEventReceiver::toggleConfigEvents( + ISurfaceComposer::ConfigChanged configChangeFlag) { + if (mEventConnection != nullptr) { + mEventConnection->toggleConfigEvents(configChangeFlag); + return NO_ERROR; + } + return NO_INIT; +} ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events, size_t count) { diff --git a/libs/gui/IDisplayEventConnection.cpp b/libs/gui/IDisplayEventConnection.cpp index c0e246fa15..dda5acf8a7 100644 --- a/libs/gui/IDisplayEventConnection.cpp +++ b/libs/gui/IDisplayEventConnection.cpp @@ -26,7 +26,8 @@ enum class Tag : uint32_t { STEAL_RECEIVE_CHANNEL = IBinder::FIRST_CALL_TRANSACTION, SET_VSYNC_RATE, REQUEST_NEXT_VSYNC, - LAST = REQUEST_NEXT_VSYNC, + TOGGLE_CONFIG_EVENTS, + LAST = TOGGLE_CONFIG_EVENTS, }; } // Anonymous namespace @@ -53,6 +54,12 @@ public: callRemoteAsync<decltype(&IDisplayEventConnection::requestNextVsync)>( Tag::REQUEST_NEXT_VSYNC); } + + void toggleConfigEvents(ISurfaceComposer::ConfigChanged configChangeFlag) override { + callRemoteAsync<decltype( + &IDisplayEventConnection::toggleConfigEvents)>(Tag::TOGGLE_CONFIG_EVENTS, + configChangeFlag); + } }; // Out-of-line virtual method definition to trigger vtable emission in this translation unit (see @@ -74,6 +81,8 @@ status_t BnDisplayEventConnection::onTransact(uint32_t code, const Parcel& data, return callLocal(data, reply, &IDisplayEventConnection::setVsyncRate); case Tag::REQUEST_NEXT_VSYNC: return callLocalAsync(data, reply, &IDisplayEventConnection::requestNextVsync); + case Tag::TOGGLE_CONFIG_EVENTS: + return callLocalAsync(data, reply, &IDisplayEventConnection::toggleConfigEvents); } } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 1d887ea931..f378fc5ef6 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -484,14 +484,22 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr mListenerCallbacks[listener].callbackIds.insert(std::make_move_iterator( callbackIds.begin()), std::make_move_iterator(callbackIds.end())); - // register surface controls for this listener that is merging - for (const auto& surfaceControl : surfaceControls) { - registerSurfaceControlForCallback(surfaceControl); - } - mListenerCallbacks[listener] - .surfaceControls.insert(std::make_move_iterator(surfaceControls.begin()), - std::make_move_iterator(surfaceControls.end())); + mListenerCallbacks[listener].surfaceControls.insert(surfaceControls.begin(), + surfaceControls.end()); + + auto& currentProcessCallbackInfo = + mListenerCallbacks[TransactionCompletedListener::getIInstance()]; + currentProcessCallbackInfo.surfaceControls + .insert(std::make_move_iterator(surfaceControls.begin()), + std::make_move_iterator(surfaceControls.end())); + + // register all surface controls for all callbackIds for this listener that is merging + for (const auto& surfaceControl : currentProcessCallbackInfo.surfaceControls) { + TransactionCompletedListener::getInstance() + ->addSurfaceControlToCallbacks(surfaceControl, + currentProcessCallbackInfo.callbackIds); + } } mInputWindowCommands.merge(other.mInputWindowCommands); diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h index f0b7ff5001..0b718010e4 100644 --- a/libs/gui/include/gui/DisplayEventDispatcher.h +++ b/libs/gui/include/gui/DisplayEventDispatcher.h @@ -31,6 +31,7 @@ public: status_t initialize(); void dispose(); status_t scheduleVsync(); + void toggleConfigEvents(ISurfaceComposer::ConfigChanged configChangeFlag); protected: virtual ~DisplayEventDispatcher() = default; @@ -39,12 +40,13 @@ private: sp<Looper> mLooper; DisplayEventReceiver mReceiver; bool mWaitingForVsync; + ISurfaceComposer::ConfigChanged mConfigChangeFlag; virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) = 0; virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) = 0; virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, - int32_t configId) = 0; + int32_t configId, nsecs_t vsyncPeriod) = 0; virtual int handleEvent(int receiveFd, int events, void* data); bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h index a558cf9e18..109e28b9dc 100644 --- a/libs/gui/include/gui/DisplayEventReceiver.h +++ b/libs/gui/include/gui/DisplayEventReceiver.h @@ -73,6 +73,7 @@ public: struct Config { int32_t configId; + nsecs_t vsyncPeriod; }; Header header; @@ -144,6 +145,11 @@ public: */ status_t requestNextVsync(); + /* + * toggleConfigEvents() toggles delivery of config change events. + */ + status_t toggleConfigEvents(ISurfaceComposer::ConfigChanged configChangeFlag); + private: sp<IDisplayEventConnection> mEventConnection; std::unique_ptr<gui::BitTube> mDataChannel; diff --git a/libs/gui/include/gui/IDisplayEventConnection.h b/libs/gui/include/gui/IDisplayEventConnection.h index d783f74d7c..8b35ef6486 100644 --- a/libs/gui/include/gui/IDisplayEventConnection.h +++ b/libs/gui/include/gui/IDisplayEventConnection.h @@ -18,7 +18,7 @@ #include <binder/IInterface.h> #include <binder/SafeInterface.h> - +#include <gui/ISurfaceComposer.h> #include <utils/Errors.h> #include <cstdint> @@ -51,6 +51,13 @@ public: * requestNextVsync() schedules the next vsync event. It has no effect if the vsync rate is > 0. */ virtual void requestNextVsync() = 0; // Asynchronous + + /* + * togglesConfigEvents() configures whether or not display config changes + * should be propagated. + */ + virtual void toggleConfigEvents( + ISurfaceComposer::ConfigChanged configChangeFlag) = 0; // Asynchronous }; class BnDisplayEventConnection : public SafeBnInterface<IDisplayEventConnection> { diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp index 05ff93e5c1..7e71ede419 100644 --- a/libs/nativedisplay/AChoreographer.cpp +++ b/libs/nativedisplay/AChoreographer.cpp @@ -17,11 +17,7 @@ #define LOG_TAG "Choreographer" //#define LOG_NDEBUG 0 -#include <cinttypes> -#include <queue> -#include <thread> - -#include <android/choreographer.h> +#include <apex/choreographer.h> #include <gui/DisplayEventDispatcher.h> #include <gui/ISurfaceComposer.h> #include <gui/SurfaceComposerClient.h> @@ -29,6 +25,11 @@ #include <utils/Mutex.h> #include <utils/Timers.h> +#include <cinttypes> +#include <optional> +#include <queue> +#include <thread> + namespace android { static inline const char* toString(bool value) { @@ -48,11 +49,17 @@ struct FrameCallback { } }; +struct RefreshRateCallback { + AChoreographer_refreshRateCallback callback; + void* data; +}; class Choreographer : public DisplayEventDispatcher, public MessageHandler { public: void postFrameCallbackDelayed(AChoreographer_frameCallback cb, AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay); + void registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data); + void unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb); enum { MSG_SCHEDULE_CALLBACKS = 0, @@ -71,18 +78,23 @@ private: void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) override; void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override; - void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, - int32_t configId) override; + void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId, + nsecs_t vsyncPeriod) override; void scheduleCallbacks(); // Protected by mLock - std::priority_queue<FrameCallback> mCallbacks; + std::priority_queue<FrameCallback> mFrameCallbacks; + + // Protected by mLock + std::vector<RefreshRateCallback> mRefreshRateCallbacks; + nsecs_t mVsyncPeriod = 0; mutable Mutex mLock; const sp<Looper> mLooper; const std::thread::id mThreadId; + const std::optional<PhysicalDisplayId> mInternalDisplayId; }; @@ -104,9 +116,11 @@ Choreographer* Choreographer::getForThread() { return gChoreographer; } -Choreographer::Choreographer(const sp<Looper>& looper) : - DisplayEventDispatcher(looper), mLooper(looper), mThreadId(std::this_thread::get_id()) { -} +Choreographer::Choreographer(const sp<Looper>& looper) + : DisplayEventDispatcher(looper), + mLooper(looper), + mThreadId(std::this_thread::get_id()), + mInternalDisplayId(SurfaceComposerClient::getInternalDisplayId()) {} void Choreographer::postFrameCallbackDelayed( AChoreographer_frameCallback cb, AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay) { @@ -114,7 +128,7 @@ void Choreographer::postFrameCallbackDelayed( FrameCallback callback{cb, cb64, data, now + delay}; { AutoMutex _l{mLock}; - mCallbacks.push(callback); + mFrameCallbacks.push(callback); } if (callback.dueTime <= now) { if (std::this_thread::get_id() != mThreadId) { @@ -129,10 +143,31 @@ void Choreographer::postFrameCallbackDelayed( } } +void Choreographer::registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data) { + { + AutoMutex _l{mLock}; + mRefreshRateCallbacks.emplace_back(RefreshRateCallback{cb, data}); + toggleConfigEvents(ISurfaceComposer::ConfigChanged::eConfigChangedDispatch); + } +} + +void Choreographer::unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb) { + { + AutoMutex _l{mLock}; + std::remove_if(mRefreshRateCallbacks.begin(), mRefreshRateCallbacks.end(), + [&](const RefreshRateCallback& callback) { + return cb == callback.callback; + }); + if (mRefreshRateCallbacks.empty()) { + toggleConfigEvents(ISurfaceComposer::ConfigChanged::eConfigChangedSuppress); + } + } +} + void Choreographer::scheduleCallbacks() { AutoMutex _{mLock}; nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - if (mCallbacks.top().dueTime <= now) { + if (mFrameCallbacks.top().dueTime <= now) { ALOGV("choreographer %p ~ scheduling vsync", this); scheduleVsync(); return; @@ -147,9 +182,9 @@ void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t { AutoMutex _l{mLock}; nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - while (!mCallbacks.empty() && mCallbacks.top().dueTime < now) { - callbacks.push_back(mCallbacks.top()); - mCallbacks.pop(); + while (!mFrameCallbacks.empty() && mFrameCallbacks.top().dueTime < now) { + callbacks.push_back(mFrameCallbacks.top()); + mFrameCallbacks.pop(); } } for (const auto& cb : callbacks) { @@ -167,11 +202,25 @@ void Choreographer::dispatchHotplug(nsecs_t, PhysicalDisplayId displayId, bool c this, displayId, toString(connected)); } -void Choreographer::dispatchConfigChanged(nsecs_t, PhysicalDisplayId displayId, - int32_t configId) { - ALOGV("choreographer %p ~ received config changed event (displayId=%" - ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", configId=%s), ignoring.", - this, displayId, toString(configId)); +// TODO(b/74619554): The PhysicalDisplayId is ignored because currently +// Choreographer only supports dispatching VSYNC events for the internal +// display, so as such Choreographer does not support the notion of multiple +// displays. When multi-display choreographer is properly supported, then +// PhysicalDisplayId should no longer be ignored. +void Choreographer::dispatchConfigChanged(nsecs_t, PhysicalDisplayId, int32_t, + nsecs_t vsyncPeriod) { + { + AutoMutex _l{mLock}; + for (const auto& cb : mRefreshRateCallbacks) { + // Only perform the callback when the old refresh rate is different + // from the new refresh rate, so that we don't dispatch the callback + // on every single configuration change. + if (mVsyncPeriod != vsyncPeriod) { + cb.callback(vsyncPeriod, cb.data); + mVsyncPeriod = vsyncPeriod; + } + } + } } void Choreographer::handleMessage(const Message& message) { @@ -223,3 +272,12 @@ void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer, AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed( nullptr, callback, data, ms2ns(delayMillis)); } +void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer, + AChoreographer_refreshRateCallback callback, + void* data) { + AChoreographer_to_Choreographer(choreographer)->registerRefreshRateCallback(callback, data); +} +void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer, + AChoreographer_refreshRateCallback callback) { + AChoreographer_to_Choreographer(choreographer)->unregisterRefreshRateCallback(callback); +} diff --git a/libs/nativedisplay/include/apex/choreographer.h b/libs/nativedisplay/include/apex/choreographer.h new file mode 100644 index 0000000000..352213edc1 --- /dev/null +++ b/libs/nativedisplay/include/apex/choreographer.h @@ -0,0 +1,43 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <android/choreographer.h> +#include <inttypes.h> + +__BEGIN_DECLS + +/** + * Prototype of the function that is called when the display refresh rate + * changes. It's passed the new vsync period in nanoseconds, as well as the data + * pointer provided by the application that registered a callback. + */ +typedef void (*AChoreographer_refreshRateCallback)(int64_t vsyncPeriodNanos, void* data); + +/** + * Registers a callback to be run when the display refresh rate changes. + */ +void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer, + AChoreographer_refreshRateCallback, void* data); + +/** + * Unregisters a callback to be run when the display refresh rate changes. + */ +void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer, + AChoreographer_refreshRateCallback); + +__END_DECLS diff --git a/libs/nativedisplay/libnativedisplay.map.txt b/libs/nativedisplay/libnativedisplay.map.txt index 3b29c18fc3..3b6a24171b 100644 --- a/libs/nativedisplay/libnativedisplay.map.txt +++ b/libs/nativedisplay/libnativedisplay.map.txt @@ -5,6 +5,8 @@ LIBNATIVEDISPLAY { AChoreographer_postFrameCallbackDelayed; # apex # introduced=30 AChoreographer_postFrameCallback64; # apex # introduced=30 AChoreographer_postFrameCallbackDelayed64; # apex # introduced=30 + AChoreographer_registerRefreshRateCallback; # apex # introduced=30 + AChoreographer_unregisterRefreshRateCallback; # apex # introduced=30 local: *; }; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index c7eb9c391a..6fd1629502 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1930,6 +1930,11 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) [&]() { return layerInfo->mutable_visible_region(); }); LayerProtoHelper::writeToProto(surfaceDamageRegion, [&]() { return layerInfo->mutable_damage_region(); }); + + if (hasColorTransform()) { + LayerProtoHelper::writeToProto(getColorTransform(), + layerInfo->mutable_color_transform()); + } } if (traceFlags & SurfaceTracing::TRACE_EXTRA) { diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index c94e439659..b4022704d5 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -155,5 +155,13 @@ void LayerProtoHelper::writeToProto( } } +void LayerProtoHelper::writeToProto(const mat4 matrix, ColorTransformProto* colorTransformProto) { + for (int i = 0; i < mat4::ROW_SIZE; i++) { + for (int j = 0; j < mat4::COL_SIZE; j++) { + colorTransformProto->add_val(matrix[i][j]); + } + } +} + } // namespace surfaceflinger } // namespace android diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h index 1754a3f2d7..502238d389 100644 --- a/services/surfaceflinger/LayerProtoHelper.h +++ b/services/surfaceflinger/LayerProtoHelper.h @@ -43,6 +43,7 @@ public: static void writeToProto(const InputWindowInfo& inputInfo, const wp<Layer>& touchableRegionBounds, std::function<InputWindowInfoProto*()> getInputWindowInfoProto); + static void writeToProto(const mat4 matrix, ColorTransformProto* colorTransformProto); }; } // namespace surfaceflinger diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index ff800c3dbf..5bdef5807f 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -103,10 +103,11 @@ DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t times } DisplayEventReceiver::Event makeConfigChanged(PhysicalDisplayId displayId, - HwcConfigIndexType configId) { + HwcConfigIndexType configId, nsecs_t vsyncPeriod) { DisplayEventReceiver::Event event; event.header = {DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED, displayId, systemTime()}; event.config.configId = configId.value(); + event.config.vsyncPeriod = vsyncPeriod; return event; } @@ -116,7 +117,7 @@ EventThreadConnection::EventThreadConnection(EventThread* eventThread, ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) : resyncCallback(std::move(resyncCallback)), - configChanged(configChanged), + mConfigChanged(configChanged), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {} @@ -145,6 +146,18 @@ void EventThreadConnection::requestNextVsync() { mEventThread->requestNextVsync(this); } +void EventThreadConnection::toggleConfigEvents(ISurfaceComposer::ConfigChanged configChangeFlag) { + ATRACE_NAME("enableConfigEvents"); + mConfigChanged = configChangeFlag; + + // In principle it's possible for rapidly toggling config events to drop an + // event here, but it's unlikely in practice. + if (configChangeFlag == ISurfaceComposer::eConfigChangedDispatch) { + mForcedConfigChangeDispatch = true; + mEventThread->requestLatestConfig(); + } +} + status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) { ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1); return size < 0 ? status_t(size) : status_t(NO_ERROR); @@ -257,6 +270,24 @@ void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) } } +void EventThread::requestLatestConfig() { + std::lock_guard<std::mutex> lock(mMutex); + auto pendingConfigChange = + std::find_if(std::begin(mPendingEvents), std::end(mPendingEvents), + [&](const DisplayEventReceiver::Event& event) { + return event.header.type == + DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED; + }); + + // If we didn't find a pending config change event, then push out the + // latest one we've ever seen. + if (pendingConfigChange == std::end(mPendingEvents)) { + mPendingEvents.push_back(mLastConfigChangeEvent); + } + + mCondition.notify_all(); +} + void EventThread::onScreenReleased() { std::lock_guard<std::mutex> lock(mMutex); if (!mVSyncState || mVSyncState->synthetic) { @@ -292,10 +323,11 @@ void EventThread::onHotplugReceived(PhysicalDisplayId displayId, bool connected) mCondition.notify_all(); } -void EventThread::onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexType configId) { +void EventThread::onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexType configId, + nsecs_t vsyncPeriod) { std::lock_guard<std::mutex> lock(mMutex); - mPendingEvents.push_back(makeConfigChanged(displayId, configId)); + mPendingEvents.push_back(makeConfigChanged(displayId, configId, vsyncPeriod)); mCondition.notify_all(); } @@ -325,6 +357,9 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) { mInterceptVSyncsCallback(event->header.timestamp); } break; + case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: + mLastConfigChangeEvent = *event; + break; } } @@ -398,8 +433,11 @@ bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: return true; - case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: - return connection->configChanged == ISurfaceComposer::eConfigChangedDispatch; + case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: { + const bool forcedDispatch = connection->mForcedConfigChangeDispatch.exchange(false); + return forcedDispatch || + connection->mConfigChanged == ISurfaceComposer::eConfigChangedDispatch; + } case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: switch (connection->vsyncRequest) { diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h index a42546c7df..641b2a5782 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -81,12 +81,19 @@ public: status_t stealReceiveChannel(gui::BitTube* outChannel) override; status_t setVsyncRate(uint32_t rate) override; void requestNextVsync() override; // asynchronous + void toggleConfigEvents(ISurfaceComposer::ConfigChanged configChangeFlag) override; // Called in response to requestNextVsync. const ResyncCallback resyncCallback; VSyncRequest vsyncRequest = VSyncRequest::None; - const ISurfaceComposer::ConfigChanged configChanged; + std::atomic<ISurfaceComposer::ConfigChanged> mConfigChanged = + ISurfaceComposer::ConfigChanged::eConfigChangedSuppress; + // Store whether we need to force dispatching a config change separately - + // if mConfigChanged ever changes before the config change is dispatched + // then we still need to propagate an initial config to the app if we + // haven't already. + std::atomic<bool> mForcedConfigChangeDispatch = false; private: virtual void onFirstRef(); @@ -110,7 +117,8 @@ public: virtual void onHotplugReceived(PhysicalDisplayId displayId, bool connected) = 0; // called when SF changes the active config and apps needs to be notified about the change - virtual void onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexType configId) = 0; + virtual void onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexType configId, + nsecs_t vsyncPeriod) = 0; virtual void dump(std::string& result) const = 0; @@ -121,6 +129,11 @@ public: 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) = 0; + + // Dispatches the most recent configuration + // Usage of this method assumes that only the primary internal display + // supports multiple display configurations. + virtual void requestLatestConfig() = 0; }; namespace impl { @@ -138,6 +151,7 @@ public: status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override; void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) override; void requestNextVsync(const sp<EventThreadConnection>& connection) override; + void requestLatestConfig() override; // called before the screen is turned off from main thread void onScreenReleased() override; @@ -147,7 +161,8 @@ public: void onHotplugReceived(PhysicalDisplayId displayId, bool connected) override; - void onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexType configId) override; + void onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexType configId, + nsecs_t vsyncPeriod) override; void dump(std::string& result) const override; @@ -182,6 +197,7 @@ private: std::vector<wp<EventThreadConnection>> mDisplayEventConnections GUARDED_BY(mMutex); std::deque<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex); + DisplayEventReceiver::Event mLastConfigChangeEvent GUARDED_BY(mMutex); // VSYNC state of connected display. struct VSyncState { diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index e845e8cb48..ff9cf86604 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -222,9 +222,9 @@ void Scheduler::onScreenReleased(ConnectionHandle handle) { } void Scheduler::onConfigChanged(ConnectionHandle handle, PhysicalDisplayId displayId, - HwcConfigIndexType configId) { + HwcConfigIndexType configId, nsecs_t vsyncPeriod) { RETURN_IF_INVALID_HANDLE(handle); - mConnections[handle].thread->onConfigChanged(displayId, configId); + mConnections[handle].thread->onConfigChanged(displayId, configId, vsyncPeriod); } void Scheduler::dump(ConnectionHandle handle, std::string& result) const { diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 2fa8b3f548..2cdb757f42 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -74,7 +74,8 @@ public: sp<EventThreadConnection> getEventConnection(ConnectionHandle); void onHotplugReceived(ConnectionHandle, PhysicalDisplayId, bool connected); - void onConfigChanged(ConnectionHandle, PhysicalDisplayId, HwcConfigIndexType configId); + void onConfigChanged(ConnectionHandle, PhysicalDisplayId, HwcConfigIndexType configId, + nsecs_t vsyncPeriod); void onScreenAcquired(ConnectionHandle); void onScreenReleased(ConnectionHandle); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d02d7833a3..8c1d168cdb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -953,8 +953,11 @@ void SurfaceFlinger::setActiveConfigInternal() { ATRACE_INT("ActiveConfigFPS", refreshRate.fps); if (mUpcomingActiveConfig.event != Scheduler::ConfigEvent::None) { + const nsecs_t vsyncPeriod = + mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId) + .vsyncPeriod; mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value, - mUpcomingActiveConfig.configId); + mUpcomingActiveConfig.configId, vsyncPeriod); } } @@ -2688,6 +2691,17 @@ void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) { mRegionSamplingThread = new RegionSamplingThread(*this, *mScheduler, RegionSamplingThread::EnvironmentTimingTunables()); + // Dispatch a config change request for the primary display on scheduler + // initialization, so that the EventThreads always contain a reference to a + // prior configuration. + // + // This is a bit hacky, but this avoids a back-pointer into the main SF + // classes from EventThread, and there should be no run-time binder cost + // anyway since there are no connected apps at this point. + const nsecs_t vsyncPeriod = + mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig).vsyncPeriod; + mScheduler->onConfigChanged(mAppConnectionHandle, primaryDisplayId.value, currentConfig, + vsyncPeriod); } void SurfaceFlinger::commitTransaction() @@ -5577,7 +5591,10 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal(const sp<DisplayDe auto configId = HwcConfigIndexType(defaultConfig); display->setActiveConfig(configId); - mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value, configId); + const nsecs_t vsyncPeriod = + mRefreshRateConfigs->getRefreshRateFromConfigId(configId).vsyncPeriod; + mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value, configId, + vsyncPeriod); return NO_ERROR; } @@ -5601,8 +5618,10 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal(const sp<DisplayDe // TODO(b/140204874): This hack triggers a notification that something has changed, so // that listeners that care about a change in allowed configs can get the notification. // Giving current ActiveConfig so that most other listeners would just drop the event + const nsecs_t vsyncPeriod = + mRefreshRateConfigs->getRefreshRateFromConfigId(display->getActiveConfig()).vsyncPeriod; mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value, - display->getActiveConfig()); + display->getActiveConfig(), vsyncPeriod); if (mRefreshRateConfigs->refreshRateSwitchingSupported()) { auto configId = mScheduler->getPreferredConfigId(); diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index 9ad9b91a9a..23df1bbd2c 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -101,6 +101,7 @@ message LayerProto { // length of the shadow to draw around the layer, it may be set on the // layer or set by a parent layer. float shadow_radius = 49; + ColorTransformProto color_transform = 50; } message PositionProto { @@ -181,3 +182,8 @@ message InputWindowInfoProto { bool replace_touchable_region_with_crop = 14; RectProto touchable_region_crop = 15; } + +message ColorTransformProto { + // This will be a 4x4 matrix of float values + repeated float val = 1; +}
\ No newline at end of file diff --git a/services/surfaceflinger/tests/DisplayConfigs_test.cpp b/services/surfaceflinger/tests/DisplayConfigs_test.cpp index 420fb290d7..d51b9a146f 100644 --- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp +++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp @@ -31,42 +31,40 @@ protected: void SetUp() override { mDisplayToken = SurfaceComposerClient::getInternalDisplayToken(); } sp<IBinder> mDisplayToken; - int32_t defaultConfigId; - float minRefreshRate; - float maxRefreshRate; }; -TEST_F(RefreshRateRangeTest, simpleSetAndGet) { - status_t res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, 1, 45, 75); - EXPECT_EQ(res, NO_ERROR); +TEST_F(RefreshRateRangeTest, setAllConfigs) { + int32_t initialDefaultConfig; + float initialMin; + float initialMax; + status_t res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, + &initialDefaultConfig, + &initialMin, &initialMax); + ASSERT_EQ(res, NO_ERROR); - res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, &defaultConfigId, - &minRefreshRate, &maxRefreshRate); - EXPECT_EQ(res, NO_ERROR); - EXPECT_EQ(defaultConfigId, 1); - EXPECT_EQ(minRefreshRate, 45); - EXPECT_EQ(maxRefreshRate, 75); -} + Vector<DisplayInfo> configs; + res = SurfaceComposerClient::getDisplayConfigs(mDisplayToken, &configs); + ASSERT_EQ(res, NO_ERROR); -TEST_F(RefreshRateRangeTest, complexSetAndGet) { - status_t res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, 1, 45, 75); - EXPECT_EQ(res, NO_ERROR); + for (size_t i = 0; i < configs.size(); i++) { + res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, i, configs[i].fps, + configs[i].fps); + ASSERT_EQ(res, NO_ERROR); - res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, &defaultConfigId, - &minRefreshRate, &maxRefreshRate); - EXPECT_EQ(res, NO_ERROR); - EXPECT_EQ(defaultConfigId, 1); - EXPECT_EQ(minRefreshRate, 45); - EXPECT_EQ(maxRefreshRate, 75); + int defaultConfig; + float minFps; + float maxFps; + res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, &defaultConfig, + &minFps, &maxFps); + ASSERT_EQ(res, NO_ERROR); + ASSERT_EQ(defaultConfig, i); + ASSERT_EQ(minFps, configs[i].fps); + ASSERT_EQ(maxFps, configs[i].fps); + } - // Second call overrides the first one. - res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, 10, 145, 875); - EXPECT_EQ(res, NO_ERROR); - res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, &defaultConfigId, - &minRefreshRate, &maxRefreshRate); - EXPECT_EQ(res, NO_ERROR); - EXPECT_EQ(defaultConfigId, 10); - EXPECT_EQ(minRefreshRate, 145); - EXPECT_EQ(maxRefreshRate, 875); + res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, initialDefaultConfig, + initialMin, initialMax); + ASSERT_EQ(res, NO_ERROR); } + } // namespace android diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter index 63ae3ae1b2..7786638b20 100644 --- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter +++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter @@ -1,5 +1,5 @@ { "presubmit": { - "filter": "*:-RefreshRateRangeTest.*:LayerCallbackTest.MergeBufferNoColor:LayerCallbackTest.MergeNoBufferColor:LayerCallbackTest.MergeOneBufferOneColor:LayerCallbackTest.Merge_SameCallback:LayerCallbackTest.Merge_DifferentClients:LayerCallbackTest.MultipleTransactions_Merge:LayerCallbackTest.MultipleTransactions_Merge_DifferentClients:LayerCallbackTest.MultipleTransactions_Merge_DifferentClients_NoStateChange:LayerCallbackTest.MultipleTransactions_Merge_DifferentClients_SameStateChange:LayerTypeAndRenderTypeTransactionTests/LayerTypeAndRenderTypeTransactionTest.SetCornerRadius/2:LayerTypeAndRenderTypeTransactionTests/LayerTypeAndRenderTypeTransactionTest.SetCornerRadius/3:LayerTypeAndRenderTypeTransactionTests/LayerTypeAndRenderTypeTransactionTest.SetCornerRadiusChildCrop/2:LayerTypeAndRenderTypeTransactionTests/LayerTypeAndRenderTypeTransactionTest.SetCornerRadiusChildCrop/3" + "filter": "*:-RefreshRateRangeTest.*:LayerTypeAndRenderTypeTransactionTests/LayerTypeAndRenderTypeTransactionTest.SetCornerRadius/2:LayerTypeAndRenderTypeTransactionTests/LayerTypeAndRenderTypeTransactionTest.SetCornerRadius/3:LayerTypeAndRenderTypeTransactionTests/LayerTypeAndRenderTypeTransactionTest.SetCornerRadiusChildCrop/2:LayerTypeAndRenderTypeTransactionTests/LayerTypeAndRenderTypeTransactionTest.SetCornerRadiusChildCrop/3" } } diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp index 80bca021ab..61d4f47c21 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -85,7 +85,8 @@ protected: void expectHotplugEventReceivedByConnection(PhysicalDisplayId expectedDisplayId, bool expectedConnected); void expectConfigChangedEventReceivedByConnection(PhysicalDisplayId expectedDisplayId, - int32_t expectedConfigId); + int32_t expectedConfigId, + nsecs_t expectedVsyncPeriod); AsyncCallRecorder<void (*)(bool)> mVSyncSetEnabledCallRecorder; AsyncCallRecorder<void (*)(VSyncSource::Callback*)> mVSyncSetCallbackCallRecorder; @@ -209,13 +210,15 @@ void EventThreadTest::expectHotplugEventReceivedByConnection(PhysicalDisplayId e } void EventThreadTest::expectConfigChangedEventReceivedByConnection( - PhysicalDisplayId expectedDisplayId, int32_t expectedConfigId) { + PhysicalDisplayId expectedDisplayId, int32_t expectedConfigId, + nsecs_t expectedVsyncPeriod) { auto args = mConnectionEventCallRecorder.waitForCall(); ASSERT_TRUE(args.has_value()); const auto& event = std::get<0>(args.value()); EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED, event.header.type); EXPECT_EQ(expectedDisplayId, event.header.displayId); EXPECT_EQ(expectedConfigId, event.config.configId); + EXPECT_EQ(expectedVsyncPeriod, event.config.vsyncPeriod); } namespace { @@ -450,18 +453,18 @@ TEST_F(EventThreadTest, postHotplugExternalConnect) { } TEST_F(EventThreadTest, postConfigChangedPrimary) { - mThread->onConfigChanged(INTERNAL_DISPLAY_ID, HwcConfigIndexType(7)); - expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 7); + mThread->onConfigChanged(INTERNAL_DISPLAY_ID, HwcConfigIndexType(7), 16666666); + expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 7, 16666666); } TEST_F(EventThreadTest, postConfigChangedExternal) { - mThread->onConfigChanged(EXTERNAL_DISPLAY_ID, HwcConfigIndexType(5)); - expectConfigChangedEventReceivedByConnection(EXTERNAL_DISPLAY_ID, 5); + mThread->onConfigChanged(EXTERNAL_DISPLAY_ID, HwcConfigIndexType(5), 16666666); + expectConfigChangedEventReceivedByConnection(EXTERNAL_DISPLAY_ID, 5, 16666666); } TEST_F(EventThreadTest, postConfigChangedPrimary64bit) { - mThread->onConfigChanged(DISPLAY_ID_64BIT, HwcConfigIndexType(7)); - expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7); + mThread->onConfigChanged(DISPLAY_ID_64BIT, HwcConfigIndexType(7), 16666666); + expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7, 16666666); } TEST_F(EventThreadTest, suppressConfigChanged) { @@ -470,8 +473,8 @@ TEST_F(EventThreadTest, suppressConfigChanged) { createConnection(suppressConnectionEventRecorder, ISurfaceComposer::eConfigChangedSuppress); - mThread->onConfigChanged(INTERNAL_DISPLAY_ID, HwcConfigIndexType(9)); - expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9); + mThread->onConfigChanged(INTERNAL_DISPLAY_ID, HwcConfigIndexType(9), 16666666); + expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9, 16666666); auto args = suppressConnectionEventRecorder.waitForCall(); ASSERT_FALSE(args.has_value()); diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h index f7c380490b..9bda095a48 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h +++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h @@ -33,13 +33,14 @@ public: MOCK_METHOD0(onScreenReleased, void()); MOCK_METHOD0(onScreenAcquired, void()); MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool)); - MOCK_METHOD2(onConfigChanged, void(PhysicalDisplayId, HwcConfigIndexType)); + MOCK_METHOD3(onConfigChanged, void(PhysicalDisplayId, HwcConfigIndexType, nsecs_t)); MOCK_CONST_METHOD1(dump, void(std::string&)); MOCK_METHOD1(setPhaseOffset, void(nsecs_t phaseOffset)); MOCK_METHOD1(registerDisplayEventConnection, status_t(const sp<android::EventThreadConnection> &)); MOCK_METHOD2(setVsyncRate, void(uint32_t, const sp<android::EventThreadConnection> &)); MOCK_METHOD1(requestNextVsync, void(const sp<android::EventThreadConnection> &)); + MOCK_METHOD0(requestLatestConfig, void()); MOCK_METHOD1(pauseVsyncCallback, void(bool)); }; |