diff options
Diffstat (limited to 'boottime_tools/bootio')
-rw-r--r-- | boottime_tools/bootio/Android.mk | 76 | ||||
-rw-r--r-- | boottime_tools/bootio/README.md | 24 | ||||
-rw-r--r-- | boottime_tools/bootio/bootio.cpp | 162 | ||||
-rw-r--r-- | boottime_tools/bootio/bootio.rc | 10 | ||||
-rw-r--r-- | boottime_tools/bootio/bootio_collector.cpp | 381 | ||||
-rw-r--r-- | boottime_tools/bootio/bootio_collector.h | 39 | ||||
-rw-r--r-- | boottime_tools/bootio/protos.proto | 55 | ||||
-rw-r--r-- | boottime_tools/bootio/sepolicy/bootio.te | 12 | ||||
-rw-r--r-- | boottime_tools/bootio/sepolicy/domain.te | 2 | ||||
-rw-r--r-- | boottime_tools/bootio/sepolicy/file.te | 2 | ||||
-rw-r--r-- | boottime_tools/bootio/sepolicy/file_contexts | 5 |
11 files changed, 768 insertions, 0 deletions
diff --git a/boottime_tools/bootio/Android.mk b/boottime_tools/bootio/Android.mk new file mode 100644 index 00000000..e4db8355 --- /dev/null +++ b/boottime_tools/bootio/Android.mk @@ -0,0 +1,76 @@ +# +# 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. +# + +LOCAL_PATH := $(call my-dir) + +bootio_lib_src_files := \ + protos.proto \ + bootio_collector.cpp \ + +bootio_src_files := \ + bootio.cpp \ + +bootio_shared_libs := \ + libbase \ + libcutils \ + liblog \ + libprotobuf-cpp-lite \ + +bootio_cflags := \ + -Wall \ + -Werror \ + -Wextra \ + +define bootio_proto_include +$(call local-generated-sources-dir)/proto/$(LOCAL_PATH) +endef + +# bootio static library +# ----------------------------------------------------------------------------- + +include $(CLEAR_VARS) + +LOCAL_MODULE := libbootio +LOCAL_MODULE_CLASS := SHARED_LIBRARIES + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/.. \ + $(call bootio_proto_include) \ + +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) +LOCAL_CFLAGS := $(bootio_cflags) +LOCAL_SHARED_LIBRARIES := $(bootio_shared_libs) +LOCAL_PROTOC_OPTIMIZE_TYPE := lite +LOCAL_SRC_FILES := $(bootio_lib_src_files) + +include $(BUILD_SHARED_LIBRARY) + + +# bootio binary +# ----------------------------------------------------------------------------- + +include $(CLEAR_VARS) + +LOCAL_MODULE := bootio +LOCAL_CFLAGS := $(bootio_cflags) +LOCAL_SHARED_LIBRARIES := \ + $(bootio_shared_libs) \ + libbootio \ + +LOCAL_INIT_RC := bootio.rc +LOCAL_SRC_FILES := $(bootio_src_files) + +include $(BUILD_EXECUTABLE) diff --git a/boottime_tools/bootio/README.md b/boottime_tools/bootio/README.md new file mode 100644 index 00000000..ca075ded --- /dev/null +++ b/boottime_tools/bootio/README.md @@ -0,0 +1,24 @@ +# bootio # + +The bootio tool records I/O for processes during boot. +To use bootio kernel must be compiled with this flags: + + CONFIG_TASKSTATS=y + CONFIG_TASK_DELAY_ACCT=y + CONFIG_TASK_XACCT=y + CONFIG_TASK_IO_ACCOUNTING=y + +To use bootio make sure it's included in product config for the board. +Create file /data/misc/bootio/start with a command like the following: + + adb shell 'echo "$TIMEOUT $SAMPLES" > /data/misc/bootio/start' + +Where the value of $TIMEOUT corresponds to the desired bootio period in +seconds and $SAMPLES corresponds to the desired number of samples. + +Note: /data/misc/bootio/start is not deleted automatically, so don't +forget to delete it when you're done collecting data. + +To see collected logs run: + + adb shell bootio -p diff --git a/boottime_tools/bootio/bootio.cpp b/boottime_tools/bootio/bootio.cpp new file mode 100644 index 00000000..629d04a7 --- /dev/null +++ b/boottime_tools/bootio/bootio.cpp @@ -0,0 +1,162 @@ +/* + * 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. + */ + +// The bootio tool provides options to collect I/O stats for processes during boot. + +#include <vector> +#include <getopt.h> +#include <unistd.h> +#include <android-base/file.h> +#include <android-base/logging.h> +#include <android-base/strings.h> +#include <log/log.h> + +#include "bootio_collector.h" + +namespace android { + +#define LOG_ROOT "/data/misc/bootio" +#define LOG_START_FILE LOG_ROOT"/start" +#define SELF_IO "/proc/self/io" + +static const int LOG_TIMEOUT_INDEX = 0; +static const int LOG_SAMPLES_INDEX = 1; +static const int LOG_MAX_TIMEOUT = 120; +static const int LOG_MAX_SAMPLES = 30; + +void ShowHelp(const char *cmd) { + fprintf(stderr, "Usage: %s [options]\n", cmd); + fprintf(stderr, + "options include:\n" + " -h, --help Show this help\n" + " -p, --print Dump the boot io data to the console\n" + "\nNo options will start data collection process.\n"); +} + +void PrintBootIo() { + printf("Boot I/O:\n"); + printf("------------\n"); + std::unique_ptr <BootioCollector> collector(new BootioCollector(LOG_ROOT)); + if (collector.get() == NULL) { + LOG(ERROR) << "Failed to create data collector"; + return; + } + collector->Print(); +} + +void StartDataCollection() { + if (access(SELF_IO, F_OK) == -1) { + LOG(ERROR) << "Kernel doesn't support I/O profiling."; + printf("Kernel doesn't support I/O profiling."); + return; + } + + int timeout = 0; + int samples = 0; + + std::string start; + android::base::ReadFileToString(LOG_START_FILE, &start); + + if (!start.empty()) { + std::vector <std::string> components = android::base::Split(start, " "); + if (components.size() != 2) { + LOG(ERROR) << "Invalid value in start file." << start; + return; + } + timeout = atoi(components.at(LOG_TIMEOUT_INDEX).c_str()); + samples = atoi(components.at(LOG_SAMPLES_INDEX).c_str()); + } else { + LOG(INFO) << "No profiling requested. Exiting"; + printf("Boot I/O: no profiling requested. Exiting.\n"); + return; + } + if (timeout <= 0 || samples <= 0) { + LOG(ERROR) << "Boot I/O: failed to parse string:" << start; + printf("Boot I/O: failed to parse string: %s\n", start.c_str()); + return; + } + if (samples > timeout || samples > LOG_MAX_SAMPLES || timeout > LOG_MAX_TIMEOUT) { + LOG(ERROR) << "Bad values for bootio. timeout=" << timeout << + " samples=" << samples << " Max timeout=" << LOG_MAX_TIMEOUT << + " Max samples=" << LOG_MAX_SAMPLES; + return; + } + LOG(INFO) << "Boot I/O: collecting data. samples=" << samples << "timeout=" << timeout; + printf("Boot I/O: collecting data\ntimeout=%d, samples=%d\n", + timeout, samples); + std::unique_ptr <BootioCollector> collector(new BootioCollector(LOG_ROOT)); + if (collector.get() == NULL) { + LOG(ERROR) << "Failed to create data collector"; + return; + } + collector->StartDataCollection(timeout, samples); +} + +} + +int main(int argc, char **argv) { + android::base::InitLogging(argv); + + LOG(INFO) << "Bootio started"; + + int optionIndex = 0; + static const struct option longOptions[] = { + {"help", no_argument, NULL, 'h'}, + {"print", no_argument, NULL, 'p'}, + {NULL, 0, NULL, 0} + }; + + int opt = 0; + bool startCollection = true; + while ((opt = getopt_long(argc, argv, "hlpr:", longOptions, &optionIndex)) != -1) { + switch (opt) { + case 0: { + const std::string option_name = longOptions[optionIndex].name; + LOG(ERROR) << "Invalid option: " << option_name; + break; + } + + case 'h': { + android::ShowHelp(argv[0]); + startCollection = false; + break; + } + + case 'p': { + android::PrintBootIo(); + startCollection = false; + break; + } + + default: { + DCHECK_EQ(opt, '?'); + + // |optopt| is an external variable set by getopt representing + // the value of the invalid option. + LOG(ERROR) << "Invalid option: " << optopt; + android::ShowHelp(argv[0]); + return EXIT_FAILURE; + } + } + } + + if (startCollection) { + android::StartDataCollection(); + } + + return 0; +} + diff --git a/boottime_tools/bootio/bootio.rc b/boottime_tools/bootio/bootio.rc new file mode 100644 index 00000000..f0074cb4 --- /dev/null +++ b/boottime_tools/bootio/bootio.rc @@ -0,0 +1,10 @@ +# This file is the LOCAL_INIT_RC file for the bootio command. + +service bootio /system/bin/bootio + class main + user root + group root + oneshot + +on post-fs-data + mkdir /data/misc/bootio 0755 root shell diff --git a/boottime_tools/bootio/bootio_collector.cpp b/boottime_tools/bootio/bootio_collector.cpp new file mode 100644 index 00000000..495a9aa4 --- /dev/null +++ b/boottime_tools/bootio/bootio_collector.cpp @@ -0,0 +1,381 @@ +/* + * 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. + */ + +#include "bootio_collector.h" +#include <android-base/logging.h> +#include <android-base/file.h> +#include <log/log.h> +#include "protos.pb.h" +#include "time.h" +#include <unordered_map> +#include <inttypes.h> +#include <dirent.h> + +namespace android { + +#define CPU_STAT_FILE "/proc/stat" +#define SAMPLES_FILE "/samples" +#define PID_STAT_FILE "/proc/%d/stat" +#define PID_CMDLINE_FILE "/proc/%d/cmdline" +#define PID_IO_FILE "/proc/%d/io" +#define PROC_DIR "/proc" + +static const int MAX_LINE = 256; + +#define die(...) { LOG(ERROR) << (__VA_ARGS__); exit(EXIT_FAILURE); } + +void PopulateCpu(CpuData& cpu) { + long unsigned utime, ntime, stime, itime; + long unsigned iowtime, irqtime, sirqtime; + FILE *file; + file = fopen(CPU_STAT_FILE, "r"); + if (!file) die("Could not open /proc/stat.\n"); + fscanf(file, "cpu %lu %lu %lu %lu %lu %lu %lu", &utime, &ntime, &stime, + &itime, &iowtime, &irqtime, &sirqtime); + fclose(file); + cpu.set_utime(utime); + cpu.set_ntime(ntime); + cpu.set_stime(stime); + cpu.set_itime(itime); + cpu.set_iowtime(iowtime); + cpu.set_irqtime(irqtime); + cpu.set_sirqtime(sirqtime); +} + +void ClearPreviousResults(std::string path) { + std::string err; + if (!android::base::RemoveFileIfExists(path, &err)) { + LOG(ERROR) << "failed to remove the file " << path << " " << err; + return; + } +} + +int ReadIo(char *filename, AppSample *sample) { + FILE *file; + char line[MAX_LINE]; + unsigned int rchar, wchar, syscr, syscw, readbytes, writebytes; + + file = fopen(filename, "r"); + if (!file) return 1; + while (fgets(line, MAX_LINE, file)) { + sscanf(line, "rchar: %u", &rchar); + sscanf(line, "wchar: %u", &wchar); + sscanf(line, "syscr: %u", &syscr); + sscanf(line, "syscw: %u", &syscw); + sscanf(line, "read_bytes: %u", &readbytes); + sscanf(line, "write_bytes: %u", &writebytes); + } + fclose(file); + sample->set_rchar(rchar); + sample->set_wchar(wchar); + sample->set_syscr(syscr); + sample->set_syscw(syscw); + sample->set_readbytes(readbytes); + sample->set_writebytes(writebytes); + return 0; +} + +int ReadStatForName(char *filename, AppData *app) { + FILE *file; + char buf[MAX_LINE], *open_paren, *close_paren; + + file = fopen(filename, "r"); + if (!file) return 1; + fgets(buf, MAX_LINE, file); + fclose(file); + + /* Split at first '(' and last ')' to get process name. */ + open_paren = strchr(buf, '('); + close_paren = strrchr(buf, ')'); + if (!open_paren || !close_paren) return 1; + + *open_paren = *close_paren = '\0'; + if (!app->has_tname()) { + app->set_tname(open_paren + 1, close_paren - open_paren - 1); + } + return 0; +} + +int ReadStat(char *filename, AppSample *sample) { + FILE *file; + char buf[MAX_LINE], *open_paren, *close_paren; + + file = fopen(filename, "r"); + if (!file) return 1; + fgets(buf, MAX_LINE, file); + fclose(file); + + /* Split at first '(' and last ')' to get process name. */ + open_paren = strchr(buf, '('); + close_paren = strrchr(buf, ')'); + if (!open_paren || !close_paren) return 1; + + uint64_t utime; + uint64_t stime; + uint64_t rss; + + /* Scan rest of string. */ + sscanf(close_paren + 1, + " %*c " "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " + "%" PRIu64 /*SCNu64*/ + "%" PRIu64 /*SCNu64*/ "%*d %*d %*d %*d %*d %*d %*d %*d " + "%" PRIu64 /*SCNu64*/ "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d", + &utime, + &stime, + &rss); + sample->set_utime(utime); + sample->set_stime(stime); + sample->set_rss(rss); + + return 0; +} + +int ReadCmdline(char *filename, AppData *app) { + FILE *file; + char line[MAX_LINE]; + + line[0] = '\0'; + file = fopen(filename, "r"); + if (!file) return 1; + fgets(line, MAX_LINE, file); + fclose(file); + if (strlen(line) > 0) { + app->set_name(line, strlen(line)); + } else { + app->set_name("N/A"); + } + return 0; +}; + +void ReadProcData(std::unordered_map<int, AppData*>& pidDataMap, DataContainer& dataContainer, + time_t currentTimeUtc, time_t currentUptime) { + DIR *procDir; + struct dirent *pidDir; + pid_t pid; + char filename[64]; + procDir = opendir(PROC_DIR); + if (!procDir) die("Could not open /proc.\n"); + while ((pidDir = readdir(procDir))) { + if (!isdigit(pidDir->d_name[0])) { + continue; + } + pid = atoi(pidDir->d_name); + AppData *data; + + // TODO: in theory same pid can be shared for multiple processes, + // might need add extra check. + if (pidDataMap.count(pid) == 0) { + data = dataContainer.add_app(); + data->set_pid(pid); + sprintf(filename, PID_STAT_FILE, pid); + ReadStatForName(filename, data); + sprintf(filename, PID_CMDLINE_FILE, pid); + ReadCmdline(filename, data); + pidDataMap[pid] = data; + } else { + data = pidDataMap[pid]; + } + AppSample *sample = data->add_samples(); + sample->set_timestamp(currentTimeUtc); + sample->set_uptime(currentUptime); + + sprintf(filename, PID_STAT_FILE, pid); + ReadStat(filename, sample); + + sprintf(filename, PID_IO_FILE, pid); + ReadIo(filename, sample); + } +} + +uint64_t SumCpuValues(CpuData& cpu) { + return cpu.utime() + cpu.ntime() + cpu.stime() + cpu.itime() + cpu.iowtime() + + cpu.irqtime() + cpu.sirqtime(); +} + +time_t GetUptime() { + std::string uptime_str; + if (!android::base::ReadFileToString("/proc/uptime", &uptime_str)) { + LOG(ERROR) << "Failed to read /proc/uptime"; + return -1; + } + + // Cast intentionally rounds down. + return static_cast<time_t>(strtod(uptime_str.c_str(), NULL)); +} + +struct Stats { + int uptime; + float cpu; + uint64_t rbytes; + uint64_t wbytes; +}; + +void PrintPids(DataContainer& data, std::unordered_map<int, uint64_t>& cpuDataMap) { + printf("rchar: number of bytes the process read, using any read-like system call " + "(from files, pipes, tty...).\n"); + printf("wchar: number of bytes the process wrote using any write-like system call.\n"); + printf("wchar: number of bytes the process wrote using any write-like system call.\n"); + printf("syscr: number of write-like system call invocations that the process performed.\n"); + printf("rbytes: number of bytes the process directly read from disk.\n"); + printf("wbytes: number of bytes the process originally dirtied in the page-cache " + "(assuming they will go to disk later).\n\n"); + + std::unique_ptr<AppSample> bootZeroSample(new AppSample()); + std::map<int, Stats> statsMap; + // Init stats map + Stats emptyStat {0, 0., 0, 0}; + for (auto it = cpuDataMap.begin(); it != cpuDataMap.end(); it++) { + statsMap[it->first] = emptyStat; + } + for (int i = 0; i < data.app_size(); i++) { + const AppData appData = data.app(i); + printf("\n-----------------------------------------------------------------------------\n"); + printf("PID:\t%u\n", appData.pid()); + printf("Name:\t%s\n", appData.name().c_str()); + printf("ThName:\t%s\n", appData.tname().c_str()); + printf("%-15s%-13s%-13s%-13s%-13s%-13s%-13s%-13s\n", "Uptime inter.", "rchar", "wchar", + "syscr", "syscw", "rbytes", "wbytes", "cpu%"); + const AppSample *olderSample = NULL; + const AppSample *newerSample = NULL; + bool isFirstSample = true; + for (int j = 0; j < appData.samples_size(); j++) { + olderSample = newerSample; + newerSample = &(appData.samples(j)); + if (olderSample == NULL) { + olderSample = bootZeroSample.get(); + } + float cpuLoad = 0.; + uint64_t cpuDelta; + if (isFirstSample) { + cpuDelta = cpuDataMap[newerSample->timestamp()]; + } else { + cpuDelta = cpuDataMap[newerSample->timestamp()] - + cpuDataMap[olderSample->timestamp()]; + } + if (cpuDelta != 0) { + cpuLoad = (newerSample->utime() - olderSample->utime() + + newerSample->stime() - olderSample->stime()) * 100. / cpuDelta; + } + Stats& stats = statsMap[newerSample->timestamp()]; + stats.uptime = newerSample->uptime(); + stats.cpu += cpuLoad; + stats.rbytes += (newerSample->readbytes() - olderSample->readbytes()); + stats.wbytes += (newerSample->writebytes() - olderSample->writebytes()); + + // Note that all of these are explicitly `long long`s, not int64_t, + // so we can't use PRId64 here. +#define NUMBER "%-13lld" + printf("%5lld - %-5lld " NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER "%-9.2f\n", +#undef NUMBER + olderSample->uptime(), + newerSample->uptime(), + newerSample->rchar() - olderSample->rchar(), + newerSample->wchar() - olderSample->wchar(), + newerSample->syscr() - olderSample->syscr(), + newerSample->syscw() - olderSample->syscw(), + newerSample->readbytes() - olderSample->readbytes(), + newerSample->writebytes() - olderSample->writebytes(), + cpuLoad); + isFirstSample = false; + } + printf("-----------------------------------------------------------------------------\n"); +#define NUMBER "%-13lld" + printf("%-15s" NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER "\n", +#undef NUMBER + "Total", + newerSample->rchar(), + newerSample->wchar(), + newerSample->syscr(), + newerSample->syscw(), + newerSample->readbytes(), + newerSample->writebytes()); + } + printf("\nAggregations\n%-10s%-13s%-13s%-13s\n", + "Total", + "rbytes", + "wbytes", + "cpu%"); + + for (auto it = statsMap.begin(); it != statsMap.end(); it++) { + printf("%-10u%-13" PRIu64 "%-13" PRIu64 "%-9.2f\n", + it->second.uptime, + it->second.rbytes, + it->second.wbytes, + it->second.cpu); + } +} + +} + +BootioCollector::BootioCollector(std::string path) { + DCHECK_EQ('/', path.back()); + path_ = path; +} + +void BootioCollector::StartDataCollection(int timeout, int samples) { + android::ClearPreviousResults(getStoragePath()); + int remaining = samples + 1; + int delayS = timeout / samples; + + std::unordered_map < int, AppData * > pidDataMap; + std::unique_ptr <DataContainer> data(new DataContainer()); + while (remaining > 0) { + time_t currentTimeUtc = time(nullptr); + time_t currentUptime = android::GetUptime(); + CpuData *cpu = data->add_cpu(); + cpu->set_timestamp(currentTimeUtc); + cpu->set_uptime(currentUptime); + android::PopulateCpu(*cpu); + android::ReadProcData(pidDataMap, *data.get(), currentTimeUtc, currentUptime); + remaining--; + if (remaining == 0) { + continue; + } + sleep(delayS); + } + std::string file_data; + if (!data->SerializeToString(&file_data)) { + LOG(ERROR) << "Failed to serialize"; + return; + } + if (!android::base::WriteStringToFile(file_data, getStoragePath())) { + LOG(ERROR) << "Failed to write samples"; + } +} + +void BootioCollector::Print() { + std::string file_data; + if (!android::base::ReadFileToString(getStoragePath(), &file_data)) { + printf("Failed to read data from file.\n"); + return; + } + std::unique_ptr <DataContainer> data(new DataContainer()); + if (!data->ParsePartialFromString(file_data)) { + printf("Failed to parse data.\n"); + return; + } + std::unordered_map<int, uint64_t> cpuDataMap; + for (int i = 0; i < data->cpu_size(); i++) { + CpuData cpu_data = data->cpu(i); + cpuDataMap[cpu_data.timestamp()] = android::SumCpuValues(cpu_data); + } + android::PrintPids(*data.get(), cpuDataMap); +} + + +std::string BootioCollector::getStoragePath() { + return path_ + SAMPLES_FILE; +} diff --git a/boottime_tools/bootio/bootio_collector.h b/boottime_tools/bootio/bootio_collector.h new file mode 100644 index 00000000..7296e6f9 --- /dev/null +++ b/boottime_tools/bootio/bootio_collector.h @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#ifndef BOOTIO_COLLECTOR_H_ +#define BOOTIO_COLLECTOR_H_ + +#include <string> +#include <android-base/macros.h> + +class BootioCollector { +public: + BootioCollector(std::string path); + + void StartDataCollection(int timeout, int samples); + + void Print(); + +private: + std::string getStoragePath(); + + std::string path_; + + DISALLOW_COPY_AND_ASSIGN(BootioCollector); +}; + +#endif // BOOTIO_COLLECTOR_H_ diff --git a/boottime_tools/bootio/protos.proto b/boottime_tools/bootio/protos.proto new file mode 100644 index 00000000..d5674ece --- /dev/null +++ b/boottime_tools/bootio/protos.proto @@ -0,0 +1,55 @@ +// 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. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +message DataContainer { + repeated AppData app = 1; + repeated CpuData cpu = 2; +}; + +message CpuData { + required int64 timestamp = 1; + required int64 uptime = 2; + required int64 utime = 3; + required int64 ntime = 4; + required int64 stime = 5; + required int64 itime = 6; + required int64 iowtime = 7; + required int64 irqtime = 9; + required int64 sirqtime = 10; +} + +message AppData { + required int32 pid = 1; + required string tname = 2; + required string name = 3; + repeated AppSample samples = 4; +} + +message AppSample { + required int64 timestamp = 1; + required int64 uptime = 2; + required int64 rchar = 3; + required int64 wchar = 4; + required int64 syscr = 5; + required int64 syscw = 6; + required int64 readbytes = 7; + required int64 writebytes = 8; + required int64 utime = 9; + required int64 stime = 10; + required int64 rss = 11; +}; diff --git a/boottime_tools/bootio/sepolicy/bootio.te b/boottime_tools/bootio/sepolicy/bootio.te new file mode 100644 index 00000000..cd0fb80d --- /dev/null +++ b/boottime_tools/bootio/sepolicy/bootio.te @@ -0,0 +1,12 @@ +# bootio command +type bootio, domain, coredomain; +type bootio_exec, exec_type, file_type; + +init_daemon_domain(bootio) + +# Allow persistent storage in /data/misc/bootio. +#allow bootio bootio_data_file:dir rw_dir_perms; +#allow bootio bootio_data_file:file create_file_perms; + +# Read access to pseudo filesystems (for /proc/stats, proc/io/io, etc). +#r_dir_file(bootio, proc) diff --git a/boottime_tools/bootio/sepolicy/domain.te b/boottime_tools/bootio/sepolicy/domain.te new file mode 100644 index 00000000..af42fe7e --- /dev/null +++ b/boottime_tools/bootio/sepolicy/domain.te @@ -0,0 +1,2 @@ +# dontaudit bootio kernel:system module_request; +allow bootio kernel:fd use;
\ No newline at end of file diff --git a/boottime_tools/bootio/sepolicy/file.te b/boottime_tools/bootio/sepolicy/file.te new file mode 100644 index 00000000..0320bc83 --- /dev/null +++ b/boottime_tools/bootio/sepolicy/file.te @@ -0,0 +1,2 @@ +# /data/misc subdirectories +type bootio_data_file, file_type, data_file_type, core_data_file_type; diff --git a/boottime_tools/bootio/sepolicy/file_contexts b/boottime_tools/bootio/sepolicy/file_contexts new file mode 100644 index 00000000..071227c2 --- /dev/null +++ b/boottime_tools/bootio/sepolicy/file_contexts @@ -0,0 +1,5 @@ +# System files +/system/bin/bootio u:object_r:bootio_exec:s0 + +# Misc data +/data/misc/bootio(/.*)? u:object_r:bootio_data_file:s0 |