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