• 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 "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 
29 using namespace std::chrono;
30 
31 namespace OHOS {
32 namespace Cloud {
33 const std::string OAID_VIRTUAL_STR = "-****-****-****-************";
34 namespace {
HexToChar(uint8_t hex)35 char HexToChar(uint8_t hex)
36 {
37     static const uint8_t maxSingleDigit = 9;  // 9 is the largest single digit
38     return (hex > maxSingleDigit) ? (hex + 0x57) : (hex + 0x30);
39 }
40 
41 /**
42  * Get v4 uuid.
43  *
44  * @return std::string, uuid.
45  */
GetUUID()46 std::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 
92 REGISTER_SYSTEM_ABILITY_BY_ID(OAIDService, OAID_SYSTME_ID, true);
93 std::mutex OAIDService::mutex_;
94 sptr<OAIDService> OAIDService::instance_;
95 
OAIDService(int32_t systemAbilityId,bool runOnCreate)96 OAIDService::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 
OAIDService()102 OAIDService::OAIDService() : state_(ServiceRunningState::STATE_NOT_START)
103 {}
104 
~OAIDService()105 OAIDService::~OAIDService(){};
106 
GetInstance()107 sptr<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 
OnStart()119 void 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 
Init()136 int32_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 
OnStop()149 void 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 
InitOaidKvStore()159 bool 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 
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)220 void 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 
CheckKvStore()236 bool 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 
ReadValueFromKvStore(const std::string & kvStoreKey,std::string & kvStoreValue)247 bool 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 
WriteValueToKvStore(const std::string & kvStoreKey,const std::string & kvStoreValue)270 bool 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 
GainOAID()292 std::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 
GetOAID()337 std::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 
ResetOAID()348 int32_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