summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TEST_MAPPING61
-rw-r--r--cmds/installd/InstalldNativeService.cpp187
-rw-r--r--cmds/installd/InstalldNativeService.h1
-rw-r--r--cmds/installd/binder/android/os/IInstalld.aidl2
-rw-r--r--cmds/installd/utils.cpp40
-rw-r--r--cmds/installd/utils.h2
-rw-r--r--cmds/servicemanager/ServiceManager.cpp13
-rw-r--r--libs/gui/DisplayEventDispatcher.cpp5
-rw-r--r--libs/gui/SurfaceControl.cpp1
-rw-r--r--libs/gui/include/gui/DisplayEventDispatcher.h1
-rw-r--r--libs/gui/include/gui/SurfaceControl.h12
-rw-r--r--libs/gui/tests/EndToEndNativeInputTest.cpp85
-rw-r--r--libs/renderengine/skia/SkiaGLRenderEngine.cpp27
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.cpp41
-rw-r--r--services/inputflinger/tests/InputDispatcher_test.cpp34
-rw-r--r--services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp1
-rw-r--r--services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp10
-rw-r--r--services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp1
-rw-r--r--services/surfaceflinger/DisplayHardware/ComposerHal.h1
-rw-r--r--services/surfaceflinger/DisplayHardware/HWC2.h150
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp4
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.h2
-rw-r--r--services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp1
-rw-r--r--services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp4
-rw-r--r--services/surfaceflinger/Layer.cpp35
-rw-r--r--services/surfaceflinger/Layer.h1
-rw-r--r--services/surfaceflinger/Scheduler/Scheduler.cpp26
-rw-r--r--services/surfaceflinger/Scheduler/Scheduler.h10
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp75
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h28
-rw-r--r--services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp6
-rw-r--r--services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h1
-rw-r--r--services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h2
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 {}