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