Merge "libbinder_random_parcel: more failures logs"
diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc
index 9186514..fa7be18 100644
--- a/cmds/atrace/atrace_userdebug.rc
+++ b/cmds/atrace/atrace_userdebug.rc
@@ -18,3 +18,9 @@
chmod 0666 /sys/kernel/tracing/events/filemap/enable
chmod 0666 /sys/kernel/debug/tracing/events/filemap/enable
+ # Allow traced_probes to use the raw_syscall filters to trace only a subset
+ # of syscalls.
+ chmod 0666 /sys/kernel/tracing/events/raw_syscalls/sys_enter/filter
+ chmod 0666 /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/filter
+ chmod 0666 /sys/kernel/tracing/events/raw_syscalls/sys_exit/filter
+ chmod 0666 /sys/kernel/debug/tracing/events/raw_syscalls/sys_exit/filter
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 25bd9a3..fd879c6 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -90,29 +90,16 @@
cc_fuzz {
name: "servicemanager_fuzzer",
- defaults: ["servicemanager_defaults"],
- host_supported: true,
- static_libs: [
- "libbase",
- "libbinder_random_parcel",
- "libcutils",
+ defaults: [
+ "servicemanager_defaults",
+ "service_fuzzer_defaults",
],
- target: {
- android: {
- shared_libs: [
- "libbinder_ndk",
- "libbinder",
- ],
- },
- host: {
- static_libs: [
- "libbinder_ndk",
- "libbinder",
- ],
- },
- },
+ host_supported: true,
srcs: ["ServiceManagerFuzzer.cpp"],
fuzz_config: {
+ libfuzzer_options: [
+ "max_len=50000",
+ ],
cc: [
"smoreland@google.com",
"waghpawan@google.com",
diff --git a/cmds/servicemanager/ServiceManagerFuzzer.cpp b/cmds/servicemanager/ServiceManagerFuzzer.cpp
index 9e2e53f..39f8522 100644
--- a/cmds/servicemanager/ServiceManagerFuzzer.cpp
+++ b/cmds/servicemanager/ServiceManagerFuzzer.cpp
@@ -26,13 +26,9 @@
using ::android::sp;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- if (size > 50000) {
- return 0;
- }
-
auto accessPtr = std::make_unique<Access>();
auto serviceManager = sp<ServiceManager>::make(std::move(accessPtr));
fuzzService(serviceManager, FuzzedDataProvider(data, size));
return 0;
-}
\ No newline at end of file
+}
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index fabf3eb..2cb6821 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -446,6 +446,7 @@
// This library is intentionally limited to these targets, and it will be removed later.
// Do not expand the visibility.
visibility: [
+ ":__subpackages__",
"//packages/modules/Virtualization:__subpackages__",
],
}
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index b5ea60f..1dc6233 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -202,6 +202,17 @@
proxy->withLock(doWithLock);
}
+sp<IBinder> IBinder::lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs) {
+ BBinder* local = localBinder();
+ if (local) {
+ return local->lookupOrCreateWeak(objectID, make, makeArgs);
+ }
+ BpBinder* proxy = this->remoteBinder();
+ LOG_ALWAYS_FATAL_IF(proxy == nullptr, "binder object must be either local or remote");
+ return proxy->lookupOrCreateWeak(objectID, make, makeArgs);
+}
+
// ---------------------------------------------------------------------------
class BBinder::RpcServerLink : public IBinder::DeathRecipient {
@@ -378,6 +389,14 @@
doWithLock();
}
+sp<IBinder> BBinder::lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs) {
+ Extras* e = getOrCreateExtras();
+ LOG_ALWAYS_FATAL_IF(!e, "no memory");
+ AutoMutex _l(e->mLock);
+ return e->mObjects.lookupOrCreateWeak(objectID, make, makeArgs);
+}
+
BBinder* BBinder::localBinder()
{
return this;
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index b6d35ef..d9b7231 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -100,6 +100,36 @@
return value;
}
+namespace {
+struct Tag {
+ wp<IBinder> binder;
+};
+} // namespace
+
+static void cleanWeak(const void* /* id */, void* obj, void* /* cookie */) {
+ delete static_cast<Tag*>(obj);
+}
+
+sp<IBinder> BpBinder::ObjectManager::lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs) {
+ entry_t& e = mObjects[objectID];
+ if (e.object != nullptr) {
+ if (auto attached = static_cast<Tag*>(e.object)->binder.promote()) {
+ return attached;
+ }
+ } else {
+ e.object = new Tag;
+ LOG_ALWAYS_FATAL_IF(!e.object, "no more memory");
+ }
+ sp<IBinder> newObj = make(makeArgs);
+
+ static_cast<Tag*>(e.object)->binder = newObj;
+ e.cleanupCookie = nullptr;
+ e.func = cleanWeak;
+
+ return newObj;
+}
+
void BpBinder::ObjectManager::kill()
{
const size_t N = mObjects.size();
@@ -516,6 +546,12 @@
doWithLock();
}
+sp<IBinder> BpBinder::lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs) {
+ AutoMutex _l(mLock);
+ return mObjects.lookupOrCreateWeak(objectID, make, makeArgs);
+}
+
BpBinder* BpBinder::remoteBinder()
{
return this;
diff --git a/libs/binder/OS.cpp b/libs/binder/OS.cpp
index 6eb7272..cc4a03b 100644
--- a/libs/binder/OS.cpp
+++ b/libs/binder/OS.cpp
@@ -48,4 +48,14 @@
return OK;
}
+status_t dupFileDescriptor(int oldFd, int* newFd) {
+ int ret = fcntl(oldFd, F_DUPFD_CLOEXEC, 0);
+ if (ret < 0) {
+ return -errno;
+ }
+
+ *newFd = ret;
+ return OK;
+}
+
} // namespace android
diff --git a/libs/binder/OS.h b/libs/binder/OS.h
index e802e9c..d6e1c78 100644
--- a/libs/binder/OS.h
+++ b/libs/binder/OS.h
@@ -28,4 +28,6 @@
status_t getRandomBytes(uint8_t* data, size_t size);
+status_t dupFileDescriptor(int oldFd, int* newFd);
+
} // namespace android
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 8b5d118..8887572 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -48,6 +48,7 @@
#include <utils/String8.h>
#include <utils/misc.h>
+#include "OS.h"
#include "RpcState.h"
#include "Static.h"
#include "Utils.h"
@@ -1477,9 +1478,9 @@
status_t Parcel::writeDupFileDescriptor(int fd)
{
- int dupFd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
- if (dupFd < 0) {
- return -errno;
+ int dupFd;
+ if (status_t err = dupFileDescriptor(fd, &dupFd); err != OK) {
+ return err;
}
status_t err = writeFileDescriptor(dupFd, true /*takeOwnership*/);
if (err != OK) {
@@ -1496,9 +1497,9 @@
status_t Parcel::writeDupParcelFileDescriptor(int fd)
{
- int dupFd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
- if (dupFd < 0) {
- return -errno;
+ int dupFd;
+ if (status_t err = dupFileDescriptor(fd, &dupFd); err != OK) {
+ return err;
}
status_t err = writeParcelFileDescriptor(dupFd, true /*takeOwnership*/);
if (err != OK) {
@@ -2295,7 +2296,12 @@
return BAD_TYPE;
}
- val->reset(fcntl(got, F_DUPFD_CLOEXEC, 0));
+ int dupFd;
+ if (status_t err = dupFileDescriptor(got, &dupFd); err != OK) {
+ return BAD_VALUE;
+ }
+
+ val->reset(dupFd);
if (val->get() < 0) {
return BAD_VALUE;
@@ -2312,7 +2318,12 @@
return BAD_TYPE;
}
- val->reset(fcntl(got, F_DUPFD_CLOEXEC, 0));
+ int dupFd;
+ if (status_t err = dupFileDescriptor(got, &dupFd); err != OK) {
+ return BAD_VALUE;
+ }
+
+ val->reset(dupFd);
if (val->get() < 0) {
return BAD_VALUE;
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index d347262..8ddfa93 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -484,6 +484,9 @@
mProtocolVersion = oldProtocolVersion;
mConnections = {};
+
+ // clear mStartedSetup so that we can reuse this RpcSession
+ mStartedSetup = false;
});
if (status_t status = connectAndInit({}, false /*incoming*/); status != OK) return status;
diff --git a/libs/binder/RpcTransportTipcAndroid.cpp b/libs/binder/RpcTransportTipcAndroid.cpp
index 79983f4..c82201b 100644
--- a/libs/binder/RpcTransportTipcAndroid.cpp
+++ b/libs/binder/RpcTransportTipcAndroid.cpp
@@ -103,7 +103,10 @@
// read and call readFn as many times as needed to get all the data
status_t ret = fillReadBuffer();
if (ret != OK) {
- return ret;
+ // We need to emulate a Linux read call, which sets errno on
+ // error and returns -1
+ errno = -ret;
+ return -1;
}
ssize_t processSize = 0;
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 46223bb..88d9ca1 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -59,6 +59,8 @@
virtual void* findObject(const void* objectID) const final;
virtual void* detachObject(const void* objectID) final;
void withLock(const std::function<void()>& doWithLock);
+ sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
+ const void* makeArgs);
virtual BBinder* localBinder();
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 19ad5e6..4172cc5 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -72,6 +72,8 @@
virtual void* findObject(const void* objectID) const final;
virtual void* detachObject(const void* objectID) final;
void withLock(const std::function<void()>& doWithLock);
+ sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
+ const void* makeArgs);
virtual BpBinder* remoteBinder();
@@ -96,6 +98,8 @@
IBinder::object_cleanup_func func);
void* find(const void* objectID) const;
void* detach(const void* objectID);
+ sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
+ const void* makeArgs);
void kill();
@@ -104,9 +108,9 @@
ObjectManager& operator=(const ObjectManager&);
struct entry_t {
- void* object;
- void* cleanupCookie;
- IBinder::object_cleanup_func func;
+ void* object = nullptr;
+ void* cleanupCookie = nullptr;
+ IBinder::object_cleanup_func func = nullptr;
};
std::map<const void*, entry_t> mObjects;
diff --git a/libs/binder/include/binder/Delegate.h b/libs/binder/include/binder/Delegate.h
new file mode 100644
index 0000000..8b3fc1c
--- /dev/null
+++ b/libs/binder/include/binder/Delegate.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <binder/IBinder.h>
+
+#ifndef __BIONIC__
+#ifndef __assert
+
+// defined differently by liblog
+#pragma push_macro("LOG_PRI")
+#ifdef LOG_PRI
+#undef LOG_PRI
+#endif
+#include <syslog.h>
+#pragma pop_macro("LOG_PRI")
+
+#define __assert(a, b, c) \
+ do { \
+ syslog(LOG_ERR, a ": " c); \
+ abort(); \
+ } while (false)
+#endif // __assert
+#endif // __BIONIC__
+
+namespace android {
+
+/*
+ * Used to manage AIDL's *Delegator types.
+ * This is used to:
+ * - create a new *Delegator object that delegates to the binder argument.
+ * - or return an existing *Delegator object that already delegates to the
+ * binder argument.
+ * - or return the underlying delegate binder if the binder argument is a
+ * *Delegator itself.
+ *
+ * @param binder - the binder to delegate to or unwrap
+ *
+ * @return pointer to the *Delegator object or the unwrapped binder object
+ */
+template <typename T>
+sp<T> delegate(const sp<T>& binder) {
+ const void* isDelegatorId = &T::descriptor;
+ const void* hasDelegatorId = &T::descriptor + 1;
+ // is binder itself a delegator?
+ if (T::asBinder(binder)->findObject(isDelegatorId)) {
+ if (T::asBinder(binder)->findObject(hasDelegatorId)) {
+ __assert(__FILE__, __LINE__,
+ "This binder has a delegator and is also delegator itself! This is "
+ "likely an unintended mixing of binders.");
+ return nullptr;
+ }
+ // unwrap the delegator
+ return static_cast<typename T::DefaultDelegator*>(binder.get())->getImpl();
+ }
+
+ struct MakeArgs {
+ const sp<T>* binder;
+ const void* id;
+ } makeArgs;
+ makeArgs.binder = &binder;
+ makeArgs.id = isDelegatorId;
+
+ // the binder is not a delegator, so construct one
+ sp<IBinder> newDelegator = T::asBinder(binder)->lookupOrCreateWeak(
+ hasDelegatorId,
+ [](const void* args) -> sp<IBinder> {
+ auto delegator = sp<typename T::DefaultDelegator>::make(
+ *static_cast<const MakeArgs*>(args)->binder);
+ // make sure we know this binder is a delegator by attaching a unique ID
+ (void)delegator->attachObject(static_cast<const MakeArgs*>(args)->id,
+ reinterpret_cast<void*>(0x1), nullptr, nullptr);
+ return delegator;
+ },
+ static_cast<const void*>(&makeArgs));
+ return sp<typename T::DefaultDelegator>::cast(newDelegator);
+}
+
+} // namespace android
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index 43fc5ff..83aaca7 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -284,6 +284,9 @@
virtual BBinder* localBinder();
virtual BpBinder* remoteBinder();
+ typedef sp<IBinder> (*object_make_func)(const void* makeArgs);
+ sp<IBinder> lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs);
protected:
virtual ~IBinder();
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
index f45aa76..c1f2620 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
@@ -58,6 +58,9 @@
#endif
AParcel_appendFrom(other.mParcel.get(), this->mParcel.get(), 0,
AParcel_getDataSize(other.mParcel.get()));
+ } else {
+ syslog(LOG_ERR,
+ "sdk_version not compatible, AParcelableHolder need sdk_version >= 31!");
}
}
#endif
@@ -192,6 +195,9 @@
if (__ANDROID_API__ >= 31) {
#endif
AParcel_reset(mParcel.get());
+ } else {
+ syslog(LOG_ERR,
+ "sdk_version not compatible, AParcelableHolder need sdk_version >= 31!");
}
}
@@ -201,6 +207,29 @@
inline bool operator==(const AParcelableHolder& rhs) const { return this == &rhs; }
inline bool operator>(const AParcelableHolder& rhs) const { return this > &rhs; }
inline bool operator>=(const AParcelableHolder& rhs) const { return this >= &rhs; }
+#if __ANDROID_API__ >= 31
+ inline AParcelableHolder& operator=(const AParcelableHolder& rhs) {
+ // AParcelableHolder has been introduced in 31.
+#ifdef __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__
+ if (__builtin_available(android 31, *)) {
+#else
+ if (__ANDROID_API__ >= 31) {
+#endif
+ this->reset();
+ if (this->mStability != rhs.mStability) {
+ syslog(LOG_ERR, "AParcelableHolder stability mismatch: this %d rhs %d!",
+ this->mStability, rhs.mStability);
+ abort();
+ }
+ AParcel_appendFrom(rhs.mParcel.get(), this->mParcel.get(), 0,
+ AParcel_getDataSize(rhs.mParcel.get()));
+ } else {
+ syslog(LOG_ERR,
+ "sdk_version not compatible, AParcelableHolder need sdk_version >= 31!");
+ }
+ return *this;
+ }
+#endif
private:
mutable ndk::ScopedAParcel mParcel;
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index c0d4487..0ec6183 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -144,24 +144,6 @@
min_sdk_version: "Tiramisu",
}
-// TODO(b/184872979): remove once the Rust API is created.
-rust_bindgen {
- name: "libbinder_rpc_unstable_bindgen",
- wrapper_src: ":libbinder_rpc_unstable_header",
- crate_name: "binder_rpc_unstable_bindgen",
- visibility: ["//packages/modules/Virtualization:__subpackages__"],
- source_stem: "bindings",
- shared_libs: [
- "libutils",
- ],
- apex_available: [
- "com.android.compos",
- "com.android.uwb",
- "com.android.virt",
- ],
- min_sdk_version: "Tiramisu",
-}
-
rust_test {
name: "libbinder_rs-internal_test",
crate_name: "binder",
@@ -188,13 +170,3 @@
clippy_lints: "none",
lints: "none",
}
-
-rust_test {
- name: "libbinder_rpc_unstable_bindgen_test",
- srcs: [":libbinder_rpc_unstable_bindgen"],
- crate_name: "binder_rpc_unstable_bindgen",
- test_suites: ["general-tests"],
- auto_gen_config: true,
- clippy_lints: "none",
- lints: "none",
-}
diff --git a/libs/binder/rust/rpcbinder/Android.bp b/libs/binder/rust/rpcbinder/Android.bp
new file mode 100644
index 0000000..067ca0d
--- /dev/null
+++ b/libs/binder/rust/rpcbinder/Android.bp
@@ -0,0 +1,50 @@
+rust_library {
+ name: "librpcbinder_rs",
+ crate_name: "rpcbinder",
+ srcs: ["src/lib.rs"],
+ shared_libs: [
+ "libutils",
+ ],
+ rustlibs: [
+ "libbinder_ndk_sys",
+ "libbinder_rpc_unstable_bindgen",
+ "libbinder_rs",
+ "libdowncast_rs",
+ "liblibc",
+ ],
+ apex_available: [
+ "com.android.compos",
+ "com.android.uwb",
+ "com.android.virt",
+ ],
+ min_sdk_version: "Tiramisu",
+}
+
+// TODO(b/184872979): remove once the RPC Binder API is stabilised.
+rust_bindgen {
+ name: "libbinder_rpc_unstable_bindgen",
+ wrapper_src: ":libbinder_rpc_unstable_header",
+ crate_name: "binder_rpc_unstable_bindgen",
+ visibility: [":__subpackages__"],
+ source_stem: "bindings",
+ shared_libs: [
+ "libbinder_rpc_unstable",
+ "libutils",
+ ],
+ apex_available: [
+ "com.android.compos",
+ "com.android.uwb",
+ "com.android.virt",
+ ],
+ min_sdk_version: "Tiramisu",
+}
+
+rust_test {
+ name: "libbinder_rpc_unstable_bindgen_test",
+ srcs: [":libbinder_rpc_unstable_bindgen"],
+ crate_name: "binder_rpc_unstable_bindgen",
+ test_suites: ["general-tests"],
+ auto_gen_config: true,
+ clippy_lints: "none",
+ lints: "none",
+}
diff --git a/libs/binder/rust/rpcbinder/src/client.rs b/libs/binder/rust/rpcbinder/src/client.rs
new file mode 100644
index 0000000..dfc6f06
--- /dev/null
+++ b/libs/binder/rust/rpcbinder/src/client.rs
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use binder::{
+ unstable_api::{new_spibinder, AIBinder},
+ FromIBinder, SpIBinder, StatusCode, Strong,
+};
+use std::os::{
+ raw::{c_int, c_void},
+ unix::io::RawFd,
+};
+
+/// Connects to an RPC Binder server over vsock.
+pub fn get_vsock_rpc_service(cid: u32, port: u32) -> Option<SpIBinder> {
+ // SAFETY: AIBinder returned by RpcClient has correct reference count, and the ownership can
+ // safely be taken by new_spibinder.
+ unsafe { new_spibinder(binder_rpc_unstable_bindgen::RpcClient(cid, port) as *mut AIBinder) }
+}
+
+/// Connects to an RPC Binder server for a particular interface over vsock.
+pub fn get_vsock_rpc_interface<T: FromIBinder + ?Sized>(
+ cid: u32,
+ port: u32,
+) -> Result<Strong<T>, StatusCode> {
+ interface_cast(get_vsock_rpc_service(cid, port))
+}
+
+/// Connects to an RPC Binder server, using the given callback to get (and take ownership of)
+/// file descriptors already connected to it.
+pub fn get_preconnected_rpc_service(
+ mut request_fd: impl FnMut() -> Option<RawFd>,
+) -> Option<SpIBinder> {
+ // Double reference the factory because trait objects aren't FFI safe.
+ let mut request_fd_ref: RequestFd = &mut request_fd;
+ let param = &mut request_fd_ref as *mut RequestFd as *mut c_void;
+
+ // SAFETY: AIBinder returned by RpcPreconnectedClient has correct reference count, and the
+ // ownership can be safely taken by new_spibinder. RpcPreconnectedClient does not take ownership
+ // of param, only passing it to request_fd_wrapper.
+ unsafe {
+ new_spibinder(binder_rpc_unstable_bindgen::RpcPreconnectedClient(
+ Some(request_fd_wrapper),
+ param,
+ ) as *mut AIBinder)
+ }
+}
+
+type RequestFd<'a> = &'a mut dyn FnMut() -> Option<RawFd>;
+
+unsafe extern "C" fn request_fd_wrapper(param: *mut c_void) -> c_int {
+ // SAFETY: This is only ever called by RpcPreconnectedClient, within the lifetime of the
+ // BinderFdFactory reference, with param being a properly aligned non-null pointer to an
+ // initialized instance.
+ let request_fd_ptr = param as *mut RequestFd;
+ let request_fd = request_fd_ptr.as_mut().unwrap();
+ if let Some(fd) = request_fd() {
+ fd
+ } else {
+ -1
+ }
+}
+
+/// Connects to an RPC Binder server for a particular interface, using the given callback to get
+/// (and take ownership of) file descriptors already connected to it.
+pub fn get_preconnected_rpc_interface<T: FromIBinder + ?Sized>(
+ request_fd: impl FnMut() -> Option<RawFd>,
+) -> Result<Strong<T>, StatusCode> {
+ interface_cast(get_preconnected_rpc_service(request_fd))
+}
+
+fn interface_cast<T: FromIBinder + ?Sized>(
+ service: Option<SpIBinder>,
+) -> Result<Strong<T>, StatusCode> {
+ if let Some(service) = service {
+ FromIBinder::try_from(service)
+ } else {
+ Err(StatusCode::NAME_NOT_FOUND)
+ }
+}
diff --git a/libs/binder/rust/rpcbinder/src/lib.rs b/libs/binder/rust/rpcbinder/src/lib.rs
new file mode 100644
index 0000000..a5eea61
--- /dev/null
+++ b/libs/binder/rust/rpcbinder/src/lib.rs
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//! API for RPC Binder services.
+
+mod client;
+mod server;
+
+pub use client::{
+ get_preconnected_rpc_interface, get_preconnected_rpc_service, get_vsock_rpc_interface,
+ get_vsock_rpc_service,
+};
+pub use server::{run_rpc_server, run_rpc_server_with_factory};
diff --git a/libs/binder/rust/rpcbinder/src/server.rs b/libs/binder/rust/rpcbinder/src/server.rs
new file mode 100644
index 0000000..d98a439
--- /dev/null
+++ b/libs/binder/rust/rpcbinder/src/server.rs
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use binder::{unstable_api::AsNative, SpIBinder};
+use std::{os::raw, ptr::null_mut};
+
+/// Runs a binder RPC server, serving the supplied binder service implementation on the given vsock
+/// port.
+///
+/// If and when the server is ready for connections (it is listening on the port), `on_ready` is
+/// called to allow appropriate action to be taken - e.g. to notify clients that they may now
+/// attempt to connect.
+///
+/// The current thread is joined to the binder thread pool to handle incoming messages.
+///
+/// Returns true if the server has shutdown normally, false if it failed in some way.
+pub fn run_rpc_server<F>(service: SpIBinder, port: u32, on_ready: F) -> bool
+where
+ F: FnOnce(),
+{
+ let mut ready_notifier = ReadyNotifier(Some(on_ready));
+ ready_notifier.run_server(service, port)
+}
+
+struct ReadyNotifier<F>(Option<F>)
+where
+ F: FnOnce();
+
+impl<F> ReadyNotifier<F>
+where
+ F: FnOnce(),
+{
+ fn run_server(&mut self, mut service: SpIBinder, port: u32) -> bool {
+ let service = service.as_native_mut() as *mut binder_rpc_unstable_bindgen::AIBinder;
+ let param = self.as_void_ptr();
+
+ // SAFETY: Service ownership is transferring to the server and won't be valid afterward.
+ // Plus the binder objects are threadsafe.
+ // RunRpcServerCallback does not retain a reference to `ready_callback` or `param`; it only
+ // uses them before it returns, which is during the lifetime of `self`.
+ unsafe {
+ binder_rpc_unstable_bindgen::RunRpcServerCallback(
+ service,
+ port,
+ Some(Self::ready_callback),
+ param,
+ )
+ }
+ }
+
+ fn as_void_ptr(&mut self) -> *mut raw::c_void {
+ self as *mut _ as *mut raw::c_void
+ }
+
+ unsafe extern "C" fn ready_callback(param: *mut raw::c_void) {
+ // SAFETY: This is only ever called by `RunRpcServerCallback`, within the lifetime of the
+ // `ReadyNotifier`, with `param` taking the value returned by `as_void_ptr` (so a properly
+ // aligned non-null pointer to an initialized instance).
+ let ready_notifier = param as *mut Self;
+ ready_notifier.as_mut().unwrap().notify()
+ }
+
+ fn notify(&mut self) {
+ if let Some(on_ready) = self.0.take() {
+ on_ready();
+ }
+ }
+}
+
+type RpcServerFactoryRef<'a> = &'a mut (dyn FnMut(u32) -> Option<SpIBinder> + Send + Sync);
+
+/// Runs a binder RPC server, using the given factory function to construct a binder service
+/// implementation for each connection.
+///
+/// The current thread is joined to the binder thread pool to handle incoming messages.
+///
+/// Returns true if the server has shutdown normally, false if it failed in some way.
+pub fn run_rpc_server_with_factory(
+ port: u32,
+ mut factory: impl FnMut(u32) -> Option<SpIBinder> + Send + Sync,
+) -> bool {
+ // Double reference the factory because trait objects aren't FFI safe.
+ // NB: The type annotation is necessary to ensure that we have a `dyn` rather than an `impl`.
+ let mut factory_ref: RpcServerFactoryRef = &mut factory;
+ let context = &mut factory_ref as *mut RpcServerFactoryRef as *mut raw::c_void;
+
+ // SAFETY: `factory_wrapper` is only ever called by `RunRpcServerWithFactory`, with context
+ // taking the pointer value above (so a properly aligned non-null pointer to an initialized
+ // `RpcServerFactoryRef`), within the lifetime of `factory_ref` (i.e. no more calls will be made
+ // after `RunRpcServerWithFactory` returns).
+ unsafe {
+ binder_rpc_unstable_bindgen::RunRpcServerWithFactory(Some(factory_wrapper), context, port)
+ }
+}
+
+unsafe extern "C" fn factory_wrapper(
+ cid: u32,
+ context: *mut raw::c_void,
+) -> *mut binder_rpc_unstable_bindgen::AIBinder {
+ // SAFETY: `context` was created from an `&mut RpcServerFactoryRef` by
+ // `run_rpc_server_with_factory`, and we are still within the lifetime of the value it is
+ // pointing to.
+ let factory_ptr = context as *mut RpcServerFactoryRef;
+ let factory = factory_ptr.as_mut().unwrap();
+
+ if let Some(mut service) = factory(cid) {
+ service.as_native_mut() as *mut binder_rpc_unstable_bindgen::AIBinder
+ } else {
+ null_mut()
+ }
+}
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index d7c6d49..1babfd5 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -684,3 +684,37 @@
],
test_suites: ["general-tests"],
}
+
+cc_defaults {
+ name: "service_fuzzer_defaults",
+ static_libs: [
+ "libbase",
+ "libbinder_random_parcel",
+ "libcutils",
+ ],
+ target: {
+ android: {
+ shared_libs: [
+ "libbinder_ndk",
+ "libbinder",
+ "libutils",
+ ],
+ },
+ host: {
+ static_libs: [
+ "libbinder_ndk",
+ "libbinder",
+ "libutils",
+ ],
+ },
+ darwin: {
+ enabled: false,
+ },
+ },
+ fuzz_config: {
+ cc: [
+ "smoreland@google.com",
+ "waghpawan@google.com",
+ ],
+ },
+}
diff --git a/libs/binder/tests/binderBinderUnitTest.cpp b/libs/binder/tests/binderBinderUnitTest.cpp
index ce2770f..b6aed0d 100644
--- a/libs/binder/tests/binderBinderUnitTest.cpp
+++ b/libs/binder/tests/binderBinderUnitTest.cpp
@@ -15,10 +15,11 @@
*/
#include <binder/Binder.h>
-#include <binder/IBinder.h>
+#include <binder/IInterface.h>
#include <gtest/gtest.h>
using android::BBinder;
+using android::IBinder;
using android::OK;
using android::sp;
@@ -48,3 +49,49 @@
binder->setExtension(ext);
EXPECT_EQ(ext, binder->getExtension());
}
+
+struct MyCookie {
+ bool* deleted;
+};
+
+class UniqueBinder : public BBinder {
+public:
+ UniqueBinder(const void* c) : cookie(reinterpret_cast<const MyCookie*>(c)) {
+ *cookie->deleted = false;
+ }
+ ~UniqueBinder() { *cookie->deleted = true; }
+ const MyCookie* cookie;
+};
+
+static sp<IBinder> make(const void* arg) {
+ return sp<UniqueBinder>::make(arg);
+}
+
+TEST(Binder, LookupOrCreateWeak) {
+ auto binder = sp<BBinder>::make();
+ bool deleted;
+ MyCookie cookie = {&deleted};
+ sp<IBinder> createdBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie);
+ EXPECT_NE(binder, createdBinder);
+
+ sp<IBinder> lookedUpBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie);
+ EXPECT_EQ(createdBinder, lookedUpBinder);
+ EXPECT_FALSE(deleted);
+}
+
+TEST(Binder, LookupOrCreateWeakDropSp) {
+ auto binder = sp<BBinder>::make();
+ bool deleted1 = false;
+ bool deleted2 = false;
+ MyCookie cookie1 = {&deleted1};
+ MyCookie cookie2 = {&deleted2};
+ sp<IBinder> createdBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie1);
+ EXPECT_NE(binder, createdBinder);
+
+ createdBinder.clear();
+ EXPECT_TRUE(deleted1);
+
+ sp<IBinder> lookedUpBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie2);
+ EXPECT_EQ(&cookie2, sp<UniqueBinder>::cast(lookedUpBinder)->cookie);
+ EXPECT_FALSE(deleted2);
+}
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index e72f39c..5de08bd 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -1158,6 +1158,42 @@
EXPECT_EQ(readValue, testValue);
}
+// see ProcessState.cpp BINDER_VM_SIZE = 1MB.
+// This value is not exposed, but some code in the framework relies on being able to use
+// buffers near the cap size.
+// TODO(b/238777741): why do larger values, like 300K fail sometimes
+constexpr size_t kSizeBytesAlmostFull = 100'000;
+constexpr size_t kSizeBytesOverFull = 1'050'000;
+
+TEST_F(BinderLibTest, GargantuanVectorSent) {
+ sp<IBinder> server = addServer();
+ ASSERT_TRUE(server != nullptr);
+
+ for (size_t i = 0; i < 10; i++) {
+ // a slight variation in size is used to consider certain possible caching implementations
+ const std::vector<uint64_t> testValue((kSizeBytesAlmostFull + i) / sizeof(uint64_t), 42);
+
+ Parcel data, reply;
+ data.writeUint64Vector(testValue);
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_ECHO_VECTOR, data, &reply), StatusEq(NO_ERROR))
+ << i;
+ std::vector<uint64_t> readValue;
+ EXPECT_THAT(reply.readUint64Vector(&readValue), StatusEq(OK));
+ EXPECT_EQ(readValue, testValue);
+ }
+}
+
+TEST_F(BinderLibTest, LimitExceededVectorSent) {
+ sp<IBinder> server = addServer();
+ ASSERT_TRUE(server != nullptr);
+ const std::vector<uint64_t> testValue(kSizeBytesOverFull / sizeof(uint64_t), 42);
+
+ Parcel data, reply;
+ data.writeUint64Vector(testValue);
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_ECHO_VECTOR, data, &reply),
+ StatusEq(FAILED_TRANSACTION));
+}
+
TEST_F(BinderLibTest, BufRejected) {
Parcel data, reply;
uint32_t buf;
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 501a604..b59308c 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -264,9 +264,13 @@
RpcSecurity rpcSecurity() const { return std::get<1>(GetParam()); }
uint32_t clientVersion() const { return std::get<2>(GetParam()); }
uint32_t serverVersion() const { return std::get<3>(GetParam()); }
- bool singleThreaded() const { return std::get<4>(GetParam()); }
+ bool serverSingleThreaded() const { return std::get<4>(GetParam()); }
bool noKernel() const { return std::get<5>(GetParam()); }
+ bool clientOrServerSingleThreaded() const {
+ return !kEnableRpcThreads || serverSingleThreaded();
+ }
+
// Whether the test params support sending FDs in parcels.
bool supportsFdTransport() const {
return clientVersion() >= 1 && serverVersion() >= 1 && rpcSecurity() != RpcSecurity::TLS &&
@@ -404,18 +408,6 @@
size_t sleepMs = 500);
};
-// Test fixture for tests that start multiple threads.
-// This includes tests with one thread but multiple sessions,
-// since a server uses one thread per session.
-class BinderRpcThreads : public BinderRpc {
-public:
- void SetUp() override {
- if constexpr (!kEnableRpcThreads) {
- GTEST_SKIP() << "Test skipped because threads were disabled at build time";
- }
- }
-};
-
TEST_P(BinderRpc, Ping) {
auto proc = createRpcTestSocketServerProcess({});
ASSERT_NE(proc.rootBinder, nullptr);
@@ -428,7 +420,13 @@
EXPECT_EQ(IBinderRpcTest::descriptor, proc.rootBinder->getInterfaceDescriptor());
}
-TEST_P(BinderRpcThreads, MultipleSessions) {
+TEST_P(BinderRpc, MultipleSessions) {
+ if (serverSingleThreaded()) {
+ // Tests with multiple sessions require a multi-threaded service,
+ // but work fine on a single-threaded client
+ GTEST_SKIP() << "This test requires a multi-threaded service";
+ }
+
auto proc = createRpcTestSocketServerProcess({.numThreads = 1, .numSessions = 5});
for (auto session : proc.proc.sessions) {
ASSERT_NE(nullptr, session.root);
@@ -436,7 +434,11 @@
}
}
-TEST_P(BinderRpcThreads, SeparateRootObject) {
+TEST_P(BinderRpc, SeparateRootObject) {
+ if (serverSingleThreaded()) {
+ GTEST_SKIP() << "This test requires a multi-threaded service";
+ }
+
SocketType type = std::get<0>(GetParam());
if (type == SocketType::PRECONNECTED || type == SocketType::UNIX) {
// we can't get port numbers for unix sockets
@@ -619,7 +621,11 @@
proc1.rootIface->repeatBinder(proc2.rootBinder, &outBinder).transactionError());
}
-TEST_P(BinderRpcThreads, CannotMixBindersBetweenTwoSessionsToTheSameServer) {
+TEST_P(BinderRpc, CannotMixBindersBetweenTwoSessionsToTheSameServer) {
+ if (serverSingleThreaded()) {
+ GTEST_SKIP() << "This test requires a multi-threaded service";
+ }
+
auto proc = createRpcTestSocketServerProcess({.numThreads = 1, .numSessions = 2});
sp<IBinder> outBinder;
@@ -775,7 +781,11 @@
return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
}
-TEST_P(BinderRpcThreads, ThreadPoolGreaterThanEqualRequested) {
+TEST_P(BinderRpc, ThreadPoolGreaterThanEqualRequested) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumThreads = 10;
auto proc = createRpcTestSocketServerProcess({.numThreads = kNumThreads});
@@ -826,14 +836,22 @@
EXPECT_LE(epochMsAfter, epochMsBefore + 3 * sleepMs);
}
-TEST_P(BinderRpcThreads, ThreadPoolOverSaturated) {
+TEST_P(BinderRpc, ThreadPoolOverSaturated) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumThreads = 10;
constexpr size_t kNumCalls = kNumThreads + 3;
auto proc = createRpcTestSocketServerProcess({.numThreads = kNumThreads});
testThreadPoolOverSaturated(proc.rootIface, kNumCalls);
}
-TEST_P(BinderRpcThreads, ThreadPoolLimitOutgoing) {
+TEST_P(BinderRpc, ThreadPoolLimitOutgoing) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumThreads = 20;
constexpr size_t kNumOutgoingConnections = 10;
constexpr size_t kNumCalls = kNumOutgoingConnections + 3;
@@ -842,7 +860,11 @@
testThreadPoolOverSaturated(proc.rootIface, kNumCalls);
}
-TEST_P(BinderRpcThreads, ThreadingStressTest) {
+TEST_P(BinderRpc, ThreadingStressTest) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumClientThreads = 10;
constexpr size_t kNumServerThreads = 10;
constexpr size_t kNumCalls = 100;
@@ -871,7 +893,11 @@
for (auto& t : threads) t.join();
}
-TEST_P(BinderRpcThreads, OnewayStressTest) {
+TEST_P(BinderRpc, OnewayStressTest) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumClientThreads = 10;
constexpr size_t kNumServerThreads = 10;
constexpr size_t kNumCalls = 1000;
@@ -906,7 +932,11 @@
EXPECT_LT(epochMsAfter, epochMsBefore + kReallyLongTimeMs);
}
-TEST_P(BinderRpcThreads, OnewayCallQueueing) {
+TEST_P(BinderRpc, OnewayCallQueueing) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumSleeps = 10;
constexpr size_t kNumExtraServerThreads = 4;
constexpr size_t kSleepMs = 50;
@@ -935,7 +965,11 @@
saturateThreadPool(1 + kNumExtraServerThreads, proc.rootIface);
}
-TEST_P(BinderRpcThreads, OnewayCallExhaustion) {
+TEST_P(BinderRpc, OnewayCallExhaustion) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumClients = 2;
constexpr size_t kTooLongMs = 1000;
@@ -978,17 +1012,16 @@
TEST_P(BinderRpc, Callbacks) {
const static std::string kTestString = "good afternoon!";
- bool bothSingleThreaded = !kEnableRpcThreads || singleThreaded();
-
for (bool callIsOneway : {true, false}) {
for (bool callbackIsOneway : {true, false}) {
for (bool delayed : {true, false}) {
- if (bothSingleThreaded && (callIsOneway || callbackIsOneway || delayed)) {
+ if (clientOrServerSingleThreaded() &&
+ (callIsOneway || callbackIsOneway || delayed)) {
// we have no incoming connections to receive the callback
continue;
}
- size_t numIncomingConnections = bothSingleThreaded ? 0 : 1;
+ size_t numIncomingConnections = clientOrServerSingleThreaded() ? 0 : 1;
auto proc = createRpcTestSocketServerProcess(
{.numThreads = 1,
.numSessions = 1,
@@ -1036,7 +1069,7 @@
}
TEST_P(BinderRpc, SingleDeathRecipient) {
- if (singleThreaded() || !kEnableRpcThreads) {
+ if (clientOrServerSingleThreaded()) {
GTEST_SKIP() << "This test requires multiple threads";
}
class MyDeathRec : public IBinder::DeathRecipient {
@@ -1062,10 +1095,7 @@
}
std::unique_lock<std::mutex> lock(dr->mMtx);
- if (!dr->dead) {
- EXPECT_EQ(std::cv_status::no_timeout, dr->mCv.wait_for(lock, 1000ms));
- }
- EXPECT_TRUE(dr->dead) << "Failed to receive the death notification.";
+ ASSERT_TRUE(dr->mCv.wait_for(lock, 1000ms, [&]() { return dr->dead; }));
// need to wait for the session to shutdown so we don't "Leak session"
EXPECT_TRUE(proc.proc.sessions.at(0).session->shutdownAndWait(true));
@@ -1073,7 +1103,7 @@
}
TEST_P(BinderRpc, SingleDeathRecipientOnShutdown) {
- if (singleThreaded() || !kEnableRpcThreads) {
+ if (clientOrServerSingleThreaded()) {
GTEST_SKIP() << "This test requires multiple threads";
}
class MyDeathRec : public IBinder::DeathRecipient {
@@ -1127,7 +1157,7 @@
}
TEST_P(BinderRpc, UnlinkDeathRecipient) {
- if (singleThreaded() || !kEnableRpcThreads) {
+ if (clientOrServerSingleThreaded()) {
GTEST_SKIP() << "This test requires multiple threads";
}
class MyDeathRec : public IBinder::DeathRecipient {
@@ -1193,7 +1223,7 @@
// libbinder.so (when using static libraries, even a client and service
// using the same kind of static library should have separate copies of the
// variables).
- if (!kEnableSharedLibs || singleThreaded() || noKernel()) {
+ if (!kEnableSharedLibs || serverSingleThreaded() || noKernel()) {
GTEST_SKIP() << "Test disabled because Binder kernel driver was disabled "
"at build time.";
}
@@ -1393,7 +1423,11 @@
return ret;
}
-TEST_P(BinderRpcThreads, Fds) {
+TEST_P(BinderRpc, Fds) {
+ if (serverSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
ssize_t beforeFds = countFds();
ASSERT_GE(beforeFds, 0);
{
@@ -1534,15 +1568,6 @@
::testing::Values(false, true)),
BinderRpc::PrintParamInfo);
-INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpcThreads,
- ::testing::Combine(::testing::ValuesIn(testSocketTypes()),
- ::testing::ValuesIn(RpcSecurityValues()),
- ::testing::ValuesIn(testVersions()),
- ::testing::ValuesIn(testVersions()),
- ::testing::Values(false),
- ::testing::Values(false, true)),
- BinderRpc::PrintParamInfo);
-
class BinderRpcServerRootObject
: public ::testing::TestWithParam<std::tuple<bool, bool, RpcSecurity>> {};
diff --git a/libs/binder/trusty/OS.cpp b/libs/binder/trusty/OS.cpp
index 187add4..b21fe6a 100644
--- a/libs/binder/trusty/OS.cpp
+++ b/libs/binder/trusty/OS.cpp
@@ -14,7 +14,11 @@
* limitations under the License.
*/
+#if defined(TRUSTY_USERSPACE)
#include <openssl/rand.h>
+#else
+#include <lib/rand/rand.h>
+#endif
#include "../OS.h"
@@ -28,8 +32,18 @@
}
status_t getRandomBytes(uint8_t* data, size_t size) {
+#if defined(TRUSTY_USERSPACE)
int res = RAND_bytes(data, size);
return res == 1 ? OK : UNKNOWN_ERROR;
+#else
+ int res = rand_get_bytes(data, size);
+ return res == 0 ? OK : UNKNOWN_ERROR;
+#endif // TRUSTY_USERSPACE
+}
+
+status_t dupFileDescriptor(int oldFd, int* newFd) {
+ // TODO: implement separately
+ return INVALID_OPERATION;
}
} // namespace android
diff --git a/libs/binder/trusty/rules.mk b/libs/binder/trusty/rules.mk
index 83475f5..d0d0861 100644
--- a/libs/binder/trusty/rules.mk
+++ b/libs/binder/trusty/rules.mk
@@ -36,6 +36,7 @@
$(LIBBINDER_DIR)/IInterface.cpp \
$(LIBBINDER_DIR)/IResultReceiver.cpp \
$(LIBBINDER_DIR)/Parcel.cpp \
+ $(LIBBINDER_DIR)/ParcelFileDescriptor.cpp \
$(LIBBINDER_DIR)/RpcServer.cpp \
$(LIBBINDER_DIR)/RpcSession.cpp \
$(LIBBINDER_DIR)/RpcState.cpp \
diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp
index 59cc7d1..d6b4579 100644
--- a/libs/input/KeyLayoutMap.cpp
+++ b/libs/input/KeyLayoutMap.cpp
@@ -25,8 +25,10 @@
#include <utils/Errors.h>
#include <utils/Timers.h>
#include <utils/Tokenizer.h>
+#if defined(__ANDROID__)
#include <vintf/RuntimeInfo.h>
#include <vintf/VintfObject.h>
+#endif
#include <cstdlib>
#include <string_view>
@@ -79,6 +81,7 @@
sensorPair<InputDeviceSensorType::SIGNIFICANT_MOTION>()};
bool kernelConfigsArePresent(const std::set<std::string>& configs) {
+#if defined(__ANDROID__)
std::shared_ptr<const android::vintf::RuntimeInfo> runtimeInfo =
android::vintf::VintfObject::GetInstance()->getRuntimeInfo(
vintf::RuntimeInfo::FetchFlag::CONFIG_GZ);
@@ -99,6 +102,10 @@
}
}
return true;
+#else
+ (void)configs; // Suppress 'unused variable' warning
+ return true;
+#endif
}
} // namespace
diff --git a/libs/sensor/fuzz/sensor_fuzzer/sensor_fuzzer.cpp b/libs/sensor/fuzz/sensor_fuzzer/sensor_fuzzer.cpp
index 129f430..0e110b7 100644
--- a/libs/sensor/fuzz/sensor_fuzzer/sensor_fuzzer.cpp
+++ b/libs/sensor/fuzz/sensor_fuzzer/sensor_fuzzer.cpp
@@ -26,8 +26,10 @@
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
FuzzedDataProvider fdp(data, size);
struct sensor_t sensor_type;
- sensor_type.name = fdp.ConsumeBytesAsString(MAX_STR_LEN).c_str();
- sensor_type.vendor = fdp.ConsumeBytesAsString(MAX_STR_LEN).c_str();
+ std::string name = fdp.ConsumeBytesAsString(MAX_STR_LEN);
+ sensor_type.name = name.c_str();
+ std::string vendor = fdp.ConsumeBytesAsString(MAX_STR_LEN);
+ sensor_type.vendor = vendor.c_str();
sensor_type.stringType = "";
sensor_type.requiredPermission = "";
sensor_type.version = fdp.ConsumeIntegral<int>();
diff --git a/services/vibratorservice/Android.bp b/services/vibratorservice/Android.bp
index 2002bdf..5403baf 100644
--- a/services/vibratorservice/Android.bp
+++ b/services/vibratorservice/Android.bp
@@ -59,6 +59,12 @@
"-Wunreachable-code",
],
+ // FIXME: Workaround LTO build breakage
+ // http://b/241699694
+ lto: {
+ never: true,
+ },
+
local_include_dirs: ["include"],
export_include_dirs: ["include"],