blob: 430e7afc7b9bc0a94b080b9c3a906a2339fdd6f9 [file] [log] [blame]
Yao Chen482d2722017-09-12 13:25:43 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Yao Chen482d2722017-09-12 13:25:43 -070016#include <android-base/file.h>
Yao Chenef99c4f2017-09-22 16:26:54 -070017#include <android/os/DropBoxManager.h>
Yao Chen482d2722017-09-12 13:25:43 -070018#include <androidfw/ZipUtils.h>
Yao Chen482d2722017-09-12 13:25:43 -070019
20#include "DropboxReader.h"
21
Yao Chen482d2722017-09-12 13:25:43 -070022using android::String16;
Yao Chen482d2722017-09-12 13:25:43 -070023using android::ZipUtils;
Yao Chenef99c4f2017-09-22 16:26:54 -070024using android::base::unique_fd;
25using android::binder::Status;
26using android::os::DropBoxManager;
27using android::sp;
Yao Chen482d2722017-09-12 13:25:43 -070028using std::vector;
29
Bookatz906a35c2017-09-20 15:26:44 -070030namespace android {
31namespace os {
32namespace statsd {
33
Yao Chen482d2722017-09-12 13:25:43 -070034status_t DropboxReader::readStatsLogs(FILE* out, const string& tag, long msec) {
35 sp<DropBoxManager> dropbox = new DropBoxManager();
yro00698da2017-09-15 10:06:40 -070036 StatsLogReport logReport;
Yao Chen482d2722017-09-12 13:25:43 -070037
38 long timestamp = msec;
39 // instead of while(true), put a hard limit 1000. Dropbox won't have more than 1000 files.
Yao Chenef99c4f2017-09-22 16:26:54 -070040 for (int i = 0; i < 1000; i++) {
Yao Chen482d2722017-09-12 13:25:43 -070041 DropBoxManager::Entry entry;
Yao Chenef99c4f2017-09-22 16:26:54 -070042 Status status = dropbox->getNextEntry(String16(tag.c_str()), timestamp, &entry);
Yao Chen482d2722017-09-12 13:25:43 -070043 if (!status.isOk()) {
44 ALOGD("No more entries, or failed to read. We can't tell unfortunately.");
45 return android::OK;
46 }
47
48 const unique_fd& fd = entry.getFd();
49
50 // use this timestamp for next query.
51 timestamp = entry.getTimestamp();
52
53 if (entry.getFlags() & DropBoxManager::IS_GZIPPED) {
yro00698da2017-09-15 10:06:40 -070054 if (!parseFromGzipFile(fd, logReport)) {
Yao Chen482d2722017-09-12 13:25:43 -070055 // Failed to parse from the file. Continue to fetch the next entry.
56 continue;
57 }
58 } else {
yro00698da2017-09-15 10:06:40 -070059 if (!parseFromFile(fd, logReport)) {
Yao Chen482d2722017-09-12 13:25:43 -070060 // Failed to parse from the file. Continue to fetch the next entry.
61 continue;
62 }
63 }
64
yro00698da2017-09-15 10:06:40 -070065 printLog(out, logReport);
Yao Chen482d2722017-09-12 13:25:43 -070066 }
67 return android::OK;
68}
69
yro00698da2017-09-15 10:06:40 -070070bool DropboxReader::parseFromGzipFile(const unique_fd& fd, StatsLogReport& logReport) {
Yao Chenef99c4f2017-09-22 16:26:54 -070071 FILE* file = fdopen(fd, "r");
Yao Chen482d2722017-09-12 13:25:43 -070072 bool result = false;
73 bool scanResult;
74 int method;
75 long compressedLen;
76 long uncompressedLen;
77 unsigned long crc32;
Yao Chenef99c4f2017-09-22 16:26:54 -070078 scanResult = ZipUtils::examineGzip(file, &method, &uncompressedLen, &compressedLen, &crc32);
Yao Chen482d2722017-09-12 13:25:43 -070079 if (scanResult && method == kCompressDeflated) {
80 vector<uint8_t> buf(uncompressedLen);
81 if (ZipUtils::inflateToBuffer(file, &buf[0], uncompressedLen, compressedLen)) {
yro00698da2017-09-15 10:06:40 -070082 if (logReport.ParseFromArray(&buf[0], uncompressedLen)) {
Yao Chen482d2722017-09-12 13:25:43 -070083 result = true;
84 }
85 }
86 } else {
87 ALOGE("This isn't a valid deflated gzip file");
88 }
89 fclose(file);
90 return result;
91}
92
93// parse a non zipped file.
yro00698da2017-09-15 10:06:40 -070094bool DropboxReader::parseFromFile(const unique_fd& fd, StatsLogReport& logReport) {
Yao Chen482d2722017-09-12 13:25:43 -070095 string content;
96 if (!android::base::ReadFdToString(fd, &content)) {
97 ALOGE("Failed to read file");
98 return false;
99 }
yro00698da2017-09-15 10:06:40 -0700100 if (!logReport.ParseFromString(content)) {
Yao Chen482d2722017-09-12 13:25:43 -0700101 ALOGE("failed to parse log entry from data");
102 return false;
103 }
104 return true;
105}
106
yro00698da2017-09-15 10:06:40 -0700107void DropboxReader::printLog(FILE* out, const StatsLogReport& logReport) {
Stefan Lafoncdb1a0e2017-09-27 20:24:15 -0700108 fprintf(out, "start_time_ns=%lld, end_time_ns=%lld, ", logReport.start_report_nanos(),
109 logReport.end_report_nanos());
yro00698da2017-09-15 10:06:40 -0700110 for (int i = 0; i < logReport.event_metrics().data_size(); i++) {
111 EventMetricData eventMetricData = logReport.event_metrics().data(i);
Stefan Lafoncdb1a0e2017-09-27 20:24:15 -0700112 // TODO: Pretty-print the proto.
113 // fprintf(out, "EventMetricData=%s", eventMetricData.SerializeAsString().c_str());
Yao Chen482d2722017-09-12 13:25:43 -0700114 }
yro00698da2017-09-15 10:06:40 -0700115 fprintf(out, "\n");
Yao Chen482d2722017-09-12 13:25:43 -0700116}
Bookatz906a35c2017-09-20 15:26:44 -0700117
Yao Chenef99c4f2017-09-22 16:26:54 -0700118} // namespace statsd
119} // namespace os
120} // namespace android