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 "client/ability_thread_client.h"
17
18 #define __STDC_FORMAT_MACROS
19 #include <cinttypes>
20
21 #include "ability_kit_command.h"
22 #include "adapter.h"
23 #include "app_manager.h"
24 #include "app_record.h"
25 #include "client/bundlems_client.h"
26 #include "element_name_utils.h"
27 #include "ipc_skeleton.h"
28 #include "rpc_errno.h"
29 #include "securec.h"
30 #include "util/abilityms_helper.h"
31 #include "utils.h"
32 #include "want_utils.h"
33
34 namespace OHOS {
35 const int MAX_MODULE_SIZE = 16;
AbilityThreadClient(uint64_t token,pid_t pid,const SvcIdentity & svcIdentity,OnRemoteDead handler)36 AbilityThreadClient::AbilityThreadClient(uint64_t token, pid_t pid, const SvcIdentity &svcIdentity,
37 OnRemoteDead handler) : token_(token), pid_(pid), svcIdentity_(svcIdentity), deathHandler_(handler)
38 {
39 }
40
AbilityThreadClient(const AbilityThreadClient & client)41 AbilityThreadClient::AbilityThreadClient(const AbilityThreadClient &client)
42 : token_(client.token_), pid_(client.pid_), svcIdentity_(client.svcIdentity_), deathHandler_(client.deathHandler_)
43 {
44 }
45
~AbilityThreadClient()46 AbilityThreadClient::~AbilityThreadClient()
47 {
48 }
49
Initialize(const char * bundleName)50 AbilityMsStatus AbilityThreadClient::Initialize(const char *bundleName)
51 {
52 if (bundleName == nullptr) {
53 return AbilityMsStatus::AppTransanctStatus("bundleName is null");
54 }
55 AppInfo *appInfo = new AppInfo();
56 appInfo->bundleName = Utils::Strdup(bundleName);
57 if (appInfo->bundleName == nullptr) {
58 delete appInfo;
59 return AbilityMsStatus::AppTransanctStatus("memory alloc fail");
60 }
61 appInfo->svcIdentity = svcIdentity_;
62 if (AddDeathRecipient(svcIdentity_, deathHandler_, appInfo, &cbid_) != 0) {
63 AdapterFree(appInfo->bundleName);
64 delete appInfo;
65 return AbilityMsStatus::AppTransanctStatus("register death callback ipc error");
66 }
67 PRINTD("AbilityThreadClient", "token(%{private}" PRIu64 ") bundleName(%{public}s) success",
68 token_, appInfo->bundleName);
69 return AbilityMsStatus::Ok();
70 }
71
GetToken() const72 uint64_t AbilityThreadClient::GetToken() const
73 {
74 return token_;
75 }
76
GetPid() const77 pid_t AbilityThreadClient::GetPid() const
78 {
79 return pid_;
80 }
81
GetSvcIdentity() const82 const SvcIdentity& AbilityThreadClient::GetSvcIdentity() const
83 {
84 return svcIdentity_;
85 }
86
AbilityTransaction(const TransactionState & state,const Want & want,AbilityType abilityType) const87 AbilityMsStatus AbilityThreadClient::AbilityTransaction(const TransactionState &state,
88 const Want &want, AbilityType abilityType) const
89 {
90 PRINTD("AbilityThreadClient", "start");
91 IpcIo req;
92 char data[MAX_IO_SIZE];
93 IpcIoInit(&req, data, MAX_IO_SIZE, MAX_OBJECTS);
94 WriteInt32(&req, state.state);
95 WriteUint64(&req, state.token);
96 WriteInt32(&req, abilityType);
97 if (!SerializeWant(&req, &want)) {
98 return AbilityMsStatus::AppTransanctStatus("SerializeWant failed");
99 }
100 MessageOption option;
101 MessageOptionInit(&option);
102 option.flags = TF_OP_ASYNC;
103 int32_t ret = SendRequest(svcIdentity_, SCHEDULER_ABILITY_LIFECYCLE, &req,
104 nullptr, option, nullptr);
105 if (ret != ERR_NONE) {
106 return AbilityMsStatus::AppTransanctStatus("lifecycle ipc error");
107 }
108 return AbilityMsStatus::Ok();
109 }
110
AppInitTransaction(const BundleInfo & bundleInfo)111 AbilityMsStatus AbilityThreadClient::AppInitTransaction(const BundleInfo &bundleInfo)
112 {
113 PRINTD("AbilityThreadClient", "start");
114 if (bundleInfo.bundleName == nullptr || bundleInfo.codePath == nullptr ||
115 bundleInfo.numOfModule > MAX_MODULE_SIZE) {
116 return AbilityMsStatus::AppTransanctStatus("app init invalid argument");
117 }
118 IpcIo req;
119 char data[MAX_IO_SIZE];
120 IpcIoInit(&req, data, MAX_IO_SIZE, 0);
121 WriteString(&req, bundleInfo.bundleName);
122 WriteString(&req, bundleInfo.codePath);
123 WriteString(&req, bundleInfo.dataPath);
124 WriteBool(&req, bundleInfo.isNativeApp);
125 // transact moduleName
126 WriteInt32(&req, bundleInfo.numOfModule);
127 for (int i = 0; i < bundleInfo.numOfModule; i++) {
128 if (bundleInfo.moduleInfos[i].moduleName != nullptr) {
129 WriteString(&req, bundleInfo.moduleInfos[i].moduleName);
130 }
131 }
132 IpcIo reply;
133 uintptr_t ptr;
134 MessageOption option;
135 MessageOptionInit(&option);
136 if (SendRequest(svcIdentity_, SCHEDULER_APP_INIT, &req,
137 &reply, option, &ptr) != ERR_NONE) {
138 return AbilityMsStatus::AppTransanctStatus("app init ipc error");
139 }
140 FreeBuffer((void *)ptr);
141 return AbilityMsStatus::Ok();
142 }
143
AppExitTransaction()144 AbilityMsStatus AbilityThreadClient::AppExitTransaction()
145 {
146 PRINTD("AbilityThreadClient", "start");
147 MessageOption option;
148 MessageOptionInit(&option);
149 option.flags = TF_OP_ASYNC;
150 if (SendRequest(svcIdentity_, SCHEDULER_APP_EXIT, nullptr,
151 nullptr, option, nullptr) != ERR_NONE) {
152 return AbilityMsStatus::AppTransanctStatus("app exit ipc error");
153 }
154 return AbilityMsStatus::Ok();
155 }
156
ConnectAbility(const Want & want,uint64_t token) const157 AbilityMsStatus AbilityThreadClient::ConnectAbility(const Want &want, uint64_t token) const
158 {
159 PRINTD("AbilityThreadClient", "connect");
160 IpcIo req;
161 char data[MAX_IO_SIZE];
162 IpcIoInit(&req, data, MAX_IO_SIZE, MAX_OBJECTS);
163 WriteUint64(&req, token);
164 if (!SerializeWant(&req, &want)) {
165 return AbilityMsStatus::TaskStatus("connectAbility", "SerializeWant failed");
166 }
167 MessageOption option;
168 MessageOptionInit(&option);
169 option.flags = TF_OP_ASYNC;
170 if (SendRequest(svcIdentity_, SCHEDULER_ABILITY_CONNECT, &req, nullptr,
171 option, nullptr) != ERR_NONE) {
172 return AbilityMsStatus::TaskStatus("connectAbility", "connectAbility exit ipc error");
173 }
174 return AbilityMsStatus::Ok();
175 }
176
DisconnectAbility(const Want & want,uint64_t token) const177 AbilityMsStatus AbilityThreadClient::DisconnectAbility(const Want &want, uint64_t token) const
178 {
179 PRINTD("AbilityThreadClient", "disconnect");
180 IpcIo req;
181 char data[MAX_IO_SIZE];
182 IpcIoInit(&req, data, MAX_IO_SIZE, MAX_OBJECTS);
183 WriteUint64(&req, token);
184 if (!SerializeWant(&req, &want)) {
185 return AbilityMsStatus::TaskStatus("disconnectAbility", "SerializeWant failed");
186 }
187 MessageOption option;
188 MessageOptionInit(&option);
189 option.flags = TF_OP_ASYNC;
190 if (SendRequest(svcIdentity_, SCHEDULER_ABILITY_DISCONNECT, &req, nullptr,
191 option, nullptr) != ERR_NONE) {
192 return AbilityMsStatus::TaskStatus("disconnectAbility", "disconnectAbility exit ipc error");
193 }
194 return AbilityMsStatus::Ok();
195 }
196
ConnectAbilityDone(const Want & want,const SvcIdentity & serviceSid,const SvcIdentity & connectSid) const197 AbilityMsStatus AbilityThreadClient::ConnectAbilityDone(const Want &want, const SvcIdentity &serviceSid,
198 const SvcIdentity &connectSid) const
199 {
200 PRINTD("AbilityThreadClient", "connectDone");
201 IpcIo req;
202 char data[MAX_IO_SIZE];
203 IpcIoInit(&req, data, MAX_IO_SIZE, 1);
204 bool ret = WriteRemoteObject(&req, &serviceSid);
205 if (!ret) {
206 return AbilityMsStatus::TaskStatus("connectAbilityDone", "WriteRemoteObject failed");
207 }
208 if (!SerializeElement(&req, want.element)) {
209 return AbilityMsStatus::TaskStatus("connectAbilityDone", "SerializeElement failed");
210 }
211
212 MessageOption option;
213 MessageOptionInit(&option);
214 option.flags = TF_OP_ASYNC;
215 if (SendRequest(connectSid, SCHEDULER_ABILITY_CONNECT, &req, nullptr,
216 option, nullptr) != ERR_NONE) {
217 return AbilityMsStatus::TaskStatus("connectAbilityDone", "connectAbilityDone ipc error");
218 }
219 return AbilityMsStatus::Ok();
220 }
221
DisconnectAbilityDone(const Want & want,const SvcIdentity & connectSid) const222 AbilityMsStatus AbilityThreadClient::DisconnectAbilityDone(const Want &want, const SvcIdentity &connectSid) const
223 {
224 PRINTD("AbilityThreadClient", "disconnectDone");
225 IpcIo req;
226 char data[MAX_IO_SIZE];
227 IpcIoInit(&req, data, MAX_IO_SIZE, 0);
228 if (!SerializeElement(&req, want.element)) {
229 return AbilityMsStatus::TaskStatus("DisconnectAbilityDone", "SerializeElement failed");
230 }
231
232 MessageOption option;
233 MessageOptionInit(&option);
234 option.flags = TF_OP_ASYNC;
235 if (SendRequest(connectSid, SCHEDULER_ABILITY_DISCONNECT, &req,
236 nullptr, option, nullptr) != ERR_NONE) {
237 ReleaseSvc(connectSid);
238 return AbilityMsStatus::TaskStatus("disconnectAbilityDone", "disconnectAbilityDone ipc error");
239 }
240 ReleaseSvc(connectSid);
241 return AbilityMsStatus::Ok();
242 }
243
DumpAbilityTransaction(const Want & want,uint64_t token)244 AbilityMsStatus AbilityThreadClient::DumpAbilityTransaction(const Want &want, uint64_t token)
245 {
246 PRINTD("AbilityThreadClient", "start");
247 IpcIo req;
248 char data[MAX_IO_SIZE];
249 IpcIoInit(&req, data, MAX_IO_SIZE, MAX_OBJECTS);
250 if (!SerializeWant(&req, &want)) {
251 return AbilityMsStatus::TaskStatus("dumpAbility", "SerializeWant failed");
252 }
253 MessageOption option;
254 MessageOptionInit(&option);
255 option.flags = TF_OP_ASYNC;
256 if (SendRequest(svcIdentity_, SCHEDULER_DUMP_ABILITY, &req,
257 nullptr, option, nullptr) != ERR_NONE) {
258 return AbilityMsStatus::AppTransanctStatus("dump ability ipc error");
259 }
260 return AbilityMsStatus::Ok();
261 }
262 }
263