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