1 /*
2 * Copyright (c) 2021 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 #include "device_info_kits.h"
16
17 #include "beget_ext.h"
18 #include "device_info_proxy.h"
19 #include "device_info_load.h"
20 #include "idevice_info.h"
21 #include "if_system_ability_manager.h"
22 #include "iservice_registry.h"
23 #include "system_ability_definition.h"
24 #include "securec.h"
25 #include "sysparam_errno.h"
26
27 namespace OHOS {
28 namespace device_info {
29
30 static const int DEVINFO_SAID = 3902;
31 static const int DEVICEINFO_LOAD_SA_TIMEOUT_MS = 5000;
32 static const int NOT_FOUND_SERVICE_ERROR_NUMBER = 29189;
33
DeviceInfoKits()34 DeviceInfoKits::DeviceInfoKits() {}
35
~DeviceInfoKits()36 DeviceInfoKits::~DeviceInfoKits() {}
37
GetInstance()38 DeviceInfoKits &DeviceInfoKits::GetInstance()
39 {
40 return DelayedRefSingleton<DeviceInfoKits>::GetInstance();
41 }
42
LoadDeviceInfoSa(std::unique_lock<std::mutex> & lock)43 void DeviceInfoKits::LoadDeviceInfoSa(std::unique_lock<std::mutex> &lock)
44 {
45 DINFO_LOGV("deviceInfoService_ is %d", deviceInfoService_ == nullptr);
46 if (deviceInfoService_ != nullptr) {
47 return;
48 }
49 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
50 DINFO_CHECK(sam != nullptr, return, "GetSystemAbilityManager return null");
51
52 auto remoteObject = sam->CheckSystemAbility(DEVINFO_SAID);
53 if (remoteObject) {
54 DINFO_LOGV("deviceinfo sa is already loaded");
55 deviceInfoService_ = iface_cast<IDeviceInfo>(remoteObject);
56 return;
57 }
58 sptr<DeviceInfoLoad> deviceInfoLoad = new (std::nothrow) DeviceInfoLoad();
59 DINFO_CHECK(deviceInfoLoad != nullptr, return, "new deviceInfoLoad fail.");
60
61 int32_t ret = sam->LoadSystemAbility(SYSPARAM_DEVICE_SERVICE_ID, deviceInfoLoad);
62 DINFO_CHECK(ret == ERR_OK, return, "LoadSystemAbility deviceinfo sa failed");
63
64 if (deathRecipient_ == nullptr) {
65 deathRecipient_ = new DeathRecipient();
66 }
67
68 // wait_for release lock and block until time out(60s) or match the condition with notice
69 auto waitStatus = deviceInfoLoadCon_.wait_for(lock, std::chrono::milliseconds(DEVICEINFO_LOAD_SA_TIMEOUT_MS),
70 [this]() { return deviceInfoService_ != nullptr; });
71 if (!waitStatus || deviceInfoService_ == nullptr) {
72 // time out or loadcallback fail
73 DINFO_LOGE("tokensync load sa timeout");
74 return;
75 }
76
77 // for dead
78 auto object = deviceInfoService_->AsObject();
79 if ((object->IsProxyObject()) && (!object->AddDeathRecipient(deathRecipient_))) {
80 DINFO_LOGE("Failed to add death recipient");
81 }
82 }
83
GetService(std::unique_lock<std::mutex> & lock)84 sptr<IDeviceInfo> DeviceInfoKits::GetService(std::unique_lock<std::mutex> &lock)
85 {
86 LoadDeviceInfoSa(lock);
87 return deviceInfoService_;
88 }
89
FinishStartSASuccess(const sptr<IRemoteObject> & remoteObject)90 void DeviceInfoKits::FinishStartSASuccess(const sptr<IRemoteObject> &remoteObject)
91 {
92 DINFO_LOGI("get deviceinfo sa success.");
93 // get lock which wait_for release and send a notice so that wait_for can out of block
94 std::unique_lock<std::mutex> lock(lock_);
95 deviceInfoService_ = iface_cast<IDeviceInfo>(remoteObject);
96 deviceInfoLoadCon_.notify_one();
97 }
98
FinishStartSAFailed()99 void DeviceInfoKits::FinishStartSAFailed()
100 {
101 DINFO_LOGI("Get deviceinfo sa failed.");
102 // get lock which wait_for release and send a notice
103 std::unique_lock<std::mutex> lock(lock_);
104 deviceInfoService_ = nullptr;
105 deviceInfoLoadCon_.notify_one();
106 }
107
RetryGetService(std::unique_lock<std::mutex> & lock)108 sptr<IDeviceInfo> DeviceInfoKits::RetryGetService(std::unique_lock<std::mutex> &lock)
109 {
110 DINFO_LOGI("deviceService is dead, retry get service");
111 if (deviceInfoService_ != nullptr) {
112 sptr<IRemoteObject> object = deviceInfoService_->AsObject();
113 if ((deathRecipient_ != nullptr)) {
114 DINFO_CHECK(object != nullptr, return GetService(lock), "object is null");
115 object->RemoveDeathRecipient(deathRecipient_);
116 }
117 if (object != nullptr) {
118 deviceInfoService_ = nullptr;
119 }
120 }
121 return GetService(lock);
122 }
123
GetUdid(std::string & result)124 int32_t DeviceInfoKits::GetUdid(std::string& result)
125 {
126 std::unique_lock<std::mutex> lock(lock_);
127 static std::optional<std::pair<int32_t, std::string>> resultPair;
128 if (resultPair.has_value()) {
129 int32_t ret = resultPair->first;
130 result = resultPair->second;
131 DINFO_LOGV("GetUdid from resultPair ret = %d", ret);
132 return ret;
133 }
134 auto deviceService = GetService(lock);
135 DINFO_CHECK(deviceService != nullptr, return -1, "Failed to get deviceinfo manager");
136 int ret = deviceService->GetUdid(result);
137 if (ret == NOT_FOUND_SERVICE_ERROR_NUMBER) {
138 auto newDeviceService = RetryGetService(lock);
139 DINFO_CHECK(newDeviceService != nullptr, return -1, "Failed to get deviceinfo manager again");
140 ret = newDeviceService->GetUdid(result);
141 }
142 DINFO_LOGI("GetSerialID from remote ret = %d", ret);
143 if (ret == 0 || ret == SYSPARAM_PERMISSION_DENIED) {
144 resultPair = std::make_optional(std::make_pair(ret, result));
145 }
146 return ret;
147 }
148
GetSerialID(std::string & result)149 int32_t DeviceInfoKits::GetSerialID(std::string& result)
150 {
151 std::unique_lock<std::mutex> lock(lock_);
152 static std::optional<std::pair<int32_t, std::string>> resultPair;
153 if (resultPair.has_value()) {
154 int32_t ret = resultPair->first;
155 result = resultPair->second;
156 DINFO_LOGV("GetSerialID from resultPair ret = %d", ret);
157 return ret;
158 }
159 auto deviceService = GetService(lock);
160 DINFO_CHECK(deviceService != nullptr, return -1, "Failed to get deviceinfo manager");
161 int ret = deviceService->GetSerialID(result);
162 if (ret == NOT_FOUND_SERVICE_ERROR_NUMBER) {
163 auto newDeviceService = RetryGetService(lock);
164 DINFO_CHECK(newDeviceService != nullptr, return -1, "Failed to get deviceinfo manager again");
165 ret = newDeviceService->GetSerialID(result);
166 }
167 DINFO_LOGI("GetSerialID from remote ret = %d", ret);
168 if (ret == 0 || ret == SYSPARAM_PERMISSION_DENIED) {
169 resultPair = std::make_optional(std::make_pair(ret, result));
170 }
171 return ret;
172 }
173
GetDiskSN(std::string & result)174 int32_t DeviceInfoKits::GetDiskSN(std::string& result)
175 {
176 std::unique_lock<std::mutex> lock(lock_);
177 static std::optional<std::pair<int32_t, std::string>> resultPair;
178 if (resultPair.has_value()) {
179 int32_t ret = resultPair->first;
180 result = resultPair->second;
181 DINFO_LOGV("GetDiskSN from resultPair ret = %d", ret);
182 return ret;
183 }
184 auto deviceService = GetService(lock);
185 DINFO_CHECK(deviceService != nullptr, return -1, "Failed to get deviceinfo manager");
186 int ret = deviceService->GetDiskSN(result);
187 if (ret == NOT_FOUND_SERVICE_ERROR_NUMBER) {
188 auto newDeviceService = RetryGetService(lock);
189 DINFO_CHECK(newDeviceService != nullptr, return -1, "Failed to get deviceinfo manager again");
190 ret = newDeviceService->GetDiskSN(result);
191 }
192 DINFO_LOGI("GetDiskSN from remote ret = %d", ret);
193 if (ret == 0 || ret == SYSPARAM_PERMISSION_DENIED) {
194 resultPair = std::make_optional(std::make_pair(ret, result));
195 }
196 return ret;
197 }
198
OnRemoteDied(const wptr<IRemoteObject> & remote)199 void DeviceInfoKits::DeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
200 {
201 DelayedRefSingleton<DeviceInfoKits>::GetInstance().ResetService(remote);
202 }
203
ResetService(const wptr<IRemoteObject> & remote)204 void DeviceInfoKits::ResetService(const wptr<IRemoteObject> &remote)
205 {
206 DINFO_LOGI("Remote is dead, reset service instance");
207 std::lock_guard<std::mutex> lock(lock_);
208 if (deviceInfoService_ != nullptr) {
209 sptr<IRemoteObject> object = deviceInfoService_->AsObject();
210 if ((object != nullptr) && (remote == object)) {
211 object->RemoveDeathRecipient(deathRecipient_);
212 deviceInfoService_ = nullptr;
213 }
214 }
215 }
216 } // namespace device_info
217 } // namespace OHOS
218