summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-prod (mdb) <android-build-team-robot@google.com>2019-10-18 00:22:19 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2019-10-18 00:22:19 +0000
commitb9005758dcf78f89c6640ffb119b5b527a417928 (patch)
treeb5c85684dd6636471f0d6851acc2e28a6bc1ecf9
parent9bb24aaa9f968ecc155dfb6e5090b861ace890d9 (diff)
parentbdefb05cd6fb65cb7d5ce0283a099939f396e4c1 (diff)
downloadnative-platform-tools-29.0.5.tar.gz
Merge "Snap for 5949240 from a1ebc66b6fe12be1f38ade6cc98f38edc980eb85 to sdk-release" into sdk-releaseplatform-tools-29.0.5
-rw-r--r--cmds/dumpstate/dumpstate.cpp4
-rw-r--r--cmds/dumpsys/dumpsys.cpp48
-rw-r--r--cmds/dumpsys/dumpsys.h8
-rw-r--r--cmds/dumpsys/tests/dumpsys_test.cpp25
-rw-r--r--libs/android_runtime_lazy/Android.bp4
-rw-r--r--libs/binder/BpBinder.cpp9
-rw-r--r--libs/binder/Parcel.cpp134
-rw-r--r--libs/binder/TEST_MAPPING6
-rw-r--r--libs/binder/include/binder/IBinder.h6
-rw-r--r--libs/binder/include/binder/Parcel.h99
-rw-r--r--libs/binder/ndk/ibinder.cpp4
-rw-r--r--libs/binder/ndk/include_ndk/android/binder_auto_utils.h17
-rw-r--r--libs/binder/ndk/include_platform/android/binder_stability.h20
-rw-r--r--libs/binder/ndk/test/Android.bp28
-rw-r--r--libs/binder/ndk/test/AndroidTest.xml32
-rw-r--r--libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl19
-rw-r--r--libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp149
-rw-r--r--libs/nativewindow/AHardwareBuffer.cpp8
-rw-r--r--services/inputflinger/host/InputDriver.cpp6
19 files changed, 490 insertions, 136 deletions
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 739f9ca8e3..67f12e8efe 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1082,7 +1082,7 @@ static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, i
std::string path(title);
path.append(" - ").append(String8(service).c_str());
size_t bytes_written = 0;
- status_t status = dumpsys.startDumpThread(service, args);
+ status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
if (status == OK) {
dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
std::chrono::duration<double> elapsed_seconds;
@@ -1154,7 +1154,7 @@ static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priori
path.append("_HIGH");
}
path.append(kProtoExt);
- status_t status = dumpsys.startDumpThread(service, args);
+ status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
if (status == OK) {
status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
bool dumpTerminated = (status == OK);
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 9f65425a04..abdf168233 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -59,12 +59,13 @@ static void usage() {
"usage: dumpsys\n"
" To dump all services.\n"
"or:\n"
- " dumpsys [-t TIMEOUT] [--priority LEVEL] [--help | -l | --skip SERVICES | "
- "SERVICE [ARGS]]\n"
+ " dumpsys [-t TIMEOUT] [--priority LEVEL] [--pid] [--help | -l | --skip SERVICES "
+ "| SERVICE [ARGS]]\n"
" --help: shows this help\n"
" -l: only list services, do not dump them\n"
" -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n"
" -T TIMEOUT_MS: TIMEOUT to use in milliseconds instead of default 10 seconds\n"
+ " --pid: dump PID instead of usual dump\n"
" --proto: filter services that support dumping data in proto format. Dumps\n"
" will be in proto format.\n"
" --priority LEVEL: filter services based on specified priority\n"
@@ -120,9 +121,11 @@ int Dumpsys::main(int argc, char* const argv[]) {
bool showListOnly = false;
bool skipServices = false;
bool asProto = false;
+ Type type = Type::DUMP;
int timeoutArgMs = 10000;
int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL;
- static struct option longOptions[] = {{"priority", required_argument, 0, 0},
+ static struct option longOptions[] = {{"pid", no_argument, 0, 0},
+ {"priority", required_argument, 0, 0},
{"proto", no_argument, 0, 0},
{"skip", no_argument, 0, 0},
{"help", no_argument, 0, 0},
@@ -157,6 +160,8 @@ int Dumpsys::main(int argc, char* const argv[]) {
usage();
return -1;
}
+ } else if (!strcmp(longOptions[optionIndex].name, "pid")) {
+ type = Type::PID;
}
break;
@@ -246,7 +251,7 @@ int Dumpsys::main(int argc, char* const argv[]) {
const String16& serviceName = services[i];
if (IsSkipped(skippedServices, serviceName)) continue;
- if (startDumpThread(serviceName, args) == OK) {
+ if (startDumpThread(type, serviceName, args) == OK) {
bool addSeparator = (N > 1);
if (addSeparator) {
writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags);
@@ -313,7 +318,18 @@ void Dumpsys::setServiceArgs(Vector<String16>& args, bool asProto, int priorityF
}
}
-status_t Dumpsys::startDumpThread(const String16& serviceName, const Vector<String16>& args) {
+static status_t dumpPidToFd(const sp<IBinder>& service, const unique_fd& fd) {
+ pid_t pid;
+ status_t status = service->getDebugPid(&pid);
+ if (status != OK) {
+ return status;
+ }
+ WriteStringToFd(std::to_string(pid) + "\n", fd.get());
+ return OK;
+}
+
+status_t Dumpsys::startDumpThread(Type type, const String16& serviceName,
+ const Vector<String16>& args) {
sp<IBinder> service = sm_->checkService(serviceName);
if (service == nullptr) {
aerr << "Can't find service: " << serviceName << endl;
@@ -333,16 +349,22 @@ status_t Dumpsys::startDumpThread(const String16& serviceName, const Vector<Stri
// dump blocks until completion, so spawn a thread..
activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable {
- int err = service->dump(remote_end.get(), args);
+ status_t err = 0;
- // It'd be nice to be able to close the remote end of the socketpair before the dump
- // call returns, to terminate our reads if the other end closes their copy of the
- // file descriptor, but then hangs for some reason. There doesn't seem to be a good
- // way to do this, though.
- remote_end.reset();
+ switch (type) {
+ case Type::DUMP:
+ err = service->dump(remote_end.get(), args);
+ break;
+ case Type::PID:
+ err = dumpPidToFd(service, remote_end);
+ break;
+ default:
+ aerr << "Unknown dump type" << static_cast<int>(type) << endl;
+ return;
+ }
- if (err != 0) {
- aerr << "Error dumping service info: (" << strerror(err) << ") "
+ if (err != OK) {
+ aerr << "Error dumping service info status_t: (" << err << ") "
<< serviceName << endl;
}
});
diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h
index c48a1e959b..929c55c364 100644
--- a/cmds/dumpsys/dumpsys.h
+++ b/cmds/dumpsys/dumpsys.h
@@ -51,6 +51,11 @@ class Dumpsys {
*/
static void setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags);
+ enum class Type {
+ DUMP, // dump using `dump` function
+ PID, // dump pid of server only
+ };
+
/**
* Starts a thread to connect to a service and get its dump output. The thread redirects
* the output to a pipe. Thread must be stopped by a subsequent callto {@code
@@ -61,7 +66,8 @@ class Dumpsys {
* {@code NAME_NOT_FOUND} service could not be found.
* {@code != OK} error
*/
- status_t startDumpThread(const String16& serviceName, const Vector<String16>& args);
+ status_t startDumpThread(Type type, const String16& serviceName,
+ const Vector<String16>& args);
/**
* Writes a section header to a file descriptor.
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index cbac839e6f..cf4e0b5a4c 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -194,7 +194,7 @@ class DumpsysTest : public Test {
CaptureStdout();
CaptureStderr();
dump_.setServiceArgs(args, supportsProto, priorityFlags);
- status_t status = dump_.startDumpThread(serviceName, args);
+ status_t status = dump_.startDumpThread(Dumpsys::Type::DUMP, serviceName, args);
EXPECT_THAT(status, Eq(0));
status = dump_.writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(500), false,
elapsedDuration, bytesWritten);
@@ -539,6 +539,27 @@ TEST_F(DumpsysTest, DumpWithPriorityHighAndProto) {
AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH);
}
+// Tests 'dumpsys --pid'
+TEST_F(DumpsysTest, ListAllServicesWithPid) {
+ ExpectListServices({"Locksmith", "Valet"});
+ ExpectCheckService("Locksmith");
+ ExpectCheckService("Valet");
+
+ CallMain({"--pid"});
+
+ AssertRunningServices({"Locksmith", "Valet"});
+ AssertOutputContains(std::to_string(getpid()));
+}
+
+// Tests 'dumpsys --pid service_name'
+TEST_F(DumpsysTest, ListServiceWithPid) {
+ ExpectCheckService("Locksmith");
+
+ CallMain({"--pid", "Locksmith"});
+
+ AssertOutput(std::to_string(getpid()) + "\n");
+}
+
TEST_F(DumpsysTest, GetBytesWritten) {
const char* serviceName = "service2";
const char* dumpContents = "dump1";
@@ -563,4 +584,4 @@ TEST_F(DumpsysTest, WriteDumpWithoutThreadStart) {
dump_.writeDump(STDOUT_FILENO, String16("service"), std::chrono::milliseconds(500),
/* as_proto = */ false, elapsedDuration, bytesWritten);
EXPECT_THAT(status, Eq(INVALID_OPERATION));
-} \ No newline at end of file
+}
diff --git a/libs/android_runtime_lazy/Android.bp b/libs/android_runtime_lazy/Android.bp
index 2d6292c4f7..09a5f39130 100644
--- a/libs/android_runtime_lazy/Android.bp
+++ b/libs/android_runtime_lazy/Android.bp
@@ -52,10 +52,6 @@ cc_library {
"libutils",
],
- required: [
- "libandroid_runtime",
- ],
-
export_include_dirs: [
"include",
],
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 50c7053b13..238c9dcc7f 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -214,16 +214,21 @@ status_t BpBinder::transact(
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
+ bool privateVendor = flags & FLAG_PRIVATE_VENDOR;
+ // don't send userspace flags to the kernel
+ flags = flags & ~FLAG_PRIVATE_VENDOR;
+
// user transactions require a given stability level
if (code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION) {
using android::internal::Stability;
auto stability = Stability::get(this);
+ auto required = privateVendor ? Stability::VENDOR : Stability::kLocalStability;
- if (CC_UNLIKELY(!Stability::check(stability, Stability::kLocalStability))) {
+ if (CC_UNLIKELY(!Stability::check(stability, required))) {
ALOGE("Cannot do a user transaction on a %s binder in a %s context.",
Stability::stabilityString(stability).c_str(),
- Stability::stabilityString(Stability::kLocalStability).c_str());
+ Stability::stabilityString(required).c_str());
return BAD_TYPE;
}
}
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index e5c7d74e23..63456404c0 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -50,10 +50,6 @@
#include <private/binder/binder_module.h>
#include "Static.h"
-#ifndef INT32_MAX
-#define INT32_MAX ((int32_t)(2147483647))
-#endif
-
#define LOG_REFS(...)
//#define LOG_REFS(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOG_ALLOC(...)
@@ -750,61 +746,37 @@ status_t Parcel::writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) {
return writeUtf8AsUtf16(*str);
}
-namespace {
-
-template<typename T>
-status_t writeByteVectorInternal(Parcel* parcel, const std::vector<T>& val)
-{
- status_t status;
- if (val.size() > std::numeric_limits<int32_t>::max()) {
- status = BAD_VALUE;
- return status;
+status_t Parcel::writeByteVectorInternal(const int8_t* data, size_t size) {
+ if (size > std::numeric_limits<int32_t>::max()) {
+ return BAD_VALUE;
}
- status = parcel->writeInt32(val.size());
+ status_t status = writeInt32(size);
if (status != OK) {
return status;
}
- void* data = parcel->writeInplace(val.size());
- if (!data) {
- status = BAD_VALUE;
- return status;
- }
-
- memcpy(data, val.data(), val.size());
- return status;
+ return write(data, size);
}
-template<typename T>
-status_t writeByteVectorInternalPtr(Parcel* parcel,
- const std::unique_ptr<std::vector<T>>& val)
-{
- if (!val) {
- return parcel->writeInt32(-1);
- }
-
- return writeByteVectorInternal(parcel, *val);
-}
-
-} // namespace
-
status_t Parcel::writeByteVector(const std::vector<int8_t>& val) {
- return writeByteVectorInternal(this, val);
+ return writeByteVectorInternal(val.data(), val.size());
}
status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val)
{
- return writeByteVectorInternalPtr(this, val);
+ if (!val) return writeInt32(-1);
+ return writeByteVectorInternal(val->data(), val->size());
}
status_t Parcel::writeByteVector(const std::vector<uint8_t>& val) {
- return writeByteVectorInternal(this, val);
+ return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());
}
status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val)
{
- return writeByteVectorInternalPtr(this, val);
+ if (!val) return writeInt32(-1);
+ return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
}
status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val)
@@ -1477,81 +1449,41 @@ restart_write:
return err;
}
-namespace {
-
-template<typename T>
-status_t readByteVectorInternal(const Parcel* parcel,
- std::vector<T>* val) {
- val->clear();
-
- int32_t size;
- status_t status = parcel->readInt32(&size);
-
- if (status != OK) {
- return status;
- }
-
- if (size < 0) {
- status = UNEXPECTED_NULL;
- return status;
+status_t Parcel::readByteVectorInternal(int8_t* data, size_t size) const {
+ if (size_t(size) > dataAvail()) {
+ return BAD_VALUE;
}
- if (size_t(size) > parcel->dataAvail()) {
- status = BAD_VALUE;
- return status;
- }
-
- T* data = const_cast<T*>(reinterpret_cast<const T*>(parcel->readInplace(size)));
- if (!data) {
- status = BAD_VALUE;
- return status;
- }
- val->reserve(size);
- val->insert(val->end(), data, data + size);
-
- return status;
-}
-
-template<typename T>
-status_t readByteVectorInternalPtr(
- const Parcel* parcel,
- std::unique_ptr<std::vector<T>>* val) {
- const int32_t start = parcel->dataPosition();
- int32_t size;
- status_t status = parcel->readInt32(&size);
- val->reset();
-
- if (status != OK || size < 0) {
- return status;
- }
-
- parcel->setDataPosition(start);
- val->reset(new (std::nothrow) std::vector<T>());
-
- status = readByteVectorInternal(parcel, val->get());
-
- if (status != OK) {
- val->reset();
- }
-
- return status;
+ return read(data, size);
}
-} // namespace
-
status_t Parcel::readByteVector(std::vector<int8_t>* val) const {
- return readByteVectorInternal(this, val);
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ return readByteVectorInternal(val->data(), val->size());
}
status_t Parcel::readByteVector(std::vector<uint8_t>* val) const {
- return readByteVectorInternal(this, val);
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ return readByteVectorInternal(reinterpret_cast<int8_t*>(val->data()), val->size());
}
status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const {
- return readByteVectorInternalPtr(this, val);
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ if (val->get() == nullptr) {
+ // resizeOutVector does not create the out vector if size is < 0.
+ // This occurs when writing a null byte vector.
+ return OK;
+ }
+ return readByteVectorInternal((*val)->data(), (*val)->size());
}
status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const {
- return readByteVectorInternalPtr(this, val);
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ if (val->get() == nullptr) {
+ // resizeOutVector does not create the out vector if size is < 0.
+ // This occurs when writing a null byte vector.
+ return OK;
+ }
+ return readByteVectorInternal(reinterpret_cast<int8_t*>((*val)->data()), (*val)->size());
}
status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const {
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 136bdb0b86..b3afd817c1 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -4,6 +4,9 @@
"name": "binderSafeInterfaceTest"
},
{
+ "name": "binderVendorDoubleLoadTest"
+ },
+ {
"name": "binderDriverInterfaceTest"
},
{
@@ -14,6 +17,9 @@
},
{
"name": "binderStabilityTest"
+ },
+ {
+ "name": "CtsNdkBinderTestCases"
}
]
}
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index 64f305274b..64604b74f0 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -62,7 +62,11 @@ public:
DEBUG_PID_TRANSACTION = B_PACK_CHARS('_', 'P', 'I', 'D'),
// Corresponds to TF_ONE_WAY -- an asynchronous call.
- FLAG_ONEWAY = 0x00000001
+ FLAG_ONEWAY = 0x00000001,
+
+ // Private userspace flag for transaction which is being requested from
+ // a vendor context.
+ FLAG_PRIVATE_VENDOR = 0x10000000,
};
IBinder();
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 87266819e6..0f8ababd6b 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -19,6 +19,7 @@
#include <map> // for legacy reasons
#include <string>
+#include <type_traits>
#include <vector>
#include <android-base/unique_fd.h>
@@ -157,6 +158,18 @@ public:
status_t writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val);
status_t writeStrongBinderVector(const std::vector<sp<IBinder>>& val);
+ // Write an Enum vector with underlying type int8_t.
+ // Does not use padding; each byte is contiguous.
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t writeEnumVector(const std::vector<T>& val);
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val);
+ // Write an Enum vector with underlying type != int8_t.
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t writeEnumVector(const std::vector<T>& val);
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val);
+
template<typename T>
status_t writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val);
template<typename T>
@@ -275,6 +288,19 @@ public:
status_t readStrongBinder(sp<IBinder>* val) const;
status_t readNullableStrongBinder(sp<IBinder>* val) const;
+
+ // Read an Enum vector with underlying type int8_t.
+ // Does not use padding; each byte is contiguous.
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t readEnumVector(std::vector<T>* val) const;
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const;
+ // Read an Enum vector with underlying type != int8_t.
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t readEnumVector(std::vector<T>* val) const;
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const;
+
template<typename T>
status_t readParcelableVector(
std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const;
@@ -438,6 +464,19 @@ private:
status_t writeRawNullableParcelable(const Parcelable*
parcelable);
+ template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0>
+ status_t writeEnum(const T& val);
+ template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0>
+ status_t writeEnum(const T& val);
+
+ template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0>
+ status_t readEnum(T* pArg) const;
+ template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0>
+ status_t readEnum(T* pArg) const;
+
+ status_t writeByteVectorInternal(const int8_t* data, size_t size);
+ status_t readByteVectorInternal(int8_t* data, size_t size) const;
+
template<typename T, typename U>
status_t unsafeReadTypedVector(std::vector<T>* val,
status_t(Parcel::*read_func)(U*) const) const;
@@ -913,6 +952,66 @@ status_t Parcel::writeParcelableVector(const std::shared_ptr<std::vector<std::un
return unsafeWriteTypedVector(*val, &Parcel::writeNullableParcelable<T>);
}
+template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
+status_t Parcel::writeEnum(const T& val) {
+ return writeInt32(static_cast<int32_t>(val));
+}
+template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>>
+status_t Parcel::writeEnum(const T& val) {
+ return writeInt64(static_cast<int64_t>(val));
+}
+
+template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::writeEnumVector(const std::vector<T>& val) {
+ return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) {
+ if (!val) return writeInt32(-1);
+ return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::writeEnumVector(const std::vector<T>& val) {
+ return writeTypedVector(val, &Parcel::writeEnum);
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) {
+ return writeNullableTypedVector(val, &Parcel::writeEnum);
+}
+
+template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
+status_t Parcel::readEnum(T* pArg) const {
+ return readInt32(reinterpret_cast<int32_t *>(pArg));
+}
+template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>>
+status_t Parcel::readEnum(T* pArg) const {
+ return readInt64(reinterpret_cast<int64_t *>(pArg));
+}
+
+template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::readEnumVector(std::vector<T>* val) const {
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ return readByteVectorInternal(reinterpret_cast<int8_t*>(val->data()), val->size());
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ if (val->get() == nullptr) {
+ // resizeOutVector does not create the out vector if size is < 0.
+ // This occurs when writing a null Enum vector.
+ return OK;
+ }
+ return readByteVectorInternal(reinterpret_cast<int8_t*>((*val)->data()), (*val)->size());
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::readEnumVector(std::vector<T>* val) const {
+ return readTypedVector(val, &Parcel::readEnum);
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
+ return readNullableTypedVector(val, &Parcel::readEnum);
+}
+
// ---------------------------------------------------------------------------
inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index b06ca86f57..e752c45d60 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -17,6 +17,7 @@
#include <android/binder_ibinder.h>
#include "ibinder_internal.h"
+#include <android/binder_stability.h>
#include <android/binder_status.h>
#include "parcel_internal.h"
#include "status_internal.h"
@@ -542,7 +543,8 @@ binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, APa
return STATUS_UNKNOWN_TRANSACTION;
}
- if ((flags & ~FLAG_ONEWAY) != 0) {
+ constexpr binder_flags_t kAllFlags = FLAG_PRIVATE_VENDOR | FLAG_ONEWAY;
+ if ((flags & ~kAllFlags) != 0) {
LOG(ERROR) << __func__ << ": Unrecognized flags sent: " << flags;
return STATUS_BAD_VALUE;
}
diff --git a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
index c6868b07ef..dc3c8d2e3a 100644
--- a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -201,7 +201,22 @@ class ScopedAStatus : public impl::ScopedAResource<AStatus*, void, AStatus_delet
/**
* See AStatus_isOk.
*/
- bool isOk() { return get() != nullptr && AStatus_isOk(get()); }
+ bool isOk() const { return get() != nullptr && AStatus_isOk(get()); }
+
+ /**
+ * See AStatus_getExceptionCode
+ */
+ binder_exception_t getExceptionCode() const { return AStatus_getExceptionCode(get()); }
+
+ /**
+ * See AStatus_getServiceSpecificError
+ */
+ int32_t getServiceSpecificError() const { return AStatus_getServiceSpecificError(get()); }
+
+ /**
+ * See AStatus_getStatus
+ */
+ binder_status_t getStatus() const { return AStatus_getStatus(get()); }
/**
* Convenience method for okay status.
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
index b03fce1e39..e1a8cfd1f0 100644
--- a/libs/binder/ndk/include_platform/android/binder_stability.h
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -20,7 +20,21 @@
__BEGIN_DECLS
-#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+/**
+ * Private addition to binder_flag_t.
+ */
+enum {
+ /**
+ * Indicates that this transaction is coupled w/ vendor.img
+ */
+ FLAG_PRIVATE_VENDOR = 0x10000000,
+};
+
+#if (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
+
+enum {
+ FLAG_PRIVATE_LOCAL = FLAG_PRIVATE_VENDOR,
+};
/**
* This interface has the stability of the vendor image.
@@ -33,6 +47,10 @@ static inline void AIBinder_markCompilationUnitStability(AIBinder* binder) {
#else // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+enum {
+ FLAG_PRIVATE_LOCAL = 0,
+};
+
/**
* This interface has the stability of the system image.
*/
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index bb1fe2f8e3..1c5dba3736 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -67,3 +67,31 @@ cc_test {
srcs: ["main_server.cpp"],
gtest: false,
}
+
+cc_test {
+ name: "binderVendorDoubleLoadTest",
+ vendor: true,
+ srcs: [
+ "binderVendorDoubleLoadTest.cpp",
+ ],
+ static_libs: [
+ "IBinderVendorDoubleLoadTest-cpp",
+ "IBinderVendorDoubleLoadTest-ndk_platform",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libbinder_ndk",
+ "libutils",
+ ],
+ test_suites: ["device-tests"],
+}
+
+aidl_interface {
+ name: "IBinderVendorDoubleLoadTest",
+ // TODO(b/119771576): only vendor is needed
+ vendor_available: true,
+ srcs: [
+ "IBinderVendorDoubleLoadTest.aidl",
+ ],
+}
diff --git a/libs/binder/ndk/test/AndroidTest.xml b/libs/binder/ndk/test/AndroidTest.xml
new file mode 100644
index 0000000000..89646f7776
--- /dev/null
+++ b/libs/binder/ndk/test/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 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.
+-->
+<configuration description="Runs binderVendorDoubleLoadTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="binderVendorDoubleLoadTest->/data/nativetest/vendor/binderVendorDoubleLoadTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/nativetest/vendor" />
+ <option name="module-name" value="binderVendorDoubleLoadTest" />
+ </test>
+</configuration>
+
diff --git a/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl b/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl
new file mode 100644
index 0000000000..3a5bd9cc56
--- /dev/null
+++ b/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+interface IBinderVendorDoubleLoadTest {
+ @utf8InCpp String RepeatString(@utf8InCpp String toRepeat);
+}
diff --git a/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp b/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp
new file mode 100644
index 0000000000..f72dc36cfd
--- /dev/null
+++ b/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2019 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 <BnBinderVendorDoubleLoadTest.h>
+#include <aidl/BnBinderVendorDoubleLoadTest.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/binder_stability.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <binder/Stability.h>
+#include <binder/Status.h>
+#include <gtest/gtest.h>
+
+#include <sys/prctl.h>
+
+using namespace android;
+using ::android::base::EndsWith;
+using ::android::base::GetProperty;
+using ::android::base::Split;
+using ::android::binder::Status;
+using ::android::internal::Stability;
+using ::ndk::ScopedAStatus;
+using ::ndk::SharedRefBase;
+using ::ndk::SpAIBinder;
+
+static const std::string kLocalNdkServerName = "NdkServer-local-IBinderVendorDoubleLoadTest";
+static const std::string kRemoteNdkServerName = "NdkServer-remote-IBinderVendorDoubleLoadTest";
+
+class NdkServer : public aidl::BnBinderVendorDoubleLoadTest {
+ ScopedAStatus RepeatString(const std::string& in, std::string* out) override {
+ *out = in;
+ return ScopedAStatus::ok();
+ }
+};
+class CppServer : public BnBinderVendorDoubleLoadTest {
+ Status RepeatString(const std::string& in, std::string* out) override {
+ *out = in;
+ return Status::ok();
+ }
+};
+
+TEST(DoubleBinder, VendorCppCantCallIntoSystem) {
+ Vector<String16> services = defaultServiceManager()->listServices();
+ EXPECT_TRUE(services.empty());
+}
+
+TEST(DoubleBinder, VendorCppCantRegisterService) {
+ sp<CppServer> cppServer = new CppServer;
+ status_t status = defaultServiceManager()->addService(String16("anything"), cppServer);
+ EXPECT_EQ(EX_TRANSACTION_FAILED, status);
+}
+
+TEST(DoubleBinder, CppVendorCantManuallyMarkVintfStability) {
+ // this test also implies that stability logic is turned on in vendor
+ ASSERT_DEATH(
+ {
+ sp<IBinder> binder = new CppServer();
+ Stability::markVintf(binder.get());
+ },
+ "Should only mark known object.");
+}
+
+TEST(DoubleBinder, NdkVendorCantManuallyMarkVintfStability) {
+ // this test also implies that stability logic is turned on in vendor
+ ASSERT_DEATH(
+ {
+ std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
+ AIBinder_markVintfStability(ndkServer->asBinder().get());
+ },
+ "Should only mark known object.");
+}
+
+TEST(DoubleBinder, CallIntoNdk) {
+ for (const std::string& serviceName : {kLocalNdkServerName, kRemoteNdkServerName}) {
+ SpAIBinder binder = SpAIBinder(AServiceManager_checkService(serviceName.c_str()));
+ ASSERT_NE(nullptr, binder.get()) << serviceName;
+ EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get())) << serviceName;
+
+ std::shared_ptr<aidl::IBinderVendorDoubleLoadTest> server =
+ aidl::IBinderVendorDoubleLoadTest::fromBinder(binder);
+
+ ASSERT_NE(nullptr, server.get()) << serviceName;
+
+ EXPECT_EQ(STATUS_OK, AIBinder_ping(server->asBinder().get()));
+
+ std::string outString;
+ ScopedAStatus status = server->RepeatString("foo", &outString);
+ EXPECT_EQ(STATUS_OK, AStatus_getExceptionCode(status.get())) << serviceName;
+ EXPECT_EQ("foo", outString) << serviceName;
+ }
+}
+
+void initDrivers() {
+ // Explicitly instantiated with the same driver that system would use.
+ // __ANDROID_VNDK__ right now uses /dev/vndbinder by default.
+ ProcessState::initWithDriver("/dev/binder");
+ ProcessState::self()->startThreadPool();
+ ABinderProcess_startThreadPool();
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ if (fork() == 0) {
+ // child process
+
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
+
+ initDrivers();
+
+ // REMOTE SERVERS
+ std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
+ CHECK(STATUS_OK == AServiceManager_addService(ndkServer->asBinder().get(),
+ kRemoteNdkServerName.c_str()));
+
+ // OR sleep forever or whatever, it doesn't matter
+ IPCThreadState::self()->joinThreadPool(true);
+ exit(1); // should not reach
+ }
+
+ sleep(1);
+
+ initDrivers();
+
+ // LOCAL SERVERS
+ std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
+ AServiceManager_addService(ndkServer->asBinder().get(), kLocalNdkServerName.c_str());
+
+ return RUN_ALL_TESTS();
+}
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index 9bd30955f3..1ec73ce961 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -266,10 +266,10 @@ int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, int so
char buf[CMSG_SPACE(kFdBufferSize)];
struct msghdr msg = {
- .msg_control = buf,
- .msg_controllen = sizeof(buf),
.msg_iov = &iov[0],
.msg_iovlen = 1,
+ .msg_control = buf,
+ .msg_controllen = sizeof(buf),
};
struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
@@ -306,10 +306,10 @@ int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** out
iov[0].iov_len = kMessageBufferSize;
struct msghdr msg = {
- .msg_control = fdBuf,
- .msg_controllen = sizeof(fdBuf),
.msg_iov = &iov[0],
.msg_iovlen = 1,
+ .msg_control = fdBuf,
+ .msg_controllen = sizeof(fdBuf),
};
int result;
diff --git a/services/inputflinger/host/InputDriver.cpp b/services/inputflinger/host/InputDriver.cpp
index 2f046c3527..683c05d8a0 100644
--- a/services/inputflinger/host/InputDriver.cpp
+++ b/services/inputflinger/host/InputDriver.cpp
@@ -127,10 +127,10 @@ input_device_identifier_t* InputDriver::createDeviceIdentifier(
input_bus_t bus, const char* uniqueId) {
auto identifier = new ::input_device_identifier {
.name = name,
- .productId = productId,
- .vendorId = vendorId,
- .bus = bus,
.uniqueId = uniqueId,
+ .bus = bus,
+ .vendorId = vendorId,
+ .productId = productId,
};
// TODO: store this identifier somewhere
return identifier;