Merge "Add binderHostDeviceTest"
diff --git a/cmds/installd/OWNERS b/cmds/installd/OWNERS
index d6807ff..643b2c2 100644
--- a/cmds/installd/OWNERS
+++ b/cmds/installd/OWNERS
@@ -4,7 +4,6 @@
jsharkey@android.com
maco@google.com
mast@google.com
-mathieuc@google.com
narayan@google.com
ngeoffray@google.com
rpl@google.com
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 02321cd..628381c 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -179,6 +179,17 @@
return transact(SET_RPC_CLIENT_TRANSACTION, data, &reply);
}
+void IBinder::withLock(const std::function<void()>& doWithLock) {
+ BBinder* local = localBinder();
+ if (local) {
+ local->withLock(doWithLock);
+ return;
+ }
+ BpBinder* proxy = this->remoteBinder();
+ LOG_ALWAYS_FATAL_IF(proxy == nullptr, "binder object must be either local or remote");
+ proxy->withLock(doWithLock);
+}
+
// ---------------------------------------------------------------------------
class BBinder::RpcServerLink : public IBinder::DeathRecipient {
@@ -311,15 +322,13 @@
return NO_ERROR;
}
-void BBinder::attachObject(
- const void* objectID, void* object, void* cleanupCookie,
- object_cleanup_func func)
-{
+void* BBinder::attachObject(const void* objectID, void* object, void* cleanupCookie,
+ object_cleanup_func func) {
Extras* e = getOrCreateExtras();
- if (!e) return; // out of memory
+ LOG_ALWAYS_FATAL_IF(!e, "no memory");
AutoMutex _l(e->mLock);
- e->mObjects.attach(objectID, object, cleanupCookie, func);
+ return e->mObjects.attach(objectID, object, cleanupCookie, func);
}
void* BBinder::findObject(const void* objectID) const
@@ -331,13 +340,20 @@
return e->mObjects.find(objectID);
}
-void BBinder::detachObject(const void* objectID)
-{
+void* BBinder::detachObject(const void* objectID) {
Extras* e = mExtras.load(std::memory_order_acquire);
- if (!e) return;
+ if (!e) return nullptr;
AutoMutex _l(e->mLock);
- e->mObjects.detach(objectID);
+ return e->mObjects.detach(objectID);
+}
+
+void BBinder::withLock(const std::function<void()>& doWithLock) {
+ Extras* e = getOrCreateExtras();
+ LOG_ALWAYS_FATAL_IF(!e, "no memory");
+
+ AutoMutex _l(e->mLock);
+ doWithLock();
}
BBinder* BBinder::localBinder()
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 5e44a0f..3099296 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -61,22 +61,22 @@
kill();
}
-void BpBinder::ObjectManager::attach(
- const void* objectID, void* object, void* cleanupCookie,
- IBinder::object_cleanup_func func)
-{
+void* BpBinder::ObjectManager::attach(const void* objectID, void* object, void* cleanupCookie,
+ IBinder::object_cleanup_func func) {
entry_t e;
e.object = object;
e.cleanupCookie = cleanupCookie;
e.func = func;
- if (mObjects.indexOfKey(objectID) >= 0) {
- ALOGE("Trying to attach object ID %p to binder ObjectManager %p with object %p, but object ID already in use",
- objectID, this, object);
- return;
+ if (ssize_t idx = mObjects.indexOfKey(objectID); idx >= 0) {
+ ALOGI("Trying to attach object ID %p to binder ObjectManager %p with object %p, but object "
+ "ID already in use",
+ objectID, this, object);
+ return mObjects[idx].object;
}
mObjects.add(objectID, e);
+ return nullptr;
}
void* BpBinder::ObjectManager::find(const void* objectID) const
@@ -86,9 +86,12 @@
return mObjects.valueAt(i).object;
}
-void BpBinder::ObjectManager::detach(const void* objectID)
-{
- mObjects.removeItem(objectID);
+void* BpBinder::ObjectManager::detach(const void* objectID) {
+ ssize_t idx = mObjects.indexOfKey(objectID);
+ if (idx < 0) return nullptr;
+ void* value = mObjects[idx].object;
+ mObjects.removeItemsAt(idx, 1);
+ return value;
}
void BpBinder::ObjectManager::kill()
@@ -406,14 +409,11 @@
recipient->binderDied(wp<BpBinder>::fromExisting(this));
}
-
-void BpBinder::attachObject(
- const void* objectID, void* object, void* cleanupCookie,
- object_cleanup_func func)
-{
+void* BpBinder::attachObject(const void* objectID, void* object, void* cleanupCookie,
+ object_cleanup_func func) {
AutoMutex _l(mLock);
ALOGV("Attaching object %p to binder %p (manager=%p)", object, this, &mObjects);
- mObjects.attach(objectID, object, cleanupCookie, func);
+ return mObjects.attach(objectID, object, cleanupCookie, func);
}
void* BpBinder::findObject(const void* objectID) const
@@ -422,10 +422,14 @@
return mObjects.find(objectID);
}
-void BpBinder::detachObject(const void* objectID)
-{
+void* BpBinder::detachObject(const void* objectID) {
AutoMutex _l(mLock);
- mObjects.detach(objectID);
+ return mObjects.detach(objectID);
+}
+
+void BpBinder::withLock(const std::function<void()>& doWithLock) {
+ AutoMutex _l(mLock);
+ doWithLock();
}
BpBinder* BpBinder::remoteBinder()
diff --git a/libs/binder/ServiceManagerHost.cpp b/libs/binder/ServiceManagerHost.cpp
index 07f5778..1c2f9b4 100644
--- a/libs/binder/ServiceManagerHost.cpp
+++ b/libs/binder/ServiceManagerHost.cpp
@@ -167,9 +167,12 @@
ALOGE("RpcSession::getRootObject returns nullptr");
return nullptr;
}
- binder->attachObject(kDeviceServiceExtraId,
- static_cast<void*>(new CommandResult(std::move(*result))), nullptr,
- &cleanupCommandResult);
+
+ LOG_ALWAYS_FATAL_IF(
+ nullptr !=
+ binder->attachObject(kDeviceServiceExtraId,
+ static_cast<void*>(new CommandResult(std::move(*result))), nullptr,
+ &cleanupCommandResult));
return binder;
}
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 012a9be..269b867 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -22,7 +22,7 @@
"name": "binderTextOutputTest"
},
{
- "name": "binderParcelTest"
+ "name": "binderUnitTest"
},
{
"name": "binderLibTest"
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 472e546..46223bb 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -54,12 +54,11 @@
uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = nullptr);
- virtual void attachObject( const void* objectID,
- void* object,
- void* cleanupCookie,
- object_cleanup_func func) final;
+ virtual void* attachObject(const void* objectID, void* object, void* cleanupCookie,
+ object_cleanup_func func) final;
virtual void* findObject(const void* objectID) const final;
- virtual void detachObject(const void* objectID) final;
+ virtual void* detachObject(const void* objectID) final;
+ void withLock(const std::function<void()>& doWithLock);
virtual BBinder* localBinder();
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 61bf018..c69bb9e 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -72,12 +72,11 @@
uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = nullptr);
- virtual void attachObject( const void* objectID,
- void* object,
- void* cleanupCookie,
- object_cleanup_func func) final;
+ virtual void* attachObject(const void* objectID, void* object, void* cleanupCookie,
+ object_cleanup_func func) final;
virtual void* findObject(const void* objectID) const final;
- virtual void detachObject(const void* objectID) final;
+ virtual void* detachObject(const void* objectID) final;
+ void withLock(const std::function<void()>& doWithLock);
virtual BpBinder* remoteBinder();
@@ -91,27 +90,23 @@
static void setLimitCallback(binder_proxy_limit_callback cb);
static void setBinderProxyCountWatermarks(int high, int low);
- class ObjectManager
- {
+ class ObjectManager {
public:
- ObjectManager();
- ~ObjectManager();
+ ObjectManager();
+ ~ObjectManager();
- void attach( const void* objectID,
- void* object,
- void* cleanupCookie,
- IBinder::object_cleanup_func func);
- void* find(const void* objectID) const;
- void detach(const void* objectID);
+ void* attach(const void* objectID, void* object, void* cleanupCookie,
+ IBinder::object_cleanup_func func);
+ void* find(const void* objectID) const;
+ void* detach(const void* objectID);
- void kill();
+ void kill();
private:
- ObjectManager(const ObjectManager&);
+ ObjectManager(const ObjectManager&);
ObjectManager& operator=(const ObjectManager&);
- struct entry_t
- {
+ struct entry_t {
void* object;
void* cleanupCookie;
IBinder::object_cleanup_func func;
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index f9cdac7..43fc5ff 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -22,6 +22,8 @@
#include <utils/String16.h>
#include <utils/Vector.h>
+#include <functional>
+
// linux/binder.h defines this, but we don't want to include it here in order to
// avoid exporting the kernel headers
#ifndef B_PACK_CHARS
@@ -255,26 +257,30 @@
* objects are invoked with their respective objectID, object, and
* cleanupCookie. Access to these APIs can be made from multiple threads,
* but calls from different threads are allowed to be interleaved.
+ *
+ * This returns the object which is already attached. If this returns a
+ * non-null value, it means that attachObject failed (a given objectID can
+ * only be used once).
*/
- virtual void attachObject( const void* objectID,
- void* object,
- void* cleanupCookie,
- object_cleanup_func func) = 0;
+ [[nodiscard]] virtual void* attachObject(const void* objectID, void* object,
+ void* cleanupCookie, object_cleanup_func func) = 0;
/**
* Returns object attached with attachObject.
*/
- virtual void* findObject(const void* objectID) const = 0;
+ [[nodiscard]] virtual void* findObject(const void* objectID) const = 0;
/**
- * WARNING: this API does not call the cleanup function for legacy reasons.
- * It also does not return void* for legacy reasons. If you need to detach
- * an object and destroy it, there are two options:
- * - if you can, don't call detachObject and instead wait for the destructor
- * to clean it up.
- * - manually retrieve and destruct the object (if multiple of your threads
- * are accessing these APIs, you must guarantee that attachObject isn't
- * called after findObject and before detachObject is called).
+ * Returns object attached with attachObject, and detaches it. This does not
+ * delete the object.
*/
- virtual void detachObject(const void* objectID) = 0;
+ [[nodiscard]] virtual void* detachObject(const void* objectID) = 0;
+
+ /**
+ * Use the lock that this binder contains internally. For instance, this can
+ * be used to modify an attached object without needing to add an additional
+ * lock (though, that attached object must be retrieved before calling this
+ * method). Calling (most) IBinder methods inside this will deadlock.
+ */
+ void withLock(const std::function<void()>& doWithLock);
virtual BBinder* localBinder();
virtual BpBinder* remoteBinder();
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 883403a..b89714a 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -47,7 +47,8 @@
void clean(const void* /*id*/, void* /*obj*/, void* /*cookie*/){/* do nothing */};
static void attach(const sp<IBinder>& binder) {
- binder->attachObject(kId, kValue, nullptr /*cookie*/, clean);
+ // can only attach once
+ CHECK_EQ(nullptr, binder->attachObject(kId, kValue, nullptr /*cookie*/, clean));
}
static bool has(const sp<IBinder>& binder) {
return binder != nullptr && binder->findObject(kId) == kValue;
@@ -57,7 +58,6 @@
namespace ABpBinderTag {
-static std::mutex gLock;
static const void* kId = "ABpBinder";
struct Value {
wp<ABpBinder> binder;
@@ -232,19 +232,14 @@
ABpBinder::~ABpBinder() {}
void ABpBinder::onLastStrongRef(const void* id) {
- {
- std::lock_guard<std::mutex> lock(ABpBinderTag::gLock);
- // Since ABpBinder is OBJECT_LIFETIME_WEAK, we must remove this weak reference in order for
- // the ABpBinder to be deleted. Since a strong reference to this ABpBinder object should no
- // longer be able to exist at the time of this method call, there is no longer a need to
- // recover it.
+ // Since ABpBinder is OBJECT_LIFETIME_WEAK, we must remove this weak reference in order for
+ // the ABpBinder to be deleted. Since a strong reference to this ABpBinder object should no
+ // longer be able to exist at the time of this method call, there is no longer a need to
+ // recover it.
- ABpBinderTag::Value* value =
- static_cast<ABpBinderTag::Value*>(remote()->findObject(ABpBinderTag::kId));
- if (value != nullptr) {
- value->binder = nullptr;
- }
- }
+ ABpBinderTag::Value* value =
+ static_cast<ABpBinderTag::Value*>(remote()->detachObject(ABpBinderTag::kId));
+ if (value) ABpBinderTag::clean(ABpBinderTag::kId, value, nullptr /*cookie*/);
BpRefBase::onLastStrongRef(id);
}
@@ -257,23 +252,28 @@
return static_cast<ABBinder*>(binder.get());
}
- // The following code ensures that for a given binder object (remote or local), if it is not an
- // ABBinder then at most one ABpBinder object exists in a given process representing it.
- std::lock_guard<std::mutex> lock(ABpBinderTag::gLock);
-
- ABpBinderTag::Value* value =
- static_cast<ABpBinderTag::Value*>(binder->findObject(ABpBinderTag::kId));
+ auto* value = static_cast<ABpBinderTag::Value*>(binder->findObject(ABpBinderTag::kId));
if (value == nullptr) {
value = new ABpBinderTag::Value;
- binder->attachObject(ABpBinderTag::kId, static_cast<void*>(value), nullptr /*cookie*/,
- ABpBinderTag::clean);
+ auto oldValue = static_cast<ABpBinderTag::Value*>(
+ binder->attachObject(ABpBinderTag::kId, static_cast<void*>(value),
+ nullptr /*cookie*/, ABpBinderTag::clean));
+
+ // allocated by another thread
+ if (oldValue) {
+ delete value;
+ value = oldValue;
+ }
}
- sp<ABpBinder> ret = value->binder.promote();
- if (ret == nullptr) {
- ret = new ABpBinder(binder);
- value->binder = ret;
- }
+ sp<ABpBinder> ret;
+ binder->withLock([&]() {
+ ret = value->binder.promote();
+ if (ret == nullptr) {
+ ret = sp<ABpBinder>::make(binder);
+ value->binder = ret;
+ }
+ });
return ret;
}
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index 22cacb4..f2c69b3 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -105,6 +105,7 @@
ABpBinder* asABpBinder() override { return this; }
private:
+ friend android::sp<ABpBinder>;
explicit ABpBinder(const ::android::sp<::android::IBinder>& binder);
};
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index 2a09afc..f79b1b7 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -50,7 +50,7 @@
/// interfaces) must implement this trait.
///
/// This is equivalent `IInterface` in C++.
-pub trait Interface: Send {
+pub trait Interface: Send + Sync {
/// Convert this binder object into a generic [`SpIBinder`] reference.
fn as_binder(&self) -> SpIBinder {
panic!("This object was not a Binder object and cannot be converted into an SpIBinder.")
diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs
index 5e324b3..a0dfeec 100644
--- a/libs/binder/rust/src/native.rs
+++ b/libs/binder/rust/src/native.rs
@@ -51,6 +51,25 @@
/// to how `Box<T>` is `Send` if `T` is `Send`.
unsafe impl<T: Remotable> Send for Binder<T> {}
+/// # Safety
+///
+/// A `Binder<T>` is a pair of unique owning pointers to two values:
+/// * a C++ ABBinder which is thread-safe, i.e. `Send + Sync`
+/// * a Rust object which implements `Remotable`; this trait requires `Send + Sync`
+///
+/// `ABBinder` contains an immutable `mUserData` pointer, which is actually a
+/// pointer to a boxed `T: Remotable`, which is `Sync`. `ABBinder` also contains
+/// a mutable pointer to its class, but mutation of this field is controlled by
+/// a mutex and it is only allowed to be set once, therefore we can concurrently
+/// access this field safely. `ABBinder` inherits from `BBinder`, which is also
+/// thread-safe. Thus `ABBinder` is thread-safe.
+///
+/// Both pointers are unique (never escape the `Binder<T>` object and are not copied)
+/// so we can essentially treat `Binder<T>` as a box-like containing the two objects;
+/// the box-like object inherits `Sync` from the two inner values, similarly
+/// to how `Box<T>` is `Sync` if `T` is `Sync`.
+unsafe impl<T: Remotable> Sync for Binder<T> {}
+
impl<T: Remotable> Binder<T> {
/// Create a new Binder remotable object with default stability
///
diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs
index e299963..cdd7c08 100644
--- a/libs/binder/rust/src/proxy.rs
+++ b/libs/binder/rust/src/proxy.rs
@@ -48,9 +48,14 @@
/// # Safety
///
-/// An `SpIBinder` is a handle to a C++ IBinder, which is thread-safe
+/// An `SpIBinder` is an immutable handle to a C++ IBinder, which is thread-safe
unsafe impl Send for SpIBinder {}
+/// # Safety
+///
+/// An `SpIBinder` is an immutable handle to a C++ IBinder, which is thread-safe
+unsafe impl Sync for SpIBinder {}
+
impl SpIBinder {
/// Create an `SpIBinder` wrapper object from a raw `AIBinder` pointer.
///
@@ -448,9 +453,14 @@
/// # Safety
///
-/// A `WpIBinder` is a handle to a C++ IBinder, which is thread-safe.
+/// A `WpIBinder` is an immutable handle to a C++ IBinder, which is thread-safe.
unsafe impl Send for WpIBinder {}
+/// # Safety
+///
+/// A `WpIBinder` is an immutable handle to a C++ IBinder, which is thread-safe.
+unsafe impl Sync for WpIBinder {}
+
impl WpIBinder {
/// Create a new weak reference from an object that can be converted into a
/// raw `AIBinder` pointer.
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 1f844e1..24afcf6 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -77,14 +77,14 @@
// unit test only, which can run on host and doesn't use /dev/binder
cc_test {
- name: "binderParcelTest",
+ name: "binderUnitTest",
host_supported: true,
target: {
darwin: {
enabled: false,
},
},
- srcs: ["binderParcelTest.cpp"],
+ srcs: ["binderParcelUnitTest.cpp", "binderBinderUnitTest.cpp"],
shared_libs: [
"libbinder",
"libutils",
diff --git a/libs/binder/tests/binderBinderUnitTest.cpp b/libs/binder/tests/binderBinderUnitTest.cpp
new file mode 100644
index 0000000..1be0c59
--- /dev/null
+++ b/libs/binder/tests/binderBinderUnitTest.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2020 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 <binder/Binder.h>
+#include <binder/IBinder.h>
+#include <gtest/gtest.h>
+
+using android::BBinder;
+using android::OK;
+using android::sp;
+
+const void* kObjectId1 = reinterpret_cast<const void*>(1);
+const void* kObjectId2 = reinterpret_cast<const void*>(2);
+void* kObject1 = reinterpret_cast<void*>(101);
+void* kObject2 = reinterpret_cast<void*>(102);
+void* kObject3 = reinterpret_cast<void*>(103);
+
+TEST(Binder, AttachObject) {
+ auto binder = sp<BBinder>::make();
+ EXPECT_EQ(nullptr, binder->attachObject(kObjectId1, kObject1, nullptr, nullptr));
+ EXPECT_EQ(nullptr, binder->attachObject(kObjectId2, kObject2, nullptr, nullptr));
+ EXPECT_EQ(kObject1, binder->attachObject(kObjectId1, kObject3, nullptr, nullptr));
+}
+
+TEST(Binder, DetachObject) {
+ auto binder = sp<BBinder>::make();
+ EXPECT_EQ(nullptr, binder->attachObject(kObjectId1, kObject1, nullptr, nullptr));
+ EXPECT_EQ(kObject1, binder->detachObject(kObjectId1));
+ EXPECT_EQ(nullptr, binder->attachObject(kObjectId1, kObject2, nullptr, nullptr));
+}
diff --git a/libs/binder/tests/binderParcelTest.cpp b/libs/binder/tests/binderParcelUnitTest.cpp
similarity index 65%
rename from libs/binder/tests/binderParcelTest.cpp
rename to libs/binder/tests/binderParcelUnitTest.cpp
index 1764228..fb49d7a 100644
--- a/libs/binder/tests/binderParcelTest.cpp
+++ b/libs/binder/tests/binderParcelUnitTest.cpp
@@ -14,20 +14,21 @@
* limitations under the License.
*/
-#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
+#include <binder/Parcel.h>
#include <gtest/gtest.h>
using android::IPCThreadState;
using android::OK;
using android::Parcel;
+using android::status_t;
using android::String16;
using android::String8;
-using android::status_t;
// Tests a second operation results in a parcel at the same location as it
// started.
-void parcelOpSameLength(const std::function<void(Parcel*)>& a, const std::function<void(Parcel*)>& b) {
+void parcelOpSameLength(const std::function<void(Parcel*)>& a,
+ const std::function<void(Parcel*)>& b) {
Parcel p;
a(&p);
size_t end = p.dataPosition();
@@ -38,33 +39,30 @@
TEST(Parcel, InverseInterfaceToken) {
const String16 token = String16("asdf");
- parcelOpSameLength([&] (Parcel* p) {
- p->writeInterfaceToken(token);
- }, [&] (Parcel* p) {
- EXPECT_TRUE(p->enforceInterface(token, IPCThreadState::self()));
- });
+ parcelOpSameLength([&](Parcel* p) { p->writeInterfaceToken(token); },
+ [&](Parcel* p) {
+ EXPECT_TRUE(p->enforceInterface(token, IPCThreadState::self()));
+ });
}
TEST(Parcel, Utf8FromUtf16Read) {
const char* token = "asdf";
- parcelOpSameLength([&] (Parcel* p) {
- p->writeString16(String16(token));
- }, [&] (Parcel* p) {
- std::string s;
- EXPECT_EQ(OK, p->readUtf8FromUtf16(&s));
- EXPECT_EQ(token, s);
- });
+ parcelOpSameLength([&](Parcel* p) { p->writeString16(String16(token)); },
+ [&](Parcel* p) {
+ std::string s;
+ EXPECT_EQ(OK, p->readUtf8FromUtf16(&s));
+ EXPECT_EQ(token, s);
+ });
}
TEST(Parcel, Utf8AsUtf16Write) {
std::string token = "asdf";
- parcelOpSameLength([&] (Parcel* p) {
- p->writeUtf8AsUtf16(token);
- }, [&] (Parcel* p) {
- String16 s;
- EXPECT_EQ(OK, p->readString16(&s));
- EXPECT_EQ(s, String16(token.c_str()));
- });
+ parcelOpSameLength([&](Parcel* p) { p->writeUtf8AsUtf16(token); },
+ [&](Parcel* p) {
+ String16 s;
+ EXPECT_EQ(OK, p->readString16(&s));
+ EXPECT_EQ(s, String16(token.c_str()));
+ });
}
template <typename T>
@@ -77,13 +75,12 @@
template <typename T, typename WRITE_FUNC>
void readWriteInverse(std::vector<T>&& ts, readFunc<T> r, WRITE_FUNC w) {
for (const T& value : ts) {
- parcelOpSameLength([&] (Parcel* p) {
- (*p.*w)(value);
- }, [&] (Parcel* p) {
- T outValue;
- EXPECT_EQ(OK, (*p.*r)(&outValue));
- EXPECT_EQ(value, outValue);
- });
+ parcelOpSameLength([&](Parcel* p) { (*p.*w)(value); },
+ [&](Parcel* p) {
+ T outValue;
+ EXPECT_EQ(OK, (*p.*r)(&outValue));
+ EXPECT_EQ(value, outValue);
+ });
}
}
@@ -96,8 +93,8 @@
readWriteInverse<T, copyWriteFunc<T>>(std::move(ts), r, w);
}
-#define TEST_READ_WRITE_INVERSE(type, name, ...) \
- TEST(Parcel, Inverse##name) { \
+#define TEST_READ_WRITE_INVERSE(type, name, ...) \
+ TEST(Parcel, Inverse##name) { \
readWriteInverse<type>(__VA_ARGS__, &Parcel::read##name, &Parcel::write##name); \
}
diff --git a/libs/binder/tests/unit_fuzzers/IBinderFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/IBinderFuzzFunctions.h
index 626b758..4a0aeba 100644
--- a/libs/binder/tests/unit_fuzzers/IBinderFuzzFunctions.h
+++ b/libs/binder/tests/unit_fuzzers/IBinderFuzzFunctions.h
@@ -62,20 +62,22 @@
object = fdp->ConsumeIntegral<uint32_t>();
cleanup_cookie = fdp->ConsumeIntegral<uint32_t>();
IBinder::object_cleanup_func func = IBinder::object_cleanup_func();
- ibinder->attachObject(fdp->ConsumeBool() ? reinterpret_cast<void*>(&objectID)
- : nullptr,
- fdp->ConsumeBool() ? reinterpret_cast<void*>(&object) : nullptr,
- fdp->ConsumeBool() ? reinterpret_cast<void*>(&cleanup_cookie)
- : nullptr,
- func);
+ (void)ibinder->attachObject(fdp->ConsumeBool() ? reinterpret_cast<void*>(&objectID)
+ : nullptr,
+ fdp->ConsumeBool() ? reinterpret_cast<void*>(&object)
+ : nullptr,
+ fdp->ConsumeBool()
+ ? reinterpret_cast<void*>(&cleanup_cookie)
+ : nullptr,
+ func);
},
[](FuzzedDataProvider* fdp, IBinder* ibinder) -> void {
uint32_t id = fdp->ConsumeIntegral<uint32_t>();
- ibinder->findObject(reinterpret_cast<void*>(&id));
+ (void)ibinder->findObject(reinterpret_cast<void*>(&id));
},
[](FuzzedDataProvider* fdp, IBinder* ibinder) -> void {
uint32_t id = fdp->ConsumeIntegral<uint32_t>();
- ibinder->detachObject(reinterpret_cast<void*>(&id));
+ (void)ibinder->detachObject(reinterpret_cast<void*>(&id));
},
[](FuzzedDataProvider* fdp, IBinder* ibinder) -> void {
uint32_t code = fdp->ConsumeIntegral<uint32_t>();