1 /*
2 * Copyright (c) 2020 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_callback.h"
17
18 #include "adapter.h"
19 #include "bundle_callback_utils.h"
20 #include "bundle_inner_interface.h"
21 #include "bundle_manager.h"
22 #include "iproxy_client.h"
23 #include "log.h"
24 #include "ohos_types.h"
25 #include "samgr_lite.h"
26
27 namespace OHOS {
~BundleCallback()28 BundleCallback::~BundleCallback()
29 {
30 if (svcIdentity_ != nullptr) {
31 UnregisterIpcCallback(*svcIdentity_);
32 TransmitServiceId(*svcIdentity_, false);
33 AdapterFree(svcIdentity_);
34 }
35 callbackMap_.clear();
36 }
37
Notify(IOwner owner,int code,IpcIo * reply)38 static int Notify(IOwner owner, int code, IpcIo *reply)
39 {
40 if ((reply == nullptr) || (owner == nullptr)) {
41 return EC_INVALID;
42 }
43 if (IpcIoPopUint8(reply) != CHANGE_CALLBACK_SERVICE_IDENTITY) {
44 return EC_INVALID;
45 }
46 uint8_t *result = reinterpret_cast<uint8_t *>(owner);
47 *result = IpcIoPopUint8(reply);
48 return EC_SUCCESS;
49 }
50
InnerCallback(uint32_t installType,uint8_t resultCode,const char * bundleName)51 int32_t InnerCallback(uint32_t installType, uint8_t resultCode, const char *bundleName)
52 {
53 if (bundleName == nullptr) {
54 return ERR_APPEXECFWK_OBJECT_NULL;
55 }
56 BundleCallbackInfo callbackInfo = BundleCallback::GetInstance().GetCallbackInfoByName(bundleName);
57 BundleStateCallback callback = callbackInfo.bundleStateCallback;
58 if (callback == nullptr) {
59 HILOG_ERROR(HILOG_MODULE_APP, "InnerCallback is nullptr");
60 return ERR_APPEXECFWK_CALLBACK_NULL_CORRESPONDING_CALLBACK;
61 }
62
63 if (resultCode != ERR_OK) {
64 callback(installType, resultCode, ObtainErrorMessage(resultCode).c_str(), bundleName, callbackInfo.data);
65 return ERR_OK;
66 }
67
68 if (installType == INSTALL_CALLBACK) {
69 callback(installType, resultCode, INSTALL_SUCCESS, bundleName, callbackInfo.data);
70 return ERR_OK;
71 }
72
73 if (installType == UNINSTALL_CALLBACK) {
74 callback(installType, resultCode, UNINSTALL_SUCCESS, bundleName, callbackInfo.data);
75 return ERR_OK;
76 }
77 HILOG_ERROR(HILOG_MODULE_APP, "param installType is invalid!");
78 return ERR_APPEXECFWK_CALLBACK_GET_ERROR_INSTALLTYPE;
79 }
80
Callback(const IpcContext * context,void * ipcMsg,IpcIo * io,void * arg)81 static int32_t Callback(const IpcContext* context, void *ipcMsg, IpcIo *io, void *arg)
82 {
83 // at here, arg is always been nullptr
84 if (ipcMsg == nullptr) {
85 HILOG_ERROR(HILOG_MODULE_APP, "BundleCallback ipcMsg is nullptr");
86 return ERR_APPEXECFWK_OBJECT_NULL;
87 }
88
89 if (io == nullptr) {
90 HILOG_ERROR(HILOG_MODULE_APP, "BundleCallback io is nullptr");
91 FreeBuffer(NULL, ipcMsg);
92 return ERR_APPEXECFWK_OBJECT_NULL;
93 }
94
95 uint32_t installType = 0;
96 int32_t ret = GetCode(ipcMsg, &installType);
97 if (ret != LITEIPC_OK) {
98 FreeBuffer(NULL, ipcMsg);
99 HILOG_ERROR(HILOG_MODULE_APP, "BundleCallback Get install type failed");
100 return ERR_APPEXECFWK_CALLBACK_GET_INSTALLTYPE_FAILED;
101 }
102 if ((installType == INSTALL_CALLBACK) || (installType == UNINSTALL_CALLBACK)) {
103 uint8_t resultCode = static_cast<uint8_t>(IpcIoPopInt32(io));
104 size_t size = 0;
105 char *bundleName = reinterpret_cast<char *>(IpcIoPopString(io, &size));
106 ret = InnerCallback(installType, resultCode, bundleName);
107 FreeBuffer(NULL, ipcMsg);
108 return ret;
109 }
110 FreeBuffer(NULL, ipcMsg);
111 HILOG_ERROR(HILOG_MODULE_APP, "BundleSelfCallback get error install type");
112 return ERR_APPEXECFWK_CALLBACK_GET_ERROR_INSTALLTYPE;
113 }
114
TransmitServiceId(const SvcIdentity & svc,bool flag)115 int32_t BundleCallback::TransmitServiceId(const SvcIdentity &svc, bool flag)
116 {
117 IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(BMS_SERVICE, BMS_FEATURE);
118 if (iUnknown == nullptr) {
119 return ERR_APPEXECFWK_CALLBACK_SERVICEID_TRANSMITTED_FAILED;
120 }
121 IClientProxy *bmsClient = nullptr;
122 int32_t result = iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, reinterpret_cast<void **>(&bmsClient));
123 if ((result != 0) || (bmsClient == nullptr)) {
124 return ERR_APPEXECFWK_CALLBACK_SERVICEID_TRANSMITTED_FAILED;
125 }
126 IpcIo ipcIo;
127 uint32_t data[IPC_IO_DATA_MAX];
128 IpcIoInit(&ipcIo, data, IPC_IO_DATA_MAX, 1);
129 IpcIoPushBool(&ipcIo, flag);
130 IpcIoPushSvc(&ipcIo, &svc);
131 if (!IpcIoAvailable(&ipcIo)) {
132 HILOG_ERROR(HILOG_MODULE_APP, "BundleCallback TransmitServiceId ipc failed");
133 return ERR_APPEXECFWK_IPCIO_UNAVAILABLED;
134 }
135 uint8_t errorCode = 0;
136 int32_t ret = bmsClient->Invoke(bmsClient, CHANGE_CALLBACK_SERVICE_IDENTITY, &ipcIo, &errorCode, Notify);
137 if (ret != OHOS_SUCCESS) {
138 HILOG_ERROR(HILOG_MODULE_APP, "TransmitServiceId calling Invoke function failed: %{public}d", ret);
139 return ERR_APPEXECFWK_INVOKE_ERROR;
140 }
141
142 return errorCode;
143 }
144
GenerateLocalServiceId()145 int32_t BundleCallback::GenerateLocalServiceId()
146 {
147 if (svcIdentity_ != nullptr) {
148 return ERR_OK;
149 }
150 svcIdentity_ = reinterpret_cast<SvcIdentity *>(AdapterMalloc(sizeof(SvcIdentity)));
151 if (svcIdentity_ == nullptr) {
152 return ERR_APPEXECFWK_CALLBACK_GENERATE_LOCAL_SERVICEID_FAILED;
153 }
154 int32_t ret = RegisterIpcCallback(Callback, 0, IPC_WAIT_FOREVER, svcIdentity_, NULL);
155 if ((ret != LITEIPC_OK)) {
156 AdapterFree(svcIdentity_);
157 return ERR_APPEXECFWK_CALLBACK_GENERATE_LOCAL_SERVICEID_FAILED;
158 }
159 ret = TransmitServiceId(*svcIdentity_, true);
160 if (ret != ERR_OK) {
161 UnregisterIpcCallback(*svcIdentity_);
162 AdapterFree(svcIdentity_);
163 return ERR_APPEXECFWK_CALLBACK_SERVICEID_TRANSMITTED_FAILED;
164 }
165 return ERR_OK;
166 }
167
168 // register callback by bundle name
RegisterBundleStateCallback(const BundleStateCallback & callback,const char * bundleName,void * data)169 int32_t BundleCallback::RegisterBundleStateCallback(const BundleStateCallback &callback,
170 const char *bundleName, void *data)
171 {
172 int32_t ret = GenerateLocalServiceId();
173 if (ret != ERR_OK) {
174 return ERR_APPEXECFWK_CALLBACK_GENERATE_LOCAL_SERVICEID_FAILED;
175 }
176
177 if ((bundleName == nullptr) || (strlen(bundleName) == 0)) {
178 // monitor all applications by the callback function bundleStateCallback_
179 bundleStateCallback_ = callback;
180 innerData_ = data;
181 callbackMap_.clear();
182 return ERR_OK;
183 }
184 // already monitor all applications
185 if (bundleStateCallback_ != nullptr) {
186 return ERR_OK;
187 }
188 std::string innerBundleName = bundleName;
189 auto it = callbackMap_.find(innerBundleName);
190 if (it != callbackMap_.end()) {
191 // already monitor the application
192 it->second.bundleStateCallback = callback;
193 it->second.data = data;
194 return ERR_OK;
195 }
196 BundleCallbackInfo bundleCallbackInfo;
197 bundleCallbackInfo.bundleStateCallback = callback;
198 bundleCallbackInfo.data = data;
199 callbackMap_.emplace(bundleName, bundleCallbackInfo);
200 return ERR_OK;
201 }
202
203 // unregister callback of all application
UnregisterBundleStateCallback()204 int32_t BundleCallback::UnregisterBundleStateCallback()
205 {
206 if (svcIdentity_ == nullptr) {
207 return ERR_APPEXECFWK_CALLBACK_UNREGISTER_FAILED;
208 }
209
210 bundleStateCallback_ = nullptr;
211 innerData_ = nullptr;
212 callbackMap_.clear();
213 (void) TransmitServiceId(*svcIdentity_, false);
214 (void) UnregisterIpcCallback(*svcIdentity_);
215 AdapterFree(svcIdentity_);
216 return ERR_OK;
217 }
218
GetCallbackInfoByName(const char * bundleName)219 BundleCallbackInfo BundleCallback::GetCallbackInfoByName(const char *bundleName)
220 {
221 BundleCallbackInfo innerCallbackInfo = { nullptr, nullptr };
222 if ((bundleName == nullptr) || (strlen(bundleName) == 0)) {
223 return innerCallbackInfo;
224 }
225
226 if (bundleStateCallback_ != nullptr) {
227 innerCallbackInfo.bundleStateCallback = bundleStateCallback_;
228 innerCallbackInfo.data = innerData_;
229 return innerCallbackInfo;
230 }
231 std::string innerBundleName = bundleName;
232 auto it = callbackMap_.find(innerBundleName);
233 if (it == callbackMap_.end()) {
234 return innerCallbackInfo;
235 }
236 return it->second;
237 }
238 } // namespace OHOS
239