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     sp<PackageInfoResolverInterface> packageInfoResolver = PackageInfoResolver::getInstance();
50     if (auto result = startWatchdogProcessService(mainLooper); !result.ok()) {
51         return result;
52     }
53     mWatchdogServiceHelper = sp<WatchdogServiceHelper>::make();
54     if (auto result = mWatchdogServiceHelper->init(mWatchdogProcessService); !result.ok()) {
55         return Error() << "Failed to initialize watchdog service helper: " << result.error();
56     }
57     if (car_watchdog_memory_profiling()) {
58         if (auto result = startPressureMonitor(); !result.ok()) {
59             ALOGE("%s", result.error().message().c_str());
60         }
61     }
62     if (auto result = startWatchdogPerfService(mWatchdogServiceHelper); !result.ok()) {
63         return result;
64     }
65     if (auto result = packageInfoResolver->initWatchdogServiceHelper(mWatchdogServiceHelper);
66         !result.ok()) {
67         return Error() << "Failed to initialize package name resolver: " << result.error();
68     }
69     mIoOveruseMonitor = sp<IoOveruseMonitor>::make(mWatchdogServiceHelper);
70     mWatchdogBinderMediator =
71             SharedRefBase::make<WatchdogBinderMediator>(mWatchdogProcessService,
72                                                         mWatchdogPerfService,
73                                                         mWatchdogServiceHelper, mIoOveruseMonitor);
74     if (auto result = mWatchdogBinderMediator->init(); !result.ok()) {
75         return Error(result.error().code())
76                 << "Failed to initialize watchdog binder mediator: " << result.error();
77     }
78     return {};
79 }
80 
terminateServices()81 void ServiceManager::terminateServices() {
82     if (mWatchdogProcessService != nullptr) {
83         mWatchdogProcessService->terminate();
84         mWatchdogProcessService.clear();
85     }
86     if (mWatchdogPerfService != nullptr) {
87         mWatchdogPerfService->terminate();
88         mWatchdogPerfService.clear();
89     }
90     if (mWatchdogBinderMediator != nullptr) {
91         mWatchdogBinderMediator->terminate();
92         mWatchdogBinderMediator.reset();
93     }
94     if (mWatchdogServiceHelper != nullptr) {
95         mWatchdogServiceHelper->terminate();
96         mWatchdogServiceHelper.clear();
97     }
98     if (mPressureMonitor != nullptr) {
99         mPressureMonitor->terminate();
100         mPressureMonitor.clear();
101     }
102     mIoOveruseMonitor.clear();
103     PackageInfoResolver::terminate();
104 }
105 
startWatchdogProcessService(const sp<Looper> & mainLooper)106 Result<void> ServiceManager::startWatchdogProcessService(const sp<Looper>& mainLooper) {
107     mWatchdogProcessService = sp<WatchdogProcessService>::make(mainLooper);
108     if (auto result = mWatchdogProcessService->start(); !result.ok()) {
109         return Error(result.error().code())
110                 << "Failed to start watchdog process monitoring service: " << result.error();
111     }
112     return {};
113 }
114 
startPressureMonitor()115 Result<void> ServiceManager::startPressureMonitor() {
116     mPressureMonitor = sp<PressureMonitor>::make();
117     if (auto result = mPressureMonitor->init(); !result.ok()) {
118         return Error() << "Failed to initialize pressure monitor: " << result.error();
119     }
120     if (auto result = mPressureMonitor->start(); !result.ok()) {
121         return Error() << "Failed to start pressure monitor: " << result.error();
122     }
123     return {};
124 }
125 
startWatchdogPerfService(const sp<WatchdogServiceHelperInterface> & watchdogServiceHelper)126 Result<void> ServiceManager::startWatchdogPerfService(
127         const sp<WatchdogServiceHelperInterface>& watchdogServiceHelper) {
128     mWatchdogPerfService = sp<WatchdogPerfService>::make(watchdogServiceHelper, elapsedRealtime);
129     if (auto result = mWatchdogPerfService->registerDataProcessor(
130                 sp<PerformanceProfiler>::make(mPressureMonitor));
131         !result.ok()) {
132         return Error() << "Failed to register performance profiler: " << result.error();
133     }
134     if (auto result = mWatchdogPerfService->start(); !result.ok()) {
135         return Error(result.error().code())
136                 << "Failed to start watchdog performance service: " << result.error();
137     }
138     return {};
139 }
140 
141 }  // namespace watchdog
142 }  // namespace automotive
143 }  // namespace android
144