/* * 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. */ #define LOG_TAG "incident" #include "incident_sections.h" #include #include #include #include #include #include #include #include #include #include #include using namespace android; using namespace android::base; using namespace android::binder; using namespace android::os; // ================================================================================ class StatusListener : public BnIncidentReportStatusListener { public: StatusListener(); virtual ~StatusListener(); virtual Status onReportStarted(); virtual Status onReportSectionStatus(int32_t section, int32_t status); virtual Status onReportServiceStatus(const String16& service, int32_t status); virtual Status onReportFinished(); virtual Status onReportFailed(); }; StatusListener::StatusListener() { } StatusListener::~StatusListener() { } Status StatusListener::onReportStarted() { return Status::ok(); } Status StatusListener::onReportSectionStatus(int32_t section, int32_t status) { fprintf(stderr, "section %d status %d\n", section, status); return Status::ok(); } Status StatusListener::onReportServiceStatus(const String16& service, int32_t status) { fprintf(stderr, "service '%s' status %d\n", String8(service).string(), status); return Status::ok(); } Status StatusListener::onReportFinished() { fprintf(stderr, "done\n"); exit(0); return Status::ok(); } Status StatusListener::onReportFailed() { fprintf(stderr, "failed\n"); exit(1); return Status::ok(); } // ================================================================================ static IncidentSection const* find_section(const char* name) { size_t low = 0; size_t high = INCIDENT_SECTION_COUNT - 1; while (low <= high) { size_t mid = (low + high) >> 1; IncidentSection const* section = INCIDENT_SECTIONS + mid; int cmp = strcmp(section->name, name); if (cmp < 0) { low = mid + 1; } else if (cmp > 0) { high = mid - 1; } else { return section; } } return NULL; } // ================================================================================ static void usage(FILE* out) { fprintf(out, "usage: incident OPTIONS [SECTION...]\n"); fprintf(out, "\n"); fprintf(out, "Takes an incident report.\n"); fprintf(out, "\n"); fprintf(out, "OPTIONS\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, "\n"); fprintf(out, " SECTION the field numbers of the incident report fields to include\n"); fprintf(out, "\n"); } int main(int argc, char** argv) { Status status; IncidentReportArgs args; enum { DEST_DROPBOX, DEST_STDOUT } destination = DEST_STDOUT; // Parse the args int opt; while ((opt = getopt(argc, argv, "bhd")) != -1) { switch (opt) { case 'b': destination = DEST_STDOUT; break; case 'h': usage(stdout); return 0; case 'd': destination = DEST_DROPBOX; break; default: usage(stderr); return 1; } } if (optind == argc) { args.setAll(true); } else { for (int i=optind; iid); } } } } // Start the thread pool. sp ps(ProcessState::self()); ps->startThreadPool(); ps->giveThreadPoolName(); // Look up the service sp service = interface_cast( defaultServiceManager()->getService(android::String16("incident"))); if (service == NULL) { fprintf(stderr, "Couldn't look up the incident service\n"); return 1; } // Construct the stream int fds[2]; pipe(fds); unique_fd readEnd(fds[0]); unique_fd writeEnd(fds[1]); if (destination == DEST_STDOUT) { // Call into the service sp listener(new StatusListener()); status = service->reportIncidentToStream(args, listener, writeEnd); if (!status.isOk()) { fprintf(stderr, "reportIncident returned \"%s\"\n", status.toString8().string()); } // Wait for the result and print out the data they send. //IPCThreadState::self()->joinThreadPool(); while (true) { int amt = splice(fds[0], NULL, STDOUT_FILENO, NULL, 4096, 0); fprintf(stderr, "spliced %d bytes\n", amt); if (amt < 0) { return errno; } else if (amt == 0) { return 0; } } } else { status = service->reportIncident(args); if (!status.isOk()) { fprintf(stderr, "reportIncident returned \"%s\"\n", status.toString8().string()); return 1; } else { return 0; } } }