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