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