diff options
62 files changed, 1695 insertions, 906 deletions
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp index ebca892139..ffa87249e2 100644 --- a/cmds/installd/dexopt.cpp +++ b/cmds/installd/dexopt.cpp @@ -318,6 +318,16 @@ static const char* kJitZygoteImage = // Phenotype property name for enabling profiling the boot class path. static const char* PROFILE_BOOT_CLASS_PATH = "profilebootclasspath"; +static bool IsBootClassPathProfilingEnable() { + std::string profile_boot_class_path = GetProperty("dalvik.vm.profilebootclasspath", ""); + profile_boot_class_path = + server_configurable_flags::GetServerConfigurableFlag( + RUNTIME_NATIVE_BOOT_NAMESPACE, + PROFILE_BOOT_CLASS_PATH, + /*default_value=*/ profile_boot_class_path); + return profile_boot_class_path == "true"; +} + class RunDex2Oat : public ExecVHelper { public: RunDex2Oat(int zip_fd, @@ -450,14 +460,7 @@ class RunDex2Oat : public ExecVHelper { ENABLE_JITZYGOTE_IMAGE, /*default_value=*/ ""); - std::string profile_boot_class_path = GetProperty("dalvik.vm.profilebootclasspath", ""); - profile_boot_class_path = - server_configurable_flags::GetServerConfigurableFlag( - RUNTIME_NATIVE_BOOT_NAMESPACE, - PROFILE_BOOT_CLASS_PATH, - /*default_value=*/ profile_boot_class_path); - - if (use_jitzygote_image == "true" || profile_boot_class_path == "true") { + if (use_jitzygote_image == "true" || IsBootClassPathProfilingEnable()) { boot_image = StringPrintf("--boot-image=%s", kJitZygoteImage); } else { boot_image = MapPropertyToArg("dalvik.vm.boot-image", "--boot-image=%s"); @@ -896,7 +899,15 @@ static bool analyze_profiles(uid_t uid, const std::string& package_name, } RunProfman profman_merge; - profman_merge.SetupMerge(profiles_fd, reference_profile_fd); + const std::vector<unique_fd>& apk_fds = std::vector<unique_fd>(); + const std::vector<std::string>& dex_locations = std::vector<std::string>(); + profman_merge.SetupMerge( + profiles_fd, + reference_profile_fd, + apk_fds, + dex_locations, + /* for_snapshot= */ false, + IsBootClassPathProfilingEnable()); pid_t pid = fork(); if (pid == 0) { /* child -- drop privileges before continuing */ @@ -2810,7 +2821,13 @@ static bool create_app_profile_snapshot(int32_t app_id, } RunProfman args; - args.SetupMerge(profiles_fd, snapshot_fd, apk_fds, dex_locations, /*for_snapshot=*/true); + // This is specifically a snapshot for an app, so don't use boot image profiles. + args.SetupMerge(profiles_fd, + snapshot_fd, + apk_fds, + dex_locations, + /* for_snapshot= */ true, + /* for_boot_image= */ false); pid_t pid = fork(); if (pid == 0) { /* child -- drop privileges before continuing */ diff --git a/data/etc/android.hardware.camera.concurrent.xml b/data/etc/android.hardware.camera.concurrent.xml new file mode 100644 index 0000000000..2cbb263341 --- /dev/null +++ b/data/etc/android.hardware.camera.concurrent.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- This is the set of features required for a camera2 device that supports concurrent operation + of front and back cameras --> +<permissions> + <feature name="android.hardware.camera.front" /> + <feature name="android.hardware.camera.concurrent" /> +</permissions> diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index a695a8ffda..856c54d89e 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -68,46 +68,47 @@ struct InputWindowInfo { // Window types from WindowManager.LayoutParams enum { FIRST_APPLICATION_WINDOW = 1, - TYPE_BASE_APPLICATION = 1, - TYPE_APPLICATION = 2, + TYPE_BASE_APPLICATION = 1, + TYPE_APPLICATION = 2, TYPE_APPLICATION_STARTING = 3, LAST_APPLICATION_WINDOW = 99, - FIRST_SUB_WINDOW = 1000, - TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW, - TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1, - TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2, - TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3, - TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4, - LAST_SUB_WINDOW = 1999, - FIRST_SYSTEM_WINDOW = 2000, - TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW, - TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1, - TYPE_PHONE = FIRST_SYSTEM_WINDOW+2, - TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3, - TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4, - TYPE_TOAST = FIRST_SYSTEM_WINDOW+5, - TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6, - TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7, - TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8, - TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9, - TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10, - TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11, - TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12, - TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13, - TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14, - TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15, - TYPE_DRAG = FIRST_SYSTEM_WINDOW+16, - TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17, - TYPE_POINTER = FIRST_SYSTEM_WINDOW+18, - TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19, - TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20, - TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21, - TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW+22, - TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24, - TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27, - TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32, - TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW+34, - LAST_SYSTEM_WINDOW = 2999, + FIRST_SUB_WINDOW = 1000, + TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW, + TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1, + TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2, + TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3, + TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4, + LAST_SUB_WINDOW = 1999, + FIRST_SYSTEM_WINDOW = 2000, + TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW, + TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW + 1, + TYPE_PHONE = FIRST_SYSTEM_WINDOW + 2, + TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW + 3, + TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW + 4, + TYPE_TOAST = FIRST_SYSTEM_WINDOW + 5, + TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 6, + TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW + 7, + TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW + 8, + TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW + 9, + TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW + 10, + TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW + 11, + TYPE_INPUT_METHOD_DIALOG = FIRST_SYSTEM_WINDOW + 12, + TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW + 13, + TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW + 14, + TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 15, + TYPE_DRAG = FIRST_SYSTEM_WINDOW + 16, + TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW + 17, + TYPE_POINTER = FIRST_SYSTEM_WINDOW + 18, + TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW + 19, + TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW + 20, + TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW + 21, + TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW + 22, + TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW + 24, + TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 27, + TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW + 32, + TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW + 34, + TYPE_NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40, + LAST_SYSTEM_WINDOW = 2999, }; enum { diff --git a/include/ui/FatVector.h b/include/ui/FatVector.h new file mode 120000 index 0000000000..c2047c07e1 --- /dev/null +++ b/include/ui/FatVector.h @@ -0,0 +1 @@ +../../libs/ui/include/ui/FatVector.h
\ No newline at end of file diff --git a/libs/binder/ActivityManager.cpp b/libs/binder/ActivityManager.cpp index 4f2709d91a..5e4c98fc7a 100644 --- a/libs/binder/ActivityManager.cpp +++ b/libs/binder/ActivityManager.cpp @@ -98,15 +98,6 @@ int32_t ActivityManager::getUidProcessState(const uid_t uid, const String16& cal return PROCESS_STATE_UNKNOWN; } -bool ActivityManager::isUidActiveOrForeground(const uid_t uid, const String16& callingPackage) -{ - sp<IActivityManager> service = getService(); - if (service != nullptr) { - return service->isUidActiveOrForeground(uid, callingPackage); - } - return false; -} - status_t ActivityManager::linkToDeath(const sp<IBinder::DeathRecipient>& recipient) { sp<IActivityManager> service = getService(); if (service != nullptr) { diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp index 9e1249baf4..1eb5363ae2 100644 --- a/libs/binder/IActivityManager.cpp +++ b/libs/binder/IActivityManager.cpp @@ -104,18 +104,6 @@ public: } return reply.readInt32(); } - - virtual bool isUidActiveOrForeground(const uid_t uid, const String16& callingPackage) - { - Parcel data, reply; - data.writeInterfaceToken(IActivityManager::getInterfaceDescriptor()); - data.writeInt32(uid); - data.writeString16(callingPackage); - remote()->transact(IS_UID_ACTIVE_OR_FOREGROUND_TRANSACTION, data, &reply); - // fail on exception - if (reply.readExceptionCode() != 0) return false; - return reply.readInt32() == 1; - } }; // ------------------------------------------------------------------------------------ diff --git a/libs/binder/include/binder/ActivityManager.h b/libs/binder/include/binder/ActivityManager.h index 0bb6d28da4..9108e31758 100644 --- a/libs/binder/include/binder/ActivityManager.h +++ b/libs/binder/include/binder/ActivityManager.h @@ -46,24 +46,25 @@ public: PROCESS_STATE_PERSISTENT = 0, PROCESS_STATE_PERSISTENT_UI = 1, PROCESS_STATE_TOP = 2, - PROCESS_STATE_BOUND_TOP = 3, - PROCESS_STATE_FOREGROUND_SERVICE = 4, - PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 5, - PROCESS_STATE_IMPORTANT_FOREGROUND = 6, - PROCESS_STATE_IMPORTANT_BACKGROUND = 7, - PROCESS_STATE_TRANSIENT_BACKGROUND = 8, - PROCESS_STATE_BACKUP = 9, - PROCESS_STATE_SERVICE = 10, - PROCESS_STATE_RECEIVER = 11, - PROCESS_STATE_TOP_SLEEPING = 12, - PROCESS_STATE_HEAVY_WEIGHT = 13, - PROCESS_STATE_HOME = 14, - PROCESS_STATE_LAST_ACTIVITY = 15, - PROCESS_STATE_CACHED_ACTIVITY = 16, - PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 17, - PROCESS_STATE_CACHED_RECENT = 18, - PROCESS_STATE_CACHED_EMPTY = 19, - PROCESS_STATE_NONEXISTENT = 20, + PROCESS_STATE_FOREGROUND_SERVICE_LOCATION = 3, + PROCESS_STATE_BOUND_TOP = 4, + PROCESS_STATE_FOREGROUND_SERVICE = 5, + PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 6, + PROCESS_STATE_IMPORTANT_FOREGROUND = 7, + PROCESS_STATE_IMPORTANT_BACKGROUND = 8, + PROCESS_STATE_TRANSIENT_BACKGROUND = 9, + PROCESS_STATE_BACKUP = 10, + PROCESS_STATE_SERVICE = 11, + PROCESS_STATE_RECEIVER = 12, + PROCESS_STATE_TOP_SLEEPING = 13, + PROCESS_STATE_HEAVY_WEIGHT = 14, + PROCESS_STATE_HOME = 15, + PROCESS_STATE_LAST_ACTIVITY = 16, + PROCESS_STATE_CACHED_ACTIVITY = 17, + PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 18, + PROCESS_STATE_CACHED_RECENT = 19, + PROCESS_STATE_CACHED_EMPTY = 20, + PROCESS_STATE_NONEXISTENT = 21, }; ActivityManager(); @@ -76,7 +77,6 @@ public: void unregisterUidObserver(const sp<IUidObserver>& observer); bool isUidActive(const uid_t uid, const String16& callingPackage); int getUidProcessState(const uid_t uid, const String16& callingPackage); - bool isUidActiveOrForeground(const uid_t uid, const String16& callingPackage); status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient); diff --git a/libs/binder/include/binder/IActivityManager.h b/libs/binder/include/binder/IActivityManager.h index 1815ecc67f..e0248f6624 100644 --- a/libs/binder/include/binder/IActivityManager.h +++ b/libs/binder/include/binder/IActivityManager.h @@ -39,15 +39,13 @@ public: virtual void unregisterUidObserver(const sp<IUidObserver>& observer) = 0; virtual bool isUidActive(const uid_t uid, const String16& callingPackage) = 0; virtual int32_t getUidProcessState(const uid_t uid, const String16& callingPackage) = 0; - virtual bool isUidActiveOrForeground(const uid_t uid, const String16& callingPackage) = 0; enum { OPEN_CONTENT_URI_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, REGISTER_UID_OBSERVER_TRANSACTION, UNREGISTER_UID_OBSERVER_TRANSACTION, IS_UID_ACTIVE_TRANSACTION, - GET_UID_PROCESS_STATE_TRANSACTION, - IS_UID_ACTIVE_OR_FOREGROUND_TRANSACTION, + GET_UID_PROCESS_STATE_TRANSACTION }; }; diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 5965201341..56591bdc63 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -19,8 +19,6 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS -#include <cutils/properties.h> - #include <gui/BLASTBufferQueue.h> #include <gui/BufferItemConsumer.h> #include <gui/GLConsumer.h> diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp index a1803d8f0e..8d80833ebe 100644 --- a/libs/gui/BufferQueueCore.cpp +++ b/libs/gui/BufferQueueCore.cpp @@ -28,7 +28,6 @@ #include <inttypes.h> -#include <cutils/properties.h> #include <cutils/atomic.h> #include <gui/BufferItem.h> diff --git a/libs/gui/DebugEGLImageTracker.cpp b/libs/gui/DebugEGLImageTracker.cpp index ab6f36444a..5762dabc55 100644 --- a/libs/gui/DebugEGLImageTracker.cpp +++ b/libs/gui/DebugEGLImageTracker.cpp @@ -14,13 +14,14 @@ * limitations under the License. */ +#include <android-base/properties.h> #include <android-base/stringprintf.h> -#include <cutils/properties.h> #include <gui/DebugEGLImageTracker.h> #include <cinttypes> #include <unordered_map> +using android::base::GetBoolProperty; using android::base::StringAppendF; std::mutex DebugEGLImageTracker::mInstanceLock; @@ -57,10 +58,7 @@ private: DebugEGLImageTracker *DebugEGLImageTracker::getInstance() { std::lock_guard lock(mInstanceLock); if (mInstance == nullptr) { - char value[PROPERTY_VALUE_MAX]; - property_get("debug.sf.enable_egl_image_tracker", value, "0"); - const bool enabled = static_cast<bool>(atoi(value)); - + const bool enabled = GetBoolProperty("debug.sf.enable_egl_image_tracker", false); if (enabled) { mInstance = new DebugEGLImageTrackerImpl(); } else { diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 6fd53cf47a..2a27a9a278 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -931,8 +931,11 @@ public: } virtual status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, - int32_t defaultConfig, float minRefreshRate, - float maxRefreshRate) { + int32_t defaultConfig, + float primaryRefreshRateMin, + float primaryRefreshRateMax, + float appRequestRefreshRateMin, + float appRequestRefreshRateMax) { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -949,14 +952,26 @@ public: ALOGE("setDesiredDisplayConfigSpecs failed to write defaultConfig: %d", result); return result; } - result = data.writeFloat(minRefreshRate); + result = data.writeFloat(primaryRefreshRateMin); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs failed to write minRefreshRate: %d", result); + ALOGE("setDesiredDisplayConfigSpecs failed to write primaryRefreshRateMin: %d", result); return result; } - result = data.writeFloat(maxRefreshRate); + result = data.writeFloat(primaryRefreshRateMax); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs failed to write maxRefreshRate: %d", result); + ALOGE("setDesiredDisplayConfigSpecs failed to write primaryRefreshRateMax: %d", result); + return result; + } + result = data.writeFloat(appRequestRefreshRateMin); + if (result != NO_ERROR) { + ALOGE("setDesiredDisplayConfigSpecs failed to write appRequestRefreshRateMin: %d", + result); + return result; + } + result = data.writeFloat(appRequestRefreshRateMax); + if (result != NO_ERROR) { + ALOGE("setDesiredDisplayConfigSpecs failed to write appRequestRefreshRateMax: %d", + result); return result; } @@ -971,9 +986,14 @@ public: virtual status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, int32_t* outDefaultConfig, - float* outMinRefreshRate, - float* outMaxRefreshRate) { - if (!outDefaultConfig || !outMinRefreshRate || !outMaxRefreshRate) return BAD_VALUE; + float* outPrimaryRefreshRateMin, + float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, + float* outAppRequestRefreshRateMax) { + if (!outDefaultConfig || !outPrimaryRefreshRateMin || !outPrimaryRefreshRateMax || + !outAppRequestRefreshRateMin || !outAppRequestRefreshRateMax) { + return BAD_VALUE; + } Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -996,14 +1016,26 @@ public: ALOGE("getDesiredDisplayConfigSpecs failed to read defaultConfig: %d", result); return result; } - result = reply.readFloat(outMinRefreshRate); + result = reply.readFloat(outPrimaryRefreshRateMin); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to read minRefreshRate: %d", result); + ALOGE("getDesiredDisplayConfigSpecs failed to read primaryRefreshRateMin: %d", result); return result; } - result = reply.readFloat(outMaxRefreshRate); + result = reply.readFloat(outPrimaryRefreshRateMax); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to read maxRefreshRate: %d", result); + ALOGE("getDesiredDisplayConfigSpecs failed to read primaryRefreshRateMax: %d", result); + return result; + } + result = reply.readFloat(outAppRequestRefreshRateMin); + if (result != NO_ERROR) { + ALOGE("getDesiredDisplayConfigSpecs failed to read appRequestRefreshRateMin: %d", + result); + return result; + } + result = reply.readFloat(outAppRequestRefreshRateMax); + if (result != NO_ERROR) { + ALOGE("getDesiredDisplayConfigSpecs failed to read appRequestRefreshRateMax: %d", + result); return result; } return reply.readInt32(); @@ -1835,20 +1867,38 @@ status_t BnSurfaceComposer::onTransact( ALOGE("setDesiredDisplayConfigSpecs: failed to read defaultConfig: %d", result); return result; } - float minRefreshRate; - result = data.readFloat(&minRefreshRate); + float primaryRefreshRateMin; + result = data.readFloat(&primaryRefreshRateMin); + if (result != NO_ERROR) { + ALOGE("setDesiredDisplayConfigSpecs: failed to read primaryRefreshRateMin: %d", + result); + return result; + } + float primaryRefreshRateMax; + result = data.readFloat(&primaryRefreshRateMax); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to read minRefreshRate: %d", result); + ALOGE("setDesiredDisplayConfigSpecs: failed to read primaryRefreshRateMax: %d", + result); return result; } - float maxRefreshRate; - result = data.readFloat(&maxRefreshRate); + float appRequestRefreshRateMin; + result = data.readFloat(&appRequestRefreshRateMin); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to read maxRefreshRate: %d", result); + ALOGE("setDesiredDisplayConfigSpecs: failed to read appRequestRefreshRateMin: %d", + result); return result; } - result = setDesiredDisplayConfigSpecs(displayToken, defaultConfig, minRefreshRate, - maxRefreshRate); + float appRequestRefreshRateMax; + result = data.readFloat(&appRequestRefreshRateMax); + if (result != NO_ERROR) { + ALOGE("setDesiredDisplayConfigSpecs: failed to read appRequestRefreshRateMax: %d", + result); + return result; + } + result = + setDesiredDisplayConfigSpecs(displayToken, defaultConfig, primaryRefreshRateMin, + primaryRefreshRateMax, appRequestRefreshRateMin, + appRequestRefreshRateMax); if (result != NO_ERROR) { ALOGE("setDesiredDisplayConfigSpecs: failed to call setDesiredDisplayConfigSpecs: " "%d", @@ -1862,11 +1912,16 @@ status_t BnSurfaceComposer::onTransact( CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IBinder> displayToken = data.readStrongBinder(); int32_t defaultConfig; - float minRefreshRate; - float maxRefreshRate; - - status_t result = getDesiredDisplayConfigSpecs(displayToken, &defaultConfig, - &minRefreshRate, &maxRefreshRate); + float primaryRefreshRateMin; + float primaryRefreshRateMax; + float appRequestRefreshRateMin; + float appRequestRefreshRateMax; + + status_t result = + getDesiredDisplayConfigSpecs(displayToken, &defaultConfig, + &primaryRefreshRateMin, &primaryRefreshRateMax, + &appRequestRefreshRateMin, + &appRequestRefreshRateMax); if (result != NO_ERROR) { ALOGE("getDesiredDisplayConfigSpecs: failed to get getDesiredDisplayConfigSpecs: " "%d", @@ -1879,14 +1934,28 @@ status_t BnSurfaceComposer::onTransact( ALOGE("getDesiredDisplayConfigSpecs: failed to write defaultConfig: %d", result); return result; } - result = reply->writeFloat(minRefreshRate); + result = reply->writeFloat(primaryRefreshRateMin); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs: failed to write minRefreshRate: %d", result); + ALOGE("getDesiredDisplayConfigSpecs: failed to write primaryRefreshRateMin: %d", + result); return result; } - result = reply->writeFloat(maxRefreshRate); + result = reply->writeFloat(primaryRefreshRateMax); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs: failed to write maxRefreshRate: %d", result); + ALOGE("getDesiredDisplayConfigSpecs: failed to write primaryRefreshRateMax: %d", + result); + return result; + } + result = reply->writeFloat(appRequestRefreshRateMin); + if (result != NO_ERROR) { + ALOGE("getDesiredDisplayConfigSpecs: failed to write appRequestRefreshRateMin: %d", + result); + return result; + } + result = reply->writeFloat(appRequestRefreshRateMax); + if (result != NO_ERROR) { + ALOGE("getDesiredDisplayConfigSpecs: failed to write appRequestRefreshRateMax: %d", + result); return result; } reply->writeInt32(result); diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index f911e70ebf..2bf8ff7581 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -57,7 +57,8 @@ bool isInterceptorRegistrationOp(int op) { return op == NATIVE_WINDOW_SET_CANCEL_INTERCEPTOR || op == NATIVE_WINDOW_SET_DEQUEUE_INTERCEPTOR || op == NATIVE_WINDOW_SET_PERFORM_INTERCEPTOR || - op == NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR; + op == NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR || + op == NATIVE_WINDOW_SET_QUERY_INTERCEPTOR; } } // namespace @@ -501,6 +502,19 @@ int Surface::performInternal(ANativeWindow* window, int operation, va_list args) int Surface::hook_query(const ANativeWindow* window, int what, int* value) { const Surface* c = getSelf(window); + { + std::shared_lock<std::shared_mutex> lock(c->mInterceptorMutex); + if (c->mQueryInterceptor != nullptr) { + auto interceptor = c->mQueryInterceptor; + auto data = c->mQueryInterceptorData; + return interceptor(window, Surface::queryInternal, data, what, value); + } + } + return c->query(what, value); +} + +int Surface::queryInternal(const ANativeWindow* window, int what, int* value) { + const Surface* c = getSelf(window); return c->query(what, value); } @@ -1177,6 +1191,9 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR: res = dispatchAddQueueInterceptor(args); break; + case NATIVE_WINDOW_SET_QUERY_INTERCEPTOR: + res = dispatchAddQueryInterceptor(args); + break; case NATIVE_WINDOW_ALLOCATE_BUFFERS: allocateBuffers(); res = NO_ERROR; @@ -1457,6 +1474,15 @@ int Surface::dispatchAddQueueInterceptor(va_list args) { return NO_ERROR; } +int Surface::dispatchAddQueryInterceptor(va_list args) { + ANativeWindow_queryInterceptor interceptor = va_arg(args, ANativeWindow_queryInterceptor); + void* data = va_arg(args, void*); + std::lock_guard<std::shared_mutex> lock(mInterceptorMutex); + mQueryInterceptor = interceptor; + mQueryInterceptorData = data; + return NO_ERROR; +} + int Surface::dispatchGetLastQueuedBuffer(va_list args) { AHardwareBuffer** buffer = va_arg(args, AHardwareBuffer**); int* fence = va_arg(args, int*); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index d9cbeb71d2..a52f298e77 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1698,22 +1698,26 @@ int SurfaceComposerClient::getActiveConfig(const sp<IBinder>& display) { status_t SurfaceComposerClient::setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, int32_t defaultConfig, - float minRefreshRate, - float maxRefreshRate) { - return ComposerService::getComposerService()->setDesiredDisplayConfigSpecs(displayToken, - defaultConfig, - minRefreshRate, - maxRefreshRate); + float primaryRefreshRateMin, + float primaryRefreshRateMax, + float appRequestRefreshRateMin, + float appRequestRefreshRateMax) { + return ComposerService::getComposerService() + ->setDesiredDisplayConfigSpecs(displayToken, defaultConfig, primaryRefreshRateMin, + primaryRefreshRateMax, appRequestRefreshRateMin, + appRequestRefreshRateMax); } status_t SurfaceComposerClient::getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, int32_t* outDefaultConfig, - float* outMinRefreshRate, - float* outMaxRefreshRate) { - return ComposerService::getComposerService()->getDesiredDisplayConfigSpecs(displayToken, - outDefaultConfig, - outMinRefreshRate, - outMaxRefreshRate); + float* outPrimaryRefreshRateMin, + float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, + float* outAppRequestRefreshRateMax) { + return ComposerService::getComposerService() + ->getDesiredDisplayConfigSpecs(displayToken, outDefaultConfig, outPrimaryRefreshRateMin, + outPrimaryRefreshRateMax, outAppRequestRefreshRateMin, + outAppRequestRefreshRateMax); } status_t SurfaceComposerClient::getDisplayColorModes(const sp<IBinder>& display, diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index b4a3fbec2a..0d33b3f695 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -426,19 +426,36 @@ public: */ virtual status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) = 0; - /* - * Sets the refresh rate boundaries for display configuration. - * For all other parameters, default configuration is used. The index for the default is - * corresponding to the configs returned from getDisplayConfigs(). + /* Sets the refresh rate boundaries for the display. + * + * The primary refresh rate range represents display manager's general guidance on the display + * configs we'll consider when switching refresh rates. Unless we get an explicit signal from an + * app, we should stay within this range. + * + * The app request refresh rate range allows us to consider more display configs when switching + * refresh rates. Although we should generally stay within the primary range, specific + * considerations, such as layer frame rate settings specified via the setFrameRate() api, may + * cause us to go outside the primary range. We never go outside the app request range. The app + * request range will be greater than or equal to the primary refresh rate range, never smaller. + * + * defaultConfig is used to narrow the list of display configs SurfaceFlinger will consider + * switching between. Only configs with a config group and resolution matching defaultConfig + * will be considered for switching. The defaultConfig index corresponds to the list of configs + * returned from getDisplayConfigs(). */ virtual status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, - int32_t defaultConfig, float minRefreshRate, - float maxRefreshRate) = 0; + int32_t defaultConfig, + float primaryRefreshRateMin, + float primaryRefreshRateMax, + float appRequestRefreshRateMin, + float appRequestRefreshRateMax) = 0; virtual status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, int32_t* outDefaultConfig, - float* outMinRefreshRate, - float* outMaxRefreshRate) = 0; + float* outPrimaryRefreshRateMin, + float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, + float* outAppRequestRefreshRateMax) = 0; /* * Gets whether brightness operations are supported on a display. * diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 917c0d4831..49c83da319 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -209,6 +209,7 @@ private: int* fenceFd); static int performInternal(ANativeWindow* window, int operation, va_list args); static int queueBufferInternal(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd); + static int queryInternal(const ANativeWindow* window, int what, int* value); static int hook_cancelBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer); @@ -261,6 +262,7 @@ private: int dispatchAddDequeueInterceptor(va_list args); int dispatchAddPerformInterceptor(va_list args); int dispatchAddQueueInterceptor(va_list args); + int dispatchAddQueryInterceptor(va_list args); int dispatchGetLastQueuedBuffer(va_list args); bool transformToDisplayInverse(); @@ -468,7 +470,7 @@ protected: mutable Mutex mMutex; // mInterceptorMutex is the mutex guarding interceptors. - std::shared_mutex mInterceptorMutex; + mutable std::shared_mutex mInterceptorMutex; ANativeWindow_cancelBufferInterceptor mCancelInterceptor = nullptr; void* mCancelInterceptorData = nullptr; @@ -478,6 +480,8 @@ protected: void* mPerformInterceptorData = nullptr; ANativeWindow_queueBufferInterceptor mQueueInterceptor = nullptr; void* mQueueInterceptorData = nullptr; + ANativeWindow_queryInterceptor mQueryInterceptor = nullptr; + void* mQueryInterceptorData = nullptr; // must be used from the lock/unlock thread sp<GraphicBuffer> mLockedBuffer; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 2fb9538390..531aed7ac4 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -118,21 +118,19 @@ public: // Shorthand for getDisplayConfigs element at getActiveConfig index. static status_t getActiveDisplayConfig(const sp<IBinder>& display, DisplayConfig*); - // Sets the refresh rate boundaries for display configuration. - // For all other parameters, default configuration is used. The index for the default is - // corresponting to the configs returned from getDisplayConfigs(). + // Sets the refresh rate boundaries for the display. static status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, - int32_t defaultConfig, float minRefreshRate, - float maxRefreshRate); - // Gets the refresh rate boundaries for display configuration. - // For all other parameters, default configuration is used. The index for the default is - // corresponting to the configs returned from getDisplayConfigs(). - // The reason is passed in for telemetry tracking, and it corresponds to the list of all - // the policy rules that were used. + int32_t defaultConfig, float primaryRefreshRateMin, + float primaryRefreshRateMax, + float appRequestRefreshRateMin, + float appRequestRefreshRateMax); + // Gets the refresh rate boundaries for the display. static status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, int32_t* outDefaultConfig, - float* outMinRefreshRate, - float* outMaxRefreshRate); + float* outPrimaryRefreshRateMin, + float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, + float* outAppRequestRefreshRateMax); // Gets the list of supported color modes for the given display static status_t getDisplayColorModes(const sp<IBinder>& display, diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index c59afba87c..5188a09c4b 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -178,7 +178,7 @@ private: mInputInfo.name = "Test info"; mInputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL; mInputInfo.layoutParamsType = InputWindowInfo::TYPE_BASE_APPLICATION; - mInputInfo.dispatchingTimeout = 100000; + mInputInfo.dispatchingTimeout = seconds_to_nanoseconds(5); mInputInfo.globalScaleFactor = 1.0; mInputInfo.canReceiveKeys = true; mInputInfo.hasFocus = true; @@ -196,7 +196,7 @@ private: InputApplicationInfo aInfo; aInfo.token = new BBinder(); aInfo.name = "Test app info"; - aInfo.dispatchingTimeout = 100000; + aInfo.dispatchingTimeout = seconds_to_nanoseconds(5); mInputInfo.applicationInfo = aInfo; } diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index d1d770e542..a1d12a5ca6 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -22,7 +22,6 @@ #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> #include <binder/ProcessState.h> #include <configstore/Utils.h> -#include <cutils/properties.h> #include <gui/BufferItemConsumer.h> #include <gui/IDisplayEventConnection.h> #include <gui/IProducerListener.h> @@ -835,14 +834,19 @@ public: return NO_ERROR; } status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& /*displayToken*/, - int32_t /*defaultConfig*/, float /*minRefreshRate*/, - float /*maxRefreshRate*/) { + int32_t /*defaultConfig*/, + float /*primaryRefreshRateMin*/, + float /*primaryRefreshRateMax*/, + float /*appRequestRefreshRateMin*/, + float /*appRequestRefreshRateMax*/) { return NO_ERROR; } status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& /*displayToken*/, int32_t* /*outDefaultConfig*/, - float* /*outMinRefreshRate*/, - float* /*outMaxRefreshRate*/) override { + float* /*outPrimaryRefreshRateMin*/, + float* /*outPrimaryRefreshRateMax*/, + float* /*outAppRequestRefreshRateMin*/, + float* /*outAppRequestRefreshRateMax*/) override { return NO_ERROR; }; status_t notifyPowerHint(int32_t /*hintId*/) override { return NO_ERROR; } diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 6e4c97ded2..b27b050d28 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -43,16 +43,15 @@ bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const { } bool InputWindowInfo::isTrustedOverlay() const { - return layoutParamsType == TYPE_INPUT_METHOD - || layoutParamsType == TYPE_INPUT_METHOD_DIALOG - || layoutParamsType == TYPE_MAGNIFICATION_OVERLAY - || layoutParamsType == TYPE_STATUS_BAR - || layoutParamsType == TYPE_NAVIGATION_BAR - || layoutParamsType == TYPE_NAVIGATION_BAR_PANEL - || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY - || layoutParamsType == TYPE_DOCK_DIVIDER - || layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY - || layoutParamsType == TYPE_INPUT_CONSUMER; + return layoutParamsType == TYPE_INPUT_METHOD || layoutParamsType == TYPE_INPUT_METHOD_DIALOG || + layoutParamsType == TYPE_MAGNIFICATION_OVERLAY || layoutParamsType == TYPE_STATUS_BAR || + layoutParamsType == TYPE_NOTIFICATION_SHADE || + layoutParamsType == TYPE_NAVIGATION_BAR || + layoutParamsType == TYPE_NAVIGATION_BAR_PANEL || + layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY || + layoutParamsType == TYPE_DOCK_DIVIDER || + layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY || + layoutParamsType == TYPE_INPUT_CONSUMER; } bool InputWindowInfo::supportsSplitTouch() const { diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index 869ca9ebe3..b78fc5dbbc 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -254,6 +254,7 @@ enum { NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR = 44, /* private */ NATIVE_WINDOW_ALLOCATE_BUFFERS = 45, /* private */ NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER = 46, /* private */ + NATIVE_WINDOW_SET_QUERY_INTERCEPTOR = 47, /* private */ // clang-format on }; @@ -1062,4 +1063,38 @@ static inline int64_t ANativeWindow_getNextFrameId(ANativeWindow* window) { return value; } +/** + * Prototype of the function that an ANativeWindow implementation would call + * when ANativeWindow_query is called. + */ +typedef int (*ANativeWindow_queryFn)(const ANativeWindow* window, int what, int* value); + +/** + * Prototype of the function that intercepts an invocation of + * ANativeWindow_queryFn, along with a data pointer that's passed by the + * caller who set the interceptor, as well as arguments that would be + * passed to ANativeWindow_queryFn if it were to be called. + */ +typedef int (*ANativeWindow_queryInterceptor)(const ANativeWindow* window, + ANativeWindow_queryFn perform, void* data, + int what, int* value); + +/** + * Registers an interceptor for ANativeWindow_query. Instead of calling + * the underlying query function, instead the provided interceptor is + * called, which may optionally call the underlying query function. An + * optional data pointer is also provided to side-channel additional arguments. + * + * Note that usage of this should only be used for specialized use-cases by + * either the system partition or to Mainline modules. This should never be + * exposed to NDK or LL-NDK. + * + * Returns NO_ERROR on success, -errno if registration failed. + */ +static inline int ANativeWindow_setQueryInterceptor(ANativeWindow* window, + ANativeWindow_queryInterceptor interceptor, + void* data) { + return window->perform(window, NATIVE_WINDOW_SET_QUERY_INTERCEPTOR, interceptor, data); +} + __END_DECLS diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index b0b4f6cb8b..92e7e715ea 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -208,9 +208,20 @@ std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(const RenderEngineCre LOG_ALWAYS_FATAL("failed to initialize EGL"); } + const auto eglVersion = eglQueryStringImplementationANDROID(display, EGL_VERSION); + if (!eglVersion) { + checkGlError(__FUNCTION__, __LINE__); + LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_VERSION) failed"); + } + + const auto eglExtensions = eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS); + if (!eglExtensions) { + checkGlError(__FUNCTION__, __LINE__); + LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_EXTENSIONS) failed"); + } + GLExtensions& extensions = GLExtensions::getInstance(); - extensions.initWithEGLStrings(eglQueryStringImplementationANDROID(display, EGL_VERSION), - eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS)); + extensions.initWithEGLStrings(eglVersion, eglExtensions); // The code assumes that ES2 or later is available if this extension is // supported. diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp index d929cc30ba..e01309b679 100644 --- a/libs/ui/Region.cpp +++ b/libs/ui/Region.cpp @@ -67,19 +67,20 @@ const Region Region::INVALID_REGION(Rect::INVALID_RECT); // ---------------------------------------------------------------------------- Region::Region() { - mStorage.add(Rect(0,0)); + mStorage.push_back(Rect(0, 0)); } Region::Region(const Region& rhs) - : mStorage(rhs.mStorage) { + mStorage.clear(); + mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end()); #if defined(VALIDATE_REGIONS) validate(rhs, "rhs copy-ctor"); #endif } Region::Region(const Rect& rhs) { - mStorage.add(rhs); + mStorage.push_back(rhs); } Region::~Region() @@ -100,8 +101,8 @@ Region::~Region() * final, correctly ordered region buffer. Each rectangle will be compared with the span directly * above it, and subdivided to resolve any remaining T-junctions. */ -static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, - Vector<Rect>& dst, int spanDirection) { +static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, FatVector<Rect>& dst, + int spanDirection) { dst.clear(); const Rect* current = end - 1; @@ -109,7 +110,7 @@ static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, // add first span immediately do { - dst.add(*current); + dst.push_back(*current); current--; } while (current->top == lastTop && current >= begin); @@ -147,12 +148,12 @@ static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, if (prev.right <= left) break; if (prev.right > left && prev.right < right) { - dst.add(Rect(prev.right, top, right, bottom)); + dst.push_back(Rect(prev.right, top, right, bottom)); right = prev.right; } if (prev.left > left && prev.left < right) { - dst.add(Rect(prev.left, top, right, bottom)); + dst.push_back(Rect(prev.left, top, right, bottom)); right = prev.left; } @@ -166,12 +167,12 @@ static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, if (prev.left >= right) break; if (prev.left > left && prev.left < right) { - dst.add(Rect(left, top, prev.left, bottom)); + dst.push_back(Rect(left, top, prev.left, bottom)); left = prev.left; } if (prev.right > left && prev.right < right) { - dst.add(Rect(left, top, prev.right, bottom)); + dst.push_back(Rect(left, top, prev.right, bottom)); left = prev.right; } // if an entry in the previous span is too far left, nothing further right in the @@ -183,7 +184,7 @@ static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, } if (left < right) { - dst.add(Rect(left, top, right, bottom)); + dst.push_back(Rect(left, top, right, bottom)); } current--; @@ -201,13 +202,14 @@ Region Region::createTJunctionFreeRegion(const Region& r) { if (r.isEmpty()) return r; if (r.isRect()) return r; - Vector<Rect> reversed; + FatVector<Rect> reversed; reverseRectsResolvingJunctions(r.begin(), r.end(), reversed, direction_RTL); Region outputRegion; - reverseRectsResolvingJunctions(reversed.begin(), reversed.end(), - outputRegion.mStorage, direction_LTR); - outputRegion.mStorage.add(r.getBounds()); // to make region valid, mStorage must end with bounds + reverseRectsResolvingJunctions(reversed.data(), reversed.data() + reversed.size(), + outputRegion.mStorage, direction_LTR); + outputRegion.mStorage.push_back( + r.getBounds()); // to make region valid, mStorage must end with bounds #if defined(VALIDATE_REGIONS) validate(outputRegion, "T-Junction free region"); @@ -222,7 +224,13 @@ Region& Region::operator = (const Region& rhs) validate(*this, "this->operator="); validate(rhs, "rhs.operator="); #endif - mStorage = rhs.mStorage; + if (this == &rhs) { + // Already equal to itself + return *this; + } + + mStorage.clear(); + mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end()); return *this; } @@ -231,7 +239,7 @@ Region& Region::makeBoundsSelf() if (mStorage.size() >= 2) { const Rect bounds(getBounds()); mStorage.clear(); - mStorage.add(bounds); + mStorage.push_back(bounds); } return *this; } @@ -255,25 +263,25 @@ bool Region::contains(int x, int y) const { void Region::clear() { mStorage.clear(); - mStorage.add(Rect(0,0)); + mStorage.push_back(Rect(0, 0)); } void Region::set(const Rect& r) { mStorage.clear(); - mStorage.add(r); + mStorage.push_back(r); } void Region::set(int32_t w, int32_t h) { mStorage.clear(); - mStorage.add(Rect(w, h)); + mStorage.push_back(Rect(w, h)); } void Region::set(uint32_t w, uint32_t h) { mStorage.clear(); - mStorage.add(Rect(w, h)); + mStorage.push_back(Rect(w, h)); } bool Region::isTriviallyEqual(const Region& region) const { @@ -299,8 +307,7 @@ bool Region::hasSameRects(const Region& other) const { void Region::addRectUnchecked(int l, int t, int r, int b) { Rect rect(l,t,r,b); - size_t where = mStorage.size() - 1; - mStorage.insertAt(rect, where, 1); + mStorage.insert(mStorage.end() - 1, rect); } // ---------------------------------------------------------------------------- @@ -358,7 +365,7 @@ Region& Region::translateSelf(int x, int y) { Region& Region::scaleSelf(float sx, float sy) { size_t count = mStorage.size(); - Rect* rects = mStorage.editArray(); + Rect* rects = mStorage.data(); while (count) { rects->left = static_cast<int32_t>(static_cast<float>(rects->left) * sx + 0.5f); rects->right = static_cast<int32_t>(static_cast<float>(rects->right) * sx + 0.5f); @@ -463,10 +470,10 @@ const Region Region::operation(const Region& rhs, int dx, int dy, uint32_t op) c class Region::rasterizer : public region_operator<Rect>::region_rasterizer { Rect bounds; - Vector<Rect>& storage; + FatVector<Rect>& storage; Rect* head; Rect* tail; - Vector<Rect> span; + FatVector<Rect> span; Rect* cur; public: explicit rasterizer(Region& reg) @@ -493,8 +500,8 @@ Region::rasterizer::~rasterizer() flushSpan(); } if (storage.size()) { - bounds.top = storage.itemAt(0).top; - bounds.bottom = storage.top().bottom; + bounds.top = storage.front().top; + bounds.bottom = storage.back().bottom; if (storage.size() == 1) { storage.clear(); } @@ -502,7 +509,7 @@ Region::rasterizer::~rasterizer() bounds.left = 0; bounds.right = 0; } - storage.add(bounds); + storage.push_back(bounds); } void Region::rasterizer::operator()(const Rect& rect) @@ -517,15 +524,15 @@ void Region::rasterizer::operator()(const Rect& rect) return; } } - span.add(rect); - cur = span.editArray() + (span.size() - 1); + span.push_back(rect); + cur = span.data() + (span.size() - 1); } void Region::rasterizer::flushSpan() { bool merge = false; if (tail-head == ssize_t(span.size())) { - Rect const* p = span.editArray(); + Rect const* p = span.data(); Rect const* q = head; if (p->top == q->bottom) { merge = true; @@ -540,17 +547,17 @@ void Region::rasterizer::flushSpan() } } if (merge) { - const int bottom = span[0].bottom; + const int bottom = span.front().bottom; Rect* r = head; while (r != tail) { r->bottom = bottom; r++; } } else { - bounds.left = min(span.itemAt(0).left, bounds.left); - bounds.right = max(span.top().right, bounds.right); - storage.appendVector(span); - tail = storage.editArray() + storage.size(); + bounds.left = min(span.front().left, bounds.left); + bounds.right = max(span.back().right, bounds.right); + storage.insert(storage.end(), span.begin(), span.end()); + tail = storage.data() + storage.size(); head = tail - span.size(); } span.clear(); @@ -558,7 +565,7 @@ void Region::rasterizer::flushSpan() bool Region::validate(const Region& reg, const char* name, bool silent) { - if (reg.mStorage.isEmpty()) { + if (reg.mStorage.empty()) { ALOGE_IF(!silent, "%s: mStorage is empty, which is never valid", name); // return immediately as the code below assumes mStorage is non-empty return false; @@ -697,9 +704,8 @@ void Region::boolean_operation(uint32_t op, Region& dst, } sk_dst.op(sk_lhs, sk_rhs, sk_op); - if (sk_dst.isEmpty() && dst.isEmpty()) - return; - + if (sk_dst.empty() && dst.empty()) return; + bool same = true; Region::const_iterator head = dst.begin(); Region::const_iterator const tail = dst.end(); @@ -794,7 +800,7 @@ void Region::translate(Region& reg, int dx, int dy) validate(reg, "translate (before)"); #endif size_t count = reg.mStorage.size(); - Rect* rects = reg.mStorage.editArray(); + Rect* rects = reg.mStorage.data(); while (count) { rects->offsetBy(dx, dy); rects++; @@ -874,24 +880,25 @@ status_t Region::unflatten(void const* buffer, size_t size) { ALOGE("Region::unflatten() failed, invalid region"); return BAD_VALUE; } - mStorage = result.mStorage; + mStorage.clear(); + mStorage.insert(mStorage.begin(), result.mStorage.begin(), result.mStorage.end()); return NO_ERROR; } // ---------------------------------------------------------------------------- Region::const_iterator Region::begin() const { - return mStorage.array(); + return mStorage.data(); } Region::const_iterator Region::end() const { // Workaround for b/77643177 // mStorage should never be empty, but somehow it is and it's causing // an abort in ubsan - if (mStorage.isEmpty()) return mStorage.array(); + if (mStorage.empty()) return mStorage.data(); size_t numRects = isRect() ? 1 : mStorage.size() - 1; - return mStorage.array() + numRects; + return mStorage.data() + numRects; } Rect const* Region::getArray(size_t* count) const { diff --git a/libs/ui/include/ui/FatVector.h b/libs/ui/include/ui/FatVector.h new file mode 100644 index 0000000000..25fe3a0a2a --- /dev/null +++ b/libs/ui/include/ui/FatVector.h @@ -0,0 +1,93 @@ +/* + * Copyright 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_REGION_FAT_VECTOR_H +#define ANDROID_REGION_FAT_VECTOR_H + +#include <stddef.h> +#include <stdlib.h> +#include <utils/Log.h> +#include <type_traits> + +#include <vector> + +namespace android { + +template <typename T, size_t SIZE = 4> +class InlineStdAllocator { +public: + struct Allocation { + private: + Allocation(const Allocation&) = delete; + void operator=(const Allocation&) = delete; + + public: + Allocation() {} + // char array instead of T array, so memory is uninitialized, with no destructors run + char array[sizeof(T) * SIZE]; + bool inUse = false; + }; + + typedef T value_type; // needed to implement std::allocator + typedef T* pointer; // needed to implement std::allocator + + explicit InlineStdAllocator(Allocation& allocation) : mAllocation(allocation) {} + InlineStdAllocator(const InlineStdAllocator& other) : mAllocation(other.mAllocation) {} + ~InlineStdAllocator() {} + + T* allocate(size_t num, const void* = 0) { + if (!mAllocation.inUse && num <= SIZE) { + mAllocation.inUse = true; + return static_cast<T*>(static_cast<void*>(mAllocation.array)); + } else { + return static_cast<T*>(static_cast<void*>(malloc(num * sizeof(T)))); + } + } + + void deallocate(pointer p, size_t) { + if (p == static_cast<T*>(static_cast<void*>(mAllocation.array))) { + mAllocation.inUse = false; + } else { + // 'free' instead of delete here - destruction handled separately + free(p); + } + } + Allocation& mAllocation; +}; + +/** + * std::vector with SIZE elements preallocated into an internal buffer. + * + * Useful for avoiding the cost of malloc in cases where only SIZE or + * fewer elements are needed in the common case. + */ +template <typename T, size_t SIZE = 4> +class FatVector : public std::vector<T, InlineStdAllocator<T, SIZE>> { +public: + FatVector() + : std::vector<T, InlineStdAllocator<T, SIZE>>(InlineStdAllocator<T, SIZE>(mAllocation)) { + this->reserve(SIZE); + } + + explicit FatVector(size_t capacity) : FatVector() { this->resize(capacity); } + +private: + typename InlineStdAllocator<T, SIZE>::Allocation mAllocation; +}; + +} // namespace android + +#endif // ANDROID_REGION_FAT_VECTOR_H diff --git a/libs/ui/include/ui/Region.h b/libs/ui/include/ui/Region.h index 2db3b10f13..6bb7b8d21c 100644 --- a/libs/ui/include/ui/Region.h +++ b/libs/ui/include/ui/Region.h @@ -21,13 +21,13 @@ #include <sys/types.h> #include <ostream> -#include <utils/Vector.h> - #include <ui/Rect.h> #include <utils/Flattenable.h> #include <android-base/macros.h> +#include "FatVector.h" + #include <string> namespace android { @@ -180,7 +180,7 @@ private: // with an extra Rect as the last element which is set to the // bounds of the region. However, if the region is // a simple Rect then mStorage contains only that rect. - Vector<Rect> mStorage; + FatVector<Rect> mStorage; }; @@ -235,4 +235,3 @@ static inline void PrintTo(const Region& region, ::std::ostream* os) { }; // namespace android #endif // ANDROID_UI_REGION_H - diff --git a/libs/ui/include_vndk/ui/FatVector.h b/libs/ui/include_vndk/ui/FatVector.h new file mode 120000 index 0000000000..bf30166784 --- /dev/null +++ b/libs/ui/include_vndk/ui/FatVector.h @@ -0,0 +1 @@ +../../include/ui/FatVector.h
\ No newline at end of file diff --git a/libs/ui/tests/Region_test.cpp b/libs/ui/tests/Region_test.cpp index b104a46364..c6b826d66e 100644 --- a/libs/ui/tests/Region_test.cpp +++ b/libs/ui/tests/Region_test.cpp @@ -152,5 +152,20 @@ TEST_F(RegionTest, Random_TJunction) { } } +TEST_F(RegionTest, EqualsToSelf) { + Region touchableRegion; + touchableRegion.orSelf(Rect(0, 0, 100, 100)); + + ASSERT_TRUE(touchableRegion.contains(50, 50)); + + // Compiler prevents us from directly calling 'touchableRegion = touchableRegion' + Region& referenceTouchableRegion = touchableRegion; + touchableRegion = referenceTouchableRegion; + + ASSERT_FALSE(touchableRegion.isEmpty()); + + ASSERT_TRUE(touchableRegion.contains(50, 50)); +} + }; // namespace android diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index 7c5c9c5f0c..5a14133eb2 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -28,8 +28,8 @@ static const int32_t DEVICE_ID = 1; static const int32_t INJECTOR_PID = 999; static const int32_t INJECTOR_UID = 1001; -static const int32_t INJECT_EVENT_TIMEOUT = 5000; -static const int32_t DISPATCHING_TIMEOUT = 100000; +static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 5s; +static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 100ms; static nsecs_t now() { return systemTime(SYSTEM_TIME_MONOTONIC); @@ -47,7 +47,7 @@ protected: private: virtual void notifyConfigurationChanged(nsecs_t) override {} - virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&, const sp<IBinder>&, + virtual nsecs_t notifyAnr(const sp<InputApplicationHandle>&, const sp<IBinder>&, const std::string& name) override { ALOGE("The window is not responding : %s", name.c_str()); return 0; @@ -98,7 +98,7 @@ public: virtual ~FakeApplicationHandle() {} virtual bool updateInfo() { - mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT; + mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count(); return true; } }; @@ -163,7 +163,7 @@ public: mInfo.name = "FakeWindowHandle"; mInfo.layoutParamsFlags = 0; mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION; - mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT; + mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count(); mInfo.frameLeft = mFrame.left; mInfo.frameTop = mFrame.top; mInfo.frameRight = mFrame.right; diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index baf2f2b917..155021d325 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -531,7 +531,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { } // Get ready to dispatch the event. - resetANRTimeoutsLocked(); + resetAnrTimeoutsLocked(); } // Now we have an event to dispatch. @@ -888,7 +888,7 @@ void InputDispatcher::drainInboundQueueLocked() { void InputDispatcher::releasePendingEventLocked() { if (mPendingEvent) { - resetANRTimeoutsLocked(); + resetAnrTimeoutsLocked(); releaseInboundEventLocked(mPendingEvent); mPendingEvent = nullptr; } @@ -1299,7 +1299,7 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked( } if (currentTime >= mInputTargetWaitTimeoutTime) { - onANRLocked(currentTime, applicationHandle, windowHandle, entry.eventTime, + onAnrLocked(currentTime, applicationHandle, windowHandle, entry.eventTime, mInputTargetWaitStartTime, reason); // Force poll loop to wake up immediately on next iteration once we get the @@ -1352,7 +1352,7 @@ nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(nsecs_t current return 0; } -void InputDispatcher::resetANRTimeoutsLocked() { +void InputDispatcher::resetAnrTimeoutsLocked() { if (DEBUG_FOCUS) { ALOGD("Resetting ANR timeouts."); } @@ -3273,14 +3273,14 @@ void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) { int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t injectorPid, int32_t injectorUid, int32_t syncMode, - int32_t timeoutMillis, uint32_t policyFlags) { + std::chrono::milliseconds timeout, uint32_t policyFlags) { #if DEBUG_INBOUND_EVENT_DETAILS ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, " - "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x", - event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags); + "syncMode=%d, timeout=%lld, policyFlags=0x%08x", + event->getType(), injectorPid, injectorUid, syncMode, timeout.count(), policyFlags); #endif - nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis); + nsecs_t endTime = now() + std::chrono::duration_cast<std::chrono::nanoseconds>(timeout).count(); policyFlags |= POLICY_FLAG_INJECTED; if (hasInjectionPermission(injectorPid, injectorUid)) { @@ -3467,8 +3467,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t injec } // release lock #if DEBUG_INJECTION - ALOGD("injectInputEvent - Finished with result %d. " - "injectorPid=%d, injectorUid=%d", + ALOGD("injectInputEvent - Finished with result %d. injectorPid=%d, injectorUid=%d", injectionResult, injectorPid, injectorUid); #endif @@ -3800,12 +3799,12 @@ void InputDispatcher::setFocusedApplication( if (inputApplicationHandle != nullptr && inputApplicationHandle->updateInfo()) { if (oldFocusedApplicationHandle != inputApplicationHandle) { if (oldFocusedApplicationHandle != nullptr) { - resetANRTimeoutsLocked(); + resetAnrTimeoutsLocked(); } mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle; } } else if (oldFocusedApplicationHandle != nullptr) { - resetANRTimeoutsLocked(); + resetAnrTimeoutsLocked(); oldFocusedApplicationHandle.clear(); mFocusedApplicationHandlesByDisplay.erase(displayId); } @@ -3886,7 +3885,7 @@ void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) { if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) { if (mDispatchFrozen && !frozen) { - resetANRTimeoutsLocked(); + resetAnrTimeoutsLocked(); } if (mDispatchEnabled && !enabled) { @@ -4026,7 +4025,7 @@ void InputDispatcher::resetAndDropEverythingLocked(const char* reason) { resetKeyRepeatLocked(); releasePendingEventLocked(); drainInboundQueueLocked(); - resetANRTimeoutsLocked(); + resetAnrTimeoutsLocked(); mTouchStatesByDisplay.clear(); mLastHoverWindowHandle.clear(); @@ -4526,7 +4525,7 @@ void InputDispatcher::onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus postCommandLocked(std::move(commandEntry)); } -void InputDispatcher::onANRLocked(nsecs_t currentTime, +void InputDispatcher::onAnrLocked(nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle, const sp<InputWindowHandle>& windowHandle, nsecs_t eventTime, nsecs_t waitStartTime, const char* reason) { @@ -4543,19 +4542,19 @@ void InputDispatcher::onANRLocked(nsecs_t currentTime, localtime_r(&t, &tm); char timestr[64]; strftime(timestr, sizeof(timestr), "%F %T", &tm); - mLastANRState.clear(); - mLastANRState += INDENT "ANR:\n"; - mLastANRState += StringPrintf(INDENT2 "Time: %s\n", timestr); - mLastANRState += + mLastAnrState.clear(); + mLastAnrState += INDENT "ANR:\n"; + mLastAnrState += StringPrintf(INDENT2 "Time: %s\n", timestr); + mLastAnrState += StringPrintf(INDENT2 "Window: %s\n", getApplicationWindowLabel(applicationHandle, windowHandle).c_str()); - mLastANRState += StringPrintf(INDENT2 "DispatchLatency: %0.1fms\n", dispatchLatency); - mLastANRState += StringPrintf(INDENT2 "WaitDuration: %0.1fms\n", waitDuration); - mLastANRState += StringPrintf(INDENT2 "Reason: %s\n", reason); - dumpDispatchStateLocked(mLastANRState); + mLastAnrState += StringPrintf(INDENT2 "DispatchLatency: %0.1fms\n", dispatchLatency); + mLastAnrState += StringPrintf(INDENT2 "WaitDuration: %0.1fms\n", waitDuration); + mLastAnrState += StringPrintf(INDENT2 "Reason: %s\n", reason); + dumpDispatchStateLocked(mLastAnrState); std::unique_ptr<CommandEntry> commandEntry = - std::make_unique<CommandEntry>(&InputDispatcher::doNotifyANRLockedInterruptible); + std::make_unique<CommandEntry>(&InputDispatcher::doNotifyAnrLockedInterruptible); commandEntry->inputApplicationHandle = applicationHandle; commandEntry->inputChannel = windowHandle != nullptr ? getInputChannelLocked(windowHandle->getToken()) : nullptr; @@ -4591,13 +4590,13 @@ void InputDispatcher::doNotifyFocusChangedLockedInterruptible(CommandEntry* comm mLock.lock(); } -void InputDispatcher::doNotifyANRLockedInterruptible(CommandEntry* commandEntry) { +void InputDispatcher::doNotifyAnrLockedInterruptible(CommandEntry* commandEntry) { sp<IBinder> token = commandEntry->inputChannel ? commandEntry->inputChannel->getConnectionToken() : nullptr; mLock.unlock(); nsecs_t newTimeout = - mPolicy->notifyANR(commandEntry->inputApplicationHandle, token, commandEntry->reason); + mPolicy->notifyAnr(commandEntry->inputApplicationHandle, token, commandEntry->reason); mLock.lock(); @@ -4958,9 +4957,9 @@ void InputDispatcher::dump(std::string& dump) { dump += "Input Dispatcher State:\n"; dumpDispatchStateLocked(dump); - if (!mLastANRState.empty()) { + if (!mLastAnrState.empty()) { dump += "\nInput Dispatcher State at time of last ANR:\n"; - dump += mLastANRState; + dump += mLastAnrState; } } diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 2b9cbcec2e..670d0e1c96 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -103,7 +103,8 @@ public: virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override; virtual int32_t injectInputEvent(const InputEvent* event, int32_t injectorPid, - int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis, + int32_t injectorUid, int32_t syncMode, + std::chrono::milliseconds timeout, uint32_t policyFlags) override; virtual std::unique_ptr<VerifiedInputEvent> verifyInputEvent(const InputEvent& event) override; @@ -314,7 +315,7 @@ private: int32_t mFocusedDisplayId GUARDED_BY(mLock); // Dispatcher state at time of last ANR. - std::string mLastANRState GUARDED_BY(mLock); + std::string mLastAnrState GUARDED_BY(mLock); // Dispatch inbound events. bool dispatchConfigurationChangedLocked(nsecs_t currentTime, ConfigurationChangedEntry* entry) @@ -360,7 +361,7 @@ private: const sp<IBinder>& inputConnectionToken) REQUIRES(mLock); nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime) REQUIRES(mLock); - void resetANRTimeoutsLocked() REQUIRES(mLock); + void resetAnrTimeoutsLocked() REQUIRES(mLock); int32_t getTargetDisplayId(const EventEntry& entry); int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry& entry, @@ -468,7 +469,7 @@ private: REQUIRES(mLock); void onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus, const sp<InputWindowHandle>& newFocus) REQUIRES(mLock); - void onANRLocked(nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle, + void onAnrLocked(nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle, const sp<InputWindowHandle>& windowHandle, nsecs_t eventTime, nsecs_t waitStartTime, const char* reason) REQUIRES(mLock); @@ -477,7 +478,7 @@ private: REQUIRES(mLock); void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); - void doNotifyANRLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); + void doNotifyAnrLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h index 09dc92c8fa..9b002f437c 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h @@ -90,8 +90,8 @@ public: * This method may be called on any thread (usually by the input manager). */ virtual int32_t injectInputEvent(const InputEvent* event, int32_t injectorPid, - int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis, - uint32_t policyFlags) = 0; + int32_t injectorUid, int32_t syncMode, + std::chrono::milliseconds timeout, uint32_t policyFlags) = 0; /* * Check whether InputEvent actually happened by checking the signature of the event. diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h index 4214488f04..667af9bbd8 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h @@ -47,7 +47,7 @@ public: /* Notifies the system that an application is not responding. * Returns a new timeout to continue waiting, or 0 to abort dispatch. */ - virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle, + virtual nsecs_t notifyAnr(const sp<InputApplicationHandle>& inputApplicationHandle, const sp<IBinder>& token, const std::string& reason) = 0; /* Notifies the system that an input channel is unrecoverably broken. */ diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index e0d32a0382..eeff757b48 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -127,19 +127,16 @@ private: mConfigurationChangedTime = when; } - virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&, - const sp<IBinder>&, - const std::string&) { + virtual nsecs_t notifyAnr(const sp<InputApplicationHandle>&, const sp<IBinder>&, + const std::string&) override { return 0; } - virtual void notifyInputChannelBroken(const sp<IBinder>&) { - } + virtual void notifyInputChannelBroken(const sp<IBinder>&) override {} - virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) { - } + virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {} - virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) { + virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override { *outConfig = mConfig; } @@ -160,19 +157,17 @@ private: return true; } - virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) { - } + virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {} - virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) { - } + virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {} - virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, - const KeyEvent*, uint32_t) { + virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, + uint32_t) override { return 0; } - virtual bool dispatchUnhandledKey(const sp<IBinder>&, - const KeyEvent*, uint32_t, KeyEvent*) { + virtual bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, + KeyEvent*) override { return false; } @@ -184,14 +179,13 @@ private: mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask); } - virtual void pokeUserActivity(nsecs_t, int32_t) { - } + virtual void pokeUserActivity(nsecs_t, int32_t) override {} - virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) { + virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override { return false; } - virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) { + virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override { mOnPointerDownToken = newToken; } @@ -313,18 +307,18 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) { INVALID_HMAC, /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, - INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, + mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, + INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0)) << "Should reject key events with undefined action."; // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API. event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, - INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, + mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, + INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0)) << "Should reject key events with ACTION_MULTIPLE."; } @@ -350,9 +344,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { 1 /* yScale */, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, - INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, + mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, + INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0)) << "Should reject motion events with undefined action."; // Rejects pointer down with invalid index. @@ -363,9 +357,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, - INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, + mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, + INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0)) << "Should reject motion events with pointer down index too large."; event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, @@ -375,9 +369,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, - INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, + mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, + INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0)) << "Should reject motion events with pointer down index too small."; // Rejects pointer up with invalid index. @@ -388,9 +382,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, - INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, + mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, + INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0)) << "Should reject motion events with pointer up index too large."; event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, @@ -400,9 +394,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, - INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, + mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, + INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0)) << "Should reject motion events with pointer up index too small."; // Rejects motion events with invalid number of pointers. @@ -412,9 +406,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 0, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, - INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, + mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, + INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0)) << "Should reject motion events with 0 pointers."; event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, @@ -423,9 +417,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, - INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, + mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, + INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0)) << "Should reject motion events with more than MAX_POINTERS pointers."; // Rejects motion events with invalid pointer ids. @@ -436,9 +430,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, - INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, + mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, + INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0)) << "Should reject motion events with pointer ids less than 0."; pointerProperties[0].id = MAX_POINTER_ID + 1; @@ -448,9 +442,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, - INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, + mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, + INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0)) << "Should reject motion events with pointer ids greater than MAX_POINTER_ID."; // Rejects motion events with duplicate pointer ids. @@ -462,9 +456,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 2, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, - INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, + mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, + INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0)) << "Should reject motion events with duplicate pointer ids."; } @@ -490,16 +484,16 @@ TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) { } // --- InputDispatcherTest SetInputWindowTest --- -static constexpr int32_t INJECT_EVENT_TIMEOUT = 500; -static constexpr nsecs_t DISPATCHING_TIMEOUT = seconds_to_nanoseconds(5); +static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms; +static constexpr std::chrono::duration DISPATCHING_TIMEOUT = 5s; class FakeApplicationHandle : public InputApplicationHandle { public: FakeApplicationHandle() {} virtual ~FakeApplicationHandle() {} - virtual bool updateInfo() { - mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT; + virtual bool updateInfo() override { + mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count(); return true; } }; @@ -634,11 +628,11 @@ public: mInfo.applicationInfo = *inputApplicationHandle->getInfo(); mInfo.token = token; - mInfo.id = 0; + mInfo.id = sId++; mInfo.name = name; mInfo.layoutParamsFlags = 0; mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION; - mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT; + mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count(); mInfo.frameLeft = 0; mInfo.frameTop = 0; mInfo.frameRight = WIDTH; @@ -672,8 +666,6 @@ public: void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; } - void setId(int32_t id) { mInfo.id = id; } - void setWindowScale(float xScale, float yScale) { mInfo.windowXScale = xScale; mInfo.windowYScale = yScale; @@ -755,8 +747,11 @@ public: private: const std::string mName; std::unique_ptr<FakeInputReceiver> mInputReceiver; + static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger }; +std::atomic<int32_t> FakeWindowHandle::sId{1}; + static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) { KeyEvent event; @@ -810,13 +805,15 @@ static int32_t injectMotionEvent(const sp<InputDispatcher>& dispatcher, int32_t } static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source, - int32_t displayId, int32_t x = 100, int32_t y = 200) { - return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, x, y); + int32_t displayId, const PointF& location = {100, 200}) { + return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location.x, + location.y); } static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source, - int32_t displayId, int32_t x = 100, int32_t y = 200) { - return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, x, y); + int32_t displayId, const PointF& location = {100, 200}) { + return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location.x, + location.y); } static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) { @@ -880,6 +877,55 @@ TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) { window->consumeMotionDown(ADISPLAY_ID_DEFAULT); } +/** + * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues. + * To ensure that window receives only events that were directly inside of it, add + * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input + * when finding touched windows. + * This test serves as a sanity check for the next test, where setInputWindows is + * called twice. + */ +TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) { + sp<FakeApplicationHandle> application = new FakeApplicationHandle(); + sp<FakeWindowHandle> window = + new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT); + window->setFrame(Rect(0, 0, 100, 100)); + window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); + + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); + ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, + injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {50, 50})) + << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; + + // Window should receive motion event. + window->consumeMotionDown(ADISPLAY_ID_DEFAULT); +} + +/** + * Calling setInputWindows twice, with the same info, should not cause any issues. + * To ensure that window receives only events that were directly inside of it, add + * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input + * when finding touched windows. + */ +TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) { + sp<FakeApplicationHandle> application = new FakeApplicationHandle(); + sp<FakeWindowHandle> window = + new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT); + window->setFrame(Rect(0, 0, 100, 100)); + window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); + + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); + ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, + injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {50, 50})) + << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; + + // Window should receive motion event. + window->consumeMotionDown(ADISPLAY_ID_DEFAULT); +} + // The foreground window should receive the first touch down event. TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) { sp<FakeApplicationHandle> application = new FakeApplicationHandle(); @@ -1821,7 +1867,6 @@ class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest { new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT); mFocusedWindow->setFrame(Rect(50, 50, 100, 100)); mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); - mFocusedWindowTouchPoint = 60; // Set focused application. mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); @@ -1842,15 +1887,16 @@ class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest { protected: sp<FakeWindowHandle> mUnfocusedWindow; sp<FakeWindowHandle> mFocusedWindow; - int32_t mFocusedWindowTouchPoint; + static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60}; }; // Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action // DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received // the onPointerDownOutsideFocus callback. TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) { - ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, - AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20)) + ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, + injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {20, 20})) << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; mUnfocusedWindow->consumeMotionDown(); @@ -1862,8 +1908,8 @@ TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Succe // DOWN on the window that doesn't have focus. Ensure no window received the // onPointerDownOutsideFocus callback. TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) { - ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, - AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20)) + ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, + injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20})) << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; mFocusedWindow->consumeMotionDown(); @@ -1889,7 +1935,7 @@ TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) { ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, - mFocusedWindowTouchPoint, mFocusedWindowTouchPoint)) + FOCUSED_WINDOW_TOUCH_POINT)) << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; mFocusedWindow->consumeMotionDown(); @@ -1910,14 +1956,12 @@ class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest { // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows. mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL | InputWindowInfo::FLAG_SPLIT_TOUCH); - mWindow1->setId(0); mWindow1->setFrame(Rect(0, 0, 100, 100)); mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2", ADISPLAY_ID_DEFAULT, mWindow1->getToken()); mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL | InputWindowInfo::FLAG_SPLIT_TOUCH); - mWindow2->setId(1); mWindow2->setFrame(Rect(100, 100, 200, 200)); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}}); diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index fb72ab8065..78bbcba4b4 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -93,11 +93,6 @@ status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32 uint32_t* outTransformHint) { if (mFlinger->authenticateSurfaceTexture(parent) == false) { ALOGE("failed to authenticate surface texture"); - // The extra parent layer check below before returning is to help with debugging - // b/134888387. Once the bug is fixed the check can be deleted. - if ((static_cast<MonitoredProducer*>(parent.get()))->getLayer() == nullptr) { - ALOGE("failed to find parent layer"); - } return BAD_VALUE; } diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h index d3712d9a5e..a0606b48f0 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h @@ -24,6 +24,7 @@ #include <compositionengine/LayerFE.h> #include <compositionengine/OutputColorSetting.h> #include <math/mat4.h> +#include <ui/Transform.h> namespace android::compositionengine { @@ -57,6 +58,9 @@ struct CompositionRefreshArgs { // Forces a color mode on the outputs being refreshed ui::ColorMode forceOutputColorMode{ui::ColorMode::NATIVE}; + // Used to correctly apply an inverse-display buffer transform if applicable + ui::Transform::RotationFlags internalDisplayRotationFlags{ui::Transform::ROT_0}; + // If true, GPU clocks will be increased when rendering blurs bool blursAreExpensive{false}; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h index cf77738ced..aa70ef836d 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h @@ -19,6 +19,7 @@ #include <optional> #include <string> +#include <ui/Transform.h> #include <utils/StrongPointer.h> // TODO(b/129481165): remove the #pragma below and fix conversion issues @@ -77,7 +78,12 @@ public: // Recalculates the state of the output layer from the output-independent // layer. If includeGeometry is false, the geometry state can be skipped. - virtual void updateCompositionState(bool includeGeometry, bool forceClientComposition) = 0; + // internalDisplayRotationFlags must be set to the rotation flags for the + // internal display, and is used to properly compute the inverse-display + // transform, if needed. + virtual void updateCompositionState( + bool includeGeometry, bool forceClientComposition, + ui::Transform::RotationFlags internalDisplayRotationFlags) = 0; // Writes the geometry state to the HWC, or does nothing if this layer does // not use the HWC. If includeGeometry is false, the geometry state can be diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h index 79df9b2551..8cb5ae8b8e 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h @@ -39,7 +39,8 @@ public: void setHwcLayer(std::shared_ptr<HWC2::Layer>) override; - void updateCompositionState(bool includeGeometry, bool forceClientComposition) override; + void updateCompositionState(bool includeGeometry, bool forceClientComposition, + ui::Transform::RotationFlags) override; void writeStateToHWC(bool) override; void writeCursorPositionToHWC() const override; @@ -55,7 +56,8 @@ public: virtual FloatRect calculateOutputSourceCrop() const; virtual Rect calculateOutputDisplayFrame() const; - virtual uint32_t calculateOutputRelativeBufferTransform() const; + virtual uint32_t calculateOutputRelativeBufferTransform( + uint32_t internalDisplayRotationFlags) const; protected: // Implemented by the final implementation for the final state it uses. diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h index 2ecbad803f..81e1fc7ea0 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h @@ -38,7 +38,7 @@ public: MOCK_CONST_METHOD0(getState, const impl::OutputLayerCompositionState&()); MOCK_METHOD0(editState, impl::OutputLayerCompositionState&()); - MOCK_METHOD2(updateCompositionState, void(bool, bool)); + MOCK_METHOD3(updateCompositionState, void(bool, bool, ui::Transform::RotationFlags)); MOCK_METHOD1(writeStateToHWC, void(bool)); MOCK_CONST_METHOD0(writeCursorPositionToHWC, void()); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 34d0cb2b67..e8f54f57b1 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -588,7 +588,8 @@ void Output::updateAndWriteCompositionState( for (auto* layer : getOutputLayersOrderedByZ()) { layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame, refreshArgs.devOptForceClientComposition || - forceClientComposition); + forceClientComposition, + refreshArgs.internalDisplayRotationFlags); if (mLayerRequestingBackgroundBlur == layer) { forceClientComposition = false; @@ -815,6 +816,43 @@ std::optional<base::unique_fd> Output::composeSurfaces( OutputCompositionState& outputCompositionState = editState(); const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition", outputState.usesClientComposition}; + + auto& renderEngine = getCompositionEngine().getRenderEngine(); + const bool supportsProtectedContent = renderEngine.supportsProtectedContent(); + + // If we the display is secure, protected content support is enabled, and at + // least one layer has protected content, we need to use a secure back + // buffer. + if (outputState.isSecure && supportsProtectedContent) { + auto layers = getOutputLayersOrderedByZ(); + bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) { + return layer->getLayerFE().getCompositionState()->hasProtectedContent; + }); + if (needsProtected != renderEngine.isProtected()) { + renderEngine.useProtectedContext(needsProtected); + } + if (needsProtected != mRenderSurface->isProtected() && + needsProtected == renderEngine.isProtected()) { + mRenderSurface->setProtected(needsProtected); + } + } + + base::unique_fd fd; + sp<GraphicBuffer> buf; + + // If we aren't doing client composition on this output, but do have a + // flipClientTarget request for this frame on this output, we still need to + // dequeue a buffer. + if (hasClientComposition || outputState.flipClientTarget) { + buf = mRenderSurface->dequeueBuffer(&fd); + if (buf == nullptr) { + ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " + "client composition for this frame", + mName.c_str()); + return {}; + } + } + base::unique_fd readyFence; if (!hasClientComposition) { setExpensiveRenderingExpected(false); @@ -823,9 +861,6 @@ std::optional<base::unique_fd> Output::composeSurfaces( ALOGV("hasClientComposition"); - auto& renderEngine = getCompositionEngine().getRenderEngine(); - const bool supportsProtectedContent = renderEngine.supportsProtectedContent(); - renderengine::DisplaySettings clientCompositionDisplay; clientCompositionDisplay.physicalDisplay = outputState.destinationClip; clientCompositionDisplay.clip = outputState.sourceClip; @@ -851,32 +886,6 @@ std::optional<base::unique_fd> Output::composeSurfaces( clientCompositionDisplay.outputDataspace); appendRegionFlashRequests(debugRegion, clientCompositionLayers); - // If we the display is secure, protected content support is enabled, and at - // least one layer has protected content, we need to use a secure back - // buffer. - if (outputState.isSecure && supportsProtectedContent) { - auto layers = getOutputLayersOrderedByZ(); - bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) { - return layer->getLayerFE().getCompositionState()->hasProtectedContent; - }); - if (needsProtected != renderEngine.isProtected()) { - renderEngine.useProtectedContext(needsProtected); - } - if (needsProtected != mRenderSurface->isProtected() && - needsProtected == renderEngine.isProtected()) { - mRenderSurface->setProtected(needsProtected); - } - } - - base::unique_fd fd; - sp<GraphicBuffer> buf = mRenderSurface->dequeueBuffer(&fd); - if (buf == nullptr) { - ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " - "client composition for this frame", - mName.c_str()); - return std::nullopt; - } - // Check if the client composition requests were rendered into the provided graphic buffer. If // so, we can reuse the buffer and avoid client composition. if (mClientCompositionRequestCache) { diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index c9a070d6f9..81f2dd1e08 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -223,7 +223,8 @@ Rect OutputLayer::calculateOutputDisplayFrame() const { return displayTransform.transform(frame); } -uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const { +uint32_t OutputLayer::calculateOutputRelativeBufferTransform( + uint32_t internalDisplayRotationFlags) const { const auto& layerState = *getLayerFE().getCompositionState(); const auto& outputState = getOutput().getState(); @@ -241,10 +242,11 @@ uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const { if (layerState.geomBufferUsesDisplayInverseTransform) { /* - * the code below applies the primary display's inverse transform to the - * buffer + * We must apply the internal display's inverse transform to the buffer + * transform, and not the one for the output this layer is on. */ - uint32_t invTransform = outputState.orientation; + uint32_t invTransform = internalDisplayRotationFlags; + // calculate the inverse transform if (invTransform & HAL_TRANSFORM_ROT_90) { invTransform ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H; @@ -261,9 +263,11 @@ uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const { // this gives us only the "orientation" component of the transform return transform.getOrientation(); -} // namespace impl +} -void OutputLayer::updateCompositionState(bool includeGeometry, bool forceClientComposition) { +void OutputLayer::updateCompositionState( + bool includeGeometry, bool forceClientComposition, + ui::Transform::RotationFlags internalDisplayRotationFlags) { const auto* layerFEState = getLayerFE().getCompositionState(); if (!layerFEState) { return; @@ -283,8 +287,8 @@ void OutputLayer::updateCompositionState(bool includeGeometry, bool forceClientC state.displayFrame = calculateOutputDisplayFrame(); state.sourceCrop = calculateOutputSourceCrop(); - state.bufferTransform = - static_cast<Hwc2::Transform>(calculateOutputRelativeBufferTransform()); + state.bufferTransform = static_cast<Hwc2::Transform>( + calculateOutputRelativeBufferTransform(internalDisplayRotationFlags)); if ((layerFEState->isSecure && !outputState.isSecure) || (state.bufferTransform & ui::Transform::ROT_INVALID)) { diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index 59889b696a..62977a4335 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -30,6 +30,7 @@ #include <compositionengine/mock/OutputLayer.h> #include <compositionengine/mock/RenderSurface.h> #include <gtest/gtest.h> +#include <renderengine/mock/RenderEngine.h> #include <ui/DisplayInfo.h> #include <ui/Rect.h> @@ -156,6 +157,8 @@ struct DisplayTestCommon : public testing::Test { DisplayTestCommon() { EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer)); + EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine)); + EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); } DisplayCreationArgs getDisplayCreationArgsForPhysicalHWCDisplay() { @@ -182,6 +185,7 @@ struct DisplayTestCommon : public testing::Test { StrictMock<android::mock::HWComposer> mHwComposer; StrictMock<Hwc2::mock::PowerAdvisor> mPowerAdvisor; + StrictMock<renderengine::mock::RenderEngine> mRenderEngine; StrictMock<mock::CompositionEngine> mCompositionEngine; sp<mock::NativeWindow> mNativeWindow = new StrictMock<mock::NativeWindow>(); }; diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index bdacb22686..020f93a607 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -361,7 +361,7 @@ TEST_F(OutputLayerTest, calculateOutputRelativeBufferTransformTestsNeeded) { mOutputState.orientation = entry.display; mOutputState.transform = ui::Transform{entry.display}; - auto actual = mOutputLayer.calculateOutputRelativeBufferTransform(); + const auto actual = mOutputLayer.calculateOutputRelativeBufferTransform(entry.display); EXPECT_EQ(entry.expected, actual) << "entry " << i; } } @@ -371,56 +371,109 @@ TEST_F(OutputLayerTest, mLayerFEState.geomBufferUsesDisplayInverseTransform = true; struct Entry { - uint32_t layer; + uint32_t layer; /* shouldn't affect the result, so we just use arbitrary values */ uint32_t buffer; uint32_t display; + uint32_t internal; uint32_t expected; }; - // Not an exhaustive list of cases, but hopefully enough. - const std::array<Entry, 24> testData = { + const std::array<Entry, 64> testData = { // clang-format off - // layer buffer display expected - /* 0 */ Entry{TR_IDENT, TR_IDENT, TR_IDENT, TR_IDENT}, - /* 1 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_90, TR_IDENT}, - /* 2 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_180, TR_IDENT}, - /* 3 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_270, TR_IDENT}, - - /* 4 */ Entry{TR_IDENT, TR_FLP_H, TR_IDENT, TR_FLP_H}, - /* 5 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_90, TR_FLP_H}, - /* 6 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_180, TR_FLP_H}, - /* 7 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_270, TR_FLP_H}, - - /* 8 */ Entry{TR_IDENT, TR_FLP_V, TR_IDENT, TR_FLP_V}, - /* 9 */ Entry{TR_IDENT, TR_ROT_90, TR_ROT_90, TR_ROT_90}, - /* 10 */ Entry{TR_IDENT, TR_ROT_180, TR_ROT_180, TR_ROT_180}, - /* 11 */ Entry{TR_IDENT, TR_ROT_270, TR_ROT_270, TR_ROT_270}, - - /* 12 */ Entry{TR_ROT_90, TR_IDENT, TR_IDENT, TR_IDENT}, - /* 13 */ Entry{TR_ROT_90, TR_FLP_H, TR_ROT_90, TR_FLP_H}, - /* 14 */ Entry{TR_ROT_90, TR_IDENT, TR_ROT_180, TR_IDENT}, - /* 15 */ Entry{TR_ROT_90, TR_FLP_H, TR_ROT_270, TR_FLP_H}, - - /* 16 */ Entry{TR_ROT_180, TR_FLP_H, TR_IDENT, TR_FLP_H}, - /* 17 */ Entry{TR_ROT_180, TR_IDENT, TR_ROT_90, TR_IDENT}, - /* 18 */ Entry{TR_ROT_180, TR_FLP_H, TR_ROT_180, TR_FLP_H}, - /* 19 */ Entry{TR_ROT_180, TR_IDENT, TR_ROT_270, TR_IDENT}, - - /* 20 */ Entry{TR_ROT_270, TR_IDENT, TR_IDENT, TR_IDENT}, - /* 21 */ Entry{TR_ROT_270, TR_FLP_H, TR_ROT_90, TR_FLP_H}, - /* 22 */ Entry{TR_ROT_270, TR_FLP_H, TR_ROT_180, TR_FLP_H}, - /* 23 */ Entry{TR_ROT_270, TR_IDENT, TR_ROT_270, TR_IDENT}, + // layer buffer display internal expected + Entry{TR_IDENT, TR_IDENT, TR_IDENT, TR_IDENT, TR_IDENT}, + Entry{TR_IDENT, TR_IDENT, TR_IDENT, TR_ROT_90, TR_ROT_270}, + Entry{TR_IDENT, TR_IDENT, TR_IDENT, TR_ROT_180, TR_ROT_180}, + Entry{TR_IDENT, TR_IDENT, TR_IDENT, TR_ROT_270, TR_ROT_90}, + + Entry{TR_IDENT, TR_IDENT, TR_ROT_90, TR_IDENT, TR_ROT_90}, + Entry{TR_ROT_90, TR_IDENT, TR_ROT_90, TR_ROT_90, TR_IDENT}, + Entry{TR_ROT_180, TR_IDENT, TR_ROT_90, TR_ROT_180, TR_ROT_270}, + Entry{TR_ROT_90, TR_IDENT, TR_ROT_90, TR_ROT_270, TR_ROT_180}, + + Entry{TR_ROT_180, TR_IDENT, TR_ROT_180, TR_IDENT, TR_ROT_180}, + Entry{TR_ROT_90, TR_IDENT, TR_ROT_180, TR_ROT_90, TR_ROT_90}, + Entry{TR_ROT_180, TR_IDENT, TR_ROT_180, TR_ROT_180, TR_IDENT}, + Entry{TR_ROT_270, TR_IDENT, TR_ROT_180, TR_ROT_270, TR_ROT_270}, + + Entry{TR_ROT_270, TR_IDENT, TR_ROT_270, TR_IDENT, TR_ROT_270}, + Entry{TR_ROT_270, TR_IDENT, TR_ROT_270, TR_ROT_90, TR_ROT_180}, + Entry{TR_ROT_180, TR_IDENT, TR_ROT_270, TR_ROT_180, TR_ROT_90}, + Entry{TR_IDENT, TR_IDENT, TR_ROT_270, TR_ROT_270, TR_IDENT}, + + // layer buffer display internal expected + Entry{TR_IDENT, TR_ROT_90, TR_IDENT, TR_IDENT, TR_ROT_90}, + Entry{TR_ROT_90, TR_ROT_90, TR_IDENT, TR_ROT_90, TR_IDENT}, + Entry{TR_ROT_180, TR_ROT_90, TR_IDENT, TR_ROT_180, TR_ROT_270}, + Entry{TR_ROT_270, TR_ROT_90, TR_IDENT, TR_ROT_270, TR_ROT_180}, + + Entry{TR_ROT_90, TR_ROT_90, TR_ROT_90, TR_IDENT, TR_ROT_180}, + Entry{TR_ROT_90, TR_ROT_90, TR_ROT_90, TR_ROT_90, TR_ROT_90}, + Entry{TR_ROT_90, TR_ROT_90, TR_ROT_90, TR_ROT_180, TR_IDENT}, + Entry{TR_ROT_270, TR_ROT_90, TR_ROT_90, TR_ROT_270, TR_ROT_270}, + + Entry{TR_IDENT, TR_ROT_90, TR_ROT_180, TR_IDENT, TR_ROT_270}, + Entry{TR_ROT_90, TR_ROT_90, TR_ROT_180, TR_ROT_90, TR_ROT_180}, + Entry{TR_ROT_180, TR_ROT_90, TR_ROT_180, TR_ROT_180, TR_ROT_90}, + Entry{TR_ROT_90, TR_ROT_90, TR_ROT_180, TR_ROT_270, TR_IDENT}, + + Entry{TR_IDENT, TR_ROT_90, TR_ROT_270, TR_IDENT, TR_IDENT}, + Entry{TR_ROT_270, TR_ROT_90, TR_ROT_270, TR_ROT_90, TR_ROT_270}, + Entry{TR_ROT_180, TR_ROT_90, TR_ROT_270, TR_ROT_180, TR_ROT_180}, + Entry{TR_ROT_270, TR_ROT_90, TR_ROT_270, TR_ROT_270, TR_ROT_90}, + + // layer buffer display internal expected + Entry{TR_IDENT, TR_ROT_180, TR_IDENT, TR_IDENT, TR_ROT_180}, + Entry{TR_IDENT, TR_ROT_180, TR_IDENT, TR_ROT_90, TR_ROT_90}, + Entry{TR_ROT_180, TR_ROT_180, TR_IDENT, TR_ROT_180, TR_IDENT}, + Entry{TR_ROT_270, TR_ROT_180, TR_IDENT, TR_ROT_270, TR_ROT_270}, + + Entry{TR_IDENT, TR_ROT_180, TR_ROT_90, TR_IDENT, TR_ROT_270}, + Entry{TR_ROT_90, TR_ROT_180, TR_ROT_90, TR_ROT_90, TR_ROT_180}, + Entry{TR_ROT_180, TR_ROT_180, TR_ROT_90, TR_ROT_180, TR_ROT_90}, + Entry{TR_ROT_180, TR_ROT_180, TR_ROT_90, TR_ROT_270, TR_IDENT}, + + Entry{TR_IDENT, TR_ROT_180, TR_ROT_180, TR_IDENT, TR_IDENT}, + Entry{TR_ROT_180, TR_ROT_180, TR_ROT_180, TR_ROT_90, TR_ROT_270}, + Entry{TR_ROT_180, TR_ROT_180, TR_ROT_180, TR_ROT_180, TR_ROT_180}, + Entry{TR_ROT_270, TR_ROT_180, TR_ROT_180, TR_ROT_270, TR_ROT_90}, + + Entry{TR_ROT_270, TR_ROT_180, TR_ROT_270, TR_IDENT, TR_ROT_90}, + Entry{TR_ROT_180, TR_ROT_180, TR_ROT_270, TR_ROT_90, TR_IDENT}, + Entry{TR_ROT_180, TR_ROT_180, TR_ROT_270, TR_ROT_180, TR_ROT_270}, + Entry{TR_ROT_270, TR_ROT_180, TR_ROT_270, TR_ROT_270, TR_ROT_180}, + + // layer buffer display internal expected + Entry{TR_IDENT, TR_ROT_270, TR_IDENT, TR_IDENT, TR_ROT_270}, + Entry{TR_ROT_90, TR_ROT_270, TR_IDENT, TR_ROT_90, TR_ROT_180}, + Entry{TR_ROT_270, TR_ROT_270, TR_IDENT, TR_ROT_180, TR_ROT_90}, + Entry{TR_IDENT, TR_ROT_270, TR_IDENT, TR_ROT_270, TR_IDENT}, + + Entry{TR_ROT_270, TR_ROT_270, TR_ROT_90, TR_IDENT, TR_IDENT}, + Entry{TR_ROT_90, TR_ROT_270, TR_ROT_90, TR_ROT_90, TR_ROT_270}, + Entry{TR_ROT_180, TR_ROT_270, TR_ROT_90, TR_ROT_180, TR_ROT_180}, + Entry{TR_ROT_90, TR_ROT_270, TR_ROT_90, TR_ROT_270, TR_ROT_90}, + + Entry{TR_IDENT, TR_ROT_270, TR_ROT_180, TR_IDENT, TR_ROT_90}, + Entry{TR_ROT_270, TR_ROT_270, TR_ROT_180, TR_ROT_90, TR_IDENT}, + Entry{TR_ROT_180, TR_ROT_270, TR_ROT_180, TR_ROT_180, TR_ROT_270}, + Entry{TR_ROT_270, TR_ROT_270, TR_ROT_180, TR_ROT_270, TR_ROT_180}, + + Entry{TR_IDENT, TR_ROT_270, TR_ROT_270, TR_IDENT, TR_ROT_180}, + Entry{TR_ROT_90, TR_ROT_270, TR_ROT_270, TR_ROT_90, TR_ROT_90}, + Entry{TR_ROT_270, TR_ROT_270, TR_ROT_270, TR_ROT_180, TR_IDENT}, + Entry{TR_ROT_270, TR_ROT_270, TR_ROT_270, TR_ROT_270, TR_ROT_270}, // clang-format on }; for (size_t i = 0; i < testData.size(); i++) { const auto& entry = testData[i]; - mLayerFEState.geomLayerTransform = ui::Transform{entry.layer}; + mLayerFEState.geomLayerTransform.set(entry.layer, 1920, 1080); mLayerFEState.geomBufferTransform = entry.buffer; mOutputState.orientation = entry.display; mOutputState.transform = ui::Transform{entry.display}; - auto actual = mOutputLayer.calculateOutputRelativeBufferTransform(); + const auto actual = mOutputLayer.calculateOutputRelativeBufferTransform(entry.internal); EXPECT_EQ(entry.expected, actual) << "entry " << i; } } @@ -436,7 +489,7 @@ struct OutputLayerPartialMockForUpdateCompositionState : public impl::OutputLaye // Mock everything called by updateCompositionState to simplify testing it. MOCK_CONST_METHOD0(calculateOutputSourceCrop, FloatRect()); MOCK_CONST_METHOD0(calculateOutputDisplayFrame, Rect()); - MOCK_CONST_METHOD0(calculateOutputRelativeBufferTransform, uint32_t()); + MOCK_CONST_METHOD1(calculateOutputRelativeBufferTransform, uint32_t(uint32_t)); // compositionengine::OutputLayer overrides const compositionengine::Output& getOutput() const override { return mOutput; } @@ -463,10 +516,11 @@ public: ~OutputLayerUpdateCompositionStateTest() = default; - void setupGeometryChildCallValues() { + void setupGeometryChildCallValues(ui::Transform::RotationFlags internalDisplayRotationFlags) { EXPECT_CALL(mOutputLayer, calculateOutputSourceCrop()).WillOnce(Return(kSourceCrop)); EXPECT_CALL(mOutputLayer, calculateOutputDisplayFrame()).WillOnce(Return(kDisplayFrame)); - EXPECT_CALL(mOutputLayer, calculateOutputRelativeBufferTransform()) + EXPECT_CALL(mOutputLayer, + calculateOutputRelativeBufferTransform(internalDisplayRotationFlags)) .WillOnce(Return(mBufferTransform)); } @@ -489,7 +543,7 @@ public: TEST_F(OutputLayerUpdateCompositionStateTest, doesNothingIfNoFECompositionState) { EXPECT_CALL(*mLayerFE, getCompositionState()).WillOnce(Return(nullptr)); - mOutputLayer.updateCompositionState(true, false); + mOutputLayer.updateCompositionState(true, false, ui::Transform::RotationFlags::ROT_90); } TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) { @@ -497,9 +551,9 @@ TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) { mOutputState.isSecure = true; mOutputLayer.editState().forceClientComposition = true; - setupGeometryChildCallValues(); + setupGeometryChildCallValues(ui::Transform::RotationFlags::ROT_90); - mOutputLayer.updateCompositionState(true, false); + mOutputLayer.updateCompositionState(true, false, ui::Transform::RotationFlags::ROT_90); validateComputedGeometryState(); @@ -511,9 +565,9 @@ TEST_F(OutputLayerUpdateCompositionStateTest, mLayerFEState.isSecure = true; mOutputState.isSecure = false; - setupGeometryChildCallValues(); + setupGeometryChildCallValues(ui::Transform::RotationFlags::ROT_0); - mOutputLayer.updateCompositionState(true, false); + mOutputLayer.updateCompositionState(true, false, ui::Transform::RotationFlags::ROT_0); validateComputedGeometryState(); @@ -527,9 +581,9 @@ TEST_F(OutputLayerUpdateCompositionStateTest, mBufferTransform = ui::Transform::ROT_INVALID; - setupGeometryChildCallValues(); + setupGeometryChildCallValues(ui::Transform::RotationFlags::ROT_0); - mOutputLayer.updateCompositionState(true, false); + mOutputLayer.updateCompositionState(true, false, ui::Transform::RotationFlags::ROT_0); validateComputedGeometryState(); @@ -544,7 +598,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, setsOutputLayerColorspaceCorrectly // should use the layers requested colorspace. mLayerFEState.isColorspaceAgnostic = false; - mOutputLayer.updateCompositionState(false, false); + mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0); EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutputLayer.getState().dataspace); @@ -552,7 +606,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, setsOutputLayerColorspaceCorrectly // should use the colorspace chosen for the whole output. mLayerFEState.isColorspaceAgnostic = true; - mOutputLayer.updateCompositionState(false, false); + mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0); EXPECT_EQ(ui::Dataspace::V0_SCRGB, mOutputLayer.getState().dataspace); } @@ -560,7 +614,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, setsOutputLayerColorspaceCorrectly TEST_F(OutputLayerUpdateCompositionStateTest, doesNotRecomputeGeometryIfNotRequested) { mOutputLayer.editState().forceClientComposition = false; - mOutputLayer.updateCompositionState(false, false); + mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0); EXPECT_EQ(false, mOutputLayer.getState().forceClientComposition); } @@ -569,7 +623,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, doesNotClearForceClientCompositionIfNotDoingGeometry) { mOutputLayer.editState().forceClientComposition = true; - mOutputLayer.updateCompositionState(false, false); + mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0); EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition); } @@ -578,7 +632,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, clientCompositionForcedFromFrontEn mLayerFEState.forceClientComposition = true; mOutputLayer.editState().forceClientComposition = false; - mOutputLayer.updateCompositionState(false, false); + mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0); EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition); } @@ -588,7 +642,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, mOutputLayer.editState().forceClientComposition = false; EXPECT_CALL(mDisplayColorProfile, isDataspaceSupported(_)).WillRepeatedly(Return(false)); - mOutputLayer.updateCompositionState(false, false); + mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0); EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition); } @@ -597,15 +651,15 @@ TEST_F(OutputLayerUpdateCompositionStateTest, clientCompositionForcedFromArgumen mLayerFEState.forceClientComposition = false; mOutputLayer.editState().forceClientComposition = false; - mOutputLayer.updateCompositionState(false, true); + mOutputLayer.updateCompositionState(false, true, ui::Transform::RotationFlags::ROT_0); EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition); mOutputLayer.editState().forceClientComposition = false; - setupGeometryChildCallValues(); + setupGeometryChildCallValues(ui::Transform::RotationFlags::ROT_0); - mOutputLayer.updateCompositionState(true, true); + mOutputLayer.updateCompositionState(true, true, ui::Transform::RotationFlags::ROT_0); EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition); } @@ -810,7 +864,7 @@ TEST_F(OutputLayerTest, displayInstallOrientationBufferTransformSetTo90) { // geomBufferTransform is set to the inverse transform. mLayerFEState.geomBufferTransform = TR_ROT_270; - EXPECT_EQ(TR_IDENT, mOutputLayer.calculateOutputRelativeBufferTransform()); + EXPECT_EQ(TR_IDENT, mOutputLayer.calculateOutputRelativeBufferTransform(ui::Transform::ROT_90)); } TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSolidColor) { diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 1c9cd9c0c0..59ed72e928 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -696,11 +696,11 @@ TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerContentForAllLayers InjectedLayer layer2; InjectedLayer layer3; - EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, false)); + EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_180)); EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(false)); - EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, false)); + EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_180)); EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(false)); - EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false)); + EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_180)); EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(false)); injectOutputLayer(layer1); @@ -712,6 +712,7 @@ TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerContentForAllLayers CompositionRefreshArgs args; args.updatingGeometryThisFrame = false; args.devOptForceClientComposition = false; + args.internalDisplayRotationFlags = ui::Transform::ROT_180; mOutput->updateAndWriteCompositionState(args); } @@ -720,11 +721,11 @@ TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerGeometryAndContentF InjectedLayer layer2; InjectedLayer layer3; - EXPECT_CALL(*layer1.outputLayer, updateCompositionState(true, false)); + EXPECT_CALL(*layer1.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0)); EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(true)); - EXPECT_CALL(*layer2.outputLayer, updateCompositionState(true, false)); + EXPECT_CALL(*layer2.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0)); EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(true)); - EXPECT_CALL(*layer3.outputLayer, updateCompositionState(true, false)); + EXPECT_CALL(*layer3.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0)); EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(true)); injectOutputLayer(layer1); @@ -744,11 +745,11 @@ TEST_F(OutputUpdateAndWriteCompositionStateTest, forcesClientCompositionForAllLa InjectedLayer layer2; InjectedLayer layer3; - EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true)); + EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0)); EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(false)); - EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true)); + EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0)); EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(false)); - EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, true)); + EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0)); EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(false)); injectOutputLayer(layer1); @@ -2797,6 +2798,7 @@ struct OutputComposeSurfacesTest : public testing::Test { mOutput.mState.usesClientComposition = true; mOutput.mState.usesDeviceComposition = false; mOutput.mState.reusedClientComposition = false; + mOutput.mState.flipClientTarget = false; EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine)); EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine)); @@ -2868,19 +2870,40 @@ const HdrCapabilities OutputComposeSurfacesTest:: TEST_F(OutputComposeSurfacesTest, doesNothingButSignalNoExpensiveRenderingIfNoClientComposition) { mOutput.mState.usesClientComposition = false; + EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); + EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)); verify().execute().expectAFenceWasReturned(); } -TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFails) { - EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false)); - EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true)); +TEST_F(OutputComposeSurfacesTest, + dequeuesABufferIfNoClientCompositionButFlipClientTargetRequested) { + mOutput.mState.usesClientComposition = false; + mOutput.mState.flipClientTarget = true; + + EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); + + EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer)); + EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)); + + verify().execute().expectAFenceWasReturned(); +} + +TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFailsForClientComposition) { + EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); + + EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr)); + + verify().execute().expectNoFenceWasReturned(); +} + +TEST_F(OutputComposeSurfacesTest, + doesMinimalWorkIfDequeueBufferFailsForNoClientCompositionButFlipClientTargetRequested) { + mOutput.mState.usesClientComposition = false; + mOutput.mState.flipClientTarget = true; + EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); - EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace)) - .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{})); - EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)) - .WillRepeatedly(Return()); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr)); @@ -3315,7 +3338,7 @@ struct OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur mLayer.layerFEState.backgroundBlurRadius = 10; mOutput.editState().isEnabled = true; - EXPECT_CALL(mLayer.outputLayer, updateCompositionState(false, true)); + EXPECT_CALL(mLayer.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0)); EXPECT_CALL(mLayer.outputLayer, writeStateToHWC(false)); EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace)) .WillOnce(Return(std::vector<LayerFE::LayerSettings>{})); @@ -3894,11 +3917,11 @@ TEST_F(OutputUpdateAndWriteCompositionStateTest, handlesBackgroundBlurRequests) InjectedLayer layer3; // Layer requesting blur, or below, should request client composition. - EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true)); + EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0)); EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(false)); - EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true)); + EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0)); EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(false)); - EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false)); + EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0)); EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(false)); layer2.layerFEState.backgroundBlurRadius = 10; diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 0ea33408db..fb82033dfa 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -349,7 +349,7 @@ Error Display::getName(std::string* outName) const Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests, std::unordered_map<HWC2::Layer*, LayerRequest>* outLayerRequests) { - uint32_t intDisplayRequests; + uint32_t intDisplayRequests = 0; std::vector<Hwc2::Layer> layerIds; std::vector<uint32_t> layerRequests; auto intError = mComposer.getDisplayRequests( diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 845295775d..752407aedc 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1532,17 +1532,33 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { void Layer::miniDumpHeader(std::string& result) { result.append("-------------------------------"); result.append("-------------------------------"); - result.append("-----------------------------\n"); + result.append("-------------------------------"); + result.append("-------------------------------"); + result.append("---------\n"); result.append(" Layer name\n"); result.append(" Z | "); result.append(" Window Type | "); result.append(" Comp Type | "); result.append(" Transform | "); result.append(" Disp Frame (LTRB) | "); - result.append(" Source Crop (LTRB)\n"); + result.append(" Source Crop (LTRB) | "); + result.append(" Frame Rate (Explicit)\n"); + result.append("-------------------------------"); result.append("-------------------------------"); result.append("-------------------------------"); - result.append("-----------------------------\n"); + result.append("-------------------------------"); + result.append("---------\n"); +} + +std::string Layer::frameRateCompatibilityString(Layer::FrameRateCompatibility compatibility) { + switch (compatibility) { + case FrameRateCompatibility::Default: + return "Default"; + case FrameRateCompatibility::ExactOrMultiple: + return "ExactOrMultiple"; + case FrameRateCompatibility::NoVote: + return "NoVote"; + } } void Layer::miniDump(std::string& result, const sp<DisplayDevice>& displayDevice) const { @@ -1578,12 +1594,21 @@ void Layer::miniDump(std::string& result, const sp<DisplayDevice>& displayDevice const Rect& frame = outputLayerState.displayFrame; StringAppendF(&result, "%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom); const FloatRect& crop = outputLayerState.sourceCrop; - StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right, + StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right, crop.bottom); + if (layerState.frameRate.rate != 0 || + layerState.frameRate.type != FrameRateCompatibility::Default) { + StringAppendF(&result, "% 6.2ffps %15s\n", layerState.frameRate.rate, + frameRateCompatibilityString(layerState.frameRate.type).c_str()); + } else { + StringAppendF(&result, "\n"); + } - result.append("- - - - - - - - - - - - - - - -"); - result.append("- - - - - - - - - - - - - - - -"); - result.append("- - - - - - - - - - - - - - -\n"); + result.append("- - - - - - - - - - - - - - - - "); + result.append("- - - - - - - - - - - - - - - - "); + result.append("- - - - - - - - - - - - - - - - "); + result.append("- - - - - - - - - - - - - - - - "); + result.append("- - -\n"); } void Layer::dumpFrameStats(std::string& result) const { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 6636b5e54a..b6303335cb 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -819,6 +819,7 @@ public: bool setFrameRate(FrameRate frameRate); virtual FrameRate getFrameRateForLayerTree() const; + static std::string frameRateCompatibilityString(FrameRateCompatibility compatibility); protected: // constant diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 2e7fbc1a78..f602412930 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -200,26 +200,22 @@ void RefreshRateOverlay::primeCache() { } } -void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { - const auto display = mFlinger.getDefaultDisplayDeviceLocked(); - if (!display) { - return; - } +void RefreshRateOverlay::setViewport(ui::Size viewport) { + Rect frame(viewport.width >> 3, viewport.height >> 5); + frame.offsetBy(viewport.width >> 5, viewport.height >> 4); + mLayer->setFrame(frame); - const int32_t left = display->getWidth() / 32; - const int32_t top = display->getHeight() / 32; - const int32_t right = left + display->getWidth() / 8; - const int32_t buttom = top + display->getHeight() / 32; + mFlinger.mTransactionFlags.fetch_or(eTransactionMask); +} +void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { auto buffer = mBufferCache[refreshRate.getFps()]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}); - mLayer->setFrame(Rect(left, top, right, buttom)); - mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } -}; // namespace android +} // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h index 6d34df220c..35c80201d7 100644 --- a/services/surfaceflinger/RefreshRateOverlay.h +++ b/services/surfaceflinger/RefreshRateOverlay.h @@ -13,19 +13,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #pragma once -#include "SurfaceFlinger.h" +#include <unordered_map> + +#include <math/vec4.h> +#include <ui/Rect.h> +#include <ui/Size.h> +#include <utils/StrongPointer.h> + +#include "Scheduler/RefreshRateConfigs.h" namespace android { +class Client; +class GraphicBuffer; +class IBinder; +class IGraphicBufferProducer; +class Layer; +class SurfaceFlinger; + using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; class RefreshRateOverlay { public: - RefreshRateOverlay(SurfaceFlinger& flinger); + explicit RefreshRateOverlay(SurfaceFlinger&); - void changeRefreshRate(const RefreshRate& refreshRate); + void setViewport(ui::Size); + void changeRefreshRate(const RefreshRate&); private: class SevenSegmentDrawer { @@ -56,7 +72,7 @@ private: void primeCache(); SurfaceFlinger& mFlinger; - sp<Client> mClient; + const sp<Client> mClient; sp<Layer> mLayer; sp<IBinder> mIBinder; sp<IGraphicBufferProducer> mGbp; @@ -68,4 +84,4 @@ private: const half3 HIGH_FPS_COLOR = half3(0.0f, 1.0f, 0.0f); }; -}; // namespace android +} // namespace android diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp index bf1fb88de7..44b4264f20 100644 --- a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp @@ -111,21 +111,28 @@ std::optional<float> LayerInfoV2::calculateRefreshRateIfPossible() { // Calculate the refresh rate by finding the average delta between frames nsecs_t totalPresentTimeDeltas = 0; + int numFrames = 0; for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) { // If there are no presentation timestamp provided we can't calculate the refresh rate if (it->presetTime == 0 || (it + 1)->presetTime == 0) { - return std::nullopt; + continue; } totalPresentTimeDeltas += std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod); + numFrames++; + } + if (numFrames == 0) { + return std::nullopt; } - const float averageFrameTime = - static_cast<float>(totalPresentTimeDeltas) / (mFrameTimes.size() - 1); + const float averageFrameTime = static_cast<float>(totalPresentTimeDeltas) / numFrames; // Now once we calculated the refresh rate we need to make sure that all the frames we captured // are evenly distributed and we don't calculate the average across some burst of frames. for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) { + if (it->presetTime == 0 || (it + 1)->presetTime == 0) { + continue; + } const nsecs_t presentTimeDeltas = std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod); if (std::abs(presentTimeDeltas - averageFrameTime) > 2 * averageFrameTime) { diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 5634adb9fd..8d958df572 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -58,7 +58,7 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContent( ATRACE_INT("ContentFPS", contentFramerate); // Find the appropriate refresh rate with minimal error - auto iter = min_element(mAvailableRefreshRates.cbegin(), mAvailableRefreshRates.cend(), + auto iter = min_element(mPrimaryRefreshRates.cbegin(), mPrimaryRefreshRates.cend(), [contentFramerate](const auto& lhs, const auto& rhs) -> bool { return std::abs(lhs->fps - contentFramerate) < std::abs(rhs->fps - contentFramerate); @@ -71,7 +71,7 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContent( constexpr float MARGIN = 0.05f; float ratio = (*iter)->fps / contentFramerate; if (std::abs(std::round(ratio) - ratio) > MARGIN) { - while (iter != mAvailableRefreshRates.cend()) { + while (iter != mPrimaryRefreshRates.cend()) { ratio = (*iter)->fps / contentFramerate; if (std::abs(std::round(ratio) - ratio) <= MARGIN) { @@ -97,8 +97,8 @@ std::pair<nsecs_t, nsecs_t> RefreshRateConfigs::getDisplayFrames(nsecs_t layerPe return {displayFramesQuot, displayFramesRem}; } -const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( - const std::vector<LayerRequirement>& layers, bool touchActive, +const RefreshRate& RefreshRateConfigs::getBestRefreshRate( + const std::vector<LayerRequirement>& layers, bool touchActive, bool idle, bool* touchConsidered) const { ATRACE_CALL(); ALOGV("getRefreshRateForContent %zu layers", layers.size()); @@ -106,13 +106,6 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( *touchConsidered = false; std::lock_guard lock(mLock); - // If there are not layers, there is not content detection, so return the current - // refresh rate. - if (layers.empty()) { - *touchConsidered = touchActive; - return touchActive ? *mAvailableRefreshRates.back() : getCurrentRefreshRateByPolicyLocked(); - } - int noVoteLayers = 0; int minVoteLayers = 0; int maxVoteLayers = 0; @@ -135,25 +128,33 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( } } - // Consider the touch event if there are no ExplicitDefault layers. - // ExplicitDefault are mostly interactive (as opposed to ExplicitExactOrMultiple) - // and therefore if those posted an explicit vote we should not change it - // if get get a touch event. - if (touchActive && explicitDefaultVoteLayers == 0) { + // Consider the touch event if there are no Explicit* layers. Otherwise wait until after we've + // selected a refresh rate to see if we should apply touch boost. + if (touchActive && explicitDefaultVoteLayers == 0 && explicitExactOrMultipleVoteLayers == 0) { *touchConsidered = true; - return *mAvailableRefreshRates.back(); + return getMaxRefreshRateByPolicyLocked(); + } + + if (!touchActive && idle) { + return getMinRefreshRateByPolicyLocked(); + } + + if (layers.empty()) { + return getCurrentRefreshRateByPolicyLocked(); } // Only if all layers want Min we should return Min if (noVoteLayers + minVoteLayers == layers.size()) { - return *mAvailableRefreshRates.front(); + return getMinRefreshRateByPolicyLocked(); } + const Policy* policy = getCurrentPolicyLocked(); + // Find the best refresh rate based on score std::vector<std::pair<const RefreshRate*, float>> scores; - scores.reserve(mAvailableRefreshRates.size()); + scores.reserve(mAppRequestRefreshRates.size()); - for (const auto refreshRate : mAvailableRefreshRates) { + for (const auto refreshRate : mAppRequestRefreshRates) { scores.emplace_back(refreshRate, 0.0f); } @@ -166,6 +167,15 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( auto weight = layer.weight; for (auto i = 0u; i < scores.size(); i++) { + bool inPrimaryRange = + scores[i].first->inPolicy(policy->primaryRange.min, policy->primaryRange.max); + if (!inPrimaryRange && layer.vote != LayerVoteType::ExplicitDefault && + layer.vote != LayerVoteType::ExplicitExactOrMultiple) { + // Only layers with explicit frame rate settings are allowed to score refresh rates + // outside the primary range. + continue; + } + // If the layer wants Max, give higher score to the higher refresh rate if (layer.vote == LayerVoteType::Max) { const auto ratio = scores[i].first->fps / scores.back().first->fps; @@ -249,6 +259,17 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( ? getBestRefreshRate(scores.rbegin(), scores.rend()) : getBestRefreshRate(scores.begin(), scores.end()); + // Consider the touch event if there are no ExplicitDefault layers. ExplicitDefault are mostly + // interactive (as opposed to ExplicitExactOrMultiple) and therefore if those posted an explicit + // vote we should not change it if we get a touch event. Only apply touch boost if it will + // actually increase the refresh rate over the normal selection. + const RefreshRate& touchRefreshRate = getMaxRefreshRateByPolicyLocked(); + if (touchActive && explicitDefaultVoteLayers == 0 && + bestRefreshRate->fps < touchRefreshRate.fps) { + *touchConsidered = true; + return touchRefreshRate; + } + return *bestRefreshRate; } @@ -278,12 +299,20 @@ const AllRefreshRatesMapType& RefreshRateConfigs::getAllRefreshRates() const { const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicy() const { std::lock_guard lock(mLock); - return *mAvailableRefreshRates.front(); + return getMinRefreshRateByPolicyLocked(); +} + +const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const { + return *mPrimaryRefreshRates.front(); } const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicy() const { std::lock_guard lock(mLock); - return *mAvailableRefreshRates.back(); + return getMaxRefreshRateByPolicyLocked(); +} + +const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked() const { + return *mPrimaryRefreshRates.back(); } const RefreshRate& RefreshRateConfigs::getCurrentRefreshRate() const { @@ -297,8 +326,8 @@ const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicy() const { } const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicyLocked() const { - if (std::find(mAvailableRefreshRates.begin(), mAvailableRefreshRates.end(), - mCurrentRefreshRate) != mAvailableRefreshRates.end()) { + if (std::find(mAppRequestRefreshRates.begin(), mAppRequestRefreshRates.end(), + mCurrentRefreshRate) != mAppRequestRefreshRates.end()) { return *mCurrentRefreshRate; } return *mRefreshRates.at(getCurrentPolicyLocked()->defaultConfig); @@ -320,7 +349,7 @@ RefreshRateConfigs::RefreshRateConfigs( const float fps = 1e9f / config->getVsyncPeriod(); mRefreshRates.emplace(configId, std::make_unique<RefreshRate>(configId, config, - base::StringPrintf("%2.ffps", fps), fps, + base::StringPrintf("%.0ffps", fps), fps, RefreshRate::ConstructorTag(0))); if (configId == currentConfigId) { mCurrentRefreshRate = mRefreshRates.at(configId).get(); @@ -342,10 +371,11 @@ bool RefreshRateConfigs::isPolicyValid(const Policy& policy) { return false; } const RefreshRate& refreshRate = *iter->second; - if (!refreshRate.inPolicy(policy.minRefreshRate, policy.maxRefreshRate)) { + if (!refreshRate.inPolicy(policy.primaryRange.min, policy.primaryRange.max)) { return false; } - return true; + return policy.appRequestRange.min <= policy.primaryRange.min && + policy.appRequestRange.max >= policy.primaryRange.max; } status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) { @@ -392,7 +422,7 @@ RefreshRateConfigs::Policy RefreshRateConfigs::getDisplayManagerPolicy() const { bool RefreshRateConfigs::isConfigAllowed(HwcConfigIndexType config) const { std::lock_guard lock(mLock); - for (const RefreshRate* refreshRate : mAvailableRefreshRates) { + for (const RefreshRate* refreshRate : mAppRequestRefreshRates) { if (refreshRate->configId == config) { return true; } @@ -430,33 +460,44 @@ void RefreshRateConfigs::constructAvailableRefreshRates() { // Filter configs based on current policy and sort based on vsync period const Policy* policy = getCurrentPolicyLocked(); const auto& defaultConfig = mRefreshRates.at(policy->defaultConfig)->hwcConfig; - ALOGV("constructAvailableRefreshRates: default %d group %d min %.2f max %.2f", - policy->defaultConfig.value(), defaultConfig->getConfigGroup(), policy->minRefreshRate, - policy->maxRefreshRate); - getSortedRefreshRateList( - [&](const RefreshRate& refreshRate) REQUIRES(mLock) { - const auto& hwcConfig = refreshRate.hwcConfig; - - return hwcConfig->getHeight() == defaultConfig->getHeight() && - hwcConfig->getWidth() == defaultConfig->getWidth() && - hwcConfig->getDpiX() == defaultConfig->getDpiX() && - hwcConfig->getDpiY() == defaultConfig->getDpiY() && - (policy->allowGroupSwitching || - hwcConfig->getConfigGroup() == defaultConfig->getConfigGroup()) && - refreshRate.inPolicy(policy->minRefreshRate, policy->maxRefreshRate); - }, - &mAvailableRefreshRates); - - std::string availableRefreshRates; - for (const auto& refreshRate : mAvailableRefreshRates) { - base::StringAppendF(&availableRefreshRates, "%s ", refreshRate->name.c_str()); - } - - ALOGV("Available refresh rates: %s", availableRefreshRates.c_str()); - LOG_ALWAYS_FATAL_IF(mAvailableRefreshRates.empty(), - "No compatible display configs for default=%d min=%.0f max=%.0f", - policy->defaultConfig.value(), policy->minRefreshRate, - policy->maxRefreshRate); + ALOGV("constructAvailableRefreshRates: default %d group %d primaryRange=[%.2f %.2f]" + " appRequestRange=[%.2f %.2f]", + policy->defaultConfig.value(), defaultConfig->getConfigGroup(), policy->primaryRange.min, + policy->primaryRange.max, policy->appRequestRange.min, policy->appRequestRange.max); + + auto filterRefreshRates = [&](float min, float max, const char* listName, + std::vector<const RefreshRate*>* outRefreshRates) { + getSortedRefreshRateList( + [&](const RefreshRate& refreshRate) REQUIRES(mLock) { + const auto& hwcConfig = refreshRate.hwcConfig; + + return hwcConfig->getHeight() == defaultConfig->getHeight() && + hwcConfig->getWidth() == defaultConfig->getWidth() && + hwcConfig->getDpiX() == defaultConfig->getDpiX() && + hwcConfig->getDpiY() == defaultConfig->getDpiY() && + (policy->allowGroupSwitching || + hwcConfig->getConfigGroup() == defaultConfig->getConfigGroup()) && + refreshRate.inPolicy(min, max); + }, + outRefreshRates); + + LOG_ALWAYS_FATAL_IF(outRefreshRates->empty(), + "No matching configs for %s range: min=%.0f max=%.0f", listName, min, + max); + auto stringifyRefreshRates = [&]() -> std::string { + std::string str; + for (auto refreshRate : *outRefreshRates) { + base::StringAppendF(&str, "%s ", refreshRate->name.c_str()); + } + return str; + }; + ALOGV("%s refresh rates: %s", listName, stringifyRefreshRates().c_str()); + }; + + filterRefreshRates(policy->primaryRange.min, policy->primaryRange.max, "primary", + &mPrimaryRefreshRates); + filterRefreshRates(policy->appRequestRange.min, policy->appRequestRange.max, "app request", + &mAppRequestRefreshRates); } } // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index dea7e90896..2657dee538 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -107,18 +107,46 @@ public: std::unordered_map<HwcConfigIndexType, std::unique_ptr<const RefreshRate>>; struct Policy { + struct Range { + float min = 0; + float max = std::numeric_limits<float>::max(); + + bool operator==(const Range& other) const { + return min == other.min && max == other.max; + } + + bool operator!=(const Range& other) const { return !(*this == other); } + }; + // The default config, used to ensure we only initiate display config switches within the // same config group as defaultConfigId's group. HwcConfigIndexType defaultConfig; - // The min and max FPS allowed by the policy. - float minRefreshRate = 0; - float maxRefreshRate = std::numeric_limits<float>::max(); + // The primary refresh rate range represents display manager's general guidance on the + // display configs we'll consider when switching refresh rates. Unless we get an explicit + // signal from an app, we should stay within this range. + Range primaryRange; + // The app request refresh rate range allows us to consider more display configs when + // switching refresh rates. Although we should generally stay within the primary range, + // specific considerations, such as layer frame rate settings specified via the + // setFrameRate() api, may cause us to go outside the primary range. We never go outside the + // app request range. The app request range will be greater than or equal to the primary + // refresh rate range, never smaller. + Range appRequestRange; // Whether or not we switch config groups to get the best frame rate. Only used by tests. bool allowGroupSwitching = false; + Policy() = default; + Policy(HwcConfigIndexType defaultConfig, const Range& range) + : Policy(defaultConfig, range, range) {} + Policy(HwcConfigIndexType defaultConfig, const Range& primaryRange, + const Range& appRequestRange) + : defaultConfig(defaultConfig), + primaryRange(primaryRange), + appRequestRange(appRequestRange) {} + bool operator==(const Policy& other) const { - return defaultConfig == other.defaultConfig && minRefreshRate == other.minRefreshRate && - maxRefreshRate == other.maxRefreshRate && + return defaultConfig == other.defaultConfig && primaryRange == other.primaryRange && + appRequestRange == other.appRequestRange && allowGroupSwitching == other.allowGroupSwitching; } @@ -184,12 +212,14 @@ public: const RefreshRate& getRefreshRateForContent(const std::vector<LayerRequirement>& layers) const EXCLUDES(mLock); - // Returns the refresh rate that fits best to the given layers. This function also gets a - // boolean flag that indicates whether user touched the screen recently to be factored in when - // choosing the refresh rate and returns whether the refresh rate was chosen as a result of - // a touch event. - const RefreshRate& getRefreshRateForContentV2(const std::vector<LayerRequirement>& layers, - bool touchActive, bool* touchConsidered) const + // Returns the refresh rate that fits best to the given layers. + // layers - The layer requirements to consider. + // touchActive - Whether the user touched the screen recently. Used to apply touch boost. + // idle - True if the system hasn't seen any buffers posted to layers recently. + // touchConsidered - An output param that tells the caller whether the refresh rate was chosen + // based on touch boost. + const RefreshRate& getBestRefreshRate(const std::vector<LayerRequirement>& layers, + bool touchActive, bool idle, bool* touchConsidered) const EXCLUDES(mLock); // Returns all the refresh rates supported by the device. This won't change at runtime. @@ -198,13 +228,15 @@ public: // Returns the lowest refresh rate supported by the device. This won't change at runtime. const RefreshRate& getMinRefreshRate() const { return *mMinSupportedRefreshRate; } - // Returns the lowest refresh rate according to the current policy. May change in runtime. + // Returns the lowest refresh rate according to the current policy. May change at runtime. Only + // uses the primary range, not the app request range. const RefreshRate& getMinRefreshRateByPolicy() const EXCLUDES(mLock); // Returns the highest refresh rate supported by the device. This won't change at runtime. const RefreshRate& getMaxRefreshRate() const { return *mMaxSupportedRefreshRate; } - // Returns the highest refresh rate according to the current policy. May change in runtime. + // Returns the highest refresh rate according to the current policy. May change at runtime. Only + // uses the primary range, not the app request range. const RefreshRate& getMaxRefreshRateByPolicy() const EXCLUDES(mLock); // Returns the current refresh rate @@ -243,6 +275,14 @@ private: // display refresh period. std::pair<nsecs_t, nsecs_t> getDisplayFrames(nsecs_t layerPeriod, nsecs_t displayPeriod) const; + // Returns the lowest refresh rate according to the current policy. May change at runtime. Only + // uses the primary range, not the app request range. + const RefreshRate& getMinRefreshRateByPolicyLocked() const REQUIRES(mLock); + + // Returns the highest refresh rate according to the current policy. May change at runtime. Only + // uses the primary range, not the app request range. + const RefreshRate& getMaxRefreshRateByPolicyLocked() const REQUIRES(mLock); + // Returns the current refresh rate, if allowed. Otherwise the default that is allowed by // the policy. const RefreshRate& getCurrentRefreshRateByPolicyLocked() const REQUIRES(mLock); @@ -254,9 +294,13 @@ private: // object is initialized. AllRefreshRatesMapType mRefreshRates; - // The list of refresh rates which are available in the current policy, ordered by vsyncPeriod - // (the first element is the lowest refresh rate) - std::vector<const RefreshRate*> mAvailableRefreshRates GUARDED_BY(mLock); + // The list of refresh rates in the primary range of the current policy, ordered by vsyncPeriod + // (the first element is the lowest refresh rate). + std::vector<const RefreshRate*> mPrimaryRefreshRates GUARDED_BY(mLock); + + // The list of refresh rates in the app request range of the current policy, ordered by + // vsyncPeriod (the first element is the lowest refresh rate). + std::vector<const RefreshRate*> mAppRequestRefreshRates GUARDED_BY(mLock); // The current config. This will change at runtime. This is set by SurfaceFlinger on // the main thread, and read by the Scheduler (and other objects) on other threads. diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 86bb6eb7de..d73fd8bee5 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -469,7 +469,7 @@ void Scheduler::notifyTouchEvent() { // that is currently on top. b/142507166 will give us this capability. std::lock_guard<std::mutex> lock(mFeatureStateLock); if (mLayerHistory) { - // Layer History will be cleared based on RefreshRateConfigs::getRefreshRateForContentV2 + // Layer History will be cleared based on RefreshRateConfigs::getBestRefreshRate mTouchTimer->reset(); @@ -574,29 +574,28 @@ void Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventO HwcConfigIndexType Scheduler::calculateRefreshRateConfigIndexType() { ATRACE_CALL(); - // NOTE: If we remove the kernel idle timer, and use our internal idle timer, this - // code will have to be refactored. If Display Power is not in normal operation we want to be in - // performance mode. When coming back to normal mode, a grace period is given with - // DisplayPowerTimer. + // If Display Power is not in normal operation we want to be in performance mode. When coming + // back to normal mode, a grace period is given with DisplayPowerTimer. if (mDisplayPowerTimer && (!mFeatures.isDisplayPowerStateNormal || mFeatures.displayPowerTimer == TimerState::Reset)) { return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getConfigId(); } + const bool touchActive = mTouchTimer && mFeatures.touch == TouchState::Active; + const bool idle = mIdleTimer && mFeatures.idleTimer == TimerState::Expired; + if (!mUseContentDetectionV2) { // As long as touch is active we want to be in performance mode. - if (mTouchTimer && mFeatures.touch == TouchState::Active) { + if (touchActive) { return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getConfigId(); } - } - // If timer has expired as it means there is no new content on the screen. - if (mIdleTimer && mFeatures.idleTimer == TimerState::Expired) { - return mRefreshRateConfigs.getMinRefreshRateByPolicy().getConfigId(); - } + // If timer has expired as it means there is no new content on the screen. + if (idle) { + return mRefreshRateConfigs.getMinRefreshRateByPolicy().getConfigId(); + } - if (!mUseContentDetectionV2) { // If content detection is off we choose performance as we don't know the content fps. if (mFeatures.contentDetectionV1 == ContentDetectionState::Off) { // NOTE: V1 always calls this, but this is not a default behavior for V2. @@ -609,13 +608,10 @@ HwcConfigIndexType Scheduler::calculateRefreshRateConfigIndexType() { } bool touchConsidered; - const auto& ret = - mRefreshRateConfigs - .getRefreshRateForContentV2(mFeatures.contentRequirements, - mTouchTimer && - mFeatures.touch == TouchState::Active, - &touchConsidered) - .getConfigId(); + const auto& ret = mRefreshRateConfigs + .getBestRefreshRate(mFeatures.contentRequirements, touchActive, idle, + &touchConsidered) + .getConfigId(); if (touchConsidered) { // Clear layer history if refresh rate was selected based on touch to allow // the hueristic to pick up with the new rate. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 79ea97ba1a..2daecaebca 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -189,7 +189,7 @@ struct ConditionalLockGuard { using ConditionalLock = ConditionalLockGuard<Mutex>; // TODO(b/141333600): Consolidate with HWC2::Display::Config::Builder::getDefaultDensity. -constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV / 160.f; +constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV; float getDensityFromProperty(const char* property, bool required) { char value[PROPERTY_VALUE_MAX]; @@ -198,7 +198,7 @@ float getDensityFromProperty(const char* property, bool required) { ALOGE("%s must be defined as a build property", property); return FALLBACK_DENSITY; } - return density / 160.f; + return density; } // Currently we only support V0_SRGB and DISPLAY_P3 as composition preference. @@ -582,14 +582,13 @@ void SurfaceFlinger::bootFinished() LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); - static_cast<void>(schedule([this]() NO_THREAD_SAFETY_ANALYSIS { + static_cast<void>(schedule([this] { readPersistentProperties(); mPowerAdvisor.onBootFinished(); mBootStage = BootStage::FINISHED; if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) { - mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this); - mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate()); + enableRefreshRateOverlay(true); } })); } @@ -830,6 +829,7 @@ status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& displayToken, Display ? mInternalDisplayDensity : FALLBACK_DENSITY; } + info->density /= ACONFIGURATION_DENSITY_MEDIUM; info->secure = display->isSecure(); info->deviceProductInfo = getDeviceProductInfoLocked(*display); @@ -934,9 +934,8 @@ int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) { } if (isPrimary) { - std::lock_guard<std::mutex> lock(mActiveConfigLock); - if (mDesiredActiveConfigChanged) { - return mDesiredActiveConfig.configId.value(); + if (const auto config = getDesiredActiveConfig()) { + return config->configId.value(); } } @@ -1003,7 +1002,7 @@ status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mo } else { const HwcConfigIndexType config(mode); const float fps = mRefreshRateConfigs->getRefreshRateFromConfigId(config).getFps(); - const scheduler::RefreshRateConfigs::Policy policy{config, fps, fps}; + const scheduler::RefreshRateConfigs::Policy policy{config, {fps, fps}}; constexpr bool kOverridePolicy = false; return setDesiredDisplayConfigSpecsInternal(display, policy, kOverridePolicy); @@ -1063,14 +1062,7 @@ void SurfaceFlinger::performSetActiveConfig() { ATRACE_CALL(); ALOGV("performSetActiveConfig"); // Store the local variable to release the lock. - const auto desiredActiveConfig = [&]() -> std::optional<ActiveConfigInfo> { - std::lock_guard<std::mutex> lock(mActiveConfigLock); - if (mDesiredActiveConfigChanged) { - return mDesiredActiveConfig; - } - return std::nullopt; - }(); - + const auto desiredActiveConfig = getDesiredActiveConfig(); if (!desiredActiveConfig) { // No desired active config pending to be applied return; @@ -1605,7 +1597,7 @@ void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate, } void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId, - hal::Connection connection) { + hal::Connection connection) NO_THREAD_SAFETY_ANALYSIS { ALOGV("%s(%d, %" PRIu64 ", %s)", __FUNCTION__, sequenceId, hwcDisplayId, connection == hal::Connection::CONNECTED ? "connected" : "disconnected"); @@ -2047,6 +2039,7 @@ void SurfaceFlinger::onMessageRefresh() { refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty; refreshArgs.updatingGeometryThisFrame = mGeometryInvalid || mVisibleRegionsDirty; refreshArgs.blursAreExpensive = mBlursAreExpensive; + refreshArgs.internalDisplayRotationFlags = DisplayDevice::getPrimaryDisplayRotationFlags(); if (CC_UNLIKELY(mDrawingState.colorMatrixChanged)) { refreshArgs.colorTransformMatrix = mDrawingState.colorMatrix; @@ -2678,9 +2671,14 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken, if (currentState.width != drawingState.width || currentState.height != drawingState.height) { display->setDisplaySize(currentState.width, currentState.height); + if (display->isPrimary()) { mScheduler->onPrimaryDisplayAreaChanged(currentState.width * currentState.height); } + + if (mRefreshRateOverlay) { + mRefreshRateOverlay->setViewport(display->getSize()); + } } } } @@ -4383,17 +4381,19 @@ void SurfaceFlinger::dumpVSync(std::string& result) const { scheduler::RefreshRateConfigs::Policy policy = mRefreshRateConfigs->getDisplayManagerPolicy(); StringAppendF(&result, "DesiredDisplayConfigSpecs (DisplayManager): default config ID: %d" - ", min: %.2f Hz, max: %.2f Hz", - policy.defaultConfig.value(), policy.minRefreshRate, policy.maxRefreshRate); + ", primary range: [%.2f %.2f], app request range: [%.2f %.2f]\n\n", + policy.defaultConfig.value(), policy.primaryRange.min, policy.primaryRange.max, + policy.appRequestRange.min, policy.appRequestRange.max); StringAppendF(&result, "(config override by backdoor: %s)\n\n", mDebugDisplayConfigSetByBackdoor ? "yes" : "no"); scheduler::RefreshRateConfigs::Policy currentPolicy = mRefreshRateConfigs->getCurrentPolicy(); if (currentPolicy != policy) { StringAppendF(&result, "DesiredDisplayConfigSpecs (Override): default config ID: %d" - ", min: %.2f Hz, max: %.2f Hz\n\n", - currentPolicy.defaultConfig.value(), currentPolicy.minRefreshRate, - currentPolicy.maxRefreshRate); + ", primary range: [%.2f %.2f], app request range: [%.2f %.2f]\n\n", + currentPolicy.defaultConfig.value(), currentPolicy.primaryRange.min, + currentPolicy.primaryRange.max, currentPolicy.appRequestRange.min, + currentPolicy.appRequestRange.max); } mScheduler->dump(mAppConnectionHandle, result); @@ -5226,15 +5226,15 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r return NO_ERROR; } case 1034: { - n = data.readInt32(); - if (n == 1 && !mRefreshRateOverlay) { - mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this); - auto& current = mRefreshRateConfigs->getCurrentRefreshRate(); - mRefreshRateOverlay->changeRefreshRate(current); - } else if (n == 0) { - mRefreshRateOverlay.reset(); - } else { - reply->writeBool(mRefreshRateOverlay != nullptr); + switch (n = data.readInt32()) { + case 0: + case 1: + enableRefreshRateOverlay(static_cast<bool>(n)); + break; + default: { + Mutex::Autolock lock(mStateLock); + reply->writeBool(mRefreshRateOverlay != nullptr); + } } return NO_ERROR; } @@ -5282,29 +5282,26 @@ void SurfaceFlinger::repaintEverythingForHWC() { void SurfaceFlinger::kernelTimerChanged(bool expired) { static bool updateOverlay = property_get_bool("debug.sf.kernel_idle_timer_update_overlay", true); - if (!updateOverlay || !mRefreshRateOverlay) return; + if (!updateOverlay) return; + if (Mutex::Autolock lock(mStateLock); !mRefreshRateOverlay) return; // Update the overlay on the main thread to avoid race conditions with // mRefreshRateConfigs->getCurrentRefreshRate() - static_cast<void>(schedule([=]() NO_THREAD_SAFETY_ANALYSIS { - if (mRefreshRateOverlay) { + static_cast<void>(schedule([=] { + const auto desiredActiveConfig = getDesiredActiveConfig(); + const auto& current = desiredActiveConfig + ? mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig->configId) + : mRefreshRateConfigs->getCurrentRefreshRate(); + const auto& min = mRefreshRateConfigs->getMinRefreshRate(); + + if (current != min) { const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false); const bool timerExpired = kernelTimerEnabled && expired; - const auto& current = [this]() -> const RefreshRate& { - std::lock_guard<std::mutex> lock(mActiveConfigLock); - if (mDesiredActiveConfigChanged) { - return mRefreshRateConfigs->getRefreshRateFromConfigId( - mDesiredActiveConfig.configId); - } - - return mRefreshRateConfigs->getCurrentRefreshRate(); - }(); - const auto& min = mRefreshRateConfigs->getMinRefreshRate(); - if (current != min) { + if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) { mRefreshRateOverlay->changeRefreshRate(timerExpired ? min : current); - mEventQueue->invalidate(); } + mEventQueue->invalidate(); } })); } @@ -5928,9 +5925,11 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal( } scheduler::RefreshRateConfigs::Policy currentPolicy = mRefreshRateConfigs->getCurrentPolicy(); - ALOGV("Setting desired display config specs: defaultConfig: %d min: %.f max: %.f", - currentPolicy.defaultConfig.value(), currentPolicy.minRefreshRate, - currentPolicy.maxRefreshRate); + ALOGV("Setting desired display config specs: defaultConfig: %d primaryRange: [%.0f %.0f]" + " expandedRange: [%.0f %.0f]", + currentPolicy.defaultConfig.value(), currentPolicy.primaryRange.min, + currentPolicy.primaryRange.max, currentPolicy.appRequestRange.min, + currentPolicy.appRequestRange.max); // TODO(b/140204874): This hack triggers a notification that something has changed, so // that listeners that care about a change in allowed configs can get the notification. @@ -5963,8 +5962,11 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal( } status_t SurfaceFlinger::setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, - int32_t defaultConfig, float minRefreshRate, - float maxRefreshRate) { + int32_t defaultConfig, + float primaryRefreshRateMin, + float primaryRefreshRateMax, + float appRequestRefreshRateMin, + float appRequestRefreshRateMax) { ATRACE_CALL(); if (!displayToken) { @@ -5982,7 +5984,9 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecs(const sp<IBinder>& display return INVALID_OPERATION; } else { using Policy = scheduler::RefreshRateConfigs::Policy; - const Policy policy{HwcConfigIndexType(defaultConfig), minRefreshRate, maxRefreshRate}; + const Policy policy{HwcConfigIndexType(defaultConfig), + {primaryRefreshRateMin, primaryRefreshRateMax}, + {appRequestRefreshRateMin, appRequestRefreshRateMax}}; constexpr bool kOverridePolicy = false; return setDesiredDisplayConfigSpecsInternal(display, policy, kOverridePolicy); @@ -5994,11 +5998,14 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecs(const sp<IBinder>& display status_t SurfaceFlinger::getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, int32_t* outDefaultConfig, - float* outMinRefreshRate, - float* outMaxRefreshRate) { + float* outPrimaryRefreshRateMin, + float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, + float* outAppRequestRefreshRateMax) { ATRACE_CALL(); - if (!displayToken || !outDefaultConfig || !outMinRefreshRate || !outMaxRefreshRate) { + if (!displayToken || !outDefaultConfig || !outPrimaryRefreshRateMin || + !outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin || !outAppRequestRefreshRateMax) { return BAD_VALUE; } @@ -6012,8 +6019,10 @@ status_t SurfaceFlinger::getDesiredDisplayConfigSpecs(const sp<IBinder>& display scheduler::RefreshRateConfigs::Policy policy = mRefreshRateConfigs->getDisplayManagerPolicy(); *outDefaultConfig = policy.defaultConfig.value(); - *outMinRefreshRate = policy.minRefreshRate; - *outMaxRefreshRate = policy.maxRefreshRate; + *outPrimaryRefreshRateMin = policy.primaryRange.min; + *outPrimaryRefreshRateMax = policy.primaryRange.max; + *outAppRequestRefreshRateMin = policy.appRequestRange.min; + *outAppRequestRefreshRateMax = policy.appRequestRange.max; return NO_ERROR; } else if (display->isVirtual()) { return INVALID_OPERATION; @@ -6023,8 +6032,10 @@ status_t SurfaceFlinger::getDesiredDisplayConfigSpecs(const sp<IBinder>& display *outDefaultConfig = getHwComposer().getActiveConfigIndex(*displayId); auto vsyncPeriod = getHwComposer().getActiveConfig(*displayId)->getVsyncPeriod(); - *outMinRefreshRate = 1e9f / vsyncPeriod; - *outMaxRefreshRate = 1e9f / vsyncPeriod; + *outPrimaryRefreshRateMin = 1e9f / vsyncPeriod; + *outPrimaryRefreshRateMax = 1e9f / vsyncPeriod; + *outAppRequestRefreshRateMin = 1e9f / vsyncPeriod; + *outAppRequestRefreshRateMax = 1e9f / vsyncPeriod; return NO_ERROR; } } @@ -6207,6 +6218,29 @@ void SurfaceFlinger::onFrameRateFlexibilityTokenReleased() { })); } +void SurfaceFlinger::enableRefreshRateOverlay(bool enable) { + static_cast<void>(schedule([=] { + std::unique_ptr<RefreshRateOverlay> overlay; + if (enable) { + overlay = std::make_unique<RefreshRateOverlay>(*this); + } + + { + Mutex::Autolock lock(mStateLock); + + // Destroy the layer of the current overlay, if any, outside the lock. + mRefreshRateOverlay.swap(overlay); + if (!mRefreshRateOverlay) return; + + if (const auto display = getDefaultDisplayDeviceLocked()) { + mRefreshRateOverlay->setViewport(display->getSize()); + } + + mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate()); + } + })); +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 294a52f062..715d5f78ea 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -493,10 +493,15 @@ private: const sp<IRegionSamplingListener>& listener) override; status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) override; status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, int32_t displayModeId, - float minRefreshRate, float maxRefreshRate) override; + float primaryRefreshRateMin, float primaryRefreshRateMax, + float appRequestRefreshRateMin, + float appRequestRefreshRateMax) override; status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, - int32_t* outDefaultConfig, float* outMinRefreshRate, - float* outMaxRefreshRate) override; + int32_t* outDefaultConfig, + float* outPrimaryRefreshRateMin, + float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, + float* outAppRequestRefreshRateMax) override; status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken, bool* outSupport) const override; status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) override; @@ -824,13 +829,13 @@ private: const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& displaySurface, const sp<IGraphicBufferProducer>& producer); - void processDisplayChangesLocked(); + void processDisplayChangesLocked() REQUIRES(mStateLock); void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState& state); void processDisplayRemoved(const wp<IBinder>& displayToken); void processDisplayChanged(const wp<IBinder>& displayToken, const DisplayDeviceState& currentState, - const DisplayDeviceState& drawingState); - void processDisplayHotplugEventsLocked(); + const DisplayDeviceState& drawingState) REQUIRES(mStateLock); + void processDisplayHotplugEventsLocked() REQUIRES(mStateLock); void dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected); @@ -1211,6 +1216,12 @@ private: * Misc */ + std::optional<ActiveConfigInfo> getDesiredActiveConfig() EXCLUDES(mActiveConfigLock) { + std::lock_guard<std::mutex> lock(mActiveConfigLock); + if (mDesiredActiveConfigChanged) return mDesiredActiveConfig; + return std::nullopt; + } + std::mutex mActiveConfigLock; // This bit is set once we start setting the config. We read from this bit during the // process. If at the end, this bit is different than mDesiredActiveConfig, we restart @@ -1253,7 +1264,8 @@ private: // This should only be accessed on the main thread. nsecs_t mFrameStartTime = 0; - std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay; + void enableRefreshRateOverlay(bool enable); + std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay GUARDED_BY(mStateLock); // Flag used to set override allowed display configs from backdoor bool mDebugDisplayConfigSetByBackdoor = false; diff --git a/services/surfaceflinger/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc index d3942e8bbe..575e70d779 100644 --- a/services/surfaceflinger/surfaceflinger.rc +++ b/services/surfaceflinger/surfaceflinger.rc @@ -4,7 +4,7 @@ service surfaceflinger /system/bin/surfaceflinger group graphics drmrpc readproc capabilities SYS_NICE onrestart restart zygote - writepid /dev/stune/foreground/tasks + task_profiles HighPerformance socket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0 socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0 socket pdx/system/vr/display/vsync stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0 diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index 507d28b143..c136708ff0 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -215,14 +215,21 @@ TEST_F(CredentialsTest, GetDisplayNativePrimariesTest) { TEST_F(CredentialsTest, SetDesiredDisplayConfigsTest) { const auto display = SurfaceComposerClient::getInternalDisplayToken(); int32_t defaultConfig; - float minFps; - float maxFps; - status_t res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(display, &defaultConfig, - &minFps, &maxFps); + float primaryFpsMin; + float primaryFpsMax; + float appRequestFpsMin; + float appRequestFpsMax; + status_t res = + SurfaceComposerClient::getDesiredDisplayConfigSpecs(display, &defaultConfig, + &primaryFpsMin, &primaryFpsMax, + &appRequestFpsMin, + &appRequestFpsMax); ASSERT_EQ(res, NO_ERROR); std::function<status_t()> condition = [=]() { - return SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, defaultConfig, minFps, - maxFps); + return SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, defaultConfig, + primaryFpsMin, primaryFpsMax, + appRequestFpsMin, + appRequestFpsMax); }; ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED)); } diff --git a/services/surfaceflinger/tests/DisplayConfigs_test.cpp b/services/surfaceflinger/tests/DisplayConfigs_test.cpp index 0ed2ffb505..debfe83577 100644 --- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp +++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp @@ -39,11 +39,16 @@ protected: TEST_F(RefreshRateRangeTest, setAllConfigs) { int32_t initialDefaultConfig; - float initialMin; - float initialMax; + float initialPrimaryMin; + float initialPrimaryMax; + float initialAppRequestMin; + float initialAppRequestMax; status_t res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, &initialDefaultConfig, - &initialMin, &initialMax); + &initialPrimaryMin, + &initialPrimaryMax, + &initialAppRequestMin, + &initialAppRequestMax); ASSERT_EQ(res, NO_ERROR); Vector<DisplayConfig> configs; @@ -53,22 +58,33 @@ TEST_F(RefreshRateRangeTest, setAllConfigs) { for (size_t i = 0; i < configs.size(); i++) { res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, i, configs[i].refreshRate, + configs[i].refreshRate, + configs[i].refreshRate, configs[i].refreshRate); ASSERT_EQ(res, NO_ERROR); int defaultConfig; - float minRefreshRate; - float maxRefreshRate; + float primaryRefreshRateMin; + float primaryRefreshRateMax; + float appRequestRefreshRateMin; + float appRequestRefreshRateMax; res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, &defaultConfig, - &minRefreshRate, &maxRefreshRate); + &primaryRefreshRateMin, + &primaryRefreshRateMax, + &appRequestRefreshRateMin, + &appRequestRefreshRateMax); ASSERT_EQ(res, NO_ERROR); ASSERT_EQ(defaultConfig, i); - ASSERT_EQ(minRefreshRate, configs[i].refreshRate); - ASSERT_EQ(maxRefreshRate, configs[i].refreshRate); + ASSERT_EQ(primaryRefreshRateMin, configs[i].refreshRate); + ASSERT_EQ(primaryRefreshRateMax, configs[i].refreshRate); + ASSERT_EQ(appRequestRefreshRateMin, configs[i].refreshRate); + ASSERT_EQ(appRequestRefreshRateMax, configs[i].refreshRate); } res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, initialDefaultConfig, - initialMin, initialMax); + initialPrimaryMin, initialPrimaryMax, + initialAppRequestMin, + initialAppRequestMax); ASSERT_EQ(res, NO_ERROR); } diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 32c58ad390..a03fd89297 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -443,6 +443,8 @@ protected: EXPECT_EQ(NO_ERROR, SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, config.refreshRate, + config.refreshRate, + config.refreshRate, config.refreshRate)); waitForDisplayTransaction(); EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i)); @@ -547,6 +549,8 @@ protected: EXPECT_EQ(NO_ERROR, SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, config.refreshRate, + config.refreshRate, + config.refreshRate, config.refreshRate)); waitForDisplayTransaction(); EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i)); @@ -659,9 +663,11 @@ protected: const auto& config = configs[i]; if (config.resolution.getWidth() == 800 && config.refreshRate == 1e9f / 11'111'111) { EXPECT_EQ(NO_ERROR, - SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, - configs[i].refreshRate, - configs[i].refreshRate)); + SurfaceComposerClient:: + setDesiredDisplayConfigSpecs(display, i, configs[i].refreshRate, + configs[i].refreshRate, + configs[i].refreshRate, + configs[i].refreshRate)); waitForDisplayTransaction(); EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i)); break; @@ -706,6 +712,8 @@ protected: EXPECT_EQ(NO_ERROR, SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, config.refreshRate, + config.refreshRate, + config.refreshRate, config.refreshRate)); waitForDisplayTransaction(); EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i)); @@ -751,6 +759,8 @@ protected: EXPECT_EQ(NO_ERROR, SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, config.refreshRate, + config.refreshRate, + config.refreshRate, config.refreshRate)); waitForDisplayTransaction(); EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i)); diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp index 6fca673f6b..15207c94a3 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp @@ -512,5 +512,46 @@ TEST_F(LayerHistoryTestV2, inactiveLayers) { EXPECT_EQ(1, frequentLayerCount(time)); } +TEST_F(LayerHistoryTestV2, calculateRefreshRate30Hz) { + const auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = systemTime(); + const nsecs_t frameTime = 33'333'333; + + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + time += frameTime; + history().record(layer.get(), time, time); + } + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(30.f, history().summarize(time)[0].desiredRefreshRate); +} + +TEST_F(LayerHistoryTestV2, calculateRefreshRate30HzSkipTimestamp) { + const auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = systemTime(); + const nsecs_t frameTime = 33'333'333; + + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + time += frameTime; + const auto timestamp = (i == PRESENT_TIME_HISTORY_SIZE / 2) ? 0 : time; + history().record(layer.get(), timestamp, time); + } + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(30.f, history().summarize(time)[0].desiredRefreshRate); +} + } // namespace } // namespace android::scheduler diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index 2ceb89c3e3..2b168b2cf2 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -166,8 +166,8 @@ TEST_F(RefreshRateConfigsTest, invalidPolicy) { auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m60OnlyConfigDevice, /*currentConfigId=*/HWC_CONFIG_ID_60); - ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy({HwcConfigIndexType(10), 60, 60}), 0); - ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 20, 40}), 0); + ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy({HwcConfigIndexType(10), {60, 60}}), 0); + ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {20, 40}}), 0); } TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap) { @@ -201,7 +201,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe ASSERT_EQ(mExpected60Config, minRate60); ASSERT_EQ(mExpected60Config, performanceRate60); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, 60, 90}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {60, 90}}), 0); refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); const auto& minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy(); @@ -226,7 +226,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe ASSERT_EQ(mExpected60Config, minRate60); ASSERT_EQ(mExpected60Config, performanceRate60); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, 60, 90}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {60, 90}}), 0); refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); const auto& minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy(); @@ -248,7 +248,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_policyChange) { ASSERT_EQ(mExpected60Config, minRate); ASSERT_EQ(mExpected90Config, performanceRate); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 60, 60}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0); auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); @@ -271,7 +271,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getCurrentRefreshRate) { EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_90); } - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, 90, 90}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {90, 90}}), 0); { auto& current = refreshRateConfigs->getCurrentRefreshRate(); EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_90); @@ -298,7 +298,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent) { EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 60, 60}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f))); EXPECT_EQ(mExpected60Config, @@ -310,7 +310,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent) { EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, 90, 90}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {90, 90}}), 0); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f))); EXPECT_EQ(mExpected90Config, @@ -321,7 +321,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent) { refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f))); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 0, 120}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {0, 120}}), 0); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f))); EXPECT_EQ(mExpected60Config, @@ -334,7 +334,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent) { refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); } -TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_noLayers) { +TEST_F(RefreshRateConfigsTest, getBestRefreshRate_noLayers) { bool ignored; auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m60_72_90Device, /*currentConfigId=*/ @@ -344,17 +344,17 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_noLayers) { // refresh rate. auto layers = std::vector<LayerRequirement>{}; EXPECT_EQ(mExpected72Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ - false, &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ + false, /*idle*/ false, &ignored)); // Current refresh rate can always be changed. refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_60); EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ - false, &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ + false, /*idle*/ false, &ignored)); } -TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_60_90) { +TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_90) { bool ignored; auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m60_90Device, @@ -366,162 +366,162 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_60_90) { lr.vote = LayerVoteType::Min; lr.name = "Min"; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.vote = LayerVoteType::Max; lr.name = "Max"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 90.0f; lr.vote = LayerVoteType::Heuristic; lr.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 60.0f; lr.name = "60Hz Heuristic"; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 45.0f; lr.name = "45Hz Heuristic"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 30.0f; lr.name = "30Hz Heuristic"; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 24.0f; lr.name = "24Hz Heuristic"; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.name = ""; - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 60, 60}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0); lr.vote = LayerVoteType::Min; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.vote = LayerVoteType::Max; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 90.0f; lr.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 60.0f; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 45.0f; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 30.0f; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 24.0f; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, 90, 90}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {90, 90}}), 0); lr.vote = LayerVoteType::Min; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.vote = LayerVoteType::Max; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 90.0f; lr.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 60.0f; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 45.0f; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 30.0f; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 24.0f; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 0, 120}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {0, 120}}), 0); lr.vote = LayerVoteType::Min; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.vote = LayerVoteType::Max; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 90.0f; lr.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 60.0f; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 45.0f; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 30.0f; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 24.0f; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); } -TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_60_72_90) { +TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_72_90) { bool ignored; auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m60_72_90Device, @@ -532,42 +532,42 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_60_72_90) { lr.vote = LayerVoteType::Min; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.vote = LayerVoteType::Max; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 90.0f; lr.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 60.0f; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 45.0f; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 30.0f; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 24.0f; EXPECT_EQ(mExpected72Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); } -TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_72_90_120) { +TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_72_90_120) { bool ignored; auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, @@ -583,27 +583,27 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_72_90_120) { lr2.desiredRefreshRate = 60.0f; lr2.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected120Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.desiredRefreshRate = 24.0f; lr1.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 48.0f; lr2.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected72Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.desiredRefreshRate = 24.0f; lr1.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 48.0f; lr2.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected72Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); } -TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_DifferentTypes) { +TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes) { bool ignored; auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, @@ -621,8 +621,8 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.vote = LayerVoteType::Heuristic; lr2.name = "60Hz Heuristic"; EXPECT_EQ(mExpected120Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.desiredRefreshRate = 24.0f; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -631,8 +631,8 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.vote = LayerVoteType::Heuristic; lr2.name = "60Hz Heuristic"; EXPECT_EQ(mExpected120Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.desiredRefreshRate = 24.0f; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -641,8 +641,8 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "60Hz ExplicitDefault"; EXPECT_EQ(mExpected120Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.desiredRefreshRate = 24.0f; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -651,8 +651,8 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.vote = LayerVoteType::Heuristic; lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.desiredRefreshRate = 24.0f; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -661,8 +661,8 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected72Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.desiredRefreshRate = 24.0f; lr1.vote = LayerVoteType::ExplicitDefault; @@ -671,8 +671,8 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.vote = LayerVoteType::Heuristic; lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.desiredRefreshRate = 24.0f; lr1.vote = LayerVoteType::Heuristic; @@ -681,8 +681,8 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz ExplicitDefault"; EXPECT_EQ(mExpected72Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.desiredRefreshRate = 24.0f; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -691,8 +691,8 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz ExplicitDefault"; EXPECT_EQ(mExpected72Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.desiredRefreshRate = 24.0f; lr1.vote = LayerVoteType::ExplicitDefault; @@ -701,11 +701,11 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_Different lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.name = "90Hz ExplicitExactOrMultiple"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); } -TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60) { +TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60) { bool ignored; auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m30_60Device, @@ -716,42 +716,42 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60) { lr.vote = LayerVoteType::Min; EXPECT_EQ(mExpected30Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.vote = LayerVoteType::Max; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 90.0f; lr.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 60.0f; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 45.0f; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 30.0f; EXPECT_EQ(mExpected30Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 24.0f; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); } -TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_72_90) { +TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_72_90) { bool ignored; auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m30_60_72_90Device, @@ -763,70 +763,70 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_72_90) { lr.vote = LayerVoteType::Min; lr.name = "Min"; EXPECT_EQ(mExpected30Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.vote = LayerVoteType::Max; lr.name = "Max"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 90.0f; lr.vote = LayerVoteType::Heuristic; lr.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 60.0f; lr.name = "60Hz Heuristic"; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 45.0f; lr.name = "45Hz Heuristic"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 30.0f; lr.name = "30Hz Heuristic"; EXPECT_EQ(mExpected30Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 24.0f; lr.name = "24Hz Heuristic"; EXPECT_EQ(mExpected72Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true, + /*idle*/ false, &ignored)); lr.desiredRefreshRate = 24.0f; lr.vote = LayerVoteType::ExplicitExactOrMultiple; lr.name = "24Hz ExplicitExactOrMultiple"; EXPECT_EQ(mExpected72Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true, + /*idle*/ false, &ignored)); } -TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_PriorityTest) { +TEST_F(RefreshRateConfigsTest, getBestRefreshRate_PriorityTest) { bool ignored; auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m30_60_90Device, @@ -840,55 +840,55 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_PriorityTest) { lr1.vote = LayerVoteType::Min; lr2.vote = LayerVoteType::Max; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.vote = LayerVoteType::Min; lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 24.0f; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.vote = LayerVoteType::Min; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 24.0f; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.vote = LayerVoteType::Max; lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 60.0f; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.vote = LayerVoteType::Max; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 60.0f; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.vote = LayerVoteType::Heuristic; lr1.desiredRefreshRate = 15.0f; lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 45.0f; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.vote = LayerVoteType::Heuristic; lr1.desiredRefreshRate = 30.0f; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 45.0f; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); } -TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_24FpsVideo) { +TEST_F(RefreshRateConfigsTest, getBestRefreshRate_24FpsVideo) { bool ignored; auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m60_90Device, @@ -901,8 +901,8 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_24FpsVideo) { for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) { lr.desiredRefreshRate = fps; const auto& refreshRate = - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored); printf("%.2fHz chooses %s\n", fps, refreshRate.getName().c_str()); EXPECT_EQ(mExpected60Config, refreshRate); } @@ -931,7 +931,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent_Explici EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(layers)); } -TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_Explicit) { +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getBestRefreshRate_Explicit) { bool ignored; auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m60_90Device, @@ -947,24 +947,24 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_Expli lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 90.0f; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.vote = LayerVoteType::ExplicitDefault; lr1.desiredRefreshRate = 90.0f; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 60.0f; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.vote = LayerVoteType::Heuristic; lr1.desiredRefreshRate = 90.0f; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 60.0f; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); } TEST_F(RefreshRateConfigsTest, testInPolicy) { @@ -975,7 +975,7 @@ TEST_F(RefreshRateConfigsTest, testInPolicy) { ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(50.0f, 59.998f)); } -TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_75HzContent) { +TEST_F(RefreshRateConfigsTest, getBestRefreshRate_75HzContent) { bool ignored; auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m60_90Device, @@ -988,14 +988,14 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_75HzContent) { for (float fps = 75.0f; fps < 100.0f; fps += 0.1f) { lr.desiredRefreshRate = fps; const auto& refreshRate = - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored); printf("%.2fHz chooses %s\n", fps, refreshRate.getName().c_str()); EXPECT_EQ(mExpected90Config, refreshRate); } } -TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_Multiples) { +TEST_F(RefreshRateConfigsTest, getBestRefreshRate_Multiples) { bool ignored; auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m60_90Device, @@ -1013,8 +1013,8 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_Multiples) { lr2.desiredRefreshRate = 90.0f; lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 60.0f; @@ -1023,8 +1023,8 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_Multiples) { lr2.desiredRefreshRate = 90.0f; lr2.name = "90Hz ExplicitDefault"; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 60.0f; @@ -1032,8 +1032,8 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_Multiples) { lr2.vote = LayerVoteType::Max; lr2.name = "Max"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 30.0f; @@ -1042,8 +1042,8 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_Multiples) { lr2.desiredRefreshRate = 90.0f; lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 30.0f; @@ -1051,8 +1051,8 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_Multiples) { lr2.vote = LayerVoteType::Max; lr2.name = "Max"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false, - &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, + /*idle*/ false, &ignored)); } TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { @@ -1072,7 +1072,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { lr2.vote = LayerVoteType::NoVote; lr2.name = "NoVote"; EXPECT_EQ(mExpected60Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, false, /*idle*/ false, &ignored)); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 60.0f; @@ -1080,7 +1080,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { lr2.vote = LayerVoteType::NoVote; lr2.name = "NoVote"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, true, &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &ignored)); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 60.0f; @@ -1088,7 +1088,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { lr2.vote = LayerVoteType::Max; lr2.name = "Max"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, true, &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &ignored)); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 60.0f; @@ -1096,7 +1096,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { lr2.vote = LayerVoteType::Max; lr2.name = "Max"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, false, /*idle*/ false, &ignored)); // The other layer starts to provide buffers lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -1106,7 +1106,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { lr2.desiredRefreshRate = 90.0f; lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, - refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored)); + refreshRateConfigs->getBestRefreshRate(layers, false, /*idle*/ false, &ignored)); } TEST_F(RefreshRateConfigsTest, touchConsidered) { @@ -1115,10 +1115,10 @@ TEST_F(RefreshRateConfigsTest, touchConsidered) { std::make_unique<RefreshRateConfigs>(m60_90Device, /*currentConfigId=*/HWC_CONFIG_ID_60); - refreshRateConfigs->getRefreshRateForContentV2({}, false, &touchConsidered); + refreshRateConfigs->getBestRefreshRate({}, false, /*idle*/ false, &touchConsidered); EXPECT_EQ(false, touchConsidered); - refreshRateConfigs->getRefreshRateForContentV2({}, true, &touchConsidered); + refreshRateConfigs->getBestRefreshRate({}, true, /*idle*/ false, &touchConsidered); EXPECT_EQ(true, touchConsidered); auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}, @@ -1130,36 +1130,40 @@ TEST_F(RefreshRateConfigsTest, touchConsidered) { lr1.desiredRefreshRate = 60.0f; lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.name = "NoVote"; - refreshRateConfigs->getRefreshRateForContentV2(layers, true, &touchConsidered); + lr2.desiredRefreshRate = 60.0f; + lr2.name = "60Hz Heuristic"; + refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &touchConsidered); EXPECT_EQ(true, touchConsidered); lr1.vote = LayerVoteType::ExplicitDefault; lr1.desiredRefreshRate = 60.0f; lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.name = "NoVote"; - refreshRateConfigs->getRefreshRateForContentV2(layers, true, &touchConsidered); + lr2.desiredRefreshRate = 60.0f; + lr2.name = "60Hz Heuristic"; + refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &touchConsidered); EXPECT_EQ(false, touchConsidered); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 60.0f; lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.name = "NoVote"; - refreshRateConfigs->getRefreshRateForContentV2(layers, true, &touchConsidered); + lr2.desiredRefreshRate = 60.0f; + lr2.name = "60Hz Heuristic"; + refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &touchConsidered); EXPECT_EQ(true, touchConsidered); lr1.vote = LayerVoteType::ExplicitDefault; lr1.desiredRefreshRate = 60.0f; - lr1.name = "60Hz ExplicitExactrMultiple"; + lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.name = "NoVote"; - refreshRateConfigs->getRefreshRateForContentV2(layers, true, &touchConsidered); + lr2.desiredRefreshRate = 60.0f; + lr2.name = "60Hz Heuristic"; + refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &touchConsidered); EXPECT_EQ(false, touchConsidered); } -TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_ExplicitDefault) { +TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitDefault) { bool ignored; auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m60_90_72_120Device, /*currentConfigId=*/ @@ -1196,7 +1200,7 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_ExplicitDefault) { lr.name = ss.str(); const auto& refreshRate = - refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored); + refreshRateConfigs->getBestRefreshRate(layers, false, /*idle*/ false, &ignored); EXPECT_FLOAT_EQ(refreshRate.getFps(), test.second) << "Expecting " << test.first << "fps => " << test.second << "Hz"; } @@ -1215,7 +1219,8 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { bool touchConsidered; ASSERT_EQ(HWC_CONFIG_ID_60, - refreshRateConfigs->getRefreshRateForContentV2(layers, false, &touchConsidered) + refreshRateConfigs + ->getBestRefreshRate(layers, false, /*idle*/ false, &touchConsidered) .getConfigId()); RefreshRateConfigs::Policy policy; @@ -1223,7 +1228,117 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { policy.allowGroupSwitching = true; ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(policy), 0); ASSERT_EQ(HWC_CONFIG_ID_90, - refreshRateConfigs->getRefreshRateForContentV2(layers, false, &touchConsidered) + refreshRateConfigs + ->getBestRefreshRate(layers, false, /*idle*/ false, &touchConsidered) + .getConfigId()); +} + +TEST_F(RefreshRateConfigsTest, primaryVsAppRequestPolicy) { + auto refreshRateConfigs = + std::make_unique<RefreshRateConfigs>(m60_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}}; + layers[0].name = "Test layer"; + + // Return the config ID from calling getBestRefreshRate() for a single layer with the + // given voteType and fps. + auto getFrameRate = [&](LayerVoteType voteType, float fps, + bool touchActive = false) -> HwcConfigIndexType { + layers[0].vote = voteType; + layers[0].desiredRefreshRate = fps; + bool touchConsidered; + return refreshRateConfigs + ->getBestRefreshRate(layers, touchActive, /*idle*/ false, &touchConsidered) + .getConfigId(); + }; + + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( + {HWC_CONFIG_ID_60, {60.f, 60.f}, {60.f, 90.f}}), + 0); + bool touchConsidered; + EXPECT_EQ(HWC_CONFIG_ID_60, + refreshRateConfigs + ->getBestRefreshRate({}, /*touchActive=*/false, /*idle*/ false, + &touchConsidered) + .getConfigId()); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::NoVote, 90.f)); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Min, 90.f)); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, 90.f)); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Heuristic, 90.f)); + EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitDefault, 90.f)); + EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f)); + + // Touch boost should be restricted to the primary range. + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, 90.f, /*touch=*/true)); + // When we're higher than the primary range max due to a layer frame rate setting, touch boost + // shouldn't drag us back down to the primary range max. + EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitDefault, 90.f, /*touch=*/true)); + EXPECT_EQ(HWC_CONFIG_ID_90, + getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f, /*touch=*/true)); + + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( + {HWC_CONFIG_ID_60, {60.f, 60.f}, {60.f, 60.f}}), + 0); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::NoVote, 90.f)); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Min, 90.f)); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, 90.f)); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Heuristic, 90.f)); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitDefault, 90.f)); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f)); +} + +TEST_F(RefreshRateConfigsTest, idle) { + auto refreshRateConfigs = + std::make_unique<RefreshRateConfigs>(m60_90Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}}; + layers[0].name = "Test layer"; + + auto getIdleFrameRate = [&](LayerVoteType voteType, bool touchActive) -> HwcConfigIndexType { + layers[0].vote = voteType; + layers[0].desiredRefreshRate = 90.f; + bool touchConsidered; + return refreshRateConfigs + ->getBestRefreshRate(layers, touchActive, /*idle=*/true, &touchConsidered) + .getConfigId(); + }; + + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( + {HWC_CONFIG_ID_60, {60.f, 90.f}, {60.f, 90.f}}), + 0); + + // Idle should be lower priority than touch boost. + EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::NoVote, true)); + EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::Min, true)); + EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::Max, true)); + EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::Heuristic, true)); + EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::ExplicitDefault, true)); + EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::ExplicitExactOrMultiple, true)); + + // With no layers, idle should still be lower priority than touch boost. + bool touchConsidered; + EXPECT_EQ(HWC_CONFIG_ID_90, + refreshRateConfigs + ->getBestRefreshRate({}, /*touchActive=*/true, /*idle=*/true, + &touchConsidered) + .getConfigId()); + + // Idle should be higher precedence than other layer frame rate considerations. + refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::NoVote, false)); + EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::Min, false)); + EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::Max, false)); + EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::Heuristic, false)); + EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::ExplicitDefault, false)); + EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::ExplicitExactOrMultiple, false)); + + // Idle should be applied rather than the current config when there are no layers. + EXPECT_EQ(HWC_CONFIG_ID_60, + refreshRateConfigs + ->getBestRefreshRate({}, /*touchActive=*/false, /*idle=*/true, + &touchConsidered) .getConfigId()); } diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp index a5f0c9f803..7bcb2c1441 100644 --- a/vulkan/libvulkan/driver.cpp +++ b/vulkan/libvulkan/driver.cpp @@ -252,18 +252,6 @@ bool Hal::Open() { result = LoadUpdatedDriver(&module); if (result == -ENOENT) { result = LoadBuiltinDriver(&module); - if (result != 0) { - // -ENOENT means the sphal namespace doesn't exist, not that there - // is a problem with the driver. - ALOGW_IF( - result != -ENOENT, - "Failed to load Vulkan driver into sphal namespace. This " - "usually means the driver has forbidden library dependencies." - "Please fix, this will soon stop working."); - result = - hw_get_module(HWVULKAN_HARDWARE_MODULE_ID, - reinterpret_cast<const hw_module_t**>(&module)); - } } if (result != 0) { android::GraphicsEnv::getInstance().setDriverLoaded( diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp index a44b9e7931..d3ed88d2eb 100644 --- a/vulkan/libvulkan/swapchain.cpp +++ b/vulkan/libvulkan/swapchain.cpp @@ -1478,7 +1478,7 @@ VkResult AcquireNextImageKHR(VkDevice device, ANativeWindowBuffer* buffer; int fence_fd; err = window->dequeueBuffer(window, &buffer, &fence_fd); - if (err == android::TIMED_OUT) { + if (err == android::TIMED_OUT || err == android::INVALID_OPERATION) { ALOGW("dequeueBuffer timed out: %s (%d)", strerror(-err), err); return timeout ? VK_TIMEOUT : VK_NOT_READY; } else if (err != android::OK) { |