1 /*
2  * Copyright (c) 2022-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 "distributed_bms_host.h"
17 
18 #include "app_log_wrapper.h"
19 #include "appexecfwk_errors.h"
20 #include "bundle_constants.h"
21 #include "bundle_memory_guard.h"
22 #include "distributed_bundle_ipc_interface_code.h"
23 #include "remote_ability_info.h"
24 
25 namespace OHOS {
26 namespace AppExecFwk {
27 namespace {
28 constexpr int32_t GET_REMOTE_ABILITY_INFO_MAX_SIZE = 10;
29 }
30 
DistributedBmsHost()31 DistributedBmsHost::DistributedBmsHost()
32 {
33     APP_LOGI("DistributedBmsHost instance is created");
34 }
35 
~DistributedBmsHost()36 DistributedBmsHost::~DistributedBmsHost()
37 {
38     APP_LOGI("DistributedBmsHost instance is destroyed");
39 }
40 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)41 int DistributedBmsHost::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
42 {
43     BundleMemoryGuard memoryGuard;
44     APP_LOGI("DistributedBmsHost receives message from client, code = %{public}u, flags = %{public}d", code,
45         option.GetFlags());
46     std::u16string descripter = DistributedBmsHost::GetDescriptor();
47     std::u16string remoteDescripter = data.ReadInterfaceToken();
48     if (descripter != remoteDescripter) {
49         APP_LOGE("verify interface token failed");
50         return ERR_INVALID_STATE;
51     }
52     switch (code) {
53         case static_cast<uint32_t>(DistributedInterfaceCode::GET_REMOTE_ABILITY_INFO):
54         case static_cast<uint32_t>(DistributedInterfaceCode::GET_REMOTE_ABILITY_INFO_WITH_LOCALE):
55             return HandleGetRemoteAbilityInfo(data, reply);
56         case static_cast<uint32_t>(DistributedInterfaceCode::GET_REMOTE_ABILITY_INFOS):
57         case static_cast<uint32_t>(DistributedInterfaceCode::GET_REMOTE_ABILITY_INFOS_WITH_LOCALE):
58             return HandleGetRemoteAbilityInfos(data, reply);
59         case static_cast<uint32_t>(DistributedInterfaceCode::GET_ABILITY_INFO):
60         case static_cast<uint32_t>(DistributedInterfaceCode::GET_ABILITY_INFO_WITH_LOCALE):
61             return HandleGetAbilityInfo(data, reply);
62         case static_cast<uint32_t>(DistributedInterfaceCode::GET_ABILITY_INFOS):
63         case static_cast<uint32_t>(DistributedInterfaceCode::GET_ABILITY_INFOS_WITH_LOCALE):
64             return HandleGetAbilityInfos(data, reply);
65         case static_cast<uint32_t>(DistributedInterfaceCode::GET_DISTRIBUTED_BUNDLE_INFO):
66             return HandleGetDistributedBundleInfo(data, reply);
67         case static_cast<uint32_t>(DistributedInterfaceCode::GET_DISTRIBUTED_BUNDLE_NAME):
68             return HandleGetDistributedBundleName(data, reply);
69         default:
70             APP_LOGW("DistributedBmsHost receives unknown code, code = %{public}d", code);
71             return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
72     }
73     return NO_ERROR;
74 }
75 
HandleGetRemoteAbilityInfo(Parcel & data,Parcel & reply)76 int DistributedBmsHost::HandleGetRemoteAbilityInfo(Parcel &data, Parcel &reply)
77 {
78     APP_LOGI("DistributedBmsHost handle get remote ability info");
79     std::unique_ptr<ElementName> elementName(data.ReadParcelable<ElementName>());
80     if (!elementName) {
81         APP_LOGE("ReadParcelable<elementName> failed");
82         return ERR_APPEXECFWK_PARCEL_ERROR;
83     }
84     std::string localeInfo = data.ReadString();
85     RemoteAbilityInfo remoteAbilityInfo;
86     int ret = GetRemoteAbilityInfo(*elementName, localeInfo, remoteAbilityInfo);
87     if (ret != NO_ERROR) {
88         APP_LOGE("GetRemoteAbilityInfo result:%{public}d", ret);
89         return ret;
90     }
91     if (!reply.WriteBool(true)) {
92         APP_LOGE("GetRemoteAbilityInfo write failed");
93         return ERR_APPEXECFWK_PARCEL_ERROR;
94     }
95     if (!reply.WriteParcelable(&remoteAbilityInfo)) {
96         APP_LOGE("GetRemoteAbilityInfo write failed");
97         return ERR_APPEXECFWK_PARCEL_ERROR;
98     }
99     return NO_ERROR;
100 }
101 
HandleGetRemoteAbilityInfos(Parcel & data,Parcel & reply)102 int DistributedBmsHost::HandleGetRemoteAbilityInfos(Parcel &data, Parcel &reply)
103 {
104     APP_LOGI("DistributedBmsHost handle get remote ability infos");
105     std::vector<ElementName> elementNames;
106     if (!GetParcelableInfos<ElementName>(data, elementNames)) {
107         APP_LOGE("GetRemoteAbilityInfos get parcelable infos failed");
108         return ERR_APPEXECFWK_PARCEL_ERROR;
109     }
110     std::string localeInfo = data.ReadString();
111     std::vector<RemoteAbilityInfo> remoteAbilityInfos;
112     int ret = GetRemoteAbilityInfos(elementNames, localeInfo, remoteAbilityInfos);
113     if (ret != NO_ERROR) {
114         APP_LOGE("GetRemoteAbilityInfos result:%{public}d", ret);
115         return ret;
116     }
117     if (!reply.WriteBool(true)) {
118         APP_LOGE("GetRemoteAbilityInfos write failed");
119         return ERR_APPEXECFWK_PARCEL_ERROR;
120     }
121     if (!WriteParcelableVector<RemoteAbilityInfo>(remoteAbilityInfos, reply)) {
122         APP_LOGE("GetRemoteAbilityInfos write failed");
123         return ERR_APPEXECFWK_PARCEL_ERROR;
124     }
125     return NO_ERROR;
126 }
127 
128 
HandleGetAbilityInfo(Parcel & data,Parcel & reply)129 int DistributedBmsHost::HandleGetAbilityInfo(Parcel &data, Parcel &reply)
130 {
131     APP_LOGI("DistributedBmsHost handle get ability info");
132     std::unique_ptr<ElementName> elementName(data.ReadParcelable<ElementName>());
133     if (!elementName) {
134         APP_LOGE("ReadParcelable<elementName> failed");
135         return ERR_APPEXECFWK_PARCEL_ERROR;
136     }
137     std::string localeInfo = data.ReadString();
138     RemoteAbilityInfo remoteAbilityInfo;
139     int ret = GetAbilityInfo(*elementName, localeInfo, remoteAbilityInfo);
140     if (ret != NO_ERROR) {
141         APP_LOGE("GetAbilityInfo result:%{public}d", ret);
142         return ret;
143     }
144     if (!reply.WriteBool(true)) {
145         APP_LOGE("GetRemoteAbilityInfo write failed");
146         return ERR_APPEXECFWK_PARCEL_ERROR;
147     }
148     if (!reply.WriteParcelable(&remoteAbilityInfo)) {
149         APP_LOGE("GetRemoteAbilityInfo write failed");
150         return ERR_APPEXECFWK_PARCEL_ERROR;
151     }
152     return NO_ERROR;
153 }
154 
HandleGetAbilityInfos(Parcel & data,Parcel & reply)155 int DistributedBmsHost::HandleGetAbilityInfos(Parcel &data, Parcel &reply)
156 {
157     APP_LOGI("DistributedBmsHost handle get ability infos");
158     std::vector<ElementName> elementNames;
159     if (!GetParcelableInfos<ElementName>(data, elementNames)) {
160         APP_LOGE("GetRemoteAbilityInfos get parcelable infos failed");
161         return ERR_APPEXECFWK_PARCEL_ERROR;
162     }
163     std::string localeInfo = data.ReadString();
164     std::vector<RemoteAbilityInfo> remoteAbilityInfos;
165     int ret = GetAbilityInfos(elementNames, localeInfo, remoteAbilityInfos);
166     if (ret != NO_ERROR) {
167         APP_LOGE("GetAbilityInfos result:%{public}d", ret);
168         return ret;
169     }
170     if (!reply.WriteBool(true)) {
171         APP_LOGE("GetAbilityInfos write failed");
172         return ERR_APPEXECFWK_PARCEL_ERROR;
173     }
174     if (!WriteParcelableVector<RemoteAbilityInfo>(remoteAbilityInfos, reply)) {
175         APP_LOGE("GetAbilityInfos write failed");
176         return ERR_APPEXECFWK_PARCEL_ERROR;
177     }
178     return NO_ERROR;
179 }
180 
HandleGetDistributedBundleInfo(Parcel & data,Parcel & reply)181 int DistributedBmsHost::HandleGetDistributedBundleInfo(Parcel &data, Parcel &reply)
182 {
183     APP_LOGI("DistributedBmsHost handle get distributedBundleInfo");
184     std::string networkId = data.ReadString();
185     std::string bundleName = data.ReadString();
186     DistributedBundleInfo distributedBundleInfo;
187     bool ret = GetDistributedBundleInfo(networkId, bundleName, distributedBundleInfo);
188     if (!ret) {
189         APP_LOGE("GetDistributedBundleInfo failed");
190         return INVALID_OPERATION;
191     }
192     if (!reply.WriteBool(true)) {
193         APP_LOGE("GetDistributedBundleInfo write failed");
194         return ERR_APPEXECFWK_PARCEL_ERROR;
195     }
196     if (!reply.WriteParcelable(&distributedBundleInfo)) {
197         APP_LOGE("GetDistributedBundleInfo write failed");
198         return ERR_APPEXECFWK_PARCEL_ERROR;
199     }
200     return NO_ERROR;
201 }
202 
HandleGetDistributedBundleName(Parcel & data,Parcel & reply)203 int32_t DistributedBmsHost::HandleGetDistributedBundleName(Parcel &data, Parcel &reply)
204 {
205     APP_LOGD("DistributedBmsHost handle get distributedBundleName");
206     std::string networkId = data.ReadString();
207     uint32_t accessTokenId = data.ReadUint32();
208     std::string bundleName;
209     int32_t ret = GetDistributedBundleName(networkId, accessTokenId, bundleName);
210     if (ret == NO_ERROR && !reply.WriteString(bundleName)) {
211         APP_LOGE("write failed");
212         return ERR_APPEXECFWK_PARCEL_ERROR;
213     }
214     return ret;
215 }
216 
217 template<typename T>
WriteParcelableVector(std::vector<T> & parcelableVector,Parcel & reply)218 bool DistributedBmsHost::WriteParcelableVector(std::vector<T> &parcelableVector, Parcel &reply)
219 {
220     if (!reply.WriteInt32(parcelableVector.size())) {
221         APP_LOGE("write ParcelableVector failed");
222         return false;
223     }
224 
225     for (auto &parcelable : parcelableVector) {
226         if (!reply.WriteParcelable(&parcelable)) {
227             APP_LOGE("write ParcelableVector failed");
228             return false;
229         }
230     }
231     return true;
232 }
233 
234 template<typename T>
GetParcelableInfos(Parcel & data,std::vector<T> & parcelableInfos)235 bool DistributedBmsHost::GetParcelableInfos(Parcel &data, std::vector<T> &parcelableInfos)
236 {
237     int32_t infoSize = data.ReadInt32();
238     if (infoSize > GET_REMOTE_ABILITY_INFO_MAX_SIZE) {
239         APP_LOGE("GetParcelableInfos elements num exceeds the limit %{public}d", GET_REMOTE_ABILITY_INFO_MAX_SIZE);
240         return false;
241     }
242     for (int32_t i = 0; i < infoSize; i++) {
243         std::unique_ptr<T> info(data.ReadParcelable<T>());
244         if (!info) {
245             APP_LOGE("Read Parcelable infos failed");
246             return false;
247         }
248         parcelableInfos.emplace_back(*info);
249     }
250     APP_LOGD("get parcelable infos success");
251     return true;
252 }
253 }  // namespace AppExecFwk
254 }  // namespace OHOS