131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv/*
231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv * Copyright (C) 2016 The Android Open Source Project
331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv *
431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv * Licensed under the Apache License, Version 2.0 (the "License");
531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv * you may not use this file except in compliance with the License.
631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv * You may obtain a copy of the License at
731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv *
831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv *      http://www.apache.org/licenses/LICENSE-2.0
931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv *
1031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv * Unless required by applicable law or agreed to in writing, software
1131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv * distributed under the License is distributed on an "AS IS" BASIS,
1231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv * See the License for the specific language governing permissions and
1431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv * limitations under the License.
1531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv */
1631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
1731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv#include "bootio_collector.h"
1831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv#include <android-base/logging.h>
1931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv#include <android-base/file.h>
2031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv#include <log/log.h>
2131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv#include "protos.pb.h"
2231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv#include "time.h"
2331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv#include <unordered_map>
2459b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv#include <inttypes.h>
2531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv#include <dirent.h>
2631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
2731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivnamespace android {
2831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
2931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv#define CPU_STAT_FILE "/proc/stat"
3031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv#define SAMPLES_FILE "/samples"
3131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv#define PID_STAT_FILE "/proc/%d/stat"
3231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv#define PID_CMDLINE_FILE "/proc/%d/cmdline"
3331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv#define PID_IO_FILE "/proc/%d/io"
3431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv#define PROC_DIR "/proc"
3531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
3631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivstatic const int PROC_NAME_LEN = 64;
3731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivstatic const int THREAD_NAME_LEN = 32;
3831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivstatic const int MAX_LINE = 256;
3931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
4031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv#define die(...) { LOG(ERROR) << (__VA_ARGS__); exit(EXIT_FAILURE); }
4131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
4231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivvoid PopulateCpu(CpuData& cpu) {
4331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    long unsigned utime, ntime, stime, itime;
4431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    long unsigned iowtime, irqtime, sirqtime;
4531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    FILE *file;
4631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    file = fopen(CPU_STAT_FILE, "r");
4731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    if (!file) die("Could not open /proc/stat.\n");
4831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    fscanf(file, "cpu  %lu %lu %lu %lu %lu %lu %lu", &utime, &ntime, &stime,
4931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv           &itime, &iowtime, &irqtime, &sirqtime);
5031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    fclose(file);
5131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    cpu.set_utime(utime);
5231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    cpu.set_ntime(ntime);
5331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    cpu.set_stime(stime);
5431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    cpu.set_itime(itime);
5531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    cpu.set_iowtime(iowtime);
5631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    cpu.set_irqtime(irqtime);
5731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    cpu.set_sirqtime(sirqtime);
5831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv}
5931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
6031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivvoid ClearPreviousResults(std::string path) {
6131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    std::string err;
6231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    if (!android::base::RemoveFileIfExists(path, &err)) {
6331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        LOG(ERROR) << "failed to remove the file " << path << " " << err;
6431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        return;
6531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    }
6631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv}
6731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
6831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivint ReadIo(char *filename, AppSample *sample) {
6931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    FILE *file;
7031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    char line[MAX_LINE];
7131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    unsigned int rchar, wchar, syscr, syscw, readbytes, writebytes;
7231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
7331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    file = fopen(filename, "r");
7431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    if (!file) return 1;
7531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    while (fgets(line, MAX_LINE, file)) {
7631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        sscanf(line, "rchar: %u", &rchar);
7731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        sscanf(line, "wchar: %u", &wchar);
7831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        sscanf(line, "syscr: %u", &syscr);
7931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        sscanf(line, "syscw: %u", &syscw);
8031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        sscanf(line, "read_bytes: %u", &readbytes);
8131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        sscanf(line, "write_bytes: %u", &writebytes);
8231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    }
8331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    fclose(file);
8431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    sample->set_rchar(rchar);
8531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    sample->set_wchar(wchar);
8631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    sample->set_syscr(syscr);
8731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    sample->set_syscw(syscw);
8831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    sample->set_readbytes(readbytes);
8931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    sample->set_writebytes(writebytes);
9031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    return 0;
9131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv}
9231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
9331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivint ReadStatForName(char *filename, AppData *app) {
9431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    FILE *file;
9531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    char buf[MAX_LINE], *open_paren, *close_paren;
9631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
9731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    file = fopen(filename, "r");
9831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    if (!file) return 1;
9931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    fgets(buf, MAX_LINE, file);
10031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    fclose(file);
10131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
10231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    /* Split at first '(' and last ')' to get process name. */
10331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    open_paren = strchr(buf, '(');
10431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    close_paren = strrchr(buf, ')');
10531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    if (!open_paren || !close_paren) return 1;
10631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
10731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    *open_paren = *close_paren = '\0';
10831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    if (!app->has_tname()) {
10931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        app->set_tname(open_paren + 1, close_paren - open_paren - 1);
11031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    }
11131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    return 0;
11231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv}
11331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
11431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivint ReadStat(char *filename, AppSample *sample) {
11531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    FILE *file;
11631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    char buf[MAX_LINE], *open_paren, *close_paren;
11731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
11831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    file = fopen(filename, "r");
11931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    if (!file) return 1;
12031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    fgets(buf, MAX_LINE, file);
12131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    fclose(file);
12231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
12331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    /* Split at first '(' and last ')' to get process name. */
12431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    open_paren = strchr(buf, '(');
12531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    close_paren = strrchr(buf, ')');
12631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    if (!open_paren || !close_paren) return 1;
12731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
12831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    uint64_t utime;
12931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    uint64_t stime;
13031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    uint64_t rss;
13131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
13231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    /* Scan rest of string. */
13331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    sscanf(close_paren + 1,
13431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv           " %*c " "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
13559b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv                   "%" PRIu64 /*SCNu64*/
13659b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv                   "%" PRIu64 /*SCNu64*/ "%*d %*d %*d %*d %*d %*d %*d %*d "
13759b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv                   "%" PRIu64 /*SCNu64*/ "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d",
13831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv           &utime,
13931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv           &stime,
14031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv           &rss);
14131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    sample->set_utime(utime);
14231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    sample->set_stime(stime);
14331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    sample->set_rss(rss);
14431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
14531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    return 0;
14631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv}
14731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
14831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivint ReadCmdline(char *filename, AppData *app) {
14931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    FILE *file;
15031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    char line[MAX_LINE];
15131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
15231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    line[0] = '\0';
15331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    file = fopen(filename, "r");
15431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    if (!file) return 1;
15531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    fgets(line, MAX_LINE, file);
15631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    fclose(file);
15731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    if (strlen(line) > 0) {
15831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        app->set_name(line, strlen(line));
15931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    } else {
16031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        app->set_name("N/A");
16131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    }
16231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    return 0;
16331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv};
16431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
16531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivvoid ReadProcData(std::unordered_map<int, AppData*>& pidDataMap, DataContainer& dataContainer,
16659b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv                  time_t currentTimeUtc, time_t currentUptime) {
16731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    DIR *procDir;
16831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    struct dirent *pidDir;
16931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    pid_t pid;
17031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    char filename[64];
17131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    procDir = opendir(PROC_DIR);
17231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    if (!procDir) die("Could not open /proc.\n");
17331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    while ((pidDir = readdir(procDir))) {
17431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        if (!isdigit(pidDir->d_name[0])) {
17531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            continue;
17631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        }
17731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        pid = atoi(pidDir->d_name);
17831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        AppData *data;
17931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
18031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        // TODO: in theory same pid can be shared for multiple processes,
18131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        // might need add extra check.
18231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        if (pidDataMap.count(pid) == 0) {
18331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            data = dataContainer.add_app();
18431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            data->set_pid(pid);
18531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            sprintf(filename, PID_STAT_FILE, pid);
18631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            ReadStatForName(filename, data);
18731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            sprintf(filename, PID_CMDLINE_FILE, pid);
18831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            ReadCmdline(filename, data);
18931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            pidDataMap[pid] = data;
19031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        } else {
19131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            data = pidDataMap[pid];
19231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        }
19331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        AppSample *sample = data->add_samples();
19431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        sample->set_timestamp(currentTimeUtc);
19559b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv        sample->set_uptime(currentUptime);
19631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
19731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        sprintf(filename, PID_STAT_FILE, pid);
19831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        ReadStat(filename, sample);
19931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
20031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        sprintf(filename, PID_IO_FILE, pid);
20131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        ReadIo(filename, sample);
20231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    }
20331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv}
20431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
20531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivuint64_t SumCpuValues(CpuData& cpu) {
20631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    return cpu.utime() + cpu.ntime() + cpu.stime() + cpu.itime() + cpu.iowtime() +
20731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv           cpu.irqtime() + cpu.sirqtime();
20831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv}
20931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
21031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivtime_t GetUptime() {
21131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    std::string uptime_str;
21231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    if (!android::base::ReadFileToString("/proc/uptime", &uptime_str)) {
21331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        LOG(ERROR) << "Failed to read /proc/uptime";
21431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        return -1;
21531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    }
21631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
21731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    // Cast intentionally rounds down.
21831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    return static_cast<time_t>(strtod(uptime_str.c_str(), NULL));
21931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv}
22031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
22159b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkivstruct Stats {
22259b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv    int uptime;
22359b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv    float cpu;
22459b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv    uint64_t rbytes;
22559b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv    uint64_t wbytes;
22659b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv};
22759b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv
22831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivvoid PrintPids(DataContainer& data, std::unordered_map<int, uint64_t>& cpuDataMap) {
22931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    printf("rchar: number of bytes the process read, using any read-like system call "
23031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv                   "(from files, pipes, tty...).\n");
23131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    printf("wchar: number of bytes the process wrote using any write-like system call.\n");
23231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    printf("wchar: number of bytes the process wrote using any write-like system call.\n");
23331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    printf("syscr: number of write-like system call invocations that the process performed.\n");
23431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    printf("rbytes: number of bytes the process directly read from disk.\n");
23531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    printf("wbytes: number of bytes the process originally dirtied in the page-cache "
23631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv                   "(assuming they will go to disk later).\n\n");
23731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
23831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    std::unique_ptr<AppSample> bootZeroSample(new AppSample());
23959b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv    std::map<int, Stats> statsMap;
24059b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv    // Init stats map
24159b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv    Stats emptyStat {0, 0., 0, 0};
24259b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv    for (auto it = cpuDataMap.begin(); it != cpuDataMap.end(); it++) {
24359b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv        statsMap[it->first] = emptyStat;
24459b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv    }
24531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    for (int i = 0; i < data.app_size(); i++) {
24631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        const AppData appData = data.app(i);
24731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        printf("\n-----------------------------------------------------------------------------\n");
24831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        printf("PID:\t%u\n", appData.pid());
24931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        printf("Name:\t%s\n", appData.name().c_str());
25031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        printf("ThName:\t%s\n", appData.tname().c_str());
25159b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv        printf("%-15s%-13s%-13s%-13s%-13s%-13s%-13s%-13s\n", "Uptime inter.", "rchar", "wchar",
25231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv               "syscr", "syscw", "rbytes", "wbytes", "cpu%");
25331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        const AppSample *olderSample = NULL;
25431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        const AppSample *newerSample = NULL;
25531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        bool isFirstSample = true;
25631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        for (int j = 0; j < appData.samples_size(); j++) {
25731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            olderSample = newerSample;
25831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            newerSample = &(appData.samples(j));
25931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            if (olderSample == NULL) {
26031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv                olderSample = bootZeroSample.get();
26131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            }
26231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            float cpuLoad = 0.;
26331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            uint64_t cpuDelta;
26431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            if (isFirstSample) {
26531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv                cpuDelta = cpuDataMap[newerSample->timestamp()];
26631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            } else {
26731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv                cpuDelta = cpuDataMap[newerSample->timestamp()] -
26831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv                        cpuDataMap[olderSample->timestamp()];
26931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            }
27031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            if (cpuDelta != 0) {
27131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv                cpuLoad = (newerSample->utime() - olderSample->utime() +
27231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv                           newerSample->stime() - olderSample->stime()) * 100. / cpuDelta;
27331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            }
27459b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv            Stats& stats = statsMap[newerSample->timestamp()];
27559b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv            stats.uptime = newerSample->uptime();
27659b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv            stats.cpu += cpuLoad;
27759b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv            stats.rbytes += (newerSample->readbytes() - olderSample->readbytes());
27859b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv            stats.wbytes += (newerSample->writebytes() - olderSample->writebytes());
27959b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv
28019b97bb5bb6d7a627d2dd15800d2d9b804f262daGeorge Burgess IV            // Note that all of these are explicitly `long long`s, not int64_t,
28119b97bb5bb6d7a627d2dd15800d2d9b804f262daGeorge Burgess IV            // so we can't use PRId64 here.
28219b97bb5bb6d7a627d2dd15800d2d9b804f262daGeorge Burgess IV#define NUMBER "%-13lld"
28319b97bb5bb6d7a627d2dd15800d2d9b804f262daGeorge Burgess IV            printf("%5lld - %-5lld  " NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER "%-9.2f\n",
28419b97bb5bb6d7a627d2dd15800d2d9b804f262daGeorge Burgess IV#undef NUMBER
28559b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv                   olderSample->uptime(),
28659b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv                   newerSample->uptime(),
28731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv                   newerSample->rchar() - olderSample->rchar(),
28831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv                   newerSample->wchar() - olderSample->wchar(),
28931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv                   newerSample->syscr() - olderSample->syscr(),
29031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv                   newerSample->syscw() - olderSample->syscw(),
29131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv                   newerSample->readbytes() - olderSample->readbytes(),
29231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv                   newerSample->writebytes() - olderSample->writebytes(),
29331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv                   cpuLoad);
29431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            isFirstSample = false;
29531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        }
29631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        printf("-----------------------------------------------------------------------------\n");
29719b97bb5bb6d7a627d2dd15800d2d9b804f262daGeorge Burgess IV#define NUMBER "%-13lld"
29819b97bb5bb6d7a627d2dd15800d2d9b804f262daGeorge Burgess IV        printf("%-15s" NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER "\n",
29919b97bb5bb6d7a627d2dd15800d2d9b804f262daGeorge Burgess IV#undef NUMBER
30031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv               "Total",
30131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv               newerSample->rchar(),
30231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv               newerSample->wchar(),
30331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv               newerSample->syscr(),
30431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv               newerSample->syscw(),
30531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv               newerSample->readbytes(),
30631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv               newerSample->writebytes());
30731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    }
30859b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv    printf("\nAggregations\n%-10s%-13s%-13s%-13s\n",
30959b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv           "Total",
31059b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv           "rbytes",
31159b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv           "wbytes",
31259b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv           "cpu%");
31359b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv
31459b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv    for (auto it = statsMap.begin(); it != statsMap.end(); it++) {
31559b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv        printf("%-10u%-13" PRIu64 "%-13" PRIu64 "%-9.2f\n",
31659b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv               it->second.uptime,
31759b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv               it->second.rbytes,
31859b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv               it->second.wbytes,
31959b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv               it->second.cpu);
32059b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv    }
32131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv}
32231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
32331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv}
32431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
32531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii TomkivBootioCollector::BootioCollector(std::string path) {
32631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    DCHECK_EQ('/', path.back());
32731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    path_ = path;
32831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv}
32931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
33031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivvoid BootioCollector::StartDataCollection(int timeout, int samples) {
33131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    android::ClearPreviousResults(getStoragePath());
33231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    int remaining = samples + 1;
33331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    int delayS = timeout / samples;
33431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
33531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    std::unordered_map < int, AppData * > pidDataMap;
33631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    std::unique_ptr <DataContainer> data(new DataContainer());
33731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    while (remaining > 0) {
33831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        time_t currentTimeUtc = time(nullptr);
33959b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv        time_t currentUptime = android::GetUptime();
34031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        CpuData *cpu = data->add_cpu();
34131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        cpu->set_timestamp(currentTimeUtc);
34259b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv        cpu->set_uptime(currentUptime);
34331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        android::PopulateCpu(*cpu);
34459b10642478f17f2d59ae0d1ca0e5c42fa17f026Vitalii Tomkiv        android::ReadProcData(pidDataMap, *data.get(), currentTimeUtc, currentUptime);
34531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        remaining--;
34631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        if (remaining == 0) {
34731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv            continue;
34831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        }
34931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        sleep(delayS);
35031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    }
35131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    std::string file_data;
35231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    if (!data->SerializeToString(&file_data)) {
35331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        LOG(ERROR) << "Failed to serialize";
35431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        return;
35531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    }
35631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    if (!android::base::WriteStringToFile(file_data, getStoragePath())) {
35731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        LOG(ERROR) << "Failed to write samples";
35831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    }
35931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv}
36031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
36131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivvoid BootioCollector::Print() {
36231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    std::string file_data;
36331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    if (!android::base::ReadFileToString(getStoragePath(), &file_data)) {
36431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        printf("Failed to read data from file.\n");
36531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        return;
36631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    }
36731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    std::unique_ptr <DataContainer> data(new DataContainer());
36831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    if (!data->ParsePartialFromString(file_data)) {
36931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        printf("Failed to parse data.\n");
37031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        return;
37131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    }
37231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    std::unordered_map<int, uint64_t> cpuDataMap;
37331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    for (int i = 0; i < data->cpu_size(); i++) {
37431c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        CpuData cpu_data = data->cpu(i);
37531c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv        cpuDataMap[cpu_data.timestamp()] = android::SumCpuValues(cpu_data);
37631c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    }
37731c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    android::PrintPids(*data.get(), cpuDataMap);
37831c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv}
37931c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
38031c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv
38131c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkivstd::string BootioCollector::getStoragePath() {
38231c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv    return path_ + SAMPLES_FILE;
38331c2e747abd0ba26e1abacbdd56d9f222e7d9e30Vitalii Tomkiv}
384