diff options
33 files changed, 565 insertions, 305 deletions
diff --git a/TEST_MAPPING b/TEST_MAPPING index 4b64203387..260ee8dd4f 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -67,5 +67,66 @@ } ] } + ], + "hwasan-postsubmit": [ + { + "name": "SurfaceFlinger_test", + "options": [ + { + "include-filter": "*CredentialsTest.*" + }, + { + "include-filter": "*SurfaceFlingerStress.*" + }, + { + "include-filter": "*SurfaceInterceptorTest.*" + }, + { + "include-filter": "*LayerTransactionTest.*" + }, + { + "include-filter": "*LayerTypeTransactionTest.*" + }, + { + "include-filter": "*LayerUpdateTest.*" + }, + { + "include-filter": "*GeometryLatchingTest.*" + }, + { + "include-filter": "*CropLatchingTest.*" + }, + { + "include-filter": "*ChildLayerTest.*" + }, + { + "include-filter": "*ScreenCaptureTest.*" + }, + { + "include-filter": "*ScreenCaptureChildOnlyTest.*" + }, + { + "include-filter": "*DereferenceSurfaceControlTest.*" + }, + { + "include-filter": "*BoundlessLayerTest.*" + }, + { + "include-filter": "*MultiDisplayLayerBoundsTest.*" + }, + { + "include-filter": "*InvalidHandleTest.*" + }, + { + "include-filter": "*VirtualDisplayTest.*" + }, + { + "include-filter": "*RelativeZTest.*" + }, + { + "include-filter": "*RefreshRateOverlayTest.*" + } + ] + } ] } diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index 7bad351aa1..c104fea624 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -55,6 +55,7 @@ #include <cutils/fs.h> #include <cutils/properties.h> #include <cutils/sched_policy.h> +#include <linux/quota.h> #include <log/log.h> // TODO: Move everything to base/logging. #include <logwrap/logwrap.h> #include <private/android_filesystem_config.h> @@ -117,6 +118,12 @@ static constexpr const char* kMntFuse = "/mnt/pass_through/0/"; static std::atomic<bool> sAppDataIsolationEnabled(false); +/** + * Flag to control if project ids are supported for internal storage + */ +static std::atomic<bool> sUsingProjectIdsFlag(false); +static std::once_flag flag; + namespace { constexpr const char* kDump = "android.permission.DUMP"; @@ -457,15 +464,40 @@ done: free(after); return res; } +static bool internal_storage_has_project_id() { + // The following path is populated in setFirstBoot, so if this file is present + // then project ids can be used. Using call once to cache the result of this check + // to avoid having to check the file presence again and again. + std::call_once(flag, []() { + auto using_project_ids = + StringPrintf("%smisc/installd/using_project_ids", android_data_dir.c_str()); + sUsingProjectIdsFlag = access(using_project_ids.c_str(), F_OK) == 0; + }); + return sUsingProjectIdsFlag; +} -static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid, gid_t gid) { +static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid, gid_t gid, + long project_id) { if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, gid) != 0) { PLOG(ERROR) << "Failed to prepare " << path; return -1; } + if (internal_storage_has_project_id()) { + return set_quota_project_id(path, project_id, true); + } return 0; } +static int prepare_app_cache_dir(const std::string& parent, const char* name, mode_t target_mode, + uid_t uid, gid_t gid, long project_id) { + auto path = StringPrintf("%s/%s", parent.c_str(), name); + int ret = prepare_app_cache_dir(parent, name, target_mode, uid, gid); + if (ret == 0 && internal_storage_has_project_id()) { + return set_quota_project_id(path, project_id, true); + } + return ret; +} + static bool prepare_app_profile_dir(const std::string& packageName, int32_t appId, int32_t userId) { if (!property_get_bool("dalvik.vm.usejitprofiles", false)) { return true; @@ -625,9 +657,11 @@ static binder::Status createAppDataDirs(const std::string& path, int32_t uid, in } // Prepare only the parent app directory - if (prepare_app_dir(path, targetMode, uid, gid) || - prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) || - prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) { + long project_id_app = get_project_id(uid, PROJECT_ID_APP_START); + long project_id_cache_app = get_project_id(uid, PROJECT_ID_APP_CACHE_START); + if (prepare_app_dir(path, targetMode, uid, gid, project_id_app) || + prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid, project_id_cache_app) || + prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid, project_id_cache_app)) { return error("Failed to prepare " + path); } @@ -771,7 +805,7 @@ binder::Status InstalldNativeService::createSdkSandboxDataPackageDirectory( LOG(DEBUG) << "Creating app-level sdk data directory: " << packagePath; #endif - if (prepare_app_dir(packagePath, 0751, AID_SYSTEM, AID_SYSTEM)) { + if (prepare_app_dir(packagePath, 0751, AID_SYSTEM, AID_SYSTEM, 0)) { return error("Failed to prepare " + packagePath); } } @@ -2088,75 +2122,78 @@ static std::string toString(std::vector<int64_t> values) { } #endif +// On devices without sdcardfs, if internal and external are on +// the same volume, a uid such as u0_a123 is used for both +// internal and external storage; therefore, subtract that +// amount from internal to make sure we don't count it double. +// This needs to happen for data, cache and OBB +static void deductDoubleSpaceIfNeeded(stats* stats, int64_t doubleSpaceToBeDeleted, uid_t uid, + const std::string& uuid) { + if (!supports_sdcardfs()) { + stats->dataSize -= doubleSpaceToBeDeleted; + long obbProjectId = get_project_id(uid, PROJECT_ID_EXT_OBB_START); + int64_t appObbSize = GetOccupiedSpaceForProjectId(uuid, obbProjectId); + stats->dataSize -= appObbSize; + } +} + static void collectQuotaStats(const std::string& uuid, int32_t userId, int32_t appId, struct stats* stats, struct stats* extStats) { - int64_t space; + int64_t space, doubleSpaceToBeDeleted = 0; uid_t uid = multiuser_get_uid(userId, appId); - if (stats != nullptr) { - if ((space = GetOccupiedSpaceForUid(uuid, uid)) != -1) { - stats->dataSize += space; - } - - int sdkSandboxUid = multiuser_get_sdk_sandbox_uid(userId, appId); - if (sdkSandboxUid != -1) { - if ((space = GetOccupiedSpaceForUid(uuid, sdkSandboxUid)) != -1) { - stats->dataSize += space; - } - } - - int cacheGid = multiuser_get_cache_gid(userId, appId); - if (cacheGid != -1) { - if ((space = GetOccupiedSpaceForGid(uuid, cacheGid)) != -1) { - stats->cacheSize += space; - } - } - - int sharedGid = multiuser_get_shared_gid(0, appId); - if (sharedGid != -1) { - if ((space = GetOccupiedSpaceForGid(uuid, sharedGid)) != -1) { - stats->codeSize += space; - } - } - } + static const bool supportsProjectId = internal_storage_has_project_id(); if (extStats != nullptr) { - static const bool supportsSdCardFs = supports_sdcardfs(); space = get_occupied_app_space_external(uuid, userId, appId); if (space != -1) { extStats->dataSize += space; - if (!supportsSdCardFs && stats != nullptr) { - // On devices without sdcardfs, if internal and external are on - // the same volume, a uid such as u0_a123 is used for - // application dirs on both internal and external storage; - // therefore, substract that amount from internal to make sure - // we don't count it double. - stats->dataSize -= space; - } + doubleSpaceToBeDeleted += space; } space = get_occupied_app_cache_space_external(uuid, userId, appId); if (space != -1) { extStats->dataSize += space; // cache counts for "data" extStats->cacheSize += space; - if (!supportsSdCardFs && stats != nullptr) { - // On devices without sdcardfs, if internal and external are on - // the same volume, a uid such as u0_a123 is used for both - // internal and external storage; therefore, substract that - // amount from internal to make sure we don't count it double. - stats->dataSize -= space; + doubleSpaceToBeDeleted += space; + } + } + + if (stats != nullptr) { + if (!supportsProjectId) { + if ((space = GetOccupiedSpaceForUid(uuid, uid)) != -1) { + stats->dataSize += space; + } + deductDoubleSpaceIfNeeded(stats, doubleSpaceToBeDeleted, uid, uuid); + int sdkSandboxUid = multiuser_get_sdk_sandbox_uid(userId, appId); + if (sdkSandboxUid != -1) { + if ((space = GetOccupiedSpaceForUid(uuid, sdkSandboxUid)) != -1) { + stats->dataSize += space; + } + } + int cacheGid = multiuser_get_cache_gid(userId, appId); + if (cacheGid != -1) { + if ((space = GetOccupiedSpaceForGid(uuid, cacheGid)) != -1) { + stats->cacheSize += space; + } + } + } else { + long projectId = get_project_id(uid, PROJECT_ID_APP_START); + if ((space = GetOccupiedSpaceForProjectId(uuid, projectId)) != -1) { + stats->dataSize += space; + } + projectId = get_project_id(uid, PROJECT_ID_APP_CACHE_START); + if ((space = GetOccupiedSpaceForProjectId(uuid, projectId)) != -1) { + stats->cacheSize += space; + stats->dataSize += space; } } - if (!supportsSdCardFs && stats != nullptr) { - // On devices without sdcardfs, the UID of OBBs on external storage - // matches the regular app UID (eg u0_a123); therefore, to avoid - // OBBs being include in stats->dataSize, compute the OBB size for - // this app, and substract it from the size reported on internal - // storage - long obbProjectId = uid - AID_APP_START + PROJECT_ID_EXT_OBB_START; - int64_t appObbSize = GetOccupiedSpaceForProjectId(uuid, obbProjectId); - stats->dataSize -= appObbSize; + int sharedGid = multiuser_get_shared_gid(0, appId); + if (sharedGid != -1) { + if ((space = GetOccupiedSpaceForGid(uuid, sharedGid)) != -1) { + stats->codeSize += space; + } } } } @@ -2293,6 +2330,12 @@ static void collectManualExternalStatsForUser(const std::string& path, struct st fts_close(fts); } static bool ownsExternalStorage(int32_t appId) { + // if project id calculation is supported then, there is no need to + // calculate in a different way and project_id based calculation can work + if (internal_storage_has_project_id()) { + return false; + } + // Fetch external storage owner appid and check if it is the same as the // current appId whose size is calculated struct stat s; @@ -3356,6 +3399,38 @@ binder::Status InstalldNativeService::hashSecondaryDexFile( dexPath, packageName, uid, volumeUuid, storageFlag, _aidl_return); return result ? ok() : error(); } +/** + * Returns true if ioctl feature (F2FS_IOC_FS{GET,SET}XATTR) is supported as + * these were introduced in Linux 4.14, so kernel versions before that will fail + * while setting project id attributes. Only when these features are enabled, + * storage calculation using project_id is enabled + */ +bool check_if_ioctl_feature_is_supported() { + bool result = false; + auto temp_path = StringPrintf("%smisc/installd/ioctl_check", android_data_dir.c_str()); + if (access(temp_path.c_str(), F_OK) != 0) { + int fd = open(temp_path.c_str(), O_CREAT | O_TRUNC | O_RDWR | O_CLOEXEC, 0644); + result = set_quota_project_id(temp_path, 0, true) == 0; + close(fd); + // delete the temp file + remove(temp_path.c_str()); + } + return result; +} + +binder::Status InstalldNativeService::setFirstBoot() { + ENFORCE_UID(AID_SYSTEM); + std::lock_guard<std::recursive_mutex> lock(mMountsLock); + std::string uuid; + if (GetOccupiedSpaceForProjectId(uuid, 0) != -1 && check_if_ioctl_feature_is_supported()) { + auto first_boot_path = + StringPrintf("%smisc/installd/using_project_ids", android_data_dir.c_str()); + if (access(first_boot_path.c_str(), F_OK) != 0) { + close(open(first_boot_path.c_str(), O_CREAT | O_TRUNC | O_RDWR | O_CLOEXEC, 0644)); + } + } + return ok(); +} binder::Status InstalldNativeService::invalidateMounts() { ENFORCE_UID(AID_SYSTEM); diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h index e6be5d89ad..87a920676d 100644 --- a/cmds/installd/InstalldNativeService.h +++ b/cmds/installd/InstalldNativeService.h @@ -168,6 +168,7 @@ public: int32_t storageFlag, std::vector<uint8_t>* _aidl_return); binder::Status invalidateMounts(); + binder::Status setFirstBoot(); binder::Status isQuotaSupported(const std::optional<std::string>& volumeUuid, bool* _aidl_return); binder::Status tryMountDataMirror(const std::optional<std::string>& volumeUuid); diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl index 2b5a35e191..79c02e8454 100644 --- a/cmds/installd/binder/android/os/IInstalld.aidl +++ b/cmds/installd/binder/android/os/IInstalld.aidl @@ -20,7 +20,7 @@ package android.os; interface IInstalld { void createUserData(@nullable @utf8InCpp String uuid, int userId, int userSerial, int flags); void destroyUserData(@nullable @utf8InCpp String uuid, int userId, int flags); - + void setFirstBoot(); android.os.CreateAppDataResult createAppData(in android.os.CreateAppDataArgs args); android.os.CreateAppDataResult[] createAppDataBatched(in android.os.CreateAppDataArgs[] args); diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp index 123e3d4181..9801a9b3a4 100644 --- a/cmds/installd/utils.cpp +++ b/cmds/installd/utils.cpp @@ -37,6 +37,7 @@ #include <android-base/unique_fd.h> #include <cutils/fs.h> #include <cutils/properties.h> +#include <linux/fs.h> #include <log/log.h> #include <private/android_filesystem_config.h> #include <private/android_projectid_config.h> @@ -424,6 +425,45 @@ std::vector<userid_t> get_known_users(const char* volume_uuid) { return users; } +long get_project_id(uid_t uid, long start_project_id_range) { + return uid - AID_APP_START + start_project_id_range; +} + +int set_quota_project_id(const std::string& path, long project_id, bool set_inherit) { + struct fsxattr fsx; + android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC))); + if (fd == -1) { + PLOG(ERROR) << "Failed to open " << path << " to set project id."; + return -1; + } + + if (ioctl(fd, FS_IOC_FSGETXATTR, &fsx) == -1) { + PLOG(ERROR) << "Failed to get extended attributes for " << path << " to get project id."; + return -1; + } + + fsx.fsx_projid = project_id; + if (ioctl(fd, FS_IOC_FSSETXATTR, &fsx) == -1) { + PLOG(ERROR) << "Failed to set project id on " << path; + return -1; + } + if (set_inherit) { + unsigned int flags; + if (ioctl(fd, FS_IOC_GETFLAGS, &flags) == -1) { + PLOG(ERROR) << "Failed to get flags for " << path << " to set project id inheritance."; + return -1; + } + + flags |= FS_PROJINHERIT_FL; + + if (ioctl(fd, FS_IOC_SETFLAGS, &flags) == -1) { + PLOG(ERROR) << "Failed to set flags for " << path << " to set project id inheritance."; + return -1; + } + } + return 0; +} + int calculate_tree_size(const std::string& path, int64_t* size, int32_t include_gid, int32_t exclude_gid, bool exclude_apps) { FTS *fts; diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h index cb3099337c..ecea1d2b1c 100644 --- a/cmds/installd/utils.h +++ b/cmds/installd/utils.h @@ -171,6 +171,8 @@ int prepare_app_cache_dir(const std::string& parent, const char* name, mode_t ta uid_t uid, gid_t gid); bool supports_sdcardfs(); +long get_project_id(uid_t uid, long start_project_id_range); +int set_quota_project_id(const std::string& path, long project_id, bool set_inherit); int64_t get_occupied_app_space_external(const std::string& uuid, int32_t userId, int32_t appId); int64_t get_occupied_app_cache_space_external(const std::string& uuid, int32_t userId, int32_t appId); diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp index 555be1ed7e..3cfe5297ca 100644 --- a/cmds/servicemanager/ServiceManager.cpp +++ b/cmds/servicemanager/ServiceManager.cpp @@ -295,28 +295,27 @@ bool isValidServiceName(const std::string& name) { Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) { auto ctx = mAccess->getCallingContext(); - // apps cannot add services if (multiuser_get_app_id(ctx.uid) >= AID_APP) { - return Status::fromExceptionCode(Status::EX_SECURITY); + return Status::fromExceptionCode(Status::EX_SECURITY, "App UIDs cannot add services"); } if (!mAccess->canAdd(ctx, name)) { - return Status::fromExceptionCode(Status::EX_SECURITY); + return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denial"); } if (binder == nullptr) { - return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT); + return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Null binder"); } if (!isValidServiceName(name)) { LOG(ERROR) << "Invalid service name: " << name; - return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT); + return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Invalid service name"); } #ifndef VENDORSERVICEMANAGER if (!meetsDeclarationRequirements(binder, name)) { // already logged - return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT); + return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "VINTF declaration error"); } #endif // !VENDORSERVICEMANAGER @@ -324,7 +323,7 @@ Status ServiceManager::addService(const std::string& name, const sp<IBinder>& bi if (binder->remoteBinder() != nullptr && binder->linkToDeath(sp<ServiceManager>::fromExisting(this)) != OK) { LOG(ERROR) << "Could not linkToDeath when adding " << name; - return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE); + return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "linkToDeath failure"); } // Overwrite the old service if it exists diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp index 39d380d9e1..dfdce20438 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -197,4 +197,9 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, return gotVsync; } +status_t DisplayEventDispatcher::getLatestVsyncEventData( + ParcelableVsyncEventData* outVsyncEventData) const { + return mReceiver.getLatestVsyncEventData(outVsyncEventData); +} + } // namespace android diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index 063dda5153..654fb336fe 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -70,6 +70,7 @@ SurfaceControl::SurfaceControl(const sp<SurfaceControl>& other) { mLayerId = other->mLayerId; mWidth = other->mWidth; mHeight = other->mHeight; + mFormat = other->mFormat; mCreateFlags = other->mCreateFlags; } diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h index 71968fa59f..a3425395bf 100644 --- a/libs/gui/include/gui/DisplayEventDispatcher.h +++ b/libs/gui/include/gui/DisplayEventDispatcher.h @@ -34,6 +34,7 @@ public: void injectEvent(const DisplayEventReceiver::Event& event); int getFd() const; virtual int handleEvent(int receiveFd, int events, void* data); + status_t getLatestVsyncEventData(ParcelableVsyncEventData* outVsyncEventData) const; protected: virtual ~DisplayEventDispatcher() = default; diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index 1690e44ecc..b72cf8390e 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -121,12 +121,12 @@ private: mutable sp<Surface> mSurfaceData; mutable sp<BLASTBufferQueue> mBbq; mutable sp<SurfaceControl> mBbqChild; - int32_t mLayerId; - uint32_t mTransformHint; - uint32_t mWidth; - uint32_t mHeight; - PixelFormat mFormat; - uint32_t mCreateFlags; + int32_t mLayerId = 0; + uint32_t mTransformHint = 0; + uint32_t mWidth = 0; + uint32_t mHeight = 0; + PixelFormat mFormat = PIXEL_FORMAT_NONE; + uint32_t mCreateFlags = 0; uint64_t mFallbackFrameNumber = 100; }; diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index fcfe21bee2..262987fd27 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -76,16 +76,30 @@ static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s; class InputSurface { public: - InputSurface(const sp<SurfaceControl> &sc, int width, int height) { + InputSurface(const sp<SurfaceControl> &sc, int width, int height, bool noInputChannel = false) { mSurfaceControl = sc; mInputFlinger = getInputFlinger(); - mClientChannel = std::make_shared<InputChannel>(); - mInputFlinger->createInputChannel("testchannels", mClientChannel.get()); + if (noInputChannel) { + mInputInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, true); + } else { + mClientChannel = std::make_shared<InputChannel>(); + mInputFlinger->createInputChannel("testchannels", mClientChannel.get()); + mInputInfo.token = mClientChannel->getConnectionToken(); + mInputConsumer = new InputConsumer(mClientChannel); + } - populateInputInfo(width, height); + mInputInfo.name = "Test info"; + mInputInfo.dispatchingTimeout = 5s; + mInputInfo.globalScaleFactor = 1.0; + mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height)); - mInputConsumer = new InputConsumer(mClientChannel); + InputApplicationInfo aInfo; + aInfo.token = new BBinder(); + aInfo.name = "Test app info"; + aInfo.dispatchingTimeoutMillis = + std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count(); + mInputInfo.applicationInfo = aInfo; } static std::unique_ptr<InputSurface> makeColorInputSurface(const sp<SurfaceComposerClient> &scc, @@ -114,6 +128,16 @@ public: return std::make_unique<InputSurface>(surfaceControl, width, height); } + static std::unique_ptr<InputSurface> makeContainerInputSurfaceNoInputChannel( + const sp<SurfaceComposerClient> &scc, int width, int height) { + sp<SurfaceControl> surfaceControl = + scc->createSurface(String8("Test Container Surface"), 100 /* height */, + 100 /* width */, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceContainer); + return std::make_unique<InputSurface>(surfaceControl, width, height, + true /* noInputChannel */); + } + static std::unique_ptr<InputSurface> makeCursorInputSurface( const sp<SurfaceComposerClient> &scc, int width, int height) { sp<SurfaceControl> surfaceControl = @@ -219,7 +243,9 @@ public: } virtual ~InputSurface() { - mInputFlinger->removeInputChannel(mClientChannel->getConnectionToken()); + if (mClientChannel) { + mInputFlinger->removeInputChannel(mClientChannel->getConnectionToken()); + } } virtual void doTransaction( @@ -263,21 +289,6 @@ private: poll(&fd, 1, timeoutMs); } - void populateInputInfo(int width, int height) { - mInputInfo.token = mClientChannel->getConnectionToken(); - mInputInfo.name = "Test info"; - mInputInfo.dispatchingTimeout = 5s; - mInputInfo.globalScaleFactor = 1.0; - mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height)); - - InputApplicationInfo aInfo; - aInfo.token = new BBinder(); - aInfo.name = "Test app info"; - aInfo.dispatchingTimeoutMillis = - std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count(); - - mInputInfo.applicationInfo = aInfo; - } public: sp<SurfaceControl> mSurfaceControl; std::shared_ptr<InputChannel> mClientChannel; @@ -984,21 +995,6 @@ TEST_F(InputSurfacesTest, drop_input_policy) { EXPECT_EQ(surface->consumeEvent(100), nullptr); } -TEST_F(InputSurfacesTest, layer_with_empty_crop_cannot_be_focused) { - std::unique_ptr<InputSurface> bufferSurface = - InputSurface::makeBufferInputSurface(mComposerClient, 100, 100); - - bufferSurface->showAt(50, 50, Rect::EMPTY_RECT); - - bufferSurface->requestFocus(); - EXPECT_EQ(bufferSurface->consumeEvent(100), nullptr); - - bufferSurface->showAt(50, 50, Rect::INVALID_RECT); - - bufferSurface->requestFocus(); - EXPECT_EQ(bufferSurface->consumeEvent(100), nullptr); -} - TEST_F(InputSurfacesTest, layer_with_valid_crop_can_be_focused) { std::unique_ptr<InputSurface> bufferSurface = InputSurface::makeBufferInputSurface(mComposerClient, 100, 100); @@ -1085,6 +1081,23 @@ TEST_F(InputSurfacesTest, replace_touchable_region_with_crop) { EXPECT_EQ(containerSurface->consumeEvent(100), nullptr); } +TEST_F(InputSurfacesTest, child_container_with_no_input_channel_blocks_parent) { + std::unique_ptr<InputSurface> parent = makeSurface(100, 100); + + parent->showAt(100, 100); + injectTap(101, 101); + parent->expectTap(1, 1); + + std::unique_ptr<InputSurface> childContainerSurface = + InputSurface::makeContainerInputSurfaceNoInputChannel(mComposerClient, 100, 100); + childContainerSurface->showAt(0, 0); + childContainerSurface->doTransaction( + [&](auto &t, auto &sc) { t.reparent(sc, parent->mSurfaceControl); }); + injectTap(101, 101); + + EXPECT_EQ(parent->consumeEvent(100), nullptr); +} + class MultiDisplayTests : public InputSurfacesTest { public: MultiDisplayTests() : InputSurfacesTest() { ProcessState::self()->startThreadPool(); } diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index 5e5618b9aa..1665550696 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -872,18 +872,21 @@ void SkiaGLRenderEngine::drawLayersInternal( // save a snapshot of the activeSurface to use as input to the blur shaders blurInput = activeSurface->makeImageSnapshot(); - // TODO we could skip this step if we know the blur will cover the entire image - // blit the offscreen framebuffer into the destination AHB - SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrc); - if (CC_UNLIKELY(mCapture->isCaptureRunning())) { - uint64_t id = mCapture->endOffscreenCapture(&offscreenCaptureState); - dstCanvas->drawAnnotation(SkRect::Make(dstCanvas->imageInfo().dimensions()), - String8::format("SurfaceID|%" PRId64, id).c_str(), - nullptr); - dstCanvas->drawImage(blurInput, 0, 0, SkSamplingOptions(), &paint); - } else { - activeSurface->draw(dstCanvas, 0, 0, SkSamplingOptions(), &paint); + // blit the offscreen framebuffer into the destination AHB, but only + // if there are blur regions. backgroundBlurRadius blurs the entire + // image below, so it can skip this step. + if (layer.blurRegions.size()) { + SkPaint paint; + paint.setBlendMode(SkBlendMode::kSrc); + if (CC_UNLIKELY(mCapture->isCaptureRunning())) { + uint64_t id = mCapture->endOffscreenCapture(&offscreenCaptureState); + dstCanvas->drawAnnotation(SkRect::Make(dstCanvas->imageInfo().dimensions()), + String8::format("SurfaceID|%" PRId64, id).c_str(), + nullptr); + dstCanvas->drawImage(blurInput, 0, 0, SkSamplingOptions(), &paint); + } else { + activeSurface->draw(dstCanvas, 0, 0, SkSamplingOptions(), &paint); + } } // assign dstCanvas to canvas and ensure that the canvas state is up to date diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 6bfac6cb5f..c8a3ccf999 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -556,6 +556,17 @@ bool isPointerFromStylus(const MotionEntry& entry, int32_t pointerIndex) { entry.pointerProperties[pointerIndex].toolType == AMOTION_EVENT_TOOL_TYPE_ERASER); } +// Determines if the given window can be targeted as InputTarget::FLAG_FOREGROUND. +// Foreground events are only sent to "foreground targetable" windows, but not all gestures sent to +// such window are necessarily targeted with the flag. For example, an event with ACTION_OUTSIDE can +// be sent to such a window, but it is not a foreground event and doesn't use +// InputTarget::FLAG_FOREGROUND. +bool canReceiveForegroundTouches(const WindowInfo& info) { + // A non-touchable window can still receive touch events (e.g. in the case of + // STYLUS_INTERCEPTOR), so prevent such windows from receiving foreground events for touches. + return !info.inputConfig.test(gui::WindowInfo::InputConfig::NOT_TOUCHABLE) && !info.isSpy(); +} + } // namespace // --- InputDispatcher --- @@ -2203,8 +2214,8 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( // Set target flags. int32_t targetFlags = InputTarget::FLAG_DISPATCH_AS_IS; - if (!info.isSpy()) { - // There should only be one new foreground (non-spy) window at this location. + if (canReceiveForegroundTouches(*windowHandle->getInfo())) { + // There should only be one touched window that can be "foreground" for the pointer. targetFlags |= InputTarget::FLAG_FOREGROUND; } @@ -2277,8 +2288,10 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( isSplit = !isFromMouse; } - int32_t targetFlags = - InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER; + int32_t targetFlags = InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER; + if (canReceiveForegroundTouches(*newTouchedWindowHandle->getInfo())) { + targetFlags |= InputTarget::FLAG_FOREGROUND; + } if (isSplit) { targetFlags |= InputTarget::FLAG_SPLIT; } @@ -2327,13 +2340,15 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( } } - // Ensure that we have at least one foreground or spy window. It's possible that we dropped some - // of the touched windows we previously found if they became paused or unresponsive or were - // removed. + // Ensure that we have at least one foreground window or at least one window that cannot be a + // foreground target. If we only have windows that are not receiving foreground touches (e.g. we + // only have windows getting ACTION_OUTSIDE), then drop the event, because there is no window + // that is actually receiving the entire gesture. if (std::none_of(tempTouchState.windows.begin(), tempTouchState.windows.end(), [](const TouchedWindow& touchedWindow) { - return (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) != 0 || - touchedWindow.windowHandle->getInfo()->isSpy(); + return !canReceiveForegroundTouches( + *touchedWindow.windowHandle->getInfo()) || + (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) != 0; })) { ALOGI("Dropping event because there is no touched window on display %d to receive it.", displayId); @@ -5072,9 +5087,11 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp< state->removeWindowByToken(fromToken); // Add new window. - int32_t newTargetFlags = oldTargetFlags & - (InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_SPLIT | - InputTarget::FLAG_DISPATCH_AS_IS); + int32_t newTargetFlags = + oldTargetFlags & (InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS); + if (canReceiveForegroundTouches(*toWindowHandle->getInfo())) { + newTargetFlags |= InputTarget::FLAG_FOREGROUND; + } state->addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds); // Store the dragging window. diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 838e6aa785..bf587050c6 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -6915,4 +6915,38 @@ TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) { window->assertNoEvents(); } +/** + * Set up a scenario to test the behavior used by the stylus handwriting detection feature. + * The scenario is as follows: + * - The stylus interceptor overlay is configured as a spy window. + * - The stylus interceptor spy receives the start of a new stylus gesture. + * - It pilfers pointers and then configures itself to no longer be a spy. + * - The stylus interceptor continues to receive the rest of the gesture. + */ +TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) { + auto [overlay, window] = setupStylusOverlayScenario(); + overlay->setSpy(true); + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}); + + sendStylusEvent(AMOTION_EVENT_ACTION_DOWN); + overlay->consumeMotionDown(); + window->consumeMotionDown(); + + // The interceptor pilfers the pointers. + EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken())); + window->consumeMotionCancel(); + + // The interceptor configures itself so that it is no longer a spy. + overlay->setSpy(false); + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}); + + // It continues to receive the rest of the stylus gesture. + sendStylusEvent(AMOTION_EVENT_ACTION_MOVE); + overlay->consumeMotionMove(); + sendStylusEvent(AMOTION_EVENT_ACTION_UP); + overlay->consumeMotionUp(); + + window->assertNoEvents(); +} + } // namespace android::inputdispatcher diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index cd0323555c..5cc0f9734b 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -165,7 +165,6 @@ struct DisplayTestCommon : public testing::Test { EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine)); EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false)); - EXPECT_CALL(mHwComposer, getBootDisplayModeSupport()).WillRepeatedly(Return(false)); } DisplayCreationArgs getDisplayCreationArgsForPhysicalDisplay() { diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 66a9ef7179..dd3858b4d0 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -1310,7 +1310,8 @@ struct OutputEnsureOutputLayerIfVisibleTest : public testing::Test { static const Region kLowerHalfBoundsNoRotation; static const Region kFullBounds90Rotation; static const Region kTransparentRegionHint; - static const Region kTransparentRegionHint90Rotation; + static const Region kTransparentRegionHintTwo; + static const Region kTransparentRegionHintTwo90Rotation; StrictMock<OutputPartialMock> mOutput; LayerFESet mGeomSnapshots; @@ -1329,8 +1330,10 @@ const Region OutputEnsureOutputLayerIfVisibleTest::kLowerHalfBoundsNoRotation = const Region OutputEnsureOutputLayerIfVisibleTest::kFullBounds90Rotation = Region(Rect(0, 0, 200, 100)); const Region OutputEnsureOutputLayerIfVisibleTest::kTransparentRegionHint = + Region(Rect(0, 0, 100, 100)); +const Region OutputEnsureOutputLayerIfVisibleTest::kTransparentRegionHintTwo = Region(Rect(25, 20, 50, 75)); -const Region OutputEnsureOutputLayerIfVisibleTest::kTransparentRegionHint90Rotation = +const Region OutputEnsureOutputLayerIfVisibleTest::kTransparentRegionHintTwo90Rotation = Region(Rect(125, 25, 180, 50)); TEST_F(OutputEnsureOutputLayerIfVisibleTest, performsGeomLatchBeforeCheckingIfLayerIncluded) { @@ -1787,6 +1790,7 @@ TEST_F(OutputEnsureOutputLayerIfVisibleTest, blockingRegionIsInOutputSpace) { mLayer.layerFEState.contentDirty = true; mLayer.layerFEState.compositionType = aidl::android::hardware::graphics::composer3::Composition::DISPLAY_DECORATION; + mLayer.layerFEState.transparentRegionHint = kTransparentRegionHintTwo; mOutput.mState.layerStackSpace.setContent(Rect(0, 0, 300, 200)); mOutput.mState.transform = ui::Transform(TR_ROT_90, 200, 300); @@ -1797,7 +1801,7 @@ TEST_F(OutputEnsureOutputLayerIfVisibleTest, blockingRegionIsInOutputSpace) { ensureOutputLayerIfVisible(); EXPECT_THAT(mLayer.outputLayerState.outputSpaceBlockingRegionHint, - RegionEq(kTransparentRegionHint90Rotation)); + RegionEq(kTransparentRegionHintTwo90Rotation)); } /* diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp index 8b376f11ec..297a776753 100644 --- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp @@ -247,7 +247,6 @@ bool AidlComposer::isSupported(OptionalFeature feature) const { case OptionalFeature::RefreshRateSwitching: case OptionalFeature::ExpectedPresentTime: case OptionalFeature::DisplayBrightnessCommand: - case OptionalFeature::BootDisplayConfig: case OptionalFeature::KernelIdleTimer: case OptionalFeature::PhysicalDisplayOrientation: return true; diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index 7d9946d23a..2dc0830209 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -94,7 +94,6 @@ public: ExpectedPresentTime, // Whether setDisplayBrightness is able to be applied as part of a display command. DisplayBrightnessCommand, - BootDisplayConfig, KernelIdleTimer, PhysicalDisplayOrientation, }; diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index d78562d3a4..a8055663f0 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -94,82 +94,78 @@ public: virtual bool hasDisplayIdleTimerCapability() const = 0; virtual void onLayerDestroyed(hal::HWLayerId layerId) = 0; - [[clang::warn_unused_result]] virtual hal::Error acceptChanges() = 0; - [[clang::warn_unused_result]] virtual base::expected<std::shared_ptr<HWC2::Layer>, hal::Error> + [[nodiscard]] virtual hal::Error acceptChanges() = 0; + [[nodiscard]] virtual base::expected<std::shared_ptr<HWC2::Layer>, hal::Error> createLayer() = 0; - [[clang::warn_unused_result]] virtual hal::Error getChangedCompositionTypes( + [[nodiscard]] virtual hal::Error getChangedCompositionTypes( std::unordered_map<Layer*, aidl::android::hardware::graphics::composer3::Composition>* outTypes) = 0; - [[clang::warn_unused_result]] virtual hal::Error getColorModes( - std::vector<hal::ColorMode>* outModes) const = 0; + [[nodiscard]] virtual hal::Error getColorModes(std::vector<hal::ColorMode>* outModes) const = 0; // Returns a bitmask which contains HdrMetadata::Type::*. - [[clang::warn_unused_result]] virtual int32_t getSupportedPerFrameMetadata() const = 0; - [[clang::warn_unused_result]] virtual hal::Error getRenderIntents( + [[nodiscard]] virtual int32_t getSupportedPerFrameMetadata() const = 0; + [[nodiscard]] virtual hal::Error getRenderIntents( hal::ColorMode colorMode, std::vector<hal::RenderIntent>* outRenderIntents) const = 0; - [[clang::warn_unused_result]] virtual hal::Error getDataspaceSaturationMatrix( - hal::Dataspace dataspace, android::mat4* outMatrix) = 0; + [[nodiscard]] virtual hal::Error getDataspaceSaturationMatrix(hal::Dataspace dataspace, + android::mat4* outMatrix) = 0; - [[clang::warn_unused_result]] virtual hal::Error getName(std::string* outName) const = 0; - [[clang::warn_unused_result]] virtual hal::Error getRequests( + [[nodiscard]] virtual hal::Error getName(std::string* outName) const = 0; + [[nodiscard]] virtual hal::Error getRequests( hal::DisplayRequest* outDisplayRequests, std::unordered_map<Layer*, hal::LayerRequest>* outLayerRequests) = 0; - [[clang::warn_unused_result]] virtual hal::Error getConnectionType( - ui::DisplayConnectionType*) const = 0; - [[clang::warn_unused_result]] virtual hal::Error supportsDoze(bool* outSupport) const = 0; - [[clang::warn_unused_result]] virtual hal::Error getHdrCapabilities( + [[nodiscard]] virtual hal::Error getConnectionType(ui::DisplayConnectionType*) const = 0; + [[nodiscard]] virtual hal::Error supportsDoze(bool* outSupport) const = 0; + [[nodiscard]] virtual hal::Error getHdrCapabilities( android::HdrCapabilities* outCapabilities) const = 0; - [[clang::warn_unused_result]] virtual hal::Error getDisplayedContentSamplingAttributes( + [[nodiscard]] virtual hal::Error getDisplayedContentSamplingAttributes( hal::PixelFormat* outFormat, hal::Dataspace* outDataspace, uint8_t* outComponentMask) const = 0; - [[clang::warn_unused_result]] virtual hal::Error setDisplayContentSamplingEnabled( - bool enabled, uint8_t componentMask, uint64_t maxFrames) const = 0; - [[clang::warn_unused_result]] virtual hal::Error getDisplayedContentSample( + [[nodiscard]] virtual hal::Error setDisplayContentSamplingEnabled(bool enabled, + uint8_t componentMask, + uint64_t maxFrames) const = 0; + [[nodiscard]] virtual hal::Error getDisplayedContentSample( uint64_t maxFrames, uint64_t timestamp, android::DisplayedFrameStats* outStats) const = 0; - [[clang::warn_unused_result]] virtual hal::Error getReleaseFences( + [[nodiscard]] virtual hal::Error getReleaseFences( std::unordered_map<Layer*, android::sp<android::Fence>>* outFences) const = 0; - [[clang::warn_unused_result]] virtual hal::Error present( - android::sp<android::Fence>* outPresentFence) = 0; - [[clang::warn_unused_result]] virtual hal::Error setClientTarget( + [[nodiscard]] virtual hal::Error present(android::sp<android::Fence>* outPresentFence) = 0; + [[nodiscard]] virtual hal::Error setClientTarget( uint32_t slot, const android::sp<android::GraphicBuffer>& target, const android::sp<android::Fence>& acquireFence, hal::Dataspace dataspace) = 0; - [[clang::warn_unused_result]] virtual hal::Error setColorMode( - hal::ColorMode mode, hal::RenderIntent renderIntent) = 0; - [[clang::warn_unused_result]] virtual hal::Error setColorTransform( - const android::mat4& matrix) = 0; - [[clang::warn_unused_result]] virtual hal::Error setOutputBuffer( + [[nodiscard]] virtual hal::Error setColorMode(hal::ColorMode mode, + hal::RenderIntent renderIntent) = 0; + [[nodiscard]] virtual hal::Error setColorTransform(const android::mat4& matrix) = 0; + [[nodiscard]] virtual hal::Error setOutputBuffer( const android::sp<android::GraphicBuffer>& buffer, const android::sp<android::Fence>& releaseFence) = 0; - [[clang::warn_unused_result]] virtual hal::Error setPowerMode(hal::PowerMode mode) = 0; - [[clang::warn_unused_result]] virtual hal::Error setVsyncEnabled(hal::Vsync enabled) = 0; - [[clang::warn_unused_result]] virtual hal::Error validate(nsecs_t expectedPresentTime, - uint32_t* outNumTypes, - uint32_t* outNumRequests) = 0; - [[clang::warn_unused_result]] virtual hal::Error presentOrValidate( - nsecs_t expectedPresentTime, uint32_t* outNumTypes, uint32_t* outNumRequests, - android::sp<android::Fence>* outPresentFence, uint32_t* state) = 0; - [[clang::warn_unused_result]] virtual std::future<hal::Error> setDisplayBrightness( + [[nodiscard]] virtual hal::Error setPowerMode(hal::PowerMode mode) = 0; + [[nodiscard]] virtual hal::Error setVsyncEnabled(hal::Vsync enabled) = 0; + [[nodiscard]] virtual hal::Error validate(nsecs_t expectedPresentTime, uint32_t* outNumTypes, + uint32_t* outNumRequests) = 0; + [[nodiscard]] virtual hal::Error presentOrValidate(nsecs_t expectedPresentTime, + uint32_t* outNumTypes, + uint32_t* outNumRequests, + android::sp<android::Fence>* outPresentFence, + uint32_t* state) = 0; + [[nodiscard]] virtual std::future<hal::Error> setDisplayBrightness( float brightness, const Hwc2::Composer::DisplayBrightnessOptions& options) = 0; - [[clang::warn_unused_result]] virtual hal::Error setActiveConfigWithConstraints( + [[nodiscard]] virtual hal::Error setActiveConfigWithConstraints( hal::HWConfigId configId, const hal::VsyncPeriodChangeConstraints& constraints, hal::VsyncPeriodChangeTimeline* outTimeline) = 0; - [[clang::warn_unused_result]] virtual hal::Error setBootDisplayConfig( - hal::HWConfigId configId) = 0; - [[clang::warn_unused_result]] virtual hal::Error clearBootDisplayConfig() = 0; - [[clang::warn_unused_result]] virtual hal::Error getPreferredBootDisplayConfig( + [[nodiscard]] virtual hal::Error setBootDisplayConfig(hal::HWConfigId configId) = 0; + [[nodiscard]] virtual hal::Error clearBootDisplayConfig() = 0; + [[nodiscard]] virtual hal::Error getPreferredBootDisplayConfig( hal::HWConfigId* configId) const = 0; - [[clang::warn_unused_result]] virtual hal::Error setAutoLowLatencyMode(bool on) = 0; - [[clang::warn_unused_result]] virtual hal::Error getSupportedContentTypes( + [[nodiscard]] virtual hal::Error setAutoLowLatencyMode(bool on) = 0; + [[nodiscard]] virtual hal::Error getSupportedContentTypes( std::vector<hal::ContentType>*) const = 0; - [[clang::warn_unused_result]] virtual hal::Error setContentType(hal::ContentType) = 0; - [[clang::warn_unused_result]] virtual hal::Error getClientTargetProperty( + [[nodiscard]] virtual hal::Error setContentType(hal::ContentType) = 0; + [[nodiscard]] virtual hal::Error getClientTargetProperty( hal::ClientTargetProperty* outClientTargetProperty, float* outWhitePointNits) = 0; - [[clang::warn_unused_result]] virtual hal::Error getDisplayDecorationSupport( + [[nodiscard]] virtual hal::Error getDisplayDecorationSupport( std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>* support) = 0; - [[clang::warn_unused_result]] virtual hal::Error setIdleTimerEnabled( - std::chrono::milliseconds timeout) = 0; - [[clang::warn_unused_result]] virtual hal::Error getPhysicalDisplayOrientation( + [[nodiscard]] virtual hal::Error setIdleTimerEnabled(std::chrono::milliseconds timeout) = 0; + [[nodiscard]] virtual hal::Error getPhysicalDisplayOrientation( Hwc2::AidlTransform* outTransform) const = 0; }; @@ -299,45 +295,39 @@ public: virtual hal::HWLayerId getId() const = 0; - [[clang::warn_unused_result]] virtual hal::Error setCursorPosition(int32_t x, int32_t y) = 0; - [[clang::warn_unused_result]] virtual hal::Error setBuffer( - uint32_t slot, const android::sp<android::GraphicBuffer>& buffer, - const android::sp<android::Fence>& acquireFence) = 0; - [[clang::warn_unused_result]] virtual hal::Error setSurfaceDamage( - const android::Region& damage) = 0; + [[nodiscard]] virtual hal::Error setCursorPosition(int32_t x, int32_t y) = 0; + [[nodiscard]] virtual hal::Error setBuffer(uint32_t slot, + const android::sp<android::GraphicBuffer>& buffer, + const android::sp<android::Fence>& acquireFence) = 0; + [[nodiscard]] virtual hal::Error setSurfaceDamage(const android::Region& damage) = 0; - [[clang::warn_unused_result]] virtual hal::Error setBlendMode(hal::BlendMode mode) = 0; - [[clang::warn_unused_result]] virtual hal::Error setColor( + [[nodiscard]] virtual hal::Error setBlendMode(hal::BlendMode mode) = 0; + [[nodiscard]] virtual hal::Error setColor( aidl::android::hardware::graphics::composer3::Color color) = 0; - [[clang::warn_unused_result]] virtual hal::Error setCompositionType( + [[nodiscard]] virtual hal::Error setCompositionType( aidl::android::hardware::graphics::composer3::Composition type) = 0; - [[clang::warn_unused_result]] virtual hal::Error setDataspace(hal::Dataspace dataspace) = 0; - [[clang::warn_unused_result]] virtual hal::Error setPerFrameMetadata( - const int32_t supportedPerFrameMetadata, const android::HdrMetadata& metadata) = 0; - [[clang::warn_unused_result]] virtual hal::Error setDisplayFrame( - const android::Rect& frame) = 0; - [[clang::warn_unused_result]] virtual hal::Error setPlaneAlpha(float alpha) = 0; - [[clang::warn_unused_result]] virtual hal::Error setSidebandStream( - const native_handle_t* stream) = 0; - [[clang::warn_unused_result]] virtual hal::Error setSourceCrop( - const android::FloatRect& crop) = 0; - [[clang::warn_unused_result]] virtual hal::Error setTransform(hal::Transform transform) = 0; - [[clang::warn_unused_result]] virtual hal::Error setVisibleRegion( - const android::Region& region) = 0; - [[clang::warn_unused_result]] virtual hal::Error setZOrder(uint32_t z) = 0; + [[nodiscard]] virtual hal::Error setDataspace(hal::Dataspace dataspace) = 0; + [[nodiscard]] virtual hal::Error setPerFrameMetadata(const int32_t supportedPerFrameMetadata, + const android::HdrMetadata& metadata) = 0; + [[nodiscard]] virtual hal::Error setDisplayFrame(const android::Rect& frame) = 0; + [[nodiscard]] virtual hal::Error setPlaneAlpha(float alpha) = 0; + [[nodiscard]] virtual hal::Error setSidebandStream(const native_handle_t* stream) = 0; + [[nodiscard]] virtual hal::Error setSourceCrop(const android::FloatRect& crop) = 0; + [[nodiscard]] virtual hal::Error setTransform(hal::Transform transform) = 0; + [[nodiscard]] virtual hal::Error setVisibleRegion(const android::Region& region) = 0; + [[nodiscard]] virtual hal::Error setZOrder(uint32_t z) = 0; // Composer HAL 2.3 - [[clang::warn_unused_result]] virtual hal::Error setColorTransform( - const android::mat4& matrix) = 0; + [[nodiscard]] virtual hal::Error setColorTransform(const android::mat4& matrix) = 0; // Composer HAL 2.4 - [[clang::warn_unused_result]] virtual hal::Error setLayerGenericMetadata( - const std::string& name, bool mandatory, const std::vector<uint8_t>& value) = 0; + [[nodiscard]] virtual hal::Error setLayerGenericMetadata(const std::string& name, + bool mandatory, + const std::vector<uint8_t>& value) = 0; // AIDL HAL - [[clang::warn_unused_result]] virtual hal::Error setBrightness(float brightness) = 0; - [[clang::warn_unused_result]] virtual hal::Error setBlockingRegion( - const android::Region& region) = 0; + [[nodiscard]] virtual hal::Error setBrightness(float brightness) = 0; + [[nodiscard]] virtual hal::Error setBlockingRegion(const android::Region& region) = 0; }; namespace impl { diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index e2e4a99179..459291a1b7 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -740,10 +740,6 @@ std::future<status_t> HWComposer::setDisplayBrightness( }); } -bool HWComposer::getBootDisplayModeSupport() { - return mComposer->isSupported(Hwc2::Composer::OptionalFeature::BootDisplayConfig); -} - status_t HWComposer::setBootDisplayMode(PhysicalDisplayId displayId, hal::HWConfigId displayModeId) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 91fe1b776d..0e15a7c575 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -267,7 +267,6 @@ public: virtual std::optional<hal::HWDisplayId> fromPhysicalDisplayId(PhysicalDisplayId) const = 0; // Composer 3.0 - virtual bool getBootDisplayModeSupport() = 0; virtual status_t setBootDisplayMode(PhysicalDisplayId, hal::HWConfigId) = 0; virtual status_t clearBootDisplayMode(PhysicalDisplayId) = 0; virtual std::optional<hal::HWConfigId> getPreferredBootDisplayMode(PhysicalDisplayId) = 0; @@ -406,7 +405,6 @@ public: const std::unordered_map<std::string, bool>& getSupportedLayerGenericMetadata() const override; // Composer 3.0 - bool getBootDisplayModeSupport() override; status_t setBootDisplayMode(PhysicalDisplayId, hal::HWConfigId) override; status_t clearBootDisplayMode(PhysicalDisplayId) override; std::optional<hal::HWConfigId> getPreferredBootDisplayMode(PhysicalDisplayId) override; diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp index e8dc084c79..d9af55396e 100644 --- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp @@ -235,7 +235,6 @@ bool HidlComposer::isSupported(OptionalFeature feature) const { return mClient_2_4 != nullptr; case OptionalFeature::ExpectedPresentTime: case OptionalFeature::DisplayBrightnessCommand: - case OptionalFeature::BootDisplayConfig: case OptionalFeature::KernelIdleTimer: case OptionalFeature::PhysicalDisplayOrientation: return false; diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp index 3dab38975c..44c086d7d3 100644 --- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp +++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp @@ -542,7 +542,7 @@ private: static constexpr double kAllowedTargetDeviationPercent = 0.05; // Target used for init and normalization, the actual value does not really matter static constexpr const std::chrono::nanoseconds kDefaultTarget = 50ms; - // amount of time after the last message was sent before the session goes stale + // Amount of time after the last message was sent before the session goes stale // actually 100ms but we use 80 here to ideally avoid going stale static constexpr const std::chrono::nanoseconds kStaleTimeout = 80ms; }; @@ -551,7 +551,7 @@ const bool AidlPowerHalWrapper::sTraceHintSessionData = base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false); const bool AidlPowerHalWrapper::sNormalizeTarget = - base::GetBoolProperty(std::string("debug.sf.normalize_hint_session_durations"), true); + base::GetBoolProperty(std::string("debug.sf.normalize_hint_session_durations"), false); PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() { static std::unique_ptr<HalWrapper> sHalWrapper = nullptr; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index aeaf1e1a14..fa5a1c82ba 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -833,6 +833,14 @@ bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relati return false; } + if (CC_UNLIKELY(relative->usingRelativeZ(LayerVector::StateSet::Drawing)) && + (relative->mDrawingState.zOrderRelativeOf == this)) { + ALOGE("Detected relative layer loop between %s and %s", + mName.c_str(), relative->mName.c_str()); + ALOGE("Ignoring new call to set relative layer"); + return false; + } + mFlinger->mSomeChildrenChanged = true; mDrawingState.sequence++; @@ -1990,6 +1998,18 @@ void Layer::prepareShadowClientComposition(LayerFE::LayerSettings& caster, } } +bool Layer::findInHierarchy(const sp<Layer>& l) { + if (l == this) { + return true; + } + for (auto& child : mDrawingChildren) { + if (child->findInHierarchy(l)) { + return true; + } + } + return false; +} + void Layer::commitChildList() { for (size_t i = 0; i < mCurrentChildren.size(); i++) { const auto& child = mCurrentChildren[i]; @@ -1997,6 +2017,17 @@ void Layer::commitChildList() { } mDrawingChildren = mCurrentChildren; mDrawingParent = mCurrentParent; + if (CC_UNLIKELY(usingRelativeZ(LayerVector::StateSet::Drawing))) { + auto zOrderRelativeOf = mDrawingState.zOrderRelativeOf.promote(); + if (zOrderRelativeOf == nullptr) return; + if (findInHierarchy(zOrderRelativeOf)) { + ALOGE("Detected Z ordering loop between %s and %s", mName.c_str(), + zOrderRelativeOf->mName.c_str()); + ALOGE("Severing rel Z loop, potentially dangerous"); + mDrawingState.isRelativeOf = false; + zOrderRelativeOf->removeZOrderRelative(this); + } + } } @@ -2177,7 +2208,6 @@ Rect Layer::getInputBounds() const { void Layer::fillInputFrameInfo(WindowInfo& info, const ui::Transform& screenToDisplay) { Rect tmpBounds = getInputBounds(); if (!tmpBounds.isValid()) { - info.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, true); info.touchableRegion.clear(); // A layer could have invalid input bounds and still expect to receive touch input if it has // replaceTouchableRegionWithCrop. For that case, the input transform needs to be calculated @@ -2392,7 +2422,8 @@ sp<Layer> Layer::getClonedRoot() { } bool Layer::hasInputInfo() const { - return mDrawingState.inputInfo.token != nullptr; + return mDrawingState.inputInfo.token != nullptr || + mDrawingState.inputInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL); } bool Layer::canReceiveInput() const { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 48a9bc50c4..846460d4b1 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -1138,6 +1138,7 @@ private: bool mIsAtRoot = false; uint32_t mLayerCreationFlags; + bool findInHierarchy(const sp<Layer>&); }; std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate); diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 74d77394af..3aa0a5f15c 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -726,10 +726,6 @@ DisplayModePtr Scheduler::getPreferredDisplayMode() { } void Scheduler::onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline) { - if (timeline.refreshRequired) { - mSchedulerCallback.scheduleComposite(FrameHint::kNone); - } - std::lock_guard<std::mutex> lock(mVsyncTimelineLock); mLastVsyncPeriodChangeTimeline = std::make_optional(timeline); @@ -739,23 +735,17 @@ void Scheduler::onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimel } } -void Scheduler::onPostComposition(nsecs_t presentTime) { - const bool recomposite = [=] { - std::lock_guard<std::mutex> lock(mVsyncTimelineLock); - if (mLastVsyncPeriodChangeTimeline && mLastVsyncPeriodChangeTimeline->refreshRequired) { - if (presentTime < mLastVsyncPeriodChangeTimeline->refreshTimeNanos) { - // We need to composite again as refreshTimeNanos is still in the future. - return true; - } - - mLastVsyncPeriodChangeTimeline->refreshRequired = false; +bool Scheduler::onPostComposition(nsecs_t presentTime) { + std::lock_guard<std::mutex> lock(mVsyncTimelineLock); + if (mLastVsyncPeriodChangeTimeline && mLastVsyncPeriodChangeTimeline->refreshRequired) { + if (presentTime < mLastVsyncPeriodChangeTimeline->refreshTimeNanos) { + // We need to composite again as refreshTimeNanos is still in the future. + return true; } - return false; - }(); - if (recomposite) { - mSchedulerCallback.scheduleComposite(FrameHint::kNone); + mLastVsyncPeriodChangeTimeline->refreshRequired = false; } + return false; } void Scheduler::onActiveDisplayAreaChanged(uint32_t displayArea) { diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index a8113d423a..0c72124119 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -83,12 +83,8 @@ class TokenManager; namespace scheduler { struct ISchedulerCallback { - // Indicates frame activity, i.e. whether commit and/or composite is taking place. - enum class FrameHint { kNone, kActive }; - using DisplayModeEvent = scheduler::DisplayModeEvent; - virtual void scheduleComposite(FrameHint) = 0; virtual void setVsyncEnabled(bool) = 0; virtual void requestDisplayMode(DisplayModePtr, DisplayModeEvent) = 0; virtual void kernelTimerChanged(bool expired) = 0; @@ -210,8 +206,8 @@ public: // Notifies the scheduler about a refresh rate timeline change. void onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline); - // Notifies the scheduler post composition. - void onPostComposition(nsecs_t presentTime); + // Notifies the scheduler post composition. Returns if recomposite is needed. + bool onPostComposition(nsecs_t presentTime); // Notifies the scheduler when the display size has changed. Called from SF's main thread void onActiveDisplayAreaChanged(uint32_t displayArea); @@ -245,8 +241,6 @@ public: private: friend class TestableScheduler; - using FrameHint = ISchedulerCallback::FrameHint; - enum class ContentDetectionState { Off, On }; enum class TimerState { Reset, Expired }; enum class TouchState { Inactive, Active }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 2edc05bc08..9f5a7df3aa 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -690,10 +690,9 @@ void SurfaceFlinger::bootFinished() { const nsecs_t duration = now - mBootTime; ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) ); - mFlagManager = std::make_unique<android::FlagManager>(); mFrameTracer->initialize(); mFrameTimeline->onBootFinished(); - getRenderEngine().setEnableTracing(mFlagManager->use_skia_tracing()); + getRenderEngine().setEnableTracing(mFlagManager.use_skia_tracing()); // wait patiently for the window manager death const String16 name("window"); @@ -721,15 +720,15 @@ void SurfaceFlinger::bootFinished() { } readPersistentProperties(); - std::optional<pid_t> renderEngineTid = getRenderEngine().getRenderEngineTid(); - std::vector<int32_t> tidList; - tidList.emplace_back(gettid()); - if (renderEngineTid.has_value()) { - tidList.emplace_back(*renderEngineTid); - } mPowerAdvisor.onBootFinished(); - mPowerAdvisor.enablePowerHint(mFlagManager->use_adpf_cpu_hint()); + mPowerAdvisor.enablePowerHint(mFlagManager.use_adpf_cpu_hint()); if (mPowerAdvisor.usePowerHintSession()) { + std::optional<pid_t> renderEngineTid = getRenderEngine().getRenderEngineTid(); + std::vector<int32_t> tidList; + tidList.emplace_back(gettid()); + if (renderEngineTid.has_value()) { + tidList.emplace_back(*renderEngineTid); + } mPowerAdvisor.startPowerHintSession(tidList); } @@ -1086,7 +1085,8 @@ status_t SurfaceFlinger::getDynamicDisplayInfo(const sp<IBinder>& displayToken, getHwComposer().supportsContentType(*displayId, hal::ContentType::GAME); info->preferredBootDisplayMode = static_cast<ui::DisplayModeId>(-1); - if (getHwComposer().getBootDisplayModeSupport()) { + + if (getHwComposer().hasCapability(Capability::BOOT_DISPLAY_CONFIG)) { if (const auto hwcId = getHwComposer().getPreferredBootDisplayMode(*displayId)) { if (const auto modeId = display->translateModeId(*hwcId)) { info->preferredBootDisplayMode = modeId->value(); @@ -1300,7 +1300,7 @@ void SurfaceFlinger::setActiveModeInHwcIfNeeded() { mScheduler->onNewVsyncPeriodChangeTimeline(outTimeline); if (outTimeline.refreshRequired) { - // Scheduler will submit an empty frame to HWC. + scheduleComposite(FrameHint::kNone); mSetActiveModePending = true; } else { // Updating the internal state should be done outside the loop, @@ -1408,7 +1408,7 @@ status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, Col status_t SurfaceFlinger::getBootDisplayModeSupport(bool* outSupport) const { auto future = mScheduler->schedule([=]() MAIN_THREAD mutable -> status_t { - *outSupport = getHwComposer().getBootDisplayModeSupport(); + *outSupport = getHwComposer().hasCapability(Capability::BOOT_DISPLAY_CONFIG); return NO_ERROR; }); return future.get(); @@ -1941,6 +1941,10 @@ void SurfaceFlinger::onComposerHalVsyncPeriodTimingChanged( hal::HWDisplayId, const hal::VsyncPeriodChangeTimeline& timeline) { Mutex::Autolock lock(mStateLock); mScheduler->onNewVsyncPeriodChangeTimeline(timeline); + + if (timeline.refreshRequired) { + scheduleComposite(FrameHint::kNone); + } } void SurfaceFlinger::onComposerHalSeamlessPossible(hal::HWDisplayId) { @@ -2248,7 +2252,9 @@ void SurfaceFlinger::composite(nsecs_t frameTime, int64_t vsyncId) { mTimeStats->recordFrameDuration(frameTime, systemTime()); - mScheduler->onPostComposition(presentTime); + if (mScheduler->onPostComposition(presentTime)) { + scheduleComposite(FrameHint::kNone); + } postFrame(); postComposition(); @@ -3670,16 +3676,13 @@ uint32_t SurfaceFlinger::clearTransactionFlags(uint32_t mask) { return mTransactionFlags.fetch_and(~mask) & mask; } -uint32_t SurfaceFlinger::setTransactionFlags(uint32_t mask) { - return setTransactionFlags(mask, TransactionSchedule::Late); -} - -uint32_t SurfaceFlinger::setTransactionFlags(uint32_t mask, TransactionSchedule schedule, - const sp<IBinder>& applyToken) { - const uint32_t old = mTransactionFlags.fetch_or(mask); +void SurfaceFlinger::setTransactionFlags(uint32_t mask, TransactionSchedule schedule, + const sp<IBinder>& applyToken) { modulateVsync(&VsyncModulator::setTransactionSchedule, schedule, applyToken); - if ((old & mask) == 0) scheduleCommit(FrameHint::kActive); - return old; + + if (const bool scheduled = mTransactionFlags.fetch_or(mask) & mask; !scheduled) { + scheduleCommit(FrameHint::kActive); + } } bool SurfaceFlinger::stopTransactionProcessing( @@ -3695,6 +3698,15 @@ bool SurfaceFlinger::stopTransactionProcessing( return false; } +int SurfaceFlinger::flushUnsignaledPendingTransactionQueues( + std::vector<TransactionState>& transactions, + std::unordered_map<sp<IBinder>, uint64_t, SpHash<IBinder>>& bufferLayersReadyToPresent, + std::unordered_set<sp<IBinder>, SpHash<IBinder>>& applyTokensWithUnsignaledTransactions) { + return flushPendingTransactionQueues(transactions, bufferLayersReadyToPresent, + applyTokensWithUnsignaledTransactions, + /*tryApplyUnsignaled*/ true); +} + int SurfaceFlinger::flushPendingTransactionQueues( std::vector<TransactionState>& transactions, std::unordered_map<sp<IBinder>, uint64_t, SpHash<IBinder>>& bufferLayersReadyToPresent, @@ -3729,8 +3741,8 @@ int SurfaceFlinger::flushPendingTransactionQueues( break; } transaction.traverseStatesWithBuffers([&](const layer_state_t& state) { - const bool frameNumberChanged = - state.bufferData->flags.test(BufferData::BufferDataChange::frameNumberChanged); + const bool frameNumberChanged = state.bufferData->flags.test( + BufferData::BufferDataChange::frameNumberChanged); if (frameNumberChanged) { bufferLayersReadyToPresent[state.surface] = state.bufferData->frameNumber; } else { @@ -3810,8 +3822,8 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) { mPendingTransactionQueues[transaction.applyToken].push(std::move(transaction)); } else { transaction.traverseStatesWithBuffers([&](const layer_state_t& state) { - const bool frameNumberChanged = - state.bufferData->flags.test(BufferData::BufferDataChange::frameNumberChanged); + const bool frameNumberChanged = state.bufferData->flags.test( + BufferData::BufferDataChange::frameNumberChanged); if (frameNumberChanged) { bufferLayersReadyToPresent[state.surface] = state.bufferData->frameNumber; } else { @@ -3820,7 +3832,7 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) { bufferLayersReadyToPresent[state.surface] = std::numeric_limits<uint64_t>::max(); } - }); + }); transactions.emplace_back(std::move(transaction)); } mTransactionQueue.pop_front(); @@ -3849,9 +3861,8 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) { // If we are allowing latch unsignaled of some form, now it's the time to go over the // transactions that were not applied and try to apply them unsignaled. if (enableLatchUnsignaledConfig != LatchUnsignaledConfig::Disabled) { - flushPendingTransactionQueues(transactions, bufferLayersReadyToPresent, - applyTokensWithUnsignaledTransactions, - /*tryApplyUnsignaled*/ true); + flushUnsignaledPendingTransactionQueues(transactions, bufferLayersReadyToPresent, + applyTokensWithUnsignaledTransactions); } return applyTransactions(transactions, vsyncId); @@ -5459,9 +5470,7 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co /* * Dump flag/property manager state */ - if (mFlagManager != nullptr) { - mFlagManager->dump(result); - } + mFlagManager.dump(result); result.append(mTimeStats->miniDump()); result.append("\n"); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index df59d5066c..f2636b446f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -56,6 +56,7 @@ #include "DisplayHardware/PowerAdvisor.h" #include "DisplayIdGenerator.h" #include "Effects/Daltonizer.h" +#include "FlagManager.h" #include "FrameTracker.h" #include "LayerVector.h" #include "Scheduler/RefreshRateConfigs.h" @@ -286,10 +287,13 @@ public: SurfaceFlingerBE& getBE() { return mBE; } const SurfaceFlingerBE& getBE() const { return mBE; } + // Indicates frame activity, i.e. whether commit and/or composite is taking place. + enum class FrameHint { kNone, kActive }; + // Schedule commit of transactions on the main thread ahead of the next VSYNC. void scheduleCommit(FrameHint); // As above, but also force composite regardless if transactions were committed. - void scheduleComposite(FrameHint) override; + void scheduleComposite(FrameHint); // As above, but also force dirty geometry to repaint. void scheduleRepaint(); // Schedule sampling independently from commit or composite. @@ -770,27 +774,27 @@ private: std::unordered_set<sp<IBinder>, SpHash<IBinder>>& applyTokensWithUnsignaledTransactions, bool tryApplyUnsignaled) REQUIRES(mStateLock, mQueueLock); + int flushUnsignaledPendingTransactionQueues( + std::vector<TransactionState>& transactions, + std::unordered_map<sp<IBinder>, uint64_t, SpHash<IBinder>>& bufferLayersReadyToPresent, + std::unordered_set<sp<IBinder>, SpHash<IBinder>>& applyTokensWithUnsignaledTransactions) + REQUIRES(mStateLock, mQueueLock); + uint32_t setClientStateLocked(const FrameTimelineInfo&, ComposerState&, int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, uint32_t permissions) REQUIRES(mStateLock); uint32_t getTransactionFlags() const; - // Sets the masked bits, and returns the old flags. - uint32_t setTransactionFlags(uint32_t mask); + // Sets the masked bits, and schedules a commit if needed. + void setTransactionFlags(uint32_t mask, TransactionSchedule = TransactionSchedule::Late, + const sp<IBinder>& applyToken = nullptr); // Clears and returns the masked bits. uint32_t clearTransactionFlags(uint32_t mask); - // Indicate SF should call doTraversal on layers, but don't trigger a wakeup! We use this cases - // where there are still pending transactions but we know they won't be ready until a frame - // arrives from a different layer. So we need to ensure we performTransaction from invalidate - // but there is no need to try and wake up immediately to do it. Rather we rely on - // onFrameAvailable or another layer update to wake us up. - void setTraversalNeeded(); - uint32_t setTransactionFlags(uint32_t mask, TransactionSchedule, - const sp<IBinder>& applyToken = {}); void commitOffscreenLayers(); + enum class TransactionReadiness { NotReady, NotReadyBarrier, @@ -1415,7 +1419,7 @@ private: const sp<WindowInfosListenerInvoker> mWindowInfosListenerInvoker; - std::unique_ptr<FlagManager> mFlagManager; + FlagManager mFlagManager; // returns the framerate of the layer with the given sequence ID float getLayerFramerate(nsecs_t now, int32_t id) const { diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp index a5a716d458..f25043cd6d 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp @@ -140,10 +140,8 @@ void SurfaceFlingerFuzzer::invokeFlinger() { mFlinger->enableLatchUnsignaledConfig = mFdp.PickValueInArray(kLatchUnsignaledConfig); - mFlinger->scheduleComposite(mFdp.ConsumeBool() - ? scheduler::ISchedulerCallback::FrameHint::kActive - : scheduler::ISchedulerCallback::FrameHint::kNone); - + using FrameHint = SurfaceFlinger::FrameHint; + mFlinger->scheduleComposite(mFdp.ConsumeBool() ? FrameHint::kActive : FrameHint::kNone); mFlinger->scheduleRepaint(); mFlinger->scheduleSample(); diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h index 93abc9f3eb..1d0f62b99b 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -810,7 +810,6 @@ public: } private: - void scheduleComposite(FrameHint) override {} void setVsyncEnabled(bool) override {} void requestDisplayMode(DisplayModePtr, DisplayModeEvent) override {} void kernelTimerChanged(bool) override {} diff --git a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h index 5083d561ac..52675869fa 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h +++ b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h @@ -23,7 +23,6 @@ namespace android::scheduler::mock { struct SchedulerCallback final : ISchedulerCallback { - MOCK_METHOD(void, scheduleComposite, (FrameHint), (override)); MOCK_METHOD(void, setVsyncEnabled, (bool), (override)); MOCK_METHOD(void, requestDisplayMode, (DisplayModePtr, DisplayModeEvent), (override)); MOCK_METHOD(void, kernelTimerChanged, (bool), (override)); @@ -31,7 +30,6 @@ struct SchedulerCallback final : ISchedulerCallback { }; struct NoOpSchedulerCallback final : ISchedulerCallback { - void scheduleComposite(FrameHint) override {} void setVsyncEnabled(bool) override {} void requestDisplayMode(DisplayModePtr, DisplayModeEvent) override {} void kernelTimerChanged(bool) override {} |