summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/incident/main.cpp58
-rw-r--r--cmds/incidentd/src/IncidentService.cpp79
-rw-r--r--cmds/incidentd/src/IncidentService.h4
-rw-r--r--cmds/incidentd/src/main.cpp3
-rw-r--r--core/java/android/os/IIncidentManager.aidl9
5 files changed, 91 insertions, 62 deletions
diff --git a/cmds/incident/main.cpp b/cmds/incident/main.cpp
index dfb4f994b866..6c3d19715c2e 100644
--- a/cmds/incident/main.cpp
+++ b/cmds/incident/main.cpp
@@ -198,6 +198,26 @@ parse_receiver_arg(const string& arg, string* pkg, string* cls)
}
// ================================================================================
+static int
+stream_output(const int read_fd, const int write_fd) {
+ while (true) {
+ uint8_t buf[4096];
+ ssize_t amt = TEMP_FAILURE_RETRY(read(read_fd, buf, sizeof(buf)));
+ if (amt < 0) {
+ break;
+ } else if (amt == 0) {
+ break;
+ }
+
+ ssize_t wamt = TEMP_FAILURE_RETRY(write(write_fd, buf, amt));
+ if (wamt != amt) {
+ return errno;
+ }
+ }
+ return 0;
+}
+
+// ================================================================================
static void
usage(FILE* out)
{
@@ -208,11 +228,13 @@ usage(FILE* out)
fprintf(out, "OPTIONS\n");
fprintf(out, " -l list available sections\n");
fprintf(out, " -p privacy spec, LOCAL, EXPLICIT or AUTOMATIC. Default AUTOMATIC.\n");
+ fprintf(out, " -r REASON human readable description of why the report is taken.\n");
fprintf(out, "\n");
fprintf(out, "and one of these destinations:\n");
fprintf(out, " -b (default) print the report to stdout (in proto format)\n");
fprintf(out, " -d send the report into dropbox\n");
- fprintf(out, " -r REASON human readable description of why the report is taken.\n");
+ fprintf(out, " -u print a full report to stdout for dumpstate to zip as a bug\n");
+ fprintf(out, " report. SECTION is ignored. Should only be called by dumpstate.\n");
fprintf(out, " -s PKG/CLS send broadcast to the broadcast receiver.\n");
fprintf(out, "\n");
fprintf(out, " SECTION the field numbers of the incident report fields to include\n");
@@ -224,14 +246,14 @@ main(int argc, char** argv)
{
Status status;
IncidentReportArgs args;
- enum { DEST_UNSET, DEST_DROPBOX, DEST_STDOUT, DEST_BROADCAST } destination = DEST_UNSET;
+ enum { DEST_UNSET, DEST_DROPBOX, DEST_STDOUT, DEST_BROADCAST, DEST_DUMPSTATE } destination = DEST_UNSET;
int privacyPolicy = PRIVACY_POLICY_AUTOMATIC;
string reason;
string receiverArg;
// Parse the args
int opt;
- while ((opt = getopt(argc, argv, "bhdlp:r:s:")) != -1) {
+ while ((opt = getopt(argc, argv, "bhdlp:r:s:u")) != -1) {
switch (opt) {
case 'h':
usage(stdout);
@@ -253,6 +275,13 @@ main(int argc, char** argv)
}
destination = DEST_DROPBOX;
break;
+ case 'u':
+ if (!(destination == DEST_UNSET || destination == DEST_DUMPSTATE)) {
+ usage(stderr);
+ return 1;
+ }
+ destination = DEST_DUMPSTATE;
+ break;
case 'p':
privacyPolicy = get_privacy_policy(optarg);
break;
@@ -355,21 +384,16 @@ main(int argc, char** argv)
// Wait for the result and print out the data they send.
//IPCThreadState::self()->joinThreadPool();
-
- while (true) {
- uint8_t buf[4096];
- ssize_t amt = TEMP_FAILURE_RETRY(read(fds[0], buf, sizeof(buf)));
- if (amt < 0) {
- break;
- } else if (amt == 0) {
- break;
- }
-
- ssize_t wamt = TEMP_FAILURE_RETRY(write(STDOUT_FILENO, buf, amt));
- if (wamt != amt) {
- return errno;
- }
+ return stream_output(fds[0], STDOUT_FILENO);
+ } else if (destination == DEST_DUMPSTATE) {
+ // Call into the service
+ sp<StatusListener> listener(new StatusListener());
+ status = service->reportIncidentToDumpstate(writeEnd, listener);
+ if (!status.isOk()) {
+ fprintf(stderr, "reportIncident returned \"%s\"\n", status.toString8().string());
+ return 1;
}
+ return stream_output(fds[0], STDOUT_FILENO);
} else {
status = service->reportIncident(args);
if (!status.isOk()) {
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index a52726396b53..999936bda1d3 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -46,12 +46,11 @@ enum {
#define DEFAULT_BYTES_SIZE_LIMIT (96 * 1024 * 1024) // 96MB
#define DEFAULT_REFACTORY_PERIOD_MS (24 * 60 * 60 * 1000) // 1 Day
-// Skip these sections for dumpstate only. Dumpstate allows 10s max for each service to dump.
+// Skip these sections (for dumpstate only)
// Skip logs (1100 - 1108) and traces (1200 - 1202) because they are already in the bug report.
-// Skip 3018 because it takes too long.
-#define SKIPPED_SECTIONS { 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, /* Logs */ \
- 1200, 1201, 1202, /* Native, hal, java traces */ \
- 3018 /* "meminfo -a --proto" */ }
+#define SKIPPED_DUMPSTATE_SECTIONS { \
+ 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, /* Logs */ \
+ 1200, 1201, 1202, /* Native, hal, java traces */ }
namespace android {
namespace os {
@@ -307,6 +306,39 @@ Status IncidentService::reportIncidentToStream(const IncidentReportArgs& args,
return Status::ok();
}
+Status IncidentService::reportIncidentToDumpstate(const unique_fd& stream,
+ const sp<IIncidentReportStatusListener>& listener) {
+ uid_t caller = IPCThreadState::self()->getCallingUid();
+ if (caller != AID_ROOT && caller != AID_SHELL) {
+ ALOGW("Calling uid %d does not have permission: only ROOT or SHELL allowed", caller);
+ return Status::fromExceptionCode(Status::EX_SECURITY, "Only ROOT or SHELL allowed");
+ }
+
+ ALOGD("Stream incident report to dumpstate");
+ IncidentReportArgs incidentArgs;
+ // Privacy policy for dumpstate incident reports is always EXPLICIT.
+ incidentArgs.setPrivacyPolicy(PRIVACY_POLICY_EXPLICIT);
+
+ int skipped[] = SKIPPED_DUMPSTATE_SECTIONS;
+ for (const Section** section = SECTION_LIST; *section; section++) {
+ const int id = (*section)->id;
+ if (std::find(std::begin(skipped), std::end(skipped), id) == std::end(skipped)
+ && !section_requires_specific_mention(id)) {
+ incidentArgs.addSection(id);
+ }
+ }
+
+ // The ReportRequest takes ownership of the fd, so we need to dup it.
+ int fd = dup(stream.get());
+ if (fd < 0) {
+ return Status::fromStatusT(-errno);
+ }
+
+ mHandler->scheduleStreamingReport(incidentArgs, listener, fd);
+
+ return Status::ok();
+}
+
Status IncidentService::systemRunning() {
if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
return Status::fromExceptionCode(Status::EX_SECURITY,
@@ -551,43 +583,6 @@ status_t IncidentService::cmd_privacy(FILE* in, FILE* out, FILE* err, Vector<Str
return NO_ERROR;
}
-status_t IncidentService::dump(int fd, const Vector<String16>& args) {
- if (std::find(args.begin(), args.end(), String16("--proto")) == args.end()) {
- ALOGD("Skip dumping incident. Only proto format is supported.");
- dprintf(fd, "Incident dump only supports proto version.\n");
- return NO_ERROR;
- }
-
- ALOGD("Dump incident proto");
- IncidentReportArgs incidentArgs;
- incidentArgs.setPrivacyPolicy(PRIVACY_POLICY_EXPLICIT);
- int skipped[] = SKIPPED_SECTIONS;
- for (const Section** section = SECTION_LIST; *section; section++) {
- const int id = (*section)->id;
- if (std::find(std::begin(skipped), std::end(skipped), id) == std::end(skipped)
- && !section_requires_specific_mention(id)) {
- incidentArgs.addSection(id);
- }
- }
-
- if (!checkIncidentPermissions(incidentArgs).isOk()) {
- return PERMISSION_DENIED;
- }
-
- // The ReportRequest takes ownership of the fd, so we need to dup it.
- int fd1 = dup(fd);
- if (fd1 < 0) {
- return -errno;
- }
-
- // TODO: Remove this. Someone even dumpstate, wanting to get an incident report
- // should use the API. That will take making dumpstated call the API, which is a
- // good thing. It also means it won't be subject to the timeout.
- mHandler->scheduleStreamingReport(incidentArgs, NULL, fd1);
-
- return NO_ERROR;
-}
-
} // namespace incidentd
} // namespace os
} // namespace android
diff --git a/cmds/incidentd/src/IncidentService.h b/cmds/incidentd/src/IncidentService.h
index 6481321bbd69..fb013d0bf92d 100644
--- a/cmds/incidentd/src/IncidentService.h
+++ b/cmds/incidentd/src/IncidentService.h
@@ -123,6 +123,9 @@ public:
const sp<IIncidentReportStatusListener>& listener,
const unique_fd& stream);
+ virtual Status reportIncidentToDumpstate(const unique_fd& stream,
+ const sp<IIncidentReportStatusListener>& listener);
+
virtual Status systemRunning();
virtual Status getIncidentReportList(const String16& pkg, const String16& cls,
@@ -140,7 +143,6 @@ public:
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags) override;
virtual status_t command(FILE* in, FILE* out, FILE* err, Vector<String8>& args);
- virtual status_t dump(int fd, const Vector<String16>& args);
private:
sp<WorkDirectory> mWorkDirectory;
diff --git a/cmds/incidentd/src/main.cpp b/cmds/incidentd/src/main.cpp
index 098d74ecd786..494882336611 100644
--- a/cmds/incidentd/src/main.cpp
+++ b/cmds/incidentd/src/main.cpp
@@ -45,8 +45,7 @@ int main(int /*argc*/, char** /*argv*/) {
// Create the service
sp<IncidentService> service = new IncidentService(looper);
- if (defaultServiceManager()->addService(String16("incident"), service, false,
- IServiceManager::DUMP_FLAG_PRIORITY_NORMAL | IServiceManager::DUMP_FLAG_PROTO) != 0) {
+ if (defaultServiceManager()->addService(String16("incident"), service) != 0) {
ALOGE("Failed to add service");
return -1;
}
diff --git a/core/java/android/os/IIncidentManager.aidl b/core/java/android/os/IIncidentManager.aidl
index 5e024b9e35d8..7e1b1e0abaf6 100644
--- a/core/java/android/os/IIncidentManager.aidl
+++ b/core/java/android/os/IIncidentManager.aidl
@@ -43,6 +43,15 @@ interface IIncidentManager {
FileDescriptor stream);
/**
+ * Takes a report with the given args, reporting status to the optional listener.
+ * This should only be callable by dumpstate (enforced by callee).
+ *
+ * When the report is completed, the system report listener will be notified.
+ */
+ oneway void reportIncidentToDumpstate(FileDescriptor stream,
+ @nullable IIncidentReportStatusListener listener);
+
+ /**
* Tell the incident daemon that the android system server is up and running.
*/
oneway void systemRunning();