• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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