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 "ServiceManager.h"
20 
21 #include "PackageInfoResolver.h"
22 #include "PerformanceProfiler.h"
23 
24 #include <android/binder_interface_utils.h>
25 #include <log/log.h>
26 #include <utils/SystemClock.h>
27 
28 namespace android {
29 namespace automotive {
30 namespace watchdog {
31 
32 using ::android::sp;
33 using ::android::base::Error;
34 using ::android::base::Result;
35 using ::android::car::feature::car_watchdog_memory_profiling;
36 using ::ndk::SharedRefBase;
37 
startServices(const sp<Looper> & mainLooper)38 Result<void> ServiceManager::startServices(const sp<Looper>& mainLooper) {
39     if (mWatchdogBinderMediator != nullptr || mWatchdogServiceHelper != nullptr ||
40         mWatchdogProcessService != nullptr || mWatchdogPerfService != nullptr) {
41         return Error(INVALID_OPERATION) << "Cannot start services more than once";
42     }
43     /*
44      * PackageInfoResolver must be initialized first on the main thread before starting any other
45      * thread because the PackageInfoResolver::getInstance method isn't thread safe. Thus initialize
46      * PackageInfoResolver by calling the PackageInfoResolver::getInstance method before starting
47      * other services as they may access PackageInfoResolver's instance during initialization.
48      */
49     std::shared_ptr<PackageInfoResolverInterface> packageInfoResolver =
50         PackageInfoResolver::getInstance();
51     if (auto result = startWatchdogProcessService(mainLooper); !result.ok()) {
52         return result;
53     }
54     mWatchdogServiceHelper = sp<WatchdogServiceHelper>::make();
55     if (auto result = mWatchdogServiceHelper->init(mWatchdogProcessService); !result.ok()) {
56         return Error() << "Failed to initialize watchdog service helper: " << result.error();
57     }
58     if (car_watchdog_memory_profiling()) {
59         if (auto result = startPressureMonitor(); !result.ok()) {
60             ALOGE("%s", result.error().message().c_str());
61         }
62     }
63     if (auto result = startWatchdogPerfService(mWatchdogServiceHelper); !result.ok()) {
64         return result;
65     }
66     if (auto result = packageInfoResolver->initWatchdogServiceHelper(mWatchdogServiceHelper);
67         !result.ok()) {
68         return Error() << "Failed to initialize package name resolver: " << result.error();
69     }
70     mIoOveruseMonitor = sp<IoOveruseMonitor>::make(mWatchdogServiceHelper);
71     mWatchdogBinderMediator =
72             SharedRefBase::make<WatchdogBinderMediator>(mWatchdogProcessService,
73                                                         mWatchdogPerfService,
74                                                         mWatchdogServiceHelper, mIoOveruseMonitor);
75     if (auto result = mWatchdogBinderMediator->init(); !result.ok()) {
76         return Error(result.error().code())
77                 << "Failed to initialize watchdog binder mediator: " << result.error();
78     }
79     return {};
80 }
81 
terminateServices()82 void ServiceManager::terminateServices() {
83     if (mWatchdogProcessService != nullptr) {
84         mWatchdogProcessService->terminate();
85         mWatchdogProcessService.clear();
86     }
87     if (mWatchdogPerfService != nullptr) {
88         mWatchdogPerfService->terminate();
89         mWatchdogPerfService.clear();
90     }
91     if (mWatchdogBinderMediator != nullptr) {
92         mWatchdogBinderMediator->terminate();
93         mWatchdogBinderMediator.reset();
94     }
95     if (mWatchdogServiceHelper != nullptr) {
96         mWatchdogServiceHelper->terminate();
97         mWatchdogServiceHelper.clear();
98     }
99     if (mPressureMonitor != nullptr) {
100         mPressureMonitor->terminate();
101         mPressureMonitor.clear();
102     }
103     mIoOveruseMonitor.clear();
104     PackageInfoResolver::terminate();
105 }
106 
startWatchdogProcessService(const sp<Looper> & mainLooper)107 Result<void> ServiceManager::startWatchdogProcessService(const sp<Looper>& mainLooper) {
108     mWatchdogProcessService = sp<WatchdogProcessService>::make(mainLooper);
109     if (auto result = mWatchdogProcessService->start(); !result.ok()) {
110         return Error(result.error().code())
111                 << "Failed to start watchdog process monitoring service: " << result.error();
112     }
113     return {};
114 }
115 
startPressureMonitor()116 Result<void> ServiceManager::startPressureMonitor() {
117     mPressureMonitor = sp<PressureMonitor>::make();
118     if (auto result = mPressureMonitor->init(); !result.ok()) {
119         return Error() << "Failed to initialize pressure monitor: " << result.error();
120     }
121     if (auto result = mPressureMonitor->start(); !result.ok()) {
122         return Error() << "Failed to start pressure monitor: " << result.error();
123     }
124     return {};
125 }
126 
startWatchdogPerfService(const sp<WatchdogServiceHelperInterface> & watchdogServiceHelper)127 Result<void> ServiceManager::startWatchdogPerfService(
128         const sp<WatchdogServiceHelperInterface>& watchdogServiceHelper) {
129     mWatchdogPerfService = sp<WatchdogPerfService>::make(watchdogServiceHelper, elapsedRealtime);
130     if (auto result = mWatchdogPerfService->registerDataProcessor(
131                 sp<PerformanceProfiler>::make(mPressureMonitor));
132         !result.ok()) {
133         return Error() << "Failed to register performance profiler: " << result.error();
134     }
135     if (auto result = mWatchdogPerfService->start(); !result.ok()) {
136         return Error(result.error().code())
137                 << "Failed to start watchdog performance service: " << result.error();
138     }
139     return {};
140 }
141 
142 }  // namespace watchdog
143 }  // namespace automotive
144 }  // namespace android
145