diff options
43 files changed, 733 insertions, 275 deletions
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp index 5cbcf9fdf6..a417837ef9 100644 --- a/cmds/dumpstate/tests/dumpstate_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_test.cpp @@ -1001,7 +1001,7 @@ TEST_F(DumpstateTest, PreDumpUiData) { // These traces are always enabled, i.e. they are always pre-dumped const std::vector<std::filesystem::path> uiTraces = { std::filesystem::path{"/data/misc/wmtrace/transactions_trace.winscope"}, - std::filesystem::path{"/data/misc/wmtrace/transition_trace.winscope"}, + std::filesystem::path{"/data/misc/wmtrace/wm_transition_trace.winscope"}, std::filesystem::path{"/data/misc/wmtrace/shell_transition_trace.winscope"}, }; diff --git a/libs/binder/ActivityManager.cpp b/libs/binder/ActivityManager.cpp index e45a656d29..aca5009148 100644 --- a/libs/binder/ActivityManager.cpp +++ b/libs/binder/ActivityManager.cpp @@ -75,6 +75,20 @@ status_t ActivityManager::registerUidObserver(const sp<IUidObserver>& observer, return DEAD_OBJECT; } +status_t ActivityManager::registerUidObserverForUids(const sp<IUidObserver>& observer, + const int32_t event, const int32_t cutpoint, + const String16& callingPackage, + const int32_t uids[], size_t nUids, + /*out*/ sp<IBinder>& observerToken) { + sp<IActivityManager> service = getService(); + if (service != nullptr) { + return service->registerUidObserverForUids(observer, event, cutpoint, callingPackage, uids, + nUids, observerToken); + } + // ActivityManagerService appears dead. Return usual error code for dead service. + return DEAD_OBJECT; +} + status_t ActivityManager::unregisterUidObserver(const sp<IUidObserver>& observer) { sp<IActivityManager> service = getService(); @@ -85,6 +99,26 @@ status_t ActivityManager::unregisterUidObserver(const sp<IUidObserver>& observer return DEAD_OBJECT; } +status_t ActivityManager::addUidToObserver(const sp<IBinder>& observerToken, + const String16& callingPackage, int32_t uid) { + sp<IActivityManager> service = getService(); + if (service != nullptr) { + return service->addUidToObserver(observerToken, callingPackage, uid); + } + // ActivityManagerService appears dead. Return usual error code for dead service. + return DEAD_OBJECT; +} + +status_t ActivityManager::removeUidFromObserver(const sp<IBinder>& observerToken, + const String16& callingPackage, int32_t uid) { + sp<IActivityManager> service = getService(); + if (service != nullptr) { + return service->removeUidFromObserver(observerToken, callingPackage, uid); + } + // ActivityManagerService appears dead. Return usual error code for dead service. + return DEAD_OBJECT; +} + bool ActivityManager::isUidActive(const uid_t uid, const String16& callingPackage) { sp<IActivityManager> service = getService(); diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp index ebdaa4cc99..84900a72ff 100644 --- a/libs/binder/IActivityManager.cpp +++ b/libs/binder/IActivityManager.cpp @@ -77,6 +77,30 @@ public: return OK; } + virtual status_t registerUidObserverForUids(const sp<IUidObserver>& observer, + const int32_t event, const int32_t cutpoint, + const String16& callingPackage, + const int32_t uids[], size_t nUids, + /*out*/ sp<IBinder>& observerToken) { + Parcel data, reply; + data.writeInterfaceToken(IActivityManager::getInterfaceDescriptor()); + data.writeStrongBinder(IInterface::asBinder(observer)); + data.writeInt32(event); + data.writeInt32(cutpoint); + data.writeString16(callingPackage); + data.writeInt32Array(nUids, uids); + status_t err = + remote()->transact(REGISTER_UID_OBSERVER_FOR_UIDS_TRANSACTION, data, &reply); + if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) { + return err; + } + err = reply.readStrongBinder(&observerToken); + if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) { + return err; + } + return OK; + } + virtual status_t unregisterUidObserver(const sp<IUidObserver>& observer) { Parcel data, reply; @@ -89,6 +113,34 @@ public: return OK; } + virtual status_t addUidToObserver(const sp<IBinder>& observerToken, + const String16& callingPackage, int32_t uid) { + Parcel data, reply; + data.writeInterfaceToken(IActivityManager::getInterfaceDescriptor()); + data.writeStrongBinder(observerToken); + data.writeString16(callingPackage); + data.writeInt32(uid); + status_t err = remote()->transact(ADD_UID_TO_OBSERVER_TRANSACTION, data, &reply); + if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) { + return err; + } + return OK; + } + + virtual status_t removeUidFromObserver(const sp<IBinder>& observerToken, + const String16& callingPackage, int32_t uid) { + Parcel data, reply; + data.writeInterfaceToken(IActivityManager::getInterfaceDescriptor()); + data.writeStrongBinder(observerToken); + data.writeString16(callingPackage); + data.writeInt32(uid); + status_t err = remote()->transact(REMOVE_UID_FROM_OBSERVER_TRANSACTION, data, &reply); + if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) { + return err; + } + return OK; + } + virtual bool isUidActive(const uid_t uid, const String16& callingPackage) { Parcel data, reply; diff --git a/libs/binder/include_activitymanager/binder/ActivityManager.h b/libs/binder/include_activitymanager/binder/ActivityManager.h index 5dfbd44dc4..9c634c7238 100644 --- a/libs/binder/include_activitymanager/binder/ActivityManager.h +++ b/libs/binder/include_activitymanager/binder/ActivityManager.h @@ -82,7 +82,15 @@ public: const int32_t event, const int32_t cutpoint, const String16& callingPackage); + status_t registerUidObserverForUids(const sp<IUidObserver>& observer, const int32_t event, + const int32_t cutpoint, const String16& callingPackage, + const int32_t uids[], size_t nUids, + /*out*/ sp<IBinder>& observerToken); status_t unregisterUidObserver(const sp<IUidObserver>& observer); + status_t addUidToObserver(const sp<IBinder>& observerToken, const String16& callingPackage, + int32_t uid); + status_t removeUidFromObserver(const sp<IBinder>& observerToken, const String16& callingPackage, + int32_t uid); bool isUidActive(const uid_t uid, const String16& callingPackage); int getUidProcessState(const uid_t uid, const String16& callingPackage); status_t checkPermission(const String16& permission, const pid_t pid, const uid_t uid, int32_t* outResult); diff --git a/libs/binder/include_activitymanager/binder/IActivityManager.h b/libs/binder/include_activitymanager/binder/IActivityManager.h index 20d12aea9a..07450c6af9 100644 --- a/libs/binder/include_activitymanager/binder/IActivityManager.h +++ b/libs/binder/include_activitymanager/binder/IActivityManager.h @@ -35,7 +35,16 @@ public: const int32_t event, const int32_t cutpoint, const String16& callingPackage) = 0; + virtual status_t registerUidObserverForUids(const sp<IUidObserver>& observer, + const int32_t event, const int32_t cutpoint, + const String16& callingPackage, + const int32_t uids[], size_t nUids, + /*out*/ sp<IBinder>& observerToken) = 0; virtual status_t unregisterUidObserver(const sp<IUidObserver>& observer) = 0; + virtual status_t addUidToObserver(const sp<IBinder>& observerToken, + const String16& callingPackage, int32_t uid) = 0; + virtual status_t removeUidFromObserver(const sp<IBinder>& observerToken, + const String16& callingPackage, int32_t uid) = 0; virtual bool isUidActive(const uid_t uid, const String16& callingPackage) = 0; virtual int32_t getUidProcessState(const uid_t uid, const String16& callingPackage) = 0; virtual status_t checkPermission(const String16& permission, @@ -51,6 +60,9 @@ public: OPEN_CONTENT_URI_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, REGISTER_UID_OBSERVER_TRANSACTION, UNREGISTER_UID_OBSERVER_TRANSACTION, + REGISTER_UID_OBSERVER_FOR_UIDS_TRANSACTION, + ADD_UID_TO_OBSERVER_TRANSACTION, + REMOVE_UID_FROM_OBSERVER_TRANSACTION, IS_UID_ACTIVE_TRANSACTION, GET_UID_PROCESS_STATE_TRANSACTION, CHECK_PERMISSION_TRANSACTION, diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp index c480056b40..5fbae3c712 100644 --- a/libs/graphicsenv/GraphicsEnv.cpp +++ b/libs/graphicsenv/GraphicsEnv.cpp @@ -433,61 +433,24 @@ bool GraphicsEnv::shouldUseAngle() { return (mUseAngle == YES) ? true : false; } -bool GraphicsEnv::angleIsSystemDriver() { - // Make sure we are init'ed - if (mAngleAppName.empty()) { - ALOGV("App name is empty. setAngleInfo() has not been called to enable ANGLE."); - return false; - } - - return (mAngleIsSystemDriver == YES) ? true : false; -} - -bool GraphicsEnv::shouldForceLegacyDriver() { - // Make sure we are init'ed - if (mAngleAppName.empty()) { - ALOGV("App name is empty. setAngleInfo() has not been called to enable ANGLE."); - return false; - } - - return (mAngleIsSystemDriver == YES && mUseAngle == NO) ? true : false; -} - -std::string GraphicsEnv::getLegacySuffix() { - return mLegacyDriverSuffix; -} - void GraphicsEnv::updateUseAngle() { - mUseAngle = NO; - const char* ANGLE_PREFER_ANGLE = "angle"; - const char* ANGLE_PREFER_LEGACY = "legacy"; - // The following is a deprecated version of "legacy" const char* ANGLE_PREFER_NATIVE = "native"; mUseAngle = NO; if (mAngleDeveloperOptIn == ANGLE_PREFER_ANGLE) { - ALOGI("Using ANGLE, the %s GLES driver for package '%s'", - mAngleIsSystemDriver == YES ? "system" : "optional", mAngleAppName.c_str()); + ALOGV("User set \"Developer Options\" to force the use of ANGLE"); mUseAngle = YES; - } else if (mAngleDeveloperOptIn == ANGLE_PREFER_LEGACY || - mAngleDeveloperOptIn == ANGLE_PREFER_NATIVE) { - ALOGI("Using the (%s) Legacy GLES driver for package '%s'", - mAngleIsSystemDriver == YES ? "optional" : "system", mAngleAppName.c_str()); + } else if (mAngleDeveloperOptIn == ANGLE_PREFER_NATIVE) { + ALOGV("User set \"Developer Options\" to force the use of Native"); } else { ALOGV("User set invalid \"Developer Options\": '%s'", mAngleDeveloperOptIn.c_str()); } } void GraphicsEnv::setAngleInfo(const std::string path, const std::string appName, - const bool angleIsSystemDriver, const std::string developerOptIn, + const std::string developerOptIn, const std::vector<std::string> eglFeatures) { - // Set whether ANGLE is the system driver: - mAngleIsSystemDriver = angleIsSystemDriver ? YES : NO; - - // Note: Given the current logic and lack of the old rules file processing, - // there seems to be little chance that mUseAngle != UNKNOWN. Leave this - // for now, even though it seems outdated. if (mUseAngle != UNKNOWN) { // We've already figured out an answer for this app, so just return. ALOGV("Already evaluated the rules file for '%s': use ANGLE = %s", appName.c_str(), @@ -508,25 +471,6 @@ void GraphicsEnv::setAngleInfo(const std::string path, const std::string appName updateUseAngle(); } -void GraphicsEnv::setLegacyDriverInfo(const std::string appName, const bool angleIsSystemDriver, - const std::string legacyDriverName) { - ALOGV("setting legacy app name to '%s'", appName.c_str()); - mAngleAppName = appName; - - // Force the use of the legacy driver instead of ANGLE - const char* ANGLE_PREFER_LEGACY = "legacy"; - mAngleDeveloperOptIn = ANGLE_PREFER_LEGACY; - ALOGV("setting ANGLE application opt-in to 'legacy'"); - - // Set whether ANGLE is the system driver: - mAngleIsSystemDriver = angleIsSystemDriver ? YES : NO; - - mLegacyDriverSuffix = legacyDriverName; - - // Update the current status of whether we should use ANGLE or not - updateUseAngle(); -} - void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths) { if (mLayerPaths.empty()) { mLayerPaths = layerPaths; diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h index 1274c46b7b..f9b234a047 100644 --- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h +++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h @@ -100,28 +100,17 @@ public: bool shouldUseAngle(std::string appName); // Check if this app process should use ANGLE. bool shouldUseAngle(); - // If ANGLE is the system GLES driver - bool angleIsSystemDriver(); - // If should use legacy driver instead of a system ANGLE driver - bool shouldForceLegacyDriver(); // Set a search path for loading ANGLE libraries. The path is a list of // directories separated by ':'. A directory can be contained in a zip file // (libraries must be stored uncompressed and page aligned); such elements // in the search path must have a '!' after the zip filename, e.g. // /system/app/ANGLEPrebuilt/ANGLEPrebuilt.apk!/lib/arm64-v8a - void setAngleInfo(const std::string path, const std::string appName, - const bool angleIsSystemDriver, std::string devOptIn, + void setAngleInfo(const std::string path, const std::string appName, std::string devOptIn, const std::vector<std::string> eglFeatures); - // Set the state so that the legacy driver will be used, and in case ANGLE - // is the system driver, provide the name of the legacy driver. - void setLegacyDriverInfo(const std::string appName, const bool angleIsSystemDriver, - const std::string legacyDriverName); // Get the ANGLE driver namespace. android_namespace_t* getAngleNamespace(); // Get the app name for ANGLE debug message. std::string& getAngleAppName(); - // Get the legacy driver's suffix name. - std::string getLegacySuffix(); const std::vector<std::string>& getAngleEglFeatures(); @@ -178,10 +167,6 @@ private: std::string mAngleDeveloperOptIn; // ANGLE EGL features; std::vector<std::string> mAngleEglFeatures; - // ANGLE is System Driver flag. - UseAngle mAngleIsSystemDriver = UNKNOWN; - // Legacy driver name to use when ANGLE is the system driver. - std::string mLegacyDriverSuffix; // Use ANGLE flag. UseAngle mUseAngle = UNKNOWN; // Vulkan debug layers libs. diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 0a63c1564e..80fed98434 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -75,6 +75,7 @@ filegroup { "android/gui/IWindowInfosListener.aidl", "android/gui/IWindowInfosReportedListener.aidl", "android/gui/WindowInfo.aidl", + "android/gui/WindowInfosUpdate.aidl", ], } @@ -90,9 +91,11 @@ cc_library_static { "android/gui/InputApplicationInfo.aidl", "android/gui/IWindowInfosListener.aidl", "android/gui/IWindowInfosReportedListener.aidl", + "android/gui/WindowInfosUpdate.aidl", "android/gui/WindowInfo.aidl", "DisplayInfo.cpp", "WindowInfo.cpp", + "WindowInfosUpdate.cpp", ], shared_libs: [ @@ -223,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/WindowInfosListenerReporter.cpp b/libs/gui/WindowInfosListenerReporter.cpp index 2b34a0fc47..76e7b6e162 100644 --- a/libs/gui/WindowInfosListenerReporter.cpp +++ b/libs/gui/WindowInfosListenerReporter.cpp @@ -17,6 +17,7 @@ #include <android/gui/ISurfaceComposer.h> #include <gui/AidlStatusUtil.h> #include <gui/WindowInfosListenerReporter.h> +#include "gui/WindowInfosUpdate.h" namespace android { @@ -84,7 +85,7 @@ status_t WindowInfosListenerReporter::removeWindowInfosListener( } binder::Status WindowInfosListenerReporter::onWindowInfosChanged( - const std::vector<WindowInfo>& windowInfos, const std::vector<DisplayInfo>& displayInfos, + const gui::WindowInfosUpdate& update, const sp<IWindowInfosReportedListener>& windowInfosReportedListener) { std::unordered_set<sp<WindowInfosListener>, gui::SpHash<WindowInfosListener>> windowInfosListeners; @@ -95,12 +96,12 @@ binder::Status WindowInfosListenerReporter::onWindowInfosChanged( windowInfosListeners.insert(listener); } - mLastWindowInfos = windowInfos; - mLastDisplayInfos = displayInfos; + mLastWindowInfos = update.windowInfos; + mLastDisplayInfos = update.displayInfos; } for (auto listener : windowInfosListeners) { - listener->onWindowInfosChanged(windowInfos, displayInfos); + listener->onWindowInfosChanged(update); } if (windowInfosReportedListener) { diff --git a/libs/gui/WindowInfosUpdate.cpp b/libs/gui/WindowInfosUpdate.cpp new file mode 100644 index 0000000000..38ae5ef102 --- /dev/null +++ b/libs/gui/WindowInfosUpdate.cpp @@ -0,0 +1,72 @@ +/* + * 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 <gui/WindowInfosUpdate.h> +#include <private/gui/ParcelUtils.h> + +namespace android::gui { + +status_t WindowInfosUpdate::readFromParcel(const android::Parcel* parcel) { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + + uint32_t size; + + SAFE_PARCEL(parcel->readUint32, &size); + windowInfos.reserve(size); + for (uint32_t i = 0; i < size; i++) { + windowInfos.push_back({}); + SAFE_PARCEL(windowInfos.back().readFromParcel, parcel); + } + + SAFE_PARCEL(parcel->readUint32, &size); + displayInfos.reserve(size); + for (uint32_t i = 0; i < size; i++) { + displayInfos.push_back({}); + SAFE_PARCEL(displayInfos.back().readFromParcel, parcel); + } + + SAFE_PARCEL(parcel->readInt64, &vsyncId); + SAFE_PARCEL(parcel->readInt64, ×tamp); + + return OK; +} + +status_t WindowInfosUpdate::writeToParcel(android::Parcel* parcel) const { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + + SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(windowInfos.size())); + for (auto& windowInfo : windowInfos) { + SAFE_PARCEL(windowInfo.writeToParcel, parcel); + } + + SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(displayInfos.size())); + for (auto& displayInfo : displayInfos) { + SAFE_PARCEL(displayInfo.writeToParcel, parcel); + } + + SAFE_PARCEL(parcel->writeInt64, vsyncId); + SAFE_PARCEL(parcel->writeInt64, timestamp); + + return OK; +} + +} // namespace android::gui diff --git a/libs/gui/android/gui/IWindowInfosListener.aidl b/libs/gui/android/gui/IWindowInfosListener.aidl index a5b2762318..400229d99f 100644 --- a/libs/gui/android/gui/IWindowInfosListener.aidl +++ b/libs/gui/android/gui/IWindowInfosListener.aidl @@ -16,12 +16,11 @@ package android.gui; -import android.gui.DisplayInfo; import android.gui.IWindowInfosReportedListener; -import android.gui.WindowInfo; +import android.gui.WindowInfosUpdate; /** @hide */ -oneway interface IWindowInfosListener -{ - void onWindowInfosChanged(in WindowInfo[] windowInfos, in DisplayInfo[] displayInfos, in @nullable IWindowInfosReportedListener windowInfosReportedListener); +oneway interface IWindowInfosListener { + void onWindowInfosChanged( + in WindowInfosUpdate update, in @nullable IWindowInfosReportedListener windowInfosReportedListener); } diff --git a/libs/gui/android/gui/WindowInfosUpdate.aidl b/libs/gui/android/gui/WindowInfosUpdate.aidl new file mode 100644 index 0000000000..0c6109da8f --- /dev/null +++ b/libs/gui/android/gui/WindowInfosUpdate.aidl @@ -0,0 +1,22 @@ +/* +** 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. +*/ + +package android.gui; + +import android.gui.DisplayInfo; +import android.gui.WindowInfo; + +parcelable WindowInfosUpdate cpp_header "gui/WindowInfosUpdate.h"; 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/include/gui/WindowInfosListener.h b/libs/gui/include/gui/WindowInfosListener.h index a18a498c5e..02c8eb5ef3 100644 --- a/libs/gui/include/gui/WindowInfosListener.h +++ b/libs/gui/include/gui/WindowInfosListener.h @@ -16,15 +16,13 @@ #pragma once -#include <gui/DisplayInfo.h> -#include <gui/WindowInfo.h> +#include <gui/WindowInfosUpdate.h> #include <utils/RefBase.h> namespace android::gui { class WindowInfosListener : public virtual RefBase { public: - virtual void onWindowInfosChanged(const std::vector<WindowInfo>&, - const std::vector<DisplayInfo>&) = 0; + virtual void onWindowInfosChanged(const WindowInfosUpdate& update) = 0; }; -} // namespace android::gui
\ No newline at end of file +} // namespace android::gui diff --git a/libs/gui/include/gui/WindowInfosListenerReporter.h b/libs/gui/include/gui/WindowInfosListenerReporter.h index 2754442a95..38cb108912 100644 --- a/libs/gui/include/gui/WindowInfosListenerReporter.h +++ b/libs/gui/include/gui/WindowInfosListenerReporter.h @@ -22,6 +22,7 @@ #include <binder/IBinder.h> #include <gui/SpHash.h> #include <gui/WindowInfosListener.h> +#include <gui/WindowInfosUpdate.h> #include <unordered_set> namespace android { @@ -29,8 +30,7 @@ namespace android { class WindowInfosListenerReporter : public gui::BnWindowInfosListener { public: static sp<WindowInfosListenerReporter> getInstance(); - binder::Status onWindowInfosChanged(const std::vector<gui::WindowInfo>&, - const std::vector<gui::DisplayInfo>&, + binder::Status onWindowInfosChanged(const gui::WindowInfosUpdate& update, const sp<gui::IWindowInfosReportedListener>&) override; status_t addWindowInfosListener( const sp<gui::WindowInfosListener>& windowInfosListener, diff --git a/libs/gui/include/gui/WindowInfosUpdate.h b/libs/gui/include/gui/WindowInfosUpdate.h new file mode 100644 index 0000000000..2ca59fb497 --- /dev/null +++ b/libs/gui/include/gui/WindowInfosUpdate.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#pragma once + +#include <binder/Parcelable.h> +#include <gui/DisplayInfo.h> +#include <gui/WindowInfo.h> + +namespace android::gui { + +struct WindowInfosUpdate : public Parcelable { + WindowInfosUpdate() {} + + WindowInfosUpdate(std::vector<WindowInfo> windowInfos, std::vector<DisplayInfo> displayInfos, + int64_t vsyncId, int64_t timestamp) + : windowInfos(std::move(windowInfos)), + displayInfos(std::move(displayInfos)), + vsyncId(vsyncId), + timestamp(timestamp) {} + + std::vector<WindowInfo> windowInfos; + std::vector<DisplayInfo> displayInfos; + int64_t vsyncId; + int64_t timestamp; + + status_t writeToParcel(android::Parcel*) const override; + status_t readFromParcel(const android::Parcel*) override; +}; + +} // namespace android::gui 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/libs/ultrahdr/jpegr.cpp b/libs/ultrahdr/jpegr.cpp index 0f7aa27354..ef927e3c56 100644 --- a/libs/ultrahdr/jpegr.cpp +++ b/libs/ultrahdr/jpegr.cpp @@ -534,7 +534,7 @@ bool JobQueue::dequeueJob(size_t& rowStart, size_t& rowEnd) { if (mQueuedAllJobs) { return false; } else { - mCv.wait(lock); + mCv.wait_for(lock, std::chrono::milliseconds(100)); } } else { auto it = mJobs.begin(); @@ -557,6 +557,8 @@ void JobQueue::enqueueJob(size_t rowStart, size_t rowEnd) { void JobQueue::markQueueForEnd() { std::unique_lock<std::mutex> lock{mMutex}; mQueuedAllJobs = true; + lock.unlock(); + mCv.notify_all(); } void JobQueue::reset() { diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp index 415e8eab70..2c3ce16f66 100644 --- a/opengl/libs/EGL/Loader.cpp +++ b/opengl/libs/EGL/Loader.cpp @@ -139,9 +139,10 @@ static void* load_wrapper(const char* path) { static const char* DRIVER_SUFFIX_PROPERTY = "ro.hardware.egl"; -static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = { - DRIVER_SUFFIX_PROPERTY, - "ro.board.platform", +static const char* HAL_SUBNAME_KEY_PROPERTIES[3] = { + "persist.graphics.egl", + DRIVER_SUFFIX_PROPERTY, + "ro.board.platform", }; static bool should_unload_system_driver(egl_connection_t* cnx) { @@ -208,8 +209,7 @@ void* Loader::open(egl_connection_t* cnx) ATRACE_CALL(); const nsecs_t openTime = systemTime(); - if (!android::GraphicsEnv::getInstance().angleIsSystemDriver() && - should_unload_system_driver(cnx)) { + if (should_unload_system_driver(cnx)) { unload_system_driver(cnx); } @@ -218,12 +218,8 @@ void* Loader::open(egl_connection_t* cnx) return cnx->dso; } - // Firstly, try to load ANGLE driver, unless we know that we shouldn't. - bool shouldForceLegacyDriver = android::GraphicsEnv::getInstance().shouldForceLegacyDriver(); - driver_t* hnd = nullptr; - if (!shouldForceLegacyDriver) { - hnd = attempt_to_load_angle(cnx); - } + // Firstly, try to load ANGLE driver. + driver_t* hnd = attempt_to_load_angle(cnx); if (!hnd) { // Secondly, try to load from driver apk. @@ -285,8 +281,10 @@ void* Loader::open(egl_connection_t* cnx) } LOG_ALWAYS_FATAL_IF(!hnd, - "couldn't find an OpenGL ES implementation, make sure you set %s or %s", - HAL_SUBNAME_KEY_PROPERTIES[0], HAL_SUBNAME_KEY_PROPERTIES[1]); + "couldn't find an OpenGL ES implementation, make sure one of %s, %s and %s " + "is set", + HAL_SUBNAME_KEY_PROPERTIES[0], HAL_SUBNAME_KEY_PROPERTIES[1], + HAL_SUBNAME_KEY_PROPERTIES[2]); if (!cnx->libEgl) { cnx->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so"); diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp index 9823fc839e..525fed115d 100644 --- a/opengl/libs/EGL/egl_display.cpp +++ b/opengl/libs/EGL/egl_display.cpp @@ -326,10 +326,10 @@ EGLBoolean egl_display_t::initialize(EGLint* major, EGLint* minor) { // device's present timestamps are reliable (which may not be the case on emulators). if (cnx->useAngle) { if (android::base::GetBoolProperty("service.sf.present_timestamp", false)) { - mExtensionString.append("EGL_ANDROID_get_frame_timestamps"); + mExtensionString.append("EGL_ANDROID_get_frame_timestamps "); } } else { - mExtensionString.append("EGL_ANDROID_get_frame_timestamps"); + mExtensionString.append("EGL_ANDROID_get_frame_timestamps "); } hasColorSpaceSupport = findExtension(disp.queryString.extensions, "EGL_KHR_gl_colorspace"); diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index cf299c0f6e..f65533ea79 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -340,8 +340,10 @@ static void benchmarkOnWindowInfosChanged(benchmark::State& state) { std::vector<gui::DisplayInfo> displayInfos{info}; for (auto _ : state) { - dispatcher.onWindowInfosChanged(windowInfos, displayInfos); - dispatcher.onWindowInfosChanged(/*windowInfos=*/{}, /*displayInfos=*/{}); + dispatcher.onWindowInfosChanged( + {windowInfos, displayInfos, /*vsyncId=*/0, /*timestamp=*/0}); + dispatcher.onWindowInfosChanged( + {/*windowInfos=*/{}, /*displayInfos=*/{}, /*vsyncId=*/{}, /*timestamp=*/0}); } dispatcher.stop(); } diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index a10c957d15..f3ada8e298 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -2476,7 +2476,8 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( newTouchedWindowHandle = nullptr; } - if (!haveSameToken(oldTouchedWindowHandle, newTouchedWindowHandle)) { + if (newTouchedWindowHandle != nullptr && + !haveSameToken(oldTouchedWindowHandle, newTouchedWindowHandle)) { ALOGD("Touch is slipping out of window %s into window %s in display %" PRId32, oldTouchedWindowHandle->getName().c_str(), newTouchedWindowHandle->getName().c_str(), displayId); @@ -5611,6 +5612,14 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) const { } else { dump += INDENT "Displays: <none>\n"; } + dump += INDENT "Window Infos:\n"; + dump += StringPrintf(INDENT2 "vsync id: %" PRId64 "\n", mWindowInfosVsyncId); + dump += StringPrintf(INDENT2 "timestamp (ns): %" PRId64 "\n", mWindowInfosTimestamp); + dump += "\n"; + dump += StringPrintf(INDENT2 "max update delay (ns): %" PRId64 "\n", mMaxWindowInfosDelay); + dump += StringPrintf(INDENT2 "max update delay vsync id: %" PRId64 "\n", + mMaxWindowInfosDelayVsyncId); + dump += "\n"; if (!mGlobalMonitorsByDisplay.empty()) { for (const auto& [displayId, monitors] : mGlobalMonitorsByDisplay) { @@ -6626,12 +6635,11 @@ void InputDispatcher::displayRemoved(int32_t displayId) { mLooper->wake(); } -void InputDispatcher::onWindowInfosChanged(const std::vector<WindowInfo>& windowInfos, - const std::vector<DisplayInfo>& displayInfos) { +void InputDispatcher::onWindowInfosChanged(const gui::WindowInfosUpdate& update) { // The listener sends the windows as a flattened array. Separate the windows by display for // more convenient parsing. std::unordered_map<int32_t, std::vector<sp<WindowInfoHandle>>> handlesPerDisplay; - for (const auto& info : windowInfos) { + for (const auto& info : update.windowInfos) { handlesPerDisplay.emplace(info.displayId, std::vector<sp<WindowInfoHandle>>()); handlesPerDisplay[info.displayId].push_back(sp<WindowInfoHandle>::make(info)); } @@ -6646,13 +6654,22 @@ void InputDispatcher::onWindowInfosChanged(const std::vector<WindowInfo>& window } mDisplayInfos.clear(); - for (const auto& displayInfo : displayInfos) { + for (const auto& displayInfo : update.displayInfos) { mDisplayInfos.emplace(displayInfo.displayId, displayInfo); } for (const auto& [displayId, handles] : handlesPerDisplay) { setInputWindowsLocked(handles, displayId); } + + mWindowInfosVsyncId = update.vsyncId; + mWindowInfosTimestamp = update.timestamp; + + int64_t delay = systemTime() - update.timestamp; + if (delay > mMaxWindowInfosDelay) { + mMaxWindowInfosDelay = delay; + mMaxWindowInfosDelayVsyncId = update.vsyncId; + } } // Wake up poll loop since it may need to make new input dispatching choices. mLooper->wake(); @@ -6675,9 +6692,8 @@ bool InputDispatcher::shouldDropInput( } void InputDispatcher::DispatcherWindowListener::onWindowInfosChanged( - const std::vector<gui::WindowInfo>& windowInfos, - const std::vector<DisplayInfo>& displayInfos) { - mDispatcher.onWindowInfosChanged(windowInfos, displayInfos); + const gui::WindowInfosUpdate& update) { + mDispatcher.onWindowInfosChanged(update); } void InputDispatcher::cancelCurrentTouch() { diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 0e9ccfb181..9b12f2f64c 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -36,7 +36,7 @@ #include <attestation/HmacKeyManager.h> #include <gui/InputApplication.h> -#include <gui/WindowInfo.h> +#include <gui/WindowInfosUpdate.h> #include <input/Input.h> #include <input/InputTransport.h> #include <limits.h> @@ -144,8 +144,7 @@ public: void displayRemoved(int32_t displayId) override; // Public because it's also used by tests to simulate the WindowInfosListener callback - void onWindowInfosChanged(const std::vector<android::gui::WindowInfo>& windowInfos, - const std::vector<android::gui::DisplayInfo>& displayInfos); + void onWindowInfosChanged(const gui::WindowInfosUpdate&); void cancelCurrentTouch() override; @@ -205,6 +204,11 @@ private: const IdGenerator mIdGenerator; + int64_t mWindowInfosVsyncId GUARDED_BY(mLock); + int64_t mWindowInfosTimestamp GUARDED_BY(mLock); + int64_t mMaxWindowInfosDelay GUARDED_BY(mLock) = -1; + int64_t mMaxWindowInfosDelayVsyncId GUARDED_BY(mLock) = -1; + // With each iteration, InputDispatcher nominally processes one queued event, // a timeout, or a response from an input consumer. // This method should only be called on the input dispatcher's own thread. @@ -356,9 +360,7 @@ private: class DispatcherWindowListener : public gui::WindowInfosListener { public: explicit DispatcherWindowListener(InputDispatcher& dispatcher) : mDispatcher(dispatcher){}; - void onWindowInfosChanged( - const std::vector<android::gui::WindowInfo>& windowInfos, - const std::vector<android::gui::DisplayInfo>& displayInfos) override; + void onWindowInfosChanged(const gui::WindowInfosUpdate&) override; private: InputDispatcher& mDispatcher; diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp index a5da3cdccc..c72425a90b 100644 --- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp @@ -270,6 +270,14 @@ std::list<NotifyArgs> TouchpadInputMapper::reconfigure(nsecs_t when, accelCurveProp.setRealValues( createAccelerationCurveForSensitivity(config.touchpadPointerSpeed, accelCurveProp.getCount())); + mPropertyProvider.getProperty("Use Custom Touchpad Scroll Accel Curve") + .setBoolValues({true}); + GesturesProp scrollCurveProp = mPropertyProvider.getProperty("Scroll Accel Curve"); + scrollCurveProp.setRealValues( + createAccelerationCurveForSensitivity(config.touchpadPointerSpeed, + scrollCurveProp.getCount())); + mPropertyProvider.getProperty("Scroll X Out Scale").setRealValues({1.0}); + mPropertyProvider.getProperty("Scroll Y Out Scale").setRealValues({1.0}); mPropertyProvider.getProperty("Invert Scrolling") .setBoolValues({config.touchpadNaturalScrollingEnabled}); mPropertyProvider.getProperty("Tap Enable") diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 41c4d69946..f6f02d8241 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -3945,7 +3945,7 @@ TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) { "Fake Window", ADISPLAY_ID_DEFAULT); window->setFocusable(true); - mDispatcher->onWindowInfosChanged({*window->getInfo()}, {}); + mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0}); setFocusedWindow(window); window->consumeFocusEvent(true); @@ -3959,7 +3959,7 @@ TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) { window->consumeKeyUp(ADISPLAY_ID_DEFAULT); // All windows are removed from the display. Ensure that we can no longer dispatch to it. - mDispatcher->onWindowInfosChanged({}, {}); + mDispatcher->onWindowInfosChanged({{}, {}, 0, 0}); window->consumeFocusEvent(false); @@ -3975,7 +3975,7 @@ TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) { // Ensure window is non-split and have some transform. window->setPreventSplitting(true); window->setWindowOffset(20, 40); - mDispatcher->onWindowInfosChanged({*window->getInfo()}, {}); + mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0}); ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, @@ -4022,12 +4022,12 @@ public: info.displayId = displayId; info.transform = transform; mDisplayInfos.push_back(std::move(info)); - mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos); + mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0}); } void addWindow(const sp<WindowInfoHandle>& windowHandle) { mWindowInfos.push_back(*windowHandle->getInfo()); - mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos); + mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0}); } void removeAllWindowsAndDisplays() { @@ -5215,7 +5215,7 @@ TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) { displayInfo.displayId = ADISPLAY_ID_DEFAULT; displayInfo.transform = transform; - mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo}); + mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0}); const NotifyMotionArgs motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, @@ -5535,6 +5535,46 @@ TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) { AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED); } +/** + * Two windows, one on the left and another on the right. The left window is slippery. The right + * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the + * touch moves from the left window into the right window, the gesture should continue to go to the + * left window. Touch shouldn't slip because the right window can't receive touches. This test + * reproduces a crash. + */ +TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) { + std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); + + sp<FakeWindowHandle> leftSlipperyWindow = + sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT); + leftSlipperyWindow->setSlippery(true); + leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100)); + + sp<FakeWindowHandle> rightDropTouchesWindow = + sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT); + rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100)); + rightDropTouchesWindow->setDropInput(true); + + mDispatcher->setInputWindows( + {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}}); + + // Start touch in the left window + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) + .build()); + leftSlipperyWindow->consumeMotionDown(); + + // And move it into the right window + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) + .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50)) + .build()); + + // Since the right window isn't eligible to receive input, touch does not slip. + // The left window continues to receive the gesture. + leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE)); + rightDropTouchesWindow->assertNoEvents(); +} + class InputDispatcherKeyRepeatTest : public InputDispatcherTest { protected: static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms @@ -5985,7 +6025,7 @@ TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) displayInfos[1].displayId = SECOND_DISPLAY_ID; displayInfos[1].transform = secondDisplayTransform; - mDispatcher->onWindowInfosChanged({}, displayInfos); + mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0}); // Enable InputFilter mDispatcher->setInputFilterEnabled(true); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index bfb7a22ae7..3371ae2d8c 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -254,8 +254,7 @@ Layer::~Layer() { mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount(); } if (mHadClonedChild) { - auto& roots = mFlinger->mLayerMirrorRoots; - roots.erase(std::remove(roots.begin(), roots.end(), this), roots.end()); + mFlinger->mNumClones--; } if (hasTrustedPresentationListener()) { mFlinger->mNumTrustedPresentationListeners--; @@ -2595,7 +2594,7 @@ void Layer::updateCloneBufferInfo() { mDrawingState.inputInfo = tmpInputInfo; } -bool Layer::updateMirrorInfo(const std::deque<Layer*>& cloneRootsPendingUpdates) { +void Layer::updateMirrorInfo() { if (mClonedChild == nullptr || !mClonedChild->isClonedFromAlive()) { // If mClonedChild is null, there is nothing to mirror. If isClonedFromAlive returns false, // it means that there is a clone, but the layer it was cloned from has been destroyed. In @@ -2603,7 +2602,7 @@ bool Layer::updateMirrorInfo(const std::deque<Layer*>& cloneRootsPendingUpdates) // destroyed. The root, this layer, will still be around since the client can continue // to hold a reference, but no cloned layers will be displayed. mClonedChild = nullptr; - return true; + return; } std::map<sp<Layer>, sp<Layer>> clonedLayersMap; @@ -2618,13 +2617,6 @@ bool Layer::updateMirrorInfo(const std::deque<Layer*>& cloneRootsPendingUpdates) mClonedChild->updateClonedDrawingState(clonedLayersMap); mClonedChild->updateClonedChildren(sp<Layer>::fromExisting(this), clonedLayersMap); mClonedChild->updateClonedRelatives(clonedLayersMap); - - for (Layer* root : cloneRootsPendingUpdates) { - if (clonedLayersMap.find(sp<Layer>::fromExisting(root)) != clonedLayersMap.end()) { - return false; - } - } - return true; } void Layer::updateClonedDrawingState(std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) { @@ -2772,7 +2764,7 @@ bool Layer::isInternalDisplayOverlay() const { void Layer::setClonedChild(const sp<Layer>& clonedChild) { mClonedChild = clonedChild; mHadClonedChild = true; - mFlinger->mLayerMirrorRoots.push_back(this); + mFlinger->mNumClones++; } bool Layer::setDropInputMode(gui::DropInputMode mode) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 43749149af..2640c92b9d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -651,7 +651,7 @@ public: gui::WindowInfo::Type getWindowType() const { return mWindowType; } - bool updateMirrorInfo(const std::deque<Layer*>& cloneRootsPendingUpdates); + void updateMirrorInfo(); /* * doTransaction - process the transaction. This is a good place to figure diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp index d606cffe40..f6b5afc6a8 100644 --- a/services/surfaceflinger/LayerRenderArea.cpp +++ b/services/surfaceflinger/LayerRenderArea.cpp @@ -85,7 +85,7 @@ void LayerRenderArea::render(std::function<void()> drawLayers) { // If layer is offscreen, update mirroring info if it exists if (mLayer->isRemovedFromCurrentState()) { mLayer->traverse(LayerVector::StateSet::Drawing, - [&](Layer* layer) { layer->updateMirrorInfo({}); }); + [&](Layer* layer) { layer->updateMirrorInfo(); }); mLayer->traverse(LayerVector::StateSet::Drawing, [&](Layer* layer) { layer->updateCloneBufferInfo(); }); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b5ba94efb5..dfe8c72bca 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" @@ -2544,7 +2545,7 @@ bool SurfaceFlinger::commit(TimePoint frameTime, VsyncId vsyncId, TimePoint expe } updateCursorAsync(); - updateInputFlinger(); + updateInputFlinger(vsyncId); if (mLayerTracingEnabled && !mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)) { // This will block and tracing should only be enabled for debugging. @@ -3732,7 +3733,7 @@ void SurfaceFlinger::commitTransactionsLocked(uint32_t transactionFlags) { doCommitTransactions(); } -void SurfaceFlinger::updateInputFlinger() { +void SurfaceFlinger::updateInputFlinger(VsyncId vsyncId) { if (!mInputFlinger || (!mUpdateInputInfo && mInputWindowCommands.empty())) { return; } @@ -3744,6 +3745,8 @@ void SurfaceFlinger::updateInputFlinger() { if (mUpdateInputInfo) { mUpdateInputInfo = false; updateWindowInfo = true; + mLastInputFlingerUpdateVsyncId = vsyncId; + mLastInputFlingerUpdateTimestamp = systemTime(); buildWindowInfos(windowInfos, displayInfos); } @@ -3773,7 +3776,9 @@ void SurfaceFlinger::updateInputFlinger() { std::move( inputWindowCommands.windowInfosReportedListeners), /* forceImmediateCall= */ visibleWindowsChanged || - !inputWindowCommands.focusRequests.empty()); + !inputWindowCommands.focusRequests.empty(), + mLastInputFlingerUpdateVsyncId, + mLastInputFlingerUpdateTimestamp); } else { // If there are listeners but no changes to input windows, call the listeners // immediately. @@ -4020,21 +4025,8 @@ void SurfaceFlinger::doCommitTransactions() { } commitOffscreenLayers(); - if (mLayerMirrorRoots.size() > 0) { - std::deque<Layer*> pendingUpdates; - pendingUpdates.insert(pendingUpdates.end(), mLayerMirrorRoots.begin(), - mLayerMirrorRoots.end()); - std::vector<Layer*> needsUpdating; - for (Layer* cloneRoot : mLayerMirrorRoots) { - pendingUpdates.pop_front(); - if (cloneRoot->updateMirrorInfo(pendingUpdates)) { - } else { - needsUpdating.push_back(cloneRoot); - } - } - for (Layer* cloneRoot : needsUpdating) { - cloneRoot->updateMirrorInfo({}); - } + if (mNumClones > 0) { + mDrawingState.traverse([&](Layer* layer) { layer->updateMirrorInfo(); }); } } @@ -4141,7 +4133,7 @@ bool SurfaceFlinger::latchBuffers() { mBootStage = BootStage::BOOTANIMATION; } - if (mLayerMirrorRoots.size() > 0) { + if (mNumClones > 0) { mDrawingState.traverse([&](Layer* layer) { layer->updateCloneBufferInfo(); }); } @@ -4401,7 +4393,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); } @@ -4480,24 +4472,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)) { @@ -4513,10 +4508,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) { @@ -4563,12 +4554,11 @@ status_t SurfaceFlinger::setTransactionState( displays, flags, applyToken, - inputWindowCommands, + std::move(inputWindowCommands), desiredPresentTime, isAutoTimestamp, std::move(uncacheBufferIds), postTime, - permissions, hasListenerCallbacks, listenerCallbacks, originPid, @@ -4597,14 +4587,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); } } @@ -4621,12 +4609,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)) { @@ -4643,12 +4631,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); @@ -4685,7 +4668,6 @@ bool SurfaceFlinger::applyAndCommitDisplayTransactionStates( uint32_t transactionFlags = 0; for (auto& transaction : transactions) { for (DisplayState& display : transaction.displays) { - display.sanitize(transaction.permissions); transactionFlags |= setDisplayStateLocked(display); } } @@ -4784,10 +4766,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) { @@ -5136,10 +5116,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) { @@ -5421,7 +5399,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++; @@ -6130,6 +6107,29 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, const std::string& comp result.append(mTimeStats->miniDump()); result.append("\n"); + + result.append("Window Infos:\n"); + StringAppendF(&result, " input flinger update vsync id: %" PRId64 "\n", + mLastInputFlingerUpdateVsyncId.value); + StringAppendF(&result, " input flinger update timestamp (ns): %" PRId64 "\n", + mLastInputFlingerUpdateTimestamp); + result.append("\n"); + + if (int64_t unsentVsyncId = mWindowInfosListenerInvoker->getUnsentMessageVsyncId().value; + unsentVsyncId != -1) { + StringAppendF(&result, " unsent input flinger update vsync id: %" PRId64 "\n", + unsentVsyncId); + StringAppendF(&result, " unsent input flinger update timestamp (ns): %" PRId64 "\n", + mWindowInfosListenerInvoker->getUnsentMessageTimestamp()); + result.append("\n"); + } + + if (uint32_t pendingMessages = mWindowInfosListenerInvoker->getPendingMessageCount(); + pendingMessages != 0) { + StringAppendF(&result, " pending input flinger calls: %" PRIu32 "\n", + mWindowInfosListenerInvoker->getPendingMessageCount()); + result.append("\n"); + } } mat4 SurfaceFlinger::calculateColorMatrix(float saturation) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 92e19c0a0a..d92ec7a3b6 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -296,7 +296,8 @@ public: // the client can no longer modify this layer directly. void onHandleDestroyed(BBinder* handle, sp<Layer>& layer, uint32_t layerId); - std::vector<Layer*> mLayerMirrorRoots; + // TODO: Remove atomic if move dtor to main thread CL lands + std::atomic<uint32_t> mNumClones; TransactionCallbackInvoker& getTransactionCallbackInvoker() { return mTransactionCallbackInvoker; @@ -510,7 +511,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, @@ -716,7 +717,7 @@ private: void updateLayerHistory(const frontend::LayerSnapshot& snapshot); frontend::Update flushLifecycleUpdates() REQUIRES(kMainThreadContext); - void updateInputFlinger(); + void updateInputFlinger(VsyncId); void persistDisplayBrightness(bool needsComposite) REQUIRES(kMainThreadContext); void buildWindowInfos(std::vector<gui::WindowInfo>& outWindowInfos, std::vector<gui::DisplayInfo>& outDisplayInfos); @@ -731,14 +732,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 +762,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. @@ -1247,6 +1249,9 @@ private: VsyncId mLastCommittedVsyncId; + VsyncId mLastInputFlingerUpdateVsyncId; + nsecs_t mLastInputFlingerUpdateTimestamp; + // If blurs should be enabled on this device. bool mSupportsBlur = false; std::atomic<uint32_t> mFrameMissedCount = 0; 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/WindowInfosListenerInvoker.cpp b/services/surfaceflinger/WindowInfosListenerInvoker.cpp index 856fbbbf33..2b62638c61 100644 --- a/services/surfaceflinger/WindowInfosListenerInvoker.cpp +++ b/services/surfaceflinger/WindowInfosListenerInvoker.cpp @@ -16,6 +16,7 @@ #include <ftl/small_vector.h> #include <gui/ISurfaceComposer.h> +#include <gui/WindowInfosUpdate.h> #include "WindowInfosListenerInvoker.h" @@ -86,11 +87,12 @@ void WindowInfosListenerInvoker::binderDied(const wp<IBinder>& who) { void WindowInfosListenerInvoker::windowInfosChanged( std::vector<WindowInfo> windowInfos, std::vector<DisplayInfo> displayInfos, - WindowInfosReportedListenerSet reportedListeners, bool forceImmediateCall) { + WindowInfosReportedListenerSet reportedListeners, bool forceImmediateCall, VsyncId vsyncId, + nsecs_t timestamp) { reportedListeners.insert(sp<WindowInfosListenerInvoker>::fromExisting(this)); auto callListeners = [this, windowInfos = std::move(windowInfos), - displayInfos = std::move(displayInfos)]( - WindowInfosReportedListenerSet reportedListeners) mutable { + displayInfos = std::move(displayInfos), vsyncId, + timestamp](WindowInfosReportedListenerSet reportedListeners) mutable { WindowInfosListenerVector windowInfosListeners; { std::scoped_lock lock(mListenersMutex); @@ -103,6 +105,9 @@ void WindowInfosListenerInvoker::windowInfosChanged( sp<WindowInfosReportedListenerInvoker>::make(windowInfosListeners, std::move(reportedListeners)); + gui::WindowInfosUpdate update(std::move(windowInfos), std::move(displayInfos), + vsyncId.value, timestamp); + for (const auto& listener : windowInfosListeners) { sp<IBinder> asBinder = IInterface::asBinder(listener); @@ -111,8 +116,7 @@ void WindowInfosListenerInvoker::windowInfosChanged( // calling onWindowInfosReported. asBinder->linkToDeath(reportedInvoker); - auto status = - listener->onWindowInfosChanged(windowInfos, displayInfos, reportedInvoker); + auto status = listener->onWindowInfosChanged(update, reportedInvoker); if (!status.isOk()) { reportedInvoker->onWindowInfosReported(); } @@ -129,11 +133,15 @@ void WindowInfosListenerInvoker::windowInfosChanged( // to reduce the amount of binder memory used. if (mActiveMessageCount > 0 && !forceImmediateCall) { mWindowInfosChangedDelayed = std::move(callListeners); + mUnsentVsyncId = vsyncId; + mUnsentTimestamp = timestamp; mReportedListenersDelayed.merge(reportedListeners); return; } mWindowInfosChangedDelayed = nullptr; + mUnsentVsyncId = {-1}; + mUnsentTimestamp = -1; reportedListeners.merge(mReportedListenersDelayed); mActiveMessageCount++; } @@ -154,6 +162,8 @@ binder::Status WindowInfosListenerInvoker::onWindowInfosReported() { mActiveMessageCount++; callListeners = std::move(mWindowInfosChangedDelayed); mWindowInfosChangedDelayed = nullptr; + mUnsentVsyncId = {-1}; + mUnsentTimestamp = -1; reportedListeners = std::move(mReportedListenersDelayed); mReportedListenersDelayed.clear(); } diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.h b/services/surfaceflinger/WindowInfosListenerInvoker.h index 4da98282a9..e35d0564b5 100644 --- a/services/surfaceflinger/WindowInfosListenerInvoker.h +++ b/services/surfaceflinger/WindowInfosListenerInvoker.h @@ -26,6 +26,8 @@ #include <gui/SpHash.h> #include <utils/Mutex.h> +#include "scheduler/VsyncId.h" + namespace android { using WindowInfosReportedListenerSet = @@ -40,10 +42,25 @@ public: void windowInfosChanged(std::vector<gui::WindowInfo>, std::vector<gui::DisplayInfo>, WindowInfosReportedListenerSet windowInfosReportedListeners, - bool forceImmediateCall); + bool forceImmediateCall, VsyncId vsyncId, nsecs_t timestamp); binder::Status onWindowInfosReported() override; + VsyncId getUnsentMessageVsyncId() { + std::scoped_lock lock(mMessagesMutex); + return mUnsentVsyncId; + } + + nsecs_t getUnsentMessageTimestamp() { + std::scoped_lock lock(mMessagesMutex); + return mUnsentTimestamp; + } + + uint32_t getPendingMessageCount() { + std::scoped_lock lock(mMessagesMutex); + return mActiveMessageCount; + } + protected: void binderDied(const wp<IBinder>& who) override; @@ -58,6 +75,8 @@ private: uint32_t mActiveMessageCount GUARDED_BY(mMessagesMutex) = 0; std::function<void(WindowInfosReportedListenerSet)> mWindowInfosChangedDelayed GUARDED_BY(mMessagesMutex); + VsyncId mUnsentVsyncId GUARDED_BY(mMessagesMutex) = {-1}; + nsecs_t mUnsentTimestamp GUARDED_BY(mMessagesMutex) = -1; WindowInfosReportedListenerSet mReportedListenersDelayed; }; diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h index c1bab0e89b..4d13aca5bb 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -590,7 +590,7 @@ public: mFlinger->binderDied(display); mFlinger->onFirstRef(); - mFlinger->updateInputFlinger(); + mFlinger->updateInputFlinger(VsyncId{0}); mFlinger->updateCursorAsync(); mutableScheduler().setVsyncConfig({.sfOffset = mFdp.ConsumeIntegral<nsecs_t>(), 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 f4a8f038d7..ad9a674456 100644 --- a/services/surfaceflinger/tests/WindowInfosListener_test.cpp +++ b/services/surfaceflinger/tests/WindowInfosListener_test.cpp @@ -16,14 +16,17 @@ #include <gtest/gtest.h> #include <gui/SurfaceComposerClient.h> +#include <gui/WindowInfosUpdate.h> #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>&)>; @@ -36,46 +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 std::vector<WindowInfo>& windowInfos, - const std::vector<DisplayInfo>&) override { - if (mPredicate(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 |