1*598139dcSAndroid Build Coastguard Worker /*
2*598139dcSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*598139dcSAndroid Build Coastguard Worker *
4*598139dcSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*598139dcSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*598139dcSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*598139dcSAndroid Build Coastguard Worker *
8*598139dcSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*598139dcSAndroid Build Coastguard Worker *
10*598139dcSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*598139dcSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*598139dcSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*598139dcSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*598139dcSAndroid Build Coastguard Worker * limitations under the License.
15*598139dcSAndroid Build Coastguard Worker */
16*598139dcSAndroid Build Coastguard Worker
17*598139dcSAndroid Build Coastguard Worker #include "PruneList.h"
18*598139dcSAndroid Build Coastguard Worker
19*598139dcSAndroid Build Coastguard Worker #include <ctype.h>
20*598139dcSAndroid Build Coastguard Worker
21*598139dcSAndroid Build Coastguard Worker #include <android-base/logging.h>
22*598139dcSAndroid Build Coastguard Worker #include <android-base/properties.h>
23*598139dcSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
24*598139dcSAndroid Build Coastguard Worker #include <android-base/strings.h>
25*598139dcSAndroid Build Coastguard Worker
Matches(LogBufferElement * element) const26*598139dcSAndroid Build Coastguard Worker bool Prune::Matches(LogBufferElement* element) const {
27*598139dcSAndroid Build Coastguard Worker return (uid_ == UID_ALL || uid_ == element->uid()) &&
28*598139dcSAndroid Build Coastguard Worker (pid_ == PID_ALL || pid_ == element->pid());
29*598139dcSAndroid Build Coastguard Worker }
30*598139dcSAndroid Build Coastguard Worker
Format() const31*598139dcSAndroid Build Coastguard Worker std::string Prune::Format() const {
32*598139dcSAndroid Build Coastguard Worker if (uid_ != UID_ALL) {
33*598139dcSAndroid Build Coastguard Worker if (pid_ != PID_ALL) {
34*598139dcSAndroid Build Coastguard Worker return android::base::StringPrintf("%u/%u", uid_, pid_);
35*598139dcSAndroid Build Coastguard Worker }
36*598139dcSAndroid Build Coastguard Worker return android::base::StringPrintf("%u", uid_);
37*598139dcSAndroid Build Coastguard Worker }
38*598139dcSAndroid Build Coastguard Worker if (pid_ != PID_ALL) {
39*598139dcSAndroid Build Coastguard Worker return android::base::StringPrintf("/%u", pid_);
40*598139dcSAndroid Build Coastguard Worker }
41*598139dcSAndroid Build Coastguard Worker // NB: pid_ == PID_ALL can not happen if uid_ == UID_ALL
42*598139dcSAndroid Build Coastguard Worker return std::string("/");
43*598139dcSAndroid Build Coastguard Worker }
44*598139dcSAndroid Build Coastguard Worker
PruneList()45*598139dcSAndroid Build Coastguard Worker PruneList::PruneList() {
46*598139dcSAndroid Build Coastguard Worker Init(nullptr);
47*598139dcSAndroid Build Coastguard Worker }
48*598139dcSAndroid Build Coastguard Worker
Init(const char * str)49*598139dcSAndroid Build Coastguard Worker bool PruneList::Init(const char* str) {
50*598139dcSAndroid Build Coastguard Worker high_priority_prune_.clear();
51*598139dcSAndroid Build Coastguard Worker low_priority_prune_.clear();
52*598139dcSAndroid Build Coastguard Worker
53*598139dcSAndroid Build Coastguard Worker // default here means take ro.logd.filter, persist.logd.filter then internal default in order.
54*598139dcSAndroid Build Coastguard Worker if (str && !strcmp(str, "default")) {
55*598139dcSAndroid Build Coastguard Worker str = nullptr;
56*598139dcSAndroid Build Coastguard Worker }
57*598139dcSAndroid Build Coastguard Worker if (str && !strcmp(str, "disable")) {
58*598139dcSAndroid Build Coastguard Worker str = "";
59*598139dcSAndroid Build Coastguard Worker }
60*598139dcSAndroid Build Coastguard Worker
61*598139dcSAndroid Build Coastguard Worker std::string filter;
62*598139dcSAndroid Build Coastguard Worker
63*598139dcSAndroid Build Coastguard Worker if (str) {
64*598139dcSAndroid Build Coastguard Worker filter = str;
65*598139dcSAndroid Build Coastguard Worker } else {
66*598139dcSAndroid Build Coastguard Worker filter = android::base::GetProperty("ro.logd.filter", "default");
67*598139dcSAndroid Build Coastguard Worker auto persist_filter = android::base::GetProperty("persist.logd.filter", "default");
68*598139dcSAndroid Build Coastguard Worker // default here means take ro.logd.filter
69*598139dcSAndroid Build Coastguard Worker if (persist_filter != "default") {
70*598139dcSAndroid Build Coastguard Worker filter = persist_filter;
71*598139dcSAndroid Build Coastguard Worker }
72*598139dcSAndroid Build Coastguard Worker }
73*598139dcSAndroid Build Coastguard Worker
74*598139dcSAndroid Build Coastguard Worker // default here means take internal default.
75*598139dcSAndroid Build Coastguard Worker if (filter == "default") {
76*598139dcSAndroid Build Coastguard Worker filter = "~! ~1000/!";
77*598139dcSAndroid Build Coastguard Worker }
78*598139dcSAndroid Build Coastguard Worker if (filter == "disable") {
79*598139dcSAndroid Build Coastguard Worker filter = "";
80*598139dcSAndroid Build Coastguard Worker }
81*598139dcSAndroid Build Coastguard Worker
82*598139dcSAndroid Build Coastguard Worker worst_uid_enabled_ = false;
83*598139dcSAndroid Build Coastguard Worker worst_pid_of_system_enabled_ = false;
84*598139dcSAndroid Build Coastguard Worker
85*598139dcSAndroid Build Coastguard Worker for (str = filter.c_str(); *str; ++str) {
86*598139dcSAndroid Build Coastguard Worker if (isspace(*str)) {
87*598139dcSAndroid Build Coastguard Worker continue;
88*598139dcSAndroid Build Coastguard Worker }
89*598139dcSAndroid Build Coastguard Worker
90*598139dcSAndroid Build Coastguard Worker std::list<Prune>* list;
91*598139dcSAndroid Build Coastguard Worker if (*str == '~' || *str == '!') { // ~ supported, ! undocumented
92*598139dcSAndroid Build Coastguard Worker ++str;
93*598139dcSAndroid Build Coastguard Worker // special case, prune the worst UID of those using at least 1/8th of the buffer.
94*598139dcSAndroid Build Coastguard Worker if (*str == '!') {
95*598139dcSAndroid Build Coastguard Worker worst_uid_enabled_ = true;
96*598139dcSAndroid Build Coastguard Worker ++str;
97*598139dcSAndroid Build Coastguard Worker if (!*str) {
98*598139dcSAndroid Build Coastguard Worker break;
99*598139dcSAndroid Build Coastguard Worker }
100*598139dcSAndroid Build Coastguard Worker if (!isspace(*str)) {
101*598139dcSAndroid Build Coastguard Worker LOG(ERROR) << "Nothing expected after '~!', but found '" << str << "'";
102*598139dcSAndroid Build Coastguard Worker return false;
103*598139dcSAndroid Build Coastguard Worker }
104*598139dcSAndroid Build Coastguard Worker continue;
105*598139dcSAndroid Build Coastguard Worker }
106*598139dcSAndroid Build Coastguard Worker // special case, translated to worst PID of System at priority
107*598139dcSAndroid Build Coastguard Worker static const char WORST_SYSTEM_PID[] = "1000/!";
108*598139dcSAndroid Build Coastguard Worker if (!strncmp(str, WORST_SYSTEM_PID, sizeof(WORST_SYSTEM_PID) - 1)) {
109*598139dcSAndroid Build Coastguard Worker worst_pid_of_system_enabled_ = true;
110*598139dcSAndroid Build Coastguard Worker str += sizeof(WORST_SYSTEM_PID) - 1;
111*598139dcSAndroid Build Coastguard Worker if (!*str) {
112*598139dcSAndroid Build Coastguard Worker break;
113*598139dcSAndroid Build Coastguard Worker }
114*598139dcSAndroid Build Coastguard Worker if (!isspace(*str)) {
115*598139dcSAndroid Build Coastguard Worker LOG(ERROR) << "Nothing expected after '~1000/!', but found '" << str << "'";
116*598139dcSAndroid Build Coastguard Worker return false;
117*598139dcSAndroid Build Coastguard Worker }
118*598139dcSAndroid Build Coastguard Worker continue;
119*598139dcSAndroid Build Coastguard Worker }
120*598139dcSAndroid Build Coastguard Worker if (!*str) {
121*598139dcSAndroid Build Coastguard Worker LOG(ERROR) << "Expected UID or PID after '~', but found nothing";
122*598139dcSAndroid Build Coastguard Worker return false;
123*598139dcSAndroid Build Coastguard Worker }
124*598139dcSAndroid Build Coastguard Worker list = &high_priority_prune_;
125*598139dcSAndroid Build Coastguard Worker } else {
126*598139dcSAndroid Build Coastguard Worker list = &low_priority_prune_;
127*598139dcSAndroid Build Coastguard Worker }
128*598139dcSAndroid Build Coastguard Worker
129*598139dcSAndroid Build Coastguard Worker uid_t uid = Prune::UID_ALL;
130*598139dcSAndroid Build Coastguard Worker if (isdigit(*str)) {
131*598139dcSAndroid Build Coastguard Worker uid = 0;
132*598139dcSAndroid Build Coastguard Worker do {
133*598139dcSAndroid Build Coastguard Worker uid = uid * 10 + *str++ - '0';
134*598139dcSAndroid Build Coastguard Worker } while (isdigit(*str));
135*598139dcSAndroid Build Coastguard Worker }
136*598139dcSAndroid Build Coastguard Worker
137*598139dcSAndroid Build Coastguard Worker pid_t pid = Prune::PID_ALL;
138*598139dcSAndroid Build Coastguard Worker if (*str == '/') {
139*598139dcSAndroid Build Coastguard Worker ++str;
140*598139dcSAndroid Build Coastguard Worker if (isdigit(*str)) {
141*598139dcSAndroid Build Coastguard Worker pid = 0;
142*598139dcSAndroid Build Coastguard Worker do {
143*598139dcSAndroid Build Coastguard Worker pid = pid * 10 + *str++ - '0';
144*598139dcSAndroid Build Coastguard Worker } while (isdigit(*str));
145*598139dcSAndroid Build Coastguard Worker }
146*598139dcSAndroid Build Coastguard Worker }
147*598139dcSAndroid Build Coastguard Worker
148*598139dcSAndroid Build Coastguard Worker if (uid == Prune::UID_ALL && pid == Prune::PID_ALL) {
149*598139dcSAndroid Build Coastguard Worker LOG(ERROR) << "Expected UID/PID combination, but found none";
150*598139dcSAndroid Build Coastguard Worker return false;
151*598139dcSAndroid Build Coastguard Worker }
152*598139dcSAndroid Build Coastguard Worker
153*598139dcSAndroid Build Coastguard Worker if (*str && !isspace(*str)) {
154*598139dcSAndroid Build Coastguard Worker LOG(ERROR) << "Nothing expected after UID/PID combination, but found '" << str << "'";
155*598139dcSAndroid Build Coastguard Worker return false;
156*598139dcSAndroid Build Coastguard Worker }
157*598139dcSAndroid Build Coastguard Worker
158*598139dcSAndroid Build Coastguard Worker list->emplace_back(uid, pid);
159*598139dcSAndroid Build Coastguard Worker if (!*str) {
160*598139dcSAndroid Build Coastguard Worker break;
161*598139dcSAndroid Build Coastguard Worker }
162*598139dcSAndroid Build Coastguard Worker }
163*598139dcSAndroid Build Coastguard Worker
164*598139dcSAndroid Build Coastguard Worker return true;
165*598139dcSAndroid Build Coastguard Worker }
166*598139dcSAndroid Build Coastguard Worker
Format() const167*598139dcSAndroid Build Coastguard Worker std::string PruneList::Format() const {
168*598139dcSAndroid Build Coastguard Worker std::vector<std::string> prune_rules;
169*598139dcSAndroid Build Coastguard Worker
170*598139dcSAndroid Build Coastguard Worker if (worst_uid_enabled_) {
171*598139dcSAndroid Build Coastguard Worker prune_rules.emplace_back("~!");
172*598139dcSAndroid Build Coastguard Worker }
173*598139dcSAndroid Build Coastguard Worker if (worst_pid_of_system_enabled_) {
174*598139dcSAndroid Build Coastguard Worker prune_rules.emplace_back("~1000/!");
175*598139dcSAndroid Build Coastguard Worker }
176*598139dcSAndroid Build Coastguard Worker for (const auto& rule : low_priority_prune_) {
177*598139dcSAndroid Build Coastguard Worker prune_rules.emplace_back(rule.Format());
178*598139dcSAndroid Build Coastguard Worker }
179*598139dcSAndroid Build Coastguard Worker for (const auto& rule : high_priority_prune_) {
180*598139dcSAndroid Build Coastguard Worker prune_rules.emplace_back("~" + rule.Format());
181*598139dcSAndroid Build Coastguard Worker }
182*598139dcSAndroid Build Coastguard Worker return android::base::Join(prune_rules, " ");
183*598139dcSAndroid Build Coastguard Worker }
184*598139dcSAndroid Build Coastguard Worker
IsHighPriority(LogBufferElement * element) const185*598139dcSAndroid Build Coastguard Worker bool PruneList::IsHighPriority(LogBufferElement* element) const {
186*598139dcSAndroid Build Coastguard Worker for (const auto& rule : high_priority_prune_) {
187*598139dcSAndroid Build Coastguard Worker if (rule.Matches(element)) {
188*598139dcSAndroid Build Coastguard Worker return true;
189*598139dcSAndroid Build Coastguard Worker }
190*598139dcSAndroid Build Coastguard Worker }
191*598139dcSAndroid Build Coastguard Worker return false;
192*598139dcSAndroid Build Coastguard Worker }
193*598139dcSAndroid Build Coastguard Worker
IsLowPriority(LogBufferElement * element) const194*598139dcSAndroid Build Coastguard Worker bool PruneList::IsLowPriority(LogBufferElement* element) const {
195*598139dcSAndroid Build Coastguard Worker for (const auto& rule : low_priority_prune_) {
196*598139dcSAndroid Build Coastguard Worker if (rule.Matches(element)) {
197*598139dcSAndroid Build Coastguard Worker return true;
198*598139dcSAndroid Build Coastguard Worker }
199*598139dcSAndroid Build Coastguard Worker }
200*598139dcSAndroid Build Coastguard Worker return false;
201*598139dcSAndroid Build Coastguard Worker }
202