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 "bundle_log.h"
24 #include "ohos_types.h"
25 #include "samgr_lite.h"
26 #include "rpc_errno.h"
27
28 namespace OHOS {
~BundleCallback()29 BundleCallback::~BundleCallback()
30 {
31 if (svcIdentity_ != nullptr) {
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 uint8_t cmd;
44 ReadUint8(reply, &cmd);
45 if (cmd != CHANGE_CALLBACK_SERVICE_IDENTITY) {
46 return EC_INVALID;
47 }
48 uint8_t *result = reinterpret_cast<uint8_t *>(owner);
49 ReadUint8(reply, result);
50 return EC_SUCCESS;
51 }
52
InnerCallback(uint32_t installType,uint8_t resultCode,const char * bundleName)53 int32_t InnerCallback(uint32_t installType, uint8_t resultCode, const char *bundleName)
54 {
55 if (bundleName == nullptr) {
56 return ERR_APPEXECFWK_OBJECT_NULL;
57 }
58 BundleCallbackInfo callbackInfo = BundleCallback::GetInstance().GetCallbackInfoByName(bundleName);
59 BundleStateCallback callback = callbackInfo.bundleStateCallback;
60 if (callback == nullptr) {
61 HILOG_ERROR(HILOG_MODULE_APP, "InnerCallback is nullptr");
62 return ERR_APPEXECFWK_CALLBACK_NULL_CORRESPONDING_CALLBACK;
63 }
64
65 if (resultCode != ERR_OK) {
66 callback(installType, resultCode, ObtainErrorMessage(resultCode).c_str(), bundleName, callbackInfo.data);
67 return ERR_OK;
68 }
69
70 if (installType == INSTALL_CALLBACK) {
71 callback(installType, resultCode, INSTALL_SUCCESS, bundleName, callbackInfo.data);
72 return ERR_OK;
73 }
74
75 if (installType == UNINSTALL_CALLBACK) {
76 callback(installType, resultCode, UNINSTALL_SUCCESS, bundleName, callbackInfo.data);
77 return ERR_OK;
78 }
79 HILOG_ERROR(HILOG_MODULE_APP, "param installType is invalid!");
80 return ERR_APPEXECFWK_CALLBACK_GET_ERROR_INSTALLTYPE;
81 }
82
Callback(uint32_t code,IpcIo * data,IpcIo * reply,MessageOption option)83 static int32_t Callback(uint32_t code, IpcIo* data, IpcIo* reply, MessageOption option)
84 {
85 if (data == nullptr) {
86 HILOG_ERROR(HILOG_MODULE_APP, "BundleCallback data is nullptr");
87 return ERR_APPEXECFWK_OBJECT_NULL;
88 }
89
90 if ((code == INSTALL_CALLBACK) || (code == UNINSTALL_CALLBACK)) {
91 int32_t readCode;
92 ReadInt32(data, &readCode);
93 uint8_t resultCode = static_cast<uint8_t>(readCode);
94 size_t size = 0;
95 char *bundleName = reinterpret_cast<char *>(ReadString(data, &size));
96 int32_t ret = InnerCallback(code, resultCode, bundleName);
97 return ret;
98 }
99 HILOG_ERROR(HILOG_MODULE_APP, "BundleSelfCallback get error install type");
100 return ERR_APPEXECFWK_CALLBACK_GET_ERROR_INSTALLTYPE;
101 }
102
TransmitServiceId(const SvcIdentity & svc,bool flag)103 int32_t BundleCallback::TransmitServiceId(const SvcIdentity &svc, bool flag)
104 {
105 IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(BMS_SERVICE, BMS_FEATURE);
106 if (iUnknown == nullptr) {
107 return ERR_APPEXECFWK_CALLBACK_SERVICEID_TRANSMITTED_FAILED;
108 }
109 IClientProxy *bmsClient = nullptr;
110 int32_t result = iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, reinterpret_cast<void **>(&bmsClient));
111 if ((result != 0) || (bmsClient == nullptr)) {
112 return ERR_APPEXECFWK_CALLBACK_SERVICEID_TRANSMITTED_FAILED;
113 }
114 IpcIo ipcIo;
115 uint32_t data[MAX_IO_SIZE];
116 IpcIoInit(&ipcIo, data, MAX_IO_SIZE, 1);
117 WriteBool(&ipcIo, flag);
118 bool writeRemote = WriteRemoteObject(&ipcIo, &svc);
119 if (!writeRemote) {
120 HILOG_ERROR(HILOG_MODULE_APP, "BundleCallback TransmitServiceId ipc failed");
121 return ERR_APPEXECFWK_IPCIO_UNAVAILABLED;
122 }
123 uint8_t errorCode = 0;
124 int32_t ret = bmsClient->Invoke(bmsClient, CHANGE_CALLBACK_SERVICE_IDENTITY, &ipcIo, &errorCode, Notify);
125 if (ret != OHOS_SUCCESS) {
126 HILOG_ERROR(HILOG_MODULE_APP, "TransmitServiceId calling Invoke function failed: %{public}d", ret);
127 return ERR_APPEXECFWK_INVOKE_ERROR;
128 }
129
130 return errorCode;
131 }
132
GenerateLocalServiceId()133 int32_t BundleCallback::GenerateLocalServiceId()
134 {
135 if (svcIdentity_ != nullptr) {
136 return ERR_OK;
137 }
138 svcIdentity_ = reinterpret_cast<SvcIdentity *>(AdapterMalloc(sizeof(SvcIdentity)));
139 if (svcIdentity_ == nullptr) {
140 return ERR_APPEXECFWK_CALLBACK_GENERATE_LOCAL_SERVICEID_FAILED;
141 }
142
143 objectStub_.func = Callback;
144 objectStub_.args = nullptr;
145 objectStub_.isRemote = false;
146
147 svcIdentity_->handle = IPC_INVALID_HANDLE;
148 svcIdentity_->token = SERVICE_TYPE_ANONYMOUS;
149 svcIdentity_->cookie = (uintptr_t)&objectStub_;
150
151 int32_t ret = TransmitServiceId(*svcIdentity_, true);
152 if (ret != ERR_OK) {
153 AdapterFree(svcIdentity_);
154 return ERR_APPEXECFWK_CALLBACK_SERVICEID_TRANSMITTED_FAILED;
155 }
156 return ERR_OK;
157 }
158
159 // register callback by bundle name
RegisterBundleStateCallback(const BundleStateCallback & callback,const char * bundleName,void * data)160 int32_t BundleCallback::RegisterBundleStateCallback(const BundleStateCallback &callback,
161 const char *bundleName, void *data)
162 {
163 int32_t ret = GenerateLocalServiceId();
164 if (ret != ERR_OK) {
165 return ERR_APPEXECFWK_CALLBACK_GENERATE_LOCAL_SERVICEID_FAILED;
166 }
167
168 if ((bundleName == nullptr) || (strlen(bundleName) == 0)) {
169 // monitor all applications by the callback function bundleStateCallback_
170 bundleStateCallback_ = callback;
171 innerData_ = data;
172 callbackMap_.clear();
173 return ERR_OK;
174 }
175 // already monitor all applications
176 if (bundleStateCallback_ != nullptr) {
177 return ERR_OK;
178 }
179 std::string innerBundleName = bundleName;
180 auto it = callbackMap_.find(innerBundleName);
181 if (it != callbackMap_.end()) {
182 // already monitor the application
183 it->second.bundleStateCallback = callback;
184 it->second.data = data;
185 return ERR_OK;
186 }
187 BundleCallbackInfo bundleCallbackInfo;
188 bundleCallbackInfo.bundleStateCallback = callback;
189 bundleCallbackInfo.data = data;
190 callbackMap_.emplace(bundleName, bundleCallbackInfo);
191 return ERR_OK;
192 }
193
194 // unregister callback of all application
UnregisterBundleStateCallback()195 int32_t BundleCallback::UnregisterBundleStateCallback()
196 {
197 if (svcIdentity_ == nullptr) {
198 return ERR_APPEXECFWK_CALLBACK_UNREGISTER_FAILED;
199 }
200
201 bundleStateCallback_ = nullptr;
202 innerData_ = nullptr;
203 callbackMap_.clear();
204 (void) TransmitServiceId(*svcIdentity_, false);
205 AdapterFree(svcIdentity_);
206 return ERR_OK;
207 }
208
GetCallbackInfoByName(const char * bundleName)209 BundleCallbackInfo BundleCallback::GetCallbackInfoByName(const char *bundleName)
210 {
211 BundleCallbackInfo innerCallbackInfo = { nullptr, nullptr };
212 if ((bundleName == nullptr) || (strlen(bundleName) == 0)) {
213 return innerCallbackInfo;
214 }
215
216 if (bundleStateCallback_ != nullptr) {
217 innerCallbackInfo.bundleStateCallback = bundleStateCallback_;
218 innerCallbackInfo.data = innerData_;
219 return innerCallbackInfo;
220 }
221 std::string innerBundleName = bundleName;
222 auto it = callbackMap_.find(innerBundleName);
223 if (it == callbackMap_.end()) {
224 return innerCallbackInfo;
225 }
226 return it->second;
227 }
228 } // namespace OHOS
229