1 /*
2  * Copyright (c) 2024 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 <utility>
16 #include <memory>
17 #include <unistd.h>
18 #include "safwk_log.h"
19 #include "string_ex.h"
20 #include "api_cache_manager.h"
21 
22 namespace OHOS {
23 namespace {
24 const std::string TAG = "ApiCacheManager";
25 }
26 
GetInstance()27 ApiCacheManager& ApiCacheManager::GetInstance()
28 {
29     static ApiCacheManager instance;
30     return instance;
31 }
32 
AddCacheApi(const std::u16string & descriptor,uint32_t apiCode,int64_t expireTimeSec)33 void ApiCacheManager::AddCacheApi(const std::u16string& descriptor, uint32_t apiCode, int64_t expireTimeSec)
34 {
35     constexpr size_t defaultCacheSize = 8;
36     auto apiPair = std::make_pair(descriptor, apiCode);
37 
38     std::lock_guard<std::mutex> lock(cachesMutex_);
39     auto iter = caches_.find(apiPair);
40     if (iter == caches_.end()) {
41         auto obj = new ExpireLruCache<std::vector<uint8_t>, std::vector<uint8_t>> (defaultCacheSize, expireTimeSec);
42         caches_[apiPair] = obj;
43         return;
44     }
45 
46     HILOGD(TAG, "Cache api(%{public}s, apiCode:%{public}u) already exists", Str16ToStr8(descriptor).c_str(), apiCode);
47     return;
48 }
49 
DelCacheApi(const std::u16string & descriptor,uint32_t apiCode)50 void ApiCacheManager::DelCacheApi(const std::u16string& descriptor, uint32_t apiCode)
51 {
52     auto apiPair = std::make_pair(descriptor, apiCode);
53     std::lock_guard<std::mutex> lock(cachesMutex_);
54     auto iter = caches_.find(apiPair);
55     if (iter != caches_.end()) {
56         if (iter->second != nullptr) {
57             delete iter->second;
58         }
59         caches_.erase(apiPair);
60         HILOGD(TAG, "Delete cache api(%{public}s, apiCode:%{public}u)", Str16ToStr8(descriptor).c_str(), apiCode);
61     }
62 
63     return;
64 }
65 
ClearCache()66 void ApiCacheManager::ClearCache()
67 {
68     std::lock_guard<std::mutex> lock(cachesMutex_);
69     for (auto &iter : caches_) {
70         if (iter.second != nullptr) {
71             iter.second->Clear();
72             HILOGD(TAG, "Clear the api(%{public}s, apiCode:%{public}u) cache",
73                 Str16ToStr8(iter.first.first).c_str(), iter.first.second);
74         }
75     }
76     return;
77 }
78 
ClearCache(const std::u16string & descriptor)79 void ApiCacheManager::ClearCache(const std::u16string& descriptor)
80 {
81     std::lock_guard<std::mutex> lock(cachesMutex_);
82     for (auto &iter : caches_) {
83         if ((iter.first.first == descriptor) && (iter.second != nullptr)) {
84             HILOGD(TAG, "Clear the api(%{public}s, apiCode:%{public}u) cache",
85                 Str16ToStr8(descriptor).c_str(), iter.first.second);
86             iter.second->Clear();
87         }
88     }
89     return;
90 }
91 
ClearCache(const std::u16string & descriptor,int32_t apiCode)92 void ApiCacheManager::ClearCache(const std::u16string& descriptor, int32_t apiCode)
93 {
94     std::lock_guard<std::mutex> lock(cachesMutex_);
95     auto iter = caches_.find(std::make_pair(descriptor, apiCode));
96     if ((iter != caches_.end()) && (iter->second != nullptr)) {
97         HILOGD(TAG, "Clear the api(%{public}s, apiCode:%{public}u) cache",
98             Str16ToStr8(descriptor).c_str(), apiCode);
99         iter->second->Clear();
100     }
101 
102     return;
103 }
104 
PreSendRequest(const std::u16string & descriptor,uint32_t apiCode,const MessageParcel & data,MessageParcel & reply)105 bool ApiCacheManager::PreSendRequest(const std::u16string& descriptor, uint32_t apiCode, const MessageParcel& data,
106     MessageParcel& reply)
107 {
108     uint8_t *key = reinterpret_cast<uint8_t *>(data.GetData());
109     size_t keySize = data.GetDataSize();
110     std::vector<uint8_t> keyVec(key, key + keySize);
111 
112     std::pair<std::u16string, uint32_t> myPair = std::make_pair(descriptor, apiCode);
113     std::lock_guard<std::mutex> lock(cachesMutex_);
114     auto cache = caches_.find(myPair);
115     if ((cache == caches_.end()) || (cache->second == nullptr)) {
116         HILOGD(TAG, "Find cache api(%{public}s, apiCode:%{public}u) from map failed, maybe this api is no cacheable",
117             Str16ToStr8(descriptor).c_str(), apiCode);
118         return false;
119     }
120 
121     std::shared_ptr<std::vector<uint8_t>> valueVec = cache->second->Get(keyVec);
122     if (valueVec == nullptr) {
123         HILOGD(TAG, "Cache hit failure");
124         return false;
125     }
126 
127     reply.WriteBuffer(reinterpret_cast<void *>(&(*valueVec)[0]), valueVec->size());
128     HILOGD(TAG, "Cache hit success");
129     return true;
130 }
131 
PostSendRequest(const std::u16string & descriptor,uint32_t apiCode,const MessageParcel & data,MessageParcel & reply)132 bool ApiCacheManager::PostSendRequest(const std::u16string& descriptor, uint32_t apiCode, const MessageParcel& data,
133     MessageParcel& reply)
134 {
135     uint8_t *key = reinterpret_cast<uint8_t *>(data.GetData());
136     size_t keySize = data.GetDataSize();
137     std::vector<uint8_t> keyVec(key, key + keySize);
138 
139     std::pair<std::u16string, uint32_t> myPair = std::make_pair(descriptor, apiCode);
140     std::lock_guard<std::mutex> lock(cachesMutex_);
141     auto cache = caches_.find(myPair);
142     if ((cache == caches_.end()) || (cache->second == nullptr)) {
143         HILOGD(TAG, "Find cache api(%{public}s, apiCode:%{public}u) from map failed, maybe this api is no cacheable",
144             Str16ToStr8(descriptor).c_str(), apiCode);
145         return false;
146     }
147 
148     uint8_t *value = reinterpret_cast<uint8_t *>(reply.GetData());
149     size_t valueSize = reply.GetDataSize();
150     std::vector<uint8_t> valueVec(value, value + valueSize);
151 
152     cache->second->Add(keyVec, valueVec);
153     HILOGD(TAG, "Cache the reply of this call");
154 
155     return true;
156 }
157 }