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