• 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 "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