1 /*
2  * Copyright (c) 2020-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 
16 #include "bundle_map.h"
17 
18 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
19 #include <pthread.h>
20 #else
21 #include "cmsis_os2.h"
22 #endif
23 #include "adapter.h"
24 #include "appexecfwk_errors.h"
25 #include "bundle_info_utils.h"
26 #include "utils.h"
27 
28 namespace OHOS {
29 const int32_t GET_BUNDLE_WITH_ABILITIES = 1;
30 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
31 static pthread_mutex_t g_bundleListMutex = PTHREAD_MUTEX_INITIALIZER;
32 #else
33 const int32_t BUNDLELIST_MUTEX_TIMEOUT = 2000;
34 static osMutexId_t g_bundleListMutex;
35 #endif
36 
BundleMap()37 BundleMap::BundleMap()
38 {
39 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
40     pthread_mutex_init(&g_bundleListMutex, nullptr);
41 #else
42     g_bundleListMutex = osMutexNew(reinterpret_cast<osMutexAttr_t *>(NULL));
43 #endif
44     bundleInfos_ = new (std::nothrow) List<BundleInfo *>();
45 }
46 
~BundleMap()47 BundleMap::~BundleMap()
48 {
49     MutexDelete(&g_bundleListMutex);
50     delete bundleInfos_;
51     bundleInfos_ = nullptr;
52 }
53 
Add(BundleInfo * bundleInfo)54 void BundleMap::Add(BundleInfo *bundleInfo)
55 {
56     if ((bundleInfo == nullptr) || (bundleInfo->bundleName == nullptr)) {
57         return;
58     }
59 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
60     MutexAcquire(&g_bundleListMutex, 0);
61 #else
62     MutexAcquire(&g_bundleListMutex, BUNDLELIST_MUTEX_TIMEOUT);
63 #endif
64     for (auto node = bundleInfos_->Begin(); node != bundleInfos_->End(); node = node->next_) {
65         BundleInfo *info = node->value_;
66         if (info != nullptr && info->bundleName != nullptr && strcmp(info->bundleName, bundleInfo->bundleName) == 0) {
67             MutexRelease(&g_bundleListMutex);
68             return;
69         }
70     }
71     bundleInfos_->PushFront(bundleInfo);
72     MutexRelease(&g_bundleListMutex);
73     return;
74 }
75 
Update(BundleInfo * bundleInfo)76 bool BundleMap::Update(BundleInfo *bundleInfo)
77 {
78     if ((bundleInfo == nullptr) || (bundleInfo->bundleName == nullptr)) {
79         return false;
80     }
81 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
82     MutexAcquire(&g_bundleListMutex, 0);
83 #else
84     MutexAcquire(&g_bundleListMutex, BUNDLELIST_MUTEX_TIMEOUT);
85 #endif
86     auto newNode = new (std::nothrow) Node<BundleInfo *>(bundleInfo);
87     if (newNode == nullptr) {
88         MutexRelease(&g_bundleListMutex);
89         return false;
90     }
91     for (auto oldNode = bundleInfos_->Begin(); oldNode != bundleInfos_->End(); oldNode = oldNode->next_) {
92         BundleInfo *info = oldNode->value_;
93         if ((info != nullptr) && (info->bundleName != nullptr) &&
94             (strcmp(info->bundleName, bundleInfo->bundleName) == 0)) {
95             oldNode->prev_->next_ = newNode;
96             oldNode->next_->prev_ = newNode;
97             newNode->prev_ = oldNode->prev_;
98             newNode->next_ = oldNode->next_;
99             BundleInfoUtils::FreeBundleInfo(info);
100             delete oldNode;
101             MutexRelease(&g_bundleListMutex);
102             return true;
103         }
104     }
105     delete newNode;
106     bundleInfos_->PushFront(bundleInfo);
107     MutexRelease(&g_bundleListMutex);
108     return true;
109 }
110 
Get(const char * bundleName) const111 BundleInfo *BundleMap::Get(const char *bundleName) const
112 {
113     if (bundleName == nullptr) {
114         return nullptr;
115     }
116 
117 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
118     MutexAcquire(&g_bundleListMutex, 0);
119 #else
120     MutexAcquire(&g_bundleListMutex, BUNDLELIST_MUTEX_TIMEOUT);
121 #endif
122     for (auto node = bundleInfos_->Begin(); node != bundleInfos_->End(); node = node->next_) {
123         BundleInfo *info = node->value_;
124         if (info != nullptr && info->bundleName != nullptr && strcmp(info->bundleName, bundleName) == 0) {
125             MutexRelease(&g_bundleListMutex);
126             return info;
127         }
128     }
129     MutexRelease(&g_bundleListMutex);
130     return nullptr;
131 }
132 
GetCopyBundleInfo(uint32_t flags,const BundleInfo * bundleInfo,BundleInfo & newBundleInfo) const133 void BundleMap::GetCopyBundleInfo(uint32_t flags, const BundleInfo *bundleInfo, BundleInfo &newBundleInfo) const
134 {
135     if (bundleInfo == nullptr) {
136         return;
137     }
138     newBundleInfo.isSystemApp = bundleInfo->isSystemApp;
139     newBundleInfo.versionCode = bundleInfo->versionCode;
140     newBundleInfo.bundleName = bundleInfo->bundleName;
141     newBundleInfo.label = bundleInfo->label;
142     newBundleInfo.versionName = bundleInfo->versionName;
143     newBundleInfo.codePath = bundleInfo->codePath;
144     newBundleInfo.dataPath = bundleInfo->dataPath;
145     newBundleInfo.compatibleApi = bundleInfo->compatibleApi;
146     newBundleInfo.targetApi = bundleInfo->targetApi;
147     newBundleInfo.vendor = bundleInfo->vendor;
148     newBundleInfo.bigIconPath = bundleInfo->bigIconPath;
149     newBundleInfo.moduleInfos = bundleInfo->moduleInfos;
150     newBundleInfo.numOfModule = bundleInfo->numOfModule;
151     newBundleInfo.appId = bundleInfo->appId;
152 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
153     newBundleInfo.isKeepAlive = bundleInfo->isKeepAlive;
154     newBundleInfo.isNativeApp = bundleInfo->isNativeApp;
155     newBundleInfo.uid = bundleInfo->uid;
156     newBundleInfo.gid = bundleInfo->gid;
157     if (flags == GET_BUNDLE_WITH_ABILITIES) {
158         newBundleInfo.abilityInfos = bundleInfo->abilityInfos;
159         newBundleInfo.numOfAbility = bundleInfo->numOfAbility;
160     } else {
161         newBundleInfo.abilityInfos = nullptr;
162         newBundleInfo.numOfAbility = 0;
163     }
164 #else
165     newBundleInfo.smallIconPath = bundleInfo->smallIconPath;
166     if (flags == GET_BUNDLE_WITH_ABILITIES) {
167         newBundleInfo.abilityInfo = bundleInfo->abilityInfo;
168     } else {
169         newBundleInfo.abilityInfo = nullptr;
170     }
171 #endif
172 }
173 
GetBundleInfos(int32_t flags,BundleInfo ** bundleInfos,int32_t * len) const174 uint8_t BundleMap::GetBundleInfos(int32_t flags, BundleInfo **bundleInfos, int32_t *len) const
175 {
176     if (bundleInfos == nullptr) {
177         return ERR_APPEXECFWK_QUERY_PARAMETER_ERROR;
178     }
179 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
180     MutexAcquire(&g_bundleListMutex, 0);
181 #else
182     MutexAcquire(&g_bundleListMutex, BUNDLELIST_MUTEX_TIMEOUT);
183 #endif
184     if (bundleInfos_->IsEmpty()) {
185         MutexRelease(&g_bundleListMutex);
186         return ERR_APPEXECFWK_QUERY_NO_INFOS;
187     }
188 
189     BundleInfo *infos = reinterpret_cast<BundleInfo *>(AdapterMalloc(sizeof(BundleInfo) * bundleInfos_->Size()));
190     if (infos == nullptr || memset_s(infos, sizeof(BundleInfo) * bundleInfos_->Size(), 0,
191         sizeof(BundleInfo) * bundleInfos_->Size()) != EOK) {
192         AdapterFree(infos);
193         MutexRelease(&g_bundleListMutex);
194         return ERR_APPEXECFWK_QUERY_INFOS_INIT_ERROR;
195     }
196     *bundleInfos = infos;
197 
198     for (auto node = bundleInfos_->Begin(); node != bundleInfos_->End(); node = node->next_) {
199         BundleInfoUtils::CopyBundleInfo(flags, infos++, *(node->value_));
200     }
201 
202     *len = bundleInfos_->Size();
203     MutexRelease(&g_bundleListMutex);
204     return ERR_OK;
205 }
206 
GetBundleInfosInner(List<BundleInfo * > & bundleInfos) const207 uint8_t BundleMap::GetBundleInfosInner(List<BundleInfo *> &bundleInfos) const
208 {
209     if (bundleInfos_->IsEmpty()) {
210         return ERR_APPEXECFWK_QUERY_NO_INFOS;
211     }
212     for (auto node = bundleInfos_->Begin(); node != bundleInfos_->End(); node = node->next_) {
213         bundleInfos.PushBack(node->value_);
214     }
215     return ERR_OK;
216 }
217 
GetBundleInfosNoReplication(int32_t flags,BundleInfo ** bundleInfos,int32_t * len) const218 uint8_t BundleMap::GetBundleInfosNoReplication(int32_t flags, BundleInfo **bundleInfos, int32_t *len) const
219 {
220     if (bundleInfos == nullptr) {
221         return ERR_APPEXECFWK_QUERY_PARAMETER_ERROR;
222     }
223 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
224     MutexAcquire(&g_bundleListMutex, 0);
225 #else
226     MutexAcquire(&g_bundleListMutex, BUNDLELIST_MUTEX_TIMEOUT);
227 #endif
228     if (bundleInfos_->IsEmpty()) {
229         MutexRelease(&g_bundleListMutex);
230         return ERR_APPEXECFWK_QUERY_NO_INFOS;
231     }
232 
233     BundleInfo *infos = reinterpret_cast<BundleInfo *>(AdapterMalloc(sizeof(BundleInfo) * bundleInfos_->Size()));
234     if (infos == nullptr || memset_s(infos, sizeof(BundleInfo) * bundleInfos_->Size(), 0,
235         sizeof(BundleInfo) * bundleInfos_->Size()) != EOK) {
236         AdapterFree(infos);
237         MutexRelease(&g_bundleListMutex);
238         return ERR_APPEXECFWK_QUERY_INFOS_INIT_ERROR;
239     }
240     *bundleInfos = infos;
241 
242     for (auto node = bundleInfos_->Begin(); node != bundleInfos_->End(); node = node->next_) {
243         BundleInfoUtils::CopyBundleInfoNoReplication(flags, infos++, *(node->value_));
244     }
245 
246     *len = bundleInfos_->Size();
247     MutexRelease(&g_bundleListMutex);
248     return ERR_OK;
249 }
250 
GetBundleInfo(const char * bundleName,int32_t flags,BundleInfo & bundleInfo) const251 uint8_t BundleMap::GetBundleInfo(const char *bundleName, int32_t flags, BundleInfo &bundleInfo) const
252 {
253     if (bundleName == nullptr) {
254         return ERR_APPEXECFWK_QUERY_PARAMETER_ERROR;
255     }
256 
257     BundleInfo *specialBundleInfo = Get(bundleName);
258     if (specialBundleInfo == nullptr) {
259         return ERR_APPEXECFWK_QUERY_NO_INFOS;
260     }
261 
262     GetCopyBundleInfo(flags, specialBundleInfo, bundleInfo);
263     return ERR_OK;
264 }
265 
Erase(const char * bundleName)266 void BundleMap::Erase(const char *bundleName)
267 {
268     if (bundleName == nullptr) {
269         return;
270     }
271 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
272     MutexAcquire(&g_bundleListMutex, 0);
273 #else
274     MutexAcquire(&g_bundleListMutex, BUNDLELIST_MUTEX_TIMEOUT);
275 #endif
276     for (auto node = bundleInfos_->Begin(); node != bundleInfos_->End(); node = node->next_) {
277         BundleInfo *info = node->value_;
278         if (info->bundleName != nullptr && strcmp(info->bundleName, bundleName) == 0) {
279             BundleInfoUtils::FreeBundleInfo(info);
280             bundleInfos_->Remove(node);
281             MutexRelease(&g_bundleListMutex);
282             return;
283         }
284     }
285     MutexRelease(&g_bundleListMutex);
286 }
287 
EraseAll()288 void BundleMap::EraseAll()
289 {
290 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
291     MutexAcquire(&g_bundleListMutex, 0);
292 #else
293     MutexAcquire(&g_bundleListMutex, BUNDLELIST_MUTEX_TIMEOUT);
294 #endif
295     for (auto node = bundleInfos_->Begin(); node != bundleInfos_->End(); node = node->next_) {
296         BundleInfoUtils::FreeBundleInfo(node->value_);
297     }
298     bundleInfos_->RemoveAll();
299     MutexRelease(&g_bundleListMutex);
300 }
301 }  // namespace OHOS
302