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 "WatchdogInternalHandler.h"
20 
21 #include "WatchdogBinderMediator.h"
22 
23 #include <android/automotive/watchdog/internal/BootPhase.h>
24 #include <android/automotive/watchdog/internal/GarageMode.h>
25 #include <android/automotive/watchdog/internal/PowerCycle.h>
26 #include <android/automotive/watchdog/internal/UserState.h>
27 #include <binder/IPCThreadState.h>
28 #include <private/android_filesystem_config.h>
29 
30 namespace android {
31 namespace automotive {
32 namespace watchdog {
33 
34 namespace aawi = ::android::automotive::watchdog::internal;
35 
36 using aawi::ComponentType;
37 using aawi::GarageMode;
38 using aawi::ICarWatchdogServiceForSystem;
39 using aawi::PowerCycle;
40 using aawi::ResourceOveruseConfiguration;
41 using ::android::sp;
42 using ::android::String16;
43 using ::android::binder::Status;
44 
45 namespace {
46 
47 constexpr const char* kNullCarWatchdogServiceError =
48         "Must provide a non-null car watchdog service instance";
49 constexpr const char* kNullCarWatchdogMonitorError =
50         "Must provide a non-null car watchdog monitor instance";
51 
checkSystemUser()52 Status checkSystemUser() {
53     if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
54         return Status::fromExceptionCode(Status::EX_SECURITY,
55                                          "Calling process does not have proper privilege");
56     }
57     return Status::ok();
58 }
59 
fromExceptionCode(int32_t exceptionCode,std::string message)60 Status fromExceptionCode(int32_t exceptionCode, std::string message) {
61     ALOGW("%s", message.c_str());
62     return Status::fromExceptionCode(exceptionCode, message.c_str());
63 }
64 
65 }  // namespace
66 
dump(int fd,const Vector<String16> & args)67 status_t WatchdogInternalHandler::dump(int fd, const Vector<String16>& args) {
68     return mBinderMediator->dump(fd, args);
69 }
70 
checkAndRegisterIoOveruseMonitor()71 void WatchdogInternalHandler::checkAndRegisterIoOveruseMonitor() {
72     if (mIoOveruseMonitor->isInitialized()) {
73         return;
74     }
75     if (const auto result = mWatchdogPerfService->registerDataProcessor(mIoOveruseMonitor);
76         !result.ok()) {
77         ALOGE("Failed to register I/O overuse monitor to watchdog performance service: %s",
78               result.error().message().c_str());
79     }
80     return;
81 }
82 
registerCarWatchdogService(const sp<ICarWatchdogServiceForSystem> & service)83 Status WatchdogInternalHandler::registerCarWatchdogService(
84         const sp<ICarWatchdogServiceForSystem>& service) {
85     Status status = checkSystemUser();
86     if (!status.isOk()) {
87         return status;
88     }
89     if (service == nullptr) {
90         return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, kNullCarWatchdogServiceError);
91     }
92     /*
93      * I/O overuse monitor reads from system, vendor, and data partitions during initialization.
94      * When CarService is running these partitions are available to read, thus register the I/O
95      * overuse monitor on processing the request to register CarService.
96      */
97     checkAndRegisterIoOveruseMonitor();
98     return mWatchdogServiceHelper->registerService(service);
99 }
100 
unregisterCarWatchdogService(const sp<ICarWatchdogServiceForSystem> & service)101 Status WatchdogInternalHandler::unregisterCarWatchdogService(
102         const sp<ICarWatchdogServiceForSystem>& service) {
103     Status status = checkSystemUser();
104     if (!status.isOk()) {
105         return status;
106     }
107     if (service == nullptr) {
108         return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, kNullCarWatchdogServiceError);
109     }
110     return mWatchdogServiceHelper->unregisterService(service);
111 }
112 
registerMonitor(const sp<aawi::ICarWatchdogMonitor> & monitor)113 Status WatchdogInternalHandler::registerMonitor(const sp<aawi::ICarWatchdogMonitor>& monitor) {
114     Status status = checkSystemUser();
115     if (!status.isOk()) {
116         return status;
117     }
118     if (monitor == nullptr) {
119         return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, kNullCarWatchdogMonitorError);
120     }
121     return mWatchdogProcessService->registerMonitor(monitor);
122 }
123 
unregisterMonitor(const sp<aawi::ICarWatchdogMonitor> & monitor)124 Status WatchdogInternalHandler::unregisterMonitor(const sp<aawi::ICarWatchdogMonitor>& monitor) {
125     Status status = checkSystemUser();
126     if (!status.isOk()) {
127         return status;
128     }
129     if (monitor == nullptr) {
130         return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, kNullCarWatchdogMonitorError);
131     }
132     return mWatchdogProcessService->unregisterMonitor(monitor);
133 }
134 
tellCarWatchdogServiceAlive(const android::sp<ICarWatchdogServiceForSystem> & service,const std::vector<int32_t> & clientsNotResponding,int32_t sessionId)135 Status WatchdogInternalHandler::tellCarWatchdogServiceAlive(
136         const android::sp<ICarWatchdogServiceForSystem>& service,
137         const std::vector<int32_t>& clientsNotResponding, int32_t sessionId) {
138     Status status = checkSystemUser();
139     if (!status.isOk()) {
140         return status;
141     }
142     if (service == nullptr) {
143         return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, kNullCarWatchdogServiceError);
144     }
145     return mWatchdogProcessService->tellCarWatchdogServiceAlive(service, clientsNotResponding,
146                                                                 sessionId);
147 }
tellDumpFinished(const android::sp<aawi::ICarWatchdogMonitor> & monitor,int32_t pid)148 Status WatchdogInternalHandler::tellDumpFinished(
149         const android::sp<aawi::ICarWatchdogMonitor>& monitor, int32_t pid) {
150     Status status = checkSystemUser();
151     if (!status.isOk()) {
152         return status;
153     }
154     if (monitor == nullptr) {
155         return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, kNullCarWatchdogMonitorError);
156     }
157     return mWatchdogProcessService->tellDumpFinished(monitor, pid);
158 }
159 
notifySystemStateChange(aawi::StateType type,int32_t arg1,int32_t arg2)160 Status WatchdogInternalHandler::notifySystemStateChange(aawi::StateType type, int32_t arg1,
161                                                         int32_t arg2) {
162     Status status = checkSystemUser();
163     if (!status.isOk()) {
164         return status;
165     }
166     switch (type) {
167         case aawi::StateType::POWER_CYCLE: {
168             PowerCycle powerCycle = static_cast<PowerCycle>(static_cast<uint32_t>(arg1));
169             if (powerCycle >= PowerCycle::NUM_POWER_CYLES) {
170                 return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
171                                          StringPrintf("Invalid power cycle %d", powerCycle));
172             }
173             return handlePowerCycleChange(powerCycle);
174         }
175         case aawi::StateType::GARAGE_MODE: {
176             GarageMode garageMode = static_cast<GarageMode>(static_cast<uint32_t>(arg1));
177             mWatchdogPerfService->setSystemState(garageMode == GarageMode::GARAGE_MODE_OFF
178                                                          ? SystemState::NORMAL_MODE
179                                                          : SystemState::GARAGE_MODE);
180             return Status::ok();
181         }
182         case aawi::StateType::USER_STATE: {
183             userid_t userId = static_cast<userid_t>(arg1);
184             aawi::UserState userState = static_cast<aawi::UserState>(static_cast<uint32_t>(arg2));
185             if (userState >= aawi::UserState::NUM_USER_STATES) {
186                 return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
187                                          StringPrintf("Invalid user state %d", userState));
188             }
189             return handleUserStateChange(userId, userState);
190         }
191         case aawi::StateType::BOOT_PHASE: {
192             aawi::BootPhase phase = static_cast<aawi::BootPhase>(static_cast<uint32_t>(arg1));
193             if (phase >= aawi::BootPhase::BOOT_COMPLETED) {
194                 if (const auto result = mWatchdogPerfService->onBootFinished(); !result.ok()) {
195                     return fromExceptionCode(result.error().code(), result.error().message());
196                 }
197             }
198             return Status::ok();
199         }
200     }
201     return fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
202                              StringPrintf("Invalid state change type %d", type));
203 }
204 
handlePowerCycleChange(PowerCycle powerCycle)205 Status WatchdogInternalHandler::handlePowerCycleChange(PowerCycle powerCycle) {
206     switch (powerCycle) {
207         case PowerCycle::POWER_CYCLE_SHUTDOWN_PREPARE:
208             ALOGI("Received SHUTDOWN_PREPARE power cycle");
209             mWatchdogProcessService->setEnabled(/*isEnabled=*/false);
210             // TODO(b/189508862): Upload resource overuse stats on shutdown prepare.
211             break;
212         case PowerCycle::POWER_CYCLE_SHUTDOWN_ENTER:
213             ALOGI("Received SHUTDOWN_ENTER power cycle");
214             mWatchdogProcessService->setEnabled(/*isEnabled=*/false);
215             break;
216         case PowerCycle::POWER_CYCLE_RESUME:
217             ALOGI("Received RESUME power cycle");
218             mWatchdogProcessService->setEnabled(/*isEnabled=*/true);
219             break;
220         default:
221             ALOGW("Unsupported power cycle: %d", powerCycle);
222             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
223                                              "Unsupported power cycle");
224     }
225     return Status::ok();
226 }
227 
handleUserStateChange(userid_t userId,aawi::UserState userState)228 Status WatchdogInternalHandler::handleUserStateChange(userid_t userId, aawi::UserState userState) {
229     std::string stateDesc;
230     switch (userState) {
231         case aawi::UserState::USER_STATE_STARTED:
232             stateDesc = "started";
233             mWatchdogProcessService->notifyUserStateChange(userId, /*isStarted=*/true);
234             break;
235         case aawi::UserState::USER_STATE_STOPPED:
236             stateDesc = "stopped";
237             mWatchdogProcessService->notifyUserStateChange(userId, /*isStarted=*/false);
238             break;
239         case aawi::UserState::USER_STATE_REMOVED:
240             stateDesc = "removed";
241             mIoOveruseMonitor->removeStatsForUser(userId);
242             break;
243         default:
244             ALOGW("Unsupported user state: %d", userState);
245             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Unsupported user state");
246     }
247     ALOGI("Received user state change: user(%" PRId32 ") is %s", userId, stateDesc.c_str());
248     return Status::ok();
249 }
250 
updateResourceOveruseConfigurations(const std::vector<ResourceOveruseConfiguration> & configs)251 Status WatchdogInternalHandler::updateResourceOveruseConfigurations(
252         const std::vector<ResourceOveruseConfiguration>& configs) {
253     Status status = checkSystemUser();
254     if (!status.isOk()) {
255         return status;
256     }
257     // Maybe retry registring I/O overuse monitor if failed to initialize previously.
258     checkAndRegisterIoOveruseMonitor();
259     if (const auto result = mIoOveruseMonitor->updateResourceOveruseConfigurations(configs);
260         !result.ok()) {
261         return fromExceptionCode(result.error().code(), result.error().message());
262     }
263     return Status::ok();
264 }
265 
getResourceOveruseConfigurations(std::vector<ResourceOveruseConfiguration> * configs)266 Status WatchdogInternalHandler::getResourceOveruseConfigurations(
267         std::vector<ResourceOveruseConfiguration>* configs) {
268     Status status = checkSystemUser();
269     if (!status.isOk()) {
270         return status;
271     }
272     // Maybe retry registring I/O overuse monitor if failed to initialize previously.
273     checkAndRegisterIoOveruseMonitor();
274     if (const auto result = mIoOveruseMonitor->getResourceOveruseConfigurations(configs);
275         !result.ok()) {
276         return fromExceptionCode(result.error().code(), result.error().message());
277     }
278     return Status::ok();
279 }
280 
controlProcessHealthCheck(bool disable)281 Status WatchdogInternalHandler::controlProcessHealthCheck(bool disable) {
282     Status status = checkSystemUser();
283     if (!status.isOk()) {
284         return status;
285     }
286     mWatchdogProcessService->setEnabled(!disable);
287     return Status::ok();
288 }
289 
290 }  // namespace watchdog
291 }  // namespace automotive
292 }  // namespace android
293