Merge "binder_rs: add OwnedParcel"
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index e3c4ede..01c4723 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -265,6 +265,22 @@
chmod 0666 /sys/kernel/tracing/per_cpu/cpu14/trace
chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu15/trace
chmod 0666 /sys/kernel/tracing/per_cpu/cpu15/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu16/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu16/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu17/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu17/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu18/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu18/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu19/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu19/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu20/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu20/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu21/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu21/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu22/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu22/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu23/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu23/trace
# Only create the tracing instance if persist.mm_events.enabled
# Attempting to remove the tracing instance after it has been created
@@ -337,6 +353,22 @@
chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu14/trace
chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu15/trace
chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu15/trace
+ chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu16/trace
+ chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu16/trace
+ chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu17/trace
+ chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu17/trace
+ chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu18/trace
+ chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu18/trace
+ chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu19/trace
+ chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu19/trace
+ chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu20/trace
+ chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu20/trace
+ chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu21/trace
+ chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu21/trace
+ chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu22/trace
+ chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu22/trace
+ chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu23/trace
+ chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu23/trace
on property:persist.debug.atrace.boottrace=1
start boottrace
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 83e6787..3722383 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -38,11 +38,6 @@
#include "DumpPool.h"
#include "TaskQueue.h"
-// Workaround for const char *args[MAX_ARGS_ARRAY_SIZE] variables until they're converted to
-// std::vector<std::string>
-// TODO: remove once not used
-#define MAX_ARGS_ARRAY_SIZE 1000
-
// TODO: move everything under this namespace
// TODO: and then remove explicitly android::os::dumpstate:: prefixes
namespace android {
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 5082eb0..157d259 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -25,6 +25,7 @@
#include <functional>
#include <inttypes.h>
#include <regex>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/capability.h>
@@ -281,36 +282,31 @@
}
status_t InstalldNativeService::dump(int fd, const Vector<String16> & /* args */) {
- auto out = std::fstream(StringPrintf("/proc/self/fd/%d", fd));
const binder::Status dump_permission = checkPermission(kDump);
if (!dump_permission.isOk()) {
- out << dump_permission.toString8() << endl;
+ dprintf(fd, "%s\n", dump_permission.toString8().c_str());
return PERMISSION_DENIED;
}
- std::lock_guard<std::recursive_mutex> lock(mLock);
- out << "installd is happy!" << endl;
+ std::lock_guard<std::recursive_mutex> lock(mLock);
{
std::lock_guard<std::recursive_mutex> lock(mMountsLock);
- out << endl << "Storage mounts:" << endl;
+ dprintf(fd, "Storage mounts:\n");
for (const auto& n : mStorageMounts) {
- out << " " << n.first << " = " << n.second << endl;
+ dprintf(fd, " %s = %s\n", n.first.c_str(), n.second.c_str());
}
}
{
std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
- out << endl << "Per-UID cache quotas:" << endl;
+ dprintf(fd, "Per-UID cache quotas:\n");
for (const auto& n : mCacheQuotas) {
- out << " " << n.first << " = " << n.second << endl;
+ dprintf(fd, " %d = %" PRId64 "\n", n.first, n.second);
}
}
- out << "is_dexopt_blocked:" << android::installd::is_dexopt_blocked() << endl;
-
- out << endl;
- out.flush();
+ dprintf(fd, "is_dexopt_blocked:%d\n", android::installd::is_dexopt_blocked());
return NO_ERROR;
}
diff --git a/cmds/rss_hwm_reset/rss_hwm_reset.rc b/cmds/rss_hwm_reset/rss_hwm_reset.rc
index fbbc820..271cbf8 100644
--- a/cmds/rss_hwm_reset/rss_hwm_reset.rc
+++ b/cmds/rss_hwm_reset/rss_hwm_reset.rc
@@ -18,7 +18,7 @@
oneshot
user nobody
group nobody readproc
- writepid /dev/cpuset/system-background/tasks
+ task_profiles ServiceCapacityLow
capabilities DAC_OVERRIDE
on property:sys.rss_hwm_reset.on=1
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
index 0b00c2d..fdbe85b 100644
--- a/cmds/service/service.cpp
+++ b/cmds/service/service.cpp
@@ -77,6 +77,9 @@
bool wantsUsage = false;
int result = 0;
+ /* Strip path off the program name. */
+ char* prog_name = basename(argv[0]);
+
while (1) {
int ic = getopt(argc, argv, "h?");
if (ic < 0)
@@ -88,7 +91,7 @@
wantsUsage = true;
break;
default:
- aerr << "service: Unknown option -" << ic << endl;
+ aerr << prog_name << ": Unknown option -" << ic << endl;
wantsUsage = true;
result = 10;
break;
@@ -103,7 +106,7 @@
sp<IServiceManager> sm = defaultServiceManager();
fflush(stdout);
if (sm == nullptr) {
- aerr << "service: Unable to get default service manager!" << endl;
+ aerr << prog_name << ": Unable to get default service manager!" << endl;
return 20;
}
@@ -117,7 +120,7 @@
aout << "Service " << argv[optind] <<
(service == nullptr ? ": not found" : ": found") << endl;
} else {
- aerr << "service: No service specified for check" << endl;
+ aerr << prog_name << ": No service specified for check" << endl;
wantsUsage = true;
result = 10;
}
@@ -152,7 +155,7 @@
if (strcmp(argv[optind], "i32") == 0) {
optind++;
if (optind >= argc) {
- aerr << "service: no integer supplied for 'i32'" << endl;
+ aerr << prog_name << ": no integer supplied for 'i32'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -161,7 +164,7 @@
} else if (strcmp(argv[optind], "i64") == 0) {
optind++;
if (optind >= argc) {
- aerr << "service: no integer supplied for 'i64'" << endl;
+ aerr << prog_name << ": no integer supplied for 'i64'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -170,7 +173,7 @@
} else if (strcmp(argv[optind], "s16") == 0) {
optind++;
if (optind >= argc) {
- aerr << "service: no string supplied for 's16'" << endl;
+ aerr << prog_name << ": no string supplied for 's16'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -179,7 +182,7 @@
} else if (strcmp(argv[optind], "f") == 0) {
optind++;
if (optind >= argc) {
- aerr << "service: no number supplied for 'f'" << endl;
+ aerr << prog_name << ": no number supplied for 'f'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -188,7 +191,7 @@
} else if (strcmp(argv[optind], "d") == 0) {
optind++;
if (optind >= argc) {
- aerr << "service: no number supplied for 'd'" << endl;
+ aerr << prog_name << ": no number supplied for 'd'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -200,7 +203,7 @@
} else if (strcmp(argv[optind], "fd") == 0) {
optind++;
if (optind >= argc) {
- aerr << "service: no path supplied for 'fd'" << endl;
+ aerr << prog_name << ": no path supplied for 'fd'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -208,7 +211,7 @@
const char *path = argv[optind++];
int fd = open(path, O_RDONLY);
if (fd < 0) {
- aerr << "service: could not open '" << path << "'" << endl;
+ aerr << prog_name << ": could not open '" << path << "'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -217,7 +220,7 @@
} else if (strcmp(argv[optind], "afd") == 0) {
optind++;
if (optind >= argc) {
- aerr << "service: no path supplied for 'afd'" << endl;
+ aerr << prog_name << ": no path supplied for 'afd'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -226,7 +229,8 @@
int fd = open(path, O_RDONLY);
struct stat statbuf;
if (fd < 0 || fstat(fd, &statbuf) != 0) {
- aerr << "service: could not open or stat '" << path << "'" << endl;
+ aerr << prog_name << ": could not open or stat"
+ << " '" << path << "'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -240,7 +244,8 @@
} else if (strcmp(argv[optind], "nfd") == 0) {
optind++;
if (optind >= argc) {
- aerr << "service: no file descriptor supplied for 'nfd'" << endl;
+ aerr << prog_name << ": no file descriptor supplied for"
+ << " 'nfd'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -327,7 +332,7 @@
// for now just set the extra field to be null.
data.writeInt32(-1);
} else {
- aerr << "service: unknown option " << argv[optind] << endl;
+ aerr << prog_name << ": unknown option " << argv[optind] << endl;
wantsUsage = true;
result = 10;
break;
@@ -337,44 +342,44 @@
service->transact(code, data, &reply);
aout << "Result: " << reply << endl;
} else {
- aerr << "service: Service " << argv[serviceArg]
+ aerr << prog_name << ": Service " << argv[serviceArg]
<< " does not exist" << endl;
result = 10;
}
} else {
if (optind < argc) {
- aerr << "service: No service specified for call" << endl;
+ aerr << prog_name << ": No service specified for call" << endl;
} else {
- aerr << "service: No code specified for call" << endl;
+ aerr << prog_name << ": No code specified for call" << endl;
}
wantsUsage = true;
result = 10;
}
} else {
- aerr << "service: Unknown command " << argv[optind] << endl;
+ aerr << prog_name << ": Unknown command " << argv[optind] << endl;
wantsUsage = true;
result = 10;
}
}
if (wantsUsage) {
- aout << "Usage: service [-h|-?]\n"
- " service list\n"
- " service check SERVICE\n"
- " service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR | null"
- " | fd f | nfd n | afd f ] ...\n"
+ aout << "Usage: " << prog_name << " [-h|-?]\n"
+ " " << prog_name << " list\n"
+ " " << prog_name << " check SERVICE\n"
+ " " << prog_name << " call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR"
+ " | null | fd f | nfd n | afd f ] ...\n"
"Options:\n"
" i32: Write the 32-bit integer N into the send parcel.\n"
" i64: Write the 64-bit integer N into the send parcel.\n"
- " f: Write the 32-bit single-precision number N into the send parcel.\n"
- " d: Write the 64-bit double-precision number N into the send parcel.\n"
+ " f: Write the 32-bit single-precision number N into the send parcel.\n"
+ " d: Write the 64-bit double-precision number N into the send parcel.\n"
" s16: Write the UTF-16 string STR into the send parcel.\n"
" null: Write a null binder into the send parcel.\n"
- " fd: Write a file descriptor for the file f to the send parcel.\n"
- " nfd: Write file descriptor n to the send parcel.\n"
- " afd: Write an ashmem file descriptor for a region containing the data from"
- " file f to the send parcel.\n";
-// " intent: Write and Intent int the send parcel. ARGS can be\n"
+ " fd: Write a file descriptor for the file f into the send parcel.\n"
+ " nfd: Write the file descriptor n into the send parcel.\n"
+ " afd: Write an ashmem file descriptor for a region containing the data from\n"
+ " file f into the send parcel.\n";
+// " intent: Write an Intent into the send parcel. ARGS can be\n"
// " action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
return result;
}
diff --git a/cmds/servicemanager/servicemanager.rc b/cmds/servicemanager/servicemanager.rc
index 6d5070f..0dd29e0 100644
--- a/cmds/servicemanager/servicemanager.rc
+++ b/cmds/servicemanager/servicemanager.rc
@@ -9,5 +9,5 @@
onrestart class_restart main
onrestart class_restart hal
onrestart class_restart early_hal
- writepid /dev/cpuset/system-background/tasks
+ task_profiles ServiceCapacityLow
shutdown critical
diff --git a/cmds/servicemanager/vndservicemanager.rc b/cmds/servicemanager/vndservicemanager.rc
index 756f6c3..c9305a1 100644
--- a/cmds/servicemanager/vndservicemanager.rc
+++ b/cmds/servicemanager/vndservicemanager.rc
@@ -2,7 +2,7 @@
class core
user system
group system readproc
- writepid /dev/cpuset/system-background/tasks
+ task_profiles ServiceCapacityLow
onrestart class_restart main
onrestart class_restart hal
onrestart class_restart early_hal
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index bb1b513..2ecb895 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -153,10 +153,6 @@
export_aidl_headers: true,
},
- // TODO(b/142684679): for com.android.media which is compiled
- // as vendor and used as system code.
- use_apex_name_macro: true,
-
cflags: [
"-Wall",
"-Wextra",
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index d3eef4e..ec9d554 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -547,7 +547,6 @@
AutoMutex _l(e->mLock);
auto rpcServer = RpcServer::make();
LOG_ALWAYS_FATAL_IF(rpcServer == nullptr, "RpcServer::make returns null");
- rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
auto link = sp<RpcServerLink>::make(rpcServer, keepAliveBinder, weakThis);
if (auto status = keepAliveBinder->linkToDeath(link, nullptr, 0); status != OK) {
ALOGE("%s: keepAliveBinder->linkToDeath returns %s", __PRETTY_FUNCTION__,
diff --git a/libs/binder/OWNERS b/libs/binder/OWNERS
index 350994a..1c8bdea 100644
--- a/libs/binder/OWNERS
+++ b/libs/binder/OWNERS
@@ -1,5 +1,7 @@
+# Bug component: 32456
arve@google.com
ctate@google.com
hackbod@google.com
maco@google.com
smoreland@google.com
+tkjos@google.com
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index dee5309..181f405 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -411,8 +411,9 @@
status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len)
{
- if (parcel->isForRpc() != isForRpc()) {
- ALOGE("Cannot append Parcel of one format to another.");
+ if (mSession != parcel->mSession) {
+ ALOGE("Cannot append Parcel from one context to another. They may be different formats, "
+ "and objects are specific to a context.");
return BAD_TYPE;
}
@@ -547,21 +548,17 @@
return mHasFds;
}
-status_t Parcel::hasFileDescriptorsInRange(size_t offset, size_t len, bool& result) const {
+status_t Parcel::hasFileDescriptorsInRange(size_t offset, size_t len, bool* result) const {
if (len > INT32_MAX || offset > INT32_MAX) {
// Don't accept size_t values which may have come from an inadvertent conversion from a
// negative int.
return BAD_VALUE;
}
- size_t limit = offset + len;
- if (offset > mDataSize || len > mDataSize || limit > mDataSize || offset > limit) {
+ size_t limit;
+ if (__builtin_add_overflow(offset, len, &limit) || limit > mDataSize) {
return BAD_VALUE;
}
- result = hasFileDescriptorsInRangeUnchecked(offset, len);
- return NO_ERROR;
-}
-
-bool Parcel::hasFileDescriptorsInRangeUnchecked(size_t offset, size_t len) const {
+ *result = false;
for (size_t i = 0; i < mObjectsSize; i++) {
size_t pos = mObjects[i];
if (pos < offset) continue;
@@ -571,10 +568,11 @@
}
const flat_binder_object* flat = reinterpret_cast<const flat_binder_object*>(mData + pos);
if (flat->hdr.type == BINDER_TYPE_FD) {
- return true;
+ *result = true;
+ break;
}
}
- return false;
+ return NO_ERROR;
}
void Parcel::markSensitive() const
@@ -2567,9 +2565,9 @@
}
}
-void Parcel::scanForFds() const
-{
- mHasFds = hasFileDescriptorsInRangeUnchecked(0, dataSize());
+void Parcel::scanForFds() const {
+ status_t status = hasFileDescriptorsInRange(0, dataSize(), &mHasFds);
+ ALOGE_IF(status != NO_ERROR, "Error %d calling hasFileDescriptorsInRange()", status);
mFdsKnown = true;
}
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 94b2806..4f21cda 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -89,13 +89,21 @@
return init(nullptr, false /*requireDefault*/);
}
+[[clang::no_destroy]] static sp<ProcessState> gProcess;
+[[clang::no_destroy]] static std::mutex gProcessMutex;
+
+static void verifyNotForked(bool forked) {
+ LOG_ALWAYS_FATAL_IF(forked, "libbinder ProcessState can not be used after fork");
+}
+
sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault)
{
- [[clang::no_destroy]] static sp<ProcessState> gProcess;
- [[clang::no_destroy]] static std::mutex gProcessMutex;
if (driver == nullptr) {
std::lock_guard<std::mutex> l(gProcessMutex);
+ if (gProcess) {
+ verifyNotForked(gProcess->mForked);
+ }
return gProcess;
}
@@ -106,6 +114,14 @@
driver = "/dev/binder";
}
+ // we must install these before instantiating the gProcess object,
+ // otherwise this would race with creating it, and there could be the
+ // possibility of an invalid gProcess object forked by another thread
+ // before these are installed
+ int ret = pthread_atfork(ProcessState::onFork, ProcessState::parentPostFork,
+ ProcessState::childPostFork);
+ LOG_ALWAYS_FATAL_IF(ret != 0, "pthread_atfork error %s", strerror(ret));
+
std::lock_guard<std::mutex> l(gProcessMutex);
gProcess = sp<ProcessState>::make(driver);
});
@@ -119,6 +135,7 @@
gProcess->getDriverName().c_str(), driver);
}
+ verifyNotForked(gProcess->mForked);
return gProcess;
}
@@ -137,6 +154,24 @@
return context;
}
+void ProcessState::onFork() {
+ // make sure another thread isn't currently retrieving ProcessState
+ gProcessMutex.lock();
+}
+
+void ProcessState::parentPostFork() {
+ gProcessMutex.unlock();
+}
+
+void ProcessState::childPostFork() {
+ // another thread might call fork before gProcess is instantiated, but after
+ // the thread handler is installed
+ if (gProcess) {
+ gProcess->mForked = true;
+ }
+ gProcessMutex.unlock();
+}
+
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
@@ -426,6 +461,7 @@
mWaitingForThreads(0),
mMaxThreads(DEFAULT_MAX_BINDER_THREADS),
mStarvationStartTimeMs(0),
+ mForked(false),
mThreadPoolStarted(false),
mThreadPoolSeq(1),
mCallRestriction(CallRestriction::NONE) {
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 967b8e3..93ed50e 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -58,10 +58,6 @@
return sp<RpcServer>::make(std::move(ctx));
}
-void RpcServer::iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction() {
- mAgreedExperimental = true;
-}
-
status_t RpcServer::setupUnixDomainServer(const char* path) {
return setupSocketServer(UnixSocketAddress(path));
}
@@ -127,14 +123,23 @@
void RpcServer::setRootObject(const sp<IBinder>& binder) {
std::lock_guard<std::mutex> _l(mLock);
+ mRootObjectFactory = nullptr;
mRootObjectWeak = mRootObject = binder;
}
void RpcServer::setRootObjectWeak(const wp<IBinder>& binder) {
std::lock_guard<std::mutex> _l(mLock);
mRootObject.clear();
+ mRootObjectFactory = nullptr;
mRootObjectWeak = binder;
}
+void RpcServer::setPerSessionRootObject(
+ std::function<sp<IBinder>(const sockaddr*, socklen_t)>&& makeObject) {
+ std::lock_guard<std::mutex> _l(mLock);
+ mRootObject.clear();
+ mRootObjectWeak.clear();
+ mRootObjectFactory = std::move(makeObject);
+}
sp<IBinder> RpcServer::getRootObject() {
std::lock_guard<std::mutex> _l(mLock);
@@ -154,14 +159,12 @@
}
void RpcServer::start() {
- LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
std::lock_guard<std::mutex> _l(mLock);
LOG_ALWAYS_FATAL_IF(mJoinThread.get(), "Already started!");
mJoinThread = std::make_unique<std::thread>(&joinRpcServer, sp<RpcServer>::fromExisting(this));
}
void RpcServer::join() {
- LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
{
std::lock_guard<std::mutex> _l(mLock);
@@ -174,8 +177,14 @@
status_t status;
while ((status = mShutdownTrigger->triggerablePoll(mServer, POLLIN)) == OK) {
- unique_fd clientFd(TEMP_FAILURE_RETRY(
- accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC | SOCK_NONBLOCK)));
+ sockaddr_storage addr;
+ socklen_t addrLen = sizeof(addr);
+
+ unique_fd clientFd(
+ TEMP_FAILURE_RETRY(accept4(mServer.get(), reinterpret_cast<sockaddr*>(&addr),
+ &addrLen, SOCK_CLOEXEC | SOCK_NONBLOCK)));
+
+ LOG_ALWAYS_FATAL_IF(addrLen > static_cast<socklen_t>(sizeof(addr)), "Truncated address");
if (clientFd < 0) {
ALOGE("Could not accept4 socket: %s", strerror(errno));
@@ -187,7 +196,7 @@
std::lock_guard<std::mutex> _l(mLock);
std::thread thread =
std::thread(&RpcServer::establishConnection, sp<RpcServer>::fromExisting(this),
- std::move(clientFd));
+ std::move(clientFd), addr, addrLen);
mConnectingThreads[thread.get_id()] = std::move(thread);
}
}
@@ -257,10 +266,8 @@
return mConnectingThreads.size();
}
-void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd) {
- // TODO(b/183988761): cannot trust this simple ID
- LOG_ALWAYS_FATAL_IF(!server->mAgreedExperimental, "no!");
-
+void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd,
+ const sockaddr_storage addr, socklen_t addrLen) {
// mShutdownTrigger can only be cleared once connection threads have joined.
// It must be set before this thread is started
LOG_ALWAYS_FATAL_IF(server->mShutdownTrigger == nullptr);
@@ -383,11 +390,23 @@
session = RpcSession::make();
session->setMaxIncomingThreads(server->mMaxThreads);
if (!session->setProtocolVersion(protocolVersion)) return;
+
+ // if null, falls back to server root
+ sp<IBinder> sessionSpecificRoot;
+ if (server->mRootObjectFactory != nullptr) {
+ sessionSpecificRoot =
+ server->mRootObjectFactory(reinterpret_cast<const sockaddr*>(&addr),
+ addrLen);
+ if (sessionSpecificRoot == nullptr) {
+ ALOGE("Warning: server returned null from root object factory");
+ }
+ }
+
if (!session->setForServer(server,
sp<RpcServer::EventListener>::fromExisting(
static_cast<RpcServer::EventListener*>(
server.get())),
- sessionId)) {
+ sessionId, sessionSpecificRoot)) {
ALOGE("Failed to attach server to session");
return;
}
@@ -478,19 +497,16 @@
}
bool RpcServer::hasServer() {
- LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
std::lock_guard<std::mutex> _l(mLock);
return mServer.ok();
}
unique_fd RpcServer::releaseServer() {
- LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
std::lock_guard<std::mutex> _l(mLock);
return std::move(mServer);
}
status_t RpcServer::setupExternalServer(base::unique_fd serverFd) {
- LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
std::lock_guard<std::mutex> _l(mLock);
if (mServer.ok()) {
ALOGE("Each RpcServer can only have one server.");
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 9eef3e8..137411b 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -700,7 +700,8 @@
}
bool RpcSession::setForServer(const wp<RpcServer>& server, const wp<EventListener>& eventListener,
- const std::vector<uint8_t>& sessionId) {
+ const std::vector<uint8_t>& sessionId,
+ const sp<IBinder>& sessionSpecificRoot) {
LOG_ALWAYS_FATAL_IF(mForServer != nullptr);
LOG_ALWAYS_FATAL_IF(server == nullptr);
LOG_ALWAYS_FATAL_IF(mEventListener != nullptr);
@@ -713,6 +714,7 @@
mId = sessionId;
mForServer = server;
mEventListener = eventListener;
+ mSessionSpecificRootObject = sessionSpecificRoot;
return true;
}
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 9ba64f3..09b3d68 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -870,7 +870,9 @@
if (server) {
switch (transaction->code) {
case RPC_SPECIAL_TRANSACT_GET_ROOT: {
- replyStatus = reply.writeStrongBinder(server->getRootObject());
+ sp<IBinder> root = session->mSessionSpecificRootObject
+ ?: server->getRootObject();
+ replyStatus = reply.writeStrongBinder(root);
break;
}
default: {
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index cf30f17..d90e803 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -87,7 +87,7 @@
void restoreAllowFds(bool lastValue);
bool hasFileDescriptors() const;
- status_t hasFileDescriptorsInRange(size_t offset, size_t length, bool& result) const;
+ status_t hasFileDescriptorsInRange(size_t offset, size_t length, bool* result) const;
// Zeros data when reallocating. Other mitigations may be added
// in the future.
@@ -576,7 +576,6 @@
status_t writeRawNullableParcelable(const Parcelable*
parcelable);
- bool hasFileDescriptorsInRangeUnchecked(size_t offset, size_t length) const;
//-----------------------------------------------------------------------------
// Generic type read and write methods for Parcel:
@@ -1237,7 +1236,9 @@
*/
size_t getOpenAshmemSize() const;
- // TODO(b/202029388): Remove 'getBlobAshmemSize' once ABI can be changed.
+private:
+ // TODO(b/202029388): Remove 'getBlobAshmemSize' once no prebuilts reference
+ // this
size_t getBlobAshmemSize() const;
};
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 72c2ab7..cf8d8e4 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -94,6 +94,10 @@
private:
static sp<ProcessState> init(const char* defaultDriver, bool requireDefault);
+ static void onFork();
+ static void parentPostFork();
+ static void childPostFork();
+
friend class IPCThreadState;
friend class sp<ProcessState>;
@@ -132,6 +136,7 @@
Vector<handle_entry> mHandleToObject;
+ bool mForked;
bool mThreadPoolStarted;
volatile int32_t mThreadPoolSeq;
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index fb2cf23..a426713 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -25,10 +25,6 @@
#include <mutex>
#include <thread>
-// WARNING: This is a feature which is still in development, and it is subject
-// to radical change. Any production use of this may subject your code to any
-// number of problems.
-
namespace android {
class FdTrigger;
@@ -99,8 +95,6 @@
*/
[[nodiscard]] status_t setupExternalServer(base::unique_fd serverFd);
- void iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
-
/**
* This must be called before adding a client session.
*
@@ -130,6 +124,10 @@
* Holds a weak reference to the root object.
*/
void setRootObjectWeak(const wp<IBinder>& binder);
+ /**
+ * Allows a root object to be created for each session
+ */
+ void setPerSessionRootObject(std::function<sp<IBinder>(const sockaddr*, socklen_t)>&& object);
sp<IBinder> getRootObject();
/**
@@ -179,11 +177,11 @@
void onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) override;
void onSessionIncomingThreadEnded() override;
- static void establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd);
+ static void establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd,
+ const sockaddr_storage addr, socklen_t addrLen);
status_t setupSocketServer(const RpcSocketAddress& address);
const std::unique_ptr<RpcTransportCtx> mCtx;
- bool mAgreedExperimental = false;
size_t mMaxThreads = 1;
std::optional<uint32_t> mProtocolVersion;
base::unique_fd mServer; // socket we are accepting sessions on
@@ -194,6 +192,7 @@
std::map<std::thread::id, std::thread> mConnectingThreads;
sp<IBinder> mRootObject;
wp<IBinder> mRootObjectWeak;
+ std::function<sp<IBinder>(const sockaddr*, socklen_t)> mRootObjectFactory;
std::map<std::vector<uint8_t>, sp<RpcSession>> mSessions;
std::unique_ptr<FdTrigger> mShutdownTrigger;
std::condition_variable mShutdownCv;
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index f5505da..bd1063d 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -26,10 +26,6 @@
#include <thread>
#include <vector>
-// WARNING: This is a feature which is still in development, and it is subject
-// to radical change. Any production use of this may subject your code to any
-// number of problems.
-
namespace android {
class Parcel;
@@ -256,7 +252,8 @@
bool init);
[[nodiscard]] bool setForServer(const wp<RpcServer>& server,
const wp<RpcSession::EventListener>& eventListener,
- const std::vector<uint8_t>& sessionId);
+ const std::vector<uint8_t>& sessionId,
+ const sp<IBinder>& sessionSpecificRoot);
sp<RpcConnection> assignIncomingConnectionToThisThread(
std::unique_ptr<RpcTransport> rpcTransport);
[[nodiscard]] bool removeIncomingConnection(const sp<RpcConnection>& connection);
@@ -313,6 +310,10 @@
sp<WaitForShutdownListener> mShutdownListener; // used for client sessions
wp<EventListener> mEventListener; // mForServer if server, mShutdownListener if client
+ // session-specific root object (if a different root is used for each
+ // session)
+ sp<IBinder> mSessionSpecificRootObject;
+
std::vector<uint8_t> mId;
std::unique_ptr<FdTrigger> mShutdownTrigger;
diff --git a/libs/binder/libbinder_rpc_unstable.cpp b/libs/binder/libbinder_rpc_unstable.cpp
index cad55fb..6dfec75 100644
--- a/libs/binder/libbinder_rpc_unstable.cpp
+++ b/libs/binder/libbinder_rpc_unstable.cpp
@@ -32,7 +32,6 @@
bool RunRpcServerCallback(AIBinder* service, unsigned int port, void (*readyCallback)(void* param),
void* param) {
auto server = RpcServer::make();
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
if (status_t status = server->setupVsockServer(port); status != OK) {
LOG(ERROR) << "Failed to set up vsock server with port " << port
<< " error: " << statusToString(status).c_str();
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 49c7b7c..81aa551 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -780,3 +780,7 @@
AIBinder_incStrong(ndkBinder.get());
return ndkBinder.get();
}
+
+void AIBinder_setMinSchedulerPolicy(AIBinder* binder, int policy, int priority) {
+ binder->asABBinder()->setMinSchedulerPolicy(policy, priority);
+}
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
index 563d011..2b18a0a 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
@@ -543,6 +543,28 @@
}
/**
+ * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'.
+ */
+template <typename P>
+binder_status_t AParcel_writeNullableStdVectorParcelableElement(AParcel* parcel,
+ const void* vectorData,
+ size_t index) {
+ const std::optional<std::vector<P>>* vector =
+ static_cast<const std::optional<std::vector<P>>*>(vectorData);
+ return AParcel_writeNullableParcelable(parcel, (*vector)->at(index));
+}
+
+/**
+ * Reads a parcelable object of type P inside a std::vector<P> at index 'index' from 'parcel'.
+ */
+template <typename P>
+binder_status_t AParcel_readNullableStdVectorParcelableElement(const AParcel* parcel,
+ void* vectorData, size_t index) {
+ std::optional<std::vector<P>>* vector = static_cast<std::optional<std::vector<P>>*>(vectorData);
+ return AParcel_readNullableParcelable(parcel, &(*vector)->at(index));
+}
+
+/**
* Writes a ScopedFileDescriptor object inside a std::vector<ScopedFileDescriptor> at index 'index'
* to 'parcel'.
*/
@@ -551,11 +573,7 @@
AParcel* parcel, const void* vectorData, size_t index) {
const std::vector<ScopedFileDescriptor>* vector =
static_cast<const std::vector<ScopedFileDescriptor>*>(vectorData);
- int writeFd = vector->at(index).get();
- if (writeFd < 0) {
- return STATUS_UNEXPECTED_NULL;
- }
- return AParcel_writeParcelFileDescriptor(parcel, writeFd);
+ return AParcel_writeRequiredParcelFileDescriptor(parcel, vector->at(index));
}
/**
@@ -567,15 +585,79 @@
const AParcel* parcel, void* vectorData, size_t index) {
std::vector<ScopedFileDescriptor>* vector =
static_cast<std::vector<ScopedFileDescriptor>*>(vectorData);
- int readFd;
- binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd);
- if (status == STATUS_OK) {
- if (readFd < 0) {
- return STATUS_UNEXPECTED_NULL;
- }
- vector->at(index).set(readFd);
- }
- return status;
+ return AParcel_readRequiredParcelFileDescriptor(parcel, &vector->at(index));
+}
+
+/**
+ * Writes a ScopedFileDescriptor object inside a std::optional<std::vector<ScopedFileDescriptor>> at
+ * index 'index' to 'parcel'.
+ */
+template <>
+inline binder_status_t AParcel_writeNullableStdVectorParcelableElement<ScopedFileDescriptor>(
+ AParcel* parcel, const void* vectorData, size_t index) {
+ const std::optional<std::vector<ScopedFileDescriptor>>* vector =
+ static_cast<const std::optional<std::vector<ScopedFileDescriptor>>*>(vectorData);
+ return AParcel_writeNullableParcelFileDescriptor(parcel, (*vector)->at(index));
+}
+
+/**
+ * Reads a ScopedFileDescriptor object inside a std::optional<std::vector<ScopedFileDescriptor>> at
+ * index 'index' from 'parcel'.
+ */
+template <>
+inline binder_status_t AParcel_readNullableStdVectorParcelableElement<ScopedFileDescriptor>(
+ const AParcel* parcel, void* vectorData, size_t index) {
+ std::optional<std::vector<ScopedFileDescriptor>>* vector =
+ static_cast<std::optional<std::vector<ScopedFileDescriptor>>*>(vectorData);
+ return AParcel_readNullableParcelFileDescriptor(parcel, &(*vector)->at(index));
+}
+
+/**
+ * Writes an SpAIBinder object inside a std::vector<SpAIBinder> at index 'index'
+ * to 'parcel'.
+ */
+template <>
+inline binder_status_t AParcel_writeStdVectorParcelableElement<SpAIBinder>(AParcel* parcel,
+ const void* vectorData,
+ size_t index) {
+ const std::vector<SpAIBinder>* vector = static_cast<const std::vector<SpAIBinder>*>(vectorData);
+ return AParcel_writeRequiredStrongBinder(parcel, vector->at(index));
+}
+
+/**
+ * Reads an SpAIBinder object inside a std::vector<SpAIBinder> at index 'index'
+ * from 'parcel'.
+ */
+template <>
+inline binder_status_t AParcel_readStdVectorParcelableElement<SpAIBinder>(const AParcel* parcel,
+ void* vectorData,
+ size_t index) {
+ std::vector<SpAIBinder>* vector = static_cast<std::vector<SpAIBinder>*>(vectorData);
+ return AParcel_readRequiredStrongBinder(parcel, &vector->at(index));
+}
+
+/**
+ * Writes an SpAIBinder object inside a std::optional<std::vector<SpAIBinder>> at index 'index'
+ * to 'parcel'.
+ */
+template <>
+inline binder_status_t AParcel_writeNullableStdVectorParcelableElement<SpAIBinder>(
+ AParcel* parcel, const void* vectorData, size_t index) {
+ const std::optional<std::vector<SpAIBinder>>* vector =
+ static_cast<const std::optional<std::vector<SpAIBinder>>*>(vectorData);
+ return AParcel_writeNullableStrongBinder(parcel, (*vector)->at(index));
+}
+
+/**
+ * Reads an SpAIBinder object inside a std::optional<std::vector<SpAIBinder>> at index 'index'
+ * from 'parcel'.
+ */
+template <>
+inline binder_status_t AParcel_readNullableStdVectorParcelableElement<SpAIBinder>(
+ const AParcel* parcel, void* vectorData, size_t index) {
+ std::optional<std::vector<SpAIBinder>>* vector =
+ static_cast<std::optional<std::vector<SpAIBinder>>*>(vectorData);
+ return AParcel_readNullableStrongBinder(parcel, &(*vector)->at(index));
}
/**
@@ -598,6 +680,30 @@
AParcel_readStdVectorParcelableElement<P>);
}
+/**
+ * Convenience API for writing a std::optional<std::vector<P>>
+ */
+template <typename P>
+static inline binder_status_t AParcel_writeVector(AParcel* parcel,
+ const std::optional<std::vector<P>>& vec) {
+ if (!vec) return AParcel_writeInt32(parcel, -1);
+ const void* vectorData = static_cast<const void*>(&vec);
+ return AParcel_writeParcelableArray(parcel, vectorData, static_cast<int32_t>(vec->size()),
+ AParcel_writeNullableStdVectorParcelableElement<P>);
+}
+
+/**
+ * Convenience API for reading a std::optional<std::vector<P>>
+ */
+template <typename P>
+static inline binder_status_t AParcel_readVector(const AParcel* parcel,
+ std::optional<std::vector<P>>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readParcelableArray(parcel, vectorData,
+ AParcel_nullableStdVectorExternalAllocator<P>,
+ AParcel_readNullableStdVectorParcelableElement<P>);
+}
+
// @START
/**
* Writes a vector of int32_t to the next location in a non-null parcel.
diff --git a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
index e315c79..b0217c4 100644
--- a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
+++ b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
@@ -55,4 +55,17 @@
*/
__attribute__((weak, warn_unused_result)) const char* AIBinder_getCallingSid() __INTRODUCED_IN(31);
+/**
+ * Sets a minimum scheduler policy for all transactions coming into this
+ * AIBinder.
+ *
+ * This must be called before the object is sent to another process.
+ * Aborts on invalid values. Not thread safe.
+ *
+ * \param binder local server binder to set the policy for
+ * \param policy scheduler policy as defined in linux UAPI
+ * \param priority priority. [-20..19] for SCHED_NORMAL, [1..99] for RT
+ */
+void AIBinder_setMinSchedulerPolicy(AIBinder* binder, int policy, int priority) __INTRODUCED_IN(33);
+
__END_DECLS
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 8605686..64170af 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -145,6 +145,7 @@
global:
AIBinder_Class_disableInterfaceTokenHeader;
AIBinder_DeathRecipient_setOnUnlinked;
+ AIBinder_setMinSchedulerPolicy; # llndk
AParcel_marshal;
AParcel_unmarshal;
};
diff --git a/libs/binder/rust/src/parcel/file_descriptor.rs b/libs/binder/rust/src/parcel/file_descriptor.rs
index f71a686..8bcc5d0 100644
--- a/libs/binder/rust/src/parcel/file_descriptor.rs
+++ b/libs/binder/rust/src/parcel/file_descriptor.rs
@@ -94,8 +94,6 @@
}
}
-impl SerializeArray for Option<ParcelFileDescriptor> {}
-
impl DeserializeOption for ParcelFileDescriptor {
fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
let mut fd = -1i32;
@@ -126,8 +124,6 @@
}
}
-impl DeserializeArray for Option<ParcelFileDescriptor> {}
-
impl Deserialize for ParcelFileDescriptor {
fn deserialize(parcel: &Parcel) -> Result<Self> {
Deserialize::deserialize(parcel)
diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs
index 499ef09..ec00e1d 100644
--- a/libs/binder/rust/src/parcel/parcelable.rs
+++ b/libs/binder/rust/src/parcel/parcelable.rs
@@ -383,6 +383,9 @@
};
}
+impl<T: DeserializeOption> DeserializeArray for Option<T> {}
+impl<T: SerializeOption> SerializeArray for Option<T> {}
+
parcelable_primitives! {
impl Serialize for bool = sys::AParcel_writeBool;
impl Deserialize for bool = sys::AParcel_readBool;
@@ -537,8 +540,6 @@
}
}
-impl SerializeArray for Option<&str> {}
-
impl Serialize for str {
fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
Some(self).serialize(parcel)
@@ -561,8 +562,6 @@
}
}
-impl SerializeArray for Option<String> {}
-
impl Deserialize for Option<String> {
fn deserialize(parcel: &Parcel) -> Result<Self> {
let mut vec: Option<Vec<u8>> = None;
diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs
index a7a3fb2..a8d0c33 100644
--- a/libs/binder/rust/src/proxy.rs
+++ b/libs/binder/rust/src/proxy.rs
@@ -427,7 +427,6 @@
}
impl SerializeArray for SpIBinder {}
-impl SerializeArray for Option<&SpIBinder> {}
impl Deserialize for SpIBinder {
fn deserialize(parcel: &Parcel) -> Result<SpIBinder> {
@@ -445,7 +444,6 @@
}
impl DeserializeArray for SpIBinder {}
-impl DeserializeArray for Option<SpIBinder> {}
/// A weak reference to a Binder remote object.
///
diff --git a/libs/binder/servicedispatcher.cpp b/libs/binder/servicedispatcher.cpp
index 23e34aa..777f3c9 100644
--- a/libs/binder/servicedispatcher.cpp
+++ b/libs/binder/servicedispatcher.cpp
@@ -90,7 +90,6 @@
LOG(ERROR) << "Cannot create RpcServer";
return EX_SOFTWARE;
}
- rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
unsigned int port;
if (status_t status = rpcServer->setupInetServer(kLocalInetAddress, 0, &port); status != OK) {
LOG(ERROR) << "setupInetServer failed: " << statusToString(status);
@@ -207,7 +206,6 @@
service = ServiceManagerProxyToNative::asBinder(interface);
auto rpcServer = RpcServer::make();
- rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
rpcServer->setRootObject(service);
unsigned int port;
if (status_t status = rpcServer->setupInetServer(kLocalInetAddress, 0, &port); status != OK) {
diff --git a/libs/binder/tests/IBinderRpcTest.aidl b/libs/binder/tests/IBinderRpcTest.aidl
index 9e10788..fdd02a4 100644
--- a/libs/binder/tests/IBinderRpcTest.aidl
+++ b/libs/binder/tests/IBinderRpcTest.aidl
@@ -18,6 +18,9 @@
oneway void sendString(@utf8InCpp String str);
@utf8InCpp String doubleString(@utf8InCpp String str);
+ // get the port that a client used to connect to this object
+ int getClientPort();
+
// number of known RPC binders to process, RpcState::countBinders by session
int[] countBinders();
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 639876f..4d316f7 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -436,6 +436,11 @@
};
};
+TEST_F(BinderLibTest, CannotUseBinderAfterFork) {
+ // EXPECT_DEATH works by forking the process
+ EXPECT_DEATH({ ProcessState::self(); }, "libbinder ProcessState can not be used after fork");
+}
+
TEST_F(BinderLibTest, WasParceled) {
auto binder = sp<BBinder>::make();
EXPECT_FALSE(binder->wasParceled());
@@ -1197,7 +1202,6 @@
auto rpcServer = RpcServer::make();
EXPECT_NE(nullptr, rpcServer);
if (rpcServer == nullptr) return {};
- rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
unsigned int port;
if (status_t status = rpcServer->setupInetServer("127.0.0.1", 0, &port); status != OK) {
ADD_FAILURE() << "setupInetServer failed" << statusToString(status);
diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp
index f8718aa..52ba9b0 100644
--- a/libs/binder/tests/binderRpcBenchmark.cpp
+++ b/libs/binder/tests/binderRpcBenchmark.cpp
@@ -206,7 +206,6 @@
if (0 == fork()) {
prctl(PR_SET_PDEATHSIG, SIGHUP); // racey, okay
server->setRootObject(sp<MyBinderRpcBenchmark>::make());
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
CHECK_EQ(OK, server->setupUnixDomainServer(addr));
server->join();
exit(1);
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index d68c6ff..0cbb880 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -109,7 +109,6 @@
base::unique_fd sink(TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)));
int sinkFd = sink.get();
auto server = RpcServer::make(newFactory(GetParam()));
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
ASSERT_FALSE(server->hasServer());
ASSERT_EQ(OK, server->setupExternalServer(std::move(sink)));
ASSERT_TRUE(server->hasServer());
@@ -174,6 +173,7 @@
class MyBinderRpcTest : public BnBinderRpcTest {
public:
wp<RpcServer> server;
+ int port = 0;
Status sendString(const std::string& str) override {
(void)str;
@@ -183,6 +183,10 @@
*strstr = str + str;
return Status::ok();
}
+ Status getClientPort(int* out) override {
+ *out = port;
+ return Status::ok();
+ }
Status countBinders(std::vector<int32_t>* out) override {
sp<RpcServer> spServer = server.promote();
if (spServer == nullptr) {
@@ -538,7 +542,6 @@
auto certVerifier = std::make_shared<RpcCertificateVerifierSimple>();
sp<RpcServer> server = RpcServer::make(newFactory(rpcSecurity, certVerifier));
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
server->setMaxThreads(options.numThreads);
unsigned int outPort = 0;
@@ -643,13 +646,39 @@
BinderRpcTestProcessSession createRpcTestSocketServerProcess(const Options& options) {
BinderRpcTestProcessSession ret{
- .proc = createRpcTestSocketServerProcess(options,
- [&](const sp<RpcServer>& server) {
- sp<MyBinderRpcTest> service =
- new MyBinderRpcTest;
- server->setRootObject(service);
- service->server = server;
- }),
+ .proc = createRpcTestSocketServerProcess(
+ options,
+ [&](const sp<RpcServer>& server) {
+ server->setPerSessionRootObject([&](const sockaddr* addr,
+ socklen_t len) {
+ sp<MyBinderRpcTest> service = sp<MyBinderRpcTest>::make();
+ switch (addr->sa_family) {
+ case AF_UNIX:
+ // nothing to save
+ break;
+ case AF_VSOCK:
+ CHECK_EQ(len, sizeof(sockaddr_vm));
+ service->port = reinterpret_cast<const sockaddr_vm*>(addr)
+ ->svm_port;
+ break;
+ case AF_INET:
+ CHECK_EQ(len, sizeof(sockaddr_in));
+ service->port = reinterpret_cast<const sockaddr_in*>(addr)
+ ->sin_port;
+ break;
+ case AF_INET6:
+ CHECK_EQ(len, sizeof(sockaddr_in));
+ service->port = reinterpret_cast<const sockaddr_in6*>(addr)
+ ->sin6_port;
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Unrecognized address family %d",
+ addr->sa_family);
+ }
+ service->server = server;
+ return service;
+ });
+ }),
};
ret.rootBinder = ret.proc.sessions.at(0).root;
@@ -682,6 +711,27 @@
}
}
+TEST_P(BinderRpc, SeparateRootObject) {
+ SocketType type = std::get<0>(GetParam());
+ if (type == SocketType::PRECONNECTED || type == SocketType::UNIX) {
+ // we can't get port numbers for unix sockets
+ return;
+ }
+
+ auto proc = createRpcTestSocketServerProcess({.numSessions = 2});
+
+ int port1 = 0;
+ EXPECT_OK(proc.rootIface->getClientPort(&port1));
+
+ sp<IBinderRpcTest> rootIface2 = interface_cast<IBinderRpcTest>(proc.proc.sessions.at(1).root);
+ int port2;
+ EXPECT_OK(rootIface2->getClientPort(&port2));
+
+ // we should have a different IBinderRpcTest object created for each
+ // session, because we use setPerSessionRootObject
+ EXPECT_NE(port1, port2);
+}
+
TEST_P(BinderRpc, TransactionsMustBeMarkedRpc) {
auto proc = createRpcTestSocketServerProcess({});
Parcel data;
@@ -690,13 +740,21 @@
}
TEST_P(BinderRpc, AppendSeparateFormats) {
- auto proc = createRpcTestSocketServerProcess({});
+ auto proc1 = createRpcTestSocketServerProcess({});
+ auto proc2 = createRpcTestSocketServerProcess({});
+
+ Parcel pRaw;
Parcel p1;
- p1.markForBinder(proc.rootBinder);
+ p1.markForBinder(proc1.rootBinder);
p1.writeInt32(3);
+ EXPECT_EQ(BAD_TYPE, p1.appendFrom(&pRaw, 0, p1.dataSize()));
+ EXPECT_EQ(BAD_TYPE, pRaw.appendFrom(&p1, 0, p1.dataSize()));
+
Parcel p2;
+ p2.markForBinder(proc2.rootBinder);
+ p2.writeInt32(7);
EXPECT_EQ(BAD_TYPE, p1.appendFrom(&p2, 0, p2.dataSize()));
EXPECT_EQ(BAD_TYPE, p2.appendFrom(&p1, 0, p1.dataSize()));
@@ -1299,11 +1357,20 @@
ASSERT_EQ(beforeFds, countFds()) << (system("ls -l /proc/self/fd/"), "fd leak?");
}
+TEST_P(BinderRpc, AidlDelegatorTest) {
+ auto proc = createRpcTestSocketServerProcess({});
+ auto myDelegator = sp<IBinderRpcTestDelegator>::make(proc.rootIface);
+ ASSERT_NE(nullptr, myDelegator);
+
+ std::string doubled;
+ EXPECT_OK(myDelegator->doubleString("cool ", &doubled));
+ EXPECT_EQ("cool cool ", doubled);
+}
+
static bool testSupportVsockLoopback() {
// We don't need to enable TLS to know if vsock is supported.
unsigned int vsockPort = allocateVsockPort();
sp<RpcServer> server = RpcServer::make(RpcTransportCtxFactoryRaw::make());
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
if (status_t status = server->setupVsockServer(vsockPort); status != OK) {
if (status == -EAFNOSUPPORT) {
return false;
@@ -1392,7 +1459,6 @@
TEST_P(BinderRpcSimple, Shutdown) {
auto addr = allocateSocketAddress();
auto server = RpcServer::make(newFactory(GetParam()));
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
ASSERT_EQ(OK, server->setupUnixDomainServer(addr.c_str()));
auto joinEnds = std::make_shared<OneOffSignal>();
@@ -1432,7 +1498,6 @@
ASSERT_EQ(OK, binder->pingBinder());
auto rpcServer = RpcServer::make();
- rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
unsigned int port;
ASSERT_EQ(OK, rpcServer->setupInetServer(kLocalInetAddress, 0, &port));
auto socket = rpcServer->releaseServer();
@@ -1471,7 +1536,6 @@
std::unique_ptr<RpcAuth> auth = std::make_unique<RpcAuthSelfSigned>()) {
auto [socketType, rpcSecurity, certificateFormat] = param;
auto rpcServer = RpcServer::make(newFactory(rpcSecurity));
- rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
switch (socketType) {
case SocketType::PRECONNECTED: {
return AssertionFailure() << "Not supported by this test";
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index 55eb847..e4f57b0 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -284,7 +284,6 @@
FUZZ_LOG() << "readObject: " << obj;
},
PARCEL_READ_NO_STATUS(uid_t, readCallingWorkSourceUid),
- PARCEL_READ_NO_STATUS(size_t, getBlobAshmemSize),
PARCEL_READ_NO_STATUS(size_t, getOpenAshmemSize),
// additional parcelable objects defined in libbinder
@@ -306,7 +305,7 @@
size_t offset = p.readUint32();
size_t length = p.readUint32();
bool result;
- status_t status = p.hasFileDescriptorsInRange(offset, length, result);
+ status_t status = p.hasFileDescriptorsInRange(offset, length, &result);
FUZZ_LOG() << " status: " << status << " result: " << result;
},
};
diff --git a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
index 6b783a4..c0a762d 100644
--- a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
@@ -95,6 +95,11 @@
PARCEL_READ(std::vector<std::string>, ndk::AParcel_readVector),
PARCEL_READ(std::optional<std::vector<std::optional<std::string>>>, ndk::AParcel_readVector),
PARCEL_READ(std::vector<SomeParcelable>, ndk::AParcel_readVector),
+ PARCEL_READ(std::optional<std::vector<std::optional<SomeParcelable>>>, ndk::AParcel_readVector),
+ PARCEL_READ(std::vector<ndk::SpAIBinder>, ndk::AParcel_readVector),
+ PARCEL_READ(std::optional<std::vector<ndk::SpAIBinder>>, ndk::AParcel_readVector),
+ PARCEL_READ(std::vector<ndk::ScopedFileDescriptor>, ndk::AParcel_readVector),
+ PARCEL_READ(std::optional<std::vector<ndk::ScopedFileDescriptor>>, ndk::AParcel_readVector),
PARCEL_READ(std::vector<int32_t>, ndk::AParcel_readVector),
PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_readVector),
PARCEL_READ(std::vector<uint32_t>, ndk::AParcel_readVector),
diff --git a/libs/binder/tests/rpc_fuzzer/Android.bp b/libs/binder/tests/rpc_fuzzer/Android.bp
index c0f0a12..71e847f 100644
--- a/libs/binder/tests/rpc_fuzzer/Android.bp
+++ b/libs/binder/tests/rpc_fuzzer/Android.bp
@@ -14,6 +14,7 @@
fuzz_config: {
cc: ["smoreland@google.com"],
},
+ corpus: ["corpus/*"],
dictionary: "binder_rpc_fuzzer.dict",
srcs: [
diff --git a/libs/binder/tests/rpc_fuzzer/corpus/special_transaction b/libs/binder/tests/rpc_fuzzer/corpus/special_transaction
new file mode 100644
index 0000000..37228ee
--- /dev/null
+++ b/libs/binder/tests/rpc_fuzzer/corpus/special_transaction
Binary files differ
diff --git a/libs/binder/tests/rpc_fuzzer/main.cpp b/libs/binder/tests/rpc_fuzzer/main.cpp
index 518849a..a8713a2 100644
--- a/libs/binder/tests/rpc_fuzzer/main.cpp
+++ b/libs/binder/tests/rpc_fuzzer/main.cpp
@@ -119,7 +119,6 @@
sp<RpcServer> server = RpcServer::make(makeTransportCtxFactory(&provider));
server->setRootObject(sp<SomeBinder>::make());
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
CHECK_EQ(OK, server->setupUnixDomainServer(kSock.c_str()));
std::thread serverThread([=] { (void)server->join(); });
@@ -158,6 +157,8 @@
}
}
+ usleep(10000);
+
if (hangupBeforeShutdown) {
connections.clear();
while (!server->listSessions().empty() || server->numUninitializedSessions()) {
diff --git a/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp b/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
index 20c5569..e77c55c 100644
--- a/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
+++ b/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
@@ -44,7 +44,6 @@
auto thread = std::thread([&]() {
prctl(PR_SET_PDEATHSIG, SIGHUP); // racey, okay
server->setRootObject(sp<BBinder>::make());
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
CHECK_EQ(OK, server->setupUnixDomainServer(addr.c_str()));
server->join();
});
diff --git a/libs/permission/include/binder/AppOpsManager.h b/libs/permission/include/binder/AppOpsManager.h
index e3d705f..abcd527 100644
--- a/libs/permission/include/binder/AppOpsManager.h
+++ b/libs/permission/include/binder/AppOpsManager.h
@@ -147,7 +147,8 @@
OP_ACTIVITY_RECOGNITION_SOURCE = 113,
OP_BLUETOOTH_ADVERTISE = 114,
OP_RECORD_INCOMING_PHONE_AUDIO = 115,
- _NUM_OP = 116
+ OP_NEARBY_WIFI_DEVICES = 116,
+ _NUM_OP = 117
};
AppOpsManager();
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index ae8f238..cc627b8 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -388,7 +388,10 @@
drawBlurLayers(renderengine, display, dstTexture);
}
- // should be the same as AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
+ // The majority of skia shaders needed by RenderEngine are related to sampling images.
+ // These need to be generated with various source textures.
+ // Make a list of applicable sources.
+ // GRALLOC_USAGE_HW_TEXTURE should be the same as AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE.
const int64_t usageExternal = GRALLOC_USAGE_HW_TEXTURE;
sp<GraphicBuffer> externalBuffer =
new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888,
@@ -396,24 +399,24 @@
const auto externalTexture =
std::make_shared<ExternalTexture>(externalBuffer, *renderengine,
ExternalTexture::Usage::READABLE);
+ std::vector<const std::shared_ptr<ExternalTexture>> textures =
+ {srcTexture, externalTexture};
- // Another external texture with a different pixel format triggers useIsOpaqueWorkaround
+ // Another external texture with a different pixel format triggers useIsOpaqueWorkaround.
+ // It doesn't have to be f16, but it can't be the usual 8888.
sp<GraphicBuffer> f16ExternalBuffer =
new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_FP16,
1, usageExternal, "primeShaderCache_external_f16");
- const auto f16ExternalTexture =
+ // The F16 texture may not be usable on all devices, so check first that it was created.
+ status_t error = f16ExternalBuffer->initCheck();
+ if (!error) {
+ const auto f16ExternalTexture =
std::make_shared<ExternalTexture>(f16ExternalBuffer, *renderengine,
ExternalTexture::Usage::READABLE);
+ textures.push_back(f16ExternalTexture);
+ }
- // The majority of shaders are related to sampling images.
- // These need to be generated with various source textures
- // The F16 texture may not be usable on all devices, so check first that it was created with
- // the requested usage bit.
- auto textures = {srcTexture, externalTexture};
- auto texturesWithF16 = {srcTexture, externalTexture, f16ExternalTexture};
- bool canUsef16 = f16ExternalBuffer->getUsage() & GRALLOC_USAGE_HW_TEXTURE;
-
- for (auto texture : canUsef16 ? texturesWithF16 : textures) {
+ for (auto texture : textures) {
drawImageLayers(renderengine, display, dstTexture, texture);
// Draw layers for b/185569240.
drawClippedLayers(renderengine, display, dstTexture, texture);
diff --git a/services/vr/virtual_touchpad/virtual_touchpad.rc b/services/vr/virtual_touchpad/virtual_touchpad.rc
index 0de0f9e..1612743 100644
--- a/services/vr/virtual_touchpad/virtual_touchpad.rc
+++ b/services/vr/virtual_touchpad/virtual_touchpad.rc
@@ -2,4 +2,4 @@
class core
user system
group system input uhid
- writepid /dev/cpuset/system/tasks
+ task_profiles VrServiceCapacityNormal