1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "driver_load_manager.h"
17
18 #include "hisysevent_adapter.h"
19 #include "iam_check.h"
20 #include "iam_logger.h"
21
22 #include "idevmgr_hdi.h"
23 #include "iservice_registry.h"
24 #include "iservmgr_hdi.h"
25 #include "relative_timer.h"
26 #include "system_ability_definition.h"
27 #include "system_param_manager.h"
28
29 #define LOG_TAG "PIN_AUTH_SA"
30
31 namespace OHOS {
32 namespace UserIam {
33 namespace PinAuth {
34 using namespace HDI;
35 using namespace HDI::ServiceManager::V1_0;
36 using namespace HDI::DeviceManager::V1_0;
37 const char *SERVICE_NAME = "pin_auth_interface_service";
38 class DriverManagerStatusListener : public ServStatListenerStub {
39 public:
40 DriverManagerStatusListener() = default;
41 ~DriverManagerStatusListener() override = default;
42
OnReceive(const ServiceStatus & status)43 void OnReceive(const ServiceStatus &status) override
44 {
45 if (status.serviceName != SERVICE_NAME) {
46 return;
47 }
48
49 IAM_LOGI("receive service %{public}s status %{public}d", status.serviceName.c_str(), status.status);
50 if (status.status == SERVIE_STATUS_START) {
51 DriverLoadManager::GetInstance().OnServiceStart();
52 } else if (status.status == SERVIE_STATUS_STOP) {
53 DriverLoadManager::GetInstance().OnServiceStop();
54 }
55 }
56 };
57
GetInstance()58 DriverLoadManager &DriverLoadManager::GetInstance()
59 {
60 static DriverLoadManager instance;
61 return instance;
62 }
63
StartSubscribe()64 void DriverLoadManager::StartSubscribe()
65 {
66 std::lock_guard<std::recursive_mutex> lock(mutex_);
67 if (isSubscribed_) {
68 return;
69 }
70
71 if (driverManagerStatusListener_ == nullptr) {
72 driverManagerStatusListener_ = SystemAbilityListener::Subscribe(
73 "DriverLoadManager", DEVICE_SERVICE_MANAGER_SA_ID,
74 []() { DriverLoadManager::GetInstance().OnDriverManagerAdd(); }, nullptr);
75 IF_FALSE_LOGE_AND_RETURN(driverManagerStatusListener_ != nullptr);
76 }
77
78 if (driverStatusListener_ == nullptr) {
79 driverStatusListener_ = new (std::nothrow) DriverManagerStatusListener();
80 IF_FALSE_LOGE_AND_RETURN(driverStatusListener_ != nullptr);
81 }
82
83 SystemParamManager::GetInstance().WatchParam(STOP_SA_KEY, [](const std::string &value) {
84 IAM_LOGI("%{public}s changed, value %{public}s", STOP_SA_KEY, value.c_str());
85 DriverLoadManager::GetInstance().OnSaStopping(value == TRUE_STR);
86 });
87 OnSaStopping(SystemParamManager::GetInstance().GetParam(STOP_SA_KEY, FALSE_STR) == TRUE_STR);
88
89 IAM_LOGI("success");
90 isSubscribed_ = true;
91 }
92
OnTimeout()93 void DriverLoadManager::OnTimeout()
94 {
95 std::lock_guard<std::recursive_mutex> lock(mutex_);
96 IAM_LOGI("timeout");
97 timerId_ = std::nullopt;
98 ProcessServiceStatus();
99 }
100
OnDriverManagerAdd()101 void DriverLoadManager::OnDriverManagerAdd()
102 {
103 std::lock_guard<std::recursive_mutex> lock(mutex_);
104 IAM_LOGI("start");
105 IF_FALSE_LOGE_AND_RETURN(driverStatusListener_ != nullptr);
106
107 auto servMgr = IServiceManager::Get();
108 IF_FALSE_LOGE_AND_RETURN(servMgr != nullptr);
109
110 (void)servMgr->UnregisterServiceStatusListener(driverStatusListener_);
111 int32_t ret = servMgr->RegisterServiceStatusListener(driverStatusListener_, DEVICE_CLASS_USERAUTH);
112 IF_FALSE_LOGE_AND_RETURN(ret == 0);
113
114 auto service = servMgr->GetService(SERVICE_NAME);
115 isDriverRunning_ = (service != nullptr);
116 IAM_LOGI("service %{public}s running: %{public}d", SERVICE_NAME, isDriverRunning_);
117
118 ProcessServiceStatus();
119 IAM_LOGI("end");
120 }
121
OnServiceStart()122 void DriverLoadManager::OnServiceStart()
123 {
124 std::lock_guard<std::recursive_mutex> lock(mutex_);
125 IAM_LOGI("service start");
126 isDriverRunning_ = true;
127 ProcessServiceStatus();
128 }
129
OnServiceStop()130 void DriverLoadManager::OnServiceStop()
131 {
132 std::lock_guard<std::recursive_mutex> lock(mutex_);
133 IAM_LOGI("service stop");
134 isDriverRunning_ = false;
135 ProcessServiceStatus();
136 }
137
OnSaStopping(bool isStopping)138 void DriverLoadManager::OnSaStopping(bool isStopping)
139 {
140 std::lock_guard<std::recursive_mutex> lock(mutex_);
141 isSaStopping_ = isStopping;
142 ProcessServiceStatus();
143 }
144
LoadDriver()145 bool DriverLoadManager::LoadDriver()
146 {
147 auto devMgr = IDeviceManager::Get();
148 IF_FALSE_LOGE_AND_RETURN_VAL(devMgr != nullptr, false);
149
150 IAM_LOGI("load hdi service begin");
151 int32_t loadDriverRet = devMgr->LoadDevice(SERVICE_NAME);
152 if (loadDriverRet != 0) {
153 IAM_LOGE("load %{public}s service failed, ret:%{public}d", SERVICE_NAME, loadDriverRet);
154 SaLoadDriverFailureTrace saLoadDriverFailureTraceInfo = {};
155 saLoadDriverFailureTraceInfo.errCode = loadDriverRet;
156 UserIam::PinAuth::ReportSaLoadDriverFailure(saLoadDriverFailureTraceInfo);
157 return false;
158 }
159 return true;
160 }
161
UnloadDriver()162 bool DriverLoadManager::UnloadDriver()
163 {
164 auto devMgr = IDeviceManager::Get();
165 IF_FALSE_LOGE_AND_RETURN_VAL(devMgr != nullptr, false);
166
167 if (devMgr->UnloadDevice(SERVICE_NAME) != 0) {
168 IAM_LOGE("unload %{public}s service failed", SERVICE_NAME);
169 return false;
170 }
171 return true;
172 }
173
ProcessServiceStatus()174 void DriverLoadManager::ProcessServiceStatus()
175 {
176 const uint32_t RETRY_LOAD_INTERVAL = 1000; // 1s
177
178 std::lock_guard<std::recursive_mutex> lock(mutex_);
179 bool shouldRunning = !isSaStopping_;
180 IAM_LOGI("process service %{public}s status %{public}d, isSaStopping_ %{public}d", SERVICE_NAME, isDriverRunning_,
181 isSaStopping_);
182 if (isDriverRunning_ != shouldRunning) {
183 if (shouldRunning) {
184 bool loadDriverRet = LoadDriver();
185 if (loadDriverRet) {
186 IAM_LOGI("load service %{public}s success", SERVICE_NAME);
187 isDriverRunning_ = true;
188 }
189 } else {
190 bool unloadDriverRet = UnloadDriver();
191 if (unloadDriverRet) {
192 IAM_LOGI("unload service %{public}s success", SERVICE_NAME);
193 isDriverRunning_ = false;
194 }
195 }
196 }
197
198 if (isDriverRunning_ == shouldRunning) {
199 if (timerId_ != std::nullopt) {
200 RelativeTimer::GetInstance().Unregister(timerId_.value());
201 timerId_ = std::nullopt;
202 }
203 } else {
204 if (timerId_ == std::nullopt) {
205 timerId_ = RelativeTimer::GetInstance().Register([this]() { OnTimeout(); }, RETRY_LOAD_INTERVAL);
206 IAM_LOGI("process fail, retry after %{public}d ms", RETRY_LOAD_INTERVAL);
207 }
208 }
209 }
210 } // namespace PinAuth
211 } // namespace UserIam
212 } // namespace OHOS
213