• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2020, 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 LOG_TAG "carwatchdogd"
18 
19 #include "WatchdogBinderMediator.h"
20 
21 #include <android-base/file.h>
22 #include <android-base/parseint.h>
23 #include <android-base/stringprintf.h>
24 #include <android-base/strings.h>
25 #include <binder/IServiceManager.h>
26 #include <log/log.h>
27 
28 namespace android {
29 namespace automotive {
30 namespace watchdog {
31 
32 using ::android::defaultServiceManager;
33 using ::android::IBinder;
34 using ::android::sp;
35 using ::android::String16;
36 using ::android::base::Error;
37 using ::android::base::Join;
38 using ::android::base::ParseUint;
39 using ::android::base::Result;
40 using ::android::base::Split;
41 using ::android::base::StringAppendF;
42 using ::android::base::StringPrintf;
43 using ::android::base::WriteStringToFd;
44 using ::android::binder::Status;
45 
46 using AddServiceFunction =
47         std::function<android::base::Result<void>(const char*,
48                                                   const android::sp<android::IBinder>&)>;
49 
50 namespace {
51 
52 constexpr const char* kHelpFlag = "--help";
53 constexpr const char* kHelpShortFlag = "-h";
54 constexpr const char* kHelpText =
55         "CarWatchdog daemon dumpsys help page:\n"
56         "Format: dumpsys android.automotive.watchdog.ICarWatchdog/default [options]\n\n"
57         "%s or %s: Displays this help text.\n"
58         "When no options are specified, carwatchdog report is generated.\n";
59 constexpr const char* kCarWatchdogServerInterface =
60         "android.automotive.watchdog.ICarWatchdog/default";
61 constexpr const char* kCarWatchdogInternalServerInterface =
62         "android.automotive.watchdog.internal.ICarWatchdog/default";
63 constexpr const char* kNullCarWatchdogClientError =
64         "Must provide a non-null car watchdog client instance";
65 
fromExceptionCode(const int32_t exceptionCode,const std::string & message)66 Status fromExceptionCode(const int32_t exceptionCode, const std::string& message) {
67     ALOGW("%s", message.c_str());
68     return Status::fromExceptionCode(exceptionCode, message.c_str());
69 }
70 
addToServiceManager(const char * serviceName,sp<IBinder> service)71 Result<void> addToServiceManager(const char* serviceName, sp<IBinder> service) {
72     status_t status = defaultServiceManager()->addService(String16(serviceName), service);
73     if (status != OK) {
74         return Error(status) << "Failed to add '" << serviceName << "' to ServiceManager";
75     }
76     return {};
77 }
78 
79 }  // namespace
80 
WatchdogBinderMediator(const android::sp<WatchdogProcessServiceInterface> & watchdogProcessService,const android::sp<WatchdogPerfServiceInterface> & watchdogPerfService,const android::sp<WatchdogServiceHelperInterface> & watchdogServiceHelper,const AddServiceFunction & addServiceHandler)81 WatchdogBinderMediator::WatchdogBinderMediator(
82         const android::sp<WatchdogProcessServiceInterface>& watchdogProcessService,
83         const android::sp<WatchdogPerfServiceInterface>& watchdogPerfService,
84         const android::sp<WatchdogServiceHelperInterface>& watchdogServiceHelper,
85         const AddServiceFunction& addServiceHandler) :
86       mWatchdogProcessService(watchdogProcessService),
87       mWatchdogPerfService(watchdogPerfService),
88       mWatchdogServiceHelper(watchdogServiceHelper),
89       mAddServiceHandler(addServiceHandler) {
90     if (mAddServiceHandler == nullptr) {
91         mAddServiceHandler = &addToServiceManager;
92     }
93     if (watchdogServiceHelper != nullptr) {
94         mIoOveruseMonitor = sp<IoOveruseMonitor>::make(watchdogServiceHelper);
95     }
96 }
97 
init()98 Result<void> WatchdogBinderMediator::init() {
99     if (mWatchdogProcessService == nullptr || mWatchdogPerfService == nullptr ||
100         mWatchdogServiceHelper == nullptr || mIoOveruseMonitor == nullptr) {
101         std::string serviceList;
102         if (mWatchdogProcessService == nullptr) {
103             StringAppendF(&serviceList, "%s%s", (!serviceList.empty() ? ", " : ""),
104                           "Watchdog process service");
105         }
106         if (mWatchdogPerfService == nullptr) {
107             StringAppendF(&serviceList, "%s%s", (!serviceList.empty() ? ", " : ""),
108                           "Watchdog performance service");
109         }
110         if (mWatchdogServiceHelper == nullptr) {
111             StringAppendF(&serviceList, "%s%s", (!serviceList.empty() ? ", " : ""),
112                           "Watchdog service helper");
113         }
114         if (mIoOveruseMonitor == nullptr) {
115             StringAppendF(&serviceList, "%s%s", (!serviceList.empty() ? ", " : ""),
116                           "I/O overuse monitor service");
117         }
118         return Error(INVALID_OPERATION)
119                 << serviceList << " must be initialized with non-null instance";
120     }
121     mWatchdogInternalHandler =
122             sp<WatchdogInternalHandler>::make(sp<WatchdogBinderMediator>::fromExisting(this),
123                                               mWatchdogServiceHelper, mWatchdogProcessService,
124                                               mWatchdogPerfService, mIoOveruseMonitor);
125     if (const auto result =
126                 mAddServiceHandler(kCarWatchdogServerInterface, sp<IBinder>::fromExisting(this));
127         !result.ok()) {
128         return result;
129     }
130     if (const auto result =
131                 mAddServiceHandler(kCarWatchdogInternalServerInterface, mWatchdogInternalHandler);
132         !result.ok()) {
133         return result;
134     }
135     return {};
136 }
137 
dump(int fd,const Vector<String16> & args)138 status_t WatchdogBinderMediator::dump(int fd, const Vector<String16>& args) {
139     int numArgs = args.size();
140     if (numArgs == 0) {
141         return dumpServices(fd, args);
142     }
143     if (numArgs == 1 && (args[0] == String16(kHelpFlag) || args[0] == String16(kHelpShortFlag))) {
144         return dumpHelpText(fd, "");
145     }
146     if (args[0] == String16(kStartCustomCollectionFlag) ||
147         args[0] == String16(kEndCustomCollectionFlag)) {
148         if (auto result = mWatchdogPerfService->onCustomCollection(fd, args); !result.ok()) {
149             std::string mode = args[0] == String16(kStartCustomCollectionFlag) ? "start" : "end";
150             std::string errorMsg = StringPrintf("Failed to %s custom I/O perf collection: %s",
151                                                 mode.c_str(), result.error().message().c_str());
152             if (result.error().code() == BAD_VALUE) {
153                 dumpHelpText(fd, errorMsg);
154             } else {
155                 ALOGW("%s", errorMsg.c_str());
156             }
157             return result.error().code();
158         }
159         return OK;
160     }
161     if (numArgs == 2 && args[0] == String16(kResetResourceOveruseStatsFlag)) {
162         std::string value = std::string(String8(args[1]));
163         std::vector<std::string> packageNames = Split(value, ",");
164         if (value.empty() || packageNames.empty()) {
165             dumpHelpText(fd,
166                          StringPrintf("Must provide valid package names: [%s]\n", value.c_str()));
167             return BAD_VALUE;
168         }
169         if (auto result = mIoOveruseMonitor->resetIoOveruseStats(packageNames); !result.ok()) {
170             ALOGW("Failed to reset stats for packages: [%s]", value.c_str());
171             return FAILED_TRANSACTION;
172         }
173         return OK;
174     }
175     dumpHelpText(fd,
176                  StringPrintf("Invalid carwatchdog dumpsys options: [%s]\n",
177                               Join(args, " ").c_str()));
178     return dumpServices(fd, args);
179 }
180 
dumpServices(int fd,const Vector<String16> & args)181 status_t WatchdogBinderMediator::dumpServices(int fd, const Vector<String16>& args) {
182     if (auto result = mWatchdogProcessService->dump(fd, args); !result.ok()) {
183         ALOGW("Failed to dump carwatchdog process service: %s", result.error().message().c_str());
184         return result.error().code();
185     }
186     if (auto result = mWatchdogPerfService->onDump(fd); !result.ok()) {
187         ALOGW("Failed to dump carwatchdog perf service: %s", result.error().message().c_str());
188         return result.error().code();
189     }
190     return OK;
191 }
192 
dumpHelpText(const int fd,const std::string & errorMsg)193 status_t WatchdogBinderMediator::dumpHelpText(const int fd, const std::string& errorMsg) {
194     if (!errorMsg.empty()) {
195         ALOGW("Error: %s", errorMsg.c_str());
196         if (!WriteStringToFd(StringPrintf("Error: %s\n\n", errorMsg.c_str()), fd)) {
197             ALOGW("Failed to write error message to fd");
198             return FAILED_TRANSACTION;
199         }
200     }
201     if (!WriteStringToFd(StringPrintf(kHelpText, kHelpFlag, kHelpShortFlag), fd) ||
202         !mWatchdogPerfService->dumpHelpText(fd) || !mIoOveruseMonitor->dumpHelpText(fd)) {
203         ALOGW("Failed to write help text to fd");
204         return FAILED_TRANSACTION;
205     }
206     return OK;
207 }
208 
registerClient(const sp<ICarWatchdogClient> & client,TimeoutLength timeout)209 Status WatchdogBinderMediator::registerClient(const sp<ICarWatchdogClient>& client,
210                                               TimeoutLength timeout) {
211     if (client == nullptr) {
212         return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, kNullCarWatchdogClientError);
213     }
214     return mWatchdogProcessService->registerClient(client, timeout);
215 }
216 
unregisterClient(const sp<ICarWatchdogClient> & client)217 Status WatchdogBinderMediator::unregisterClient(const sp<ICarWatchdogClient>& client) {
218     if (client == nullptr) {
219         return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, kNullCarWatchdogClientError);
220     }
221     return mWatchdogProcessService->unregisterClient(client);
222 }
223 
tellClientAlive(const sp<ICarWatchdogClient> & client,int32_t sessionId)224 Status WatchdogBinderMediator::tellClientAlive(const sp<ICarWatchdogClient>& client,
225                                                int32_t sessionId) {
226     if (client == nullptr) {
227         return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, kNullCarWatchdogClientError);
228     }
229     return mWatchdogProcessService->tellClientAlive(client, sessionId);
230 }
231 
addResourceOveruseListener(const std::vector<ResourceType> & resourceTypes,const sp<IResourceOveruseListener> & listener)232 Status WatchdogBinderMediator::addResourceOveruseListener(
233         const std::vector<ResourceType>& resourceTypes,
234         const sp<IResourceOveruseListener>& listener) {
235     if (listener == nullptr) {
236         return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
237                                  "Must provide a non-null resource overuse listener");
238     }
239     if (resourceTypes.size() != 1 || resourceTypes[0] != ResourceType::IO) {
240         return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
241                                  "Must provide exactly one I/O resource type");
242     }
243     /*
244      * When more resource types are added, implement a new module to manage listeners for all
245      * resources.
246      */
247     if (const auto result = mIoOveruseMonitor->addIoOveruseListener(listener); !result.ok()) {
248         return fromExceptionCode(result.error().code(),
249                                  StringPrintf("Failed to register resource overuse listener: %s ",
250                                               result.error().message().c_str()));
251     }
252     return Status::ok();
253 }
254 
removeResourceOveruseListener(const sp<IResourceOveruseListener> & listener)255 Status WatchdogBinderMediator::removeResourceOveruseListener(
256         const sp<IResourceOveruseListener>& listener) {
257     if (listener == nullptr) {
258         return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
259                                  "Must provide a non-null resource overuse listener");
260     }
261     if (const auto result = mIoOveruseMonitor->removeIoOveruseListener(listener); !result.ok()) {
262         return fromExceptionCode(result.error().code(),
263                                  StringPrintf("Failed to unregister resource overuse listener: %s",
264                                               result.error().message().c_str()));
265     }
266     return Status::ok();
267 }
268 
getResourceOveruseStats(const std::vector<ResourceType> & resourceTypes,std::vector<ResourceOveruseStats> * resourceOveruseStats)269 Status WatchdogBinderMediator::getResourceOveruseStats(
270         const std::vector<ResourceType>& resourceTypes,
271         std::vector<ResourceOveruseStats>* resourceOveruseStats) {
272     if (resourceOveruseStats == nullptr) {
273         return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
274                                  "Must provide a non-null resource overuse stats parcelable");
275     }
276     if (resourceTypes.size() != 1 || resourceTypes[0] != ResourceType::IO) {
277         return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
278                                  "Must provide exactly one I/O resource type");
279     }
280     IoOveruseStats ioOveruseStats;
281     if (const auto result = mIoOveruseMonitor->getIoOveruseStats(&ioOveruseStats); !result.ok()) {
282         return fromExceptionCode(result.error().code(),
283                                  StringPrintf("Failed to get resource overuse stats: %s",
284                                               result.error().message().c_str()));
285     }
286     ResourceOveruseStats stats;
287     stats.set<ResourceOveruseStats::ioOveruseStats>(std::move(ioOveruseStats));
288     resourceOveruseStats->emplace_back(std::move(stats));
289     return Status::ok();
290 }
291 
registerMediator(const sp<ICarWatchdogClient> &)292 Status WatchdogBinderMediator::registerMediator(const sp<ICarWatchdogClient>& /*mediator*/) {
293     return fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
294                              "Deprecated method registerMediator");
295 }
296 
unregisterMediator(const sp<ICarWatchdogClient> &)297 Status WatchdogBinderMediator::unregisterMediator(const sp<ICarWatchdogClient>& /*mediator*/) {
298     return fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
299                              "Deprecated method unregisterMediator");
300 }
301 
registerMonitor(const sp<ICarWatchdogMonitor> &)302 Status WatchdogBinderMediator::registerMonitor(const sp<ICarWatchdogMonitor>& /*monitor*/) {
303     return fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION, "Deprecated method registerMonitor");
304 }
305 
unregisterMonitor(const sp<ICarWatchdogMonitor> &)306 Status WatchdogBinderMediator::unregisterMonitor(const sp<ICarWatchdogMonitor>& /*monitor*/) {
307     return fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
308                              "Deprecated method unregisterMonitor");
309 }
310 
tellMediatorAlive(const sp<ICarWatchdogClient> &,const std::vector<int32_t> &,int32_t)311 Status WatchdogBinderMediator::tellMediatorAlive(
312         const sp<ICarWatchdogClient>& /*mediator*/,
313         const std::vector<int32_t>& /*clientsNotResponding*/, int32_t /*sessionId*/) {
314     return fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
315                              "Deprecated method tellMediatorAlive");
316 }
317 
tellDumpFinished(const sp<ICarWatchdogMonitor> &,int32_t)318 Status WatchdogBinderMediator::tellDumpFinished(const sp<ICarWatchdogMonitor>& /*monitor*/,
319                                                 int32_t /*pid*/) {
320     return fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
321                              "Deprecated method tellDumpFinished");
322 }
323 
notifySystemStateChange(StateType,int32_t,int32_t)324 Status WatchdogBinderMediator::notifySystemStateChange(StateType /*type*/, int32_t /*arg1*/,
325                                                        int32_t /*arg2*/) {
326     return fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
327                              "Deprecated method notifySystemStateChange");
328 }
329 
330 }  // namespace watchdog
331 }  // namespace automotive
332 }  // namespace android
333