1/* 2 * Copyright (c) 2023 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 "oaid_service.h" 16#include <mutex> 17#include <openssl/rand.h> 18#include <singleton.h> 19#include <string> 20#include <unistd.h> 21#include "oaid_common.h" 22#include "oaid_file_operator.h" 23#include "system_ability.h" 24#include "system_ability_definition.h" 25#include "oaid_service_stub.h" 26#include "oaid_service_define.h" 27#include "oaid_observer_manager.h" 28 29using namespace std::chrono; 30 31namespace OHOS { 32namespace Cloud { 33const std::string OAID_VIRTUAL_STR = "-****-****-****-************"; 34namespace { 35char HexToChar(uint8_t hex) 36{ 37 static const uint8_t MAX_SINGLE_DIGIT = 9; // 9 is the largest single digit 38 return (hex > MAX_SINGLE_DIGIT) ? (hex + 0x57) : (hex + 0x30); 39} 40 41/** 42 * Get v4 uuid. 43 * 44 * @return std::string, uuid. 45 */ 46std::string GetUUID() 47{ 48 static const int8_t UUID_LENGTH = 16; // The UUID is 128 bits, that is 16 bytes. 49 static const int8_t VERSION_INDEX = 6; // Obtain the seventh byte of the randomly generated UUID, that is uuid[6]. 50 static const int8_t CHAR_LOW_WIDTH = 4; // Lower 4 bits of the char type 51 static const int8_t N_INDEX = 8; // Reset the ninth byte of the UUID, that is UUID[8]. 52 unsigned char uuid[UUID_LENGTH] = {0}; 53 int re = RAND_bytes(uuid, sizeof(uuid)); 54 if (re == 0) { 55 return ""; 56 } 57 58 /** 59 * xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx 60 * M is uuid version: 4 61 * N is 8,9,a,b 62 */ 63 uuid[VERSION_INDEX] = (uuid[VERSION_INDEX] & 0x0F) | 0x40; 64 int minN = 0x8; 65 int maxN = 0xb; 66 unsigned char randNumber[1] = {minN}; 67 RAND_bytes(randNumber, sizeof(randNumber)); 68 unsigned char num = static_cast<unsigned char>(randNumber[0] % (maxN - minN + 1) + minN); 69 uuid[N_INDEX] = (uuid[N_INDEX] & 0x0F) | (num << CHAR_LOW_WIDTH); 70 71 static const size_t LINE_INDEX_MAX = 10; // until i=10 72 static const size_t LINE_INDEX_MIN = 4; // Add a hyphen (-) every two bytes starting from i=4. 73 static const size_t EVEN_FACTOR = 2; // the even factor is assigned to 2, and all even numbers are divisible by 2. 74 std::string formatUuid = ""; 75 for (size_t i = 0; i < sizeof(uuid); i++) { 76 unsigned char value = uuid[i]; 77 if (i >= LINE_INDEX_MIN && i <= LINE_INDEX_MAX && i % EVEN_FACTOR == 0) { 78 formatUuid += "-"; 79 } 80 formatUuid += HexToChar(value >> CHAR_LOW_WIDTH); 81 unsigned char highValue = value & 0xF0; 82 if (highValue == 0) { 83 formatUuid += HexToChar(value); 84 } else { 85 formatUuid += HexToChar(value % (value & highValue)); 86 } 87 } 88 return formatUuid; 89} 90} // namespace 91 92REGISTER_SYSTEM_ABILITY_BY_ID(OAIDService, OAID_SYSTME_ID, true); 93std::mutex OAIDService::mutex_; 94sptr<OAIDService> OAIDService::instance_; 95 96OAIDService::OAIDService(int32_t systemAbilityId, bool runOnCreate) 97 : SystemAbility(systemAbilityId, runOnCreate), state_(ServiceRunningState::STATE_NOT_START) 98{ 99 OAID_HILOGI(OAID_MODULE_SERVICE, "Start."); 100} 101 102OAIDService::OAIDService() : state_(ServiceRunningState::STATE_NOT_START) 103{} 104 105OAIDService::~OAIDService(){}; 106 107sptr<OAIDService> OAIDService::GetInstance() 108{ 109 if (instance_ == nullptr) { 110 std::lock_guard<std::mutex> autoLock(mutex_); 111 if (instance_ == nullptr) { 112 OAID_HILOGI(OAID_MODULE_SERVICE, "Instance success."); 113 instance_ = new OAIDService; 114 } 115 } 116 return instance_; 117} 118 119void OAIDService::OnStart() 120{ 121 if (state_ == ServiceRunningState::STATE_RUNNING) { 122 OAID_HILOGE(OAID_MODULE_SERVICE, " OAIDService is already running."); 123 return; 124 } 125 126 if (Init() != ERR_OK) { 127 OAID_HILOGE(OAID_MODULE_SERVICE, "Init failed, Try again 10s later."); 128 return; 129 } 130 AddSystemAbilityListener(OAID_SYSTME_ID); 131 132 OAID_HILOGI(OAID_MODULE_SERVICE, "Start OAID service success."); 133 return; 134} 135 136int32_t OAIDService::Init() 137{ 138 bool ret = Publish(this); 139 if (!ret) { 140 OAID_HILOGE(OAID_MODULE_SERVICE, "OAID service init failed."); 141 return ERR_SYSYTEM_ERROR; 142 } 143 144 OAID_HILOGI(OAID_MODULE_SERVICE, "OAID service init Success."); 145 state_ = ServiceRunningState::STATE_RUNNING; 146 return ERR_OK; 147} 148 149void OAIDService::OnStop() 150{ 151 if (state_ != ServiceRunningState::STATE_RUNNING) { 152 return; 153 } 154 155 state_ = ServiceRunningState::STATE_NOT_START; 156 OAID_HILOGI(OAID_MODULE_SERVICE, "Stop success."); 157} 158 159bool OAIDService::InitOaidKvStore() 160{ 161 DistributedKv::DistributedKvDataManager manager; 162 DistributedKv::Options options; 163 164 DistributedKv::AppId appId; 165 appId.appId = OAID_DATA_BASE_APP_ID; 166 167 options.createIfMissing = true; 168 options.encrypt = true; 169 options.autoSync = false; 170 options.kvStoreType = DistributedKv::KvStoreType::SINGLE_VERSION; 171 options.area = DistributedKv::EL1; 172 options.baseDir = OAID_DATA_BASE_DIR + appId.appId; 173 options.securityLevel = DistributedKv::SecurityLevel::S1; 174 175 DistributedKv::StoreId storeId; 176 storeId.storeId = OAID_DATA_BASE_STORE_ID; 177 DistributedKv::Status status = DistributedKv::Status::SUCCESS; 178 179 if (oaidKvStore_ == nullptr) { 180 uint32_t retries = 0; 181 do { 182 OAID_HILOGI(OAID_MODULE_SERVICE, "InitOaidKvStore: retries=%{public}u!", retries); 183 status = manager.GetSingleKvStore(options, appId, storeId, oaidKvStore_); 184 if (status == DistributedKv::Status::STORE_NOT_FOUND) { 185 OAID_HILOGE(OAID_MODULE_SERVICE, "InitOaidKvStore: STORE_NOT_FOUND!"); 186 } 187 188 if ((status == DistributedKv::Status::SUCCESS) || (status == DistributedKv::Status::STORE_NOT_FOUND)) { 189 break; 190 } else { 191 OAID_HILOGE(OAID_MODULE_SERVICE, "Kvstore Connect failed! Retrying."); 192 retries++; 193 usleep(KVSTORE_CONNECT_RETRY_DELAY_TIME); 194 } 195 } while (retries <= KVSTORE_CONNECT_RETRY_COUNT); 196 } 197 198 if (oaidKvStore_ == nullptr) { 199 if (status == DistributedKv::Status::STORE_NOT_FOUND) { 200 OAID_HILOGI(OAID_MODULE_SERVICE, "First Boot: Create OaidKvStore"); 201 options.createIfMissing = true; 202 // [create and] open and initialize kvstore instance. 203 status = manager.GetSingleKvStore(options, appId, storeId, oaidKvStore_); 204 if (status == DistributedKv::Status::SUCCESS) { 205 OAID_HILOGE(OAID_MODULE_SERVICE, "Create OaidKvStore success!"); 206 } else { 207 OAID_HILOGE(OAID_MODULE_SERVICE, "Create OaidKvStore Failed!"); 208 } 209 } 210 } 211 212 if (oaidKvStore_ == nullptr) { 213 OAID_HILOGE(OAID_MODULE_SERVICE, "InitOaidKvStore: Failed!"); 214 return false; 215 } 216 217 return true; 218} 219 220void OAIDService::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) 221{ 222 OAID_HILOGI(OAID_MODULE_SERVICE, "OnAddSystemAbility OAIDService"); 223 bool result = false; 224 switch (systemAbilityId) { 225 case OAID_SYSTME_ID: 226 OAID_HILOGI(OAID_MODULE_SERVICE, "OnAddSystemAbility kv data service start"); 227 result = InitOaidKvStore(); 228 OAID_HILOGI(OAID_MODULE_SERVICE, "OnAddSystemAbility InitOaidKvStore is %{public}d", result); 229 break; 230 default: 231 OAID_HILOGI(OAID_MODULE_SERVICE, "OnAddSystemAbility unhandled sysabilityId:%{public}d", systemAbilityId); 232 break; 233 } 234} 235 236bool OAIDService::CheckKvStore() 237{ 238 if (oaidKvStore_ != nullptr) { 239 return true; 240 } 241 242 bool result = InitOaidKvStore(); 243 OAID_HILOGI(OAID_MODULE_SERVICE, "InitOaidKvStore: %{public}s", result == true ? "success" : "failed"); 244 return result; 245} 246 247bool OAIDService::ReadValueFromKvStore(const std::string &kvStoreKey, std::string &kvStoreValue) 248{ 249 std::lock_guard<std::mutex> lock(mutex_); 250 251 if (!CheckKvStore()) { 252 OAID_HILOGE(OAID_MODULE_SERVICE, "ReadValueFromKvStore:oaidKvStore_ is nullptr"); 253 return false; 254 } 255 256 DistributedKv::Key key(kvStoreKey); 257 DistributedKv::Value value; 258 DistributedKv::Status status = oaidKvStore_->Get(key, value); 259 if (status == DistributedKv::Status::SUCCESS) { 260 OAID_HILOGI(OAID_MODULE_SERVICE, "%{public}d get value from kvStore", status); 261 } else { 262 OAID_HILOGE(OAID_MODULE_SERVICE, "%{public}d get value from kvStore failed", status); 263 return false; 264 } 265 kvStoreValue = value.ToString(); 266 267 return true; 268} 269 270bool OAIDService::WriteValueToKvStore(const std::string &kvStoreKey, const std::string &kvStoreValue) 271{ 272 std::lock_guard<std::mutex> lock(mutex_); 273 274 if (!CheckKvStore()) { 275 OAID_HILOGE(OAID_MODULE_SERVICE, "WriteValueToKvStore:oaidKvStore_ is nullptr"); 276 return false; 277 } 278 279 DistributedKv::Key key(kvStoreKey); 280 DistributedKv::Value value(kvStoreValue); 281 DistributedKv::Status status = oaidKvStore_->Put(key, value); 282 if (status == DistributedKv::Status::SUCCESS) { 283 OAID_HILOGI(OAID_MODULE_SERVICE, "%{public}d updated to kvStore", status); 284 } else { 285 OAID_HILOGE(OAID_MODULE_SERVICE, "%{public}d update to kvStore failed", status); 286 return false; 287 } 288 289 return true; 290} 291 292std::string OAIDService::GainOAID() 293{ 294 OAID_HILOGI(OAID_MODULE_SERVICE, "Gain OAID Begin."); 295 std::string oaidKvStoreStr = OAID_ALLZERO_STR; 296 updateMutex_.lock(); 297 if (OAIDFileOperator::IsFileExsit(OAID_UPDATE)) { 298 OAIDFileOperator::OpenAndReadFile(OAID_UPDATE, oaidKvStoreStr); 299 OAIDFileOperator::ClearFile(OAID_UPDATE); 300 std::string oaid; 301 cJSON *root = cJSON_Parse(oaidKvStoreStr.c_str()); 302 if (root != nullptr && !cJSON_IsInvalid(root)) { 303 cJSON *oaidObj = cJSON_GetObjectItem(root, "oaid"); 304 if (cJSON_IsString(oaidObj)) { 305 oaid = oaidObj->valuestring; 306 } 307 } 308 cJSON_Delete(root); 309 oaid_ = oaid; 310 bool update = WriteValueToKvStore(OAID_KVSTORE_KEY, oaid_); 311 OAID_HILOGI(OAID_MODULE_SERVICE, "update oaid %{public}s", update ? "success" : "failed"); 312 updateMutex_.unlock(); 313 return oaid_; 314 } 315 updateMutex_.unlock(); 316 bool result = ReadValueFromKvStore(OAID_KVSTORE_KEY, oaidKvStoreStr); 317 OAID_HILOGI(OAID_MODULE_SERVICE, "ReadValueFromKvStore %{public}s", result ? "success" : "failed"); 318 319 if (oaidKvStoreStr != OAID_ALLZERO_STR && !oaidKvStoreStr.empty()) { 320 if (oaid_.empty()) { 321 oaid_ = oaidKvStoreStr; 322 OAID_HILOGI(OAID_MODULE_SERVICE, "The Oaid in the memory is empty, it get oaid from kvdb successfully"); 323 } 324 return oaid_; 325 } else { 326 if (oaid_.empty()) { 327 oaid_ = GetUUID(); 328 OAID_HILOGI(OAID_MODULE_SERVICE, "The oaid has been regenerated."); 329 } 330 } 331 result = WriteValueToKvStore(OAID_KVSTORE_KEY, oaid_); 332 OAID_HILOGI(OAID_MODULE_SERVICE, "WriteValueToKvStore %{public}s", result == true ? "success" : "failed"); 333 OAID_HILOGI(OAID_MODULE_SERVICE, "Gain OAID Finish."); 334 return oaid_; 335} 336 337std::string OAIDService::GetOAID() 338{ 339 OAID_HILOGI(OAID_MODULE_SERVICE, "Begin."); 340 341 std::string oaid = GainOAID(); 342 std::string target = oaid.substr(0, 9).append(OAID_VIRTUAL_STR); 343 OAID_HILOGI(OAID_MODULE_SERVICE, "getOaid success oaid is: %{public}s", target.c_str()); 344 OAID_HILOGI(OAID_MODULE_SERVICE, "End."); 345 return oaid; 346} 347 348int32_t OAIDService::ResetOAID() 349{ 350 OAID_HILOGI(OAID_MODULE_SERVICE, "ResetOAID."); 351 std::string resetOaid = GetUUID(); 352 oaid_ = resetOaid; 353 bool result = WriteValueToKvStore(OAID_KVSTORE_KEY, resetOaid); 354 OAID_HILOGI(OAID_MODULE_SERVICE, "ResetOAID WriteValueToKvStore %{public}s", result == true ? "success" : "failed"); 355 std::string target = resetOaid.substr(0, 9).append(OAID_VIRTUAL_STR); 356 OAID_HILOGI(OAID_MODULE_SERVICE, "resetOaid success oaid is: %{public}s", target.c_str()); 357 // 调用单例对象的oberser->OnUpdateOaid 358 DelayedSingleton<OaidObserverManager>::GetInstance()->OnUpdateOaid(resetOaid); 359 return ERR_OK; 360} 361} // namespace Cloud 362} // namespace OHOS 363