Merge "Virtual rotary encoder native support" into main
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index 0300f8c..766c768 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -418,6 +418,14 @@
defaults: ["frameworks_native_data_etc_defaults"],
}
+// installed in system
+prebuilt_etc {
+ name: "android.software.preview_sdk.prebuilt.xml",
+ relative_install_path: "permissions",
+ src: "android.software.preview_sdk.xml",
+ filename_from_src: true,
+}
+
prebuilt_etc {
name: "android.software.sip.voip.prebuilt.xml",
src: "android.software.sip.voip.xml",
@@ -460,6 +468,22 @@
defaults: ["frameworks_native_data_etc_defaults"],
}
+// installed in system
+prebuilt_etc {
+ name: "android.software.webview.prebuilt.xml",
+ relative_install_path: "permissions",
+ src: "android.software.webview.xml",
+ filename_from_src: true,
+}
+
+// installed in system
+prebuilt_etc {
+ name: "android.software.window_magnification.prebuilt.xml",
+ relative_install_path: "permissions",
+ src: "android.software.window_magnification.xml",
+ filename_from_src: true,
+}
+
prebuilt_etc {
name: "aosp_excluded_hardware.prebuilt.xml",
src: "aosp_excluded_hardware.xml",
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index f31f8d3..1c8aa37 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -268,6 +268,21 @@
"-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION",
"-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
],
+
+ target: {
+ bionic: {
+ // Hide symbols by default and set the BUILDING_LIBBINDER macro so that
+ // the code knows to export them.
+ //
+ // Only enabled on bionic builds, where RTTI is disabled, because
+ // it is failing to export required typeinfo symbols.
+ // TODO: b/341341056 - Find a solution for non-bionic builds.
+ cflags: [
+ "-fvisibility=hidden",
+ "-DBUILDING_LIBBINDER",
+ ],
+ },
+ },
}
cc_defaults {
@@ -442,8 +457,10 @@
name: "libbinder_kernel_defaults",
srcs: [
"BufferedTextOutput.cpp",
+ "BackendUnifiedServiceManager.cpp",
"IPCThreadState.cpp",
"IServiceManager.cpp",
+ "IServiceManagerFFI.cpp",
"ProcessState.cpp",
"Static.cpp",
":libbinder_aidl",
@@ -519,7 +536,6 @@
"ParcelableHolder.cpp",
"PersistableBundle.cpp",
],
-
target: {
android: {
// NOT static to keep the wire protocol unfrozen
diff --git a/libs/binder/BackendUnifiedServiceManager.cpp b/libs/binder/BackendUnifiedServiceManager.cpp
new file mode 100644
index 0000000..496c5ef
--- /dev/null
+++ b/libs/binder/BackendUnifiedServiceManager.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2024 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 "BackendUnifiedServiceManager.h"
+
+namespace android {
+
+using AidlServiceManager = android::os::IServiceManager;
+
+BackendUnifiedServiceManager::BackendUnifiedServiceManager(const sp<AidlServiceManager>& impl)
+ : mTheRealServiceManager(impl) {}
+
+sp<AidlServiceManager> BackendUnifiedServiceManager::getImpl() {
+ return mTheRealServiceManager;
+}
+binder::Status BackendUnifiedServiceManager::getService(const ::std::string& name,
+ sp<IBinder>* _aidl_return) {
+ return mTheRealServiceManager->getService(name, _aidl_return);
+}
+binder::Status BackendUnifiedServiceManager::checkService(const ::std::string& name,
+ sp<IBinder>* _aidl_return) {
+ return mTheRealServiceManager->checkService(name, _aidl_return);
+}
+binder::Status BackendUnifiedServiceManager::addService(const ::std::string& name,
+ const sp<IBinder>& service,
+ bool allowIsolated, int32_t dumpPriority) {
+ return mTheRealServiceManager->addService(name, service, allowIsolated, dumpPriority);
+}
+binder::Status BackendUnifiedServiceManager::listServices(
+ int32_t dumpPriority, ::std::vector<::std::string>* _aidl_return) {
+ return mTheRealServiceManager->listServices(dumpPriority, _aidl_return);
+}
+binder::Status BackendUnifiedServiceManager::registerForNotifications(
+ const ::std::string& name, const sp<os::IServiceCallback>& callback) {
+ return mTheRealServiceManager->registerForNotifications(name, callback);
+}
+binder::Status BackendUnifiedServiceManager::unregisterForNotifications(
+ const ::std::string& name, const sp<os::IServiceCallback>& callback) {
+ return mTheRealServiceManager->unregisterForNotifications(name, callback);
+}
+binder::Status BackendUnifiedServiceManager::isDeclared(const ::std::string& name,
+ bool* _aidl_return) {
+ return mTheRealServiceManager->isDeclared(name, _aidl_return);
+}
+binder::Status BackendUnifiedServiceManager::getDeclaredInstances(
+ const ::std::string& iface, ::std::vector<::std::string>* _aidl_return) {
+ return mTheRealServiceManager->getDeclaredInstances(iface, _aidl_return);
+}
+binder::Status BackendUnifiedServiceManager::updatableViaApex(
+ const ::std::string& name, ::std::optional<::std::string>* _aidl_return) {
+ return mTheRealServiceManager->updatableViaApex(name, _aidl_return);
+}
+binder::Status BackendUnifiedServiceManager::getUpdatableNames(
+ const ::std::string& apexName, ::std::vector<::std::string>* _aidl_return) {
+ return mTheRealServiceManager->getUpdatableNames(apexName, _aidl_return);
+}
+binder::Status BackendUnifiedServiceManager::getConnectionInfo(
+ const ::std::string& name, ::std::optional<os::ConnectionInfo>* _aidl_return) {
+ return mTheRealServiceManager->getConnectionInfo(name, _aidl_return);
+}
+binder::Status BackendUnifiedServiceManager::registerClientCallback(
+ const ::std::string& name, const sp<IBinder>& service,
+ const sp<os::IClientCallback>& callback) {
+ return mTheRealServiceManager->registerClientCallback(name, service, callback);
+}
+binder::Status BackendUnifiedServiceManager::tryUnregisterService(const ::std::string& name,
+ const sp<IBinder>& service) {
+ return mTheRealServiceManager->tryUnregisterService(name, service);
+}
+binder::Status BackendUnifiedServiceManager::getServiceDebugInfo(
+ ::std::vector<os::ServiceDebugInfo>* _aidl_return) {
+ return mTheRealServiceManager->getServiceDebugInfo(_aidl_return);
+}
+
+[[clang::no_destroy]] static std::once_flag gUSmOnce;
+[[clang::no_destroy]] static sp<BackendUnifiedServiceManager> gUnifiedServiceManager;
+
+sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager() {
+ std::call_once(gUSmOnce, []() {
+#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
+ /* wait for service manager */ {
+ using std::literals::chrono_literals::operator""s;
+ using android::base::WaitForProperty;
+ while (!WaitForProperty("servicemanager.ready", "true", 1s)) {
+ ALOGE("Waited for servicemanager.ready for a second, waiting another...");
+ }
+ }
+#endif
+
+ sp<AidlServiceManager> sm = nullptr;
+ while (sm == nullptr) {
+ sm = interface_cast<AidlServiceManager>(
+ ProcessState::self()->getContextObject(nullptr));
+ if (sm == nullptr) {
+ ALOGE("Waiting 1s on context object on %s.",
+ ProcessState::self()->getDriverName().c_str());
+ sleep(1);
+ }
+ }
+
+ gUnifiedServiceManager = sp<BackendUnifiedServiceManager>::make(sm);
+ });
+
+ return gUnifiedServiceManager;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/binder/BackendUnifiedServiceManager.h b/libs/binder/BackendUnifiedServiceManager.h
new file mode 100644
index 0000000..a67d5ba
--- /dev/null
+++ b/libs/binder/BackendUnifiedServiceManager.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <android-base/properties.h>
+#include <android/os/BnServiceManager.h>
+#include <android/os/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+
+namespace android {
+
+class BackendUnifiedServiceManager : public android::os::BnServiceManager {
+public:
+ explicit BackendUnifiedServiceManager(const sp<os::IServiceManager>& impl);
+
+ sp<os::IServiceManager> getImpl();
+ binder::Status getService(const ::std::string& name, sp<IBinder>* _aidl_return) override;
+ binder::Status checkService(const ::std::string& name, sp<IBinder>* _aidl_return) override;
+ binder::Status addService(const ::std::string& name, const sp<IBinder>& service,
+ bool allowIsolated, int32_t dumpPriority) override;
+ binder::Status listServices(int32_t dumpPriority,
+ ::std::vector<::std::string>* _aidl_return) override;
+ binder::Status registerForNotifications(const ::std::string& name,
+ const sp<os::IServiceCallback>& callback) override;
+ binder::Status unregisterForNotifications(const ::std::string& name,
+ const sp<os::IServiceCallback>& callback) override;
+ binder::Status isDeclared(const ::std::string& name, bool* _aidl_return) override;
+ binder::Status getDeclaredInstances(const ::std::string& iface,
+ ::std::vector<::std::string>* _aidl_return) override;
+ binder::Status updatableViaApex(const ::std::string& name,
+ ::std::optional<::std::string>* _aidl_return) override;
+ binder::Status getUpdatableNames(const ::std::string& apexName,
+ ::std::vector<::std::string>* _aidl_return) override;
+ binder::Status getConnectionInfo(const ::std::string& name,
+ ::std::optional<os::ConnectionInfo>* _aidl_return) override;
+ binder::Status registerClientCallback(const ::std::string& name, const sp<IBinder>& service,
+ const sp<os::IClientCallback>& callback) override;
+ binder::Status tryUnregisterService(const ::std::string& name,
+ const sp<IBinder>& service) override;
+ binder::Status getServiceDebugInfo(::std::vector<os::ServiceDebugInfo>* _aidl_return) override;
+
+ // for legacy ABI
+ const String16& getInterfaceDescriptor() const override {
+ return mTheRealServiceManager->getInterfaceDescriptor();
+ }
+
+ IBinder* onAsBinder() override { return IInterface::asBinder(mTheRealServiceManager).get(); }
+
+private:
+ sp<os::IServiceManager> mTheRealServiceManager;
+};
+
+sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager();
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index fbcf823..5844c85 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "ServiceManagerCppClient"
+#include <BackendUnifiedServiceManager.h>
#include <binder/IServiceManager.h>
#include <inttypes.h>
@@ -111,14 +112,12 @@
std::vector<IServiceManager::ServiceDebugInfo> getServiceDebugInfo() override;
// for legacy ABI
const String16& getInterfaceDescriptor() const override {
- return mTheRealServiceManager->getInterfaceDescriptor();
+ return mUnifiedServiceManager->getInterfaceDescriptor();
}
- IBinder* onAsBinder() override {
- return IInterface::asBinder(mTheRealServiceManager).get();
- }
+ IBinder* onAsBinder() override { return IInterface::asBinder(mUnifiedServiceManager).get(); }
protected:
- sp<AidlServiceManager> mTheRealServiceManager;
+ sp<BackendUnifiedServiceManager> mUnifiedServiceManager;
// AidlRegistrationCallback -> services that its been registered for
// notifications.
using LocalRegistrationAndWaiter =
@@ -136,9 +135,9 @@
// will still have the 5s delay that is expected by a large amount of Android code.
//
// When implementing ServiceManagerShim, use realGetService instead of
- // mTheRealServiceManager->getService so that it can be overridden in ServiceManagerHostShim.
+ // mUnifiedServiceManager->getService so that it can be overridden in ServiceManagerHostShim.
virtual Status realGetService(const std::string& name, sp<IBinder>* _aidl_return) {
- return mTheRealServiceManager->getService(name, _aidl_return);
+ return mUnifiedServiceManager->getService(name, _aidl_return);
}
};
@@ -148,26 +147,7 @@
sp<IServiceManager> defaultServiceManager()
{
std::call_once(gSmOnce, []() {
-#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
- /* wait for service manager */ {
- using std::literals::chrono_literals::operator""s;
- using android::base::WaitForProperty;
- while (!WaitForProperty("servicemanager.ready", "true", 1s)) {
- ALOGE("Waited for servicemanager.ready for a second, waiting another...");
- }
- }
-#endif
-
- sp<AidlServiceManager> sm = nullptr;
- while (sm == nullptr) {
- sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
- if (sm == nullptr) {
- ALOGE("Waiting 1s on context object on %s.", ProcessState::self()->getDriverName().c_str());
- sleep(1);
- }
- }
-
- gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
+ gDefaultServiceManager = sp<ServiceManagerShim>::make(getBackendUnifiedServiceManager());
});
return gDefaultServiceManager;
@@ -290,9 +270,9 @@
// ----------------------------------------------------------------------
-ServiceManagerShim::ServiceManagerShim(const sp<AidlServiceManager>& impl)
- : mTheRealServiceManager(impl)
-{}
+ServiceManagerShim::ServiceManagerShim(const sp<AidlServiceManager>& impl) {
+ mUnifiedServiceManager = sp<BackendUnifiedServiceManager>::make(impl);
+}
// This implementation could be simplified and made more efficient by delegating
// to waitForService. However, this changes the threading structure in some
@@ -345,7 +325,7 @@
sp<IBinder> ServiceManagerShim::checkService(const String16& name) const
{
sp<IBinder> ret;
- if (!mTheRealServiceManager->checkService(String8(name).c_str(), &ret).isOk()) {
+ if (!mUnifiedServiceManager->checkService(String8(name).c_str(), &ret).isOk()) {
return nullptr;
}
return ret;
@@ -354,15 +334,15 @@
status_t ServiceManagerShim::addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated, int dumpsysPriority)
{
- Status status = mTheRealServiceManager->addService(
- String8(name).c_str(), service, allowIsolated, dumpsysPriority);
+ Status status = mUnifiedServiceManager->addService(String8(name).c_str(), service,
+ allowIsolated, dumpsysPriority);
return status.exceptionCode();
}
Vector<String16> ServiceManagerShim::listServices(int dumpsysPriority)
{
std::vector<std::string> ret;
- if (!mTheRealServiceManager->listServices(dumpsysPriority, &ret).isOk()) {
+ if (!mUnifiedServiceManager->listServices(dumpsysPriority, &ret).isOk()) {
return {};
}
@@ -420,15 +400,13 @@
if (out != nullptr) return out;
sp<Waiter> waiter = sp<Waiter>::make();
- if (Status status = mTheRealServiceManager->registerForNotifications(name, waiter);
+ if (Status status = mUnifiedServiceManager->registerForNotifications(name, waiter);
!status.isOk()) {
ALOGW("Failed to registerForNotifications in waitForService for %s: %s", name.c_str(),
status.toString8().c_str());
return nullptr;
}
- Defer unregister ([&] {
- mTheRealServiceManager->unregisterForNotifications(name, waiter);
- });
+ Defer unregister([&] { mUnifiedServiceManager->unregisterForNotifications(name, waiter); });
while(true) {
{
@@ -469,7 +447,7 @@
bool ServiceManagerShim::isDeclared(const String16& name) {
bool declared;
- if (Status status = mTheRealServiceManager->isDeclared(String8(name).c_str(), &declared);
+ if (Status status = mUnifiedServiceManager->isDeclared(String8(name).c_str(), &declared);
!status.isOk()) {
ALOGW("Failed to get isDeclared for %s: %s", String8(name).c_str(),
status.toString8().c_str());
@@ -481,7 +459,7 @@
Vector<String16> ServiceManagerShim::getDeclaredInstances(const String16& interface) {
std::vector<std::string> out;
if (Status status =
- mTheRealServiceManager->getDeclaredInstances(String8(interface).c_str(), &out);
+ mUnifiedServiceManager->getDeclaredInstances(String8(interface).c_str(), &out);
!status.isOk()) {
ALOGW("Failed to getDeclaredInstances for %s: %s", String8(interface).c_str(),
status.toString8().c_str());
@@ -498,7 +476,7 @@
std::optional<String16> ServiceManagerShim::updatableViaApex(const String16& name) {
std::optional<std::string> declared;
- if (Status status = mTheRealServiceManager->updatableViaApex(String8(name).c_str(), &declared);
+ if (Status status = mUnifiedServiceManager->updatableViaApex(String8(name).c_str(), &declared);
!status.isOk()) {
ALOGW("Failed to get updatableViaApex for %s: %s", String8(name).c_str(),
status.toString8().c_str());
@@ -509,7 +487,7 @@
Vector<String16> ServiceManagerShim::getUpdatableNames(const String16& apexName) {
std::vector<std::string> out;
- if (Status status = mTheRealServiceManager->getUpdatableNames(String8(apexName).c_str(), &out);
+ if (Status status = mUnifiedServiceManager->getUpdatableNames(String8(apexName).c_str(), &out);
!status.isOk()) {
ALOGW("Failed to getUpdatableNames for %s: %s", String8(apexName).c_str(),
status.toString8().c_str());
@@ -528,7 +506,7 @@
const String16& name) {
std::optional<os::ConnectionInfo> connectionInfo;
if (Status status =
- mTheRealServiceManager->getConnectionInfo(String8(name).c_str(), &connectionInfo);
+ mUnifiedServiceManager->getConnectionInfo(String8(name).c_str(), &connectionInfo);
!status.isOk()) {
ALOGW("Failed to get ConnectionInfo for %s: %s", String8(name).c_str(),
status.toString8().c_str());
@@ -549,7 +527,7 @@
sp<RegistrationWaiter> registrationWaiter = sp<RegistrationWaiter>::make(cb);
std::lock_guard<std::mutex> lock(mNameToRegistrationLock);
if (Status status =
- mTheRealServiceManager->registerForNotifications(nameStr, registrationWaiter);
+ mUnifiedServiceManager->registerForNotifications(nameStr, registrationWaiter);
!status.isOk()) {
ALOGW("Failed to registerForNotifications for %s: %s", nameStr.c_str(),
status.toString8().c_str());
@@ -600,7 +578,7 @@
ALOGE("%s Callback passed wasn't used to register for notifications", __FUNCTION__);
return BAD_VALUE;
}
- if (Status status = mTheRealServiceManager->unregisterForNotifications(String8(name).c_str(),
+ if (Status status = mUnifiedServiceManager->unregisterForNotifications(String8(name).c_str(),
registrationWaiter);
!status.isOk()) {
ALOGW("Failed to get service manager to unregisterForNotifications for %s: %s",
@@ -613,7 +591,7 @@
std::vector<IServiceManager::ServiceDebugInfo> ServiceManagerShim::getServiceDebugInfo() {
std::vector<os::ServiceDebugInfo> serviceDebugInfos;
std::vector<IServiceManager::ServiceDebugInfo> ret;
- if (Status status = mTheRealServiceManager->getServiceDebugInfo(&serviceDebugInfos);
+ if (Status status = mUnifiedServiceManager->getServiceDebugInfo(&serviceDebugInfos);
!status.isOk()) {
ALOGW("%s Failed to get ServiceDebugInfo", __FUNCTION__);
return ret;
diff --git a/libs/binder/IServiceManagerFFI.cpp b/libs/binder/IServiceManagerFFI.cpp
new file mode 100644
index 0000000..7d4d7dc
--- /dev/null
+++ b/libs/binder/IServiceManagerFFI.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 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/os/IServiceManager.h>
+
+#include <BackendUnifiedServiceManager.h>
+#include <binder/IServiceManagerFFI.h>
+
+namespace android::impl {
+sp<android::os::IServiceManager>
+getJavaServicemanagerImplPrivateDoNotUseExceptInTheOnePlaceItIsUsed() {
+ return getBackendUnifiedServiceManager();
+}
+
+} // namespace android::impl
diff --git a/libs/binder/include/binder/IServiceManagerFFI.h b/libs/binder/include/binder/IServiceManagerFFI.h
new file mode 100644
index 0000000..7537355
--- /dev/null
+++ b/libs/binder/include/binder/IServiceManagerFFI.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <android/os/IServiceManager.h>
+
+namespace android::impl {
+
+LIBBINDER_EXPORTED sp<android::os::IServiceManager>
+getJavaServicemanagerImplPrivateDoNotUseExceptInTheOnePlaceItIsUsed();
+
+} // namespace android::impl
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index ff6b558..2699368 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -62,7 +62,7 @@
status_t setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state,
- const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
+ Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
InputWindowCommands commands, int64_t desiredPresentTime, bool isAutoTimestamp,
const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId,
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index af91bb3..5db5394 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1059,7 +1059,8 @@
uncacheBuffer.token = BufferCache::getInstance().getToken();
uncacheBuffer.id = cacheId;
Vector<ComposerState> composerStates;
- status_t status = sf->setTransactionState(FrameTimelineInfo{}, composerStates, {},
+ Vector<DisplayState> displayStates;
+ status_t status = sf->setTransactionState(FrameTimelineInfo{}, composerStates, displayStates,
ISurfaceComposer::eOneWay,
Transaction::getDefaultApplyToken(), {}, systemTime(),
true, {uncacheBuffer}, false, {}, generateId(), {});
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index eb4a802..1ecc216 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -112,7 +112,7 @@
/* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
virtual status_t setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state,
- const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
+ Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
InputWindowCommands inputWindowCommands, int64_t desiredPresentTime,
bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffer,
bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks,
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 43cd0f8..5e91088 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -636,7 +636,7 @@
status_t setTransactionState(
const FrameTimelineInfo& /*frameTimelineInfo*/, Vector<ComposerState>& /*state*/,
- const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
+ Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
const sp<IBinder>& /*applyToken*/, InputWindowCommands /*inputWindowCommands*/,
int64_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/,
const std::vector<client_cache_t>& /*cachedBuffer*/, bool /*hasListenerCallbacks*/,
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index e62640e..5f37125 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -514,7 +514,7 @@
auto shader = parameters.shader;
if (stretchEffect.hasEffect()) {
const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr;
- if (graphicBuffer && parameters.shader) {
+ if (graphicBuffer && shader) {
shader = mStretchShaderFactory.createSkShader(shader, stretchEffect);
}
}
@@ -525,21 +525,26 @@
static_cast<ui::PixelFormat>(targetBuffer->getPixelFormat()))
: std::nullopt;
- if (parameters.display.tonemapStrategy == DisplaySettings::TonemapStrategy::Local) {
- // TODO: Handle color matrix transforms in linear space.
- SkImage* image = parameters.shader->isAImage((SkMatrix*)nullptr, (SkTileMode*)nullptr);
- if (image) {
- static MouriMap kMapper;
- const float ratio = getHdrRenderType(parameters.layer.sourceDataspace, format) ==
- HdrRenderType::GENERIC_HDR
- ? 1.0f
- : parameters.layerDimmingRatio;
- return kMapper.mouriMap(getActiveContext(), parameters.shader, ratio);
- }
+ const auto hdrType = getHdrRenderType(parameters.layer.sourceDataspace, format,
+ parameters.layerDimmingRatio);
+
+ const auto usingLocalTonemap =
+ parameters.display.tonemapStrategy == DisplaySettings::TonemapStrategy::Local &&
+ hdrType != HdrRenderType::SDR &&
+ shader->isAImage((SkMatrix*)nullptr, (SkTileMode*)nullptr);
+
+ if (usingLocalTonemap) {
+ static MouriMap kMapper;
+ const float ratio =
+ hdrType == HdrRenderType::GENERIC_HDR ? 1.0f : parameters.layerDimmingRatio;
+ shader = kMapper.mouriMap(getActiveContext(), shader, ratio);
}
+ // disable tonemapping if we already locally tonemapped
+ auto inputDataspace =
+ usingLocalTonemap ? parameters.outputDataSpace : parameters.layer.sourceDataspace;
auto effect =
- shaders::LinearEffect{.inputDataspace = parameters.layer.sourceDataspace,
+ shaders::LinearEffect{.inputDataspace = inputDataspace,
.outputDataspace = parameters.outputDataSpace,
.undoPremultipliedAlpha = parameters.undoPremultipliedAlpha,
.fakeOutputDataspace = parameters.fakeOutputDataspace};
@@ -555,20 +560,22 @@
mat4 colorTransform = parameters.layer.colorTransform;
- colorTransform *=
- mat4::scale(vec4(parameters.layerDimmingRatio, parameters.layerDimmingRatio,
- parameters.layerDimmingRatio, 1.f));
+ if (!usingLocalTonemap) {
+ colorTransform *=
+ mat4::scale(vec4(parameters.layerDimmingRatio, parameters.layerDimmingRatio,
+ parameters.layerDimmingRatio, 1.f));
+ }
const auto targetBuffer = parameters.layer.source.buffer.buffer;
const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr;
const auto hardwareBuffer = graphicBuffer ? graphicBuffer->toAHardwareBuffer() : nullptr;
- return createLinearEffectShader(parameters.shader, effect, runtimeEffect,
- std::move(colorTransform), parameters.display.maxLuminance,
+ return createLinearEffectShader(shader, effect, runtimeEffect, std::move(colorTransform),
+ parameters.display.maxLuminance,
parameters.display.currentLuminanceNits,
parameters.layer.source.buffer.maxLuminanceNits,
hardwareBuffer, parameters.display.renderIntent);
}
- return parameters.shader;
+ return shader;
}
void SkiaRenderEngine::initCanvas(SkCanvas* canvas, const DisplaySettings& display) {
diff --git a/libs/renderengine/skia/filters/MouriMap.cpp b/libs/renderengine/skia/filters/MouriMap.cpp
index 7d8b8a5..cc25fcc 100644
--- a/libs/renderengine/skia/filters/MouriMap.cpp
+++ b/libs/renderengine/skia/filters/MouriMap.cpp
@@ -84,13 +84,13 @@
float3 linear = toLinearSrgb(rgba.rgb) * hdrSdrRatio;
if (localMax <= 1.0) {
- return float4(fromLinearSrgb(linear), 1.0);
+ return float4(fromLinearSrgb(linear), rgba.a);
}
float maxRGB = max(linear.r, max(linear.g, linear.b));
localMax = max(localMax, maxRGB);
float gain = (1 + maxRGB / (localMax * localMax)) / (1 + maxRGB);
- return float4(fromLinearSrgb(linear * gain), 1.0);
+ return float4(fromLinearSrgb(linear * gain), rgba.a);
}
)");
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 540f55d..643499c 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -1002,26 +1002,23 @@
return *device->configuration;
}
-status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const {
- outAxisInfo->clear();
+std::optional<RawAbsoluteAxisInfo> EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis) const {
if (axis < 0 || axis > ABS_MAX) {
- return NAME_NOT_FOUND;
+ return std::nullopt;
}
std::scoped_lock _l(mLock);
const Device* device = getDeviceLocked(deviceId);
if (device == nullptr) {
- return NAME_NOT_FOUND;
+ return std::nullopt;
}
// We can read the RawAbsoluteAxisInfo even if the device is disabled and doesn't have a valid
// fd, because the info is populated once when the device is first opened, and it doesn't change
// throughout the device lifecycle.
auto it = device->absState.find(axis);
if (it == device->absState.end()) {
- return NAME_NOT_FOUND;
+ return std::nullopt;
}
- *outAxisInfo = it->second.info;
- return OK;
+ return it->second.info;
}
bool EventHub::hasRelativeAxis(int32_t deviceId, int axis) const {
@@ -1134,22 +1131,20 @@
return device->swState.test(sw) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
}
-status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const {
- *outValue = 0;
+std::optional<int32_t> EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis) const {
if (axis < 0 || axis > ABS_MAX) {
- return NAME_NOT_FOUND;
+ return std::nullopt;
}
std::scoped_lock _l(mLock);
const Device* device = getDeviceLocked(deviceId);
if (device == nullptr || !device->hasValidFd()) {
- return NAME_NOT_FOUND;
+ return std::nullopt;
}
const auto it = device->absState.find(axis);
if (it == device->absState.end()) {
- return NAME_NOT_FOUND;
+ return std::nullopt;
}
- *outValue = it->second.value;
- return OK;
+ return it->second.value;
}
base::Result<std::vector<int32_t>> EventHub::getMtSlotValues(int32_t deviceId, int32_t axis,
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index 7cf584d..2a43466 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -21,6 +21,7 @@
#include <filesystem>
#include <functional>
#include <map>
+#include <optional>
#include <ostream>
#include <string>
#include <unordered_map>
@@ -278,8 +279,8 @@
*/
virtual std::optional<PropertyMap> getConfiguration(int32_t deviceId) const = 0;
- virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const = 0;
+ virtual std::optional<RawAbsoluteAxisInfo> getAbsoluteAxisInfo(int32_t deviceId,
+ int axis) const = 0;
virtual bool hasRelativeAxis(int32_t deviceId, int axis) const = 0;
@@ -339,8 +340,7 @@
virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const = 0;
virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0;
virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0;
- virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
- int32_t* outValue) const = 0;
+ virtual std::optional<int32_t> getAbsoluteAxisValue(int32_t deviceId, int32_t axis) const = 0;
/* Query Multi-Touch slot values for an axis. Returns error or an 1 indexed array of size
* (slotCount + 1). The value at the 0 index is set to queried axis. */
virtual base::Result<std::vector<int32_t>> getMtSlotValues(int32_t deviceId, int32_t axis,
@@ -511,8 +511,8 @@
std::optional<PropertyMap> getConfiguration(int32_t deviceId) const override final;
- status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const override final;
+ std::optional<RawAbsoluteAxisInfo> getAbsoluteAxisInfo(int32_t deviceId,
+ int axis) const override final;
bool hasRelativeAxis(int32_t deviceId, int axis) const override final;
@@ -559,8 +559,8 @@
int32_t getSwitchState(int32_t deviceId, int32_t sw) const override final;
int32_t getKeyCodeForKeyLocation(int32_t deviceId,
int32_t locationKeyCode) const override final;
- status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
- int32_t* outValue) const override final;
+ std::optional<int32_t> getAbsoluteAxisValue(int32_t deviceId,
+ int32_t axis) const override final;
base::Result<std::vector<int32_t>> getMtSlotValues(int32_t deviceId, int32_t axis,
size_t slotCount) const override final;
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 2a7e262..086c26f 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -306,9 +306,12 @@
return mEventHub->getDeviceControllerNumber(mId);
}
inline status_t getAbsoluteAxisInfo(int32_t code, RawAbsoluteAxisInfo* axisInfo) const {
- if (const auto status = mEventHub->getAbsoluteAxisInfo(mId, code, axisInfo); status != OK) {
- return status;
+ std::optional<RawAbsoluteAxisInfo> info = mEventHub->getAbsoluteAxisInfo(mId, code);
+ if (!info.has_value()) {
+ axisInfo->clear();
+ return NAME_NOT_FOUND;
}
+ *axisInfo = *info;
// Validate axis info for InputDevice.
if (axisInfo->valid && axisInfo->minValue == axisInfo->maxValue) {
@@ -379,8 +382,8 @@
return mEventHub->getKeyCodeForKeyLocation(mId, locationKeyCode);
}
inline int32_t getSwitchState(int32_t sw) const { return mEventHub->getSwitchState(mId, sw); }
- inline status_t getAbsoluteAxisValue(int32_t code, int32_t* outValue) const {
- return mEventHub->getAbsoluteAxisValue(mId, code, outValue);
+ inline std::optional<int32_t> getAbsoluteAxisValue(int32_t code) const {
+ return mEventHub->getAbsoluteAxisValue(mId, code);
}
inline base::Result<std::vector<int32_t>> getMtSlotValues(int32_t axis,
size_t slotCount) const {
@@ -432,9 +435,8 @@
}
inline bool hasAbsoluteAxis(int32_t code) const {
- RawAbsoluteAxisInfo info;
- mEventHub->getAbsoluteAxisInfo(mId, code, &info);
- return info.valid;
+ std::optional<RawAbsoluteAxisInfo> info = mEventHub->getAbsoluteAxisInfo(mId, code);
+ return info.has_value() && info->valid;
}
inline bool isKeyPressed(int32_t scanCode) const {
return mEventHub->getScanCodeState(mId, scanCode) == AKEY_STATE_DOWN;
@@ -442,11 +444,6 @@
inline bool isKeyCodePressed(int32_t keyCode) const {
return mEventHub->getKeyCodeState(mId, keyCode) == AKEY_STATE_DOWN;
}
- inline int32_t getAbsoluteAxisValue(int32_t code) const {
- int32_t value;
- mEventHub->getAbsoluteAxisValue(mId, code, &value);
- return value;
- }
inline bool isDeviceEnabled() { return mEventHub->isDeviceEnabled(mId); }
inline status_t enableDevice() { return mEventHub->enableDevice(mId); }
inline status_t disableDevice() { return mEventHub->disableDevice(mId); }
diff --git a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
index 4919068..8dc6e4d 100644
--- a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
@@ -139,13 +139,11 @@
if (!mUsingSlotsProtocol) {
return;
}
- int32_t initialSlot;
- if (const auto status = deviceContext.getAbsoluteAxisValue(ABS_MT_SLOT, &initialSlot);
- status == OK) {
- mCurrentSlot = initialSlot;
+ if (const std::optional<int32_t> initialSlot = deviceContext.getAbsoluteAxisValue(ABS_MT_SLOT);
+ initialSlot.has_value()) {
+ mCurrentSlot = initialSlot.value();
} else {
- ALOGE("Could not retrieve current multi-touch slot index. status=%s",
- statusToString(status).c_str());
+ ALOGE("Could not retrieve current multi-touch slot index");
}
}
diff --git a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp
index 2b82ddf..4cf9243 100644
--- a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp
@@ -26,13 +26,13 @@
}
void SingleTouchMotionAccumulator::reset(InputDeviceContext& deviceContext) {
- mAbsX = deviceContext.getAbsoluteAxisValue(ABS_X);
- mAbsY = deviceContext.getAbsoluteAxisValue(ABS_Y);
- mAbsPressure = deviceContext.getAbsoluteAxisValue(ABS_PRESSURE);
- mAbsToolWidth = deviceContext.getAbsoluteAxisValue(ABS_TOOL_WIDTH);
- mAbsDistance = deviceContext.getAbsoluteAxisValue(ABS_DISTANCE);
- mAbsTiltX = deviceContext.getAbsoluteAxisValue(ABS_TILT_X);
- mAbsTiltY = deviceContext.getAbsoluteAxisValue(ABS_TILT_Y);
+ mAbsX = deviceContext.getAbsoluteAxisValue(ABS_X).value_or(0);
+ mAbsY = deviceContext.getAbsoluteAxisValue(ABS_Y).value_or(0);
+ mAbsPressure = deviceContext.getAbsoluteAxisValue(ABS_PRESSURE).value_or(0);
+ mAbsToolWidth = deviceContext.getAbsoluteAxisValue(ABS_TOOL_WIDTH).value_or(0);
+ mAbsDistance = deviceContext.getAbsoluteAxisValue(ABS_DISTANCE).value_or(0);
+ mAbsTiltX = deviceContext.getAbsoluteAxisValue(ABS_TILT_X).value_or(0);
+ mAbsTiltY = deviceContext.getAbsoluteAxisValue(ABS_TILT_Y).value_or(0);
}
void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
diff --git a/services/inputflinger/tests/FakeEventHub.cpp b/services/inputflinger/tests/FakeEventHub.cpp
index daa000f..12736c8 100644
--- a/services/inputflinger/tests/FakeEventHub.cpp
+++ b/services/inputflinger/tests/FakeEventHub.cpp
@@ -16,6 +16,8 @@
#include "FakeEventHub.h"
+#include <optional>
+
#include <android-base/thread_annotations.h>
#include <gtest/gtest.h>
#include <linux/input-event-codes.h>
@@ -263,18 +265,16 @@
return device->configuration;
}
-status_t FakeEventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const {
+std::optional<RawAbsoluteAxisInfo> FakeEventHub::getAbsoluteAxisInfo(int32_t deviceId,
+ int axis) const {
Device* device = getDevice(deviceId);
if (device) {
ssize_t index = device->absoluteAxes.indexOfKey(axis);
if (index >= 0) {
- *outAxisInfo = device->absoluteAxes.valueAt(index);
- return OK;
+ return device->absoluteAxes.valueAt(index);
}
}
- outAxisInfo->clear();
- return -1;
+ return std::nullopt;
}
bool FakeEventHub::hasRelativeAxis(int32_t deviceId, int axis) const {
@@ -417,18 +417,15 @@
return AKEY_STATE_UNKNOWN;
}
-status_t FakeEventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
- int32_t* outValue) const {
+std::optional<int32_t> FakeEventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis) const {
Device* device = getDevice(deviceId);
if (device) {
ssize_t index = device->absoluteAxisValue.indexOfKey(axis);
if (index >= 0) {
- *outValue = device->absoluteAxisValue.valueAt(index);
- return OK;
+ return device->absoluteAxisValue.valueAt(index);
}
}
- *outValue = 0;
- return -1;
+ return std::nullopt;
}
void FakeEventHub::setMtSlotValues(int32_t deviceId, int32_t axis,
diff --git a/services/inputflinger/tests/FakeEventHub.h b/services/inputflinger/tests/FakeEventHub.h
index f07b344..c2c875f 100644
--- a/services/inputflinger/tests/FakeEventHub.h
+++ b/services/inputflinger/tests/FakeEventHub.h
@@ -168,8 +168,8 @@
InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override;
int32_t getDeviceControllerNumber(int32_t) const override;
std::optional<PropertyMap> getConfiguration(int32_t deviceId) const override;
- status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const override;
+ std::optional<RawAbsoluteAxisInfo> getAbsoluteAxisInfo(int32_t deviceId,
+ int axis) const override;
bool hasRelativeAxis(int32_t deviceId, int axis) const override;
bool hasInputProperty(int32_t, int) const override;
bool hasMscEvent(int32_t deviceId, int mscEvent) const override final;
@@ -187,7 +187,7 @@
std::optional<RawLayoutInfo> getRawLayoutInfo(int32_t deviceId) const override;
int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override;
int32_t getSwitchState(int32_t deviceId, int32_t sw) const override;
- status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const override;
+ std::optional<int32_t> getAbsoluteAxisValue(int32_t deviceId, int32_t axis) const override;
int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const override;
// Return true if the device has non-empty key layout.
diff --git a/services/inputflinger/tests/HardwareProperties_test.cpp b/services/inputflinger/tests/HardwareProperties_test.cpp
index 8dfa8c8..643fab6 100644
--- a/services/inputflinger/tests/HardwareProperties_test.cpp
+++ b/services/inputflinger/tests/HardwareProperties_test.cpp
@@ -48,24 +48,20 @@
static constexpr int32_t EVENTHUB_ID = 1;
void setupValidAxis(int axis, int32_t min, int32_t max, int32_t resolution) {
- EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis, testing::_))
- .WillRepeatedly([=](int32_t, int32_t, RawAbsoluteAxisInfo* outAxisInfo) {
- outAxisInfo->valid = true;
- outAxisInfo->minValue = min;
- outAxisInfo->maxValue = max;
- outAxisInfo->flat = 0;
- outAxisInfo->fuzz = 0;
- outAxisInfo->resolution = resolution;
- return OK;
- });
+ EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis))
+ .WillRepeatedly(Return(std::optional<RawAbsoluteAxisInfo>{{
+ .valid = true,
+ .minValue = min,
+ .maxValue = max,
+ .flat = 0,
+ .fuzz = 0,
+ .resolution = resolution,
+ }}));
}
void setupInvalidAxis(int axis) {
- EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis, testing::_))
- .WillRepeatedly([=](int32_t, int32_t, RawAbsoluteAxisInfo* outAxisInfo) {
- outAxisInfo->valid = false;
- return -1;
- });
+ EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis))
+ .WillRepeatedly(Return(std::nullopt));
}
void setProperty(int property, bool value) {
diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp
index b5c9232..19bc5be 100644
--- a/services/inputflinger/tests/InputMapperTest.cpp
+++ b/services/inputflinger/tests/InputMapperTest.cpp
@@ -57,16 +57,16 @@
void InputMapperUnitTest::setupAxis(int axis, bool valid, int32_t min, int32_t max,
int32_t resolution) {
- EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis, _))
- .WillRepeatedly([=](int32_t, int32_t, RawAbsoluteAxisInfo* outAxisInfo) {
- outAxisInfo->valid = valid;
- outAxisInfo->minValue = min;
- outAxisInfo->maxValue = max;
- outAxisInfo->flat = 0;
- outAxisInfo->fuzz = 0;
- outAxisInfo->resolution = resolution;
- return valid ? OK : -1;
- });
+ EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis))
+ .WillRepeatedly(Return(valid ? std::optional<RawAbsoluteAxisInfo>{{
+ .valid = true,
+ .minValue = min,
+ .maxValue = max,
+ .flat = 0,
+ .fuzz = 0,
+ .resolution = resolution,
+ }}
+ : std::nullopt));
}
void InputMapperUnitTest::expectScanCodes(bool present, std::set<int> scanCodes) {
diff --git a/services/inputflinger/tests/InterfaceMocks.h b/services/inputflinger/tests/InterfaceMocks.h
index 16d3193..bacc6d4 100644
--- a/services/inputflinger/tests/InterfaceMocks.h
+++ b/services/inputflinger/tests/InterfaceMocks.h
@@ -91,8 +91,8 @@
MOCK_METHOD(InputDeviceIdentifier, getDeviceIdentifier, (int32_t deviceId), (const));
MOCK_METHOD(int32_t, getDeviceControllerNumber, (int32_t deviceId), (const));
MOCK_METHOD(std::optional<PropertyMap>, getConfiguration, (int32_t deviceId), (const));
- MOCK_METHOD(status_t, getAbsoluteAxisInfo,
- (int32_t deviceId, int axis, RawAbsoluteAxisInfo* outAxisInfo), (const));
+ MOCK_METHOD(std::optional<RawAbsoluteAxisInfo>, getAbsoluteAxisInfo,
+ (int32_t deviceId, int axis), (const));
MOCK_METHOD(bool, hasRelativeAxis, (int32_t deviceId, int axis), (const));
MOCK_METHOD(bool, hasInputProperty, (int32_t deviceId, int property), (const));
MOCK_METHOD(bool, hasMscEvent, (int32_t deviceId, int mscEvent), (const));
@@ -131,7 +131,7 @@
MOCK_METHOD(int32_t, getKeyCodeState, (int32_t deviceId, int32_t keyCode), (const, override));
MOCK_METHOD(int32_t, getSwitchState, (int32_t deviceId, int32_t sw), (const, override));
- MOCK_METHOD(status_t, getAbsoluteAxisValue, (int32_t deviceId, int32_t axis, int32_t* outValue),
+ MOCK_METHOD(std::optional<int32_t>, getAbsoluteAxisValue, (int32_t deviceId, int32_t axis),
(const, override));
MOCK_METHOD(base::Result<std::vector<int32_t>>, getMtSlotValues,
(int32_t deviceId, int32_t axis, size_t slotCount), (const, override));
diff --git a/services/inputflinger/tests/MultiTouchInputMapper_test.cpp b/services/inputflinger/tests/MultiTouchInputMapper_test.cpp
index b5f8971..d4d3c38 100644
--- a/services/inputflinger/tests/MultiTouchInputMapper_test.cpp
+++ b/services/inputflinger/tests/MultiTouchInputMapper_test.cpp
@@ -99,11 +99,8 @@
setupAxis(ABS_MT_TOOL_TYPE, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
// reset current slot at the beginning
- EXPECT_CALL(mMockEventHub, getAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, _))
- .WillRepeatedly([](int32_t, int32_t, int32_t* outValue) {
- *outValue = 0;
- return OK;
- });
+ EXPECT_CALL(mMockEventHub, getAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT))
+ .WillRepeatedly(Return(0));
// mark all slots not in use
mockSlotValues({});
@@ -211,11 +208,8 @@
const auto pointerCoordsBeforeReset = std::get<NotifyMotionArgs>(args.back()).pointerCoords;
// On buffer overflow mapper will be reset and MT slots data will be repopulated
- EXPECT_CALL(mMockEventHub, getAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, _))
- .WillRepeatedly([=](int32_t, int32_t, int32_t* outValue) {
- *outValue = 1;
- return OK;
- });
+ EXPECT_CALL(mMockEventHub, getAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT))
+ .WillRepeatedly(Return(1));
mockSlotValues(
{{1, {Point{x1, y1}, FIRST_TRACKING_ID}}, {2, {Point{x2, y2}, SECOND_TRACKING_ID}}});
diff --git a/services/inputflinger/tests/TouchpadInputMapper_test.cpp b/services/inputflinger/tests/TouchpadInputMapper_test.cpp
index 2b62dd1..1afb4f0 100644
--- a/services/inputflinger/tests/TouchpadInputMapper_test.cpp
+++ b/services/inputflinger/tests/TouchpadInputMapper_test.cpp
@@ -103,11 +103,8 @@
setupAxis(ABS_MT_DISTANCE, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
setupAxis(ABS_MT_TOOL_TYPE, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
- EXPECT_CALL(mMockEventHub, getAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, testing::_))
- .WillRepeatedly([](int32_t eventHubId, int32_t, int32_t* outValue) {
- *outValue = 0;
- return OK;
- });
+ EXPECT_CALL(mMockEventHub, getAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT))
+ .WillRepeatedly(Return(0));
EXPECT_CALL(mMockEventHub, getMtSlotValues(EVENTHUB_ID, testing::_, testing::_))
.WillRepeatedly([]() -> base::Result<std::vector<int32_t>> {
return base::ResultError("Axis not supported", NAME_NOT_FOUND);
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
index ff425dd..6dea540 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -17,6 +17,7 @@
#include <map>
#include <memory>
+#include <optional>
#include <EventHub.h>
#include <InputDevice.h>
@@ -119,16 +120,26 @@
void setAbsoluteAxisInfo(int32_t deviceId, int axis, const RawAbsoluteAxisInfo& axisInfo) {
mAxes[deviceId][axis] = axisInfo;
}
- status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const override {
+ std::optional<RawAbsoluteAxisInfo> getAbsoluteAxisInfo(int32_t deviceId,
+ int axis) const override {
if (auto deviceAxesIt = mAxes.find(deviceId); deviceAxesIt != mAxes.end()) {
const std::map<int, RawAbsoluteAxisInfo>& deviceAxes = deviceAxesIt->second;
if (auto axisInfoIt = deviceAxes.find(axis); axisInfoIt != deviceAxes.end()) {
- *outAxisInfo = axisInfoIt->second;
- return OK;
+ return axisInfoIt->second;
}
}
- return mFdp->ConsumeIntegral<status_t>();
+ if (mFdp->ConsumeBool()) {
+ return std::optional<RawAbsoluteAxisInfo>({
+ .valid = mFdp->ConsumeBool(),
+ .minValue = mFdp->ConsumeIntegral<int32_t>(),
+ .maxValue = mFdp->ConsumeIntegral<int32_t>(),
+ .flat = mFdp->ConsumeIntegral<int32_t>(),
+ .fuzz = mFdp->ConsumeIntegral<int32_t>(),
+ .resolution = mFdp->ConsumeIntegral<int32_t>(),
+ });
+ } else {
+ return std::nullopt;
+ }
}
bool hasRelativeAxis(int32_t deviceId, int axis) const override { return mFdp->ConsumeBool(); }
bool hasInputProperty(int32_t deviceId, int property) const override {
@@ -197,9 +208,12 @@
int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const override {
return mFdp->ConsumeIntegral<int32_t>();
}
- status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
- int32_t* outValue) const override {
- return mFdp->ConsumeIntegral<status_t>();
+ std::optional<int32_t> getAbsoluteAxisValue(int32_t deviceId, int32_t axis) const override {
+ if (mFdp->ConsumeBool()) {
+ return mFdp->ConsumeIntegral<int32_t>();
+ } else {
+ return std::nullopt;
+ }
}
base::Result<std::vector<int32_t>> getMtSlotValues(int32_t deviceId, int32_t axis,
size_t slotCount) const override {
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 5b9a102..b40aea4 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -1102,7 +1102,7 @@
}
ftl::Future<std::monostate> Output::presentFrameAndReleaseLayersAsync(bool flushEvenWhenDisabled) {
- return ftl::Future<bool>(std::move(mHwComposerAsyncWorker->send([&]() {
+ return ftl::Future<bool>(std::move(mHwComposerAsyncWorker->send([this, flushEvenWhenDisabled]() {
presentFrameAndReleaseLayers(flushEvenWhenDisabled);
return true;
})))
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index 846727b..be5ffbc 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -1641,7 +1641,7 @@
case FrameRateCategory::Normal:
return FpsRange{60_Hz, 120_Hz};
case FrameRateCategory::Low:
- return FpsRange{30_Hz, 120_Hz};
+ return FpsRange{48_Hz, 120_Hz};
case FrameRateCategory::HighHint:
case FrameRateCategory::NoPreference:
case FrameRateCategory::Default:
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 26e11e5..e669261 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -1118,8 +1118,10 @@
.emitEvent = !choice.consideredSignals.idle});
}
- frameRateOverridesChanged = updateFrameRateOverridesLocked(consideredSignals, modeOpt->fps);
-
+ if (!FlagManager::getInstance().vrr_bugfix_dropped_frame()) {
+ frameRateOverridesChanged =
+ updateFrameRateOverridesLocked(consideredSignals, modeOpt->fps);
+ }
if (mPolicy.modeOpt != modeOpt) {
mPolicy.modeOpt = modeOpt;
refreshRateChanged = true;
@@ -1134,6 +1136,12 @@
if (refreshRateChanged) {
mSchedulerCallback.requestDisplayModes(std::move(modeRequests));
}
+
+ if (FlagManager::getInstance().vrr_bugfix_dropped_frame()) {
+ std::scoped_lock lock(mPolicyLock);
+ frameRateOverridesChanged =
+ updateFrameRateOverridesLocked(consideredSignals, mPolicy.modeOpt->fps);
+ }
if (frameRateOverridesChanged) {
mSchedulerCallback.triggerOnFrameRateOverridesChanged();
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5b40acf..fd4bd11 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5169,7 +5169,7 @@
status_t SurfaceFlinger::setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& states,
- const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
+ Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp,
const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId,
@@ -5184,7 +5184,7 @@
composerState.state.sanitize(permissions);
}
- for (DisplayState display : displays) {
+ for (DisplayState& display : displays) {
display.sanitize(permissions);
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index ee541c4..7762bbe 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -559,7 +559,7 @@
sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const;
status_t setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state,
- const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
+ Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
InputWindowCommands inputWindowCommands, int64_t desiredPresentTime,
bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers,
bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks,
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
index 2e3273c..a56bb51 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -136,6 +136,7 @@
DUMP_READ_ONLY_FLAG(vulkan_renderengine);
DUMP_READ_ONLY_FLAG(renderable_buffer_usage);
DUMP_READ_ONLY_FLAG(vrr_bugfix_24q4);
+ DUMP_READ_ONLY_FLAG(vrr_bugfix_dropped_frame);
DUMP_READ_ONLY_FLAG(restore_blur_step);
DUMP_READ_ONLY_FLAG(dont_skip_on_early_ro);
DUMP_READ_ONLY_FLAG(protected_if_client);
@@ -242,6 +243,7 @@
FLAG_MANAGER_READ_ONLY_FLAG(dont_skip_on_early_ro, "")
FLAG_MANAGER_READ_ONLY_FLAG(protected_if_client, "")
FLAG_MANAGER_READ_ONLY_FLAG(vrr_bugfix_24q4, "");
+FLAG_MANAGER_READ_ONLY_FLAG(vrr_bugfix_dropped_frame, "")
FLAG_MANAGER_READ_ONLY_FLAG(ce_fence_promise, "");
FLAG_MANAGER_READ_ONLY_FLAG(graphite_renderengine, "debug.renderengine.graphite")
FLAG_MANAGER_READ_ONLY_FLAG(latch_unsignaled_with_auto_refresh_changed, "");
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
index ab7a474..8799295 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -73,6 +73,7 @@
bool screenshot_fence_preservation() const;
bool vulkan_renderengine() const;
bool vrr_bugfix_24q4() const;
+ bool vrr_bugfix_dropped_frame() const;
bool renderable_buffer_usage() const;
bool restore_blur_step() const;
bool dont_skip_on_early_ro() const;
diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
index f4d4ee9..919ec17 100644
--- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
@@ -136,4 +136,15 @@
}
} # vrr_bugfix_24q4
+flag {
+ name: "vrr_bugfix_dropped_frame"
+ namespace: "core_graphics"
+ description: "bug fix for VRR dropped frame"
+ bug: "343603085"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+} # vrr_bugfix_dropped_frame
+
# IMPORTANT - please keep alphabetize to reduce merge conflicts
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index ebe11fb..d355e72 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -26,6 +26,7 @@
#include <private/android_filesystem_config.h>
#include <private/gui/ComposerServiceAIDL.h>
#include <ui/DisplayMode.h>
+#include <ui/DisplayState.h>
#include <ui/DynamicDisplayInfo.h>
#include <utils/String8.h>
#include <functional>
@@ -276,7 +277,7 @@
TEST_F(CredentialsTest, CaptureLayersTest) {
setupBackgroundSurface();
sp<GraphicBuffer> outBuffer;
- std::function<status_t()> condition = [=]() {
+ std::function<status_t()> condition = [=, this]() {
LayerCaptureArgs captureArgs;
captureArgs.layerHandle = mBGSurfaceControl->getHandle();
captureArgs.sourceCrop = {0, 0, 1, 1};
@@ -396,6 +397,56 @@
}
}
+TEST_F(CredentialsTest, DisplayTransactionPermissionTest) {
+ const auto display = getFirstDisplayToken();
+
+ ui::DisplayState displayState;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState));
+ const ui::Rotation initialOrientation = displayState.orientation;
+
+ // Set display orientation from an untrusted process. This should fail silently.
+ {
+ UIDFaker f{AID_BIN};
+ Transaction transaction;
+ Rect layerStackRect;
+ Rect displayRect;
+ transaction.setDisplayProjection(display, initialOrientation + ui::ROTATION_90,
+ layerStackRect, displayRect);
+ transaction.apply(/*synchronous=*/true);
+ }
+
+ // Verify that the display orientation did not change.
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState));
+ ASSERT_EQ(initialOrientation, displayState.orientation);
+
+ // Set display orientation from a trusted process.
+ {
+ UIDFaker f{AID_SYSTEM};
+ Transaction transaction;
+ Rect layerStackRect;
+ Rect displayRect;
+ transaction.setDisplayProjection(display, initialOrientation + ui::ROTATION_90,
+ layerStackRect, displayRect);
+ transaction.apply(/*synchronous=*/true);
+ }
+
+ // Verify that the display orientation did change.
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState));
+ ASSERT_EQ(initialOrientation + ui::ROTATION_90, displayState.orientation);
+
+ // Reset orientation
+ {
+ UIDFaker f{AID_SYSTEM};
+ Transaction transaction;
+ Rect layerStackRect;
+ Rect displayRect;
+ transaction.setDisplayProjection(display, initialOrientation, layerStackRect, displayRect);
+ transaction.apply(/*synchronous=*/true);
+ }
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState));
+ ASSERT_EQ(initialOrientation, displayState.orientation);
+}
+
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
index cf9a7d3..06c4e30 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
@@ -1562,7 +1562,7 @@
// When frame rates get an equal score, the lower is chosen, unless there are Max votes.
{0_Hz, FrameRateCategory::High, 90_Hz},
{0_Hz, FrameRateCategory::Normal, 60_Hz},
- {0_Hz, FrameRateCategory::Low, 30_Hz},
+ {0_Hz, FrameRateCategory::Low, 60_Hz},
{0_Hz, FrameRateCategory::NoPreference, 60_Hz},
// Cases that have both desired frame rate and frame rate category requirements.
@@ -1609,6 +1609,77 @@
}
}
+TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_120_vrr) {
+ if (GetParam() != Config::FrameRateOverride::Enabled) {
+ return;
+ }
+
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+ // Device with VRR config mode
+ auto selector = createSelector(kVrrMode_120, kModeId120);
+
+ struct Case {
+ // Params
+ Fps desiredFrameRate = 0_Hz;
+ FrameRateCategory frameRateCategory = FrameRateCategory::Default;
+
+ // Expected result
+ Fps expectedFrameRate = 0_Hz;
+ };
+
+ // Prepare a table with the vote and the expected refresh rate
+ const std::initializer_list<Case> testCases = {
+ // Cases that only have frame rate category requirements, but no desired frame rate.
+ // When frame rates get an equal score, the lower is chosen, unless there are Max votes.
+ {0_Hz, FrameRateCategory::High, 120_Hz},
+ {0_Hz, FrameRateCategory::Normal, 60_Hz},
+ {0_Hz, FrameRateCategory::Low, 48_Hz},
+ {0_Hz, FrameRateCategory::NoPreference, 120_Hz},
+
+ // Cases that have both desired frame rate and frame rate category requirements.
+ {24_Hz, FrameRateCategory::High, 120_Hz},
+ {30_Hz, FrameRateCategory::High, 120_Hz},
+ {12_Hz, FrameRateCategory::Normal, 60_Hz},
+ {24_Hz, FrameRateCategory::Low, 48_Hz},
+ {30_Hz, FrameRateCategory::NoPreference, 30_Hz},
+
+ // Cases that only have desired frame rate.
+ {30_Hz, FrameRateCategory::Default, 30_Hz},
+ };
+
+ for (auto testCase : testCases) {
+ std::vector<LayerRequirement> layers;
+ ALOGI("**** %s: Testing desiredFrameRate=%s, frameRateCategory=%s", __func__,
+ to_string(testCase.desiredFrameRate).c_str(),
+ ftl::enum_string(testCase.frameRateCategory).c_str());
+
+ if (testCase.desiredFrameRate.isValid()) {
+ std::stringstream ss;
+ ss << to_string(testCase.desiredFrameRate) << "ExplicitDefault";
+ LayerRequirement layer = {.name = ss.str(),
+ .vote = LayerVoteType::ExplicitDefault,
+ .desiredRefreshRate = testCase.desiredFrameRate,
+ .weight = 1.f};
+ layers.push_back(layer);
+ }
+
+ if (testCase.frameRateCategory != FrameRateCategory::Default) {
+ std::stringstream ss;
+ ss << "ExplicitCategory (" << ftl::enum_string(testCase.frameRateCategory) << ")";
+ LayerRequirement layer = {.name = ss.str(),
+ .vote = LayerVoteType::ExplicitCategory,
+ .frameRateCategory = testCase.frameRateCategory,
+ .weight = 1.f};
+ layers.push_back(layer);
+ }
+
+ EXPECT_EQ(testCase.expectedFrameRate, selector.getBestFrameRateMode(layers).fps)
+ << "Did not get expected frame rate for frameRate="
+ << to_string(testCase.desiredFrameRate)
+ << " category=" << ftl::enum_string(testCase.frameRateCategory);
+ }
+}
+
TEST_P(RefreshRateSelectorTest,
getBestFrameRateMode_withFrameRateCategoryMultiLayers_30_60_90_120) {
auto selector = createSelector(makeModes(kMode30, kMode60, kMode90, kMode120), kModeId60);
@@ -2140,14 +2211,14 @@
// These layers may switch modes because smoothSwitchOnly=false.
{FrameRateCategory::Default, false, 120_Hz, kModeId120},
{FrameRateCategory::NoPreference, false, 120_Hz, kModeId120},
- {FrameRateCategory::Low, false, 30_Hz, kModeId60},
+ {FrameRateCategory::Low, false, 60_Hz, kModeId60},
{FrameRateCategory::Normal, false, 60_Hz, kModeId60},
{FrameRateCategory::High, false, 120_Hz, kModeId120},
// These layers cannot change mode due to smoothSwitchOnly, and will definitely use
// active mode (120Hz).
{FrameRateCategory::NoPreference, true, 120_Hz, kModeId120},
- {FrameRateCategory::Low, true, 40_Hz, kModeId120},
+ {FrameRateCategory::Low, true, 120_Hz, kModeId120},
{FrameRateCategory::Normal, true, 120_Hz, kModeId120},
{FrameRateCategory::High, true, 120_Hz, kModeId120},
};
@@ -2207,13 +2278,13 @@
{FrameRateCategory::Default, false, 120_Hz},
// TODO(b/266481656): Once this bug is fixed, NoPreference should be a lower frame rate.
{FrameRateCategory::NoPreference, false, 120_Hz},
- {FrameRateCategory::Low, false, 30_Hz},
+ {FrameRateCategory::Low, false, 48_Hz},
{FrameRateCategory::Normal, false, 60_Hz},
{FrameRateCategory::High, false, 120_Hz},
{FrameRateCategory::Default, true, 120_Hz},
// TODO(b/266481656): Once this bug is fixed, NoPreference should be a lower frame rate.
{FrameRateCategory::NoPreference, true, 120_Hz},
- {FrameRateCategory::Low, true, 30_Hz},
+ {FrameRateCategory::Low, true, 48_Hz},
{FrameRateCategory::Normal, true, 60_Hz},
{FrameRateCategory::High, true, 120_Hz},
};
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 4197cbd..b5b36be 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -528,7 +528,7 @@
auto setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& states,
- const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
+ Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers,
bool hasListenerCallbacks, std::vector<ListenerCallbacks>& listenerCallbacks,
diff --git a/vulkan/Android.bp b/vulkan/Android.bp
index 2bf905c..0da9cc0 100644
--- a/vulkan/Android.bp
+++ b/vulkan/Android.bp
@@ -26,6 +26,8 @@
cc_library_headers {
name: "hwvulkan_headers",
+ host_supported: true, // Used for verification in Berberis.
+ native_bridge_supported: true, // Used for verification in Berberis.
vendor_available: true,
header_libs: [
"libcutils_headers",
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index a9706bc..a3fe33e 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -178,7 +178,7 @@
INIT_PROC(false, instance, GetPhysicalDeviceExternalSemaphoreProperties);
INIT_PROC(false, instance, GetPhysicalDeviceExternalFenceProperties);
INIT_PROC(false, instance, EnumeratePhysicalDeviceGroups);
- INIT_PROC_EXT(KHR_swapchain, false, instance, GetPhysicalDevicePresentRectanglesKHR);
+ INIT_PROC_EXT(KHR_swapchain, true, instance, GetPhysicalDevicePresentRectanglesKHR);
INIT_PROC(false, instance, GetPhysicalDeviceToolProperties);
// clang-format on
@@ -325,9 +325,9 @@
INIT_PROC(false, dev, BindBufferMemory2);
INIT_PROC(false, dev, BindImageMemory2);
INIT_PROC(false, dev, CmdSetDeviceMask);
- INIT_PROC_EXT(KHR_swapchain, false, dev, GetDeviceGroupPresentCapabilitiesKHR);
- INIT_PROC_EXT(KHR_swapchain, false, dev, GetDeviceGroupSurfacePresentModesKHR);
- INIT_PROC_EXT(KHR_swapchain, false, dev, AcquireNextImage2KHR);
+ INIT_PROC_EXT(KHR_swapchain, true, dev, GetDeviceGroupPresentCapabilitiesKHR);
+ INIT_PROC_EXT(KHR_swapchain, true, dev, GetDeviceGroupSurfacePresentModesKHR);
+ INIT_PROC_EXT(KHR_swapchain, true, dev, AcquireNextImage2KHR);
INIT_PROC(false, dev, CmdDispatchBase);
INIT_PROC(false, dev, CreateDescriptorUpdateTemplate);
INIT_PROC(false, dev, DestroyDescriptorUpdateTemplate);
@@ -659,6 +659,8 @@
"vkGetDrmDisplayEXT",
"vkGetInstanceProcAddr",
"vkGetPhysicalDeviceCalibrateableTimeDomainsEXT",
+ "vkGetPhysicalDeviceCalibrateableTimeDomainsKHR",
+ "vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR",
"vkGetPhysicalDeviceDisplayPlaneProperties2KHR",
"vkGetPhysicalDeviceDisplayProperties2KHR",
"vkGetPhysicalDeviceExternalBufferProperties",
@@ -703,6 +705,7 @@
"vkGetPhysicalDeviceToolProperties",
"vkGetPhysicalDeviceToolPropertiesEXT",
"vkGetPhysicalDeviceVideoCapabilitiesKHR",
+ "vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR",
"vkGetPhysicalDeviceVideoFormatPropertiesKHR",
"vkSubmitDebugUtilsMessageEXT",
};
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 9e67725..00e987f 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1473,23 +1473,14 @@
image_format_properties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
image_format_properties.pNext = &ahb_usage;
- if (instance_dispatch.GetPhysicalDeviceImageFormatProperties2) {
- VkResult result = instance_dispatch.GetPhysicalDeviceImageFormatProperties2(
- pdev, &image_format_info, &image_format_properties);
- if (result != VK_SUCCESS) {
- ALOGE("VkGetPhysicalDeviceImageFormatProperties2 for AHB usage failed: %d", result);
- return VK_ERROR_SURFACE_LOST_KHR;
- }
- }
- else {
- VkResult result = instance_dispatch.GetPhysicalDeviceImageFormatProperties2KHR(
- pdev, &image_format_info,
- &image_format_properties);
- if (result != VK_SUCCESS) {
- ALOGE("VkGetPhysicalDeviceImageFormatProperties2KHR for AHB usage failed: %d",
- result);
- return VK_ERROR_SURFACE_LOST_KHR;
- }
+ VkResult result = GetPhysicalDeviceImageFormatProperties2(
+ pdev, &image_format_info, &image_format_properties);
+ if (result != VK_SUCCESS) {
+ ALOGE(
+ "VkGetPhysicalDeviceImageFormatProperties2 for AHB usage "
+ "failed: %d",
+ result);
+ return VK_ERROR_SURFACE_LOST_KHR;
}
// Determine if USAGE_FRONT_BUFFER is needed.
diff --git a/vulkan/scripts/generator_common.py b/vulkan/scripts/generator_common.py
index 866c1b7..6b4cbad 100644
--- a/vulkan/scripts/generator_common.py
+++ b/vulkan/scripts/generator_common.py
@@ -351,9 +351,50 @@
'external', 'vulkan-headers', 'registry', 'vk.xml')
tree = element_tree.parse(registry)
root = tree.getroot()
+
+ for exts in root.iter('extensions'):
+ for extension in exts.iter('extension'):
+ if 'vulkan' not in extension.get('supported').split(','):
+ # ANDROID_native_buffer is a weird special case -- it's declared in vk.xml as
+ # disabled but we _do_ want to generate plumbing for it in the Android loader.
+ if extension.get('name') != 'VK_ANDROID_native_buffer':
+ print('skip extension disabled or not for vulkan: ' + extension.get('name'))
+ continue
+
+ apiversion = 'VK_VERSION_1_0'
+ if extension.tag == 'extension':
+ extname = extension.get('name')
+ if (extension.get('type') == 'instance' and
+ extension.get('promotedto') is not None):
+ promoted_inst_ext_dict[extname] = \
+ version_2_api_version(extension.get('promotedto'))
+ for req in extension.iter('require'):
+ if req.get('feature') is not None:
+ apiversion = req.get('feature')
+ for commands in req:
+ if commands.tag == 'command':
+ cmd_name = commands.get('name')
+ if cmd_name not in extension_dict:
+ extension_dict[cmd_name] = extname
+ version_dict[cmd_name] = apiversion
+
+ for feature in root.iter('feature'):
+ if 'vulkan' not in feature.get('api').split(','):
+ continue
+
+ apiversion = feature.get('name')
+ for req in feature.iter('require'):
+ for command in req:
+ if command.tag == 'command':
+ cmd_name = command.get('name')
+ version_dict[cmd_name] = apiversion
+
for commands in root.iter('commands'):
for command in commands:
if command.tag == 'command':
+ if command.get('api') == 'vulkansc':
+ continue
+
parameter_list = []
protoset = False
cmd_name = ''
@@ -361,12 +402,18 @@
if command.get('alias') is not None:
alias = command.get('alias')
cmd_name = command.get('name')
- alias_dict[cmd_name] = alias
- command_list.append(cmd_name)
- param_dict[cmd_name] = param_dict[alias].copy()
- return_type_dict[cmd_name] = return_type_dict[alias]
+ # At this stage all valid commands have been added to the version
+ # dict so we can use it to filter valid commands
+ if cmd_name in version_dict:
+ alias_dict[cmd_name] = alias
+ command_list.append(cmd_name)
+ param_dict[cmd_name] = param_dict[alias].copy()
+ return_type_dict[cmd_name] = return_type_dict[alias]
for params in command:
if params.tag == 'param':
+ if params.get('api') == 'vulkansc':
+ # skip SC-only param variant
+ continue
param_type = ''
if params.text is not None and params.text.strip():
param_type = params.text.strip() + ' '
@@ -387,39 +434,13 @@
cmd_type = c.text
if c.tag == 'name':
cmd_name = c.text
- protoset = True
- command_list.append(cmd_name)
- return_type_dict[cmd_name] = cmd_type
+ if cmd_name in version_dict:
+ protoset = True
+ command_list.append(cmd_name)
+ return_type_dict[cmd_name] = cmd_type
if protoset:
param_dict[cmd_name] = parameter_list.copy()
- for exts in root.iter('extensions'):
- for extension in exts:
- apiversion = 'VK_VERSION_1_0'
- if extension.tag == 'extension':
- extname = extension.get('name')
- if (extension.get('type') == 'instance' and
- extension.get('promotedto') is not None):
- promoted_inst_ext_dict[extname] = \
- version_2_api_version(extension.get('promotedto'))
- for req in extension:
- if req.get('feature') is not None:
- apiversion = req.get('feature')
- for commands in req:
- if commands.tag == 'command':
- cmd_name = commands.get('name')
- if cmd_name not in extension_dict:
- extension_dict[cmd_name] = extname
- version_dict[cmd_name] = apiversion
-
- for feature in root.iter('feature'):
- apiversion = feature.get('name')
- for req in feature:
- for command in req:
- if command.tag == 'command':
- cmd_name = command.get('name')
- if cmd_name in command_list:
- version_dict[cmd_name] = apiversion
version_code_set = set()
for version in version_dict.values():
diff --git a/vulkan/scripts/null_generator.py b/vulkan/scripts/null_generator.py
index e9faef6..3624c1d 100644
--- a/vulkan/scripts/null_generator.py
+++ b/vulkan/scripts/null_generator.py
@@ -89,6 +89,8 @@
f.write(gencom.copyright_and_warning(2015))
f.write("""\
+#include <android/hardware_buffer.h>
+
#include <algorithm>
#include "null_driver_gen.h"