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