diff options
author | 2021-05-25 13:25:06 +0000 | |
---|---|---|
committer | 2021-05-25 13:25:06 +0000 | |
commit | aa11e58c63a745b42d3d565ff4e9e35ecd32099f (patch) | |
tree | 3e9ad02b3f750ec296c049c5bc8353be2aae924c | |
parent | 45916263e09d63771c7cc9748f134b45de563c05 (diff) | |
parent | c238fa8420d69ff1f8b1353116b5b1c9f2220c9a (diff) |
Add SF side tunnel mode listener am: 8f04b30c59 am: 2833f90b06 am: c238fa8420
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/14340746
Change-Id: Ib98149545d6feb82c5e720710d4adbe233a6e46f
-rw-r--r-- | libs/gui/ISurfaceComposer.cpp | 50 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 10 | ||||
-rw-r--r-- | libs/gui/aidl/android/gui/ITunnelModeEnabledListener.aidl | 29 | ||||
-rw-r--r-- | libs/gui/include/gui/ISurfaceComposer.h | 18 | ||||
-rw-r--r-- | libs/gui/include/gui/SurfaceComposerClient.h | 5 | ||||
-rw-r--r-- | libs/gui/tests/Surface_test.cpp | 10 | ||||
-rw-r--r-- | services/surfaceflinger/Android.bp | 1 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 28 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 7 | ||||
-rw-r--r-- | services/surfaceflinger/TunnelModeEnabledReporter.cpp | 85 | ||||
-rw-r--r-- | services/surfaceflinger/TunnelModeEnabledReporter.h | 66 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/Android.bp | 1 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h | 1 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp | 194 |
14 files changed, 505 insertions, 0 deletions
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 0436758e72..f6a48d7abd 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -829,6 +829,36 @@ public: return error; } + virtual status_t addTunnelModeEnabledListener( + const sp<gui::ITunnelModeEnabledListener>& listener) { + Parcel data, reply; + SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor()); + SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener)); + + const status_t error = + remote()->transact(BnSurfaceComposer::ADD_TUNNEL_MODE_ENABLED_LISTENER, data, + &reply); + if (error != NO_ERROR) { + ALOGE("addTunnelModeEnabledListener: Failed to transact"); + } + return error; + } + + virtual status_t removeTunnelModeEnabledListener( + const sp<gui::ITunnelModeEnabledListener>& listener) { + Parcel data, reply; + SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor()); + SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener)); + + const status_t error = + remote()->transact(BnSurfaceComposer::REMOVE_TUNNEL_MODE_ENABLED_LISTENER, data, + &reply); + if (error != NO_ERROR) { + ALOGE("removeTunnelModeEnabledListener: Failed to transact"); + } + return error; + } + status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, ui::DisplayModeId defaultMode, bool allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax, @@ -1748,6 +1778,26 @@ status_t BnSurfaceComposer::onTransact( } return removeFpsListener(listener); } + case ADD_TUNNEL_MODE_ENABLED_LISTENER: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<gui::ITunnelModeEnabledListener> listener; + status_t result = data.readNullableStrongBinder(&listener); + if (result != NO_ERROR) { + ALOGE("addTunnelModeEnabledListener: Failed to read listener"); + return result; + } + return addTunnelModeEnabledListener(listener); + } + case REMOVE_TUNNEL_MODE_ENABLED_LISTENER: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<gui::ITunnelModeEnabledListener> listener; + status_t result = data.readNullableStrongBinder(&listener); + if (result != NO_ERROR) { + ALOGE("removeTunnelModeEnabledListener: Failed to read listener"); + return result; + } + return removeTunnelModeEnabledListener(listener); + } case SET_DESIRED_DISPLAY_MODE_SPECS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IBinder> displayToken = data.readStrongBinder(); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 1bb63930a7..521f2b0046 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -2077,6 +2077,16 @@ status_t SurfaceComposerClient::removeFpsListener(const sp<gui::IFpsListener>& l return ComposerService::getComposerService()->removeFpsListener(listener); } +status_t SurfaceComposerClient::addTunnelModeEnabledListener( + const sp<gui::ITunnelModeEnabledListener>& listener) { + return ComposerService::getComposerService()->addTunnelModeEnabledListener(listener); +} + +status_t SurfaceComposerClient::removeTunnelModeEnabledListener( + const sp<gui::ITunnelModeEnabledListener>& listener) { + return ComposerService::getComposerService()->removeTunnelModeEnabledListener(listener); +} + bool SurfaceComposerClient::getDisplayBrightnessSupport(const sp<IBinder>& displayToken) { bool support = false; ComposerService::getComposerService()->getDisplayBrightnessSupport(displayToken, &support); diff --git a/libs/gui/aidl/android/gui/ITunnelModeEnabledListener.aidl b/libs/gui/aidl/android/gui/ITunnelModeEnabledListener.aidl new file mode 100644 index 0000000000..2a89ccacec --- /dev/null +++ b/libs/gui/aidl/android/gui/ITunnelModeEnabledListener.aidl @@ -0,0 +1,29 @@ +/* + * Copyright 2021 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. + */ + +package android.gui; + +/** @hide */ +oneway interface ITunnelModeEnabledListener { + + /** + * Called when tunnel mode status has changed. Tunnel mode is: + * - enabled when there is a sideband stream attached to one of the layers in + * surface flinger + * - disabled when there is no layer with a sideband stream + */ + void onTunnelModeEnabledChanged(boolean enabled); +} diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index c420e4a8d4..6b1e6c1592 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -21,6 +21,7 @@ #include <android/gui/IHdrLayerInfoListener.h> #include <android/gui/IScreenCaptureListener.h> #include <android/gui/ITransactionTraceListener.h> +#include <android/gui/ITunnelModeEnabledListener.h> #include <binder/IBinder.h> #include <binder/IInterface.h> #include <gui/FrameTimelineInfo.h> @@ -375,6 +376,21 @@ public: */ virtual status_t removeFpsListener(const sp<gui::IFpsListener>& listener) = 0; + /* Registers a listener to receive tunnel mode enabled updates from SurfaceFlinger. + * + * Requires ACCESS_SURFACE_FLINGER permission. + */ + virtual status_t addTunnelModeEnabledListener( + const sp<gui::ITunnelModeEnabledListener>& listener) = 0; + + /* + * Removes a listener that was receiving tunnel mode enabled updates from SurfaceFlinger. + * + * Requires ACCESS_SURFACE_FLINGER permission. + */ + virtual status_t removeTunnelModeEnabledListener( + const sp<gui::ITunnelModeEnabledListener>& listener) = 0; + /* Sets the refresh rate boundaries for the display. * * The primary refresh rate range represents display manager's general guidance on the display @@ -605,6 +621,8 @@ public: ADD_HDR_LAYER_INFO_LISTENER, REMOVE_HDR_LAYER_INFO_LISTENER, ON_PULL_ATOM, + ADD_TUNNEL_MODE_ENABLED_LISTENER, + REMOVE_TUNNEL_MODE_ENABLED_LISTENER, // Always append new enum to the end. }; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 86f1b63e24..9dadea8d44 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -50,6 +50,7 @@ class HdrCapabilities; class ISurfaceComposerClient; class IGraphicBufferProducer; class IRegionSamplingListener; +class ITunnelModeEnabledListener; class Region; struct SurfaceControlStats { @@ -610,6 +611,10 @@ public: static status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener); static status_t addFpsListener(int32_t taskId, const sp<gui::IFpsListener>& listener); static status_t removeFpsListener(const sp<gui::IFpsListener>& listener); + static status_t addTunnelModeEnabledListener( + const sp<gui::ITunnelModeEnabledListener>& listener); + static status_t removeTunnelModeEnabledListener( + const sp<gui::ITunnelModeEnabledListener>& listener); private: virtual void onFirstRef(); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 7002adf1ba..42c2c1098d 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -843,6 +843,16 @@ public: return NO_ERROR; } status_t removeFpsListener(const sp<gui::IFpsListener>& /*listener*/) { return NO_ERROR; } + + status_t addTunnelModeEnabledListener(const sp<gui::ITunnelModeEnabledListener>& /*listener*/) { + return NO_ERROR; + } + + status_t removeTunnelModeEnabledListener( + const sp<gui::ITunnelModeEnabledListener>& /*listener*/) { + return NO_ERROR; + } + status_t setDesiredDisplayModeSpecs(const sp<IBinder>& /*displayToken*/, ui::DisplayModeId /*defaultMode*/, bool /*allowGroupSwitching*/, diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index f20bfe1b41..e669e4532b 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -188,6 +188,7 @@ filegroup { "SurfaceInterceptor.cpp", "SurfaceTracing.cpp", "TransactionCallbackInvoker.cpp", + "TunnelModeEnabledReporter.cpp", ], } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 488e6f1390..2227dab6cb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -130,6 +130,7 @@ #include "SurfaceFlingerProperties.h" #include "SurfaceInterceptor.h" #include "TimeStats/TimeStats.h" +#include "TunnelModeEnabledReporter.h" #include "android-base/parseint.h" #include "android-base/stringprintf.h" #include "android-base/strings.h" @@ -1519,6 +1520,26 @@ status_t SurfaceFlinger::removeFpsListener(const sp<gui::IFpsListener>& listener return NO_ERROR; } +status_t SurfaceFlinger::addTunnelModeEnabledListener( + const sp<gui::ITunnelModeEnabledListener>& listener) { + if (!listener) { + return BAD_VALUE; + } + + mTunnelModeEnabledReporter->addListener(listener); + return NO_ERROR; +} + +status_t SurfaceFlinger::removeTunnelModeEnabledListener( + const sp<gui::ITunnelModeEnabledListener>& listener) { + if (!listener) { + return BAD_VALUE; + } + + mTunnelModeEnabledReporter->removeListener(listener); + return NO_ERROR; +} + status_t SurfaceFlinger::getDisplayBrightnessSupport(const sp<IBinder>& displayToken, bool* outSupport) const { if (!displayToken || !outSupport) { @@ -2225,6 +2246,10 @@ void SurfaceFlinger::postComposition() { if (mFpsReporter) { mFpsReporter->dispatchLayerFps(); } + + if (mTunnelModeEnabledReporter) { + mTunnelModeEnabledReporter->updateTunnelModeStatus(); + } hdrInfoListeners.reserve(mHdrLayerInfoListeners.size()); for (const auto& [displayId, reporter] : mHdrLayerInfoListeners) { if (reporter && reporter->hasListeners()) { @@ -3111,6 +3136,7 @@ void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) { mRegionSamplingThread = new RegionSamplingThread(*this, RegionSamplingThread::EnvironmentTimingTunables()); mFpsReporter = new FpsReporter(*mFrameTimeline, *this); + mTunnelModeEnabledReporter = new TunnelModeEnabledReporter(*this); // Dispatch a mode change request for the primary display on scheduler // initialization, so that the EventThreads always contain a reference to a // prior configuration. @@ -5117,6 +5143,8 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES: case SET_DISPLAY_CONTENT_SAMPLING_ENABLED: case GET_DISPLAYED_CONTENT_SAMPLE: + case ADD_TUNNEL_MODE_ENABLED_LISTENER: + case REMOVE_TUNNEL_MODE_ENABLED_LISTENER: case NOTIFY_POWER_BOOST: case SET_GLOBAL_SHADOW_SETTINGS: case ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN: { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index ee354c6ec2..49bedb153c 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -90,6 +90,7 @@ namespace android { class Client; class EventThread; class FpsReporter; +class TunnelModeEnabledReporter; class HdrLayerInfoReporter; class HWComposer; struct SetInputWindowsListener; @@ -350,6 +351,7 @@ private: friend class BufferStateLayer; friend class Client; friend class FpsReporter; + friend class TunnelModeEnabledReporter; friend class Layer; friend class MonitoredProducer; friend class RefreshRateOverlay; @@ -662,6 +664,10 @@ private: status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) override; status_t addFpsListener(int32_t taskId, const sp<gui::IFpsListener>& listener) override; status_t removeFpsListener(const sp<gui::IFpsListener>& listener) override; + status_t addTunnelModeEnabledListener( + const sp<gui::ITunnelModeEnabledListener>& listener) override; + status_t removeTunnelModeEnabledListener( + const sp<gui::ITunnelModeEnabledListener>& listener) override; status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, ui::DisplayModeId displayModeId, bool allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax, @@ -1374,6 +1380,7 @@ private: bool mLumaSampling = true; sp<RegionSamplingThread> mRegionSamplingThread; sp<FpsReporter> mFpsReporter; + sp<TunnelModeEnabledReporter> mTunnelModeEnabledReporter; ui::DisplayPrimaries mInternalDisplayPrimaries; const float mInternalDisplayDensity; diff --git a/services/surfaceflinger/TunnelModeEnabledReporter.cpp b/services/surfaceflinger/TunnelModeEnabledReporter.cpp new file mode 100644 index 0000000000..1b3ddf7a00 --- /dev/null +++ b/services/surfaceflinger/TunnelModeEnabledReporter.cpp @@ -0,0 +1,85 @@ +/* + * Copyright 2021 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. + */ + +#undef LOG_TAG +#define LOG_TAG "TunnelModeEnabledReporter" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include <algorithm> + +#include "Layer.h" +#include "SurfaceFlinger.h" +#include "TunnelModeEnabledReporter.h" + +namespace android { + +TunnelModeEnabledReporter::TunnelModeEnabledReporter(SurfaceFlinger& flinger) : mFlinger(flinger) {} + +void TunnelModeEnabledReporter::updateTunnelModeStatus() { + bool tunnelModeEnabled = false; + mFlinger.mCurrentState.traverse([&](Layer* layer) { + auto& currentState = layer->getCurrentState(); + if (currentState.sidebandStream != nullptr) { + tunnelModeEnabled = true; + return; + } + }); + dispatchTunnelModeEnabled(tunnelModeEnabled); +} + +void TunnelModeEnabledReporter::dispatchTunnelModeEnabled(bool tunnelModeEnabled) { + std::vector<sp<gui::ITunnelModeEnabledListener>> localListeners; + { + std::scoped_lock lock(mMutex); + if (mTunnelModeEnabled == tunnelModeEnabled) { + return; + } + mTunnelModeEnabled = tunnelModeEnabled; + + std::transform(mListeners.begin(), mListeners.end(), std::back_inserter(localListeners), + [](const std::pair<wp<IBinder>, sp<gui::ITunnelModeEnabledListener>>& + entry) { return entry.second; }); + } + + for (sp<gui::ITunnelModeEnabledListener>& listener : localListeners) { + listener->onTunnelModeEnabledChanged(tunnelModeEnabled); + } +} + +void TunnelModeEnabledReporter::binderDied(const wp<IBinder>& who) { + std::scoped_lock lock(mMutex); + mListeners.erase(who); +} + +void TunnelModeEnabledReporter::addListener(const sp<gui::ITunnelModeEnabledListener>& listener) { + sp<IBinder> asBinder = IInterface::asBinder(listener); + asBinder->linkToDeath(this); + bool tunnelModeEnabled = false; + { + std::scoped_lock lock(mMutex); + mListeners.emplace(wp<IBinder>(asBinder), listener); + tunnelModeEnabled = mTunnelModeEnabled; + } + listener->onTunnelModeEnabledChanged(tunnelModeEnabled); +} + +void TunnelModeEnabledReporter::removeListener( + const sp<gui::ITunnelModeEnabledListener>& listener) { + std::lock_guard lock(mMutex); + mListeners.erase(wp<IBinder>(IInterface::asBinder(listener))); +} + +} // namespace android diff --git a/services/surfaceflinger/TunnelModeEnabledReporter.h b/services/surfaceflinger/TunnelModeEnabledReporter.h new file mode 100644 index 0000000000..d55507a8e9 --- /dev/null +++ b/services/surfaceflinger/TunnelModeEnabledReporter.h @@ -0,0 +1,66 @@ +/* + * Copyright 2021 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-base/thread_annotations.h> +#include <android/gui/ITunnelModeEnabledListener.h> +#include <binder/IBinder.h> + +#include <unordered_map> + +namespace android { + +class Layer; +class SurfaceFlinger; + +class TunnelModeEnabledReporter : public IBinder::DeathRecipient { +public: + TunnelModeEnabledReporter(SurfaceFlinger& flinger); + + // Checks if there is a tunnel mode enabled state change and if so, dispatches the updated + // tunnel mode enabled/disabled state to the registered listeners + // This method performs layer stack traversals, so mStateLock must be held when calling this + // method. + void updateTunnelModeStatus(); + + // Dispatches tunnelModeEnabled to all registered listeners + void dispatchTunnelModeEnabled(bool tunnelModeEnabled); + + // Override for IBinder::DeathRecipient + void binderDied(const wp<IBinder>&) override; + + // Registers a TunnelModeEnabled listener + void addListener(const sp<gui::ITunnelModeEnabledListener>& listener); + + // Deregisters a TunnelModeEnabled listener + void removeListener(const sp<gui::ITunnelModeEnabledListener>& listener); + +private: + mutable std::mutex mMutex; + struct WpHash { + size_t operator()(const wp<IBinder>& p) const { + return std::hash<IBinder*>()(p.unsafe_get()); + } + }; + + SurfaceFlinger& mFlinger; + std::unordered_map<wp<IBinder>, sp<gui::ITunnelModeEnabledListener>, WpHash> mListeners + GUARDED_BY(mMutex); + bool mTunnelModeEnabled GUARDED_BY(mMutex) = false; +}; + +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 83575bd72e..7512fd3dfe 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -86,6 +86,7 @@ cc_test { "TransactionApplicationTest.cpp", "TransactionFrameTracerTest.cpp", "TransactionSurfaceFrameTest.cpp", + "TunnelModeEnabledReporterTest.cpp", "StrongTypingTest.cpp", "VSyncDispatchTimerQueueTest.cpp", "VSyncDispatchRealtimeTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 82eb3bfc18..d78f36cd27 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -272,6 +272,7 @@ public: static void setLayerSidebandStream(const sp<Layer>& layer, const sp<NativeHandle>& sidebandStream) { layer->mDrawingState.sidebandStream = sidebandStream; + layer->mCurrentState.sidebandStream = sidebandStream; layer->mSidebandStream = sidebandStream; layer->editCompositionState()->sidebandStream = sidebandStream; } diff --git a/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp new file mode 100644 index 0000000000..d7d7ea77d6 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp @@ -0,0 +1,194 @@ +/* + * Copyright 2021 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. + */ + +#undef LOG_TAG +#define LOG_TAG "TunnelModeEnabledReporterTest" + +#include <android/gui/BnTunnelModeEnabledListener.h> +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <gui/LayerMetadata.h> + +#include "BufferStateLayer.h" +#include "TestableSurfaceFlinger.h" +#include "TunnelModeEnabledReporter.h" +#include "mock/DisplayHardware/MockComposer.h" +#include "mock/MockEventThread.h" + +namespace android { + +using testing::_; +using testing::Mock; +using testing::Return; + +using android::Hwc2::IComposer; +using android::Hwc2::IComposerClient; + +using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector; + +constexpr int DEFAULT_SIDEBAND_STREAM = 51; + +struct TestableTunnelModeEnabledListener : public gui::BnTunnelModeEnabledListener { + TestableTunnelModeEnabledListener() {} + + bool mTunnelModeEnabled = false; + + binder::Status onTunnelModeEnabledChanged(bool tunnelModeEnabled) override { + mTunnelModeEnabled = tunnelModeEnabled; + return binder::Status::ok(); + } +}; + +class TunnelModeEnabledReporterTest : public testing::Test { +public: + TunnelModeEnabledReporterTest(); + ~TunnelModeEnabledReporterTest() override; + +protected: + static constexpr uint32_t WIDTH = 100; + static constexpr uint32_t HEIGHT = 100; + static constexpr uint32_t LAYER_FLAGS = 0; + + void setupScheduler(); + void setupComposer(uint32_t virtualDisplayCount); + sp<BufferStateLayer> createBufferStateLayer(LayerMetadata metadata); + + TestableSurfaceFlinger mFlinger; + Hwc2::mock::Composer* mComposer = nullptr; + sp<TestableTunnelModeEnabledListener> mTunnelModeEnabledListener = + new TestableTunnelModeEnabledListener(); + sp<TunnelModeEnabledReporter> mTunnelModeEnabledReporter = + new TunnelModeEnabledReporter(*(mFlinger.flinger())); +}; + +TunnelModeEnabledReporterTest::TunnelModeEnabledReporterTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); + setupScheduler(); + mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>()); + mTunnelModeEnabledReporter->dispatchTunnelModeEnabled(false); +} + +TunnelModeEnabledReporterTest::~TunnelModeEnabledReporterTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); + mTunnelModeEnabledReporter->dispatchTunnelModeEnabled(false); + mTunnelModeEnabledReporter->removeListener(mTunnelModeEnabledListener); +} + +sp<BufferStateLayer> TunnelModeEnabledReporterTest::createBufferStateLayer( + LayerMetadata metadata = {}) { + sp<Client> client; + LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", WIDTH, HEIGHT, + LAYER_FLAGS, metadata); + return new BufferStateLayer(args); +} + +void TunnelModeEnabledReporterTest::setupScheduler() { + auto eventThread = std::make_unique<mock::EventThread>(); + auto sfEventThread = std::make_unique<mock::EventThread>(); + + EXPECT_CALL(*eventThread, registerDisplayEventConnection(_)); + EXPECT_CALL(*eventThread, createEventConnection(_, _)) + .WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0, + ResyncCallback()))); + + EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_)); + EXPECT_CALL(*sfEventThread, createEventConnection(_, _)) + .WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0, + ResyncCallback()))); + + auto vsyncController = std::make_unique<mock::VsyncController>(); + auto vsyncTracker = std::make_unique<mock::VSyncTracker>(); + + EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); + EXPECT_CALL(*vsyncTracker, currentPeriod()) + .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)); + EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); + mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker), + std::move(eventThread), std::move(sfEventThread)); +} + +namespace { + +TEST_F(TunnelModeEnabledReporterTest, callsAddedListeners) { + mTunnelModeEnabledReporter->addListener(mTunnelModeEnabledListener); + + bool expectedTunnelModeEnabled = false; + mTunnelModeEnabledReporter->dispatchTunnelModeEnabled(expectedTunnelModeEnabled); + EXPECT_EQ(expectedTunnelModeEnabled, mTunnelModeEnabledListener->mTunnelModeEnabled); + + expectedTunnelModeEnabled = true; + mTunnelModeEnabledReporter->dispatchTunnelModeEnabled(expectedTunnelModeEnabled); + EXPECT_EQ(expectedTunnelModeEnabled, mTunnelModeEnabledListener->mTunnelModeEnabled); + + mTunnelModeEnabledReporter->removeListener(mTunnelModeEnabledListener); + + mTunnelModeEnabledReporter->dispatchTunnelModeEnabled(false); + EXPECT_EQ(expectedTunnelModeEnabled, mTunnelModeEnabledListener->mTunnelModeEnabled); +} + +TEST_F(TunnelModeEnabledReporterTest, callsNewListenerImmediately) { + bool expectedTunnelModeEnabled = false; + mTunnelModeEnabledReporter->dispatchTunnelModeEnabled(expectedTunnelModeEnabled); + + mTunnelModeEnabledReporter->addListener(mTunnelModeEnabledListener); + EXPECT_EQ(expectedTunnelModeEnabled, mTunnelModeEnabledListener->mTunnelModeEnabled); +} + +TEST_F(TunnelModeEnabledReporterTest, callsNewListenerWithFreshInformation) { + sp<Layer> layer = createBufferStateLayer(); + sp<NativeHandle> stream = + NativeHandle::create(reinterpret_cast<native_handle_t*>(DEFAULT_SIDEBAND_STREAM), + false); + mFlinger.setLayerSidebandStream(layer, stream); + mFlinger.mutableCurrentState().layersSortedByZ.add(layer); + mTunnelModeEnabledReporter->updateTunnelModeStatus(); + mTunnelModeEnabledReporter->addListener(mTunnelModeEnabledListener); + EXPECT_EQ(true, mTunnelModeEnabledListener->mTunnelModeEnabled); + mTunnelModeEnabledReporter->removeListener(mTunnelModeEnabledListener); + + mFlinger.mutableCurrentState().layersSortedByZ.remove(layer); + mTunnelModeEnabledReporter->updateTunnelModeStatus(); + mTunnelModeEnabledReporter->addListener(mTunnelModeEnabledListener); + EXPECT_EQ(false, mTunnelModeEnabledListener->mTunnelModeEnabled); +} + +TEST_F(TunnelModeEnabledReporterTest, layerWithSidebandStreamTriggersUpdate) { + mTunnelModeEnabledReporter->addListener(mTunnelModeEnabledListener); + EXPECT_EQ(false, mTunnelModeEnabledListener->mTunnelModeEnabled); + + sp<Layer> simpleLayer = createBufferStateLayer(); + sp<Layer> layerWithSidebandStream = createBufferStateLayer(); + sp<NativeHandle> stream = + NativeHandle::create(reinterpret_cast<native_handle_t*>(DEFAULT_SIDEBAND_STREAM), + false); + mFlinger.setLayerSidebandStream(layerWithSidebandStream, stream); + + mFlinger.mutableCurrentState().layersSortedByZ.add(simpleLayer); + mFlinger.mutableCurrentState().layersSortedByZ.add(layerWithSidebandStream); + mTunnelModeEnabledReporter->updateTunnelModeStatus(); + EXPECT_EQ(true, mTunnelModeEnabledListener->mTunnelModeEnabled); + + mFlinger.mutableCurrentState().layersSortedByZ.remove(layerWithSidebandStream); + mTunnelModeEnabledReporter->updateTunnelModeStatus(); + EXPECT_EQ(false, mTunnelModeEnabledListener->mTunnelModeEnabled); +} + +} // namespace +} // namespace android |