Merge "Suppress logcat error messages when frame timestamp is not found" into main
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 6576ffd..c407f48 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -170,6 +170,7 @@
#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
#define BLK_DEV_SYS_DIR "/sys/block"
+#define AFLAGS "/system/bin/aflags"
#define RECOVERY_DIR "/cache/recovery"
#define RECOVERY_DATA_DIR "/data/misc/recovery"
#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
@@ -1785,6 +1786,10 @@
RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
CommandOptions::WithTimeout(10).Always().DropRoot().Build());
+ RunCommand("ACONFIG FLAGS DUMP", {AFLAGS, "list"},
+ CommandOptions::WithTimeout(10).Always().AsRootIfAvailable().Build());
+ RunCommand("WHICH ACONFIG FLAG STORAGE", {AFLAGS, "which-backing"},
+ CommandOptions::WithTimeout(10).Always().AsRootIfAvailable().Build());
RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp
index 319716e..cbba711 100644
--- a/libs/arect/Android.bp
+++ b/libs/arect/Android.bp
@@ -40,6 +40,7 @@
cc_library_headers {
name: "libarect_headers",
+ host_supported: true,
vendor_available: true,
min_sdk_version: "29",
// TODO(b/153609531): remove when no longer needed.
diff --git a/libs/binder/BackendUnifiedServiceManager.cpp b/libs/binder/BackendUnifiedServiceManager.cpp
index 5680798..52b485a 100644
--- a/libs/binder/BackendUnifiedServiceManager.cpp
+++ b/libs/binder/BackendUnifiedServiceManager.cpp
@@ -34,37 +34,47 @@
using IAccessor = android::os::IAccessor;
static const char* kStaticCachableList[] = {
+ // go/keep-sorted start
+ "accessibility",
+ "account",
"activity",
- "android.hardware.thermal.IThermal/default",
- "android.hardware.power.IPower/default",
- "android.frameworks.stats.IStats/default",
- "android.system.suspend.ISystemSuspend/default",
+ "alarm",
+ "android.system.keystore2.IKeystoreService/default",
"appops",
"audio",
"batterystats",
"carrier_config",
"connectivity",
+ "content",
"content_capture",
"device_policy",
"display",
"dropbox",
"econtroller",
+ "graphicsstats",
+ "input",
+ "input_method",
"isub",
+ "jobscheduler",
"legacy_permission",
"location",
"media.extractor",
"media.metrics",
"media.player",
"media.resource_manager",
+ "media_resource_monitor",
+ "mount",
"netd_listener",
"netstats",
"network_management",
"nfc",
+ "notification",
+ "package",
"package_native",
"performance_hint",
"permission",
- "permissionmgr",
"permission_checker",
+ "permissionmgr",
"phone",
"platform_compat",
"power",
@@ -76,9 +86,12 @@
"time_detector",
"trust",
"uimode",
+ "user",
"virtualdevice",
"virtualdevice_native",
"webviewupdate",
+ "window",
+ // go/keep-sorted end
};
bool BinderCacheWithInvalidation::isClientSideCachingEnabled(const std::string& serviceName) {
diff --git a/libs/binder/FdTrigger.cpp b/libs/binder/FdTrigger.cpp
index f0aa801..7263e23 100644
--- a/libs/binder/FdTrigger.cpp
+++ b/libs/binder/FdTrigger.cpp
@@ -108,7 +108,7 @@
// POLLNVAL: invalid FD number, e.g. not opened.
if (pfd[0].revents & POLLNVAL) {
- ALOGE("Invalid FD number (%d) in FdTrigger (POLLNVAL)", pfd[0].fd);
+ LOG_ALWAYS_FATAL("Invalid FD number (%d) in FdTrigger (POLLNVAL)", pfd[0].fd);
return BAD_VALUE;
}
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 1d26d85..6698d0c 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -232,6 +232,15 @@
return cmd;
}
+static void printReturnCommandParcel(std::ostream& out, const Parcel& parcel) {
+ const void* cmds = parcel.data();
+ out << "\t" << HexDump(cmds, parcel.dataSize()) << "\n";
+ IF_LOG_COMMANDS() {
+ const void* end = parcel.data() + parcel.dataSize();
+ while (cmds < end) cmds = printReturnCommand(out, cmds);
+ }
+}
+
static const void* printCommand(std::ostream& out, const void* _cmd) {
static const size_t N = sizeof(kCommandStrings)/sizeof(kCommandStrings[0]);
const int32_t* cmd = (const int32_t*)_cmd;
@@ -1235,13 +1244,15 @@
if (err >= NO_ERROR) {
if (bwr.write_consumed > 0) {
- if (bwr.write_consumed < mOut.dataSize())
+ if (bwr.write_consumed < mOut.dataSize()) {
+ std::ostringstream logStream;
+ printReturnCommandParcel(logStream, mIn);
LOG_ALWAYS_FATAL("Driver did not consume write buffer. "
- "err: %s consumed: %zu of %zu",
- statusToString(err).c_str(),
- (size_t)bwr.write_consumed,
- mOut.dataSize());
- else {
+ "err: %s consumed: %zu of %zu.\n"
+ "Return command: %s",
+ statusToString(err).c_str(), (size_t)bwr.write_consumed,
+ mOut.dataSize(), logStream.str().c_str());
+ } else {
mOut.setDataSize(0);
processPostWriteDerefs();
}
@@ -1252,14 +1263,8 @@
}
IF_LOG_COMMANDS() {
std::ostringstream logStream;
- logStream << "Remaining data size: " << mOut.dataSize() << "\n";
- logStream << "Received commands from driver: ";
- const void* cmds = mIn.data();
- const void* end = mIn.data() + mIn.dataSize();
- logStream << "\t" << HexDump(cmds, mIn.dataSize()) << "\n";
- while (cmds < end) cmds = printReturnCommand(logStream, cmds);
- std::string message = logStream.str();
- ALOGI("%s", message.c_str());
+ printReturnCommandParcel(logStream, mIn);
+ ALOGI("%s", logStream.str().c_str());
}
return NO_ERROR;
}
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 88761d7..77b80ef 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -157,12 +157,21 @@
class AccessorProvider {
public:
- AccessorProvider(RpcAccessorProvider&& provider) : mProvider(std::move(provider)) {}
- sp<IBinder> provide(const String16& name) { return mProvider(name); }
+ AccessorProvider(std::set<std::string>&& instances, RpcAccessorProvider&& provider)
+ : mInstances(std::move(instances)), mProvider(std::move(provider)) {}
+ sp<IBinder> provide(const String16& name) {
+ if (mInstances.count(String8(name).c_str()) > 0) {
+ return mProvider(name);
+ } else {
+ return nullptr;
+ }
+ }
+ const std::set<std::string>& instances() { return mInstances; }
private:
AccessorProvider() = delete;
+ std::set<std::string> mInstances;
RpcAccessorProvider mProvider;
};
@@ -318,10 +327,32 @@
return sp<CppBackendShim>::make(sp<BackendUnifiedServiceManager>::make(sm));
}
-std::weak_ptr<AccessorProvider> addAccessorProvider(RpcAccessorProvider&& providerCallback) {
+// gAccessorProvidersMutex must be locked already
+static bool isInstanceProvidedLocked(const std::string& instance) {
+ return gAccessorProviders.end() !=
+ std::find_if(gAccessorProviders.begin(), gAccessorProviders.end(),
+ [&instance](const AccessorProviderEntry& entry) {
+ return entry.mProvider->instances().count(instance) > 0;
+ });
+}
+
+std::weak_ptr<AccessorProvider> addAccessorProvider(std::set<std::string>&& instances,
+ RpcAccessorProvider&& providerCallback) {
+ if (instances.empty()) {
+ ALOGE("Set of instances is empty! Need a non empty set of instances to provide for.");
+ return std::weak_ptr<AccessorProvider>();
+ }
std::lock_guard<std::mutex> lock(gAccessorProvidersMutex);
+ for (const auto& instance : instances) {
+ if (isInstanceProvidedLocked(instance)) {
+ ALOGE("The instance %s is already provided for by a previously added "
+ "RpcAccessorProvider.",
+ instance.c_str());
+ return std::weak_ptr<AccessorProvider>();
+ }
+ }
std::shared_ptr<AccessorProvider> provider =
- std::make_shared<AccessorProvider>(std::move(providerCallback));
+ std::make_shared<AccessorProvider>(std::move(instances), std::move(providerCallback));
std::weak_ptr<AccessorProvider> receipt = provider;
gAccessorProviders.push_back(AccessorProviderEntry(std::move(provider)));
@@ -331,8 +362,9 @@
status_t removeAccessorProvider(std::weak_ptr<AccessorProvider> wProvider) {
std::shared_ptr<AccessorProvider> provider = wProvider.lock();
if (provider == nullptr) {
- ALOGE("The provider supplied to removeAccessorProvider has already been removed.");
- return NAME_NOT_FOUND;
+ ALOGE("The provider supplied to removeAccessorProvider has already been removed or the "
+ "argument to this function was nullptr.");
+ return BAD_VALUE;
}
std::lock_guard<std::mutex> lock(gAccessorProvidersMutex);
size_t sizeBefore = gAccessorProviders.size();
diff --git a/libs/binder/OS.h b/libs/binder/OS.h
index 04869a1..64b1fd4 100644
--- a/libs/binder/OS.h
+++ b/libs/binder/OS.h
@@ -27,6 +27,7 @@
LIBBINDER_EXPORTED void trace_begin(uint64_t tag, const char* name);
LIBBINDER_EXPORTED void trace_end(uint64_t tag);
LIBBINDER_EXPORTED void trace_int(uint64_t tag, const char* name, int32_t value);
+LIBBINDER_EXPORTED uint64_t get_trace_enabled_tags();
status_t setNonBlocking(borrowed_fd fd);
diff --git a/libs/binder/OS_android.cpp b/libs/binder/OS_android.cpp
index 893ee15..4e9230c 100644
--- a/libs/binder/OS_android.cpp
+++ b/libs/binder/OS_android.cpp
@@ -48,6 +48,10 @@
atrace_int(tag, name, value);
}
+uint64_t get_trace_enabled_tags() {
+ return atrace_enabled_tags;
+}
+
} // namespace os
// Legacy trace symbol. To be removed once all of downstream rebuilds.
diff --git a/libs/binder/OS_non_android_linux.cpp b/libs/binder/OS_non_android_linux.cpp
index 0c64eb6..6bba823 100644
--- a/libs/binder/OS_non_android_linux.cpp
+++ b/libs/binder/OS_non_android_linux.cpp
@@ -41,6 +41,10 @@
void trace_int(uint64_t, const char*, int32_t) {}
+uint64_t get_trace_enabled_tags() {
+ return 0;
+}
+
uint64_t GetThreadId() {
return syscall(__NR_gettid);
}
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 879f319..2b23276 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -24,6 +24,7 @@
#include <utils/String16.h>
#include <utils/Vector.h>
#include <optional>
+#include <set>
namespace android {
@@ -224,20 +225,36 @@
typedef std::function<status_t(const String16& name, sockaddr* outAddr, socklen_t addrSize)>
RpcSocketAddressProvider;
-typedef std::function<sp<IBinder>(const String16& name)> RpcAccessorProvider;
+/**
+ * This callback provides a way for clients to get access to remote services by
+ * providing an Accessor object from libbinder that can connect to the remote
+ * service over sockets.
+ *
+ * \param instance name of the service that the callback will provide an
+ * Accessor for. The provided accessor will be used to set up a client
+ * RPC connection in libbinder in order to return a binder for the
+ * associated remote service.
+ *
+ * \return IBinder of the Accessor object that libbinder implements.
+ * nullptr if the provider callback doesn't know how to reach the
+ * service or doesn't want to provide access for any other reason.
+ */
+typedef std::function<sp<IBinder>(const String16& instance)> RpcAccessorProvider;
class AccessorProvider;
/**
- * Register an accessor provider for the service manager APIs.
+ * Register a RpcAccessorProvider for the service manager APIs.
*
+ * \param instances that the RpcAccessorProvider knows about and can provide an
+ * Accessor for.
* \param provider callback that generates Accessors.
*
* \return A pointer used as a recept for the successful addition of the
* AccessorProvider. This is needed to unregister it later.
*/
[[nodiscard]] LIBBINDER_EXPORTED std::weak_ptr<AccessorProvider> addAccessorProvider(
- RpcAccessorProvider&& providerCallback);
+ std::set<std::string>&& instances, RpcAccessorProvider&& providerCallback);
/**
* Remove an accessor provider using the pointer provided by addAccessorProvider
diff --git a/libs/binder/include/binder/Trace.h b/libs/binder/include/binder/Trace.h
index 2f450cb..a3e6c8a 100644
--- a/libs/binder/include/binder/Trace.h
+++ b/libs/binder/include/binder/Trace.h
@@ -42,6 +42,7 @@
void trace_begin(uint64_t tag, const char* name);
void trace_end(uint64_t tag);
void trace_int(uint64_t tag, const char* name, int32_t value);
+uint64_t get_trace_enabled_tags();
} // namespace os
class LIBBINDER_EXPORTED ScopedTrace {
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 5f45cb2..a7423b3 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -95,6 +95,7 @@
"persistable_bundle.cpp",
"process.cpp",
"service_manager.cpp",
+ "binder_rpc.cpp",
],
static_libs: [
diff --git a/libs/binder/ndk/binder_rpc.cpp b/libs/binder/ndk/binder_rpc.cpp
new file mode 100644
index 0000000..2cc5f81
--- /dev/null
+++ b/libs/binder/ndk/binder_rpc.cpp
@@ -0,0 +1,352 @@
+/*
+ * 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/binder_rpc.h>
+#include <arpa/inet.h>
+#include <binder/IServiceManager.h>
+#include <linux/vm_sockets.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <variant>
+
+#include "ibinder_internal.h"
+#include "status_internal.h"
+
+using ::android::defaultServiceManager;
+using ::android::IBinder;
+using ::android::IServiceManager;
+using ::android::OK;
+using ::android::sp;
+using ::android::status_t;
+using ::android::String16;
+using ::android::String8;
+using ::android::binder::Status;
+
+#define LOG_ACCESSOR_DEBUG(...)
+// #define LOG_ACCESSOR_DEBUG(...) ALOGW(__VA_ARGS__)
+
+struct ABinderRpc_ConnectionInfo {
+ std::variant<sockaddr_vm, sockaddr_un, sockaddr_in> addr;
+};
+
+struct ABinderRpc_Accessor final : public ::android::RefBase {
+ static ABinderRpc_Accessor* make(const char* instance, const sp<IBinder>& binder) {
+ LOG_ALWAYS_FATAL_IF(binder == nullptr, "ABinderRpc_Accessor requires a non-null binder");
+ status_t status = android::validateAccessor(String16(instance), binder);
+ if (status != OK) {
+ ALOGE("The given binder is not a valid IAccessor for %s. Status: %s", instance,
+ android::statusToString(status).c_str());
+ return nullptr;
+ }
+ return new ABinderRpc_Accessor(binder);
+ }
+
+ sp<IBinder> asBinder() { return mAccessorBinder; }
+
+ ~ABinderRpc_Accessor() { LOG_ACCESSOR_DEBUG("ABinderRpc_Accessor dtor"); }
+
+ private:
+ ABinderRpc_Accessor(sp<IBinder> accessor) : mAccessorBinder(accessor) {}
+ ABinderRpc_Accessor() = delete;
+ sp<IBinder> mAccessorBinder;
+};
+
+struct ABinderRpc_AccessorProvider {
+ public:
+ static ABinderRpc_AccessorProvider* make(std::weak_ptr<android::AccessorProvider> cookie) {
+ if (cookie.expired()) {
+ ALOGE("Null AccessorProvider cookie from libbinder");
+ return nullptr;
+ }
+ return new ABinderRpc_AccessorProvider(cookie);
+ }
+ std::weak_ptr<android::AccessorProvider> mProviderCookie;
+
+ private:
+ ABinderRpc_AccessorProvider() = delete;
+
+ ABinderRpc_AccessorProvider(std::weak_ptr<android::AccessorProvider> provider)
+ : mProviderCookie(provider) {}
+};
+
+struct OnDeleteProviderHolder {
+ OnDeleteProviderHolder(void* data, ABinderRpc_AccessorProviderUserData_deleteCallback onDelete)
+ : mData(data), mOnDelete(onDelete) {}
+ ~OnDeleteProviderHolder() {
+ if (mOnDelete) {
+ mOnDelete(mData);
+ }
+ }
+ void* mData;
+ ABinderRpc_AccessorProviderUserData_deleteCallback mOnDelete;
+ // needs to be copyable for std::function, but we will never copy it
+ OnDeleteProviderHolder(const OnDeleteProviderHolder&) {
+ LOG_ALWAYS_FATAL("This object can't be copied!");
+ }
+
+ private:
+ OnDeleteProviderHolder() = delete;
+};
+
+ABinderRpc_AccessorProvider* ABinderRpc_registerAccessorProvider(
+ ABinderRpc_AccessorProvider_getAccessorCallback provider, const char** instances,
+ size_t numInstances, void* data,
+ ABinderRpc_AccessorProviderUserData_deleteCallback onDelete) {
+ if (provider == nullptr) {
+ ALOGE("Null provider passed to ABinderRpc_registerAccessorProvider");
+ return nullptr;
+ }
+ if (data && onDelete == nullptr) {
+ ALOGE("If a non-null data ptr is passed to ABinderRpc_registerAccessorProvider, then a "
+ "ABinderRpc_AccessorProviderUserData_deleteCallback must alse be passed to delete "
+ "the data object once the ABinderRpc_AccessorProvider is removed.");
+ return nullptr;
+ }
+ if (numInstances == 0 || instances == nullptr) {
+ ALOGE("No instances passed to ABinderRpc_registerAccessorProvider. numInstances: %zu",
+ numInstances);
+ return nullptr;
+ }
+ std::set<std::string> instanceStrings;
+ for (size_t i = 0; i < numInstances; i++) {
+ instanceStrings.emplace(instances[i]);
+ }
+ // call the onDelete when the last reference of this goes away (when the
+ // last reference to the generate std::function goes away).
+ std::shared_ptr<OnDeleteProviderHolder> onDeleteHolder =
+ std::make_shared<OnDeleteProviderHolder>(data, onDelete);
+ android::RpcAccessorProvider generate = [provider,
+ onDeleteHolder](const String16& name) -> sp<IBinder> {
+ ABinderRpc_Accessor* accessor = provider(String8(name).c_str(), onDeleteHolder->mData);
+ if (accessor == nullptr) {
+ ALOGE("The supplied ABinderRpc_AccessorProvider_getAccessorCallback returned nullptr");
+ return nullptr;
+ }
+ sp<IBinder> binder = accessor->asBinder();
+ ABinderRpc_Accessor_delete(accessor);
+ return binder;
+ };
+
+ std::weak_ptr<android::AccessorProvider> cookie =
+ android::addAccessorProvider(std::move(instanceStrings), std::move(generate));
+ return ABinderRpc_AccessorProvider::make(cookie);
+}
+
+void ABinderRpc_unregisterAccessorProvider(ABinderRpc_AccessorProvider* provider) {
+ if (provider == nullptr) {
+ LOG_ALWAYS_FATAL("Attempting to remove a null ABinderRpc_AccessorProvider");
+ }
+
+ status_t status = android::removeAccessorProvider(provider->mProviderCookie);
+ // There shouldn't be a way to get here because the caller won't have a
+ // ABinderRpc_AccessorProvider* without calling ABinderRpc_registerAccessorProvider
+ LOG_ALWAYS_FATAL_IF(status == android::BAD_VALUE, "Provider (%p) is not valid. Status: %s",
+ provider, android::statusToString(status).c_str());
+ LOG_ALWAYS_FATAL_IF(status == android::NAME_NOT_FOUND,
+ "Provider (%p) was already unregistered. Status: %s", provider,
+ android::statusToString(status).c_str());
+ LOG_ALWAYS_FATAL_IF(status != OK,
+ "Unknown error when attempting to unregister ABinderRpc_AccessorProvider "
+ "(%p). Status: %s",
+ provider, android::statusToString(status).c_str());
+
+ delete provider;
+}
+
+struct OnDeleteConnectionInfoHolder {
+ OnDeleteConnectionInfoHolder(void* data,
+ ABinderRpc_ConnectionInfoProviderUserData_delete onDelete)
+ : mData(data), mOnDelete(onDelete) {}
+ ~OnDeleteConnectionInfoHolder() {
+ if (mOnDelete) {
+ mOnDelete(mData);
+ }
+ }
+ void* mData;
+ ABinderRpc_ConnectionInfoProviderUserData_delete mOnDelete;
+ // needs to be copyable for std::function, but we will never copy it
+ OnDeleteConnectionInfoHolder(const OnDeleteConnectionInfoHolder&) {
+ LOG_ALWAYS_FATAL("This object can't be copied!");
+ }
+
+ private:
+ OnDeleteConnectionInfoHolder() = delete;
+};
+
+ABinderRpc_Accessor* ABinderRpc_Accessor_new(
+ const char* instance, ABinderRpc_ConnectionInfoProvider provider, void* data,
+ ABinderRpc_ConnectionInfoProviderUserData_delete onDelete) {
+ if (instance == nullptr) {
+ ALOGE("Instance argument must be valid when calling ABinderRpc_Accessor_new");
+ return nullptr;
+ }
+ if (data && onDelete == nullptr) {
+ ALOGE("If a non-null data ptr is passed to ABinderRpc_Accessor_new, then a "
+ "ABinderRpc_ConnectionInfoProviderUserData_delete callback must alse be passed to "
+ "delete "
+ "the data object once the ABinderRpc_Accessor is deleted.");
+ return nullptr;
+ }
+ std::shared_ptr<OnDeleteConnectionInfoHolder> onDeleteHolder =
+ std::make_shared<OnDeleteConnectionInfoHolder>(data, onDelete);
+ if (provider == nullptr) {
+ ALOGE("Can't create a new ABinderRpc_Accessor without a ABinderRpc_ConnectionInfoProvider "
+ "and it is "
+ "null");
+ return nullptr;
+ }
+ android::RpcSocketAddressProvider generate = [provider, onDeleteHolder](
+ const String16& name, sockaddr* outAddr,
+ size_t addrLen) -> status_t {
+ std::unique_ptr<ABinderRpc_ConnectionInfo> info(
+ provider(String8(name).c_str(), onDeleteHolder->mData));
+ if (info == nullptr) {
+ ALOGE("The supplied ABinderRpc_ConnectionInfoProvider returned nullptr");
+ return android::NAME_NOT_FOUND;
+ }
+ if (auto addr = std::get_if<sockaddr_vm>(&info->addr)) {
+ LOG_ALWAYS_FATAL_IF(addr->svm_family != AF_VSOCK,
+ "ABinderRpc_ConnectionInfo invalid family");
+ if (addrLen < sizeof(sockaddr_vm)) {
+ ALOGE("Provided outAddr is too small! Expecting %zu, got %zu", sizeof(sockaddr_vm),
+ addrLen);
+ return android::BAD_VALUE;
+ }
+ LOG_ACCESSOR_DEBUG(
+ "Connection info provider found AF_VSOCK. family %d, port %d, cid %d",
+ addr->svm_family, addr->svm_port, addr->svm_cid);
+ *reinterpret_cast<sockaddr_vm*>(outAddr) = *addr;
+ } else if (auto addr = std::get_if<sockaddr_un>(&info->addr)) {
+ LOG_ALWAYS_FATAL_IF(addr->sun_family != AF_UNIX,
+ "ABinderRpc_ConnectionInfo invalid family");
+ if (addrLen < sizeof(sockaddr_un)) {
+ ALOGE("Provided outAddr is too small! Expecting %zu, got %zu", sizeof(sockaddr_un),
+ addrLen);
+ return android::BAD_VALUE;
+ }
+ *reinterpret_cast<sockaddr_un*>(outAddr) = *addr;
+ } else if (auto addr = std::get_if<sockaddr_in>(&info->addr)) {
+ LOG_ALWAYS_FATAL_IF(addr->sin_family != AF_INET,
+ "ABinderRpc_ConnectionInfo invalid family");
+ if (addrLen < sizeof(sockaddr_in)) {
+ ALOGE("Provided outAddr is too small! Expecting %zu, got %zu", sizeof(sockaddr_in),
+ addrLen);
+ return android::BAD_VALUE;
+ }
+ *reinterpret_cast<sockaddr_in*>(outAddr) = *addr;
+ } else {
+ LOG_ALWAYS_FATAL(
+ "Unsupported address family type when trying to get ARpcConnection info. A "
+ "new variant was added to the ABinderRpc_ConnectionInfo and this needs to be "
+ "updated.");
+ }
+ return OK;
+ };
+ sp<IBinder> accessorBinder = android::createAccessor(String16(instance), std::move(generate));
+ if (accessorBinder == nullptr) {
+ ALOGE("service manager did not get us an accessor");
+ return nullptr;
+ }
+ LOG_ACCESSOR_DEBUG("service manager found an accessor, so returning one now from _new");
+ return ABinderRpc_Accessor::make(instance, accessorBinder);
+}
+
+void ABinderRpc_Accessor_delete(ABinderRpc_Accessor* accessor) {
+ delete accessor;
+}
+
+AIBinder* ABinderRpc_Accessor_asBinder(ABinderRpc_Accessor* accessor) {
+ if (!accessor) {
+ ALOGE("ABinderRpc_Accessor argument is null.");
+ return nullptr;
+ }
+
+ sp<IBinder> binder = accessor->asBinder();
+ sp<AIBinder> aBinder = ABpBinder::lookupOrCreateFromBinder(binder);
+ AIBinder* ptr = aBinder.get();
+ if (ptr == nullptr) {
+ LOG_ALWAYS_FATAL("Failed to lookupOrCreateFromBinder");
+ }
+ ptr->incStrong(nullptr);
+ return ptr;
+}
+
+ABinderRpc_Accessor* ABinderRpc_Accessor_fromBinder(const char* instance, AIBinder* binder) {
+ if (!binder) {
+ ALOGE("binder argument is null");
+ return nullptr;
+ }
+ sp<IBinder> accessorBinder = binder->getBinder();
+ if (accessorBinder) {
+ return ABinderRpc_Accessor::make(instance, accessorBinder);
+ } else {
+ ALOGE("Attempting to get an ABinderRpc_Accessor for %s but AIBinder::getBinder returned "
+ "null",
+ instance);
+ return nullptr;
+ }
+}
+
+ABinderRpc_ConnectionInfo* ABinderRpc_ConnectionInfo_new(const sockaddr* addr, socklen_t len) {
+ if (addr == nullptr || len < 0 || static_cast<size_t>(len) < sizeof(sa_family_t)) {
+ ALOGE("Invalid arguments in Arpc_Connection_new");
+ return nullptr;
+ }
+ // socklen_t was int32_t on 32-bit and uint32_t on 64 bit.
+ size_t socklen = len < 0 || static_cast<uintmax_t>(len) > SIZE_MAX ? 0 : len;
+
+ if (addr->sa_family == AF_VSOCK) {
+ if (len != sizeof(sockaddr_vm)) {
+ ALOGE("Incorrect size of %zu for AF_VSOCK sockaddr_vm. Expecting %zu", socklen,
+ sizeof(sockaddr_vm));
+ return nullptr;
+ }
+ sockaddr_vm vm = *reinterpret_cast<const sockaddr_vm*>(addr);
+ LOG_ACCESSOR_DEBUG("Arpc_ConnectionInfo_new found AF_VSOCK. family %d, port %d, cid %d",
+ vm.svm_family, vm.svm_port, vm.svm_cid);
+ return new ABinderRpc_ConnectionInfo(vm);
+ } else if (addr->sa_family == AF_UNIX) {
+ if (len != sizeof(sockaddr_un)) {
+ ALOGE("Incorrect size of %zu for AF_UNIX sockaddr_un. Expecting %zu", socklen,
+ sizeof(sockaddr_un));
+ return nullptr;
+ }
+ sockaddr_un un = *reinterpret_cast<const sockaddr_un*>(addr);
+ LOG_ACCESSOR_DEBUG("Arpc_ConnectionInfo_new found AF_UNIX. family %d, path %s",
+ un.sun_family, un.sun_path);
+ return new ABinderRpc_ConnectionInfo(un);
+ } else if (addr->sa_family == AF_INET) {
+ if (len != sizeof(sockaddr_in)) {
+ ALOGE("Incorrect size of %zu for AF_INET sockaddr_in. Expecting %zu", socklen,
+ sizeof(sockaddr_in));
+ return nullptr;
+ }
+ sockaddr_in in = *reinterpret_cast<const sockaddr_in*>(addr);
+ LOG_ACCESSOR_DEBUG("Arpc_ConnectionInfo_new found AF_INET. family %d, address %s, port %d",
+ in.sin_family, inet_ntoa(in.sin_addr), ntohs(in.sin_port));
+ return new ABinderRpc_ConnectionInfo(in);
+ }
+
+ ALOGE("ARpc APIs only support AF_VSOCK right now but the supplied sockadder::sa_family is: %hu",
+ addr->sa_family);
+ return nullptr;
+}
+
+void ABinderRpc_ConnectionInfo_delete(ABinderRpc_ConnectionInfo* info) {
+ delete info;
+}
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index af280d3..ff31dd0 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -18,8 +18,10 @@
#include <android/binder_ibinder_platform.h>
#include <android/binder_stability.h>
#include <android/binder_status.h>
+#include <binder/Functional.h>
#include <binder/IPCThreadState.h>
#include <binder/IResultReceiver.h>
+#include <binder/Trace.h>
#if __has_include(<private/android_filesystem_config.h>)
#include <private/android_filesystem_config.h>
#endif
@@ -40,6 +42,23 @@
using ::android::String16;
using ::android::String8;
using ::android::wp;
+using ::android::binder::impl::make_scope_guard;
+using ::android::binder::impl::scope_guard;
+using ::android::binder::os::get_trace_enabled_tags;
+using ::android::binder::os::trace_begin;
+using ::android::binder::os::trace_end;
+
+// transaction codes for getInterfaceHash and getInterfaceVersion are defined
+// in file : system/tools/aidl/aidl.cpp
+static constexpr int kGetInterfaceVersionId = 0x00fffffe;
+static const char* kInterfaceVersion = "getInterfaceVersion";
+static constexpr int kGetInterfaceHashId = 0x00fffffd;
+static const char* kInterfaceHash = "getInterfaceHash";
+static const char* kNdkTrace = "AIDL::ndk::";
+static const char* kServerTrace = "::server";
+static const char* kClientTrace = "::client";
+static const char* kSeparator = "::";
+static const char* kUnknownCode = "Unknown_Transaction_Code:";
namespace ABBinderTag {
@@ -90,6 +109,51 @@
return sanitized;
}
+const std::string getMethodName(const AIBinder_Class* clazz, transaction_code_t code) {
+ // TODO(b/150155678) - Move getInterfaceHash and getInterfaceVersion to libbinder and remove
+ // hardcoded cases.
+ if (code <= clazz->getTransactionCodeToFunctionLength() && code >= FIRST_CALL_TRANSACTION) {
+ // Codes have FIRST_CALL_TRANSACTION as added offset. Subtract to access function name
+ return clazz->getFunctionName(code);
+ } else if (code == kGetInterfaceVersionId) {
+ return kInterfaceVersion;
+ } else if (code == kGetInterfaceHashId) {
+ return kInterfaceHash;
+ }
+ return kUnknownCode + std::to_string(code);
+}
+
+const std::string getTraceSectionName(const AIBinder_Class* clazz, transaction_code_t code,
+ bool isServer) {
+ if (clazz == nullptr) {
+ ALOGE("class associated with binder is null. Class is needed to add trace with interface "
+ "name and function name");
+ return kNdkTrace;
+ }
+
+ const std::string descriptor = clazz->getInterfaceDescriptorUtf8();
+ const std::string methodName = getMethodName(clazz, code);
+
+ size_t traceSize =
+ strlen(kNdkTrace) + descriptor.size() + strlen(kSeparator) + methodName.size();
+ traceSize += isServer ? strlen(kServerTrace) : strlen(kClientTrace);
+
+ std::string trace;
+ // reserve to avoid repeated allocations
+ trace.reserve(traceSize);
+
+ trace += kNdkTrace;
+ trace += clazz->getInterfaceDescriptorUtf8();
+ trace += kSeparator;
+ trace += methodName;
+ trace += isServer ? kServerTrace : kClientTrace;
+
+ LOG_ALWAYS_FATAL_IF(trace.size() != traceSize, "Trace size mismatch. Expected %zu, got %zu",
+ traceSize, trace.size());
+
+ return trace;
+}
+
bool AIBinder::associateClass(const AIBinder_Class* clazz) {
if (clazz == nullptr) return false;
@@ -203,6 +267,17 @@
status_t ABBinder::onTransact(transaction_code_t code, const Parcel& data, Parcel* reply,
binder_flags_t flags) {
+ std::string sectionName;
+ bool tracingEnabled = get_trace_enabled_tags() & ATRACE_TAG_AIDL;
+ if (tracingEnabled) {
+ sectionName = getTraceSectionName(getClass(), code, true /*isServer*/);
+ trace_begin(ATRACE_TAG_AIDL, sectionName.c_str());
+ }
+
+ scope_guard guard = make_scope_guard([&]() {
+ if (tracingEnabled) trace_end(ATRACE_TAG_AIDL);
+ });
+
if (isUserCommand(code)) {
if (getClass()->writeHeader && !data.checkInterface(this)) {
return STATUS_BAD_TYPE;
@@ -385,6 +460,31 @@
mInterfaceDescriptor(interfaceDescriptor),
mWideInterfaceDescriptor(interfaceDescriptor) {}
+bool AIBinder_Class::setTransactionCodeMap(const char** transactionCodeMap, size_t length) {
+ if (mTransactionCodeToFunction != nullptr) {
+ ALOGE("mTransactionCodeToFunction is already set!");
+ return false;
+ }
+ mTransactionCodeToFunction = transactionCodeMap;
+ mTransactionCodeToFunctionLength = length;
+ return true;
+}
+
+const char* AIBinder_Class::getFunctionName(transaction_code_t code) const {
+ if (mTransactionCodeToFunction == nullptr) {
+ ALOGE("mTransactionCodeToFunction is not set!");
+ return nullptr;
+ }
+
+ if (code < FIRST_CALL_TRANSACTION ||
+ code - FIRST_CALL_TRANSACTION >= mTransactionCodeToFunctionLength) {
+ ALOGE("Function name for requested code not found!");
+ return nullptr;
+ }
+
+ return mTransactionCodeToFunction[code - FIRST_CALL_TRANSACTION];
+}
+
AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor,
AIBinder_Class_onCreate onCreate,
AIBinder_Class_onDestroy onDestroy,
@@ -404,6 +504,24 @@
clazz->onDump = onDump;
}
+void AIBinder_Class_setTransactionCodeToFunctionNameMap(AIBinder_Class* clazz,
+ const char** transactionCodeToFunction,
+ size_t length) {
+ LOG_ALWAYS_FATAL_IF(clazz == nullptr || transactionCodeToFunction == nullptr,
+ "Valid clazz and transactionCodeToFunction are needed to set code to "
+ "function mapping.");
+ LOG_ALWAYS_FATAL_IF(!clazz->setTransactionCodeMap(transactionCodeToFunction, length),
+ "Failed to set transactionCodeToFunction to clazz! Is "
+ "transactionCodeToFunction already set?");
+}
+
+const char* AIBinder_Class_getFunctionName(AIBinder_Class* clazz, transaction_code_t code) {
+ LOG_ALWAYS_FATAL_IF(
+ clazz == nullptr,
+ "Valid clazz is needed to get function name for requested transaction code");
+ return clazz->getFunctionName(code);
+}
+
void AIBinder_Class_disableInterfaceTokenHeader(AIBinder_Class* clazz) {
LOG_ALWAYS_FATAL_IF(clazz == nullptr, "disableInterfaceTokenHeader requires non-null clazz");
@@ -734,6 +852,19 @@
binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
AParcel** out, binder_flags_t flags) {
+ const AIBinder_Class* clazz = binder ? binder->getClass() : nullptr;
+
+ std::string sectionName;
+ bool tracingEnabled = get_trace_enabled_tags() & ATRACE_TAG_AIDL;
+ if (tracingEnabled) {
+ sectionName = getTraceSectionName(clazz, code, false /*isServer*/);
+ trace_begin(ATRACE_TAG_AIDL, sectionName.c_str());
+ }
+
+ scope_guard guard = make_scope_guard([&]() {
+ if (tracingEnabled) trace_end(ATRACE_TAG_AIDL);
+ });
+
if (in == nullptr) {
ALOGE("%s: requires non-null in parameter", __func__);
return STATUS_UNEXPECTED_NULL;
@@ -872,4 +1003,4 @@
"AIBinder_setInheritRt must be called on a local binder");
localBinder->setInheritRt(inheritRt);
-}
+}
\ No newline at end of file
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index f5b738c..a93dc1f 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -132,6 +132,9 @@
const ::android::String16& getInterfaceDescriptor() const { return mWideInterfaceDescriptor; }
const char* getInterfaceDescriptorUtf8() const { return mInterfaceDescriptor.c_str(); }
+ bool setTransactionCodeMap(const char** transactionCodeMap, size_t transactionCodeMapSize);
+ const char* getFunctionName(transaction_code_t code) const;
+ size_t getTransactionCodeToFunctionLength() const { return mTransactionCodeToFunctionLength; }
// whether a transaction header should be written
bool writeHeader = true;
@@ -151,6 +154,10 @@
// This must be a String16 since BBinder virtual getInterfaceDescriptor returns a reference to
// one.
const ::android::String16 mWideInterfaceDescriptor;
+ // Array which holds names of the functions
+ const char** mTransactionCodeToFunction = nullptr;
+ // length of mmTransactionCodeToFunctionLength array
+ size_t mTransactionCodeToFunctionLength = 0;
};
// Ownership is like this (when linked to death):
diff --git a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
index af56bf0..379bdbb 100644
--- a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
@@ -30,6 +30,17 @@
#include <android/binder_auto_utils.h>
#include <android/binder_ibinder.h>
+#if defined(__ANDROID_VENDOR__)
+#include <android/llndk-versioning.h>
+#elif !defined(API_LEVEL_AT_LEAST)
+#if defined(__BIONIC__)
+#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) \
+ (__builtin_available(android sdk_api_level, *))
+#else
+#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) (true)
+#endif // __BIONIC__
+#endif // __ANDROID_VENDOR__
+
#if __has_include(<android/binder_shell.h>)
#include <android/binder_shell.h>
#define HAS_BINDER_SHELL_COMMAND
@@ -164,7 +175,8 @@
* Helper method to create a class
*/
static inline AIBinder_Class* defineClass(const char* interfaceDescriptor,
- AIBinder_Class_onTransact onTransact);
+ AIBinder_Class_onTransact onTransact,
+ const char** codeToFunction, size_t functionCount);
private:
class ICInterfaceData {
@@ -255,7 +267,8 @@
}
AIBinder_Class* ICInterface::defineClass(const char* interfaceDescriptor,
- AIBinder_Class_onTransact onTransact) {
+ AIBinder_Class_onTransact onTransact,
+ const char** codeToFunction, size_t functionCount) {
AIBinder_Class* clazz = AIBinder_Class_define(interfaceDescriptor, ICInterfaceData::onCreate,
ICInterfaceData::onDestroy, onTransact);
if (clazz == nullptr) {
@@ -274,6 +287,17 @@
AIBinder_Class_setHandleShellCommand(clazz, ICInterfaceData::handleShellCommand);
}
#endif
+
+// TODO(b/368559337): fix versioning on product partition
+#if !defined(__ANDROID_PRODUCT__) && \
+ (defined(__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__) || __ANDROID_API__ >= 36)
+ if API_LEVEL_AT_LEAST (36, 202504) {
+ AIBinder_Class_setTransactionCodeToFunctionNameMap(clazz, codeToFunction, functionCount);
+ }
+#else
+ (void)codeToFunction;
+ (void)functionCount;
+#endif // defined(__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__) || __ANDROID_API__ >= 36
return clazz;
}
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 72d255e..2f6c4e3 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -219,6 +219,50 @@
void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) __INTRODUCED_IN(29);
/**
+ * Associates a mapping of transaction codes(transaction_code_t) to function names for the given
+ * class.
+ *
+ * Trace messages will use the provided names instead of bare integer codes when set. If not set by
+ * this function, trace messages will only be identified by the bare code. This should be called one
+ * time during clazz initialization. clazz and transactionCodeToFunctionMap should have same
+ * lifetime. Resetting/clearing the transactionCodeToFunctionMap is not allowed.
+ *
+ * Available since API level 36.
+ *
+ * \param clazz class which should use this transaction to code function map.
+ * \param transactionCodeToFunctionMap array of function names indexed by transaction code.
+ * Transaction codes start from 1, functions with transaction code 1 will correspond to index 0 in
+ * transactionCodeToFunctionMap. When defining methods, transaction codes are expected to be
+ * contiguous, and this is required for maximum memory efficiency.
+ * You can use nullptr if certain transaction codes are not used. Lifetime should be same as clazz.
+ * \param length number of elements in the transactionCodeToFunctionMap
+ *
+ * \return true if setting codeToFunction to clazz is successful. return false if clazz or
+ * codeToFunction is nullptr.
+ */
+void AIBinder_Class_setTransactionCodeToFunctionNameMap(AIBinder_Class* clazz,
+ const char** transactionCodeToFunctionMap,
+ size_t length) __INTRODUCED_IN(36);
+
+/**
+ * Get function name associated with transaction code for given class
+ *
+ * This function returns function name associated with provided transaction code for given class.
+ * AIBinder_Class_setTransactionCodeToFunctionNameMap should be called first to associate function
+ * to transaction code mapping.
+ *
+ * Available since API level 36.
+ *
+ * \param clazz class for which function name is requested
+ * \param transactionCode transaction_code_t for which function name is requested.
+ *
+ * \return function name in form of const char* if transaction code is valid for given class.
+ * if transaction code is invalid or transactionCodeToFunctionMap is not set, nullptr is returned
+ */
+const char* AIBinder_Class_getFunctionName(AIBinder_Class* clazz, transaction_code_t code)
+ __INTRODUCED_IN(36);
+
+/**
* This tells users of this class not to use a transaction header. By default, libbinder_ndk users
* read/write transaction headers implicitly (in the SDK, this must be manually written by
* android.os.Parcel#writeInterfaceToken, and it is read/checked with
diff --git a/libs/binder/ndk/include_ndk/android/persistable_bundle.h b/libs/binder/ndk/include_ndk/android/persistable_bundle.h
index 5e0d4da..1d516ae 100644
--- a/libs/binder/ndk/include_ndk/android/persistable_bundle.h
+++ b/libs/binder/ndk/include_ndk/android/persistable_bundle.h
@@ -17,13 +17,6 @@
#pragma once
#include <android/binder_parcel.h>
-#if defined(__ANDROID_VENDOR__)
-#include <android/llndk-versioning.h>
-#else
-#if !defined(__INTRODUCED_IN_LLNDK)
-#define __INTRODUCED_IN_LLNDK(level) __attribute__((annotate("introduced_in_llndk=" #level)))
-#endif
-#endif // __ANDROID_VENDOR__
#include <stdbool.h>
#include <stdint.h>
#include <sys/cdefs.h>
@@ -83,8 +76,7 @@
*
* \return Pointer to a new APersistableBundle
*/
-APersistableBundle* _Nullable APersistableBundle_new() __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+APersistableBundle* _Nullable APersistableBundle_new() __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Create a new APersistableBundle based off an existing APersistableBundle.
@@ -98,7 +90,7 @@
* \return Pointer to a new APersistableBundle
*/
APersistableBundle* _Nullable APersistableBundle_dup(const APersistableBundle* _Nonnull pBundle)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Delete an APersistableBundle. This must always be called when finished using
@@ -109,7 +101,7 @@
* Available since API level 202404.
*/
void APersistableBundle_delete(APersistableBundle* _Nullable pBundle)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Check for equality of APersistableBundles.
@@ -123,7 +115,7 @@
*/
bool APersistableBundle_isEqual(const APersistableBundle* _Nonnull lhs,
const APersistableBundle* _Nonnull rhs)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Read an APersistableBundle from an AParcel.
@@ -142,7 +134,7 @@
*/
binder_status_t APersistableBundle_readFromParcel(
const AParcel* _Nonnull parcel, APersistableBundle* _Nullable* _Nonnull outPBundle)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Write an APersistableBundle to an AParcel.
@@ -162,7 +154,7 @@
*/
binder_status_t APersistableBundle_writeToParcel(const APersistableBundle* _Nonnull pBundle,
AParcel* _Nonnull parcel)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get the size of an APersistableBundle. This is the number of mappings in the
@@ -175,7 +167,7 @@
* \return number of mappings in the object
*/
int32_t APersistableBundle_size(const APersistableBundle* _Nonnull pBundle)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Erase any entries added with the provided key.
@@ -188,7 +180,7 @@
* \return number of entries erased. Either 0 or 1.
*/
int32_t APersistableBundle_erase(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Put a boolean associated with the provided key.
@@ -201,8 +193,7 @@
* Available since API level 202404.
*/
void APersistableBundle_putBoolean(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key,
- bool val) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ bool val) __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Put an int32_t associated with the provided key.
@@ -215,8 +206,7 @@
* Available since API level 202404.
*/
void APersistableBundle_putInt(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key,
- int32_t val) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ int32_t val) __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Put an int64_t associated with the provided key.
@@ -229,8 +219,7 @@
* Available since API level 202404.
*/
void APersistableBundle_putLong(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key,
- int64_t val) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ int64_t val) __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Put a double associated with the provided key.
@@ -243,8 +232,7 @@
* Available since API level 202404.
*/
void APersistableBundle_putDouble(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key,
- double val) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ double val) __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Put a string associated with the provided key.
@@ -258,8 +246,7 @@
* Available since API level 202404.
*/
void APersistableBundle_putString(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key,
- const char* _Nonnull val) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ const char* _Nonnull val) __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Put a boolean vector associated with the provided key.
@@ -275,8 +262,7 @@
*/
void APersistableBundle_putBooleanVector(APersistableBundle* _Nonnull pBundle,
const char* _Nonnull key, const bool* _Nonnull vec,
- int32_t num) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ int32_t num) __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Put an int32_t vector associated with the provided key.
@@ -292,7 +278,7 @@
*/
void APersistableBundle_putIntVector(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key,
const int32_t* _Nonnull vec, int32_t num)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Put an int64_t vector associated with the provided key.
@@ -308,8 +294,7 @@
*/
void APersistableBundle_putLongVector(APersistableBundle* _Nonnull pBundle,
const char* _Nonnull key, const int64_t* _Nonnull vec,
- int32_t num) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ int32_t num) __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Put a double vector associated with the provided key.
@@ -325,8 +310,7 @@
*/
void APersistableBundle_putDoubleVector(APersistableBundle* _Nonnull pBundle,
const char* _Nonnull key, const double* _Nonnull vec,
- int32_t num) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ int32_t num) __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Put a string vector associated with the provided key.
@@ -343,7 +327,7 @@
void APersistableBundle_putStringVector(APersistableBundle* _Nonnull pBundle,
const char* _Nonnull key,
const char* _Nullable const* _Nullable vec, int32_t num)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Put an APersistableBundle associated with the provided key.
@@ -359,7 +343,7 @@
void APersistableBundle_putPersistableBundle(APersistableBundle* _Nonnull pBundle,
const char* _Nonnull key,
const APersistableBundle* _Nonnull val)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get a boolean associated with the provided key.
@@ -374,7 +358,7 @@
*/
bool APersistableBundle_getBoolean(const APersistableBundle* _Nonnull pBundle,
const char* _Nonnull key, bool* _Nonnull val)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get an int32_t associated with the provided key.
@@ -388,8 +372,7 @@
* \return true if a value exists for the provided key
*/
bool APersistableBundle_getInt(const APersistableBundle* _Nonnull pBundle, const char* _Nonnull key,
- int32_t* _Nonnull val) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ int32_t* _Nonnull val) __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get an int64_t associated with the provided key.
@@ -404,7 +387,7 @@
*/
bool APersistableBundle_getLong(const APersistableBundle* _Nonnull pBundle,
const char* _Nonnull key, int64_t* _Nonnull val)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get a double associated with the provided key.
@@ -419,7 +402,7 @@
*/
bool APersistableBundle_getDouble(const APersistableBundle* _Nonnull pBundle,
const char* _Nonnull key, double* _Nonnull val)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get a string associated with the provided key.
@@ -440,8 +423,7 @@
int32_t APersistableBundle_getString(const APersistableBundle* _Nonnull pBundle,
const char* _Nonnull key, char* _Nullable* _Nonnull val,
APersistableBundle_stringAllocator stringAllocator,
- void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get a boolean vector associated with the provided key and place it in the
@@ -468,7 +450,7 @@
int32_t APersistableBundle_getBooleanVector(const APersistableBundle* _Nonnull pBundle,
const char* _Nonnull key, bool* _Nullable buffer,
int32_t bufferSizeBytes)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get an int32_t vector associated with the provided key and place it in the
@@ -494,8 +476,7 @@
*/
int32_t APersistableBundle_getIntVector(const APersistableBundle* _Nonnull pBundle,
const char* _Nonnull key, int32_t* _Nullable buffer,
- int32_t bufferSizeBytes) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ int32_t bufferSizeBytes) __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get an int64_t vector associated with the provided key and place it in the
@@ -521,8 +502,8 @@
*/
int32_t APersistableBundle_getLongVector(const APersistableBundle* _Nonnull pBundle,
const char* _Nonnull key, int64_t* _Nullable buffer,
- int32_t bufferSizeBytes) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ int32_t bufferSizeBytes)
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get a double vector associated with the provided key and place it in the
@@ -549,7 +530,7 @@
int32_t APersistableBundle_getDoubleVector(const APersistableBundle* _Nonnull pBundle,
const char* _Nonnull key, double* _Nullable buffer,
int32_t bufferSizeBytes)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get a string vector associated with the provided key and place it in the
@@ -586,7 +567,7 @@
int32_t bufferSizeBytes,
APersistableBundle_stringAllocator stringAllocator,
void* _Nullable context)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get an APersistableBundle* associated with the provided key.
@@ -605,7 +586,7 @@
bool APersistableBundle_getPersistableBundle(const APersistableBundle* _Nonnull pBundle,
const char* _Nonnull key,
APersistableBundle* _Nullable* _Nonnull outBundle)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get all of the keys associated with this specific type and place it in the
@@ -638,7 +619,7 @@
int32_t bufferSizeBytes,
APersistableBundle_stringAllocator stringAllocator,
void* _Nullable context)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get all of the keys associated with this specific type and place it in the
@@ -669,8 +650,7 @@
int32_t APersistableBundle_getIntKeys(const APersistableBundle* _Nonnull pBundle,
char* _Nullable* _Nullable outKeys, int32_t bufferSizeBytes,
APersistableBundle_stringAllocator stringAllocator,
- void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get all of the keys associated with this specific type and place it in the
@@ -701,8 +681,7 @@
int32_t APersistableBundle_getLongKeys(const APersistableBundle* _Nonnull pBundle,
char* _Nullable* _Nullable outKeys, int32_t bufferSizeBytes,
APersistableBundle_stringAllocator stringAllocator,
- void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get all of the keys associated with this specific type and place it in the
@@ -734,8 +713,8 @@
char* _Nullable* _Nullable outKeys,
int32_t bufferSizeBytes,
APersistableBundle_stringAllocator stringAllocator,
- void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ void* _Nullable context)
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get all of the keys associated with this specific type and place it in the
@@ -767,8 +746,8 @@
char* _Nullable* _Nullable outKeys,
int32_t bufferSizeBytes,
APersistableBundle_stringAllocator stringAllocator,
- void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ void* _Nullable context)
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get all of the keys associated with this specific type and place it in the
@@ -801,7 +780,7 @@
int32_t bufferSizeBytes,
APersistableBundle_stringAllocator stringAllocator,
void* _Nullable context)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get all of the keys associated with this specific type and place it in the
@@ -834,7 +813,7 @@
int32_t bufferSizeBytes,
APersistableBundle_stringAllocator stringAllocator,
void* _Nullable context)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get all of the keys associated with this specific type and place it in the
@@ -867,7 +846,7 @@
int32_t bufferSizeBytes,
APersistableBundle_stringAllocator stringAllocator,
void* _Nullable context)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get all of the keys associated with this specific type and place it in the
@@ -899,7 +878,7 @@
int32_t bufferSizeBytes,
APersistableBundle_stringAllocator stringAllocator,
void* _Nullable context)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get all of the keys associated with this specific type and place it in the
@@ -932,7 +911,7 @@
int32_t bufferSizeBytes,
APersistableBundle_stringAllocator stringAllocator,
void* _Nullable context)
- __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Get all of the keys associated with this specific type and place it in the
@@ -963,6 +942,6 @@
int32_t APersistableBundle_getPersistableBundleKeys(
const APersistableBundle* _Nonnull pBundle, char* _Nullable* _Nullable outKeys,
int32_t bufferSizeBytes, APersistableBundle_stringAllocator stringAllocator,
- void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
+ void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__);
__END_DECLS
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index 41b30a0..cc4943b 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -18,7 +18,6 @@
#include <android/binder_ibinder.h>
#include <android/binder_status.h>
-#include <android/llndk-versioning.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
@@ -257,8 +256,7 @@
* \return the result of dlopen of the specified HAL
*/
void* AServiceManager_openDeclaredPassthroughHal(const char* interface, const char* instance,
- int flag) __INTRODUCED_IN(__ANDROID_API_V__)
- __INTRODUCED_IN_LLNDK(202404);
+ int flag) __INTRODUCED_IN(__ANDROID_API_V__);
/**
* Prevent lazy services without client from shutting down their process
diff --git a/libs/binder/ndk/include_platform/android/binder_rpc.h b/libs/binder/ndk/include_platform/android/binder_rpc.h
new file mode 100644
index 0000000..4c5471f
--- /dev/null
+++ b/libs/binder/ndk/include_platform/android/binder_rpc.h
@@ -0,0 +1,261 @@
+/*
+ * 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/binder_ibinder.h>
+#include <sys/socket.h>
+
+__BEGIN_DECLS
+
+/**
+ * This represents an IAccessor implementation from libbinder that is
+ * responsible for providing a pre-connected socket file descriptor for a
+ * specific service. The service is an RpcServer and the pre-connected socket is
+ * used to set up a client RpcSession underneath libbinder's IServiceManager APIs
+ * to provide the client with the service's binder for remote communication.
+ */
+typedef struct ABinderRpc_Accessor ABinderRpc_Accessor;
+
+/**
+ * This represents an object that supplies ABinderRpc_Accessors to libbinder
+ * when they are requested. They are requested any time a client is attempting
+ * to get a service through IServiceManager APIs when the services aren't known by
+ * servicemanager.
+ */
+typedef struct ABinderRpc_AccessorProvider ABinderRpc_AccessorProvider;
+
+/**
+ * This represents information necessary for libbinder to be able to connect to a
+ * remote service.
+ * It supports connecting to linux sockets and is created using sockaddr
+ * types for sockets supported by libbinder like sockaddr_in, sockaddr_un,
+ * sockaddr_vm.
+ */
+typedef struct ABinderRpc_ConnectionInfo ABinderRpc_ConnectionInfo;
+
+/**
+ * These APIs provide a way for clients of binder services to be able to get a
+ * binder object of that service through the existing libbinder/libbinder_ndk
+ * Service Manager APIs when that service is using RPC Binder over sockets
+ * instead kernel binder.
+ *
+ * Some of these APIs are used on Android hosts when kernel binder is supported
+ * and the usual servicemanager process is available. Some of these APIs are
+ * only required when there is no kernel binder or extra servicemanager process
+ * such as the case of microdroid or similar VMs.
+ */
+
+/**
+ * This callback is responsible for returning ABinderRpc_Accessor objects for a given
+ * service instance. These ABinderRpc_Accessor objects are implemented by
+ * libbinder_ndk and backed by implementations of android::os::IAccessor in
+ * libbinder.
+ *
+ * \param instance name of the service like
+ * `android.hardware.vibrator.IVibrator/default`
+ * \param data the data that was associated with this instance when the callback
+ * was registered.
+ * \return The ABinderRpc_Accessor associated with the service `instance`. This
+ * callback gives up ownership of the object once it returns it. The
+ * caller of this callback (libbinder_ndk) is responsible for deleting it
+ * with ABinderRpc_Accessor_delete.
+ */
+typedef ABinderRpc_Accessor* _Nullable (*ABinderRpc_AccessorProvider_getAccessorCallback)(
+ const char* _Nonnull instance, void* _Nullable data);
+
+/**
+ * This callback is responsible deleting the `void* data` object that is passed
+ * in to ABinderRpc_registerAccessorProvider for the ABinderRpc_AccessorProvider_getAccessorCallback
+ * to use. That object is owned by the ABinderRpc_AccessorProvider and must remain valid for the
+ * lifetime of the callback because it may be called and use the object.
+ * This _delete callback is called after the ABinderRpc_AccessorProvider is remove and
+ * is guaranteed never to be called again.
+ *
+ * \param data a pointer to data that the ABinderRpc_AccessorProvider_getAccessorCallback uses which
+ * is to be deleted by this call.
+ */
+typedef void (*ABinderRpc_AccessorProviderUserData_deleteCallback)(void* _Nullable data);
+
+/**
+ * Inject an ABinderRpc_AccessorProvider_getAccessorCallback into the process for
+ * the Service Manager APIs to use to retrieve ABinderRpc_Accessor objects associated
+ * with different RPC Binder services.
+ *
+ * \param provider callback that returns ABinderRpc_Accessors for libbinder to set up
+ * RPC clients with.
+ * \param instances array of instances that are supported by this provider. It
+ * will only be called if the client is looking for an instance that is
+ * in this list. These instances must be unique per-process. If an
+ * instance is being registered that was previously registered, this call
+ * will fail and the ABinderRpc_AccessorProviderUserData_deleteCallback
+ * will be called to clean up the data.
+ * \param number of instances in the instances array.
+ * \param data pointer that is passed to the ABinderRpc_AccessorProvider callback.
+ * IMPORTANT: The ABinderRpc_AccessorProvider now OWNS that object that data
+ * points to. It can be used as necessary in the callback. The data MUST
+ * remain valid for the lifetime of the provider callback.
+ * Do not attempt to give ownership of the same object to different
+ * providers throguh multiple calls to this function because the first
+ * one to be deleted will call the onDelete callback.
+ * \param onDelete callback used to delete the objects that `data` points to.
+ * This is called after ABinderRpc_AccessorProvider is guaranteed to never be
+ * called again. Before this callback is called, `data` must remain
+ * valid.
+ * \return nullptr on error if the data pointer is non-null and the onDelete
+ * callback is null or if an instance in the instances list was previously
+ * registered. In the error case of duplicate instances, if data was
+ * provided with a ABinderRpc_AccessorProviderUserData_deleteCallback,
+ * the callback will be called to delete the data.
+ * Otherwise returns a pointer to the ABinderRpc_AccessorProvider that
+ * can be used to remove with ABinderRpc_unregisterAccessorProvider.
+ */
+ABinderRpc_AccessorProvider* _Nullable ABinderRpc_registerAccessorProvider(
+ ABinderRpc_AccessorProvider_getAccessorCallback _Nonnull provider,
+ const char* _Nullable* _Nonnull instances, size_t numInstances, void* _Nullable data,
+ ABinderRpc_AccessorProviderUserData_deleteCallback _Nullable onDelete) __INTRODUCED_IN(36);
+
+/**
+ * Remove an ABinderRpc_AccessorProvider from libbinder. This will remove references
+ * from the ABinderRpc_AccessorProvider and will no longer call the
+ * ABinderRpc_AccessorProvider_getAccessorCallback.
+ *
+ * Note: The `data` object that was used when adding the accessor will be
+ * deleted by the ABinderRpc_AccessorProviderUserData_deleteCallback at some
+ * point after this call. Do not use the object and do not try to delete
+ * it through any other means.
+ * Note: This will abort when used incorrectly if this provider was never
+ * registered or if it were already unregistered.
+ *
+ * \param provider to be removed and deleted
+ *
+ */
+void ABinderRpc_unregisterAccessorProvider(ABinderRpc_AccessorProvider* _Nonnull provider)
+ __INTRODUCED_IN(36);
+
+/**
+ * Callback which returns the RPC connection information for libbinder to use to
+ * connect to a socket that a given service is listening on. This is needed to
+ * create an ABinderRpc_Accessor so it can connect to these services.
+ *
+ * \param instance name of the service to connect to
+ * \param data userdata for this callback. The pointer is provided in
+ * ABinderRpc_Accessor_new.
+ * \return ABinderRpc_ConnectionInfo with socket connection information for `instance`
+ */
+typedef ABinderRpc_ConnectionInfo* _Nullable (*ABinderRpc_ConnectionInfoProvider)(
+ const char* _Nonnull instance, void* _Nullable data) __INTRODUCED_IN(36);
+/**
+ * This callback is responsible deleting the `void* data` object that is passed
+ * in to ABinderRpc_Accessor_new for the ABinderRpc_ConnectionInfoProvider to use. That
+ * object is owned by the ABinderRpc_Accessor and must remain valid for the
+ * lifetime the Accessor because it may be used by the connection info provider
+ * callback.
+ * This _delete callback is called after the ABinderRpc_Accessor is removed and
+ * is guaranteed never to be called again.
+ *
+ * \param data a pointer to data that the ABinderRpc_AccessorProvider uses which is to
+ * be deleted by this call.
+ */
+typedef void (*ABinderRpc_ConnectionInfoProviderUserData_delete)(void* _Nullable data);
+
+/**
+ * Create a new ABinderRpc_Accessor. This creates an IAccessor object in libbinder
+ * that can use the info from the ABinderRpc_ConnectionInfoProvider to connect to a
+ * socket that the service with `instance` name is listening to.
+ *
+ * \param instance name of the service that is listening on the socket
+ * \param provider callback that can get the socket connection information for the
+ * instance. This connection information may be dynamic, so the
+ * provider will be called any time a new connection is required.
+ * \param data pointer that is passed to the ABinderRpc_ConnectionInfoProvider callback.
+ * IMPORTANT: The ABinderRpc_ConnectionInfoProvider now OWNS that object that data
+ * points to. It can be used as necessary in the callback. The data MUST
+ * remain valid for the lifetime of the provider callback.
+ * Do not attempt to give ownership of the same object to different
+ * providers through multiple calls to this function because the first
+ * one to be deleted will call the onDelete callback.
+ * \param onDelete callback used to delete the objects that `data` points to.
+ * This is called after ABinderRpc_ConnectionInfoProvider is guaranteed to never be
+ * called again. Before this callback is called, `data` must remain
+ * valid.
+ * \return an ABinderRpc_Accessor instance. This is deleted by the caller once it is
+ * no longer needed.
+ */
+ABinderRpc_Accessor* _Nullable ABinderRpc_Accessor_new(
+ const char* _Nonnull instance, ABinderRpc_ConnectionInfoProvider _Nonnull provider,
+ void* _Nullable data, ABinderRpc_ConnectionInfoProviderUserData_delete _Nullable onDelete)
+ __INTRODUCED_IN(36);
+
+/**
+ * Delete an ABinderRpc_Accessor
+ *
+ * \param accessor to delete
+ */
+void ABinderRpc_Accessor_delete(ABinderRpc_Accessor* _Nonnull accessor) __INTRODUCED_IN(36);
+
+/**
+ * Return the AIBinder associated with an ABinderRpc_Accessor. This can be used to
+ * send the Accessor to another process or even register it with servicemanager.
+ *
+ * \param accessor to get the AIBinder for
+ * \return binder of the supplied accessor with one strong ref count
+ */
+AIBinder* _Nullable ABinderRpc_Accessor_asBinder(ABinderRpc_Accessor* _Nonnull accessor)
+ __INTRODUCED_IN(36);
+
+/**
+ * Return the ABinderRpc_Accessor associated with an AIBinder. The instance must match
+ * the ABinderRpc_Accessor implementation, and the AIBinder must a proxy binder for a
+ * remote service (ABpBinder).
+ * This can be used when receivng an AIBinder from another process that the
+ * other process obtained from ABinderRpc_Accessor_asBinder.
+ *
+ * \param instance name of the service that the Accessor is responsible for.
+ * \param accessorBinder proxy binder from another processes ABinderRpc_Accessor.
+ * \return ABinderRpc_Accessor representing the other processes ABinderRpc_Accessor
+ * implementation. This function does not take ownership of the
+ * ABinderRpc_Accessor (so the caller needs to delete with
+ * ABinderRpc_Accessor_delete), and it preserves the recount of the bidner
+ * object.
+ */
+ABinderRpc_Accessor* _Nullable ABinderRpc_Accessor_fromBinder(const char* _Nonnull instance,
+ AIBinder* _Nonnull accessorBinder)
+ __INTRODUCED_IN(36);
+
+/**
+ * Create a new ABinderRpc_ConnectionInfo with sockaddr. This can be supported socket
+ * types like sockaddr_vm (vsock) and sockaddr_un (Unix Domain Sockets).
+ *
+ * \param addr sockaddr pointer that can come from supported socket
+ * types like sockaddr_vm (vsock) and sockaddr_un (Unix Domain Sockets).
+ * \param len length of the concrete sockaddr type being used. Like
+ * sizeof(sockaddr_vm) when sockaddr_vm is used.
+ * \return the connection info based on the given sockaddr
+ */
+ABinderRpc_ConnectionInfo* _Nullable ABinderRpc_ConnectionInfo_new(const sockaddr* _Nonnull addr,
+ socklen_t len)
+ __INTRODUCED_IN(36);
+
+/**
+ * Delete an ABinderRpc_ConnectionInfo object that was created with
+ * ABinderRpc_ConnectionInfo_new.
+ *
+ * \param info object to be deleted
+ */
+void ABinderRpc_ConnectionInfo_delete(ABinderRpc_ConnectionInfo* _Nonnull info) __INTRODUCED_IN(36);
+
+__END_DECLS
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 826e199..c885816 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -248,6 +248,22 @@
AServiceManager_openDeclaredPassthroughHal; # systemapi llndk=202404
};
+LIBBINDER_NDK36 { # introduced=36
+ global:
+ AIBinder_Class_setTransactionCodeToFunctionNameMap;
+ AIBinder_Class_setTransactionCodeToFunctionNameMap; # llndk=202504
+ AIBinder_Class_getFunctionName;
+ AIBinder_Class_getFunctionName; # llndk=202504
+ ABinderRpc_registerAccessorProvider; # systemapi
+ ABinderRpc_unregisterAccessorProvider; # systemapi
+ ABinderRpc_Accessor_new; # systemapi
+ ABinderRpc_Accessor_delete; # systemapi
+ ABinderRpc_Accessor_asBinder; # systemapi
+ ABinderRpc_Accessor_fromBinder; # systemapi
+ ABinderRpc_ConnectionInfo_new; # systemapi
+ ABinderRpc_ConnectionInfo_delete; # systemapi
+};
+
LIBBINDER_NDK_PLATFORM {
global:
AParcel_getAllowFds;
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index f518a22..e5a3da4 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -46,6 +46,7 @@
#include "android/binder_ibinder.h"
using namespace android;
+using namespace std::chrono_literals;
constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest";
@@ -54,7 +55,7 @@
constexpr char kActiveServicesNdkUnitTestService[] = "ActiveServicesNdkUnitTestService";
constexpr char kBinderNdkUnitTestServiceFlagged[] = "BinderNdkUnitTestFlagged";
-constexpr unsigned int kShutdownWaitTime = 11;
+constexpr auto kShutdownWaitTime = 30s;
constexpr uint64_t kContextTestValue = 0xb4e42fb4d9a1d715;
class MyTestFoo : public IFoo {
@@ -253,12 +254,22 @@
}
bool isServiceRunning(const char* serviceName) {
- AIBinder* binder = AServiceManager_checkService(serviceName);
- if (binder == nullptr) {
- return false;
+ static const sp<android::IServiceManager> sm(android::defaultServiceManager());
+ const Vector<String16> services = sm->listServices();
+ for (const auto service : services) {
+ if (service == String16(serviceName)) return true;
}
- AIBinder_decStrong(binder);
+ return false;
+}
+bool isServiceShutdownWithWait(const char* serviceName) {
+ LOG(INFO) << "About to check and wait for shutdown of " << std::string(serviceName);
+ const auto before = std::chrono::steady_clock::now();
+ while (isServiceRunning(serviceName)) {
+ sleep(1);
+ const auto after = std::chrono::steady_clock::now();
+ if (after - before >= kShutdownWaitTime) return false;
+ }
return true;
}
@@ -450,8 +461,8 @@
service = nullptr;
IPCThreadState::self()->flushCommands();
// Make sure the service is dead after some time of no use
- sleep(kShutdownWaitTime);
- ASSERT_EQ(nullptr, AServiceManager_checkService(kLazyBinderNdkUnitTestService));
+ ASSERT_TRUE(isServiceShutdownWithWait(kLazyBinderNdkUnitTestService))
+ << "Service failed to shut down";
}
TEST(NdkBinder, ForcedPersistenceTest) {
@@ -466,14 +477,12 @@
service = nullptr;
IPCThreadState::self()->flushCommands();
- sleep(kShutdownWaitTime);
-
- bool isRunning = isServiceRunning(kForcePersistNdkUnitTestService);
-
if (i == 0) {
- ASSERT_TRUE(isRunning) << "Service shut down when it shouldn't have.";
+ ASSERT_TRUE(isServiceRunning(kForcePersistNdkUnitTestService))
+ << "Service shut down when it shouldn't have.";
} else {
- ASSERT_FALSE(isRunning) << "Service failed to shut down.";
+ ASSERT_TRUE(isServiceShutdownWithWait(kForcePersistNdkUnitTestService))
+ << "Service failed to shut down";
}
}
}
@@ -491,10 +500,7 @@
service = nullptr;
IPCThreadState::self()->flushCommands();
- LOG(INFO) << "ActiveServicesCallbackTest about to sleep";
- sleep(kShutdownWaitTime);
-
- ASSERT_FALSE(isServiceRunning(kActiveServicesNdkUnitTestService))
+ ASSERT_TRUE(isServiceShutdownWithWait(kActiveServicesNdkUnitTestService))
<< "Service failed to shut down.";
}
@@ -1102,6 +1108,37 @@
EXPECT_EQ(deleteCount, 0);
}
+void* EmptyOnCreate(void* args) {
+ return args;
+}
+void EmptyOnDestroy(void* /*userData*/) {}
+binder_status_t EmptyOnTransact(AIBinder* /*binder*/, transaction_code_t /*code*/,
+ const AParcel* /*in*/, AParcel* /*out*/) {
+ return STATUS_OK;
+}
+
+TEST(NdkBinder_DeathTest, SetCodeMapTwice) {
+ const char* codeToFunction1[] = {"function-1", "function-2", "function-3"};
+ const char* codeToFunction2[] = {"function-4", "function-5"};
+ const char* interfaceName = "interface_descriptor";
+ AIBinder_Class* clazz =
+ AIBinder_Class_define(interfaceName, EmptyOnCreate, EmptyOnDestroy, EmptyOnTransact);
+ AIBinder_Class_setTransactionCodeToFunctionNameMap(clazz, codeToFunction1, 3);
+ // Reset/clear is not allowed
+ EXPECT_DEATH(AIBinder_Class_setTransactionCodeToFunctionNameMap(clazz, codeToFunction2, 2), "");
+}
+
+TEST(NdkBinder_DeathTest, SetNullCodeMap) {
+ const char* codeToFunction[] = {"function-1", "function-2", "function-3"};
+ const char* interfaceName = "interface_descriptor";
+ AIBinder_Class* clazz =
+ AIBinder_Class_define(interfaceName, EmptyOnCreate, EmptyOnDestroy, EmptyOnTransact);
+ EXPECT_DEATH(AIBinder_Class_setTransactionCodeToFunctionNameMap(nullptr, codeToFunction, 3),
+ "");
+ EXPECT_DEATH(AIBinder_Class_setTransactionCodeToFunctionNameMap(clazz, nullptr, 0), "");
+ EXPECT_DEATH(AIBinder_Class_setTransactionCodeToFunctionNameMap(nullptr, nullptr, 0), "");
+}
+
int main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 0e653af..8b0dda3 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -532,6 +532,9 @@
static_libs: [
"libbinder_rpc_single_threaded",
],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
}
cc_test {
diff --git a/libs/binder/tests/binderCacheUnitTest.cpp b/libs/binder/tests/binderCacheUnitTest.cpp
index 92dab19..482d197 100644
--- a/libs/binder/tests/binderCacheUnitTest.cpp
+++ b/libs/binder/tests/binderCacheUnitTest.cpp
@@ -137,9 +137,9 @@
ASSERT_EQ(binder1, result);
// Kill the server, this should remove from cache.
- foo.killServer(binder1);
pid_t pid;
ASSERT_EQ(OK, binder1->getDebugPid(&pid));
+ foo.killServer(binder1);
system(("kill -9 " + std::to_string(pid)).c_str());
sp<IBinder> binder2 = sp<BBinder>::make();
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index fbca35e..11150bc 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -46,6 +46,13 @@
#include "binderRpcTestCommon.h"
#include "binderRpcTestFixture.h"
+// TODO need to add IServiceManager.cpp/.h to libbinder_no_kernel
+#ifdef BINDER_WITH_KERNEL_IPC
+#include "android-base/logging.h"
+#include "android/binder_manager.h"
+#include "android/binder_rpc.h"
+#endif // BINDER_WITH_KERNEL_IPC
+
using namespace std::chrono_literals;
using namespace std::placeholders;
using android::binder::borrowed_fd;
@@ -454,7 +461,7 @@
GTEST_SKIP() << "This test requires multiple threads";
}
- constexpr size_t kNumThreads = 10;
+ constexpr size_t kNumThreads = 5;
auto proc = createRpcTestSocketServerProcess({.numThreads = kNumThreads});
@@ -499,11 +506,11 @@
EXPECT_GE(epochMsAfter, epochMsBefore + 2 * sleepMs);
- // Potential flake, but make sure calls are handled in parallel. Due
- // to past flakes, this only checks that the amount of time taken has
- // some parallelism. Other tests such as ThreadPoolGreaterThanEqualRequested
- // check this more exactly.
- EXPECT_LE(epochMsAfter, epochMsBefore + (numCalls - 1) * sleepMs);
+ // b/272429574, b/365294257
+ // This flakes too much to test. Parallelization is tested
+ // in ThreadPoolGreaterThanEqualRequested and other tests.
+ // Test to make sure calls are handled in parallel.
+ // EXPECT_LE(epochMsAfter, epochMsBefore + (numCalls - 1) * sleepMs);
}
TEST_P(BinderRpc, ThreadPoolOverSaturated) {
@@ -515,8 +522,7 @@
constexpr size_t kNumCalls = kNumThreads + 3;
auto proc = createRpcTestSocketServerProcess({.numThreads = kNumThreads});
- // b/272429574 - below 500ms, the test fails
- testThreadPoolOverSaturated(proc.rootIface, kNumCalls, 500 /*ms*/);
+ testThreadPoolOverSaturated(proc.rootIface, kNumCalls, 200 /*ms*/);
}
TEST_P(BinderRpc, ThreadPoolLimitOutgoing) {
@@ -530,8 +536,7 @@
auto proc = createRpcTestSocketServerProcess(
{.numThreads = kNumThreads, .numOutgoingConnections = kNumOutgoingConnections});
- // b/272429574 - below 500ms, the test fails
- testThreadPoolOverSaturated(proc.rootIface, kNumCalls, 500 /*ms*/);
+ testThreadPoolOverSaturated(proc.rootIface, kNumCalls, 200 /*ms*/);
}
TEST_P(BinderRpc, ThreadingStressTest) {
@@ -1206,27 +1211,29 @@
auto proc = createRpcTestSocketServerProcess({.numThreads = kNumThreads});
EXPECT_EQ(OK, proc.rootBinder->pingBinder());
- auto receipt = addAccessorProvider([&](const String16& name) -> sp<IBinder> {
- return createAccessor(name,
- [&](const String16& name, sockaddr* outAddr,
- socklen_t addrSize) -> status_t {
- if (outAddr == nullptr ||
- addrSize < proc.proc->sessions[0].addrLen) {
- return BAD_VALUE;
- }
- if (name == kInstanceName) {
- if (proc.proc->sessions[0].addr.ss_family == AF_UNIX) {
- sockaddr_un* un = reinterpret_cast<sockaddr_un*>(
- &proc.proc->sessions[0].addr);
- ALOGE("inside callback: %s", un->sun_path);
- }
- std::memcpy(outAddr, &proc.proc->sessions[0].addr,
- proc.proc->sessions[0].addrLen);
- return OK;
- }
- return NAME_NOT_FOUND;
- });
- });
+ auto receipt = addAccessorProvider(
+ {String8(kInstanceName).c_str()}, [&](const String16& name) -> sp<IBinder> {
+ return createAccessor(name,
+ [&](const String16& name, sockaddr* outAddr,
+ socklen_t addrSize) -> status_t {
+ if (outAddr == nullptr ||
+ addrSize < proc.proc->sessions[0].addrLen) {
+ return BAD_VALUE;
+ }
+ if (name == kInstanceName) {
+ if (proc.proc->sessions[0].addr.ss_family ==
+ AF_UNIX) {
+ sockaddr_un* un = reinterpret_cast<sockaddr_un*>(
+ &proc.proc->sessions[0].addr);
+ ALOGE("inside callback: %s", un->sun_path);
+ }
+ std::memcpy(outAddr, &proc.proc->sessions[0].addr,
+ proc.proc->sessions[0].addrLen);
+ return OK;
+ }
+ return NAME_NOT_FOUND;
+ });
+ });
EXPECT_FALSE(receipt.expired());
@@ -1253,7 +1260,8 @@
bool isProviderDeleted = false;
- auto receipt = addAccessorProvider([&](const String16&) -> sp<IBinder> { return nullptr; });
+ auto receipt = addAccessorProvider({String8(kInstanceName).c_str()},
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
EXPECT_FALSE(receipt.expired());
sp<IBinder> binder = defaultServiceManager()->checkService(kInstanceName);
@@ -1263,6 +1271,32 @@
EXPECT_EQ(status, OK);
}
+TEST_P(BinderRpcAccessor, InjectDuplicateAccessorProvider) {
+ const String16 kInstanceName("super.cool.service/better_than_default");
+ const String16 kInstanceName2("super.cool.service/better_than_default2");
+
+ auto receipt =
+ addAccessorProvider({String8(kInstanceName).c_str(), String8(kInstanceName2).c_str()},
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+ EXPECT_FALSE(receipt.expired());
+ // reject this because it's associated with an already used instance name
+ auto receipt2 = addAccessorProvider({String8(kInstanceName).c_str()},
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+ EXPECT_TRUE(receipt2.expired());
+
+ // the first provider should still be usable
+ sp<IBinder> binder = defaultServiceManager()->checkService(kInstanceName);
+ EXPECT_EQ(binder, nullptr);
+
+ status_t status = removeAccessorProvider(receipt);
+ EXPECT_EQ(status, OK);
+}
+
+TEST_P(BinderRpcAccessor, InjectAccessorProviderNoInstance) {
+ auto receipt = addAccessorProvider({}, [&](const String16&) -> sp<IBinder> { return nullptr; });
+ EXPECT_TRUE(receipt.expired());
+}
+
TEST_P(BinderRpcAccessor, InjectNoSockaddrProvided) {
constexpr size_t kNumThreads = 10;
const String16 kInstanceName("super.cool.service/better_than_default");
@@ -1273,12 +1307,15 @@
bool isProviderDeleted = false;
bool isAccessorDeleted = false;
- auto receipt = addAccessorProvider([&](const String16& name) -> sp<IBinder> {
- return createAccessor(name, [&](const String16&, sockaddr*, socklen_t) -> status_t {
- // don't fill in outAddr
- return NAME_NOT_FOUND;
- });
- });
+ auto receipt = addAccessorProvider({String8(kInstanceName).c_str()},
+ [&](const String16& name) -> sp<IBinder> {
+ return createAccessor(name,
+ [&](const String16&, sockaddr*,
+ socklen_t) -> status_t {
+ // don't fill in outAddr
+ return NAME_NOT_FOUND;
+ });
+ });
EXPECT_FALSE(receipt.expired());
@@ -1289,6 +1326,269 @@
EXPECT_EQ(status, OK);
}
+constexpr const char* kARpcInstance = "some.instance.name.IFoo/default";
+const char* kARpcSupportedServices[] = {
+ kARpcInstance,
+};
+const uint32_t kARpcNumSupportedServices = 1;
+
+struct ConnectionInfoData {
+ sockaddr_storage addr;
+ socklen_t len;
+ bool* isDeleted;
+ ~ConnectionInfoData() {
+ if (isDeleted) *isDeleted = true;
+ }
+};
+
+struct AccessorProviderData {
+ sockaddr_storage addr;
+ socklen_t len;
+ bool* isDeleted;
+ ~AccessorProviderData() {
+ if (isDeleted) *isDeleted = true;
+ }
+};
+
+void accessorProviderDataOnDelete(void* data) {
+ delete reinterpret_cast<AccessorProviderData*>(data);
+}
+void infoProviderDataOnDelete(void* data) {
+ delete reinterpret_cast<ConnectionInfoData*>(data);
+}
+
+ABinderRpc_ConnectionInfo* infoProvider(const char* instance, void* cookie) {
+ if (instance == nullptr || cookie == nullptr) return nullptr;
+ ConnectionInfoData* data = reinterpret_cast<ConnectionInfoData*>(cookie);
+ return ABinderRpc_ConnectionInfo_new(reinterpret_cast<const sockaddr*>(&data->addr), data->len);
+}
+
+ABinderRpc_Accessor* getAccessor(const char* instance, void* cookie) {
+ if (instance == nullptr || cookie == nullptr) return nullptr;
+ if (0 != strcmp(instance, kARpcInstance)) return nullptr;
+
+ AccessorProviderData* data = reinterpret_cast<AccessorProviderData*>(cookie);
+
+ ConnectionInfoData* info = new ConnectionInfoData{
+ .addr = data->addr,
+ .len = data->len,
+ .isDeleted = nullptr,
+ };
+
+ return ABinderRpc_Accessor_new(instance, infoProvider, info, infoProviderDataOnDelete);
+}
+
+class BinderARpcNdk : public ::testing::Test {};
+
+TEST_F(BinderARpcNdk, ARpcProviderNewDelete) {
+ bool isDeleted = false;
+
+ AccessorProviderData* data = new AccessorProviderData{{}, 0, &isDeleted};
+
+ ABinderRpc_AccessorProvider* provider =
+ ABinderRpc_registerAccessorProvider(getAccessor, kARpcSupportedServices,
+ kARpcNumSupportedServices, data,
+ accessorProviderDataOnDelete);
+
+ ASSERT_NE(provider, nullptr);
+ EXPECT_FALSE(isDeleted);
+
+ ABinderRpc_unregisterAccessorProvider(provider);
+
+ EXPECT_TRUE(isDeleted);
+}
+
+TEST_F(BinderARpcNdk, ARpcProviderDuplicateInstance) {
+ const char* instance = "some.instance.name.IFoo/default";
+ const uint32_t numInstances = 2;
+ const char* instances[numInstances] = {
+ instance,
+ "some.other.instance/default",
+ };
+
+ bool isDeleted = false;
+
+ AccessorProviderData* data = new AccessorProviderData{{}, 0, &isDeleted};
+
+ ABinderRpc_AccessorProvider* provider =
+ ABinderRpc_registerAccessorProvider(getAccessor, instances, numInstances, data,
+ accessorProviderDataOnDelete);
+
+ ASSERT_NE(provider, nullptr);
+ EXPECT_FALSE(isDeleted);
+
+ const uint32_t numInstances2 = 1;
+ const char* instances2[numInstances2] = {
+ instance,
+ };
+ bool isDeleted2 = false;
+ AccessorProviderData* data2 = new AccessorProviderData{{}, 0, &isDeleted2};
+ ABinderRpc_AccessorProvider* provider2 =
+ ABinderRpc_registerAccessorProvider(getAccessor, instances2, numInstances2, data2,
+ accessorProviderDataOnDelete);
+
+ EXPECT_EQ(provider2, nullptr);
+ // If it fails to be registered, the data is still cleaned up with
+ // accessorProviderDataOnDelete
+ EXPECT_TRUE(isDeleted2);
+
+ ABinderRpc_unregisterAccessorProvider(provider);
+
+ EXPECT_TRUE(isDeleted);
+}
+
+TEST_F(BinderARpcNdk, ARpcProviderRegisterNoInstance) {
+ const uint32_t numInstances = 0;
+ const char* instances[numInstances] = {};
+
+ bool isDeleted = false;
+ AccessorProviderData* data = new AccessorProviderData{{}, 0, &isDeleted};
+
+ ABinderRpc_AccessorProvider* provider =
+ ABinderRpc_registerAccessorProvider(getAccessor, instances, numInstances, data,
+ accessorProviderDataOnDelete);
+ ASSERT_EQ(provider, nullptr);
+}
+
+TEST_F(BinderARpcNdk, ARpcAccessorNewDelete) {
+ bool isDeleted = false;
+
+ ConnectionInfoData* data = new ConnectionInfoData{{}, 0, &isDeleted};
+
+ ABinderRpc_Accessor* accessor =
+ ABinderRpc_Accessor_new("gshoe_service", infoProvider, data, infoProviderDataOnDelete);
+ ASSERT_NE(accessor, nullptr);
+ EXPECT_FALSE(isDeleted);
+
+ ABinderRpc_Accessor_delete(accessor);
+ EXPECT_TRUE(isDeleted);
+}
+
+TEST_F(BinderARpcNdk, ARpcConnectionInfoNewDelete) {
+ sockaddr_vm addr{
+ .svm_family = AF_VSOCK,
+ .svm_port = VMADDR_PORT_ANY,
+ .svm_cid = VMADDR_CID_ANY,
+ };
+
+ ABinderRpc_ConnectionInfo* info =
+ ABinderRpc_ConnectionInfo_new(reinterpret_cast<sockaddr*>(&addr), sizeof(sockaddr_vm));
+ EXPECT_NE(info, nullptr);
+
+ ABinderRpc_ConnectionInfo_delete(info);
+}
+
+TEST_F(BinderARpcNdk, ARpcAsFromBinderAsBinder) {
+ bool isDeleted = false;
+
+ ConnectionInfoData* data = new ConnectionInfoData{{}, 0, &isDeleted};
+
+ ABinderRpc_Accessor* accessor =
+ ABinderRpc_Accessor_new("gshoe_service", infoProvider, data, infoProviderDataOnDelete);
+ ASSERT_NE(accessor, nullptr);
+ EXPECT_FALSE(isDeleted);
+
+ {
+ ndk::SpAIBinder binder = ndk::SpAIBinder(ABinderRpc_Accessor_asBinder(accessor));
+ EXPECT_NE(binder.get(), nullptr);
+
+ ABinderRpc_Accessor* accessor2 =
+ ABinderRpc_Accessor_fromBinder("wrong_service_name", binder.get());
+ // The API checks for the expected service name that is associated with
+ // the accessor!
+ EXPECT_EQ(accessor2, nullptr);
+
+ accessor2 = ABinderRpc_Accessor_fromBinder("gshoe_service", binder.get());
+ EXPECT_NE(accessor2, nullptr);
+
+ // this is a new ABinderRpc_Accessor object that wraps the underlying
+ // libbinder object.
+ EXPECT_NE(accessor, accessor2);
+
+ ndk::SpAIBinder binder2 = ndk::SpAIBinder(ABinderRpc_Accessor_asBinder(accessor2));
+ EXPECT_EQ(binder.get(), binder2.get());
+
+ ABinderRpc_Accessor_delete(accessor2);
+ }
+
+ EXPECT_FALSE(isDeleted);
+ ABinderRpc_Accessor_delete(accessor);
+ EXPECT_TRUE(isDeleted);
+}
+
+TEST_F(BinderARpcNdk, ARpcRequireProviderOnDeleteCallback) {
+ EXPECT_EQ(nullptr,
+ ABinderRpc_registerAccessorProvider(getAccessor, kARpcSupportedServices,
+ kARpcNumSupportedServices,
+ reinterpret_cast<void*>(1), nullptr));
+}
+
+TEST_F(BinderARpcNdk, ARpcRequireInfoOnDeleteCallback) {
+ EXPECT_EQ(nullptr,
+ ABinderRpc_Accessor_new("the_best_service_name", infoProvider,
+ reinterpret_cast<void*>(1), nullptr));
+}
+
+TEST_F(BinderARpcNdk, ARpcNoDataNoProviderOnDeleteCallback) {
+ ABinderRpc_AccessorProvider* provider =
+ ABinderRpc_registerAccessorProvider(getAccessor, kARpcSupportedServices,
+ kARpcNumSupportedServices, nullptr, nullptr);
+ ASSERT_NE(nullptr, provider);
+ ABinderRpc_unregisterAccessorProvider(provider);
+}
+
+TEST_F(BinderARpcNdk, ARpcNoDataNoInfoOnDeleteCallback) {
+ ABinderRpc_Accessor* accessor =
+ ABinderRpc_Accessor_new("the_best_service_name", infoProvider, nullptr, nullptr);
+ ASSERT_NE(nullptr, accessor);
+ ABinderRpc_Accessor_delete(accessor);
+}
+
+TEST_F(BinderARpcNdk, ARpcDoubleRemoveProvider) {
+ ABinderRpc_AccessorProvider* provider =
+ ABinderRpc_registerAccessorProvider(getAccessor, kARpcSupportedServices,
+ kARpcNumSupportedServices, nullptr, nullptr);
+ ASSERT_NE(nullptr, provider);
+ ABinderRpc_unregisterAccessorProvider(provider);
+ EXPECT_DEATH(ABinderRpc_unregisterAccessorProvider(provider), " was already unregistered");
+}
+
+TEST_F(BinderARpcNdk, ARpcNullArgs_ConnectionInfo_new) {
+ sockaddr_storage addr;
+ EXPECT_EQ(nullptr, ABinderRpc_ConnectionInfo_new(reinterpret_cast<const sockaddr*>(&addr), 0));
+}
+
+TEST_P(BinderRpcAccessor, ARpcGetService) {
+ constexpr size_t kNumThreads = 10;
+ bool isDeleted = false;
+
+ auto proc = createRpcTestSocketServerProcess({.numThreads = kNumThreads});
+ EXPECT_EQ(OK, proc.rootBinder->pingBinder());
+
+ AccessorProviderData* data =
+ new AccessorProviderData{proc.proc->sessions[0].addr, proc.proc->sessions[0].addrLen,
+ &isDeleted};
+
+ ABinderRpc_AccessorProvider* provider =
+ ABinderRpc_registerAccessorProvider(getAccessor, kARpcSupportedServices,
+ kARpcNumSupportedServices, data,
+ accessorProviderDataOnDelete);
+
+ EXPECT_NE(provider, nullptr);
+ EXPECT_FALSE(isDeleted);
+
+ {
+ ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_checkService(kARpcInstance));
+ ASSERT_NE(binder.get(), nullptr);
+ EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get()));
+ }
+
+ ABinderRpc_unregisterAccessorProvider(provider);
+ EXPECT_TRUE(isDeleted);
+
+ waitForExtraSessionCleanup(proc);
+}
+
#endif // BINDER_WITH_KERNEL_IPC
#ifdef BINDER_RPC_TO_TRUSTY_TEST
diff --git a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
index 3a1471e..e3a3371 100644
--- a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
@@ -49,7 +49,8 @@
return STATUS_UNKNOWN_TRANSACTION;
}
-static AIBinder_Class* g_class = ::ndk::ICInterface::defineClass("ISomeInterface", onTransact);
+static AIBinder_Class* g_class =
+ ::ndk::ICInterface::defineClass("ISomeInterface", onTransact, nullptr, 0);
class BpSomeInterface : public ::ndk::BpCInterface<ISomeInterface> {
public:
diff --git a/libs/binder/trusty/OS.cpp b/libs/binder/trusty/OS.cpp
index 157ab3c..ba9e457 100644
--- a/libs/binder/trusty/OS.cpp
+++ b/libs/binder/trusty/OS.cpp
@@ -42,6 +42,10 @@
void trace_int(uint64_t, const char*, int32_t) {}
+uint64_t get_trace_enabled_tags() {
+ return 0;
+}
+
uint64_t GetThreadId() {
return 0;
}
diff --git a/libs/binder/trusty/ndk/include/android/llndk-versioning.h b/libs/binder/trusty/ndk/include/android/llndk-versioning.h
index 3ae3d8f..e955a34 100644
--- a/libs/binder/trusty/ndk/include/android/llndk-versioning.h
+++ b/libs/binder/trusty/ndk/include/android/llndk-versioning.h
@@ -15,4 +15,5 @@
*/
#pragma once
-#define __INTRODUCED_IN_LLNDK(x) /* nothing on Trusty */
+// TODO(b/349936395): set to true for Trusty
+#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) (false)
diff --git a/libs/debugstore/OWNERS b/libs/debugstore/OWNERS
index 428a1a2..c8e22b7 100644
--- a/libs/debugstore/OWNERS
+++ b/libs/debugstore/OWNERS
@@ -1,3 +1,2 @@
benmiles@google.com
-gaillard@google.com
mohamadmahmoud@google.com
diff --git a/libs/debugstore/rust/Android.bp b/libs/debugstore/rust/Android.bp
index 55ba3c3..9475333 100644
--- a/libs/debugstore/rust/Android.bp
+++ b/libs/debugstore/rust/Android.bp
@@ -23,7 +23,6 @@
rustlibs: [
"libcrossbeam_queue",
"libparking_lot",
- "libonce_cell",
"libcxx",
],
shared_libs: ["libutils"],
diff --git a/libs/debugstore/rust/src/core.rs b/libs/debugstore/rust/src/core.rs
index 1dfa512..6bf79d4 100644
--- a/libs/debugstore/rust/src/core.rs
+++ b/libs/debugstore/rust/src/core.rs
@@ -17,12 +17,14 @@
use super::event_type::EventType;
use super::storage::Storage;
use crate::cxxffi::uptimeMillis;
-use once_cell::sync::Lazy;
use std::fmt;
-use std::sync::atomic::{AtomicU64, Ordering};
+use std::sync::{
+ atomic::{AtomicU64, Ordering},
+ LazyLock,
+};
// Lazily initialized static instance of DebugStore.
-static INSTANCE: Lazy<DebugStore> = Lazy::new(DebugStore::new);
+static INSTANCE: LazyLock<DebugStore> = LazyLock::new(DebugStore::new);
/// The `DebugStore` struct is responsible for managing debug events and data.
pub struct DebugStore {
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 739c3c2..044170c 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -1096,6 +1096,17 @@
AsyncWorker::getInstance().post(
[listener = mListener, slots = slots]() { listener->onBuffersDiscarded(slots); });
}
+
+ void onBufferDetached(int slot) override {
+ AsyncWorker::getInstance().post(
+ [listener = mListener, slot = slot]() { listener->onBufferDetached(slot); });
+ }
+
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_CONSUMER_ATTACH_CALLBACK)
+ void onBufferAttached() override {
+ AsyncWorker::getInstance().post([listener = mListener]() { listener->onBufferAttached(); });
+ }
+#endif
};
// Extends the BufferQueueProducer to create a wrapper around the listener so the listener calls
diff --git a/libs/gui/IProducerListener.cpp b/libs/gui/IProducerListener.cpp
index 7700795..8b9b090 100644
--- a/libs/gui/IProducerListener.cpp
+++ b/libs/gui/IProducerListener.cpp
@@ -184,4 +184,10 @@
void BnProducerListener::onBuffersDiscarded(const std::vector<int32_t>& /*discardedSlots*/) {
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_CONSUMER_ATTACH_CALLBACK)
+bool BnProducerListener::needsAttachNotify() {
+ return true;
+}
+#endif
+
} // namespace android
diff --git a/libs/gui/include/gui/IProducerListener.h b/libs/gui/include/gui/IProducerListener.h
index 3dcc6b6..43bf6a7 100644
--- a/libs/gui/include/gui/IProducerListener.h
+++ b/libs/gui/include/gui/IProducerListener.h
@@ -90,6 +90,9 @@
Parcel* reply, uint32_t flags = 0);
virtual bool needsReleaseNotify();
virtual void onBuffersDiscarded(const std::vector<int32_t>& slots);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_CONSUMER_ATTACH_CALLBACK)
+ virtual bool needsAttachNotify();
+#endif
};
#else
@@ -103,6 +106,9 @@
virtual ~StubProducerListener();
virtual void onBufferReleased() {}
virtual bool needsReleaseNotify() { return false; }
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_CONSUMER_ATTACH_CALLBACK)
+ virtual bool needsAttachNotify() { return false; }
+#endif
};
} // namespace android
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index e9d799e..9c0a41e 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -91,6 +91,7 @@
},
},
},
+ native_coverage: false,
}
// NOTE: This is a compile time test, and does not need to be
diff --git a/libs/nativewindow/rust/src/handle.rs b/libs/nativewindow/rust/src/handle.rs
index a3a9dc6..c41ab8d 100644
--- a/libs/nativewindow/rust/src/handle.rs
+++ b/libs/nativewindow/rust/src/handle.rs
@@ -12,7 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use std::{mem::forget, ptr::NonNull};
+use std::{
+ ffi::c_int,
+ mem::forget,
+ os::fd::{BorrowedFd, FromRawFd, IntoRawFd, OwnedFd},
+ ptr::NonNull,
+};
/// Rust wrapper around `native_handle_t`.
///
@@ -22,6 +27,108 @@
pub struct NativeHandle(NonNull<ffi::native_handle_t>);
impl NativeHandle {
+ /// Creates a new `NativeHandle` with the given file descriptors and integer values.
+ ///
+ /// The `NativeHandle` will take ownership of the file descriptors and close them when it is
+ /// dropped.
+ pub fn new(fds: Vec<OwnedFd>, ints: &[c_int]) -> Option<Self> {
+ let fd_count = fds.len();
+ // SAFETY: native_handle_create doesn't have any safety requirements.
+ let handle = unsafe {
+ ffi::native_handle_create(fd_count.try_into().unwrap(), ints.len().try_into().unwrap())
+ };
+ let handle = NonNull::new(handle)?;
+ for (i, fd) in fds.into_iter().enumerate() {
+ // SAFETY: `handle` must be valid because it was just created, and the array offset is
+ // within the bounds of what we allocated above.
+ unsafe {
+ *(*handle.as_ptr()).data.as_mut_ptr().add(i) = fd.into_raw_fd();
+ }
+ }
+ for (i, value) in ints.iter().enumerate() {
+ // SAFETY: `handle` must be valid because it was just created, and the array offset is
+ // within the bounds of what we allocated above. Note that `data` is uninitialized
+ // until after this so we can't use `slice::from_raw_parts_mut` or similar to create a
+ // reference to it so we use raw pointers arithmetic instead.
+ unsafe {
+ *(*handle.as_ptr()).data.as_mut_ptr().add(fd_count + i) = *value;
+ }
+ }
+ // SAFETY: `handle` must be valid because it was just created.
+ unsafe {
+ ffi::native_handle_set_fdsan_tag(handle.as_ptr());
+ }
+ Some(Self(handle))
+ }
+
+ /// Returns a borrowed view of all the file descriptors in this native handle.
+ pub fn fds(&self) -> Vec<BorrowedFd> {
+ self.data()[..self.fd_count()]
+ .iter()
+ .map(|fd| {
+ // SAFETY: The `native_handle_t` maintains ownership of the file descriptor so it
+ // won't be closed until this `NativeHandle` is destroyed. The `BorrowedFd` will
+ // have a lifetime constrained to that of `&self`, so it can't outlive it.
+ unsafe { BorrowedFd::borrow_raw(*fd) }
+ })
+ .collect()
+ }
+
+ /// Returns the integer values in this native handle.
+ pub fn ints(&self) -> &[c_int] {
+ &self.data()[self.fd_count()..]
+ }
+
+ /// Destroys the `NativeHandle`, taking ownership of the file descriptors it contained.
+ pub fn into_fds(self) -> Vec<OwnedFd> {
+ let fds = self.data()[..self.fd_count()]
+ .iter()
+ .map(|fd| {
+ // SAFETY: The `native_handle_t` has ownership of the file descriptor, and
+ // after this we destroy it without closing the file descriptor so we can take over
+ // ownership of it.
+ unsafe { OwnedFd::from_raw_fd(*fd) }
+ })
+ .collect();
+
+ // SAFETY: Our wrapped `native_handle_t` pointer is always valid, and it won't be accessed
+ // after this because we own it and forget it.
+ unsafe {
+ assert_eq!(ffi::native_handle_delete(self.0.as_ptr()), 0);
+ }
+ // Don't drop self, as that would cause `native_handle_close` to be called and close the
+ // file descriptors.
+ forget(self);
+ fds
+ }
+
+ /// Returns a reference to the underlying `native_handle_t`.
+ fn as_ref(&self) -> &ffi::native_handle_t {
+ // SAFETY: All the ways of creating a `NativeHandle` ensure that the `native_handle_t` is
+ // valid and initialised, and lives as long as the `NativeHandle`. We enforce Rust's
+ // aliasing rules by giving the reference a lifetime matching that of `&self`.
+ unsafe { self.0.as_ref() }
+ }
+
+ /// Returns the number of file descriptors included in the native handle.
+ fn fd_count(&self) -> usize {
+ self.as_ref().numFds.try_into().unwrap()
+ }
+
+ /// Returns the number of integer values included in the native handle.
+ fn int_count(&self) -> usize {
+ self.as_ref().numInts.try_into().unwrap()
+ }
+
+ /// Returns a slice reference for all the used `data` field of the native handle, including both
+ /// file descriptors and integers.
+ fn data(&self) -> &[c_int] {
+ let total_count = self.fd_count() + self.int_count();
+ // SAFETY: The data must have been initialised with this number of elements when the
+ // `NativeHandle` was created.
+ unsafe { self.as_ref().data.as_slice(total_count) }
+ }
+
/// Wraps a raw `native_handle_t` pointer, taking ownership of it.
///
/// # Safety
@@ -90,3 +197,47 @@
// SAFETY: A `NativeHandle` can be used from different threads simultaneously, as is is just
// integers and file descriptors.
unsafe impl Sync for NativeHandle {}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use std::fs::File;
+
+ #[test]
+ fn create_empty() {
+ let handle = NativeHandle::new(vec![], &[]).unwrap();
+ assert_eq!(handle.fds().len(), 0);
+ assert_eq!(handle.ints(), &[]);
+ }
+
+ #[test]
+ fn create_with_ints() {
+ let handle = NativeHandle::new(vec![], &[1, 2, 42]).unwrap();
+ assert_eq!(handle.fds().len(), 0);
+ assert_eq!(handle.ints(), &[1, 2, 42]);
+ }
+
+ #[test]
+ fn create_with_fd() {
+ let file = File::open("/dev/null").unwrap();
+ let handle = NativeHandle::new(vec![file.into()], &[]).unwrap();
+ assert_eq!(handle.fds().len(), 1);
+ assert_eq!(handle.ints(), &[]);
+ }
+
+ #[test]
+ fn clone() {
+ let file = File::open("/dev/null").unwrap();
+ let original = NativeHandle::new(vec![file.into()], &[42]).unwrap();
+ assert_eq!(original.ints(), &[42]);
+ assert_eq!(original.fds().len(), 1);
+
+ let cloned = original.clone();
+ drop(original);
+
+ assert_eq!(cloned.ints(), &[42]);
+ assert_eq!(cloned.fds().len(), 1);
+
+ drop(cloned);
+ }
+}
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index ffb6cdb..b0c6e44 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -388,8 +388,8 @@
}
}
- const uint64_t usage = static_cast<uint64_t>(
- android_convertGralloc1To0Usage(inProducerUsage, inConsumerUsage));
+ const uint64_t usage = static_cast<uint64_t>(ANDROID_NATIVE_UNSIGNED_CAST(
+ android_convertGralloc1To0Usage(inProducerUsage, inConsumerUsage)));
auto result = getBufferMapper().lock(handle, usage, rect, base::unique_fd{fenceFd});
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index b6ab2f5..7b5a27d 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -208,8 +208,10 @@
status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle, uint64_t producerUsage,
uint64_t consumerUsage, const Rect& bounds, void** vaddr,
int fenceFd) {
- return lockAsync(handle, android_convertGralloc1To0Usage(producerUsage, consumerUsage), bounds,
- vaddr, fenceFd);
+ return lockAsync(handle,
+ ANDROID_NATIVE_UNSIGNED_CAST(
+ android_convertGralloc1To0Usage(producerUsage, consumerUsage)),
+ bounds, vaddr, fenceFd);
}
status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle, uint32_t usage,
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index cf0d46a..18b6c5e 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -116,4 +116,5 @@
unit_test: true,
},
test_suites: ["device-tests"],
+ native_coverage: false,
}
diff --git a/services/inputflinger/tests/InputTracingTest.cpp b/services/inputflinger/tests/InputTracingTest.cpp
index 2ccd93e..3cc4bdd 100644
--- a/services/inputflinger/tests/InputTracingTest.cpp
+++ b/services/inputflinger/tests/InputTracingTest.cpp
@@ -133,8 +133,8 @@
mDispatcher->setFocusedWindow(request);
}
- void tapAndExpect(const std::vector<const sp<FakeWindowHandle>>& windows,
- Level inboundTraceLevel, Level dispatchTraceLevel, InputTraceSession& s) {
+ void tapAndExpect(const std::vector<sp<FakeWindowHandle>>& windows, Level inboundTraceLevel,
+ Level dispatchTraceLevel, InputTraceSession& s) {
const auto down = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
.pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(110))
.build();
@@ -156,7 +156,7 @@
}
}
- void keypressAndExpect(const std::vector<const sp<FakeWindowHandle>>& windows,
+ void keypressAndExpect(const std::vector<sp<FakeWindowHandle>>& windows,
Level inboundTraceLevel, Level dispatchTraceLevel,
InputTraceSession& s) {
const auto down = KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build();
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index dd86e4f..a4368a6 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -841,7 +841,8 @@
return score.overallScore == 0;
});
- if (policy->primaryRangeIsSingleRate()) {
+ // TODO(b/364651864): Evaluate correctness of primaryRangeIsSingleRate.
+ if (!isVrrDevice() && policy->primaryRangeIsSingleRate()) {
// If we never scored any layers, then choose the rate from the primary
// range instead of picking a random score from the app range.
if (noLayerScore) {
@@ -887,10 +888,10 @@
const auto touchRefreshRates = rankFrameRates(anchorGroup, RefreshRateOrder::Descending);
using fps_approx_ops::operator<;
- if (scores.front().frameRateMode.fps < touchRefreshRates.front().frameRateMode.fps) {
- ALOGV("Touch Boost");
+ if (scores.front().frameRateMode.fps <= touchRefreshRates.front().frameRateMode.fps) {
+ ALOGV("Touch Boost [late]");
ATRACE_FORMAT_INSTANT("%s (Touch Boost [late])",
- to_string(touchRefreshRates.front().frameRateMode.fps).c_str());
+ to_string(touchRefreshRates.front().frameRateMode.fps).c_str());
return {touchRefreshRates, GlobalSignals{.touch = true}};
}
}
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h b/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h
index 2c397bd..a54d435 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h
@@ -134,8 +134,11 @@
}
size_t getPresentFenceShift(Period minFramePeriod) const {
- const bool isTwoVsyncsAhead = targetsVsyncsAhead<2>(minFramePeriod);
size_t shift = 0;
+ if (minFramePeriod.ns() == 0) {
+ return shift;
+ }
+ const bool isTwoVsyncsAhead = targetsVsyncsAhead<2>(minFramePeriod);
if (isTwoVsyncsAhead) {
shift = static_cast<size_t>(expectedFrameDuration().ns() / minFramePeriod.ns());
if (shift >= mPresentFences.size()) {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1aaa128..d4d32aa 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2334,7 +2334,7 @@
if (flushTransactions) {
needsTraversal |= commitMirrorDisplays(vsyncId);
needsTraversal |= commitCreatedLayers(vsyncId, update.layerCreatedStates);
- needsTraversal |= applyTransactions(update.transactions, vsyncId);
+ needsTraversal |= applyTransactions(update.transactions);
}
outTransactionsAreEmpty = !needsTraversal;
const bool shouldCommit = (getTransactionFlags() & ~eTransactionFlushNeeded) || needsTraversal;
@@ -2515,7 +2515,7 @@
bool newDataLatched = false;
ATRACE_NAME("DisplayCallbackAndStatsUpdates");
- mustComposite |= applyTransactionsLocked(update.transactions, vsyncId);
+ mustComposite |= applyTransactionsLocked(update.transactions);
traverseLegacyLayers([&](Layer* layer) { layer->commitTransaction(); });
const nsecs_t latchTime = systemTime();
bool unused = false;
@@ -5090,20 +5090,18 @@
}
// For tests only
-bool SurfaceFlinger::flushTransactionQueues(VsyncId vsyncId) {
+bool SurfaceFlinger::flushTransactionQueues() {
mTransactionHandler.collectTransactions();
std::vector<TransactionState> transactions = mTransactionHandler.flushTransactions();
- return applyTransactions(transactions, vsyncId);
+ return applyTransactions(transactions);
}
-bool SurfaceFlinger::applyTransactions(std::vector<TransactionState>& transactions,
- VsyncId vsyncId) {
+bool SurfaceFlinger::applyTransactions(std::vector<TransactionState>& transactions) {
Mutex::Autolock lock(mStateLock);
- return applyTransactionsLocked(transactions, vsyncId);
+ return applyTransactionsLocked(transactions);
}
-bool SurfaceFlinger::applyTransactionsLocked(std::vector<TransactionState>& transactions,
- VsyncId vsyncId) {
+bool SurfaceFlinger::applyTransactionsLocked(std::vector<TransactionState>& transactions) {
bool needsTraversal = false;
// Now apply all transactions.
for (auto& transaction : transactions) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index a3534b5..2369043 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -814,9 +814,9 @@
REQUIRES(mStateLock, kMainThreadContext);
// Flush pending transactions that were presented after desiredPresentTime.
// For test only
- bool flushTransactionQueues(VsyncId) REQUIRES(kMainThreadContext);
+ bool flushTransactionQueues() REQUIRES(kMainThreadContext);
- bool applyTransactions(std::vector<TransactionState>&, VsyncId) REQUIRES(kMainThreadContext);
+ bool applyTransactions(std::vector<TransactionState>&) REQUIRES(kMainThreadContext);
bool applyAndCommitDisplayTransactionStatesLocked(std::vector<TransactionState>& transactions)
REQUIRES(kMainThreadContext, mStateLock);
@@ -854,7 +854,7 @@
static LatchUnsignaledConfig getLatchUnsignaledConfig();
bool shouldLatchUnsignaled(const layer_state_t&, size_t numStates, bool firstTransaction) const;
- bool applyTransactionsLocked(std::vector<TransactionState>& transactions, VsyncId)
+ bool applyTransactionsLocked(std::vector<TransactionState>& transactions)
REQUIRES(mStateLock, kMainThreadContext);
uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);
uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands)
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
index cf9a7d3..4ffd52b 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
@@ -1766,6 +1766,43 @@
}
}
+TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_vrrHighHintTouch_primaryRangeIsSingleRate) {
+ if (GetParam() != Config::FrameRateOverride::Enabled) {
+ return;
+ }
+
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+
+ auto selector = createSelector(kVrrMode_120, kModeId120);
+ selector.setActiveMode(kModeId120, 60_Hz);
+
+ // Change primary physical range to be single rate, which on VRR device should not affect
+ // fps scoring.
+ EXPECT_EQ(SetPolicyResult::Changed,
+ selector.setDisplayManagerPolicy({kModeId120, {120_Hz, 120_Hz}}));
+
+ std::vector<LayerRequirement> layers = {{.weight = 1.f}, {.weight = 1.f}};
+ layers[0].vote = LayerVoteType::ExplicitCategory;
+ layers[0].frameRateCategory = FrameRateCategory::HighHint;
+ layers[0].name = "ExplicitCategory HighHint";
+
+ auto actualRankedFrameRates = selector.getRankedFrameRates(layers);
+ // Expect late touch boost from HighHint.
+ EXPECT_EQ(120_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps);
+ EXPECT_EQ(kModeId120, actualRankedFrameRates.ranking.front().frameRateMode.modePtr->getId());
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
+
+ layers[1].vote = LayerVoteType::ExplicitExactOrMultiple;
+ layers[1].desiredRefreshRate = 30_Hz;
+ layers[1].name = "ExplicitExactOrMultiple 30Hz";
+
+ actualRankedFrameRates = selector.getRankedFrameRates(layers);
+ // Expect late touch boost from HighHint.
+ EXPECT_EQ(120_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps);
+ EXPECT_EQ(kModeId120, actualRankedFrameRates.ranking.front().frameRateMode.modePtr->getId());
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
+}
+
TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_HighHint) {
auto selector = createSelector(makeModes(kMode24, kMode30, kMode60, kMode120), kModeId60);
@@ -1884,7 +1921,7 @@
// Gets touch boost
EXPECT_EQ(120_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps);
EXPECT_EQ(kModeId120, actualRankedFrameRates.ranking.front().frameRateMode.modePtr->getId());
- EXPECT_FALSE(actualRankedFrameRates.consideredSignals.touch);
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
}
TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_TouchBoost) {
@@ -1978,7 +2015,7 @@
lr2.name = "Max";
actualRankedFrameRates = selector.getRankedFrameRates(layers, {.touch = true});
EXPECT_FRAME_RATE_MODE(kMode120, 120_Hz, actualRankedFrameRates.ranking.front().frameRateMode);
- EXPECT_FALSE(actualRankedFrameRates.consideredSignals.touch);
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
lr1.vote = LayerVoteType::ExplicitCategory;
lr1.frameRateCategory = FrameRateCategory::Normal;
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index f063809..1f7bf5f 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -133,7 +133,9 @@
using Scheduler::resyncAllToHardwareVsync;
auto& mutableLayerHistory() { return mLayerHistory; }
- auto& mutableAttachedChoreographers() { return mAttachedChoreographers; }
+ auto& mutableAttachedChoreographers() NO_THREAD_SAFETY_ANALYSIS {
+ return mAttachedChoreographers;
+ }
size_t layerHistorySize() NO_THREAD_SAFETY_ANALYSIS {
return mLayerHistory.mActiveLayerInfos.size() + mLayerHistory.mInactiveLayerInfos.size();
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 4197cbd..c11b555 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -547,7 +547,7 @@
}
auto flushTransactionQueues() {
- return FTL_FAKE_GUARD(kMainThreadContext, mFlinger->flushTransactionQueues(kVsyncId));
+ return FTL_FAKE_GUARD(kMainThreadContext, mFlinger->flushTransactionQueues());
}
auto onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
@@ -663,8 +663,10 @@
* post-conditions.
*/
- const auto& displays() const { return mFlinger->mDisplays; }
- const auto& physicalDisplays() const { return mFlinger->mPhysicalDisplays; }
+ const auto& displays() const NO_THREAD_SAFETY_ANALYSIS { return mFlinger->mDisplays; }
+ const auto& physicalDisplays() const NO_THREAD_SAFETY_ANALYSIS {
+ return mFlinger->mPhysicalDisplays;
+ }
const auto& currentState() const { return mFlinger->mCurrentState; }
const auto& drawingState() const { return mFlinger->mDrawingState; }
const auto& transactionFlags() const { return mFlinger->mTransactionFlags; }
@@ -677,13 +679,17 @@
auto& mutableDisplayModeController() { return mFlinger->mDisplayModeController; }
auto& mutableCurrentState() { return mFlinger->mCurrentState; }
auto& mutableDisplayColorSetting() { return mFlinger->mDisplayColorSetting; }
- auto& mutableDisplays() { return mFlinger->mDisplays; }
- auto& mutablePhysicalDisplays() { return mFlinger->mPhysicalDisplays; }
+ auto& mutableDisplays() NO_THREAD_SAFETY_ANALYSIS { return mFlinger->mDisplays; }
+ auto& mutablePhysicalDisplays() NO_THREAD_SAFETY_ANALYSIS {
+ return mFlinger->mPhysicalDisplays;
+ }
auto& mutableDrawingState() { return mFlinger->mDrawingState; }
auto& mutableGeometryDirty() { return mFlinger->mGeometryDirty; }
auto& mutableVisibleRegionsDirty() { return mFlinger->mVisibleRegionsDirty; }
auto& mutableMainThreadId() { return mFlinger->mMainThreadId; }
- auto& mutablePendingHotplugEvents() { return mFlinger->mPendingHotplugEvents; }
+ auto& mutablePendingHotplugEvents() NO_THREAD_SAFETY_ANALYSIS {
+ return mFlinger->mPendingHotplugEvents;
+ }
auto& mutableTransactionFlags() { return mFlinger->mTransactionFlags; }
auto& mutableDebugDisableHWC() { return mFlinger->mDebugDisableHWC; }
auto& mutableMaxRenderTargetSize() { return mFlinger->mMaxRenderTargetSize; }
@@ -691,7 +697,7 @@
auto& mutableHwcDisplayData() { return getHwComposer().mDisplayData; }
auto& mutableHwcPhysicalDisplayIdMap() { return getHwComposer().mPhysicalDisplayIdMap; }
auto& mutablePrimaryHwcDisplayId() { return getHwComposer().mPrimaryHwcDisplayId; }
- auto& mutableActiveDisplayId() { return mFlinger->mActiveDisplayId; }
+ auto& mutableActiveDisplayId() NO_THREAD_SAFETY_ANALYSIS { return mFlinger->mActiveDisplayId; }
auto& mutablePreviouslyComposedLayers() { return mFlinger->mPreviouslyComposedLayers; }
auto& mutableActiveDisplayRotationFlags() {