Merge "Do not load keylayout if required kernel module is missing"
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 1c3a4f2..a417493 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -292,12 +292,9 @@
write /sys/kernel/tracing/synthetic_events "rss_stat_throttled unsigned int mm_id; unsigned int curr; int member; long size"
write /sys/kernel/debug/tracing/synthetic_events "rss_stat_throttled unsigned int mm_id; unsigned int curr; int member; long size"
-# Set up histogram triggers
- # rss_stat_throttled (bucket size == 512KB)
- chmod 0666 /sys/kernel/tracing/events/kmem/rss_stat/trigger
+ # allow creating event triggers
chmod 0666 /sys/kernel/debug/tracing/events/kmem/rss_stat/trigger
- write /sys/kernel/tracing/events/kmem/rss_stat/trigger "hist:keys=mm_id,member:bucket=size/0x80000:onchange($$bucket).rss_stat_throttled(mm_id,curr,member,size)"
- write /sys/kernel/debug/tracing/events/kmem/rss_stat/trigger "hist:keys=mm_id,member:bucket=size/0x80000:onchange($$bucket).rss_stat_throttled(mm_id,curr,member,size)"
+ chmod 0666 /sys/kernel/tracing/events/kmem/rss_stat/trigger
# Only create the tracing instance if persist.mm_events.enabled
# Attempting to remove the tracing instance after it has been created
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index f0b2b28..942a17e 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2106,7 +2106,7 @@
int timeout_failures = 0;
bool dalvik_found = false;
- const std::set<int> hal_pids = get_interesting_hal_pids();
+ const std::set<int> hal_pids = get_interesting_pids();
struct dirent* d;
while ((d = readdir(proc.get()))) {
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index 49c1318..f0c19b9 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -65,6 +65,7 @@
const sp<LocalRegistrationCallback>&));
MOCK_METHOD2(unregisterForNotifications, status_t(const String16&,
const sp<LocalRegistrationCallback>&));
+ MOCK_METHOD0(getServiceDebugInfo, std::vector<ServiceDebugInfo>());
protected:
MOCK_METHOD0(onAsBinder, IBinder*());
};
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 21d98e0..6d3c88d 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -216,6 +216,7 @@
"abseil-*",
"android-*",
"bugprone-*",
+ "-bugprone-branch-clone", // b/155034972
"cert-*",
"clang-analyzer-*",
"google-*",
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index ea2f8d2..fd2d868 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -99,6 +99,8 @@
status_t unregisterForNotifications(const String16& service,
const sp<AidlRegistrationCallback>& cb) override;
+
+ std::vector<IServiceManager::ServiceDebugInfo> getServiceDebugInfo() override;
// for legacy ABI
const String16& getInterfaceDescriptor() const override {
return mTheRealServiceManager->getInterfaceDescriptor();
@@ -543,6 +545,23 @@
return OK;
}
+std::vector<IServiceManager::ServiceDebugInfo> ServiceManagerShim::getServiceDebugInfo() {
+ std::vector<os::ServiceDebugInfo> serviceDebugInfos;
+ std::vector<IServiceManager::ServiceDebugInfo> ret;
+ if (Status status = mTheRealServiceManager->getServiceDebugInfo(&serviceDebugInfos);
+ !status.isOk()) {
+ ALOGW("%s Failed to get ServiceDebugInfo", __FUNCTION__);
+ return ret;
+ }
+ for (const auto& serviceDebugInfo : serviceDebugInfos) {
+ IServiceManager::ServiceDebugInfo retInfo;
+ retInfo.pid = serviceDebugInfo.debugPid;
+ retInfo.name = serviceDebugInfo.name;
+ ret.emplace_back(retInfo);
+ }
+ return ret;
+}
+
#ifndef __ANDROID__
// ServiceManagerShim for host. Implements the old libbinder android::IServiceManager API.
// The internal implementation of the AIDL interface android::os::IServiceManager calls into
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index f5de5b1..419df86 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -27,6 +27,7 @@
#include "Debug.h"
#include "RpcWireFormat.h"
+#include "Utils.h"
#include <random>
@@ -493,9 +494,15 @@
}
}
+ // objectTable always empty for now. Will be populated from `data` soon.
+ std::vector<uint32_t> objectTable;
+ Span<const uint32_t> objectTableSpan = {objectTable.data(), objectTable.size()};
+
uint32_t bodySize;
LOG_ALWAYS_FATAL_IF(__builtin_add_overflow(sizeof(RpcWireTransaction), data.dataSize(),
- &bodySize),
+ &bodySize) ||
+ __builtin_add_overflow(objectTableSpan.byteSize(), bodySize,
+ &bodySize),
"Too much data %zu", data.dataSize());
RpcWireHeader command{
.command = RPC_COMMAND_TRANSACT,
@@ -507,6 +514,8 @@
.code = code,
.flags = flags,
.asyncNumber = asyncNumber,
+ // bodySize didn't overflow => this cast is safe
+ .parcelDataSize = static_cast<uint32_t>(data.dataSize()),
};
constexpr size_t kWaitMaxUs = 1000000;
@@ -521,6 +530,7 @@
{&command, sizeof(RpcWireHeader)},
{&transaction, sizeof(RpcWireTransaction)},
{const_cast<uint8_t*>(data.data()), data.dataSize()},
+ objectTableSpan.toIovec(),
};
if (status_t status = rpcSend(connection, session, "transaction", iovs, arraysize(iovs),
[&] {
@@ -585,7 +595,9 @@
return status;
}
- if (command.bodySize < sizeof(RpcWireReply)) {
+ const size_t rpcReplyWireSize = RpcWireReply::wireSize(session->getProtocolVersion().value());
+
+ if (command.bodySize < rpcReplyWireSize) {
ALOGE("Expecting %zu but got %" PRId32 " bytes for RpcWireReply. Terminating!",
sizeof(RpcWireReply), command.bodySize);
(void)session->shutdownAndWait(false);
@@ -593,11 +605,13 @@
}
RpcWireReply rpcReply;
- CommandData data(command.bodySize - sizeof(RpcWireReply));
+ memset(&rpcReply, 0, sizeof(RpcWireReply)); // zero because of potential short read
+
+ CommandData data(command.bodySize - rpcReplyWireSize);
if (!data.valid()) return NO_MEMORY;
iovec iovs[]{
- {&rpcReply, sizeof(RpcWireReply)},
+ {&rpcReply, rpcReplyWireSize},
{data.data(), data.size()},
};
if (status_t status = rpcRec(connection, session, "reply body", iovs, arraysize(iovs));
@@ -605,11 +619,15 @@
return status;
if (rpcReply.status != OK) return rpcReply.status;
- uint8_t* parcelData = data.data();
- size_t parcelDataSize = data.size();
- data.release();
- reply->rpcSetDataReference(session, parcelData, parcelDataSize, cleanup_reply_data);
+ Span<const uint8_t> parcelSpan = {data.data(), data.size()};
+ if (session->getProtocolVersion().value() >=
+ RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_FEATURE_EXPLICIT_PARCEL_SIZE) {
+ Span<const uint8_t> objectTableBytes = parcelSpan.splitOff(rpcReply.parcelDataSize);
+ LOG_ALWAYS_FATAL_IF(objectTableBytes.size > 0, "Non-empty object table not supported yet.");
+ }
+ data.release();
+ reply->rpcSetDataReference(session, parcelSpan.data, parcelSpan.size, cleanup_reply_data);
return OK;
}
@@ -824,12 +842,22 @@
reply.markForRpc(session);
if (replyStatus == OK) {
+ Span<const uint8_t> parcelSpan = {transaction->data,
+ transactionData.size() -
+ offsetof(RpcWireTransaction, data)};
+ if (session->getProtocolVersion().value() >=
+ RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_FEATURE_EXPLICIT_PARCEL_SIZE) {
+ Span<const uint8_t> objectTableBytes = parcelSpan.splitOff(transaction->parcelDataSize);
+ LOG_ALWAYS_FATAL_IF(objectTableBytes.size > 0,
+ "Non-empty object table not supported yet.");
+ }
+
Parcel data;
// transaction->data is owned by this function. Parcel borrows this data and
// only holds onto it for the duration of this function call. Parcel will be
// deleted before the 'transactionData' object.
- data.rpcSetDataReference(session, transaction->data,
- transactionData.size() - offsetof(RpcWireTransaction, data),
+
+ data.rpcSetDataReference(session, parcelSpan.data, parcelSpan.size,
do_nothing_to_transact_data);
if (target) {
@@ -941,8 +969,16 @@
replyStatus = flushExcessBinderRefs(session, addr, target);
}
+ const size_t rpcReplyWireSize = RpcWireReply::wireSize(session->getProtocolVersion().value());
+
+ // objectTable always empty for now. Will be populated from `reply` soon.
+ std::vector<uint32_t> objectTable;
+ Span<const uint32_t> objectTableSpan = {objectTable.data(), objectTable.size()};
+
uint32_t bodySize;
- LOG_ALWAYS_FATAL_IF(__builtin_add_overflow(sizeof(RpcWireReply), reply.dataSize(), &bodySize),
+ LOG_ALWAYS_FATAL_IF(__builtin_add_overflow(rpcReplyWireSize, reply.dataSize(), &bodySize) ||
+ __builtin_add_overflow(objectTableSpan.byteSize(), bodySize,
+ &bodySize),
"Too much data for reply %zu", reply.dataSize());
RpcWireHeader cmdReply{
.command = RPC_COMMAND_REPLY,
@@ -950,12 +986,17 @@
};
RpcWireReply rpcReply{
.status = replyStatus,
+ // NOTE: Not necessarily written to socket depending on session
+ // version.
+ // NOTE: bodySize didn't overflow => this cast is safe
+ .parcelDataSize = static_cast<uint32_t>(reply.dataSize()),
+ .reserved = {0, 0, 0},
};
-
iovec iovs[]{
{&cmdReply, sizeof(RpcWireHeader)},
- {&rpcReply, sizeof(RpcWireReply)},
+ {&rpcReply, rpcReplyWireSize},
{const_cast<uint8_t*>(reply.data()), reply.dataSize()},
+ objectTableSpan.toIovec(),
};
return rpcSend(connection, session, "reply", iovs, arraysize(iovs), std::nullopt);
}
diff --git a/libs/binder/RpcWireFormat.h b/libs/binder/RpcWireFormat.h
index d9b5ca0..7e2aa79 100644
--- a/libs/binder/RpcWireFormat.h
+++ b/libs/binder/RpcWireFormat.h
@@ -131,7 +131,10 @@
uint64_t asyncNumber;
- uint32_t reserved[4];
+ // The size of the Parcel data directly following RpcWireTransaction.
+ uint32_t parcelDataSize;
+
+ uint32_t reserved[3];
uint8_t data[];
};
@@ -139,8 +142,23 @@
struct RpcWireReply {
int32_t status; // transact return
+
+ // -- Fields below only transmitted starting at protocol version 1 --
+
+ // The size of the Parcel data directly following RpcWireReply.
+ uint32_t parcelDataSize;
+
+ uint32_t reserved[3];
+
+ // Byte size of RpcWireReply in the wire protocol.
+ static size_t wireSize(uint32_t protocolVersion) {
+ if (protocolVersion == 0) {
+ return sizeof(int32_t);
+ }
+ return sizeof(RpcWireReply);
+ }
};
-static_assert(sizeof(RpcWireReply) == 4);
+static_assert(sizeof(RpcWireReply) == 20);
#pragma clang diagnostic pop
diff --git a/libs/binder/Utils.h b/libs/binder/Utils.h
index 150d520..7dcb70e 100644
--- a/libs/binder/Utils.h
+++ b/libs/binder/Utils.h
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-#include <cstdint>
#include <stddef.h>
+#include <cstdint>
+#include <optional>
#include <android-base/result.h>
#include <android-base/unique_fd.h>
@@ -39,4 +40,26 @@
status_t getRandomBytes(uint8_t* data, size_t size);
+// View of contiguous sequence. Similar to std::span.
+template <typename T>
+struct Span {
+ T* data = nullptr;
+ size_t size = 0;
+
+ size_t byteSize() { return size * sizeof(T); }
+
+ iovec toIovec() { return {const_cast<std::remove_const_t<T>*>(data), byteSize()}; }
+
+ // Truncates `this` to a length of `offset` and returns a span with the
+ // remainder.
+ //
+ // Aborts if offset > size.
+ Span<T> splitOff(size_t offset) {
+ LOG_ALWAYS_FATAL_IF(offset > size);
+ Span<T> rest = {data + offset, size - offset};
+ size = offset;
+ return rest;
+ }
+};
+
} // namespace android
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index bb55831..413c97f 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -134,6 +134,12 @@
virtual status_t unregisterForNotifications(const String16& name,
const sp<LocalRegistrationCallback>& callback) = 0;
+
+ struct ServiceDebugInfo {
+ std::string name;
+ int pid;
+ };
+ virtual std::vector<ServiceDebugInfo> getServiceDebugInfo() = 0;
};
sp<IServiceManager> defaultServiceManager();
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index cb81584..e76b140 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -38,7 +38,13 @@
constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_NEXT = 1;
constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL = 0xF0000000;
-constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION = 0;
+constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION = RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL;
+
+// Starting with this version:
+//
+// * RpcWireReply is larger (4 bytes -> 20).
+// * RpcWireTransaction and RpcWireReplyV1 include the parcel data size.
+constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_FEATURE_EXPLICIT_PARCEL_SIZE = 1;
/**
* This represents a session (group of connections) between a client
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 79c8c8f..32e018d 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -113,6 +113,7 @@
"abseil-*",
"android-*",
"bugprone-*",
+ "-bugprone-branch-clone", // b/155034972
"cert-*",
"clang-analyzer-*",
"-clang-analyzer-core.CallAndMessage",
diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs
index b7c7ae4..3edeebf 100644
--- a/libs/binder/rust/src/native.rs
+++ b/libs/binder/rust/src/native.rs
@@ -335,11 +335,16 @@
// We don't own this file, so we need to be careful not to drop it.
let file = ManuallyDrop::new(File::from_raw_fd(fd));
- if args.is_null() {
+ if args.is_null() && num_args != 0 {
return StatusCode::UNEXPECTED_NULL as status_t;
}
- let args = slice::from_raw_parts(args, num_args as usize);
- let args: Vec<_> = args.iter().map(|s| CStr::from_ptr(*s)).collect();
+
+ let args = if args.is_null() || num_args == 0 {
+ vec![]
+ } else {
+ slice::from_raw_parts(args, num_args as usize)
+ .iter().map(|s| CStr::from_ptr(*s)).collect()
+ };
let object = sys::AIBinder_getUserData(binder);
let binder: &T = &*(object as *const T);
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 0247e42..5161469 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -99,17 +99,19 @@
EXPECT_DEATH(p.markForBinder(sp<BBinder>::make()), "");
}
-class BinderRpcSimple : public ::testing::TestWithParam<RpcSecurity> {
+class BinderRpcServerOnly : public ::testing::TestWithParam<std::tuple<RpcSecurity, uint32_t>> {
public:
static std::string PrintTestParam(const ::testing::TestParamInfo<ParamType>& info) {
- return newFactory(info.param)->toCString();
+ return std::string(newFactory(std::get<0>(info.param))->toCString()) + "_serverV" +
+ std::to_string(std::get<1>(info.param));
}
};
-TEST_P(BinderRpcSimple, SetExternalServerTest) {
+TEST_P(BinderRpcServerOnly, SetExternalServerTest) {
base::unique_fd sink(TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)));
int sinkFd = sink.get();
- auto server = RpcServer::make(newFactory(GetParam()));
+ auto server = RpcServer::make(newFactory(std::get<0>(GetParam())));
+ server->setProtocolVersion(std::get<1>(GetParam()));
ASSERT_FALSE(server->hasServer());
ASSERT_EQ(OK, server->setupExternalServer(std::move(sink)));
ASSERT_TRUE(server->hasServer());
@@ -480,7 +482,8 @@
return serverFd;
}
-class BinderRpc : public ::testing::TestWithParam<std::tuple<SocketType, RpcSecurity>> {
+class BinderRpc
+ : public ::testing::TestWithParam<std::tuple<SocketType, RpcSecurity, uint32_t, uint32_t>> {
public:
struct Options {
size_t numThreads = 1;
@@ -490,8 +493,9 @@
};
static inline std::string PrintParamInfo(const testing::TestParamInfo<ParamType>& info) {
- auto [type, security] = info.param;
- return PrintToString(type) + "_" + newFactory(security)->toCString();
+ auto [type, security, clientVersion, serverVersion] = info.param;
+ return PrintToString(type) + "_" + newFactory(security)->toCString() + "_clientV" +
+ std::to_string(clientVersion) + "_serverV" + std::to_string(serverVersion);
}
static inline void writeString(android::base::borrowed_fd fd, std::string_view str) {
@@ -533,16 +537,19 @@
SocketType socketType = std::get<0>(GetParam());
RpcSecurity rpcSecurity = std::get<1>(GetParam());
+ uint32_t clientVersion = std::get<2>(GetParam());
+ uint32_t serverVersion = std::get<3>(GetParam());
unsigned int vsockPort = allocateVsockPort();
std::string addr = allocateSocketAddress();
auto ret = ProcessSession{
- .host = Process([&](android::base::borrowed_fd writeEnd,
+ .host = Process([=](android::base::borrowed_fd writeEnd,
android::base::borrowed_fd readEnd) {
auto certVerifier = std::make_shared<RpcCertificateVerifierSimple>();
sp<RpcServer> server = RpcServer::make(newFactory(rpcSecurity, certVerifier));
+ server->setProtocolVersion(serverVersion);
server->setMaxThreads(options.numThreads);
unsigned int outPort = 0;
@@ -618,6 +625,7 @@
status_t status;
for (const auto& session : sessions) {
+ CHECK(session->setProtocolVersion(clientVersion));
session->setMaxIncomingThreads(options.numIncomingConnections);
session->setMaxOutgoingThreads(options.numOutgoingConnections);
@@ -755,7 +763,7 @@
p1.markForBinder(proc1.rootBinder);
p1.writeInt32(3);
- EXPECT_EQ(BAD_TYPE, p1.appendFrom(&pRaw, 0, p1.dataSize()));
+ EXPECT_EQ(BAD_TYPE, p1.appendFrom(&pRaw, 0, pRaw.dataSize()));
EXPECT_EQ(BAD_TYPE, pRaw.appendFrom(&p1, 0, p1.dataSize()));
Parcel p2;
@@ -1420,9 +1428,20 @@
return ret;
}
+static std::vector<uint32_t> testVersions() {
+ std::vector<uint32_t> versions;
+ for (size_t i = 0; i < RPC_WIRE_PROTOCOL_VERSION_NEXT; i++) {
+ versions.push_back(i);
+ }
+ versions.push_back(RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL);
+ return versions;
+}
+
INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpc,
::testing::Combine(::testing::ValuesIn(testSocketTypes()),
- ::testing::ValuesIn(RpcSecurityValues())),
+ ::testing::ValuesIn(RpcSecurityValues()),
+ ::testing::ValuesIn(testVersions()),
+ ::testing::ValuesIn(testVersions())),
BinderRpc::PrintParamInfo);
class BinderRpcServerRootObject
@@ -1476,9 +1495,10 @@
bool mValue = false;
};
-TEST_P(BinderRpcSimple, Shutdown) {
+TEST_P(BinderRpcServerOnly, Shutdown) {
auto addr = allocateSocketAddress();
- auto server = RpcServer::make(newFactory(GetParam()));
+ auto server = RpcServer::make(newFactory(std::get<0>(GetParam())));
+ server->setProtocolVersion(std::get<1>(GetParam()));
ASSERT_EQ(OK, server->setupUnixDomainServer(addr.c_str()));
auto joinEnds = std::make_shared<OneOffSignal>();
@@ -1548,12 +1568,17 @@
ASSERT_EQ(OK, rpcBinder->pingBinder());
}
-INSTANTIATE_TEST_CASE_P(BinderRpc, BinderRpcSimple, ::testing::ValuesIn(RpcSecurityValues()),
- BinderRpcSimple::PrintTestParam);
+INSTANTIATE_TEST_CASE_P(BinderRpc, BinderRpcServerOnly,
+ ::testing::Combine(::testing::ValuesIn(RpcSecurityValues()),
+ ::testing::ValuesIn(testVersions())),
+ BinderRpcServerOnly::PrintTestParam);
class RpcTransportTestUtils {
public:
- using Param = std::tuple<SocketType, RpcSecurity, std::optional<RpcCertificateFormat>>;
+ // Only parameterized only server version because `RpcSession` is bypassed
+ // in the client half of the tests.
+ using Param =
+ std::tuple<SocketType, RpcSecurity, std::optional<RpcCertificateFormat>, uint32_t>;
using ConnectToServer = std::function<base::unique_fd()>;
// A server that handles client socket connections.
@@ -1565,8 +1590,9 @@
[[nodiscard]] AssertionResult setUp(
const Param& param,
std::unique_ptr<RpcAuth> auth = std::make_unique<RpcAuthSelfSigned>()) {
- auto [socketType, rpcSecurity, certificateFormat] = param;
+ auto [socketType, rpcSecurity, certificateFormat, serverVersion] = param;
auto rpcServer = RpcServer::make(newFactory(rpcSecurity));
+ rpcServer->setProtocolVersion(serverVersion);
switch (socketType) {
case SocketType::PRECONNECTED: {
return AssertionFailure() << "Not supported by this test";
@@ -1696,7 +1722,8 @@
explicit Client(ConnectToServer connectToServer) : mConnectToServer(connectToServer) {}
Client(Client&&) = default;
[[nodiscard]] AssertionResult setUp(const Param& param) {
- auto [socketType, rpcSecurity, certificateFormat] = param;
+ auto [socketType, rpcSecurity, certificateFormat, serverVersion] = param;
+ (void)serverVersion;
mFdTrigger = FdTrigger::make();
mCtx = newFactory(rpcSecurity, mCertVerifier)->newClientCtx();
if (mCtx == nullptr) return AssertionFailure() << "newClientCtx";
@@ -1767,23 +1794,28 @@
using Server = RpcTransportTestUtils::Server;
using Client = RpcTransportTestUtils::Client;
static inline std::string PrintParamInfo(const testing::TestParamInfo<ParamType>& info) {
- auto [socketType, rpcSecurity, certificateFormat] = info.param;
+ auto [socketType, rpcSecurity, certificateFormat, serverVersion] = info.param;
auto ret = PrintToString(socketType) + "_" + newFactory(rpcSecurity)->toCString();
if (certificateFormat.has_value()) ret += "_" + PrintToString(*certificateFormat);
+ ret += "_serverV" + std::to_string(serverVersion);
return ret;
}
static std::vector<ParamType> getRpcTranportTestParams() {
std::vector<ParamType> ret;
- for (auto socketType : testSocketTypes(false /* hasPreconnected */)) {
- for (auto rpcSecurity : RpcSecurityValues()) {
- switch (rpcSecurity) {
- case RpcSecurity::RAW: {
- ret.emplace_back(socketType, rpcSecurity, std::nullopt);
- } break;
- case RpcSecurity::TLS: {
- ret.emplace_back(socketType, rpcSecurity, RpcCertificateFormat::PEM);
- ret.emplace_back(socketType, rpcSecurity, RpcCertificateFormat::DER);
- } break;
+ for (auto serverVersion : testVersions()) {
+ for (auto socketType : testSocketTypes(false /* hasPreconnected */)) {
+ for (auto rpcSecurity : RpcSecurityValues()) {
+ switch (rpcSecurity) {
+ case RpcSecurity::RAW: {
+ ret.emplace_back(socketType, rpcSecurity, std::nullopt, serverVersion);
+ } break;
+ case RpcSecurity::TLS: {
+ ret.emplace_back(socketType, rpcSecurity, RpcCertificateFormat::PEM,
+ serverVersion);
+ ret.emplace_back(socketType, rpcSecurity, RpcCertificateFormat::DER,
+ serverVersion);
+ } break;
+ }
}
}
}
@@ -1791,7 +1823,8 @@
}
template <typename A, typename B>
status_t trust(const A& a, const B& b) {
- auto [socketType, rpcSecurity, certificateFormat] = GetParam();
+ auto [socketType, rpcSecurity, certificateFormat, serverVersion] = GetParam();
+ (void)serverVersion;
return RpcTransportTestUtils::trust(rpcSecurity, certificateFormat, a, b);
}
};
@@ -1827,7 +1860,8 @@
}
TEST_P(RpcTransportTest, UntrustedServer) {
- auto [socketType, rpcSecurity, certificateFormat] = GetParam();
+ auto [socketType, rpcSecurity, certificateFormat, serverVersion] = GetParam();
+ (void)serverVersion;
auto untrustedServer = std::make_unique<Server>();
ASSERT_TRUE(untrustedServer->setUp(GetParam()));
@@ -1845,7 +1879,9 @@
client.run(handshakeOk);
}
TEST_P(RpcTransportTest, MaliciousServer) {
- auto [socketType, rpcSecurity, certificateFormat] = GetParam();
+ auto [socketType, rpcSecurity, certificateFormat, serverVersion] = GetParam();
+ (void)serverVersion;
+
auto validServer = std::make_unique<Server>();
ASSERT_TRUE(validServer->setUp(GetParam()));
@@ -1868,7 +1904,9 @@
}
TEST_P(RpcTransportTest, UntrustedClient) {
- auto [socketType, rpcSecurity, certificateFormat] = GetParam();
+ auto [socketType, rpcSecurity, certificateFormat, serverVersion] = GetParam();
+ (void)serverVersion;
+
auto server = std::make_unique<Server>();
ASSERT_TRUE(server->setUp(GetParam()));
@@ -1887,7 +1925,9 @@
}
TEST_P(RpcTransportTest, MaliciousClient) {
- auto [socketType, rpcSecurity, certificateFormat] = GetParam();
+ auto [socketType, rpcSecurity, certificateFormat, serverVersion] = GetParam();
+ (void)serverVersion;
+
auto server = std::make_unique<Server>();
ASSERT_TRUE(server->setUp(GetParam()));
@@ -1973,23 +2013,24 @@
RpcTransportTest::PrintParamInfo);
class RpcTransportTlsKeyTest
- : public testing::TestWithParam<std::tuple<SocketType, RpcCertificateFormat, RpcKeyFormat>> {
+ : public testing::TestWithParam<
+ std::tuple<SocketType, RpcCertificateFormat, RpcKeyFormat, uint32_t>> {
public:
template <typename A, typename B>
status_t trust(const A& a, const B& b) {
- auto [socketType, certificateFormat, keyFormat] = GetParam();
+ auto [socketType, certificateFormat, keyFormat, serverVersion] = GetParam();
+ (void)serverVersion;
return RpcTransportTestUtils::trust(RpcSecurity::TLS, certificateFormat, a, b);
}
static std::string PrintParamInfo(const testing::TestParamInfo<ParamType>& info) {
- auto [socketType, certificateFormat, keyFormat] = info.param;
- auto ret = PrintToString(socketType) + "_certificate_" + PrintToString(certificateFormat) +
- "_key_" + PrintToString(keyFormat);
- return ret;
+ auto [socketType, certificateFormat, keyFormat, serverVersion] = info.param;
+ return PrintToString(socketType) + "_certificate_" + PrintToString(certificateFormat) +
+ "_key_" + PrintToString(keyFormat) + "_serverV" + std::to_string(serverVersion);
};
};
TEST_P(RpcTransportTlsKeyTest, PreSignedCertificate) {
- auto [socketType, certificateFormat, keyFormat] = GetParam();
+ auto [socketType, certificateFormat, keyFormat, serverVersion] = GetParam();
std::vector<uint8_t> pkeyData, certData;
{
@@ -2004,8 +2045,8 @@
auto desPkey = deserializeUnencryptedPrivatekey(pkeyData, keyFormat);
auto desCert = deserializeCertificate(certData, certificateFormat);
auto auth = std::make_unique<RpcAuthPreSigned>(std::move(desPkey), std::move(desCert));
- auto utilsParam =
- std::make_tuple(socketType, RpcSecurity::TLS, std::make_optional(certificateFormat));
+ auto utilsParam = std::make_tuple(socketType, RpcSecurity::TLS,
+ std::make_optional(certificateFormat), serverVersion);
auto server = std::make_unique<RpcTransportTestUtils::Server>();
ASSERT_TRUE(server->setUp(utilsParam, std::move(auth)));
@@ -2024,7 +2065,8 @@
BinderRpc, RpcTransportTlsKeyTest,
testing::Combine(testing::ValuesIn(testSocketTypes(false /* hasPreconnected*/)),
testing::Values(RpcCertificateFormat::PEM, RpcCertificateFormat::DER),
- testing::Values(RpcKeyFormat::PEM, RpcKeyFormat::DER)),
+ testing::Values(RpcKeyFormat::PEM, RpcKeyFormat::DER),
+ testing::ValuesIn(testVersions())),
RpcTransportTlsKeyTest::PrintParamInfo);
} // namespace android
diff --git a/libs/binder/tests/binderRpcWireProtocolTest.cpp b/libs/binder/tests/binderRpcWireProtocolTest.cpp
index 4fcf42d..3dab2c7 100644
--- a/libs/binder/tests/binderRpcWireProtocolTest.cpp
+++ b/libs/binder/tests/binderRpcWireProtocolTest.cpp
@@ -233,11 +233,15 @@
"0100000025000000|03000000|00000000|ffffffff|03000000|00000000|00000000|"
"07000000020000003a0044000000000000000000|f8ffffff020000003a002f00000000000000000008000000";
+TEST(RpcWire, V0) {
+ checkRepr(kCurrentRepr, 0);
+}
+
TEST(RpcWire, CurrentVersion) {
checkRepr(kCurrentRepr, RPC_WIRE_PROTOCOL_VERSION);
}
-static_assert(RPC_WIRE_PROTOCOL_VERSION == 0,
+static_assert(RPC_WIRE_PROTOCOL_VERSION == RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL,
"If the binder wire protocol is updated, this test should test additional versions. "
"The binder wire protocol should only be updated on upstream AOSP.");
diff --git a/libs/dumputils/Android.bp b/libs/dumputils/Android.bp
index acda402..09fbdea 100644
--- a/libs/dumputils/Android.bp
+++ b/libs/dumputils/Android.bp
@@ -26,6 +26,7 @@
shared_libs: [
"libbase",
+ "libbinder",
"libhidlbase",
"liblog",
"libutils",
@@ -33,7 +34,10 @@
srcs: ["dump_utils.cpp"],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
export_include_dirs: [
"include",
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 29c788b..0f1a02a 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -20,6 +20,7 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <binder/IServiceManager.h>
#include <dumputils/dump_utils.h>
#include <log/log.h>
@@ -52,8 +53,8 @@
NULL,
};
-/* list of hal interface to dump containing process during native dumps */
-static const char* hal_interfaces_to_dump[] {
+/* list of hidl hal interface to dump containing process during native dumps */
+static const char* hidl_hal_interfaces_to_dump[] {
"android.hardware.audio@4.0::IDevicesFactory",
"android.hardware.audio@5.0::IDevicesFactory",
"android.hardware.audio@6.0::IDevicesFactory",
@@ -82,6 +83,11 @@
NULL,
};
+/* list of hal interface to dump containing process during native dumps */
+static const std::vector<std::string> aidl_interfaces_to_dump {
+ "android.hardware.camera.provider.ICameraProvider",
+};
+
/* list of extra hal interfaces to dump containing process during native dumps */
// This is filled when dumpstate is called.
static std::set<const std::string> extra_hal_interfaces_to_dump;
@@ -104,7 +110,7 @@
// check if interface is included in either default hal list or extra hal list
bool should_dump_hal_interface(const std::string& interface) {
- for (const char** i = hal_interfaces_to_dump; *i; i++) {
+ for (const char** i = hidl_hal_interfaces_to_dump; *i; i++) {
if (interface == *i) {
return true;
}
@@ -130,14 +136,26 @@
return false;
}
-std::set<int> get_interesting_hal_pids() {
+static void get_interesting_aidl_pids(std::set<int> &pids) {
+ using ServiceDebugInfo = android::IServiceManager::ServiceDebugInfo;
+ auto sm = android::defaultServiceManager();
+ std::vector<ServiceDebugInfo> serviceDebugInfos = sm->getServiceDebugInfo();
+ for (const auto & serviceDebugInfo : serviceDebugInfos) {
+ for (const auto &aidl_prefix : aidl_interfaces_to_dump) {
+ // Check for prefix match with aidl interface to dump
+ if (serviceDebugInfo.name.rfind(aidl_prefix, 0) == 0) {
+ pids.insert(serviceDebugInfo.pid);
+ }
+ }
+ }
+}
+
+static void get_interesting_hidl_pids(std::set<int> &pids) {
using android::hidl::manager::V1_0::IServiceManager;
using android::sp;
using android::hardware::Return;
sp<IServiceManager> manager = IServiceManager::getService();
- std::set<int> pids;
-
read_extra_hals_to_dump_from_property();
Return<void> ret = manager->debugDump([&](auto& hals) {
@@ -146,11 +164,9 @@
continue;
}
- if (!should_dump_hal_interface(info.interfaceName)) {
- continue;
+ if (should_dump_hal_interface(info.interfaceName)) {
+ pids.insert(info.pid);
}
-
- pids.insert(info.pid);
}
});
@@ -158,7 +174,14 @@
ALOGE("Could not get list of HAL PIDs: %s\n", ret.description().c_str());
}
- return pids; // whether it was okay or not
+ return;
+}
+
+std::set<int> get_interesting_pids() {
+ std::set<int> interesting_pids;
+ get_interesting_hidl_pids(interesting_pids);
+ get_interesting_aidl_pids(interesting_pids);
+ return interesting_pids;
}
bool IsZygote(int pid) {
diff --git a/libs/dumputils/include/dumputils/dump_utils.h b/libs/dumputils/include/dumputils/dump_utils.h
index 25f7127..7c5329d 100644
--- a/libs/dumputils/include/dumputils/dump_utils.h
+++ b/libs/dumputils/include/dumputils/dump_utils.h
@@ -21,7 +21,7 @@
bool should_dump_native_traces(const char* path);
-std::set<int> get_interesting_hal_pids();
+std::set<int> get_interesting_pids();
bool IsZygote(int pid);
diff --git a/libs/fakeservicemanager/ServiceManager.cpp b/libs/fakeservicemanager/ServiceManager.cpp
index 61e4a98..6c6d7f3 100644
--- a/libs/fakeservicemanager/ServiceManager.cpp
+++ b/libs/fakeservicemanager/ServiceManager.cpp
@@ -94,4 +94,8 @@
return INVALID_OPERATION;
}
+std::vector<IServiceManager::ServiceDebugInfo> ServiceManager::getServiceDebugInfo() {
+ std::vector<IServiceManager::ServiceDebugInfo> ret;
+ return ret;
+}
} // namespace android
diff --git a/libs/fakeservicemanager/ServiceManager.h b/libs/fakeservicemanager/ServiceManager.h
index 6d6e008..e0af5d4 100644
--- a/libs/fakeservicemanager/ServiceManager.h
+++ b/libs/fakeservicemanager/ServiceManager.h
@@ -20,6 +20,7 @@
#include <map>
#include <optional>
+#include <vector>
namespace android {
@@ -58,6 +59,9 @@
status_t unregisterForNotifications(const String16& name,
const sp<LocalRegistrationCallback>& callback) override;
+
+ std::vector<IServiceManager::ServiceDebugInfo> getServiceDebugInfo() override;
+
private:
std::map<String16, sp<IBinder>> mNameToService;
};
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 77a883b..bf275a5 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -391,6 +391,71 @@
}
}
+void layer_state_t::sanitize(int32_t permissions) {
+ // TODO: b/109894387
+ //
+ // SurfaceFlinger's renderer is not prepared to handle cropping in the face of arbitrary
+ // rotation. To see the problem observe that if we have a square parent, and a child
+ // of the same size, then we rotate the child 45 degrees around its center, the child
+ // must now be cropped to a non rectangular 8 sided region.
+ //
+ // Of course we can fix this in the future. For now, we are lucky, SurfaceControl is
+ // private API, and arbitrary rotation is used in limited use cases, for instance:
+ // - WindowManager only uses rotation in one case, which is on a top level layer in which
+ // cropping is not an issue.
+ // - Launcher, as a privileged app, uses this to transition an application to PiP
+ // (picture-in-picture) mode.
+ //
+ // However given that abuse of rotation matrices could lead to surfaces extending outside
+ // of cropped areas, we need to prevent non-root clients without permission
+ // ACCESS_SURFACE_FLINGER nor ROTATE_SURFACE_FLINGER
+ // (a.k.a. everyone except WindowManager / tests / Launcher) from setting non rectangle
+ // preserving transformations.
+ if (what & eMatrixChanged) {
+ if (!(permissions & Permission::ROTATE_SURFACE_FLINGER)) {
+ ui::Transform t;
+ t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
+ if (!t.preserveRects()) {
+ what &= ~eMatrixChanged;
+ ALOGE("Stripped non rect preserving matrix in sanitize");
+ }
+ }
+ }
+
+ if (what & layer_state_t::eInputInfoChanged) {
+ if (!(permissions & Permission::ACCESS_SURFACE_FLINGER)) {
+ what &= ~eInputInfoChanged;
+ ALOGE("Stripped attempt to set eInputInfoChanged in sanitize");
+ }
+ }
+ if (what & layer_state_t::eTrustedOverlayChanged) {
+ if (!(permissions & Permission::ACCESS_SURFACE_FLINGER)) {
+ what &= ~eTrustedOverlayChanged;
+ ALOGE("Stripped attempt to set eTrustedOverlay in sanitize");
+ }
+ }
+ if (what & layer_state_t::eDropInputModeChanged) {
+ if (!(permissions & Permission::ACCESS_SURFACE_FLINGER)) {
+ what &= ~eDropInputModeChanged;
+ ALOGE("Stripped attempt to set eDropInputModeChanged in sanitize");
+ }
+ }
+ if (what & layer_state_t::eFrameRateSelectionPriority) {
+ if (!(permissions & Permission::ACCESS_SURFACE_FLINGER)) {
+ what &= ~eFrameRateSelectionPriority;
+ ALOGE("Stripped attempt to set eFrameRateSelectionPriority in sanitize");
+ }
+ }
+ if (what & layer_state_t::eFrameRateChanged) {
+ if (!ValidateFrameRate(frameRate, frameRateCompatibility,
+ changeFrameRateStrategy,
+ "layer_state_t::sanitize",
+ permissions & Permission::ACCESS_SURFACE_FLINGER)) {
+ what &= ~eFrameRateChanged; // logged in ValidateFrameRate
+ }
+ }
+}
+
void layer_state_t::merge(const layer_state_t& other) {
if (other.what & ePositionChanged) {
what |= ePositionChanged;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 725ea65..4bcc9d5 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -551,6 +551,13 @@
mListenerCallbacks = other.mListenerCallbacks;
}
+void SurfaceComposerClient::Transaction::sanitize() {
+ for (auto & [handle, composerState] : mComposerStates) {
+ composerState.state.sanitize(0 /* permissionMask */);
+ }
+ mInputWindowCommands.clear();
+}
+
std::unique_ptr<SurfaceComposerClient::Transaction>
SurfaceComposerClient::Transaction::createFromParcel(const Parcel* parcel) {
auto transaction = std::make_unique<Transaction>();
@@ -635,7 +642,6 @@
if (composerState.read(*parcel) == BAD_VALUE) {
return BAD_VALUE;
}
-
composerStates[surfaceControlHandle] = composerState;
}
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 03e4aac..2a8d30d 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -61,6 +61,12 @@
* Used to communicate layer information between SurfaceFlinger and its clients.
*/
struct layer_state_t {
+ enum Permission {
+ ACCESS_SURFACE_FLINGER = 0x1,
+ ROTATE_SURFACE_FLINGER = 0x2,
+ INTERNAL_SYSTEM_WINDOW = 0x4,
+ };
+
enum {
eLayerHidden = 0x01, // SURFACE_HIDDEN in SurfaceControl.java
eLayerOpaque = 0x02, // SURFACE_OPAQUE
@@ -128,6 +134,7 @@
status_t read(const Parcel& input);
bool hasBufferChanges() const;
bool hasValidBuffer() const;
+ void sanitize(int32_t permissions);
struct matrix22_t {
float dsdx{0};
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 0d1d1a3..76b6d44 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -590,6 +590,14 @@
void setAnimationTransaction();
void setEarlyWakeupStart();
void setEarlyWakeupEnd();
+
+ /**
+ * Strip the transaction of all permissioned requests, required when
+ * accepting transactions across process boundaries.
+ *
+ * TODO (b/213644870): Remove all permissioned things from Transaction
+ */
+ void sanitize();
};
status_t clearLayerFrameStats(const sp<IBinder>& token) const;
diff --git a/services/gpuservice/tests/unittests/GpuMemTest.cpp b/services/gpuservice/tests/unittests/GpuMemTest.cpp
index e916221..36ae179 100644
--- a/services/gpuservice/tests/unittests/GpuMemTest.cpp
+++ b/services/gpuservice/tests/unittests/GpuMemTest.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "gpuservice_unittest"
#include <android-base/stringprintf.h>
+#define BPF_MAP_MAKE_VISIBLE_FOR_TESTING
#include <bpf/BpfMap.h>
#include <gmock/gmock.h>
#include <gpumem/GpuMem.h>
@@ -65,11 +66,11 @@
mTestableGpuMem = TestableGpuMem(mGpuMem.get());
mTestableGpuMem.setInitialized();
errno = 0;
- mTestMap = bpf::BpfMap<uint64_t, uint64_t>(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE,
- BPF_F_NO_PREALLOC);
+ mTestMap = std::move(bpf::BpfMap<uint64_t, uint64_t>(BPF_MAP_TYPE_HASH,
+ TEST_MAP_SIZE,
+ BPF_F_NO_PREALLOC));
EXPECT_EQ(0, errno);
- EXPECT_LE(0, mTestMap.getMap().get());
EXPECT_TRUE(mTestMap.isValid());
}
diff --git a/services/gpuservice/tests/unittests/GpuMemTracerTest.cpp b/services/gpuservice/tests/unittests/GpuMemTracerTest.cpp
index d76f039..5c04210 100644
--- a/services/gpuservice/tests/unittests/GpuMemTracerTest.cpp
+++ b/services/gpuservice/tests/unittests/GpuMemTracerTest.cpp
@@ -17,6 +17,7 @@
#undef LOG_TAG
#define LOG_TAG "gpuservice_unittest"
+#define BPF_MAP_MAKE_VISIBLE_FOR_TESTING
#include <bpf/BpfMap.h>
#include <gpumem/GpuMem.h>
#include <gtest/gtest.h>
@@ -64,11 +65,11 @@
mTestableGpuMem = TestableGpuMem(mGpuMem.get());
errno = 0;
- mTestMap = bpf::BpfMap<uint64_t, uint64_t>(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE,
- BPF_F_NO_PREALLOC);
+ mTestMap = std::move(bpf::BpfMap<uint64_t, uint64_t>(BPF_MAP_TYPE_HASH,
+ TEST_MAP_SIZE,
+ BPF_F_NO_PREALLOC));
EXPECT_EQ(0, errno);
- EXPECT_LE(0, mTestMap.getMap().get());
EXPECT_TRUE(mTestMap.isValid());
}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index da7ff71..f94917c 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1608,8 +1608,10 @@
void Layer::setChildrenDrawingParent(const sp<Layer>& newParent) {
for (const sp<Layer>& child : mDrawingChildren) {
child->mDrawingParent = newParent;
+ const float parentShadowRadius =
+ newParent->canDrawShadows() ? 0.f : newParent->mEffectiveShadowRadius;
child->computeBounds(newParent->mBounds, newParent->mEffectiveTransform,
- newParent->mEffectiveShadowRadius);
+ parentShadowRadius);
}
}
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 46a6cfb..e60625b 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -805,10 +805,6 @@
}
}
- // NOTE: Any new formats that are added must be coordinated across different
- // Android users. This includes the ANGLE team (a layered implementation of
- // OpenGL-ES).
-
VkResult result = VK_SUCCESS;
if (formats) {
uint32_t transfer_count = all_formats.size();