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