diff options
author | android-build-prod (mdb) <android-build-team-robot@google.com> | 2019-10-18 00:22:19 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2019-10-18 00:22:19 +0000 |
commit | b9005758dcf78f89c6640ffb119b5b527a417928 (patch) | |
tree | b5c85684dd6636471f0d6851acc2e28a6bc1ecf9 | |
parent | 9bb24aaa9f968ecc155dfb6e5090b861ace890d9 (diff) | |
parent | bdefb05cd6fb65cb7d5ce0283a099939f396e4c1 (diff) | |
download | native-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.cpp | 4 | ||||
-rw-r--r-- | cmds/dumpsys/dumpsys.cpp | 48 | ||||
-rw-r--r-- | cmds/dumpsys/dumpsys.h | 8 | ||||
-rw-r--r-- | cmds/dumpsys/tests/dumpsys_test.cpp | 25 | ||||
-rw-r--r-- | libs/android_runtime_lazy/Android.bp | 4 | ||||
-rw-r--r-- | libs/binder/BpBinder.cpp | 9 | ||||
-rw-r--r-- | libs/binder/Parcel.cpp | 134 | ||||
-rw-r--r-- | libs/binder/TEST_MAPPING | 6 | ||||
-rw-r--r-- | libs/binder/include/binder/IBinder.h | 6 | ||||
-rw-r--r-- | libs/binder/include/binder/Parcel.h | 99 | ||||
-rw-r--r-- | libs/binder/ndk/ibinder.cpp | 4 | ||||
-rw-r--r-- | libs/binder/ndk/include_ndk/android/binder_auto_utils.h | 17 | ||||
-rw-r--r-- | libs/binder/ndk/include_platform/android/binder_stability.h | 20 | ||||
-rw-r--r-- | libs/binder/ndk/test/Android.bp | 28 | ||||
-rw-r--r-- | libs/binder/ndk/test/AndroidTest.xml | 32 | ||||
-rw-r--r-- | libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl | 19 | ||||
-rw-r--r-- | libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp | 149 | ||||
-rw-r--r-- | libs/nativewindow/AHardwareBuffer.cpp | 8 | ||||
-rw-r--r-- | services/inputflinger/host/InputDriver.cpp | 6 |
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; |