diff options
52 files changed, 987 insertions, 426 deletions
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 9cccd5b14b..584d7c50db 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -253,7 +253,7 @@ int64_t GetModuleMetadataVersion() { MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str()); return 0L; } - MYLOGD("Module metadata package name: %s", package_name.c_str()); + MYLOGD("Module metadata package name: %s\n", package_name.c_str()); int64_t version_code; status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()), &version_code); @@ -300,12 +300,10 @@ static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot( * Returns a vector of dump fds under |dir_path| with a given |file_prefix|. * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime| * is set, the vector only contains files that were written in the last 30 minutes. - * If |limit_by_count| is set, the vector only contains the ten latest files. */ static std::vector<DumpData> GetDumpFds(const std::string& dir_path, const std::string& file_prefix, - bool limit_by_mtime, - bool limit_by_count = true) { + bool limit_by_mtime) { const time_t thirty_minutes_ago = ds.now_ - 60 * 30; std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir); @@ -349,15 +347,6 @@ static std::vector<DumpData> GetDumpFds(const std::string& dir_path, dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime}); } - // Sort in descending modification time so that we only keep the newest - // reports if |limit_by_count| is true. - std::sort(dump_data.begin(), dump_data.end(), - [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; }); - - if (limit_by_count && dump_data.size() > 10) { - dump_data.erase(dump_data.begin() + 10, dump_data.end()); - } - return dump_data; } @@ -887,6 +876,17 @@ static void DoKernelLogcat() { CommandOptions::WithTimeoutInMs(timeout_ms).Build()); } +static void DoSystemLogcat(time_t since) { + char since_str[80]; + strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since)); + + unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"}); + RunCommand("SYSTEM LOG", + {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T", + since_str}, + CommandOptions::WithTimeoutInMs(timeout_ms).Build()); +} + static void DoLogcat() { unsigned long timeout_ms; // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags"); @@ -1083,7 +1083,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; @@ -1155,7 +1155,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); @@ -1377,8 +1377,6 @@ static Dumpstate::RunStatus dumpstate() { ds.TakeScreenshot(); } - DoLogcat(); - AddAnrTraceFiles(); // NOTE: tombstones are always added as separate entries in the zip archive @@ -1535,6 +1533,12 @@ static Dumpstate::RunStatus DumpstateDefault() { // keep the system stats as close to its initial state as possible. RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysCritical); + // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the + // buffer. + DoLogcat(); + // Capture timestamp after first logcat to use in next logcat + time_t logcat_ts = time(nullptr); + /* collect stack traces from Dalvik and native processes (needs root) */ RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpTraces, &dump_traces_path); @@ -1572,12 +1576,19 @@ static Dumpstate::RunStatus DumpstateDefault() { RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"}); } + DumpFile("PSI cpu", "/proc/pressure/cpu"); + DumpFile("PSI memory", "/proc/pressure/memory"); + DumpFile("PSI io", "/proc/pressure/io"); + if (!DropRootUser()) { return Dumpstate::RunStatus::ERROR; } RETURN_IF_USER_DENIED_CONSENT(); - return dumpstate(); + Dumpstate::RunStatus status = dumpstate(); + // Capture logcat since the last time we did it. + DoSystemLogcat(logcat_ts); + return status; } // This method collects common dumpsys for telephony and wifi diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp index 181046a7a7..7e6f6f53e5 100644 --- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp @@ -216,8 +216,8 @@ class ZippedBugreportGenerationTest : public Test { duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); } - static const char* getZipFilePath() { - return ds.GetPath(".zip").c_str(); + static const std::string getZipFilePath() { + return ds.GetPath(".zip"); } }; std::shared_ptr<std::vector<SectionInfo>> ZippedBugreportGenerationTest::sections = @@ -226,12 +226,12 @@ Dumpstate& ZippedBugreportGenerationTest::ds = Dumpstate::GetInstance(); std::chrono::milliseconds ZippedBugreportGenerationTest::duration = 0s; TEST_F(ZippedBugreportGenerationTest, IsGeneratedWithoutErrors) { - EXPECT_EQ(access(getZipFilePath(), F_OK), 0); + EXPECT_EQ(access(getZipFilePath().c_str(), F_OK), 0); } TEST_F(ZippedBugreportGenerationTest, Is3MBto30MBinSize) { struct stat st; - EXPECT_EQ(stat(getZipFilePath(), &st), 0); + EXPECT_EQ(stat(getZipFilePath().c_str(), &st), 0); EXPECT_GE(st.st_size, 3000000 /* 3MB */); EXPECT_LE(st.st_size, 30000000 /* 30MB */); } @@ -250,7 +250,7 @@ class ZippedBugReportContentsTest : public Test { public: ZipArchiveHandle handle; void SetUp() { - ASSERT_EQ(OpenArchive(ZippedBugreportGenerationTest::getZipFilePath(), &handle), 0); + ASSERT_EQ(OpenArchive(ZippedBugreportGenerationTest::getZipFilePath().c_str(), &handle), 0); } void TearDown() { CloseArchive(handle); @@ -314,7 +314,7 @@ TEST_F(ZippedBugReportContentsTest, ContainsSomeFileSystemFiles) { class BugreportSectionTest : public Test { public: static void SetUpTestCase() { - ParseSections(ZippedBugreportGenerationTest::getZipFilePath(), + ParseSections(ZippedBugreportGenerationTest::getZipFilePath().c_str(), ZippedBugreportGenerationTest::sections.get()); } 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/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp index 7eee749be9..838d11d6d8 100644 --- a/cmds/installd/dexopt.cpp +++ b/cmds/installd/dexopt.cpp @@ -303,6 +303,9 @@ static const char* ENABLE_APEX_IMAGE = "enable_apex_image"; // Location of the apex image. static const char* kApexImage = "/system/framework/apex.art"; +// Phenotype property name for enabling profiling the boot class path. +static const char* PROFILE_BOOT_CLASS_PATH = "profilebootclasspath"; + class RunDex2Oat : public ExecVHelper { public: RunDex2Oat(int zip_fd, @@ -402,7 +405,15 @@ class RunDex2Oat : public ExecVHelper { server_configurable_flags::GetServerConfigurableFlag(RUNTIME_NATIVE_BOOT_NAMESPACE, ENABLE_APEX_IMAGE, /*default_value=*/ ""); - if (use_apex_image == "true") { + + std::string profile_boot_class_path = GetProperty("dalvik.vm.profilebootclasspath", ""); + profile_boot_class_path = + server_configurable_flags::GetServerConfigurableFlag( + RUNTIME_NATIVE_BOOT_NAMESPACE, + PROFILE_BOOT_CLASS_PATH, + /*default_value=*/ profile_boot_class_path); + + if (use_apex_image == "true" || profile_boot_class_path == "true") { boot_image = StringPrintf("-Ximage:%s", kApexImage); } else { boot_image = MapPropertyToArg("dalvik.vm.boot-image", "-Ximage:%s"); @@ -709,8 +720,7 @@ class RunProfman : public ExecVHelper { const unique_fd& reference_profile_fd, const std::vector<unique_fd>& apk_fds, const std::vector<std::string>& dex_locations, - bool copy_and_update, - bool store_aggregation_counters) { + bool copy_and_update) { // TODO(calin): Assume for now we run in the bg compile job (which is in // most of the invocation). With the current data flow, is not very easy or @@ -742,10 +752,6 @@ class RunProfman : public ExecVHelper { AddArg("--copy-and-update-profile-key"); } - if (store_aggregation_counters) { - AddArg("--store-aggregation-counters"); - } - // Do not add after dex2oat_flags, they should override others for debugging. PrepareArgs(profman_bin); } @@ -753,14 +759,12 @@ class RunProfman : public ExecVHelper { void SetupMerge(const std::vector<unique_fd>& profiles_fd, const unique_fd& reference_profile_fd, const std::vector<unique_fd>& apk_fds = std::vector<unique_fd>(), - const std::vector<std::string>& dex_locations = std::vector<std::string>(), - bool store_aggregation_counters = false) { + const std::vector<std::string>& dex_locations = std::vector<std::string>()) { SetupArgs(profiles_fd, reference_profile_fd, apk_fds, dex_locations, - /*copy_and_update=*/false, - store_aggregation_counters); + /*copy_and_update=*/false); } void SetupCopyAndUpdate(unique_fd&& profile_fd, @@ -777,8 +781,7 @@ class RunProfman : public ExecVHelper { reference_profile_fd_, apk_fds_, dex_locations, - /*copy_and_update=*/true, - /*store_aggregation_counters=*/false); + /*copy_and_update=*/true); } void SetupDump(const std::vector<unique_fd>& profiles_fd, @@ -792,8 +795,7 @@ class RunProfman : public ExecVHelper { reference_profile_fd, apk_fds, dex_locations, - /*copy_and_update=*/false, - /*store_aggregation_counters=*/false); + /*copy_and_update=*/false); } void Exec() { @@ -2828,8 +2830,7 @@ static bool create_boot_image_profile_snapshot(const std::string& package_name, args.SetupMerge(profiles_fd, snapshot_fd, apk_fds, - dex_locations, - /*store_aggregation_counters=*/true); + dex_locations); pid_t pid = fork(); if (pid == 0) { /* child -- drop privileges before continuing */ diff --git a/cmds/installd/tests/installd_cache_test.cpp b/cmds/installd/tests/installd_cache_test.cpp index db0907017c..5a5cb53431 100644 --- a/cmds/installd/tests/installd_cache_test.cpp +++ b/cmds/installd/tests/installd_cache_test.cpp @@ -67,29 +67,29 @@ bool create_cache_path(char path[PKG_PATH_MAX] ATTRIBUTE_UNUSED, } static void mkdir(const char* path) { - const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str(); - ::mkdir(fullPath, 0755); + const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path); + ::mkdir(fullPath.c_str(), 0755); } static void touch(const char* path, int len, int time) { - const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str(); - int fd = ::open(fullPath, O_RDWR | O_CREAT, 0644); + const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path); + int fd = ::open(fullPath.c_str(), O_RDWR | O_CREAT, 0644); ::fallocate(fd, 0, 0, len); ::close(fd); struct utimbuf times; times.actime = times.modtime = std::time(0) + time; - ::utime(fullPath, ×); + ::utime(fullPath.c_str(), ×); } static int exists(const char* path) { - const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str(); - return ::access(fullPath, F_OK); + const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path); + return ::access(fullPath.c_str(), F_OK); } static int64_t size(const char* path) { - const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str(); + const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path); struct stat buf; - if (!stat(fullPath, &buf)) { + if (!stat(fullPath.c_str(), &buf)) { return buf.st_size; } else { return -1; @@ -107,8 +107,8 @@ static int64_t free() { } static void setxattr(const char* path, const char* key) { - const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str(); - ::setxattr(fullPath, key, "", 0, 0); + const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path); + ::setxattr(fullPath.c_str(), key, "", 0, 0); } class CacheTest : public testing::Test { diff --git a/cmds/servicemanager/Access.cpp b/cmds/servicemanager/Access.cpp index 606477fee7..b7e520f2f1 100644 --- a/cmds/servicemanager/Access.cpp +++ b/cmds/servicemanager/Access.cpp @@ -137,7 +137,7 @@ bool Access::actionAllowed(const CallingContext& sctx, const char* tctx, const c bool Access::actionAllowedFromLookup(const CallingContext& sctx, const std::string& name, const char *perm) { char *tctx = nullptr; - if (selabel_lookup(getSehandle(), &tctx, name.c_str(), 0) != 0) { + if (selabel_lookup(getSehandle(), &tctx, name.c_str(), SELABEL_CTX_ANDROID_SERVICE) != 0) { LOG(ERROR) << "SELinux: No match for " << name << " in service_contexts.\n"; return false; } diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp index 934436847e..934646da41 100644 --- a/cmds/servicemanager/ServiceManager.cpp +++ b/cmds/servicemanager/ServiceManager.cpp @@ -165,7 +165,7 @@ Status ServiceManager::addService(const std::string& name, const sp<IBinder>& bi #endif // !VENDORSERVICEMANAGER // implicitly unlinked when the binder is removed - if (OK != binder->linkToDeath(this)) { + if (binder->remoteBinder() != nullptr && binder->linkToDeath(this) != OK) { LOG(ERROR) << "Could not linkToDeath when adding " << name; return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE); } diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp index 11d43a6ee3..4b12fc6e72 100644 --- a/cmds/servicemanager/main.cpp +++ b/cmds/servicemanager/main.cpp @@ -23,11 +23,12 @@ #include "Access.h" #include "ServiceManager.h" -using ::android::sp; -using ::android::ProcessState; +using ::android::Access; using ::android::IPCThreadState; +using ::android::ProcessState; using ::android::ServiceManager; -using ::android::Access; +using ::android::os::IServiceManager; +using ::android::sp; int main(int argc, char** argv) { if (argc > 2) { @@ -41,6 +42,10 @@ int main(int argc, char** argv) { ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY); sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>()); + if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) { + LOG(ERROR) << "Could not self register servicemanager"; + } + IPCThreadState::self()->setTheContextObject(manager); ps->becomeContextManager(nullptr, nullptr); 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/Android.bp b/libs/binder/Android.bp index 296e3f6c53..2a140f4507 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -71,7 +71,12 @@ cc_library { // libbinder does not offer a stable wire protocol. // if a second copy of it is installed, then it may break after security // or dessert updates. Instead, apex users should use libbinder_ndk. - no_apex: true, + apex_available: [ + "//apex_available:platform", + // TODO(b/139016109) remove these three + "com.android.media.swcodec", + "test_com.android.media.swcodec", + ], srcs: [ "Binder.cpp", @@ -159,3 +164,16 @@ filegroup { ], path: "aidl", } + +aidl_interface { + name: "libbinder_aidl_test_stub", + local_include_dir: "aidl", + srcs: [":libbinder_aidl"], + visibility: [":__subpackages__"], + vendor_available: true, + backend: { + java: { + enabled: false, + }, + }, +} 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/IMemory.cpp b/libs/binder/IMemory.cpp index 094f89f7d9..222b32c921 100644 --- a/libs/binder/IMemory.cpp +++ b/libs/binder/IMemory.cpp @@ -149,6 +149,10 @@ void* IMemory::fastPointer(const sp<IBinder>& binder, ssize_t offset) const return static_cast<char*>(base) + offset; } +void* IMemory::unsecurePointer() const { + return pointer(); +} + void* IMemory::pointer() const { ssize_t offset; sp<IMemoryHeap> heap = getMemory(&offset); diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index ee637e24bf..a30df14bd6 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -43,6 +43,47 @@ namespace android { using AidlServiceManager = android::os::IServiceManager; using android::binder::Status; +// libbinder's IServiceManager.h can't rely on the values generated by AIDL +// because many places use its headers via include_dirs (meaning, without +// declaring the dependency in the build system). So, for now, we can just check +// the values here. +static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_CRITICAL == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL); +static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_HIGH == IServiceManager::DUMP_FLAG_PRIORITY_HIGH); +static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_NORMAL == IServiceManager::DUMP_FLAG_PRIORITY_NORMAL); +static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_DEFAULT == IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT); +static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_ALL == IServiceManager::DUMP_FLAG_PRIORITY_ALL); +static_assert(AidlServiceManager::DUMP_FLAG_PROTO == IServiceManager::DUMP_FLAG_PROTO); + +const String16& IServiceManager::getInterfaceDescriptor() const { + return AidlServiceManager::descriptor; +} +IServiceManager::IServiceManager() {} +IServiceManager::~IServiceManager() {} + +// From the old libbinder IServiceManager interface to IServiceManager. +class ServiceManagerShim : public IServiceManager +{ +public: + explicit ServiceManagerShim (const sp<AidlServiceManager>& impl); + + sp<IBinder> getService(const String16& name) const override; + sp<IBinder> checkService(const String16& name) const override; + status_t addService(const String16& name, const sp<IBinder>& service, + bool allowIsolated, int dumpsysPriority) override; + Vector<String16> listServices(int dumpsysPriority) override; + sp<IBinder> waitForService(const String16& name16) override; + + // for legacy ABI + const String16& getInterfaceDescriptor() const override { + return mTheRealServiceManager->getInterfaceDescriptor(); + } + IBinder* onAsBinder() override { + return IInterface::asBinder(mTheRealServiceManager).get(); + } +private: + sp<AidlServiceManager> mTheRealServiceManager; +}; + sp<IServiceManager> defaultServiceManager() { static Mutex gDefaultServiceManagerLock; @@ -53,8 +94,9 @@ sp<IServiceManager> defaultServiceManager() { AutoMutex _l(gDefaultServiceManagerLock); while (gDefaultServiceManager == nullptr) { - gDefaultServiceManager = interface_cast<IServiceManager>( - ProcessState::self()->getContextObject(nullptr)); + gDefaultServiceManager = new ServiceManagerShim( + interface_cast<AidlServiceManager>( + ProcessState::self()->getContextObject(nullptr))); if (gDefaultServiceManager == nullptr) sleep(1); } @@ -147,142 +189,136 @@ bool checkPermission(const String16& permission, pid_t pid, uid_t uid) // ---------------------------------------------------------------------- -class BpServiceManager : public BpInterface<IServiceManager> +ServiceManagerShim::ServiceManagerShim(const sp<AidlServiceManager>& impl) + : mTheRealServiceManager(impl) +{} + +sp<IBinder> ServiceManagerShim::getService(const String16& name) const { -public: - explicit BpServiceManager(const sp<IBinder>& impl) - : BpInterface<IServiceManager>(impl), - mTheRealServiceManager(interface_cast<AidlServiceManager>(impl)) - { + static bool gSystemBootCompleted = false; + + sp<IBinder> svc = checkService(name); + if (svc != nullptr) return svc; + + const bool isVendorService = + strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0; + const long timeout = uptimeMillis() + 5000; + // Vendor code can't access system properties + if (!gSystemBootCompleted && !isVendorService) { +#ifdef __ANDROID__ + char bootCompleted[PROPERTY_VALUE_MAX]; + property_get("sys.boot_completed", bootCompleted, "0"); + gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false; +#else + gSystemBootCompleted = true; +#endif } + // retry interval in millisecond; note that vendor services stay at 100ms + const long sleepTime = gSystemBootCompleted ? 1000 : 100; - sp<IBinder> getService(const String16& name) const override - { - static bool gSystemBootCompleted = false; + int n = 0; + while (uptimeMillis() < timeout) { + n++; + ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(), + ProcessState::self()->getDriverName().c_str()); + usleep(1000*sleepTime); sp<IBinder> svc = checkService(name); if (svc != nullptr) return svc; + } + ALOGW("Service %s didn't start. Returning NULL", String8(name).string()); + return nullptr; +} - const bool isVendorService = - strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0; - const long timeout = uptimeMillis() + 5000; - // Vendor code can't access system properties - if (!gSystemBootCompleted && !isVendorService) { -#ifdef __ANDROID__ - char bootCompleted[PROPERTY_VALUE_MAX]; - property_get("sys.boot_completed", bootCompleted, "0"); - gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false; -#else - gSystemBootCompleted = true; -#endif - } - // retry interval in millisecond; note that vendor services stay at 100ms - const long sleepTime = gSystemBootCompleted ? 1000 : 100; - - int n = 0; - while (uptimeMillis() < timeout) { - n++; - ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(), - ProcessState::self()->getDriverName().c_str()); - usleep(1000*sleepTime); - - sp<IBinder> svc = checkService(name); - if (svc != nullptr) return svc; - } - ALOGW("Service %s didn't start. Returning NULL", String8(name).string()); +sp<IBinder> ServiceManagerShim::checkService(const String16& name) const +{ + sp<IBinder> ret; + if (!mTheRealServiceManager->checkService(String8(name).c_str(), &ret).isOk()) { return nullptr; } + return ret; +} - sp<IBinder> checkService(const String16& name) const override { - sp<IBinder> ret; - if (!mTheRealServiceManager->checkService(String8(name).c_str(), &ret).isOk()) { - return nullptr; - } - return ret; +status_t ServiceManagerShim::addService(const String16& name, const sp<IBinder>& service, + bool allowIsolated, int dumpsysPriority) +{ + Status status = mTheRealServiceManager->addService( + String8(name).c_str(), service, allowIsolated, dumpsysPriority); + return status.exceptionCode(); +} + +Vector<String16> ServiceManagerShim::listServices(int dumpsysPriority) +{ + std::vector<std::string> ret; + if (!mTheRealServiceManager->listServices(dumpsysPriority, &ret).isOk()) { + return {}; } - status_t addService(const String16& name, const sp<IBinder>& service, - bool allowIsolated, int dumpsysPriority) override { - Status status = mTheRealServiceManager->addService(String8(name).c_str(), service, allowIsolated, dumpsysPriority); - return status.exceptionCode(); + Vector<String16> res; + res.setCapacity(ret.size()); + for (const std::string& name : ret) { + res.push(String16(name.c_str())); } + return res; +} - virtual Vector<String16> listServices(int dumpsysPriority) { - std::vector<std::string> ret; - if (!mTheRealServiceManager->listServices(dumpsysPriority, &ret).isOk()) { - return {}; +sp<IBinder> ServiceManagerShim::waitForService(const String16& name16) +{ + class Waiter : public android::os::BnServiceCallback { + Status onRegistration(const std::string& /*name*/, + const sp<IBinder>& binder) override { + std::unique_lock<std::mutex> lock(mMutex); + mBinder = binder; + lock.unlock(); + mCv.notify_one(); + return Status::ok(); } + public: + sp<IBinder> mBinder; + std::mutex mMutex; + std::condition_variable mCv; + }; - Vector<String16> res; - res.setCapacity(ret.size()); - for (const std::string& name : ret) { - res.push(String16(name.c_str())); - } - return res; + const std::string name = String8(name16).c_str(); + + sp<IBinder> out; + if (!mTheRealServiceManager->getService(name, &out).isOk()) { + return nullptr; } + if(out != nullptr) return out; - sp<IBinder> waitForService(const String16& name16) override { - class Waiter : public android::os::BnServiceCallback { - Status onRegistration(const std::string& /*name*/, - const sp<IBinder>& binder) override { - std::unique_lock<std::mutex> lock(mMutex); - mBinder = binder; - lock.unlock(); - mCv.notify_one(); - return Status::ok(); - } - public: - sp<IBinder> mBinder; - std::mutex mMutex; - std::condition_variable mCv; - }; + sp<Waiter> waiter = new Waiter; + if (!mTheRealServiceManager->registerForNotifications( + name, waiter).isOk()) { + return nullptr; + } - const std::string name = String8(name16).c_str(); + while(true) { + { + std::unique_lock<std::mutex> lock(waiter->mMutex); + using std::literals::chrono_literals::operator""s; + waiter->mCv.wait_for(lock, 1s, [&] { + return waiter->mBinder != nullptr; + }); + if (waiter->mBinder != nullptr) return waiter->mBinder; + } - sp<IBinder> out; + // Handle race condition for lazy services. Here is what can happen: + // - the service dies (not processed by init yet). + // - sm processes death notification. + // - sm gets getService and calls init to start service. + // - init gets the start signal, but the service already appears + // started, so it does nothing. + // - init gets death signal, but doesn't know it needs to restart + // the service + // - we need to request service again to get it to start if (!mTheRealServiceManager->getService(name, &out).isOk()) { return nullptr; } if(out != nullptr) return out; - sp<Waiter> waiter = new Waiter; - if (!mTheRealServiceManager->registerForNotifications( - name, waiter).isOk()) { - return nullptr; - } - - while(true) { - { - std::unique_lock<std::mutex> lock(waiter->mMutex); - using std::literals::chrono_literals::operator""s; - waiter->mCv.wait_for(lock, 1s, [&] { - return waiter->mBinder != nullptr; - }); - if (waiter->mBinder != nullptr) return waiter->mBinder; - } - - // Handle race condition for lazy services. Here is what can happen: - // - the service dies (not processed by init yet). - // - sm processes death notification. - // - sm gets getService and calls init to start service. - // - init gets the start signal, but the service already appears - // started, so it does nothing. - // - init gets death signal, but doesn't know it needs to restart - // the service - // - we need to request service again to get it to start - if (!mTheRealServiceManager->getService(name, &out).isOk()) { - return nullptr; - } - if(out != nullptr) return out; - - ALOGW("Waited one second for %s", name.c_str()); - } + ALOGW("Waited one second for %s", name.c_str()); } - -private: - sp<AidlServiceManager> mTheRealServiceManager; -}; - -IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager"); +} } // namespace android 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/ProcessState.cpp b/libs/binder/ProcessState.cpp index 0336d3ebd4..ea61dc5aff 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -188,6 +188,30 @@ ssize_t ProcessState::getKernelReferences(size_t buf_count, uintptr_t* buf) return count; } +// Queries the driver for the current strong reference count of the node +// that the handle points to. Can only be used by the servicemanager. +// +// Returns -1 in case of failure, otherwise the strong reference count. +ssize_t ProcessState::getStrongRefCountForNodeByHandle(int32_t handle) { + binder_node_info_for_ref info; + memset(&info, 0, sizeof(binder_node_info_for_ref)); + + info.handle = handle; + + status_t result = ioctl(mDriverFD, BINDER_GET_NODE_INFO_FOR_REF, &info); + + if (result != OK) { + static bool logged = false; + if (!logged) { + ALOGW("Kernel does not support BINDER_GET_NODE_INFO_FOR_REF."); + logged = true; + } + return -1; + } + + return info.strong_count; +} + void ProcessState::setCallRestriction(CallRestriction restriction) { LOG_ALWAYS_FATAL_IF(IPCThreadState::selfOrNull() != nullptr, "Call restrictions must be set before the threadpool is started."); 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/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl index 60c2cceaf2..471b63fb5e 100644 --- a/libs/binder/aidl/android/os/IServiceManager.aidl +++ b/libs/binder/aidl/android/os/IServiceManager.aidl @@ -31,22 +31,22 @@ interface IServiceManager { * Must update values in IServiceManager.h */ /* Allows services to dump sections according to priorities. */ - const int DUMP_FLAG_PRIORITY_CRITICAL = 1; // 1 << 0 - const int DUMP_FLAG_PRIORITY_HIGH = 2; // 1 << 1 - const int DUMP_FLAG_PRIORITY_NORMAL = 4; // 1 << 2 + const int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0; + const int DUMP_FLAG_PRIORITY_HIGH = 1 << 1; + const int DUMP_FLAG_PRIORITY_NORMAL = 1 << 2; /** * Services are by default registered with a DEFAULT dump priority. DEFAULT priority has the * same priority as NORMAL priority but the services are not called with dump priority * arguments. */ - const int DUMP_FLAG_PRIORITY_DEFAULT = 8; // 1 << 3 + const int DUMP_FLAG_PRIORITY_DEFAULT = 1 << 3; const int DUMP_FLAG_PRIORITY_ALL = 15; // DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH // | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PRIORITY_DEFAULT; /* Allows services to dump sections in protobuf format. */ - const int DUMP_FLAG_PROTO = 16; // 1 << 4 + const int DUMP_FLAG_PROTO = 1 << 4; /** * Retrieve an existing service called @a name from the 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/IInterface.h b/libs/binder/include/binder/IInterface.h index 5793a1cf6b..28ffa48e32 100644 --- a/libs/binder/include/binder/IInterface.h +++ b/libs/binder/include/binder/IInterface.h @@ -88,8 +88,12 @@ private: \ public: \ +#define __IINTF_CONCAT(x, y) (x ## y) #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \ - const ::android::String16 I##INTERFACE::descriptor(NAME); \ + const ::android::StaticString16 \ + I##INTERFACE##_descriptor_static_str16(__IINTF_CONCAT(u, NAME));\ + const ::android::String16 I##INTERFACE::descriptor( \ + I##INTERFACE##_descriptor_static_str16); \ const ::android::String16& \ I##INTERFACE::getInterfaceDescriptor() const { \ return I##INTERFACE::descriptor; \ diff --git a/libs/binder/include/binder/IMemory.h b/libs/binder/include/binder/IMemory.h index 372802978b..98e92c4441 100644 --- a/libs/binder/include/binder/IMemory.h +++ b/libs/binder/include/binder/IMemory.h @@ -76,6 +76,8 @@ public: // NOLINTNEXTLINE(google-default-arguments) virtual sp<IMemoryHeap> getMemory(ssize_t* offset=nullptr, size_t* size=nullptr) const = 0; + void* unsecurePointer() const; + // helpers void* fastPointer(const sp<IBinder>& heap, ssize_t offset) const; void* pointer() const; diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h index def1bea974..a675513793 100644 --- a/libs/binder/include/binder/IServiceManager.h +++ b/libs/binder/include/binder/IServiceManager.h @@ -26,12 +26,22 @@ namespace android { // ---------------------------------------------------------------------- +/** + * Service manager for C++ services. + * + * IInterface is only for legacy ABI compatibility + */ class IServiceManager : public IInterface { public: - DECLARE_META_INTERFACE(ServiceManager) + // for ABI compatibility + virtual const String16& getInterfaceDescriptor() const; + + IServiceManager(); + virtual ~IServiceManager(); + /** - * Must match values in IServiceManager.java + * Must match values in IServiceManager.aidl */ /* Allows services to dump sections according to priorities. */ static const int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0; 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/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h index f7c38f418d..e57ff1c260 100644 --- a/libs/binder/include/binder/ProcessState.h +++ b/libs/binder/include/binder/ProcessState.h @@ -69,6 +69,14 @@ public: ssize_t getKernelReferences(size_t count, uintptr_t* buf); + // Only usable by the context manager. + // This refcount includes: + // 1. Strong references to the node by this and other processes + // 2. Temporary strong references held by the kernel during a + // transaction on the node. + // It does NOT include local strong references to the node + ssize_t getStrongRefCountForNodeByHandle(int32_t handle); + enum class CallRestriction { // all calls okay NONE, 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..ebd08b2f71 100644 --- a/libs/binder/ndk/test/Android.bp +++ b/libs/binder/ndk/test/Android.bp @@ -67,3 +67,32 @@ cc_test { srcs: ["main_server.cpp"], gtest: false, } + +cc_test { + name: "binderVendorDoubleLoadTest", + vendor: true, + srcs: [ + "binderVendorDoubleLoadTest.cpp", + ], + static_libs: [ + "IBinderVendorDoubleLoadTest-cpp", + "IBinderVendorDoubleLoadTest-ndk_platform", + "libbinder_aidl_test_stub-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..d3ccdc2878 --- /dev/null +++ b/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp @@ -0,0 +1,168 @@ +/* + * 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 <aidl/android/os/IServiceManager.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; + } +} + +TEST(DoubleBinder, CallIntoSystemStabilityNdk) { + // picking an arbitrary system service + SpAIBinder binder = SpAIBinder(AServiceManager_checkService("manager")); + ASSERT_NE(nullptr, binder.get()); + + // can make stable transaction to system server + EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get())); + + using aidl::android::os::IServiceManager; + std::shared_ptr<IServiceManager> manager = IServiceManager::fromBinder(binder); + ASSERT_NE(nullptr, manager.get()); + + std::vector<std::string> services; + ASSERT_EQ( + STATUS_BAD_TYPE, + manager->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &services).getStatus()); +} + +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/math/include/math/quat.h b/libs/math/include/math/quat.h index 1936a2baec..07573c5ecf 100644 --- a/libs/math/include/math/quat.h +++ b/libs/math/include/math/quat.h @@ -109,7 +109,7 @@ public: // initialize from 4 values to w + xi + yj + zk template<typename A, typename B, typename C, typename D> - constexpr TQuaternion(A w, B x, C y, D z) : x(x), y(y), z(z), w(w) { } + constexpr TQuaternion(A w, B x, C y, D z) : x(static_cast<T>(x)), y(static_cast<T>(y)), z(static_cast<T>(z)), w(static_cast<T>(w)) { } // initialize from a vec3 + a value to : v.xi + v.yj + v.zk + w template<typename A, typename B> diff --git a/libs/math/include/math/vec2.h b/libs/math/include/math/vec2.h index a34763347c..e0adb7f6cc 100644 --- a/libs/math/include/math/vec2.h +++ b/libs/math/include/math/vec2.h @@ -89,7 +89,7 @@ public: constexpr TVec2(A v) : x(v), y(v) { } template<typename A, typename B> - constexpr TVec2(A x, B y) : x(x), y(y) { } + constexpr TVec2(A x, B y) : x(static_cast<T>(x)), y(static_cast<T>(y)) { } template<typename A> explicit diff --git a/libs/math/include/math/vec3.h b/libs/math/include/math/vec3.h index 009fd84e3b..21fb684efc 100644 --- a/libs/math/include/math/vec3.h +++ b/libs/math/include/math/vec3.h @@ -86,13 +86,13 @@ public: // handles implicit conversion to a tvec4. must not be explicit. template<typename A, typename = typename std::enable_if<std::is_arithmetic<A>::value >::type> - constexpr TVec3(A v) : x(v), y(v), z(v) { } + constexpr TVec3(A v) : x(static_cast<T>(v)), y(static_cast<T>(v)), z(static_cast<T>(v)) { } template<typename A, typename B, typename C> - constexpr TVec3(A x, B y, C z) : x(x), y(y), z(z) { } + constexpr TVec3(A x, B y, C z) : x(static_cast<T>(x)), y(static_cast<T>(y)), z(static_cast<T>(z)) { } template<typename A, typename B> - constexpr TVec3(const TVec2<A>& v, B z) : x(v.x), y(v.y), z(z) { } + constexpr TVec3(const TVec2<A>& v, B z) : x(v.x), y(v.y), z(static_cast<T>(z)) { } template<typename A> explicit 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/libs/ui/ColorSpace.cpp b/libs/ui/ColorSpace.cpp index 7a14af1c9d..df390e2588 100644 --- a/libs/ui/ColorSpace.cpp +++ b/libs/ui/ColorSpace.cpp @@ -364,7 +364,11 @@ std::unique_ptr<float3[]> ColorSpace::createLUT(uint32_t size, const ColorSpace& for (uint32_t z = 0; z < size; z++) { for (int32_t y = int32_t(size - 1); y >= 0; y--) { for (uint32_t x = 0; x < size; x++) { - *data++ = connector.transform({x * m, y * m, z * m}); + *data++ = connector.transform({ + static_cast<float>(x) * m, + static_cast<float>(y) * m, + static_cast<float>(z) * m, + }); } } } diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp index 0861a1f9a3..1dd59f43a7 100644 --- a/libs/ui/GraphicBufferAllocator.cpp +++ b/libs/ui/GraphicBufferAllocator.cpp @@ -80,7 +80,7 @@ void GraphicBufferAllocator::dump(std::string& result) const { if (rec.size) { StringAppendF(&result, "%10p: %7.2f KiB | %4u (%4u) x %4u | %4u | %8X | 0x%" PRIx64 " | %s\n", - list.keyAt(i), rec.size / 1024.0, rec.width, rec.stride, rec.height, + list.keyAt(i), static_cast<double>(rec.size) / 1024.0, rec.width, rec.stride, rec.height, rec.layerCount, rec.format, rec.usage, rec.requestorName.c_str()); } else { StringAppendF(&result, @@ -90,7 +90,7 @@ void GraphicBufferAllocator::dump(std::string& result) const { } total += rec.size; } - StringAppendF(&result, "Total allocated (estimate): %.2f KB\n", total / 1024.0); + StringAppendF(&result, "Total allocated (estimate): %.2f KB\n", static_cast<double>(total) / 1024.0); result.append(mAllocator->dumpDebugInfo()); } diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp index 55e3b99aa1..1222cd6fad 100644 --- a/libs/ui/Region.cpp +++ b/libs/ui/Region.cpp @@ -339,10 +339,10 @@ Region& Region::scaleSelf(float sx, float sy) { size_t count = mStorage.size(); Rect* rects = mStorage.editArray(); while (count) { - rects->left = static_cast<int32_t>(rects->left * sx + 0.5f); - rects->right = static_cast<int32_t>(rects->right * sx + 0.5f); - rects->top = static_cast<int32_t>(rects->top * sy + 0.5f); - rects->bottom = static_cast<int32_t>(rects->bottom * sy + 0.5f); + rects->left = static_cast<int32_t>(static_cast<float>(rects->left) * sx + 0.5f); + rects->right = static_cast<int32_t>(static_cast<float>(rects->right) * sx + 0.5f); + rects->top = static_cast<int32_t>(static_cast<float>(rects->top) * sy + 0.5f); + rects->bottom = static_cast<int32_t>(static_cast<float>(rects->bottom) * sy + 0.5f); rects++; count--; } diff --git a/libs/ui/include/ui/Size.h b/libs/ui/include/ui/Size.h index c39d8af1d6..d9b713df4c 100644 --- a/libs/ui/include/ui/Size.h +++ b/libs/ui/include/ui/Size.h @@ -132,7 +132,7 @@ struct Size { // Otherwise we leverage implicit conversion to safely compare values of // different types, to ensure we return a value clamped to the range of // ToType. - return v < toLowest ? toLowest : (v > toHighest ? toHighest : static_cast<ToType>(v)); + return v < toLowest ? toLowest : (static_cast<ToType>(v) > toHighest ? toHighest : static_cast<ToType>(v)); } }; diff --git a/opengl/tests/gl_perf/fill_common.cpp b/opengl/tests/gl_perf/fill_common.cpp index fefedc0939..613f1c6aa1 100644 --- a/opengl/tests/gl_perf/fill_common.cpp +++ b/opengl/tests/gl_perf/fill_common.cpp @@ -191,10 +191,10 @@ static void setupVA() { static void randUniform(int pgm, const char *var) { GLint loc = glGetUniformLocation(pgm, var); if (loc >= 0) { - float x = ((float)rand()) / RAND_MAX; - float y = ((float)rand()) / RAND_MAX; - float z = ((float)rand()) / RAND_MAX; - float w = ((float)rand()) / RAND_MAX; + float x = ((float)rand()) / (float)RAND_MAX; + float y = ((float)rand()) / (float)RAND_MAX; + float z = ((float)rand()) / (float)RAND_MAX; + float w = ((float)rand()) / (float)RAND_MAX; glUniform4f(loc, x, y, z, w); } } 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; diff --git a/services/surfaceflinger/TimeStats/OWNERS b/services/surfaceflinger/TimeStats/OWNERS index ac02d12fcd..1441f91489 100644 --- a/services/surfaceflinger/TimeStats/OWNERS +++ b/services/surfaceflinger/TimeStats/OWNERS @@ -1 +1,2 @@ -zzyiwei@google.com
\ No newline at end of file +alecmouri@google.com +zzyiwei@google.com diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp index 71048db920..3d56656896 100644 --- a/vulkan/libvulkan/api.cpp +++ b/vulkan/libvulkan/api.cpp @@ -519,7 +519,11 @@ LayerChain::LayerChain(bool is_instance, get_device_proc_addr_(nullptr), driver_extensions_(nullptr), driver_extension_count_(0) { - enabled_extensions_.set(driver::ProcHook::EXTENSION_CORE); + // advertise the loader supported core Vulkan API version at vulkan::api + for (uint32_t i = driver::ProcHook::EXTENSION_CORE_1_0; + i != driver::ProcHook::EXTENSION_COUNT; ++i) { + enabled_extensions_.set(i); + } } LayerChain::~LayerChain() { diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl index bdd3573b11..a5a0405f2d 100644 --- a/vulkan/libvulkan/code-generator.tmpl +++ b/vulkan/libvulkan/code-generator.tmpl @@ -765,6 +765,19 @@ VK_KHR_bind_memory2 {{end}} + +{{/* +------------------------------------------------------------------------------ + Emits the ProcHook enum for core Vulkan API verions. +------------------------------------------------------------------------------ +*/}} +{{define "driver.GetProcHookEnum"}} + {{if GetAnnotation $ "vulkan1_1"}}ProcHook::EXTENSION_CORE_1_1 + {{else}}ProcHook::EXTENSION_CORE_1_0 + {{end}} +{{end}} + + {{/* ------------------------------------------------------------------------------ Emits true if a function needs a ProcHook stub. @@ -778,6 +791,8 @@ VK_KHR_bind_memory2 {{if $ext}} {{if not (Macro "IsExtensionInternal" $ext)}}true{{end}} {{end}} + + {{if GetAnnotation $ "vulkan1_1"}}true{{end}} {{end}} {{end}} @@ -801,7 +816,8 @@ VK_KHR_bind_memory2 {{TrimPrefix "VK_" $e}}, {{end}} ¶ - EXTENSION_CORE, // valid bit + EXTENSION_CORE_1_0, + EXTENSION_CORE_1_1, EXTENSION_COUNT, EXTENSION_UNKNOWN, }; @@ -838,14 +854,21 @@ VK_KHR_bind_memory2 {{AssertType $ "Function"}} {{if (Macro "driver.NeedProcHookStub" $)}} + {{$ext_name := Strings ("")}} + {{$ext_hook := Strings ("")}} {{$ext := GetAnnotation $ "extension"}} - {{$ext_name := index $ext.Arguments 0}} + {{if $ext}} + {{$ext_name = index $ext.Arguments 0}} + {{$ext_hook = Strings ("ProcHook::") (Macro "BaseName" $ext)}} + {{else}} + {{$ext_name = Strings ("VK_VERSION_1_0")}} + {{$ext_hook = (Macro "driver.GetProcHookEnum" $)}} + {{end}} {{$base := (Macro "BaseName" $)}} VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) { {{$p0 := index $.CallParameters 0}} - {{$ext_hook := Strings ("ProcHook::") (Macro "BaseName" $ext)}} if (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) { {{if not (IsVoid $.Return.Type)}}return §{{end}} @@ -878,7 +901,7 @@ VK_KHR_bind_memory2 { "{{$.Name}}", ProcHook::GLOBAL, - ProcHook::EXTENSION_CORE, + {{Macro "driver.GetProcHookEnum" $}}, reinterpret_cast<PFN_vkVoidFunction>({{$base}}), nullptr, }, @@ -911,7 +934,7 @@ VK_KHR_bind_memory2 nullptr, {{end}} {{else}} - ProcHook::EXTENSION_CORE, + {{Macro "driver.GetProcHookEnum" $}}, reinterpret_cast<PFN_vkVoidFunction>({{$base}}), nullptr, {{end}} @@ -934,18 +957,23 @@ VK_KHR_bind_memory2 ProcHook::DEVICE, {{$ext := GetAnnotation $ "extension"}} - {{if $ext}} - ProcHook::{{Macro "BaseName" $ext}}, - - {{if (Macro "IsExtensionInternal" $ext)}} - nullptr, - nullptr, + {{if or $ext (GetAnnotation $ "vulkan1_1")}} + {{if $ext}} + ProcHook::{{Macro "BaseName" $ext}}, + {{if Macro "IsExtensionInternal" $ext}} + nullptr, + nullptr, + {{else}} + reinterpret_cast<PFN_vkVoidFunction>({{$base}}), + reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}), + {{end}} {{else}} + {{Macro "driver.GetProcHookEnum" $}}, reinterpret_cast<PFN_vkVoidFunction>({{$base}}), reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}), {{end}} {{else}} - ProcHook::EXTENSION_CORE, + {{Macro "driver.GetProcHookEnum" $}}, reinterpret_cast<PFN_vkVoidFunction>({{$base}}), nullptr, {{end}} diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp index 23506bad54..85e1c923e7 100644 --- a/vulkan/libvulkan/driver.cpp +++ b/vulkan/libvulkan/driver.cpp @@ -24,7 +24,10 @@ #include <dlfcn.h> #include <algorithm> #include <array> +#include <climits> #include <new> +#include <sstream> +#include <string> #include <log/log.h> @@ -104,6 +107,7 @@ class CreateInfoWrapper { VkResult Validate(); void DowngradeApiVersion(); + void UpgradeDeviceCoreApiVersion(uint32_t api_version); const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const; const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const; @@ -152,15 +156,12 @@ class CreateInfoWrapper { Hal Hal::hal_; void* LoadLibrary(const android_dlextinfo& dlextinfo, - const char* subname, - int subname_len) { + const std::string_view subname) { ATRACE_CALL(); - const char kLibFormat[] = "vulkan.%*s.so"; - char* name = static_cast<char*>( - alloca(sizeof(kLibFormat) + static_cast<size_t>(subname_len))); - sprintf(name, kLibFormat, subname_len, subname); - return android_dlopen_ext(name, RTLD_LOCAL | RTLD_NOW, &dlextinfo); + std::stringstream ss; + ss << "vulkan." << subname << ".so"; + return android_dlopen_ext(ss.str().c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo); } const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{ @@ -180,8 +181,9 @@ int LoadDriver(android_namespace_t* library_namespace, char prop[PROPERTY_VALUE_MAX]; for (auto key : HAL_SUBNAME_KEY_PROPERTIES) { int prop_len = property_get(key, prop, nullptr); - if (prop_len > 0) { - so = LoadLibrary(dlextinfo, prop, prop_len); + if (prop_len > 0 && prop_len <= UINT_MAX) { + std::string_view lib_name(prop, static_cast<unsigned int>(prop_len)); + so = LoadLibrary(dlextinfo, lib_name); if (so) break; } @@ -333,8 +335,12 @@ CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info, physical_dev_(VK_NULL_HANDLE), instance_info_(create_info), extension_filter_() { - hook_extensions_.set(ProcHook::EXTENSION_CORE); - hal_extensions_.set(ProcHook::EXTENSION_CORE); + // instance core versions need to match the loader api version + for (uint32_t i = ProcHook::EXTENSION_CORE_1_0; + i != ProcHook::EXTENSION_COUNT; ++i) { + hook_extensions_.set(i); + hal_extensions_.set(i); + } } CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev, @@ -345,8 +351,9 @@ CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev, physical_dev_(physical_dev), dev_info_(create_info), extension_filter_() { - hook_extensions_.set(ProcHook::EXTENSION_CORE); - hal_extensions_.set(ProcHook::EXTENSION_CORE); + // initialize with baseline core API version + hook_extensions_.set(ProcHook::EXTENSION_CORE_1_0); + hal_extensions_.set(ProcHook::EXTENSION_CORE_1_0); } CreateInfoWrapper::~CreateInfoWrapper() { @@ -545,7 +552,8 @@ void CreateInfoWrapper::FilterExtension(const char* name) { case ProcHook::ANDROID_external_memory_android_hardware_buffer: case ProcHook::ANDROID_native_buffer: case ProcHook::GOOGLE_display_timing: - case ProcHook::EXTENSION_CORE: + case ProcHook::EXTENSION_CORE_1_0: + case ProcHook::EXTENSION_CORE_1_1: case ProcHook::EXTENSION_COUNT: // Device and meta extensions. If we ever get here it's a bug in // our code. But enumerating them lets us avoid having a default @@ -593,7 +601,8 @@ void CreateInfoWrapper::FilterExtension(const char* name) { case ProcHook::EXT_debug_report: case ProcHook::EXT_swapchain_colorspace: case ProcHook::ANDROID_native_buffer: - case ProcHook::EXTENSION_CORE: + case ProcHook::EXTENSION_CORE_1_0: + case ProcHook::EXTENSION_CORE_1_1: case ProcHook::EXTENSION_COUNT: // Instance and meta extensions. If we ever get here it's a bug // in our code. But enumerating them lets us avoid having a @@ -641,6 +650,28 @@ void CreateInfoWrapper::DowngradeApiVersion() { } } +void CreateInfoWrapper::UpgradeDeviceCoreApiVersion(uint32_t api_version) { + ALOG_ASSERT(!is_instance_, "Device only API called by instance wrapper."); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wold-style-cast" + api_version ^= VK_VERSION_PATCH(api_version); +#pragma clang diagnostic pop + // cap the API version to the loader supported highest version + if (api_version > VK_API_VERSION_1_1) + api_version = VK_API_VERSION_1_1; + switch (api_version) { + case VK_API_VERSION_1_1: + hook_extensions_.set(ProcHook::EXTENSION_CORE_1_1); + hal_extensions_.set(ProcHook::EXTENSION_CORE_1_1); + [[clang::fallthrough]]; + case VK_API_VERSION_1_0: + break; + default: + ALOGD("Unknown upgrade API version[%u]", api_version); + break; + } +} + VKAPI_ATTR void* DefaultAllocate(void*, size_t size, size_t alignment, @@ -776,7 +807,7 @@ PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) { : nullptr; break; case ProcHook::DEVICE: - proc = (hook->extension == ProcHook::EXTENSION_CORE) + proc = (hook->extension == ProcHook::EXTENSION_CORE_1_0) ? hook->proc : hook->checked_proc; break; @@ -1124,6 +1155,13 @@ VkResult CreateDevice(VkPhysicalDevice physicalDevice, if (!data) return VK_ERROR_OUT_OF_HOST_MEMORY; + VkPhysicalDeviceProperties properties; + ATRACE_BEGIN("driver.GetPhysicalDeviceProperties"); + instance_data.driver.GetPhysicalDeviceProperties(physicalDevice, + &properties); + ATRACE_END(); + + wrapper.UpgradeDeviceCoreApiVersion(properties.apiVersion); data->hook_extensions |= wrapper.GetHookExtensions(); // call into the driver @@ -1168,12 +1206,6 @@ VkResult CreateDevice(VkPhysicalDevice physicalDevice, return VK_ERROR_INCOMPATIBLE_DRIVER; } - VkPhysicalDeviceProperties properties; - ATRACE_BEGIN("driver.GetPhysicalDeviceProperties"); - instance_data.driver.GetPhysicalDeviceProperties(physicalDevice, - &properties); - ATRACE_END(); - if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) { // Log that the app is hitting software Vulkan implementation android::GraphicsEnv::getInstance().setCpuVulkanInUse(); diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h index 57c956d9a4..047a27adc9 100644 --- a/vulkan/libvulkan/driver.h +++ b/vulkan/libvulkan/driver.h @@ -67,9 +67,7 @@ struct InstanceData { : opaque_api_data(), allocator(alloc), driver(), - get_device_proc_addr(nullptr) { - hook_extensions.set(ProcHook::EXTENSION_CORE); - } + get_device_proc_addr(nullptr) {} api::InstanceData opaque_api_data; @@ -89,9 +87,7 @@ struct DeviceData { : opaque_api_data(), allocator(alloc), debug_report_callbacks(debug_report_callbacks_), - driver() { - hook_extensions.set(ProcHook::EXTENSION_CORE); - } + driver() {} api::DeviceData opaque_api_data; diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp index 574c3273d0..aa31735eef 100644 --- a/vulkan/libvulkan/driver_gen.cpp +++ b/vulkan/libvulkan/driver_gen.cpp @@ -31,6 +31,23 @@ namespace { // clang-format off +VKAPI_ATTR VkResult checkedBindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) { + if (GetData(device).hook_extensions[ProcHook::EXTENSION_CORE_1_1]) { + return BindImageMemory2(device, bindInfoCount, pBindInfos); + } else { + Logger(device).Err(device, "VK_VERSION_1_0 not enabled. vkBindImageMemory2 not executed."); + return VK_SUCCESS; + } +} + +VKAPI_ATTR void checkedGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) { + if (GetData(device).hook_extensions[ProcHook::EXTENSION_CORE_1_1]) { + GetDeviceQueue2(device, pQueueInfo, pQueue); + } else { + Logger(device).Err(device, "VK_VERSION_1_0 not enabled. vkGetDeviceQueue2 not executed."); + } +} + VKAPI_ATTR VkResult checkedCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain) { if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) { return CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); @@ -174,16 +191,16 @@ const ProcHook g_proc_hooks[] = { { "vkAllocateCommandBuffers", ProcHook::DEVICE, - ProcHook::EXTENSION_CORE, + ProcHook::EXTENSION_CORE_1_0, reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers), nullptr, }, { "vkBindImageMemory2", ProcHook::DEVICE, - ProcHook::EXTENSION_CORE, + ProcHook::EXTENSION_CORE_1_1, reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory2), - nullptr, + reinterpret_cast<PFN_vkVoidFunction>(checkedBindImageMemory2), }, { "vkBindImageMemory2KHR", @@ -209,14 +226,14 @@ const ProcHook g_proc_hooks[] = { { "vkCreateDevice", ProcHook::INSTANCE, - ProcHook::EXTENSION_CORE, + ProcHook::EXTENSION_CORE_1_0, reinterpret_cast<PFN_vkVoidFunction>(CreateDevice), nullptr, }, { "vkCreateInstance", ProcHook::GLOBAL, - ProcHook::EXTENSION_CORE, + ProcHook::EXTENSION_CORE_1_0, reinterpret_cast<PFN_vkVoidFunction>(CreateInstance), nullptr, }, @@ -244,14 +261,14 @@ const ProcHook g_proc_hooks[] = { { "vkDestroyDevice", ProcHook::DEVICE, - ProcHook::EXTENSION_CORE, + ProcHook::EXTENSION_CORE_1_0, reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice), nullptr, }, { "vkDestroyInstance", ProcHook::INSTANCE, - ProcHook::EXTENSION_CORE, + ProcHook::EXTENSION_CORE_1_0, reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance), nullptr, }, @@ -272,28 +289,28 @@ const ProcHook g_proc_hooks[] = { { "vkEnumerateDeviceExtensionProperties", ProcHook::INSTANCE, - ProcHook::EXTENSION_CORE, + ProcHook::EXTENSION_CORE_1_0, reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties), nullptr, }, { "vkEnumerateInstanceExtensionProperties", ProcHook::GLOBAL, - ProcHook::EXTENSION_CORE, + ProcHook::EXTENSION_CORE_1_0, reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties), nullptr, }, { "vkEnumeratePhysicalDeviceGroups", ProcHook::INSTANCE, - ProcHook::EXTENSION_CORE, + ProcHook::EXTENSION_CORE_1_1, reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDeviceGroups), nullptr, }, { "vkEnumeratePhysicalDevices", ProcHook::INSTANCE, - ProcHook::EXTENSION_CORE, + ProcHook::EXTENSION_CORE_1_0, reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices), nullptr, }, @@ -314,28 +331,28 @@ const ProcHook g_proc_hooks[] = { { "vkGetDeviceProcAddr", ProcHook::DEVICE, - ProcHook::EXTENSION_CORE, + ProcHook::EXTENSION_CORE_1_0, reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr), nullptr, }, { "vkGetDeviceQueue", ProcHook::DEVICE, - ProcHook::EXTENSION_CORE, + ProcHook::EXTENSION_CORE_1_0, reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue), nullptr, }, { "vkGetDeviceQueue2", ProcHook::DEVICE, - ProcHook::EXTENSION_CORE, + ProcHook::EXTENSION_CORE_1_1, reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue2), - nullptr, + reinterpret_cast<PFN_vkVoidFunction>(checkedGetDeviceQueue2), }, { "vkGetInstanceProcAddr", ProcHook::INSTANCE, - ProcHook::EXTENSION_CORE, + ProcHook::EXTENSION_CORE_1_0, reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr), nullptr, }, diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h index 3faf6c0e32..831efb7026 100644 --- a/vulkan/libvulkan/driver_gen.h +++ b/vulkan/libvulkan/driver_gen.h @@ -48,7 +48,8 @@ struct ProcHook { ANDROID_external_memory_android_hardware_buffer, KHR_bind_memory2, - EXTENSION_CORE, // valid bit + EXTENSION_CORE_1_0, + EXTENSION_CORE_1_1, EXTENSION_COUNT, EXTENSION_UNKNOWN, }; diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp index 5679412732..dd917393d1 100644 --- a/vulkan/libvulkan/layers_extensions.cpp +++ b/vulkan/libvulkan/layers_extensions.cpp @@ -24,6 +24,7 @@ #include <string.h> #include <sys/prctl.h> +#include <memory> #include <mutex> #include <string> #include <vector> @@ -101,9 +102,7 @@ class LayerLibrary { bool EnumerateLayers(size_t library_idx, std::vector<Layer>& instance_layers) const; - void* GetGPA(const Layer& layer, - const char* gpa_name, - size_t gpa_name_len) const; + void* GetGPA(const Layer& layer, const std::string_view gpa_name) const; const std::string GetFilename() { return filename_; } @@ -226,17 +225,10 @@ bool LayerLibrary::EnumerateLayers(size_t library_idx, } // get layer properties - VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca( - (num_instance_layers + num_device_layers) * sizeof(VkLayerProperties))); - result = enumerate_instance_layers(&num_instance_layers, properties); - if (result != VK_SUCCESS) { - ALOGE("vkEnumerateInstanceLayerProperties failed for library '%s': %d", - path_.c_str(), result); - return false; - } + auto properties = std::make_unique<VkLayerProperties[]>(num_instance_layers + num_device_layers); if (num_device_layers > 0) { result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers, - properties + num_instance_layers); + properties.get() + num_instance_layers); if (result != VK_SUCCESS) { ALOGE( "vkEnumerateDeviceLayerProperties failed for library '%s': %d", @@ -321,21 +313,11 @@ bool LayerLibrary::EnumerateLayers(size_t library_idx, return true; } -void* LayerLibrary::GetGPA(const Layer& layer, - const char* gpa_name, - size_t gpa_name_len) const { - void* gpa; - size_t layer_name_len = - std::max(size_t{2}, strlen(layer.properties.layerName)); - char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1)); - strcpy(name, layer.properties.layerName); - strcpy(name + layer_name_len, gpa_name); - if (!(gpa = GetTrampoline(name))) { - strcpy(name, "vk"); - strcpy(name + 2, gpa_name); - gpa = GetTrampoline(name); - } - return gpa; +void* LayerLibrary::GetGPA(const Layer& layer, const std::string_view gpa_name) const { + std::string layer_name { layer.properties.layerName }; + if (void* gpa = GetTrampoline((layer_name.append(gpa_name).c_str()))) + return gpa; + return GetTrampoline((std::string {"vk"}.append(gpa_name)).c_str()); } // ---------------------------------------------------------------------------- @@ -470,10 +452,9 @@ const VkExtensionProperties* FindExtension( } void* GetLayerGetProcAddr(const Layer& layer, - const char* gpa_name, - size_t gpa_name_len) { + const std::string_view gpa_name) { const LayerLibrary& library = g_layer_libraries[layer.library_idx]; - return library.GetGPA(layer, gpa_name, gpa_name_len); + return library.GetGPA(layer, gpa_name); } } // anonymous namespace @@ -556,13 +537,13 @@ LayerRef::LayerRef(LayerRef&& other) noexcept : layer_(other.layer_) { PFN_vkGetInstanceProcAddr LayerRef::GetGetInstanceProcAddr() const { return layer_ ? reinterpret_cast<PFN_vkGetInstanceProcAddr>( - GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr", 19)) + GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr")) : nullptr; } PFN_vkGetDeviceProcAddr LayerRef::GetGetDeviceProcAddr() const { return layer_ ? reinterpret_cast<PFN_vkGetDeviceProcAddr>( - GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr", 17)) + GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr")) : nullptr; } diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp index 5f4c6b1305..cc0df08835 100644 --- a/vulkan/libvulkan/swapchain.cpp +++ b/vulkan/libvulkan/swapchain.cpp @@ -1280,6 +1280,7 @@ VkResult CreateSwapchainKHR(VkDevice device, VkImageCreateInfo image_create = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .pNext = &image_native_buffer, + .flags = createProtectedSwapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u, .imageType = VK_IMAGE_TYPE_2D, .format = create_info->imageFormat, .extent = {0, 0, 1}, @@ -1288,7 +1289,6 @@ VkResult CreateSwapchainKHR(VkDevice device, .samples = VK_SAMPLE_COUNT_1_BIT, .tiling = VK_IMAGE_TILING_OPTIMAL, .usage = create_info->imageUsage, - .flags = createProtectedSwapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u, .sharingMode = create_info->imageSharingMode, .queueFamilyIndexCount = create_info->queueFamilyIndexCount, .pQueueFamilyIndices = create_info->pQueueFamilyIndices, diff --git a/vulkan/tools/vkinfo.cpp b/vulkan/tools/vkinfo.cpp index 89bc926aa6..f9e4916722 100644 --- a/vulkan/tools/vkinfo.cpp +++ b/vulkan/tools/vkinfo.cpp @@ -195,10 +195,10 @@ void GatherGpuInfo(VkPhysicalDevice gpu, .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .queueCreateInfoCount = 1, .pQueueCreateInfos = &queue_create_info, - .enabledExtensionCount = num_extensions, - .ppEnabledExtensionNames = extensions, .enabledLayerCount = (options.validate) ? num_layers : 0, .ppEnabledLayerNames = kValidationLayers, + .enabledExtensionCount = num_extensions, + .ppEnabledExtensionNames = extensions, .pEnabledFeatures = &info.features, }; result = vkCreateDevice(gpu, &create_info, nullptr, &device); @@ -272,10 +272,10 @@ void GatherInfo(VulkanInfo* info, const Options& options) { const VkInstanceCreateInfo create_info = { .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .pApplicationInfo = &application_info, - .enabledExtensionCount = num_extensions, - .ppEnabledExtensionNames = extensions, .enabledLayerCount = (options.validate) ? num_layers : 0, .ppEnabledLayerNames = kValidationLayers, + .enabledExtensionCount = num_extensions, + .ppEnabledExtensionNames = extensions, }; VkInstance instance; result = vkCreateInstance(&create_info, nullptr, &instance); |