• 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 #define DEBUG false  // STOPSHIP if true.
19 
20 #include "WatchdogProcessService.h"
21 
22 #include <android-base/chrono_utils.h>
23 #include <android-base/file.h>
24 #include <android-base/properties.h>
25 #include <android-base/stringprintf.h>
26 #include <binder/IPCThreadState.h>
27 
28 namespace android {
29 namespace automotive {
30 namespace watchdog {
31 
32 using std::literals::chrono_literals::operator""s;
33 using android::base::Error;
34 using android::base::GetProperty;
35 using android::base::Result;
36 using android::base::StringAppendF;
37 using android::base::StringPrintf;
38 using android::base::WriteStringToFd;
39 using android::binder::Status;
40 
41 namespace {
42 
43 const std::vector<TimeoutLength> kTimeouts = {TimeoutLength::TIMEOUT_CRITICAL,
44                                               TimeoutLength::TIMEOUT_MODERATE,
45                                               TimeoutLength::TIMEOUT_NORMAL};
46 
timeoutToDurationNs(const TimeoutLength & timeout)47 std::chrono::nanoseconds timeoutToDurationNs(const TimeoutLength& timeout) {
48     switch (timeout) {
49         case TimeoutLength::TIMEOUT_CRITICAL:
50             return 3s;  // 3s and no buffer time.
51         case TimeoutLength::TIMEOUT_MODERATE:
52             return 6s;  // 5s + 1s as buffer time.
53         case TimeoutLength::TIMEOUT_NORMAL:
54             return 12s;  // 10s + 2s as buffer time.
55     }
56 }
57 
pidArrayToString(const std::vector<int32_t> & pids)58 std::string pidArrayToString(const std::vector<int32_t>& pids) {
59     size_t size = pids.size();
60     if (size == 0) {
61         return "";
62     }
63     std::string buffer;
64     StringAppendF(&buffer, "%d", pids[0]);
65     for (int i = 1; i < size; i++) {
66         int pid = pids[i];
67         StringAppendF(&buffer, ", %d", pid);
68     }
69     return buffer;
70 }
71 
isSystemShuttingDown()72 bool isSystemShuttingDown() {
73     std::string sysPowerCtl;
74     std::istringstream tokenStream(GetProperty("sys.powerctl", ""));
75     std::getline(tokenStream, sysPowerCtl, ',');
76     return sysPowerCtl == "reboot" || sysPowerCtl == "shutdown";
77 }
78 
79 }  // namespace
80 
WatchdogProcessService(const sp<Looper> & handlerLooper)81 WatchdogProcessService::WatchdogProcessService(const sp<Looper>& handlerLooper) :
82       mHandlerLooper(handlerLooper), mLastSessionId(0) {
83     mMessageHandler = new MessageHandlerImpl(this);
84     mWatchdogEnabled = true;
85     for (const auto& timeout : kTimeouts) {
86         mClients.insert(std::make_pair(timeout, std::vector<ClientInfo>()));
87         mPingedClients.insert(std::make_pair(timeout, PingedClientMap()));
88     }
89 }
90 
registerClient(const sp<ICarWatchdogClient> & client,TimeoutLength timeout)91 Status WatchdogProcessService::registerClient(const sp<ICarWatchdogClient>& client,
92                                               TimeoutLength timeout) {
93     Mutex::Autolock lock(mMutex);
94     return registerClientLocked(client, timeout, ClientType::Regular);
95 }
96 
unregisterClient(const sp<ICarWatchdogClient> & client)97 Status WatchdogProcessService::unregisterClient(const sp<ICarWatchdogClient>& client) {
98     Mutex::Autolock lock(mMutex);
99     sp<IBinder> binder = BnCarWatchdog::asBinder(client);
100     // kTimeouts is declared as global static constant to cover all kinds of timeout (CRITICAL,
101     // MODERATE, NORMAL).
102     return unregisterClientLocked(kTimeouts, binder, ClientType::Regular);
103 }
104 
registerMediator(const sp<ICarWatchdogClient> & mediator)105 Status WatchdogProcessService::registerMediator(const sp<ICarWatchdogClient>& mediator) {
106     Mutex::Autolock lock(mMutex);
107     // Mediator's timeout is always TIMEOUT_CRITICAL.
108     return registerClientLocked(mediator, TimeoutLength::TIMEOUT_CRITICAL, ClientType::Mediator);
109 }
110 
unregisterMediator(const sp<ICarWatchdogClient> & mediator)111 Status WatchdogProcessService::unregisterMediator(const sp<ICarWatchdogClient>& mediator) {
112     std::vector<TimeoutLength> timeouts = {TimeoutLength::TIMEOUT_CRITICAL};
113     sp<IBinder> binder = BnCarWatchdog::asBinder(mediator);
114     Mutex::Autolock lock(mMutex);
115     return unregisterClientLocked(timeouts, binder, ClientType::Mediator);
116 }
117 
registerMonitor(const sp<ICarWatchdogMonitor> & monitor)118 Status WatchdogProcessService::registerMonitor(const sp<ICarWatchdogMonitor>& monitor) {
119     Mutex::Autolock lock(mMutex);
120     sp<IBinder> binder = BnCarWatchdog::asBinder(monitor);
121     if (mMonitor != nullptr && binder == BnCarWatchdog::asBinder(mMonitor)) {
122         return Status::ok();
123     }
124     status_t ret = binder->linkToDeath(this);
125     if (ret != OK) {
126         ALOGW("Cannot register the monitor. The monitor is dead.");
127         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "The monitor is dead.");
128     }
129     mMonitor = monitor;
130     if (DEBUG) {
131         ALOGD("Car watchdog monitor is registered");
132     }
133     return Status::ok();
134 }
135 
unregisterMonitor(const sp<ICarWatchdogMonitor> & monitor)136 Status WatchdogProcessService::unregisterMonitor(const sp<ICarWatchdogMonitor>& monitor) {
137     Mutex::Autolock lock(mMutex);
138     if (mMonitor != monitor) {
139         ALOGW("Cannot unregister the monitor. The monitor has not been registered.");
140         return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
141                                          "The monitor has not been registered.");
142     }
143     sp<IBinder> binder = BnCarWatchdog::asBinder(monitor);
144     binder->unlinkToDeath(this);
145     mMonitor = nullptr;
146     if (DEBUG) {
147         ALOGD("Car watchdog monitor is unregistered");
148     }
149     return Status::ok();
150 }
151 
tellClientAlive(const sp<ICarWatchdogClient> & client,int32_t sessionId)152 Status WatchdogProcessService::tellClientAlive(const sp<ICarWatchdogClient>& client,
153                                                int32_t sessionId) {
154     Mutex::Autolock lock(mMutex);
155     return tellClientAliveLocked(client, sessionId);
156 }
157 
tellMediatorAlive(const sp<ICarWatchdogClient> & mediator,const std::vector<int32_t> & clientsNotResponding,int32_t sessionId)158 Status WatchdogProcessService::tellMediatorAlive(const sp<ICarWatchdogClient>& mediator,
159                                                  const std::vector<int32_t>& clientsNotResponding,
160                                                  int32_t sessionId) {
161     Status status;
162     {
163         Mutex::Autolock lock(mMutex);
164         if (DEBUG) {
165             std::string buffer;
166             int size = clientsNotResponding.size();
167             if (size != 0) {
168                 StringAppendF(&buffer, "%d", clientsNotResponding[0]);
169                 for (int i = 1; i < clientsNotResponding.size(); i++) {
170                     StringAppendF(&buffer, ", %d", clientsNotResponding[i]);
171                 }
172                 ALOGD("Mediator(session: %d) responded with non-responding clients: %s", sessionId,
173                       buffer.c_str());
174             }
175         }
176         status = tellClientAliveLocked(mediator, sessionId);
177     }
178     if (status.isOk()) {
179         dumpAndKillAllProcesses(clientsNotResponding);
180     }
181     return status;
182 }
183 
tellDumpFinished(const sp<ICarWatchdogMonitor> & monitor,int32_t pid)184 Status WatchdogProcessService::tellDumpFinished(const sp<ICarWatchdogMonitor>& monitor,
185                                                 int32_t pid) {
186     Mutex::Autolock lock(mMutex);
187     if (mMonitor == nullptr || monitor == nullptr ||
188         BnCarWatchdog::asBinder(monitor) != BnCarWatchdog::asBinder(mMonitor)) {
189         return Status::
190                 fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
191                                   "The monitor is not registered or an invalid monitor is given");
192     }
193     ALOGI("Process(pid: %d) has been dumped and killed", pid);
194     return Status::ok();
195 }
196 
notifyPowerCycleChange(PowerCycle cycle)197 Status WatchdogProcessService::notifyPowerCycleChange(PowerCycle cycle) {
198     std::string buffer;
199     Mutex::Autolock lock(mMutex);
200     bool oldStatus = mWatchdogEnabled;
201     switch (cycle) {
202         case PowerCycle::POWER_CYCLE_SHUTDOWN:
203             mWatchdogEnabled = false;
204             buffer = "SHUTDOWN power cycle";
205             break;
206         case PowerCycle::POWER_CYCLE_SUSPEND:
207             mWatchdogEnabled = false;
208             buffer = "SUSPEND power cycle";
209             break;
210         case PowerCycle::POWER_CYCLE_RESUME:
211             mWatchdogEnabled = true;
212             for (const auto& timeout : kTimeouts) {
213                 startHealthCheckingLocked(timeout);
214             }
215             buffer = "RESUME power cycle";
216             break;
217         default:
218             ALOGW("Unsupported power cycle: %d", cycle);
219             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
220                                              "Unsupported power cycle");
221     }
222     ALOGI("Received %s", buffer.c_str());
223     if (oldStatus != mWatchdogEnabled) {
224         ALOGI("Car watchdog is %s", mWatchdogEnabled ? "enabled" : "disabled");
225     }
226     return Status::ok();
227 }
228 
notifyUserStateChange(userid_t userId,UserState state)229 Status WatchdogProcessService::notifyUserStateChange(userid_t userId, UserState state) {
230     std::string buffer;
231     Mutex::Autolock lock(mMutex);
232     switch (state) {
233         case UserState::USER_STATE_STARTED:
234             mStoppedUserId.erase(userId);
235             buffer = StringPrintf("user(%d) is started", userId);
236             break;
237         case UserState::USER_STATE_STOPPED:
238             mStoppedUserId.insert(userId);
239             buffer = StringPrintf("user(%d) is stopped", userId);
240             break;
241         default:
242             ALOGW("Unsupported user state: %d", state);
243             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Unsupported user state");
244     }
245     ALOGI("Received user state change: %s", buffer.c_str());
246     return Status::ok();
247 }
248 
dump(int fd,const Vector<String16> &)249 Result<void> WatchdogProcessService::dump(int fd, const Vector<String16>& /*args*/) {
250     Mutex::Autolock lock(mMutex);
251     const char* indent = "  ";
252     const char* doubleIndent = "    ";
253     std::string buffer;
254     WriteStringToFd("CAR WATCHDOG PROCESS SERVICE\n", fd);
255     WriteStringToFd(StringPrintf("%sWatchdog enabled: %s\n", indent,
256                                  mWatchdogEnabled ? "true" : "false"),
257                     fd);
258     WriteStringToFd(StringPrintf("%sRegistered clients\n", indent), fd);
259     int count = 1;
260     for (const auto& timeout : kTimeouts) {
261         std::vector<ClientInfo>& clients = mClients[timeout];
262         for (auto it = clients.begin(); it != clients.end(); it++, count++) {
263             WriteStringToFd(StringPrintf("%sClient #%d: %s\n", doubleIndent, count,
264                                          it->toString().c_str()),
265                             fd);
266         }
267     }
268     WriteStringToFd(StringPrintf("%sMonitor registered: %s\n", indent,
269                                  mMonitor == nullptr ? "false" : "true"),
270                     fd);
271     WriteStringToFd(StringPrintf("%sisSystemShuttingDown: %s\n", indent,
272                                  isSystemShuttingDown() ? "true" : "false"),
273                     fd);
274     buffer = "none";
275     bool first = true;
276     for (const auto& userId : mStoppedUserId) {
277         if (first) {
278             buffer = StringPrintf("%d", userId);
279             first = false;
280         } else {
281             StringAppendF(&buffer, ", %d", userId);
282         }
283     }
284     WriteStringToFd(StringPrintf("%sStopped users: %s\n", indent, buffer.c_str()), fd);
285     return {};
286 }
287 
doHealthCheck(int what)288 void WatchdogProcessService::doHealthCheck(int what) {
289     mHandlerLooper->removeMessages(mMessageHandler, what);
290     if (!isWatchdogEnabled()) {
291         return;
292     }
293     const TimeoutLength timeout = static_cast<TimeoutLength>(what);
294     dumpAndKillClientsIfNotResponding(timeout);
295 
296     /* Generates a temporary/local vector containing clients.
297      * Using a local copy may send unnecessary ping messages to clients after they are unregistered.
298      * Clients should be able to handle them.
299      */
300     std::vector<ClientInfo> clientsToCheck;
301     PingedClientMap& pingedClients = mPingedClients[timeout];
302     {
303         Mutex::Autolock lock(mMutex);
304         pingedClients.clear();
305         clientsToCheck = mClients[timeout];
306         for (auto& clientInfo : clientsToCheck) {
307             if (mStoppedUserId.count(clientInfo.userId) > 0) {
308                 continue;
309             }
310             int sessionId = getNewSessionId();
311             clientInfo.sessionId = sessionId;
312             pingedClients.insert(std::make_pair(sessionId, clientInfo));
313         }
314     }
315 
316     for (const auto& clientInfo : clientsToCheck) {
317         Status status = clientInfo.client->checkIfAlive(clientInfo.sessionId, timeout);
318         if (!status.isOk()) {
319             ALOGW("Sending a ping message to client(pid: %d) failed: %s", clientInfo.pid,
320                   status.exceptionMessage().c_str());
321             {
322                 Mutex::Autolock lock(mMutex);
323                 pingedClients.erase(clientInfo.sessionId);
324             }
325         }
326     }
327     // Though the size of pingedClients is a more specific measure, clientsToCheck is used as a
328     // conservative approach.
329     if (clientsToCheck.size() > 0) {
330         auto durationNs = timeoutToDurationNs(timeout);
331         mHandlerLooper->sendMessageDelayed(durationNs.count(), mMessageHandler, Message(what));
332     }
333 }
334 
terminate()335 void WatchdogProcessService::terminate() {
336     Mutex::Autolock lock(mMutex);
337     for (const auto& timeout : kTimeouts) {
338         std::vector<ClientInfo>& clients = mClients[timeout];
339         for (auto it = clients.begin(); it != clients.end();) {
340             sp<IBinder> binder = BnCarWatchdog::asBinder((*it).client);
341             binder->unlinkToDeath(this);
342             it = clients.erase(it);
343         }
344     }
345 }
346 
binderDied(const wp<IBinder> & who)347 void WatchdogProcessService::binderDied(const wp<IBinder>& who) {
348     Mutex::Autolock lock(mMutex);
349     IBinder* binder = who.unsafe_get();
350     // Check if dead binder is monitor.
351     sp<IBinder> monitor = BnCarWatchdog::asBinder(mMonitor);
352     if (monitor == binder) {
353         mMonitor = nullptr;
354         ALOGW("The monitor has died.");
355         return;
356     }
357     findClientAndProcessLocked(kTimeouts, binder,
358                                [&](std::vector<ClientInfo>& clients,
359                                    std::vector<ClientInfo>::const_iterator it) {
360                                    ALOGW("Client(pid: %d) died", it->pid);
361                                    clients.erase(it);
362                                });
363 }
364 
isRegisteredLocked(const sp<ICarWatchdogClient> & client)365 bool WatchdogProcessService::isRegisteredLocked(const sp<ICarWatchdogClient>& client) {
366     sp<IBinder> binder = BnCarWatchdog::asBinder(client);
367     return findClientAndProcessLocked(kTimeouts, binder, nullptr);
368 }
369 
registerClientLocked(const sp<ICarWatchdogClient> & client,TimeoutLength timeout,ClientType clientType)370 Status WatchdogProcessService::registerClientLocked(const sp<ICarWatchdogClient>& client,
371                                                     TimeoutLength timeout, ClientType clientType) {
372     const char* clientName = clientType == ClientType::Regular ? "client" : "mediator";
373     if (isRegisteredLocked(client)) {
374         ALOGW("Cannot register the %s: the %s is already registered.", clientName, clientName);
375         return Status::ok();
376     }
377     sp<IBinder> binder = BnCarWatchdog::asBinder(client);
378     status_t status = binder->linkToDeath(this);
379     if (status != OK) {
380         std::string errorStr = StringPrintf("The %s is dead", clientName);
381         const char* errorCause = errorStr.c_str();
382         ALOGW("Cannot register the %s: %s", clientName, errorCause);
383         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, errorCause);
384     }
385     std::vector<ClientInfo>& clients = mClients[timeout];
386     pid_t callingPid = IPCThreadState::self()->getCallingPid();
387     uid_t callingUid = IPCThreadState::self()->getCallingUid();
388     clients.push_back(ClientInfo(client, callingPid, callingUid, clientType));
389 
390     // If the client array becomes non-empty, start health checking.
391     if (clients.size() == 1) {
392         startHealthCheckingLocked(timeout);
393     }
394     if (DEBUG) {
395         ALOGD("Car watchdog %s(pid: %d, timeout: %d) is registered", clientName, callingPid,
396               timeout);
397     }
398     return Status::ok();
399 }
400 
unregisterClientLocked(const std::vector<TimeoutLength> & timeouts,sp<IBinder> binder,ClientType clientType)401 Status WatchdogProcessService::unregisterClientLocked(const std::vector<TimeoutLength>& timeouts,
402                                                       sp<IBinder> binder, ClientType clientType) {
403     const char* clientName = clientType == ClientType::Regular ? "client" : "mediator";
404     bool result = findClientAndProcessLocked(timeouts, binder,
405                                              [&](std::vector<ClientInfo>& clients,
406                                                  std::vector<ClientInfo>::const_iterator it) {
407                                                  binder->unlinkToDeath(this);
408                                                  clients.erase(it);
409                                              });
410     if (!result) {
411         std::string errorStr = StringPrintf("The %s has not been registered", clientName);
412         const char* errorCause = errorStr.c_str();
413         ALOGW("Cannot unregister the %s: %s", clientName, errorCause);
414         return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, errorCause);
415     }
416     if (DEBUG) {
417         ALOGD("Car watchdog %s is unregistered", clientName);
418     }
419     return Status::ok();
420 }
421 
tellClientAliveLocked(const sp<ICarWatchdogClient> & client,int32_t sessionId)422 Status WatchdogProcessService::tellClientAliveLocked(const sp<ICarWatchdogClient>& client,
423                                                      int32_t sessionId) {
424     const sp<IBinder> binder = BnCarWatchdog::asBinder(client);
425     for (const auto& timeout : kTimeouts) {
426         PingedClientMap& clients = mPingedClients[timeout];
427         PingedClientMap::const_iterator it = clients.find(sessionId);
428         if (it == clients.cend() || binder != BnCarWatchdog::asBinder(it->second.client)) {
429             continue;
430         }
431         clients.erase(it);
432         return Status::ok();
433     }
434     return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
435                                      "The client is not registered or the session ID is not found");
436 }
437 
findClientAndProcessLocked(const std::vector<TimeoutLength> timeouts,const sp<IBinder> binder,const Processor & processor)438 bool WatchdogProcessService::findClientAndProcessLocked(const std::vector<TimeoutLength> timeouts,
439                                                         const sp<IBinder> binder,
440                                                         const Processor& processor) {
441     for (const auto& timeout : timeouts) {
442         std::vector<ClientInfo>& clients = mClients[timeout];
443         for (auto it = clients.begin(); it != clients.end(); it++) {
444             if (BnCarWatchdog::asBinder((*it).client) != binder) {
445                 continue;
446             }
447             if (processor != nullptr) {
448                 processor(clients, it);
449             }
450             return true;
451         }
452     }
453     return false;
454 }
455 
startHealthCheckingLocked(TimeoutLength timeout)456 Result<void> WatchdogProcessService::startHealthCheckingLocked(TimeoutLength timeout) {
457     PingedClientMap& clients = mPingedClients[timeout];
458     clients.clear();
459     int what = static_cast<int>(timeout);
460     auto durationNs = timeoutToDurationNs(timeout);
461     mHandlerLooper->sendMessageDelayed(durationNs.count(), mMessageHandler, Message(what));
462     return {};
463 }
464 
dumpAndKillClientsIfNotResponding(TimeoutLength timeout)465 Result<void> WatchdogProcessService::dumpAndKillClientsIfNotResponding(TimeoutLength timeout) {
466     std::vector<int32_t> processIds;
467     std::vector<sp<ICarWatchdogClient>> clientsToNotify;
468     {
469         Mutex::Autolock lock(mMutex);
470         PingedClientMap& clients = mPingedClients[timeout];
471         for (PingedClientMap::const_iterator it = clients.cbegin(); it != clients.cend(); it++) {
472             pid_t pid = -1;
473             userid_t userId = -1;
474             sp<ICarWatchdogClient> client = it->second.client;
475             sp<IBinder> binder = BnCarWatchdog::asBinder(client);
476             std::vector<TimeoutLength> timeouts = {timeout};
477             findClientAndProcessLocked(timeouts, binder,
478                                        [&](std::vector<ClientInfo>& clients,
479                                            std::vector<ClientInfo>::const_iterator it) {
480                                            pid = (*it).pid;
481                                            userId = (*it).userId;
482                                            clients.erase(it);
483                                        });
484             if (pid != -1 && mStoppedUserId.count(userId) == 0) {
485                 clientsToNotify.push_back(client);
486                 processIds.push_back(pid);
487             }
488         }
489     }
490     for (auto&& client : clientsToNotify) {
491         client->prepareProcessTermination();
492     }
493     return dumpAndKillAllProcesses(processIds);
494 }
495 
dumpAndKillAllProcesses(const std::vector<int32_t> & processesNotResponding)496 Result<void> WatchdogProcessService::dumpAndKillAllProcesses(
497         const std::vector<int32_t>& processesNotResponding) {
498     size_t size = processesNotResponding.size();
499     if (size == 0) {
500         return {};
501     }
502     std::string pidString = pidArrayToString(processesNotResponding);
503     sp<ICarWatchdogMonitor> monitor;
504     {
505         Mutex::Autolock lock(mMutex);
506         if (mMonitor == nullptr) {
507             std::string errorMsg =
508                     StringPrintf("Cannot dump and kill processes(pid = %s): Monitor is not set",
509                                  pidString.c_str());
510             ALOGW("%s", errorMsg.c_str());
511             return Error() << errorMsg;
512         }
513         monitor = mMonitor;
514     }
515     if (isSystemShuttingDown()) {
516         ALOGI("Skip dumping and killing processes(%s): The system is shutting down",
517               pidString.c_str());
518         return {};
519     }
520     monitor->onClientsNotResponding(processesNotResponding);
521     if (DEBUG) {
522         ALOGD("Dumping and killing processes is requested: %s", pidString.c_str());
523     }
524     return {};
525 }
526 
getNewSessionId()527 int32_t WatchdogProcessService::getNewSessionId() {
528     // Make sure that session id is always positive number.
529     if (++mLastSessionId <= 0) {
530         mLastSessionId = 1;
531     }
532     return mLastSessionId;
533 }
534 
isWatchdogEnabled()535 bool WatchdogProcessService::isWatchdogEnabled() {
536     Mutex::Autolock lock(mMutex);
537     return mWatchdogEnabled;
538 }
539 
toString()540 std::string WatchdogProcessService::ClientInfo::toString() {
541     std::string buffer;
542     StringAppendF(&buffer, "pid = %d, userId = %d, type = %s", pid, userId,
543                   type == Regular ? "Regular" : "Mediator");
544     return buffer;
545 }
546 
MessageHandlerImpl(const sp<WatchdogProcessService> & service)547 WatchdogProcessService::MessageHandlerImpl::MessageHandlerImpl(
548         const sp<WatchdogProcessService>& service) :
549       mService(service) {}
550 
handleMessage(const Message & message)551 void WatchdogProcessService::MessageHandlerImpl::handleMessage(const Message& message) {
552     switch (message.what) {
553         case static_cast<int>(TimeoutLength::TIMEOUT_CRITICAL):
554         case static_cast<int>(TimeoutLength::TIMEOUT_MODERATE):
555         case static_cast<int>(TimeoutLength::TIMEOUT_NORMAL):
556             mService->doHealthCheck(message.what);
557             break;
558         default:
559             ALOGW("Unknown message: %d", message.what);
560     }
561 }
562 
563 }  // namespace watchdog
564 }  // namespace automotive
565 }  // namespace android
566