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 27namespace OHOS { 28namespace device_info { 29 30static const int DEVINFO_SAID = 3902; 31static const int DEVICEINFO_LOAD_SA_TIMEOUT_MS = 5000; 32 33DeviceInfoKits::DeviceInfoKits() {} 34 35DeviceInfoKits::~DeviceInfoKits() {} 36 37DeviceInfoKits &DeviceInfoKits::GetInstance() 38{ 39 return DelayedRefSingleton<DeviceInfoKits>::GetInstance(); 40} 41 42void DeviceInfoKits::LoadDeviceInfoSa(std::unique_lock<std::mutex> &lock) 43{ 44 DINFO_LOGV("deviceInfoService_ is %d", deviceInfoService_ == nullptr); 45 if (deviceInfoService_ != nullptr) { 46 return; 47 } 48 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 49 DINFO_CHECK(sam != nullptr, return, "GetSystemAbilityManager return null"); 50 51 auto remoteObject = sam->CheckSystemAbility(DEVINFO_SAID); 52 if (remoteObject) { 53 DINFO_LOGV("deviceinfo sa is already loaded"); 54 deviceInfoService_ = iface_cast<IDeviceInfo>(remoteObject); 55 return; 56 } 57 sptr<DeviceInfoLoad> deviceInfoLoad = new (std::nothrow) DeviceInfoLoad(); 58 DINFO_CHECK(deviceInfoLoad != nullptr, return, "new deviceInfoLoad fail."); 59 60 int32_t ret = sam->LoadSystemAbility(SYSPARAM_DEVICE_SERVICE_ID, deviceInfoLoad); 61 DINFO_CHECK(ret == ERR_OK, return, "LoadSystemAbility deviceinfo sa failed"); 62 63 if (deathRecipient_ == nullptr) { 64 deathRecipient_ = new DeathRecipient(); 65 } 66 67 // wait_for release lock and block until time out(60s) or match the condition with notice 68 auto waitStatus = deviceInfoLoadCon_.wait_for(lock, std::chrono::milliseconds(DEVICEINFO_LOAD_SA_TIMEOUT_MS), 69 [this]() { return deviceInfoService_ != nullptr; }); 70 if (!waitStatus || deviceInfoService_ == nullptr) { 71 // time out or loadcallback fail 72 DINFO_LOGE("tokensync load sa timeout"); 73 return; 74 } 75 76 // for dead 77 auto object = deviceInfoService_->AsObject(); 78 if ((object->IsProxyObject()) && (!object->AddDeathRecipient(deathRecipient_))) { 79 DINFO_LOGE("Failed to add death recipient"); 80 } 81} 82 83sptr<IDeviceInfo> DeviceInfoKits::GetService(std::unique_lock<std::mutex> &lock) 84{ 85 LoadDeviceInfoSa(lock); 86 return deviceInfoService_; 87} 88 89void DeviceInfoKits::FinishStartSASuccess(const sptr<IRemoteObject> &remoteObject) 90{ 91 DINFO_LOGI("get deviceinfo sa success."); 92 // get lock which wait_for release and send a notice so that wait_for can out of block 93 std::unique_lock<std::mutex> lock(lock_); 94 deviceInfoService_ = iface_cast<IDeviceInfo>(remoteObject); 95 deviceInfoLoadCon_.notify_one(); 96} 97 98void DeviceInfoKits::FinishStartSAFailed() 99{ 100 DINFO_LOGI("Get deviceinfo sa failed."); 101 // get lock which wait_for release and send a notice 102 std::unique_lock<std::mutex> lock(lock_); 103 deviceInfoService_ = nullptr; 104 deviceInfoLoadCon_.notify_one(); 105} 106 107int32_t DeviceInfoKits::GetUdid(std::string& result) 108{ 109 std::unique_lock<std::mutex> lock(lock_); 110 static std::optional<std::pair<int32_t, std::string>> resultPair; 111 if (resultPair.has_value()) { 112 int32_t ret = resultPair->first; 113 result = resultPair->second; 114 DINFO_LOGV("GetUdid from resultPair ret = %d", ret); 115 return ret; 116 } 117 auto deviceService = GetService(lock); 118 DINFO_CHECK(deviceService != nullptr, return -1, "Failed to get deviceinfo manager"); 119 int ret = deviceService->GetUdid(result); 120 DINFO_LOGV("GetSerialID from remote ret = %d", ret); 121 if (ret == 0 || ret == SYSPARAM_PERMISSION_DENIED) { 122 resultPair = std::make_optional(std::make_pair(ret, result)); 123 } 124 return ret; 125} 126 127int32_t DeviceInfoKits::GetSerialID(std::string& result) 128{ 129 std::unique_lock<std::mutex> lock(lock_); 130 static std::optional<std::pair<int32_t, std::string>> resultPair; 131 if (resultPair.has_value()) { 132 int32_t ret = resultPair->first; 133 result = resultPair->second; 134 DINFO_LOGV("GetSerialID from resultPair ret = %d", ret); 135 return ret; 136 } 137 auto deviceService = GetService(lock); 138 DINFO_CHECK(deviceService != nullptr, return -1, "Failed to get deviceinfo manager"); 139 int ret = deviceService->GetSerialID(result); 140 DINFO_LOGV("GetSerialID from remote ret = %d", ret); 141 if (ret == 0 || ret == SYSPARAM_PERMISSION_DENIED) { 142 resultPair = std::make_optional(std::make_pair(ret, result)); 143 } 144 return ret; 145} 146 147void DeviceInfoKits::DeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote) 148{ 149 DelayedRefSingleton<DeviceInfoKits>::GetInstance().ResetService(remote); 150} 151 152void DeviceInfoKits::ResetService(const wptr<IRemoteObject> &remote) 153{ 154 DINFO_LOGI("Remote is dead, reset service instance"); 155 std::lock_guard<std::mutex> lock(lock_); 156 if (deviceInfoService_ != nullptr) { 157 sptr<IRemoteObject> object = deviceInfoService_->AsObject(); 158 if ((object != nullptr) && (remote == object)) { 159 object->RemoveDeathRecipient(deathRecipient_); 160 deviceInfoService_ = nullptr; 161 } 162 } 163} 164} // namespace device_info 165} // namespace OHOS 166