Home | History | Annotate | Download | only in jni
      1 // Copyright 2017 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <signal.h>
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 
     10 #include <memory>
     11 #include <set>
     12 #include <string>
     13 #include <sstream>
     14 
     15 #include "atrace_process_dump.h"
     16 #include "logging.h"
     17 
     18 namespace {
     19 
     20 std::unique_ptr<AtraceProcessDump> g_prog;
     21 
     22 void ParseFullDumpConfig(const std::string& config, AtraceProcessDump* prog) {
     23   using FullDumpMode = AtraceProcessDump::FullDumpMode;
     24   if (config == "all") {
     25     prog->set_full_dump_mode(FullDumpMode::kAllProcesses);
     26   } else if (config == "apps") {
     27     prog->set_full_dump_mode(FullDumpMode::kAllJavaApps);
     28   } else {
     29     std::set<std::string> whitelist;
     30     std::istringstream ss(config);
     31     std::string entry;
     32     while (std::getline(ss, entry, ',')) {
     33       whitelist.insert(entry);
     34     }
     35     if (whitelist.empty())
     36       return;
     37     prog->set_full_dump_mode(FullDumpMode::kOnlyWhitelisted);
     38     prog->set_full_dump_whitelist(whitelist);
     39   }
     40 }
     41 
     42 }  // namespace
     43 
     44 int main(int argc, char** argv) {
     45   if (argc == 2 && !strcmp(argv[1], "--echo-ts")) {
     46     // Used by clock sync marker to correct the difference between
     47     // Linux monotonic clocks on the device and host.
     48     printf("%llu\n", time_utils::GetTimestamp());
     49     return 0;
     50   }
     51 
     52   bool background = false;
     53   int dump_interval_ms = 5000;
     54   char out_file[PATH_MAX] = {};
     55   bool dump_to_file = false;
     56   int count = -1;
     57 
     58   AtraceProcessDump* prog = new AtraceProcessDump();
     59   g_prog = std::unique_ptr<AtraceProcessDump>(prog);
     60 
     61   if (geteuid()) {
     62     fprintf(stderr, "Must run as root\n");
     63     exit(EXIT_FAILURE);
     64   }
     65 
     66   int opt;
     67   while ((opt = getopt(argc, argv, "bm:gst:o:c:")) != -1) {
     68     switch (opt) {
     69       case 'b':
     70         background = true;
     71         break;
     72       case 'm':
     73         ParseFullDumpConfig(optarg, prog);
     74         break;
     75       case 'g':
     76         prog->enable_graphics_stats();
     77         break;
     78       case 's':
     79         prog->enable_print_smaps();
     80         break;
     81       case 't':
     82         dump_interval_ms = atoi(optarg);
     83         CHECK(dump_interval_ms > 0);
     84         break;
     85       case 'c':
     86         count = atoi(optarg);
     87         CHECK(count > 0);
     88         break;
     89       case 'o':
     90         strncpy(out_file, optarg, sizeof(out_file));
     91         dump_to_file = true;
     92         break;
     93       default:
     94         fprintf(stderr,
     95                 "Usage: %s [-b] [-m full_dump_filter] [-g] [-s] "
     96                 "[-t dump_interval_ms] "
     97                 "[-c dumps_count] [-o out.json]\n",
     98                 argv[0]);
     99         exit(EXIT_FAILURE);
    100     }
    101   }
    102 
    103   prog->set_dump_count(count);
    104   prog->SetDumpInterval(dump_interval_ms);
    105 
    106   FILE* out_stream = stdout;
    107   char tmp_file[PATH_MAX];
    108   if (dump_to_file) {
    109     unlink(out_file);
    110     sprintf(tmp_file, "%s.tmp", out_file);
    111     out_stream = fopen(tmp_file, "w");
    112     CHECK(out_stream);
    113   }
    114 
    115   if (background) {
    116     if (!dump_to_file) {
    117       fprintf(stderr, "-b requires -o for output dump path.\n");
    118       exit(EXIT_FAILURE);
    119     }
    120     printf("Continuing in background. kill -TERM to terminate the daemon.\n");
    121     CHECK(daemon(0 /* nochdir */, 0 /* noclose */) == 0);
    122   }
    123 
    124   auto on_exit = [](int) { g_prog->Stop(); };
    125   signal(SIGINT, on_exit);
    126   signal(SIGTERM, on_exit);
    127 
    128   prog->RunAndPrintJson(out_stream);
    129   fclose(out_stream);
    130 
    131   if (dump_to_file)
    132     rename(tmp_file, out_file);
    133 }
    134