diff options
-rw-r--r-- | cmds/atrace/Android.bp | 4 | ||||
-rw-r--r-- | cmds/atrace/atrace.cpp | 33 | ||||
-rw-r--r-- | cmds/dumpstate/Android.mk | 28 | ||||
-rw-r--r-- | cmds/dumpstate/DumpstateUtil.h | 146 | ||||
-rw-r--r-- | cmds/dumpstate/dumpstate.cpp | 71 | ||||
-rw-r--r-- | cmds/dumpstate/dumpstate.h | 119 | ||||
-rw-r--r-- | cmds/dumpstate/tests/dumpstate_test.cpp | 2 | ||||
-rw-r--r-- | cmds/dumpstate/utils.cpp | 98 | ||||
-rw-r--r-- | include/binder/AppOpsManager.h | 3 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/ComposerHal.cpp | 17 |
10 files changed, 345 insertions, 176 deletions
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp index 194a5650c9..69ed416388 100644 --- a/cmds/atrace/Android.bp +++ b/cmds/atrace/Android.bp @@ -6,6 +6,10 @@ cc_binary { shared_libs: [ "libbinder", + "libhwbinder", + "android.hidl.manager@1.0", + "libhidlbase", + "libhidltransport", "liblog", "libcutils", "libutils", diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp index 8faf276758..a217c5d11f 100644 --- a/cmds/atrace/atrace.cpp +++ b/cmds/atrace/atrace.cpp @@ -37,6 +37,8 @@ #include <binder/IServiceManager.h> #include <binder/Parcel.h> +#include <android/hidl/manager/1.0/IServiceManager.h> +#include <hidl/ServiceManagement.h> #include <cutils/properties.h> #include <utils/String8.h> @@ -47,6 +49,7 @@ using namespace android; +using std::string; #define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) #define MAX_SYS_FILES 10 @@ -517,6 +520,35 @@ static bool pokeBinderServices() return true; } +// Poke all the HAL processes in the system to get them to re-read +// their system properties. +static void pokeHalServices() +{ + using ::android::hidl::manager::V1_0::IServiceManager; + using ::android::hardware::IBinder; + using ::android::hardware::hidl_string; + using ::android::hardware::Parcel; + + Parcel data; + + sp<IServiceManager> sm = ::android::hardware::defaultServiceManager(); + sm->list([&](const auto &interfaces) { + for (size_t i = 0; i < interfaces.size(); i++) { + string fqInstanceName = interfaces[i]; + string::size_type n = fqInstanceName.find("/"); + if (n == std::string::npos || interfaces[i].size() == n+1) + continue; + hidl_string fqInterfaceName = fqInstanceName.substr(0, n); + hidl_string instanceName = fqInstanceName.substr(n+1, std::string::npos); + sm->get(fqInterfaceName, instanceName, [&](const auto &interface) { + // TODO(b/32756130) + // Once IServiceManager returns IBase, use interface->notifySyspropsChanged() here + interface->transact(IBinder::SYSPROPS_TRANSACTION, data, nullptr, 0, nullptr); + }); + } + }); +} + // Set the trace tags that userland tracing uses, and poke the running // processes to pick up the new value. static bool setTagsProperty(uint64_t tags) @@ -759,6 +791,7 @@ static bool setUpTrace() } ok &= setAppCmdlineProperty(&packageList[0]); ok &= pokeBinderServices(); + pokeHalServices(); // Disable all the sysfs enables. This is done as a separate loop from // the enables to allow the same enable to exist in multiple categories. diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk index e11bf30c29..7edc7ded7b 100644 --- a/cmds/dumpstate/Android.mk +++ b/cmds/dumpstate/Android.mk @@ -14,6 +14,7 @@ COMMON_LOCAL_CFLAGS := \ COMMON_SRC_FILES := \ utils.cpp COMMON_SHARED_LIBRARIES := \ + android.hardware.dumpstate@1.0 \ libbase \ libbinder \ libcutils \ @@ -22,6 +23,27 @@ COMMON_SHARED_LIBRARIES := \ liblog \ libselinux \ libutils +COMMON_STATIC_LIBRARIES := \ + libdumpstateutil \ + $(COMMON_ZIP_LIBRARIES) + +# ====================# +# libdumpstateutil # +# ====================# +include $(CLEAR_VARS) + +LOCAL_MODULE := libdumpstateutil + +LOCAL_CFLAGS := $(COMMON_LOCAL_CFLAGS) +LOCAL_C_INCLUDES := $(LOCAL_PATH) +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) +LOCAL_SRC_FILES := \ + utils.cpp # TODO: temporary, until functions are moved to DumpstateUtil.cpp +# TODO: include just what it uses (libbase, libcutils, etc...) once split from utils.cpp +LOCAL_SHARED_LIBRARIES := $(COMMON_SHARED_LIBRARIES) +LOCAL_STATIC_LIBRARIES := $(COMMON_ZIP_LIBRARIES) + +include $(BUILD_STATIC_LIBRARY) # ====================# # libdumpstateheaders # @@ -35,7 +57,7 @@ LOCAL_MODULE := libdumpstateheaders LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \ $(COMMON_SHARED_LIBRARIES) LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := \ - $(COMMON_ZIP_LIBRARIES) + $(COMMON_STATIC_LIBRARIES) # Soong requires that whats is on LOCAL_EXPORTED_ is also on LOCAL_ LOCAL_SHARED_LIBRARIES := $(LOCAL_EXPORT_SHARED_LIBRARY_HEADERS) LOCAL_STATIC_LIBRARIES := $(LOCAL_EXPORT_STATIC_LIBRARY_HEADERS) @@ -81,7 +103,7 @@ LOCAL_MODULE := dumpstate LOCAL_SHARED_LIBRARIES := $(COMMON_SHARED_LIBRARIES) -LOCAL_STATIC_LIBRARIES := $(COMMON_ZIP_LIBRARIES) +LOCAL_STATIC_LIBRARIES := $(COMMON_STATIC_LIBRARIES) LOCAL_HAL_STATIC_LIBRARIES := libdumpstate @@ -106,7 +128,7 @@ LOCAL_SRC_FILES := $(COMMON_SRC_FILES) \ DumpstateService.cpp \ tests/dumpstate_test.cpp -LOCAL_STATIC_LIBRARIES := $(COMMON_ZIP_LIBRARIES) \ +LOCAL_STATIC_LIBRARIES := $(COMMON_STATIC_LIBRARIES) \ libgmock LOCAL_SHARED_LIBRARIES := $(COMMON_SHARED_LIBRARIES) diff --git a/cmds/dumpstate/DumpstateUtil.h b/cmds/dumpstate/DumpstateUtil.h new file mode 100644 index 0000000000..42a91db340 --- /dev/null +++ b/cmds/dumpstate/DumpstateUtil.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2016 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 FRAMEWORK_NATIVE_CMD_DUMPSTATE_UTIL_H_ +#define FRAMEWORK_NATIVE_CMD_DUMPSTATE_UTIL_H_ + +// TODO: use android::os::dumpstate (must wait until device code is refactored) + +/* + * Defines the Linux user that should be executing a command. + */ +enum RootMode { + /* Explicitly change the `uid` and `gid` to be `shell`.*/ + DROP_ROOT, + /* Don't change the `uid` and `gid`. */ + DONT_DROP_ROOT, + /* Prefix the command with `/PATH/TO/su root`. Won't work non user builds. */ + SU_ROOT +}; + +/* + * Defines what should happen with the `stdout` stream of a command. + */ +enum StdoutMode { + /* Don't change `stdout`. */ + NORMAL_STDOUT, + /* Redirect `stdout` to `stderr`. */ + REDIRECT_TO_STDERR +}; + +/* + * Value object used to set command options. + * + * Typically constructed using a builder with chained setters. Examples: + * + * CommandOptions::WithTimeout(20).AsRoot().Build(); + * CommandOptions::WithTimeout(10).Always().RedirectStderr().Build(); + * + * Although the builder could be used to dynamically set values. Example: + * + * CommandOptions::CommandOptionsBuilder options = + * CommandOptions::WithTimeout(10); + * if (!is_user_build()) { + * options.AsRoot(); + * } + * RunCommand("command", {"args"}, options.Build()); + */ +class CommandOptions { + private: + class CommandOptionsValues { + private: + CommandOptionsValues(int64_t timeout); + + int64_t timeout_; + bool always_; + RootMode root_mode_; + StdoutMode stdout_mode_; + std::string logging_message_; + + friend class CommandOptions; + friend class CommandOptionsBuilder; + }; + + CommandOptions(const CommandOptionsValues& values); + + const CommandOptionsValues values; + + public: + class CommandOptionsBuilder { + public: + /* Sets the command to always run, even on `dry-run` mode. */ + CommandOptionsBuilder& Always(); + /* Sets the command's RootMode as `SU_ROOT` */ + CommandOptionsBuilder& AsRoot(); + /* Sets the command's RootMode as `DROP_ROOT` */ + CommandOptionsBuilder& DropRoot(); + /* Sets the command's StdoutMode `REDIRECT_TO_STDERR` */ + CommandOptionsBuilder& RedirectStderr(); + /* When not empty, logs a message before executing the command. + * Must contain a `%s`, which will be replaced by the full command line, and end on `\n`. */ + CommandOptionsBuilder& Log(const std::string& message); + /* Builds the command options. */ + CommandOptions Build(); + + private: + CommandOptionsBuilder(int64_t timeout); + CommandOptionsValues values; + friend class CommandOptions; + }; + + /** Gets the command timeout, in seconds. */ + int64_t Timeout() const; + /* Checks whether the command should always be run, even on dry-run mode. */ + bool Always() const; + /** Gets the RootMode of the command. */ + RootMode RootMode() const; + /** Gets the StdoutMode of the command. */ + StdoutMode StdoutMode() const; + /** Gets the logging message header, it any. */ + std::string LoggingMessage() const; + + /** Creates a builder with the requied timeout. */ + static CommandOptionsBuilder WithTimeout(int64_t timeout); + + // Common options. + static CommandOptions DEFAULT; + static CommandOptions AS_ROOT_5; + static CommandOptions AS_ROOT_10; + static CommandOptions AS_ROOT_20; +}; + +/* + * Forks a command, waits for it to finish, and returns its status. + * + * |fd| file descriptor that receives the command's 'stdout'. + * |full_command| array containing the command (first entry) and its arguments. + * Must contain at least one element. + * |options| optional argument defining the command's behavior. + * |description| optional description of the command to be used on log messages. If empty, + * the command path (without arguments) will be used instead. + */ +int RunCommandToFd(int fd, const std::vector<const char*>& full_command, + const CommandOptions& options = CommandOptions::DEFAULT, + const std::string& description = ""); + +/* + * Dumps the contents of a file into a file descriptor. + * + * |fd| file descriptor where the file is dumped into. + * |path| location of the file to be dumped. + */ +int DumpFileToFd(int fd, const std::string& path); + +#endif // FRAMEWORK_NATIVE_CMD_DUMPSTATE_UTIL_H_ diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index ea70fe5540..8879ab8daf 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -41,6 +41,8 @@ #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/unique_fd.h> +#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h> +#include <cutils/native_handle.h> #include <cutils/properties.h> #include <hardware_legacy/power.h> #include <openssl/sha.h> @@ -90,7 +92,7 @@ static int RunCommand(const std::string& title, const std::vector<std::string>& return ds.RunCommand(title, fullCommand, options); } static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs, - const CommandOptions& options = CommandOptions::DEFAULT_DUMPSYS, + const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS, long dumpsysTimeout = 0) { return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeout); } @@ -462,6 +464,9 @@ static void DumpModemLogs() { MYLOGE("Unable to add modem log %s to zip file\n", modem_log_file.c_str()); } else { MYLOGD("Modem Log %s is added to zip\n", modem_log_file.c_str()); + if (remove(modem_log_file.c_str())) { + MYLOGE("Error removing modem log %s\n", modem_log_file.c_str()); + } } } @@ -680,7 +685,8 @@ void Dumpstate::PrintHeader() const { printf("Network: %s\n", network.c_str()); printf("Kernel: "); - JustDumpFile("", "/proc/version"); + fflush(stdout); + DumpFileToFd(STDOUT_FILENO, "/proc/version"); printf("Command line: %s\n", strtok(cmdline_buf, "\n")); printf("Bugreport format version: %s\n", version_.c_str()); printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_, @@ -1088,15 +1094,7 @@ static void dumpstate() { DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats"); DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state"); - printf("========================================================\n"); - printf("== Board\n"); - printf("========================================================\n"); - - { - DurationReporter tmpDr("dumpstate_board()"); - dumpstate_board(); - printf("\n"); - } + ds.DumpstateBoard(); /* Migrate the ril_dumpstate to a dumpstate_board()? */ int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0); @@ -1161,6 +1159,57 @@ static void dumpstate() { printf("========================================================\n"); } +void Dumpstate::DumpstateBoard() { + DurationReporter duration_reporter("dumpstate_board()"); + printf("========================================================\n"); + printf("== Board\n"); + printf("========================================================\n"); + fflush(stdout); + + android::sp<android::hardware::dumpstate::V1_0::IDumpstateDevice> dumpstate_device( + android::hardware::dumpstate::V1_0::IDumpstateDevice::getService("DumpstateDevice")); + if (dumpstate_device == nullptr) { + // TODO: temporary workaround until devices on master implement it + MYLOGE("no IDumpstateDevice implementation; using legacy dumpstate_board()\n"); + dumpstate_board(); + return; + } + + if (!IsZipping()) { + MYLOGE("Not dumping board info because it's not a zipped bugreport\n"); + return; + } + + std::string path = ds.GetPath("-dumpstate-board.txt"); + MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path.c_str()); + + int fd = + TEMP_FAILURE_RETRY(open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)); + if (fd < 0) { + MYLOGE("Could not open file %s: %s\n", path.c_str(), strerror(errno)); + return; + } + + native_handle_t* handle = native_handle_create(1, 0); + if (handle == nullptr) { + MYLOGE("Could not create native_handle\n"); + return; + } + handle->data[0] = fd; + + dumpstate_device->dumpstateBoard(handle); + + AddZipEntry("dumpstate-board.txt", path); + + native_handle_close(handle); + native_handle_delete(handle); + + if (remove(path.c_str()) != 0) { + MYLOGE("Could not remove(%s): %s\n", path.c_str(), strerror(errno)); + } +} + static void ShowUsageAndExit(int exitCode = 1) { fprintf(stderr, "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] " diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h index 3d3d7ed295..969348fc2e 100644 --- a/cmds/dumpstate/dumpstate.h +++ b/cmds/dumpstate/dumpstate.h @@ -40,6 +40,7 @@ #include <android-base/macros.h> #include <ziparchive/zip_writer.h> +#include "DumpstateUtil.h" #include "android/os/BnDumpstate.h" // Workaround for const char *args[MAX_ARGS_ARRAY_SIZE] variables until they're converted to @@ -53,28 +54,6 @@ extern "C" { #endif /* - * Defines the Linux user that should be executing a command. - */ -enum RootMode { - /* Explicitly change the `uid` and `gid` to be `shell`.*/ - DROP_ROOT, - /* Don't change the `uid` and `gid`. */ - DONT_DROP_ROOT, - /* Prefix the command with `/PATH/TO/su root`. Won't work non user builds. */ - SU_ROOT -}; - -/* - * Defines what should happen with the `stdout` stream of a command. - */ -enum StdoutMode { - /* Don't change `stdout`. */ - NORMAL_STDOUT, - /* Redirect `stdout` to `stderr`. */ - REDIRECT_TO_STDERR -}; - -/* * Helper class used to report how long it takes for a section to finish. * * Typical usage: @@ -102,88 +81,6 @@ class DurationReporter { }; /* - * Value object used to set command options. - * - * Typically constructed using a builder with chained setters. Examples: - * - * CommandOptions::WithTimeout(20).AsRoot().Build(); - * CommandOptions::WithTimeout(10).Always().RedirectStderr().Build(); - * - * Although the builder could be used to dynamically set values. Example: - * - * CommandOptions::CommandOptionsBuilder options = - * CommandOptions::WithTimeout(10); - * if (!is_user_build()) { - * options.AsRoot(); - * } - * RunCommand("command", {"args"}, options.Build()); - */ -class CommandOptions { - private: - class CommandOptionsValues { - private: - CommandOptionsValues(long timeout); - - long timeout_; - bool always_; - RootMode root_mode_; - StdoutMode stdout_mode_; - std::string logging_message_; - - friend class CommandOptions; - friend class CommandOptionsBuilder; - }; - - CommandOptions(const CommandOptionsValues& values); - - const CommandOptionsValues values; - - public: - class CommandOptionsBuilder { - public: - /* Sets the command to always run, even on `dry-run` mode. */ - CommandOptionsBuilder& Always(); - /* Sets the command's RootMode as `SU_ROOT` */ - CommandOptionsBuilder& AsRoot(); - /* Sets the command's RootMode as `DROP_ROOT` */ - CommandOptionsBuilder& DropRoot(); - /* Sets the command's StdoutMode `REDIRECT_TO_STDERR` */ - CommandOptionsBuilder& RedirectStderr(); - /* When not empty, logs a message before executing the command. - * Must contain a `%s`, which will be replaced by the full command line, and end on `\n`. */ - CommandOptionsBuilder& Log(const std::string& message); - /* Builds the command options. */ - CommandOptions Build(); - - private: - CommandOptionsBuilder(long timeout); - CommandOptionsValues values; - friend class CommandOptions; - }; - - /** Gets the command timeout, in seconds. */ - long Timeout() const; - /* Checks whether the command should always be run, even on dry-run mode. */ - bool Always() const; - /** Gets the RootMode of the command. */ - RootMode RootMode() const; - /** Gets the StdoutMode of the command. */ - StdoutMode StdoutMode() const; - /** Gets the logging message header, it any. */ - std::string LoggingMessage() const; - - /** Creates a builder with the requied timeout. */ - static CommandOptionsBuilder WithTimeout(long timeout); - - // Common options. - static CommandOptions DEFAULT; - static CommandOptions DEFAULT_DUMPSYS; - static CommandOptions AS_ROOT_5; - static CommandOptions AS_ROOT_10; - static CommandOptions AS_ROOT_20; -}; - -/* * Keeps track of current progress and estimated max, saving stats on file to tune up future runs. * * Each `dumpstate` section contributes to the total weight by an individual weight, so the overall @@ -272,6 +169,8 @@ class Dumpstate { friend class DumpstateTest; public: + static CommandOptions DEFAULT_DUMPSYS; + static Dumpstate& GetInstance(); /* @@ -316,8 +215,7 @@ class Dumpstate { * timeout from `options`) */ void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args, - const CommandOptions& options = CommandOptions::DEFAULT_DUMPSYS, - long dumpsys_timeout = 0); + const CommandOptions& options = DEFAULT_DUMPSYS, long dumpsys_timeout = 0); /* * Prints the contents of a file. @@ -362,6 +260,8 @@ class Dumpstate { // TODO: temporary method until Dumpstate object is properly set void SetProgress(std::unique_ptr<Progress> progress); + void DumpstateBoard(); + /* * Updates the overall progress of the bugreport generation by the given weight increment. */ @@ -454,13 +354,6 @@ class Dumpstate { Dumpstate(const std::string& version = VERSION_CURRENT, bool dry_run = false, const std::string& build_type = "user"); - // Internal version of RunCommand that just runs it, without updating progress. - int JustRunCommand(const char* command, const char* path, std::vector<const char*>& args, - const CommandOptions& options) const; - - // Internal version of RunCommand that just dumps it, without updating progress. - int JustDumpFile(const std::string& title, const std::string& path) const; - // Whether this is a dry run. bool dry_run_; diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp index 0d68901272..9613576a75 100644 --- a/cmds/dumpstate/tests/dumpstate_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_test.cpp @@ -548,7 +548,7 @@ class ProgressTest : public DumpstateBaseTest { android::base::StringPrintf("%d %d\n", expected_runs, expected_average); std::string actual_content; ASSERT_TRUE(android::base::ReadFileToString(path, &actual_content)) - << "could not read statsfrom" << path; + << "could not read stats from " << path; ASSERT_THAT(actual_content, StrEq(expected_content)) << "invalid stats on " << path; } }; diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp index b5f328d732..c322d9febc 100644 --- a/cmds/dumpstate/utils.cpp +++ b/cmds/dumpstate/utils.cpp @@ -97,12 +97,12 @@ static const int STATS_MAX_N_RUNS = 1000; static const long STATS_MAX_AVERAGE = 100000; CommandOptions CommandOptions::DEFAULT = CommandOptions::WithTimeout(10).Build(); -CommandOptions CommandOptions::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build(); +CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build(); CommandOptions CommandOptions::AS_ROOT_5 = CommandOptions::WithTimeout(5).AsRoot().Build(); CommandOptions CommandOptions::AS_ROOT_10 = CommandOptions::WithTimeout(10).AsRoot().Build(); CommandOptions CommandOptions::AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build(); -CommandOptions::CommandOptionsBuilder::CommandOptionsBuilder(long timeout) : values(timeout) { +CommandOptions::CommandOptionsBuilder::CommandOptionsBuilder(int64_t timeout) : values(timeout) { } CommandOptions::CommandOptionsBuilder& CommandOptions::CommandOptionsBuilder::Always() { @@ -135,7 +135,7 @@ CommandOptions CommandOptions::CommandOptionsBuilder::Build() { return CommandOptions(values); } -CommandOptions::CommandOptionsValues::CommandOptionsValues(long timeout) +CommandOptions::CommandOptionsValues::CommandOptionsValues(int64_t timeout) : timeout_(timeout), always_(false), root_mode_(DONT_DROP_ROOT), @@ -146,7 +146,7 @@ CommandOptions::CommandOptionsValues::CommandOptionsValues(long timeout) CommandOptions::CommandOptions(const CommandOptionsValues& values) : values(values) { } -long CommandOptions::Timeout() const { +int64_t CommandOptions::Timeout() const { return values.timeout_; } @@ -166,7 +166,7 @@ std::string CommandOptions::LoggingMessage() const { return values.logging_message_; } -CommandOptions::CommandOptionsBuilder CommandOptions::WithTimeout(long timeout) { +CommandOptions::CommandOptionsBuilder CommandOptions::WithTimeout(int64_t timeout) { return CommandOptions::CommandOptionsBuilder(timeout); } @@ -657,9 +657,9 @@ void do_showmap(int pid, const char *name) { } // TODO: when converted to a Dumpstate function, it should be const -static int _dump_file_from_fd(const std::string& title, const char* path, int fd) { +static int _dump_file_from_fd_to_fd(const std::string& title, const char* path, int fd, int out_fd) { if (!title.empty()) { - printf("------ %s (%s", title.c_str(), path); + dprintf(out_fd, "------ %s (%s", title.c_str(), path); struct stat st; // Only show the modification time of non-device files. @@ -671,9 +671,9 @@ static int _dump_file_from_fd(const std::string& title, const char* path, int fd char stamp[80]; time_t mtime = st.st_mtime; strftime(stamp, sizeof(stamp), "%Y-%m-%d %H:%M:%S", localtime(&mtime)); - printf(": %s", stamp); + dprintf(out_fd, ": %s", stamp); } - printf(") ------\n"); + dprintf(out_fd, ") ------\n"); } bool newline = false; @@ -688,24 +688,23 @@ static int _dump_file_from_fd(const std::string& title, const char* path, int fd uint64_t elapsed = DurationReporter::Nanotime(); int ret = TEMP_FAILURE_RETRY(select(fd + 1, &read_set, NULL, NULL, &tm)); if (ret == -1) { - printf("*** %s: select failed: %s\n", path, strerror(errno)); + dprintf(out_fd, "*** %s: select failed: %s\n", path, strerror(errno)); newline = true; break; } else if (ret == 0) { elapsed = DurationReporter::Nanotime() - elapsed; - printf("*** %s: Timed out after %.3fs\n", path, - (float) elapsed / NANOS_PER_SEC); + dprintf(out_fd, "*** %s: Timed out after %.3fs\n", path, (float)elapsed / NANOS_PER_SEC); newline = true; break; } else { char buffer[65536]; ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer))); if (bytes_read > 0) { - fwrite(buffer, bytes_read, 1, stdout); + android::base::WriteFully(out_fd, buffer, bytes_read); newline = (buffer[bytes_read-1] == '\n'); } else { if (bytes_read == -1) { - printf("*** %s: Failed to read from fd: %s", path, strerror(errno)); + dprintf(out_fd, "*** %s: Failed to read from fd: %s", path, strerror(errno)); newline = true; } break; @@ -715,25 +714,14 @@ static int _dump_file_from_fd(const std::string& title, const char* path, int fd UpdateProgress(WEIGHT_FILE); close(fd); - if (!newline) printf("\n"); - if (!title.empty()) printf("\n"); + if (!newline) dprintf(out_fd, "\n"); + if (!title.empty()) dprintf(out_fd, "\n"); return 0; } -int Dumpstate::DumpFile(const std::string& title, const std::string& path) { - DurationReporter duration_reporter(title); - if (IsDryRun()) { - if (!title.empty()) { - printf("------ %s (%s) ------\n", title.c_str(), path.c_str()); - printf("\t(skipped on dry run)\n"); - } - UpdateProgress(WEIGHT_FILE); - return 0; - } - return JustDumpFile(title, path); -} - -int Dumpstate::JustDumpFile(const std::string& title, const std::string& path) const { +// Internal function used by both DumpFile and DumpFileToFd - the former wants to print title +// information, while the later doesn't. +static int DumpFileToFd(const std::string& title, int out_fd, const std::string& path) { int fd = TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)); if (fd < 0) { int err = errno; @@ -744,7 +732,24 @@ int Dumpstate::JustDumpFile(const std::string& title, const std::string& path) c } return -1; } - return _dump_file_from_fd(title, path.c_str(), fd); + return _dump_file_from_fd_to_fd(title, path.c_str(), fd, out_fd); +} + +int DumpFileToFd(int out_fd, const std::string& path) { + return DumpFileToFd("", out_fd, path); +} + +int Dumpstate::DumpFile(const std::string& title, const std::string& path) { + DurationReporter duration_reporter(title); + if (IsDryRun()) { + if (!title.empty()) { + printf("------ %s (%s) ------\n", title.c_str(), path.c_str()); + printf("\t(skipped on dry run)\n"); + } + UpdateProgress(WEIGHT_FILE); + return 0; + } + return DumpFileToFd(title, STDOUT_FILENO, path); } int read_file_as_long(const char *path, long int *output) { @@ -855,7 +860,7 @@ int dump_file_from_fd(const char *title, const char *path, int fd) { close(fd); return -1; } - return _dump_file_from_fd(title, path, fd); + return _dump_file_from_fd_to_fd(title, path, fd, STDOUT_FILENO); } bool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) { @@ -909,6 +914,8 @@ int Dumpstate::RunCommand(const std::string& title, const std::vector<std::strin return -1; } + // TODO: SU_ROOT logic must be moved to RunCommandToFd + int size = full_command.size() + 1; // null terminated int starting_index = 0; if (options.RootMode() == SU_ROOT) { @@ -935,7 +942,6 @@ int Dumpstate::RunCommand(const std::string& title, const std::vector<std::strin } } args[i] = nullptr; - const char* path = args[0]; const char* command = command_string.c_str(); if (options.RootMode() == SU_ROOT && ds.IsUserBuild()) { @@ -963,7 +969,7 @@ int Dumpstate::RunCommand(const std::string& title, const std::vector<std::strin return 0; } - int status = JustRunCommand(command, path, args, options); + int status = RunCommandToFd(STDOUT_FILENO, args, options, command); /* TODO: for now we're simplifying the progress calculation by using the * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys, @@ -978,8 +984,15 @@ int Dumpstate::RunCommand(const std::string& title, const std::vector<std::strin return status; } -int Dumpstate::JustRunCommand(const char* command, const char* path, std::vector<const char*>& args, - const CommandOptions& options) const { +int RunCommandToFd(int fd, const std::vector<const char*>& full_command, + const CommandOptions& options, const std::string& description) { + if (full_command.empty()) { + MYLOGE("No arguments on RunCommandToFd'\n"); + return -1; + } + const char* path = full_command[0]; + const char* command = description.empty() ? path : description.c_str(); + bool silent = (options.StdoutMode() == REDIRECT_TO_STDERR); uint64_t start = DurationReporter::Nanotime(); @@ -1001,9 +1014,13 @@ int Dumpstate::JustRunCommand(const char* command, const char* path, std::vector return -1; } + if (STDOUT_FILENO != fd) { + TEMP_FAILURE_RETRY(dup2(fd, STDOUT_FILENO)); + close(fd); + } if (silent) { - // Redirect stderr to stdout - dup2(STDERR_FILENO, STDOUT_FILENO); + // Redirect stderr to fd + dup2(STDERR_FILENO, fd); } /* make sure the child dies when dumpstate dies */ @@ -1015,11 +1032,10 @@ int Dumpstate::JustRunCommand(const char* command, const char* path, std::vector sigact.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sigact, NULL); - execvp(path, (char**)args.data()); + execvp(path, (char**)full_command.data()); // execvp's result will be handled after waitpid_with_timeout() below, but // if it failed, it's safer to exit dumpstate. MYLOGD("execvp on command '%s' failed (error: %s)\n", command, strerror(errno)); - fflush(stdout); // Must call _exit (instead of exit), otherwise it will corrupt the zip // file. _exit(EXIT_FAILURE); @@ -1028,6 +1044,8 @@ int Dumpstate::JustRunCommand(const char* command, const char* path, std::vector /* handle parent case */ int status; bool ret = waitpid_with_timeout(pid, options.Timeout(), &status); + fsync(fd); + uint64_t elapsed = DurationReporter::Nanotime() - start; if (!ret) { if (errno == ETIMEDOUT) { diff --git a/include/binder/AppOpsManager.h b/include/binder/AppOpsManager.h index 042927c176..4212776e89 100644 --- a/include/binder/AppOpsManager.h +++ b/include/binder/AppOpsManager.h @@ -91,7 +91,8 @@ public: OP_USE_SIP = 53, OP_PROCESS_OUTGOING_CALLS = 54, OP_USE_FINGERPRINT = 55, - OP_BODY_SENSORS = 56 + OP_BODY_SENSORS = 56, + OP_AUDIO_ACCESSIBILITY_VOLUME = 64, }; AppOpsManager(); diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index 128e2b0106..06f67baf86 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -26,6 +26,7 @@ namespace android { using hardware::Return; using hardware::hidl_vec; +using hardware::hidl_handle; namespace Hwc2 { @@ -39,14 +40,14 @@ public: mHandle = (buffer) ? buffer : native_handle_init(mStorage, 0, 0); } - operator const native_handle_t*() const + operator const hidl_handle&() const { return mHandle; } private: NATIVE_HANDLE_DECLARE_STORAGE(mStorage, 0, 0); - const native_handle_t* mHandle; + hidl_handle mHandle; }; class FenceHandle @@ -55,13 +56,15 @@ public: FenceHandle(int fd, bool owned) : mOwned(owned) { + native_handle_t* handle; if (fd >= 0) { - mHandle = native_handle_init(mStorage, 1, 0); - mHandle->data[0] = fd; + handle = native_handle_init(mStorage, 1, 0); + handle->data[0] = fd; } else { // nullptr is not a valid handle to HIDL - mHandle = native_handle_init(mStorage, 0, 0); + handle = native_handle_init(mStorage, 0, 0); } + mHandle = handle; } ~FenceHandle() @@ -71,7 +74,7 @@ public: } } - operator const native_handle_t*() const + operator const hidl_handle&() const { return mHandle; } @@ -79,7 +82,7 @@ public: private: bool mOwned; NATIVE_HANDLE_DECLARE_STORAGE(mStorage, 1, 0); - native_handle_t* mHandle; + hidl_handle mHandle; }; // assume NO_RESOURCES when Status::isOk returns false |