DO NOT MERGE - Merge PPRL.190305.001 into master
Bug: 127812889
Change-Id: I737b7713ecfa941d42f7f17c35846b3b066a7c03
diff --git a/.clang-format b/.clang-format
deleted file mode 100644
index 9b3f9d9..0000000
--- a/.clang-format
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-
-BasedOnStyle: Google
-CommentPragmas: NOLINT:.*
-DerivePointerAlignment: false
-AllowShortFunctionsOnASingleLine: Inline
-ColumnLimit: 100
-TabWidth: 4
-UseTab: Never
-IndentWidth: 4
diff --git a/Android.bp b/Android.bp
index 4214d85..f372618 100644
--- a/Android.bp
+++ b/Android.bp
@@ -23,6 +23,7 @@
"liblog",
"libcutils",
"libutils",
+ "libbinderthreadstate",
],
export_shared_lib_headers: [
"libbase",
@@ -31,6 +32,7 @@
export_include_dirs: ["include"],
include_dirs: ["frameworks/native/include"],
+ recovery_available: true,
vendor_available: true,
vndk: {
enabled: true,
@@ -70,7 +72,7 @@
defaults: [
"libhwbinder_defaults",
"hwbinder_pgo",
- "hwbinder_lto"
+ "hwbinder_lto",
],
}
@@ -94,6 +96,7 @@
enable_profile_use: true,
},
}
+
// Provide lto property to build hwbinder with LTO
cc_defaults {
name: "hwbinder_lto",
diff --git a/Binder.cpp b/Binder.cpp
index 147c7ca..72884f0 100644
--- a/Binder.cpp
+++ b/Binder.cpp
@@ -43,12 +43,12 @@
BHwBinder* IBinder::localBinder()
{
- return NULL;
+ return nullptr;
}
BpHwBinder* IBinder::remoteBinder()
{
- return NULL;
+ return nullptr;
}
bool IBinder::checkSubclass(const void* /*subclassID*/) const
@@ -116,7 +116,7 @@
err = onTransact(code, data, reply, flags,
[&](auto &replyParcel) {
replyParcel.setDataPosition(0);
- if (callback != NULL) {
+ if (callback != nullptr) {
callback(replyParcel);
}
});
@@ -154,7 +154,7 @@
void* BHwBinder::findObject(const void* objectID) const
{
Extras* e = mExtras.load(std::memory_order_acquire);
- if (!e) return NULL;
+ if (!e) return nullptr;
AutoMutex _l(e->mLock);
return e->mObjects.find(objectID);
@@ -217,7 +217,7 @@
};
BpHwRefBase::BpHwRefBase(const sp<IBinder>& o)
- : mRemote(o.get()), mRefs(NULL), mState(0)
+ : mRemote(o.get()), mRefs(nullptr), mState(0)
{
if (mRemote) {
mRemote->incStrong(this); // Removed on first IncStrong().
diff --git a/BpHwBinder.cpp b/BpHwBinder.cpp
index 90b3c6f..aacbc8d 100644
--- a/BpHwBinder.cpp
+++ b/BpHwBinder.cpp
@@ -62,7 +62,7 @@
void* BpHwBinder::ObjectManager::find(const void* objectID) const
{
const ssize_t i = mObjects.indexOfKey(objectID);
- if (i < 0) return NULL;
+ if (i < 0) return nullptr;
return mObjects.valueAt(i).object;
}
@@ -77,7 +77,7 @@
ALOGV("Killing %zu objects in manager %p", N, this);
for (size_t i=0; i<N; i++) {
const entry_t& e = mObjects.valueAt(i);
- if (e.func != NULL) {
+ if (e.func != nullptr) {
e.func(mObjects.keyAt(i), e.object, e.cleanupCookie);
}
}
@@ -91,7 +91,7 @@
: mHandle(handle)
, mAlive(1)
, mObitsSent(0)
- , mObituaries(NULL)
+ , mObituaries(nullptr)
{
ALOGV("Creating BpHwBinder %p handle %d\n", this, mHandle);
@@ -121,7 +121,7 @@
ob.cookie = cookie;
ob.flags = flags;
- LOG_ALWAYS_FATAL_IF(recipient == NULL,
+ LOG_ALWAYS_FATAL_IF(recipient == nullptr,
"linkToDeath(): recipient must be non-NULL");
{
@@ -161,9 +161,9 @@
for (size_t i=0; i<N; i++) {
const Obituary& obit = mObituaries->itemAt(i);
if ((obit.recipient == recipient
- || (recipient == NULL && obit.cookie == cookie))
+ || (recipient == nullptr && obit.cookie == cookie))
&& obit.flags == flags) {
- if (outRecipient != NULL) {
+ if (outRecipient != nullptr) {
*outRecipient = mObituaries->itemAt(i).recipient;
}
mObituaries->removeAt(i);
@@ -173,7 +173,7 @@
self->clearDeathNotification(mHandle, this);
self->flushCommands();
delete mObituaries;
- mObituaries = NULL;
+ mObituaries = nullptr;
}
return NO_ERROR;
}
@@ -192,12 +192,12 @@
mLock.lock();
Vector<Obituary>* obits = mObituaries;
- if(obits != NULL) {
+ if(obits != nullptr) {
ALOGV("Clearing sent death notification: %p handle %d\n", this, mHandle);
IPCThreadState* self = IPCThreadState::self();
self->clearDeathNotification(mHandle, this);
self->flushCommands();
- mObituaries = NULL;
+ mObituaries = nullptr;
}
mObitsSent = 1;
mLock.unlock();
@@ -205,7 +205,7 @@
ALOGV("Reporting death of proxy %p for %zu recipients\n",
this, obits ? obits->size() : 0U);
- if (obits != NULL) {
+ if (obits != nullptr) {
const size_t N = obits->size();
for (size_t i=0; i<N; i++) {
reportOneDeath(obits->itemAt(i));
@@ -215,11 +215,18 @@
}
}
+// Returns the strong refcount on the object this proxy points to, or
+// -1 in case of failure.
+ssize_t BpHwBinder::getNodeStrongRefCount()
+{
+ return ProcessState::self()->getStrongRefCountForNodeByHandle(mHandle);
+}
+
void BpHwBinder::reportOneDeath(const Obituary& obit)
{
sp<DeathRecipient> recipient = obit.recipient.promote();
ALOGV("Reporting death to recipient: %p\n", recipient.get());
- if (recipient == NULL) return;
+ if (recipient == nullptr) return;
recipient->binderDied(this);
}
@@ -259,13 +266,13 @@
mLock.lock();
Vector<Obituary>* obits = mObituaries;
- if(obits != NULL) {
+ if(obits != nullptr) {
if (ipc) ipc->clearDeathNotification(mHandle, this);
- mObituaries = NULL;
+ mObituaries = nullptr;
}
mLock.unlock();
- if (obits != NULL) {
+ if (obits != nullptr) {
// XXX Should we tell any remaining DeathRecipient
// objects that the last strong ref has gone away, so they
// are no longer linked?
diff --git a/BufferedTextOutput.cpp b/BufferedTextOutput.cpp
index 9bddde5..3c7db8b 100644
--- a/BufferedTextOutput.cpp
+++ b/BufferedTextOutput.cpp
@@ -27,6 +27,7 @@
#include <hwbinder/Static.h>
+#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
@@ -39,7 +40,7 @@
{
explicit BufferState(int32_t _seq)
: seq(_seq)
- , buffer(NULL)
+ , buffer(nullptr)
, bufferPos(0)
, bufferSize(0)
, atFront(true)
@@ -91,7 +92,7 @@
Vector<sp<BufferedTextOutput::BufferState> > states;
};
-static mutex_t gMutex;
+static pthread_mutex_t gMutex = PTHREAD_MUTEX_INITIALIZER;
static thread_store_t tls;
@@ -117,7 +118,7 @@
{
int32_t res = -1;
- mutex_lock(&gMutex);
+ pthread_mutex_lock(&gMutex);
if (gFreeBufferIndex >= 0) {
res = gFreeBufferIndex;
@@ -129,17 +130,17 @@
gTextBuffers.add(-1);
}
- mutex_unlock(&gMutex);
+ pthread_mutex_unlock(&gMutex);
return res;
}
static void freeBufferIndex(int32_t idx)
{
- mutex_lock(&gMutex);
+ pthread_mutex_lock(&gMutex);
gTextBuffers.editItemAt(idx) = gFreeBufferIndex;
gFreeBufferIndex = idx;
- mutex_unlock(&gMutex);
+ pthread_mutex_unlock(&gMutex);
}
// ---------------------------------------------------------------------------
@@ -265,13 +266,13 @@
if ((mFlags&MULTITHREADED) != 0) {
ThreadState* ts = getThreadState();
if (ts) {
- while (ts->states.size() <= (size_t)mIndex) ts->states.add(NULL);
+ while (ts->states.size() <= (size_t)mIndex) ts->states.add(nullptr);
BufferState* bs = ts->states[mIndex].get();
- if (bs != NULL && bs->seq == mSeq) return bs;
+ if (bs != nullptr && bs->seq == mSeq) return bs;
ts->states.editItemAt(mIndex) = new BufferState(mIndex);
bs = ts->states[mIndex].get();
- if (bs != NULL) return bs;
+ if (bs != nullptr) return bs;
}
}
diff --git a/Debug.cpp b/Debug.cpp
index d304d21..38e3a3f 100644
--- a/Debug.cpp
+++ b/Debug.cpp
@@ -166,13 +166,13 @@
else if (bytesPerLine >= 8) alignment = 2;
else alignment = 1;
}
- if (func == NULL) func = defaultPrintFunc;
+ if (func == nullptr) func = defaultPrintFunc;
size_t offset;
unsigned char *pos = (unsigned char *)buf;
- if (pos == NULL) {
+ if (pos == nullptr) {
if (singleLineBytesCutoff < 0) func(cookie, "\n");
func(cookie, "(NULL)");
return;
@@ -302,7 +302,7 @@
ssize_t getHWBinderKernelReferences(size_t count, uintptr_t* buf) {
sp<ProcessState> proc = ProcessState::selfOrNull();
- if (proc.get() == NULL) {
+ if (proc.get() == nullptr) {
return 0;
}
diff --git a/IInterface.cpp b/IInterface.cpp
index 01866e6..3545325 100644
--- a/IInterface.cpp
+++ b/IInterface.cpp
@@ -33,14 +33,14 @@
// static
sp<IBinder> IInterface::asBinder(const IInterface* iface)
{
- if (iface == NULL) return NULL;
+ if (iface == nullptr) return nullptr;
return const_cast<IInterface*>(iface)->onAsBinder();
}
// static
sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface)
{
- if (iface == NULL) return NULL;
+ if (iface == nullptr) return nullptr;
return iface->onAsBinder();
}
diff --git a/IPCThreadState.cpp b/IPCThreadState.cpp
index b36838e..0b86c01 100644
--- a/IPCThreadState.cpp
+++ b/IPCThreadState.cpp
@@ -17,12 +17,15 @@
#define LOG_TAG "hw-IPCThreadState"
#include <hwbinder/IPCThreadState.h>
+#include <binderthreadstate/IPCThreadStateBase.h>
#include <hwbinder/Binder.h>
#include <hwbinder/BpHwBinder.h>
#include <hwbinder/TextOutput.h>
#include <hwbinder/binder_kernel.h>
+#include <android-base/macros.h>
+#include <utils/CallStack.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
#include <utils/threads.h>
@@ -275,7 +278,6 @@
static bool gHaveTLS = false;
static pthread_key_t gTLS = 0;
static bool gShutdown = false;
-static bool gDisableBackgroundScheduling = false;
IPCThreadState* IPCThreadState::self()
{
@@ -289,7 +291,7 @@
if (gShutdown) {
ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
- return NULL;
+ return nullptr;
}
pthread_mutex_lock(&gTLSMutex);
@@ -299,7 +301,7 @@
pthread_mutex_unlock(&gTLSMutex);
ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
strerror(key_create_value));
- return NULL;
+ return nullptr;
}
gHaveTLS = true;
}
@@ -314,7 +316,7 @@
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
return st;
}
- return NULL;
+ return nullptr;
}
void IPCThreadState::shutdown()
@@ -326,17 +328,15 @@
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(gTLS);
if (st) {
delete st;
- pthread_setspecific(gTLS, NULL);
+ pthread_setspecific(gTLS, nullptr);
}
pthread_key_delete(gTLS);
gHaveTLS = false;
}
}
-void IPCThreadState::disableBackgroundScheduling(bool disable)
-{
- gDisableBackgroundScheduling = disable;
-}
+// TODO(b/66905301): remove symbol
+void IPCThreadState::disableBackgroundScheduling(bool /* disable */) {}
sp<ProcessState> IPCThreadState::process()
{
@@ -478,6 +478,16 @@
pthread_mutex_unlock(&mProcess->mThreadCountLock);
}
+ if (UNLIKELY(!mPostCommandTasks.empty())) {
+ // make a copy in case the post transaction task makes a binder
+ // call and that other process calls back into us
+ std::vector<std::function<void(void)>> tasks = mPostCommandTasks;
+ mPostCommandTasks.clear();
+ for (const auto& func : tasks) {
+ func();
+ }
+ }
+
return result;
}
@@ -627,7 +637,7 @@
LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
(flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
- err = writeTransactionData(BC_TRANSACTION_SG, flags, handle, code, data, NULL);
+ err = writeTransactionData(BC_TRANSACTION_SG, flags, handle, code, data, nullptr);
if (err != NO_ERROR) {
if (reply) reply->setError(err);
@@ -635,6 +645,16 @@
}
if ((flags & TF_ONE_WAY) == 0) {
+ if (UNLIKELY(mCallRestriction != ProcessState::CallRestriction::NONE)) {
+ if (mCallRestriction == ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY) {
+ ALOGE("Process making non-oneway call but is restricted.");
+ CallStack::logStack("non-oneway call", CallStack::getCurrent(10).get(),
+ ANDROID_LOG_ERROR);
+ } else /* FATAL_IF_NOT_ONEWAY */ {
+ LOG_ALWAYS_FATAL("Process may not make oneway calls.");
+ }
+ }
+
#if 0
if (code == 4) { // relayout
ALOGI(">>>>>> CALLING transaction 4");
@@ -663,7 +683,7 @@
else alog << "(none requested)" << endl;
}
} else {
- err = waitForResponse(NULL, NULL);
+ err = waitForResponse(nullptr, nullptr);
}
return err;
@@ -712,7 +732,7 @@
mOut.writeInt32(handle);
status_t result = UNKNOWN_ERROR;
- waitForResponse(NULL, &result);
+ waitForResponse(nullptr, &result);
#if LOG_REFCOUNTS
printf("IPCThreadState::attemptIncStrongHandle(%ld) = %s\n",
@@ -757,7 +777,8 @@
mStrictModePolicy(0),
mLastTransactionBinderFlags(0),
mIsLooper(false),
- mIsPollingThread(false) {
+ mIsPollingThread(false),
+ mCallRestriction(mProcess->mCallRestriction) {
pthread_setspecific(gTLS, this);
clearCaller();
mIn.setDataCapacity(256);
@@ -765,6 +786,7 @@
// TODO(b/67742352): remove this variable from the class
(void)mMyThreadId;
+ mIPCThreadStateBase = IPCThreadStateBase::self();
}
IPCThreadState::~IPCThreadState()
@@ -778,7 +800,7 @@
err = writeTransactionData(BC_REPLY_SG, flags, -1, 0, reply, &statusBuffer);
if (err < NO_ERROR) return err;
- return waitForResponse(NULL, NULL);
+ return waitForResponse(nullptr, nullptr);
}
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
@@ -814,7 +836,7 @@
case BR_ACQUIRE_RESULT:
{
- ALOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");
+ ALOG_ASSERT(acquireResult != nullptr, "Unexpected brACQUIRE_RESULT");
const int32_t result = mIn.readInt32();
if (!acquireResult) continue;
*acquireResult = result ? NO_ERROR : INVALID_OPERATION;
@@ -838,14 +860,14 @@
freeBuffer, this);
} else {
err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
- freeBuffer(NULL,
+ freeBuffer(nullptr,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
}
} else {
- freeBuffer(NULL,
+ freeBuffer(nullptr,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
@@ -1025,6 +1047,10 @@
return (mIsLooper && mProcess->mMaxThreads <= 1) || mIsPollingThread;
}
+void IPCThreadState::addPostCommandTask(const std::function<void(void)>& task) {
+ mPostCommandTasks.push_back(task);
+}
+
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BHwBinder* obj;
@@ -1120,6 +1146,9 @@
"Not enough command data for brTRANSACTION");
if (result != NO_ERROR) break;
+ // Record the fact that we're in a hwbinder call
+ mIPCThreadStateBase->pushCurrentState(
+ IPCThreadStateBase::CallState::HWBINDER);
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
@@ -1186,6 +1215,7 @@
error = mContextObject->transact(tr.code, buffer, &reply, tr.flags, reply_callback);
}
+ mIPCThreadStateBase->popCurrentState();
if ((tr.flags & TF_ONE_WAY) == 0) {
if (!reply_sent) {
// Should have been a reply but there wasn't, so there
@@ -1258,6 +1288,11 @@
return result;
}
+bool IPCThreadState::isServingCall() const
+{
+ return mIPCThreadStateBase->getCurrentBinderCallState() == IPCThreadStateBase::CallState::HWBINDER;
+}
+
void IPCThreadState::threadDestructor(void *st)
{
IPCThreadState* const self = static_cast<IPCThreadState*>(st);
@@ -1282,8 +1317,8 @@
IF_LOG_COMMANDS() {
alog << "Writing BC_FREE_BUFFER for " << data << endl;
}
- ALOG_ASSERT(data != NULL, "Called with NULL data");
- if (parcel != NULL) parcel->closeFileDescriptors();
+ ALOG_ASSERT(data != nullptr, "Called with NULL data");
+ if (parcel != nullptr) parcel->closeFileDescriptors();
IPCThreadState* state = self();
state->mOut.writeInt32(BC_FREE_BUFFER);
state->mOut.writePointer((uintptr_t)data);
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
deleted file mode 100644
index 213c93a..0000000
--- a/PREUPLOAD.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-[Options]
-ignore_merged_commits = true
-
-[Builtin Hooks]
-clang_format = true
diff --git a/Parcel.cpp b/Parcel.cpp
index 2b1bb90..38d97eb 100644
--- a/Parcel.cpp
+++ b/Parcel.cpp
@@ -111,7 +111,7 @@
return;
case BINDER_TYPE_HANDLE: {
const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle);
- if (b != NULL) {
+ if (b != nullptr) {
LOG_REFS("Parcel %p acquiring reference on remote %p", who, b.get());
b->incStrong(who);
}
@@ -119,7 +119,7 @@
}
case BINDER_TYPE_WEAK_HANDLE: {
const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle);
- if (b != NULL) b.get_refs()->incWeak(who);
+ if (b != nullptr) b.get_refs()->incWeak(who);
return;
}
}
@@ -157,7 +157,7 @@
return;
case BINDER_TYPE_HANDLE: {
const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle);
- if (b != NULL) {
+ if (b != nullptr) {
LOG_REFS("Parcel %p releasing reference on remote %p", who, b.get());
b->decStrong(who);
}
@@ -165,7 +165,7 @@
}
case BINDER_TYPE_WEAK_HANDLE: {
const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle);
- if (b != NULL) b.get_refs()->decWeak(who);
+ if (b != nullptr) b.get_refs()->decWeak(who);
return;
}
case BINDER_TYPE_FD: {
@@ -198,11 +198,11 @@
{
flat_binder_object obj;
- if (binder != NULL) {
+ if (binder != nullptr) {
BHwBinder *local = binder->localBinder();
if (!local) {
BpHwBinder *proxy = binder->remoteBinder();
- if (proxy == NULL) {
+ if (proxy == nullptr) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;
@@ -241,13 +241,13 @@
flat_binder_object obj;
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
- if (binder != NULL) {
+ if (binder != nullptr) {
sp<IBinder> real = binder.promote();
- if (real != NULL) {
+ if (real != nullptr) {
IBinder *local = real->localBinder();
if (!local) {
BpHwBinder *proxy = real->remoteBinder();
- if (proxy == NULL) {
+ if (proxy == nullptr) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;
@@ -274,13 +274,13 @@
obj.hdr.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
- return finish_flatten_binder(NULL, obj, out);
+ return finish_flatten_binder(nullptr, obj, out);
} else {
obj.hdr.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
- return finish_flatten_binder(NULL, obj, out);
+ return finish_flatten_binder(nullptr, obj, out);
}
}
@@ -300,7 +300,7 @@
switch (flat->hdr.type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast<IBinder*>(flat->cookie);
- return finish_unflatten_binder(NULL, *flat, in);
+ return finish_unflatten_binder(nullptr, *flat, in);
case BINDER_TYPE_HANDLE:
*out = proc->getStrongProxyForHandle(flat->handle);
return finish_unflatten_binder(
@@ -319,16 +319,16 @@
switch (flat->hdr.type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast<IBinder*>(flat->cookie);
- return finish_unflatten_binder(NULL, *flat, in);
+ return finish_unflatten_binder(nullptr, *flat, in);
case BINDER_TYPE_WEAK_BINDER:
if (flat->binder != 0) {
out->set_object_and_refs(
reinterpret_cast<IBinder*>(flat->cookie),
reinterpret_cast<RefBase::weakref_type*>(flat->binder));
} else {
- *out = NULL;
+ *out = nullptr;
}
- return finish_unflatten_binder(NULL, *flat, in);
+ return finish_unflatten_binder(nullptr, *flat, in);
case BINDER_TYPE_HANDLE:
case BINDER_TYPE_WEAK_HANDLE:
*out = proc->getWeakProxyForHandle(flat->handle);
@@ -569,14 +569,14 @@
if (len > INT32_MAX) {
// don't accept size_t values which may have come from an
// inadvertent conversion from a negative int.
- return NULL;
+ return nullptr;
}
const size_t padded = pad_size(len);
// sanity check for integer overflow
if (mDataPos+padded < mDataPos) {
- return NULL;
+ return nullptr;
}
if ((mDataPos+padded) <= mDataCapacity) {
@@ -607,7 +607,7 @@
status_t err = growData(padded);
if (err == NO_ERROR) goto restart_write;
- return NULL;
+ return nullptr;
}
status_t Parcel::writeInt8(int8_t val)
@@ -705,7 +705,7 @@
status_t Parcel::writeString16(const char16_t* str, size_t len)
{
- if (str == NULL) return writeInt32(-1);
+ if (str == nullptr) return writeInt32(-1);
status_t err = writeInt32(len);
if (err == NO_ERROR) {
@@ -789,7 +789,7 @@
size_t newSize = ((mObjectsSize+2)*3)/2;
if (newSize * sizeof(binder_size_t) < mObjectsSize) return NO_MEMORY; // overflow
binder_size_t* objects = (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
- if (objects == NULL) return NO_MEMORY;
+ if (objects == nullptr) return NO_MEMORY;
mObjects = objects;
mObjectsCapacity = newSize;
}
@@ -1124,7 +1124,7 @@
if (len > INT32_MAX) {
// don't accept size_t values which may have come from an
// inadvertent conversion from a negative int.
- return NULL;
+ return nullptr;
}
if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize
@@ -1134,7 +1134,7 @@
ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos);
return data;
}
- return NULL;
+ return nullptr;
}
template<class T>
@@ -1336,7 +1336,7 @@
return str;
}
}
- return NULL;
+ return nullptr;
}
String16 Parcel::readString16() const
{
@@ -1390,12 +1390,12 @@
if (size >= 0 && size < INT32_MAX) {
*outLen = size;
const char16_t* str = (const char16_t*)readInplace((size+1)*sizeof(char16_t));
- if (str != NULL) {
+ if (str != nullptr) {
return str;
}
}
*outLen = 0;
- return NULL;
+ return nullptr;
}
status_t Parcel::readStrongBinder(sp<IBinder>* val) const
{
@@ -1520,7 +1520,7 @@
ALOGW("Attempt to read object from Parcel %p at offset %zu that is not in the object list",
this, DPOS);
}
- return NULL;
+ return nullptr;
}
template const flat_binder_object* Parcel::readObject<flat_binder_object>(size_t *objects_offset) const;
@@ -2022,7 +2022,7 @@
ALOGV("restartWrite Setting data pos of %p to %zu", this, mDataPos);
free(mObjects);
- mObjects = NULL;
+ mObjects = nullptr;
mObjectsSize = mObjectsCapacity = 0;
mNextObjectHint = 0;
mHasFds = false;
@@ -2071,7 +2071,7 @@
mError = NO_MEMORY;
return NO_MEMORY;
}
- binder_size_t* objects = NULL;
+ binder_size_t* objects = nullptr;
if (objectsSize) {
objects = (binder_size_t*)calloc(objectsSize, sizeof(binder_size_t));
@@ -2098,7 +2098,7 @@
}
//ALOGI("Freeing data ref of %p (pid=%d)", this, getpid());
mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);
- mOwner = NULL;
+ mOwner = nullptr;
LOG_ALLOC("Parcel %p: taking ownership of %zu capacity", this, desired);
pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
@@ -2174,7 +2174,7 @@
return NO_MEMORY;
}
- if(!(mDataCapacity == 0 && mObjects == NULL
+ if(!(mDataCapacity == 0 && mObjects == nullptr
&& mObjectsCapacity == 0)) {
ALOGE("continueWrite: %zu/%p/%zu/%zu", mDataCapacity, mObjects, mObjectsCapacity, desired);
}
@@ -2199,20 +2199,20 @@
{
LOG_ALLOC("Parcel %p: initState", this);
mError = NO_ERROR;
- mData = 0;
+ mData = nullptr;
mDataSize = 0;
mDataCapacity = 0;
mDataPos = 0;
ALOGV("initState Setting data size of %p to %zu", this, mDataSize);
ALOGV("initState Setting data pos of %p to %zu", this, mDataPos);
- mObjects = NULL;
+ mObjects = nullptr;
mObjectsSize = 0;
mObjectsCapacity = 0;
mNextObjectHint = 0;
mHasFds = false;
mFdsKnown = true;
mAllowFds = true;
- mOwner = NULL;
+ mOwner = nullptr;
clearCache();
mNumRef = 0;
diff --git a/ProcessState.cpp b/ProcessState.cpp
index 37e3611..8a8b7cc 100644
--- a/ProcessState.cpp
+++ b/ProcessState.cpp
@@ -68,7 +68,7 @@
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
- if (gProcess != NULL) {
+ if (gProcess != nullptr) {
return gProcess;
}
gProcess = new ProcessState(DEFAULT_BINDER_VM_SIZE);
@@ -82,7 +82,7 @@
sp<ProcessState> ProcessState::initWithMmapSize(size_t mmap_size) {
Mutex::Autolock _l(gProcessMutex);
- if (gProcess != NULL) {
+ if (gProcess != nullptr) {
LOG_ALWAYS_FATAL_IF(mmap_size != gProcess->getMmapSize(),
"ProcessState already initialized with a different mmap size.");
return gProcess;
@@ -112,18 +112,18 @@
{
mLock.lock();
sp<IBinder> object(
- mContexts.indexOfKey(name) >= 0 ? mContexts.valueFor(name) : NULL);
+ mContexts.indexOfKey(name) >= 0 ? mContexts.valueFor(name) : nullptr);
mLock.unlock();
//printf("Getting context object %s for %p\n", String8(name).string(), caller.get());
- if (object != NULL) return object;
+ if (object != nullptr) return object;
// Don't attempt to retrieve contexts if we manage them
if (mManagesContexts) {
ALOGE("getContextObject(%s) failed, but we manage the contexts!\n",
String8(name).string());
- return NULL;
+ return nullptr;
}
IPCThreadState* ipc = IPCThreadState::self();
@@ -140,7 +140,7 @@
ipc->flushCommands();
- if (object != NULL) setContextObject(object, name);
+ if (object != nullptr) setContextObject(object, name);
return object;
}
@@ -184,8 +184,8 @@
if (result == 0) {
mManagesContexts = true;
} else if (result == -1) {
- mBinderContextCheckFunc = NULL;
- mBinderContextUserData = NULL;
+ mBinderContextCheckFunc = nullptr;
+ mBinderContextUserData = nullptr;
ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
}
}
@@ -201,7 +201,7 @@
ssize_t ProcessState::getKernelReferences(size_t buf_count, uintptr_t* buf) {
binder_node_debug_info info = {};
- uintptr_t* end = buf ? buf + buf_count : NULL;
+ uintptr_t* end = buf ? buf + buf_count : nullptr;
size_t count = 0;
do {
@@ -220,19 +220,44 @@
return count;
}
+// Queries the driver for the current strong reference count of the node
+// that the handle points to. Can only be used by the servicemanager.
+//
+// Returns -1 in case of failure, otherwise the strong reference count.
+ssize_t ProcessState::getStrongRefCountForNodeByHandle(int32_t handle) {
+ binder_node_info_for_ref info;
+ memset(&info, 0, sizeof(binder_node_info_for_ref));
+
+ info.handle = handle;
+
+ status_t result = ioctl(mDriverFD, BINDER_GET_NODE_INFO_FOR_REF, &info);
+
+ if (result != OK) {
+ return -1;
+ }
+
+ return info.strong_count;
+}
+
size_t ProcessState::getMmapSize() {
return mMmapSize;
}
+void ProcessState::setCallRestriction(CallRestriction restriction) {
+ LOG_ALWAYS_FATAL_IF(IPCThreadState::selfOrNull(), "Call restrictions must be set before the threadpool is started.");
+
+ mCallRestriction = restriction;
+}
+
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
const size_t N=mHandleToObject.size();
if (N <= (size_t)handle) {
handle_entry e;
- e.binder = NULL;
- e.refs = NULL;
+ e.binder = nullptr;
+ e.refs = nullptr;
status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
- if (err < NO_ERROR) return NULL;
+ if (err < NO_ERROR) return nullptr;
}
return &mHandleToObject.editItemAt(handle);
}
@@ -245,12 +270,12 @@
handle_entry* e = lookupHandleLocked(handle);
- if (e != NULL) {
+ if (e != nullptr) {
// We need to create a new BpHwBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. See comment
// in getWeakProxyForHandle() for more info about this.
IBinder* b = e->binder;
- if (b == NULL || !e->refs->attemptIncWeak(this)) {
+ if (b == nullptr || !e->refs->attemptIncWeak(this)) {
b = new BpHwBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
@@ -275,7 +300,7 @@
handle_entry* e = lookupHandleLocked(handle);
- if (e != NULL) {
+ if (e != nullptr) {
// We need to create a new BpHwBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. The
// attemptIncWeak() is safe because we know the BpHwBinder destructor will always
@@ -284,7 +309,7 @@
// releasing a reference on this BpHwBinder, and a new reference on its handle
// arriving from the driver.
IBinder* b = e->binder;
- if (b == NULL || !e->refs->attemptIncWeak(this)) {
+ if (b == nullptr || !e->refs->attemptIncWeak(this)) {
b = new BpHwBinder(handle);
result = b;
e->binder = b;
@@ -307,7 +332,7 @@
// This handle may have already been replaced with a new BpHwBinder
// (if someone failed the AttemptIncWeak() above); we don't want
// to overwrite it.
- if (e && e->binder == binder) e->binder = NULL;
+ if (e && e->binder == binder) e->binder = nullptr;
}
String8 ProcessState::makeBinderThreadName() {
@@ -329,24 +354,37 @@
}
status_t ProcessState::setThreadPoolConfiguration(size_t maxThreads, bool callerJoinsPool) {
- LOG_ALWAYS_FATAL_IF(maxThreads < 1, "Binder threadpool must have a minimum of one thread.");
- status_t result = NO_ERROR;
+ // if the caller joins the pool, then there will be one thread which is impossible.
+ LOG_ALWAYS_FATAL_IF(maxThreads == 0 && callerJoinsPool,
+ "Binder threadpool must have a minimum of one thread if caller joins pool.");
+
+ size_t threadsToAllocate = maxThreads;
+
+ // If the caller is going to join the pool it will contribute one thread to the threadpool.
+ // This is part of the API's contract.
+ if (callerJoinsPool) threadsToAllocate--;
+
+ // If we can, spawn one thread from userspace when the threadpool is started. This ensures
+ // that there is always a thread available to start more threads as soon as the threadpool
+ // is started.
+ bool spawnThreadOnStart = threadsToAllocate > 0;
+ if (spawnThreadOnStart) threadsToAllocate--;
+
// the BINDER_SET_MAX_THREADS ioctl really tells the kernel how many threads
// it's allowed to spawn, *in addition* to any threads we may have already
- // spawned locally. If 'callerJoinsPool' is true, it means that the caller
- // will join the threadpool, and so the kernel needs to create one less thread.
- // If 'callerJoinsPool' is false, we will still spawn a thread locally, and we should
- // also tell the kernel to create one less thread than what was requested here.
- size_t kernelMaxThreads = maxThreads - 1;
- if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &kernelMaxThreads) != -1) {
- AutoMutex _l(mLock);
- mMaxThreads = maxThreads;
- mSpawnThreadOnStart = !callerJoinsPool;
- } else {
- result = -errno;
- ALOGE("Binder ioctl to set max threads failed: %s", strerror(-result));
+ // spawned locally.
+ size_t kernelMaxThreads = threadsToAllocate;
+
+ AutoMutex _l(mLock);
+ if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &kernelMaxThreads) == -1) {
+ ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
+ return -errno;
}
- return result;
+
+ mMaxThreads = maxThreads;
+ mSpawnThreadOnStart = spawnThreadOnStart;
+
+ return NO_ERROR;
}
size_t ProcessState::getMaxThreads() {
@@ -393,19 +431,20 @@
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
- , mBinderContextCheckFunc(NULL)
- , mBinderContextUserData(NULL)
+ , mBinderContextCheckFunc(nullptr)
+ , mBinderContextUserData(nullptr)
, mThreadPoolStarted(false)
, mSpawnThreadOnStart(true)
, mThreadPoolSeq(1)
, mMmapSize(mmap_size)
+ , mCallRestriction(CallRestriction::NONE)
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
- mVMStart = mmap(0, mMmapSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
+ mVMStart = mmap(nullptr, mMmapSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// *sigh*
- ALOGE("Using /dev/hwbinder failed: unable to mmap transaction memory.\n");
+ ALOGE("Mmapping /dev/hwbinder failed: %s\n", strerror(errno));
close(mDriverFD);
mDriverFD = -1;
}
diff --git a/Static.cpp b/Static.cpp
index a84f811..87f632c 100644
--- a/Static.cpp
+++ b/Static.cpp
@@ -76,20 +76,5 @@
Mutex& gProcessMutex = *new Mutex;
sp<ProcessState> gProcess;
-class LibHwbinderIPCtStatics
-{
-public:
- LibHwbinderIPCtStatics()
- {
- }
-
- ~LibHwbinderIPCtStatics()
- {
- IPCThreadState::shutdown();
- }
-};
-
-static LibHwbinderIPCtStatics gIPCStatics;
-
} // namespace hardware
} // namespace android
diff --git a/include/hwbinder/Binder.h b/include/hwbinder/Binder.h
index 1efa342..4289f2d 100644
--- a/include/hwbinder/Binder.h
+++ b/include/hwbinder/Binder.h
@@ -37,13 +37,13 @@
TransactCallback callback = nullptr);
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
- void* cookie = NULL,
+ void* cookie = nullptr,
uint32_t flags = 0);
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
- void* cookie = NULL,
+ void* cookie = nullptr,
uint32_t flags = 0,
- wp<DeathRecipient>* outRecipient = NULL);
+ wp<DeathRecipient>* outRecipient = nullptr);
virtual void attachObject( const void* objectID,
void* object,
@@ -97,6 +97,7 @@
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
+public:
inline IBinder* remote() const { return mRemote; }
private:
diff --git a/include/hwbinder/BpHwBinder.h b/include/hwbinder/BpHwBinder.h
index dc3073a..73d2dd0 100644
--- a/include/hwbinder/BpHwBinder.h
+++ b/include/hwbinder/BpHwBinder.h
@@ -39,12 +39,12 @@
TransactCallback callback = nullptr);
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
- void* cookie = NULL,
+ void* cookie = nullptr,
uint32_t flags = 0);
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
- void* cookie = NULL,
+ void* cookie = nullptr,
uint32_t flags = 0,
- wp<DeathRecipient>* outRecipient = NULL);
+ wp<DeathRecipient>* outRecipient = nullptr);
virtual void attachObject( const void* objectID,
void* object,
@@ -57,7 +57,12 @@
status_t setConstantData(const void* data, size_t size);
void sendObituary();
-
+ // This refcount includes:
+ // 1. Strong references to the node by this and other processes
+ // 2. Temporary strong references held by the kernel during a
+ // transaction on the node.
+ // It does NOT include local strong references to the node
+ ssize_t getNodeStrongRefCount();
class ObjectManager
{
public:
diff --git a/include/hwbinder/Debug.h b/include/hwbinder/Debug.h
index 03127cb..0c173a4 100644
--- a/include/hwbinder/Debug.h
+++ b/include/hwbinder/Debug.h
@@ -32,12 +32,12 @@
typedef void (*debugPrintFunc)(void* cookie, const char* txt);
void printTypeCode(uint32_t typeCode,
- debugPrintFunc func = 0, void* cookie = 0);
+ debugPrintFunc func = nullptr, void* cookie = nullptr);
void printHexData(int32_t indent, const void *buf, size_t length,
size_t bytesPerLine=16, int32_t singleLineBytesCutoff=16,
size_t alignment=0, bool cArrayStyle=false,
- debugPrintFunc func = 0, void* cookie = 0);
+ debugPrintFunc func = nullptr, void* cookie = nullptr);
ssize_t getHWBinderKernelReferences(size_t count, uintptr_t* buf);
diff --git a/include/hwbinder/IBinder.h b/include/hwbinder/IBinder.h
index 5648101..b8f3b0e 100644
--- a/include/hwbinder/IBinder.h
+++ b/include/hwbinder/IBinder.h
@@ -86,7 +86,7 @@
* directly do with it now that it has passed on.)
*/
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
- void* cookie = NULL,
+ void* cookie = nullptr,
uint32_t flags = 0) = 0;
/**
@@ -97,19 +97,39 @@
* added with that cookie will be unlinked.
*/
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
- void* cookie = NULL,
+ void* cookie = nullptr,
uint32_t flags = 0,
- wp<DeathRecipient>* outRecipient = NULL) = 0;
+ wp<DeathRecipient>* outRecipient = nullptr) = 0;
virtual bool checkSubclass(const void* subclassID) const;
typedef void (*object_cleanup_func)(const void* id, void* obj, void* cleanupCookie);
+ /**
+ * This object is attached for the lifetime of this binder object. When
+ * this binder object is destructed, the cleanup function of all attached
+ * 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.
+ */
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;
+ /**
+ * 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).
+ */
virtual void detachObject(const void* objectID) = 0;
virtual BHwBinder* localBinder();
diff --git a/include/hwbinder/IPCThreadState.h b/include/hwbinder/IPCThreadState.h
index 32eea8c..69b7f65 100644
--- a/include/hwbinder/IPCThreadState.h
+++ b/include/hwbinder/IPCThreadState.h
@@ -22,12 +22,17 @@
#include <hwbinder/ProcessState.h>
#include <utils/Vector.h>
+#include <functional>
+
#if defined(_WIN32)
typedef int uid_t;
#endif
// ---------------------------------------------------------------------------
namespace android {
+
+class IPCThreadStateBase;
+
namespace hardware {
class IPCThreadState
@@ -84,12 +89,10 @@
static void shutdown();
- // Call this to disable switching threads to background scheduling when
- // receiving incoming IPC calls. This is specifically here for the
- // Android system process, since it expects to have background apps calling
- // in to it but doesn't want to acquire locks in its services while in
- // the background.
+ // TODO(b/66905301): remove symbol
+private:
static void disableBackgroundScheduling(bool disable);
+public:
// Call blocks until the number of executing binder threads is less than
// the maximum number of binder threads threads allowed for this process.
@@ -101,13 +104,43 @@
bool isLooperThread();
bool isOnlyBinderThread();
-private:
- IPCThreadState();
- ~IPCThreadState();
+ // Is this thread currently serving a hwbinder call. This method
+ // returns true if while traversing backwards from the function call
+ // stack for this thread, we encounter a function serving a hwbinder
+ // call before encountering a binder call / hitting the end of the
+ // call stack.
+ // Eg: If thread T1 went through the following call pattern
+ // 1) T1 receives and executes binder call B1.
+ // 2) While handling B1, T1 makes hwbinder call H1.
+ // 3) The handler of H1, calls into T1 with a callback H2.
+ // If isServingCall() is called during B1 before 3), this method
+ // will return false, else true.
+ //
+ // ----
+ // | H2 | ---> While callback H2 is being handled during 3).
+ // ----
+ // | B1 | ---> While B1 is being handled, hwbinder call H1 made.
+ // ----
+ // Fig: Thread Call stack while handling H2.
+ //
+ // This is since after 3), while traversing the thread call stack,
+ // we hit a hwbinder call before a binder call / end of stack.
+ // This method may be typically used to determine whether to use
+ // hardware::IPCThreadState methods or IPCThreadState methods to
+ // infer information about thread state.
+ bool isServingCall() const;
+
+ // Tasks which are done on the binder thread after the thread returns to the
+ // threadpool.
+ void addPostCommandTask(const std::function<void(void)>& task);
+
+ private:
+ IPCThreadState();
+ ~IPCThreadState();
status_t sendReply(const Parcel& reply, uint32_t flags);
status_t waitForResponse(Parcel *reply,
- status_t *acquireResult=NULL);
+ status_t *acquireResult=nullptr);
status_t talkWithDriver(bool doReceive=true);
status_t writeTransactionData(int32_t cmd,
uint32_t binderFlags,
@@ -145,6 +178,11 @@
sp<BHwBinder> mContextObject;
bool mIsLooper;
bool mIsPollingThread;
+
+ std::vector<std::function<void(void)>> mPostCommandTasks;
+ IPCThreadStateBase *mIPCThreadStateBase;
+
+ ProcessState::CallRestriction mCallRestriction;
};
}; // namespace hardware
diff --git a/include/hwbinder/ProcessState.h b/include/hwbinder/ProcessState.h
index 2f72059..c42d8a8 100644
--- a/include/hwbinder/ProcessState.h
+++ b/include/hwbinder/ProcessState.h
@@ -70,7 +70,26 @@
void giveThreadPoolName();
ssize_t getKernelReferences(size_t count, uintptr_t* buf);
+ // This refcount includes:
+ // 1. Strong references to the node by this and other processes
+ // 2. Temporary strong references held by the kernel during a
+ // transaction on the node.
+ // It does NOT include local strong references to the node
+ ssize_t getStrongRefCountForNodeByHandle(int32_t handle);
size_t getMmapSize();
+
+ enum class CallRestriction {
+ // all calls okay
+ NONE,
+ // log when calls are blocking
+ ERROR_IF_NOT_ONEWAY,
+ // abort process on blocking calls
+ FATAL_IF_NOT_ONEWAY,
+ };
+ // Sets calling restrictions for all transactions in this process. This must be called
+ // before any threads are spawned.
+ void setCallRestriction(CallRestriction restriction);
+
private:
friend class IPCThreadState;
@@ -117,7 +136,9 @@
bool mThreadPoolStarted;
bool mSpawnThreadOnStart;
volatile int32_t mThreadPoolSeq;
- size_t mMmapSize;
+ const size_t mMmapSize;
+
+ CallRestriction mCallRestriction;
};
}; // namespace hardware
diff --git a/vts/performance/Android.bp b/vts/performance/Android.bp
index c5fa2a0..b5097df 100644
--- a/vts/performance/Android.bp
+++ b/vts/performance/Android.bp
@@ -29,14 +29,24 @@
"libutils",
"libcutils",
],
+
+ static_libs: ["android.hardware.tests.libhwbinder@1.0"],
+
+ // Allow dlsym'ing self for statically linked passthrough implementations
+ ldflags: ["-rdynamic"],
+
+ // impls should never be static, these are used only for testing purposes
+ // and test portability since this test pairs with specific hal
+ // implementations
+ whole_static_libs: [
+ "android.hardware.tests.libhwbinder@1.0-impl",
+ ],
}
cc_benchmark {
name: "libhwbinder_benchmark",
defaults: ["libhwbinder_test_defaults"],
srcs: ["Benchmark.cpp"],
- static_libs: ["android.hardware.tests.libhwbinder@1.0"],
- required: ["android.hardware.tests.libhwbinder@1.0-impl"],
}
// build for benchmark test based on binder.
@@ -60,8 +70,6 @@
name: "hwbinderThroughputTest",
defaults: ["libhwbinder_test_defaults"],
srcs: ["Benchmark_throughput.cpp"],
- static_libs: ["android.hardware.tests.libhwbinder@1.0"],
- required: ["android.hardware.tests.libhwbinder@1.0-impl"],
}
// build for latency benchmark test for hwbinder.
@@ -73,8 +81,4 @@
"Latency.cpp",
"PerfTest.cpp",
],
-
- static_libs: ["android.hardware.tests.libhwbinder@1.0"],
-
- required: ["android.hardware.tests.libhwbinder@1.0-impl"],
}
diff --git a/vts/performance/PerfTest.h b/vts/performance/PerfTest.h
index 3fa4b8d..2ca1d89 100644
--- a/vts/performance/PerfTest.h
+++ b/vts/performance/PerfTest.h
@@ -34,7 +34,7 @@
class Pipe {
public:
static tuple<Pipe, Pipe> createPipePair();
- Pipe(Pipe&& rval);
+ Pipe(Pipe&& rval) noexcept;
~Pipe();
inline void signal() {
bool val = true;