1 /*
2 * Copyright (c) 2022 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
16 #include "permission_used_record_cache.h"
17 #include "accesstoken_log.h"
18 #include "constant.h"
19 #include "generic_values.h"
20 #include "permission_record.h"
21 #include "permission_record_manager.h"
22 #include "permission_record_node.h"
23 #include "permission_record_repository.h"
24 #include "permission_used_record_db.h"
25 #include "privacy_field_const.h"
26 #include "time_util.h"
27
28 namespace OHOS {
29 namespace Security {
30 namespace AccessToken {
31 namespace {
32 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {
33 LOG_CORE, SECURITY_DOMAIN_PRIVACY, "PermissionUsedRecordCache"
34 };
35 }
PermissionUsedRecordCache()36 PermissionUsedRecordCache::PermissionUsedRecordCache()
37 : hasInited_(false), readRecordBufferTaskWorker_("PermissionUsedRecordCache") {}
38
~PermissionUsedRecordCache()39 PermissionUsedRecordCache::~PermissionUsedRecordCache()
40 {
41 if (!hasInited_) {
42 return;
43 }
44 this->readRecordBufferTaskWorker_.Stop();
45 this->hasInited_ = false;
46 }
47
GetInstance()48 PermissionUsedRecordCache& PermissionUsedRecordCache::GetInstance()
49 {
50 static PermissionUsedRecordCache instance;
51
52 if (!instance.hasInited_) {
53 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(instance.initLock_);
54 if (!instance.hasInited_) {
55 instance.readRecordBufferTaskWorker_.Start(1);
56 instance.hasInited_ = true;
57 }
58 }
59 return instance;
60 }
61
RecordMergeCheck(const PermissionRecord & record1,const PermissionRecord & record2)62 bool PermissionUsedRecordCache::RecordMergeCheck(const PermissionRecord& record1, const PermissionRecord& record2)
63 {
64 // timestamp in the same minute
65 if (!TimeUtil::IsTimeStampsSameMinute(record1.timestamp, record2.timestamp)) {
66 return false;
67 }
68
69 // the same tokenID + opCode + status + lockScreenStatus
70 if ((record1.tokenId != record2.tokenId) ||
71 (record1.opCode != record2.opCode) ||
72 (record1.status != record2.status) ||
73 (record1.lockScreenStatus != record2.lockScreenStatus)) {
74 return false;
75 }
76
77 bool startFlag = ((record1.timestamp == record2.timestamp) && // same timestamp
78 ((record1.accessCount == 0) && (record2.accessCount == 1)) &&
79 ((record1.rejectCount == 0) && (record2.rejectCount == 0)));
80 // true means record1 is instantaneous record add by StartUsingPermission, record2 is add by StopUsingPermission
81 if (startFlag) {
82 ACCESSTOKEN_LOG_DEBUG(LABEL, "StopUsingPermission record combine StartUsingPermission record.");
83 return true;
84 }
85
86 // both success
87 if (((record1.accessCount > 0) && (record2.accessCount == 0)) ||
88 ((record1.accessCount == 0) && (record2.accessCount > 0))) {
89 return false;
90 }
91
92 // both failure
93 if (((record1.rejectCount > 0) && (record2.rejectCount == 0)) ||
94 ((record1.rejectCount == 0) && (record2.rejectCount > 0))) {
95 return false;
96 }
97
98 return true;
99 }
100
101 // data from cache1 to cache2, should use deep copy to avoid data change in multithread scene
DeepCopyFromHead(const std::shared_ptr<PermissionUsedRecordNode> & oriHeadNode,std::shared_ptr<PermissionUsedRecordNode> & copyHeadNode,int32_t copyCount)102 void PermissionUsedRecordCache::DeepCopyFromHead(const std::shared_ptr<PermissionUsedRecordNode>& oriHeadNode,
103 std::shared_ptr<PermissionUsedRecordNode>& copyHeadNode, int32_t copyCount)
104 {
105 ACCESSTOKEN_LOG_INFO(LABEL, "deep copy count is %{public}d.", copyCount);
106
107 std::shared_ptr<PermissionUsedRecordNode> head = oriHeadNode;
108 std::shared_ptr<PermissionUsedRecordNode> currentNode = copyHeadNode;
109
110 if (head == nullptr) {
111 return;
112 } else {
113 currentNode->record = head->record;
114 }
115
116 while (head->next != nullptr) {
117 if (copyCount <= 0) {
118 break;
119 }
120
121 head = head->next;
122 std::shared_ptr<PermissionUsedRecordNode> tmpNode = std::make_shared<PermissionUsedRecordNode>();
123 tmpNode->record = head->record;
124 tmpNode->pre = currentNode;
125 currentNode->next = tmpNode;
126 currentNode = currentNode->next;
127 copyCount--;
128 }
129 }
130
AddRecordToBuffer(const PermissionRecord & record)131 void PermissionUsedRecordCache::AddRecordToBuffer(const PermissionRecord& record)
132 {
133 std::shared_ptr<PermissionUsedRecordNode> curFindMergePos;
134 std::shared_ptr<PermissionUsedRecordNode> persistPendingBufferHead = std::make_shared<PermissionUsedRecordNode>();
135 std::shared_ptr<PermissionUsedRecordNode> persistPendingBufferEnd = nullptr;
136 PermissionRecord mergedRecord = record;
137 {
138 Utils::UniqueWriteGuard<Utils::RWLock> lock1(this->cacheLock1_);
139 curFindMergePos = curRecordBufferPos_;
140 int32_t remainCount = 0; // records left in cache1
141 while (curFindMergePos != recordBufferHead_) {
142 auto pre = curFindMergePos->pre.lock();
143 if ((record.timestamp - curFindMergePos->record.timestamp) >= INTERVAL) {
144 persistPendingBufferEnd = curFindMergePos;
145 break;
146 } else if (RecordMergeCheck(curFindMergePos->record, record)) {
147 MergeRecord(mergedRecord, curFindMergePos);
148 } else {
149 remainCount++;
150 }
151 curFindMergePos = pre;
152 }
153 AddRecordNode(mergedRecord); // refresh curRecordBUfferPos and readableSize
154 remainCount++;
155 // when current record timestamp more than last record timestamp 15mins
156 if ((remainCount >= MAX_PERSIST_SIZE) || (persistPendingBufferEnd != nullptr)) {
157 ACCESSTOKEN_LOG_INFO(LABEL, "reset record count: %{public}d", remainCount);
158 /*
159 * when remainCount reach the max, move all data from cache1 to cache2
160 * otherwise copyCount should be readableSize_ - remainCount beause curFindMergePos match from tail to head
161 */
162 int32_t copyCount = remainCount >= MAX_PERSIST_SIZE ? remainCount : readableSize_ - remainCount;
163 DeepCopyFromHead(recordBufferHead_, persistPendingBufferHead, copyCount);
164
165 ResetRecordBufferWhenAdd(remainCount, persistPendingBufferEnd);
166 }
167 }
168 if (persistPendingBufferEnd != nullptr) {
169 AddToPersistQueue(persistPendingBufferHead);
170 }
171 }
172
MergeRecord(PermissionRecord & record,std::shared_ptr<PermissionUsedRecordNode> curFindMergePos)173 void PermissionUsedRecordCache::MergeRecord(PermissionRecord& record,
174 std::shared_ptr<PermissionUsedRecordNode> curFindMergePos)
175 {
176 record.accessDuration += curFindMergePos->record.accessDuration;
177 record.accessCount += curFindMergePos->record.accessCount;
178 record.rejectCount += curFindMergePos->record.rejectCount;
179 if (curRecordBufferPos_ == curFindMergePos) {
180 curRecordBufferPos_ = curRecordBufferPos_->pre.lock();
181 }
182 DeleteRecordNode(curFindMergePos); // delete old same node
183 readableSize_--;
184 }
185
AddToPersistQueue(const std::shared_ptr<PermissionUsedRecordNode> persistPendingBufferHead)186 void PermissionUsedRecordCache::AddToPersistQueue(
187 const std::shared_ptr<PermissionUsedRecordNode> persistPendingBufferHead)
188 {
189 bool startPersist = false;
190 {
191 Utils::UniqueWriteGuard<Utils::RWLock> lock2(this->cacheLock2_);
192 persistPendingBufferQueue_.emplace_back(persistPendingBufferHead);
193 if (!persistIsRunning_) {
194 startPersist = true;
195 }
196 }
197 if (startPersist) {
198 ExecuteReadRecordBufferTask();
199 }
200 }
201
ExecuteReadRecordBufferTask()202 void PermissionUsedRecordCache::ExecuteReadRecordBufferTask()
203 {
204 if (readRecordBufferTaskWorker_.GetCurTaskNum() > 1) {
205 ACCESSTOKEN_LOG_INFO(LABEL, "Already has read record buffer task!");
206 return;
207 }
208 auto readRecordBufferTask = [this]() {
209 ACCESSTOKEN_LOG_INFO(LABEL, "ReadRecordBuffer task called");
210 PersistPendingRecords();
211 };
212 readRecordBufferTaskWorker_.AddTask(readRecordBufferTask);
213 }
214
PersistPendingRecords()215 int32_t PermissionUsedRecordCache::PersistPendingRecords()
216 {
217 std::shared_ptr<PermissionUsedRecordNode> persistPendingBufferHead;
218 bool isEmpty;
219 {
220 Utils::UniqueWriteGuard<Utils::RWLock> lock2(this->cacheLock2_);
221 isEmpty = persistPendingBufferQueue_.empty();
222 persistIsRunning_ = true;
223 }
224 ACCESSTOKEN_LOG_INFO(LABEL, "add %{public}d record node", readableSize_);
225 while (!isEmpty) {
226 {
227 Utils::UniqueWriteGuard<Utils::RWLock> lock2(this->cacheLock2_);
228 persistPendingBufferHead = persistPendingBufferQueue_[0];
229 persistPendingBufferQueue_.erase(persistPendingBufferQueue_.begin());
230 }
231 std::vector<GenericValues> insertValues;
232 std::shared_ptr<PermissionUsedRecordNode> curPendingRecordNode =
233 persistPendingBufferHead->next;
234 while (curPendingRecordNode != nullptr) {
235 auto next = curPendingRecordNode->next;
236 GenericValues tmpRecordValues;
237 PermissionRecord tmpRecord = curPendingRecordNode->record;
238 PermissionRecord::TranslationIntoGenericValues(tmpRecord, tmpRecordValues);
239 insertValues.emplace_back(tmpRecordValues);
240 DeleteRecordNode(curPendingRecordNode);
241 curPendingRecordNode = next;
242 }
243 if (!insertValues.empty() && !PermissionRecordRepository::GetInstance().AddRecordValues(insertValues)) {
244 ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to persist pending records, insertValues size: %{public}u",
245 static_cast<uint32_t>(insertValues.size()));
246 }
247 {
248 Utils::UniqueReadGuard<Utils::RWLock> lock2(this->cacheLock2_);
249 isEmpty = persistPendingBufferQueue_.empty();
250 }
251 }
252 {
253 Utils::UniqueWriteGuard<Utils::RWLock> lock2(this->cacheLock2_);
254 if (isEmpty) { // free persistPendingBufferQueue
255 std::vector<std::shared_ptr<PermissionUsedRecordNode>> tmpPersistPendingBufferQueue;
256 std::swap(tmpPersistPendingBufferQueue, persistPendingBufferQueue_);
257 }
258 persistIsRunning_ = false;
259 }
260 return true;
261 }
262
263 #ifdef POWER_MANAGER_ENABLE
PersistPendingRecordsImmediately()264 void PermissionUsedRecordCache::PersistPendingRecordsImmediately()
265 {
266 std::shared_ptr<PermissionUsedRecordNode> persistPendingBufferHead = std::make_shared<PermissionUsedRecordNode>();
267 // this function can be use only when receive shut down callback
268 {
269 Utils::UniqueWriteGuard<Utils::RWLock> lock1(this->cacheLock1_);
270 DeepCopyFromHead(recordBufferHead_, persistPendingBufferHead, readableSize_);
271 }
272 {
273 Utils::UniqueWriteGuard<Utils::RWLock> lock2(this->cacheLock2_);
274 persistPendingBufferQueue_.emplace_back(persistPendingBufferHead);
275 }
276
277 PersistPendingRecords();
278 }
279 #endif
280
RemoveRecords(const AccessTokenID tokenId)281 int32_t PermissionUsedRecordCache::RemoveRecords(const AccessTokenID tokenId)
282 {
283 std::shared_ptr<PermissionUsedRecordNode> curFindDeletePos;
284 std::shared_ptr<PermissionUsedRecordNode> persistPendingBufferHead = std::make_shared<PermissionUsedRecordNode>();
285 std::shared_ptr<PermissionUsedRecordNode> persistPendingBufferEnd = nullptr;
286
287 {
288 int32_t countPersistPendingNode = 0;
289 Utils::UniqueWriteGuard<Utils::RWLock> lock1(this->cacheLock1_);
290 curFindDeletePos = recordBufferHead_->next;
291 while (curFindDeletePos != nullptr) {
292 auto next = curFindDeletePos->next;
293 if (curFindDeletePos->record.tokenId == tokenId) {
294 if (curRecordBufferPos_ == curFindDeletePos) {
295 curRecordBufferPos_ = curFindDeletePos->pre.lock();
296 }
297 DeleteRecordNode(curFindDeletePos);
298 readableSize_--;
299 } else if (TimeUtil::GetCurrentTimestamp() - curFindDeletePos->record.timestamp >= INTERVAL) {
300 persistPendingBufferEnd = curFindDeletePos;
301 countPersistPendingNode++;
302 }
303 curFindDeletePos = next;
304 }
305
306 // this should do after delete the matched tokenID data
307 if (persistPendingBufferEnd != nullptr) {
308 DeepCopyFromHead(recordBufferHead_, persistPendingBufferHead, countPersistPendingNode);
309
310 int32_t remainCount = readableSize_ - countPersistPendingNode;
311 ResetRecordBuffer(remainCount, persistPendingBufferEnd);
312 }
313 }
314
315 RemoveFromPersistQueueAndDatabase(tokenId);
316 if (persistPendingBufferEnd != nullptr) { // add to queue
317 AddToPersistQueue(persistPendingBufferHead);
318 }
319 return Constant::SUCCESS;
320 }
321
RemoveFromPersistQueueAndDatabase(const AccessTokenID tokenId)322 void PermissionUsedRecordCache::RemoveFromPersistQueueAndDatabase(const AccessTokenID tokenId)
323 {
324 {
325 std::shared_ptr<PermissionUsedRecordNode> curFindDeletePos;
326 Utils::UniqueWriteGuard<Utils::RWLock> lock2(this->cacheLock2_);
327 if (!persistPendingBufferQueue_.empty()) {
328 for (const auto& persistHead : persistPendingBufferQueue_) {
329 curFindDeletePos = persistHead->next;
330 while (curFindDeletePos != nullptr) {
331 auto next = curFindDeletePos->next;
332 if (curFindDeletePos->record.tokenId == tokenId) {
333 DeleteRecordNode(curFindDeletePos);
334 }
335 curFindDeletePos = next;
336 }
337 }
338 }
339 }
340 GenericValues record;
341 record.Put(PrivacyFiledConst::FIELD_TOKEN_ID, static_cast<int32_t>(tokenId));
342 PermissionRecordRepository::GetInstance().RemoveRecordValues(record); // remove from database
343 }
344
GetRecords(const std::vector<std::string> & permissionList,const GenericValues & andConditionValues,std::vector<GenericValues> & findRecordsValues,int32_t cache1QueryCount)345 void PermissionUsedRecordCache::GetRecords(const std::vector<std::string>& permissionList,
346 const GenericValues& andConditionValues, std::vector<GenericValues>& findRecordsValues, int32_t cache1QueryCount)
347 {
348 std::set<int32_t> opCodeList;
349 std::shared_ptr<PermissionUsedRecordNode> curFindPos;
350 std::shared_ptr<PermissionUsedRecordNode> persistPendingBufferHead = std::make_shared<PermissionUsedRecordNode>();
351 std::shared_ptr<PermissionUsedRecordNode> persistPendingBufferEnd = nullptr;
352 int32_t countPersistPendingNode = 0;
353 AccessTokenID tokenId = andConditionValues.GetInt(PrivacyFiledConst::FIELD_TOKEN_ID);
354 TransferToOpcode(opCodeList, permissionList);
355 {
356 Utils::UniqueWriteGuard<Utils::RWLock> lock1(this->cacheLock1_);
357 curFindPos = recordBufferHead_->next;
358 while (curFindPos != nullptr) {
359 if (cache1QueryCount == 0) {
360 break;
361 }
362 auto next = curFindPos->next;
363 if (RecordCompare(tokenId, opCodeList, andConditionValues, curFindPos->record)) {
364 GenericValues recordValues;
365 PermissionRecord::TranslationIntoGenericValues(curFindPos->record, recordValues);
366 findRecordsValues.emplace_back(recordValues);
367 cache1QueryCount--;
368 }
369 if (TimeUtil::GetCurrentTimestamp() - curFindPos->record.timestamp >= INTERVAL) {
370 persistPendingBufferEnd = curFindPos;
371 countPersistPendingNode++;
372 }
373 curFindPos = next;
374 }
375
376 if (persistPendingBufferEnd != nullptr) {
377 DeepCopyFromHead(recordBufferHead_, persistPendingBufferHead, countPersistPendingNode);
378
379 int32_t remainCount = readableSize_ - countPersistPendingNode;
380 ResetRecordBuffer(remainCount, persistPendingBufferEnd);
381 }
382 }
383
384 if (cache1QueryCount > 0) {
385 GetFromPersistQueueAndDatabase(opCodeList, andConditionValues, findRecordsValues, cache1QueryCount);
386 }
387
388 // this should after query persist queue and database
389 if (countPersistPendingNode != 0) {
390 AddToPersistQueue(persistPendingBufferHead);
391 }
392 }
393
GetFromPersistQueueAndDatabase(const std::set<int32_t> & opCodeList,const GenericValues & andConditionValues,std::vector<GenericValues> & findRecordsValues,int32_t cache2QueryCount)394 void PermissionUsedRecordCache::GetFromPersistQueueAndDatabase(const std::set<int32_t>& opCodeList,
395 const GenericValues& andConditionValues, std::vector<GenericValues>& findRecordsValues, int32_t cache2QueryCount)
396 {
397 AccessTokenID tokenId = andConditionValues.GetInt(PrivacyFiledConst::FIELD_TOKEN_ID);
398 std::shared_ptr<PermissionUsedRecordNode> curFindPos;
399 {
400 Utils::UniqueReadGuard<Utils::RWLock> lock2(this->cacheLock2_);
401 for (const auto& persistHead : persistPendingBufferQueue_) {
402 curFindPos = persistHead->next;
403 while (curFindPos != nullptr) {
404 auto next = curFindPos->next;
405 if (RecordCompare(tokenId, opCodeList, andConditionValues, curFindPos->record)) {
406 GenericValues recordValues;
407 PermissionRecord::TranslationIntoGenericValues(curFindPos->record, recordValues);
408 if (cache2QueryCount == 0) {
409 break;
410 }
411 findRecordsValues.emplace_back(recordValues);
412 cache2QueryCount--;
413 }
414 curFindPos = next;
415 }
416 if (cache2QueryCount == 0) {
417 return;
418 }
419 }
420 }
421
422 if (!PermissionRecordRepository::GetInstance().FindRecordValues(opCodeList, andConditionValues,
423 findRecordsValues, cache2QueryCount)) { // find records from database
424 ACCESSTOKEN_LOG_ERROR(LABEL, "find records from database failed");
425 }
426 }
427
ResetRecordBufferWhenAdd(const int32_t remainCount,std::shared_ptr<PermissionUsedRecordNode> & persistPendingBufferEnd)428 void PermissionUsedRecordCache::ResetRecordBufferWhenAdd(const int32_t remainCount,
429 std::shared_ptr<PermissionUsedRecordNode>& persistPendingBufferEnd)
430 {
431 std::shared_ptr<PermissionUsedRecordNode> tmpRecordBufferHead =
432 std::make_shared<PermissionUsedRecordNode>();
433 if (remainCount >= MAX_PERSIST_SIZE) {
434 readableSize_ = 1;
435 tmpRecordBufferHead->next = curRecordBufferPos_;
436 persistPendingBufferEnd = curRecordBufferPos_->pre.lock();
437 persistPendingBufferEnd->next.reset(); //release the last node next
438 recordBufferHead_ = tmpRecordBufferHead;
439 recordBufferHead_->next->pre = recordBufferHead_;
440 return;
441 }
442 readableSize_ = remainCount;
443 // refresh recordBufferHead
444 tmpRecordBufferHead->next = persistPendingBufferEnd->next;
445 persistPendingBufferEnd->next.reset(); //release persistPendingBufferEnd->next
446 recordBufferHead_ = tmpRecordBufferHead;
447 // recordBufferHead_->next->pre equals to persistPendingBufferEnd, reset recordBufferHead_->next->pre
448 recordBufferHead_->next->pre = recordBufferHead_;
449 }
450
ResetRecordBuffer(const int32_t remainCount,std::shared_ptr<PermissionUsedRecordNode> & persistPendingBufferEnd)451 void PermissionUsedRecordCache::ResetRecordBuffer(const int32_t remainCount,
452 std::shared_ptr<PermissionUsedRecordNode>& persistPendingBufferEnd)
453 {
454 readableSize_ = remainCount;
455 // refresh recordBufferHead
456 std::shared_ptr<PermissionUsedRecordNode> tmpRecordBufferHead =
457 std::make_shared<PermissionUsedRecordNode>();
458 tmpRecordBufferHead->next = persistPendingBufferEnd->next;
459 persistPendingBufferEnd->next.reset();
460 recordBufferHead_ = tmpRecordBufferHead;
461
462 if (persistPendingBufferEnd == curRecordBufferPos_) {
463 // persistPendingBufferEnd == curRecordBufferPos, reset curRecordBufferPos
464 curRecordBufferPos_ = recordBufferHead_;
465 } else {
466 // recordBufferHead_->next->pre = persistPendingBufferEnd, reset recordBufferHead_->next->pre
467 recordBufferHead_->next->pre = recordBufferHead_;
468 }
469 }
470
TransferToOpcode(std::set<int32_t> & opCodeList,const std::vector<std::string> & permissionList)471 void PermissionUsedRecordCache::TransferToOpcode(std::set<int32_t>& opCodeList,
472 const std::vector<std::string>& permissionList)
473 {
474 for (const auto& permission : permissionList) {
475 int32_t opCode = Constant::OP_INVALID;
476 Constant::TransferPermissionToOpcode(permission, opCode);
477 opCodeList.insert(opCode);
478 }
479 }
480
RecordCompare(const AccessTokenID tokenId,const std::set<int32_t> & opCodeList,const GenericValues & andConditionValues,const PermissionRecord & record)481 bool PermissionUsedRecordCache::RecordCompare(const AccessTokenID tokenId, const std::set<int32_t>& opCodeList,
482 const GenericValues& andConditionValues, const PermissionRecord& record)
483 {
484 // compare tokenId
485 if (record.tokenId != tokenId) {
486 return false;
487 }
488 // compare opCode
489 if (!opCodeList.empty() && opCodeList.find(record.opCode) == opCodeList.end()) {
490 return false;
491 }
492
493 std::vector<std::string> andColumns = andConditionValues.GetAllKeys();
494 if (!andColumns.empty()) {
495 for (auto andColumn : andColumns) {
496 // compare begin timestamp
497 if ((andColumn == PrivacyFiledConst::FIELD_TIMESTAMP_BEGIN) &&
498 (record.timestamp < andConditionValues.GetInt64(andColumn))) {
499 return false;
500 } else if ((andColumn == PrivacyFiledConst::FIELD_TIMESTAMP_END) &&
501 (record.timestamp > andConditionValues.GetInt64(andColumn))) {
502 return false;
503 } else if ((andColumn == PrivacyFiledConst::FIELD_TIMESTAMP) &&
504 (record.timestamp != andConditionValues.GetInt64(andColumn))) {
505 return false;
506 }
507
508 // compare lockScreenStatus
509 if ((andColumn == PrivacyFiledConst::FIELD_LOCKSCREEN_STATUS) &&
510 (record.lockScreenStatus != andConditionValues.GetInt(andColumn))) {
511 return false;
512 }
513
514 // compare app status
515 if ((andColumn == PrivacyFiledConst::FIELD_STATUS) &&
516 (record.status != andConditionValues.GetInt(andColumn))) {
517 return false;
518 }
519 }
520 }
521 return true;
522 }
523
FindTokenIdList(std::set<AccessTokenID> & tokenIdList)524 void PermissionUsedRecordCache::FindTokenIdList(std::set<AccessTokenID>& tokenIdList)
525 {
526 std::shared_ptr<PermissionUsedRecordNode> curFindPos;
527 {
528 // find tokenIdList from recordBuffer
529 Utils::UniqueReadGuard<Utils::RWLock> lock1(this->cacheLock1_);
530 curFindPos = recordBufferHead_->next;
531 while (curFindPos != nullptr) {
532 auto next = curFindPos->next;
533 tokenIdList.emplace((AccessTokenID)curFindPos->record.tokenId);
534 curFindPos = next;
535 }
536 }
537 {
538 // find tokenIdList from BufferQueue
539 Utils::UniqueReadGuard<Utils::RWLock> lock2(this->cacheLock2_);
540 if (!persistPendingBufferQueue_.empty()) {
541 for (auto persistHead : persistPendingBufferQueue_) {
542 curFindPos = persistHead->next;
543 while (curFindPos != nullptr) {
544 auto next = curFindPos->next;
545 tokenIdList.emplace((AccessTokenID)curFindPos->record.tokenId);
546 curFindPos = next;
547 }
548 }
549 }
550 }
551 }
552
AddRecordNode(const PermissionRecord & record)553 void PermissionUsedRecordCache::AddRecordNode(const PermissionRecord& record)
554 {
555 std::shared_ptr<PermissionUsedRecordNode> tmpRecordNode = std::make_shared<PermissionUsedRecordNode>();
556 tmpRecordNode->record = record;
557 tmpRecordNode->pre = curRecordBufferPos_;
558 curRecordBufferPos_->next = tmpRecordNode;
559 curRecordBufferPos_ = curRecordBufferPos_->next;
560 readableSize_++;
561 }
562
DeleteRecordNode(std::shared_ptr<PermissionUsedRecordNode> deleteRecordNode)563 void PermissionUsedRecordCache::DeleteRecordNode(std::shared_ptr<PermissionUsedRecordNode> deleteRecordNode)
564 {
565 std::shared_ptr<PermissionUsedRecordNode> pre = deleteRecordNode->pre.lock();
566 if (deleteRecordNode->next == nullptr) { // End of the linked list
567 pre->next = nullptr;
568 } else {
569 std::shared_ptr<PermissionUsedRecordNode> next = deleteRecordNode->next;
570 pre->next = next;
571 next->pre = pre;
572 }
573 }
574 } // namespace AccessToken
575 } // namespace Security
576 } // namespace OHOS