Merge "Avoid UI freezing when reading battery capacity/status"
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 0f7c489..ac101ec 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -25,6 +25,7 @@
"CrateManager.cpp",
"InstalldNativeService.cpp",
"QuotaUtils.cpp",
+ "SysTrace.cpp",
"dexopt.cpp",
"execv_helper.cpp",
"globals.cpp",
@@ -173,7 +174,7 @@
// Needs to be wherever installd is as it's execed by
// installd.
- required: ["migrate_legacy_obb_data.sh"],
+ required: ["migrate_legacy_obb_data"],
}
// OTA chroot tool
@@ -299,6 +300,6 @@
// Script to migrate legacy obb data.
sh_binary {
- name: "migrate_legacy_obb_data.sh",
+ name: "migrate_legacy_obb_data",
src: "migrate_legacy_obb_data.sh",
}
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 6ee3070..2c8adc7 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -16,8 +16,6 @@
#include "InstalldNativeService.h"
-#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
-
#include <errno.h>
#include <fts.h>
#include <inttypes.h>
@@ -75,6 +73,7 @@
#include "CrateManager.h"
#include "MatchExtensionGen.h"
#include "QuotaUtils.h"
+#include "SysTrace.h"
#ifndef LOG_TAG
#define LOG_TAG "installd"
@@ -1327,7 +1326,7 @@
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
for (auto userId : get_known_users(uuid_)) {
LOCK_USER();
- ATRACE_BEGIN("fixup user");
+ atrace_pm_begin("fixup user");
FTS* fts;
FTSENT* p;
auto ce_path = create_data_user_ce_path(uuid_, userId);
@@ -1417,7 +1416,7 @@
}
}
fts_close(fts);
- ATRACE_END();
+ atrace_pm_end();
}
return ok();
}
@@ -1955,7 +1954,6 @@
return error("Failed to determine free space for " + data_path);
}
- int64_t cleared = 0;
int64_t needed = targetFreeBytes - free;
if (!defy_target) {
LOG(DEBUG) << "Device " << data_path << " has " << free << " free; requested "
@@ -1971,7 +1969,7 @@
// files from the UIDs which are most over their allocated quota
// 1. Create trackers for every known UID
- ATRACE_BEGIN("create");
+ atrace_pm_begin("create");
const auto users = get_known_users(uuid_);
#ifdef GRANULAR_LOCKS
std::vector<UserLock> userLocks;
@@ -2052,11 +2050,10 @@
}
fts_close(fts);
}
- ATRACE_END();
+ atrace_pm_end();
// 2. Populate tracker stats and insert into priority queue
- ATRACE_BEGIN("populate");
- int64_t cacheTotal = 0;
+ atrace_pm_begin("populate");
auto cmp = [](std::shared_ptr<CacheTracker> left, std::shared_ptr<CacheTracker> right) {
return (left->getCacheRatio() < right->getCacheRatio());
};
@@ -2065,13 +2062,12 @@
for (const auto& it : trackers) {
it.second->loadStats();
queue.push(it.second);
- cacheTotal += it.second->cacheUsed;
}
- ATRACE_END();
+ atrace_pm_end();
// 3. Bounce across the queue, freeing items from whichever tracker is
// the most over their assigned quota
- ATRACE_BEGIN("bounce");
+ atrace_pm_begin("bounce");
std::shared_ptr<CacheTracker> active;
while (active || !queue.empty()) {
// Only look at apps under quota when explicitly requested
@@ -2111,7 +2107,6 @@
}
active->cacheUsed -= item->size;
needed -= item->size;
- cleared += item->size;
}
if (!defy_target) {
@@ -2128,7 +2123,7 @@
}
}
}
- ATRACE_END();
+ atrace_pm_end();
} else {
return error("Legacy cache logic no longer supported");
@@ -2473,84 +2468,84 @@
flags &= ~FLAG_USE_QUOTA;
}
- ATRACE_BEGIN("obb");
+ atrace_pm_begin("obb");
for (const auto& packageName : packageNames) {
auto obbCodePath = create_data_media_package_path(uuid_, userId,
"obb", packageName.c_str());
calculate_tree_size(obbCodePath, &extStats.codeSize);
}
- ATRACE_END();
+ atrace_pm_end();
// Calculating the app size of the external storage owning app in a manual way, since
// calculating it through quota apis also includes external media storage in the app storage
// numbers
if (flags & FLAG_USE_QUOTA && appId >= AID_APP_START && !ownsExternalStorage(appId)) {
- ATRACE_BEGIN("code");
+ atrace_pm_begin("code");
for (const auto& codePath : codePaths) {
calculate_tree_size(codePath, &stats.codeSize, -1,
multiuser_get_shared_gid(0, appId));
}
- ATRACE_END();
+ atrace_pm_end();
- ATRACE_BEGIN("quota");
+ atrace_pm_begin("quota");
collectQuotaStats(uuidString, userId, appId, &stats, &extStats);
- ATRACE_END();
+ atrace_pm_end();
} else {
- ATRACE_BEGIN("code");
+ atrace_pm_begin("code");
for (const auto& codePath : codePaths) {
calculate_tree_size(codePath, &stats.codeSize);
}
- ATRACE_END();
+ atrace_pm_end();
for (size_t i = 0; i < packageNames.size(); i++) {
const char* pkgname = packageNames[i].c_str();
- ATRACE_BEGIN("data");
+ atrace_pm_begin("data");
auto cePath = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInodes[i]);
collectManualStats(cePath, &stats);
auto dePath = create_data_user_de_package_path(uuid_, userId, pkgname);
collectManualStats(dePath, &stats);
- ATRACE_END();
+ atrace_pm_end();
// In case of sdk sandbox storage (e.g. /data/misc_ce/0/sdksandbox/<package-name>),
// collect individual stats of each subdirectory (shared, storage of each sdk etc.)
if (appId >= AID_APP_START && appId <= AID_APP_END) {
- ATRACE_BEGIN("sdksandbox");
+ atrace_pm_begin("sdksandbox");
auto sdkSandboxCePath =
create_data_misc_sdk_sandbox_package_path(uuid_, true, userId, pkgname);
collectManualStatsForSubDirectories(sdkSandboxCePath, &stats);
auto sdkSandboxDePath =
create_data_misc_sdk_sandbox_package_path(uuid_, false, userId, pkgname);
collectManualStatsForSubDirectories(sdkSandboxDePath, &stats);
- ATRACE_END();
+ atrace_pm_end();
}
if (!uuid) {
- ATRACE_BEGIN("profiles");
+ atrace_pm_begin("profiles");
calculate_tree_size(
create_primary_current_profile_package_dir_path(userId, pkgname),
&stats.dataSize);
calculate_tree_size(
create_primary_reference_profile_package_dir_path(pkgname),
&stats.codeSize);
- ATRACE_END();
+ atrace_pm_end();
}
- ATRACE_BEGIN("external");
+ atrace_pm_begin("external");
auto extPath = create_data_media_package_path(uuid_, userId, "data", pkgname);
collectManualStats(extPath, &extStats);
auto mediaPath = create_data_media_package_path(uuid_, userId, "media", pkgname);
calculate_tree_size(mediaPath, &extStats.dataSize);
- ATRACE_END();
+ atrace_pm_end();
}
if (!uuid) {
- ATRACE_BEGIN("dalvik");
+ atrace_pm_begin("dalvik");
int32_t sharedGid = multiuser_get_shared_gid(0, appId);
if (sharedGid != -1) {
calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
sharedGid, -1);
}
- ATRACE_END();
+ atrace_pm_end();
}
}
@@ -2696,41 +2691,41 @@
}
if (flags & FLAG_USE_QUOTA) {
- ATRACE_BEGIN("code");
+ atrace_pm_begin("code");
calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize, -1, -1, true);
- ATRACE_END();
+ atrace_pm_end();
- ATRACE_BEGIN("data");
+ atrace_pm_begin("data");
auto cePath = create_data_user_ce_path(uuid_, userId);
collectManualStatsForUser(cePath, &stats, true);
auto dePath = create_data_user_de_path(uuid_, userId);
collectManualStatsForUser(dePath, &stats, true);
- ATRACE_END();
+ atrace_pm_end();
if (!uuid) {
- ATRACE_BEGIN("profile");
+ atrace_pm_begin("profile");
auto userProfilePath = create_primary_cur_profile_dir_path(userId);
calculate_tree_size(userProfilePath, &stats.dataSize, -1, -1, true);
auto refProfilePath = create_primary_ref_profile_dir_path();
calculate_tree_size(refProfilePath, &stats.codeSize, -1, -1, true);
- ATRACE_END();
+ atrace_pm_end();
}
- ATRACE_BEGIN("external");
+ atrace_pm_begin("external");
auto sizes = getExternalSizesForUserWithQuota(uuidString, userId, appIds);
extStats.dataSize += sizes.totalSize;
extStats.codeSize += sizes.obbSize;
- ATRACE_END();
+ atrace_pm_end();
if (!uuid) {
- ATRACE_BEGIN("dalvik");
+ atrace_pm_begin("dalvik");
calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
-1, -1, true);
calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize,
-1, -1, true);
- ATRACE_END();
+ atrace_pm_end();
}
- ATRACE_BEGIN("quota");
+ atrace_pm_begin("quota");
int64_t dataSize = extStats.dataSize;
for (auto appId : appIds) {
if (appId >= AID_APP_START) {
@@ -2742,54 +2737,54 @@
}
}
extStats.dataSize = dataSize;
- ATRACE_END();
+ atrace_pm_end();
} else {
- ATRACE_BEGIN("obb");
+ atrace_pm_begin("obb");
auto obbPath = create_data_path(uuid_) + "/media/obb";
calculate_tree_size(obbPath, &extStats.codeSize);
- ATRACE_END();
+ atrace_pm_end();
- ATRACE_BEGIN("code");
+ atrace_pm_begin("code");
calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize);
- ATRACE_END();
+ atrace_pm_end();
- ATRACE_BEGIN("data");
+ atrace_pm_begin("data");
auto cePath = create_data_user_ce_path(uuid_, userId);
collectManualStatsForUser(cePath, &stats);
auto dePath = create_data_user_de_path(uuid_, userId);
collectManualStatsForUser(dePath, &stats);
- ATRACE_END();
+ atrace_pm_end();
- ATRACE_BEGIN("sdksandbox");
+ atrace_pm_begin("sdksandbox");
auto sdkSandboxCePath = create_data_misc_sdk_sandbox_path(uuid_, true, userId);
collectManualStatsForUser(sdkSandboxCePath, &stats, false, true);
auto sdkSandboxDePath = create_data_misc_sdk_sandbox_path(uuid_, false, userId);
collectManualStatsForUser(sdkSandboxDePath, &stats, false, true);
- ATRACE_END();
+ atrace_pm_end();
if (!uuid) {
- ATRACE_BEGIN("profile");
+ atrace_pm_begin("profile");
auto userProfilePath = create_primary_cur_profile_dir_path(userId);
calculate_tree_size(userProfilePath, &stats.dataSize);
auto refProfilePath = create_primary_ref_profile_dir_path();
calculate_tree_size(refProfilePath, &stats.codeSize);
- ATRACE_END();
+ atrace_pm_end();
}
- ATRACE_BEGIN("external");
+ atrace_pm_begin("external");
auto dataMediaPath = create_data_media_path(uuid_, userId);
collectManualExternalStatsForUser(dataMediaPath, &extStats);
#if MEASURE_DEBUG
LOG(DEBUG) << "Measured external data " << extStats.dataSize << " cache "
<< extStats.cacheSize;
#endif
- ATRACE_END();
+ atrace_pm_end();
if (!uuid) {
- ATRACE_BEGIN("dalvik");
+ atrace_pm_begin("dalvik");
calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize);
calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize);
- ATRACE_END();
+ atrace_pm_end();
}
}
@@ -2837,16 +2832,16 @@
}
if (flags & FLAG_USE_QUOTA) {
- ATRACE_BEGIN("quota");
+ atrace_pm_begin("quota");
auto sizes = getExternalSizesForUserWithQuota(uuidString, userId, appIds);
totalSize = sizes.totalSize;
audioSize = sizes.audioSize;
videoSize = sizes.videoSize;
imageSize = sizes.imageSize;
obbSize = sizes.obbSize;
- ATRACE_END();
+ atrace_pm_end();
- ATRACE_BEGIN("apps");
+ atrace_pm_begin("apps");
struct stats extStats;
memset(&extStats, 0, sizeof(extStats));
for (auto appId : appIds) {
@@ -2855,9 +2850,9 @@
}
}
appSize = extStats.dataSize;
- ATRACE_END();
+ atrace_pm_end();
} else {
- ATRACE_BEGIN("manual");
+ atrace_pm_begin("manual");
FTS *fts;
FTSENT *p;
auto path = create_data_media_path(uuid_, userId);
@@ -2900,16 +2895,16 @@
}
}
fts_close(fts);
- ATRACE_END();
+ atrace_pm_end();
- ATRACE_BEGIN("obb");
+ atrace_pm_begin("obb");
auto obbPath = StringPrintf("%s/Android/obb",
create_data_media_path(uuid_, userId).c_str());
calculate_tree_size(obbPath, &obbSize);
if (!(flags & FLAG_USE_QUOTA)) {
totalSize -= obbSize;
}
- ATRACE_END();
+ atrace_pm_end();
}
std::vector<int64_t> ret;
@@ -3713,7 +3708,7 @@
ENFORCE_UID(AID_SYSTEM);
// NOTE: The lint warning doesn't apply to the use of system(3) with
// absolute parse and no command line arguments.
- if (system("/system/bin/migrate_legacy_obb_data.sh") != 0) { // NOLINT(cert-env33-c)
+ if (system("/system/bin/migrate_legacy_obb_data") != 0) { // NOLINT(cert-env33-c)
LOG(ERROR) << "Unable to migrate legacy obb data";
}
diff --git a/cmds/installd/SysTrace.cpp b/cmds/installd/SysTrace.cpp
new file mode 100644
index 0000000..fa65c77
--- /dev/null
+++ b/cmds/installd/SysTrace.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
+
+#include "SysTrace.h"
+#include <utils/Trace.h>
+
+namespace android::installd {
+void atrace_pm_begin(const char* name) {
+ ATRACE_BEGIN(name);
+}
+
+void atrace_pm_end() {
+ ATRACE_END();
+}
+} /* namespace android::installd */
diff --git a/cmds/installd/SysTrace.h b/cmds/installd/SysTrace.h
new file mode 100644
index 0000000..18506a9
--- /dev/null
+++ b/cmds/installd/SysTrace.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+namespace android::installd {
+void atrace_pm_begin(const char*);
+void atrace_pm_end();
+} /* namespace android::installd */
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 4d9b710..ffc082d 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -523,7 +523,6 @@
*/
bool is_valid_package_name(const std::string& packageName) {
// This logic is borrowed from PackageParser.java
- bool hasSep = false;
bool front = true;
auto it = packageName.begin();
@@ -539,7 +538,6 @@
}
}
if (c == '.') {
- hasSep = true;
front = true;
continue;
}
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 5dca468..4ff629d 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -89,6 +89,7 @@
"Stability.cpp",
"Status.cpp",
"TextOutput.cpp",
+ "Trace.cpp",
"Utils.cpp",
],
diff --git a/libs/binder/FdTrigger.cpp b/libs/binder/FdTrigger.cpp
index d123fd1..8ee6cb0 100644
--- a/libs/binder/FdTrigger.cpp
+++ b/libs/binder/FdTrigger.cpp
@@ -22,6 +22,7 @@
#include <poll.h>
#include <android-base/macros.h>
+#include <android-base/scopeguard.h>
#include "RpcState.h"
namespace android {
@@ -53,25 +54,34 @@
#endif
}
-status_t FdTrigger::triggerablePoll(base::borrowed_fd fd, int16_t event) {
+status_t FdTrigger::triggerablePoll(const android::RpcTransportFd& transportFd, int16_t event) {
#ifdef BINDER_RPC_SINGLE_THREADED
if (mTriggered) {
return DEAD_OBJECT;
}
#endif
- LOG_ALWAYS_FATAL_IF(event == 0, "triggerablePoll %d with event 0 is not allowed", fd.get());
+ LOG_ALWAYS_FATAL_IF(event == 0, "triggerablePoll %d with event 0 is not allowed",
+ transportFd.fd.get());
pollfd pfd[]{
- {.fd = fd.get(), .events = static_cast<int16_t>(event), .revents = 0},
+ {.fd = transportFd.fd.get(), .events = static_cast<int16_t>(event), .revents = 0},
#ifndef BINDER_RPC_SINGLE_THREADED
{.fd = mRead.get(), .events = 0, .revents = 0},
#endif
};
+
+ LOG_ALWAYS_FATAL_IF(transportFd.isInPollingState() == true,
+ "Only one thread should be polling on Fd!");
+
+ transportFd.setPollingState(true);
+ auto pollingStateGuard =
+ android::base::make_scope_guard([&]() { transportFd.setPollingState(false); });
+
int ret = TEMP_FAILURE_RETRY(poll(pfd, arraysize(pfd), -1));
if (ret < 0) {
return -errno;
}
- LOG_ALWAYS_FATAL_IF(ret == 0, "poll(%d) returns 0 with infinite timeout", fd.get());
+ LOG_ALWAYS_FATAL_IF(ret == 0, "poll(%d) returns 0 with infinite timeout", transportFd.fd.get());
// At least one FD has events. Check them.
diff --git a/libs/binder/FdTrigger.h b/libs/binder/FdTrigger.h
index a25dc11..5fbf290 100644
--- a/libs/binder/FdTrigger.h
+++ b/libs/binder/FdTrigger.h
@@ -21,6 +21,8 @@
#include <android-base/unique_fd.h>
#include <utils/Errors.h>
+#include <binder/RpcTransport.h>
+
namespace android {
/** This is not a pipe. */
@@ -53,7 +55,8 @@
* true - time to read!
* false - trigger happened
*/
- [[nodiscard]] status_t triggerablePoll(base::borrowed_fd fd, int16_t event);
+ [[nodiscard]] status_t triggerablePoll(const android::RpcTransportFd& transportFd,
+ int16_t event);
private:
#ifdef BINDER_RPC_SINGLE_THREADED
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 2efd113..e581d0b 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -86,7 +86,7 @@
LOG_ALWAYS_FATAL_IF(socketAddress.addr()->sa_family != AF_INET, "expecting inet");
sockaddr_in addr{};
socklen_t len = sizeof(addr);
- if (0 != getsockname(mServer.get(), reinterpret_cast<sockaddr*>(&addr), &len)) {
+ if (0 != getsockname(mServer.fd.get(), reinterpret_cast<sockaddr*>(&addr), &len)) {
int savedErrno = errno;
ALOGE("Could not getsockname at %s: %s", socketAddress.toString().c_str(),
strerror(savedErrno));
@@ -181,7 +181,7 @@
{
RpcMutexLockGuard _l(mLock);
- LOG_ALWAYS_FATAL_IF(!mServer.ok(), "RpcServer must be setup to join.");
+ LOG_ALWAYS_FATAL_IF(!mServer.fd.ok(), "RpcServer must be setup to join.");
LOG_ALWAYS_FATAL_IF(mShutdownTrigger != nullptr, "Already joined");
mJoinThreadRunning = true;
mShutdownTrigger = FdTrigger::make();
@@ -194,24 +194,24 @@
static_assert(addr.size() >= sizeof(sockaddr_storage), "kRpcAddressSize is too small");
socklen_t addrLen = addr.size();
- unique_fd clientFd(
- TEMP_FAILURE_RETRY(accept4(mServer.get(), reinterpret_cast<sockaddr*>(addr.data()),
- &addrLen, SOCK_CLOEXEC | SOCK_NONBLOCK)));
+ RpcTransportFd clientSocket(unique_fd(TEMP_FAILURE_RETRY(
+ accept4(mServer.fd.get(), reinterpret_cast<sockaddr*>(addr.data()), &addrLen,
+ SOCK_CLOEXEC | SOCK_NONBLOCK))));
LOG_ALWAYS_FATAL_IF(addrLen > static_cast<socklen_t>(sizeof(sockaddr_storage)),
"Truncated address");
- if (clientFd < 0) {
+ if (clientSocket.fd < 0) {
ALOGE("Could not accept4 socket: %s", strerror(errno));
continue;
}
- LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get());
+ LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.fd.get(), clientSocket.fd.get());
{
RpcMutexLockGuard _l(mLock);
RpcMaybeThread thread =
RpcMaybeThread(&RpcServer::establishConnection,
- sp<RpcServer>::fromExisting(this), std::move(clientFd), addr,
+ sp<RpcServer>::fromExisting(this), std::move(clientSocket), addr,
addrLen, RpcSession::join);
auto& threadRef = mConnectingThreads[thread.get_id()];
@@ -296,7 +296,7 @@
}
void RpcServer::establishConnection(
- sp<RpcServer>&& server, base::unique_fd clientFd, std::array<uint8_t, kRpcAddressSize> addr,
+ sp<RpcServer>&& server, RpcTransportFd clientFd, std::array<uint8_t, kRpcAddressSize> addr,
size_t addrLen,
std::function<void(sp<RpcSession>&&, RpcSession::PreJoinSetupResult&&)>&& joinFn) {
// mShutdownTrigger can only be cleared once connection threads have joined.
@@ -306,7 +306,7 @@
status_t status = OK;
- int clientFdForLog = clientFd.get();
+ int clientFdForLog = clientFd.fd.get();
auto client = server->mCtx->newTransport(std::move(clientFd), server->mShutdownTrigger.get());
if (client == nullptr) {
ALOGE("Dropping accept4()-ed socket because sslAccept fails");
@@ -488,15 +488,15 @@
LOG_RPC_DETAIL("Setting up socket server %s", addr.toString().c_str());
LOG_ALWAYS_FATAL_IF(hasServer(), "Each RpcServer can only have one server.");
- unique_fd serverFd(TEMP_FAILURE_RETRY(
- socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)));
- if (serverFd == -1) {
+ RpcTransportFd transportFd(unique_fd(TEMP_FAILURE_RETRY(
+ socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0))));
+ if (!transportFd.fd.ok()) {
int savedErrno = errno;
ALOGE("Could not create socket: %s", strerror(savedErrno));
return -savedErrno;
}
- if (0 != TEMP_FAILURE_RETRY(bind(serverFd.get(), addr.addr(), addr.addrSize()))) {
+ if (0 != TEMP_FAILURE_RETRY(bind(transportFd.fd.get(), addr.addr(), addr.addrSize()))) {
int savedErrno = errno;
ALOGE("Could not bind socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
return -savedErrno;
@@ -506,7 +506,7 @@
// the backlog is increased to a large number.
// TODO(b/189955605): Once we create threads dynamically & lazily, the backlog can be reduced
// to 1.
- if (0 != TEMP_FAILURE_RETRY(listen(serverFd.get(), 50 /*backlog*/))) {
+ if (0 != TEMP_FAILURE_RETRY(listen(transportFd.fd.get(), 50 /*backlog*/))) {
int savedErrno = errno;
ALOGE("Could not listen socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
return -savedErrno;
@@ -514,7 +514,7 @@
LOG_RPC_DETAIL("Successfully setup socket server %s", addr.toString().c_str());
- if (status_t status = setupExternalServer(std::move(serverFd)); status != OK) {
+ if (status_t status = setupExternalServer(std::move(transportFd.fd)); status != OK) {
ALOGE("Another thread has set up server while calling setupSocketServer. Race?");
return status;
}
@@ -542,17 +542,17 @@
bool RpcServer::hasServer() {
RpcMutexLockGuard _l(mLock);
- return mServer.ok();
+ return mServer.fd.ok();
}
unique_fd RpcServer::releaseServer() {
RpcMutexLockGuard _l(mLock);
- return std::move(mServer);
+ return std::move(mServer.fd);
}
status_t RpcServer::setupExternalServer(base::unique_fd serverFd) {
RpcMutexLockGuard _l(mLock);
- if (mServer.ok()) {
+ if (mServer.fd.ok()) {
ALOGE("Each RpcServer can only have one server.");
return INVALID_OPERATION;
}
@@ -560,4 +560,14 @@
return OK;
}
+bool RpcServer::hasActiveRequests() {
+ RpcMutexLockGuard _l(mLock);
+ for (const auto& [_, session] : mSessions) {
+ if (session->hasActiveRequests()) {
+ return true;
+ }
+ }
+ return !mServer.isInPollingState();
+}
+
} // namespace android
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index eee28d6..49843e5 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -162,7 +162,8 @@
return NAME_NOT_FOUND;
}
-status_t RpcSession::setupPreconnectedClient(unique_fd fd, std::function<unique_fd()>&& request) {
+status_t RpcSession::setupPreconnectedClient(base::unique_fd fd,
+ std::function<unique_fd()>&& request) {
return setupClient([&](const std::vector<uint8_t>& sessionId, bool incoming) -> status_t {
if (!fd.ok()) {
fd = request();
@@ -172,7 +173,9 @@
ALOGE("setupPreconnectedClient: %s", res.error().message().c_str());
return res.error().code() == 0 ? UNKNOWN_ERROR : -res.error().code();
}
- status_t status = initAndAddConnection(std::move(fd), sessionId, incoming);
+
+ RpcTransportFd transportFd(std::move(fd));
+ status_t status = initAndAddConnection(std::move(transportFd), sessionId, incoming);
fd = unique_fd(); // Explicitly reset after move to avoid analyzer warning.
return status;
});
@@ -190,7 +193,8 @@
return -savedErrno;
}
- auto server = mCtx->newTransport(std::move(serverFd), mShutdownTrigger.get());
+ RpcTransportFd transportFd(std::move(serverFd));
+ auto server = mCtx->newTransport(std::move(transportFd), mShutdownTrigger.get());
if (server == nullptr) {
ALOGE("Unable to set up RpcTransport");
return UNKNOWN_ERROR;
@@ -572,12 +576,14 @@
return -savedErrno;
}
- if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) {
+ RpcTransportFd transportFd(std::move(serverFd));
+
+ if (0 != TEMP_FAILURE_RETRY(connect(transportFd.fd.get(), addr.addr(), addr.addrSize()))) {
int connErrno = errno;
if (connErrno == EAGAIN || connErrno == EINPROGRESS) {
// For non-blocking sockets, connect() may return EAGAIN (for unix domain socket) or
// EINPROGRESS (for others). Call poll() and getsockopt() to get the error.
- status_t pollStatus = mShutdownTrigger->triggerablePoll(serverFd, POLLOUT);
+ status_t pollStatus = mShutdownTrigger->triggerablePoll(transportFd, POLLOUT);
if (pollStatus != OK) {
ALOGE("Could not POLLOUT after connect() on non-blocking socket: %s",
statusToString(pollStatus).c_str());
@@ -585,8 +591,8 @@
}
// Set connErrno to the errno that connect() would have set if the fd were blocking.
socklen_t connErrnoLen = sizeof(connErrno);
- int ret =
- getsockopt(serverFd.get(), SOL_SOCKET, SO_ERROR, &connErrno, &connErrnoLen);
+ int ret = getsockopt(transportFd.fd.get(), SOL_SOCKET, SO_ERROR, &connErrno,
+ &connErrnoLen);
if (ret == -1) {
int savedErrno = errno;
ALOGE("Could not getsockopt() after connect() on non-blocking socket: %s. "
@@ -608,16 +614,17 @@
return -connErrno;
}
}
- LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());
+ LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(),
+ transportFd.fd.get());
- return initAndAddConnection(std::move(serverFd), sessionId, incoming);
+ return initAndAddConnection(std::move(transportFd), sessionId, incoming);
}
ALOGE("Ran out of retries to connect to %s", addr.toString().c_str());
return UNKNOWN_ERROR;
}
-status_t RpcSession::initAndAddConnection(unique_fd fd, const std::vector<uint8_t>& sessionId,
+status_t RpcSession::initAndAddConnection(RpcTransportFd fd, const std::vector<uint8_t>& sessionId,
bool incoming) {
LOG_ALWAYS_FATAL_IF(mShutdownTrigger == nullptr);
auto server = mCtx->newTransport(std::move(fd), mShutdownTrigger.get());
@@ -945,4 +952,24 @@
}
}
+bool RpcSession::hasActiveConnection(const std::vector<sp<RpcConnection>>& connections) {
+ for (const auto& connection : connections) {
+ if (connection->exclusiveTid != std::nullopt && !connection->rpcTransport->isWaiting()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool RpcSession::hasActiveRequests() {
+ RpcMutexUniqueLock _l(mMutex);
+ if (hasActiveConnection(mConnections.mIncoming)) {
+ return true;
+ }
+ if (hasActiveConnection(mConnections.mOutgoing)) {
+ return true;
+ }
+ return mConnections.mWaitingThreads != 0;
+}
+
} // namespace android
diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp
index 51326f6..65e8fac 100644
--- a/libs/binder/RpcTransportRaw.cpp
+++ b/libs/binder/RpcTransportRaw.cpp
@@ -36,11 +36,11 @@
// RpcTransport with TLS disabled.
class RpcTransportRaw : public RpcTransport {
public:
- explicit RpcTransportRaw(android::base::unique_fd socket) : mSocket(std::move(socket)) {}
+ explicit RpcTransportRaw(android::RpcTransportFd socket) : mSocket(std::move(socket)) {}
status_t pollRead(void) override {
uint8_t buf;
ssize_t ret = TEMP_FAILURE_RETRY(
- ::recv(mSocket.get(), &buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT));
+ ::recv(mSocket.fd.get(), &buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT));
if (ret < 0) {
int savedErrno = errno;
if (savedErrno == EAGAIN || savedErrno == EWOULDBLOCK) {
@@ -100,7 +100,7 @@
msg.msg_controllen = CMSG_SPACE(fdsByteSize);
ssize_t processedSize = TEMP_FAILURE_RETRY(
- sendmsg(mSocket.get(), &msg, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC));
+ sendmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC));
if (processedSize > 0) {
sentFds = true;
}
@@ -113,10 +113,10 @@
// non-negative int and can be cast to either.
.msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
};
- return TEMP_FAILURE_RETRY(sendmsg(mSocket.get(), &msg, MSG_NOSIGNAL));
+ return TEMP_FAILURE_RETRY(sendmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL));
};
- return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, send, "sendmsg",
- POLLOUT, altPoll);
+ return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, send, "sendmsg", POLLOUT,
+ altPoll);
}
status_t interruptableReadFully(
@@ -135,7 +135,7 @@
.msg_controllen = sizeof(msgControlBuf),
};
ssize_t processSize =
- TEMP_FAILURE_RETRY(recvmsg(mSocket.get(), &msg, MSG_NOSIGNAL));
+ TEMP_FAILURE_RETRY(recvmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL));
if (processSize < 0) {
return -1;
}
@@ -171,21 +171,23 @@
// non-negative int and can be cast to either.
.msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
};
- return TEMP_FAILURE_RETRY(recvmsg(mSocket.get(), &msg, MSG_NOSIGNAL));
+ return TEMP_FAILURE_RETRY(recvmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL));
};
- return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, recv, "recvmsg",
- POLLIN, altPoll);
+ return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, recv, "recvmsg", POLLIN,
+ altPoll);
}
+ virtual bool isWaiting() { return mSocket.isInPollingState(); }
+
private:
- base::unique_fd mSocket;
+ android::RpcTransportFd mSocket;
};
// RpcTransportCtx with TLS disabled.
class RpcTransportCtxRaw : public RpcTransportCtx {
public:
- std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd, FdTrigger*) const {
- return std::make_unique<RpcTransportRaw>(std::move(fd));
+ std::unique_ptr<RpcTransport> newTransport(android::RpcTransportFd socket, FdTrigger*) const {
+ return std::make_unique<RpcTransportRaw>(std::move(socket));
}
std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; }
};
diff --git a/libs/binder/RpcTransportTipcAndroid.cpp b/libs/binder/RpcTransportTipcAndroid.cpp
index c82201b..453279c 100644
--- a/libs/binder/RpcTransportTipcAndroid.cpp
+++ b/libs/binder/RpcTransportTipcAndroid.cpp
@@ -36,8 +36,7 @@
// RpcTransport for writing Trusty IPC clients in Android.
class RpcTransportTipcAndroid : public RpcTransport {
public:
- explicit RpcTransportTipcAndroid(android::base::unique_fd socket)
- : mSocket(std::move(socket)) {}
+ explicit RpcTransportTipcAndroid(android::RpcTransportFd socket) : mSocket(std::move(socket)) {}
status_t pollRead() override {
if (mReadBufferPos < mReadBufferSize) {
@@ -46,7 +45,7 @@
}
// Trusty IPC device is not a socket, so MSG_PEEK is not available
- pollfd pfd{.fd = mSocket.get(), .events = static_cast<int16_t>(POLLIN), .revents = 0};
+ pollfd pfd{.fd = mSocket.fd.get(), .events = static_cast<int16_t>(POLLIN), .revents = 0};
ssize_t ret = TEMP_FAILURE_RETRY(::poll(&pfd, 1, 0));
if (ret < 0) {
int savedErrno = errno;
@@ -84,9 +83,9 @@
// to send any.
LOG_ALWAYS_FATAL_IF(ancillaryFds != nullptr && !ancillaryFds->empty(),
"File descriptors are not supported on Trusty yet");
- return TEMP_FAILURE_RETRY(tipc_send(mSocket.get(), iovs, niovs, nullptr, 0));
+ return TEMP_FAILURE_RETRY(tipc_send(mSocket.fd.get(), iovs, niovs, nullptr, 0));
};
- return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, writeFn, "tipc_send",
+ return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, writeFn, "tipc_send",
POLLOUT, altPoll);
}
@@ -120,10 +119,12 @@
return processSize;
};
- return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, readFn, "read",
- POLLIN, altPoll);
+ return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, readFn, "read", POLLIN,
+ altPoll);
}
+ bool isWaiting() override { return mSocket.isInPollingState(); }
+
private:
status_t fillReadBuffer() {
if (mReadBufferPos < mReadBufferSize) {
@@ -146,8 +147,8 @@
mReadBufferSize = 0;
while (true) {
- ssize_t processSize =
- TEMP_FAILURE_RETRY(read(mSocket.get(), mReadBuffer.get(), mReadBufferCapacity));
+ ssize_t processSize = TEMP_FAILURE_RETRY(
+ read(mSocket.fd.get(), mReadBuffer.get(), mReadBufferCapacity));
if (processSize == 0) {
return DEAD_OBJECT;
} else if (processSize < 0) {
@@ -173,7 +174,7 @@
}
}
- base::unique_fd mSocket;
+ RpcTransportFd mSocket;
// For now, we copy all the input data into a temporary buffer because
// we might get multiple interruptableReadFully calls per message, but
@@ -192,7 +193,7 @@
// RpcTransportCtx for Trusty.
class RpcTransportCtxTipcAndroid : public RpcTransportCtx {
public:
- std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd,
+ std::unique_ptr<RpcTransport> newTransport(android::RpcTransportFd fd,
FdTrigger*) const override {
return std::make_unique<RpcTransportTipcAndroid>(std::move(fd));
}
diff --git a/libs/binder/RpcTransportTls.cpp b/libs/binder/RpcTransportTls.cpp
index 09b5c17..3e98ecc 100644
--- a/libs/binder/RpcTransportTls.cpp
+++ b/libs/binder/RpcTransportTls.cpp
@@ -182,8 +182,8 @@
// If |sslError| is WANT_READ / WANT_WRITE, poll for POLLIN / POLLOUT respectively. Otherwise
// return error. Also return error if |fdTrigger| is triggered before or during poll().
status_t pollForSslError(
- android::base::borrowed_fd fd, int sslError, FdTrigger* fdTrigger, const char* fnString,
- int additionalEvent,
+ const android::RpcTransportFd& fd, int sslError, FdTrigger* fdTrigger,
+ const char* fnString, int additionalEvent,
const std::optional<android::base::function_ref<status_t()>>& altPoll) {
switch (sslError) {
case SSL_ERROR_WANT_READ:
@@ -198,7 +198,7 @@
private:
bool mHandled = false;
- status_t handlePoll(int event, android::base::borrowed_fd fd, FdTrigger* fdTrigger,
+ status_t handlePoll(int event, const android::RpcTransportFd& fd, FdTrigger* fdTrigger,
const char* fnString,
const std::optional<android::base::function_ref<status_t()>>& altPoll) {
status_t ret;
@@ -277,7 +277,7 @@
class RpcTransportTls : public RpcTransport {
public:
- RpcTransportTls(android::base::unique_fd socket, Ssl ssl)
+ RpcTransportTls(RpcTransportFd socket, Ssl ssl)
: mSocket(std::move(socket)), mSsl(std::move(ssl)) {}
status_t pollRead(void) override;
status_t interruptableWriteFully(
@@ -290,8 +290,10 @@
const std::optional<android::base::function_ref<status_t()>>& altPoll,
std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override;
+ bool isWaiting() { return mSocket.isInPollingState(); };
+
private:
- android::base::unique_fd mSocket;
+ android::RpcTransportFd mSocket;
Ssl mSsl;
};
@@ -350,7 +352,7 @@
int sslError = mSsl.getError(writeSize);
// TODO(b/195788248): BIO should contain the FdTrigger, and send(2) / recv(2) should be
// triggerablePoll()-ed. Then additionalEvent is no longer necessary.
- status_t pollStatus = errorQueue.pollForSslError(mSocket.get(), sslError, fdTrigger,
+ status_t pollStatus = errorQueue.pollForSslError(mSocket, sslError, fdTrigger,
"SSL_write", POLLIN, altPoll);
if (pollStatus != OK) return pollStatus;
// Do not advance buffer. Try SSL_write() again.
@@ -398,7 +400,7 @@
return DEAD_OBJECT;
}
int sslError = mSsl.getError(readSize);
- status_t pollStatus = errorQueue.pollForSslError(mSocket.get(), sslError, fdTrigger,
+ status_t pollStatus = errorQueue.pollForSslError(mSocket, sslError, fdTrigger,
"SSL_read", 0, altPoll);
if (pollStatus != OK) return pollStatus;
// Do not advance buffer. Try SSL_read() again.
@@ -409,8 +411,8 @@
}
// For |ssl|, set internal FD to |fd|, and do handshake. Handshake is triggerable by |fdTrigger|.
-bool setFdAndDoHandshake(Ssl* ssl, android::base::borrowed_fd fd, FdTrigger* fdTrigger) {
- bssl::UniquePtr<BIO> bio = newSocketBio(fd);
+bool setFdAndDoHandshake(Ssl* ssl, const android::RpcTransportFd& socket, FdTrigger* fdTrigger) {
+ bssl::UniquePtr<BIO> bio = newSocketBio(socket.fd);
TEST_AND_RETURN(false, bio != nullptr);
auto [_, errorQueue] = ssl->call(SSL_set_bio, bio.get(), bio.get());
(void)bio.release(); // SSL_set_bio takes ownership.
@@ -430,7 +432,7 @@
return false;
}
int sslError = ssl->getError(ret);
- status_t pollStatus = errorQueue.pollForSslError(fd, sslError, fdTrigger,
+ status_t pollStatus = errorQueue.pollForSslError(socket, sslError, fdTrigger,
"SSL_do_handshake", 0, std::nullopt);
if (pollStatus != OK) return false;
}
@@ -442,7 +444,7 @@
typename = std::enable_if_t<std::is_base_of_v<RpcTransportCtxTls, Impl>>>
static std::unique_ptr<RpcTransportCtxTls> create(
std::shared_ptr<RpcCertificateVerifier> verifier, RpcAuth* auth);
- std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd,
+ std::unique_ptr<RpcTransport> newTransport(RpcTransportFd fd,
FdTrigger* fdTrigger) const override;
std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override;
@@ -513,15 +515,15 @@
return ret;
}
-std::unique_ptr<RpcTransport> RpcTransportCtxTls::newTransport(android::base::unique_fd fd,
+std::unique_ptr<RpcTransport> RpcTransportCtxTls::newTransport(android::RpcTransportFd socket,
FdTrigger* fdTrigger) const {
bssl::UniquePtr<SSL> ssl(SSL_new(mCtx.get()));
TEST_AND_RETURN(nullptr, ssl != nullptr);
Ssl wrapped(std::move(ssl));
preHandshake(&wrapped);
- TEST_AND_RETURN(nullptr, setFdAndDoHandshake(&wrapped, fd, fdTrigger));
- return std::make_unique<RpcTransportTls>(std::move(fd), std::move(wrapped));
+ TEST_AND_RETURN(nullptr, setFdAndDoHandshake(&wrapped, socket, fdTrigger));
+ return std::make_unique<RpcTransportTls>(std::move(socket), std::move(wrapped));
}
class RpcTransportCtxTlsServer : public RpcTransportCtxTls {
diff --git a/libs/binder/RpcTransportUtils.h b/libs/binder/RpcTransportUtils.h
index 00cb2af..32f0db8 100644
--- a/libs/binder/RpcTransportUtils.h
+++ b/libs/binder/RpcTransportUtils.h
@@ -25,8 +25,8 @@
template <typename SendOrReceive>
status_t interruptableReadOrWrite(
- int socketFd, FdTrigger* fdTrigger, iovec* iovs, int niovs, SendOrReceive sendOrReceiveFun,
- const char* funName, int16_t event,
+ const android::RpcTransportFd& socket, FdTrigger* fdTrigger, iovec* iovs, int niovs,
+ SendOrReceive sendOrReceiveFun, const char* funName, int16_t event,
const std::optional<android::base::function_ref<status_t()>>& altPoll) {
MAYBE_WAIT_IN_FLAKE_MODE;
@@ -99,7 +99,7 @@
return DEAD_OBJECT;
}
} else {
- if (status_t status = fdTrigger->triggerablePoll(socketFd, event); status != OK)
+ if (status_t status = fdTrigger->triggerablePoll(socket, event); status != OK)
return status;
if (!havePolled) havePolled = true;
}
diff --git a/libs/binder/Trace.cpp b/libs/binder/Trace.cpp
new file mode 100644
index 0000000..1ebfa1a
--- /dev/null
+++ b/libs/binder/Trace.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/Trace.h>
+#include <cutils/trace.h>
+
+namespace android {
+namespace binder {
+
+void atrace_begin(uint64_t tag, const char* name) {
+ ::atrace_begin(tag, name);
+}
+
+void atrace_end(uint64_t tag) {
+ ::atrace_end(tag);
+}
+
+} // namespace binder
+} // namespace android
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index 52bda0e..2c99334 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -187,6 +187,11 @@
std::vector<sp<RpcSession>> listSessions();
size_t numUninitializedSessions();
+ /**
+ * Whether any requests are currently being processed.
+ */
+ bool hasActiveRequests();
+
~RpcServer();
private:
@@ -199,7 +204,7 @@
static constexpr size_t kRpcAddressSize = 128;
static void establishConnection(
- sp<RpcServer>&& server, base::unique_fd clientFd,
+ sp<RpcServer>&& server, RpcTransportFd clientFd,
std::array<uint8_t, kRpcAddressSize> addr, size_t addrLen,
std::function<void(sp<RpcSession>&&, RpcSession::PreJoinSetupResult&&)>&& joinFn);
[[nodiscard]] status_t setupSocketServer(const RpcSocketAddress& address);
@@ -210,7 +215,7 @@
// A mode is supported if the N'th bit is on, where N is the mode enum's value.
std::bitset<8> mSupportedFileDescriptorTransportModes = std::bitset<8>().set(
static_cast<size_t>(RpcSession::FileDescriptorTransportMode::NONE));
- base::unique_fd mServer; // socket we are accepting sessions on
+ RpcTransportFd mServer; // socket we are accepting sessions on
RpcMutex mLock; // for below
std::unique_ptr<RpcMaybeThread> mJoinThread;
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index 428e272..a25ba98 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -189,6 +189,11 @@
*/
[[nodiscard]] status_t sendDecStrong(const BpBinder* binder);
+ /**
+ * Whether any requests are currently being processed.
+ */
+ bool hasActiveRequests();
+
~RpcSession();
/**
@@ -269,7 +274,7 @@
[[nodiscard]] status_t setupOneSocketConnection(const RpcSocketAddress& address,
const std::vector<uint8_t>& sessionId,
bool incoming);
- [[nodiscard]] status_t initAndAddConnection(base::unique_fd fd,
+ [[nodiscard]] status_t initAndAddConnection(RpcTransportFd fd,
const std::vector<uint8_t>& sessionId,
bool incoming);
[[nodiscard]] status_t addIncomingConnection(std::unique_ptr<RpcTransport> rpcTransport);
@@ -286,6 +291,11 @@
[[nodiscard]] status_t initShutdownTrigger();
+ /**
+ * Checks whether any connection is active (Not polling on fd)
+ */
+ bool hasActiveConnection(const std::vector<sp<RpcConnection>>& connections);
+
enum class ConnectionUse {
CLIENT,
CLIENT_ASYNC,
diff --git a/libs/binder/include/binder/RpcTransport.h b/libs/binder/include/binder/RpcTransport.h
index 5197ef9..fd52a3a 100644
--- a/libs/binder/include/binder/RpcTransport.h
+++ b/libs/binder/include/binder/RpcTransport.h
@@ -30,12 +30,14 @@
#include <utils/Errors.h>
#include <binder/RpcCertificateFormat.h>
+#include <binder/RpcThreads.h>
#include <sys/uio.h>
namespace android {
class FdTrigger;
+struct RpcTransportFd;
// Represents a socket connection.
// No thread-safety is guaranteed for these APIs.
@@ -81,6 +83,15 @@
const std::optional<android::base::function_ref<status_t()>> &altPoll,
std::vector<std::variant<base::unique_fd, base::borrowed_fd>> *ancillaryFds) = 0;
+ /**
+ * Check whether any threads are blocked while polling the transport
+ * for read operations
+ * Return:
+ * True - Specifies that there is active polling on transport.
+ * False - No active polling on transport
+ */
+ [[nodiscard]] virtual bool isWaiting() = 0;
+
protected:
RpcTransport() = default;
};
@@ -96,7 +107,7 @@
// Implementation details: for TLS, this function may incur I/O. |fdTrigger| may be used
// to interrupt I/O. This function blocks until handshake is finished.
[[nodiscard]] virtual std::unique_ptr<RpcTransport> newTransport(
- android::base::unique_fd fd, FdTrigger *fdTrigger) const = 0;
+ android::RpcTransportFd fd, FdTrigger *fdTrigger) const = 0;
// Return the preconfigured certificate of this context.
//
@@ -129,4 +140,36 @@
RpcTransportCtxFactory() = default;
};
+struct RpcTransportFd {
+private:
+ mutable bool isPolling{false};
+
+ void setPollingState(bool state) const { isPolling = state; }
+
+public:
+ base::unique_fd fd;
+
+ RpcTransportFd() = default;
+ explicit RpcTransportFd(base::unique_fd &&descriptor)
+ : isPolling(false), fd(std::move(descriptor)) {}
+
+ RpcTransportFd(RpcTransportFd &&transportFd) noexcept
+ : isPolling(transportFd.isPolling), fd(std::move(transportFd.fd)) {}
+
+ RpcTransportFd &operator=(RpcTransportFd &&transportFd) noexcept {
+ fd = std::move(transportFd.fd);
+ isPolling = transportFd.isPolling;
+ return *this;
+ }
+
+ RpcTransportFd &operator=(base::unique_fd &&descriptor) noexcept {
+ fd = std::move(descriptor);
+ isPolling = false;
+ return *this;
+ }
+
+ bool isInPollingState() const { return isPolling; }
+ friend class FdTrigger;
+};
+
} // namespace android
diff --git a/libs/binder/include/binder/Trace.h b/libs/binder/include/binder/Trace.h
new file mode 100644
index 0000000..9937842
--- /dev/null
+++ b/libs/binder/include/binder/Trace.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cutils/trace.h>
+#include <stdint.h>
+
+namespace android {
+namespace binder {
+
+// Trampoline functions allowing generated aidls to trace binder transactions without depending on
+// libcutils/libutils
+void atrace_begin(uint64_t tag, const char* name);
+void atrace_end(uint64_t tag);
+
+class ScopedTrace {
+public:
+ inline ScopedTrace(uint64_t tag, const char* name) : mTag(tag) { atrace_begin(mTag, name); }
+
+ inline ~ScopedTrace() { atrace_end(mTag); }
+
+private:
+ uint64_t mTag;
+};
+
+} // namespace binder
+} // namespace android
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 32e018d..33d28e6 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -57,6 +57,7 @@
srcs: [
"ibinder.cpp",
"ibinder_jni.cpp",
+ "libbinder.cpp",
"parcel.cpp",
"parcel_jni.cpp",
"process.cpp",
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 9778ec0..28d1f16 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -14,21 +14,19 @@
* limitations under the License.
*/
+#include <android-base/logging.h>
#include <android/binder_ibinder.h>
#include <android/binder_ibinder_platform.h>
-#include <android/binder_libbinder.h>
-#include "ibinder_internal.h"
-
#include <android/binder_stability.h>
#include <android/binder_status.h>
-#include "parcel_internal.h"
-#include "status_internal.h"
-
-#include <android-base/logging.h>
#include <binder/IPCThreadState.h>
#include <binder/IResultReceiver.h>
#include <private/android_filesystem_config.h>
+#include "ibinder_internal.h"
+#include "parcel_internal.h"
+#include "status_internal.h"
+
using DeathRecipient = ::android::IBinder::DeathRecipient;
using ::android::IBinder;
@@ -782,17 +780,6 @@
return ::android::IPCThreadState::self()->getCallingSid();
}
-android::sp<android::IBinder> AIBinder_toPlatformBinder(AIBinder* binder) {
- if (binder == nullptr) return nullptr;
- return binder->getBinder();
-}
-
-AIBinder* AIBinder_fromPlatformBinder(const android::sp<android::IBinder>& binder) {
- sp<AIBinder> ndkBinder = ABpBinder::lookupOrCreateFromBinder(binder);
- 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 0bf1e3d..95eee26 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
@@ -1639,7 +1639,6 @@
return AParcel_writeParcelable(parcel, value);
} else {
static_assert(dependent_false_v<T>, "unrecognized type");
- return STATUS_OK;
}
}
@@ -1707,7 +1706,6 @@
return AParcel_readParcelable(parcel, value);
} else {
static_assert(dependent_false_v<T>, "unrecognized type");
- return STATUS_OK;
}
}
diff --git a/libs/binder/ndk/include_cpp/android/binder_to_string.h b/libs/binder/ndk/include_cpp/android/binder_to_string.h
index ef71a81..d7840ec 100644
--- a/libs/binder/ndk/include_cpp/android/binder_to_string.h
+++ b/libs/binder/ndk/include_cpp/android/binder_to_string.h
@@ -162,7 +162,12 @@
} else if constexpr (std::is_same_v<bool, _T>) {
return t ? "true" : "false";
} else if constexpr (std::is_same_v<char16_t, _T>) {
+ // TODO(b/244494451): codecvt is deprecated in C++17 -- suppress the
+ // warnings. There's no replacement in the standard library yet.
+ _Pragma("clang diagnostic push")
+ _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"");
return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>().to_bytes(t);
+ _Pragma("clang diagnostic pop");
} else if constexpr (std::is_arithmetic_v<_T>) {
return std::to_string(t);
} else if constexpr (std::is_same_v<std::string, _T>) {
diff --git a/libs/binder/ndk/include_platform/android/binder_libbinder.h b/libs/binder/ndk/include_platform/android/binder_libbinder.h
index f0c00e8..dfe12a1 100644
--- a/libs/binder/ndk/include_platform/android/binder_libbinder.h
+++ b/libs/binder/ndk/include_platform/android/binder_libbinder.h
@@ -19,7 +19,9 @@
#if !defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__)
#include <android/binder_ibinder.h>
+#include <android/binder_parcel.h>
#include <binder/IBinder.h>
+#include <binder/Parcel.h>
/**
* Get libbinder version of binder from AIBinder.
@@ -47,4 +49,26 @@
*/
AIBinder* AIBinder_fromPlatformBinder(const android::sp<android::IBinder>& binder);
+/**
+ * View libbinder version of parcel from AParcel (mutable).
+ *
+ * The lifetime of the returned parcel is the lifetime of the input AParcel.
+ * Do not ues this reference after dropping the AParcel.
+ *
+ * \param parcel non-null parcel with ownership retained by client
+ * \return platform parcel object
+ */
+android::Parcel* AParcel_viewPlatformParcel(AParcel* parcel);
+
+/**
+ * View libbinder version of parcel from AParcel (const version).
+ *
+ * The lifetime of the returned parcel is the lifetime of the input AParcel.
+ * Do not ues this reference after dropping the AParcel.
+ *
+ * \param parcel non-null parcel with ownership retained by client
+ * \return platform parcel object
+ */
+const android::Parcel* AParcel_viewPlatformParcel(const AParcel* parcel);
+
#endif
diff --git a/libs/binder/ndk/libbinder.cpp b/libs/binder/ndk/libbinder.cpp
new file mode 100644
index 0000000..f94d81d
--- /dev/null
+++ b/libs/binder/ndk/libbinder.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_libbinder.h>
+
+#include "ibinder_internal.h"
+#include "parcel_internal.h"
+
+using ::android::IBinder;
+using ::android::Parcel;
+using ::android::sp;
+
+sp<IBinder> AIBinder_toPlatformBinder(AIBinder* binder) {
+ if (binder == nullptr) return nullptr;
+ return binder->getBinder();
+}
+
+AIBinder* AIBinder_fromPlatformBinder(const sp<IBinder>& binder) {
+ sp<AIBinder> ndkBinder = ABpBinder::lookupOrCreateFromBinder(binder);
+ AIBinder_incStrong(ndkBinder.get());
+ return ndkBinder.get();
+}
+
+Parcel* AParcel_viewPlatformParcel(AParcel* parcel) {
+ return parcel->get();
+}
+
+const Parcel* AParcel_viewPlatformParcel(const AParcel* parcel) {
+ return parcel->get();
+}
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 6bc9814..259a736 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -158,6 +158,7 @@
extern "C++" {
AIBinder_fromPlatformBinder*;
AIBinder_toPlatformBinder*;
+ AParcel_viewPlatformParcel*;
};
local:
*;
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 1b136dc..6d29238 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -661,6 +661,15 @@
}
}
+TEST(NdkBinder, ConvertToPlatformParcel) {
+ ndk::ScopedAParcel parcel = ndk::ScopedAParcel(AParcel_create());
+ EXPECT_EQ(OK, AParcel_writeInt32(parcel.get(), 42));
+
+ android::Parcel* pparcel = AParcel_viewPlatformParcel(parcel.get());
+ pparcel->setDataPosition(0);
+ EXPECT_EQ(42, pparcel->readInt32());
+}
+
class MyResultReceiver : public BnResultReceiver {
public:
Mutex mMutex;
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 4c037b7..21b0354 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -1773,7 +1773,7 @@
}
}
mFd = rpcServer->releaseServer();
- if (!mFd.ok()) return AssertionFailure() << "releaseServer returns invalid fd";
+ if (!mFd.fd.ok()) return AssertionFailure() << "releaseServer returns invalid fd";
mCtx = newFactory(rpcSecurity, mCertVerifier, std::move(auth))->newServerCtx();
if (mCtx == nullptr) return AssertionFailure() << "newServerCtx";
mSetup = true;
@@ -1794,7 +1794,7 @@
std::vector<std::thread> threads;
while (OK == mFdTrigger->triggerablePoll(mFd, POLLIN)) {
base::unique_fd acceptedFd(
- TEMP_FAILURE_RETRY(accept4(mFd.get(), nullptr, nullptr /*length*/,
+ TEMP_FAILURE_RETRY(accept4(mFd.fd.get(), nullptr, nullptr /*length*/,
SOCK_CLOEXEC | SOCK_NONBLOCK)));
threads.emplace_back(&Server::handleOne, this, std::move(acceptedFd));
}
@@ -1803,7 +1803,8 @@
}
void handleOne(android::base::unique_fd acceptedFd) {
ASSERT_TRUE(acceptedFd.ok());
- auto serverTransport = mCtx->newTransport(std::move(acceptedFd), mFdTrigger.get());
+ RpcTransportFd transportFd(std::move(acceptedFd));
+ auto serverTransport = mCtx->newTransport(std::move(transportFd), mFdTrigger.get());
if (serverTransport == nullptr) return; // handshake failed
ASSERT_TRUE(mPostConnect(serverTransport.get(), mFdTrigger.get()));
}
@@ -1822,7 +1823,7 @@
std::unique_ptr<std::thread> mThread;
ConnectToServer mConnectToServer;
std::unique_ptr<FdTrigger> mFdTrigger = FdTrigger::make();
- base::unique_fd mFd;
+ RpcTransportFd mFd;
std::unique_ptr<RpcTransportCtx> mCtx;
std::shared_ptr<RpcCertificateVerifierSimple> mCertVerifier =
std::make_shared<RpcCertificateVerifierSimple>();
@@ -1869,7 +1870,7 @@
// connect() and do handshake
bool setUpTransport() {
mFd = mConnectToServer();
- if (!mFd.ok()) return AssertionFailure() << "Cannot connect to server";
+ if (!mFd.fd.ok()) return AssertionFailure() << "Cannot connect to server";
mClientTransport = mCtx->newTransport(std::move(mFd), mFdTrigger.get());
return mClientTransport != nullptr;
}
@@ -1898,9 +1899,11 @@
ASSERT_EQ(readOk, readMessage());
}
+ bool isTransportWaiting() { return mClientTransport->isWaiting(); }
+
private:
ConnectToServer mConnectToServer;
- base::unique_fd mFd;
+ RpcTransportFd mFd;
std::unique_ptr<FdTrigger> mFdTrigger = FdTrigger::make();
std::unique_ptr<RpcTransportCtx> mCtx;
std::shared_ptr<RpcCertificateVerifierSimple> mCertVerifier =
@@ -2147,6 +2150,56 @@
ASSERT_FALSE(client.readMessage(msg2));
}
+TEST_P(RpcTransportTest, CheckWaitingForRead) {
+ std::mutex readMutex;
+ std::condition_variable readCv;
+ bool shouldContinueReading = false;
+ // Server will write data on transport once its started
+ auto serverPostConnect = [&](RpcTransport* serverTransport, FdTrigger* fdTrigger) {
+ std::string message(RpcTransportTestUtils::kMessage);
+ iovec messageIov{message.data(), message.size()};
+ auto status = serverTransport->interruptableWriteFully(fdTrigger, &messageIov, 1,
+ std::nullopt, nullptr);
+ if (status != OK) return AssertionFailure() << statusToString(status);
+
+ {
+ std::unique_lock<std::mutex> lock(readMutex);
+ shouldContinueReading = true;
+ lock.unlock();
+ readCv.notify_all();
+ }
+ return AssertionSuccess();
+ };
+
+ // Setup Server and client
+ auto server = std::make_unique<Server>();
+ ASSERT_TRUE(server->setUp(GetParam()));
+
+ Client client(server->getConnectToServerFn());
+ ASSERT_TRUE(client.setUp(GetParam()));
+
+ ASSERT_EQ(OK, trust(&client, server));
+ ASSERT_EQ(OK, trust(server, &client));
+ server->setPostConnect(serverPostConnect);
+
+ server->start();
+ ASSERT_TRUE(client.setUpTransport());
+ {
+ // Wait till server writes data
+ std::unique_lock<std::mutex> lock(readMutex);
+ ASSERT_TRUE(readCv.wait_for(lock, 3s, [&] { return shouldContinueReading; }));
+ }
+
+ // Since there is no read polling here, we will get polling count 0
+ ASSERT_FALSE(client.isTransportWaiting());
+ ASSERT_TRUE(client.readMessage(RpcTransportTestUtils::kMessage));
+ // Thread should increment polling count, read and decrement polling count
+ // Again, polling count should be zero here
+ ASSERT_FALSE(client.isTransportWaiting());
+
+ server->shutdown();
+}
+
INSTANTIATE_TEST_CASE_P(BinderRpc, RpcTransportTest,
::testing::ValuesIn(RpcTransportTest::getRpcTranportTestParams()),
RpcTransportTest::PrintParamInfo);
diff --git a/libs/binder/tests/parcel_fuzzer/binder_ndk.h b/libs/binder/tests/parcel_fuzzer/binder_ndk.h
index 81e79b5..d19f25b 100644
--- a/libs/binder/tests/parcel_fuzzer/binder_ndk.h
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.h
@@ -18,29 +18,27 @@
#include <android/binder_auto_utils.h>
#include <vector>
+#include <android/binder_libbinder.h>
#include <android/binder_parcel.h>
#include "parcel_fuzzer.h"
-// libbinder_ndk doesn't export this header which breaks down its API for NDK
-// and APEX users, but we need access to it to fuzz.
-#include "../../ndk/parcel_internal.h"
-
class NdkParcelAdapter {
public:
- NdkParcelAdapter() : mParcel(new AParcel(nullptr /*binder*/)) {}
+ NdkParcelAdapter() : mParcel(AParcel_create()) {}
const AParcel* aParcel() const { return mParcel.get(); }
AParcel* aParcel() { return mParcel.get(); }
- android::Parcel* parcel() { return aParcel()->get(); }
+ const android::Parcel* parcel() const { return AParcel_viewPlatformParcel(aParcel()); }
+ android::Parcel* parcel() { return AParcel_viewPlatformParcel(aParcel()); }
- const uint8_t* data() const { return aParcel()->get()->data(); }
- size_t dataSize() const { return aParcel()->get()->dataSize(); }
- size_t dataAvail() const { return aParcel()->get()->dataAvail(); }
- size_t dataPosition() const { return aParcel()->get()->dataPosition(); }
- size_t dataCapacity() const { return aParcel()->get()->dataCapacity(); }
+ const uint8_t* data() const { return parcel()->data(); }
+ size_t dataSize() const { return parcel()->dataSize(); }
+ size_t dataAvail() const { return parcel()->dataAvail(); }
+ size_t dataPosition() const { return parcel()->dataPosition(); }
+ size_t dataCapacity() const { return parcel()->dataCapacity(); }
android::status_t setData(const uint8_t* buffer, size_t len) {
- return aParcel()->get()->setData(buffer, len);
+ return parcel()->setData(buffer, len);
}
android::status_t appendFrom(const NdkParcelAdapter* parcel, int32_t start, int32_t len) {
diff --git a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
index 32494e3..25f6096 100644
--- a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
+++ b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
@@ -17,6 +17,9 @@
#include <fuzzbinder/random_parcel.h>
+#include <android-base/logging.h>
+#include <binder/ProcessState.h>
+
namespace android {
void fuzzService(const sp<IBinder>& binder, FuzzedDataProvider&& provider) {
@@ -60,6 +63,15 @@
options.extraFds.push_back(base::unique_fd(dup(retFds[i])));
}
}
+
+ // invariants
+
+ auto ps = ProcessState::selfOrNull();
+ if (ps) {
+ CHECK_EQ(0, ps->getThreadPoolMaxTotalThreadCount())
+ << "Binder threadpool should not be started by fuzzer because coverage can only "
+ "cover in-process calls.";
+ }
}
} // namespace android
diff --git a/libs/binder/tests/rpc_fuzzer/main.cpp b/libs/binder/tests/rpc_fuzzer/main.cpp
index a8713a2..f68a561 100644
--- a/libs/binder/tests/rpc_fuzzer/main.cpp
+++ b/libs/binder/tests/rpc_fuzzer/main.cpp
@@ -157,8 +157,6 @@
}
}
- usleep(10000);
-
if (hangupBeforeShutdown) {
connections.clear();
while (!server->listSessions().empty() || server->numUninitializedSessions()) {
@@ -167,6 +165,10 @@
}
}
+ while (server->hasActiveRequests()) {
+ usleep(10);
+ }
+
while (!server->shutdown()) usleep(1);
serverThread.join();
diff --git a/libs/binder/trusty/RpcServerTrusty.cpp b/libs/binder/trusty/RpcServerTrusty.cpp
index cb77575..18ce316 100644
--- a/libs/binder/trusty/RpcServerTrusty.cpp
+++ b/libs/binder/trusty/RpcServerTrusty.cpp
@@ -118,10 +118,12 @@
};
base::unique_fd clientFd(chan);
+ android::RpcTransportFd transportFd(std::move(clientFd));
+
std::array<uint8_t, RpcServer::kRpcAddressSize> addr;
constexpr size_t addrLen = sizeof(*peer);
memcpy(addr.data(), peer, addrLen);
- RpcServer::establishConnection(sp(server->mRpcServer), std::move(clientFd), addr, addrLen,
+ RpcServer::establishConnection(sp(server->mRpcServer), std::move(transportFd), addr, addrLen,
joinFn);
return rc;
diff --git a/libs/binder/trusty/RpcTransportTipcTrusty.cpp b/libs/binder/trusty/RpcTransportTipcTrusty.cpp
index 1e2d798..0b67b9f 100644
--- a/libs/binder/trusty/RpcTransportTipcTrusty.cpp
+++ b/libs/binder/trusty/RpcTransportTipcTrusty.cpp
@@ -33,7 +33,7 @@
// RpcTransport for Trusty.
class RpcTransportTipcTrusty : public RpcTransport {
public:
- explicit RpcTransportTipcTrusty(android::base::unique_fd socket) : mSocket(std::move(socket)) {}
+ explicit RpcTransportTipcTrusty(android::RpcTransportFd socket) : mSocket(std::move(socket)) {}
~RpcTransportTipcTrusty() { releaseMessage(); }
status_t pollRead() override {
@@ -64,7 +64,7 @@
.num_handles = 0, // TODO: add ancillaryFds
.handles = nullptr,
};
- ssize_t rc = send_msg(mSocket.get(), &msg);
+ ssize_t rc = send_msg(mSocket.fd.get(), &msg);
if (rc == ERR_NOT_ENOUGH_BUFFER) {
// Peer is blocked, wait until it unblocks.
// TODO: when tipc supports a send-unblocked handler,
@@ -72,7 +72,7 @@
// when the handler gets called by the library
uevent uevt;
do {
- rc = ::wait(mSocket.get(), &uevt, INFINITE_TIME);
+ rc = ::wait(mSocket.fd.get(), &uevt, INFINITE_TIME);
if (rc < 0) {
return statusFromTrusty(rc);
}
@@ -83,7 +83,7 @@
// Retry the send, it should go through this time because
// sending is now unblocked
- rc = send_msg(mSocket.get(), &msg);
+ rc = send_msg(mSocket.fd.get(), &msg);
}
if (rc < 0) {
return statusFromTrusty(rc);
@@ -130,7 +130,7 @@
.num_handles = 0, // TODO: support ancillaryFds
.handles = nullptr,
};
- ssize_t rc = read_msg(mSocket.get(), mMessageInfo.id, mMessageOffset, &msg);
+ ssize_t rc = read_msg(mSocket.fd.get(), mMessageInfo.id, mMessageOffset, &msg);
if (rc < 0) {
return statusFromTrusty(rc);
}
@@ -170,6 +170,8 @@
}
}
+ bool isWaiting() override { return mSocket.isInPollingState(); }
+
private:
status_t ensureMessage(bool wait) {
int rc;
@@ -180,7 +182,7 @@
/* TODO: interruptible wait, maybe with a timeout??? */
uevent uevt;
- rc = ::wait(mSocket.get(), &uevt, wait ? INFINITE_TIME : 0);
+ rc = ::wait(mSocket.fd.get(), &uevt, wait ? INFINITE_TIME : 0);
if (rc < 0) {
if (rc == ERR_TIMED_OUT && !wait) {
// If we timed out with wait==false, then there's no message
@@ -193,7 +195,7 @@
return OK;
}
- rc = get_msg(mSocket.get(), &mMessageInfo);
+ rc = get_msg(mSocket.fd.get(), &mMessageInfo);
if (rc < 0) {
return statusFromTrusty(rc);
}
@@ -205,12 +207,12 @@
void releaseMessage() {
if (mHaveMessage) {
- put_msg(mSocket.get(), mMessageInfo.id);
+ put_msg(mSocket.fd.get(), mMessageInfo.id);
mHaveMessage = false;
}
}
- base::unique_fd mSocket;
+ android::RpcTransportFd mSocket;
bool mHaveMessage = false;
ipc_msg_info mMessageInfo;
@@ -220,9 +222,9 @@
// RpcTransportCtx for Trusty.
class RpcTransportCtxTipcTrusty : public RpcTransportCtx {
public:
- std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd,
+ std::unique_ptr<RpcTransport> newTransport(android::RpcTransportFd socket,
FdTrigger*) const override {
- return std::make_unique<RpcTransportTipcTrusty>(std::move(fd));
+ return std::make_unique<RpcTransportTipcTrusty>(std::move(socket));
}
std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; }
};
diff --git a/libs/binderthreadstate/test.cpp b/libs/binderthreadstate/test.cpp
index 44e2fd1..2f73137 100644
--- a/libs/binderthreadstate/test.cpp
+++ b/libs/binderthreadstate/test.cpp
@@ -68,8 +68,13 @@
static void callAidl(size_t id, int32_t idx) {
sp<IAidlStuff> stuff;
- CHECK(OK == android::getService<IAidlStuff>(String16(id2name(id).c_str()), &stuff));
- CHECK(stuff->call(idx).isOk());
+ CHECK_EQ(OK, android::getService<IAidlStuff>(String16(id2name(id).c_str()), &stuff));
+ auto ret = stuff->call(idx);
+ CHECK(ret.isOk()) << ret;
+}
+
+static inline std::ostream& operator<<(std::ostream& o, const BinderCallType& s) {
+ return o << static_cast<std::underlying_type_t<BinderCallType>>(s);
}
class HidlServer : public IHidlStuff {
@@ -79,13 +84,13 @@
size_t otherId;
Return<void> callLocal() {
- CHECK(BinderCallType::NONE == getCurrentServingCall());
+ CHECK_EQ(BinderCallType::NONE, getCurrentServingCall());
return android::hardware::Status::ok();
}
Return<void> call(int32_t idx) {
LOG(INFO) << "HidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx
<< " with tid: " << gettid();
- CHECK(BinderCallType::HWBINDER == getCurrentServingCall());
+ CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall());
if (idx > 0) {
if (thisId == kP1Id && idx % 4 < 2) {
callHidl(otherId, idx - 1);
@@ -93,7 +98,7 @@
callAidl(otherId, idx - 1);
}
}
- CHECK(BinderCallType::HWBINDER == getCurrentServingCall());
+ CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall());
return android::hardware::Status::ok();
}
};
@@ -104,13 +109,13 @@
size_t otherId;
Status callLocal() {
- CHECK(BinderCallType::NONE == getCurrentServingCall());
+ CHECK_EQ(BinderCallType::NONE, getCurrentServingCall());
return Status::ok();
}
Status call(int32_t idx) {
LOG(INFO) << "AidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx
<< " with tid: " << gettid();
- CHECK(BinderCallType::BINDER == getCurrentServingCall());
+ CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall());
if (idx > 0) {
if (thisId == kP2Id && idx % 4 < 2) {
callHidl(otherId, idx - 1);
@@ -118,7 +123,7 @@
callAidl(otherId, idx - 1);
}
}
- CHECK(BinderCallType::BINDER == getCurrentServingCall());
+ CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall());
return Status::ok();
}
};
@@ -161,13 +166,14 @@
// AIDL
android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
sp<AidlServer> aidlServer = new AidlServer(thisId, otherId);
- CHECK(OK == defaultServiceManager()->addService(String16(id2name(thisId).c_str()), aidlServer));
+ CHECK_EQ(OK,
+ defaultServiceManager()->addService(String16(id2name(thisId).c_str()), aidlServer));
android::ProcessState::self()->startThreadPool();
// HIDL
android::hardware::configureRpcThreadpool(1, true /*callerWillJoin*/);
sp<IHidlStuff> hidlServer = new HidlServer(thisId, otherId);
- CHECK(OK == hidlServer->registerAsService(id2name(thisId).c_str()));
+ CHECK_EQ(OK, hidlServer->registerAsService(id2name(thisId).c_str()));
android::hardware::joinRpcThreadpool();
return EXIT_FAILURE;
diff --git a/libs/gui/OWNERS b/libs/gui/OWNERS
index 31bf895..05b5533 100644
--- a/libs/gui/OWNERS
+++ b/libs/gui/OWNERS
@@ -2,8 +2,9 @@
alecmouri@google.com
chaviw@google.com
chrisforbes@google.com
-lpy@google.com
jreck@google.com
+lpy@google.com
+pdwilliams@google.com
racarr@google.com
vishnun@google.com
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 3732fee..429760f 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -465,7 +465,7 @@
if (flattenWordCount == 13) {
usage = (uint64_t(buf[12]) << 32) | uint32_t(buf[6]);
} else {
- usage = uint64_t(usage_deprecated);
+ usage = uint64_t(ANDROID_NATIVE_UNSIGNED_CAST(usage_deprecated));
}
native_handle* h =
native_handle_create(static_cast<int>(numFds), static_cast<int>(numInts));
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 41878e3..18d670a 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -147,6 +147,7 @@
srcs: [":libinputflinger_base_sources"],
shared_libs: [
"libbase",
+ "libbinder",
"libcutils",
"libinput",
"liblog",
diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS
index 2ece51c..6011d0d 100644
--- a/services/surfaceflinger/OWNERS
+++ b/services/surfaceflinger/OWNERS
@@ -2,6 +2,7 @@
alecmouri@google.com
chaviw@google.com
lpy@google.com
+pdwilliams@google.com
racarr@google.com
scroggo@google.com
-vishnun@google.com
\ No newline at end of file
+vishnun@google.com
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
index bdcab51..665a7ee 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
@@ -19,6 +19,7 @@
#define LOG_TAG "VSyncReactor"
//#define LOG_NDEBUG 0
+#include <assert.h>
#include <cutils/properties.h>
#include <log/log.h>
#include <utils/Trace.h>
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index d33bc10..434c297 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -52,19 +52,12 @@
#pragma clang diagnostic ignored "-Wconversion"
class CredentialsTest : public ::testing::Test {
protected:
- void SetUp() override {
- // Start the tests as root.
- seteuid(AID_ROOT);
-
- ASSERT_NO_FATAL_FAILURE(initClient());
- }
+ void SetUp() override { ASSERT_NO_FATAL_FAILURE(initClient()); }
void TearDown() override {
mComposerClient->dispose();
mBGSurfaceControl.clear();
mComposerClient.clear();
- // Finish the tests as root.
- seteuid(AID_ROOT);
}
sp<IBinder> mDisplay;
@@ -99,31 +92,6 @@
}
/**
- * Sets UID to imitate Graphic's process.
- */
- void setGraphicsUID() {
- seteuid(AID_ROOT);
- seteuid(AID_GRAPHICS);
- }
-
- /**
- * Sets UID to imitate System's process.
- */
- void setSystemUID() {
- seteuid(AID_ROOT);
- seteuid(AID_SYSTEM);
- }
-
- /**
- * Sets UID to imitate a process that doesn't have any special privileges in
- * our code.
- */
- void setBinUID() {
- seteuid(AID_ROOT);
- seteuid(AID_BIN);
- }
-
- /**
* Template function the check a condition for different types of users: root
* graphics, system, and non-supported user. Root, graphics, and system should
* always equal privilegedValue, and non-supported user should equal unprivilegedValue.
@@ -131,24 +99,34 @@
template <typename T>
void checkWithPrivileges(std::function<T()> condition, T privilegedValue, T unprivilegedValue) {
// Check with root.
- seteuid(AID_ROOT);
- ASSERT_EQ(privilegedValue, condition());
+ {
+ UIDFaker f(AID_SYSTEM);
+ ASSERT_EQ(privilegedValue, condition());
+ }
// Check as a Graphics user.
- setGraphicsUID();
- ASSERT_EQ(privilegedValue, condition());
+ {
+ UIDFaker f(AID_GRAPHICS);
+ ASSERT_EQ(privilegedValue, condition());
+ }
// Check as a system user.
- setSystemUID();
- ASSERT_EQ(privilegedValue, condition());
+ {
+ UIDFaker f(AID_SYSTEM);
+ ASSERT_EQ(privilegedValue, condition());
+ }
// Check as a non-supported user.
- setBinUID();
- ASSERT_EQ(unprivilegedValue, condition());
+ {
+ UIDFaker f(AID_BIN);
+ ASSERT_EQ(unprivilegedValue, condition());
+ }
// Check as shell since shell has some additional permissions
- seteuid(AID_SHELL);
- ASSERT_EQ(unprivilegedValue, condition());
+ {
+ UIDFaker f(AID_SHELL);
+ ASSERT_EQ(privilegedValue, condition());
+ }
}
};
@@ -157,17 +135,23 @@
ASSERT_NO_FATAL_FAILURE(initClient());
// Graphics can init the client.
- setGraphicsUID();
- ASSERT_NO_FATAL_FAILURE(initClient());
+ {
+ UIDFaker f(AID_GRAPHICS);
+ ASSERT_NO_FATAL_FAILURE(initClient());
+ }
// System can init the client.
- setSystemUID();
- ASSERT_NO_FATAL_FAILURE(initClient());
+ {
+ UIDFaker f(AID_SYSTEM);
+ ASSERT_NO_FATAL_FAILURE(initClient());
+ }
// Anyone else can init the client.
- setBinUID();
- mComposerClient = new SurfaceComposerClient;
- ASSERT_NO_FATAL_FAILURE(initClient());
+ {
+ UIDFaker f(AID_BIN);
+ mComposerClient = new SurfaceComposerClient;
+ ASSERT_NO_FATAL_FAILURE(initClient());
+ }
}
TEST_F(CredentialsTest, GetBuiltInDisplayAccessTest) {
@@ -181,7 +165,7 @@
TEST_F(CredentialsTest, AllowedGetterMethodsTest) {
// The following methods are tested with a UID that is not root, graphics,
// or system, to show that anyone can access them.
- setBinUID();
+ UIDFaker f(AID_BIN);
const auto display = SurfaceComposerClient::getInternalDisplayToken();
ASSERT_TRUE(display != nullptr);
@@ -250,24 +234,34 @@
};
// Check with root.
- seteuid(AID_ROOT);
- ASSERT_FALSE(condition());
+ {
+ UIDFaker f(AID_ROOT);
+ ASSERT_FALSE(condition());
+ }
// Check as a Graphics user.
- setGraphicsUID();
- ASSERT_TRUE(condition());
+ {
+ UIDFaker f(AID_GRAPHICS);
+ ASSERT_TRUE(condition());
+ }
// Check as a system user.
- setSystemUID();
- ASSERT_TRUE(condition());
+ {
+ UIDFaker f(AID_SYSTEM);
+ ASSERT_TRUE(condition());
+ }
// Check as a non-supported user.
- setBinUID();
- ASSERT_FALSE(condition());
+ {
+ UIDFaker f(AID_BIN);
+ ASSERT_FALSE(condition());
+ }
// Check as shell since shell has some additional permissions
- seteuid(AID_SHELL);
- ASSERT_FALSE(condition());
+ {
+ UIDFaker f(AID_SHELL);
+ ASSERT_FALSE(condition());
+ }
condition = [=]() {
sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
@@ -313,17 +307,22 @@
// is called when we call dumpsys. I don't see a reason why we should change this.
std::vector<LayerDebugInfo> outLayers;
// Check with root.
- seteuid(AID_ROOT);
- ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
+ {
+ UIDFaker f(AID_ROOT);
+ ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
+ }
// Check as a shell.
- seteuid(AID_SHELL);
- ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
+ {
+ UIDFaker f(AID_SHELL);
+ ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
+ }
// Check as anyone else.
- seteuid(AID_ROOT);
- seteuid(AID_BIN);
- ASSERT_EQ(PERMISSION_DENIED, sf->getLayerDebugInfo(&outLayers));
+ {
+ UIDFaker f(AID_BIN);
+ ASSERT_EQ(PERMISSION_DENIED, sf->getLayerDebugInfo(&outLayers));
+ }
}
TEST_F(CredentialsTest, IsWideColorDisplayBasicCorrectness) {
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 5ff9399..1fe8800 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -19,6 +19,8 @@
#include <android/hardware/graphics/common/1.0/types.h>
#include <grallocusage/GrallocUsageConversion.h>
#include <graphicsenv/GraphicsEnv.h>
+#include <hardware/gralloc.h>
+#include <hardware/gralloc1.h>
#include <log/log.h>
#include <sync/sync.h>
#include <system/window.h>
@@ -42,6 +44,26 @@
namespace {
+static uint64_t convertGralloc1ToBufferUsage(uint64_t producerUsage,
+ uint64_t consumerUsage) {
+ static_assert(uint64_t(GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN) ==
+ uint64_t(GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN),
+ "expected ConsumerUsage and ProducerUsage CPU_READ_OFTEN "
+ "bits to match");
+ uint64_t merged = producerUsage | consumerUsage;
+ if ((merged & (GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN)) ==
+ GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN) {
+ merged &= ~uint64_t(GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN);
+ merged |= BufferUsage::CPU_READ_OFTEN;
+ }
+ if ((merged & (GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN)) ==
+ GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN) {
+ merged &= ~uint64_t(GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN);
+ merged |= BufferUsage::CPU_WRITE_OFTEN;
+ }
+ return merged;
+}
+
const VkSurfaceTransformFlagsKHR kSupportedTransforms =
VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR |
VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR |
@@ -1337,7 +1359,7 @@
num_images = 1;
}
- int32_t legacy_usage = 0;
+ uint64_t native_usage = 0;
if (dispatch.GetSwapchainGrallocUsage2ANDROID) {
uint64_t consumer_usage, producer_usage;
ATRACE_BEGIN("GetSwapchainGrallocUsage2ANDROID");
@@ -1349,10 +1371,11 @@
ALOGE("vkGetSwapchainGrallocUsage2ANDROID failed: %d", result);
return VK_ERROR_SURFACE_LOST_KHR;
}
- legacy_usage =
- android_convertGralloc1To0Usage(producer_usage, consumer_usage);
+ native_usage =
+ convertGralloc1ToBufferUsage(consumer_usage, producer_usage);
} else if (dispatch.GetSwapchainGrallocUsageANDROID) {
ATRACE_BEGIN("GetSwapchainGrallocUsageANDROID");
+ int32_t legacy_usage = 0;
result = dispatch.GetSwapchainGrallocUsageANDROID(
device, create_info->imageFormat, create_info->imageUsage,
&legacy_usage);
@@ -1361,8 +1384,9 @@
ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result);
return VK_ERROR_SURFACE_LOST_KHR;
}
+ native_usage = static_cast<uint64_t>(legacy_usage);
}
- uint64_t native_usage = static_cast<uint64_t>(legacy_usage);
+ native_usage |= surface.consumer_usage;
bool createProtectedSwapchain = false;
if (create_info->flags & VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR) {