Merge "installd: Implement support for userdata snapshot and restore."
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 4459cef..fb00508 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -138,6 +138,12 @@
chmod 0666 /sys/kernel/tracing/events/block/block_rq_complete/enable
chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable
+ # filemap events for iorapd
+ chmod 0666 /sys/kernel/tracing/events/filemap/mm_filemap_add_to_page_cache/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/filemap/mm_filemap_add_to_page_cache/enable
+ chmod 0666 /sys/kernel/tracing/events/filemap/mm_filemap_delete_from_page_cache/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/filemap/mm_filemap_delete_from_page_cache/enable
+
# Tracing disabled by default
write /sys/kernel/debug/tracing/tracing_on 0
write /sys/kernel/tracing/tracing_on 0
@@ -163,7 +169,7 @@
chmod 0666 /sys/kernel/tracing/per_cpu/cpu5/trace
chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu6/trace
chmod 0666 /sys/kernel/tracing/per_cpu/cpu6/trace
- chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu6/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu7/trace
chmod 0666 /sys/kernel/tracing/per_cpu/cpu7/trace
chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu8/trace
chmod 0666 /sys/kernel/tracing/per_cpu/cpu8/trace
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 6596fa2..eb0d50d 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -43,9 +43,8 @@
static void* callAndNotify(void* data) {
Dumpstate& ds = *static_cast<Dumpstate*>(data);
- // TODO(111441001): Return status on listener.
ds.Run();
- MYLOGE("Finished Run()\n");
+ MYLOGD("Finished Run()\n");
return nullptr;
}
@@ -98,7 +97,10 @@
return binder::Status::ok();
}
-binder::Status DumpstateService::startBugreport(const android::base::unique_fd& bugreport_fd,
+// TODO(b/111441001): Hook up to consent service & copy final br only if user approves.
+binder::Status DumpstateService::startBugreport(int32_t /* calling_uid */,
+ const std::string& /* calling_package */,
+ const android::base::unique_fd& bugreport_fd,
const android::base::unique_fd& screenshot_fd,
int bugreport_mode,
const sp<IDumpstateListener>& listener) {
@@ -138,7 +140,18 @@
return binder::Status::ok();
}
+binder::Status DumpstateService::cancelBugreport() {
+ // This is a no-op since the cancellation is done from java side via setting sys properties.
+ // See BugreportManagerServiceImpl.
+ // TODO(b/111441001): maybe make native and java sides use different binder interface
+ // to avoid these annoyances.
+ return binder::Status::ok();
+}
+
status_t DumpstateService::dump(int fd, const Vector<String16>&) {
+ std::string destination = ds_.options_->bugreport_fd.get() != -1
+ ? StringPrintf("[fd:%d]", ds_.options_->bugreport_fd.get())
+ : ds_.bugreport_internal_dir_.c_str();
dprintf(fd, "id: %d\n", ds_.id_);
dprintf(fd, "pid: %d\n", ds_.pid_);
dprintf(fd, "update_progress: %s\n", ds_.options_->do_progress_updates ? "true" : "false");
@@ -149,8 +162,7 @@
dprintf(fd, "args: %s\n", ds_.options_->args.c_str());
dprintf(fd, "extra_options: %s\n", ds_.options_->extra_options.c_str());
dprintf(fd, "version: %s\n", ds_.version_.c_str());
- dprintf(fd, "bugreport_dir: %s\n", ds_.bugreport_dir_.c_str());
- dprintf(fd, "bugreport_internal_dir_: %s\n", ds_.bugreport_internal_dir_.c_str());
+ dprintf(fd, "bugreport_dir: %s\n", destination.c_str());
dprintf(fd, "screenshot_path: %s\n", ds_.screenshot_path_.c_str());
dprintf(fd, "log_path: %s\n", ds_.log_path_.c_str());
dprintf(fd, "tmp_path: %s\n", ds_.tmp_path_.c_str());
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index 1705317..faeea53 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -42,10 +42,14 @@
bool getSectionDetails,
sp<IDumpstateToken>* returned_token) override;
- binder::Status startBugreport(const android::base::unique_fd& bugreport_fd,
+ binder::Status startBugreport(int32_t calling_uid, const std::string& calling_package,
+ const android::base::unique_fd& bugreport_fd,
const android::base::unique_fd& screenshot_fd, int bugreport_mode,
const sp<IDumpstateListener>& listener) override;
+ // No-op
+ binder::Status cancelBugreport();
+
private:
Dumpstate& ds_;
std::mutex lock_;
diff --git a/cmds/dumpstate/README.md b/cmds/dumpstate/README.md
index 6ac17d8..273a5a6 100644
--- a/cmds/dumpstate/README.md
+++ b/cmds/dumpstate/README.md
@@ -49,7 +49,7 @@
Then run:
```
-mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest64/dumpstate_test* /data/nativetest64 && adb shell /data/nativetest64/dumpstate_test/dumpstate_test
+mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest64/dumpstate_* /data/nativetest64 && adb shell /data/nativetest64/dumpstate_test/dumpstate_test
```
And to run just one test (for example, `DumpstateTest.RunCommandNoArgs`):
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index d24c953..f58535e 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -59,14 +59,29 @@
// Default mode.
const int BUGREPORT_MODE_DEFAULT = 6;
+ // TODO(b/111441001): Should the args be for the consuming application rather than triggering?
/*
* Starts a bugreport in the background.
*
+ *<p>Shows the user a dialog to get consent for sharing the bugreport with the calling
+ * application. If they deny {@link IDumpstateListener#onError} will be called. If they
+ * consent and bugreport generation is successful artifacts will be copied to the given fds and
+ * {@link IDumpstateListener#onFinished} will be called. If there
+ * are errors in bugreport generation {@link IDumpstateListener#onError} will be called.
+ *
+ * @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 bugreportMode the mode that specifies other run time options; must be one of above
* @param listener callback for updates; optional
*/
- void startBugreport(FileDescriptor bugreportFd, FileDescriptor screenshotFd, int bugreportMode,
- IDumpstateListener listener);
+ void startBugreport(int callingUid, @utf8InCpp String callingPackage,
+ FileDescriptor bugreportFd, FileDescriptor screenshotFd,
+ int bugreportMode, IDumpstateListener listener);
+
+ /*
+ * Cancels the bugreport currently in progress.
+ */
+ void cancelBugreport();
}
diff --git a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
index 2966c86..8396acd 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
@@ -35,20 +35,18 @@
/* Bugreport encountered a runtime error */
const int BUGREPORT_ERROR_RUNTIME_ERROR = 2;
+ /* User denied consent to share the bugreport with the specified app */
+ const int BUGREPORT_ERROR_USER_DENIED_CONSENT = 3;
+
/**
* Called on an error condition with one of the error codes listed above.
*/
oneway void onError(int errorCode);
/**
- * Called when taking bugreport finishes successfully
- *
- * @param durationMs time capturing bugreport took in milliseconds
- * @param title title for the bugreport; helpful in reminding the user why they took it
- * @param description detailed description for the bugreport
+ * Called when taking bugreport finishes successfully.
*/
- oneway void onFinished(long durationMs, @utf8InCpp String title,
- @utf8InCpp String description);
+ oneway void onFinished();
// TODO(b/111441001): Remove old methods when not used anymore.
void onProgressUpdated(int progress);
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 712f861..c005084 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -135,10 +135,6 @@
return fd;
}
-static int OpenForWrite(std::string path) {
- return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-}
static int OpenForRead(std::string path) {
return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
@@ -169,17 +165,6 @@
return false;
}
-static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
- if (input_file == output_file) {
- MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
- output_file.c_str());
- return false;
- }
-
- MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
- android::base::unique_fd out_fd(OpenForWrite(output_file));
- return CopyFileToFd(input_file, out_fd.get());
-}
} // namespace
} // namespace os
@@ -475,47 +460,6 @@
return false;
}
-static void dump_systrace() {
- if (!ds.IsZipping()) {
- MYLOGD("Not dumping systrace because it's not a zipped bugreport\n");
- return;
- }
- std::string systrace_path = ds.GetPath("-systrace.txt");
- if (systrace_path.empty()) {
- MYLOGE("Not dumping systrace because path is empty\n");
- return;
- }
- const char* path = "/sys/kernel/debug/tracing/tracing_on";
- long int is_tracing;
- if (read_file_as_long(path, &is_tracing)) {
- return; // error already logged
- }
- if (is_tracing <= 0) {
- MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
- return;
- }
-
- MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
- systrace_path.c_str());
- if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
- CommandOptions::WithTimeout(120).Build())) {
- MYLOGE("systrace timed out, its zip entry will be incomplete\n");
- // TODO: RunCommand tries to kill the process, but atrace doesn't die
- // peacefully; ideally, we should call strace to stop itself, but there is no such option
- // yet (just a --async_stop, which stops and dump
- // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
- // MYLOGE("could not stop systrace ");
- // }
- }
- if (!ds.AddZipEntry("systrace.txt", systrace_path)) {
- MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
- } else {
- if (remove(systrace_path.c_str())) {
- MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
- }
- }
-}
-
static bool skip_not_stat(const char *path) {
static const char stat[] = "/stat";
size_t len = strlen(path);
@@ -1440,12 +1384,8 @@
/* Dumps state for the default case. Returns true if everything went fine. */
static bool DumpstateDefault() {
- // Dumps systrace right away, otherwise it will be filled with unnecessary events.
- // First try to dump anrd trace if the daemon is running. Otherwise, dump
- // the raw trace.
- if (!dump_anrd_trace()) {
- dump_systrace();
- }
+ // Try to dump anrd trace if the daemon is running.
+ dump_anrd_trace();
// Invoking the following dumpsys calls before dump_traces() to try and
// keep the system stats as close to its initial state as possible.
@@ -1714,6 +1654,7 @@
"progress (requires -o and -B)\n"
" -R: take bugreport in remote mode (requires -o, -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");
}
@@ -1845,16 +1786,9 @@
static void PrepareToWriteToFile() {
MaybeResolveSymlink(&ds.bugreport_internal_dir_);
- std::string base_name_part1 = "bugreport";
- if (!ds.options_->use_outfile.empty()) {
- ds.bugreport_dir_ = dirname(ds.options_->use_outfile.c_str());
- base_name_part1 = basename(ds.options_->use_outfile.c_str());
- }
-
std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
- ds.base_name_ =
- StringPrintf("%s-%s-%s", base_name_part1.c_str(), device_name.c_str(), build_id.c_str());
+ ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
if (ds.options_->do_add_date) {
char date[80];
strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
@@ -1877,17 +1811,16 @@
std::string destination = ds.options_->bugreport_fd.get() != -1
? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
- : ds.bugreport_dir_.c_str();
+ : ds.bugreport_internal_dir_.c_str();
MYLOGD(
"Bugreport dir: %s\n"
- "Internal Bugreport dir: %s\n"
"Base name: %s\n"
"Suffix: %s\n"
"Log path: %s\n"
"Temporary path: %s\n"
"Screenshot path: %s\n",
- destination.c_str(), ds.bugreport_internal_dir_.c_str(), ds.base_name_.c_str(),
- ds.name_.c_str(), ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
+ destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
+ ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
if (ds.options_->do_zip_file) {
ds.path_ = ds.GetPath(".zip");
@@ -1954,18 +1887,13 @@
}
}
// The zip file lives in an internal directory. Copy it over to output.
- bool copy_succeeded = false;
if (ds.options_->bugreport_fd.get() != -1) {
- copy_succeeded = android::os::CopyFileToFd(ds.path_, ds.options_->bugreport_fd.get());
- } else {
- ds.final_path_ = ds.GetPath(ds.bugreport_dir_, ".zip");
- copy_succeeded = android::os::CopyFileToFile(ds.path_, ds.final_path_);
- }
- if (copy_succeeded) {
- if (remove(ds.path_.c_str())) {
+ bool copy_succeeded =
+ android::os::CopyFileToFd(ds.path_, ds.options_->bugreport_fd.get());
+ if (!copy_succeeded && remove(ds.path_.c_str())) {
MYLOGE("remove(%s): %s", ds.path_.c_str(), strerror(errno));
}
- }
+ } // else - the file just remains in the internal directory.
}
}
if (do_text_file) {
@@ -1991,8 +1919,8 @@
/* Broadcasts that we are done with the bugreport */
static void SendBugreportFinishedBroadcast() {
// TODO(b/111441001): use callback instead of broadcast.
- if (!ds.final_path_.empty()) {
- MYLOGI("Final bugreport path: %s\n", ds.final_path_.c_str());
+ if (!ds.path_.empty()) {
+ MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
// clang-format off
std::vector<std::string> am_args = {
@@ -2000,7 +1928,7 @@
"--ei", "android.intent.extra.ID", std::to_string(ds.id_),
"--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
"--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
- "--es", "android.intent.extra.BUGREPORT", ds.final_path_,
+ "--es", "android.intent.extra.BUGREPORT", ds.path_,
"--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
};
// clang-format on
@@ -2022,7 +1950,7 @@
if (ds.options_->is_remote_mode) {
am_args.push_back("--es");
am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
- am_args.push_back(SHA256_file_hash(ds.final_path_));
+ am_args.push_back(SHA256_file_hash(ds.path_));
SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
} else {
SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
@@ -2160,7 +2088,6 @@
MYLOGI("wifi_only: %d\n", options.wifi_only);
MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
MYLOGI("fd: %d\n", options.bugreport_fd.get());
- MYLOGI("use_outfile: %s\n", options.use_outfile.c_str());
MYLOGI("extra_options: %s\n", options.extra_options.c_str());
MYLOGI("args: %s\n", options.args.c_str());
MYLOGI("notification_title: %s\n", options.notification_title.c_str());
@@ -2186,12 +2113,14 @@
Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
RunStatus status = RunStatus::OK;
int c;
- while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
+ while ((c = getopt(argc, argv, "dho:svqzpPBRSV:w")) != -1) {
switch (c) {
// clang-format off
case 'd': do_add_date = true; break;
case 'z': do_zip_file = true; break;
- case 'o': use_outfile = optarg; break;
+ // o=use_outfile not supported anymore.
+ // TODO(b/111441001): Remove when all callers have migrated.
+ case 'o': break;
case 's': use_socket = true; break;
case 'S': use_control_socket = true; break;
case 'v': show_header_only = true; break;
@@ -2201,6 +2130,9 @@
case 'R': is_remote_mode = true; break;
case 'B': do_broadcast = true; break;
case 'V': break; // compatibility no-op
+ case 'w':
+ // This was already processed
+ break;
case 'h':
status = RunStatus::HELP;
break;
@@ -2232,9 +2164,7 @@
return false;
}
- bool has_out_file_options = !use_outfile.empty() || bugreport_fd.get() != -1;
- if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) &&
- !has_out_file_options) {
+ if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) && !OutputToFile()) {
return false;
}
@@ -2256,6 +2186,26 @@
options_ = std::move(options);
}
+Dumpstate::RunStatus Dumpstate::Run() {
+ Dumpstate::RunStatus status = RunInternal();
+ if (listener_ != nullptr) {
+ switch (status) {
+ case Dumpstate::RunStatus::OK:
+ listener_->onFinished();
+ break;
+ case Dumpstate::RunStatus::HELP:
+ break;
+ case Dumpstate::RunStatus::INVALID_INPUT:
+ listener_->onError(android::os::IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
+ break;
+ case Dumpstate::RunStatus::ERROR:
+ listener_->onError(android::os::IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
+ break;
+ }
+ }
+ return status;
+}
+
/*
* Dumps relevant information to a bugreport based on the given options.
*
@@ -2274,10 +2224,10 @@
* If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
* gets added to the archive.
*
- * Bugreports are first generated in a local directory and later copied to the caller's fd or
- * directory.
+ * Bugreports are first generated in a local directory and later copied to the caller's fd if
+ * supplied.
*/
-Dumpstate::RunStatus Dumpstate::Run() {
+Dumpstate::RunStatus Dumpstate::RunInternal() {
LogDumpOptions(*options_);
if (!options_->ValidateOptions()) {
MYLOGE("Invalid options specified\n");
@@ -2316,7 +2266,7 @@
}
// Redirect output if needed
- bool is_redirecting = !options_->use_socket && !options_->use_outfile.empty();
+ bool is_redirecting = options_->OutputToFile();
// TODO: temporarily set progress until it's part of the Dumpstate constructor
std::string stats_path =
@@ -2467,7 +2417,7 @@
}
/* rename or zip the (now complete) .tmp file to its final location */
- if (!options_->use_outfile.empty()) {
+ if (options_->OutputToFile()) {
FinalizeFile();
}
@@ -2482,6 +2432,7 @@
/* tell activity manager we're done */
if (options_->do_broadcast) {
SendBugreportFinishedBroadcast();
+ // Note that listener_ is notified in Run();
}
MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 529111e..3dfe4e9 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -331,6 +331,7 @@
bool do_add_date = false;
bool do_zip_file = false;
bool do_vibrate = true;
+ // Writes bugreport content to a socket; only flatfile format is supported.
bool use_socket = false;
bool use_control_socket = false;
bool do_fb = false;
@@ -342,13 +343,11 @@
bool wifi_only = false;
// Whether progress updates should be published.
bool do_progress_updates = false;
- // File descriptor to output zip file. Takes precedence over use_outfile.
+ // File descriptor to output zip file.
android::base::unique_fd bugreport_fd;
// File descriptor to screenshot file.
// TODO(b/111441001): Use this fd.
android::base::unique_fd screenshot_fd;
- // Partial path to output file.
- std::string use_outfile;
// TODO: rename to MODE.
// Extra options passed as system property.
std::string extra_options;
@@ -367,6 +366,13 @@
/* Returns true if the options set so far are consistent. */
bool ValidateOptions() const;
+
+ /* Returns if options specified require writing bugreport to a file */
+ bool OutputToFile() const {
+ // If we are not writing to socket, we will write to a file. If bugreport_fd is
+ // specified, it is preferred. If not bugreport is written to /bugreports.
+ return !use_socket;
+ }
};
// TODO: initialize fields on constructor
@@ -424,13 +430,6 @@
// Full path of the temporary file containing the screenshot (when requested).
std::string screenshot_path_;
- // TODO(b/111441001): remove when obsolete.
- // Full path of the final zip file inside the caller-specified directory, if available.
- std::string final_path_;
-
- // The caller-specified directory, if available.
- std::string bugreport_dir_;
-
// Pointer to the zipped file.
std::unique_ptr<FILE, int (*)(FILE*)> zip_file{nullptr, fclose};
@@ -449,6 +448,8 @@
std::vector<DumpData> anr_data_;
private:
+ RunStatus RunInternal();
+
// Used by GetInstance() only.
explicit Dumpstate(const std::string& version = VERSION_CURRENT);
diff --git a/cmds/dumpstate/dumpstate.rc b/cmds/dumpstate/dumpstate.rc
index 2e72574..14937b8 100644
--- a/cmds/dumpstate/dumpstate.rc
+++ b/cmds/dumpstate/dumpstate.rc
@@ -17,3 +17,9 @@
class main
disabled
oneshot
+
+# bugreportd starts dumpstate binder service and makes it wait for a listener to connect.
+service bugreportd /system/bin/dumpstate -w
+ class main
+ disabled
+ oneshot
diff --git a/cmds/dumpstate/main.cpp b/cmds/dumpstate/main.cpp
index 78aad11..68d3733 100644
--- a/cmds/dumpstate/main.cpp
+++ b/cmds/dumpstate/main.cpp
@@ -14,8 +14,55 @@
* limitations under the License.
*/
+#define LOG_TAG "dumpstate"
+
+#include <binder/IPCThreadState.h>
+
+#include "DumpstateInternal.h"
+#include "DumpstateService.h"
#include "dumpstate.h"
+namespace {
+
+// Returns true if we should start the service and wait for a listener
+// to bind with bugreport options.
+bool ShouldStartServiceAndWait(int argc, char* argv[]) {
+ bool do_wait = false;
+ int c;
+ // Keep flags in sync with Dumpstate::DumpOptions::Initialize.
+ while ((c = getopt(argc, argv, "wdho:svqzpPBRSV:")) != -1 && !do_wait) {
+ switch (c) {
+ case 'w':
+ do_wait = true;
+ break;
+ default:
+ // Ignore all other options
+ break;
+ }
+ }
+
+ // Reset next index used by getopt so getopt can be called called again in Dumpstate::Run to
+ // parse bugreport options.
+ optind = 1;
+ return do_wait;
+}
+
+} // namespace
+
int main(int argc, char* argv[]) {
- return run_main(argc, argv);
+ if (ShouldStartServiceAndWait(argc, argv)) {
+ int ret;
+ if ((ret = android::os::DumpstateService::Start()) != android::OK) {
+ MYLOGE("Unable to start 'dumpstate' service: %d", ret);
+ exit(1);
+ }
+ MYLOGI("'dumpstate' service started and will wait for a call to startBugreport()");
+
+ // Waits forever for an incoming connection.
+ // TODO(b/111441001): should this time out?
+ android::IPCThreadState::self()->joinThreadPool();
+ return 0;
+ } else {
+ return run_main(argc, argv);
+ }
}
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index c57775f..570c6c9 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -61,9 +61,8 @@
dprintf(outFd_, "\rError %d", error_code);
return binder::Status::ok();
}
- binder::Status onFinished(int64_t duration_ms, const ::std::string&,
- const ::std::string&) override {
- dprintf(outFd_, "\rFinished in %lld", (long long) duration_ms);
+ binder::Status onFinished() override {
+ dprintf(outFd_, "\rFinished");
return binder::Status::ok();
}
binder::Status onProgressUpdated(int32_t progress) override {
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 98ee1b0..eb73d41 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -61,8 +61,7 @@
public:
MOCK_METHOD1(onProgress, binder::Status(int32_t progress));
MOCK_METHOD1(onError, binder::Status(int32_t error_code));
- MOCK_METHOD3(onFinished, binder::Status(int64_t duration_ms, const ::std::string& title,
- const ::std::string& description));
+ MOCK_METHOD0(onFinished, binder::Status());
MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress));
MOCK_METHOD1(onMaxProgressUpdated, binder::Status(int32_t max_progress));
MOCK_METHOD4(onSectionComplete, binder::Status(const ::std::string& name, int32_t status,
@@ -173,7 +172,6 @@
EXPECT_FALSE(options_.do_add_date);
EXPECT_FALSE(options_.do_zip_file);
- EXPECT_EQ("", options_.use_outfile);
EXPECT_FALSE(options_.use_socket);
EXPECT_FALSE(options_.use_control_socket);
EXPECT_FALSE(options_.show_header_only);
@@ -191,7 +189,6 @@
const_cast<char*>("-S"),
const_cast<char*>("-d"),
const_cast<char*>("-z"),
- const_cast<char*>("-o abc"),
};
// clang-format on
@@ -201,7 +198,6 @@
EXPECT_TRUE(options_.do_add_date);
EXPECT_TRUE(options_.do_zip_file);
EXPECT_TRUE(options_.use_control_socket);
- EXPECT_EQ(" abc", std::string(options_.use_outfile));
// Other options retain default values
EXPECT_TRUE(options_.do_vibrate);
@@ -228,7 +224,6 @@
// Other options retain default values
EXPECT_TRUE(options_.do_vibrate);
- EXPECT_EQ("", options_.use_outfile);
EXPECT_FALSE(options_.do_add_date);
EXPECT_FALSE(options_.do_zip_file);
EXPECT_FALSE(options_.use_control_socket);
@@ -247,7 +242,6 @@
const_cast<char*>("-p"),
const_cast<char*>("-B"),
const_cast<char*>("-z"),
- const_cast<char*>("-o abc"),
};
// clang-format on
property_set("dumpstate.options", "bugreportfull");
@@ -259,7 +253,6 @@
EXPECT_TRUE(options_.do_fb);
EXPECT_TRUE(options_.do_zip_file);
EXPECT_TRUE(options_.do_broadcast);
- EXPECT_EQ(" abc", std::string(options_.use_outfile));
// Other options retain default values
EXPECT_TRUE(options_.do_vibrate);
@@ -279,7 +272,6 @@
const_cast<char*>("-p"),
const_cast<char*>("-B"),
const_cast<char*>("-z"),
- const_cast<char*>("-o abc"),
};
// clang-format on
@@ -294,7 +286,6 @@
EXPECT_TRUE(options_.do_progress_updates);
EXPECT_TRUE(options_.do_start_service);
EXPECT_FALSE(options_.do_fb);
- EXPECT_EQ(" abc", std::string(options_.use_outfile));
// Other options retain default values
EXPECT_TRUE(options_.do_vibrate);
@@ -312,7 +303,6 @@
const_cast<char*>("-p"),
const_cast<char*>("-B"),
const_cast<char*>("-z"),
- const_cast<char*>("-o abc"),
};
// clang-format on
@@ -327,7 +317,6 @@
EXPECT_TRUE(options_.is_remote_mode);
EXPECT_FALSE(options_.do_vibrate);
EXPECT_FALSE(options_.do_fb);
- EXPECT_EQ(" abc", std::string(options_.use_outfile));
// Other options retain default values
EXPECT_FALSE(options_.use_control_socket);
@@ -344,7 +333,6 @@
const_cast<char*>("-p"),
const_cast<char*>("-B"),
const_cast<char*>("-z"),
- const_cast<char*>("-o abc"),
};
// clang-format on
@@ -359,7 +347,6 @@
EXPECT_TRUE(options_.do_zip_file);
EXPECT_TRUE(options_.do_progress_updates);
EXPECT_TRUE(options_.do_start_service);
- EXPECT_EQ(" abc", std::string(options_.use_outfile));
// Other options retain default values
EXPECT_TRUE(options_.do_vibrate);
@@ -377,7 +364,6 @@
const_cast<char*>("-p"),
const_cast<char*>("-B"),
const_cast<char*>("-z"),
- const_cast<char*>("-o abc"),
};
// clang-format on
@@ -391,7 +377,6 @@
EXPECT_TRUE(options_.do_broadcast);
EXPECT_TRUE(options_.do_zip_file);
EXPECT_TRUE(options_.telephony_only);
- EXPECT_EQ(" abc", std::string(options_.use_outfile));
// Other options retain default values
EXPECT_TRUE(options_.do_vibrate);
@@ -410,7 +395,6 @@
const_cast<char*>("-p"),
const_cast<char*>("-B"),
const_cast<char*>("-z"),
- const_cast<char*>("-o abc"),
};
// clang-format on
@@ -424,7 +408,6 @@
EXPECT_TRUE(options_.do_broadcast);
EXPECT_TRUE(options_.do_zip_file);
EXPECT_TRUE(options_.wifi_only);
- EXPECT_EQ(" abc", std::string(options_.use_outfile));
// Other options retain default values
EXPECT_TRUE(options_.do_vibrate);
@@ -444,7 +427,6 @@
const_cast<char*>("-p"),
const_cast<char*>("-B"),
const_cast<char*>("-z"),
- const_cast<char*>("-o abc"),
};
// clang-format on
@@ -457,7 +439,6 @@
EXPECT_TRUE(options_.do_fb);
EXPECT_TRUE(options_.do_zip_file);
EXPECT_TRUE(options_.do_broadcast);
- EXPECT_EQ(" abc", std::string(options_.use_outfile));
// Other options retain default values
EXPECT_TRUE(options_.do_vibrate);
@@ -475,7 +456,6 @@
const_cast<char*>("dumpstate"),
const_cast<char*>("-d"),
const_cast<char*>("-z"),
- const_cast<char*>("-o abc"),
const_cast<char*>("-s"),
const_cast<char*>("-S"),
@@ -488,7 +468,6 @@
EXPECT_TRUE(options_.do_add_date);
EXPECT_TRUE(options_.do_zip_file);
// TODO: Maybe we should trim the filename
- EXPECT_EQ(" abc", std::string(options_.use_outfile));
EXPECT_TRUE(options_.use_socket);
EXPECT_TRUE(options_.use_control_socket);
@@ -527,7 +506,6 @@
// Other options retain default values
EXPECT_FALSE(options_.do_add_date);
EXPECT_FALSE(options_.do_zip_file);
- EXPECT_EQ("", options_.use_outfile);
EXPECT_FALSE(options_.use_socket);
EXPECT_FALSE(options_.use_control_socket);
}
@@ -562,15 +540,21 @@
TEST_F(DumpOptionsTest, ValidateOptionsNeedOutfile1) {
options_.do_zip_file = true;
+ // Writing to socket = !writing to file.
+ options_.use_socket = true;
EXPECT_FALSE(options_.ValidateOptions());
- options_.use_outfile = "a/b/c";
+
+ options_.use_socket = false;
EXPECT_TRUE(options_.ValidateOptions());
}
TEST_F(DumpOptionsTest, ValidateOptionsNeedOutfile2) {
options_.do_broadcast = true;
+ // Writing to socket = !writing to file.
+ options_.use_socket = true;
EXPECT_FALSE(options_.ValidateOptions());
- options_.use_outfile = "a/b/c";
+
+ options_.use_socket = false;
EXPECT_TRUE(options_.ValidateOptions());
}
@@ -579,13 +563,11 @@
EXPECT_FALSE(options_.ValidateOptions());
options_.do_zip_file = true;
- options_.use_outfile = "a/b/c"; // do_zip_file needs outfile
EXPECT_TRUE(options_.ValidateOptions());
}
TEST_F(DumpOptionsTest, ValidateOptionsUpdateProgressNeedsBroadcast) {
options_.do_progress_updates = true;
- options_.use_outfile = "a/b/c"; // do_progress_updates needs outfile
EXPECT_FALSE(options_.ValidateOptions());
options_.do_broadcast = true;
@@ -599,7 +581,6 @@
options_.do_broadcast = true;
options_.do_zip_file = true;
options_.do_add_date = true;
- options_.use_outfile = "a/b/c"; // do_broadcast needs outfile
EXPECT_TRUE(options_.ValidateOptions());
}
@@ -656,8 +637,9 @@
}
if (update_progress) {
- message += android::base::StringPrintf("Setting progress (%s): %d/%d\n",
- listener_name.c_str(), progress, max);
+ message += android::base::StringPrintf("Setting progress (%s): %d/%d (%d%%)\n",
+ listener_name.c_str(), progress, max,
+ (100 * progress / max));
}
return message;
@@ -816,12 +798,14 @@
SetProgress(0, 30);
EXPECT_CALL(*listener, onProgressUpdated(20));
+ EXPECT_CALL(*listener, onProgress(66)); // 20/30 %
EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
std::string progress_message = GetProgressMessage(ds.listener_name_, 20, 30);
EXPECT_THAT(out, StrEq("stdout\n"));
EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
EXPECT_CALL(*listener, onProgressUpdated(30));
+ EXPECT_CALL(*listener, onProgress(100)); // 35/35 %
EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Build()));
progress_message = GetProgressMessage(ds.listener_name_, 30, 30);
EXPECT_THAT(out, StrEq("stdout\n"));
@@ -830,6 +814,7 @@
// Run a command that will increase maximum timeout.
EXPECT_CALL(*listener, onProgressUpdated(31));
EXPECT_CALL(*listener, onMaxProgressUpdated(37));
+ EXPECT_CALL(*listener, onProgress(83)); // 31/37 %
EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
progress_message = GetProgressMessage(ds.listener_name_, 31, 37, 30); // 20% increase
EXPECT_THAT(out, StrEq("stdout\n"));
@@ -838,6 +823,7 @@
// Make sure command ran while in dry_run is counted.
SetDryRun(true);
EXPECT_CALL(*listener, onProgressUpdated(35));
+ EXPECT_CALL(*listener, onProgress(94)); // 35/37 %
EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
progress_message = GetProgressMessage(ds.listener_name_, 35, 37);
EXPECT_THAT(out, IsEmpty());
@@ -854,6 +840,7 @@
// First update should always be sent.
EXPECT_CALL(*listener, onProgressUpdated(1));
+ EXPECT_CALL(*listener, onProgress(12)); // 1/12 %
EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
std::string progress_message = GetProgressMessage(ds.listener_name_, 1, 8);
EXPECT_THAT(out, StrEq("stdout\n"));
@@ -866,6 +853,7 @@
// Third update should be sent because it reaches threshold (6 - 1 = 5).
EXPECT_CALL(*listener, onProgressUpdated(6));
+ EXPECT_CALL(*listener, onProgress(75)); // 6/8 %
EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
progress_message = GetProgressMessage(ds.listener_name_, 6, 8);
EXPECT_THAT(out, StrEq("stdout\n"));
@@ -1105,6 +1093,7 @@
SetProgress(0, 30);
EXPECT_CALL(*listener, onProgressUpdated(5));
+ EXPECT_CALL(*listener, onProgress(16)); // 5/30 %
EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
std::string progress_message =
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 990fd43..528e43d 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -949,16 +949,22 @@
fsync(control_socket_fd_);
}
+ int percent = 100 * progress / max;
if (listener_ != nullptr) {
- if (progress % 100 == 0) {
- // We don't want to spam logcat, so only log multiples of 100.
- MYLOGD("Setting progress (%s): %d/%d\n", listener_name_.c_str(), progress, max);
+ if (percent % 5 == 0) {
+ // We don't want to spam logcat, so only log multiples of 5.
+ MYLOGD("Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(), progress, max,
+ percent);
} else {
// stderr is ignored on normal invocations, but useful when calling
// /system/bin/dumpstate directly for debuggging.
- fprintf(stderr, "Setting progress (%s): %d/%d\n", listener_name_.c_str(), progress, max);
+ fprintf(stderr, "Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(),
+ progress, max, percent);
}
+ // TODO(b/111441001): Remove in favor of onProgress
listener_->onProgressUpdated(progress);
+
+ listener_->onProgress(percent);
}
}
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 2e9701f..f574752 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -18,6 +18,7 @@
"dexopt.cpp",
"globals.cpp",
"utils.cpp",
+ "view_compiler.cpp",
":installd_aidl",
],
header_libs: [
@@ -188,6 +189,7 @@
"globals.cpp",
"otapreopt.cpp",
"utils.cpp",
+ "view_compiler.cpp",
],
header_libs: ["dex2oat_headers"],
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index afabbbb..9e252ee 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -61,6 +61,7 @@
#include "installd_deps.h"
#include "otapreopt_utils.h"
#include "utils.h"
+#include "view_compiler.h"
#include "CacheTracker.h"
#include "MatchExtensionGen.h"
@@ -1959,6 +1960,17 @@
return res ? error(res, error_msg) : ok();
}
+binder::Status InstalldNativeService::compileLayouts(const std::string& apkPath,
+ const std::string& packageName,
+ const std ::string& outDexFile, int uid,
+ bool* _aidl_return) {
+ const char* apk_path = apkPath.c_str();
+ const char* package_name = packageName.c_str();
+ const char* out_dex_file = outDexFile.c_str();
+ *_aidl_return = android::installd::view_compiler(apk_path, package_name, out_dex_file, uid);
+ return *_aidl_return ? ok() : error("viewcompiler failed");
+}
+
binder::Status InstalldNativeService::markBootComplete(const std::string& instructionSet) {
ENFORCE_UID(AID_SYSTEM);
std::lock_guard<std::recursive_mutex> lock(mLock);
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 123859a..098a0c2 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -95,6 +95,9 @@
const std::unique_ptr<std::string>& dexMetadataPath,
const std::unique_ptr<std::string>& compilationReason);
+ binder::Status compileLayouts(const std::string& apkPath, const std::string& packageName,
+ const std::string& outDexFile, int uid, bool* _aidl_return);
+
binder::Status rmdex(const std::string& codePath, const std::string& instructionSet);
binder::Status mergeProfiles(int32_t uid, const std::string& packageName,
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 13efe13..a70e9ff 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -55,6 +55,8 @@
@nullable @utf8InCpp String profileName,
@nullable @utf8InCpp String dexMetadataPath,
@nullable @utf8InCpp String compilationReason);
+ boolean compileLayouts(@utf8InCpp String apkPath, @utf8InCpp String packageName,
+ @utf8InCpp String outDexFile, int uid);
void rmdex(@utf8InCpp String codePath, @utf8InCpp String instructionSet);
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 32c1313..10110a8 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -627,27 +627,6 @@
}
}
-static void drop_capabilities(uid_t uid) {
- if (setgid(uid) != 0) {
- PLOG(ERROR) << "setgid(" << uid << ") failed in installd during dexopt";
- exit(DexoptReturnCodes::kSetGid);
- }
- if (setuid(uid) != 0) {
- PLOG(ERROR) << "setuid(" << uid << ") failed in installd during dexopt";
- exit(DexoptReturnCodes::kSetUid);
- }
- // drop capabilities
- struct __user_cap_header_struct capheader;
- struct __user_cap_data_struct capdata[2];
- memset(&capheader, 0, sizeof(capheader));
- memset(&capdata, 0, sizeof(capdata));
- capheader.version = _LINUX_CAPABILITY_VERSION_3;
- if (capset(&capheader, &capdata[0]) < 0) {
- PLOG(ERROR) << "capset failed";
- exit(DexoptReturnCodes::kCapSet);
- }
-}
-
static constexpr int PROFMAN_BIN_RETURN_CODE_COMPILE = 0;
static constexpr int PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION = 1;
static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 2;
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 6582ba5..24f5eab 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -20,6 +20,7 @@
#include <fcntl.h>
#include <fts.h>
#include <stdlib.h>
+#include <sys/capability.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/xattr.h>
@@ -34,6 +35,7 @@
#include <log/log.h>
#include <private/android_filesystem_config.h>
+#include "dexopt_return_codes.h"
#include "globals.h" // extern variables.
#ifndef LOG_TAG
@@ -1084,5 +1086,26 @@
}
}
+void drop_capabilities(uid_t uid) {
+ if (setgid(uid) != 0) {
+ PLOG(ERROR) << "setgid(" << uid << ") failed in installd during dexopt";
+ exit(DexoptReturnCodes::kSetGid);
+ }
+ if (setuid(uid) != 0) {
+ PLOG(ERROR) << "setuid(" << uid << ") failed in installd during dexopt";
+ exit(DexoptReturnCodes::kSetUid);
+ }
+ // drop capabilities
+ struct __user_cap_header_struct capheader;
+ struct __user_cap_data_struct capdata[2];
+ memset(&capheader, 0, sizeof(capheader));
+ memset(&capdata, 0, sizeof(capdata));
+ capheader.version = _LINUX_CAPABILITY_VERSION_3;
+ if (capset(&capheader, &capdata[0]) < 0) {
+ PLOG(ERROR) << "capset failed";
+ exit(DexoptReturnCodes::kCapSet);
+ }
+}
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index a36fce1..430f515 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -147,6 +147,8 @@
// It returns true if there were no errors at all, and false otherwise.
bool collect_profiles(std::vector<std::string>* profiles_paths);
+void drop_capabilities(uid_t uid);
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/view_compiler.cpp b/cmds/installd/view_compiler.cpp
new file mode 100644
index 0000000..f1ac717
--- /dev/null
+++ b/cmds/installd/view_compiler.cpp
@@ -0,0 +1,99 @@
+/*
+ * 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 "view_compiler.h"
+
+#include <string>
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "utils.h"
+
+#include "android-base/logging.h"
+#include "android-base/stringprintf.h"
+#include "android-base/unique_fd.h"
+
+namespace android {
+namespace installd {
+
+using base::unique_fd;
+
+bool view_compiler(const char* apk_path, const char* package_name, const char* out_dex_file,
+ int uid) {
+ CHECK(apk_path != nullptr);
+ CHECK(package_name != nullptr);
+ CHECK(out_dex_file != nullptr);
+
+ // viewcompiler won't have permission to open anything, so we have to open the files first
+ // and pass file descriptors.
+
+ // Open input file
+ unique_fd infd{open(apk_path, 0)};
+ if (infd.get() < 0) {
+ PLOG(ERROR) << "Could not open input file: " << apk_path;
+ return false;
+ }
+
+ // Set up output file. viewcompiler can't open outputs by fd, but it can write to stdout, so
+ // we close stdout and open it towards the right output.
+ unique_fd outfd{open(out_dex_file, O_CREAT | O_TRUNC | O_WRONLY, 0644)};
+ if (outfd.get() < 0) {
+ PLOG(ERROR) << "Could not open output file: " << out_dex_file;
+ return false;
+ }
+ if (fchmod(outfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) != 0) {
+ PLOG(ERROR) << "Could not change output file permissions";
+ return false;
+ }
+ if (close(STDOUT_FILENO) != 0) {
+ PLOG(ERROR) << "Could not close stdout";
+ return false;
+ }
+ if (dup2(outfd, STDOUT_FILENO) < 0) {
+ PLOG(ERROR) << "Could not duplicate output file descriptor";
+ return false;
+ }
+
+ // Prepare command line arguments for viewcompiler
+ std::string args[] = {"/system/bin/viewcompiler",
+ "--apk",
+ "--infd",
+ android::base::StringPrintf("%d", infd.get()),
+ "--dex",
+ "--package",
+ package_name};
+ char* const argv[] = {const_cast<char*>(args[0].c_str()), const_cast<char*>(args[1].c_str()),
+ const_cast<char*>(args[2].c_str()), const_cast<char*>(args[3].c_str()),
+ const_cast<char*>(args[4].c_str()), const_cast<char*>(args[5].c_str()),
+ const_cast<char*>(args[6].c_str()), nullptr};
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ // Now that we've opened the files we need, drop privileges.
+ drop_capabilities(uid);
+ execv("/system/bin/viewcompiler", argv);
+ _exit(1);
+ }
+
+ return wait_child(pid) == 0;
+}
+
+} // namespace installd
+} // namespace android
\ No newline at end of file
diff --git a/cmds/installd/view_compiler.h b/cmds/installd/view_compiler.h
new file mode 100644
index 0000000..f7c6e57
--- /dev/null
+++ b/cmds/installd/view_compiler.h
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+#ifndef VIEW_COMPILER_H_
+#define VIEW_COMPILER_H_
+
+namespace android {
+namespace installd {
+
+bool view_compiler(const char* apk_path, const char* package_name, const char* out_dex_file,
+ int uid);
+
+} // namespace installd
+} // namespace android
+
+#endif // VIEW_COMPILER_H_
\ No newline at end of file
diff --git a/data/etc/android.hardware.telephony.ims.xml b/data/etc/android.hardware.telephony.ims.xml
new file mode 100644
index 0000000..eeb7b00
--- /dev/null
+++ b/data/etc/android.hardware.telephony.ims.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<!-- Feature for devices that support IMS via ImsService APIs. -->
+<permissions>
+ <feature name="android.hardware.telephony.ims" />
+</permissions>
diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h
index 537c957..b377a41 100644
--- a/libs/gui/include/gui/BufferQueueCore.h
+++ b/libs/gui/include/gui/BufferQueueCore.h
@@ -40,13 +40,14 @@
#define BQ_LOGW(x, ...) ALOGW("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
#define BQ_LOGE(x, ...) ALOGE("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
-#define ATRACE_BUFFER_INDEX(index) \
- if (ATRACE_ENABLED()) { \
- char ___traceBuf[1024]; \
- snprintf(___traceBuf, 1024, "%s: %d", \
- mCore->mConsumerName.string(), (index)); \
- android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf); \
- }
+#define ATRACE_BUFFER_INDEX(index) \
+ do { \
+ if (ATRACE_ENABLED()) { \
+ char ___traceBuf[1024]; \
+ snprintf(___traceBuf, 1024, "%s: %d", mCore->mConsumerName.string(), (index)); \
+ android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf); \
+ } \
+ } while (false)
namespace android {
diff --git a/libs/sensor/include/sensor/Sensor.h b/libs/sensor/include/sensor/Sensor.h
index 6926f7f..324d443 100644
--- a/libs/sensor/include/sensor/Sensor.h
+++ b/libs/sensor/include/sensor/Sensor.h
@@ -57,15 +57,15 @@
uint8_t b[16];
int64_t i64[2];
};
- uuid_t(const uint8_t (&uuid)[16]) { memcpy(b, uuid, sizeof(b));}
+ explicit uuid_t(const uint8_t (&uuid)[16]) { memcpy(b, uuid, sizeof(b));}
uuid_t() : b{0} {}
};
Sensor(const Sensor&) = default;
Sensor& operator=(const Sensor&) = default;
- Sensor(const char * name = "");
- Sensor(struct sensor_t const* hwSensor, int halVersion = 0);
+ explicit Sensor(const char * name = "");
+ explicit Sensor(struct sensor_t const* hwSensor, int halVersion = 0);
Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersion = 0);
~Sensor();
diff --git a/libs/sensor/include/sensor/SensorEventQueue.h b/libs/sensor/include/sensor/SensorEventQueue.h
index baed2ee..8176578 100644
--- a/libs/sensor/include/sensor/SensorEventQueue.h
+++ b/libs/sensor/include/sensor/SensorEventQueue.h
@@ -64,7 +64,7 @@
// Default sensor sample period
static constexpr int32_t SENSOR_DELAY_NORMAL = 200000;
- SensorEventQueue(const sp<ISensorEventConnection>& connection);
+ explicit SensorEventQueue(const sp<ISensorEventConnection>& connection);
virtual ~SensorEventQueue();
virtual void onFirstRef();
diff --git a/libs/sensor/include/sensor/SensorManager.h b/libs/sensor/include/sensor/SensorManager.h
index 23f7a91..f09c9c6 100644
--- a/libs/sensor/include/sensor/SensorManager.h
+++ b/libs/sensor/include/sensor/SensorManager.h
@@ -71,7 +71,7 @@
void sensorManagerDied();
static status_t waitForSensorService(sp<ISensorServer> *server);
- SensorManager(const String16& opPackageName);
+ explicit SensorManager(const String16& opPackageName);
status_t assertStateLocked();
private:
diff --git a/services/sensorservice/SensorRecord.h b/services/sensorservice/SensorRecord.h
index 5a35410..031744a 100644
--- a/services/sensorservice/SensorRecord.h
+++ b/services/sensorservice/SensorRecord.h
@@ -25,7 +25,7 @@
class SensorService::SensorRecord {
public:
- SensorRecord(const sp<const SensorEventConnection>& connection);
+ explicit SensorRecord(const sp<const SensorEventConnection>& connection);
bool addConnection(const sp<const SensorEventConnection>& connection);
bool removeConnection(const wp<const SensorEventConnection>& connection);
size_t getNumConnections() const { return mConnections.size(); }
diff --git a/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
index ddcee28..8d7a05b 100644
--- a/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
+++ b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
@@ -43,7 +43,7 @@
struct SensorManager final : public ISensorManager {
- SensorManager(JavaVM* vm);
+ explicit SensorManager(JavaVM* vm);
~SensorManager();
// Methods from ::android::frameworks::sensorservice::V1_0::ISensorManager follow.
diff --git a/services/sensorservice/mat.h b/services/sensorservice/mat.h
index 495c14e..934ae58 100644
--- a/services/sensorservice/mat.h
+++ b/services/sensorservice/mat.h
@@ -139,13 +139,13 @@
mat() { }
mat(const mat& rhs) : base(rhs) { }
- mat(const base& rhs) : base(rhs) { } // NOLINT(implicit)
+ mat(const base& rhs) : base(rhs) { } // NOLINT(google-explicit-constructor)
// -----------------------------------------------------------------------
// conversion constructors
// sets the diagonal to the value, off-diagonal to zero
- mat(pTYPE rhs) { // NOLINT(implicit)
+ mat(pTYPE rhs) { // NOLINT(google-explicit-constructor)
helpers::doAssign(*this, rhs);
}
diff --git a/services/sensorservice/vec.h b/services/sensorservice/vec.h
index 9e5d280..c195434 100644
--- a/services/sensorservice/vec.h
+++ b/services/sensorservice/vec.h
@@ -322,12 +322,12 @@
vec() { }
vec(const vec& rhs) : base(rhs) { }
- vec(const base& rhs) : base(rhs) { } // NOLINT(implicit)
+ vec(const base& rhs) : base(rhs) { } // NOLINT(google-explicit-constructor)
// -----------------------------------------------------------------------
// conversion constructors
- vec(pTYPE rhs) { // NOLINT(implicit)
+ vec(pTYPE rhs) { // NOLINT(google-explicit-constructor)
for (size_t i=0 ; i<SIZE ; i++)
base::operator[](i) = rhs;
}
diff --git a/services/surfaceflinger/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc
index aea602b..5bec502 100644
--- a/services/surfaceflinger/surfaceflinger.rc
+++ b/services/surfaceflinger/surfaceflinger.rc
@@ -2,6 +2,7 @@
class core animation
user system
group graphics drmrpc readproc
+ updatable
onrestart restart zygote
writepid /dev/stune/foreground/tasks
socket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0