blob: 1d75e20d7eaa55652e99fd0c0f9046feb7416324 [file] [log] [blame]
yro947fbce2017-11-15 22:50:23 -08001/*
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 */
16
17#define DEBUG true // STOPSHIP if true
18#include "Log.h"
19
20#include "storage/StorageManager.h"
21#include "android-base/stringprintf.h"
22
23#include <android-base/file.h>
24#include <dirent.h>
25
yro947fbce2017-11-15 22:50:23 -080026namespace android {
27namespace os {
28namespace statsd {
29
Yao Chenf09569f2017-12-13 17:00:51 -080030using android::util::FIELD_COUNT_REPEATED;
31using android::util::FIELD_TYPE_MESSAGE;
32using std::map;
33
yro03faf092017-12-12 00:17:50 -080034#define STATS_SERVICE_DIR "/data/misc/stats-service"
yro947fbce2017-11-15 22:50:23 -080035
36// for ConfigMetricsReportList
37const int FIELD_ID_REPORTS = 2;
38
39using android::base::StringPrintf;
40using std::unique_ptr;
41
42void StorageManager::writeFile(const char* file, const void* buffer, int numBytes) {
43 int fd = open(file, O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR);
Stefan Lafonc7bdc622017-11-27 12:54:21 -080044 if (fd == -1) {
yro947fbce2017-11-15 22:50:23 -080045 VLOG("Attempt to access %s but failed", file);
46 return;
47 }
48
49 int result = write(fd, buffer, numBytes);
50 if (result == numBytes) {
51 VLOG("Successfully wrote %s", file);
52 } else {
53 VLOG("Failed to write %s", file);
54 }
55 close(fd);
56}
57
58void StorageManager::deleteFile(const char* file) {
59 if (remove(file) != 0) {
60 VLOG("Attempt to delete %s but is not found", file);
61 } else {
62 VLOG("Successfully deleted %s", file);
63 }
64}
65
66void StorageManager::deleteAllFiles(const char* path) {
67 unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir);
68 if (dir == NULL) {
69 VLOG("Directory does not exist: %s", path);
70 return;
71 }
72
73 dirent* de;
74 while ((de = readdir(dir.get()))) {
75 char* name = de->d_name;
76 if (name[0] == '.') continue;
77 deleteFile(StringPrintf("%s/%s", path, name).c_str());
78 }
79}
80
81void StorageManager::deletePrefixedFiles(const char* path, const char* prefix) {
82 unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir);
83 if (dir == NULL) {
84 VLOG("Directory does not exist: %s", path);
85 return;
86 }
87
88 dirent* de;
89 while ((de = readdir(dir.get()))) {
90 char* name = de->d_name;
91 if (name[0] == '.' || strncmp(name, prefix, strlen(prefix)) != 0) {
92 continue;
93 }
94 deleteFile(StringPrintf("%s/%s", path, name).c_str());
95 }
96}
97
98void StorageManager::sendBroadcast(const char* path,
99 const std::function<void(const ConfigKey&)>& sendBroadcast) {
100 unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir);
101 if (dir == NULL) {
102 VLOG("no stats-data directory on disk");
103 return;
104 }
105
106 dirent* de;
107 while ((de = readdir(dir.get()))) {
108 char* name = de->d_name;
109 if (name[0] == '.') continue;
110 VLOG("file %s", name);
111
112 int index = 0;
113 int uid = 0;
yro6e304ec2018-01-16 21:00:30 -0800114 int64_t configID = 0;
yro947fbce2017-11-15 22:50:23 -0800115 char* substr = strtok(name, "-");
116 // Timestamp lives at index 2 but we skip parsing it as it's not needed.
117 while (substr != nullptr && index < 2) {
yro6e304ec2018-01-16 21:00:30 -0800118 if (index == 0) {
yro947fbce2017-11-15 22:50:23 -0800119 uid = atoi(substr);
yro6e304ec2018-01-16 21:00:30 -0800120 } else if (index == 1) {
121 configID = StrToInt64(substr);
yro947fbce2017-11-15 22:50:23 -0800122 }
123 index++;
yro6e304ec2018-01-16 21:00:30 -0800124 substr = strtok(nullptr, "-");
yro947fbce2017-11-15 22:50:23 -0800125 }
126 if (index < 2) continue;
127
yro6e304ec2018-01-16 21:00:30 -0800128 sendBroadcast(ConfigKey(uid, configID));
yro947fbce2017-11-15 22:50:23 -0800129 }
130}
131
132void StorageManager::appendConfigMetricsReport(const char* path, ProtoOutputStream& proto) {
133 unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir);
Yao Chen72506222017-11-25 15:33:09 -0800134 if (dir == NULL) {
yro947fbce2017-11-15 22:50:23 -0800135 VLOG("Path %s does not exist", path);
136 return;
137 }
138
139 dirent* de;
140 while ((de = readdir(dir.get()))) {
141 char* name = de->d_name;
142 if (name[0] == '.') continue;
143 VLOG("file %s", name);
144
145 int index = 0;
146 int uid = 0;
yro6e304ec2018-01-16 21:00:30 -0800147 int64_t configID = 0;
148 int64_t timestamp = 0;
yro947fbce2017-11-15 22:50:23 -0800149 char* substr = strtok(name, "-");
yro6e304ec2018-01-16 21:00:30 -0800150 while (substr != nullptr && index < 3) {
151 if (index == 0) {
yro947fbce2017-11-15 22:50:23 -0800152 uid = atoi(substr);
yro6e304ec2018-01-16 21:00:30 -0800153 } else if (index == 1) {
154 configID = StrToInt64(substr);
155 } else if (index == 2) {
156 timestamp = atoi(substr);
yro947fbce2017-11-15 22:50:23 -0800157 }
158 index++;
yro6e304ec2018-01-16 21:00:30 -0800159 substr = strtok(nullptr, "-");
yro947fbce2017-11-15 22:50:23 -0800160 }
yro6e304ec2018-01-16 21:00:30 -0800161 if (index < 3) continue;
162 string file_name = StringPrintf("%s/%d-%lld-%lld", STATS_SERVICE_DIR, uid,
163 (long long)configID, (long long)timestamp);
yro947fbce2017-11-15 22:50:23 -0800164 int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC);
165 if (fd != -1) {
166 string content;
167 if (android::base::ReadFdToString(fd, &content)) {
168 proto.write(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS,
169 content.c_str());
170 }
171 close(fd);
172 }
173
174 // Remove file from disk after reading.
175 remove(file_name.c_str());
176 }
177}
178
Yao Chenf09569f2017-12-13 17:00:51 -0800179void StorageManager::readConfigFromDisk(map<ConfigKey, StatsdConfig>& configsMap) {
yro947fbce2017-11-15 22:50:23 -0800180 unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR), closedir);
181 if (dir == NULL) {
182 VLOG("no default config on disk");
183 return;
184 }
185
186 dirent* de;
187 while ((de = readdir(dir.get()))) {
188 char* name = de->d_name;
189 if (name[0] == '.') continue;
190 VLOG("file %s", name);
191
192 int index = 0;
193 int uid = 0;
yro6e304ec2018-01-16 21:00:30 -0800194 int64_t configID = 0;
195 int64_t timestamp = 0;
yro947fbce2017-11-15 22:50:23 -0800196 char* substr = strtok(name, "-");
yro6e304ec2018-01-16 21:00:30 -0800197 while (substr != nullptr && index < 3) {
198 if (index == 0) {
yro947fbce2017-11-15 22:50:23 -0800199 uid = atoi(substr);
yro6e304ec2018-01-16 21:00:30 -0800200 } else if (index == 1) {
201 configID = StrToInt64(substr);
202 } else if (index == 2) {
203 timestamp = atoi(substr);
yro947fbce2017-11-15 22:50:23 -0800204 }
205 index++;
yro6e304ec2018-01-16 21:00:30 -0800206 substr = strtok(nullptr, "-");
yro947fbce2017-11-15 22:50:23 -0800207 }
yro6e304ec2018-01-16 21:00:30 -0800208 if (index < 3) continue;
Yangster-mac94e197c2018-01-02 16:03:03 -0800209
yro6e304ec2018-01-16 21:00:30 -0800210 string file_name = StringPrintf("%s/%d-%lld-%lld", STATS_SERVICE_DIR, uid,
211 (long long)configID, (long long)timestamp);
yro947fbce2017-11-15 22:50:23 -0800212 int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC);
213 if (fd != -1) {
214 string content;
215 if (android::base::ReadFdToString(fd, &content)) {
216 StatsdConfig config;
217 if (config.ParseFromString(content)) {
yro6e304ec2018-01-16 21:00:30 -0800218 configsMap[ConfigKey(uid, configID)] = config;
219 VLOG("map key uid=%d|configID=%lld", uid, (long long)configID);
yro947fbce2017-11-15 22:50:23 -0800220 }
221 }
222 close(fd);
223 }
224 }
225}
226
227} // namespace statsd
228} // namespace os
229} // namespace android