diff options
author | 2023-04-14 18:50:53 +0000 | |
---|---|---|
committer | 2023-05-08 21:38:26 +0000 | |
commit | c78f53cd0e9ce68cc52a851584b6ce5b34baef7d (patch) | |
tree | d2712bcb15c44121d03e6c659ad321b676767f99 | |
parent | b1e4e9fba5b211ffc9abc62cd80570e81ec2a73a (diff) |
Cleaned up transaction sanitize calls
Exposed a way for a client to invoke sanitize with a uid and pid to
ensure we don't remove states when the process that added it was
privileged.
Added a helper function to get the permission ints based on the String
permission values so SF and clients can call the same API.
In SF, call sanitize as soon as setTransactionState is called since
that's the point where the Transaction has been passed over binder so we
can identify the calling uid. This allows us to remove the permission
values passed to applyTransactionState and unifies the places that were
calling sanitize.
Test: CredentialsTest
Bug: 267794530
Change-Id: I30c1800f0fee43df1cee82464139db7b56a7d911
-rw-r--r-- | libs/gui/Android.bp | 1 | ||||
-rw-r--r-- | libs/gui/ISurfaceComposer.cpp | 8 | ||||
-rw-r--r-- | libs/gui/LayerStatePermissions.cpp | 58 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 12 | ||||
-rw-r--r-- | libs/gui/include/gui/ISurfaceComposer.h | 2 | ||||
-rw-r--r-- | libs/gui/include/gui/LayerStatePermissions.h | 29 | ||||
-rw-r--r-- | libs/gui/include/gui/SurfaceComposerClient.h | 2 | ||||
-rw-r--r-- | libs/gui/tests/Surface_test.cpp | 2 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 64 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 27 | ||||
-rw-r--r-- | services/surfaceflinger/TransactionState.h | 4 | ||||
-rw-r--r-- | services/surfaceflinger/tests/Credentials_test.cpp | 53 | ||||
-rw-r--r-- | services/surfaceflinger/tests/WindowInfosListener_test.cpp | 39 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp | 2 | ||||
-rw-r--r-- | services/surfaceflinger/tests/utils/WindowInfosListenerUtils.h | 74 |
15 files changed, 277 insertions, 100 deletions
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 33bb343c9d..80fed98434 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -226,6 +226,7 @@ cc_library_shared { "ITransactionCompletedListener.cpp", "LayerDebugInfo.cpp", "LayerMetadata.cpp", + "LayerStatePermissions.cpp", "LayerState.cpp", "OccupancyTracker.cpp", "StreamSplitter.cpp", diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index cefb9a71d6..d72f65eb7a 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -62,7 +62,7 @@ public: status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state, const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, - const InputWindowCommands& commands, int64_t desiredPresentTime, + InputWindowCommands commands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks, @@ -188,9 +188,9 @@ status_t BnSurfaceComposer::onTransact( SAFE_PARCEL(data.readUint64, &transactionId); return setTransactionState(frameTimelineInfo, state, displays, stateFlags, applyToken, - inputWindowCommands, desiredPresentTime, isAutoTimestamp, - uncacheBuffers, hasListenerCallbacks, listenerCallbacks, - transactionId); + std::move(inputWindowCommands), desiredPresentTime, + isAutoTimestamp, uncacheBuffers, hasListenerCallbacks, + listenerCallbacks, transactionId); } default: { return BBinder::onTransact(code, data, reply, flags); diff --git a/libs/gui/LayerStatePermissions.cpp b/libs/gui/LayerStatePermissions.cpp new file mode 100644 index 0000000000..28697ca953 --- /dev/null +++ b/libs/gui/LayerStatePermissions.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2023 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. + */ + +#include <binder/IPCThreadState.h> +#include <gui/LayerStatePermissions.h> +#include <private/android_filesystem_config.h> +#ifndef __ANDROID_VNDK__ +#include <binder/PermissionCache.h> +#endif // __ANDROID_VNDK__ +#include <gui/LayerState.h> + +namespace android { +std::unordered_map<std::string, int> LayerStatePermissions::mPermissionMap = { + // If caller has ACCESS_SURFACE_FLINGER, they automatically get ROTATE_SURFACE_FLINGER + // permission, as well + {"android.permission.ACCESS_SURFACE_FLINGER", + layer_state_t::Permission::ACCESS_SURFACE_FLINGER | + layer_state_t::Permission::ROTATE_SURFACE_FLINGER}, + {"android.permission.ROTATE_SURFACE_FLINGER", + layer_state_t::Permission::ROTATE_SURFACE_FLINGER}, + {"android.permission.INTERNAL_SYSTEM_WINDOW", + layer_state_t::Permission::INTERNAL_SYSTEM_WINDOW}, +}; + +static bool callingThreadHasPermission(const std::string& permission __attribute__((unused)), + int pid __attribute__((unused)), + int uid __attribute__((unused))) { +#ifndef __ANDROID_VNDK__ + return uid == AID_GRAPHICS || uid == AID_SYSTEM || + PermissionCache::checkPermission(String16(permission.c_str()), pid, uid); +#endif // __ANDROID_VNDK__ + return false; +} + +uint32_t LayerStatePermissions::getTransactionPermissions(int pid, int uid) { + uint32_t permissions = 0; + for (auto [permissionName, permissionVal] : mPermissionMap) { + if (callingThreadHasPermission(permissionName, pid, uid)) { + permissions |= permissionVal; + } + } + + return permissions; +} +} // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index eb5cc4f8ab..1b13ec1c06 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -54,6 +54,7 @@ #include <ui/DynamicDisplayInfo.h> #include <android-base/thread_annotations.h> +#include <gui/LayerStatePermissions.h> #include <private/gui/ComposerService.h> #include <private/gui/ComposerServiceAIDL.h> @@ -716,11 +717,16 @@ SurfaceComposerClient::Transaction::Transaction(const Transaction& other) mListenerCallbacks = other.mListenerCallbacks; } -void SurfaceComposerClient::Transaction::sanitize() { +void SurfaceComposerClient::Transaction::sanitize(int pid, int uid) { + uint32_t permissions = LayerStatePermissions::getTransactionPermissions(pid, uid); for (auto & [handle, composerState] : mComposerStates) { - composerState.state.sanitize(0 /* permissionMask */); + composerState.state.sanitize(permissions); + } + if (!mInputWindowCommands.empty() && + (permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER) == 0) { + ALOGE("Only privileged callers are allowed to send input commands."); + mInputWindowCommands.clear(); } - mInputWindowCommands.clear(); } std::unique_ptr<SurfaceComposerClient::Transaction> diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 1e67225a4e..bd21851c14 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -113,7 +113,7 @@ public: virtual status_t setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state, const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, - const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, + InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffer, bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) = 0; diff --git a/libs/gui/include/gui/LayerStatePermissions.h b/libs/gui/include/gui/LayerStatePermissions.h new file mode 100644 index 0000000000..a90f30c621 --- /dev/null +++ b/libs/gui/include/gui/LayerStatePermissions.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2023 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. + */ + +#include <stdint.h> +#include <string> +#include <unordered_map> + +namespace android { +class LayerStatePermissions { +public: + static uint32_t getTransactionPermissions(int pid, int uid); + +private: + static std::unordered_map<std::string, int> mPermissionMap; +}; +} // namespace android
\ No newline at end of file diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 945b164fdc..8d2cdaf5b8 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -744,7 +744,7 @@ public: * * TODO (b/213644870): Remove all permissioned things from Transaction */ - void sanitize(); + void sanitize(int pid, int uid); static sp<IBinder> getDefaultApplyToken(); static void setDefaultApplyToken(sp<IBinder> applyToken); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index fccc408473..5bc6904563 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -699,7 +699,7 @@ public: Vector<ComposerState>& /*state*/, const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/, const sp<IBinder>& /*applyToken*/, - const InputWindowCommands& /*inputWindowCommands*/, + InputWindowCommands /*inputWindowCommands*/, int64_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const std::vector<client_cache_t>& /*cachedBuffer*/, bool /*hasListenerCallbacks*/, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 2d406788cf..95159d7d2a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -110,6 +110,7 @@ #include <unordered_map> #include <vector> +#include <gui/LayerStatePermissions.h> #include <ui/DisplayIdentification.h> #include "BackgroundExecutor.h" #include "Client.h" @@ -4405,7 +4406,7 @@ bool SurfaceFlinger::applyTransactionsLocked(std::vector<TransactionState>& tran transaction.inputWindowCommands, transaction.desiredPresentTime, transaction.isAutoTimestamp, std::move(transaction.uncacheBufferIds), transaction.postTime, - transaction.permissions, transaction.hasListenerCallbacks, + transaction.hasListenerCallbacks, transaction.listenerCallbacks, transaction.originPid, transaction.originUid, transaction.id); } @@ -4484,24 +4485,27 @@ bool SurfaceFlinger::shouldLatchUnsignaled(const sp<Layer>& layer, const layer_s status_t SurfaceFlinger::setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& states, const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, - const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, - bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers, - bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks, - uint64_t transactionId) { + InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, + const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks, + const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) { ATRACE_CALL(); - uint32_t permissions = - callingThreadHasUnscopedSurfaceFlingerAccess() ? - layer_state_t::Permission::ACCESS_SURFACE_FLINGER : 0; - // Avoid checking for rotation permissions if the caller already has ACCESS_SURFACE_FLINGER - // permissions. - if ((permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER) || - callingThreadHasPermission(sRotateSurfaceFlinger)) { - permissions |= layer_state_t::Permission::ROTATE_SURFACE_FLINGER; + IPCThreadState* ipc = IPCThreadState::self(); + const int originPid = ipc->getCallingPid(); + const int originUid = ipc->getCallingUid(); + uint32_t permissions = LayerStatePermissions::getTransactionPermissions(originPid, originUid); + for (auto composerState : states) { + composerState.state.sanitize(permissions); } - if (callingThreadHasPermission(sInternalSystemWindow)) { - permissions |= layer_state_t::Permission::INTERNAL_SYSTEM_WINDOW; + for (DisplayState display : displays) { + display.sanitize(permissions); + } + + if (!inputWindowCommands.empty() && + (permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER) == 0) { + ALOGE("Only privileged callers are allowed to send input commands."); + inputWindowCommands.clear(); } if (flags & (eEarlyWakeupStart | eEarlyWakeupEnd)) { @@ -4517,10 +4521,6 @@ status_t SurfaceFlinger::setTransactionState( const int64_t postTime = systemTime(); - IPCThreadState* ipc = IPCThreadState::self(); - const int originPid = ipc->getCallingPid(); - const int originUid = ipc->getCallingUid(); - std::vector<uint64_t> uncacheBufferIds; uncacheBufferIds.reserve(uncacheBuffers.size()); for (const auto& uncacheBuffer : uncacheBuffers) { @@ -4567,12 +4567,11 @@ status_t SurfaceFlinger::setTransactionState( displays, flags, applyToken, - inputWindowCommands, + std::move(inputWindowCommands), desiredPresentTime, isAutoTimestamp, std::move(uncacheBufferIds), postTime, - permissions, hasListenerCallbacks, listenerCallbacks, originPid, @@ -4601,14 +4600,12 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector<uint64_t>& uncacheBufferIds, - const int64_t postTime, uint32_t permissions, - bool hasListenerCallbacks, + const int64_t postTime, bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks, int originPid, int originUid, uint64_t transactionId) { uint32_t transactionFlags = 0; if (!mLayerLifecycleManagerEnabled) { for (DisplayState& display : displays) { - display.sanitize(permissions); transactionFlags |= setDisplayStateLocked(display); } } @@ -4625,12 +4622,12 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin if (mLegacyFrontEndEnabled) { clientStateFlags |= setClientStateLocked(frameTimelineInfo, resolvedState, desiredPresentTime, - isAutoTimestamp, postTime, permissions, transactionId); + isAutoTimestamp, postTime, transactionId); } else /*mLayerLifecycleManagerEnabled*/ { clientStateFlags |= updateLayerCallbacksAndStats(frameTimelineInfo, resolvedState, desiredPresentTime, isAutoTimestamp, - postTime, permissions, transactionId); + postTime, transactionId); } if ((flags & eAnimation) && resolvedState.state.surface) { if (const auto layer = LayerHandle::getLayer(resolvedState.state.surface)) { @@ -4647,12 +4644,7 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin } transactionFlags |= clientStateFlags; - - if (permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER) { - transactionFlags |= addInputWindowCommands(inputWindowCommands); - } else if (!inputWindowCommands.empty()) { - ALOGE("Only privileged callers are allowed to send input commands."); - } + transactionFlags |= addInputWindowCommands(inputWindowCommands); for (uint64_t uncacheBufferId : uncacheBufferIds) { mBufferIdsToUncache.push_back(uncacheBufferId); @@ -4689,7 +4681,6 @@ bool SurfaceFlinger::applyAndCommitDisplayTransactionStates( uint32_t transactionFlags = 0; for (auto& transaction : transactions) { for (DisplayState& display : transaction.displays) { - display.sanitize(transaction.permissions); transactionFlags |= setDisplayStateLocked(display); } } @@ -4788,10 +4779,8 @@ bool SurfaceFlinger::callingThreadHasUnscopedSurfaceFlingerAccess(bool usePermis uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTimelineInfo, ResolvedComposerState& composerState, int64_t desiredPresentTime, bool isAutoTimestamp, - int64_t postTime, uint32_t permissions, - uint64_t transactionId) { + int64_t postTime, uint64_t transactionId) { layer_state_t& s = composerState.state; - s.sanitize(permissions); std::vector<ListenerCallbacks> filteredListeners; for (auto& listener : s.listeners) { @@ -5140,10 +5129,8 @@ uint32_t SurfaceFlinger::updateLayerCallbacksAndStats(const FrameTimelineInfo& f ResolvedComposerState& composerState, int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, - uint32_t permissions, uint64_t transactionId) { layer_state_t& s = composerState.state; - s.sanitize(permissions); std::vector<ListenerCallbacks> filteredListeners; for (auto& listener : s.listeners) { @@ -5425,7 +5412,6 @@ void SurfaceFlinger::initializeDisplays() { const nsecs_t now = systemTime(); state.desiredPresentTime = now; state.postTime = now; - state.permissions = layer_state_t::ACCESS_SURFACE_FLINGER; state.originPid = mPid; state.originUid = static_cast<int>(getuid()); const uint64_t transactionId = (static_cast<uint64_t>(mPid) << 32) | mUniqueTransactionId++; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 8cc0184e99..cfaa221a45 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -510,7 +510,7 @@ private: status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state, const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, - const InputWindowCommands& inputWindowCommands, + InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks, @@ -731,14 +731,16 @@ private: /* * Transactions */ - bool applyTransactionState( - const FrameTimelineInfo& info, std::vector<ResolvedComposerState>& state, - Vector<DisplayState>& displays, uint32_t flags, - const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, - bool isAutoTimestamp, const std::vector<uint64_t>& uncacheBufferIds, - const int64_t postTime, uint32_t permissions, bool hasListenerCallbacks, - const std::vector<ListenerCallbacks>& listenerCallbacks, int originPid, int originUid, - uint64_t transactionId) REQUIRES(mStateLock); + bool applyTransactionState(const FrameTimelineInfo& info, + std::vector<ResolvedComposerState>& state, + Vector<DisplayState>& displays, uint32_t flags, + const InputWindowCommands& inputWindowCommands, + const int64_t desiredPresentTime, bool isAutoTimestamp, + const std::vector<uint64_t>& uncacheBufferIds, + const int64_t postTime, bool hasListenerCallbacks, + const std::vector<ListenerCallbacks>& listenerCallbacks, + int originPid, int originUid, uint64_t transactionId) + REQUIRES(mStateLock); // Flush pending transactions that were presented after desiredPresentTime. // For test only bool flushTransactionQueues(VsyncId) REQUIRES(kMainThreadContext); @@ -759,12 +761,11 @@ private: uint32_t setClientStateLocked(const FrameTimelineInfo&, ResolvedComposerState&, int64_t desiredPresentTime, bool isAutoTimestamp, - int64_t postTime, uint32_t permissions, uint64_t transactionId) - REQUIRES(mStateLock); + int64_t postTime, uint64_t transactionId) REQUIRES(mStateLock); uint32_t updateLayerCallbacksAndStats(const FrameTimelineInfo&, ResolvedComposerState&, int64_t desiredPresentTime, bool isAutoTimestamp, - int64_t postTime, uint32_t permissions, - uint64_t transactionId) REQUIRES(mStateLock); + int64_t postTime, uint64_t transactionId) + REQUIRES(mStateLock); uint32_t getTransactionFlags() const; // Sets the masked bits, and schedules a commit if needed. diff --git a/services/surfaceflinger/TransactionState.h b/services/surfaceflinger/TransactionState.h index 35c8b6c647..62a7dfd0f1 100644 --- a/services/surfaceflinger/TransactionState.h +++ b/services/surfaceflinger/TransactionState.h @@ -54,7 +54,7 @@ struct TransactionState { const Vector<DisplayState>& displayStates, uint32_t transactionFlags, const sp<IBinder>& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, - std::vector<uint64_t> uncacheBufferIds, int64_t postTime, uint32_t permissions, + std::vector<uint64_t> uncacheBufferIds, int64_t postTime, bool hasListenerCallbacks, std::vector<ListenerCallbacks> listenerCallbacks, int originPid, int originUid, uint64_t transactionId) : frameTimelineInfo(frameTimelineInfo), @@ -67,7 +67,6 @@ struct TransactionState { isAutoTimestamp(isAutoTimestamp), uncacheBufferIds(std::move(uncacheBufferIds)), postTime(postTime), - permissions(permissions), hasListenerCallbacks(hasListenerCallbacks), listenerCallbacks(listenerCallbacks), originPid(originPid), @@ -126,7 +125,6 @@ struct TransactionState { bool isAutoTimestamp; std::vector<uint64_t> uncacheBufferIds; int64_t postTime; - uint32_t permissions; bool hasListenerCallbacks; std::vector<ListenerCallbacks> listenerCallbacks; int originPid; diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index 4a45eb5586..69e9a169e3 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -31,6 +31,7 @@ #include <utils/String8.h> #include <functional> #include "utils/ScreenshotUtils.h" +#include "utils/WindowInfosListenerUtils.h" namespace android { @@ -378,6 +379,58 @@ TEST_F(CredentialsTest, GetActiveColorModeBasicCorrectness) { ASSERT_NE(static_cast<ColorMode>(BAD_VALUE), colorMode); } +TEST_F(CredentialsTest, TransactionPermissionTest) { + WindowInfosListenerUtils windowInfosListenerUtils; + std::string name = "Test Layer"; + sp<IBinder> token = sp<BBinder>::make(); + WindowInfo windowInfo; + windowInfo.name = name; + windowInfo.token = token; + sp<SurfaceControl> surfaceControl = + mComposerClient->createSurface(String8(name.c_str()), 100, 100, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceBufferState); + const Rect crop(0, 0, 100, 100); + { + UIDFaker f(AID_SYSTEM); + Transaction() + .setLayerStack(surfaceControl, ui::DEFAULT_LAYER_STACK) + .show(surfaceControl) + .setLayer(surfaceControl, INT32_MAX - 1) + .setCrop(surfaceControl, crop) + .setInputWindowInfo(surfaceControl, windowInfo) + .apply(); + } + + // Called from non privileged process + Transaction().setTrustedOverlay(surfaceControl, true); + { + UIDFaker f(AID_SYSTEM); + auto windowIsPresentAndNotTrusted = [&](const std::vector<WindowInfo>& windowInfos) { + auto foundWindowInfo = + WindowInfosListenerUtils::findMatchingWindowInfo(windowInfo, windowInfos); + if (!foundWindowInfo) { + return false; + } + return !foundWindowInfo->inputConfig.test(WindowInfo::InputConfig::TRUSTED_OVERLAY); + }; + windowInfosListenerUtils.waitForWindowInfosPredicate(windowIsPresentAndNotTrusted); + } + + { + UIDFaker f(AID_SYSTEM); + Transaction().setTrustedOverlay(surfaceControl, true); + auto windowIsPresentAndTrusted = [&](const std::vector<WindowInfo>& windowInfos) { + auto foundWindowInfo = + WindowInfosListenerUtils::findMatchingWindowInfo(windowInfo, windowInfos); + if (!foundWindowInfo) { + return false; + } + return foundWindowInfo->inputConfig.test(WindowInfo::InputConfig::TRUSTED_OVERLAY); + }; + windowInfosListenerUtils.waitForWindowInfosPredicate(windowIsPresentAndTrusted); + } +} + } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/tests/WindowInfosListener_test.cpp b/services/surfaceflinger/tests/WindowInfosListener_test.cpp index 3f27360cb7..ad9a674456 100644 --- a/services/surfaceflinger/tests/WindowInfosListener_test.cpp +++ b/services/surfaceflinger/tests/WindowInfosListener_test.cpp @@ -20,11 +20,13 @@ #include <private/android_filesystem_config.h> #include <cstdint> #include <future> +#include "utils/WindowInfosListenerUtils.h" namespace android { using Transaction = SurfaceComposerClient::Transaction; using gui::DisplayInfo; using gui::WindowInfo; +constexpr auto findMatchingWindowInfo = WindowInfosListenerUtils::findMatchingWindowInfo; using WindowInfosPredicate = std::function<bool(const std::vector<WindowInfo>&)>; @@ -37,45 +39,14 @@ protected: void TearDown() override { seteuid(AID_ROOT); } - struct WindowInfosListener : public gui::WindowInfosListener { - public: - WindowInfosListener(WindowInfosPredicate predicate, std::promise<void>& promise) - : mPredicate(std::move(predicate)), mPromise(promise) {} - - void onWindowInfosChanged(const gui::WindowInfosUpdate& update) override { - if (mPredicate(update.windowInfos)) { - mPromise.set_value(); - } - } - - private: - WindowInfosPredicate mPredicate; - std::promise<void>& mPromise; - }; - sp<SurfaceComposerClient> mClient; + WindowInfosListenerUtils mWindowInfosListenerUtils; - bool waitForWindowInfosPredicate(WindowInfosPredicate predicate) { - std::promise<void> promise; - auto listener = sp<WindowInfosListener>::make(std::move(predicate), promise); - mClient->addWindowInfosListener(listener); - auto future = promise.get_future(); - bool satisfied = future.wait_for(std::chrono::seconds{1}) == std::future_status::ready; - mClient->removeWindowInfosListener(listener); - return satisfied; + bool waitForWindowInfosPredicate(const WindowInfosPredicate& predicate) { + return mWindowInfosListenerUtils.waitForWindowInfosPredicate(std::move(predicate)); } }; -const WindowInfo* findMatchingWindowInfo(const WindowInfo& targetWindowInfo, - const std::vector<WindowInfo>& windowInfos) { - for (const WindowInfo& windowInfo : windowInfos) { - if (windowInfo.token == targetWindowInfo.token) { - return &windowInfo; - } - } - return nullptr; -} - TEST_F(WindowInfosListenerTest, WindowInfoAddedAndRemoved) { std::string name = "Test Layer"; sp<IBinder> token = sp<BBinder>::make(); diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index dbb7c6ce63..6a641b3926 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -386,7 +386,7 @@ public: transaction.applyToken, transaction.inputWindowCommands, transaction.desiredPresentTime, - transaction.isAutoTimestamp, {}, systemTime(), 0, + transaction.isAutoTimestamp, {}, systemTime(), mHasListenerCallbacks, mCallbacks, getpid(), static_cast<int>(getuid()), transaction.id); mFlinger.setTransactionStateInternal(transactionState); diff --git a/services/surfaceflinger/tests/utils/WindowInfosListenerUtils.h b/services/surfaceflinger/tests/utils/WindowInfosListenerUtils.h new file mode 100644 index 0000000000..8e28a75ed4 --- /dev/null +++ b/services/surfaceflinger/tests/utils/WindowInfosListenerUtils.h @@ -0,0 +1,74 @@ +/* + * Copyright 2023 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. + */ + +#include <gtest/gtest.h> +#include <gui/SurfaceComposerClient.h> +#include <private/android_filesystem_config.h> +#include <cstdint> +#include <future> + +namespace android { +using Transaction = SurfaceComposerClient::Transaction; +using gui::DisplayInfo; +using gui::WindowInfo; + +using WindowInfosPredicate = std::function<bool(const std::vector<WindowInfo>&)>; + +class WindowInfosListenerUtils { +public: + WindowInfosListenerUtils() { mClient = sp<SurfaceComposerClient>::make(); } + + bool waitForWindowInfosPredicate(const WindowInfosPredicate& predicate) { + std::promise<void> promise; + auto listener = sp<WindowInfosListener>::make(std::move(predicate), promise); + mClient->addWindowInfosListener(listener); + auto future = promise.get_future(); + bool satisfied = future.wait_for(std::chrono::seconds{1}) == std::future_status::ready; + mClient->removeWindowInfosListener(listener); + return satisfied; + } + + static const WindowInfo* findMatchingWindowInfo(const WindowInfo& targetWindowInfo, + const std::vector<WindowInfo>& windowInfos) { + for (const WindowInfo& windowInfo : windowInfos) { + if (windowInfo.token == targetWindowInfo.token) { + return &windowInfo; + } + } + return nullptr; + } + +private: + struct WindowInfosListener : public gui::WindowInfosListener { + public: + WindowInfosListener(WindowInfosPredicate predicate, std::promise<void>& promise) + : mPredicate(std::move(predicate)), mPromise(promise) {} + + void onWindowInfosChanged(const gui::WindowInfosUpdate& update) override { + if (mPredicate(update.windowInfos)) { + mPromise.set_value(); + } + } + + private: + WindowInfosPredicate mPredicate; + std::promise<void>& mPromise; + }; + + sp<SurfaceComposerClient> mClient; +}; + +} // namespace android |