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 
16 #include "bundle_resource_host.h"
17 
18 #include "app_log_wrapper.h"
19 #include "bundle_framework_core_ipc_interface_code.h"
20 #include "bundle_memory_guard.h"
21 #include "hitrace_meter.h"
22 #include "datetime_ex.h"
23 #include "ipc_types.h"
24 #include "json_util.h"
25 #include "string_ex.h"
26 
27 namespace OHOS {
28 namespace AppExecFwk {
29 namespace {
30 constexpr size_t MAX_PARCEL_CAPACITY = 1024 * 1024 * 1024; // max allow 1 GB resource size
31 constexpr size_t MAX_IPC_ALLOWED_CAPACITY = 100 * 1024 * 1024; // max ipc size 100MB
32 const std::string BUNDLE_RESOURCE_ASHMEM_NAME = "bundleResourceAshemeName";
33 }
BundleResourceHost()34 BundleResourceHost::BundleResourceHost()
35 {
36     APP_LOGD("start");
37 }
38 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)39 int32_t BundleResourceHost::OnRemoteRequest(uint32_t code, MessageParcel &data,
40     MessageParcel &reply, MessageOption &option)
41 {
42     BundleMemoryGuard memoryGuard;
43     APP_LOGD("bundle resource host onReceived message, the message code is %{public}u", code);
44     std::u16string descriptor = BundleResourceHost::GetDescriptor();
45     std::u16string remoteDescriptor = data.ReadInterfaceToken();
46     if (descriptor != remoteDescriptor) {
47         APP_LOGE("fail to write reply message in bundle mgr host due to the reply is nullptr");
48         return OBJECT_NULL;
49     }
50 
51     ErrCode errCode = ERR_OK;
52     switch (code) {
53         case static_cast<uint32_t>(BundleResourceInterfaceCode::GET_BUNDLE_RESOURCE_INFO):
54             errCode = this->HandleGetBundleResourceInfo(data, reply);
55             break;
56         case static_cast<uint32_t>(BundleResourceInterfaceCode::GET_LAUNCHER_ABILITY_RESOURCE_INFO):
57             errCode = this->HandleGetLauncherAbilityResourceInfo(data, reply);
58             break;
59         case static_cast<uint32_t>(BundleResourceInterfaceCode::GET_ALL_BUNDLE_RESOURCE_INFO):
60             errCode = this->HandleGetAllBundleResourceInfo(data, reply);
61             break;
62         case static_cast<uint32_t>(BundleResourceInterfaceCode::GET_ALL_LAUNCHER_ABILITY_RESOURCE_INFO):
63             errCode = this->HandleGetAllLauncherAbilityResourceInfo(data, reply);
64             break;
65         case static_cast<uint32_t>(BundleResourceInterfaceCode::ADD_RESOURCE_INFO_BY_BUNDLE_NAME):
66             errCode = this->HandleAddResourceInfoByBundleName(data, reply);
67             break;
68         case static_cast<uint32_t>(BundleResourceInterfaceCode::ADD_RESOURCE_INFO_BY_ABILITY):
69             errCode = this->HandleAddResourceInfoByAbility(data, reply);
70             break;
71         case static_cast<uint32_t>(BundleResourceInterfaceCode::DELETE_RESOURCE_INFO):
72             errCode = this->HandleDeleteResourceInfo(data, reply);
73             break;
74         default:
75             APP_LOGW("bundle resource host receives unknown %{public}u", code);
76             return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
77     }
78     APP_LOGD("bundle resource host finish to process message, errCode: %{public}d", errCode);
79     return (errCode == ERR_OK) ? NO_ERROR : UNKNOWN_ERROR;
80 }
81 
HandleGetBundleResourceInfo(MessageParcel & data,MessageParcel & reply)82 ErrCode BundleResourceHost::HandleGetBundleResourceInfo(MessageParcel &data, MessageParcel &reply)
83 {
84     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
85     std::string bundleName = data.ReadString();
86     uint32_t flags = data.ReadUint32();
87     int32_t appIndex = data.ReadInt32();
88     BundleResourceInfo bundleResourceInfo;
89     ErrCode ret = GetBundleResourceInfo(bundleName, flags, bundleResourceInfo, appIndex);
90     if (!reply.WriteInt32(ret)) {
91         APP_LOGE("write failed");
92         return ERR_APPEXECFWK_PARCEL_ERROR;
93     }
94     if (ret == ERR_OK) {
95         return WriteParcelInfo<BundleResourceInfo>(bundleResourceInfo, reply);
96     }
97     return ERR_OK;
98 }
99 
HandleGetLauncherAbilityResourceInfo(MessageParcel & data,MessageParcel & reply)100 ErrCode BundleResourceHost::HandleGetLauncherAbilityResourceInfo(MessageParcel &data, MessageParcel &reply)
101 {
102     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
103     std::string bundleName = data.ReadString();
104     uint32_t flags = data.ReadUint32();
105     int32_t appIndex = data.ReadInt32();
106     std::vector<LauncherAbilityResourceInfo> launcherAbilityResourceInfos;
107     ErrCode ret = GetLauncherAbilityResourceInfo(bundleName, flags, launcherAbilityResourceInfos, appIndex);
108     if (!reply.WriteInt32(ret)) {
109         APP_LOGE("write failed");
110         return ERR_APPEXECFWK_PARCEL_ERROR;
111     }
112     if (ret == ERR_OK) {
113         return WriteVectorToParcel<LauncherAbilityResourceInfo>(launcherAbilityResourceInfos, reply);
114     }
115     return ERR_OK;
116 }
117 
HandleGetAllBundleResourceInfo(MessageParcel & data,MessageParcel & reply)118 ErrCode BundleResourceHost::HandleGetAllBundleResourceInfo(MessageParcel &data, MessageParcel &reply)
119 {
120     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
121     uint32_t flags = data.ReadUint32();
122     std::vector<BundleResourceInfo> bundleResourceInfos;
123     ErrCode ret = GetAllBundleResourceInfo(flags, bundleResourceInfos);
124     if (!reply.WriteInt32(ret)) {
125         APP_LOGE("write failed");
126         return ERR_APPEXECFWK_PARCEL_ERROR;
127     }
128     if (ret == ERR_OK) {
129         return WriteVectorToParcel<BundleResourceInfo>(bundleResourceInfos, reply);
130     }
131     return ERR_OK;
132 }
133 
HandleGetAllLauncherAbilityResourceInfo(MessageParcel & data,MessageParcel & reply)134 ErrCode BundleResourceHost::HandleGetAllLauncherAbilityResourceInfo(MessageParcel &data, MessageParcel &reply)
135 {
136     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
137     uint32_t flags = data.ReadUint32();
138     std::vector<LauncherAbilityResourceInfo> launcherAbilityResourceInfos;
139     ErrCode ret = GetAllLauncherAbilityResourceInfo(flags, launcherAbilityResourceInfos);
140     if (!reply.WriteInt32(ret)) {
141         APP_LOGE("write failed");
142         return ERR_APPEXECFWK_PARCEL_ERROR;
143     }
144     if (ret == ERR_OK) {
145         return WriteVectorToParcel<LauncherAbilityResourceInfo>(launcherAbilityResourceInfos, reply);
146     }
147     return ERR_OK;
148 }
149 
HandleAddResourceInfoByBundleName(MessageParcel & data,MessageParcel & reply)150 ErrCode BundleResourceHost::HandleAddResourceInfoByBundleName(MessageParcel &data, MessageParcel &reply)
151 {
152     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
153     std::string bundleName = data.ReadString();
154     int32_t userId = data.ReadInt32();
155     ErrCode ret = AddResourceInfoByBundleName(bundleName, userId);
156     if (!reply.WriteInt32(ret)) {
157         APP_LOGE("write failed");
158         return ERR_APPEXECFWK_PARCEL_ERROR;
159     }
160     return ERR_OK;
161 }
162 
HandleAddResourceInfoByAbility(MessageParcel & data,MessageParcel & reply)163 ErrCode BundleResourceHost::HandleAddResourceInfoByAbility(MessageParcel &data, MessageParcel &reply)
164 {
165     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
166     std::string bundleName = data.ReadString();
167     std::string moduleName = data.ReadString();
168     std::string abilityName = data.ReadString();
169     int32_t userId = data.ReadInt32();
170     ErrCode ret = AddResourceInfoByAbility(bundleName, moduleName, abilityName, userId);
171     if (!reply.WriteInt32(ret)) {
172         APP_LOGE("write failed");
173         return ERR_APPEXECFWK_PARCEL_ERROR;
174     }
175     return ERR_OK;
176 }
177 
HandleDeleteResourceInfo(MessageParcel & data,MessageParcel & reply)178 ErrCode BundleResourceHost::HandleDeleteResourceInfo(MessageParcel &data, MessageParcel &reply)
179 {
180     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
181     std::string key = data.ReadString();
182     ErrCode ret = DeleteResourceInfo(key);
183     if (!reply.WriteInt32(ret)) {
184         APP_LOGE("write failed");
185         return ERR_APPEXECFWK_PARCEL_ERROR;
186     }
187     return ERR_OK;
188 }
189 
AllocatAshmemNum()190 int32_t BundleResourceHost::AllocatAshmemNum()
191 {
192     std::lock_guard<std::mutex> lock(bundleAshmemMutex_);
193     return ashmemNum_++;
194 }
195 
WriteParcelableIntoAshmem(MessageParcel & tempParcel,MessageParcel & reply)196 ErrCode BundleResourceHost::WriteParcelableIntoAshmem(MessageParcel &tempParcel, MessageParcel &reply)
197 {
198     size_t dataSize = tempParcel.GetDataSize();
199     // The ashmem name must be unique.
200     sptr<Ashmem> ashmem = Ashmem::CreateAshmem(
201         (BUNDLE_RESOURCE_ASHMEM_NAME + std::to_string(AllocatAshmemNum())).c_str(), dataSize);
202     if (ashmem == nullptr) {
203         APP_LOGE("Create shared memory failed");
204         return ERR_APPEXECFWK_PARCEL_ERROR;
205     }
206 
207     // Set the read/write mode of the ashme.
208     if (!ashmem->MapReadAndWriteAshmem()) {
209         APP_LOGE("Map shared memory fail");
210         return ERR_APPEXECFWK_PARCEL_ERROR;
211     }
212     // Write the size and content of each item to the ashmem.
213     int32_t offset = 0;
214     if (!ashmem->WriteToAshmem(reinterpret_cast<uint8_t *>(tempParcel.GetData()), dataSize, offset)) {
215         APP_LOGE("Write info to shared memory fail");
216         return ERR_APPEXECFWK_PARCEL_ERROR;
217     }
218 
219     if (!reply.WriteAshmem(ashmem)) {
220         APP_LOGE("Write ashmem to tempParcel fail");
221         return ERR_APPEXECFWK_PARCEL_ERROR;
222     }
223     return ERR_OK;
224 }
225 
226 template<typename T>
WriteParcelInfo(const T & parcelInfo,MessageParcel & reply)227 ErrCode BundleResourceHost::WriteParcelInfo(const T &parcelInfo, MessageParcel &reply)
228 {
229     MessageParcel tmpParcel;
230     (void)tmpParcel.SetMaxCapacity(MAX_PARCEL_CAPACITY);
231     if (!tmpParcel.WriteParcelable(&parcelInfo)) {
232         APP_LOGE("write parcel failed");
233         return ERR_APPEXECFWK_PARCEL_ERROR;
234     }
235     size_t dataSize = tmpParcel.GetDataSize();
236     if (!reply.WriteUint32(dataSize)) {
237         APP_LOGE("write parcel failed");
238         return ERR_APPEXECFWK_PARCEL_ERROR;
239     }
240     if (dataSize > MAX_IPC_ALLOWED_CAPACITY) {
241         APP_LOGI("datasize is too large, use ashmem");
242         return WriteParcelableIntoAshmem(tmpParcel, reply);
243     }
244     if (!reply.WriteRawData(reinterpret_cast<uint8_t *>(tmpParcel.GetData()), dataSize)) {
245         APP_LOGE("write parcel failed");
246         return ERR_APPEXECFWK_PARCEL_ERROR;
247     }
248     return ERR_OK;
249 }
250 
251 template<typename T>
WriteVectorToParcel(std::vector<T> & parcelVector,MessageParcel & reply)252 ErrCode BundleResourceHost::WriteVectorToParcel(std::vector<T> &parcelVector, MessageParcel &reply)
253 {
254     MessageParcel tempParcel;
255     (void)tempParcel.SetMaxCapacity(MAX_PARCEL_CAPACITY);
256     if (!tempParcel.WriteInt32(parcelVector.size())) {
257         APP_LOGE("write failed");
258         return ERR_APPEXECFWK_PARCEL_ERROR;
259     }
260 
261     for (auto &parcel : parcelVector) {
262         if (!tempParcel.WriteParcelable(&parcel)) {
263             APP_LOGE("write failed");
264             return ERR_APPEXECFWK_PARCEL_ERROR;
265         }
266     }
267 
268     size_t dataSize = tempParcel.GetDataSize();
269     if (!reply.WriteUint32(dataSize)) {
270         APP_LOGE("write failed");
271         return ERR_APPEXECFWK_PARCEL_ERROR;
272     }
273 
274     if (dataSize > MAX_IPC_ALLOWED_CAPACITY) {
275         APP_LOGI("datasize is too large, use ashmem");
276         return WriteParcelableIntoAshmem(tempParcel, reply);
277     }
278     if (!reply.WriteRawData(reinterpret_cast<uint8_t *>(tempParcel.GetData()), dataSize)) {
279         APP_LOGE("write parcel failed");
280         return ERR_APPEXECFWK_PARCEL_ERROR;
281     }
282     return ERR_OK;
283 }
284 } // AppExecFwk
285 } // OHOS
286