diff options
82 files changed, 1393 insertions, 2047 deletions
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp index a4b00f8e0c..587d25f9ed 100644 --- a/cmds/atrace/atrace.cpp +++ b/cmds/atrace/atrace.cpp @@ -1467,10 +1467,11 @@ int main(int argc, char **argv) // Reset the trace buffer size to 1. if (traceStop) { - cleanUpVendorTracing(); cleanUpUserspaceTracing(); - if (!onlyUserspace) + if (!onlyUserspace) { + cleanUpVendorTracing(); cleanUpKernelTracing(); + } } return g_traceAborted ? 1 : 0; diff --git a/cmds/bugreport/bugreport.cpp b/cmds/bugreport/bugreport.cpp index 917c8132b7..840ae473bc 100644 --- a/cmds/bugreport/bugreport.cpp +++ b/cmds/bugreport/bugreport.cpp @@ -37,7 +37,7 @@ int main() { property_set("ctl.start", "dumpstate"); // Socket will not be available until service starts. - int s; + int s = -1; for (int i = 0; i < 20; i++) { s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); diff --git a/cmds/bugreportz/main.cpp b/cmds/bugreportz/main.cpp index 74a95b0b57..40346bee1f 100644 --- a/cmds/bugreportz/main.cpp +++ b/cmds/bugreportz/main.cpp @@ -72,7 +72,7 @@ int main(int argc, char* argv[]) { property_set("ctl.start", "dumpstatez"); // Socket will not be available until service starts. - int s; + int s = -1; for (int i = 0; i < 20; i++) { s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); if (s >= 0) break; diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp index ee32cb4495..4020480479 100644 --- a/cmds/dumpstate/Android.bp +++ b/cmds/dumpstate/Android.bp @@ -123,7 +123,6 @@ cc_binary { "lsmod", "lsof", "netstat", - "parse_radio_log", "printenv", "procrank", "screencap", @@ -146,6 +145,8 @@ cc_test { "tests/dumpstate_test.cpp", ], static_libs: ["libgmock"], + test_config: "dumpstate_test.xml", + data: [":dumpstate_test_fixture", "tests/testdata/**/*"] } cc_test { diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp index ddae9ea8f6..37ba4f906e 100644 --- a/cmds/dumpstate/DumpstateService.cpp +++ b/cmds/dumpstate/DumpstateService.cpp @@ -151,15 +151,15 @@ binder::Status DumpstateService::startBugreport(int32_t calling_uid, signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT); } - if (bugreport_fd.get() == -1 || screenshot_fd.get() == -1) { - // TODO(b/111441001): screenshot fd should be optional + std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>(); + options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_fd, + screenshot_fd); + + if (bugreport_fd.get() == -1 || (options->do_fb && screenshot_fd.get() == -1)) { MYLOGE("Invalid filedescriptor"); signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT); } - std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>(); - options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_fd, - screenshot_fd); ds_ = &(Dumpstate::GetInstance()); ds_->SetOptions(std::move(options)); diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl index 347856ddcb..cb2d8b8d2c 100644 --- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl +++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl @@ -73,7 +73,7 @@ interface IDumpstate { * @param callingUid UID of the original application that requested the report. * @param callingPackage package of the original application that requested the report. * @param bugreportFd the file to which the zipped bugreport should be written - * @param screenshotFd the file to which screenshot should be written; optional + * @param screenshotFd the file to which screenshot should be written * @param bugreportMode the mode that specifies other run time options; must be one of above * @param listener callback for updates; optional */ diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 4ac7b689cf..cc745708c8 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -94,7 +94,6 @@ using android::os::IDumpstateListener; using android::os::dumpstate::CommandOptions; using android::os::dumpstate::DumpFileToFd; using android::os::dumpstate::DumpstateSectionReporter; -using android::os::dumpstate::GetPidByName; using android::os::dumpstate::PropertiesHelper; typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult; @@ -421,108 +420,6 @@ static void dump_dev_files(const char *title, const char *driverpath, const char closedir(d); } - - -// dump anrd's trace and add to the zip file. -// 1. check if anrd is running on this device. -// 2. send a SIGUSR1 to its pid which will dump anrd's trace. -// 3. wait until the trace generation completes and add to the zip file. -static bool dump_anrd_trace() { - unsigned int pid; - char buf[50], path[PATH_MAX]; - struct dirent *trace; - struct stat st; - DIR *trace_dir; - int retry = 5; - long max_ctime = 0, old_mtime; - long long cur_size = 0; - const char *trace_path = "/data/misc/anrd/"; - - if (!ds.IsZipping()) { - MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n"); - return false; - } - - // find anrd's pid if it is running. - pid = GetPidByName("/system/bin/anrd"); - - if (pid > 0) { - if (stat(trace_path, &st) == 0) { - old_mtime = st.st_mtime; - } else { - MYLOGE("Failed to find: %s\n", trace_path); - return false; - } - - // send SIGUSR1 to the anrd to generate a trace. - sprintf(buf, "%u", pid); - if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf}, - CommandOptions::WithTimeout(1).Build())) { - MYLOGE("anrd signal timed out. Please manually collect trace\n"); - return false; - } - - while (retry-- > 0 && old_mtime == st.st_mtime) { - sleep(1); - stat(trace_path, &st); - } - - if (retry < 0 && old_mtime == st.st_mtime) { - MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path); - return false; - } - - // identify the trace file by its creation time. - if (!(trace_dir = opendir(trace_path))) { - MYLOGE("Can't open trace file under %s\n", trace_path); - } - while ((trace = readdir(trace_dir))) { - if (strcmp(trace->d_name, ".") == 0 - || strcmp(trace->d_name, "..") == 0) { - continue; - } - sprintf(path, "%s%s", trace_path, trace->d_name); - if (stat(path, &st) == 0) { - if (st.st_ctime > max_ctime) { - max_ctime = st.st_ctime; - sprintf(buf, "%s", trace->d_name); - } - } - } - closedir(trace_dir); - - // Wait until the dump completes by checking the size of the trace. - if (max_ctime > 0) { - sprintf(path, "%s%s", trace_path, buf); - while(true) { - sleep(1); - if (stat(path, &st) == 0) { - if (st.st_size == cur_size) { - break; - } else if (st.st_size > cur_size) { - cur_size = st.st_size; - } else { - return false; - } - } else { - MYLOGE("Cant stat() %s anymore\n", path); - return false; - } - } - // Add to the zip file. - if (!ds.AddZipEntry("anrd_trace.txt", path)) { - MYLOGE("Unable to add anrd_trace file %s to zip file\n", path); - } else { - android::os::UnlinkAndLogOnError(path); - return true; - } - } else { - MYLOGE("Can't stats any trace file under %s\n", trace_path); - } - } - return false; -} - static bool skip_not_stat(const char *path) { static const char stat[] = "/stat"; size_t len = strlen(path); @@ -1380,7 +1277,7 @@ static Dumpstate::RunStatus dumpstate() { /* Dump Bluetooth HCI logs */ ds.AddDir("/data/misc/bluetooth/logs", true); - if (!ds.do_early_screenshot_) { + if (ds.options_->do_fb && !ds.do_early_screenshot_) { MYLOGI("taking late screenshot\n"); ds.TakeScreenshot(); } @@ -1419,8 +1316,6 @@ static Dumpstate::RunStatus dumpstate() { RunCommand("FILESYSTEMS & FREE SPACE", {"df"}); - RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"}); - /* Binder state is expensive to look at as it uses a lot of memory. */ DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log"); DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log"); @@ -1428,7 +1323,6 @@ static Dumpstate::RunStatus dumpstate() { DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats"); DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state"); - RunDumpsys("WINSCOPE TRACE", {"window", "trace"}); /* Add window and surface trace files. */ if (!PropertiesHelper::IsUserBuild()) { ds.AddDir(WMTRACE_DATA_DIR, false); @@ -1539,9 +1433,6 @@ static Dumpstate::RunStatus dumpstate() { * with the caller. */ static Dumpstate::RunStatus DumpstateDefault() { - // Try to dump anrd trace if the daemon is running. - dump_anrd_trace(); - // Invoking the following dumpsys calls before DumpTraces() to try and // keep the system stats as close to its initial state as possible. RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysCritical); @@ -1903,22 +1794,21 @@ void Dumpstate::DumpstateBoard() { static void ShowUsage() { fprintf(stderr, - "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] " + "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-d] [-p] " "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n" " -h: display this help message\n" " -b: play sound file instead of vibrate, at beginning of job\n" " -e: play sound file instead of vibrate, at end of job\n" - " -o: write to file (instead of stdout)\n" - " -d: append date to filename (requires -o)\n" - " -p: capture screenshot to filename.png (requires -o)\n" - " -z: generate zipped file (requires -o)\n" + " -d: append date to filename\n" + " -p: capture screenshot to filename.png\n" + " -z: generate zipped file\n" " -s: write output to control socket (for init)\n" - " -S: write file location to control socket (for init; requires -o and -z)\n" + " -S: write file location to control socket (for init; requires -z)\n" " -q: disable vibrate\n" - " -B: send broadcast when finished (requires -o)\n" + " -B: send broadcast when finished\n" " -P: send broadcast when started and update system properties on " - "progress (requires -o and -B)\n" - " -R: take bugreport in remote mode (requires -o, -z, -d and -B, " + "progress (requires -B)\n" + " -R: take bugreport in remote mode (requires -z, -d and -B, " "shouldn't be used with -P)\n" " -w: start binder service and make it wait for a call to startBugreport\n" " -v: prints the dumpstate header and exit\n"); @@ -2402,7 +2292,6 @@ Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) } } - // TODO: use helper function to convert argv into a string for (int i = 0; i < argc; i++) { args += argv[i]; if (i < argc - 1) { @@ -2626,13 +2515,8 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, } if (options_->do_fb && do_early_screenshot_) { - if (screenshot_path_.empty()) { - // should not have happened - MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n"); - } else { - MYLOGI("taking early screenshot\n"); - TakeScreenshot(); - } + MYLOGI("taking early screenshot\n"); + TakeScreenshot(); } if (options_->do_zip_file && zip_file != nullptr) { diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h index d02ec759a7..ae6a72171a 100644 --- a/cmds/dumpstate/dumpstate.h +++ b/cmds/dumpstate/dumpstate.h @@ -441,8 +441,7 @@ class Dumpstate { // Full path of the bugreport file, be it zip or text, inside bugreport_internal_dir_. std::string path_; - // TODO: If temporary this should be removed at the end. - // Full path of the temporary file containing the screenshot (when requested). + // Full path of the file containing the screenshot (when requested). std::string screenshot_path_; // Pointer to the zipped file. diff --git a/cmds/dumpstate/dumpstate_test.xml b/cmds/dumpstate/dumpstate_test.xml new file mode 100644 index 0000000000..e4e4a30a1e --- /dev/null +++ b/cmds/dumpstate/dumpstate_test.xml @@ -0,0 +1,29 @@ +<?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="Config for dumpstate_test"> + <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> + <option name="cleanup" value="true" /> + <option name="push" value="dumpstate_test->/data/local/tmp/dumpstate_test" /> + </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/> + <option name="test-suite-tag" value="apct" /> + <test class="com.android.tradefed.testtype.GTest" > + <option name="native-test-device-path" value="/data/local/tmp" /> + <option name="file-exclusion-filter-regex" value=".*/dumpstate_test_fixture" /> + <option name="file-exclusion-filter-regex" value=".*/tests/.*" /> + <option name="module-name" value="dumpstate_test" /> + </test> +</configuration> diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp index fc3642c912..5bde7db287 100644 --- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp @@ -208,7 +208,7 @@ class ZippedBugReportContentsTest : public Test { void FileExists(const char* filename, uint32_t minsize, uint32_t maxsize) { ZipEntry entry; - EXPECT_EQ(FindEntry(handle, ZipString(filename), &entry), 0); + EXPECT_EQ(FindEntry(handle, filename, &entry), 0); EXPECT_GT(entry.uncompressed_length, minsize); EXPECT_LT(entry.uncompressed_length, maxsize); } @@ -217,7 +217,7 @@ class ZippedBugReportContentsTest : public Test { TEST_F(ZippedBugReportContentsTest, ContainsMainEntry) { ZipEntry mainEntryLoc; // contains main entry name file - EXPECT_EQ(FindEntry(handle, ZipString("main_entry.txt"), &mainEntryLoc), 0); + EXPECT_EQ(FindEntry(handle, "main_entry.txt", &mainEntryLoc), 0); char* buf = new char[mainEntryLoc.uncompressed_length]; ExtractToMemory(handle, &mainEntryLoc, (uint8_t*)buf, mainEntryLoc.uncompressed_length); @@ -230,7 +230,7 @@ TEST_F(ZippedBugReportContentsTest, ContainsMainEntry) { TEST_F(ZippedBugReportContentsTest, ContainsVersion) { ZipEntry entry; // contains main entry name file - EXPECT_EQ(FindEntry(handle, ZipString("version.txt"), &entry), 0); + EXPECT_EQ(FindEntry(handle, "version.txt", &entry), 0); char* buf = new char[entry.uncompressed_length + 1]; ExtractToMemory(handle, &entry, (uint8_t*)buf, entry.uncompressed_length); diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp index 71d15f4761..0e88e43258 100644 --- a/cmds/dumpstate/tests/dumpstate_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_test.cpp @@ -105,9 +105,8 @@ class DumpstateBaseTest : public Test { protected: const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str()); - const std::string kFixturesPath = kTestPath + "/../dumpstate_test_fixture/"; - const std::string kTestDataPath = kFixturesPath + "tests/testdata/"; - const std::string kSimpleCommand = kFixturesPath + "dumpstate_test_fixture"; + const std::string kTestDataPath = kTestPath + "/tests/testdata/"; + const std::string kSimpleCommand = kTestPath + "/dumpstate_test_fixture"; const std::string kEchoCommand = "/system/bin/echo"; /* @@ -664,7 +663,8 @@ TEST_F(DumpstateTest, RunCommandNoTitle) { TEST_F(DumpstateTest, RunCommandWithTitle) { EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand})); EXPECT_THAT(err, StrEq("stderr\n")); - // We don't know the exact duration, so we check the prefix and suffix + // The duration may not get output, depending on how long it takes, + // so we just check the prefix. EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n")); } @@ -699,7 +699,8 @@ TEST_F(DumpstateTest, RunCommandWithMultipleArgs) { TEST_F(DumpstateTest, RunCommandDryRun) { SetDryRun(true); EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand})); - // We don't know the exact duration, so we check the prefix and suffix + // The duration may not get output, depending on how long it takes, + // so we just check the prefix. EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\n\t(skipped on dry run)\n")); EXPECT_THAT(err, IsEmpty()); @@ -1037,7 +1038,8 @@ TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) { TEST_F(DumpstateTest, DumpFileNotFoundWithTitle) { EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist")); EXPECT_THAT(err, IsEmpty()); - // We don't know the exact duration, so we check the prefix and suffix + // The duration may not get output, depending on how long it takes, + // so we just check the prefix. EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No " "such file or directory\n")); } diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp index 0bb80dcfba..4cbf5776d3 100644 --- a/cmds/dumpstate/utils.cpp +++ b/cmds/dumpstate/utils.cpp @@ -733,6 +733,11 @@ int open_socket(const char *service) { struct sockaddr addr; socklen_t alen = sizeof(addr); int fd = accept(s, &addr, &alen); + + // Close socket just after accept(), to make sure that connect() by client will get error + // when the socket is used by the other services. + close(s); + if (fd < 0) { MYLOGE("accept(control socket): %s\n", strerror(errno)); return -1; diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp index c80ae3bbf6..75dec371bc 100644 --- a/cmds/installd/Android.bp +++ b/cmds/installd/Android.bp @@ -138,6 +138,7 @@ cc_binary { cc_binary { name: "otapreopt_chroot", + defaults: ["libapexd-deps"], cflags: [ "-Wall", "-Werror", @@ -150,20 +151,11 @@ cc_binary { ], shared_libs: [ "libbase", - "libbinder", "liblog", - "libprotobuf-cpp-full", - "libselinux", "libutils", - "libziparchive", ], static_libs: [ - "libapex", "libapexd", - "lib_apex_manifest_proto", - "libavb", - "libdm", - "libvold_binder", ], } @@ -172,6 +164,7 @@ filegroup { srcs: [ "binder/android/os/IInstalld.aidl", ], + path: "binder", } // diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index caac2e89a7..dd51898422 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -2107,10 +2107,15 @@ binder::Status InstalldNativeService::dexopt(const std::string& apkPath, int32_t CHECK_ARGUMENT_PATH(dexMetadataPath); std::lock_guard<std::recursive_mutex> lock(mLock); + const char* oat_dir = getCStr(outputPath); + const char* instruction_set = instructionSet.c_str(); + if (oat_dir != nullptr && !createOatDir(oat_dir, instruction_set).isOk()) { + // Can't create oat dir - let dexopt use cache dir. + oat_dir = nullptr; + } + const char* apk_path = apkPath.c_str(); const char* pkgname = getCStr(packageName, "*"); - const char* instruction_set = instructionSet.c_str(); - const char* oat_dir = getCStr(outputPath); const char* compiler_filter = compilerFilter.c_str(); const char* volume_uuid = getCStr(uuid); const char* class_loader_context = getCStr(classLoaderContext); diff --git a/cmds/installd/OWNERS b/cmds/installd/OWNERS index 56739181bb..9a21104131 100644 --- a/cmds/installd/OWNERS +++ b/cmds/installd/OWNERS @@ -4,7 +4,9 @@ agampe@google.com calin@google.com jsharkey@android.com maco@google.com +mast@google.com mathieuc@google.com narayan@google.com ngeoffray@google.com +rpl@google.com toddke@google.com diff --git a/cmds/installd/art_helper/Android.bp b/cmds/installd/art_helper/Android.bp deleted file mode 100644 index c47dd722f9..0000000000 --- a/cmds/installd/art_helper/Android.bp +++ /dev/null @@ -1,12 +0,0 @@ -// Inherit image values. -art_global_defaults { - name: "libartimagevalues_defaults", -} - -cc_library_static { - name: "libartimagevalues", - defaults: ["libartimagevalues_defaults"], - srcs: ["art_image_values.cpp"], - export_include_dirs: ["."], - cflags: ["-Wconversion"], -} diff --git a/cmds/installd/art_helper/art_image_values.cpp b/cmds/installd/art_helper/art_image_values.cpp deleted file mode 100644 index a139049d9f..0000000000 --- a/cmds/installd/art_helper/art_image_values.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2018 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 "art_image_values.h" - -namespace android { -namespace installd { -namespace art { - -uint32_t GetImageBaseAddress() { - return ART_BASE_ADDRESS; -} -int32_t GetImageMinBaseAddressDelta() { - return ART_BASE_ADDRESS_MIN_DELTA; -} -int32_t GetImageMaxBaseAddressDelta() { - return ART_BASE_ADDRESS_MAX_DELTA; -} - -static_assert(ART_BASE_ADDRESS_MIN_DELTA < ART_BASE_ADDRESS_MAX_DELTA, "Inconsistent setup"); - -} // namespace art -} // namespace installd -} // namespace android diff --git a/cmds/installd/art_helper/art_image_values.h b/cmds/installd/art_helper/art_image_values.h deleted file mode 100644 index 20c44c953f..0000000000 --- a/cmds/installd/art_helper/art_image_values.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2018 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. - */ - -#ifndef FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H -#define FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H - -#include <cstdint> - -namespace android { -namespace installd { -namespace art { - -uint32_t GetImageBaseAddress(); -int32_t GetImageMinBaseAddressDelta(); -int32_t GetImageMaxBaseAddressDelta(); - -} // namespace art -} // namespace installd -} // namespace android - -#endif // FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp index dbb4f22372..7eee749be9 100644 --- a/cmds/installd/dexopt.cpp +++ b/cmds/installd/dexopt.cpp @@ -2117,14 +2117,20 @@ int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* ins // Create a swap file if necessary. unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path); - // Create the app image file if needed. - Dex2oatFileWrapper image_fd = maybe_open_app_image( - out_oat_path, generate_app_image, is_public, uid, is_secondary_dex); - // Open the reference profile if needed. Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile( pkgname, dex_path, profile_name, profile_guided, is_public, uid, is_secondary_dex); + if (reference_profile_fd.get() == -1) { + // We don't create an app image without reference profile since there is no speedup from + // loading it in that case and instead will be a small overhead. + generate_app_image = false; + } + + // Create the app image file if needed. + Dex2oatFileWrapper image_fd = maybe_open_app_image( + out_oat_path, generate_app_image, is_public, uid, is_secondary_dex); + unique_fd dex_metadata_fd; if (dex_metadata_path != nullptr) { dex_metadata_fd.reset(TEMP_FAILURE_RETRY(open(dex_metadata_path, O_RDONLY | O_NOFOLLOW))); diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp index de7b2499b8..db36ce3c9e 100644 --- a/cmds/installd/otapreopt.cpp +++ b/cmds/installd/otapreopt.cpp @@ -445,9 +445,11 @@ private: } cmd.push_back(StringPrintf("--oat-file=%s", oat_path.c_str())); - int32_t base_offset = ChooseRelocationOffsetDelta(art::GetImageMinBaseAddressDelta(), - art::GetImageMaxBaseAddressDelta()); - cmd.push_back(StringPrintf("--base=0x%x", art::GetImageBaseAddress() + base_offset)); + int32_t base_offset = ChooseRelocationOffsetDelta( + art::imagevalues::GetImageMinBaseAddressDelta(), + art::imagevalues::GetImageMaxBaseAddressDelta()); + cmd.push_back(StringPrintf("--base=0x%x", + art::imagevalues::GetImageBaseAddress() + base_offset)); cmd.push_back(StringPrintf("--instruction-set=%s", isa)); @@ -464,7 +466,7 @@ private: "--compiler-filter=", false, cmd); - cmd.push_back("--image-classes=/system/etc/preloaded-classes"); + cmd.push_back("--profile-file=/system/etc/boot-image.prof"); // TODO: Compiled-classes. const std::string* extra_opts = system_properties_.GetProperty("dalvik.vm.image-dex2oat-flags"); diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp index 2e2cc182ec..0c4badf489 100644 --- a/cmds/installd/otapreopt_chroot.cpp +++ b/cmds/installd/otapreopt_chroot.cpp @@ -64,16 +64,18 @@ static std::vector<apex::ApexFile> ActivateApexPackages() { // system/apex/apexd/apexd_main.cpp. // // Only scan the APEX directory under /system (within the chroot dir). - apex::scanPackagesDirAndActivate(apex::kApexPackageSystemDir); + // Cast call to void to suppress warn_unused_result. + static_cast<void>(apex::scanPackagesDirAndActivate(apex::kApexPackageSystemDir)); return apex::getActivePackages(); } static void DeactivateApexPackages(const std::vector<apex::ApexFile>& active_packages) { for (const apex::ApexFile& apex_file : active_packages) { const std::string& package_path = apex_file.GetPath(); - apex::Status status = apex::deactivatePackage(package_path); - if (!status.Ok()) { - LOG(ERROR) << "Failed to deactivate " << package_path << ": " << status.ErrorMessage(); + base::Result<void> status = apex::deactivatePackage(package_path); + if (!status) { + LOG(ERROR) << "Failed to deactivate " << package_path << ": " + << status.error(); } } } diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp index aa79fdc100..bd45005fd1 100644 --- a/cmds/installd/tests/Android.bp +++ b/cmds/installd/tests/Android.bp @@ -89,6 +89,8 @@ cc_test { "libinstalld", "liblog", "liblogwrap", + "libziparchive", + "libz", ], test_config: "installd_dexopt_test.xml", } diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp index fa2b0d9660..73780eccbf 100644 --- a/cmds/installd/tests/installd_dexopt_test.cpp +++ b/cmds/installd/tests/installd_dexopt_test.cpp @@ -41,6 +41,7 @@ #include "globals.h" #include "tests/test_utils.h" #include "utils.h" +#include "ziparchive/zip_writer.h" using android::base::ReadFully; using android::base::unique_fd; @@ -195,6 +196,7 @@ protected: std::unique_ptr<std::string> volume_uuid_; std::string package_name_; std::string apk_path_; + std::string empty_dm_file_; std::string app_apk_dir_; std::string app_private_dir_ce_; std::string app_private_dir_de_; @@ -239,18 +241,14 @@ protected: } ::testing::AssertionResult create_mock_app() { - // Create the oat dir. - app_oat_dir_ = app_apk_dir_ + "/oat"; // For debug mode, the directory might already exist. Avoid erroring out. if (mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755) != 0 && !kDebug) { return ::testing::AssertionFailure() << "Could not create app dir " << app_apk_dir_ << " : " << strerror(errno); } - binder::Status status = service_->createOatDir(app_oat_dir_, kRuntimeIsa); - if (!status.isOk()) { - return ::testing::AssertionFailure() << "Could not create oat dir: " - << status.toString8().c_str(); - } + + // Initialize the oat dir path. + app_oat_dir_ = app_apk_dir_ + "/oat"; // Copy the primary apk. apk_path_ = app_apk_dir_ + "/base.jar"; @@ -260,8 +258,28 @@ protected: << " : " << error_msg; } + // Create an empty dm file. + empty_dm_file_ = apk_path_ + ".dm"; + { + int fd = open(empty_dm_file_.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + if (fd < 0) { + return ::testing::AssertionFailure() << "Could not open " << empty_dm_file_; + } + FILE* file = fdopen(fd, "wb"); + if (file == nullptr) { + return ::testing::AssertionFailure() << "Null file for " << empty_dm_file_ + << " fd=" << fd; + } + ZipWriter writer(file); + // Add vdex to zip. + writer.StartEntry("primary.prof", ZipWriter::kCompress); + writer.FinishEntry(); + writer.Finish(); + close(fd); + } + // Create the app user data. - status = service_->createAppData( + binder::Status status = service_->createAppData( volume_uuid_, package_name_, kTestUserId, @@ -479,7 +497,7 @@ protected: bool prof_result; ASSERT_BINDER_SUCCESS(service_->prepareAppProfile( package_name_, kTestUserId, kTestAppId, *profile_name_ptr, apk_path_, - /*dex_metadata*/ nullptr, &prof_result)); + dm_path_ptr, &prof_result)); ASSERT_TRUE(prof_result); binder::Status result = service_->dexopt(apk_path_, @@ -625,6 +643,16 @@ TEST_F(DexoptTest, DexoptPrimaryPublic) { DEX2OAT_FROM_SCRATCH); } +TEST_F(DexoptTest, DexoptPrimaryPublicCreateOatDir) { + LOG(INFO) << "DexoptPrimaryPublic"; + ASSERT_BINDER_SUCCESS(service_->createOatDir(app_oat_dir_, kRuntimeIsa)); + CompilePrimaryDexOk("verify", + DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC, + app_oat_dir_.c_str(), + kTestAppGid, + DEX2OAT_FROM_SCRATCH); +} + TEST_F(DexoptTest, DexoptPrimaryFailedInvalidFilter) { LOG(INFO) << "DexoptPrimaryFailedInvalidFilter"; binder::Status status; @@ -645,7 +673,9 @@ TEST_F(DexoptTest, DexoptPrimaryProfileNonPublic) { DEXOPT_BOOTCOMPLETE | DEXOPT_PROFILE_GUIDED | DEXOPT_GENERATE_APP_IMAGE, app_oat_dir_.c_str(), kTestAppGid, - DEX2OAT_FROM_SCRATCH); + DEX2OAT_FROM_SCRATCH, + /*binder_result=*/nullptr, + empty_dm_file_.c_str()); } TEST_F(DexoptTest, DexoptPrimaryProfilePublic) { @@ -655,7 +685,9 @@ TEST_F(DexoptTest, DexoptPrimaryProfilePublic) { DEXOPT_GENERATE_APP_IMAGE, app_oat_dir_.c_str(), kTestAppGid, - DEX2OAT_FROM_SCRATCH); + DEX2OAT_FROM_SCRATCH, + /*binder_result=*/nullptr, + empty_dm_file_.c_str()); } TEST_F(DexoptTest, DexoptPrimaryBackgroundOk) { @@ -665,7 +697,9 @@ TEST_F(DexoptTest, DexoptPrimaryBackgroundOk) { DEXOPT_GENERATE_APP_IMAGE, app_oat_dir_.c_str(), kTestAppGid, - DEX2OAT_FROM_SCRATCH); + DEX2OAT_FROM_SCRATCH, + /*binder_result=*/nullptr, + empty_dm_file_.c_str()); } TEST_F(DexoptTest, ResolveStartupConstStrings) { @@ -684,7 +718,9 @@ TEST_F(DexoptTest, ResolveStartupConstStrings) { DEXOPT_GENERATE_APP_IMAGE, app_oat_dir_.c_str(), kTestAppGid, - DEX2OAT_FROM_SCRATCH); + DEX2OAT_FROM_SCRATCH, + /*binder_result=*/nullptr, + empty_dm_file_.c_str()); run_cmd_and_process_output( "oatdump --header-only --oat-file=" + odex, [&](const std::string& line) { @@ -701,7 +737,9 @@ TEST_F(DexoptTest, ResolveStartupConstStrings) { DEXOPT_GENERATE_APP_IMAGE, app_oat_dir_.c_str(), kTestAppGid, - DEX2OAT_FROM_SCRATCH); + DEX2OAT_FROM_SCRATCH, + /*binder_result=*/nullptr, + empty_dm_file_.c_str()); run_cmd_and_process_output( "oatdump --header-only --oat-file=" + odex, [&](const std::string& line) { diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp index 93d878b607..495cc80a5c 100644 --- a/cmds/lshal/Android.bp +++ b/cmds/lshal/Android.bp @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -cc_library_shared { +cc_library_static { name: "liblshal", shared_libs: [ "libbase", @@ -47,13 +47,16 @@ cc_defaults { name: "lshal_defaults", shared_libs: [ "libbase", + "libcutils", + "libutils", "libhidlbase", - "libhidl-gen-utils", "libhidltransport", - "liblshal", - "libutils", + "libhidl-gen-hash", + "libhidl-gen-utils", + "libvintf", ], static_libs: [ + "liblshal", "libprocpartition", ], cflags: ["-Wall", "-Werror"], @@ -69,14 +72,18 @@ cc_binary { cc_test { name: "lshal_test", + test_suites: ["device-tests"], defaults: ["lshal_defaults"], gtest: true, static_libs: [ - "libgmock" + "android.hardware.tests.baz@1.0", + "libgmock", ], shared_libs: [ + "libhwbinder", + "libhidlbase", + "libhidltransport", "libvintf", - "android.hardware.tests.baz@1.0" ], srcs: [ "test.cpp" diff --git a/cmds/lshal/Command.h b/cmds/lshal/Command.h index e19e3f7fc2..84809d9a5d 100644 --- a/cmds/lshal/Command.h +++ b/cmds/lshal/Command.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_COMMAND_H_ -#define FRAMEWORK_NATIVE_CMDS_LSHAL_COMMAND_H_ +#pragma once #include "utils.h" @@ -48,5 +47,3 @@ protected: } // namespace lshal } // namespace android - -#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_ diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp index 0952db6e72..af22ac9b3d 100644 --- a/cmds/lshal/DebugCommand.cpp +++ b/cmds/lshal/DebugCommand.cpp @@ -79,7 +79,7 @@ void DebugCommand::usage() const { " lshal debug [-E] <interface> [options [options [...]]] \n" " Print debug information of a specified interface.\n" " -E: excludes debug output if HAL is actually a subclass.\n" - " <inteface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n" + " <interface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n" " If instance name is missing `default` is used.\n" " options: space separated options to IBase::debug.\n"; @@ -88,4 +88,3 @@ void DebugCommand::usage() const { } // namespace lshal } // namespace android - diff --git a/cmds/lshal/DebugCommand.h b/cmds/lshal/DebugCommand.h index 3c3f56fde5..cd57e31bfc 100644 --- a/cmds/lshal/DebugCommand.h +++ b/cmds/lshal/DebugCommand.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_ -#define FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_ +#pragma once #include <string> @@ -53,5 +52,3 @@ private: } // namespace lshal } // namespace android - -#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_ diff --git a/cmds/lshal/HelpCommand.h b/cmds/lshal/HelpCommand.h index da0cba6f42..bfa850075d 100644 --- a/cmds/lshal/HelpCommand.h +++ b/cmds/lshal/HelpCommand.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_HELP_COMMAND_H_ -#define FRAMEWORK_NATIVE_CMDS_LSHAL_HELP_COMMAND_H_ +#pragma once #include <string> @@ -44,5 +43,3 @@ public: } // namespace lshal } // namespace android - -#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_HELP_COMMAND_H_ diff --git a/cmds/lshal/ListCommand.h b/cmds/lshal/ListCommand.h index 85195fcc54..b3ed23d1fc 100644 --- a/cmds/lshal/ListCommand.h +++ b/cmds/lshal/ListCommand.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_ -#define FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_ +#pragma once #include <getopt.h> #include <stdint.h> @@ -206,5 +205,3 @@ private: } // namespace lshal } // namespace android - -#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_ diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h index 9457f1e563..2679650611 100644 --- a/cmds/lshal/Lshal.h +++ b/cmds/lshal/Lshal.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_ -#define FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_ +#pragma once #include <iostream> #include <string> @@ -76,5 +75,3 @@ private: } // namespace lshal } // namespace android - -#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_ diff --git a/cmds/lshal/NullableOStream.h b/cmds/lshal/NullableOStream.h index 737d3a2963..7cffcf8193 100644 --- a/cmds/lshal/NullableOStream.h +++ b/cmds/lshal/NullableOStream.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_NULLABLE_O_STREAM_H_ -#define FRAMEWORK_NATIVE_CMDS_LSHAL_NULLABLE_O_STREAM_H_ +#pragma once #include <iostream> @@ -69,5 +68,3 @@ private: } // namespace lshal } // namespace android - -#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_NULLABLE_O_STREAM_H_ diff --git a/cmds/lshal/PipeRelay.h b/cmds/lshal/PipeRelay.h index 8dc3093742..8350160419 100644 --- a/cmds/lshal/PipeRelay.h +++ b/cmds/lshal/PipeRelay.h @@ -14,9 +14,7 @@ * limitations under the License. */ -#ifndef FRAMEWORKS_NATIVE_CMDS_LSHAL_PIPE_RELAY_H_ - -#define FRAMEWORKS_NATIVE_CMDS_LSHAL_PIPE_RELAY_H_ +#pragma once #include <android-base/macros.h> #include <ostream> @@ -53,6 +51,3 @@ private: } // namespace lshal } // namespace android - -#endif // FRAMEWORKS_NATIVE_CMDS_LSHAL_PIPE_RELAY_H_ - diff --git a/cmds/lshal/TEST_MAPPING b/cmds/lshal/TEST_MAPPING new file mode 100644 index 0000000000..0320624699 --- /dev/null +++ b/cmds/lshal/TEST_MAPPING @@ -0,0 +1,8 @@ +{ + "presubmit": [ + { + "name": "lshal_test" + } + ] +} + diff --git a/cmds/lshal/TableEntry.h b/cmds/lshal/TableEntry.h index 601b7e25f9..0ff0c96d38 100644 --- a/cmds/lshal/TableEntry.h +++ b/cmds/lshal/TableEntry.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_ -#define FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_ +#pragma once #include <stdint.h> @@ -157,5 +156,3 @@ private: } // namespace lshal } // namespace android - -#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_ diff --git a/cmds/lshal/TextTable.h b/cmds/lshal/TextTable.h index 301b4bd969..be41a08251 100644 --- a/cmds/lshal/TextTable.h +++ b/cmds/lshal/TextTable.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_TEXT_TABLE_H_ -#define FRAMEWORK_NATIVE_CMDS_LSHAL_TEXT_TABLE_H_ +#pragma once #include <iostream> #include <string> @@ -80,5 +79,3 @@ private: } // namespace lshal } // namespace android - -#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_TEXT_TABLE_H_ diff --git a/cmds/lshal/Timeout.h b/cmds/lshal/Timeout.h index 46d817759d..e8d22d9b58 100644 --- a/cmds/lshal/Timeout.h +++ b/cmds/lshal/Timeout.h @@ -14,6 +14,8 @@ * limitations under the License. */ +#pragma once + #include <condition_variable> #include <chrono> #include <functional> diff --git a/cmds/lshal/libprocpartition/include/procpartition/procpartition.h b/cmds/lshal/libprocpartition/include/procpartition/procpartition.h index 7e864327af..ca1e690694 100644 --- a/cmds/lshal/libprocpartition/include/procpartition/procpartition.h +++ b/cmds/lshal/libprocpartition/include/procpartition/procpartition.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_PROCPARTITION_H_ -#define FRAMEWORK_NATIVE_CMDS_LSHAL_PROCPARTITION_H_ +#pragma once #include <sys/types.h> @@ -44,5 +43,3 @@ Partition getPartition(pid_t pid); } // namespace procpartition } // namespace android - -#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_PROCPARTITION_H_ diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp index fc8d58b3d8..76f7c7f9eb 100644 --- a/cmds/lshal/test.cpp +++ b/cmds/lshal/test.cpp @@ -493,19 +493,19 @@ TEST_F(ListTest, DumpVintf) { TEST_F(ListTest, DumpDefault) { const std::string expected = "[fake description 0]\n" - "R Interface Thread Use Server Clients\n" - "N a.h.foo1@1.0::IFoo/1 11/21 1 2 4\n" - "Y a.h.foo2@2.0::IFoo/2 12/22 2 3 5\n" + "VINTF R Interface Thread Use Server Clients\n" + "X N a.h.foo1@1.0::IFoo/1 11/21 1 2 4\n" + "X Y a.h.foo2@2.0::IFoo/2 12/22 2 3 5\n" "\n" "[fake description 1]\n" - "R Interface Thread Use Server Clients\n" - "? a.h.foo3@3.0::IFoo/3 N/A N/A 4 6\n" - "? a.h.foo4@4.0::IFoo/4 N/A N/A 5 7\n" + "VINTF R Interface Thread Use Server Clients\n" + "X ? a.h.foo3@3.0::IFoo/3 N/A N/A 4 6\n" + "X ? a.h.foo4@4.0::IFoo/4 N/A N/A 5 7\n" "\n" "[fake description 2]\n" - "R Interface Thread Use Server Clients\n" - "? a.h.foo5@5.0::IFoo/5 N/A N/A 6 8\n" - "? a.h.foo6@6.0::IFoo/6 N/A N/A 7 9\n" + "VINTF R Interface Thread Use Server Clients\n" + "X ? a.h.foo5@5.0::IFoo/5 N/A N/A 6 8\n" + "X ? a.h.foo6@6.0::IFoo/6 N/A N/A 7 9\n" "\n"; optind = 1; // mimic Lshal::parseArg() diff --git a/cmds/lshal/utils.h b/cmds/lshal/utils.h index 240155e4d0..04f52726e3 100644 --- a/cmds/lshal/utils.h +++ b/cmds/lshal/utils.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_UTILS_H_ -#define FRAMEWORK_NATIVE_CMDS_LSHAL_UTILS_H_ +#pragma once #include <iomanip> #include <iostream> @@ -88,5 +87,3 @@ void replaceAll(std::string *s, char from, char to); } // namespace lshal } // namespace android - -#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_UTILS_H_ diff --git a/cmds/servicemanager/Access.cpp b/cmds/servicemanager/Access.cpp new file mode 100644 index 0000000000..f4005c4dee --- /dev/null +++ b/cmds/servicemanager/Access.cpp @@ -0,0 +1,140 @@ +/* + * 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 "Access.h" + +#include <android-base/logging.h> +#include <binder/IPCThreadState.h> +#include <log/log_safetynet.h> +#include <selinux/android.h> +#include <selinux/avc.h> + +namespace android { + +#ifdef VENDORSERVICEMANAGER +constexpr bool kIsVendor = true; +#else +constexpr bool kIsVendor = false; +#endif + +static std::string getPidcon(pid_t pid) { + android_errorWriteLog(0x534e4554, "121035042"); + + char* lookup = nullptr; + if (getpidcon(pid, &lookup) < 0) { + LOG(ERROR) << "SELinux: getpidcon(pid=" << pid << ") failed to retrieve pid context"; + return ""; + } + std::string result = lookup; + freecon(lookup); + return result; +} + +static struct selabel_handle* getSehandle() { + static struct selabel_handle* gSehandle = nullptr; + + if (gSehandle != nullptr && selinux_status_updated()) { + selabel_close(gSehandle); + gSehandle = nullptr; + } + + if (gSehandle == nullptr) { + gSehandle = kIsVendor + ? selinux_android_vendor_service_context_handle() + : selinux_android_service_context_handle(); + } + + CHECK(gSehandle != nullptr); + return gSehandle; +} + +static int auditCallback(void *data, security_class_t /*cls*/, char *buf, size_t len) { + const Access::CallingContext* ad = reinterpret_cast<Access::CallingContext*>(data); + + if (!ad) { + LOG(ERROR) << "No service manager audit data"; + return 0; + } + + snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name.c_str(), ad->debugPid, ad->uid); + return 0; +} + +Access::Access() { + union selinux_callback cb; + + cb.func_audit = auditCallback; + selinux_set_callback(SELINUX_CB_AUDIT, cb); + + cb.func_log = kIsVendor ? selinux_vendor_log_callback : selinux_log_callback; + selinux_set_callback(SELINUX_CB_LOG, cb); + + CHECK(selinux_status_open(true /*fallback*/) >= 0); + + CHECK(getcon(&mThisProcessContext) == 0); +} + +Access::~Access() { + freecon(mThisProcessContext); +} + +Access::CallingContext Access::getCallingContext(const std::string& name) { + IPCThreadState* ipc = IPCThreadState::self(); + + const char* callingSid = ipc->getCallingSid(); + pid_t callingPid = ipc->getCallingPid(); + + return CallingContext { + .debugPid = callingPid, + .uid = ipc->getCallingUid(), + .sid = callingSid ? std::string(callingSid) : getPidcon(callingPid), + .name = name, + }; +} + +bool Access::canFind(const CallingContext& ctx) { + return actionAllowedFromLookup(ctx, "find"); +} + +bool Access::canAdd(const CallingContext& ctx) { + return actionAllowedFromLookup(ctx, "add"); +} + +bool Access::canList(const CallingContext& ctx) { + CHECK(ctx.name == ""); + + return actionAllowed(ctx, mThisProcessContext, "list"); +} + +bool Access::actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm) { + const char* tclass = "service_manager"; + + return 0 == selinux_check_access(sctx.sid.c_str(), tctx, tclass, perm, reinterpret_cast<void*>(const_cast<CallingContext*>((&sctx)))); +} + +bool Access::actionAllowedFromLookup(const CallingContext& sctx, const char *perm) { + char *tctx = nullptr; + if (selabel_lookup(getSehandle(), &tctx, sctx.name.c_str(), 0) != 0) { + LOG(ERROR) << "SELinux: No match for " << sctx.name << " in service_contexts.\n"; + return false; + } + + bool allowed = actionAllowed(sctx, tctx, perm); + freecon(tctx); + return allowed; +} + +} // android diff --git a/cmds/servicemanager/Access.h b/cmds/servicemanager/Access.h new file mode 100644 index 0000000000..b2c78cc34d --- /dev/null +++ b/cmds/servicemanager/Access.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#pragma once + +#include <string> +#include <sys/types.h> + +namespace android { + +// singleton +class Access { +public: + Access(); + virtual ~Access(); + + Access(const Access&) = delete; + Access& operator=(const Access&) = delete; + Access(Access&&) = delete; + Access& operator=(Access&&) = delete; + + struct CallingContext { + pid_t debugPid; + uid_t uid; + std::string sid; + + // name of the service + // + // empty if call is unrelated to service (e.g. list) + std::string name; + }; + + virtual CallingContext getCallingContext(const std::string& name); + + virtual bool canFind(const CallingContext& ctx); + virtual bool canAdd(const CallingContext& ctx); + virtual bool canList(const CallingContext& ctx); + +private: + bool actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm); + bool actionAllowedFromLookup(const CallingContext& sctx, const char *perm); + + char* mThisProcessContext = nullptr; +}; + +}; diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp index 428561bc8a..9cf3c5c134 100644 --- a/cmds/servicemanager/Android.bp +++ b/cmds/servicemanager/Android.bp @@ -1,51 +1,51 @@ cc_defaults { - name: "servicemanager_flags", + name: "servicemanager_defaults", cflags: [ "-Wall", "-Wextra", "-Werror", ], - product_variables: { - binder32bit: { - cflags: ["-DBINDER_IPC_32BIT=1"], - }, - }, - shared_libs: ["liblog"], -} - -cc_binary { - name: "bctest", - defaults: ["servicemanager_flags"], srcs: [ - "bctest.c", - "binder.c", + "Access.cpp", + "ServiceManager.cpp", + ], + + shared_libs: [ + "libbase", + "libbinder", // also contains servicemanager_interface + "libcutils", + "liblog", + "libutils", + "libselinux", ], } cc_binary { name: "servicemanager", - defaults: ["servicemanager_flags"], - srcs: [ - "service_manager.c", - "binder.c", - ], - shared_libs: ["libcutils", "libselinux"], + defaults: ["servicemanager_defaults"], init_rc: ["servicemanager.rc"], + srcs: ["main.cpp"], } cc_binary { name: "vndservicemanager", - defaults: ["servicemanager_flags"], + defaults: ["servicemanager_defaults"], + init_rc: ["vndservicemanager.rc"], vendor: true, - srcs: [ - "service_manager.c", - "binder.c", - ], cflags: [ "-DVENDORSERVICEMANAGER=1", ], - shared_libs: ["libcutils", "libselinux"], - init_rc: ["vndservicemanager.rc"], + srcs: ["main.cpp"], +} + +cc_test { + name: "servicemanager_test", + test_suites: ["device-tests"], + defaults: ["servicemanager_defaults"], + srcs: [ + "test_sm.cpp", + ], + static_libs: ["libgmock"], } diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp new file mode 100644 index 0000000000..b88b67d138 --- /dev/null +++ b/cmds/servicemanager/ServiceManager.cpp @@ -0,0 +1,144 @@ +/* + * 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 "ServiceManager.h" + +#include <android-base/logging.h> +#include <cutils/android_filesystem_config.h> +#include <cutils/multiuser.h> + +using ::android::binder::Status; + +namespace android { + +ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access)) {} + +Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) { + // Servicemanager is single-threaded and cannot block. This method exists for legacy reasons. + return checkService(name, outBinder); +} + +Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) { + auto ctx = mAccess->getCallingContext(name); + + auto it = mNameToService.find(name); + if (it == mNameToService.end()) { + *outBinder = nullptr; + return Status::ok(); + } + + const Service& service = it->second; + + if (!service.allowIsolated) { + uid_t appid = multiuser_get_app_id(ctx.uid); + bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END; + + if (isIsolated) { + *outBinder = nullptr; + return Status::ok(); + } + } + + // TODO(b/136023468): move this check to be first + if (!mAccess->canFind(ctx)) { + // returns ok and null for legacy reasons + *outBinder = nullptr; + return Status::ok(); + } + + *outBinder = service.binder; + return Status::ok(); +} + +Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) { + auto ctx = mAccess->getCallingContext(name); + + // apps cannot add services + if (multiuser_get_app_id(ctx.uid) >= AID_APP) { + return Status::fromExceptionCode(Status::EX_SECURITY); + } + + if (!mAccess->canAdd(ctx)) { + return Status::fromExceptionCode(Status::EX_SECURITY); + } + + if (binder == nullptr) { + return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT); + } + + // match legacy rules + if (name.size() == 0 || name.size() > 127) { + return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT); + } + + if (OK != binder->linkToDeath(this)) { + LOG(ERROR) << "Could not linkToDeath when adding " << name; + return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE); + } + + auto it = mNameToService.find(name); + if (it != mNameToService.end()) { + if (OK != it->second.binder->unlinkToDeath(this)) { + LOG(WARNING) << "Could not unlinkToDeath when adding " << name; + } + } + + mNameToService[name] = Service { + .binder = binder, + .allowIsolated = allowIsolated, + .dumpPriority = dumpPriority, + }; + + return Status::ok(); +} + +Status ServiceManager::listServices(int32_t dumpPriority, std::vector<std::string>* outList) { + if (!mAccess->canList(mAccess->getCallingContext(""))) { + return Status::fromExceptionCode(Status::EX_SECURITY); + } + + size_t toReserve = 0; + for (auto const& [name, service] : mNameToService) { + (void) name; + + if (service.dumpPriority & dumpPriority) ++toReserve; + } + + CHECK(outList->empty()); + + outList->reserve(toReserve); + for (auto const& [name, service] : mNameToService) { + (void) service; + + if (service.dumpPriority & dumpPriority) { + outList->push_back(name); + } + } + + return Status::ok(); +} + +void ServiceManager::binderDied(const wp<IBinder>& who) { + for (auto it = mNameToService.begin(); it != mNameToService.end();) { + if (who == it->second.binder) { + it = mNameToService.erase(it); + } else { + ++it; + } + } +} + +} // namespace android diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h new file mode 100644 index 0000000000..78e48052b8 --- /dev/null +++ b/cmds/servicemanager/ServiceManager.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#pragma once + +#include <android/os/BnServiceManager.h> + +#include "Access.h" + +namespace android { + +class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient { +public: + ServiceManager(std::unique_ptr<Access>&& access); + + binder::Status getService(const std::string& name, sp<IBinder>* outBinder) override; + binder::Status checkService(const std::string& name, sp<IBinder>* outBinder) override; + binder::Status addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) override; + binder::Status listServices(int32_t dumpPriority, std::vector<std::string>* outList) override; + + void binderDied(const wp<IBinder>& who) override; + +private: + struct Service { + sp<IBinder> binder; + bool allowIsolated; + int32_t dumpPriority; + }; + + std::map<std::string, Service> mNameToService; + std::unique_ptr<Access> mAccess; +}; + +} // namespace android diff --git a/cmds/servicemanager/TEST_MAPPING b/cmds/servicemanager/TEST_MAPPING new file mode 100644 index 0000000000..3e47269fe0 --- /dev/null +++ b/cmds/servicemanager/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "presubmit": [ + { + "name": "servicemanager_test" + } + ] +} diff --git a/cmds/servicemanager/bctest.c b/cmds/servicemanager/bctest.c deleted file mode 100644 index 354df670e5..0000000000 --- a/cmds/servicemanager/bctest.c +++ /dev/null @@ -1,107 +0,0 @@ -/* Copyright 2008 The Android Open Source Project - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -#include "binder.h" - -uint32_t svcmgr_lookup(struct binder_state *bs, uint32_t target, const char *name) -{ - uint32_t handle; - unsigned iodata[512/4]; - struct binder_io msg, reply; - - bio_init(&msg, iodata, sizeof(iodata), 4); - bio_put_uint32(&msg, 0); // strict mode header - bio_put_string16_x(&msg, SVC_MGR_NAME); - bio_put_string16_x(&msg, name); - - if (binder_call(bs, &msg, &reply, target, SVC_MGR_CHECK_SERVICE)) - return 0; - - handle = bio_get_ref(&reply); - - if (handle) - binder_acquire(bs, handle); - - binder_done(bs, &msg, &reply); - - return handle; -} - -int svcmgr_publish(struct binder_state *bs, uint32_t target, const char *name, void *ptr) -{ - int status; - unsigned iodata[512/4]; - struct binder_io msg, reply; - - bio_init(&msg, iodata, sizeof(iodata), 4); - bio_put_uint32(&msg, 0); // strict mode header - bio_put_string16_x(&msg, SVC_MGR_NAME); - bio_put_string16_x(&msg, name); - bio_put_obj(&msg, ptr); - - if (binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE)) - return -1; - - status = bio_get_uint32(&reply); - - binder_done(bs, &msg, &reply); - - return status; -} - -unsigned token; - -int main(int argc, char **argv) -{ - struct binder_state *bs; - uint32_t svcmgr = BINDER_SERVICE_MANAGER; - uint32_t handle; - - bs = binder_open("/dev/binder", 128*1024); - if (!bs) { - fprintf(stderr, "failed to open binder driver\n"); - return -1; - } - - argc--; - argv++; - while (argc > 0) { - if (!strcmp(argv[0],"alt")) { - handle = svcmgr_lookup(bs, svcmgr, "alt_svc_mgr"); - if (!handle) { - fprintf(stderr,"cannot find alt_svc_mgr\n"); - return -1; - } - svcmgr = handle; - fprintf(stderr,"svcmgr is via %x\n", handle); - } else if (!strcmp(argv[0],"lookup")) { - if (argc < 2) { - fprintf(stderr,"argument required\n"); - return -1; - } - handle = svcmgr_lookup(bs, svcmgr, argv[1]); - fprintf(stderr,"lookup(%s) = %x\n", argv[1], handle); - argc--; - argv++; - } else if (!strcmp(argv[0],"publish")) { - if (argc < 2) { - fprintf(stderr,"argument required\n"); - return -1; - } - svcmgr_publish(bs, svcmgr, argv[1], &token); - argc--; - argv++; - } else { - fprintf(stderr,"unknown command %s\n", argv[0]); - return -1; - } - argc--; - argv++; - } - return 0; -} diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c deleted file mode 100644 index cf3b1728b6..0000000000 --- a/cmds/servicemanager/binder.c +++ /dev/null @@ -1,682 +0,0 @@ -/* Copyright 2008 The Android Open Source Project - */ - -#define LOG_TAG "Binder" - -#include <errno.h> -#include <fcntl.h> -#include <inttypes.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mman.h> -#include <unistd.h> - -#include <log/log.h> - -#include "binder.h" - -#define MAX_BIO_SIZE (1 << 30) - -#define TRACE 0 - -void bio_init_from_txn(struct binder_io *io, struct binder_transaction_data *txn); - -#if TRACE -void hexdump(void *_data, size_t len) -{ - unsigned char *data = _data; - size_t count; - - for (count = 0; count < len; count++) { - if ((count & 15) == 0) - fprintf(stderr,"%04zu:", count); - fprintf(stderr," %02x %c", *data, - (*data < 32) || (*data > 126) ? '.' : *data); - data++; - if ((count & 15) == 15) - fprintf(stderr,"\n"); - } - if ((count & 15) != 0) - fprintf(stderr,"\n"); -} - -void binder_dump_txn(struct binder_transaction_data *txn) -{ - struct flat_binder_object *obj; - binder_size_t *offs = (binder_size_t *)(uintptr_t)txn->data.ptr.offsets; - size_t count = txn->offsets_size / sizeof(binder_size_t); - - fprintf(stderr," target %016"PRIx64" cookie %016"PRIx64" code %08x flags %08x\n", - (uint64_t)txn->target.ptr, (uint64_t)txn->cookie, txn->code, txn->flags); - fprintf(stderr," pid %8d uid %8d data %"PRIu64" offs %"PRIu64"\n", - txn->sender_pid, txn->sender_euid, (uint64_t)txn->data_size, (uint64_t)txn->offsets_size); - hexdump((void *)(uintptr_t)txn->data.ptr.buffer, txn->data_size); - while (count--) { - obj = (struct flat_binder_object *) (((char*)(uintptr_t)txn->data.ptr.buffer) + *offs++); - fprintf(stderr," - type %08x flags %08x ptr %016"PRIx64" cookie %016"PRIx64"\n", - obj->type, obj->flags, (uint64_t)obj->binder, (uint64_t)obj->cookie); - } -} - -#define NAME(n) case n: return #n -const char *cmd_name(uint32_t cmd) -{ - switch(cmd) { - NAME(BR_NOOP); - NAME(BR_TRANSACTION_COMPLETE); - NAME(BR_INCREFS); - NAME(BR_ACQUIRE); - NAME(BR_RELEASE); - NAME(BR_DECREFS); - NAME(BR_TRANSACTION); - NAME(BR_REPLY); - NAME(BR_FAILED_REPLY); - NAME(BR_DEAD_REPLY); - NAME(BR_DEAD_BINDER); - default: return "???"; - } -} -#else -#define hexdump(a,b) do{} while (0) -#define binder_dump_txn(txn) do{} while (0) -#endif - -#define BIO_F_SHARED 0x01 /* needs to be buffer freed */ -#define BIO_F_OVERFLOW 0x02 /* ran out of space */ -#define BIO_F_IOERROR 0x04 -#define BIO_F_MALLOCED 0x08 /* needs to be free()'d */ - -struct binder_state -{ - int fd; - void *mapped; - size_t mapsize; -}; - -struct binder_state *binder_open(const char* driver, size_t mapsize) -{ - struct binder_state *bs; - struct binder_version vers; - - bs = malloc(sizeof(*bs)); - if (!bs) { - errno = ENOMEM; - return NULL; - } - - bs->fd = open(driver, O_RDWR | O_CLOEXEC); - if (bs->fd < 0) { - fprintf(stderr,"binder: cannot open %s (%s)\n", - driver, strerror(errno)); - goto fail_open; - } - - if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) || - (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) { - fprintf(stderr, - "binder: kernel driver version (%d) differs from user space version (%d)\n", - vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION); - goto fail_open; - } - - bs->mapsize = mapsize; - bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); - if (bs->mapped == MAP_FAILED) { - fprintf(stderr,"binder: cannot map device (%s)\n", - strerror(errno)); - goto fail_map; - } - - return bs; - -fail_map: - close(bs->fd); -fail_open: - free(bs); - return NULL; -} - -void binder_close(struct binder_state *bs) -{ - munmap(bs->mapped, bs->mapsize); - close(bs->fd); - free(bs); -} - -int binder_become_context_manager(struct binder_state *bs) -{ - struct flat_binder_object obj; - memset(&obj, 0, sizeof(obj)); - obj.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX; - - int result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR_EXT, &obj); - - // fallback to original method - if (result != 0) { - android_errorWriteLog(0x534e4554, "121035042"); - - result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); - } - return result; -} - -int binder_write(struct binder_state *bs, void *data, size_t len) -{ - struct binder_write_read bwr; - int res; - - bwr.write_size = len; - bwr.write_consumed = 0; - bwr.write_buffer = (uintptr_t) data; - bwr.read_size = 0; - bwr.read_consumed = 0; - bwr.read_buffer = 0; - res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); - if (res < 0) { - fprintf(stderr,"binder_write: ioctl failed (%s)\n", - strerror(errno)); - } - return res; -} - -void binder_free_buffer(struct binder_state *bs, - binder_uintptr_t buffer_to_free) -{ - struct { - uint32_t cmd_free; - binder_uintptr_t buffer; - } __attribute__((packed)) data; - data.cmd_free = BC_FREE_BUFFER; - data.buffer = buffer_to_free; - binder_write(bs, &data, sizeof(data)); -} - -void binder_send_reply(struct binder_state *bs, - struct binder_io *reply, - binder_uintptr_t buffer_to_free, - int status) -{ - struct { - uint32_t cmd_free; - binder_uintptr_t buffer; - uint32_t cmd_reply; - struct binder_transaction_data txn; - } __attribute__((packed)) data; - - data.cmd_free = BC_FREE_BUFFER; - data.buffer = buffer_to_free; - data.cmd_reply = BC_REPLY; - data.txn.target.ptr = 0; - data.txn.cookie = 0; - data.txn.code = 0; - if (status) { - data.txn.flags = TF_STATUS_CODE; - data.txn.data_size = sizeof(int); - data.txn.offsets_size = 0; - data.txn.data.ptr.buffer = (uintptr_t)&status; - data.txn.data.ptr.offsets = 0; - } else { - data.txn.flags = 0; - data.txn.data_size = reply->data - reply->data0; - data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0); - data.txn.data.ptr.buffer = (uintptr_t)reply->data0; - data.txn.data.ptr.offsets = (uintptr_t)reply->offs0; - } - binder_write(bs, &data, sizeof(data)); -} - -int binder_parse(struct binder_state *bs, struct binder_io *bio, - uintptr_t ptr, size_t size, binder_handler func) -{ - int r = 1; - uintptr_t end = ptr + (uintptr_t) size; - - while (ptr < end) { - uint32_t cmd = *(uint32_t *) ptr; - ptr += sizeof(uint32_t); -#if TRACE - fprintf(stderr,"%s:\n", cmd_name(cmd)); -#endif - switch(cmd) { - case BR_NOOP: - break; - case BR_TRANSACTION_COMPLETE: - break; - case BR_INCREFS: - case BR_ACQUIRE: - case BR_RELEASE: - case BR_DECREFS: -#if TRACE - fprintf(stderr," %p, %p\n", (void *)ptr, (void *)(ptr + sizeof(void *))); -#endif - ptr += sizeof(struct binder_ptr_cookie); - break; - case BR_TRANSACTION_SEC_CTX: - case BR_TRANSACTION: { - struct binder_transaction_data_secctx txn; - if (cmd == BR_TRANSACTION_SEC_CTX) { - if ((end - ptr) < sizeof(struct binder_transaction_data_secctx)) { - ALOGE("parse: txn too small (binder_transaction_data_secctx)!\n"); - return -1; - } - memcpy(&txn, (void*) ptr, sizeof(struct binder_transaction_data_secctx)); - ptr += sizeof(struct binder_transaction_data_secctx); - } else /* BR_TRANSACTION */ { - if ((end - ptr) < sizeof(struct binder_transaction_data)) { - ALOGE("parse: txn too small (binder_transaction_data)!\n"); - return -1; - } - memcpy(&txn.transaction_data, (void*) ptr, sizeof(struct binder_transaction_data)); - ptr += sizeof(struct binder_transaction_data); - - txn.secctx = 0; - } - - binder_dump_txn(&txn.transaction_data); - if (func) { - unsigned rdata[256/4]; - struct binder_io msg; - struct binder_io reply; - int res; - - bio_init(&reply, rdata, sizeof(rdata), 4); - bio_init_from_txn(&msg, &txn.transaction_data); - res = func(bs, &txn, &msg, &reply); - if (txn.transaction_data.flags & TF_ONE_WAY) { - binder_free_buffer(bs, txn.transaction_data.data.ptr.buffer); - } else { - binder_send_reply(bs, &reply, txn.transaction_data.data.ptr.buffer, res); - } - } - break; - } - case BR_REPLY: { - struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr; - if ((end - ptr) < sizeof(*txn)) { - ALOGE("parse: reply too small!\n"); - return -1; - } - binder_dump_txn(txn); - if (bio) { - bio_init_from_txn(bio, txn); - bio = 0; - } else { - /* todo FREE BUFFER */ - } - ptr += sizeof(*txn); - r = 0; - break; - } - case BR_DEAD_BINDER: { - struct binder_death *death = (struct binder_death *)(uintptr_t) *(binder_uintptr_t *)ptr; - ptr += sizeof(binder_uintptr_t); - death->func(bs, death->ptr); - break; - } - case BR_FAILED_REPLY: - r = -1; - break; - case BR_DEAD_REPLY: - r = -1; - break; - default: - ALOGE("parse: OOPS %d\n", cmd); - return -1; - } - } - - return r; -} - -void binder_acquire(struct binder_state *bs, uint32_t target) -{ - uint32_t cmd[2]; - cmd[0] = BC_ACQUIRE; - cmd[1] = target; - binder_write(bs, cmd, sizeof(cmd)); -} - -void binder_release(struct binder_state *bs, uint32_t target) -{ - uint32_t cmd[2]; - cmd[0] = BC_RELEASE; - cmd[1] = target; - binder_write(bs, cmd, sizeof(cmd)); -} - -void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death) -{ - struct { - uint32_t cmd; - struct binder_handle_cookie payload; - } __attribute__((packed)) data; - - data.cmd = BC_REQUEST_DEATH_NOTIFICATION; - data.payload.handle = target; - data.payload.cookie = (uintptr_t) death; - binder_write(bs, &data, sizeof(data)); -} - -int binder_call(struct binder_state *bs, - struct binder_io *msg, struct binder_io *reply, - uint32_t target, uint32_t code) -{ - int res; - struct binder_write_read bwr; - struct { - uint32_t cmd; - struct binder_transaction_data txn; - } __attribute__((packed)) writebuf; - unsigned readbuf[32]; - - if (msg->flags & BIO_F_OVERFLOW) { - fprintf(stderr,"binder: txn buffer overflow\n"); - goto fail; - } - - writebuf.cmd = BC_TRANSACTION; - writebuf.txn.target.handle = target; - writebuf.txn.code = code; - writebuf.txn.flags = 0; - writebuf.txn.data_size = msg->data - msg->data0; - writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0); - writebuf.txn.data.ptr.buffer = (uintptr_t)msg->data0; - writebuf.txn.data.ptr.offsets = (uintptr_t)msg->offs0; - - bwr.write_size = sizeof(writebuf); - bwr.write_consumed = 0; - bwr.write_buffer = (uintptr_t) &writebuf; - - hexdump(msg->data0, msg->data - msg->data0); - for (;;) { - bwr.read_size = sizeof(readbuf); - bwr.read_consumed = 0; - bwr.read_buffer = (uintptr_t) readbuf; - - res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); - - if (res < 0) { - fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno)); - goto fail; - } - - res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0); - if (res == 0) return 0; - if (res < 0) goto fail; - } - -fail: - memset(reply, 0, sizeof(*reply)); - reply->flags |= BIO_F_IOERROR; - return -1; -} - -void binder_loop(struct binder_state *bs, binder_handler func) -{ - int res; - struct binder_write_read bwr; - uint32_t readbuf[32]; - - bwr.write_size = 0; - bwr.write_consumed = 0; - bwr.write_buffer = 0; - - readbuf[0] = BC_ENTER_LOOPER; - binder_write(bs, readbuf, sizeof(uint32_t)); - - for (;;) { - bwr.read_size = sizeof(readbuf); - bwr.read_consumed = 0; - bwr.read_buffer = (uintptr_t) readbuf; - - res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); - - if (res < 0) { - ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno)); - break; - } - - res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func); - if (res == 0) { - ALOGE("binder_loop: unexpected reply?!\n"); - break; - } - if (res < 0) { - ALOGE("binder_loop: io error %d %s\n", res, strerror(errno)); - break; - } - } -} - -void bio_init_from_txn(struct binder_io *bio, struct binder_transaction_data *txn) -{ - bio->data = bio->data0 = (char *)(intptr_t)txn->data.ptr.buffer; - bio->offs = bio->offs0 = (binder_size_t *)(intptr_t)txn->data.ptr.offsets; - bio->data_avail = txn->data_size; - bio->offs_avail = txn->offsets_size / sizeof(size_t); - bio->flags = BIO_F_SHARED; -} - -void bio_init(struct binder_io *bio, void *data, - size_t maxdata, size_t maxoffs) -{ - size_t n = maxoffs * sizeof(size_t); - - if (n > maxdata) { - bio->flags = BIO_F_OVERFLOW; - bio->data_avail = 0; - bio->offs_avail = 0; - return; - } - - bio->data = bio->data0 = (char *) data + n; - bio->offs = bio->offs0 = data; - bio->data_avail = maxdata - n; - bio->offs_avail = maxoffs; - bio->flags = 0; -} - -static void *bio_alloc(struct binder_io *bio, size_t size) -{ - size = (size + 3) & (~3); - if (size > bio->data_avail) { - bio->flags |= BIO_F_OVERFLOW; - return NULL; - } else { - void *ptr = bio->data; - bio->data += size; - bio->data_avail -= size; - return ptr; - } -} - -void binder_done(struct binder_state *bs, - __unused struct binder_io *msg, - struct binder_io *reply) -{ - struct { - uint32_t cmd; - uintptr_t buffer; - } __attribute__((packed)) data; - - if (reply->flags & BIO_F_SHARED) { - data.cmd = BC_FREE_BUFFER; - data.buffer = (uintptr_t) reply->data0; - binder_write(bs, &data, sizeof(data)); - reply->flags = 0; - } -} - -static struct flat_binder_object *bio_alloc_obj(struct binder_io *bio) -{ - struct flat_binder_object *obj; - - obj = bio_alloc(bio, sizeof(*obj)); - - if (obj && bio->offs_avail) { - bio->offs_avail--; - *bio->offs++ = ((char*) obj) - ((char*) bio->data0); - return obj; - } - - bio->flags |= BIO_F_OVERFLOW; - return NULL; -} - -void bio_put_uint32(struct binder_io *bio, uint32_t n) -{ - uint32_t *ptr = bio_alloc(bio, sizeof(n)); - if (ptr) - *ptr = n; -} - -void bio_put_obj(struct binder_io *bio, void *ptr) -{ - struct flat_binder_object *obj; - - obj = bio_alloc_obj(bio); - if (!obj) - return; - - obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; - obj->hdr.type = BINDER_TYPE_BINDER; - obj->binder = (uintptr_t)ptr; - obj->cookie = 0; -} - -void bio_put_ref(struct binder_io *bio, uint32_t handle) -{ - struct flat_binder_object *obj; - - if (handle) - obj = bio_alloc_obj(bio); - else - obj = bio_alloc(bio, sizeof(*obj)); - - if (!obj) - return; - - obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; - obj->hdr.type = BINDER_TYPE_HANDLE; - obj->handle = handle; - obj->cookie = 0; -} - -void bio_put_string16(struct binder_io *bio, const uint16_t *str) -{ - size_t len; - uint16_t *ptr; - - if (!str) { - bio_put_uint32(bio, 0xffffffff); - return; - } - - len = 0; - while (str[len]) len++; - - if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) { - bio_put_uint32(bio, 0xffffffff); - return; - } - - /* Note: The payload will carry 32bit size instead of size_t */ - bio_put_uint32(bio, (uint32_t) len); - len = (len + 1) * sizeof(uint16_t); - ptr = bio_alloc(bio, len); - if (ptr) - memcpy(ptr, str, len); -} - -void bio_put_string16_x(struct binder_io *bio, const char *_str) -{ - unsigned char *str = (unsigned char*) _str; - size_t len; - uint16_t *ptr; - - if (!str) { - bio_put_uint32(bio, 0xffffffff); - return; - } - - len = strlen(_str); - - if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) { - bio_put_uint32(bio, 0xffffffff); - return; - } - - /* Note: The payload will carry 32bit size instead of size_t */ - bio_put_uint32(bio, len); - ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t)); - if (!ptr) - return; - - while (*str) - *ptr++ = *str++; - *ptr++ = 0; -} - -static void *bio_get(struct binder_io *bio, size_t size) -{ - size = (size + 3) & (~3); - - if (bio->data_avail < size){ - bio->data_avail = 0; - bio->flags |= BIO_F_OVERFLOW; - return NULL; - } else { - void *ptr = bio->data; - bio->data += size; - bio->data_avail -= size; - return ptr; - } -} - -uint32_t bio_get_uint32(struct binder_io *bio) -{ - uint32_t *ptr = bio_get(bio, sizeof(*ptr)); - return ptr ? *ptr : 0; -} - -uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz) -{ - size_t len; - - /* Note: The payload will carry 32bit size instead of size_t */ - len = (size_t) bio_get_uint32(bio); - if (sz) - *sz = len; - return bio_get(bio, (len + 1) * sizeof(uint16_t)); -} - -static struct flat_binder_object *_bio_get_obj(struct binder_io *bio) -{ - size_t n; - size_t off = bio->data - bio->data0; - - /* TODO: be smarter about this? */ - for (n = 0; n < bio->offs_avail; n++) { - if (bio->offs[n] == off) - return bio_get(bio, sizeof(struct flat_binder_object)); - } - - bio->data_avail = 0; - bio->flags |= BIO_F_OVERFLOW; - return NULL; -} - -uint32_t bio_get_ref(struct binder_io *bio) -{ - struct flat_binder_object *obj; - - obj = _bio_get_obj(bio); - if (!obj) - return 0; - - if (obj->hdr.type == BINDER_TYPE_HANDLE) - return obj->handle; - - return 0; -} diff --git a/cmds/servicemanager/binder.h b/cmds/servicemanager/binder.h deleted file mode 100644 index a9ccc74130..0000000000 --- a/cmds/servicemanager/binder.h +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright 2008 The Android Open Source Project - */ - -#ifndef _BINDER_H_ -#define _BINDER_H_ - -#include <linux/android/binder.h> -#include <sys/ioctl.h> - -struct binder_state; - -struct binder_io -{ - char *data; /* pointer to read/write from */ - binder_size_t *offs; /* array of offsets */ - size_t data_avail; /* bytes available in data buffer */ - size_t offs_avail; /* entries available in offsets array */ - - char *data0; /* start of data buffer */ - binder_size_t *offs0; /* start of offsets buffer */ - uint32_t flags; - uint32_t unused; -}; - -struct binder_death { - void (*func)(struct binder_state *bs, void *ptr); - void *ptr; -}; - -/* the one magic handle */ -#define BINDER_SERVICE_MANAGER 0U - -#define SVC_MGR_NAME "android.os.IServiceManager" - -enum { - /* Must match definitions in IBinder.h and IServiceManager.h */ - PING_TRANSACTION = B_PACK_CHARS('_','P','N','G'), - SVC_MGR_GET_SERVICE = 1, - SVC_MGR_CHECK_SERVICE, - SVC_MGR_ADD_SERVICE, - SVC_MGR_LIST_SERVICES, -}; - -typedef int (*binder_handler)(struct binder_state *bs, - struct binder_transaction_data_secctx *txn, - struct binder_io *msg, - struct binder_io *reply); - -struct binder_state *binder_open(const char* driver, size_t mapsize); -void binder_close(struct binder_state *bs); - -/* initiate a blocking binder call - * - returns zero on success - */ -int binder_call(struct binder_state *bs, - struct binder_io *msg, struct binder_io *reply, - uint32_t target, uint32_t code); - -/* release any state associate with the binder_io - * - call once any necessary data has been extracted from the - * binder_io after binder_call() returns - * - can safely be called even if binder_call() fails - */ -void binder_done(struct binder_state *bs, - struct binder_io *msg, struct binder_io *reply); - -/* manipulate strong references */ -void binder_acquire(struct binder_state *bs, uint32_t target); -void binder_release(struct binder_state *bs, uint32_t target); - -void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death); - -void binder_loop(struct binder_state *bs, binder_handler func); - -int binder_become_context_manager(struct binder_state *bs); - -/* allocate a binder_io, providing a stack-allocated working - * buffer, size of the working buffer, and how many object - * offset entries to reserve from the buffer - */ -void bio_init(struct binder_io *bio, void *data, - size_t maxdata, size_t maxobjects); - -void bio_put_obj(struct binder_io *bio, void *ptr); -void bio_put_ref(struct binder_io *bio, uint32_t handle); -void bio_put_uint32(struct binder_io *bio, uint32_t n); -void bio_put_string16(struct binder_io *bio, const uint16_t *str); -void bio_put_string16_x(struct binder_io *bio, const char *_str); - -uint32_t bio_get_uint32(struct binder_io *bio); -uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz); -uint32_t bio_get_ref(struct binder_io *bio); - -#endif diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp new file mode 100644 index 0000000000..9f6193b97a --- /dev/null +++ b/cmds/servicemanager/main.cpp @@ -0,0 +1,53 @@ +/* + * 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 <android-base/logging.h> +#include <binder/IPCThreadState.h> +#include <binder/ProcessState.h> +#include <binder/Status.h> +#include <utils/StrongPointer.h> + +#include "Access.h" +#include "ServiceManager.h" + +using ::android::sp; +using ::android::ProcessState; +using ::android::IPCThreadState; +using ::android::ServiceManager; +using ::android::Access; + +int main(int argc, char** argv) { + if (argc > 2) { + LOG(FATAL) << "usage: " << argv[0] << " [binder driver]"; + } + + const char* driver = argc == 2 ? argv[1] : "/dev/binder"; + + android::base::InitLogging(nullptr, &android::base::KernelLogger); + + sp<ProcessState> ps = ProcessState::initWithDriver(driver); + ps->setThreadPoolMaxThreadCount(0); + ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY); + + sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>()); + IPCThreadState::self()->setTheContextObject(manager); + ps->becomeContextManager(nullptr, nullptr); + + IPCThreadState::self()->joinThreadPool(); + + // should not be reached + return EXIT_FAILURE; +} diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c deleted file mode 100644 index ec3fac538d..0000000000 --- a/cmds/servicemanager/service_manager.c +++ /dev/null @@ -1,442 +0,0 @@ -/* Copyright 2008 The Android Open Source Project - */ - -#include <errno.h> -#include <fcntl.h> -#include <inttypes.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <cutils/android_filesystem_config.h> -#include <cutils/multiuser.h> - -#include <selinux/android.h> -#include <selinux/avc.h> - -#include "binder.h" - -#ifdef VENDORSERVICEMANAGER -#define LOG_TAG "VendorServiceManager" -#else -#define LOG_TAG "ServiceManager" -#endif -#include <log/log.h> - -struct audit_data { - pid_t pid; - uid_t uid; - const char *name; -}; - -const char *str8(const uint16_t *x, size_t x_len) -{ - static char buf[128]; - size_t max = 127; - char *p = buf; - - if (x_len < max) { - max = x_len; - } - - if (x) { - while ((max > 0) && (*x != '\0')) { - *p++ = *x++; - max--; - } - } - *p++ = 0; - return buf; -} - -int str16eq(const uint16_t *a, const char *b) -{ - while (*a && *b) - if (*a++ != *b++) return 0; - if (*a || *b) - return 0; - return 1; -} - -static char *service_manager_context; -static struct selabel_handle* sehandle; - -static bool check_mac_perms(pid_t spid, const char* sid, uid_t uid, const char *tctx, const char *perm, const char *name) -{ - char *lookup_sid = NULL; - const char *class = "service_manager"; - bool allowed; - struct audit_data ad; - - if (sid == NULL && getpidcon(spid, &lookup_sid) < 0) { - ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid); - return false; - } - - ad.pid = spid; - ad.uid = uid; - ad.name = name; - - if (sid == NULL) { - android_errorWriteLog(0x534e4554, "121035042"); - } - - int result = selinux_check_access(sid ? sid : lookup_sid, tctx, class, perm, (void *) &ad); - allowed = (result == 0); - - freecon(lookup_sid); - return allowed; -} - -static bool check_mac_perms_from_getcon(pid_t spid, const char* sid, uid_t uid, const char *perm) -{ - return check_mac_perms(spid, sid, uid, service_manager_context, perm, NULL); -} - -static bool check_mac_perms_from_lookup(pid_t spid, const char* sid, uid_t uid, const char *perm, const char *name) -{ - bool allowed; - char *tctx = NULL; - - if (!sehandle) { - ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n"); - abort(); - } - - if (selabel_lookup(sehandle, &tctx, name, 0) != 0) { - ALOGE("SELinux: No match for %s in service_contexts.\n", name); - return false; - } - - allowed = check_mac_perms(spid, sid, uid, tctx, perm, name); - freecon(tctx); - return allowed; -} - -static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid) -{ - const char *perm = "add"; - - if (multiuser_get_app_id(uid) >= AID_APP) { - return 0; /* Don't allow apps to register services */ - } - - return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0; -} - -static int svc_can_list(pid_t spid, const char* sid, uid_t uid) -{ - const char *perm = "list"; - return check_mac_perms_from_getcon(spid, sid, uid, perm) ? 1 : 0; -} - -static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid) -{ - const char *perm = "find"; - return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0; -} - -struct svcinfo -{ - struct svcinfo *next; - uint32_t handle; - struct binder_death death; - int allow_isolated; - uint32_t dumpsys_priority; - size_t len; - uint16_t name[0]; -}; - -struct svcinfo *svclist = NULL; - -struct svcinfo *find_svc(const uint16_t *s16, size_t len) -{ - struct svcinfo *si; - - for (si = svclist; si; si = si->next) { - if ((len == si->len) && - !memcmp(s16, si->name, len * sizeof(uint16_t))) { - return si; - } - } - return NULL; -} - -void svcinfo_death(struct binder_state *bs, void *ptr) -{ - struct svcinfo *si = (struct svcinfo* ) ptr; - - ALOGI("service '%s' died\n", str8(si->name, si->len)); - if (si->handle) { - binder_release(bs, si->handle); - si->handle = 0; - } -} - -uint16_t svcmgr_id[] = { - 'a','n','d','r','o','i','d','.','o','s','.', - 'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r' -}; - - -uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid, const char* sid) -{ - struct svcinfo *si = find_svc(s, len); - - if (!si || !si->handle) { - return 0; - } - - if (!si->allow_isolated) { - // If this service doesn't allow access from isolated processes, - // then check the uid to see if it is isolated. - uid_t appid = uid % AID_USER; - if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) { - return 0; - } - } - - if (!svc_can_find(s, len, spid, sid, uid)) { - return 0; - } - - return si->handle; -} - -int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle, - uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid, const char* sid) { - struct svcinfo *si; - - //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle, - // allow_isolated ? "allow_isolated" : "!allow_isolated", uid); - - if (!handle || (len == 0) || (len > 127)) - return -1; - - if (!svc_can_register(s, len, spid, sid, uid)) { - ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n", - str8(s, len), handle, uid); - return -1; - } - - si = find_svc(s, len); - if (si) { - if (si->handle) { - ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n", - str8(s, len), handle, uid); - svcinfo_death(bs, si); - } - si->handle = handle; - } else { - si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t)); - if (!si) { - ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n", - str8(s, len), handle, uid); - return -1; - } - si->handle = handle; - si->len = len; - memcpy(si->name, s, (len + 1) * sizeof(uint16_t)); - si->name[len] = '\0'; - si->death.func = (void*) svcinfo_death; - si->death.ptr = si; - si->allow_isolated = allow_isolated; - si->dumpsys_priority = dumpsys_priority; - si->next = svclist; - svclist = si; - } - - binder_acquire(bs, handle); - binder_link_to_death(bs, handle, &si->death); - return 0; -} - -int svcmgr_handler(struct binder_state *bs, - struct binder_transaction_data_secctx *txn_secctx, - struct binder_io *msg, - struct binder_io *reply) -{ - struct svcinfo *si; - uint16_t *s; - size_t len; - uint32_t handle; - uint32_t strict_policy; - int allow_isolated; - uint32_t dumpsys_priority; - - struct binder_transaction_data *txn = &txn_secctx->transaction_data; - - //ALOGI("target=%p code=%d pid=%d uid=%d\n", - // (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid); - - if (txn->target.ptr != BINDER_SERVICE_MANAGER) - return -1; - - if (txn->code == PING_TRANSACTION) - return 0; - - // Equivalent to Parcel::enforceInterface(), reading the RPC - // header with the strict mode policy mask and the interface name. - // Note that we ignore the strict_policy and don't propagate it - // further (since we do no outbound RPCs anyway). - strict_policy = bio_get_uint32(msg); - bio_get_uint32(msg); // Ignore worksource header. - s = bio_get_string16(msg, &len); - if (s == NULL) { - return -1; - } - - if ((len != (sizeof(svcmgr_id) / 2)) || - memcmp(svcmgr_id, s, sizeof(svcmgr_id))) { - fprintf(stderr,"invalid id %s\n", str8(s, len)); - return -1; - } - - if (sehandle && selinux_status_updated() > 0) { -#ifdef VENDORSERVICEMANAGER - struct selabel_handle *tmp_sehandle = selinux_android_vendor_service_context_handle(); -#else - struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle(); -#endif - if (tmp_sehandle) { - selabel_close(sehandle); - sehandle = tmp_sehandle; - } - } - - switch(txn->code) { - case SVC_MGR_GET_SERVICE: - case SVC_MGR_CHECK_SERVICE: - s = bio_get_string16(msg, &len); - if (s == NULL) { - return -1; - } - handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid, - (const char*) txn_secctx->secctx); - if (!handle) - break; - bio_put_ref(reply, handle); - return 0; - - case SVC_MGR_ADD_SERVICE: - s = bio_get_string16(msg, &len); - if (s == NULL) { - return -1; - } - handle = bio_get_ref(msg); - allow_isolated = bio_get_uint32(msg) ? 1 : 0; - dumpsys_priority = bio_get_uint32(msg); - if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority, - txn->sender_pid, (const char*) txn_secctx->secctx)) - return -1; - break; - - case SVC_MGR_LIST_SERVICES: { - uint32_t n = bio_get_uint32(msg); - uint32_t req_dumpsys_priority = bio_get_uint32(msg); - - if (!svc_can_list(txn->sender_pid, (const char*) txn_secctx->secctx, txn->sender_euid)) { - ALOGE("list_service() uid=%d - PERMISSION DENIED\n", - txn->sender_euid); - return -1; - } - si = svclist; - // walk through the list of services n times skipping services that - // do not support the requested priority - while (si) { - if (si->dumpsys_priority & req_dumpsys_priority) { - if (n == 0) break; - n--; - } - si = si->next; - } - if (si) { - bio_put_string16(reply, si->name); - return 0; - } - return -1; - } - default: - ALOGE("unknown code %d\n", txn->code); - return -1; - } - - bio_put_uint32(reply, 0); - return 0; -} - - -static int audit_callback(void *data, __unused security_class_t cls, char *buf, size_t len) -{ - struct audit_data *ad = (struct audit_data *)data; - - if (!ad || !ad->name) { - ALOGE("No service manager audit data"); - return 0; - } - - snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name, ad->pid, ad->uid); - return 0; -} - -int main(int argc, char** argv) -{ - struct binder_state *bs; - union selinux_callback cb; - char *driver; - - if (argc > 1) { - driver = argv[1]; - } else { - driver = "/dev/binder"; - } - - bs = binder_open(driver, 128*1024); - if (!bs) { -#ifdef VENDORSERVICEMANAGER - ALOGW("failed to open binder driver %s\n", driver); - while (true) { - sleep(UINT_MAX); - } -#else - ALOGE("failed to open binder driver %s\n", driver); -#endif - return -1; - } - - if (binder_become_context_manager(bs)) { - ALOGE("cannot become context manager (%s)\n", strerror(errno)); - return -1; - } - - cb.func_audit = audit_callback; - selinux_set_callback(SELINUX_CB_AUDIT, cb); -#ifdef VENDORSERVICEMANAGER - cb.func_log = selinux_vendor_log_callback; -#else - cb.func_log = selinux_log_callback; -#endif - selinux_set_callback(SELINUX_CB_LOG, cb); - -#ifdef VENDORSERVICEMANAGER - sehandle = selinux_android_vendor_service_context_handle(); -#else - sehandle = selinux_android_service_context_handle(); -#endif - selinux_status_open(true); - - if (sehandle == NULL) { - ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n"); - abort(); - } - - if (getcon(&service_manager_context) != 0) { - ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n"); - abort(); - } - - - binder_loop(bs, svcmgr_handler); - - return 0; -} diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp new file mode 100644 index 0000000000..812d5cacd5 --- /dev/null +++ b/cmds/servicemanager/test_sm.cpp @@ -0,0 +1,261 @@ +/* + * 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 <binder/ProcessState.h> +#include <cutils/android_filesystem_config.h> +#include <gtest/gtest.h> +#include <gmock/gmock.h> + +#include "Access.h" +#include "ServiceManager.h" + +using android::sp; +using android::Access; +using android::IBinder; +using android::ServiceManager; +using android::os::IServiceManager; +using testing::_; +using testing::ElementsAre; +using testing::NiceMock; +using testing::Return; + +static sp<IBinder> getBinder() { + // It doesn't matter what remote binder it is, we just need one so that linkToDeath will work. + // The context manager (servicemanager) is easy to get and is in another process. + return android::ProcessState::self()->getContextObject(nullptr); +} + +class MockAccess : public Access { +public: + MOCK_METHOD1(getCallingContext, CallingContext(const std::string& name)); + MOCK_METHOD1(canAdd, bool(const CallingContext&)); + MOCK_METHOD1(canFind, bool(const CallingContext&)); + MOCK_METHOD1(canList, bool(const CallingContext&)); +}; + +static sp<ServiceManager> getPermissiveServiceManager() { + std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>(); + + ON_CALL(*access, getCallingContext(_)).WillByDefault(Return(Access::CallingContext{})); + ON_CALL(*access, canAdd(_)).WillByDefault(Return(true)); + ON_CALL(*access, canFind(_)).WillByDefault(Return(true)); + ON_CALL(*access, canList(_)).WillByDefault(Return(true)); + + sp<ServiceManager> sm = new ServiceManager(std::move(access)); + return sm; +} + +TEST(AddService, HappyHappy) { + auto sm = getPermissiveServiceManager(); + EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); +} + +TEST(AddService, EmptyNameDisallowed) { + auto sm = getPermissiveServiceManager(); + EXPECT_FALSE(sm->addService("", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); +} + +TEST(AddService, JustShortEnoughServiceNameHappy) { + auto sm = getPermissiveServiceManager(); + EXPECT_TRUE(sm->addService(std::string(127, 'a'), getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); +} + +TEST(AddService, TooLongNameDisallowed) { + auto sm = getPermissiveServiceManager(); + EXPECT_FALSE(sm->addService(std::string(128, 'a'), getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); +} + +TEST(AddService, AddNullServiceDisallowed) { + auto sm = getPermissiveServiceManager(); + EXPECT_FALSE(sm->addService("foo", nullptr, false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); +} + +TEST(AddService, AddDisallowedFromApp) { + for (uid_t uid : { AID_APP_START, AID_APP_START + 1, AID_APP_END }) { + std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>(); + EXPECT_CALL(*access, getCallingContext(_)).WillOnce(Return(Access::CallingContext{ + .debugPid = 1337, + .uid = uid, + })); + EXPECT_CALL(*access, canAdd(_)).Times(0); + sp<ServiceManager> sm = new ServiceManager(std::move(access)); + + EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); + } + +} + +TEST(AddService, HappyOverExistingService) { + auto sm = getPermissiveServiceManager(); + EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); + EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); +} + +TEST(AddService, NoPermissions) { + std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>(); + + EXPECT_CALL(*access, getCallingContext(_)).WillOnce(Return(Access::CallingContext{})); + EXPECT_CALL(*access, canAdd(_)).WillOnce(Return(false)); + + sp<ServiceManager> sm = new ServiceManager(std::move(access)); + + EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); +} + +TEST(GetService, HappyHappy) { + auto sm = getPermissiveServiceManager(); + EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); + + sp<IBinder> out; + EXPECT_TRUE(sm->getService("foo", &out).isOk()); + EXPECT_EQ(getBinder(), out); +} + +TEST(GetService, NonExistant) { + auto sm = getPermissiveServiceManager(); + + sp<IBinder> out; + EXPECT_TRUE(sm->getService("foo", &out).isOk()); + EXPECT_EQ(nullptr, out.get()); +} + +TEST(GetService, NoPermissionsForGettingService) { + std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>(); + + EXPECT_CALL(*access, getCallingContext(_)).WillRepeatedly(Return(Access::CallingContext{})); + EXPECT_CALL(*access, canAdd(_)).WillOnce(Return(true)); + EXPECT_CALL(*access, canFind(_)).WillOnce(Return(false)); + + sp<ServiceManager> sm = new ServiceManager(std::move(access)); + + EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); + + sp<IBinder> out; + // returns nullptr but has OK status for legacy compatibility + EXPECT_TRUE(sm->getService("foo", &out).isOk()); + EXPECT_EQ(nullptr, out.get()); +} + +TEST(GetService, AllowedFromIsolated) { + std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>(); + + EXPECT_CALL(*access, getCallingContext(_)) + // something adds it + .WillOnce(Return(Access::CallingContext{})) + // next call is from isolated app + .WillOnce(Return(Access::CallingContext{ + .uid = AID_ISOLATED_START, + })); + EXPECT_CALL(*access, canAdd(_)).WillOnce(Return(true)); + EXPECT_CALL(*access, canFind(_)).WillOnce(Return(true)); + + sp<ServiceManager> sm = new ServiceManager(std::move(access)); + + EXPECT_TRUE(sm->addService("foo", getBinder(), true /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); + + sp<IBinder> out; + EXPECT_TRUE(sm->getService("foo", &out).isOk()); + EXPECT_EQ(getBinder(), out.get()); +} + +TEST(GetService, NotAllowedFromIsolated) { + std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>(); + + EXPECT_CALL(*access, getCallingContext(_)) + // something adds it + .WillOnce(Return(Access::CallingContext{})) + // next call is from isolated app + .WillOnce(Return(Access::CallingContext{ + .uid = AID_ISOLATED_START, + })); + EXPECT_CALL(*access, canAdd(_)).WillOnce(Return(true)); + + // TODO(b/136023468): when security check is first, this should be called first + // EXPECT_CALL(*access, canFind(_)).WillOnce(Return(true)); + + sp<ServiceManager> sm = new ServiceManager(std::move(access)); + + EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); + + sp<IBinder> out; + // returns nullptr but has OK status for legacy compatibility + EXPECT_TRUE(sm->getService("foo", &out).isOk()); + EXPECT_EQ(nullptr, out.get()); +} + +TEST(ListServices, NoPermissions) { + std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>(); + + EXPECT_CALL(*access, getCallingContext(_)).WillOnce(Return(Access::CallingContext{})); + EXPECT_CALL(*access, canList(_)).WillOnce(Return(false)); + + sp<ServiceManager> sm = new ServiceManager(std::move(access)); + + std::vector<std::string> out; + EXPECT_FALSE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk()); + EXPECT_TRUE(out.empty()); +} + +TEST(ListServices, AllServices) { + auto sm = getPermissiveServiceManager(); + + EXPECT_TRUE(sm->addService("sd", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); + EXPECT_TRUE(sm->addService("sc", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_NORMAL).isOk()); + EXPECT_TRUE(sm->addService("sb", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_HIGH).isOk()); + EXPECT_TRUE(sm->addService("sa", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL).isOk()); + + std::vector<std::string> out; + EXPECT_TRUE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk()); + + // all there and in the right order + EXPECT_THAT(out, ElementsAre("sa", "sb", "sc", "sd")); +} + +TEST(ListServices, CriticalServices) { + auto sm = getPermissiveServiceManager(); + + EXPECT_TRUE(sm->addService("sd", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); + EXPECT_TRUE(sm->addService("sc", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_NORMAL).isOk()); + EXPECT_TRUE(sm->addService("sb", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_HIGH).isOk()); + EXPECT_TRUE(sm->addService("sa", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL).isOk()); + + std::vector<std::string> out; + EXPECT_TRUE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL, &out).isOk()); + + // all there and in the right order + EXPECT_THAT(out, ElementsAre("sa")); +} diff --git a/include/android/font.h b/include/android/font.h index 435a573f51..8001ee1938 100644 --- a/include/android/font.h +++ b/include/android/font.h @@ -16,7 +16,7 @@ /** * @addtogroup Font - * { + * @{ */ /** diff --git a/include/android/font_matcher.h b/include/android/font_matcher.h index e286a4c812..0b8f892b9b 100644 --- a/include/android/font_matcher.h +++ b/include/android/font_matcher.h @@ -16,7 +16,7 @@ /** * @addtogroup Font - * { + * @{ */ /** diff --git a/include/android/system_fonts.h b/include/android/system_fonts.h index dde9055c7a..f0485a1871 100644 --- a/include/android/system_fonts.h +++ b/include/android/system_fonts.h @@ -16,7 +16,7 @@ /** * @addtogroup Font - * { + * @{ */ /** diff --git a/include/audiomanager/OWNERS b/include/audiomanager/OWNERS new file mode 100644 index 0000000000..2bd527cc3f --- /dev/null +++ b/include/audiomanager/OWNERS @@ -0,0 +1,2 @@ +elaurent@google.com +jmtrivi@google.com diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index aedf6b0d18..760d55b751 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -94,7 +94,6 @@ cc_library_shared { "PermissionController.cpp", "ProcessInfoService.cpp", "IpPrefix.cpp", - ":libbinder_aidl", ], }, }, @@ -142,7 +141,7 @@ filegroup { name: "libbinder_aidl", srcs: [ "aidl/android/content/pm/IPackageManagerNative.aidl", + "aidl/android/os/IServiceManager.aidl", ], + path: "aidl", } - -subdirs = ["tests"] diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp index ec170f7a65..67f968aea0 100644 --- a/libs/binder/BpBinder.cpp +++ b/libs/binder/BpBinder.cpp @@ -387,21 +387,6 @@ BpBinder::~BpBinder() } } - mLock.lock(); - Vector<Obituary>* obits = mObituaries; - if(obits != nullptr) { - if (ipc) ipc->clearDeathNotification(mHandle, this); - mObituaries = nullptr; - } - mLock.unlock(); - - if (obits != nullptr) { - // XXX Should we tell any remaining DeathRecipient - // objects that the last strong ref has gone away, so they - // are no longer linked? - delete obits; - } - if (ipc) { ipc->expungeHandle(mHandle, this); ipc->decWeakHandle(mHandle); @@ -423,6 +408,25 @@ void BpBinder::onLastStrongRef(const void* /*id*/) } IPCThreadState* ipc = IPCThreadState::self(); if (ipc) ipc->decStrongHandle(mHandle); + + mLock.lock(); + Vector<Obituary>* obits = mObituaries; + if(obits != nullptr) { + if (!obits->isEmpty()) { + ALOGI("onLastStrongRef automatically unlinking death recipients"); + } + + if (ipc) ipc->clearDeathNotification(mHandle, this); + mObituaries = nullptr; + } + mLock.unlock(); + + if (obits != nullptr) { + // XXX Should we tell any remaining DeathRecipient + // objects that the last strong ref has gone away, so they + // are no longer linked? + delete obits; + } } bool BpBinder::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/) diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index 9a561cba64..3424c28883 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -33,6 +33,7 @@ #include <private/binder/binder_module.h> #include <private/binder/Static.h> +#include <atomic> #include <errno.h> #include <inttypes.h> #include <pthread.h> @@ -116,7 +117,7 @@ static const int64_t kWorkSourcePropagatedBitIndex = 32; static const char* getReturnString(uint32_t cmd) { - size_t idx = cmd & 0xff; + size_t idx = cmd & _IOC_NRMASK; if (idx < sizeof(kReturnStrings) / sizeof(kReturnStrings[0])) return kReturnStrings[idx]; else @@ -278,14 +279,14 @@ static const void* printCommand(TextOutput& out, const void* _cmd) } static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER; -static bool gHaveTLS = false; +static std::atomic<bool> gHaveTLS(false); static pthread_key_t gTLS = 0; -static bool gShutdown = false; -static bool gDisableBackgroundScheduling = false; +static std::atomic<bool> gShutdown = false; +static std::atomic<bool> gDisableBackgroundScheduling = false; IPCThreadState* IPCThreadState::self() { - if (gHaveTLS) { + if (gHaveTLS.load(std::memory_order_acquire)) { restart: const pthread_key_t k = gTLS; IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k); @@ -293,13 +294,14 @@ restart: return new IPCThreadState; } - if (gShutdown) { + // Racey, heuristic test for simultaneous shutdown. + if (gShutdown.load(std::memory_order_relaxed)) { ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n"); return nullptr; } pthread_mutex_lock(&gTLSMutex); - if (!gHaveTLS) { + if (!gHaveTLS.load(std::memory_order_relaxed)) { int key_create_value = pthread_key_create(&gTLS, threadDestructor); if (key_create_value != 0) { pthread_mutex_unlock(&gTLSMutex); @@ -307,7 +309,7 @@ restart: strerror(key_create_value)); return nullptr; } - gHaveTLS = true; + gHaveTLS.store(true, std::memory_order_release); } pthread_mutex_unlock(&gTLSMutex); goto restart; @@ -315,7 +317,7 @@ restart: IPCThreadState* IPCThreadState::selfOrNull() { - if (gHaveTLS) { + if (gHaveTLS.load(std::memory_order_acquire)) { const pthread_key_t k = gTLS; IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k); return st; @@ -325,9 +327,9 @@ IPCThreadState* IPCThreadState::selfOrNull() void IPCThreadState::shutdown() { - gShutdown = true; + gShutdown.store(true, std::memory_order_relaxed); - if (gHaveTLS) { + if (gHaveTLS.load(std::memory_order_acquire)) { // XXX Need to wait for all thread pool threads to exit! IPCThreadState* st = (IPCThreadState*)pthread_getspecific(gTLS); if (st) { @@ -335,18 +337,18 @@ void IPCThreadState::shutdown() pthread_setspecific(gTLS, nullptr); } pthread_key_delete(gTLS); - gHaveTLS = false; + gHaveTLS.store(false, std::memory_order_release); } } void IPCThreadState::disableBackgroundScheduling(bool disable) { - gDisableBackgroundScheduling = disable; + gDisableBackgroundScheduling.store(disable, std::memory_order_relaxed); } bool IPCThreadState::backgroundSchedulingDisabled() { - return gDisableBackgroundScheduling; + return gDisableBackgroundScheduling.load(std::memory_order_relaxed); } sp<ProcessState> IPCThreadState::process() @@ -674,11 +676,11 @@ status_t IPCThreadState::transact(int32_t handle, if ((flags & TF_ONE_WAY) == 0) { if (UNLIKELY(mCallRestriction != ProcessState::CallRestriction::NONE)) { if (mCallRestriction == ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY) { - ALOGE("Process making non-oneway call but is restricted."); + ALOGE("Process making non-oneway call (code: %u) but is restricted.", code); CallStack::logStack("non-oneway call", CallStack::getCurrent(10).get(), ANDROID_LOG_ERROR); } else /* FATAL_IF_NOT_ONEWAY */ { - LOG_ALWAYS_FATAL("Process may not make oneway calls."); + LOG_ALWAYS_FATAL("Process may not make oneway calls (code: %u).", code); } } @@ -1060,7 +1062,7 @@ status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, sp<BBinder> the_context_object; -void setTheContextObject(sp<BBinder> obj) +void IPCThreadState::setTheContextObject(sp<BBinder> obj) { the_context_object = obj; } diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index 4ba6c2a923..07550fb571 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -18,6 +18,7 @@ #include <binder/IServiceManager.h> +#include <android/os/IServiceManager.h> #include <utils/Log.h> #include <binder/IPCThreadState.h> #ifndef __ANDROID_VNDK__ @@ -34,8 +35,14 @@ namespace android { +using AidlServiceManager = android::os::IServiceManager; +using android::binder::Status; + sp<IServiceManager> defaultServiceManager() { + static Mutex gDefaultServiceManagerLock; + static sp<IServiceManager> gDefaultServiceManager; + if (gDefaultServiceManager != nullptr) return gDefaultServiceManager; { @@ -74,10 +81,13 @@ bool checkCallingPermission(const String16& permission, int32_t* outPid, int32_t bool checkPermission(const String16& permission, pid_t pid, uid_t uid) { + static Mutex gPermissionControllerLock; + static sp<IPermissionController> gPermissionController; + sp<IPermissionController> pc; - gDefaultServiceManagerLock.lock(); + gPermissionControllerLock.lock(); pc = gPermissionController; - gDefaultServiceManagerLock.unlock(); + gPermissionControllerLock.unlock(); int64_t startTime = 0; @@ -101,11 +111,11 @@ bool checkPermission(const String16& permission, pid_t pid, uid_t uid) } // Object is dead! - gDefaultServiceManagerLock.lock(); + gPermissionControllerLock.lock(); if (gPermissionController == pc) { gPermissionController = nullptr; } - gDefaultServiceManagerLock.unlock(); + gPermissionControllerLock.unlock(); } // Need to retrieve the permission controller. @@ -121,9 +131,9 @@ bool checkPermission(const String16& permission, pid_t pid, uid_t uid) } else { pc = interface_cast<IPermissionController>(binder); // Install the new permission controller, and try again. - gDefaultServiceManagerLock.lock(); + gPermissionControllerLock.lock(); gPermissionController = pc; - gDefaultServiceManagerLock.unlock(); + gPermissionControllerLock.unlock(); } } } @@ -136,12 +146,15 @@ class BpServiceManager : public BpInterface<IServiceManager> { public: explicit BpServiceManager(const sp<IBinder>& impl) - : BpInterface<IServiceManager>(impl) + : BpInterface<IServiceManager>(impl), + mTheRealServiceManager(interface_cast<AidlServiceManager>(impl)) { } - virtual sp<IBinder> getService(const String16& name) const + sp<IBinder> getService(const String16& name) const override { + static bool gSystemBootCompleted = false; + sp<IBinder> svc = checkService(name); if (svc != nullptr) return svc; @@ -171,43 +184,36 @@ public: return nullptr; } - virtual sp<IBinder> checkService( const String16& name) const - { - Parcel data, reply; - data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); - data.writeString16(name); - remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); - return reply.readStrongBinder(); + sp<IBinder> checkService(const String16& name) const override { + sp<IBinder> ret; + if (!mTheRealServiceManager->checkService(String8(name).c_str(), &ret).isOk()) { + return nullptr; + } + return ret; } - virtual status_t addService(const String16& name, const sp<IBinder>& service, - bool allowIsolated, int dumpsysPriority) { - Parcel data, reply; - data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); - data.writeString16(name); - data.writeStrongBinder(service); - data.writeInt32(allowIsolated ? 1 : 0); - data.writeInt32(dumpsysPriority); - status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); - return err == NO_ERROR ? reply.readExceptionCode() : err; + 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(); } virtual Vector<String16> listServices(int dumpsysPriority) { - Vector<String16> res; - int n = 0; + std::vector<std::string> ret; + if (!mTheRealServiceManager->listServices(dumpsysPriority, &ret).isOk()) { + return {}; + } - for (;;) { - Parcel data, reply; - data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); - data.writeInt32(n++); - data.writeInt32(dumpsysPriority); - status_t err = remote()->transact(LIST_SERVICES_TRANSACTION, data, &reply); - if (err != NO_ERROR) - break; - res.add(reply.readString16()); + Vector<String16> res; + res.setCapacity(ret.size()); + for (const std::string& name : ret) { + res.push(String16(name.c_str())); } return res; } + +private: + sp<AidlServiceManager> mTheRealServiceManager; }; IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager"); diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index afa3d33349..458961b70d 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -93,7 +93,7 @@ enum { BLOB_ASHMEM_MUTABLE = 2, }; -void acquire_object(const sp<ProcessState>& proc, +static void acquire_object(const sp<ProcessState>& proc, const flat_binder_object& obj, const void* who, size_t* outAshmemSize) { switch (obj.hdr.type) { @@ -135,12 +135,6 @@ void acquire_object(const sp<ProcessState>& proc, ALOGD("Invalid object type 0x%08x", obj.hdr.type); } -void acquire_object(const sp<ProcessState>& proc, - const flat_binder_object& obj, const void* who) -{ - acquire_object(proc, obj, who, nullptr); -} - static void release_object(const sp<ProcessState>& proc, const flat_binder_object& obj, const void* who, size_t* outAshmemSize) { @@ -189,19 +183,13 @@ static void release_object(const sp<ProcessState>& proc, ALOGE("Invalid object type 0x%08x", obj.hdr.type); } -void release_object(const sp<ProcessState>& proc, - const flat_binder_object& obj, const void* who) -{ - release_object(proc, obj, who, nullptr); -} - inline static status_t finish_flatten_binder( const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out) { return out->writeObject(flat, false); } -status_t flatten_binder(const sp<ProcessState>& /*proc*/, +static status_t flatten_binder(const sp<ProcessState>& /*proc*/, const sp<IBinder>& binder, Parcel* out) { flat_binder_object obj; @@ -243,7 +231,7 @@ status_t flatten_binder(const sp<ProcessState>& /*proc*/, return finish_flatten_binder(binder, obj, out); } -status_t flatten_binder(const sp<ProcessState>& /*proc*/, +static status_t flatten_binder(const sp<ProcessState>& /*proc*/, const wp<IBinder>& binder, Parcel* out) { flat_binder_object obj; @@ -299,7 +287,7 @@ inline static status_t finish_unflatten_binder( return NO_ERROR; } -status_t unflatten_binder(const sp<ProcessState>& proc, +static status_t unflatten_binder(const sp<ProcessState>& proc, const Parcel& in, sp<IBinder>* out) { const flat_binder_object* flat = in.readObject(false); @@ -318,7 +306,7 @@ status_t unflatten_binder(const sp<ProcessState>& proc, return BAD_TYPE; } -status_t unflatten_binder(const sp<ProcessState>& proc, +static status_t unflatten_binder(const sp<ProcessState>& proc, const Parcel& in, wp<IBinder>* out) { const flat_binder_object* flat = in.readObject(false); diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index 63f49ddba7..b25cd7bf12 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -40,7 +40,7 @@ #include <sys/stat.h> #include <sys/types.h> -#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2) +#define DEFAULT_BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2) #define DEFAULT_MAX_BINDER_THREADS 15 #ifdef __ANDROID_VNDK__ @@ -77,7 +77,13 @@ sp<ProcessState> ProcessState::self() if (gProcess != nullptr) { return gProcess; } - gProcess = new ProcessState(kDefaultDriver); + gProcess = new ProcessState(kDefaultDriver, DEFAULT_BINDER_VM_SIZE); + return gProcess; +} + +sp<ProcessState> ProcessState::selfOrNull() +{ + Mutex::Autolock _l(gProcessMutex); return gProcess; } @@ -98,13 +104,19 @@ sp<ProcessState> ProcessState::initWithDriver(const char* driver) driver = "/dev/binder"; } - gProcess = new ProcessState(driver); + gProcess = new ProcessState(driver, DEFAULT_BINDER_VM_SIZE); return gProcess; } -sp<ProcessState> ProcessState::selfOrNull() -{ +sp<ProcessState> ProcessState::initWithMmapSize(size_t mmap_size) { Mutex::Autolock _l(gProcessMutex); + if (gProcess != nullptr) { + LOG_ALWAYS_FATAL_IF(mmap_size != gProcess->getMmapSize(), + "ProcessState already initialized with a different mmap size."); + return gProcess; + } + + gProcess = new ProcessState(kDefaultDriver, mmap_size); return gProcess; } @@ -237,6 +249,10 @@ ssize_t ProcessState::getKernelReferences(size_t buf_count, uintptr_t* buf) return count; } +size_t ProcessState::getMmapSize() { + return mMmapSize; +} + void ProcessState::setCallRestriction(CallRestriction restriction) { LOG_ALWAYS_FATAL_IF(IPCThreadState::selfOrNull(), "Call restrictions must be set before the threadpool is started."); @@ -421,7 +437,7 @@ static int open_driver(const char *driver) return fd; } -ProcessState::ProcessState(const char *driver) +ProcessState::ProcessState(const char *driver, size_t mmap_size) : mDriverName(String8(driver)) , mDriverFD(open_driver(driver)) , mVMStart(MAP_FAILED) @@ -435,11 +451,12 @@ ProcessState::ProcessState(const char *driver) , mBinderContextUserData(nullptr) , mThreadPoolStarted(false) , mThreadPoolSeq(1) + , mMmapSize(mmap_size) , mCallRestriction(CallRestriction::NONE) { if (mDriverFD >= 0) { // mmap the binder, providing a chunk of virtual address space to receive transactions. - mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); + mVMStart = mmap(nullptr, mMmapSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); if (mVMStart == MAP_FAILED) { // *sigh* ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str()); @@ -449,14 +466,14 @@ ProcessState::ProcessState(const char *driver) } } - LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating."); + LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver '%s' could not be opened. Terminating.", driver); } ProcessState::~ProcessState() { if (mDriverFD >= 0) { if (mVMStart != MAP_FAILED) { - munmap(mVMStart, BINDER_VM_SIZE); + munmap(mVMStart, mMmapSize); } close(mDriverFD); } diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp index bd0e6f9a11..8625c6f278 100644 --- a/libs/binder/Static.cpp +++ b/libs/binder/Static.cpp @@ -75,13 +75,4 @@ TextOutput& aerr(gStderrTextOutput); Mutex& gProcessMutex = *new Mutex; sp<ProcessState> gProcess; -// ------------ IServiceManager.cpp - -Mutex gDefaultServiceManagerLock; -sp<IServiceManager> gDefaultServiceManager; -#ifndef __ANDROID_VNDK__ -sp<IPermissionController> gPermissionController; -#endif -bool gSystemBootCompleted = false; - } // namespace android diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl new file mode 100644 index 0000000000..50a72aa9e4 --- /dev/null +++ b/libs/binder/aidl/android/os/IServiceManager.aidl @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2006 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. + */ + +package android.os; + +/** + * Basic interface for finding and publishing system services. + * + * You likely want to use android.os.ServiceManager in Java or + * android::IServiceManager in C++ in order to use this interface. + * + * @hide + */ +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 + /** + * 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_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 + + /** + * Retrieve an existing service called @a name from the + * service manager. + * + * This is the same as checkService (returns immediately) but + * exists for legacy purposes. + * + * Returns null if the service does not exist. + */ + @UnsupportedAppUsage + IBinder getService(@utf8InCpp String name); + + /** + * Retrieve an existing service called @a name from the service + * manager. Non-blocking. Returns null if the service does not + * exist. + */ + @UnsupportedAppUsage + IBinder checkService(@utf8InCpp String name); + + /** + * Place a new @a service called @a name into the service + * manager. + */ + void addService(@utf8InCpp String name, IBinder service, + boolean allowIsolated, int dumpPriority); + + /** + * Return a list of all currently running services. + */ + @utf8InCpp String[] listServices(int dumpPriority); +} diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h index 1d4f88113a..78f2e1d831 100644 --- a/libs/binder/include/binder/BpBinder.h +++ b/libs/binder/include/binder/BpBinder.h @@ -67,7 +67,6 @@ public: virtual BpBinder* remoteBinder(); - status_t setConstantData(const void* data, size_t size); void sendObituary(); static uint32_t getBinderProxyCount(uint32_t uid); diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h index 614b0b33dd..b810f7e8ee 100644 --- a/libs/binder/include/binder/IPCThreadState.h +++ b/libs/binder/include/binder/IPCThreadState.h @@ -110,6 +110,8 @@ public: // the maximum number of binder threads threads allowed for this process. void blockUntilThreadAvailable(); + // Service manager registration + void setTheContextObject(sp<BBinder> obj); // Is this thread currently serving a binder call. This method // returns true if while traversing backwards from the function call diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h index e5219a5590..0cdabb0265 100644 --- a/libs/binder/include/binder/Parcel.h +++ b/libs/binder/include/binder/Parcel.h @@ -932,23 +932,6 @@ inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel) return to; } -// --------------------------------------------------------------------------- - -// Generic acquire and release of objects. -void acquire_object(const sp<ProcessState>& proc, - const flat_binder_object& obj, const void* who); -void release_object(const sp<ProcessState>& proc, - const flat_binder_object& obj, const void* who); - -void flatten_binder(const sp<ProcessState>& proc, - const sp<IBinder>& binder, flat_binder_object* out); -void flatten_binder(const sp<ProcessState>& proc, - const wp<IBinder>& binder, flat_binder_object* out); -status_t unflatten_binder(const sp<ProcessState>& proc, - const flat_binder_object& flat, sp<IBinder>* out); -status_t unflatten_binder(const sp<ProcessState>& proc, - const flat_binder_object& flat, wp<IBinder>* out); - }; // namespace android // --------------------------------------------------------------------------- diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h index 224cb36807..1622ba2712 100644 --- a/libs/binder/include/binder/ProcessState.h +++ b/libs/binder/include/binder/ProcessState.h @@ -36,6 +36,8 @@ class ProcessState : public virtual RefBase public: static sp<ProcessState> self(); static sp<ProcessState> selfOrNull(); + // Note: don't call self() or selfOrNull() before initWithMmapSize() + static sp<ProcessState> initWithMmapSize(size_t mmapSize); // size in bytes /* initWithDriver() can be used to configure libbinder to use * a different binder driver dev node. It must be called *before* @@ -76,6 +78,7 @@ public: String8 getDriverName(); ssize_t getKernelReferences(size_t count, uintptr_t* buf); + size_t getMmapSize(); enum class CallRestriction { // all calls okay @@ -92,7 +95,7 @@ public: private: friend class IPCThreadState; - explicit ProcessState(const char* driver); + explicit ProcessState(const char* driver, size_t mmap_size); ~ProcessState(); ProcessState(const ProcessState& o); @@ -121,6 +124,8 @@ private: int64_t mStarvationStartTimeMs; mutable Mutex mLock; // protects everything below. + // TODO: mManagesContexts is often accessed without the lock. + // Explain why that's safe. Vector<handle_entry>mHandleToObject; @@ -135,6 +140,7 @@ private: String8 mRootDir; bool mThreadPoolStarted; volatile int32_t mThreadPoolSeq; + const size_t mMmapSize; CallRestriction mCallRestriction; }; diff --git a/libs/binder/include/private/binder/Static.h b/libs/binder/include/private/binder/Static.h index 171be7791e..f8e0ee5f8d 100644 --- a/libs/binder/include/private/binder/Static.h +++ b/libs/binder/include/private/binder/Static.h @@ -21,10 +21,6 @@ #include <binder/IBinder.h> #include <binder/ProcessState.h> -#ifndef __ANDROID_VNDK__ -#include <binder/IPermissionController.h> -#endif -#include <binder/IServiceManager.h> namespace android { @@ -35,12 +31,4 @@ extern Vector<int32_t> gTextBuffers; extern Mutex& gProcessMutex; extern sp<ProcessState> gProcess; -// For IServiceManager.cpp -extern Mutex gDefaultServiceManagerLock; -extern sp<IServiceManager> gDefaultServiceManager; -#ifndef __ANDROID_VNDK__ -extern sp<IPermissionController> gPermissionController; -#endif -extern bool gSystemBootCompleted; - } // namespace android diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp index c451780dd7..3e005c958e 100644 --- a/libs/binder/tests/Android.bp +++ b/libs/binder/tests/Android.bp @@ -26,28 +26,28 @@ cc_defaults { cc_test { name: "binderDriverInterfaceTest_IPC_32", - srcs: ["binderDriverInterfaceTest.cpp"], defaults: ["binder_test_defaults"], + srcs: ["binderDriverInterfaceTest.cpp"], compile_multilib: "32", cflags: ["-DBINDER_IPC_32BIT=1"], } cc_test { + name: "binderDriverInterfaceTest", + defaults: ["binder_test_defaults"], product_variables: { binder32bit: { cflags: ["-DBINDER_IPC_32BIT=1"], }, }, - name: "binderDriverInterfaceTest", srcs: ["binderDriverInterfaceTest.cpp"], - defaults: ["binder_test_defaults"], } cc_test { name: "binderValueTypeTest", - srcs: ["binderValueTypeTest.cpp"], defaults: ["binder_test_defaults"], + srcs: ["binderValueTypeTest.cpp"], shared_libs: [ "libbinder", "libutils", @@ -56,8 +56,8 @@ cc_test { cc_test { name: "binderLibTest_IPC_32", - srcs: ["binderLibTest.cpp"], defaults: ["binder_test_defaults"], + srcs: ["binderLibTest.cpp"], shared_libs: [ "libbinder", "libutils", @@ -67,14 +67,14 @@ cc_test { } cc_test { + name: "binderLibTest", + defaults: ["binder_test_defaults"], product_variables: { binder32bit: { cflags: ["-DBINDER_IPC_32BIT=1"], }, }, - defaults: ["binder_test_defaults"], - name: "binderLibTest", srcs: ["binderLibTest.cpp"], shared_libs: [ "libbinder", @@ -84,8 +84,8 @@ cc_test { cc_test { name: "binderThroughputTest", - srcs: ["binderThroughputTest.cpp"], defaults: ["binder_test_defaults"], + srcs: ["binderThroughputTest.cpp"], shared_libs: [ "libbinder", "libutils", @@ -101,8 +101,8 @@ cc_test { cc_test { name: "binderTextOutputTest", - srcs: ["binderTextOutputTest.cpp"], defaults: ["binder_test_defaults"], + srcs: ["binderTextOutputTest.cpp"], shared_libs: [ "libbinder", "libutils", @@ -112,8 +112,8 @@ cc_test { cc_test { name: "schd-dbg", - srcs: ["schd-dbg.cpp"], defaults: ["binder_test_defaults"], + srcs: ["schd-dbg.cpp"], shared_libs: [ "libbinder", "libutils", @@ -123,8 +123,8 @@ cc_test { cc_test { name: "binderSafeInterfaceTest", - srcs: ["binderSafeInterfaceTest.cpp"], defaults: ["binder_test_defaults"], + srcs: ["binderSafeInterfaceTest.cpp"], cppflags: [ "-Weverything", diff --git a/libs/binder/tests/binderDriverInterfaceTest.cpp b/libs/binder/tests/binderDriverInterfaceTest.cpp index 77ebac8f5a..6508bb1283 100644 --- a/libs/binder/tests/binderDriverInterfaceTest.cpp +++ b/libs/binder/tests/binderDriverInterfaceTest.cpp @@ -286,7 +286,13 @@ TEST_F(BinderDriverInterfaceTest, Transaction) { EXPECT_EQ(0u, br.arg2.cookie); EXPECT_EQ(0u, br.arg2.code); EXPECT_EQ(0u, br.arg2.flags); - EXPECT_EQ(0u, br.arg2.data_size); + + // ping returns a 4 byte header in libbinder, but the original + // C implementation of servicemanager returns a 0 byte header + if (br.arg2.data_size != 0 && br.arg2.data_size != 4) { + ADD_FAILURE() << br.arg2.data_size << " is expected to be 0 or 4"; + } + EXPECT_EQ(0u, br.arg2.offsets_size); SCOPED_TRACE("3rd WriteRead"); diff --git a/libs/sensorprivacy/Android.bp b/libs/sensorprivacy/Android.bp index e0e3469fbb..4a606ffec2 100644 --- a/libs/sensorprivacy/Android.bp +++ b/libs/sensorprivacy/Android.bp @@ -28,8 +28,7 @@ cc_library_shared { ], srcs: [ - "aidl/android/hardware/ISensorPrivacyListener.aidl", - "aidl/android/hardware/ISensorPrivacyManager.aidl", + ":libsensorprivacy_aidl", "SensorPrivacyManager.cpp", ], @@ -45,3 +44,12 @@ cc_library_shared { export_shared_lib_headers: ["libbinder"], } + +filegroup { + name: "libsensorprivacy_aidl", + srcs: [ + "aidl/android/hardware/ISensorPrivacyListener.aidl", + "aidl/android/hardware/ISensorPrivacyManager.aidl", + ], + path: "aidl", +} diff --git a/opengl/libs/ETC1/etc1.cpp b/opengl/libs/ETC1/etc1.cpp index 97d10851de..19d428a394 100644 --- a/opengl/libs/ETC1/etc1.cpp +++ b/opengl/libs/ETC1/etc1.cpp @@ -378,34 +378,30 @@ static void etc_encodeBaseColors(etc1_byte* pBaseColors, const etc1_byte* pColors, etc_compressed* pCompressed) { int r1, g1, b1, r2, g2, b2; // 8 bit base colors for sub-blocks bool differential; - { - int r51 = convert8To5(pColors[0]); - int g51 = convert8To5(pColors[1]); - int b51 = convert8To5(pColors[2]); - int r52 = convert8To5(pColors[3]); - int g52 = convert8To5(pColors[4]); - int b52 = convert8To5(pColors[5]); - - r1 = convert5To8(r51); - g1 = convert5To8(g51); - b1 = convert5To8(b51); - - int dr = r52 - r51; - int dg = g52 - g51; - int db = b52 - b51; - - differential = inRange4bitSigned(dr) && inRange4bitSigned(dg) - && inRange4bitSigned(db); - if (differential) { - r2 = convert5To8(r51 + dr); - g2 = convert5To8(g51 + dg); - b2 = convert5To8(b51 + db); - pCompressed->high |= (r51 << 27) | ((7 & dr) << 24) | (g51 << 19) - | ((7 & dg) << 16) | (b51 << 11) | ((7 & db) << 8) | 2; - } - } - - if (!differential) { + int r51 = convert8To5(pColors[0]); + int g51 = convert8To5(pColors[1]); + int b51 = convert8To5(pColors[2]); + int r52 = convert8To5(pColors[3]); + int g52 = convert8To5(pColors[4]); + int b52 = convert8To5(pColors[5]); + + r1 = convert5To8(r51); + g1 = convert5To8(g51); + b1 = convert5To8(b51); + + int dr = r52 - r51; + int dg = g52 - g51; + int db = b52 - b51; + + differential = inRange4bitSigned(dr) && inRange4bitSigned(dg) + && inRange4bitSigned(db); + if (differential) { + r2 = convert5To8(r51 + dr); + g2 = convert5To8(g51 + dg); + b2 = convert5To8(b51 + db); + pCompressed->high |= (r51 << 27) | ((7 & dr) << 24) | (g51 << 19) + | ((7 & dg) << 16) | (b51 << 11) | ((7 & db) << 8) | 2; + } else { int r41 = convert8To4(pColors[0]); int g41 = convert8To4(pColors[1]); int b41 = convert8To4(pColors[2]); diff --git a/services/gpuservice/OWNERS b/services/gpuservice/OWNERS new file mode 100644 index 0000000000..5d028393f6 --- /dev/null +++ b/services/gpuservice/OWNERS @@ -0,0 +1,3 @@ +chrisforbes@google.com +lpy@google.com +zzyiwei@google.com diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 4cd0a13861..9aa4e85e2f 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -100,6 +100,10 @@ cc_defaults { lto: { thin: true, }, + // TODO(b/131771163): Fix broken fuzzer support with LTO. + sanitize: { + fuzzer: false, + }, } cc_library_headers { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 2d319101b3..9c8251f13e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -529,9 +529,9 @@ void SurfaceFlinger::bootFinished() // wait patiently for the window manager death const String16 name("window"); - sp<IBinder> window(defaultServiceManager()->getService(name)); - if (window != 0) { - window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this)); + mWindowManager = defaultServiceManager()->getService(name); + if (mWindowManager != 0) { + mWindowManager->linkToDeath(static_cast<IBinder::DeathRecipient*>(this)); } sp<IBinder> input(defaultServiceManager()->getService( String16("inputflinger"))); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index ddfe88c928..c5c4103db5 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1084,6 +1084,9 @@ private: // either AID_GRAPHICS or AID_SYSTEM. status_t CheckTransactCodeCredentials(uint32_t code); + // to linkToDeath + sp<IBinder> mWindowManager; + std::unique_ptr<dvr::VrFlinger> mVrFlinger; std::atomic<bool> mVrFlingerRequestsDisplay = false; static bool useVrFlinger; diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp index cb368b0886..d03cb7b22a 100644 --- a/services/surfaceflinger/layerproto/Android.bp +++ b/services/surfaceflinger/layerproto/Android.bp @@ -43,7 +43,7 @@ java_library_static { type: "nano", }, srcs: ["*.proto"], - no_framework_libs: true, + sdk_version: "core_platform", target: { android: { jarjar_rules: "jarjar-rules.txt", diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index f9e0b6413b..a892a2abd0 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -54,10 +54,11 @@ using namespace sftest; namespace { // Mock test helpers +using ::testing::_; +using ::testing::DoAll; using ::testing::Invoke; using ::testing::Return; using ::testing::SetArgPointee; -using ::testing::_; using Transaction = SurfaceComposerClient::Transaction; diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp index 4c34b938c8..1604775da5 100644 --- a/services/vr/hardware_composer/Android.bp +++ b/services/vr/hardware_composer/Android.bp @@ -1,180 +1,153 @@ cc_library_shared { - name: "libvr_hwc-hal", + name: "libvr_hwc-hal", + + srcs: [ + "impl/vr_hwc.cpp", + "impl/vr_composer_client.cpp", + ], + + static_libs: [ + "libbroadcastring", + "libdisplay", + ], + + shared_libs: [ + "android.frameworks.vr.composer@1.0", + "android.hardware.graphics.composer@2.1", + "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", + "libbase", + "libbufferhubqueue", + "libbinder", + "libcutils", + "libfmq", + "libhardware", + "libhidlbase", + "libhidltransport", + "liblog", + "libsync", + "libui", + "libutils", + "libpdx_default_transport", + ], + + header_libs: [ + "android.hardware.graphics.composer@2.1-command-buffer", + "android.hardware.graphics.composer@2.1-hal", + ], + + export_header_lib_headers: [ + "android.hardware.graphics.composer@2.1-hal", + ], + + export_static_lib_headers: [ + "libdisplay", + ], + + export_shared_lib_headers: [ + "android.frameworks.vr.composer@1.0", + "android.hardware.graphics.composer@2.1", + ], + + export_include_dirs: ["."], + + cflags: [ + "-DLOG_TAG=\"vr_hwc\"", + "-DATRACE_TAG=ATRACE_TAG_GRAPHICS", + "-Wall", + "-Werror", + "-Wno-error=unused-private-field", + // Warnings in vr_hwc.cpp to be fixed after sync of goog/master. + "-Wno-sign-compare", + "-Wno-unused-parameter", + ], - srcs: [ - "impl/vr_hwc.cpp", - "impl/vr_composer_client.cpp", - ], - - static_libs: [ - "libbroadcastring", - "libdisplay", - ], - - shared_libs: [ - "android.frameworks.vr.composer@1.0", - "android.hardware.graphics.composer@2.1", - "android.hardware.graphics.mapper@2.0", - "android.hardware.graphics.mapper@3.0", - "libbase", - "libbufferhubqueue", - "libbinder", - "libcutils", - "libfmq", - "libhardware", - "libhidlbase", - "libhidltransport", - "liblog", - "libsync", - "libui", - "libutils", - "libpdx_default_transport", - ], - - header_libs: [ - "android.hardware.graphics.composer@2.1-command-buffer", - "android.hardware.graphics.composer@2.1-hal", - ], - - export_header_lib_headers: [ - "android.hardware.graphics.composer@2.1-hal", - ], - - export_static_lib_headers: [ - "libdisplay", - ], - - export_shared_lib_headers: [ - "android.frameworks.vr.composer@1.0", - "android.hardware.graphics.composer@2.1", - ], - - export_include_dirs: ["."], - - cflags: [ - "-DLOG_TAG=\"vr_hwc\"", - "-DATRACE_TAG=ATRACE_TAG_GRAPHICS", - "-Wall", - "-Werror", - "-Wno-error=unused-private-field", - // Warnings in vr_hwc.cpp to be fixed after sync of goog/master. - "-Wno-sign-compare", - "-Wno-unused-parameter", - ], - -} - -cc_library_static { - name: "libvr_hwc-binder", - srcs: [ - "aidl/android/dvr/IVrComposer.aidl", - "aidl/android/dvr/IVrComposerCallback.aidl", - "aidl/android/dvr/parcelable_composer_frame.cpp", - "aidl/android/dvr/parcelable_composer_layer.cpp", - "aidl/android/dvr/parcelable_unique_fd.cpp", - ], - aidl: { - include_dirs: ["frameworks/native/services/vr/hardware_composer/aidl"], - export_aidl_headers: true, - }, - export_include_dirs: ["aidl"], - - cflags: [ - "-Wall", - "-Werror", - ], - - shared_libs: [ - "libbinder", - "libui", - "libutils", - "libvr_hwc-hal", - ], } cc_library_static { - name: "libvr_hwc-impl", - srcs: [ - "vr_composer.cpp", - ], - static_libs: [ - "libvr_hwc-binder", - ], - shared_libs: [ - "libbase", - "libbinder", - "liblog", - "libui", - "libutils", - "libvr_hwc-hal", - ], - export_shared_lib_headers: [ - "libvr_hwc-hal", - ], - cflags: [ - "-DLOG_TAG=\"vr_hwc\"", - "-Wall", - "-Werror", - ], + name: "libvr_hwc-impl", + srcs: [ + "vr_composer.cpp", + ], + static_libs: [ + "libvr_hwc-binder", + ], + shared_libs: [ + "libbase", + "libbinder", + "liblog", + "libui", + "libutils", + "libvr_hwc-hal", + ], + export_shared_lib_headers: [ + "libvr_hwc-hal", + ], + cflags: [ + "-DLOG_TAG=\"vr_hwc\"", + "-Wall", + "-Werror", + ], } cc_binary { - name: "vr_hwc", - vintf_fragments: ["manifest_vr_hwc.xml"], - srcs: [ - "vr_hardware_composer_service.cpp" - ], - static_libs: [ - "libvr_hwc-impl", - // NOTE: This needs to be included after the *-impl lib otherwise the - // symbols in the *-binder library get optimized out. - "libvr_hwc-binder", - ], - shared_libs: [ - "android.frameworks.vr.composer@1.0", - "android.hardware.graphics.composer@2.1", - "libbase", - "libbinder", - "liblog", - "libhardware", - "libhidlbase", - "libui", - "libutils", - "libvr_hwc-hal", - ], - cflags: [ - "-DLOG_TAG=\"vr_hwc\"", - "-Wall", - "-Werror", - ], - init_rc: [ - "vr_hwc.rc", - ], + name: "vr_hwc", + vintf_fragments: ["manifest_vr_hwc.xml"], + srcs: [ + "vr_hardware_composer_service.cpp", + ], + static_libs: [ + "libvr_hwc-impl", + // NOTE: This needs to be included after the *-impl lib otherwise the + // symbols in the *-binder library get optimized out. + "libvr_hwc-binder", + ], + shared_libs: [ + "android.frameworks.vr.composer@1.0", + "android.hardware.graphics.composer@2.1", + "libbase", + "libbinder", + "liblog", + "libhardware", + "libhwbinder", + "libhidlbase", + "libui", + "libutils", + "libvr_hwc-hal", + ], + cflags: [ + "-DLOG_TAG=\"vr_hwc\"", + "-Wall", + "-Werror", + ], + init_rc: [ + "vr_hwc.rc", + ], } cc_test { - name: "vr_hwc_test", - gtest: true, - srcs: ["tests/vr_composer_test.cpp"], - static_libs: [ - "libgtest", - "libvr_hwc-impl", - // NOTE: This needs to be included after the *-impl lib otherwise the - // symbols in the *-binder library get optimized out. - "libvr_hwc-binder", - ], - cflags: [ - "-Wall", - "-Werror", - // warnings in vr_composer_test.cpp to be fixed after merge of goog/master - "-Wno-sign-compare", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "libbinder", - "liblog", - "libui", - "libutils", - ], + name: "vr_hwc_test", + gtest: true, + srcs: ["tests/vr_composer_test.cpp"], + static_libs: [ + "libgtest", + "libvr_hwc-impl", + // NOTE: This needs to be included after the *-impl lib otherwise the + // symbols in the *-binder library get optimized out. + "libvr_hwc-binder", + ], + cflags: [ + "-Wall", + "-Werror", + // warnings in vr_composer_test.cpp to be fixed after merge of goog/master + "-Wno-sign-compare", + "-Wno-unused-parameter", + ], + shared_libs: [ + "libbase", + "libbinder", + "liblog", + "libui", + "libutils", + ], } diff --git a/services/vr/hardware_composer/aidl/Android.bp b/services/vr/hardware_composer/aidl/Android.bp new file mode 100644 index 0000000000..a1d5392071 --- /dev/null +++ b/services/vr/hardware_composer/aidl/Android.bp @@ -0,0 +1,27 @@ +cc_library_static { + name: "libvr_hwc-binder", + srcs: [ + "android/dvr/IVrComposer.aidl", + "android/dvr/IVrComposerCallback.aidl", + "android/dvr/parcelable_composer_frame.cpp", + "android/dvr/parcelable_composer_layer.cpp", + "android/dvr/parcelable_unique_fd.cpp", + ], + aidl: { + local_include_dirs: ["."], + export_aidl_headers: true, + }, + export_include_dirs: ["."], + + cflags: [ + "-Wall", + "-Werror", + ], + + shared_libs: [ + "libbinder", + "libui", + "libutils", + "libvr_hwc-hal", + ], +} diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp index 131a306c08..dcaa663160 100644 --- a/services/vr/virtual_touchpad/Android.bp +++ b/services/vr/virtual_touchpad/Android.bp @@ -62,7 +62,7 @@ cc_test { service_src = [ "main.cpp", "VirtualTouchpadService.cpp", - "aidl/android/dvr/IVirtualTouchpadService.aidl", + ":virtualtouchpad_aidl", ] service_static_libs = [ @@ -99,7 +99,7 @@ cc_binary { client_src = [ "VirtualTouchpadClient.cpp", "DvrVirtualTouchpadClient.cpp", - "aidl/android/dvr/IVirtualTouchpadService.aidl", + ":virtualtouchpad_aidl", ] client_shared_libs = [ @@ -122,3 +122,9 @@ cc_library { name: "libvirtualtouchpadclient", export_include_dirs: ["include"], } + +filegroup { + name: "virtualtouchpad_aidl", + srcs: ["aidl/android/dvr/IVirtualTouchpadService.aidl"], + path: "aidl", +} diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp index af1adcff62..5679412732 100644 --- a/vulkan/libvulkan/layers_extensions.cpp +++ b/vulkan/libvulkan/layers_extensions.cpp @@ -388,9 +388,8 @@ void ForEachFileInZip(const std::string& zipname, return; } std::string prefix(dir_in_zip + "/"); - const ZipString prefix_str(prefix.c_str()); void* iter_cookie = nullptr; - if ((err = StartIteration(zip, &iter_cookie, &prefix_str, nullptr)) != 0) { + if ((err = StartIteration(zip, &iter_cookie, prefix, "")) != 0) { ALOGE("failed to iterate entries in apk '%s': %d", zipname.c_str(), err); CloseArchive(zip); @@ -399,11 +398,9 @@ void ForEachFileInZip(const std::string& zipname, ALOGD("searching for layers in '%s!/%s'", zipname.c_str(), dir_in_zip.c_str()); ZipEntry entry; - ZipString name; + std::string name; while (Next(iter_cookie, &entry, &name) == 0) { - std::string filename( - reinterpret_cast<const char*>(name.name) + prefix.length(), - name.name_length - prefix.length()); + std::string filename(name.substr(prefix.length())); // only enumerate direct entries of the directory, not subdirectories if (filename.find('/') != filename.npos) continue; |