Merge "Fix region sampling for secure layers" into main
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index cd4926a..4160a72 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -68,6 +68,7 @@
const char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
const char* k_userInitiatedTraceProperty = "debug.atrace.user_initiated";
+const char* k_tracePreferSdkProperty = "debug.atrace.prefer_sdk";
const char* k_traceAppsNumberProperty = "debug.atrace.app_number";
const char* k_traceAppsPropertyTemplate = "debug.atrace.app_%d";
const char* k_coreServiceCategory = "core_services";
@@ -600,6 +601,17 @@
}
}
+// Set the property that's read by userspace to prefer the perfetto SDK.
+static bool setPreferSdkProperty(uint64_t tags)
+{
+ std::string value = android::base::StringPrintf("%#" PRIx64, tags);
+ if (!android::base::SetProperty(k_tracePreferSdkProperty, value)) {
+ fprintf(stderr, "error setting prefer_sdk system property\n");
+ return false;
+ }
+ return true;
+}
+
// Set the system property that indicates which apps should perform
// application-level tracing.
static bool setAppCmdlineProperty(char* cmdline)
@@ -918,6 +930,17 @@
setTracingEnabled(false);
}
+static bool preferSdkCategories() {
+ uint64_t tags = 0;
+ for (size_t i = 0; i < arraysize(k_categories); i++) {
+ if (g_categoryEnables[i]) {
+ const TracingCategory& c = k_categories[i];
+ tags |= c.tags;
+ }
+ }
+ return setPreferSdkProperty(tags);
+}
+
// Read data from the tracing pipe and forward to stdout
static void streamTrace()
{
@@ -1108,6 +1131,9 @@
" CPU performance, like pagecache usage.\n"
" --list_categories\n"
" list the available tracing categories\n"
+ " --prefer_sdk\n"
+ " prefer the perfetto sdk over legacy atrace for\n"
+ " categories and exits immediately\n"
" -o filename write the trace to the specified file instead\n"
" of stdout.\n"
);
@@ -1252,6 +1278,7 @@
bool traceStop = true;
bool traceDump = true;
bool traceStream = false;
+ bool preferSdk = false;
bool onlyUserspace = false;
if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
@@ -1276,6 +1303,7 @@
{"only_userspace", no_argument, nullptr, 0 },
{"list_categories", no_argument, nullptr, 0 },
{"stream", no_argument, nullptr, 0 },
+ {"prefer_sdk", no_argument, nullptr, 0 },
{nullptr, 0, nullptr, 0 }
};
@@ -1348,6 +1376,8 @@
} else if (!strcmp(long_options[option_index].name, "stream")) {
traceStream = true;
traceDump = false;
+ } else if (!strcmp(long_options[option_index].name, "prefer_sdk")) {
+ preferSdk = true;
} else if (!strcmp(long_options[option_index].name, "list_categories")) {
listSupportedCategories();
exit(0);
@@ -1362,6 +1392,11 @@
}
}
+ if (preferSdk) {
+ bool res = preferSdkCategories();
+ exit(res ? 0 : 1);
+ }
+
if (onlyUserspace) {
if (!async || !(traceStart || traceStop)) {
fprintf(stderr, "--only_userspace can only be used with "
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 6548810..b26a194 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -275,7 +275,7 @@
* Return DEAD_OBJECT if the channel's peer has been closed.
* Other errors probably indicate that the channel is broken.
*/
- status_t receiveMessage(InputMessage* msg);
+ android::base::Result<InputMessage> receiveMessage();
/* Tells whether there is a message in the channel available to be received.
*
diff --git a/include/input/VirtualInputDevice.h b/include/input/VirtualInputDevice.h
index 222dac8..9bbaa0c 100644
--- a/include/input/VirtualInputDevice.h
+++ b/include/input/VirtualInputDevice.h
@@ -122,4 +122,11 @@
bool handleStylusUp(uint16_t tool, std::chrono::nanoseconds eventTime);
};
+class VirtualRotaryEncoder : public VirtualInputDevice {
+public:
+ VirtualRotaryEncoder(android::base::unique_fd fd);
+ virtual ~VirtualRotaryEncoder() override;
+ bool writeScrollEvent(float scrollAmount, std::chrono::nanoseconds eventTime);
+};
+
} // namespace android
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index bd6a08e..1c8aa37 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -457,8 +457,10 @@
name: "libbinder_kernel_defaults",
srcs: [
"BufferedTextOutput.cpp",
+ "BackendUnifiedServiceManager.cpp",
"IPCThreadState.cpp",
"IServiceManager.cpp",
+ "IServiceManagerFFI.cpp",
"ProcessState.cpp",
"Static.cpp",
":libbinder_aidl",
@@ -534,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/Functional.h b/libs/binder/include/binder/Functional.h
index 08e3b21..bb0e5f4 100644
--- a/libs/binder/include/binder/Functional.h
+++ b/libs/binder/include/binder/Functional.h
@@ -17,11 +17,38 @@
#pragma once
#include <functional>
-#include <memory>
+#include <optional>
namespace android::binder::impl {
template <typename F>
+class scope_guard;
+
+template <typename F>
+scope_guard<F> make_scope_guard(F f);
+
+template <typename F>
+class scope_guard {
+public:
+ inline ~scope_guard() {
+ if (f_.has_value()) std::move(f_.value())();
+ }
+ inline void release() { f_.reset(); }
+
+private:
+ friend scope_guard<F> android::binder::impl::make_scope_guard(F);
+
+ inline scope_guard(F&& f) : f_(std::move(f)) {}
+
+ std::optional<F> f_;
+};
+
+template <typename F>
+inline scope_guard<F> make_scope_guard(F f) {
+ return scope_guard<F>(std::move(f));
+}
+
+template <typename F>
constexpr void assert_small_callable() {
// While this buffer (std::function::__func::__buf_) is an implementation detail generally not
// accessible to users, it's a good bet to assume its size to be around 3 pointers.
@@ -32,12 +59,6 @@
"Try using std::ref, but make sure lambda lives long enough to be called.");
}
-template <typename F>
-std::unique_ptr<void, std::function<void(void*)>> make_scope_guard(F&& f) {
- assert_small_callable<decltype(std::bind(f))>();
- return {reinterpret_cast<void*>(true), std::bind(f)};
-}
-
template <typename T>
class SmallFunction : public std::function<T> {
public:
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/input/InputConsumer.cpp b/libs/input/InputConsumer.cpp
index fcf490d..dce528f 100644
--- a/libs/input/InputConsumer.cpp
+++ b/libs/input/InputConsumer.cpp
@@ -235,8 +235,9 @@
mMsgDeferred = false;
} else {
// Receive a fresh message.
- status_t result = mChannel->receiveMessage(&mMsg);
- if (result == OK) {
+ android::base::Result<InputMessage> result = mChannel->receiveMessage();
+ if (result.ok()) {
+ mMsg = std::move(result.value());
const auto [_, inserted] =
mConsumeTimes.emplace(mMsg.header.seq, systemTime(SYSTEM_TIME_MONOTONIC));
LOG_ALWAYS_FATAL_IF(!inserted, "Already have a consume time for seq=%" PRIu32,
@@ -244,11 +245,11 @@
// Trace the event processing timeline - event was just read from the socket
ATRACE_ASYNC_BEGIN(mProcessingTraceTag.c_str(), /*cookie=*/mMsg.header.seq);
- }
- if (result) {
+ } else {
// Consume the next batched event unless batches are being held for later.
- if (consumeBatches || result != WOULD_BLOCK) {
- result = consumeBatch(factory, frameTime, outSeq, outEvent);
+ if (consumeBatches || result.error().code() != WOULD_BLOCK) {
+ result = android::base::Error(
+ consumeBatch(factory, frameTime, outSeq, outEvent));
if (*outEvent) {
ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
"channel '%s' consumer ~ consumed batch event, seq=%u",
@@ -256,7 +257,7 @@
break;
}
}
- return result;
+ return result.error().code();
}
}
diff --git a/libs/input/InputConsumerNoResampling.cpp b/libs/input/InputConsumerNoResampling.cpp
index 15d992f..e193983 100644
--- a/libs/input/InputConsumerNoResampling.cpp
+++ b/libs/input/InputConsumerNoResampling.cpp
@@ -362,36 +362,36 @@
std::vector<InputMessage> InputConsumerNoResampling::readAllMessages() {
std::vector<InputMessage> messages;
while (true) {
- InputMessage msg;
- status_t result = mChannel->receiveMessage(&msg);
- switch (result) {
- case OK: {
- const auto [_, inserted] =
- mConsumeTimes.emplace(msg.header.seq, systemTime(SYSTEM_TIME_MONOTONIC));
- LOG_ALWAYS_FATAL_IF(!inserted, "Already have a consume time for seq=%" PRIu32,
- msg.header.seq);
+ android::base::Result<InputMessage> result = mChannel->receiveMessage();
+ if (result.ok()) {
+ const InputMessage& msg = *result;
+ const auto [_, inserted] =
+ mConsumeTimes.emplace(msg.header.seq, systemTime(SYSTEM_TIME_MONOTONIC));
+ LOG_ALWAYS_FATAL_IF(!inserted, "Already have a consume time for seq=%" PRIu32,
+ msg.header.seq);
- // Trace the event processing timeline - event was just read from the socket
- // TODO(b/329777420): distinguish between multiple instances of InputConsumer
- // in the same process.
- ATRACE_ASYNC_BEGIN("InputConsumer processing", /*cookie=*/msg.header.seq);
- messages.push_back(msg);
- break;
- }
- case WOULD_BLOCK: {
- return messages;
- }
- case DEAD_OBJECT: {
- LOG(FATAL) << "Got a dead object for " << mChannel->getName();
- break;
- }
- case BAD_VALUE: {
- LOG(FATAL) << "Got a bad value for " << mChannel->getName();
- break;
- }
- default: {
- LOG(FATAL) << "Unexpected error: " << result;
- break;
+ // Trace the event processing timeline - event was just read from the socket
+ // TODO(b/329777420): distinguish between multiple instances of InputConsumer
+ // in the same process.
+ ATRACE_ASYNC_BEGIN("InputConsumer processing", /*cookie=*/msg.header.seq);
+ messages.push_back(msg);
+ } else { // !result.ok()
+ switch (result.error().code()) {
+ case WOULD_BLOCK: {
+ return messages;
+ }
+ case DEAD_OBJECT: {
+ LOG(FATAL) << "Got a dead object for " << mChannel->getName();
+ break;
+ }
+ case BAD_VALUE: {
+ LOG(FATAL) << "Got a bad value for " << mChannel->getName();
+ break;
+ }
+ default: {
+ LOG(FATAL) << "Unexpected error: " << result.error().message();
+ break;
+ }
}
}
}
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 47b4228..bac681d 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -424,10 +424,11 @@
return OK;
}
-status_t InputChannel::receiveMessage(InputMessage* msg) {
+android::base::Result<InputMessage> InputChannel::receiveMessage() {
ssize_t nRead;
+ InputMessage msg;
do {
- nRead = ::recv(getFd(), msg, sizeof(InputMessage), MSG_DONTWAIT);
+ nRead = ::recv(getFd(), &msg, sizeof(InputMessage), MSG_DONTWAIT);
} while (nRead == -1 && errno == EINTR);
if (nRead < 0) {
@@ -435,36 +436,36 @@
ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ receive message failed, errno=%d",
name.c_str(), errno);
if (error == EAGAIN || error == EWOULDBLOCK) {
- return WOULD_BLOCK;
+ return android::base::Error(WOULD_BLOCK);
}
if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED) {
- return DEAD_OBJECT;
+ return android::base::Error(DEAD_OBJECT);
}
- return -error;
+ return android::base::Error(-error);
}
if (nRead == 0) { // check for EOF
ALOGD_IF(DEBUG_CHANNEL_MESSAGES,
"channel '%s' ~ receive message failed because peer was closed", name.c_str());
- return DEAD_OBJECT;
+ return android::base::Error(DEAD_OBJECT);
}
- if (!msg->isValid(nRead)) {
+ if (!msg.isValid(nRead)) {
ALOGE("channel '%s' ~ received invalid message of size %zd", name.c_str(), nRead);
- return BAD_VALUE;
+ return android::base::Error(BAD_VALUE);
}
ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ received message of type %s", name.c_str(),
- ftl::enum_string(msg->header.type).c_str());
+ ftl::enum_string(msg.header.type).c_str());
if (ATRACE_ENABLED()) {
// Add an additional trace point to include data about the received message.
std::string message =
StringPrintf("receiveMessage(inputChannel=%s, seq=0x%" PRIx32 ", type=%s)",
- name.c_str(), msg->header.seq,
- ftl::enum_string(msg->header.type).c_str());
+ name.c_str(), msg.header.seq,
+ ftl::enum_string(msg.header.type).c_str());
ATRACE_NAME(message.c_str());
}
- return OK;
+ return msg;
}
bool InputChannel::probablyHasInput() const {
@@ -729,15 +730,16 @@
}
android::base::Result<InputPublisher::ConsumerResponse> InputPublisher::receiveConsumerResponse() {
- InputMessage msg;
- status_t result = mChannel->receiveMessage(&msg);
- if (result) {
- if (debugTransportPublisher() && result != WOULD_BLOCK) {
+ android::base::Result<InputMessage> result = mChannel->receiveMessage();
+ if (!result.ok()) {
+ if (debugTransportPublisher() && result.error().code() != WOULD_BLOCK) {
LOG(INFO) << "channel '" << mChannel->getName() << "' publisher ~ " << __func__ << ": "
- << strerror(result);
+ << result.error().message();
}
- return android::base::Error(result);
+ return result.error();
}
+
+ const InputMessage& msg = *result;
if (msg.header.type == InputMessage::Type::FINISHED) {
ALOGD_IF(debugTransportPublisher(),
"channel '%s' publisher ~ %s: finished: seq=%u, handled=%s",
diff --git a/libs/input/VirtualInputDevice.cpp b/libs/input/VirtualInputDevice.cpp
index eea06f1..b73ee65 100644
--- a/libs/input/VirtualInputDevice.cpp
+++ b/libs/input/VirtualInputDevice.cpp
@@ -509,4 +509,15 @@
return true;
}
+// --- VirtualRotaryEncoder ---
+VirtualRotaryEncoder::VirtualRotaryEncoder(unique_fd fd) : VirtualInputDevice(std::move(fd)) {}
+
+VirtualRotaryEncoder::~VirtualRotaryEncoder() {}
+
+bool VirtualRotaryEncoder::writeScrollEvent(float scrollAmount,
+ std::chrono::nanoseconds eventTime) {
+ return writeInputEvent(EV_REL, REL_WHEEL, static_cast<int32_t>(scrollAmount), eventTime) &&
+ writeInputEvent(EV_SYN, SYN_REPORT, 0, eventTime);
+}
+
} // namespace android
diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp
index 02d4c07..435bdcd 100644
--- a/libs/input/tests/InputChannel_test.cpp
+++ b/libs/input/tests/InputChannel_test.cpp
@@ -78,9 +78,10 @@
EXPECT_EQ(OK, serverChannel->sendMessage(&serverMsg))
<< "server channel should be able to send message to client channel";
- InputMessage clientMsg;
- EXPECT_EQ(OK, clientChannel->receiveMessage(&clientMsg))
+ android::base::Result<InputMessage> clientMsgResult = clientChannel->receiveMessage();
+ ASSERT_TRUE(clientMsgResult.ok())
<< "client channel should be able to receive message from server channel";
+ const InputMessage& clientMsg = *clientMsgResult;
EXPECT_EQ(serverMsg.header.type, clientMsg.header.type)
<< "client channel should receive the correct message from server channel";
EXPECT_EQ(serverMsg.body.key.action, clientMsg.body.key.action)
@@ -94,9 +95,10 @@
EXPECT_EQ(OK, clientChannel->sendMessage(&clientReply))
<< "client channel should be able to send message to server channel";
- InputMessage serverReply;
- EXPECT_EQ(OK, serverChannel->receiveMessage(&serverReply))
+ android::base::Result<InputMessage> serverReplyResult = serverChannel->receiveMessage();
+ ASSERT_TRUE(serverReplyResult.ok())
<< "server channel should be able to receive message from client channel";
+ const InputMessage& serverReply = *serverReplyResult;
EXPECT_EQ(clientReply.header.type, serverReply.header.type)
<< "server channel should receive the correct message from client channel";
EXPECT_EQ(clientReply.header.seq, serverReply.header.seq)
@@ -134,9 +136,10 @@
<< "client channel should observe that message is available before receiving it";
// Receive (consume) the message.
- InputMessage clientMsg;
- EXPECT_EQ(OK, receiverChannel->receiveMessage(&clientMsg))
+ android::base::Result<InputMessage> clientMsgResult = receiverChannel->receiveMessage();
+ ASSERT_TRUE(clientMsgResult.ok())
<< "client channel should be able to receive message from server channel";
+ const InputMessage& clientMsg = *clientMsgResult;
EXPECT_EQ(serverMsg.header.type, clientMsg.header.type)
<< "client channel should receive the correct message from server channel";
EXPECT_EQ(serverMsg.body.key.action, clientMsg.body.key.action)
@@ -156,8 +159,8 @@
ASSERT_EQ(OK, result)
<< "should have successfully opened a channel pair";
- InputMessage msg;
- EXPECT_EQ(WOULD_BLOCK, clientChannel->receiveMessage(&msg))
+ android::base::Result<InputMessage> msgResult = clientChannel->receiveMessage();
+ EXPECT_EQ(WOULD_BLOCK, msgResult.error().code())
<< "receiveMessage should have returned WOULD_BLOCK";
}
@@ -172,8 +175,8 @@
serverChannel.reset(); // close server channel
- InputMessage msg;
- EXPECT_EQ(DEAD_OBJECT, clientChannel->receiveMessage(&msg))
+ android::base::Result<InputMessage> msgResult = clientChannel->receiveMessage();
+ EXPECT_EQ(DEAD_OBJECT, msgResult.error().code())
<< "receiveMessage should have returned DEAD_OBJECT";
}
@@ -207,7 +210,7 @@
MotionClassification::DEEP_PRESS,
};
- InputMessage serverMsg = {}, clientMsg;
+ InputMessage serverMsg = {};
serverMsg.header.type = InputMessage::Type::MOTION;
serverMsg.header.seq = 1;
serverMsg.body.motion.pointerCount = 1;
@@ -218,11 +221,13 @@
EXPECT_EQ(OK, serverChannel->sendMessage(&serverMsg))
<< "server channel should be able to send message to client channel";
- EXPECT_EQ(OK, clientChannel->receiveMessage(&clientMsg))
+ android::base::Result<InputMessage> clientMsgResult = clientChannel->receiveMessage();
+ ASSERT_TRUE(clientMsgResult.ok())
<< "client channel should be able to receive message from server channel";
+ const InputMessage& clientMsg = *clientMsgResult;
EXPECT_EQ(serverMsg.header.type, clientMsg.header.type);
- EXPECT_EQ(classification, clientMsg.body.motion.classification) <<
- "Expected to receive " << motionClassificationToString(classification);
+ EXPECT_EQ(classification, clientMsg.body.motion.classification)
+ << "Expected to receive " << motionClassificationToString(classification);
}
}
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index c39da95..5f37125 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -525,7 +525,8 @@
static_cast<ui::PixelFormat>(targetBuffer->getPixelFormat()))
: std::nullopt;
- const auto hdrType = getHdrRenderType(parameters.layer.sourceDataspace, format);
+ const auto hdrType = getHdrRenderType(parameters.layer.sourceDataspace, format,
+ parameters.layerDimmingRatio);
const auto usingLocalTonemap =
parameters.display.tonemapStrategy == DisplaySettings::TonemapStrategy::Local &&
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index e76b648..b2f15b4 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -78,6 +78,7 @@
name: "libinputreader_defaults",
srcs: [":libinputreader_sources"],
shared_libs: [
+ "android.companion.virtualdevice.flags-aconfig-cc-host",
"libbase",
"libcap",
"libcrypto",
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 65583e9..643499c 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -33,6 +33,8 @@
#include <sys/sysmacros.h>
#include <unistd.h>
+#include <android_companion_virtualdevice_flags.h>
+
#define LOG_TAG "EventHub"
// #define LOG_NDEBUG 0
@@ -68,6 +70,8 @@
namespace android {
+namespace vd_flags = android::companion::virtualdevice::flags;
+
using namespace ftl::flag_operators;
static const char* DEVICE_INPUT_PATH = "/dev/input";
@@ -2498,6 +2502,12 @@
}
}
+ // See if the device is a rotary encoder with a single scroll axis and nothing else.
+ if (vd_flags::virtual_rotary() && device->classes == ftl::Flags<InputDeviceClass>(0) &&
+ device->relBitmask.test(REL_WHEEL) && !device->relBitmask.test(REL_HWHEEL)) {
+ device->classes |= InputDeviceClass::ROTARY_ENCODER;
+ }
+
// If the device isn't recognized as something we handle, don't monitor it.
if (device->classes == ftl::Flags<InputDeviceClass>(0)) {
ALOGV("Dropping device: id=%d, path='%s', name='%s'", deviceId, devicePath.c_str(),
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 7fd5597..086c26f 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -308,6 +308,7 @@
inline status_t getAbsoluteAxisInfo(int32_t code, RawAbsoluteAxisInfo* axisInfo) const {
std::optional<RawAbsoluteAxisInfo> info = mEventHub->getAbsoluteAxisInfo(mId, code);
if (!info.has_value()) {
+ axisInfo->clear();
return NAME_NOT_FOUND;
}
*axisInfo = *info;
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
index 27ff52f..20fd359 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
@@ -84,12 +84,18 @@
}
}
if (!changes.any() || changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) {
- std::optional<DisplayViewport> internalViewport =
- config.getDisplayViewportByType(ViewportType::INTERNAL);
- if (internalViewport) {
- mOrientation = internalViewport->orientation;
+ if (getDeviceContext().getAssociatedViewport()) {
+ mDisplayId = getDeviceContext().getAssociatedViewport()->displayId;
+ mOrientation = getDeviceContext().getAssociatedViewport()->orientation;
} else {
- mOrientation = ui::ROTATION_0;
+ mDisplayId = ui::LogicalDisplayId::INVALID;
+ std::optional<DisplayViewport> internalViewport =
+ config.getDisplayViewportByType(ViewportType::INTERNAL);
+ if (internalViewport) {
+ mOrientation = internalViewport->orientation;
+ } else {
+ mOrientation = ui::ROTATION_0;
+ }
}
}
return out;
@@ -124,8 +130,6 @@
// Send motion event.
if (scrolled) {
int32_t metaState = getContext()->getGlobalMetaState();
- // This is not a pointer, so it's not associated with a display.
- ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID;
if (mOrientation == ui::ROTATION_180) {
scroll = -scroll;
@@ -147,7 +151,7 @@
out.push_back(
NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0,
+ mDisplayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0,
metaState, /*buttonState=*/0, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
&pointerCoords, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
index 14c540b..7e80415 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
@@ -47,6 +47,7 @@
int32_t mSource;
float mScalingFactor;
ui::Rotation mOrientation;
+ ui::LogicalDisplayId mDisplayId = ui::LogicalDisplayId::INVALID;
std::unique_ptr<SlopController> mSlopController;
explicit RotaryEncoderInputMapper(InputDeviceContext& deviceContext,
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index cf0d46a..bddf43e 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -76,6 +76,7 @@
"PointerChoreographer_test.cpp",
"PreferStylusOverTouch_test.cpp",
"PropertyProvider_test.cpp",
+ "RotaryEncoderInputMapper_test.cpp",
"SlopController_test.cpp",
"SyncQueue_test.cpp",
"TimerProvider_test.cpp",
diff --git a/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp b/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp
new file mode 100644
index 0000000..94cfc32
--- /dev/null
+++ b/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright 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 "RotaryEncoderInputMapper.h"
+
+#include <list>
+#include <string>
+#include <tuple>
+#include <variant>
+
+#include <android-base/logging.h>
+#include <gtest/gtest.h>
+#include <input/DisplayViewport.h>
+#include <linux/input-event-codes.h>
+#include <linux/input.h>
+#include <utils/Timers.h>
+
+#include "InputMapperTest.h"
+#include "InputReaderBase.h"
+#include "InterfaceMocks.h"
+#include "NotifyArgs.h"
+#include "TestEventMatchers.h"
+#include "ui/Rotation.h"
+
+#define TAG "RotaryEncoderInputMapper_test"
+
+namespace android {
+
+using testing::AllOf;
+using testing::Return;
+using testing::VariantWith;
+constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
+constexpr ui::LogicalDisplayId SECONDARY_DISPLAY_ID = ui::LogicalDisplayId{DISPLAY_ID.val() + 1};
+constexpr int32_t DISPLAY_WIDTH = 480;
+constexpr int32_t DISPLAY_HEIGHT = 800;
+
+namespace {
+
+DisplayViewport createViewport() {
+ DisplayViewport v;
+ v.orientation = ui::Rotation::Rotation0;
+ v.logicalRight = DISPLAY_HEIGHT;
+ v.logicalBottom = DISPLAY_WIDTH;
+ v.physicalRight = DISPLAY_HEIGHT;
+ v.physicalBottom = DISPLAY_WIDTH;
+ v.deviceWidth = DISPLAY_HEIGHT;
+ v.deviceHeight = DISPLAY_WIDTH;
+ v.isActive = true;
+ return v;
+}
+
+DisplayViewport createPrimaryViewport() {
+ DisplayViewport v = createViewport();
+ v.displayId = DISPLAY_ID;
+ v.uniqueId = "local:1";
+ return v;
+}
+
+DisplayViewport createSecondaryViewport() {
+ DisplayViewport v = createViewport();
+ v.displayId = SECONDARY_DISPLAY_ID;
+ v.uniqueId = "local:2";
+ v.type = ViewportType::EXTERNAL;
+ return v;
+}
+
+/**
+ * A fake InputDeviceContext that allows the associated viewport to be specified for the mapper.
+ *
+ * This is currently necessary because InputMapperUnitTest doesn't register the mappers it creates
+ * with the InputDevice object, meaning that InputDevice::isIgnored becomes true, and the input
+ * device doesn't set its associated viewport when it's configured.
+ *
+ * TODO(b/319217713): work out a way to avoid this fake.
+ */
+class ViewportFakingInputDeviceContext : public InputDeviceContext {
+public:
+ ViewportFakingInputDeviceContext(InputDevice& device, int32_t eventHubId,
+ std::optional<DisplayViewport> viewport)
+ : InputDeviceContext(device, eventHubId), mAssociatedViewport(viewport) {}
+
+ ViewportFakingInputDeviceContext(InputDevice& device, int32_t eventHubId)
+ : ViewportFakingInputDeviceContext(device, eventHubId, createPrimaryViewport()) {}
+
+ std::optional<DisplayViewport> getAssociatedViewport() const override {
+ return mAssociatedViewport;
+ }
+
+ void setViewport(const std::optional<DisplayViewport>& viewport) {
+ mAssociatedViewport = viewport;
+ }
+
+private:
+ std::optional<DisplayViewport> mAssociatedViewport;
+};
+
+} // namespace
+
+/**
+ * Unit tests for RotaryEncoderInputMapper.
+ */
+class RotaryEncoderInputMapperTest : public InputMapperUnitTest {
+protected:
+ void SetUp() override { SetUpWithBus(BUS_USB); }
+ void SetUpWithBus(int bus) override {
+ InputMapperUnitTest::SetUpWithBus(bus);
+
+ EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL))
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL))
+ .WillRepeatedly(Return(false));
+ }
+};
+
+TEST_F(RotaryEncoderInputMapperTest, ConfigureDisplayIdWithAssociatedViewport) {
+ DisplayViewport primaryViewport = createPrimaryViewport();
+ DisplayViewport secondaryViewport = createSecondaryViewport();
+ mReaderConfiguration.setDisplayViewports({primaryViewport, secondaryViewport});
+
+ // Set up the secondary display as the associated viewport of the mapper.
+ createDevice();
+ ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, secondaryViewport);
+ mMapper = createInputMapper<RotaryEncoderInputMapper>(deviceContext, mReaderConfiguration);
+
+ std::list<NotifyArgs> args;
+ // Ensure input events are generated for the secondary display.
+ args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL, 1);
+ args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
+ EXPECT_THAT(args,
+ ElementsAre(VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
+ WithSource(AINPUT_SOURCE_ROTARY_ENCODER),
+ WithDisplayId(SECONDARY_DISPLAY_ID)))));
+}
+
+TEST_F(RotaryEncoderInputMapperTest, ConfigureDisplayIdNoAssociatedViewport) {
+ // Set up the default display.
+ mFakePolicy->clearViewports();
+ mFakePolicy->addDisplayViewport(createPrimaryViewport());
+
+ // Set up the mapper with no associated viewport.
+ createDevice();
+ mMapper = createInputMapper<RotaryEncoderInputMapper>(*mDeviceContext, mReaderConfiguration);
+
+ // Ensure input events are generated without display ID
+ std::list<NotifyArgs> args;
+ args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL, 1);
+ args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
+ EXPECT_THAT(args,
+ ElementsAre(VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
+ WithSource(AINPUT_SOURCE_ROTARY_ENCODER),
+ WithDisplayId(ui::LogicalDisplayId::INVALID)))));
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 13a1464..e65efc5 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/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/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",