Merge "Read pointer choreographer flag at boot" into main
diff --git a/data/etc/android.software.contextualsearch.xml b/data/etc/android.software.contextualsearch.xml
new file mode 100644
index 0000000..4564ac8
--- /dev/null
+++ b/data/etc/android.software.contextualsearch.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<!-- Feature for devices supporting contextual search helper. -->
+<permissions>
+ <feature name="android.software.contextualsearch" />
+</permissions>
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 3af9ec7..bf7a0ba 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -258,24 +258,11 @@
}
}
-void ABBinder::addDeathRecipient(const ::android::sp<AIBinder_DeathRecipient>& /* recipient */,
- void* /* cookie */) {
- LOG_ALWAYS_FATAL("Should not reach this. Can't linkToDeath local binders.");
-}
-
ABpBinder::ABpBinder(const ::android::sp<::android::IBinder>& binder)
: AIBinder(nullptr /*clazz*/), mRemote(binder) {
LOG_ALWAYS_FATAL_IF(binder == nullptr, "binder == nullptr");
}
-
-ABpBinder::~ABpBinder() {
- for (auto& recip : mDeathRecipients) {
- sp<AIBinder_DeathRecipient> strongRecip = recip.recipient.promote();
- if (strongRecip) {
- strongRecip->pruneThisTransferEntry(getBinder(), recip.cookie);
- }
- }
-}
+ABpBinder::~ABpBinder() {}
sp<AIBinder> ABpBinder::lookupOrCreateFromBinder(const ::android::sp<::android::IBinder>& binder) {
if (binder == nullptr) {
@@ -314,11 +301,6 @@
return ret;
}
-void ABpBinder::addDeathRecipient(const ::android::sp<AIBinder_DeathRecipient>& recipient,
- void* cookie) {
- mDeathRecipients.emplace_back(recipient, cookie);
-}
-
struct AIBinder_Weak {
wp<AIBinder> binder;
};
@@ -444,17 +426,6 @@
LOG_ALWAYS_FATAL_IF(onDied == nullptr, "onDied == nullptr");
}
-void AIBinder_DeathRecipient::pruneThisTransferEntry(const sp<IBinder>& who, void* cookie) {
- std::lock_guard<std::mutex> l(mDeathRecipientsMutex);
- mDeathRecipients.erase(std::remove_if(mDeathRecipients.begin(), mDeathRecipients.end(),
- [&](const sp<TransferDeathRecipient>& tdr) {
- auto tdrWho = tdr->getWho();
- return tdrWho != nullptr && tdrWho.promote() == who &&
- cookie == tdr->getCookie();
- }),
- mDeathRecipients.end());
-}
-
void AIBinder_DeathRecipient::pruneDeadTransferEntriesLocked() {
mDeathRecipients.erase(std::remove_if(mDeathRecipients.begin(), mDeathRecipients.end(),
[](const sp<TransferDeathRecipient>& tdr) {
@@ -583,11 +554,8 @@
return STATUS_UNEXPECTED_NULL;
}
- binder_status_t ret = recipient->linkToDeath(binder->getBinder(), cookie);
- if (ret == STATUS_OK) {
- binder->addDeathRecipient(recipient, cookie);
- }
- return ret;
+ // returns binder_status_t
+ return recipient->linkToDeath(binder->getBinder(), cookie);
}
binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index a2682d8..9d5368f 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -51,8 +51,6 @@
::android::sp<::android::IBinder> binder = const_cast<AIBinder*>(this)->getBinder();
return binder->remoteBinder() != nullptr;
}
- virtual void addDeathRecipient(const ::android::sp<AIBinder_DeathRecipient>& recipient,
- void* cookie) = 0;
private:
// AIBinder instance is instance of this class for a local object. In order to transact on a
@@ -80,8 +78,6 @@
::android::status_t dump(int fd, const ::android::Vector<::android::String16>& args) override;
::android::status_t onTransact(uint32_t code, const ::android::Parcel& data,
::android::Parcel* reply, binder_flags_t flags) override;
- void addDeathRecipient(const ::android::sp<AIBinder_DeathRecipient>& /* recipient */,
- void* /* cookie */) override;
private:
ABBinder(const AIBinder_Class* clazz, void* userData);
@@ -110,19 +106,12 @@
bool isServiceFuzzing() const { return mServiceFuzzing; }
void setServiceFuzzing() { mServiceFuzzing = true; }
- void addDeathRecipient(const ::android::sp<AIBinder_DeathRecipient>& recipient,
- void* cookie) override;
private:
friend android::sp<ABpBinder>;
explicit ABpBinder(const ::android::sp<::android::IBinder>& binder);
::android::sp<::android::IBinder> mRemote;
bool mServiceFuzzing = false;
- struct DeathRecipientInfo {
- android::wp<AIBinder_DeathRecipient> recipient;
- void* cookie;
- };
- std::vector<DeathRecipientInfo> mDeathRecipients;
};
struct AIBinder_Class {
@@ -194,7 +183,6 @@
binder_status_t linkToDeath(const ::android::sp<::android::IBinder>&, void* cookie);
binder_status_t unlinkToDeath(const ::android::sp<::android::IBinder>& binder, void* cookie);
void setOnUnlinked(AIBinder_DeathRecipient_onBinderUnlinked onUnlinked);
- void pruneThisTransferEntry(const ::android::sp<::android::IBinder>&, void* cookie);
private:
// When the user of this API deletes a Bp object but not the death recipient, the
diff --git a/libs/binder/ndk/tests/iface.cpp b/libs/binder/ndk/tests/iface.cpp
index ca92727..3ee36cd 100644
--- a/libs/binder/ndk/tests/iface.cpp
+++ b/libs/binder/ndk/tests/iface.cpp
@@ -25,7 +25,6 @@
const char* IFoo::kSomeInstanceName = "libbinder_ndk-test-IFoo";
const char* IFoo::kInstanceNameToDieFor = "libbinder_ndk-test-IFoo-to-die";
-const char* IFoo::kInstanceNameToDieFor2 = "libbinder_ndk-test-IFoo-to-die2";
const char* IFoo::kIFooDescriptor = "my-special-IFoo-class";
struct IFoo_Class_Data {
diff --git a/libs/binder/ndk/tests/include/iface/iface.h b/libs/binder/ndk/tests/include/iface/iface.h
index 0cdd50b..0a562f0 100644
--- a/libs/binder/ndk/tests/include/iface/iface.h
+++ b/libs/binder/ndk/tests/include/iface/iface.h
@@ -27,7 +27,6 @@
public:
static const char* kSomeInstanceName;
static const char* kInstanceNameToDieFor;
- static const char* kInstanceNameToDieFor2;
static const char* kIFooDescriptor;
static AIBinder_Class* kClass;
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index ce63b82..966ec95 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -536,7 +536,6 @@
bool deathReceived = false;
std::function<void(void)> onDeath = [&] {
- std::unique_lock<std::mutex> lockDeath(deathMutex);
std::cerr << "Binder died (as requested)." << std::endl;
deathReceived = true;
deathCv.notify_one();
@@ -548,7 +547,6 @@
bool wasDeathReceivedFirst = false;
std::function<void(void)> onUnlink = [&] {
- std::unique_lock<std::mutex> lockUnlink(unlinkMutex);
std::cerr << "Binder unlinked (as requested)." << std::endl;
wasDeathReceivedFirst = deathReceived;
unlinkReceived = true;
@@ -562,6 +560,7 @@
EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, static_cast<void*>(cookie)));
+ // the binder driver should return this if the service dies during the transaction
EXPECT_EQ(STATUS_DEAD_OBJECT, foo->die());
foo = nullptr;
@@ -580,123 +579,6 @@
binder = nullptr;
}
-TEST(NdkBinder, DeathRecipientDropBinderNoDeath) {
- using namespace std::chrono_literals;
-
- std::mutex deathMutex;
- std::condition_variable deathCv;
- bool deathReceived = false;
-
- std::function<void(void)> onDeath = [&] {
- std::unique_lock<std::mutex> lockDeath(deathMutex);
- std::cerr << "Binder died (as requested)." << std::endl;
- deathReceived = true;
- deathCv.notify_one();
- };
-
- std::mutex unlinkMutex;
- std::condition_variable unlinkCv;
- bool unlinkReceived = false;
- bool wasDeathReceivedFirst = false;
-
- std::function<void(void)> onUnlink = [&] {
- std::unique_lock<std::mutex> lockUnlink(unlinkMutex);
- std::cerr << "Binder unlinked (as requested)." << std::endl;
- wasDeathReceivedFirst = deathReceived;
- unlinkReceived = true;
- unlinkCv.notify_one();
- };
-
- // keep the death recipient around
- ndk::ScopedAIBinder_DeathRecipient recipient(AIBinder_DeathRecipient_new(LambdaOnDeath));
- AIBinder_DeathRecipient_setOnUnlinked(recipient.get(), LambdaOnUnlink);
-
- {
- AIBinder* binder;
- sp<IFoo> foo = IFoo::getService(IFoo::kInstanceNameToDieFor2, &binder);
- ASSERT_NE(nullptr, foo.get());
- ASSERT_NE(nullptr, binder);
-
- DeathRecipientCookie* cookie = new DeathRecipientCookie{&onDeath, &onUnlink};
-
- EXPECT_EQ(STATUS_OK,
- AIBinder_linkToDeath(binder, recipient.get(), static_cast<void*>(cookie)));
- // let the sp<IFoo> and AIBinder fall out of scope
- AIBinder_decStrong(binder);
- binder = nullptr;
- }
-
- {
- std::unique_lock<std::mutex> lockDeath(deathMutex);
- EXPECT_FALSE(deathCv.wait_for(lockDeath, 100ms, [&] { return deathReceived; }));
- EXPECT_FALSE(deathReceived);
- }
-
- {
- std::unique_lock<std::mutex> lockUnlink(unlinkMutex);
- EXPECT_TRUE(deathCv.wait_for(lockUnlink, 1s, [&] { return unlinkReceived; }));
- EXPECT_TRUE(unlinkReceived);
- EXPECT_FALSE(wasDeathReceivedFirst);
- }
-}
-
-TEST(NdkBinder, DeathRecipientDropBinderOnDied) {
- using namespace std::chrono_literals;
-
- std::mutex deathMutex;
- std::condition_variable deathCv;
- bool deathReceived = false;
-
- sp<IFoo> foo;
- AIBinder* binder;
- std::function<void(void)> onDeath = [&] {
- std::unique_lock<std::mutex> lockDeath(deathMutex);
- std::cerr << "Binder died (as requested)." << std::endl;
- deathReceived = true;
- AIBinder_decStrong(binder);
- binder = nullptr;
- deathCv.notify_one();
- };
-
- std::mutex unlinkMutex;
- std::condition_variable unlinkCv;
- bool unlinkReceived = false;
- bool wasDeathReceivedFirst = false;
-
- std::function<void(void)> onUnlink = [&] {
- std::unique_lock<std::mutex> lockUnlink(unlinkMutex);
- std::cerr << "Binder unlinked (as requested)." << std::endl;
- wasDeathReceivedFirst = deathReceived;
- unlinkReceived = true;
- unlinkCv.notify_one();
- };
-
- ndk::ScopedAIBinder_DeathRecipient recipient(AIBinder_DeathRecipient_new(LambdaOnDeath));
- AIBinder_DeathRecipient_setOnUnlinked(recipient.get(), LambdaOnUnlink);
-
- foo = IFoo::getService(IFoo::kInstanceNameToDieFor2, &binder);
- ASSERT_NE(nullptr, foo.get());
- ASSERT_NE(nullptr, binder);
-
- DeathRecipientCookie* cookie = new DeathRecipientCookie{&onDeath, &onUnlink};
- EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient.get(), static_cast<void*>(cookie)));
-
- EXPECT_EQ(STATUS_DEAD_OBJECT, foo->die());
-
- {
- std::unique_lock<std::mutex> lockDeath(deathMutex);
- EXPECT_TRUE(deathCv.wait_for(lockDeath, 1s, [&] { return deathReceived; }));
- EXPECT_TRUE(deathReceived);
- }
-
- {
- std::unique_lock<std::mutex> lockUnlink(unlinkMutex);
- EXPECT_TRUE(deathCv.wait_for(lockUnlink, 100ms, [&] { return unlinkReceived; }));
- EXPECT_TRUE(unlinkReceived);
- EXPECT_TRUE(wasDeathReceivedFirst);
- }
-}
-
TEST(NdkBinder, RetrieveNonNdkService) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@@ -1076,10 +958,6 @@
}
if (fork() == 0) {
prctl(PR_SET_PDEATHSIG, SIGHUP);
- return manualThreadPoolService(IFoo::kInstanceNameToDieFor2);
- }
- if (fork() == 0) {
- prctl(PR_SET_PDEATHSIG, SIGHUP);
return manualPollingService(IFoo::kSomeInstanceName);
}
if (fork() == 0) {
diff --git a/libs/gui/FrameRateUtils.cpp b/libs/gui/FrameRateUtils.cpp
index 11524e2..01aa7ed 100644
--- a/libs/gui/FrameRateUtils.cpp
+++ b/libs/gui/FrameRateUtils.cpp
@@ -42,6 +42,7 @@
if (compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT &&
compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE &&
+ compatibility != ANATIVEWINDOW_FRAME_RATE_GTE &&
(!privileged ||
(compatibility != ANATIVEWINDOW_FRAME_RATE_EXACT &&
compatibility != ANATIVEWINDOW_FRAME_RATE_NO_VOTE))) {
diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp
index 9429d2c..86bf0ee 100644
--- a/libs/gui/WindowInfo.cpp
+++ b/libs/gui/WindowInfo.cpp
@@ -262,8 +262,6 @@
}
std::ostream& operator<<(std::ostream& out, const WindowInfo& info) {
- std::string transform;
- info.transform.dump(transform, "transform", " ");
out << "name=" << info.name << ", id=" << info.id << ", displayId=" << info.displayId
<< ", inputConfig=" << info.inputConfig.string() << ", alpha=" << info.alpha << ", frame=["
<< info.frame.left << "," << info.frame.top << "][" << info.frame.right << ","
@@ -274,9 +272,11 @@
<< ", ownerUid=" << info.ownerUid.toString() << ", dispatchingTimeout="
<< std::chrono::duration_cast<std::chrono::milliseconds>(info.dispatchingTimeout).count()
<< "ms, token=" << info.token.get()
- << ", touchOcclusionMode=" << ftl::enum_string(info.touchOcclusionMode) << "\n"
- << transform;
- if (info.canOccludePresentation) out << " canOccludePresentation";
+ << ", touchOcclusionMode=" << ftl::enum_string(info.touchOcclusionMode);
+ if (info.canOccludePresentation) out << ", canOccludePresentation";
+ std::string transform;
+ info.transform.dump(transform, "transform", " ");
+ out << "\n" << transform;
return out;
}
diff --git a/libs/gui/fuzzer/Android.bp b/libs/gui/fuzzer/Android.bp
deleted file mode 100644
index 35dd9ec..0000000
--- a/libs/gui/fuzzer/Android.bp
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_native_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_native_license"],
- default_team: "trendy_team_android_core_graphics_stack",
-}
-
-cc_defaults {
- name: "libgui_fuzzer_defaults",
- defaults: ["android.hardware.power-ndk_shared"],
- static_libs: [
- "android.hidl.token@1.0-utils",
- "libbinder_random_parcel",
- "libgui_aidl_static",
- "libgui_window_info_static",
- "libpdx",
- "libgmock",
- "libgui_mocks",
- "libgmock_ndk",
- "libgmock_main",
- "libgtest_ndk_c++",
- "libgmock_main_ndk",
- "librenderengine_mocks",
- "perfetto_trace_protos",
- "libcompositionengine_mocks",
- "perfetto_trace_protos",
- ],
- shared_libs: [
- "android.hardware.configstore@1.0",
- "android.hardware.configstore-utils",
- "android.hardware.graphics.bufferqueue@1.0",
- "android.hardware.graphics.bufferqueue@2.0",
- "android.hidl.token@1.0",
- "libSurfaceFlingerProp",
- "libgui",
- "libbase",
- "liblog",
- "libEGL",
- "libGLESv2",
- "libbinder",
- "libcutils",
- "libhidlbase",
- "libinput",
- "libui",
- "libutils",
- "libnativewindow",
- "libvndksupport",
- ],
- header_libs: [
- "libdvr_headers",
- "libui_fuzzableDataspaces_headers",
- ],
- fuzz_config: {
- cc: [
- "android-media-fuzzing-reports@google.com",
- ],
- componentid: 155276,
- hotlists: [
- "4593311",
- ],
- description: "The fuzzer targets the APIs of libgui library",
- vector: "local_no_privileges_required",
- service_privilege: "privileged",
- users: "multi_user",
- fuzzed_code_usage: "shipped",
- },
-}
-
-cc_fuzz {
- name: "libgui_surfaceComposer_fuzzer",
- srcs: [
- "libgui_surfaceComposer_fuzzer.cpp",
- ],
- defaults: [
- "libgui_fuzzer_defaults",
- "service_fuzzer_defaults",
- ],
-}
-
-cc_fuzz {
- name: "libgui_surfaceComposerClient_fuzzer",
- srcs: [
- "libgui_surfaceComposerClient_fuzzer.cpp",
- ],
- defaults: [
- "libgui_fuzzer_defaults",
- "service_fuzzer_defaults",
- ],
-}
-
-cc_fuzz {
- name: "libgui_parcelable_fuzzer",
- srcs: [
- "libgui_parcelable_fuzzer.cpp",
- ],
- defaults: [
- "libgui_fuzzer_defaults",
- ],
-}
-
-cc_fuzz {
- name: "libgui_bufferQueue_fuzzer",
- srcs: [
- "libgui_bufferQueue_fuzzer.cpp",
- ],
- defaults: [
- "libgui_fuzzer_defaults",
- ],
-}
-
-cc_fuzz {
- name: "libgui_consumer_fuzzer",
- srcs: [
- "libgui_consumer_fuzzer.cpp",
- ],
- defaults: [
- "libgui_fuzzer_defaults",
- ],
-}
-
-cc_fuzz {
- name: "libgui_displayEvent_fuzzer",
- srcs: [
- "libgui_displayEvent_fuzzer.cpp",
- ],
- defaults: [
- "libgui_fuzzer_defaults",
- ],
-}
diff --git a/libs/gui/fuzzer/README.md b/libs/gui/fuzzer/README.md
deleted file mode 100644
index 96e27c9..0000000
--- a/libs/gui/fuzzer/README.md
+++ /dev/null
@@ -1,219 +0,0 @@
-# Fuzzers for Libgui
-
-## Table of contents
-+ [libgui_surfaceComposer_fuzzer](#SurfaceComposer)
-+ [libgui_surfaceComposerClient_fuzzer](#SurfaceComposerClient)
-+ [libgui_parcelable_fuzzer](#Libgui_Parcelable)
-+ [libgui_bufferQueue_fuzzer](#BufferQueue)
-+ [libgui_consumer_fuzzer](#Libgui_Consumer)
-+ [libgui_displayEvent_fuzzer](#LibGui_DisplayEvent)
-
-# <a name="libgui_surfaceComposer_fuzzer"></a> Fuzzer for SurfaceComposer
-
-SurfaceComposer supports the following parameters:
-1. SurfaceWidth (parameter name:`width`)
-2. SurfaceHeight (parameter name:`height`)
-3. TransactionStateFlags (parameter name:`flags`)
-4. TransformHint (parameter name:`outTransformHint`)
-5. SurfacePixelFormat (parameter name:`format`)
-6. LayerId (parameter name:`outLayerId`)
-7. SurfaceComposerTags (parameter name:`surfaceTag`)
-8. PowerBoostID (parameter name:`boostId`)
-9. VsyncSource (parameter name:`vsyncSource`)
-10. EventRegistrationFlags (parameter name:`eventRegistration`)
-11. FrameRateCompatibility (parameter name:`frameRateCompatibility`)
-12. ChangeFrameRateStrategy (parameter name:`changeFrameRateStrategy`)
-13. HdrTypes (parameter name:`hdrTypes`)
-
-| Parameter| Valid Values| Configured Value|
-|------------- |-------------| ----- |
-|`surfaceTag` | 0.`BnSurfaceComposer::BOOT_FINISHED`, 1.`BnSurfaceComposer::CREATE_CONNECTION`, 2.`BnSurfaceComposer::GET_STATIC_DISPLAY_INFO`, 3.`BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION`, 4.`BnSurfaceComposer::CREATE_DISPLAY`, 5.`BnSurfaceComposer::DESTROY_DISPLAY`, 6.`BnSurfaceComposer::GET_PHYSICAL_DISPLAY_TOKEN`, 7.`BnSurfaceComposer::SET_TRANSACTION_STATE`, 8.`BnSurfaceComposer::AUTHENTICATE_SURFACE`, 9.`BnSurfaceComposer::GET_SUPPORTED_FRAME_TIMESTAMPS`, 10.`BnSurfaceComposer::GET_DISPLAY_STATE`, 11.`BnSurfaceComposer::CAPTURE_DISPLAY`, 12.`BnSurfaceComposer::CAPTURE_LAYERS`, 13.`BnSurfaceComposer::CLEAR_ANIMATION_FRAME_STATS`, 14.`BnSurfaceComposer::GET_ANIMATION_FRAME_STATS`, 15.`BnSurfaceComposer::SET_POWER_MODE`, 16.`BnSurfaceComposer::GET_DISPLAY_STATS`, 17.`BnSurfaceComposer::SET_ACTIVE_COLOR_MODE`, 18.`BnSurfaceComposer::ENABLE_VSYNC_INJECTIONS`, 19.`BnSurfaceComposer::INJECT_VSYNC`, 20.`BnSurfaceComposer::GET_LAYER_DEBUG_INFO`, 21.`BnSurfaceComposer::GET_COMPOSITION_PREFERENCE`, 22.`BnSurfaceComposer::GET_COLOR_MANAGEMENT`, 23.`BnSurfaceComposer::GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES`, 24.`BnSurfaceComposer::SET_DISPLAY_CONTENT_SAMPLING_ENABLED`, 25.`BnSurfaceComposer::GET_DISPLAYED_CONTENT_SAMPLE`, 26.`BnSurfaceComposer::GET_PROTECTED_CONTENT_SUPPORT`, 27.`BnSurfaceComposer::IS_WIDE_COLOR_DISPLAY`, 28.`BnSurfaceComposer::GET_DISPLAY_NATIVE_PRIMARIES`, 29.`BnSurfaceComposer::GET_PHYSICAL_DISPLAY_IDS`, 30.`BnSurfaceComposer::ADD_REGION_SAMPLING_LISTENER`, 31.`BnSurfaceComposer::REMOVE_REGION_SAMPLING_LISTENER`, 32.`BnSurfaceComposer::SET_DESIRED_DISPLAY_MODE_SPECS`, 33.`BnSurfaceComposer::GET_DESIRED_DISPLAY_MODE_SPECS`, 34.`BnSurfaceComposer::GET_DISPLAY_BRIGHTNESS_SUPPORT`, 35.`BnSurfaceComposer::SET_DISPLAY_BRIGHTNESS`, 36.`BnSurfaceComposer::CAPTURE_DISPLAY_BY_ID`, 37.`BnSurfaceComposer::NOTIFY_POWER_BOOST`, 38.`BnSurfaceComposer::SET_GLOBAL_SHADOW_SETTINGS`, 39.`BnSurfaceComposer::SET_AUTO_LOW_LATENCY_MODE`, 40.`BnSurfaceComposer::SET_GAME_CONTENT_TYPE`, 41.`BnSurfaceComposer::SET_FRAME_RATE`, 42.`BnSurfaceComposer::ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN`, 43.`BnSurfaceComposer::SET_FRAME_TIMELINE_INFO`, 44.`BnSurfaceComposer::ADD_TRANSACTION_TRACE_LISTENER`, 45.`BnSurfaceComposer::GET_GPU_CONTEXT_PRIORITY`, 46.`BnSurfaceComposer::GET_MAX_ACQUIRED_BUFFER_COUNT`, 47.`BnSurfaceComposer::GET_DYNAMIC_DISPLAY_INFO`, 48.`BnSurfaceComposer::ADD_FPS_LISTENER`, 49.`BnSurfaceComposer::REMOVE_FPS_LISTENER`, 50.`BnSurfaceComposer::OVERRIDE_HDR_TYPES`, 51.`BnSurfaceComposer::ADD_HDR_LAYER_INFO_LISTENER`, 52.`BnSurfaceComposer::REMOVE_HDR_LAYER_INFO_LISTENER`, 53.`BnSurfaceComposer::ON_PULL_ATOM`, 54.`BnSurfaceComposer::ADD_TUNNEL_MODE_ENABLED_LISTENER`, 55.`BnSurfaceComposer::REMOVE_TUNNEL_MODE_ENABLED_LISTENER` | Value obtained from FuzzedDataProvider|
-|`boostId`| 0.`hardware::power::Boost::INTERACTION`, 1.`hardware::power::Boost::DISPLAY_UPDATE_IMMINENT`, 2.`hardware::power::Boost::ML_ACC`, 3.`hardware::power::Boost::AUDIO_LAUNCH`, 4.`hardware::power::Boost::CAMERA_LAUNCH`, 5.`hardware::power::Boost::CAMERA_SHOT` |Value obtained from FuzzedDataProvider|
-|`vsyncSource`| 0.`ISurfaceComposer::eVsyncSourceApp`, 1.`ISurfaceComposer::eVsyncSourceSurfaceFlinger`, |Value obtained from FuzzedDataProvider|
-|`eventRegistration`| 0.`ISurfaceComposer::EventRegistration::modeChanged`, 1.`ISurfaceComposer::EventRegistration::frameRateOverride` |Value obtained from FuzzedDataProvider|
-|`frameRateCompatibility`| 0.`ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT`, 1.`ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE` |Value obtained from FuzzedDataProvider|
-|`changeFrameRateStrategy`| 0.`ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS`, 1.`ANATIVEWINDOW_CHANGE_FRAME_RATE_ALWAYS` |Value obtained from FuzzedDataProvider|
-|`hdrTypes`| 0.`ui::Hdr::DOLBY_VISION`, 1.`ui::Hdr::HDR10`, 2.`ui::Hdr::HLG`, 3.`ui::Hdr::HDR10_PLUS` |Value obtained from FuzzedDataProvider|
-
-#### Steps to run
-1. Build the fuzzer
-```
- $ mm -j$(nproc) libgui_surfaceComposer_fuzzer
-```
-2. Run on device
-```
- $ adb sync data
- $ adb shell /data/fuzz/arm64/libgui_surfaceComposer_fuzzer/libgui_surfaceComposer_fuzzer
-```
-
-# <a name="libgui_surfaceComposerClient_fuzzer"></a> Fuzzer for SurfaceComposerClient
-
-SurfaceComposerClient supports the following data sources:
-1. SurfaceWidth (parameter name:`width`)
-2. SurfaceHeight (parameter name:`height`)
-3. TransactionStateFlags (parameter name:`flags`)
-4. TransformHint (parameter name:`outTransformHint`)
-5. SurfacePixelFormat (parameter name:`format`)
-6. LayerId (parameter name:`outLayerId`)
-7. SurfaceComposerClientTags (parameter name:`surfaceTag`)
-8. DefaultMode (parameter name:`defaultMode`)
-9. PrimaryRefreshRateMin (parameter name:`primaryRefreshRateMin`)
-10. PrimaryRefreshRateMax (parameter name:`primaryRefreshRateMax`)
-11. AppRefreshRateMin (parameter name:`appRefreshRateMin`)
-12. AppRefreshRateMax (parameter name:`appRefreshRateMax`)
-13. DisplayPowerMode (parameter name:`mode`)
-14. CacheId (parameter name:`cacheId`)
-15. DisplayBrightness (parameter name:`brightness`)
-16. PowerBoostID (parameter name:`boostId`)
-17. AtomId (parameter name:`atomId`)
-18. ComponentMask (parameter name:`componentMask`)
-19. MaxFrames (parameter name:`maxFrames`)
-20. TaskId (parameter name:`taskId`)
-21. Alpha (parameter name:`aplha`)
-22. CornerRadius (parameter name:`cornerRadius`)
-23. BackgroundBlurRadius (parameter name:`backgroundBlurRadius`)
-24. Half3Color (parameter name:`color`)
-25. LayerStack (parameter name:`layerStack`)
-26. Dataspace (parameter name:`dataspace`)
-27. Api (parameter name:`api`)
-28. Priority (parameter name:`priority`)
-29. TouchableRegionPointX (parameter name:`pointX`)
-30. TouchableRegionPointY (parameter name:`pointY`)
-31. ColorMode (parameter name:`colorMode`)
-32. WindowInfoFlags (parameter name:`flags`)
-33. WindowInfoTransformOrientation (parameter name:`transform`)
-
-| Parameter| Valid Values| Configured Value|
-|------------- |-------------| ----- |
-|`surfaceTag`| 0.`Tag::CREATE_SURFACE`, 1.`Tag::CREATE_WITH_SURFACE_PARENT`, 2.`Tag::CLEAR_LAYER_FRAME_STATS`, 3.`Tag::GET_LAYER_FRAME_STATS`, 4.`Tag::MIRROR_SURFACE`, 5.`Tag::LAST` |Value obtained from FuzzedDataProvider|
-|`mode`| 0.`gui::TouchOcclusionMode::BLOCK_UNTRUSTED`, 1.`gui::TouchOcclusionMode::USE_OPACITY`, 2.`gui::TouchOcclusionMode::ALLOW` |Value obtained from FuzzedDataProvider|
-|`boostId`| 0.`hardware::power::Boost::INTERACTION`, 1.`hardware::power::Boost::DISPLAY_UPDATE_IMMINENT`, 2.`hardware::power::Boost::ML_ACC`, 3.`hardware::power::Boost::AUDIO_LAUNCH`, 4.`hardware::power::Boost::CAMERA_LAUNCH`, 5.`hardware::power::Boost::CAMERA_SHOT` |Value obtained from FuzzedDataProvider|
-|`colorMode`|0.`ui::ColorMode::NATIVE`, 1.`ui::ColorMode::STANDARD_BT601_625`, 2.`ui::ColorMode::STANDARD_BT601_625_UNADJUSTED`, 3.`ui::ColorMode::STANDARD_BT601_525`, 4.`ui::ColorMode::STANDARD_BT601_525_UNADJUSTED`, 5.`ui::ColorMode::STANDARD_BT709`, 6.`ui::ColorMode::DCI_P3`, 7.`ui::ColorMode::SRGB`, 8.`ui::ColorMode::ADOBE_RGB`, 9.`ui::ColorMode::DISPLAY_P3`, 10.`ui::ColorMode::BT2020`, 11.`ui::ColorMode::BT2100_PQ`, 12.`ui::ColorMode::BT2100_HLG`, 13.`ui::ColorMode::DISPLAY_BT2020` |Value obtained from FuzzedDataProvider|
-|`flags`|0 .`gui::WindowInfo::Flag::ALLOW_LOCK_WHILE_SCREEN_ON`, 1.`gui::WindowInfo::Flag::DIM_BEHIND`, 2.`gui::WindowInfo::Flag::BLUR_BEHIND`, 3.`gui::WindowInfo::Flag::NOT_FOCUSABLE`, 4.`gui::WindowInfo::Flag::NOT_TOUCHABLE`, 5.`gui::WindowInfo::Flag::NOT_TOUCH_MODAL`, 6.`gui::WindowInfo::Flag::TOUCHABLE_WHEN_WAKING`, 7.`gui::WindowInfo::Flag::KEEP_SCREEN_ON`, 8.`gui::WindowInfo::Flag::LAYOUT_IN_SCREEN`, 9.`gui::WindowInfo::Flag::LAYOUT_NO_LIMITS`, 10.`gui::WindowInfo::Flag::FULLSCREEN`, 11.`gui::WindowInfo::Flag::FORCE_NOT_FULLSCREEN`, 12.`gui::WindowInfo::Flag::DITHER`, 13.`gui::WindowInfo::Flag::SECURE`, 14.`gui::WindowInfo::Flag::SCALED`, 15.`gui::WindowInfo::Flag::IGNORE_CHEEK_PRESSES`, 16.`gui::WindowInfo::Flag::LAYOUT_INSET_DECOR`, 17.`gui::WindowInfo::Flag::ALT_FOCUSABLE_IM`, 18.`gui::WindowInfo::Flag::WATCH_OUTSIDE_TOUCH`, 19.`gui::WindowInfo::Flag::SHOW_WHEN_LOCKED`, 20.`gui::WindowInfo::Flag::SHOW_WALLPAPER`, 21.`gui::WindowInfo::Flag::TURN_SCREEN_ON`, 22.`gui::WindowInfo::Flag::DISMISS_KEYGUARD`, 23.`gui::WindowInfo::Flag::SPLIT_TOUCH`, 24.`gui::WindowInfo::Flag::HARDWARE_ACCELERATED`, 25.`gui::WindowInfo::Flag::LAYOUT_IN_OVERSCAN`, 26.`gui::WindowInfo::Flag::TRANSLUCENT_STATUS`, 27.`gui::WindowInfo::Flag::TRANSLUCENT_NAVIGATION`, 28.`gui::WindowInfo::Flag::LOCAL_FOCUS_MODE`, 29.`gui::WindowInfo::Flag::SLIPPERY`, 30.`gui::WindowInfo::Flag::LAYOUT_ATTACHED_IN_DECOR`, 31.`gui::WindowInfo::Flag::DRAWS_SYSTEM_BAR_BACKGROUNDS`, |Value obtained from FuzzedDataProvider|
-|`dataspace`| 0.`ui::Dataspace::UNKNOWN`, 1.`ui::Dataspace::ARBITRARY`, 2.`ui::Dataspace::STANDARD_SHIFT`, 3.`ui::Dataspace::STANDARD_MASK`, 4.`ui::Dataspace::STANDARD_UNSPECIFIED`, 5.`ui::Dataspace::STANDARD_BT709`, 6.`ui::Dataspace::STANDARD_BT601_625`, 7.`ui::Dataspace::STANDARD_BT601_625_UNADJUSTED`, 8.`ui::Dataspace::STANDARD_BT601_525`, 9.`ui::Dataspace::STANDARD_BT601_525_UNADJUSTED`, 10.`ui::Dataspace::STANDARD_BT2020`, 11.`ui::Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE`, 12.`ui::Dataspace::STANDARD_BT470M`, 13.`ui::Dataspace::STANDARD_FILM`, 14.`ui::Dataspace::STANDARD_DCI_P3`, 15.`ui::Dataspace::STANDARD_ADOBE_RGB`, 16.`ui::Dataspace::TRANSFER_SHIFT`, 17.`ui::Dataspace::TRANSFER_MASK`, 18.`ui::Dataspace::TRANSFER_UNSPECIFIED`, 19.`ui::Dataspace::TRANSFER_LINEAR`, 20.`ui::Dataspace::TRANSFER_SRGB`, 21.`ui::Dataspace::TRANSFER_SMPTE_170M`, 22.`ui::Dataspace::TRANSFER_GAMMA2_2`, 23.`ui::Dataspace::TRANSFER_GAMMA2_6`, 24.`ui::Dataspace::TRANSFER_GAMMA2_8`, 25.`ui::Dataspace::TRANSFER_ST2084`, 26.`ui::Dataspace::TRANSFER_HLG`, 27.`ui::Dataspace::RANGE_SHIFT`, 28.`ui::Dataspace::RANGE_MASK`, 29.`ui::Dataspace::RANGE_UNSPECIFIED`, 30.`ui::Dataspace::RANGE_FULL`, 31.`ui::Dataspace::RANGE_LIMITED`, 32.`ui::Dataspace::RANGE_EXTENDED`, 33.`ui::Dataspace::SRGB_LINEAR`, 34.`ui::Dataspace::V0_SRGB_LINEAR`, 35.`ui::Dataspace::V0_SCRGB_LINEAR`, 36.`ui::Dataspace::SRGB`, 37.`ui::Dataspace::V0_SRGB`, 38.`ui::Dataspace::V0_SCRGB`, 39.`ui::Dataspace::JFIF`, 40.`ui::Dataspace::V0_JFIF`, 41.`ui::Dataspace::BT601_625`, 42.`ui::Dataspace::V0_BT601_625`, 43.`ui::Dataspace::BT601_525`, 44.`ui::Dataspace::V0_BT601_525`, 45.`ui::Dataspace::BT709`, 46.`ui::Dataspace::V0_BT709`, 47.`ui::Dataspace::DCI_P3_LINEAR`, 48.`ui::Dataspace::DCI_P3`, 49.`ui::Dataspace::DISPLAY_P3_LINEAR`, 50.`ui::Dataspace::DISPLAY_P3`, 51.`ui::Dataspace::ADOBE_RGB`, 52.`ui::Dataspace::BT2020_LINEAR`, 53.`ui::Dataspace::BT2020`, 54.`ui::Dataspace::BT2020_PQ`, 55.`ui::Dataspace::DEPTH`, 56.`ui::Dataspace::SENSOR`, 57.`ui::Dataspace::BT2020_ITU`, 58.`ui::Dataspace::BT2020_ITU_PQ`, 59.`ui::Dataspace::BT2020_ITU_HLG`, 60.`ui::Dataspace::BT2020_HLG`, 61.`ui::Dataspace::DISPLAY_BT2020`, 62.`ui::Dataspace::DYNAMIC_DEPTH`, 63.`ui::Dataspace::JPEG_APP_SEGMENTS`, 64.`ui::Dataspace::HEIF`, |Value obtained from FuzzedDataProvider|
-|`transform`| 0.`ui::Transform::ROT_0`, 1.`ui::Transform::FLIP_H`, 2.`ui::Transform::FLIP_V`, 3.`ui::Transform::ROT_90`, 4.`ui::Transform::ROT_180`, 5.`ui::Transform::ROT_270` |Value obtained from FuzzedDataProvider|
-
-#### Steps to run
-1. Build the fuzzer
-```
- $ mm -j$(nproc) libgui_surfaceComposerClient_fuzzer
-```
-2. To run on device
-```
- $ adb sync data
- $ adb shell /data/fuzz/arm64/libgui_surfaceComposerClient_fuzzer/libgui_surfaceComposerClient_fuzzer
-```
-
-# <a name="libgui_parcelable_fuzzer"></a> Fuzzer for Libgui_Parcelable
-
-Libgui_Parcelable supports the following parameters:
-1. LayerMetadataKey (parameter name:`key`)
-2. Dataspace (parameter name:`mDataspace`)
-
-| Parameter| Valid Values| Configured Value|
-|------------- |-------------| ----- |
-|`key`| 0.`view::LayerMetadataKey::METADATA_OWNER_UID`, 1.`view::LayerMetadataKey::METADATA_WINDOW_TYPE`, 2.`view::LayerMetadataKey::METADATA_TASK_ID`, 3.`view::LayerMetadataKey::METADATA_MOUSE_CURSOR`, 4.`view::LayerMetadataKey::METADATA_ACCESSIBILITY_ID`, 5.`view::LayerMetadataKey::METADATA_OWNER_PID`, 6.`view::LayerMetadataKey::METADATA_DEQUEUE_TIME`, 7.`view::LayerMetadataKey::METADATA_GAME_MODE`, |Value obtained from FuzzedDataProvider|
-|`mDataSpace`| 0.`ui::Dataspace::UNKNOWN`, 1.`ui::Dataspace::ARBITRARY`, 2.`ui::Dataspace::STANDARD_SHIFT`, 3.`ui::Dataspace::STANDARD_MASK`, 4.`ui::Dataspace::STANDARD_UNSPECIFIED`, 5.`ui::Dataspace::STANDARD_BT709`, 6.`ui::Dataspace::STANDARD_BT601_625`, 7.`ui::Dataspace::STANDARD_BT601_625_UNADJUSTED`, 8.`ui::Dataspace::STANDARD_BT601_525`, 9.`ui::Dataspace::STANDARD_BT601_525_UNADJUSTED`, 10.`ui::Dataspace::STANDARD_BT2020`, 11.`ui::Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE`, 12.`ui::Dataspace::STANDARD_BT470M`, 13.`ui::Dataspace::STANDARD_FILM`, 14.`ui::Dataspace::STANDARD_DCI_P3`, 15.`ui::Dataspace::STANDARD_ADOBE_RGB`, 16.`ui::Dataspace::TRANSFER_SHIFT`, 17.`ui::Dataspace::TRANSFER_MASK`, 18.`ui::Dataspace::TRANSFER_UNSPECIFIED`, 19.`ui::Dataspace::TRANSFER_LINEAR`, 20.`ui::Dataspace::TRANSFER_SRGB`, 21.`ui::Dataspace::TRANSFER_SMPTE_170M`, 22.`ui::Dataspace::TRANSFER_GAMMA2_2`, 23.`ui::Dataspace::TRANSFER_GAMMA2_6`, 24.`ui::Dataspace::TRANSFER_GAMMA2_8`, 25.`ui::Dataspace::TRANSFER_ST2084`, 26.`ui::Dataspace::TRANSFER_HLG`, 27.`ui::Dataspace::RANGE_SHIFT`, 28.`ui::Dataspace::RANGE_MASK`, 29.`ui::Dataspace::RANGE_UNSPECIFIED`, 30.`ui::Dataspace::RANGE_FULL`, 31.`ui::Dataspace::RANGE_LIMITED`, 32.`ui::Dataspace::RANGE_EXTENDED`, 33.`ui::Dataspace::SRGB_LINEAR`, 34.`ui::Dataspace::V0_SRGB_LINEAR`, 35.`ui::Dataspace::V0_SCRGB_LINEAR`, 36.`ui::Dataspace::SRGB`, 37.`ui::Dataspace::V0_SRGB`, 38.`ui::Dataspace::V0_SCRGB`, 39.`ui::Dataspace::JFIF`, 40.`ui::Dataspace::V0_JFIF`, 41.`ui::Dataspace::BT601_625`, 42.`ui::Dataspace::V0_BT601_625`, 43.`ui::Dataspace::BT601_525`, 44.`ui::Dataspace::V0_BT601_525`, 45.`ui::Dataspace::BT709`, 46.`ui::Dataspace::V0_BT709`, 47.`ui::Dataspace::DCI_P3_LINEAR`, 48.`ui::Dataspace::DCI_P3`, 49.`ui::Dataspace::DISPLAY_P3_LINEAR`, 50.`ui::Dataspace::DISPLAY_P3`, 51.`ui::Dataspace::ADOBE_RGB`, 52.`ui::Dataspace::BT2020_LINEAR`, 53.`ui::Dataspace::BT2020`, 54.`ui::Dataspace::BT2020_PQ`, 55.`ui::Dataspace::DEPTH`, 56.`ui::Dataspace::SENSOR`, 57.`ui::Dataspace::BT2020_ITU`, 58.`ui::Dataspace::BT2020_ITU_PQ`, 59.`ui::Dataspace::BT2020_ITU_HLG`, 60.`ui::Dataspace::BT2020_HLG`, 61.`ui::Dataspace::DISPLAY_BT2020`, 62.`ui::Dataspace::DYNAMIC_DEPTH`, 63.`ui::Dataspace::JPEG_APP_SEGMENTS`, 64.`ui::Dataspace::HEIF`, |Value obtained from FuzzedDataProvider|
-
-#### Steps to run
-1. Build the fuzzer
-```
- $ mm -j$(nproc) libgui_fuzzer
-```
-2. Run on device
-```
- $ adb sync data
- $ adb shell /data/fuzz/arm64/libgui_fuzzer/libgui_fuzzer
-```
-
-# <a name="libgui_bufferQueue_fuzzer"></a> Fuzzer for BufferQueue
-
-BufferQueue supports the following parameters:
-1. SurfaceWidth (parameter name:`width`)
-2. SurfaceHeight (parameter name:`height`)
-3. TransactionStateFlags (parameter name:`flags`)
-4. TransformHint (parameter name:`outTransformHint`)
-5. SurfacePixelFormat (parameter name:`format`)
-6. LayerId (parameter name:`layerId`)
-7. BufferId (parameter name:`bufferId`)
-8. FrameNumber (parameter name:`frameNumber`)
-9. FrameRate (parameter name:`frameRate`)
-10. Compatability (parameter name:`compatability`)
-11. LatchTime (parameter name:`latchTime`)
-12. AcquireTime (parameter name:`acquireTime`)
-13. RefreshTime (parameter name:`refreshTime`)
-14. DequeueTime (parameter name:`dequeueTime`)
-15. Slot (parameter name:`slot`)
-16. MaxBuffers (parameter name:`maxBuffers`)
-17. GenerationNumber (parameter name:`generationNumber`)
-18. Api (parameter name:`api`)
-19. Usage (parameter name:`usage`)
-20. MaxFrameNumber (parameter name:`maxFrameNumber`)
-21. BufferCount (parameter name:`bufferCount`)
-22. MaxAcquredBufferCount (parameter name:`maxAcquredBufferCount`)
-23. Status (parameter name:`status`)
-24. ApiConnection (parameter name:`apiConnection`)
-25. Dataspace (parameter name:`dataspace`)
-
-| Parameter| Valid Values| Configured Value|
-|------------- |-------------| ----- |
-|`status`| 0.`OK`, 1.`NO_MEMORY`, 2.`NO_INIT`, 3.`BAD_VALUE`, 4.`DEAD_OBJECT`, 5.`INVALID_OPERATION`, 6.`TIMED_OUT`, 7.`WOULD_BLOCK`, 8.`UNKNOWN_ERROR`, 9.`ALREADY_EXISTS`, |Value obtained from FuzzedDataProvider|
-|`apiConnection`| 0.`BufferQueueCore::CURRENTLY_CONNECTED_API`, 1.`BufferQueueCore::NO_CONNECTED_API`, 2.`NATIVE_WINDOW_API_EGL`, 3.`NATIVE_WINDOW_API_CPU`, 4.`NATIVE_WINDOW_API_MEDIA`, 5.`NATIVE_WINDOW_API_CAMERA`, |Value obtained from FuzzedDataProvider|
-|`dataspace`| 0.`ui::Dataspace::UNKNOWN`, 1.`ui::Dataspace::ARBITRARY`, 2.`ui::Dataspace::STANDARD_SHIFT`, 3.`ui::Dataspace::STANDARD_MASK`, 4.`ui::Dataspace::STANDARD_UNSPECIFIED`, 5.`ui::Dataspace::STANDARD_BT709`, 6.`ui::Dataspace::STANDARD_BT601_625`, 7.`ui::Dataspace::STANDARD_BT601_625_UNADJUSTED`, 8.`ui::Dataspace::STANDARD_BT601_525`, 9.`ui::Dataspace::STANDARD_BT601_525_UNADJUSTED`, 10.`ui::Dataspace::STANDARD_BT2020`, 11.`ui::Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE`, 12.`ui::Dataspace::STANDARD_BT470M`, 13.`ui::Dataspace::STANDARD_FILM`, 14.`ui::Dataspace::STANDARD_DCI_P3`, 15.`ui::Dataspace::STANDARD_ADOBE_RGB`, 16.`ui::Dataspace::TRANSFER_SHIFT`, 17.`ui::Dataspace::TRANSFER_MASK`, 18.`ui::Dataspace::TRANSFER_UNSPECIFIED`, 19.`ui::Dataspace::TRANSFER_LINEAR`, 20.`ui::Dataspace::TRANSFER_SRGB`, 21.`ui::Dataspace::TRANSFER_SMPTE_170M`, 22.`ui::Dataspace::TRANSFER_GAMMA2_2`, 23.`ui::Dataspace::TRANSFER_GAMMA2_6`, 24.`ui::Dataspace::TRANSFER_GAMMA2_8`, 25.`ui::Dataspace::TRANSFER_ST2084`, 26.`ui::Dataspace::TRANSFER_HLG`, 27.`ui::Dataspace::RANGE_SHIFT`, 28.`ui::Dataspace::RANGE_MASK`, 29.`ui::Dataspace::RANGE_UNSPECIFIED`, 30.`ui::Dataspace::RANGE_FULL`, 31.`ui::Dataspace::RANGE_LIMITED`, 32.`ui::Dataspace::RANGE_EXTENDED`, 33.`ui::Dataspace::SRGB_LINEAR`, 34.`ui::Dataspace::V0_SRGB_LINEAR`, 35.`ui::Dataspace::V0_SCRGB_LINEAR`, 36.`ui::Dataspace::SRGB`, 37.`ui::Dataspace::V0_SRGB`, 38.`ui::Dataspace::V0_SCRGB`, 39.`ui::Dataspace::JFIF`, 40.`ui::Dataspace::V0_JFIF`, 41.`ui::Dataspace::BT601_625`, 42.`ui::Dataspace::V0_BT601_625`, 43.`ui::Dataspace::BT601_525`, 44.`ui::Dataspace::V0_BT601_525`, 45.`ui::Dataspace::BT709`, 46.`ui::Dataspace::V0_BT709`, 47.`ui::Dataspace::DCI_P3_LINEAR`, 48.`ui::Dataspace::DCI_P3`, 49.`ui::Dataspace::DISPLAY_P3_LINEAR`, 50.`ui::Dataspace::DISPLAY_P3`, 51.`ui::Dataspace::ADOBE_RGB`, 52.`ui::Dataspace::BT2020_LINEAR`, 53.`ui::Dataspace::BT2020`, 54.`ui::Dataspace::BT2020_PQ`, 55.`ui::Dataspace::DEPTH`, 56.`ui::Dataspace::SENSOR`, 57.`ui::Dataspace::BT2020_ITU`, 58.`ui::Dataspace::BT2020_ITU_PQ`, 59.`ui::Dataspace::BT2020_ITU_HLG`, 60.`ui::Dataspace::BT2020_HLG`, 61.`ui::Dataspace::DISPLAY_BT2020`, 62.`ui::Dataspace::DYNAMIC_DEPTH`, 63.`ui::Dataspace::JPEG_APP_SEGMENTS`, 64.`ui::Dataspace::HEIF`, |Value obtained from FuzzedDataProvider|
-
-#### Steps to run
-1. Build the fuzzer
-```
- $ mm -j$(nproc) libgui_bufferQueue_fuzzer
-```
-2. To run on device
-```
- $ adb sync data
- $ adb shell /data/fuzz/arm64/libgui_bufferQueue_fuzzer/libgui_bufferQueue_fuzzer
-```
-
-# <a name="libgui_consumer_fuzzer"></a> Fuzzer for Libgui_Consumer
-
-Libgui_Consumer supports the following parameters:
-1. GraphicWidth (parameter name:`graphicWidth`)
-2. GraphicHeight (parameter name:`graphicHeight`)
-4. TransformHint (parameter name:`outTransformHint`)
-5. GraphicPixelFormat (parameter name:`format`)
-6. Usage (parameter name:`usage`)
-
-#### Steps to run
-1. Build the fuzzer
-```
- $ mm -j$(nproc) libgui_consumer_fuzzer
-```
-2. Run on device
-```
- $ adb sync data
- $ adb shell /data/fuzz/arm64/libgui_consumer_fuzzer/libgui_consumer_fuzzer
-```
-
-# <a name="libgui_displayEvent_fuzzer"></a> Fuzzer for LibGui_DisplayEvent
-
-LibGui_DisplayEvent supports the following parameters:
-1. DisplayEventType (parameter name:`type`)
-2. Events (parameter name:`events`)
-3. VsyncSource (parameter name:`vsyncSource`)
-4. EventRegistrationFlags (parameter name:`flags`)
-
-| Parameter| Valid Values| Configured Value|
-|------------- |-------------| ----- |
-|`vsyncSource`| 0.`ISurfaceComposer::eVsyncSourceApp`, 1.`ISurfaceComposer::eVsyncSourceSurfaceFlinger`, |Value obtained from FuzzedDataProvider|
-|`flags`| 0.`ISurfaceComposer::EventRegistration::modeChanged`, 1.`ISurfaceComposer::EventRegistration::frameRateOverride`, |Value obtained from FuzzedDataProvider|
-|`type`| 0.`DisplayEventReceiver::DISPLAY_EVENT_NULL`, 1.`DisplayEventReceiver::DISPLAY_EVENT_VSYNC`, 2.`DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG`, 3.`DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE`, 4.`DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE`, 5.`DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH`, |Value obtained from FuzzedDataProvider|
-|`events`| 0.`Looper::EVENT_INPUT`, 1.`Looper::EVENT_OUTPUT`, 2.`Looper::EVENT_ERROR`, 3.`Looper::EVENT_HANGUP`, 4.`Looper::EVENT_INVALID`, |Value obtained from FuzzedDataProvider|
-
-#### Steps to run
-1. Build the fuzzer
-```
- $ mm -j$(nproc) libgui_displayEvent_fuzzer
-```
-2. Run on device
-```
- $ adb sync data
- $ adb shell /data/fuzz/arm64/libgui_displayEvent_fuzzer/libgui_displayEvent_fuzzer
-```
diff --git a/libs/gui/fuzzer/libgui_bufferQueue_fuzzer.cpp b/libs/gui/fuzzer/libgui_bufferQueue_fuzzer.cpp
deleted file mode 100644
index 2e270b7..0000000
--- a/libs/gui/fuzzer/libgui_bufferQueue_fuzzer.cpp
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <android-base/stringprintf.h>
-#include <gui/BufferQueueConsumer.h>
-#include <gui/BufferQueueCore.h>
-#include <gui/BufferQueueProducer.h>
-#include <gui/bufferqueue/2.0/types.h>
-#include <system/window.h>
-
-#include <libgui_fuzzer_utils.h>
-
-using namespace android;
-using namespace hardware::graphics::bufferqueue;
-using namespace V1_0::utils;
-using namespace V2_0::utils;
-
-constexpr int32_t kMaxBytes = 256;
-
-constexpr int32_t kError[] = {
- OK, NO_MEMORY, NO_INIT, BAD_VALUE, DEAD_OBJECT, INVALID_OPERATION,
- TIMED_OUT, WOULD_BLOCK, UNKNOWN_ERROR, ALREADY_EXISTS,
-};
-
-constexpr int32_t kAPIConnection[] = {
- BufferQueueCore::CURRENTLY_CONNECTED_API,
- BufferQueueCore::NO_CONNECTED_API,
- NATIVE_WINDOW_API_EGL,
- NATIVE_WINDOW_API_CPU,
- NATIVE_WINDOW_API_MEDIA,
- NATIVE_WINDOW_API_CAMERA,
-};
-
-class BufferQueueFuzzer {
-public:
- BufferQueueFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
- void process();
-
-private:
- void invokeTypes();
- void invokeH2BGraphicBufferV1();
- void invokeH2BGraphicBufferV2();
- void invokeBufferQueueConsumer();
- void invokeBufferQueueProducer();
- void invokeBlastBufferQueue();
- void invokeQuery(sp<BufferQueueProducer>);
- void invokeQuery(sp<V1_0::utils::H2BGraphicBufferProducer>);
- void invokeQuery(sp<V2_0::utils::H2BGraphicBufferProducer>);
- void invokeAcquireBuffer(sp<BufferQueueConsumer>);
- void invokeOccupancyTracker(sp<BufferQueueConsumer>);
- sp<SurfaceControl> makeSurfaceControl();
- sp<BLASTBufferQueue> makeBLASTBufferQueue(sp<SurfaceControl>);
-
- FuzzedDataProvider mFdp;
-};
-
-class ManageResourceHandle {
-public:
- ManageResourceHandle(FuzzedDataProvider* fdp) {
- mNativeHandle = native_handle_create(0 /*numFds*/, 1 /*numInts*/);
- mShouldOwn = fdp->ConsumeBool();
- mStream = NativeHandle::create(mNativeHandle, mShouldOwn);
- }
- ~ManageResourceHandle() {
- if (!mShouldOwn) {
- native_handle_close(mNativeHandle);
- native_handle_delete(mNativeHandle);
- }
- }
- sp<NativeHandle> getStream() { return mStream; }
-
-private:
- bool mShouldOwn;
- sp<NativeHandle> mStream;
- native_handle_t* mNativeHandle;
-};
-
-sp<SurfaceControl> BufferQueueFuzzer::makeSurfaceControl() {
- sp<IBinder> handle;
- const sp<FakeBnSurfaceComposerClient> testClient(new FakeBnSurfaceComposerClient());
- sp<SurfaceComposerClient> client = new SurfaceComposerClient(testClient);
- sp<BnGraphicBufferProducer> producer;
- uint32_t layerId = mFdp.ConsumeIntegral<uint32_t>();
- std::string layerName = base::StringPrintf("#%d", layerId);
- return sp<SurfaceControl>::make(client, handle, layerId, layerName,
- mFdp.ConsumeIntegral<int32_t>(),
- mFdp.ConsumeIntegral<uint32_t>(),
- mFdp.ConsumeIntegral<int32_t>(),
- mFdp.ConsumeIntegral<uint32_t>(),
- mFdp.ConsumeIntegral<uint32_t>());
-}
-
-sp<BLASTBufferQueue> BufferQueueFuzzer::makeBLASTBufferQueue(sp<SurfaceControl> surface) {
- return sp<BLASTBufferQueue>::make(mFdp.ConsumeRandomLengthString(kMaxBytes), surface,
- mFdp.ConsumeIntegral<uint32_t>(),
- mFdp.ConsumeIntegral<uint32_t>(),
- mFdp.ConsumeIntegral<int32_t>());
-}
-
-void BufferQueueFuzzer::invokeBlastBufferQueue() {
- sp<SurfaceControl> surface = makeSurfaceControl();
- sp<BLASTBufferQueue> queue = makeBLASTBufferQueue(surface);
-
- BufferItem item;
- queue->onFrameAvailable(item);
- queue->onFrameReplaced(item);
- uint64_t bufferId = mFdp.ConsumeIntegral<uint64_t>();
- queue->onFrameDequeued(bufferId);
- queue->onFrameCancelled(bufferId);
-
- SurfaceComposerClient::Transaction next;
- uint64_t frameNumber = mFdp.ConsumeIntegral<uint64_t>();
- queue->mergeWithNextTransaction(&next, frameNumber);
- queue->applyPendingTransactions(frameNumber);
-
- queue->update(surface, mFdp.ConsumeIntegral<uint32_t>(), mFdp.ConsumeIntegral<uint32_t>(),
- mFdp.ConsumeIntegral<int32_t>());
- queue->setFrameRate(mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeIntegral<int8_t>(),
- mFdp.ConsumeBool() /*shouldBeSeamless*/);
- FrameTimelineInfo info;
- queue->setFrameTimelineInfo(mFdp.ConsumeIntegral<uint64_t>(), info);
-
- ManageResourceHandle handle(&mFdp);
- queue->setSidebandStream(handle.getStream());
-
- queue->getLastTransformHint();
- queue->getLastAcquiredFrameNum();
-
- CompositorTiming compTiming;
- sp<Fence> previousFence = new Fence(memfd_create("pfd", MFD_ALLOW_SEALING));
- sp<Fence> gpuFence = new Fence(memfd_create("gfd", MFD_ALLOW_SEALING));
- FrameEventHistoryStats frameStats(frameNumber, mFdp.ConsumeIntegral<uint64_t>(), gpuFence,
- compTiming, mFdp.ConsumeIntegral<int64_t>(),
- mFdp.ConsumeIntegral<int64_t>());
- std::vector<SurfaceControlStats> stats;
- sp<Fence> presentFence = new Fence(memfd_create("fd", MFD_ALLOW_SEALING));
- SurfaceControlStats controlStats(surface, mFdp.ConsumeIntegral<int64_t>(),
- mFdp.ConsumeIntegral<int64_t>(), presentFence, previousFence,
- mFdp.ConsumeIntegral<uint32_t>(), frameStats,
- mFdp.ConsumeIntegral<uint32_t>());
- stats.push_back(controlStats);
-}
-
-void BufferQueueFuzzer::invokeQuery(sp<BufferQueueProducer> producer) {
- int32_t value;
- producer->query(mFdp.ConsumeIntegral<int32_t>(), &value);
-}
-
-void BufferQueueFuzzer::invokeQuery(sp<V1_0::utils::H2BGraphicBufferProducer> producer) {
- int32_t value;
- producer->query(mFdp.ConsumeIntegral<int32_t>(), &value);
-}
-
-void BufferQueueFuzzer::invokeQuery(sp<V2_0::utils::H2BGraphicBufferProducer> producer) {
- int32_t value;
- producer->query(mFdp.ConsumeIntegral<int32_t>(), &value);
-}
-
-void BufferQueueFuzzer::invokeBufferQueueProducer() {
- sp<BufferQueueCore> core(new BufferQueueCore());
- sp<BufferQueueProducer> producer(new BufferQueueProducer(core));
- const sp<android::IProducerListener> listener;
- android::IGraphicBufferProducer::QueueBufferOutput output;
- uint32_t api = mFdp.ConsumeIntegral<uint32_t>();
- producer->connect(listener, api, mFdp.ConsumeBool() /*producerControlledByApp*/, &output);
-
- sp<GraphicBuffer> buffer;
- int32_t slot = mFdp.ConsumeIntegral<int32_t>();
- uint32_t maxBuffers = mFdp.ConsumeIntegral<uint32_t>();
- producer->requestBuffer(slot, &buffer);
- producer->setMaxDequeuedBufferCount(maxBuffers);
- producer->setAsyncMode(mFdp.ConsumeBool() /*async*/);
-
- android::IGraphicBufferProducer::QueueBufferInput input;
- producer->attachBuffer(&slot, buffer);
- producer->queueBuffer(slot, input, &output);
-
- int32_t format = mFdp.ConsumeIntegral<int32_t>();
- uint32_t width = mFdp.ConsumeIntegral<uint32_t>();
- uint32_t height = mFdp.ConsumeIntegral<uint32_t>();
- uint64_t usage = mFdp.ConsumeIntegral<uint64_t>();
- uint64_t outBufferAge;
- FrameEventHistoryDelta outTimestamps;
- sp<android::Fence> fence;
- producer->dequeueBuffer(&slot, &fence, width, height, format, usage, &outBufferAge,
- &outTimestamps);
- producer->detachBuffer(slot);
- producer->detachNextBuffer(&buffer, &fence);
- producer->cancelBuffer(slot, fence);
-
- invokeQuery(producer);
-
- ManageResourceHandle handle(&mFdp);
- producer->setSidebandStream(handle.getStream());
-
- producer->allocateBuffers(width, height, format, usage);
- producer->allowAllocation(mFdp.ConsumeBool() /*allow*/);
- producer->setSharedBufferMode(mFdp.ConsumeBool() /*sharedBufferMode*/);
- producer->setAutoRefresh(mFdp.ConsumeBool() /*autoRefresh*/);
- producer->setLegacyBufferDrop(mFdp.ConsumeBool() /*drop*/);
- producer->setAutoPrerotation(mFdp.ConsumeBool() /*autoPrerotation*/);
-
- producer->setGenerationNumber(mFdp.ConsumeIntegral<uint32_t>());
- producer->setDequeueTimeout(mFdp.ConsumeIntegral<uint32_t>());
- producer->disconnect(api);
-}
-
-void BufferQueueFuzzer::invokeAcquireBuffer(sp<BufferQueueConsumer> consumer) {
- BufferItem item;
- consumer->acquireBuffer(&item, mFdp.ConsumeIntegral<uint32_t>(),
- mFdp.ConsumeIntegral<uint64_t>());
-}
-
-void BufferQueueFuzzer::invokeOccupancyTracker(sp<BufferQueueConsumer> consumer) {
- String8 outResult;
- String8 prefix((mFdp.ConsumeRandomLengthString(kMaxBytes)).c_str());
- consumer->dumpState(prefix, &outResult);
-
- std::vector<OccupancyTracker::Segment> outHistory;
- consumer->getOccupancyHistory(mFdp.ConsumeBool() /*forceFlush*/, &outHistory);
-}
-
-void BufferQueueFuzzer::invokeBufferQueueConsumer() {
- sp<BufferQueueCore> core(new BufferQueueCore());
- sp<BufferQueueConsumer> consumer(new BufferQueueConsumer(core));
- sp<android::IConsumerListener> listener;
- consumer->consumerConnect(listener, mFdp.ConsumeBool() /*controlledByApp*/);
- invokeAcquireBuffer(consumer);
-
- int32_t slot = mFdp.ConsumeIntegral<int32_t>();
- sp<GraphicBuffer> buffer =
- new GraphicBuffer(mFdp.ConsumeIntegral<uint32_t>(), mFdp.ConsumeIntegral<uint32_t>(),
- mFdp.ConsumeIntegral<int32_t>(), mFdp.ConsumeIntegral<uint32_t>(),
- mFdp.ConsumeIntegral<uint64_t>());
- consumer->attachBuffer(&slot, buffer);
- consumer->detachBuffer(slot);
-
- consumer->setDefaultBufferSize(mFdp.ConsumeIntegral<uint32_t>(),
- mFdp.ConsumeIntegral<uint32_t>());
- consumer->setMaxBufferCount(mFdp.ConsumeIntegral<int32_t>());
- consumer->setMaxAcquiredBufferCount(mFdp.ConsumeIntegral<int32_t>());
-
- String8 name((mFdp.ConsumeRandomLengthString(kMaxBytes)).c_str());
- consumer->setConsumerName(name);
- consumer->setDefaultBufferFormat(mFdp.ConsumeIntegral<int32_t>());
- android_dataspace dataspace =
- static_cast<android_dataspace>(mFdp.PickValueInArray(kDataspaces));
- consumer->setDefaultBufferDataSpace(dataspace);
-
- consumer->setTransformHint(mFdp.ConsumeIntegral<uint32_t>());
- consumer->setConsumerUsageBits(mFdp.ConsumeIntegral<uint64_t>());
- consumer->setConsumerIsProtected(mFdp.ConsumeBool() /*isProtected*/);
- invokeOccupancyTracker(consumer);
-
- sp<Fence> releaseFence = new Fence(memfd_create("fd", MFD_ALLOW_SEALING));
- consumer->releaseBuffer(mFdp.ConsumeIntegral<int32_t>(), mFdp.ConsumeIntegral<uint64_t>(),
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, releaseFence);
- consumer->consumerDisconnect();
-}
-
-void BufferQueueFuzzer::invokeTypes() {
- HStatus hStatus;
- int32_t status = mFdp.PickValueInArray(kError);
- bool bufferNeedsReallocation = mFdp.ConsumeBool();
- bool releaseAllBuffers = mFdp.ConsumeBool();
- b2h(status, &hStatus, &bufferNeedsReallocation, &releaseAllBuffers);
- h2b(hStatus, &status);
-
- HConnectionType type;
- int32_t apiConnection = mFdp.PickValueInArray(kAPIConnection);
- b2h(apiConnection, &type);
- h2b(type, &apiConnection);
-}
-
-void BufferQueueFuzzer::invokeH2BGraphicBufferV1() {
- sp<V1_0::utils::H2BGraphicBufferProducer> producer(
- new V1_0::utils::H2BGraphicBufferProducer(new FakeGraphicBufferProducerV1()));
- const sp<android::IProducerListener> listener;
- android::IGraphicBufferProducer::QueueBufferOutput output;
- uint32_t api = mFdp.ConsumeIntegral<uint32_t>();
- producer->connect(listener, api, mFdp.ConsumeBool() /*producerControlledByApp*/, &output);
-
- sp<GraphicBuffer> buffer;
- int32_t slot = mFdp.ConsumeIntegral<int32_t>();
- producer->requestBuffer(slot, &buffer);
- producer->setMaxDequeuedBufferCount(mFdp.ConsumeIntegral<int32_t>());
- producer->setAsyncMode(mFdp.ConsumeBool());
-
- android::IGraphicBufferProducer::QueueBufferInput input;
- input.fence = new Fence(memfd_create("ffd", MFD_ALLOW_SEALING));
- producer->attachBuffer(&slot, buffer);
- producer->queueBuffer(slot, input, &output);
-
- int32_t format = mFdp.ConsumeIntegral<int32_t>();
- uint32_t width = mFdp.ConsumeIntegral<uint32_t>();
- uint32_t height = mFdp.ConsumeIntegral<uint32_t>();
- uint64_t usage = mFdp.ConsumeIntegral<uint64_t>();
- uint64_t outBufferAge;
- FrameEventHistoryDelta outTimestamps;
- sp<android::Fence> fence;
- producer->dequeueBuffer(&slot, &fence, width, height, format, usage, &outBufferAge,
- &outTimestamps);
- producer->detachBuffer(slot);
- producer->cancelBuffer(slot, fence);
-
- invokeQuery(producer);
-
- ManageResourceHandle handle(&mFdp);
- producer->setSidebandStream(handle.getStream());
-
- producer->allocateBuffers(width, height, format, usage);
- producer->allowAllocation(mFdp.ConsumeBool() /*allow*/);
- producer->setSharedBufferMode(mFdp.ConsumeBool() /*sharedBufferMode*/);
- producer->setAutoRefresh(mFdp.ConsumeBool() /*autoRefresh*/);
-
- producer->setGenerationNumber(mFdp.ConsumeIntegral<uint32_t>());
- producer->setDequeueTimeout(mFdp.ConsumeIntegral<uint32_t>());
- producer->disconnect(api);
-}
-
-void BufferQueueFuzzer::invokeH2BGraphicBufferV2() {
- sp<V2_0::utils::H2BGraphicBufferProducer> producer(
- new V2_0::utils::H2BGraphicBufferProducer(new FakeGraphicBufferProducerV2()));
- const sp<android::IProducerListener> listener;
- android::IGraphicBufferProducer::QueueBufferOutput output;
- uint32_t api = mFdp.ConsumeIntegral<uint32_t>();
- producer->connect(listener, api, mFdp.ConsumeBool() /*producerControlledByApp*/, &output);
-
- sp<GraphicBuffer> buffer;
- int32_t slot = mFdp.ConsumeIntegral<int32_t>();
- producer->requestBuffer(slot, &buffer);
- producer->setMaxDequeuedBufferCount(mFdp.ConsumeIntegral<uint32_t>());
- producer->setAsyncMode(mFdp.ConsumeBool());
-
- android::IGraphicBufferProducer::QueueBufferInput input;
- input.fence = new Fence(memfd_create("ffd", MFD_ALLOW_SEALING));
- producer->attachBuffer(&slot, buffer);
- producer->queueBuffer(slot, input, &output);
-
- int32_t format = mFdp.ConsumeIntegral<int32_t>();
- uint32_t width = mFdp.ConsumeIntegral<uint32_t>();
- uint32_t height = mFdp.ConsumeIntegral<uint32_t>();
- uint64_t usage = mFdp.ConsumeIntegral<uint64_t>();
- uint64_t outBufferAge;
- FrameEventHistoryDelta outTimestamps;
- sp<android::Fence> fence;
- producer->dequeueBuffer(&slot, &fence, width, height, format, usage, &outBufferAge,
- &outTimestamps);
- producer->detachBuffer(slot);
- producer->cancelBuffer(slot, fence);
-
- invokeQuery(producer);
-
- ManageResourceHandle handle(&mFdp);
- producer->setSidebandStream(handle.getStream());
-
- producer->allocateBuffers(width, height, format, usage);
- producer->allowAllocation(mFdp.ConsumeBool() /*allow*/);
- producer->setSharedBufferMode(mFdp.ConsumeBool() /*sharedBufferMode*/);
- producer->setAutoRefresh(mFdp.ConsumeBool() /*autoRefresh*/);
-
- producer->setGenerationNumber(mFdp.ConsumeIntegral<uint32_t>());
- producer->setDequeueTimeout(mFdp.ConsumeIntegral<uint32_t>());
- producer->disconnect(api);
-}
-
-void BufferQueueFuzzer::process() {
- invokeBlastBufferQueue();
- invokeH2BGraphicBufferV1();
- invokeH2BGraphicBufferV2();
- invokeTypes();
- invokeBufferQueueConsumer();
- invokeBufferQueueProducer();
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- BufferQueueFuzzer bufferQueueFuzzer(data, size);
- bufferQueueFuzzer.process();
- return 0;
-}
diff --git a/libs/gui/fuzzer/libgui_consumer_fuzzer.cpp b/libs/gui/fuzzer/libgui_consumer_fuzzer.cpp
deleted file mode 100644
index 24a046d..0000000
--- a/libs/gui/fuzzer/libgui_consumer_fuzzer.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <gui/BufferQueueConsumer.h>
-#include <gui/BufferQueueCore.h>
-#include <gui/BufferQueueProducer.h>
-#include <gui/GLConsumer.h>
-#include <libgui_fuzzer_utils.h>
-
-using namespace android;
-
-constexpr int32_t kMinBuffer = 0;
-constexpr int32_t kMaxBuffer = 100000;
-
-class ConsumerFuzzer {
-public:
- ConsumerFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
- void process();
-
-private:
- FuzzedDataProvider mFdp;
-};
-
-void ConsumerFuzzer::process() {
- sp<BufferQueueCore> core(new BufferQueueCore());
- sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
-
- uint64_t maxBuffers = mFdp.ConsumeIntegralInRange<uint64_t>(kMinBuffer, kMaxBuffer);
- sp<CpuConsumer> cpu(
- new CpuConsumer(consumer, maxBuffers, mFdp.ConsumeBool() /*controlledByApp*/));
- CpuConsumer::LockedBuffer lockBuffer;
- cpu->lockNextBuffer(&lockBuffer);
- cpu->unlockBuffer(lockBuffer);
- cpu->abandon();
-
- uint32_t tex = mFdp.ConsumeIntegral<uint32_t>();
- sp<GLConsumer> glComsumer(new GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL,
- mFdp.ConsumeBool() /*useFenceSync*/,
- mFdp.ConsumeBool() /*isControlledByApp*/));
- sp<Fence> releaseFence = new Fence(memfd_create("rfd", MFD_ALLOW_SEALING));
- glComsumer->setReleaseFence(releaseFence);
- glComsumer->updateTexImage();
- glComsumer->releaseTexImage();
-
- sp<GraphicBuffer> buffer =
- new GraphicBuffer(mFdp.ConsumeIntegral<uint32_t>(), mFdp.ConsumeIntegral<uint32_t>(),
- mFdp.ConsumeIntegral<int32_t>(), mFdp.ConsumeIntegral<uint32_t>(),
- mFdp.ConsumeIntegral<uint64_t>());
- float mtx[16];
- glComsumer->getTransformMatrix(mtx);
- glComsumer->computeTransformMatrix(mtx, buffer, getRect(&mFdp),
- mFdp.ConsumeIntegral<uint32_t>(),
- mFdp.ConsumeBool() /*filtering*/);
- glComsumer->scaleDownCrop(getRect(&mFdp), mFdp.ConsumeIntegral<uint32_t>(),
- mFdp.ConsumeIntegral<uint32_t>());
-
- glComsumer->setDefaultBufferSize(mFdp.ConsumeIntegral<uint32_t>(),
- mFdp.ConsumeIntegral<uint32_t>());
- glComsumer->setFilteringEnabled(mFdp.ConsumeBool() /*enabled*/);
-
- glComsumer->setConsumerUsageBits(mFdp.ConsumeIntegral<uint64_t>());
- glComsumer->attachToContext(tex);
- glComsumer->abandon();
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- ConsumerFuzzer consumerFuzzer(data, size);
- consumerFuzzer.process();
- return 0;
-}
diff --git a/libs/gui/fuzzer/libgui_displayEvent_fuzzer.cpp b/libs/gui/fuzzer/libgui_displayEvent_fuzzer.cpp
deleted file mode 100644
index 0d2a52b..0000000
--- a/libs/gui/fuzzer/libgui_displayEvent_fuzzer.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/gui/ISurfaceComposer.h>
-
-#include <libgui_fuzzer_utils.h>
-
-using namespace android;
-
-constexpr gui::ISurfaceComposer::VsyncSource kVsyncSource[] = {
- gui::ISurfaceComposer::VsyncSource::eVsyncSourceApp,
- gui::ISurfaceComposer::VsyncSource::eVsyncSourceSurfaceFlinger,
-};
-
-constexpr gui::ISurfaceComposer::EventRegistration kEventRegistration[] = {
- gui::ISurfaceComposer::EventRegistration::modeChanged,
- gui::ISurfaceComposer::EventRegistration::frameRateOverride,
-};
-
-constexpr uint32_t kDisplayEvent[] = {
- DisplayEventReceiver::DISPLAY_EVENT_NULL,
- DisplayEventReceiver::DISPLAY_EVENT_VSYNC,
- DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG,
- DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE,
- DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE,
- DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH,
-};
-
-constexpr int32_t kEvents[] = {
- Looper::EVENT_INPUT, Looper::EVENT_OUTPUT, Looper::EVENT_ERROR,
- Looper::EVENT_HANGUP, Looper::EVENT_INVALID,
-};
-
-DisplayEventReceiver::Event buildDisplayEvent(FuzzedDataProvider* fdp, uint32_t type,
- DisplayEventReceiver::Event event) {
- switch (type) {
- case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: {
- event.vsync.count = fdp->ConsumeIntegral<uint32_t>();
- event.vsync.vsyncData.frameInterval = fdp->ConsumeIntegral<uint64_t>();
- event.vsync.vsyncData.preferredFrameTimelineIndex = fdp->ConsumeIntegral<uint32_t>();
- for (size_t idx = 0; idx < gui::VsyncEventData::kFrameTimelinesCapacity; ++idx) {
- event.vsync.vsyncData.frameTimelines[idx].vsyncId = fdp->ConsumeIntegral<int64_t>();
- event.vsync.vsyncData.frameTimelines[idx].deadlineTimestamp =
- fdp->ConsumeIntegral<uint64_t>();
- event.vsync.vsyncData.frameTimelines[idx].expectedPresentationTime =
- fdp->ConsumeIntegral<uint64_t>();
- }
- break;
-
- }
- case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: {
- event.hotplug =
- DisplayEventReceiver::Event::Hotplug{fdp->ConsumeBool() /*connected*/,
- fdp->ConsumeIntegral<
- int32_t>() /*connectionError*/};
- break;
- }
- case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: {
- event.modeChange =
- DisplayEventReceiver::Event::ModeChange{fdp->ConsumeIntegral<int32_t>(),
- fdp->ConsumeIntegral<int64_t>()};
- break;
- }
- case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
- case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH: {
- event.frameRateOverride =
- DisplayEventReceiver::Event::FrameRateOverride{fdp->ConsumeIntegral<uint32_t>(),
- fdp->ConsumeFloatingPoint<
- float>()};
- break;
- }
- }
- return event;
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- FuzzedDataProvider fdp(data, size);
- sp<Looper> looper;
- sp<FakeDisplayEventDispatcher> dispatcher(
- new FakeDisplayEventDispatcher(looper, fdp.PickValueInArray(kVsyncSource),
- fdp.PickValueInArray(kEventRegistration)));
-
- dispatcher->initialize();
- DisplayEventReceiver::Event event;
- uint32_t type = fdp.PickValueInArray(kDisplayEvent);
- PhysicalDisplayId displayId;
- event.header =
- DisplayEventReceiver::Event::Header{type, displayId, fdp.ConsumeIntegral<int64_t>()};
- event = buildDisplayEvent(&fdp, type, event);
-
- dispatcher->injectEvent(event);
- dispatcher->handleEvent(0, fdp.PickValueInArray(kEvents), nullptr);
- return 0;
-}
diff --git a/libs/gui/fuzzer/libgui_fuzzer_utils.h b/libs/gui/fuzzer/libgui_fuzzer_utils.h
deleted file mode 100644
index 2bdbd43..0000000
--- a/libs/gui/fuzzer/libgui_fuzzer_utils.h
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <android/gui/BnRegionSamplingListener.h>
-#include <android/gui/BnSurfaceComposer.h>
-#include <android/gui/BnSurfaceComposerClient.h>
-#include <android/gui/IDisplayEventConnection.h>
-#include <android/gui/ISurfaceComposerClient.h>
-#include <fuzzer/FuzzedDataProvider.h>
-#include <gmock/gmock.h>
-#include <gui/BLASTBufferQueue.h>
-#include <gui/DisplayEventDispatcher.h>
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/LayerDebugInfo.h>
-#include <gui/LayerState.h>
-#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
-#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
-#include <ui/fuzzer/FuzzableDataspaces.h>
-
-namespace android {
-
-constexpr uint32_t kOrientation[] = {
- ui::Transform::ROT_0, ui::Transform::FLIP_H, ui::Transform::FLIP_V,
- ui::Transform::ROT_90, ui::Transform::ROT_180, ui::Transform::ROT_270,
-};
-
-Rect getRect(FuzzedDataProvider* fdp) {
- const int32_t left = fdp->ConsumeIntegral<int32_t>();
- const int32_t top = fdp->ConsumeIntegral<int32_t>();
- const int32_t right = fdp->ConsumeIntegral<int32_t>();
- const int32_t bottom = fdp->ConsumeIntegral<int32_t>();
- return Rect(left, top, right, bottom);
-}
-
-gui::DisplayBrightness getBrightness(FuzzedDataProvider* fdp) {
- static constexpr float kMinBrightness = 0;
- static constexpr float kMaxBrightness = 1;
- gui::DisplayBrightness brightness;
- brightness.sdrWhitePoint =
- fdp->ConsumeFloatingPointInRange<float>(kMinBrightness, kMaxBrightness);
- brightness.sdrWhitePointNits =
- fdp->ConsumeFloatingPointInRange<float>(kMinBrightness, kMaxBrightness);
- brightness.displayBrightness =
- fdp->ConsumeFloatingPointInRange<float>(kMinBrightness, kMaxBrightness);
- brightness.displayBrightnessNits =
- fdp->ConsumeFloatingPointInRange<float>(kMinBrightness, kMaxBrightness);
- return brightness;
-}
-
-class FakeBnSurfaceComposer : public gui::BnSurfaceComposer {
-public:
- MOCK_METHOD(binder::Status, bootFinished, (), (override));
- MOCK_METHOD(binder::Status, createDisplayEventConnection,
- (gui::ISurfaceComposer::VsyncSource, gui::ISurfaceComposer::EventRegistration,
- const sp<IBinder>& /*layerHandle*/, sp<gui::IDisplayEventConnection>*),
- (override));
- MOCK_METHOD(binder::Status, createConnection, (sp<gui::ISurfaceComposerClient>*), (override));
- MOCK_METHOD(binder::Status, createDisplay, (const std::string&, bool, float, sp<IBinder>*),
- (override));
- MOCK_METHOD(binder::Status, destroyDisplay, (const sp<IBinder>&), (override));
- MOCK_METHOD(binder::Status, getPhysicalDisplayIds, (std::vector<int64_t>*), (override));
- MOCK_METHOD(binder::Status, getPhysicalDisplayToken, (int64_t, sp<IBinder>*), (override));
- MOCK_METHOD(binder::Status, setPowerMode, (const sp<IBinder>&, int), (override));
- MOCK_METHOD(binder::Status, getSupportedFrameTimestamps, (std::vector<FrameEvent>*),
- (override));
- MOCK_METHOD(binder::Status, getDisplayStats, (const sp<IBinder>&, gui::DisplayStatInfo*),
- (override));
- MOCK_METHOD(binder::Status, getDisplayState, (const sp<IBinder>&, gui::DisplayState*),
- (override));
- MOCK_METHOD(binder::Status, getStaticDisplayInfo, (int64_t, gui::StaticDisplayInfo*),
- (override));
- MOCK_METHOD(binder::Status, getDynamicDisplayInfoFromId, (int64_t, gui::DynamicDisplayInfo*),
- (override));
- MOCK_METHOD(binder::Status, getDynamicDisplayInfoFromToken,
- (const sp<IBinder>&, gui::DynamicDisplayInfo*), (override));
- MOCK_METHOD(binder::Status, getDisplayNativePrimaries,
- (const sp<IBinder>&, gui::DisplayPrimaries*), (override));
- MOCK_METHOD(binder::Status, setActiveColorMode, (const sp<IBinder>&, int), (override));
- MOCK_METHOD(binder::Status, setBootDisplayMode, (const sp<IBinder>&, int), (override));
- MOCK_METHOD(binder::Status, clearBootDisplayMode, (const sp<IBinder>&), (override));
- MOCK_METHOD(binder::Status, getBootDisplayModeSupport, (bool*), (override));
- MOCK_METHOD(binder::Status, getHdrConversionCapabilities,
- (std::vector<gui::HdrConversionCapability>*), (override));
- MOCK_METHOD(binder::Status, setHdrConversionStrategy,
- (const gui::HdrConversionStrategy&, int32_t*), (override));
- MOCK_METHOD(binder::Status, getHdrOutputConversionSupport, (bool*), (override));
- MOCK_METHOD(binder::Status, setAutoLowLatencyMode, (const sp<IBinder>&, bool), (override));
- MOCK_METHOD(binder::Status, setGameContentType, (const sp<IBinder>&, bool), (override));
- MOCK_METHOD(binder::Status, captureDisplay,
- (const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&), (override));
- MOCK_METHOD(binder::Status, captureDisplayById,
- (int64_t, const gui::CaptureArgs&, const sp<IScreenCaptureListener>&), (override));
- MOCK_METHOD(binder::Status, captureLayers,
- (const LayerCaptureArgs&, const sp<IScreenCaptureListener>&), (override));
- MOCK_METHOD(binder::Status, captureLayersSync,
- (const LayerCaptureArgs&, gui::ScreenCaptureResults*), (override));
- MOCK_METHOD(binder::Status, clearAnimationFrameStats, (), (override));
- MOCK_METHOD(binder::Status, getAnimationFrameStats, (gui::FrameStats*), (override));
- MOCK_METHOD(binder::Status, overrideHdrTypes, (const sp<IBinder>&, const std::vector<int32_t>&),
- (override));
- MOCK_METHOD(binder::Status, onPullAtom, (int32_t, gui::PullAtomData*), (override));
- MOCK_METHOD(binder::Status, getLayerDebugInfo, (std::vector<gui::LayerDebugInfo>*), (override));
- MOCK_METHOD(binder::Status, getCompositionPreference, (gui::CompositionPreference*),
- (override));
- MOCK_METHOD(binder::Status, getDisplayedContentSamplingAttributes,
- (const sp<IBinder>&, gui::ContentSamplingAttributes*), (override));
- MOCK_METHOD(binder::Status, setDisplayContentSamplingEnabled,
- (const sp<IBinder>&, bool, int8_t, int64_t), (override));
- MOCK_METHOD(binder::Status, getDisplayedContentSample,
- (const sp<IBinder>&, int64_t, int64_t, gui::DisplayedFrameStats*), (override));
- MOCK_METHOD(binder::Status, getProtectedContentSupport, (bool*), (override));
- MOCK_METHOD(binder::Status, isWideColorDisplay, (const sp<IBinder>&, bool*), (override));
- MOCK_METHOD(binder::Status, addRegionSamplingListener,
- (const gui::ARect&, const sp<IBinder>&, const sp<gui::IRegionSamplingListener>&),
- (override));
- MOCK_METHOD(binder::Status, removeRegionSamplingListener,
- (const sp<gui::IRegionSamplingListener>&), (override));
- MOCK_METHOD(binder::Status, addFpsListener, (int32_t, const sp<gui::IFpsListener>&),
- (override));
- MOCK_METHOD(binder::Status, removeFpsListener, (const sp<gui::IFpsListener>&), (override));
- MOCK_METHOD(binder::Status, addTunnelModeEnabledListener,
- (const sp<gui::ITunnelModeEnabledListener>&), (override));
- MOCK_METHOD(binder::Status, removeTunnelModeEnabledListener,
- (const sp<gui::ITunnelModeEnabledListener>&), (override));
- MOCK_METHOD(binder::Status, setDesiredDisplayModeSpecs,
- (const sp<IBinder>&, const gui::DisplayModeSpecs&), (override));
- MOCK_METHOD(binder::Status, getDesiredDisplayModeSpecs,
- (const sp<IBinder>&, gui::DisplayModeSpecs*), (override));
- MOCK_METHOD(binder::Status, getDisplayBrightnessSupport, (const sp<IBinder>&, bool*),
- (override));
- MOCK_METHOD(binder::Status, setDisplayBrightness,
- (const sp<IBinder>&, const gui::DisplayBrightness&), (override));
- MOCK_METHOD(binder::Status, addHdrLayerInfoListener,
- (const sp<IBinder>&, const sp<gui::IHdrLayerInfoListener>&), (override));
- MOCK_METHOD(binder::Status, removeHdrLayerInfoListener,
- (const sp<IBinder>&, const sp<gui::IHdrLayerInfoListener>&), (override));
- MOCK_METHOD(binder::Status, notifyPowerBoost, (int), (override));
- MOCK_METHOD(binder::Status, setGlobalShadowSettings,
- (const gui::Color&, const gui::Color&, float, float, float), (override));
- MOCK_METHOD(binder::Status, getDisplayDecorationSupport,
- (const sp<IBinder>&, std::optional<gui::DisplayDecorationSupport>*), (override));
- MOCK_METHOD(binder::Status, setGameModeFrameRateOverride, (int32_t, float), (override));
- MOCK_METHOD(binder::Status, setGameDefaultFrameRateOverride, (int32_t, float), (override));
- MOCK_METHOD(binder::Status, enableRefreshRateOverlay, (bool), (override));
- MOCK_METHOD(binder::Status, setDebugFlash, (int), (override));
- MOCK_METHOD(binder::Status, scheduleComposite, (), (override));
- MOCK_METHOD(binder::Status, scheduleCommit, (), (override));
- MOCK_METHOD(binder::Status, forceClientComposition, (bool), (override));
- MOCK_METHOD(binder::Status, updateSmallAreaDetection,
- (const std::vector<int32_t>&, const std::vector<float>&), (override));
- MOCK_METHOD(binder::Status, setSmallAreaDetectionThreshold, (int32_t, float), (override));
- MOCK_METHOD(binder::Status, getGpuContextPriority, (int32_t*), (override));
- MOCK_METHOD(binder::Status, getMaxAcquiredBufferCount, (int32_t*), (override));
- MOCK_METHOD(binder::Status, addWindowInfosListener,
- (const sp<gui::IWindowInfosListener>&, gui::WindowInfosListenerInfo*), (override));
- MOCK_METHOD(binder::Status, removeWindowInfosListener, (const sp<gui::IWindowInfosListener>&),
- (override));
- MOCK_METHOD(binder::Status, getOverlaySupport, (gui::OverlayProperties*), (override));
- MOCK_METHOD(binder::Status, getStalledTransactionInfo,
- (int32_t, std::optional<gui::StalledTransactionInfo>*), (override));
- MOCK_METHOD(binder::Status, getSchedulingPolicy, (gui::SchedulingPolicy*), (override));
-};
-
-class FakeBnSurfaceComposerClient : public gui::BnSurfaceComposerClient {
-public:
- MOCK_METHOD(binder::Status, createSurface,
- (const std::string& name, int32_t flags, const sp<IBinder>& parent,
- const gui::LayerMetadata& metadata, gui::CreateSurfaceResult* outResult),
- (override));
-
- MOCK_METHOD(binder::Status, clearLayerFrameStats, (const sp<IBinder>& handle), (override));
-
- MOCK_METHOD(binder::Status, getLayerFrameStats,
- (const sp<IBinder>& handle, gui::FrameStats* outStats), (override));
-
- MOCK_METHOD(binder::Status, mirrorSurface,
- (const sp<IBinder>& mirrorFromHandle, gui::CreateSurfaceResult* outResult),
- (override));
-
- MOCK_METHOD(binder::Status, mirrorDisplay,
- (int64_t displayId, gui::CreateSurfaceResult* outResult), (override));
-
- MOCK_METHOD(binder::Status, getSchedulingPolicy, (gui::SchedulingPolicy*), (override));
-};
-
-class FakeDisplayEventDispatcher : public DisplayEventDispatcher {
-public:
- FakeDisplayEventDispatcher(const sp<Looper>& looper,
- gui::ISurfaceComposer::VsyncSource vsyncSource,
- gui::ISurfaceComposer::EventRegistration eventRegistration)
- : DisplayEventDispatcher(looper, vsyncSource, eventRegistration){};
-
- MOCK_METHOD4(dispatchVsync, void(nsecs_t, PhysicalDisplayId, uint32_t, VsyncEventData));
- MOCK_METHOD3(dispatchHotplug, void(nsecs_t, PhysicalDisplayId, bool));
- MOCK_METHOD2(dispatchHotplugConnectionError, void(nsecs_t, int32_t));
- MOCK_METHOD4(dispatchModeChanged, void(nsecs_t, PhysicalDisplayId, int32_t, nsecs_t));
- MOCK_METHOD2(dispatchNullEvent, void(nsecs_t, PhysicalDisplayId));
- MOCK_METHOD3(dispatchFrameRateOverrides,
- void(nsecs_t, PhysicalDisplayId, std::vector<FrameRateOverride>));
- MOCK_METHOD3(dispatchHdcpLevelsChanged, void(PhysicalDisplayId, int32_t, int32_t));
-};
-
-} // namespace android
-
-namespace android::hardware {
-
-namespace graphics::bufferqueue::V1_0::utils {
-
-class FakeGraphicBufferProducerV1 : public HGraphicBufferProducer {
-public:
- FakeGraphicBufferProducerV1() {
- ON_CALL(*this, setMaxDequeuedBufferCount).WillByDefault([]() { return 0; });
- ON_CALL(*this, setAsyncMode).WillByDefault([]() { return 0; });
- ON_CALL(*this, detachBuffer).WillByDefault([]() { return 0; });
- ON_CALL(*this, cancelBuffer).WillByDefault([]() { return 0; });
- ON_CALL(*this, disconnect).WillByDefault([]() { return 0; });
- ON_CALL(*this, setSidebandStream).WillByDefault([]() { return 0; });
- ON_CALL(*this, allowAllocation).WillByDefault([]() { return 0; });
- ON_CALL(*this, setGenerationNumber).WillByDefault([]() { return 0; });
- ON_CALL(*this, setSharedBufferMode).WillByDefault([]() { return 0; });
- ON_CALL(*this, setAutoRefresh).WillByDefault([]() { return 0; });
- ON_CALL(*this, setDequeueTimeout).WillByDefault([]() { return 0; });
- ON_CALL(*this, setLegacyBufferDrop).WillByDefault([]() { return 0; });
- };
- MOCK_METHOD2(requestBuffer, Return<void>(int, requestBuffer_cb));
- MOCK_METHOD1(setMaxDequeuedBufferCount, Return<int32_t>(int32_t));
- MOCK_METHOD1(setAsyncMode, Return<int32_t>(bool));
- MOCK_METHOD6(dequeueBuffer,
- Return<void>(uint32_t, uint32_t, graphics::common::V1_0::PixelFormat, uint32_t,
- bool, dequeueBuffer_cb));
- MOCK_METHOD1(detachBuffer, Return<int32_t>(int));
- MOCK_METHOD1(detachNextBuffer, Return<void>(detachNextBuffer_cb));
- MOCK_METHOD2(attachBuffer, Return<void>(const media::V1_0::AnwBuffer&, attachBuffer_cb));
- MOCK_METHOD3(
- queueBuffer,
- Return<void>(
- int,
- const graphics::bufferqueue::V1_0::IGraphicBufferProducer::QueueBufferInput&,
- queueBuffer_cb));
- MOCK_METHOD2(cancelBuffer, Return<int32_t>(int, const hidl_handle&));
- MOCK_METHOD2(query, Return<void>(int32_t, query_cb));
- MOCK_METHOD4(connect,
- Return<void>(const sp<graphics::bufferqueue::V1_0::IProducerListener>&, int32_t,
- bool, connect_cb));
- MOCK_METHOD2(disconnect,
- Return<int32_t>(
- int, graphics::bufferqueue::V1_0::IGraphicBufferProducer::DisconnectMode));
- MOCK_METHOD1(setSidebandStream, Return<int32_t>(const hidl_handle&));
- MOCK_METHOD4(allocateBuffers,
- Return<void>(uint32_t, uint32_t, graphics::common::V1_0::PixelFormat, uint32_t));
- MOCK_METHOD1(allowAllocation, Return<int32_t>(bool));
- MOCK_METHOD1(setGenerationNumber, Return<int32_t>(uint32_t));
- MOCK_METHOD1(getConsumerName, Return<void>(getConsumerName_cb));
- MOCK_METHOD1(setSharedBufferMode, Return<int32_t>(bool));
- MOCK_METHOD1(setAutoRefresh, Return<int32_t>(bool));
- MOCK_METHOD1(setDequeueTimeout, Return<int32_t>(nsecs_t));
- MOCK_METHOD1(setLegacyBufferDrop, Return<int32_t>(bool));
- MOCK_METHOD1(getLastQueuedBuffer, Return<void>(getLastQueuedBuffer_cb));
- MOCK_METHOD1(getFrameTimestamps, Return<void>(getFrameTimestamps_cb));
- MOCK_METHOD1(getUniqueId, Return<void>(getUniqueId_cb));
-};
-
-}; // namespace graphics::bufferqueue::V1_0::utils
-
-namespace graphics::bufferqueue::V2_0::utils {
-
-class FakeGraphicBufferProducerV2 : public HGraphicBufferProducer {
-public:
- FakeGraphicBufferProducerV2() {
- ON_CALL(*this, setMaxDequeuedBufferCount).WillByDefault([]() { return Status::OK; });
- ON_CALL(*this, setAsyncMode).WillByDefault([]() { return Status::OK; });
- ON_CALL(*this, detachBuffer).WillByDefault([]() { return Status::OK; });
- ON_CALL(*this, cancelBuffer).WillByDefault([]() { return Status::OK; });
- ON_CALL(*this, disconnect).WillByDefault([]() { return Status::OK; });
- ON_CALL(*this, allocateBuffers).WillByDefault([]() { return Status::OK; });
- ON_CALL(*this, allowAllocation).WillByDefault([]() { return Status::OK; });
- ON_CALL(*this, setGenerationNumber).WillByDefault([]() { return Status::OK; });
- ON_CALL(*this, setDequeueTimeout).WillByDefault([]() { return Status::OK; });
- ON_CALL(*this, getUniqueId).WillByDefault([]() { return 0; });
- };
- MOCK_METHOD2(requestBuffer, Return<void>(int, requestBuffer_cb));
- MOCK_METHOD1(setMaxDequeuedBufferCount, Return<graphics::bufferqueue::V2_0::Status>(int));
- MOCK_METHOD1(setAsyncMode, Return<graphics::bufferqueue::V2_0::Status>(bool));
- MOCK_METHOD2(
- dequeueBuffer,
- Return<void>(
- const graphics::bufferqueue::V2_0::IGraphicBufferProducer::DequeueBufferInput&,
- dequeueBuffer_cb));
- MOCK_METHOD1(detachBuffer, Return<graphics::bufferqueue::V2_0::Status>(int));
- MOCK_METHOD1(detachNextBuffer, Return<void>(detachNextBuffer_cb));
- MOCK_METHOD3(attachBuffer,
- Return<void>(const graphics::common::V1_2::HardwareBuffer&, uint32_t,
- attachBuffer_cb));
- MOCK_METHOD3(
- queueBuffer,
- Return<void>(
- int,
- const graphics::bufferqueue::V2_0::IGraphicBufferProducer::QueueBufferInput&,
- queueBuffer_cb));
- MOCK_METHOD2(cancelBuffer,
- Return<graphics::bufferqueue::V2_0::Status>(int, const hidl_handle&));
- MOCK_METHOD2(query, Return<void>(int32_t, query_cb));
- MOCK_METHOD4(connect,
- Return<void>(const sp<graphics::bufferqueue::V2_0::IProducerListener>&,
- graphics::bufferqueue::V2_0::ConnectionType, bool, connect_cb));
- MOCK_METHOD1(disconnect,
- Return<graphics::bufferqueue::V2_0::Status>(
- graphics::bufferqueue::V2_0::ConnectionType));
- MOCK_METHOD4(allocateBuffers,
- Return<graphics::bufferqueue::V2_0::Status>(uint32_t, uint32_t, uint32_t,
- uint64_t));
- MOCK_METHOD1(allowAllocation, Return<graphics::bufferqueue::V2_0::Status>(bool));
- MOCK_METHOD1(setGenerationNumber, Return<graphics::bufferqueue::V2_0::Status>(uint32_t));
- MOCK_METHOD1(getConsumerName, Return<void>(getConsumerName_cb));
- MOCK_METHOD1(setDequeueTimeout, Return<graphics::bufferqueue::V2_0::Status>(int64_t));
- MOCK_METHOD0(getUniqueId, Return<uint64_t>());
-};
-
-}; // namespace graphics::bufferqueue::V2_0::utils
-}; // namespace android::hardware
diff --git a/libs/gui/fuzzer/libgui_parcelable_fuzzer.cpp b/libs/gui/fuzzer/libgui_parcelable_fuzzer.cpp
deleted file mode 100644
index 9f0f6ca..0000000
--- a/libs/gui/fuzzer/libgui_parcelable_fuzzer.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <gui/BufferQueueConsumer.h>
-#include <gui/BufferQueueCore.h>
-#include <gui/BufferQueueProducer.h>
-#include <gui/LayerMetadata.h>
-#include <gui/OccupancyTracker.h>
-#include <gui/StreamSplitter.h>
-#include <gui/Surface.h>
-#include <gui/SurfaceControl.h>
-#include <gui/view/Surface.h>
-#include <libgui_fuzzer_utils.h>
-#include "android/view/LayerMetadataKey.h"
-
-using namespace android;
-
-constexpr int32_t kMaxBytes = 256;
-constexpr int32_t kMatrixSize = 4;
-constexpr int32_t kLayerMetadataKeyCount = 8;
-
-constexpr uint32_t kMetadataKey[] = {
- (uint32_t)view::LayerMetadataKey::METADATA_OWNER_UID,
- (uint32_t)view::LayerMetadataKey::METADATA_WINDOW_TYPE,
- (uint32_t)view::LayerMetadataKey::METADATA_TASK_ID,
- (uint32_t)view::LayerMetadataKey::METADATA_MOUSE_CURSOR,
- (uint32_t)view::LayerMetadataKey::METADATA_ACCESSIBILITY_ID,
- (uint32_t)view::LayerMetadataKey::METADATA_OWNER_PID,
- (uint32_t)view::LayerMetadataKey::METADATA_DEQUEUE_TIME,
- (uint32_t)view::LayerMetadataKey::METADATA_GAME_MODE,
-};
-
-class ParcelableFuzzer {
-public:
- ParcelableFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
- void process();
-
-private:
- void invokeStreamSplitter();
- void invokeOccupancyTracker();
- void invokeLayerDebugInfo();
- void invokeLayerMetadata();
- void invokeViewSurface();
-
- FuzzedDataProvider mFdp;
-};
-
-void ParcelableFuzzer::invokeViewSurface() {
- view::Surface surface;
- surface.name = String16((mFdp.ConsumeRandomLengthString(kMaxBytes)).c_str());
- Parcel parcel;
- surface.writeToParcel(&parcel);
- parcel.setDataPosition(0);
- surface.readFromParcel(&parcel);
- bool nameAlreadyWritten = mFdp.ConsumeBool();
- surface.writeToParcel(&parcel, nameAlreadyWritten);
- parcel.setDataPosition(0);
- surface.readFromParcel(&parcel, mFdp.ConsumeBool());
-}
-
-void ParcelableFuzzer::invokeLayerMetadata() {
- std::unordered_map<uint32_t, std::vector<uint8_t>> map;
- for (size_t idx = 0; idx < kLayerMetadataKeyCount; ++idx) {
- std::vector<uint8_t> data;
- for (size_t idx1 = 0; idx1 < mFdp.ConsumeIntegral<uint32_t>(); ++idx1) {
- data.push_back(mFdp.ConsumeIntegral<uint8_t>());
- }
- map[kMetadataKey[idx]] = data;
- }
- LayerMetadata metadata(map);
- uint32_t key = mFdp.PickValueInArray(kMetadataKey);
- metadata.setInt32(key, mFdp.ConsumeIntegral<int32_t>());
- metadata.itemToString(key, (mFdp.ConsumeRandomLengthString(kMaxBytes)).c_str());
-
- Parcel parcel;
- metadata.writeToParcel(&parcel);
- parcel.setDataPosition(0);
- metadata.readFromParcel(&parcel);
-}
-
-void ParcelableFuzzer::invokeLayerDebugInfo() {
- gui::LayerDebugInfo info;
- info.mName = mFdp.ConsumeRandomLengthString(kMaxBytes);
- info.mParentName = mFdp.ConsumeRandomLengthString(kMaxBytes);
- info.mType = mFdp.ConsumeRandomLengthString(kMaxBytes);
- info.mLayerStack = mFdp.ConsumeIntegral<uint32_t>();
- info.mX = mFdp.ConsumeFloatingPoint<float>();
- info.mY = mFdp.ConsumeFloatingPoint<float>();
- info.mZ = mFdp.ConsumeIntegral<uint32_t>();
- info.mWidth = mFdp.ConsumeIntegral<int32_t>();
- info.mHeight = mFdp.ConsumeIntegral<int32_t>();
- info.mActiveBufferWidth = mFdp.ConsumeIntegral<int32_t>();
- info.mActiveBufferHeight = mFdp.ConsumeIntegral<int32_t>();
- info.mActiveBufferStride = mFdp.ConsumeIntegral<int32_t>();
- info.mActiveBufferFormat = mFdp.ConsumeIntegral<int32_t>();
- info.mNumQueuedFrames = mFdp.ConsumeIntegral<int32_t>();
-
- info.mFlags = mFdp.ConsumeIntegral<uint32_t>();
- info.mPixelFormat = mFdp.ConsumeIntegral<int32_t>();
- info.mTransparentRegion = Region(getRect(&mFdp));
- info.mVisibleRegion = Region(getRect(&mFdp));
- info.mSurfaceDamageRegion = Region(getRect(&mFdp));
- info.mCrop = getRect(&mFdp);
- info.mDataSpace = static_cast<android_dataspace>(mFdp.PickValueInArray(kDataspaces));
- info.mColor = half4(mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeFloatingPoint<float>(),
- mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeFloatingPoint<float>());
- for (size_t idx = 0; idx < kMatrixSize; ++idx) {
- info.mMatrix[idx / 2][idx % 2] = mFdp.ConsumeFloatingPoint<float>();
- }
- info.mIsOpaque = mFdp.ConsumeBool();
- info.mContentDirty = mFdp.ConsumeBool();
- info.mStretchEffect.width = mFdp.ConsumeFloatingPoint<float>();
- info.mStretchEffect.height = mFdp.ConsumeFloatingPoint<float>();
- info.mStretchEffect.vectorX = mFdp.ConsumeFloatingPoint<float>();
- info.mStretchEffect.vectorY = mFdp.ConsumeFloatingPoint<float>();
- info.mStretchEffect.maxAmountX = mFdp.ConsumeFloatingPoint<float>();
- info.mStretchEffect.maxAmountY = mFdp.ConsumeFloatingPoint<float>();
- info.mStretchEffect.mappedChildBounds =
- FloatRect(mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeFloatingPoint<float>(),
- mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeFloatingPoint<float>());
-
- Parcel parcel;
- info.writeToParcel(&parcel);
- parcel.setDataPosition(0);
- info.readFromParcel(&parcel);
-}
-
-void ParcelableFuzzer::invokeOccupancyTracker() {
- nsecs_t totalTime = mFdp.ConsumeIntegral<uint32_t>();
- size_t numFrames = mFdp.ConsumeIntegral<size_t>();
- float occupancyAverage = mFdp.ConsumeFloatingPoint<float>();
- OccupancyTracker::Segment segment(totalTime, numFrames, occupancyAverage,
- mFdp.ConsumeBool() /*usedThirdBuffer*/);
- Parcel parcel;
- segment.writeToParcel(&parcel);
- parcel.setDataPosition(0);
- segment.readFromParcel(&parcel);
-}
-
-void ParcelableFuzzer::invokeStreamSplitter() {
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer);
- sp<StreamSplitter> splitter;
- StreamSplitter::createSplitter(consumer, &splitter);
- splitter->addOutput(producer);
- std::string name = mFdp.ConsumeRandomLengthString(kMaxBytes);
- splitter->setName(String8(name.c_str()));
-}
-
-void ParcelableFuzzer::process() {
- invokeStreamSplitter();
- invokeOccupancyTracker();
- invokeLayerDebugInfo();
- invokeLayerMetadata();
- invokeViewSurface();
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- ParcelableFuzzer libGuiFuzzer(data, size);
- libGuiFuzzer.process();
- return 0;
-}
diff --git a/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp b/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp
deleted file mode 100644
index 4daa3be..0000000
--- a/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <aidl/android/hardware/power/Boost.h>
-#include <fuzzbinder/libbinder_driver.h>
-#include <gui/Surface.h>
-#include <gui/SurfaceComposerClient.h>
-#include <libgui_fuzzer_utils.h>
-#include "android-base/stringprintf.h"
-
-using namespace android;
-
-constexpr int32_t kRandomStringMaxBytes = 256;
-
-constexpr ui::ColorMode kColormodes[] = {ui::ColorMode::NATIVE,
- ui::ColorMode::STANDARD_BT601_625,
- ui::ColorMode::STANDARD_BT601_625_UNADJUSTED,
- ui::ColorMode::STANDARD_BT601_525,
- ui::ColorMode::STANDARD_BT601_525_UNADJUSTED,
- ui::ColorMode::STANDARD_BT709,
- ui::ColorMode::DCI_P3,
- ui::ColorMode::SRGB,
- ui::ColorMode::ADOBE_RGB,
- ui::ColorMode::DISPLAY_P3,
- ui::ColorMode::BT2020,
- ui::ColorMode::BT2100_PQ,
- ui::ColorMode::BT2100_HLG,
- ui::ColorMode::DISPLAY_BT2020};
-
-constexpr aidl::android::hardware::power::Boost kBoost[] = {
- aidl::android::hardware::power::Boost::INTERACTION,
- aidl::android::hardware::power::Boost::DISPLAY_UPDATE_IMMINENT,
- aidl::android::hardware::power::Boost::ML_ACC,
- aidl::android::hardware::power::Boost::AUDIO_LAUNCH,
- aidl::android::hardware::power::Boost::CAMERA_LAUNCH,
- aidl::android::hardware::power::Boost::CAMERA_SHOT,
-};
-
-constexpr gui::TouchOcclusionMode kMode[] = {
- gui::TouchOcclusionMode::BLOCK_UNTRUSTED,
- gui::TouchOcclusionMode::USE_OPACITY,
- gui::TouchOcclusionMode::ALLOW,
-};
-
-constexpr gui::WindowInfo::Flag kFlags[] = {
- gui::WindowInfo::Flag::ALLOW_LOCK_WHILE_SCREEN_ON,
- gui::WindowInfo::Flag::DIM_BEHIND,
- gui::WindowInfo::Flag::BLUR_BEHIND,
- gui::WindowInfo::Flag::NOT_FOCUSABLE,
- gui::WindowInfo::Flag::NOT_TOUCHABLE,
- gui::WindowInfo::Flag::NOT_TOUCH_MODAL,
- gui::WindowInfo::Flag::TOUCHABLE_WHEN_WAKING,
- gui::WindowInfo::Flag::KEEP_SCREEN_ON,
- gui::WindowInfo::Flag::LAYOUT_IN_SCREEN,
- gui::WindowInfo::Flag::LAYOUT_NO_LIMITS,
- gui::WindowInfo::Flag::FULLSCREEN,
- gui::WindowInfo::Flag::FORCE_NOT_FULLSCREEN,
- gui::WindowInfo::Flag::DITHER,
- gui::WindowInfo::Flag::SECURE,
- gui::WindowInfo::Flag::SCALED,
- gui::WindowInfo::Flag::IGNORE_CHEEK_PRESSES,
- gui::WindowInfo::Flag::LAYOUT_INSET_DECOR,
- gui::WindowInfo::Flag::ALT_FOCUSABLE_IM,
- gui::WindowInfo::Flag::WATCH_OUTSIDE_TOUCH,
- gui::WindowInfo::Flag::SHOW_WHEN_LOCKED,
- gui::WindowInfo::Flag::SHOW_WALLPAPER,
- gui::WindowInfo::Flag::TURN_SCREEN_ON,
- gui::WindowInfo::Flag::DISMISS_KEYGUARD,
- gui::WindowInfo::Flag::SPLIT_TOUCH,
- gui::WindowInfo::Flag::HARDWARE_ACCELERATED,
- gui::WindowInfo::Flag::LAYOUT_IN_OVERSCAN,
- gui::WindowInfo::Flag::TRANSLUCENT_STATUS,
- gui::WindowInfo::Flag::TRANSLUCENT_NAVIGATION,
- gui::WindowInfo::Flag::LOCAL_FOCUS_MODE,
- gui::WindowInfo::Flag::SLIPPERY,
- gui::WindowInfo::Flag::LAYOUT_ATTACHED_IN_DECOR,
- gui::WindowInfo::Flag::DRAWS_SYSTEM_BAR_BACKGROUNDS,
-};
-
-constexpr gui::WindowInfo::Type kType[] = {
- gui::WindowInfo::Type::UNKNOWN,
- gui::WindowInfo::Type::FIRST_APPLICATION_WINDOW,
- gui::WindowInfo::Type::BASE_APPLICATION,
- gui::WindowInfo::Type::APPLICATION,
- gui::WindowInfo::Type::APPLICATION_STARTING,
- gui::WindowInfo::Type::LAST_APPLICATION_WINDOW,
- gui::WindowInfo::Type::FIRST_SUB_WINDOW,
- gui::WindowInfo::Type::APPLICATION_PANEL,
- gui::WindowInfo::Type::APPLICATION_MEDIA,
- gui::WindowInfo::Type::APPLICATION_SUB_PANEL,
- gui::WindowInfo::Type::APPLICATION_ATTACHED_DIALOG,
- gui::WindowInfo::Type::APPLICATION_MEDIA_OVERLAY,
-};
-
-constexpr gui::WindowInfo::InputConfig kFeatures[] = {
- gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL,
- gui::WindowInfo::InputConfig::DISABLE_USER_ACTIVITY,
- gui::WindowInfo::InputConfig::DROP_INPUT,
- gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED,
- gui::WindowInfo::InputConfig::SPY,
- gui::WindowInfo::InputConfig::INTERCEPTS_STYLUS,
-};
-
-class SurfaceComposerClientFuzzer {
-public:
- SurfaceComposerClientFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
- void process();
-
-private:
- void invokeSurfaceComposerClient();
- void invokeSurfaceComposerClientBinder();
- void invokeSurfaceComposerTransaction();
- void getWindowInfo(gui::WindowInfo*);
- sp<SurfaceControl> makeSurfaceControl();
- BlurRegion getBlurRegion();
- void fuzzOnPullAtom();
- gui::DisplayModeSpecs getDisplayModeSpecs();
-
- FuzzedDataProvider mFdp;
-};
-
-gui::DisplayModeSpecs SurfaceComposerClientFuzzer::getDisplayModeSpecs() {
- const auto getRefreshRateRange = [&] {
- gui::DisplayModeSpecs::RefreshRateRanges::RefreshRateRange range;
- range.min = mFdp.ConsumeFloatingPoint<float>();
- range.max = mFdp.ConsumeFloatingPoint<float>();
- return range;
- };
-
- const auto getRefreshRateRanges = [&] {
- gui::DisplayModeSpecs::RefreshRateRanges ranges;
- ranges.physical = getRefreshRateRange();
- ranges.render = getRefreshRateRange();
- return ranges;
- };
-
- String8 displayName((mFdp.ConsumeRandomLengthString(kRandomStringMaxBytes)).c_str());
- sp<IBinder> displayToken =
- SurfaceComposerClient::createDisplay(displayName, mFdp.ConsumeBool() /*secure*/);
- gui::DisplayModeSpecs specs;
- specs.defaultMode = mFdp.ConsumeIntegral<int32_t>();
- specs.allowGroupSwitching = mFdp.ConsumeBool();
- specs.primaryRanges = getRefreshRateRanges();
- specs.appRequestRanges = getRefreshRateRanges();
- return specs;
-}
-
-BlurRegion SurfaceComposerClientFuzzer::getBlurRegion() {
- int32_t left = mFdp.ConsumeIntegral<int32_t>();
- int32_t right = mFdp.ConsumeIntegral<int32_t>();
- int32_t top = mFdp.ConsumeIntegral<int32_t>();
- int32_t bottom = mFdp.ConsumeIntegral<int32_t>();
- uint32_t blurRadius = mFdp.ConsumeIntegral<uint32_t>();
- float alpha = mFdp.ConsumeFloatingPoint<float>();
- float cornerRadiusTL = mFdp.ConsumeFloatingPoint<float>();
- float cornerRadiusTR = mFdp.ConsumeFloatingPoint<float>();
- float cornerRadiusBL = mFdp.ConsumeFloatingPoint<float>();
- float cornerRadiusBR = mFdp.ConsumeFloatingPoint<float>();
- return BlurRegion{blurRadius, cornerRadiusTL, cornerRadiusTR, cornerRadiusBL,
- cornerRadiusBR, alpha, left, top,
- right, bottom};
-}
-
-void SurfaceComposerClientFuzzer::getWindowInfo(gui::WindowInfo* windowInfo) {
- windowInfo->id = mFdp.ConsumeIntegral<int32_t>();
- windowInfo->name = mFdp.ConsumeRandomLengthString(kRandomStringMaxBytes);
- windowInfo->layoutParamsFlags = mFdp.PickValueInArray(kFlags);
- windowInfo->layoutParamsType = mFdp.PickValueInArray(kType);
- windowInfo->frame = Rect(mFdp.ConsumeIntegral<int32_t>(), mFdp.ConsumeIntegral<int32_t>(),
- mFdp.ConsumeIntegral<int32_t>(), mFdp.ConsumeIntegral<int32_t>());
- windowInfo->surfaceInset = mFdp.ConsumeIntegral<int32_t>();
- windowInfo->alpha = mFdp.ConsumeFloatingPointInRange<float>(0, 1);
- ui::Transform transform(mFdp.PickValueInArray(kOrientation));
- windowInfo->transform = transform;
- windowInfo->touchableRegion = Region(getRect(&mFdp));
- windowInfo->replaceTouchableRegionWithCrop = mFdp.ConsumeBool();
- windowInfo->touchOcclusionMode = mFdp.PickValueInArray(kMode);
- windowInfo->ownerPid = gui::Pid{mFdp.ConsumeIntegral<pid_t>()};
- windowInfo->ownerUid = gui::Uid{mFdp.ConsumeIntegral<uid_t>()};
- windowInfo->packageName = mFdp.ConsumeRandomLengthString(kRandomStringMaxBytes);
- windowInfo->inputConfig = mFdp.PickValueInArray(kFeatures);
-}
-
-sp<SurfaceControl> SurfaceComposerClientFuzzer::makeSurfaceControl() {
- sp<IBinder> handle;
- const sp<FakeBnSurfaceComposerClient> testClient(new FakeBnSurfaceComposerClient());
- sp<SurfaceComposerClient> client = new SurfaceComposerClient(testClient);
- sp<BnGraphicBufferProducer> producer;
- uint32_t width = mFdp.ConsumeIntegral<uint32_t>();
- uint32_t height = mFdp.ConsumeIntegral<uint32_t>();
- uint32_t transformHint = mFdp.ConsumeIntegral<uint32_t>();
- uint32_t flags = mFdp.ConsumeIntegral<uint32_t>();
- int32_t format = mFdp.ConsumeIntegral<int32_t>();
- int32_t layerId = mFdp.ConsumeIntegral<int32_t>();
- std::string layerName = base::StringPrintf("#%d", layerId);
- return new SurfaceControl(client, handle, layerId, layerName, width, height, format,
- transformHint, flags);
-}
-
-void SurfaceComposerClientFuzzer::invokeSurfaceComposerTransaction() {
- sp<SurfaceControl> surface = makeSurfaceControl();
-
- SurfaceComposerClient::Transaction transaction;
- int32_t layer = mFdp.ConsumeIntegral<int32_t>();
- transaction.setLayer(surface, layer);
-
- sp<SurfaceControl> relativeSurface = makeSurfaceControl();
- transaction.setRelativeLayer(surface, relativeSurface, layer);
-
- Region transparentRegion(getRect(&mFdp));
- transaction.setTransparentRegionHint(surface, transparentRegion);
- transaction.setAlpha(surface, mFdp.ConsumeFloatingPoint<float>());
-
- transaction.setCornerRadius(surface, mFdp.ConsumeFloatingPoint<float>());
- transaction.setBackgroundBlurRadius(surface, mFdp.ConsumeFloatingPoint<float>());
- std::vector<BlurRegion> regions;
- uint32_t vectorSize = mFdp.ConsumeIntegralInRange<uint32_t>(0, 100);
- regions.resize(vectorSize);
- for (size_t idx = 0; idx < vectorSize; ++idx) {
- regions.push_back(getBlurRegion());
- }
- transaction.setBlurRegions(surface, regions);
-
- transaction.setLayerStack(surface, {mFdp.ConsumeIntegral<uint32_t>()});
- half3 color = {mFdp.ConsumeIntegral<uint32_t>(), mFdp.ConsumeIntegral<uint32_t>(),
- mFdp.ConsumeIntegral<uint32_t>()};
- transaction.setColor(surface, color);
- transaction.setBackgroundColor(surface, color, mFdp.ConsumeFloatingPoint<float>(),
- mFdp.PickValueInArray(kDataspaces));
-
- transaction.setApi(surface, mFdp.ConsumeIntegral<int32_t>());
- transaction.setFrameRateSelectionPriority(surface, mFdp.ConsumeIntegral<int32_t>());
- transaction.setColorSpaceAgnostic(surface, mFdp.ConsumeBool() /*agnostic*/);
-
- gui::WindowInfo windowInfo;
- getWindowInfo(&windowInfo);
- transaction.setInputWindowInfo(surface, windowInfo);
- Parcel windowParcel;
- windowInfo.writeToParcel(&windowParcel);
- windowParcel.setDataPosition(0);
- windowInfo.readFromParcel(&windowParcel);
-
- windowInfo.addTouchableRegion(getRect(&mFdp));
- int32_t pointX = mFdp.ConsumeIntegral<int32_t>();
- int32_t pointY = mFdp.ConsumeIntegral<int32_t>();
- windowInfo.touchableRegionContainsPoint(pointX, pointY);
- windowInfo.frameContainsPoint(pointX, pointY);
-
- Parcel transactionParcel;
- transaction.writeToParcel(&transactionParcel);
- transactionParcel.setDataPosition(0);
- transaction.readFromParcel(&transactionParcel);
- SurfaceComposerClient::Transaction::createFromParcel(&transactionParcel);
-}
-
-void SurfaceComposerClientFuzzer::fuzzOnPullAtom() {
- std::string outData;
- bool success;
- SurfaceComposerClient::onPullAtom(mFdp.ConsumeIntegral<int32_t>(), &outData, &success);
-}
-
-void SurfaceComposerClientFuzzer::invokeSurfaceComposerClient() {
- String8 displayName((mFdp.ConsumeRandomLengthString(kRandomStringMaxBytes)).c_str());
- sp<IBinder> displayToken =
- SurfaceComposerClient::createDisplay(displayName, mFdp.ConsumeBool() /*secure*/);
- SurfaceComposerClient::setDesiredDisplayModeSpecs(displayToken, getDisplayModeSpecs());
-
- ui::ColorMode colorMode = mFdp.PickValueInArray(kColormodes);
- SurfaceComposerClient::setActiveColorMode(displayToken, colorMode);
- SurfaceComposerClient::setAutoLowLatencyMode(displayToken, mFdp.ConsumeBool() /*on*/);
- SurfaceComposerClient::setGameContentType(displayToken, mFdp.ConsumeBool() /*on*/);
- SurfaceComposerClient::setDisplayPowerMode(displayToken, mFdp.ConsumeIntegral<int32_t>());
- SurfaceComposerClient::doUncacheBufferTransaction(mFdp.ConsumeIntegral<uint64_t>());
-
- SurfaceComposerClient::setDisplayBrightness(displayToken, getBrightness(&mFdp));
- aidl::android::hardware::power::Boost boostId = mFdp.PickValueInArray(kBoost);
- SurfaceComposerClient::notifyPowerBoost((int32_t)boostId);
-
- String8 surfaceName((mFdp.ConsumeRandomLengthString(kRandomStringMaxBytes)).c_str());
- sp<BBinder> handle(new BBinder());
- sp<BnGraphicBufferProducer> producer;
- sp<Surface> surfaceParent(
- new Surface(producer, mFdp.ConsumeBool() /*controlledByApp*/, handle));
-
- fuzzOnPullAtom();
- SurfaceComposerClient::setDisplayContentSamplingEnabled(displayToken,
- mFdp.ConsumeBool() /*enable*/,
- mFdp.ConsumeIntegral<uint8_t>(),
- mFdp.ConsumeIntegral<uint64_t>());
-
- sp<IBinder> stopLayerHandle;
- sp<gui::IRegionSamplingListener> listener = sp<gui::IRegionSamplingListenerDefault>::make();
- sp<gui::IRegionSamplingListenerDelegator> sampleListener =
- new gui::IRegionSamplingListenerDelegator(listener);
- SurfaceComposerClient::addRegionSamplingListener(getRect(&mFdp), stopLayerHandle,
- sampleListener);
- sp<gui::IFpsListenerDefault> fpsListener;
- SurfaceComposerClient::addFpsListener(mFdp.ConsumeIntegral<int32_t>(), fpsListener);
-}
-
-void SurfaceComposerClientFuzzer::invokeSurfaceComposerClientBinder() {
- sp<FakeBnSurfaceComposerClient> client(new FakeBnSurfaceComposerClient());
- fuzzService(client.get(), std::move(mFdp));
-}
-
-void SurfaceComposerClientFuzzer::process() {
- invokeSurfaceComposerClient();
- invokeSurfaceComposerTransaction();
- invokeSurfaceComposerClientBinder();
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- SurfaceComposerClientFuzzer surfaceComposerClientFuzzer(data, size);
- surfaceComposerClientFuzzer.process();
- return 0;
-}
diff --git a/libs/gui/fuzzer/libgui_surfaceComposer_fuzzer.cpp b/libs/gui/fuzzer/libgui_surfaceComposer_fuzzer.cpp
deleted file mode 100644
index 6d5427b..0000000
--- a/libs/gui/fuzzer/libgui_surfaceComposer_fuzzer.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <fuzzbinder/libbinder_driver.h>
-#include <fuzzer/FuzzedDataProvider.h>
-#include <libgui_fuzzer_utils.h>
-
-using namespace android;
-
-class SurfaceComposerFuzzer {
-public:
- SurfaceComposerFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
- void process();
-
-private:
- FuzzedDataProvider mFdp;
-};
-
-void SurfaceComposerFuzzer::process() {
- sp<FakeBnSurfaceComposer> composer(new FakeBnSurfaceComposer());
- fuzzService(composer.get(), std::move(mFdp));
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- SurfaceComposerFuzzer surfaceComposerFuzzer(data, size);
- surfaceComposerFuzzer.process();
- return 0;
-}
diff --git a/libs/gui/tests/FrameRateUtilsTest.cpp b/libs/gui/tests/FrameRateUtilsTest.cpp
index 5fe22b0..04bfb28 100644
--- a/libs/gui/tests/FrameRateUtilsTest.cpp
+++ b/libs/gui/tests/FrameRateUtilsTest.cpp
@@ -34,6 +34,8 @@
ANATIVEWINDOW_CHANGE_FRAME_RATE_ALWAYS, ""));
EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, ""));
+ EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_GTE,
+ ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, ""));
// Privileged APIs.
EXPECT_FALSE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_EXACT,
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index d4dbc45..c348833 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -20,12 +20,14 @@
#include <unistd.h>
#include <ctype.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <ftl/enum.h>
#include <gui/constants.h>
#include <input/InputDevice.h>
#include <input/InputEventLabels.h>
+using android::base::GetProperty;
using android::base::StringPrintf;
namespace android {
@@ -96,21 +98,22 @@
// Treblized input device config files will be located /product/usr, /system_ext/usr,
// /odm/usr or /vendor/usr.
- // These files may also be in the com.android.input.config APEX.
- const char* rootsForPartition[]{
- "/product",
- "/system_ext",
- "/odm",
- "/vendor",
- "/apex/com.android.input.config/etc",
- getenv("ANDROID_ROOT"),
+ std::vector<std::string> pathPrefixes{
+ "/product/usr/",
+ "/system_ext/usr/",
+ "/odm/usr/",
+ "/vendor/usr/",
};
- for (size_t i = 0; i < size(rootsForPartition); i++) {
- if (rootsForPartition[i] == nullptr) {
- continue;
- }
- path = rootsForPartition[i];
- path += "/usr/";
+ // These files may also be in the APEX pointed by input_device.config_file.apex sysprop.
+ if (auto apex = GetProperty("input_device.config_file.apex", ""); !apex.empty()) {
+ pathPrefixes.push_back("/apex/" + apex + "/etc/usr/");
+ }
+ // ANDROID_ROOT may not be set on host
+ if (auto android_root = getenv("ANDROID_ROOT"); android_root != nullptr) {
+ pathPrefixes.push_back(std::string(android_root) + "/usr/");
+ }
+ for (const auto& prefix : pathPrefixes) {
+ path = prefix;
appendInputDeviceConfigurationFileRelativePath(path, name, type);
#if DEBUG_PROBE
ALOGD("Probing for system provided input device configuration file: path='%s'",
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.cpp b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
index b43ab6c..eb7a9d5 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
@@ -378,6 +378,11 @@
BAIL("Could not find a Vulkan 1.1+ physical device");
}
+ if (physDevProps.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) {
+ // TODO: b/326633110 - SkiaVK is not working correctly on swiftshader path.
+ BAIL("CPU implementations of Vulkan is not supported");
+ }
+
// Check for syncfd support. Bail if we cannot both import and export them.
VkPhysicalDeviceExternalSemaphoreInfo semInfo = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
diff --git a/services/inputflinger/dispatcher/trace/ThreadedBackend.cpp b/services/inputflinger/dispatcher/trace/ThreadedBackend.cpp
index a58d52a..25bc227 100644
--- a/services/inputflinger/dispatcher/trace/ThreadedBackend.cpp
+++ b/services/inputflinger/dispatcher/trace/ThreadedBackend.cpp
@@ -21,7 +21,6 @@
#include "InputTracingPerfettoBackend.h"
#include <android-base/logging.h>
-#include <utils/AndroidThreads.h>
namespace android::inputdispatcher::trace::impl {
@@ -39,7 +38,10 @@
template <typename Backend>
ThreadedBackend<Backend>::ThreadedBackend(Backend&& innerBackend)
- : mTracerThread(&ThreadedBackend::threadLoop, this), mBackend(std::move(innerBackend)) {}
+ : mTracerThread(
+ "InputTracer", [this]() { threadLoop(); },
+ [this]() { mThreadWakeCondition.notify_all(); }),
+ mBackend(std::move(innerBackend)) {}
template <typename Backend>
ThreadedBackend<Backend>::~ThreadedBackend() {
@@ -48,7 +50,6 @@
mThreadExit = true;
}
mThreadWakeCondition.notify_all();
- mTracerThread.join();
}
template <typename Backend>
@@ -74,38 +75,33 @@
template <typename Backend>
void ThreadedBackend<Backend>::threadLoop() {
- androidSetThreadName("InputTracer");
+ std::vector<TraceEntry> entries;
- std::vector<std::variant<TracedKeyEvent, TracedMotionEvent, WindowDispatchArgs>> events;
+ { // acquire lock
+ std::unique_lock lock(mLock);
+ base::ScopedLockAssertion assumeLocked(mLock);
- while (true) {
- { // acquire lock
- std::unique_lock lock(mLock);
- base::ScopedLockAssertion assumeLocked(mLock);
-
- // Wait until we need to process more events or exit.
- mThreadWakeCondition.wait(lock, [&]() REQUIRES(mLock) {
- return mThreadExit || !mQueue.empty();
- });
- if (mThreadExit) {
- return;
- }
-
- mQueue.swap(events);
- } // release lock
-
- // Trace the events into the backend without holding the lock to reduce the amount of
- // work performed in the critical section.
- for (const auto& event : events) {
- std::visit(Visitor{[&](const TracedMotionEvent& e) { mBackend.traceMotionEvent(e); },
- [&](const TracedKeyEvent& e) { mBackend.traceKeyEvent(e); },
- [&](const WindowDispatchArgs& args) {
- mBackend.traceWindowDispatch(args);
- }},
- event);
+ // Wait until we need to process more events or exit.
+ mThreadWakeCondition.wait(lock,
+ [&]() REQUIRES(mLock) { return mThreadExit || !mQueue.empty(); });
+ if (mThreadExit) {
+ return;
}
- events.clear();
+
+ mQueue.swap(entries);
+ } // release lock
+
+ // Trace the events into the backend without holding the lock to reduce the amount of
+ // work performed in the critical section.
+ for (const auto& entry : entries) {
+ std::visit(Visitor{[&](const TracedMotionEvent& e) { mBackend.traceMotionEvent(e); },
+ [&](const TracedKeyEvent& e) { mBackend.traceKeyEvent(e); },
+ [&](const WindowDispatchArgs& args) {
+ mBackend.traceWindowDispatch(args);
+ }},
+ entry);
}
+ entries.clear();
}
// Explicit template instantiation for the PerfettoBackend.
diff --git a/services/inputflinger/dispatcher/trace/ThreadedBackend.h b/services/inputflinger/dispatcher/trace/ThreadedBackend.h
index c42f896..5776cf9 100644
--- a/services/inputflinger/dispatcher/trace/ThreadedBackend.h
+++ b/services/inputflinger/dispatcher/trace/ThreadedBackend.h
@@ -16,11 +16,11 @@
#pragma once
+#include "InputThread.h"
#include "InputTracingPerfettoBackend.h"
#include <android-base/thread_annotations.h>
#include <mutex>
-#include <thread>
#include <variant>
#include <vector>
@@ -44,12 +44,12 @@
private:
std::mutex mLock;
- std::thread mTracerThread;
+ InputThread mTracerThread;
bool mThreadExit GUARDED_BY(mLock){false};
std::condition_variable mThreadWakeCondition;
Backend mBackend;
- std::vector<std::variant<TracedKeyEvent, TracedMotionEvent, WindowDispatchArgs>> mQueue
- GUARDED_BY(mLock);
+ using TraceEntry = std::variant<TracedKeyEvent, TracedMotionEvent, WindowDispatchArgs>;
+ std::vector<TraceEntry> mQueue GUARDED_BY(mLock);
using WindowDispatchArgs = InputTracingBackendInterface::WindowDispatchArgs;
diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
index 797ebcc..764bb56 100644
--- a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
+++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
@@ -67,7 +67,6 @@
: mDeviceId(deviceId),
mReaderContext(readerContext),
mPointerController(readerContext.getPointerController(deviceId)),
- mEnablePointerChoreographer(input_flags::enable_pointer_choreographer()),
mEnableFlingStop(input_flags::enable_touchpad_fling_stop()) {
deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mXAxisInfo);
deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mYAxisInfo);
@@ -175,8 +174,7 @@
const Gesture& gesture) {
float deltaX = gesture.details.move.dx;
float deltaY = gesture.details.move.dy;
- const auto [oldXCursorPosition, oldYCursorPosition] =
- mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
+ const auto [oldXCursorPosition, oldYCursorPosition] = mPointerController->getPosition();
if (ENABLE_TOUCHPAD_PALM_REJECTION_V2) {
bool wasHoverCancelled = mIsHoverCancelled;
// Gesture will be cancelled if it started before the user started typing and
@@ -214,8 +212,7 @@
if (!down) {
out += enterHover(when, readTime, oldXCursorPosition, oldYCursorPosition);
}
- const auto [newXCursorPosition, newYCursorPosition] =
- mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
+ const auto [newXCursorPosition, newYCursorPosition] = mPointerController->getPosition();
PointerCoords coords;
coords.clear();
@@ -239,8 +236,7 @@
mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER);
mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
- const auto [xCursorPosition, yCursorPosition] =
- mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
+ const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
PointerCoords coords;
coords.clear();
@@ -320,8 +316,7 @@
std::list<NotifyArgs> GestureConverter::releaseAllButtons(nsecs_t when, nsecs_t readTime) {
std::list<NotifyArgs> out;
- const auto [xCursorPosition, yCursorPosition] =
- mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
+ const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
PointerCoords coords;
coords.clear();
@@ -356,8 +351,7 @@
const Gesture& gesture) {
std::list<NotifyArgs> out;
PointerCoords& coords = mFakeFingerCoords[0];
- const auto [xCursorPosition, yCursorPosition] =
- mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
+ const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
if (mCurrentClassification != MotionClassification::TWO_FINGER_SWIPE) {
out += exitHover(when, readTime, xCursorPosition, yCursorPosition);
@@ -415,9 +409,8 @@
// avoid side effects (e.g. activation of UI elements).
// TODO(b/326056750): add an API for fling stops.
mFlingMayBeInProgress = false;
- const auto [xCursorPosition, yCursorPosition] = mEnablePointerChoreographer
- ? FloatPoint{0, 0}
- : mPointerController->getPosition();
+ const auto [xCursorPosition, yCursorPosition] =
+ mPointerController->getPosition();
PointerCoords coords;
coords.clear();
coords.setAxisValue(AMOTION_EVENT_AXIS_X, xCursorPosition);
@@ -461,8 +454,7 @@
std::list<NotifyArgs> GestureConverter::endScroll(nsecs_t when, nsecs_t readTime) {
std::list<NotifyArgs> out;
- const auto [xCursorPosition, yCursorPosition] =
- mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
+ const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_SCROLL_X_DISTANCE, 0);
mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_SCROLL_Y_DISTANCE, 0);
NotifyMotionArgs args =
@@ -482,8 +474,7 @@
float dx, float dy) {
std::list<NotifyArgs> out = {};
- const auto [xCursorPosition, yCursorPosition] =
- mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
+ const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
if (mCurrentClassification != MotionClassification::MULTI_FINGER_SWIPE) {
// If the user changes the number of fingers mid-way through a swipe (e.g. they start with
// three and then put a fourth finger down), the gesture library will treat it as two
@@ -547,8 +538,7 @@
if (mCurrentClassification != MotionClassification::MULTI_FINGER_SWIPE) {
return out;
}
- const auto [xCursorPosition, yCursorPosition] =
- mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
+ const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET, 0);
mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET, 0);
@@ -571,8 +561,7 @@
[[nodiscard]] std::list<NotifyArgs> GestureConverter::handlePinch(nsecs_t when, nsecs_t readTime,
const Gesture& gesture) {
- const auto [xCursorPosition, yCursorPosition] =
- mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
+ const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
// Pinch gesture phases are reported a little differently from others, in that the same details
// struct is used for all phases of the gesture, just with different zoom_state values. When
@@ -630,8 +619,7 @@
std::list<NotifyArgs> GestureConverter::endPinch(nsecs_t when, nsecs_t readTime) {
std::list<NotifyArgs> out;
- const auto [xCursorPosition, yCursorPosition] =
- mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition();
+ const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_PINCH_SCALE_FACTOR, 1.0);
out.push_back(makeMotionArgs(when, readTime,
diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.h b/services/inputflinger/reader/mapper/gestures/GestureConverter.h
index ffab039..c8f437e 100644
--- a/services/inputflinger/reader/mapper/gestures/GestureConverter.h
+++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.h
@@ -105,7 +105,6 @@
const int32_t mDeviceId;
InputReaderContext& mReaderContext;
std::shared_ptr<PointerControllerInterface> mPointerController;
- const bool mEnablePointerChoreographer;
const bool mEnableFlingStop;
std::optional<int32_t> mDisplayId;
diff --git a/services/inputflinger/rust/slow_keys_filter.rs b/services/inputflinger/rust/slow_keys_filter.rs
index 01165b5..09fbf40 100644
--- a/services/inputflinger/rust/slow_keys_filter.rs
+++ b/services/inputflinger/rust/slow_keys_filter.rs
@@ -28,6 +28,9 @@
use std::collections::HashSet;
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
+// Policy flags from Input.h
+const POLICY_FLAG_DISABLE_KEY_REPEAT: i32 = 0x08000000;
+
#[derive(Debug)]
struct OngoingKeyDown {
scancode: i32,
@@ -129,6 +132,12 @@
let mut pending_event = *event;
pending_event.downTime += slow_filter.slow_key_threshold_ns;
pending_event.eventTime = pending_event.downTime;
+ // Currently a slow keys user ends up repeating the presses key quite often
+ // since default repeat thresholds are very low, so blocking repeat for events
+ // when slow keys is enabled.
+ // TODO(b/322327461): Allow key repeat with slow keys, once repeat key rate and
+ // thresholds can be modified in the settings.
+ pending_event.policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
slow_filter.pending_down_events.push(pending_event);
}
KeyEventAction::UP => {
@@ -200,7 +209,7 @@
mod tests {
use crate::input_filter::{test_callbacks::TestCallbacks, test_filter::TestFilter, Filter};
use crate::input_filter_thread::test_thread::TestThread;
- use crate::slow_keys_filter::SlowKeysFilter;
+ use crate::slow_keys_filter::{SlowKeysFilter, POLICY_FLAG_DISABLE_KEY_REPEAT};
use android_hardware_input_common::aidl::android::hardware::input::common::Source::Source;
use com_android_server_inputflinger::aidl::com::android::server::inputflinger::{
DeviceInfo::DeviceInfo, KeyEvent::KeyEvent, KeyEventAction::KeyEventAction,
@@ -285,6 +294,7 @@
action: KeyEventAction::DOWN,
downTime: 100,
eventTime: 100,
+ policyFlags: POLICY_FLAG_DISABLE_KEY_REPEAT,
..BASE_KEY_EVENT
}
);
diff --git a/services/inputflinger/tests/FakePointerController.cpp b/services/inputflinger/tests/FakePointerController.cpp
index 31e1173..dc199e2 100644
--- a/services/inputflinger/tests/FakePointerController.cpp
+++ b/services/inputflinger/tests/FakePointerController.cpp
@@ -37,16 +37,22 @@
}
void FakePointerController::setPosition(float x, float y) {
+ if (!mEnabled) return;
+
mX = x;
mY = y;
}
FloatPoint FakePointerController::getPosition() const {
+ if (!mEnabled) {
+ return {0, 0};
+ }
+
return {mX, mY};
}
int32_t FakePointerController::getDisplayId() const {
- if (!mDisplayId) {
+ if (!mEnabled || !mDisplayId) {
return ADISPLAY_ID_NONE;
}
return *mDisplayId;
@@ -64,6 +70,8 @@
}
void FakePointerController::setCustomPointerIcon(const SpriteIcon& icon) {
+ if (!mEnabled) return;
+
ASSERT_FALSE(mCustomIconStyle.has_value()) << "Custom pointer icon was set more than once";
mCustomIconStyle = icon.style;
}
@@ -114,10 +122,14 @@
}
std::optional<FloatRect> FakePointerController::getBounds() const {
+ if (!mEnabled) return std::nullopt;
+
return mHaveBounds ? std::make_optional<FloatRect>(mMinX, mMinY, mMaxX, mMaxY) : std::nullopt;
}
void FakePointerController::move(float deltaX, float deltaY) {
+ if (!mEnabled) return;
+
mX += deltaX;
if (mX < mMinX) mX = mMinX;
if (mX > mMaxX) mX = mMaxX;
@@ -127,14 +139,20 @@
}
void FakePointerController::fade(Transition) {
+ if (!mEnabled) return;
+
mIsPointerShown = false;
}
void FakePointerController::unfade(Transition) {
+ if (!mEnabled) return;
+
mIsPointerShown = true;
}
void FakePointerController::setSpots(const PointerCoords*, const uint32_t*, BitSet32 spotIdBits,
int32_t displayId) {
+ if (!mEnabled) return;
+
std::vector<int32_t> newSpots;
// Add spots for fingers that are down.
for (BitSet32 idBits(spotIdBits); !idBits.isEmpty();) {
@@ -146,6 +164,8 @@
}
void FakePointerController::clearSpots() {
+ if (!mEnabled) return;
+
mSpotsByDisplay.clear();
}
diff --git a/services/inputflinger/tests/FakePointerController.h b/services/inputflinger/tests/FakePointerController.h
index 061ae62..536b447 100644
--- a/services/inputflinger/tests/FakePointerController.h
+++ b/services/inputflinger/tests/FakePointerController.h
@@ -30,6 +30,9 @@
class FakePointerController : public PointerControllerInterface {
public:
+ FakePointerController() : FakePointerController(/*enabled=*/true) {}
+ FakePointerController(bool enabled) : mEnabled(enabled) {}
+
virtual ~FakePointerController() {}
void setBounds(float minX, float minY, float maxX, float maxY);
@@ -64,6 +67,7 @@
int32_t displayId) override;
void clearSpots() override;
+ const bool mEnabled;
bool mHaveBounds{false};
float mMinX{0}, mMinY{0}, mMaxX{0}, mMaxY{0};
float mX{0}, mY{0};
diff --git a/services/inputflinger/tests/GestureConverter_test.cpp b/services/inputflinger/tests/GestureConverter_test.cpp
index ca9ef8e..337b52b 100644
--- a/services/inputflinger/tests/GestureConverter_test.cpp
+++ b/services/inputflinger/tests/GestureConverter_test.cpp
@@ -69,7 +69,8 @@
mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, -500, 500, 0, 0, 20);
mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, -500, 500, 0, 0, 20);
- mFakePointerController = std::make_shared<FakePointerController>();
+ mFakePointerController = std::make_shared<FakePointerController>(
+ /*enabled=*/!input_flags::enable_pointer_choreographer());
mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
mFakePointerController->setPosition(POINTER_X, POINTER_Y);
mFakePolicy->setPointerController(mFakePointerController);
diff --git a/services/sensorservice/AidlSensorHalWrapper.cpp b/services/sensorservice/AidlSensorHalWrapper.cpp
index e60db93..91c2d1f 100644
--- a/services/sensorservice/AidlSensorHalWrapper.cpp
+++ b/services/sensorservice/AidlSensorHalWrapper.cpp
@@ -178,6 +178,11 @@
if ((eventFlagState & asBaseType(INTERNAL_WAKE)) && mReconnecting) {
ALOGD("Event FMQ internal wake, returning from poll with no events");
return DEAD_OBJECT;
+ } else if ((eventFlagState & asBaseType(INTERNAL_WAKE)) && mInHalBypassMode &&
+ availableEvents == 0) {
+ ALOGD("Event FMQ internal wake due to HAL Bypass Mode, returning from poll with no "
+ "events");
+ return OK;
}
}
@@ -221,6 +226,17 @@
status_t AidlSensorHalWrapper::setOperationMode(SensorService::Mode mode) {
if (mSensors == nullptr) return NO_INIT;
+ if (mode == SensorService::Mode::HAL_BYPASS_REPLAY_DATA_INJECTION) {
+ if (!mInHalBypassMode) {
+ mInHalBypassMode = true;
+ mEventQueueFlag->wake(asBaseType(INTERNAL_WAKE));
+ }
+ return OK;
+ } else {
+ if (mInHalBypassMode) {
+ mInHalBypassMode = false;
+ }
+ }
return convertToStatus(mSensors->setOperationMode(static_cast<ISensors::OperationMode>(mode)));
}
diff --git a/services/sensorservice/HidlSensorHalWrapper.cpp b/services/sensorservice/HidlSensorHalWrapper.cpp
index c55c9b4..8c867bd 100644
--- a/services/sensorservice/HidlSensorHalWrapper.cpp
+++ b/services/sensorservice/HidlSensorHalWrapper.cpp
@@ -203,6 +203,11 @@
if ((eventFlagState & asBaseType(INTERNAL_WAKE)) && mReconnecting) {
ALOGD("Event FMQ internal wake, returning from poll with no events");
return DEAD_OBJECT;
+ } else if ((eventFlagState & asBaseType(INTERNAL_WAKE)) && mInHalBypassMode &&
+ availableEvents == 0) {
+ ALOGD("Event FMQ internal wake due to HAL Bypass Mode, returning from poll with no "
+ "events");
+ return OK;
}
}
@@ -251,6 +256,17 @@
status_t HidlSensorHalWrapper::setOperationMode(SensorService::Mode mode) {
if (mSensors == nullptr) return NO_INIT;
+ if (mode == SensorService::Mode::HAL_BYPASS_REPLAY_DATA_INJECTION) {
+ if (!mInHalBypassMode) {
+ mInHalBypassMode = true;
+ mEventQueueFlag->wake(asBaseType(INTERNAL_WAKE));
+ }
+ return OK;
+ } else {
+ if (mInHalBypassMode) {
+ mInHalBypassMode = false;
+ }
+ }
return checkReturnAndGetStatus(
mSensors->setOperationMode(static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
}
diff --git a/services/sensorservice/ISensorHalWrapper.h b/services/sensorservice/ISensorHalWrapper.h
index 3d33540..891dfe5 100644
--- a/services/sensorservice/ISensorHalWrapper.h
+++ b/services/sensorservice/ISensorHalWrapper.h
@@ -97,6 +97,8 @@
virtual void writeWakeLockHandled(uint32_t count) = 0;
std::atomic_bool mReconnecting = false;
+
+ std::atomic_bool mInHalBypassMode = false;
};
} // namespace android
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 8e9dfea..f62562c 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -812,7 +812,6 @@
}
mInHalBypassMode = true;
}
- return OK;
} else {
if (mInHalBypassMode) {
// We are transitioning out of HAL Bypass mode. We need to notify the reader thread
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 1c2f6cb..921e05d 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -1276,7 +1276,9 @@
if (isProtected && supportsProtectedContent) {
auto layers = getOutputLayersOrderedByZ();
bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) {
- return layer->getLayerFE().getCompositionState()->hasProtectedContent;
+ return layer->getLayerFE().getCompositionState()->hasProtectedContent &&
+ (!FlagManager::getInstance().protected_if_client() ||
+ layer->requiresClientComposition());
});
if (needsProtected != mRenderSurface->isProtected()) {
mRenderSurface->setProtected(needsProtected);
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 62cfaf4..799c7ed 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -4051,6 +4051,7 @@
Layer() {
EXPECT_CALL(*mLayerFE, getCompositionState()).WillRepeatedly(Return(&mLayerFEState));
EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(*mLayerFE));
+ EXPECT_CALL(mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
}
StrictMock<mock::OutputLayer> mOutputLayer;
@@ -4091,6 +4092,7 @@
};
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNoProtectedContentLayers) {
+ SET_FLAG_FOR_TEST(flags::protected_if_client, true);
if (FlagManager::getInstance().display_protected()) {
mOutput.mState.isProtected = true;
} else {
@@ -4109,6 +4111,7 @@
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNotEnabled) {
+ SET_FLAG_FOR_TEST(flags::protected_if_client, true);
if (FlagManager::getInstance().display_protected()) {
mOutput.mState.isProtected = true;
} else {
@@ -4135,6 +4138,7 @@
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledEverywhere) {
+ SET_FLAG_FOR_TEST(flags::protected_if_client, true);
if (FlagManager::getInstance().display_protected()) {
mOutput.mState.isProtected = true;
} else {
@@ -4152,6 +4156,7 @@
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderSurface) {
+ SET_FLAG_FOR_TEST(flags::protected_if_client, true);
if (FlagManager::getInstance().display_protected()) {
mOutput.mState.isProtected = true;
} else {
@@ -5096,5 +5101,79 @@
mOutput->present(mRefreshArgs);
}
+/*
+ * Output::updateProtectedContentState()
+ */
+
+struct OutputUpdateProtectedContentStateTest : public testing::Test {
+ struct OutputPartialMock : public OutputPartialMockBase {
+ // Sets up the helper functions called by the function under test to use
+ // mock implementations.
+ MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
+ };
+
+ OutputUpdateProtectedContentStateTest() {
+ mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
+ EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
+ EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
+ EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
+ EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0))
+ .WillRepeatedly(Return(&mLayer1.mOutputLayer));
+ EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1))
+ .WillRepeatedly(Return(&mLayer2.mOutputLayer));
+ }
+
+ struct Layer {
+ Layer() {
+ EXPECT_CALL(*mLayerFE, getCompositionState()).WillRepeatedly(Return(&mLayerFEState));
+ EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(*mLayerFE));
+ }
+
+ StrictMock<mock::OutputLayer> mOutputLayer;
+ sp<StrictMock<mock::LayerFE>> mLayerFE = sp<StrictMock<mock::LayerFE>>::make();
+ LayerFECompositionState mLayerFEState;
+ };
+
+ mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
+ StrictMock<OutputPartialMock> mOutput;
+ StrictMock<mock::CompositionEngine> mCompositionEngine;
+ StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
+ Layer mLayer1;
+ Layer mLayer2;
+};
+
+TEST_F(OutputUpdateProtectedContentStateTest, ifProtectedContentLayerComposeByHWC) {
+ SET_FLAG_FOR_TEST(flags::protected_if_client, true);
+ if (FlagManager::getInstance().display_protected()) {
+ mOutput.mState.isProtected = true;
+ } else {
+ mOutput.mState.isSecure = true;
+ }
+ mLayer1.mLayerFEState.hasProtectedContent = false;
+ mLayer2.mLayerFEState.hasProtectedContent = true;
+ EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
+ EXPECT_CALL(mLayer1.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
+ EXPECT_CALL(mLayer2.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
+ mOutput.updateProtectedContentState();
+}
+
+TEST_F(OutputUpdateProtectedContentStateTest, ifProtectedContentLayerComposeByClient) {
+ SET_FLAG_FOR_TEST(flags::protected_if_client, true);
+ if (FlagManager::getInstance().display_protected()) {
+ mOutput.mState.isProtected = true;
+ } else {
+ mOutput.mState.isSecure = true;
+ }
+ mLayer1.mLayerFEState.hasProtectedContent = false;
+ mLayer2.mLayerFEState.hasProtectedContent = true;
+ EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
+ EXPECT_CALL(*mRenderSurface, setProtected(true));
+ EXPECT_CALL(mLayer1.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
+ EXPECT_CALL(mLayer2.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
+ mOutput.updateProtectedContentState();
+}
+
} // namespace
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index c888ccc..77e045d 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -377,8 +377,8 @@
constexpr bool kIsProtected = false;
if (const auto fenceResult =
- mFlinger.captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, buffer,
- kRegionSampling, kGrayscale, kIsProtected, nullptr)
+ mFlinger.captureScreenshot(std::move(renderAreaFuture), getLayerSnapshots, buffer,
+ kRegionSampling, kGrayscale, kIsProtected, nullptr)
.get();
fenceResult.ok()) {
fenceResult.value()->waitForever(LOG_TAG);
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index e696e8c..93350b5 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -972,6 +972,7 @@
LOG_ALWAYS_FATAL_IF(layer->vote != LayerVoteType::ExplicitDefault &&
layer->vote != LayerVoteType::ExplicitExactOrMultiple &&
layer->vote != LayerVoteType::ExplicitExact &&
+ layer->vote != LayerVoteType::ExplicitGte &&
layer->vote != LayerVoteType::ExplicitCategory,
"Invalid layer vote type for frame rate overrides");
for (auto& [fps, score] : scoredFrameRates) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index e6c58a3..3f91682 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -154,9 +154,13 @@
if (isNew) {
onHardwareVsyncRequest(displayId, false);
}
+
+ dispatchHotplug(displayId, Hotplug::Connected);
}
void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) {
+ dispatchHotplug(displayId, Hotplug::Disconnected);
+
demotePacesetterDisplay();
std::shared_ptr<VsyncSchedule> pacesetterVsyncSchedule;
@@ -375,15 +379,18 @@
return connection;
}
-void Scheduler::onHotplugReceived(Cycle cycle, PhysicalDisplayId displayId, bool connected) {
+void Scheduler::dispatchHotplug(PhysicalDisplayId displayId, Hotplug hotplug) {
if (hasEventThreads()) {
- eventThreadFor(cycle).onHotplugReceived(displayId, connected);
+ const bool connected = hotplug == Hotplug::Connected;
+ eventThreadFor(Cycle::Render).onHotplugReceived(displayId, connected);
+ eventThreadFor(Cycle::LastComposite).onHotplugReceived(displayId, connected);
}
}
-void Scheduler::onHotplugConnectionError(Cycle cycle, int32_t errorCode) {
+void Scheduler::dispatchHotplugError(int32_t errorCode) {
if (hasEventThreads()) {
- eventThreadFor(cycle).onHotplugConnectionError(errorCode);
+ eventThreadFor(Cycle::Render).onHotplugConnectionError(errorCode);
+ eventThreadFor(Cycle::LastComposite).onHotplugConnectionError(errorCode);
}
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index dc32225..09f75fd 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -142,8 +142,10 @@
return cycle == Cycle::Render ? mRenderEventConnection : mLastCompositeEventConnection;
}
- void onHotplugReceived(Cycle, PhysicalDisplayId, bool connected);
- void onHotplugConnectionError(Cycle, int32_t errorCode);
+ enum class Hotplug { Connected, Disconnected };
+ void dispatchHotplug(PhysicalDisplayId, Hotplug);
+
+ void dispatchHotplugError(int32_t errorCode);
void onPrimaryDisplayModeChanged(Cycle, const FrameRateMode&) EXCLUDES(mPolicyLock);
void onNonPrimaryDisplayModeChanged(Cycle, const FrameRateMode&);
diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
index 84ccf8e..6d6b70d 100644
--- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
@@ -20,7 +20,7 @@
#include <android-base/stringprintf.h>
#include <ftl/concat.h>
-#include <utils/Trace.h>
+#include <gui/TraceUtils.h>
#include <log/log_main.h>
#include <scheduler/TimeKeeper.h>
@@ -44,6 +44,17 @@
TimePoint::fromNs(nextVsyncTime)};
}
+void traceEntry(const VSyncDispatchTimerQueueEntry& entry, nsecs_t now) {
+ if (!ATRACE_ENABLED() || !entry.wakeupTime().has_value() || !entry.targetVsync().has_value()) {
+ return;
+ }
+
+ ftl::Concat trace(ftl::truncated<5>(entry.name()), " alarm in ",
+ ns2us(*entry.wakeupTime() - now), "us; VSYNC in ",
+ ns2us(*entry.targetVsync() - now), "us");
+ ATRACE_FORMAT_INSTANT(trace.c_str());
+}
+
} // namespace
VSyncDispatch::~VSyncDispatch() = default;
@@ -87,6 +98,7 @@
ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTiming timing,
VSyncTracker& tracker, nsecs_t now) {
+ ATRACE_NAME("VSyncDispatchTimerQueueEntry::schedule");
auto nextVsyncTime =
tracker.nextAnticipatedVSyncTimeFrom(std::max(timing.lastVsync,
now + timing.workDuration +
@@ -98,6 +110,8 @@
mArmedInfo && (nextVsyncTime > (mArmedInfo->mActualVsyncTime + mMinVsyncDistance));
bool const wouldSkipAWakeup =
mArmedInfo && ((nextWakeupTime > (mArmedInfo->mActualWakeupTime + mMinVsyncDistance)));
+ ATRACE_FORMAT_INSTANT("%s: wouldSkipAVsyncTarget=%d wouldSkipAWakeup=%d", mName.c_str(),
+ wouldSkipAVsyncTarget, wouldSkipAWakeup);
if (FlagManager::getInstance().dont_skip_on_early_ro()) {
if (wouldSkipAVsyncTarget || wouldSkipAWakeup) {
nextVsyncTime = mArmedInfo->mActualVsyncTime;
@@ -122,7 +136,7 @@
ScheduleResult VSyncDispatchTimerQueueEntry::addPendingWorkloadUpdate(
VSyncTracker& tracker, nsecs_t now, VSyncDispatch::ScheduleTiming timing) {
mWorkloadUpdateInfo = timing;
- const auto armedInfo = update(tracker, now, timing, mArmedInfo);
+ const auto armedInfo = getArmedInfo(tracker, now, timing, mArmedInfo);
return {TimePoint::fromNs(armedInfo.mActualWakeupTime),
TimePoint::fromNs(armedInfo.mActualVsyncTime)};
}
@@ -140,11 +154,13 @@
bool const nextVsyncTooClose = mLastDispatchTime &&
(nextVsyncTime - *mLastDispatchTime + mMinVsyncDistance) <= currentPeriod;
if (alreadyDispatchedForVsync) {
+ ATRACE_FORMAT_INSTANT("alreadyDispatchedForVsync");
return tracker.nextAnticipatedVSyncTimeFrom(*mLastDispatchTime + mMinVsyncDistance,
*mLastDispatchTime);
}
if (nextVsyncTooClose) {
+ ATRACE_FORMAT_INSTANT("nextVsyncTooClose");
return tracker.nextAnticipatedVSyncTimeFrom(*mLastDispatchTime + currentPeriod,
*mLastDispatchTime + currentPeriod);
}
@@ -152,9 +168,11 @@
return nextVsyncTime;
}
-auto VSyncDispatchTimerQueueEntry::update(VSyncTracker& tracker, nsecs_t now,
- VSyncDispatch::ScheduleTiming timing,
- std::optional<ArmingInfo> armedInfo) const -> ArmingInfo {
+auto VSyncDispatchTimerQueueEntry::getArmedInfo(VSyncTracker& tracker, nsecs_t now,
+ VSyncDispatch::ScheduleTiming timing,
+ std::optional<ArmingInfo> armedInfo) const
+ -> ArmingInfo {
+ ATRACE_NAME("VSyncDispatchTimerQueueEntry::getArmedInfo");
const auto earliestReadyBy = now + timing.workDuration + timing.readyDuration;
const auto earliestVsync = std::max(earliestReadyBy, timing.lastVsync);
@@ -165,29 +183,39 @@
const auto nextReadyTime = nextVsyncTime - timing.readyDuration;
const auto nextWakeupTime = nextReadyTime - timing.workDuration;
- bool const wouldSkipAVsyncTarget =
- armedInfo && (nextVsyncTime > (armedInfo->mActualVsyncTime + mMinVsyncDistance));
- bool const wouldSkipAWakeup =
- armedInfo && (nextWakeupTime > (armedInfo->mActualWakeupTime + mMinVsyncDistance));
- if (FlagManager::getInstance().dont_skip_on_early_ro() &&
- (wouldSkipAVsyncTarget || wouldSkipAWakeup)) {
- return *armedInfo;
+ if (FlagManager::getInstance().dont_skip_on_early_ro()) {
+ bool const wouldSkipAVsyncTarget =
+ armedInfo && (nextVsyncTime > (armedInfo->mActualVsyncTime + mMinVsyncDistance));
+ bool const wouldSkipAWakeup =
+ armedInfo && (nextWakeupTime > (armedInfo->mActualWakeupTime + mMinVsyncDistance));
+ ATRACE_FORMAT_INSTANT("%s: wouldSkipAVsyncTarget=%d wouldSkipAWakeup=%d", mName.c_str(),
+ wouldSkipAVsyncTarget, wouldSkipAWakeup);
+ if (wouldSkipAVsyncTarget || wouldSkipAWakeup) {
+ return *armedInfo;
+ }
}
return ArmingInfo{nextWakeupTime, nextVsyncTime, nextReadyTime};
}
void VSyncDispatchTimerQueueEntry::update(VSyncTracker& tracker, nsecs_t now) {
+ ATRACE_NAME("VSyncDispatchTimerQueueEntry::update");
if (!mArmedInfo && !mWorkloadUpdateInfo) {
return;
}
if (mWorkloadUpdateInfo) {
+ const auto workDelta = mWorkloadUpdateInfo->workDuration - mScheduleTiming.workDuration;
+ const auto readyDelta = mWorkloadUpdateInfo->readyDuration - mScheduleTiming.readyDuration;
+ const auto lastVsyncDelta = mWorkloadUpdateInfo->lastVsync - mScheduleTiming.lastVsync;
+ ATRACE_FORMAT_INSTANT("Workload updated workDelta=%" PRId64 " readyDelta=%" PRId64
+ " lastVsyncDelta=%" PRId64,
+ workDelta, readyDelta, lastVsyncDelta);
mScheduleTiming = *mWorkloadUpdateInfo;
mWorkloadUpdateInfo.reset();
}
- mArmedInfo = update(tracker, now, mScheduleTiming, mArmedInfo);
+ mArmedInfo = getArmedInfo(tracker, now, mScheduleTiming, mArmedInfo);
}
void VSyncDispatchTimerQueueEntry::disarm() {
@@ -282,6 +310,7 @@
void VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor(
nsecs_t now, CallbackMap::const_iterator skipUpdateIt) {
+ ATRACE_CALL();
std::optional<nsecs_t> min;
std::optional<nsecs_t> targetVsync;
std::optional<std::string_view> nextWakeupName;
@@ -294,7 +323,10 @@
if (it != skipUpdateIt) {
callback->update(*mTracker, now);
}
- auto const wakeupTime = *callback->wakeupTime();
+
+ traceEntry(*callback, now);
+
+ const auto wakeupTime = *callback->wakeupTime();
if (!min || *min > wakeupTime) {
nextWakeupName = callback->name();
min = wakeupTime;
@@ -303,11 +335,6 @@
}
if (min && min < mIntendedWakeupTime) {
- if (ATRACE_ENABLED() && nextWakeupName && targetVsync) {
- ftl::Concat trace(ftl::truncated<5>(*nextWakeupName), " alarm in ", ns2us(*min - now),
- "us; VSYNC in ", ns2us(*targetVsync - now), "us");
- ATRACE_NAME(trace.c_str());
- }
setTimer(*min, now);
} else {
ATRACE_NAME("cancel timer");
@@ -316,6 +343,7 @@
}
void VSyncDispatchTimerQueue::timerCallback() {
+ ATRACE_CALL();
struct Invocation {
std::shared_ptr<VSyncDispatchTimerQueueEntry> callback;
nsecs_t vsyncTimestamp;
@@ -338,8 +366,9 @@
continue;
}
- auto const readyTime = callback->readyTime();
+ traceEntry(*callback, now);
+ auto const readyTime = callback->readyTime();
auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast<nsecs_t>(0));
if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) {
callback->executing();
@@ -353,6 +382,8 @@
}
for (auto const& invocation : invocations) {
+ ftl::Concat trace(ftl::truncated<5>(invocation.callback->name()));
+ ATRACE_FORMAT("%s: %s", __func__, trace.c_str());
invocation.callback->callback(invocation.vsyncTimestamp, invocation.wakeupTimestamp,
invocation.deadlineTimestamp);
}
diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h
index 252c09c..e4ddc03 100644
--- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h
+++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h
@@ -91,8 +91,8 @@
};
nsecs_t adjustVsyncIfNeeded(VSyncTracker& tracker, nsecs_t nextVsyncTime) const;
- ArmingInfo update(VSyncTracker&, nsecs_t now, VSyncDispatch::ScheduleTiming,
- std::optional<ArmingInfo>) const;
+ ArmingInfo getArmedInfo(VSyncTracker&, nsecs_t now, VSyncDispatch::ScheduleTiming,
+ std::optional<ArmingInfo>) const;
const std::string mName;
const VSyncDispatch::Callback mCallback;
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index 8697696..2f9dfea 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -45,11 +45,35 @@
static auto constexpr kMaxPercent = 100u;
+namespace {
+nsecs_t getVsyncFixup(VSyncPredictor::Model model, Period minFramePeriod, nsecs_t vsyncTime,
+ std::optional<nsecs_t> lastVsyncOpt) {
+ const auto threshold = model.slope / 2;
+
+ if (FlagManager::getInstance().vrr_config() && lastVsyncOpt) {
+ const auto vsyncDiff = vsyncTime - *lastVsyncOpt;
+ if (vsyncDiff >= threshold && vsyncDiff <= minFramePeriod.ns() - threshold) {
+ const auto vsyncFixup = *lastVsyncOpt + minFramePeriod.ns() - vsyncTime;
+ ATRACE_FORMAT_INSTANT("minFramePeriod violation. next in %.2f which is %.2f from prev. "
+ "adjust by %.2f",
+ static_cast<float>(vsyncTime - TimePoint::now().ns()) / 1e6f,
+ static_cast<float>(vsyncTime - *lastVsyncOpt) / 1e6f,
+ static_cast<float>(vsyncFixup) / 1e6f);
+ return vsyncFixup;
+ }
+ }
+
+ return 0;
+}
+} // namespace
+
VSyncPredictor::~VSyncPredictor() = default;
-VSyncPredictor::VSyncPredictor(ftl::NonNull<DisplayModePtr> modePtr, size_t historySize,
- size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent)
- : mId(modePtr->getPhysicalDisplayId()),
+VSyncPredictor::VSyncPredictor(std::unique_ptr<Clock> clock, ftl::NonNull<DisplayModePtr> modePtr,
+ size_t historySize, size_t minimumSamplesForPrediction,
+ uint32_t outlierTolerancePercent)
+ : mClock(std::move(clock)),
+ mId(modePtr->getPhysicalDisplayId()),
mTraceOn(property_get_bool("debug.sf.vsp_trace", false)),
kHistorySize(historySize),
kMinimumSamplesForPrediction(minimumSamplesForPrediction),
@@ -147,7 +171,7 @@
mKnownTimestamp = timestamp;
}
ATRACE_FORMAT_INSTANT("timestamp rejected. mKnownTimestamp was %.2fms ago",
- (systemTime() - *mKnownTimestamp) / 1e6f);
+ (mClock->now() - *mKnownTimestamp) / 1e6f);
return false;
}
@@ -250,17 +274,6 @@
return true;
}
-auto VSyncPredictor::getVsyncSequenceLocked(nsecs_t timestamp) const -> VsyncSequence {
- const auto vsync = snapToVsync(timestamp);
- if (!mLastVsyncSequence) return {vsync, 0};
-
- const auto [slope, _] = getVSyncPredictionModelLocked();
- const auto [lastVsyncTime, lastVsyncSequence] = *mLastVsyncSequence;
- const auto vsyncSequence = lastVsyncSequence +
- static_cast<int64_t>(std::round((vsync - lastVsyncTime) / static_cast<float>(slope)));
- return {vsync, vsyncSequence};
-}
-
nsecs_t VSyncPredictor::snapToVsync(nsecs_t timePoint) const {
auto const [slope, intercept] = getVSyncPredictionModelLocked();
@@ -298,51 +311,32 @@
}
nsecs_t VSyncPredictor::nextAnticipatedVSyncTimeFrom(nsecs_t timePoint,
- std::optional<nsecs_t> lastVsyncOpt) const {
+ std::optional<nsecs_t> lastVsyncOpt) {
ATRACE_CALL();
std::lock_guard lock(mMutex);
- const auto currentPeriod = mRateMap.find(idealPeriod())->second.slope;
- const auto threshold = currentPeriod / 2;
- const auto minFramePeriod = minFramePeriodLocked().ns();
- const auto lastFrameMissed =
- lastVsyncOpt && std::abs(*lastVsyncOpt - mLastMissedVsync.ns()) < threshold;
- const nsecs_t baseTime =
- FlagManager::getInstance().vrr_config() && !lastFrameMissed && lastVsyncOpt
- ? std::max(timePoint, *lastVsyncOpt + minFramePeriod - threshold)
- : timePoint;
- return snapToVsyncAlignedWithRenderRate(baseTime);
-}
-nsecs_t VSyncPredictor::snapToVsyncAlignedWithRenderRate(nsecs_t timePoint) const {
- // update the mLastVsyncSequence for reference point
- mLastVsyncSequence = getVsyncSequenceLocked(timePoint);
+ const auto now = TimePoint::fromNs(mClock->now());
+ purgeTimelines(now);
- const auto renderRatePhase = [&]() REQUIRES(mMutex) -> int {
- if (!mRenderRateOpt) return 0;
- const auto divisor =
- RefreshRateSelector::getFrameRateDivisor(Fps::fromPeriodNsecs(idealPeriod()),
- *mRenderRateOpt);
- if (divisor <= 1) return 0;
-
- int mod = mLastVsyncSequence->seq % divisor;
- if (mod == 0) return 0;
-
- // This is actually a bug fix, but guarded with vrr_config since we found it with this
- // config
- if (FlagManager::getInstance().vrr_config()) {
- if (mod < 0) mod += divisor;
+ std::optional<TimePoint> vsyncOpt;
+ for (auto& timeline : mTimelines) {
+ vsyncOpt = timeline.nextAnticipatedVSyncTimeFrom(getVSyncPredictionModelLocked(),
+ minFramePeriodLocked(),
+ snapToVsync(timePoint), mMissedVsync,
+ lastVsyncOpt);
+ if (vsyncOpt) {
+ break;
}
+ }
+ LOG_ALWAYS_FATAL_IF(!vsyncOpt);
- return divisor - mod;
- }();
-
- if (renderRatePhase == 0) {
- return mLastVsyncSequence->vsyncTime;
+ if (*vsyncOpt > mLastCommittedVsync) {
+ mLastCommittedVsync = *vsyncOpt;
+ ATRACE_FORMAT_INSTANT("mLastCommittedVsync in %.2fms",
+ float(mLastCommittedVsync.ns() - mClock->now()) / 1e6f);
}
- auto const [slope, intercept] = getVSyncPredictionModelLocked();
- const auto approximateNextVsync = mLastVsyncSequence->vsyncTime + slope * renderRatePhase;
- return snapToVsync(approximateNextVsync - slope / 2);
+ return vsyncOpt->ns();
}
/*
@@ -353,32 +347,28 @@
* isVSyncInPhase(33.3, 30) = false
* isVSyncInPhase(50.0, 30) = true
*/
-bool VSyncPredictor::isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const {
- std::lock_guard lock(mMutex);
- const auto divisor =
- RefreshRateSelector::getFrameRateDivisor(Fps::fromPeriodNsecs(idealPeriod()),
- frameRate);
- return isVSyncInPhaseLocked(timePoint, static_cast<unsigned>(divisor));
-}
-
-bool VSyncPredictor::isVSyncInPhaseLocked(nsecs_t timePoint, unsigned divisor) const {
- const TimePoint now = TimePoint::now();
- const auto getTimePointIn = [](TimePoint now, nsecs_t timePoint) -> float {
- return ticks<std::milli, float>(TimePoint::fromNs(timePoint) - now);
- };
- ATRACE_FORMAT("%s timePoint in: %.2f divisor: %zu", __func__, getTimePointIn(now, timePoint),
- divisor);
-
- if (divisor <= 1 || timePoint == 0) {
+bool VSyncPredictor::isVSyncInPhase(nsecs_t timePoint, Fps frameRate) {
+ if (timePoint == 0) {
return true;
}
- const nsecs_t period = mRateMap[idealPeriod()].slope;
+ std::lock_guard lock(mMutex);
+ const auto model = getVSyncPredictionModelLocked();
+ const nsecs_t period = model.slope;
const nsecs_t justBeforeTimePoint = timePoint - period / 2;
- const auto vsyncSequence = getVsyncSequenceLocked(justBeforeTimePoint);
- ATRACE_FORMAT_INSTANT("vsync in: %.2f sequence: %" PRId64,
- getTimePointIn(now, vsyncSequence.vsyncTime), vsyncSequence.seq);
- return vsyncSequence.seq % divisor == 0;
+ const auto now = TimePoint::fromNs(mClock->now());
+ const auto vsync = snapToVsync(justBeforeTimePoint);
+
+ purgeTimelines(now);
+
+ for (auto& timeline : mTimelines) {
+ if (timeline.validUntil() && timeline.validUntil()->ns() > vsync) {
+ return timeline.isVSyncInPhase(model, vsync, frameRate);
+ }
+ }
+
+ // The last timeline should always be valid
+ return mTimelines.back().isVSyncInPhase(model, vsync, frameRate);
}
void VSyncPredictor::setRenderRate(Fps renderRate) {
@@ -386,6 +376,9 @@
ALOGV("%s %s: RenderRate %s ", __func__, to_string(mId).c_str(), to_string(renderRate).c_str());
std::lock_guard lock(mMutex);
mRenderRateOpt = renderRate;
+ mTimelines.back().freeze(TimePoint::fromNs(mLastCommittedVsync.ns() + mIdealPeriod.ns() / 2));
+ mTimelines.emplace_back(mIdealPeriod, renderRate);
+ purgeTimelines(TimePoint::fromNs(mClock->now()));
}
void VSyncPredictor::setDisplayModePtr(ftl::NonNull<DisplayModePtr> modePtr) {
@@ -415,8 +408,9 @@
clearTimestamps();
}
-void VSyncPredictor::ensureMinFrameDurationIsKept(TimePoint expectedPresentTime,
- TimePoint lastConfirmedPresentTime) {
+Duration VSyncPredictor::ensureMinFrameDurationIsKept(TimePoint expectedPresentTime,
+ TimePoint lastConfirmedPresentTime) {
+ ATRACE_CALL();
const auto currentPeriod = mRateMap.find(idealPeriod())->second.slope;
const auto threshold = currentPeriod / 2;
const auto minFramePeriod = minFramePeriodLocked().ns();
@@ -442,17 +436,20 @@
if (!mPastExpectedPresentTimes.empty()) {
const auto phase = Duration(mPastExpectedPresentTimes.back() - expectedPresentTime);
if (phase > 0ns) {
- if (mLastVsyncSequence) {
- mLastVsyncSequence->vsyncTime += phase.ns();
+ for (auto& timeline : mTimelines) {
+ timeline.shiftVsyncSequence(phase);
}
mPastExpectedPresentTimes.clear();
+ return phase;
}
}
+
+ return 0ns;
}
void VSyncPredictor::onFrameBegin(TimePoint expectedPresentTime,
TimePoint lastConfirmedPresentTime) {
- ATRACE_CALL();
+ ATRACE_NAME("VSyncPredictor::onFrameBegin");
std::lock_guard lock(mMutex);
if (!mDisplayModePtr->getVrrConfig()) return;
@@ -482,11 +479,14 @@
}
}
- ensureMinFrameDurationIsKept(expectedPresentTime, lastConfirmedPresentTime);
+ const auto phase = ensureMinFrameDurationIsKept(expectedPresentTime, lastConfirmedPresentTime);
+ if (phase > 0ns) {
+ mMissedVsync = {expectedPresentTime, minFramePeriodLocked()};
+ }
}
void VSyncPredictor::onFrameMissed(TimePoint expectedPresentTime) {
- ATRACE_CALL();
+ ATRACE_NAME("VSyncPredictor::onFrameMissed");
std::lock_guard lock(mMutex);
if (!mDisplayModePtr->getVrrConfig()) return;
@@ -496,14 +496,15 @@
const auto lastConfirmedPresentTime =
TimePoint::fromNs(expectedPresentTime.ns() + currentPeriod);
- ensureMinFrameDurationIsKept(expectedPresentTime, lastConfirmedPresentTime);
- mLastMissedVsync = expectedPresentTime;
+ const auto phase = ensureMinFrameDurationIsKept(expectedPresentTime, lastConfirmedPresentTime);
+ if (phase > 0ns) {
+ mMissedVsync = {expectedPresentTime, Duration::fromNs(0)};
+ }
}
VSyncPredictor::Model VSyncPredictor::getVSyncPredictionModel() const {
std::lock_guard lock(mMutex);
- const auto model = VSyncPredictor::getVSyncPredictionModelLocked();
- return {model.slope, model.intercept};
+ return VSyncPredictor::getVSyncPredictionModelLocked();
}
VSyncPredictor::Model VSyncPredictor::getVSyncPredictionModelLocked() const {
@@ -524,6 +525,11 @@
mTimestamps.clear();
mLastTimestampIndex = 0;
}
+
+ mTimelines.clear();
+ mLastCommittedVsync = TimePoint::fromNs(0);
+ mIdealPeriod = Period::fromNs(idealPeriod());
+ mTimelines.emplace_back(mIdealPeriod, mRenderRateOpt);
}
bool VSyncPredictor::needsMoreSamples() const {
@@ -547,6 +553,130 @@
period / 1e6f, periodInterceptTuple.slope / 1e6f,
periodInterceptTuple.intercept);
}
+ StringAppendF(&result, "\tmTimelines.size()=%zu\n", mTimelines.size());
+}
+
+void VSyncPredictor::purgeTimelines(android::TimePoint now) {
+ while (mTimelines.size() > 1) {
+ const auto validUntilOpt = mTimelines.front().validUntil();
+ if (validUntilOpt && *validUntilOpt < now) {
+ mTimelines.pop_front();
+ } else {
+ break;
+ }
+ }
+ LOG_ALWAYS_FATAL_IF(mTimelines.empty());
+ LOG_ALWAYS_FATAL_IF(mTimelines.back().validUntil().has_value());
+}
+
+VSyncPredictor::VsyncTimeline::VsyncTimeline(Period idealPeriod, std::optional<Fps> renderRateOpt)
+ : mIdealPeriod(idealPeriod), mRenderRateOpt(renderRateOpt) {}
+
+void VSyncPredictor::VsyncTimeline::freeze(TimePoint lastVsync) {
+ LOG_ALWAYS_FATAL_IF(mValidUntil.has_value());
+ ATRACE_FORMAT_INSTANT("renderRate %s valid for %.2f",
+ mRenderRateOpt ? to_string(*mRenderRateOpt).c_str() : "NA",
+ float(lastVsync.ns() - TimePoint::now().ns()) / 1e6f);
+ mValidUntil = lastVsync;
+}
+
+std::optional<TimePoint> VSyncPredictor::VsyncTimeline::nextAnticipatedVSyncTimeFrom(
+ Model model, Period minFramePeriod, nsecs_t vsync, MissedVsync missedVsync,
+ std::optional<nsecs_t> lastVsyncOpt) {
+ ATRACE_FORMAT("renderRate %s", mRenderRateOpt ? to_string(*mRenderRateOpt).c_str() : "NA");
+
+ const auto threshold = model.slope / 2;
+ const auto lastFrameMissed =
+ lastVsyncOpt && std::abs(*lastVsyncOpt - missedVsync.vsync.ns()) < threshold;
+ nsecs_t vsyncTime = snapToVsyncAlignedWithRenderRate(model, vsync);
+ nsecs_t vsyncFixupTime = 0;
+ if (FlagManager::getInstance().vrr_config() && lastFrameMissed) {
+ vsyncTime += missedVsync.fixup.ns();
+ ATRACE_FORMAT_INSTANT("lastFrameMissed");
+ } else {
+ vsyncFixupTime = getVsyncFixup(model, minFramePeriod, vsyncTime, lastVsyncOpt);
+ vsyncTime += vsyncFixupTime;
+ }
+
+ ATRACE_FORMAT_INSTANT("vsync in %.2fms", float(vsyncTime - TimePoint::now().ns()) / 1e6f);
+ if (mValidUntil && vsyncTime > mValidUntil->ns()) {
+ ATRACE_FORMAT_INSTANT("no longer valid for vsync in %.2f",
+ static_cast<float>(vsyncTime - TimePoint::now().ns()) / 1e6f);
+ return std::nullopt;
+ }
+
+ if (vsyncFixupTime > 0) {
+ shiftVsyncSequence(Duration::fromNs(vsyncFixupTime));
+ }
+
+ return TimePoint::fromNs(vsyncTime);
+}
+
+auto VSyncPredictor::VsyncTimeline::getVsyncSequenceLocked(Model model, nsecs_t vsync)
+ -> VsyncSequence {
+ if (!mLastVsyncSequence) return {vsync, 0};
+
+ const auto [lastVsyncTime, lastVsyncSequence] = *mLastVsyncSequence;
+ const auto vsyncSequence = lastVsyncSequence +
+ static_cast<int64_t>(std::round((vsync - lastVsyncTime) /
+ static_cast<float>(model.slope)));
+ return {vsync, vsyncSequence};
+}
+
+nsecs_t VSyncPredictor::VsyncTimeline::snapToVsyncAlignedWithRenderRate(Model model,
+ nsecs_t vsync) {
+ // update the mLastVsyncSequence for reference point
+ mLastVsyncSequence = getVsyncSequenceLocked(model, vsync);
+
+ const auto renderRatePhase = [&]() -> int {
+ if (!mRenderRateOpt) return 0;
+ const auto divisor =
+ RefreshRateSelector::getFrameRateDivisor(Fps::fromPeriodNsecs(mIdealPeriod.ns()),
+ *mRenderRateOpt);
+ if (divisor <= 1) return 0;
+
+ int mod = mLastVsyncSequence->seq % divisor;
+ if (mod == 0) return 0;
+
+ // This is actually a bug fix, but guarded with vrr_config since we found it with this
+ // config
+ if (FlagManager::getInstance().vrr_config()) {
+ if (mod < 0) mod += divisor;
+ }
+
+ return divisor - mod;
+ }();
+
+ if (renderRatePhase == 0) {
+ return mLastVsyncSequence->vsyncTime;
+ }
+
+ return mLastVsyncSequence->vsyncTime + model.slope * renderRatePhase;
+}
+
+bool VSyncPredictor::VsyncTimeline::isVSyncInPhase(Model model, nsecs_t vsync, Fps frameRate) {
+ const auto getVsyncIn = [](TimePoint now, nsecs_t timePoint) -> float {
+ return ticks<std::milli, float>(TimePoint::fromNs(timePoint) - now);
+ };
+
+ Fps displayFps = mRenderRateOpt ? *mRenderRateOpt : Fps::fromPeriodNsecs(mIdealPeriod.ns());
+ const auto divisor = RefreshRateSelector::getFrameRateDivisor(displayFps, frameRate);
+ const auto now = TimePoint::now();
+
+ if (divisor <= 1) {
+ return true;
+ }
+ const auto vsyncSequence = getVsyncSequenceLocked(model, vsync);
+ ATRACE_FORMAT_INSTANT("vsync in: %.2f sequence: %" PRId64 " divisor: %zu",
+ getVsyncIn(now, vsyncSequence.vsyncTime), vsyncSequence.seq, divisor);
+ return vsyncSequence.seq % divisor == 0;
+}
+
+void VSyncPredictor::VsyncTimeline::shiftVsyncSequence(Duration phase) {
+ if (mLastVsyncSequence) {
+ ATRACE_FORMAT_INSTANT("adjusting vsync by %.2f", static_cast<float>(phase.ns()) / 1e6f);
+ mLastVsyncSequence->vsyncTime += phase.ns();
+ }
}
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.h b/services/surfaceflinger/Scheduler/VSyncPredictor.h
index 8fd7e60..c175765 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.h
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h
@@ -22,6 +22,7 @@
#include <vector>
#include <android-base/thread_annotations.h>
+#include <scheduler/TimeKeeper.h>
#include <ui/DisplayId.h>
#include "VSyncTracker.h"
@@ -31,6 +32,7 @@
class VSyncPredictor : public VSyncTracker {
public:
/*
+ * \param [in] Clock The clock abstraction. Useful for unit tests.
* \param [in] PhysicalDisplayid The display this corresponds to.
* \param [in] modePtr The initial display mode
* \param [in] historySize The internal amount of entries to store in the model.
@@ -38,13 +40,13 @@
* predicting. \param [in] outlierTolerancePercent a number 0 to 100 that will be used to filter
* samples that fall outlierTolerancePercent from an anticipated vsync event.
*/
- VSyncPredictor(ftl::NonNull<DisplayModePtr> modePtr, size_t historySize,
+ VSyncPredictor(std::unique_ptr<Clock>, ftl::NonNull<DisplayModePtr> modePtr, size_t historySize,
size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent);
~VSyncPredictor();
bool addVsyncTimestamp(nsecs_t timestamp) final EXCLUDES(mMutex);
nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint,
- std::optional<nsecs_t> lastVsyncOpt = {}) const final
+ std::optional<nsecs_t> lastVsyncOpt = {}) final
EXCLUDES(mMutex);
nsecs_t currentPeriod() const final EXCLUDES(mMutex);
Period minFramePeriod() const final EXCLUDES(mMutex);
@@ -62,7 +64,7 @@
VSyncPredictor::Model getVSyncPredictionModel() const EXCLUDES(mMutex);
- bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const final EXCLUDES(mMutex);
+ bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) final EXCLUDES(mMutex);
void setDisplayModePtr(ftl::NonNull<DisplayModePtr>) final EXCLUDES(mMutex);
@@ -75,10 +77,42 @@
void dump(std::string& result) const final EXCLUDES(mMutex);
private:
+ struct VsyncSequence {
+ nsecs_t vsyncTime;
+ int64_t seq;
+ };
+
+ struct MissedVsync {
+ TimePoint vsync;
+ Duration fixup = Duration::fromNs(0);
+ };
+
+ class VsyncTimeline {
+ public:
+ VsyncTimeline(Period idealPeriod, std::optional<Fps> renderRateOpt);
+ std::optional<TimePoint> nextAnticipatedVSyncTimeFrom(
+ Model model, Period minFramePeriod, nsecs_t vsyncTime, MissedVsync lastMissedVsync,
+ std::optional<nsecs_t> lastVsyncOpt = {});
+ void freeze(TimePoint lastVsync);
+ std::optional<TimePoint> validUntil() const { return mValidUntil; }
+ bool isVSyncInPhase(Model, nsecs_t vsync, Fps frameRate);
+ void shiftVsyncSequence(Duration phase);
+
+ private:
+ nsecs_t snapToVsyncAlignedWithRenderRate(Model model, nsecs_t vsync);
+ VsyncSequence getVsyncSequenceLocked(Model, nsecs_t vsync);
+
+ const Period mIdealPeriod = Duration::fromNs(0);
+ const std::optional<Fps> mRenderRateOpt;
+ std::optional<TimePoint> mValidUntil;
+ std::optional<VsyncSequence> mLastVsyncSequence;
+ };
+
VSyncPredictor(VSyncPredictor const&) = delete;
VSyncPredictor& operator=(VSyncPredictor const&) = delete;
void clearTimestamps() REQUIRES(mMutex);
+ const std::unique_ptr<Clock> mClock;
const PhysicalDisplayId mId;
inline void traceInt64If(const char* name, int64_t value) const;
@@ -88,16 +122,10 @@
bool validate(nsecs_t timestamp) const REQUIRES(mMutex);
Model getVSyncPredictionModelLocked() const REQUIRES(mMutex);
nsecs_t snapToVsync(nsecs_t timePoint) const REQUIRES(mMutex);
- nsecs_t snapToVsyncAlignedWithRenderRate(nsecs_t timePoint) const REQUIRES(mMutex);
- bool isVSyncInPhaseLocked(nsecs_t timePoint, unsigned divisor) const REQUIRES(mMutex);
Period minFramePeriodLocked() const REQUIRES(mMutex);
- void ensureMinFrameDurationIsKept(TimePoint, TimePoint) REQUIRES(mMutex);
+ Duration ensureMinFrameDurationIsKept(TimePoint, TimePoint) REQUIRES(mMutex);
+ void purgeTimelines(android::TimePoint now) REQUIRES(mMutex);
- struct VsyncSequence {
- nsecs_t vsyncTime;
- int64_t seq;
- };
- VsyncSequence getVsyncSequenceLocked(nsecs_t timestamp) const REQUIRES(mMutex);
nsecs_t idealPeriod() const REQUIRES(mMutex);
bool const mTraceOn;
@@ -115,13 +143,15 @@
std::vector<nsecs_t> mTimestamps GUARDED_BY(mMutex);
ftl::NonNull<DisplayModePtr> mDisplayModePtr GUARDED_BY(mMutex);
- std::optional<Fps> mRenderRateOpt GUARDED_BY(mMutex);
-
- mutable std::optional<VsyncSequence> mLastVsyncSequence GUARDED_BY(mMutex);
std::deque<TimePoint> mPastExpectedPresentTimes GUARDED_BY(mMutex);
- TimePoint mLastMissedVsync GUARDED_BY(mMutex);
+ MissedVsync mMissedVsync GUARDED_BY(mMutex);
+
+ std::deque<VsyncTimeline> mTimelines GUARDED_BY(mMutex);
+ TimePoint mLastCommittedVsync GUARDED_BY(mMutex) = TimePoint::fromNs(0);
+ Period mIdealPeriod GUARDED_BY(mMutex) = Duration::fromNs(0);
+ std::optional<Fps> mRenderRateOpt GUARDED_BY(mMutex);
};
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/VSyncTracker.h b/services/surfaceflinger/Scheduler/VSyncTracker.h
index 37bd4b4..1e55a87 100644
--- a/services/surfaceflinger/Scheduler/VSyncTracker.h
+++ b/services/surfaceflinger/Scheduler/VSyncTracker.h
@@ -56,8 +56,8 @@
* and avoid crossing the minimal frame period of a VRR display.
* \return A prediction of the timestamp of a vsync event.
*/
- virtual nsecs_t nextAnticipatedVSyncTimeFrom(
- nsecs_t timePoint, std::optional<nsecs_t> lastVsyncOpt = {}) const = 0;
+ virtual nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint,
+ std::optional<nsecs_t> lastVsyncOpt = {}) = 0;
/*
* The current period of the vsync signal.
@@ -82,7 +82,7 @@
* \param [in] timePoint A vsync timestamp
* \param [in] frameRate The frame rate to check for
*/
- virtual bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const = 0;
+ virtual bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) = 0;
/*
* Sets the active mode of the display which includes the vsync period and other VRR attributes.
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
index 001938c..2fa3318 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
@@ -120,8 +120,8 @@
constexpr size_t kMinSamplesForPrediction = 6;
constexpr uint32_t kDiscardOutlierPercent = 20;
- return std::make_unique<VSyncPredictor>(modePtr, kHistorySize, kMinSamplesForPrediction,
- kDiscardOutlierPercent);
+ return std::make_unique<VSyncPredictor>(std::make_unique<SystemClock>(), modePtr, kHistorySize,
+ kMinSamplesForPrediction, kDiscardOutlierPercent);
}
VsyncSchedule::DispatchPtr VsyncSchedule::createDispatch(TrackerPtr tracker) {
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.h b/services/surfaceflinger/Scheduler/VsyncSchedule.h
index 85cd3e7..881d678 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.h
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.h
@@ -81,7 +81,7 @@
bool addResyncSample(TimePoint timestamp, ftl::Optional<Period> hwcVsyncPeriod);
// TODO(b/185535769): Hide behind API.
- const VsyncTracker& getTracker() const { return *mTracker; }
+ VsyncTracker& getTracker() const { return *mTracker; }
VsyncTracker& getTracker() { return *mTracker; }
VsyncController& getController() { return *mController; }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 08a78cc..46a2259 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -886,7 +886,6 @@
// the DisplayDevice, hence the above commit of the primary display. Remove that special case by
// initializing the Scheduler after configureLocked, once decoupled from DisplayDevice.
initScheduler(display);
- dispatchDisplayHotplugEvent(display->getPhysicalId(), true);
mLayerTracing.setTakeLayersSnapshotProtoFunction([&](uint32_t traceFlags) {
auto snapshot = perfetto::protos::LayersSnapshotProto{};
@@ -1756,7 +1755,7 @@
}
display->overrideHdrTypes(hdrTypes);
- dispatchDisplayHotplugEvent(display->getPhysicalId(), true /* connected */);
+ mScheduler->dispatchHotplug(display->getPhysicalId(), scheduler::Scheduler::Hotplug::Connected);
return NO_ERROR;
}
@@ -2128,10 +2127,9 @@
vsyncPeriod.has_value()) {
// use ~0 instead of -1 as AidlComposerHal.cpp passes the param as unsigned int32
if (mIsHotplugErrViaNegVsync && vsyncPeriod.value() == ~0) {
- const int32_t hotplugErrorCode = static_cast<int32_t>(-timestamp);
- ALOGD("SurfaceFlinger got hotplugErrorCode=%d for display %" PRIu64, hotplugErrorCode,
- hwcDisplayId);
- mScheduler->onHotplugConnectionError(scheduler::Cycle::Render, hotplugErrorCode);
+ const auto errorCode = static_cast<int32_t>(-timestamp);
+ ALOGD("%s: Hotplug error %d for display %" PRIu64, __func__, errorCode, hwcDisplayId);
+ mScheduler->dispatchHotplugError(errorCode);
return;
}
@@ -2140,8 +2138,7 @@
// one byte is good enough to encode android.hardware.drm.HdcpLevel
const int32_t maxLevel = (value >> 8) & 0xFF;
const int32_t connectedLevel = value & 0xFF;
- ALOGD("SurfaceFlinger got HDCP level changed: connected=%d, max=%d for "
- "display=%" PRIu64,
+ ALOGD("%s: HDCP levels changed (connected=%d, max=%d) for display %" PRIu64, __func__,
connectedLevel, maxLevel, hwcDisplayId);
updateHdcpLevels(hwcDisplayId, connectedLevel, maxLevel);
return;
@@ -2180,9 +2177,10 @@
}
if (FlagManager::getInstance().hotplug2()) {
- ALOGD("SurfaceFlinger got hotplug event=%d", static_cast<int32_t>(event));
// TODO(b/311403559): use enum type instead of int
- mScheduler->onHotplugConnectionError(scheduler::Cycle::Render, static_cast<int32_t>(event));
+ const auto errorCode = static_cast<int32_t>(event);
+ ALOGD("%s: Hotplug error %d for display %" PRIu64, __func__, errorCode, hwcDisplayId);
+ mScheduler->dispatchHotplugError(errorCode);
}
}
@@ -3476,9 +3474,8 @@
if (!activeMode) {
ALOGE("Failed to hotplug display %s", to_string(displayId).c_str());
if (FlagManager::getInstance().hotplug2()) {
- mScheduler->onHotplugConnectionError(scheduler::Cycle::Render,
- static_cast<int32_t>(
- DisplayHotplugEvent::ERROR_UNKNOWN));
+ mScheduler->dispatchHotplugError(
+ static_cast<int32_t>(DisplayHotplugEvent::ERROR_UNKNOWN));
}
getHwComposer().disconnectDisplay(displayId);
return nullptr;
@@ -3528,11 +3525,6 @@
return "Connecting";
}
-void SurfaceFlinger::dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected) {
- mScheduler->onHotplugReceived(scheduler::Cycle::Render, displayId, connected);
- mScheduler->onHotplugReceived(scheduler::Cycle::LastComposite, displayId, connected);
-}
-
void SurfaceFlinger::dispatchDisplayModeChangeEvent(PhysicalDisplayId displayId,
const scheduler::FrameRateMode& mode) {
// TODO(b/255635821): Merge code paths and move to Scheduler.
@@ -3721,16 +3713,11 @@
displaySurface, producer);
if (mScheduler && !display->isVirtual()) {
- const auto displayId = display->getPhysicalId();
- {
- // TODO(b/241285876): Annotate `processDisplayAdded` instead.
- ftl::FakeGuard guard(kMainThreadContext);
+ // TODO(b/241285876): Annotate `processDisplayAdded` instead.
+ ftl::FakeGuard guard(kMainThreadContext);
- // For hotplug reconnect, renew the registration since display modes have been reloaded.
- mScheduler->registerDisplay(displayId, display->holdRefreshRateSelector());
- }
-
- dispatchDisplayHotplugEvent(displayId, true);
+ // For hotplug reconnect, renew the registration since display modes have been reloaded.
+ mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector());
}
if (display->isVirtual()) {
@@ -3769,7 +3756,6 @@
if (display->isVirtual()) {
releaseVirtualDisplay(display->getVirtualId());
} else {
- dispatchDisplayHotplugEvent(display->getPhysicalId(), false);
mScheduler->unregisterDisplay(display->getPhysicalId());
}
}
@@ -4405,6 +4391,9 @@
/* workDuration */ activeRefreshRate.getPeriod(),
/* readyDuration */ configs.late.sfWorkDuration);
+ // Dispatch after EventThread creation, since registerDisplay above skipped dispatch.
+ mScheduler->dispatchHotplug(display->getPhysicalId(), scheduler::Scheduler::Hotplug::Connected);
+
mScheduler->initVsync(*mFrameTimeline->getTokenManager(), configs.late.sfWorkDuration);
mRegionSamplingThread =
@@ -4713,7 +4702,14 @@
return TransactionReadiness::NotReady;
}
- if (!mScheduler->isVsyncValid(expectedPresentTime, transaction.originUid)) {
+ const auto vsyncId = VsyncId{transaction.frameTimelineInfo.vsyncId};
+
+ // Transactions with VsyncId are already throttled by the vsyncId (i.e. Choreographer issued
+ // the vsyncId according to the frame rate override cadence) so we shouldn't throttle again
+ // when applying the transaction. Otherwise we might throttle older transactions
+ // incorrectly as the frame rate of SF changed before it drained the older transactions.
+ if (ftl::to_underlying(vsyncId) == FrameTimelineInfo::INVALID_VSYNC_ID &&
+ !mScheduler->isVsyncValid(expectedPresentTime, transaction.originUid)) {
ATRACE_FORMAT("!isVsyncValid expectedPresentTime: %" PRId64 " uid: %d", expectedPresentTime,
transaction.originUid);
return TransactionReadiness::NotReady;
@@ -4721,8 +4717,7 @@
// If the client didn't specify desiredPresentTime, use the vsyncId to determine the
// expected present time of this transaction.
- if (transaction.isAutoTimestamp &&
- frameIsEarly(expectedPresentTime, VsyncId{transaction.frameTimelineInfo.vsyncId})) {
+ if (transaction.isAutoTimestamp && frameIsEarly(expectedPresentTime, vsyncId)) {
ATRACE_FORMAT("frameIsEarly vsyncId: %" PRId64 " expectedPresentTime: %" PRId64,
transaction.frameTimelineInfo.vsyncId, expectedPresentTime);
return TransactionReadiness::NotReady;
@@ -8074,6 +8069,19 @@
args.allowProtected, args.grayscale, captureListener);
}
+bool SurfaceFlinger::layersHasProtectedLayer(
+ const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const {
+ bool protectedLayerFound = false;
+ for (auto& [_, layerFe] : layers) {
+ protectedLayerFound |=
+ (layerFe->mSnapshot->isVisible && layerFe->mSnapshot->hasProtectedContent);
+ if (protectedLayerFound) {
+ break;
+ }
+ }
+ return protectedLayerFound;
+}
+
void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
GetLayerSnapshotsFunction getLayerSnapshots,
ui::Size bufferSize, ui::PixelFormat reqPixelFormat,
@@ -8089,6 +8097,9 @@
return;
}
+ // Snapshots must be taken from the main thread.
+ auto layers = mScheduler->schedule([=]() { return getLayerSnapshots(); }).get();
+
// Loop over all visible layers to see whether there's any protected layer. A protected layer is
// typically a layer with DRM contents, or have the GRALLOC_USAGE_PROTECTED set on the buffer.
// A protected layer has no implication on whether it's secure, which is explicitly set by
@@ -8096,18 +8107,7 @@
const bool supportsProtected = getRenderEngine().supportsProtectedContent();
bool hasProtectedLayer = false;
if (allowProtected && supportsProtected) {
- hasProtectedLayer = mScheduler
- ->schedule([=]() {
- bool protectedLayerFound = false;
- auto layers = getLayerSnapshots();
- for (auto& [_, layerFe] : layers) {
- protectedLayerFound |=
- (layerFe->mSnapshot->isVisible &&
- layerFe->mSnapshot->hasProtectedContent);
- }
- return protectedLayerFound;
- })
- .get();
+ hasProtectedLayer = layersHasProtectedLayer(layers);
}
const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected;
const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER |
@@ -8132,52 +8132,53 @@
renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
renderengine::impl::ExternalTexture::Usage::
WRITEABLE);
- auto fence = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, texture,
- false /* regionSampling */, grayscale, isProtected,
- captureListener);
- fence.get();
+ auto futureFence =
+ captureScreenshot(std::move(renderAreaFuture), getLayerSnapshots, texture,
+ false /* regionSampling */, grayscale, isProtected, captureListener);
+ futureFence.get();
}
-ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon(
+ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot(
RenderAreaFuture renderAreaFuture, GetLayerSnapshotsFunction getLayerSnapshots,
const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener) {
ATRACE_CALL();
- auto future = mScheduler->schedule(
- [=, this, renderAreaFuture = std::move(renderAreaFuture)]() FTL_FAKE_GUARD(
- kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> {
- ScreenCaptureResults captureResults;
- std::shared_ptr<RenderArea> renderArea = renderAreaFuture.get();
- if (!renderArea) {
- ALOGW("Skipping screen capture because of invalid render area.");
- if (captureListener) {
- captureResults.fenceResult = base::unexpected(NO_MEMORY);
+ auto takeScreenshotFn = [=, this, renderAreaFuture = std::move(renderAreaFuture)]() REQUIRES(
+ kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> {
+ ScreenCaptureResults captureResults;
+ std::shared_ptr<RenderArea> renderArea = renderAreaFuture.get();
+ if (!renderArea) {
+ ALOGW("Skipping screen capture because of invalid render area.");
+ if (captureListener) {
+ captureResults.fenceResult = base::unexpected(NO_MEMORY);
+ captureListener->onScreenCaptureCompleted(captureResults);
+ }
+ return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share();
+ }
+
+ ftl::SharedFuture<FenceResult> renderFuture;
+ renderArea->render([&]() FTL_FAKE_GUARD(kMainThreadContext) {
+ renderFuture = renderScreenImpl(renderArea, getLayerSnapshots, buffer, regionSampling,
+ grayscale, isProtected, captureResults);
+ });
+
+ if (captureListener) {
+ // Defer blocking on renderFuture back to the Binder thread.
+ return ftl::Future(std::move(renderFuture))
+ .then([captureListener, captureResults = std::move(captureResults)](
+ FenceResult fenceResult) mutable -> FenceResult {
+ captureResults.fenceResult = std::move(fenceResult);
captureListener->onScreenCaptureCompleted(captureResults);
- }
- return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share();
- }
+ return base::unexpected(NO_ERROR);
+ })
+ .share();
+ }
+ return renderFuture;
+ };
- ftl::SharedFuture<FenceResult> renderFuture;
- renderArea->render([&]() FTL_FAKE_GUARD(kMainThreadContext) {
- renderFuture =
- renderScreenImpl(renderArea, getLayerSnapshots, buffer, regionSampling,
- grayscale, isProtected, captureResults);
- });
-
- if (captureListener) {
- // Defer blocking on renderFuture back to the Binder thread.
- return ftl::Future(std::move(renderFuture))
- .then([captureListener, captureResults = std::move(captureResults)](
- FenceResult fenceResult) mutable -> FenceResult {
- captureResults.fenceResult = std::move(fenceResult);
- captureListener->onScreenCaptureCompleted(captureResults);
- return base::unexpected(NO_ERROR);
- })
- .share();
- }
- return renderFuture;
- });
+ auto future =
+ mScheduler->schedule(FTL_FAKE_GUARD(kMainThreadContext, std::move(takeScreenshotFn)));
// Flatten nested futures.
auto chain = ftl::Future(std::move(future)).then([](ftl::SharedFuture<FenceResult> future) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index bada829..1ce8606 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -874,13 +874,17 @@
// Boot animation, on/off animations and screen capture
void startBootAnim();
+ bool layersHasProtectedLayer(const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const;
+
void captureScreenCommon(RenderAreaFuture, GetLayerSnapshotsFunction, ui::Size bufferSize,
ui::PixelFormat, bool allowProtected, bool grayscale,
const sp<IScreenCaptureListener>&);
- ftl::SharedFuture<FenceResult> captureScreenCommon(
+
+ ftl::SharedFuture<FenceResult> captureScreenshot(
RenderAreaFuture, GetLayerSnapshotsFunction,
const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
bool grayscale, bool isProtected, const sp<IScreenCaptureListener>&);
+
ftl::SharedFuture<FenceResult> renderScreenImpl(
std::shared_ptr<const RenderArea>, GetLayerSnapshotsFunction,
const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
@@ -1050,7 +1054,6 @@
const DisplayDeviceState& drawingState)
REQUIRES(mStateLock, kMainThreadContext);
- void dispatchDisplayHotplugEvent(PhysicalDisplayId, bool connected);
void dispatchDisplayModeChangeEvent(PhysicalDisplayId, const scheduler::FrameRateMode&)
REQUIRES(mStateLock);
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
index f7adc0e..b7f06a9 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -131,6 +131,7 @@
DUMP_READ_ONLY_FLAG(renderable_buffer_usage);
DUMP_READ_ONLY_FLAG(restore_blur_step);
DUMP_READ_ONLY_FLAG(dont_skip_on_early_ro);
+ DUMP_READ_ONLY_FLAG(protected_if_client);
#undef DUMP_READ_ONLY_FLAG
#undef DUMP_SERVER_FLAG
#undef DUMP_FLAG_INTERVAL
@@ -210,6 +211,7 @@
FLAG_MANAGER_READ_ONLY_FLAG(renderable_buffer_usage, "")
FLAG_MANAGER_READ_ONLY_FLAG(restore_blur_step, "debug.renderengine.restore_blur_step")
FLAG_MANAGER_READ_ONLY_FLAG(dont_skip_on_early_ro, "")
+FLAG_MANAGER_READ_ONLY_FLAG(protected_if_client, "")
/// Trunk stable server flags ///
FLAG_MANAGER_SERVER_FLAG(refresh_rate_overlay_on_external_display, "")
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
index 18f623f..241c814 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -71,6 +71,7 @@
bool renderable_buffer_usage() const;
bool restore_blur_step() const;
bool dont_skip_on_early_ro() const;
+ bool protected_if_client() const;
protected:
// overridden for unit tests
diff --git a/services/surfaceflinger/surfaceflinger_flags.aconfig b/services/surfaceflinger/surfaceflinger_flags.aconfig
index f5ec1ee..eda0674 100644
--- a/services/surfaceflinger/surfaceflinger_flags.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags.aconfig
@@ -194,3 +194,14 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "protected_if_client"
+ namespace: "core_graphics"
+ description: "Only set the RenderSurface to protected if protected layers are in client composition."
+ bug: "307674749"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 10e2220..049b092 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -25,6 +25,7 @@
#include "Scheduler/EventThread.h"
#include "Scheduler/RefreshRateSelector.h"
#include "Scheduler/VSyncPredictor.h"
+#include "Scheduler/VSyncReactor.h"
#include "TestableScheduler.h"
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockDisplayMode.h"
@@ -563,7 +564,8 @@
hal::VrrConfig{.minFrameIntervalNs = static_cast<int32_t>(
frameRate.getPeriodNsecs())}));
std::shared_ptr<VSyncPredictor> vrrTracker =
- std::make_shared<VSyncPredictor>(kMode, kHistorySize, kMinimumSamplesForPrediction,
+ std::make_shared<VSyncPredictor>(std::make_unique<SystemClock>(), kMode, kHistorySize,
+ kMinimumSamplesForPrediction,
kOutlierTolerancePercent);
std::shared_ptr<RefreshRateSelector> vrrSelectorPtr =
std::make_shared<RefreshRateSelector>(makeModes(kMode), kMode->getId());
@@ -578,6 +580,8 @@
vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate);
scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate);
vrrTracker->addVsyncTimestamp(0);
+ // Set 1000 as vsync seq #0
+ vrrTracker->nextAnticipatedVSyncTimeFrom(700);
EXPECT_EQ(Fps::fromPeriodNsecs(1000),
scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
@@ -587,7 +591,7 @@
TimePoint::fromNs(2000)));
// Not crossing the min frame period
- EXPECT_EQ(Fps::fromPeriodNsecs(1500),
+ EXPECT_EQ(Fps::fromPeriodNsecs(1000),
scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
TimePoint::fromNs(2500)));
// Change render rate
@@ -595,6 +599,9 @@
vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate);
scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate);
+ // Set 2000 as vsync seq #0
+ vrrTracker->nextAnticipatedVSyncTimeFrom(1700);
+
EXPECT_EQ(Fps::fromPeriodNsecs(2000),
scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
TimePoint::fromNs(2000)));
diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
index d891008..c22deab 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
@@ -48,7 +48,7 @@
Period minFramePeriod() const final { return Period::fromNs(currentPeriod()); }
void resetModel() final {}
bool needsMoreSamples() const final { return false; }
- bool isVSyncInPhase(nsecs_t, Fps) const final { return false; }
+ bool isVSyncInPhase(nsecs_t, Fps) final { return false; }
void setDisplayModePtr(ftl::NonNull<DisplayModePtr>) final {}
void setRenderRate(Fps) final {}
void onFrameBegin(TimePoint, TimePoint) final {}
@@ -64,7 +64,7 @@
public:
FixedRateIdealStubTracker() : StubTracker{toNs(3ms)} {}
- nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint, std::optional<nsecs_t>) const final {
+ nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint, std::optional<nsecs_t>) final {
auto const floor = timePoint % mPeriod;
if (floor == 0) {
return timePoint;
@@ -77,7 +77,7 @@
public:
VRRStubTracker(nsecs_t period) : StubTracker(period) {}
- nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t time_point, std::optional<nsecs_t>) const final {
+ nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t time_point, std::optional<nsecs_t>) final {
std::lock_guard lock(mMutex);
auto const normalized_to_base = time_point - mBase;
auto const floor = (normalized_to_base) % mPeriod;
diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
index b9f3d70..6b9ea56 100644
--- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
@@ -75,6 +75,28 @@
return ftl::as_non_null(createDisplayMode(DisplayModeId(0), refreshRate, kGroup, kResolution,
DEFAULT_DISPLAY_ID));
}
+
+class TestClock : public Clock {
+public:
+ TestClock() = default;
+
+ nsecs_t now() const override { return mNow; }
+ void setNow(nsecs_t now) { mNow = now; }
+
+private:
+ nsecs_t mNow = 0;
+};
+
+class ClockWrapper : public Clock {
+public:
+ ClockWrapper(std::shared_ptr<Clock> const& clock) : mClock(clock) {}
+
+ nsecs_t now() const { return mClock->now(); }
+
+private:
+ std::shared_ptr<Clock> const mClock;
+};
+
} // namespace
struct VSyncPredictorTest : testing::Test {
@@ -86,8 +108,10 @@
static constexpr size_t kOutlierTolerancePercent = 25;
static constexpr nsecs_t mMaxRoundingError = 100;
- VSyncPredictor tracker{mMode, kHistorySize, kMinimumSamplesForPrediction,
- kOutlierTolerancePercent};
+ std::shared_ptr<TestClock> mClock{std::make_shared<TestClock>()};
+
+ VSyncPredictor tracker{std::make_unique<ClockWrapper>(mClock), mMode, kHistorySize,
+ kMinimumSamplesForPrediction, kOutlierTolerancePercent};
};
TEST_F(VSyncPredictorTest, reportsAnticipatedPeriod) {
@@ -408,7 +432,8 @@
// See b/151146131
TEST_F(VSyncPredictorTest, hasEnoughPrecision) {
const auto mode = displayMode(mPeriod);
- VSyncPredictor tracker{mode, 20, kMinimumSamplesForPrediction, kOutlierTolerancePercent};
+ VSyncPredictor tracker{std::make_unique<ClockWrapper>(mClock), mode, 20,
+ kMinimumSamplesForPrediction, kOutlierTolerancePercent};
std::vector<nsecs_t> const simulatedVsyncs{840873348817, 840890049444, 840906762675,
840923581635, 840940161584, 840956868096,
840973702473, 840990256277, 841007116851,
@@ -606,35 +631,6 @@
EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 5100), Eq(mNow + 7 * mPeriod));
}
-TEST_F(VSyncPredictorTest, setRenderRateOfDivisorIsInPhase) {
- auto last = mNow;
- for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
- EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(last + mPeriod));
- mNow += mPeriod;
- last = mNow;
- tracker.addVsyncTimestamp(mNow);
- }
-
- const auto refreshRate = Fps::fromPeriodNsecs(mPeriod);
-
- tracker.setRenderRate(refreshRate / 4);
- EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + 3 * mPeriod));
- EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 3 * mPeriod), Eq(mNow + 7 * mPeriod));
- EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 7 * mPeriod), Eq(mNow + 11 * mPeriod));
-
- tracker.setRenderRate(refreshRate / 2);
- EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + 1 * mPeriod));
- EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 1 * mPeriod), Eq(mNow + 3 * mPeriod));
- EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 3 * mPeriod), Eq(mNow + 5 * mPeriod));
- EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 5 * mPeriod), Eq(mNow + 7 * mPeriod));
- EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 7 * mPeriod), Eq(mNow + 9 * mPeriod));
- EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 9 * mPeriod), Eq(mNow + 11 * mPeriod));
-
- tracker.setRenderRate(refreshRate / 6);
- EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + 1 * mPeriod));
- EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 1 * mPeriod), Eq(mNow + 7 * mPeriod));
-}
-
TEST_F(VSyncPredictorTest, setRenderRateIsIgnoredIfNotDivisor) {
auto last = mNow;
for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
@@ -670,8 +666,8 @@
.setVrrConfig(std::move(vrrConfig))
.build());
- VSyncPredictor vrrTracker{kMode, kHistorySize, kMinimumSamplesForPrediction,
- kOutlierTolerancePercent};
+ VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
+ kMinimumSamplesForPrediction, kOutlierTolerancePercent};
vrrTracker.setRenderRate(minFrameRate);
vrrTracker.addVsyncTimestamp(0);
@@ -687,7 +683,44 @@
vrrTracker.onFrameMissed(TimePoint::fromNs(4500));
EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4500, 4500));
EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
+
+ vrrTracker.onFrameBegin(TimePoint::fromNs(7000), TimePoint::fromNs(6500));
+ EXPECT_EQ(10500, vrrTracker.nextAnticipatedVSyncTimeFrom(9000, 7000));
}
+
+TEST_F(VSyncPredictorTest, renderRateIsPreservedForCommittedVsyncs) {
+ tracker.addVsyncTimestamp(1000);
+
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(1000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(5001), Eq(6000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(6001), Eq(7000));
+
+ tracker.setRenderRate(Fps::fromPeriodNsecs(2000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(1000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(5001), Eq(6000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(6001), Eq(7000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(7001), Eq(8000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(8001), Eq(10000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(9001), Eq(10000));
+
+ tracker.setRenderRate(Fps::fromPeriodNsecs(3000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(1000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(5001), Eq(6000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(6001), Eq(7000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(7001), Eq(8000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(8001), Eq(10000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(9001), Eq(10000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(10001), Eq(11000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(11001), Eq(14000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(12001), Eq(14000));
+
+ // Check the purge logic works
+ mClock->setNow(20000);
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(2000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(5001), Eq(8000));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(6001), Eq(8000));
+}
+
} // namespace android::scheduler
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/unittests/mock/MockVSyncTracker.h b/services/surfaceflinger/tests/unittests/mock/MockVSyncTracker.h
index 3870983..6d10a5c 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockVSyncTracker.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockVSyncTracker.h
@@ -29,12 +29,12 @@
MOCK_METHOD(bool, addVsyncTimestamp, (nsecs_t), (override));
MOCK_METHOD(nsecs_t, nextAnticipatedVSyncTimeFrom, (nsecs_t, std::optional<nsecs_t>),
- (const, override));
+ (override));
MOCK_METHOD(nsecs_t, currentPeriod, (), (const, override));
MOCK_METHOD(Period, minFramePeriod, (), (const, override));
MOCK_METHOD(void, resetModel, (), (override));
MOCK_METHOD(bool, needsMoreSamples, (), (const, override));
- MOCK_METHOD(bool, isVSyncInPhase, (nsecs_t, Fps), (const, override));
+ MOCK_METHOD(bool, isVSyncInPhase, (nsecs_t, Fps), (override));
MOCK_METHOD(void, setDisplayModePtr, (ftl::NonNull<DisplayModePtr>), (override));
MOCK_METHOD(void, setRenderRate, (Fps), (override));
MOCK_METHOD(void, onFrameBegin, (TimePoint, TimePoint), (override));
diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp
index 63ecaec..f10ba44 100644
--- a/services/vibratorservice/VibratorHalWrapper.cpp
+++ b/services/vibratorservice/VibratorHalWrapper.cpp
@@ -56,75 +56,6 @@
// -------------------------------------------------------------------------------------------------
-const constexpr char* STATUS_T_ERROR_MESSAGE_PREFIX = "status_t = ";
-const constexpr char* STATUS_V_1_0_ERROR_MESSAGE_PREFIX =
- "android::hardware::vibrator::V1_0::Status = ";
-
-template <typename T>
-HalResult<T> HalResult<T>::fromStatus(V1_0::Status status, T data) {
- switch (status) {
- case V1_0::Status::OK:
- return HalResult<T>::ok(data);
- case V1_0::Status::UNSUPPORTED_OPERATION:
- return HalResult<T>::unsupported();
- default:
- return HalResult<T>::failed(STATUS_V_1_0_ERROR_MESSAGE_PREFIX + toString(status));
- }
-}
-
-template <typename T>
-template <typename R>
-HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, T data) {
- return ret.isOk() ? HalResult<T>::ok(data) : HalResult<T>::failed(ret.description());
-}
-
-template <typename T>
-template <typename R>
-HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, V1_0::Status status, T data) {
- return ret.isOk() ? HalResult<T>::fromStatus(status, data)
- : HalResult<T>::failed(ret.description());
-}
-
-// -------------------------------------------------------------------------------------------------
-
-HalResult<void> HalResult<void>::fromStatus(status_t status) {
- if (status == android::OK) {
- return HalResult<void>::ok();
- }
- return HalResult<void>::failed(STATUS_T_ERROR_MESSAGE_PREFIX + statusToString(status));
-}
-
-HalResult<void> HalResult<void>::fromStatus(binder::Status status) {
- if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION ||
- status.transactionError() == android::UNKNOWN_TRANSACTION) {
- // UNKNOWN_TRANSACTION means the HAL implementation is an older version, so this is
- // the same as the operation being unsupported by this HAL. Should not retry.
- return HalResult<void>::unsupported();
- }
- if (status.isOk()) {
- return HalResult<void>::ok();
- }
- return HalResult<void>::failed(std::string(status.toString8().c_str()));
-}
-
-HalResult<void> HalResult<void>::fromStatus(V1_0::Status status) {
- switch (status) {
- case V1_0::Status::OK:
- return HalResult<void>::ok();
- case V1_0::Status::UNSUPPORTED_OPERATION:
- return HalResult<void>::unsupported();
- default:
- return HalResult<void>::failed(STATUS_V_1_0_ERROR_MESSAGE_PREFIX + toString(status));
- }
-}
-
-template <typename R>
-HalResult<void> HalResult<void>::fromReturn(hardware::Return<R>& ret) {
- return ret.isOk() ? HalResult<void>::ok() : HalResult<void>::failed(ret.description());
-}
-
-// -------------------------------------------------------------------------------------------------
-
Info HalWrapper::getInfo() {
getCapabilities();
getPrimitiveDurations();
@@ -269,7 +200,7 @@
// -------------------------------------------------------------------------------------------------
HalResult<void> AidlHalWrapper::ping() {
- return HalResult<void>::fromStatus(IInterface::asBinder(getHal())->pingBinder());
+ return HalResultFactory::fromStatus(IInterface::asBinder(getHal())->pingBinder());
}
void AidlHalWrapper::tryReconnect() {
@@ -291,7 +222,7 @@
static_cast<int32_t>(capabilities.value() & Capabilities::ON_CALLBACK);
auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr;
- auto ret = HalResult<void>::fromStatus(getHal()->on(timeout.count(), cb));
+ auto ret = HalResultFactory::fromStatus(getHal()->on(timeout.count(), cb));
if (!supportsCallback && ret.isOk()) {
mCallbackScheduler->schedule(completionCallback, timeout);
}
@@ -300,23 +231,23 @@
}
HalResult<void> AidlHalWrapper::off() {
- return HalResult<void>::fromStatus(getHal()->off());
+ return HalResultFactory::fromStatus(getHal()->off());
}
HalResult<void> AidlHalWrapper::setAmplitude(float amplitude) {
- return HalResult<void>::fromStatus(getHal()->setAmplitude(amplitude));
+ return HalResultFactory::fromStatus(getHal()->setAmplitude(amplitude));
}
HalResult<void> AidlHalWrapper::setExternalControl(bool enabled) {
- return HalResult<void>::fromStatus(getHal()->setExternalControl(enabled));
+ return HalResultFactory::fromStatus(getHal()->setExternalControl(enabled));
}
HalResult<void> AidlHalWrapper::alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) {
- return HalResult<void>::fromStatus(getHal()->alwaysOnEnable(id, effect, strength));
+ return HalResultFactory::fromStatus(getHal()->alwaysOnEnable(id, effect, strength));
}
HalResult<void> AidlHalWrapper::alwaysOnDisable(int32_t id) {
- return HalResult<void>::fromStatus(getHal()->alwaysOnDisable(id));
+ return HalResultFactory::fromStatus(getHal()->alwaysOnDisable(id));
}
HalResult<milliseconds> AidlHalWrapper::performEffect(
@@ -330,7 +261,7 @@
auto result = getHal()->perform(effect, strength, cb, &lengthMs);
milliseconds length = milliseconds(lengthMs);
- auto ret = HalResult<milliseconds>::fromStatus(result, length);
+ auto ret = HalResultFactory::fromStatus<milliseconds>(result, length);
if (!supportsCallback && ret.isOk()) {
mCallbackScheduler->schedule(completionCallback, length);
}
@@ -357,38 +288,40 @@
duration += milliseconds(effect.delayMs);
}
- return HalResult<milliseconds>::fromStatus(getHal()->compose(primitives, cb), duration);
+ return HalResultFactory::fromStatus<milliseconds>(getHal()->compose(primitives, cb), duration);
}
HalResult<void> AidlHalWrapper::performPwleEffect(const std::vector<PrimitivePwle>& primitives,
const std::function<void()>& completionCallback) {
// This method should always support callbacks, so no need to double check.
auto cb = new HalCallbackWrapper(completionCallback);
- return HalResult<void>::fromStatus(getHal()->composePwle(primitives, cb));
+ return HalResultFactory::fromStatus(getHal()->composePwle(primitives, cb));
}
HalResult<Capabilities> AidlHalWrapper::getCapabilitiesInternal() {
int32_t capabilities = 0;
auto result = getHal()->getCapabilities(&capabilities);
- return HalResult<Capabilities>::fromStatus(result, static_cast<Capabilities>(capabilities));
+ return HalResultFactory::fromStatus<Capabilities>(result,
+ static_cast<Capabilities>(capabilities));
}
HalResult<std::vector<Effect>> AidlHalWrapper::getSupportedEffectsInternal() {
std::vector<Effect> supportedEffects;
auto result = getHal()->getSupportedEffects(&supportedEffects);
- return HalResult<std::vector<Effect>>::fromStatus(result, supportedEffects);
+ return HalResultFactory::fromStatus<std::vector<Effect>>(result, supportedEffects);
}
HalResult<std::vector<Braking>> AidlHalWrapper::getSupportedBrakingInternal() {
std::vector<Braking> supportedBraking;
auto result = getHal()->getSupportedBraking(&supportedBraking);
- return HalResult<std::vector<Braking>>::fromStatus(result, supportedBraking);
+ return HalResultFactory::fromStatus<std::vector<Braking>>(result, supportedBraking);
}
HalResult<std::vector<CompositePrimitive>> AidlHalWrapper::getSupportedPrimitivesInternal() {
std::vector<CompositePrimitive> supportedPrimitives;
auto result = getHal()->getSupportedPrimitives(&supportedPrimitives);
- return HalResult<std::vector<CompositePrimitive>>::fromStatus(result, supportedPrimitives);
+ return HalResultFactory::fromStatus<std::vector<CompositePrimitive>>(result,
+ supportedPrimitives);
}
HalResult<std::vector<milliseconds>> AidlHalWrapper::getPrimitiveDurationsInternal(
@@ -408,7 +341,7 @@
}
int32_t duration = 0;
auto result = getHal()->getPrimitiveDuration(primitive, &duration);
- auto halResult = HalResult<int32_t>::fromStatus(result, duration);
+ auto halResult = HalResultFactory::fromStatus<int32_t>(result, duration);
if (halResult.isUnsupported()) {
// Should not happen, supported primitives should always support requesting duration.
ALOGE("Supported primitive %zu returned unsupported for getPrimitiveDuration",
@@ -427,55 +360,55 @@
HalResult<milliseconds> AidlHalWrapper::getPrimitiveDelayMaxInternal() {
int32_t delay = 0;
auto result = getHal()->getCompositionDelayMax(&delay);
- return HalResult<milliseconds>::fromStatus(result, milliseconds(delay));
+ return HalResultFactory::fromStatus<milliseconds>(result, milliseconds(delay));
}
HalResult<milliseconds> AidlHalWrapper::getPrimitiveDurationMaxInternal() {
int32_t delay = 0;
auto result = getHal()->getPwlePrimitiveDurationMax(&delay);
- return HalResult<milliseconds>::fromStatus(result, milliseconds(delay));
+ return HalResultFactory::fromStatus<milliseconds>(result, milliseconds(delay));
}
HalResult<int32_t> AidlHalWrapper::getCompositionSizeMaxInternal() {
int32_t size = 0;
auto result = getHal()->getCompositionSizeMax(&size);
- return HalResult<int32_t>::fromStatus(result, size);
+ return HalResultFactory::fromStatus<int32_t>(result, size);
}
HalResult<int32_t> AidlHalWrapper::getPwleSizeMaxInternal() {
int32_t size = 0;
auto result = getHal()->getPwleCompositionSizeMax(&size);
- return HalResult<int32_t>::fromStatus(result, size);
+ return HalResultFactory::fromStatus<int32_t>(result, size);
}
HalResult<float> AidlHalWrapper::getMinFrequencyInternal() {
float minFrequency = 0;
auto result = getHal()->getFrequencyMinimum(&minFrequency);
- return HalResult<float>::fromStatus(result, minFrequency);
+ return HalResultFactory::fromStatus<float>(result, minFrequency);
}
HalResult<float> AidlHalWrapper::getResonantFrequencyInternal() {
float f0 = 0;
auto result = getHal()->getResonantFrequency(&f0);
- return HalResult<float>::fromStatus(result, f0);
+ return HalResultFactory::fromStatus<float>(result, f0);
}
HalResult<float> AidlHalWrapper::getFrequencyResolutionInternal() {
float frequencyResolution = 0;
auto result = getHal()->getFrequencyResolution(&frequencyResolution);
- return HalResult<float>::fromStatus(result, frequencyResolution);
+ return HalResultFactory::fromStatus<float>(result, frequencyResolution);
}
HalResult<float> AidlHalWrapper::getQFactorInternal() {
float qFactor = 0;
auto result = getHal()->getQFactor(&qFactor);
- return HalResult<float>::fromStatus(result, qFactor);
+ return HalResultFactory::fromStatus<float>(result, qFactor);
}
HalResult<std::vector<float>> AidlHalWrapper::getMaxAmplitudesInternal() {
std::vector<float> amplitudes;
auto result = getHal()->getBandwidthAmplitudeMap(&litudes);
- return HalResult<std::vector<float>>::fromStatus(result, amplitudes);
+ return HalResultFactory::fromStatus<std::vector<float>>(result, amplitudes);
}
sp<Aidl::IVibrator> AidlHalWrapper::getHal() {
@@ -488,7 +421,7 @@
template <typename I>
HalResult<void> HidlHalWrapper<I>::ping() {
auto result = getHal()->ping();
- return HalResult<void>::fromReturn(result);
+ return HalResultFactory::fromReturn(result);
}
template <typename I>
@@ -504,7 +437,7 @@
HalResult<void> HidlHalWrapper<I>::on(milliseconds timeout,
const std::function<void()>& completionCallback) {
auto result = getHal()->on(timeout.count());
- auto ret = HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
+ auto ret = HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
if (ret.isOk()) {
mCallbackScheduler->schedule(completionCallback, timeout);
}
@@ -514,14 +447,14 @@
template <typename I>
HalResult<void> HidlHalWrapper<I>::off() {
auto result = getHal()->off();
- return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
+ return HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
}
template <typename I>
HalResult<void> HidlHalWrapper<I>::setAmplitude(float amplitude) {
uint8_t amp = static_cast<uint8_t>(amplitude * std::numeric_limits<uint8_t>::max());
auto result = getHal()->setAmplitude(amp);
- return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
+ return HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
}
template <typename I>
@@ -547,7 +480,7 @@
hardware::Return<bool> result = getHal()->supportsAmplitudeControl();
Capabilities capabilities =
result.withDefault(false) ? Capabilities::AMPLITUDE_CONTROL : Capabilities::NONE;
- return HalResult<Capabilities>::fromReturn(result, capabilities);
+ return HalResultFactory::fromReturn<Capabilities>(result, capabilities);
}
template <typename I>
@@ -566,7 +499,7 @@
auto result = std::invoke(performFn, handle, effect, effectStrength, effectCallback);
milliseconds length = milliseconds(lengthMs);
- auto ret = HalResult<milliseconds>::fromReturn(result, status, length);
+ auto ret = HalResultFactory::fromReturn<milliseconds>(result, status, length);
if (ret.isOk()) {
mCallbackScheduler->schedule(completionCallback, length);
}
@@ -638,7 +571,7 @@
HalResult<void> HidlHalWrapperV1_3::setExternalControl(bool enabled) {
auto result = getHal()->setExternalControl(static_cast<uint32_t>(enabled));
- return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
+ return HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
}
HalResult<milliseconds> HidlHalWrapperV1_3::performEffect(
@@ -671,7 +604,7 @@
sp<V1_3::IVibrator> hal = getHal();
auto amplitudeResult = hal->supportsAmplitudeControl();
if (!amplitudeResult.isOk()) {
- return HalResult<Capabilities>::fromReturn(amplitudeResult, capabilities);
+ return HalResultFactory::fromReturn<Capabilities>(amplitudeResult, capabilities);
}
auto externalControlResult = hal->supportsExternalControl();
@@ -686,7 +619,7 @@
}
}
- return HalResult<Capabilities>::fromReturn(externalControlResult, capabilities);
+ return HalResultFactory::fromReturn<Capabilities>(externalControlResult, capabilities);
}
// -------------------------------------------------------------------------------------------------
diff --git a/services/vibratorservice/VibratorManagerHalController.cpp b/services/vibratorservice/VibratorManagerHalController.cpp
index 0df0bfa..aa5b7fc 100644
--- a/services/vibratorservice/VibratorManagerHalController.cpp
+++ b/services/vibratorservice/VibratorManagerHalController.cpp
@@ -46,8 +46,6 @@
HalResult<T> ManagerHalController::processHalResult(HalResult<T> result, const char* functionName) {
if (result.isFailed()) {
ALOGE("VibratorManager HAL %s failed: %s", functionName, result.errorMessage());
- std::lock_guard<std::mutex> lock(mConnectedHalMutex);
- mConnectedHal->tryReconnect();
}
return result;
}
@@ -70,12 +68,16 @@
hal = mConnectedHal;
}
- HalResult<T> ret = processHalResult(halFn(hal), functionName);
- for (int i = 0; i < MAX_RETRIES && ret.isFailed(); i++) {
- ret = processHalResult(halFn(hal), functionName);
+ HalResult<T> result = processHalResult(halFn(hal), functionName);
+ for (int i = 0; i < MAX_RETRIES && result.shouldRetry(); i++) {
+ {
+ std::lock_guard<std::mutex> lock(mConnectedHalMutex);
+ mConnectedHal->tryReconnect();
+ }
+ result = processHalResult(halFn(hal), functionName);
}
- return ret;
+ return result;
}
// -------------------------------------------------------------------------------------------------
diff --git a/services/vibratorservice/VibratorManagerHalWrapper.cpp b/services/vibratorservice/VibratorManagerHalWrapper.cpp
index 6e660e7..1341266 100644
--- a/services/vibratorservice/VibratorManagerHalWrapper.cpp
+++ b/services/vibratorservice/VibratorManagerHalWrapper.cpp
@@ -55,8 +55,8 @@
return HalResult<std::shared_ptr<HalController>>::ok(mController);
}
// Controller.init did not connect to any vibrator HAL service, so the device has no vibrator.
- return HalResult<std::shared_ptr<HalController>>::failed(MISSING_VIBRATOR_MESSAGE_PREFIX +
- std::to_string(id));
+ return HalResult<std::shared_ptr<HalController>>::failed(
+ (MISSING_VIBRATOR_MESSAGE_PREFIX + std::to_string(id)).c_str());
}
HalResult<void> LegacyManagerHalWrapper::prepareSynced(const std::vector<int32_t>&) {
@@ -75,10 +75,10 @@
std::shared_ptr<HalWrapper> AidlManagerHalWrapper::connectToVibrator(
int32_t vibratorId, std::shared_ptr<CallbackScheduler> callbackScheduler) {
- std::function<HalResult<sp<Aidl::IVibrator>>()> reconnectFn = [=]() {
+ std::function<HalResult<sp<Aidl::IVibrator>>()> reconnectFn = [=, this]() {
sp<Aidl::IVibrator> vibrator;
auto result = this->getHal()->getVibrator(vibratorId, &vibrator);
- return HalResult<sp<Aidl::IVibrator>>::fromStatus(result, vibrator);
+ return HalResultFactory::fromStatus<sp<Aidl::IVibrator>>(result, vibrator);
};
auto result = reconnectFn();
if (!result.isOk()) {
@@ -88,12 +88,12 @@
if (!vibrator) {
return nullptr;
}
- return std::move(std::make_unique<AidlHalWrapper>(std::move(callbackScheduler),
- std::move(vibrator), reconnectFn));
+ return std::make_unique<AidlHalWrapper>(std::move(callbackScheduler), std::move(vibrator),
+ reconnectFn);
}
HalResult<void> AidlManagerHalWrapper::ping() {
- return HalResult<void>::fromStatus(IInterface::asBinder(getHal())->pingBinder());
+ return HalResultFactory::fromStatus(IInterface::asBinder(getHal())->pingBinder());
}
void AidlManagerHalWrapper::tryReconnect() {
@@ -112,8 +112,8 @@
}
int32_t cap = 0;
auto result = getHal()->getCapabilities(&cap);
- auto ret = HalResult<ManagerCapabilities>::fromStatus(result,
- static_cast<ManagerCapabilities>(cap));
+ auto capabilities = static_cast<ManagerCapabilities>(cap);
+ auto ret = HalResultFactory::fromStatus<ManagerCapabilities>(result, capabilities);
if (ret.isOk()) {
// Cache copy of returned value.
mCapabilities.emplace(ret.value());
@@ -129,7 +129,7 @@
}
std::vector<int32_t> ids;
auto result = getHal()->getVibratorIds(&ids);
- auto ret = HalResult<std::vector<int32_t>>::fromStatus(result, ids);
+ auto ret = HalResultFactory::fromStatus<std::vector<int32_t>>(result, ids);
if (ret.isOk()) {
// Cache copy of returned value and the individual controllers.
mVibratorIds.emplace(ret.value());
@@ -152,12 +152,12 @@
if (it != mVibrators.end()) {
return HalResult<std::shared_ptr<HalController>>::ok(it->second);
}
- return HalResult<std::shared_ptr<HalController>>::failed(MISSING_VIBRATOR_MESSAGE_PREFIX +
- std::to_string(id));
+ return HalResult<std::shared_ptr<HalController>>::failed(
+ (MISSING_VIBRATOR_MESSAGE_PREFIX + std::to_string(id)).c_str());
}
HalResult<void> AidlManagerHalWrapper::prepareSynced(const std::vector<int32_t>& ids) {
- auto ret = HalResult<void>::fromStatus(getHal()->prepareSynced(ids));
+ auto ret = HalResultFactory::fromStatus(getHal()->prepareSynced(ids));
if (ret.isOk()) {
// Force reload of all vibrator controllers that were prepared for a sync operation here.
// This will trigger calls to getVibrator(id) on each controller, so they can use the
@@ -179,11 +179,11 @@
bool supportsCallback = capabilities.isOk() &&
static_cast<int32_t>(capabilities.value() & ManagerCapabilities::TRIGGER_CALLBACK);
auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr;
- return HalResult<void>::fromStatus(getHal()->triggerSynced(cb));
+ return HalResultFactory::fromStatus(getHal()->triggerSynced(cb));
}
HalResult<void> AidlManagerHalWrapper::cancelSynced() {
- auto ret = HalResult<void>::fromStatus(getHal()->cancelSynced());
+ auto ret = HalResultFactory::fromStatus(getHal()->cancelSynced());
if (ret.isOk()) {
// Force reload of all vibrator controllers that were prepared for a sync operation before.
// This will trigger calls to getVibrator(id) on each controller, so they can use the
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalController.h b/services/vibratorservice/include/vibratorservice/VibratorHalController.h
index 6b73d17..f97442d 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalController.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalController.h
@@ -64,7 +64,29 @@
*/
Info getInfo() {
static Info sDefaultInfo = InfoCache().get();
- return apply<Info>([](HalWrapper* hal) { return hal->getInfo(); }, sDefaultInfo, "getInfo");
+ if (!init()) {
+ ALOGV("Skipped getInfo because Vibrator HAL is not available");
+ return sDefaultInfo;
+ }
+ std::shared_ptr<HalWrapper> hal;
+ {
+ std::lock_guard<std::mutex> lock(mConnectedHalMutex);
+ hal = mConnectedHal;
+ }
+
+ for (int i = 0; i < MAX_RETRIES; i++) {
+ Info result = hal.get()->getInfo();
+ result.logFailures();
+ if (result.shouldRetry()) {
+ tryReconnect();
+ } else {
+ return result;
+ }
+ }
+
+ Info result = hal.get()->getInfo();
+ result.logFailures();
+ return result;
}
/* Calls given HAL function, applying automatic retries to reconnect with the HAL when the
@@ -72,7 +94,7 @@
*/
template <typename T>
HalResult<T> doWithRetry(const HalFunction<HalResult<T>>& halFn, const char* functionName) {
- return apply(halFn, HalResult<T>::unsupported(), functionName);
+ return doWithRetry<T>(halFn, HalResult<T>::unsupported(), functionName);
}
private:
@@ -90,7 +112,8 @@
* function name is for logging purposes.
*/
template <typename T>
- T apply(const HalFunction<T>& halFn, T defaultValue, const char* functionName) {
+ HalResult<T> doWithRetry(const HalFunction<HalResult<T>>& halFn, HalResult<T> defaultValue,
+ const char* functionName) {
if (!init()) {
ALOGV("Skipped %s because Vibrator HAL is not available", functionName);
return defaultValue;
@@ -101,16 +124,22 @@
hal = mConnectedHal;
}
- for (int i = 0; i < MAX_RETRIES; i++) {
- T result = halFn(hal.get());
- if (result.isFailedLogged(functionName)) {
- tryReconnect();
- } else {
- return result;
- }
+ HalResult<T> result = doOnce(hal.get(), halFn, functionName);
+ for (int i = 0; i < MAX_RETRIES && result.shouldRetry(); i++) {
+ tryReconnect();
+ result = doOnce(hal.get(), halFn, functionName);
}
+ return result;
+ }
- return halFn(hal.get());
+ template <typename T>
+ HalResult<T> doOnce(HalWrapper* hal, const HalFunction<HalResult<T>>& halFn,
+ const char* functionName) {
+ HalResult<T> result = halFn(hal);
+ if (result.isFailed()) {
+ ALOGE("Vibrator HAL %s failed: %s", functionName, result.errorMessage());
+ }
+ return result;
}
};
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
index d2cc9ad..39c4eb4 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
@@ -31,101 +31,154 @@
// -------------------------------------------------------------------------------------------------
+// Base class to represent a generic result of a call to the Vibrator HAL wrapper.
+class BaseHalResult {
+public:
+ bool isOk() const { return mStatus == SUCCESS; }
+ bool isFailed() const { return mStatus == FAILED; }
+ bool isUnsupported() const { return mStatus == UNSUPPORTED; }
+ bool shouldRetry() const { return isFailed() && mDeadObject; }
+ const char* errorMessage() const { return mErrorMessage.c_str(); }
+
+protected:
+ enum Status { SUCCESS, UNSUPPORTED, FAILED };
+ Status mStatus;
+ std::string mErrorMessage;
+ bool mDeadObject;
+
+ explicit BaseHalResult(Status status, const char* errorMessage = "", bool deadObject = false)
+ : mStatus(status), mErrorMessage(errorMessage), mDeadObject(deadObject) {}
+ virtual ~BaseHalResult() = default;
+};
+
// Result of a call to the Vibrator HAL wrapper, holding data if successful.
template <typename T>
-class HalResult {
+class HalResult : public BaseHalResult {
public:
static HalResult<T> ok(T value) { return HalResult(value); }
- static HalResult<T> failed(std::string msg) {
- return HalResult(std::move(msg), /* unsupported= */ false);
+ static HalResult<T> unsupported() { return HalResult(Status::UNSUPPORTED); }
+ static HalResult<T> failed(const char* msg) { return HalResult(Status::FAILED, msg); }
+ static HalResult<T> transactionFailed(const char* msg) {
+ return HalResult(Status::FAILED, msg, /* deadObject= */ true);
}
- static HalResult<T> unsupported() { return HalResult("", /* unsupported= */ true); }
+ // This will throw std::bad_optional_access if this result is not ok.
+ const T& value() const { return mValue.value(); }
+ const T valueOr(T&& defaultValue) const { return mValue.value_or(defaultValue); }
+
+private:
+ std::optional<T> mValue;
+
+ explicit HalResult(T value)
+ : BaseHalResult(Status::SUCCESS), mValue(std::make_optional(value)) {}
+ explicit HalResult(Status status, const char* errorMessage = "", bool deadObject = false)
+ : BaseHalResult(status, errorMessage, deadObject), mValue() {}
+};
+
+// Empty result of a call to the Vibrator HAL wrapper.
+template <>
+class HalResult<void> : public BaseHalResult {
+public:
+ static HalResult<void> ok() { return HalResult(Status::SUCCESS); }
+ static HalResult<void> unsupported() { return HalResult(Status::UNSUPPORTED); }
+ static HalResult<void> failed(const char* msg) { return HalResult(Status::FAILED, msg); }
+ static HalResult<void> transactionFailed(const char* msg) {
+ return HalResult(Status::FAILED, msg, /* deadObject= */ true);
+ }
+
+private:
+ explicit HalResult(Status status, const char* errorMessage = "", bool deadObject = false)
+ : BaseHalResult(status, errorMessage, deadObject) {}
+};
+
+// -------------------------------------------------------------------------------------------------
+
+// Factory functions that convert failed HIDL/AIDL results into HalResult instances.
+// Implementation of static template functions needs to be in this header file for the linker.
+class HalResultFactory {
+public:
+ template <typename T>
static HalResult<T> fromStatus(binder::Status status, T data) {
+ return status.isOk() ? HalResult<T>::ok(data) : fromFailedStatus<T>(status);
+ }
+
+ template <typename T>
+ static HalResult<T> fromStatus(hardware::vibrator::V1_0::Status status, T data) {
+ return (status == hardware::vibrator::V1_0::Status::OK) ? HalResult<T>::ok(data)
+ : fromFailedStatus<T>(status);
+ }
+
+ template <typename T, typename R>
+ static HalResult<T> fromReturn(hardware::Return<R>& ret, T data) {
+ return ret.isOk() ? HalResult<T>::ok(data) : fromFailedReturn<T, R>(ret);
+ }
+
+ template <typename T, typename R>
+ static HalResult<T> fromReturn(hardware::Return<R>& ret,
+ hardware::vibrator::V1_0::Status status, T data) {
+ return ret.isOk() ? fromStatus<T>(status, data) : fromFailedReturn<T, R>(ret);
+ }
+
+ static HalResult<void> fromStatus(status_t status) {
+ return (status == android::OK) ? HalResult<void>::ok() : fromFailedStatus<void>(status);
+ }
+
+ static HalResult<void> fromStatus(binder::Status status) {
+ return status.isOk() ? HalResult<void>::ok() : fromFailedStatus<void>(status);
+ }
+
+ static HalResult<void> fromStatus(hardware::vibrator::V1_0::Status status) {
+ return (status == hardware::vibrator::V1_0::Status::OK) ? HalResult<void>::ok()
+ : fromFailedStatus<void>(status);
+ }
+
+ template <typename R>
+ static HalResult<void> fromReturn(hardware::Return<R>& ret) {
+ return ret.isOk() ? HalResult<void>::ok() : fromFailedReturn<void, R>(ret);
+ }
+
+private:
+ template <typename T>
+ static HalResult<T> fromFailedStatus(status_t status) {
+ auto msg = "status_t = " + statusToString(status);
+ return (status == android::DEAD_OBJECT) ? HalResult<T>::transactionFailed(msg.c_str())
+ : HalResult<T>::failed(msg.c_str());
+ }
+
+ template <typename T>
+ static HalResult<T> fromFailedStatus(binder::Status status) {
if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
// UNKNOWN_TRANSACTION means the HAL implementation is an older version, so this is
// the same as the operation being unsupported by this HAL. Should not retry.
return HalResult<T>::unsupported();
}
- if (status.isOk()) {
- return HalResult<T>::ok(data);
+ if (status.exceptionCode() == binder::Status::EX_TRANSACTION_FAILED) {
+ return HalResult<T>::transactionFailed(status.toString8().c_str());
}
return HalResult<T>::failed(status.toString8().c_str());
}
- static HalResult<T> fromStatus(hardware::vibrator::V1_0::Status status, T data);
- template <typename R>
- static HalResult<T> fromReturn(hardware::Return<R>& ret, T data);
-
- template <typename R>
- static HalResult<T> fromReturn(hardware::Return<R>& ret,
- hardware::vibrator::V1_0::Status status, T data);
-
- // This will throw std::bad_optional_access if this result is not ok.
- const T& value() const { return mValue.value(); }
- const T valueOr(T&& defaultValue) const { return mValue.value_or(defaultValue); }
- bool isOk() const { return !mUnsupported && mValue.has_value(); }
- bool isFailed() const { return !mUnsupported && !mValue.has_value(); }
- bool isUnsupported() const { return mUnsupported; }
- const char* errorMessage() const { return mErrorMessage.c_str(); }
- bool isFailedLogged(const char* functionNameForLogging) const {
- if (isFailed()) {
- ALOGE("Vibrator HAL %s failed: %s", functionNameForLogging, errorMessage());
- return true;
+ template <typename T>
+ static HalResult<T> fromFailedStatus(hardware::vibrator::V1_0::Status status) {
+ switch (status) {
+ case hardware::vibrator::V1_0::Status::UNSUPPORTED_OPERATION:
+ return HalResult<T>::unsupported();
+ default:
+ auto msg = "android::hardware::vibrator::V1_0::Status = " + toString(status);
+ return HalResult<T>::failed(msg.c_str());
}
- return false;
}
-private:
- std::optional<T> mValue;
- std::string mErrorMessage;
- bool mUnsupported;
-
- explicit HalResult(T value)
- : mValue(std::make_optional(value)), mErrorMessage(), mUnsupported(false) {}
- explicit HalResult(std::string errorMessage, bool unsupported)
- : mValue(), mErrorMessage(std::move(errorMessage)), mUnsupported(unsupported) {}
-};
-
-// Empty result of a call to the Vibrator HAL wrapper.
-template <>
-class HalResult<void> {
-public:
- static HalResult<void> ok() { return HalResult(); }
- static HalResult<void> failed(std::string msg) { return HalResult(std::move(msg)); }
- static HalResult<void> unsupported() { return HalResult(/* unsupported= */ true); }
-
- static HalResult<void> fromStatus(status_t status);
- static HalResult<void> fromStatus(binder::Status status);
- static HalResult<void> fromStatus(hardware::vibrator::V1_0::Status status);
-
- template <typename R>
- static HalResult<void> fromReturn(hardware::Return<R>& ret);
-
- bool isOk() const { return !mUnsupported && !mFailed; }
- bool isFailed() const { return !mUnsupported && mFailed; }
- bool isUnsupported() const { return mUnsupported; }
- const char* errorMessage() const { return mErrorMessage.c_str(); }
- bool isFailedLogged(const char* functionNameForLogging) const {
- if (isFailed()) {
- ALOGE("Vibrator HAL %s failed: %s", functionNameForLogging, errorMessage());
- return true;
- }
- return false;
+ template <typename T, typename R>
+ static HalResult<T> fromFailedReturn(hardware::Return<R>& ret) {
+ return ret.isDeadObject() ? HalResult<T>::transactionFailed(ret.description().c_str())
+ : HalResult<T>::failed(ret.description().c_str());
}
-
-private:
- std::string mErrorMessage;
- bool mFailed;
- bool mUnsupported;
-
- explicit HalResult(bool unsupported = false)
- : mErrorMessage(), mFailed(false), mUnsupported(unsupported) {}
- explicit HalResult(std::string errorMessage)
- : mErrorMessage(std::move(errorMessage)), mFailed(true), mUnsupported(false) {}
};
+// -------------------------------------------------------------------------------------------------
+
class HalCallbackWrapper : public hardware::vibrator::BnVibratorCallback {
public:
HalCallbackWrapper(std::function<void()> completionCallback)
@@ -192,21 +245,44 @@
const HalResult<float> qFactor;
const HalResult<std::vector<float>> maxAmplitudes;
- bool isFailedLogged(const char*) const {
- return capabilities.isFailedLogged("getCapabilities") ||
- supportedEffects.isFailedLogged("getSupportedEffects") ||
- supportedBraking.isFailedLogged("getSupportedBraking") ||
- supportedPrimitives.isFailedLogged("getSupportedPrimitives") ||
- primitiveDurations.isFailedLogged("getPrimitiveDuration") ||
- primitiveDelayMax.isFailedLogged("getPrimitiveDelayMax") ||
- pwlePrimitiveDurationMax.isFailedLogged("getPwlePrimitiveDurationMax") ||
- compositionSizeMax.isFailedLogged("getCompositionSizeMax") ||
- pwleSizeMax.isFailedLogged("getPwleSizeMax") ||
- minFrequency.isFailedLogged("getMinFrequency") ||
- resonantFrequency.isFailedLogged("getResonantFrequency") ||
- frequencyResolution.isFailedLogged("getFrequencyResolution") ||
- qFactor.isFailedLogged("getQFactor") ||
- maxAmplitudes.isFailedLogged("getMaxAmplitudes");
+ void logFailures() const {
+ logFailure<Capabilities>(capabilities, "getCapabilities");
+ logFailure<std::vector<hardware::vibrator::Effect>>(supportedEffects,
+ "getSupportedEffects");
+ logFailure<std::vector<hardware::vibrator::Braking>>(supportedBraking,
+ "getSupportedBraking");
+ logFailure<std::vector<hardware::vibrator::CompositePrimitive>>(supportedPrimitives,
+ "getSupportedPrimitives");
+ logFailure<std::vector<std::chrono::milliseconds>>(primitiveDurations,
+ "getPrimitiveDuration");
+ logFailure<std::chrono::milliseconds>(primitiveDelayMax, "getPrimitiveDelayMax");
+ logFailure<std::chrono::milliseconds>(pwlePrimitiveDurationMax,
+ "getPwlePrimitiveDurationMax");
+ logFailure<int32_t>(compositionSizeMax, "getCompositionSizeMax");
+ logFailure<int32_t>(pwleSizeMax, "getPwleSizeMax");
+ logFailure<float>(minFrequency, "getMinFrequency");
+ logFailure<float>(resonantFrequency, "getResonantFrequency");
+ logFailure<float>(frequencyResolution, "getFrequencyResolution");
+ logFailure<float>(qFactor, "getQFactor");
+ logFailure<std::vector<float>>(maxAmplitudes, "getMaxAmplitudes");
+ }
+
+ bool shouldRetry() const {
+ return capabilities.shouldRetry() || supportedEffects.shouldRetry() ||
+ supportedBraking.shouldRetry() || supportedPrimitives.shouldRetry() ||
+ primitiveDurations.shouldRetry() || primitiveDelayMax.shouldRetry() ||
+ pwlePrimitiveDurationMax.shouldRetry() || compositionSizeMax.shouldRetry() ||
+ pwleSizeMax.shouldRetry() || minFrequency.shouldRetry() ||
+ resonantFrequency.shouldRetry() || frequencyResolution.shouldRetry() ||
+ qFactor.shouldRetry() || maxAmplitudes.shouldRetry();
+ }
+
+private:
+ template <typename T>
+ void logFailure(HalResult<T> result, const char* functionName) const {
+ if (result.isFailed()) {
+ ALOGE("Vibrator HAL %s failed: %s", functionName, result.errorMessage());
+ }
}
};
@@ -230,27 +306,29 @@
}
private:
+ // Create a transaction failed results as default so we can retry on the first time we get them.
static const constexpr char* MSG = "never loaded";
- HalResult<Capabilities> mCapabilities = HalResult<Capabilities>::failed(MSG);
+ HalResult<Capabilities> mCapabilities = HalResult<Capabilities>::transactionFailed(MSG);
HalResult<std::vector<hardware::vibrator::Effect>> mSupportedEffects =
- HalResult<std::vector<hardware::vibrator::Effect>>::failed(MSG);
+ HalResult<std::vector<hardware::vibrator::Effect>>::transactionFailed(MSG);
HalResult<std::vector<hardware::vibrator::Braking>> mSupportedBraking =
- HalResult<std::vector<hardware::vibrator::Braking>>::failed(MSG);
+ HalResult<std::vector<hardware::vibrator::Braking>>::transactionFailed(MSG);
HalResult<std::vector<hardware::vibrator::CompositePrimitive>> mSupportedPrimitives =
- HalResult<std::vector<hardware::vibrator::CompositePrimitive>>::failed(MSG);
+ HalResult<std::vector<hardware::vibrator::CompositePrimitive>>::transactionFailed(MSG);
HalResult<std::vector<std::chrono::milliseconds>> mPrimitiveDurations =
- HalResult<std::vector<std::chrono::milliseconds>>::failed(MSG);
+ HalResult<std::vector<std::chrono::milliseconds>>::transactionFailed(MSG);
HalResult<std::chrono::milliseconds> mPrimitiveDelayMax =
- HalResult<std::chrono::milliseconds>::failed(MSG);
+ HalResult<std::chrono::milliseconds>::transactionFailed(MSG);
HalResult<std::chrono::milliseconds> mPwlePrimitiveDurationMax =
- HalResult<std::chrono::milliseconds>::failed(MSG);
- HalResult<int32_t> mCompositionSizeMax = HalResult<int>::failed(MSG);
- HalResult<int32_t> mPwleSizeMax = HalResult<int>::failed(MSG);
- HalResult<float> mMinFrequency = HalResult<float>::failed(MSG);
- HalResult<float> mResonantFrequency = HalResult<float>::failed(MSG);
- HalResult<float> mFrequencyResolution = HalResult<float>::failed(MSG);
- HalResult<float> mQFactor = HalResult<float>::failed(MSG);
- HalResult<std::vector<float>> mMaxAmplitudes = HalResult<std::vector<float>>::failed(MSG);
+ HalResult<std::chrono::milliseconds>::transactionFailed(MSG);
+ HalResult<int32_t> mCompositionSizeMax = HalResult<int>::transactionFailed(MSG);
+ HalResult<int32_t> mPwleSizeMax = HalResult<int>::transactionFailed(MSG);
+ HalResult<float> mMinFrequency = HalResult<float>::transactionFailed(MSG);
+ HalResult<float> mResonantFrequency = HalResult<float>::transactionFailed(MSG);
+ HalResult<float> mFrequencyResolution = HalResult<float>::transactionFailed(MSG);
+ HalResult<float> mQFactor = HalResult<float>::transactionFailed(MSG);
+ HalResult<std::vector<float>> mMaxAmplitudes =
+ HalResult<std::vector<float>>::transactionFailed(MSG);
friend class HalWrapper;
};
diff --git a/services/vibratorservice/test/VibratorHalControllerTest.cpp b/services/vibratorservice/test/VibratorHalControllerTest.cpp
index 8e77bc5..9b95d74 100644
--- a/services/vibratorservice/test/VibratorHalControllerTest.cpp
+++ b/services/vibratorservice/test/VibratorHalControllerTest.cpp
@@ -107,17 +107,38 @@
ASSERT_EQ(1, mConnectCounter);
}
-TEST_F(VibratorHalControllerTest, TestGetInfoRetriesOnAnyFailure) {
+TEST_F(VibratorHalControllerTest, TestGetInfoRetriesOnTransactionFailure) {
EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
EXPECT_CALL(*mMockHal.get(), getCapabilitiesInternal())
.Times(Exactly(2))
- .WillOnce(Return(vibrator::HalResult<vibrator::Capabilities>::failed("message")))
+ .WillOnce(Return(vibrator::HalResult<vibrator::Capabilities>::transactionFailed("msg")))
.WillRepeatedly(Return(vibrator::HalResult<vibrator::Capabilities>::ok(
vibrator::Capabilities::ON_CALLBACK)));
auto result = mController->getInfo();
- ASSERT_FALSE(result.capabilities.isFailed());
+ ASSERT_TRUE(result.capabilities.isOk());
+ ASSERT_EQ(1, mConnectCounter);
+}
+TEST_F(VibratorHalControllerTest, TestGetInfoDoesNotRetryOnOperationFailure) {
+ EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(0));
+ EXPECT_CALL(*mMockHal.get(), getCapabilitiesInternal())
+ .Times(Exactly(1))
+ .WillRepeatedly(Return(vibrator::HalResult<vibrator::Capabilities>::failed("msg")));
+
+ auto result = mController->getInfo();
+ ASSERT_TRUE(result.capabilities.isFailed());
+ ASSERT_EQ(1, mConnectCounter);
+}
+
+TEST_F(VibratorHalControllerTest, TestGetInfoDoesNotRetryOnUnsupported) {
+ EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(0));
+ EXPECT_CALL(*mMockHal.get(), getCapabilitiesInternal())
+ .Times(Exactly(1))
+ .WillRepeatedly(Return(vibrator::HalResult<vibrator::Capabilities>::unsupported()));
+
+ auto result = mController->getInfo();
+ ASSERT_TRUE(result.capabilities.isUnsupported());
ASSERT_EQ(1, mConnectCounter);
}
@@ -128,48 +149,54 @@
auto result = mController->doWithRetry<void>(ON_FN, "on");
ASSERT_TRUE(result.isOk());
-
ASSERT_EQ(1, mConnectCounter);
}
-TEST_F(VibratorHalControllerTest, TestUnsupportedApiResultDoNotResetHalConnection) {
+TEST_F(VibratorHalControllerTest, TestUnsupportedApiResultDoesNotResetHalConnection) {
+ EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(0));
EXPECT_CALL(*mMockHal.get(), off())
.Times(Exactly(1))
.WillRepeatedly(Return(vibrator::HalResult<void>::unsupported()));
- ASSERT_EQ(0, mConnectCounter);
auto result = mController->doWithRetry<void>(OFF_FN, "off");
ASSERT_TRUE(result.isUnsupported());
ASSERT_EQ(1, mConnectCounter);
}
-TEST_F(VibratorHalControllerTest, TestFailedApiResultResetsHalConnection) {
+TEST_F(VibratorHalControllerTest, TestOperationFailedApiResultDoesNotResetHalConnection) {
+ EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(0));
EXPECT_CALL(*mMockHal.get(), on(_, _))
- .Times(Exactly(2))
+ .Times(Exactly(1))
.WillRepeatedly(Return(vibrator::HalResult<void>::failed("message")));
- EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
-
- ASSERT_EQ(0, mConnectCounter);
auto result = mController->doWithRetry<void>(ON_FN, "on");
ASSERT_TRUE(result.isFailed());
ASSERT_EQ(1, mConnectCounter);
}
-TEST_F(VibratorHalControllerTest, TestFailedApiResultReturnsSuccessAfterRetries) {
+TEST_F(VibratorHalControllerTest, TestTransactionFailedApiResultResetsHalConnection) {
+ EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
+ EXPECT_CALL(*mMockHal.get(), on(_, _))
+ .Times(Exactly(2))
+ .WillRepeatedly(Return(vibrator::HalResult<void>::transactionFailed("message")));
+
+ auto result = mController->doWithRetry<void>(ON_FN, "on");
+ ASSERT_TRUE(result.isFailed());
+ ASSERT_EQ(1, mConnectCounter);
+}
+
+TEST_F(VibratorHalControllerTest, TestTransactionFailedApiResultReturnsSuccessAfterRetries) {
{
InSequence seq;
EXPECT_CALL(*mMockHal.get(), ping())
.Times(Exactly(1))
- .WillRepeatedly(Return(vibrator::HalResult<void>::failed("message")));
+ .WillRepeatedly(Return(vibrator::HalResult<void>::transactionFailed("message")));
EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
EXPECT_CALL(*mMockHal.get(), ping())
.Times(Exactly(1))
.WillRepeatedly(Return(vibrator::HalResult<void>::ok()));
}
- ASSERT_EQ(0, mConnectCounter);
-
auto result = mController->doWithRetry<void>(PING_FN, "ping");
ASSERT_TRUE(result.isOk());
ASSERT_EQ(1, mConnectCounter);
@@ -221,11 +248,11 @@
});
EXPECT_CALL(*mMockHal.get(), ping())
.Times(Exactly(1))
- .WillRepeatedly(Return(vibrator::HalResult<void>::failed("message")));
+ .WillRepeatedly(Return(vibrator::HalResult<void>::transactionFailed("message")));
EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
EXPECT_CALL(*mMockHal.get(), ping())
.Times(Exactly(1))
- .WillRepeatedly(Return(vibrator::HalResult<void>::failed("message")));
+ .WillRepeatedly(Return(vibrator::HalResult<void>::transactionFailed("message")));
}
std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
diff --git a/services/vibratorservice/test/VibratorManagerHalControllerTest.cpp b/services/vibratorservice/test/VibratorManagerHalControllerTest.cpp
index e5fbbae..11a8b66 100644
--- a/services/vibratorservice/test/VibratorManagerHalControllerTest.cpp
+++ b/services/vibratorservice/test/VibratorManagerHalControllerTest.cpp
@@ -98,8 +98,10 @@
.WillRepeatedly(Return(voidResult));
if (cardinality > 1) {
- // One reconnection call after each failure.
- EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(7 * cardinality));
+ // One reconnection for each retry.
+ EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(7 * (cardinality - 1)));
+ } else {
+ EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(0));
}
}
};
@@ -141,14 +143,12 @@
ASSERT_EQ(1, mConnectCounter);
}
-TEST_F(VibratorManagerHalControllerTest, TestUnsupportedApiResultDoNotResetHalConnection) {
+TEST_F(VibratorManagerHalControllerTest, TestUnsupportedApiResultDoesNotResetHalConnection) {
setHalExpectations(/* cardinality= */ 1, vibrator::HalResult<void>::unsupported(),
vibrator::HalResult<vibrator::ManagerCapabilities>::unsupported(),
vibrator::HalResult<std::vector<int32_t>>::unsupported(),
vibrator::HalResult<std::shared_ptr<HalController>>::unsupported());
- ASSERT_EQ(0, mConnectCounter);
-
ASSERT_TRUE(mController->ping().isUnsupported());
ASSERT_TRUE(mController->getCapabilities().isUnsupported());
ASSERT_TRUE(mController->getVibratorIds().isUnsupported());
@@ -160,13 +160,28 @@
ASSERT_EQ(1, mConnectCounter);
}
-TEST_F(VibratorManagerHalControllerTest, TestFailedApiResultResetsHalConnection) {
- setHalExpectations(MAX_ATTEMPTS, vibrator::HalResult<void>::failed("message"),
- vibrator::HalResult<vibrator::ManagerCapabilities>::failed("message"),
- vibrator::HalResult<std::vector<int32_t>>::failed("message"),
- vibrator::HalResult<std::shared_ptr<HalController>>::failed("message"));
+TEST_F(VibratorManagerHalControllerTest, TestOperationFailedApiResultDoesNotResetHalConnection) {
+ setHalExpectations(/* cardinality= */ 1, vibrator::HalResult<void>::failed("msg"),
+ vibrator::HalResult<vibrator::ManagerCapabilities>::failed("msg"),
+ vibrator::HalResult<std::vector<int32_t>>::failed("msg"),
+ vibrator::HalResult<std::shared_ptr<HalController>>::failed("msg"));
- ASSERT_EQ(0, mConnectCounter);
+ ASSERT_TRUE(mController->ping().isFailed());
+ ASSERT_TRUE(mController->getCapabilities().isFailed());
+ ASSERT_TRUE(mController->getVibratorIds().isFailed());
+ ASSERT_TRUE(mController->getVibrator(VIBRATOR_ID).isFailed());
+ ASSERT_TRUE(mController->prepareSynced(VIBRATOR_IDS).isFailed());
+ ASSERT_TRUE(mController->triggerSynced([]() {}).isFailed());
+ ASSERT_TRUE(mController->cancelSynced().isFailed());
+
+ ASSERT_EQ(1, mConnectCounter);
+}
+
+TEST_F(VibratorManagerHalControllerTest, TestTransactionFailedApiResultResetsHalConnection) {
+ setHalExpectations(MAX_ATTEMPTS, vibrator::HalResult<void>::transactionFailed("m"),
+ vibrator::HalResult<vibrator::ManagerCapabilities>::transactionFailed("m"),
+ vibrator::HalResult<std::vector<int32_t>>::transactionFailed("m"),
+ vibrator::HalResult<std::shared_ptr<HalController>>::transactionFailed("m"));
ASSERT_TRUE(mController->ping().isFailed());
ASSERT_TRUE(mController->getCapabilities().isFailed());
@@ -184,14 +199,13 @@
InSequence seq;
EXPECT_CALL(*mMockHal.get(), ping())
.Times(Exactly(1))
- .WillRepeatedly(Return(vibrator::HalResult<void>::failed("message")));
+ .WillRepeatedly(Return(vibrator::HalResult<void>::transactionFailed("message")));
EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
EXPECT_CALL(*mMockHal.get(), ping())
.Times(Exactly(1))
.WillRepeatedly(Return(vibrator::HalResult<void>::ok()));
}
- ASSERT_EQ(0, mConnectCounter);
ASSERT_TRUE(mController->ping().isOk());
ASSERT_EQ(1, mConnectCounter);
}
diff --git a/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp
index 1593cb1..dffc281 100644
--- a/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp
+++ b/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp
@@ -254,13 +254,14 @@
EXPECT_CALL(*mMockHal.get(), getVibrator(Eq(kVibratorId), _))
.Times(Exactly(3))
.WillOnce(DoAll(SetArgPointee<1>(nullptr),
- Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))))
+ Return(Status::fromExceptionCode(
+ Status::Exception::EX_TRANSACTION_FAILED))))
.WillRepeatedly(DoAll(SetArgPointee<1>(mMockVibrator), Return(Status())));
EXPECT_CALL(*mMockVibrator.get(), off())
.Times(Exactly(3))
- .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
- .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
+ .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_TRANSACTION_FAILED)))
+ .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_TRANSACTION_FAILED)))
.WillRepeatedly(Return(Status()));
// Get vibrator controller is successful even if first getVibrator.