1 /*
2  * Copyright (c) 2021 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 "abilityms_slite_client.h"
17 
18 #include "ability_errors.h"
19 #include "abilityms_log.h"
20 #include "adapter.h"
21 #include "cmsis_os2.h"
22 #include "los_task.h"
23 #include "samgr_lite.h"
24 #include "securec.h"
25 #include "want.h"
26 #include "utils.h"
27 
28 namespace OHOS {
29 namespace AbilitySlite {
Initialize() const30 bool AbilityMsClient::Initialize() const
31 {
32     if (amsProxy_ != nullptr) {
33         return true;
34     }
35     int retry = RETRY_TIMES;
36     while (retry--) {
37         IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(AMS_SERVICE, AMS_SLITE_FEATURE);
38         if (iUnknown == nullptr) {
39             HILOG_ERROR(HILOG_MODULE_APP, "iUnknown is null");
40             osDelay(ERROR_SLEEP_TIMES); // sleep 300ms
41             continue;
42         }
43 
44         (void)iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&amsProxy_);
45         if (amsProxy_ == nullptr) {
46             HILOG_ERROR(HILOG_MODULE_APP, "ams proxy is null");
47             osDelay(ERROR_SLEEP_TIMES); // sleep 300ms
48             continue;
49         }
50         return true;
51     }
52     return false;
53 }
54 
SendRequestToAms(Request & request) const55 int32_t AbilityMsClient::SendRequestToAms(Request &request) const
56 {
57     int32_t retry = RETRY_TIMES;
58     while (retry--) {
59         int32_t ret = SAMGR_SendRequest(identity_, &request, nullptr);
60         if (ret == EC_SUCCESS) {
61             return ERR_OK;
62         }
63         HILOG_WARN(HILOG_MODULE_APP, "SendRequestToAms SAMGR_SendRequest failed with %{public}d", ret);
64         osDelay(ERROR_SLEEP_TIMES); // sleep 300ms
65     }
66     HILOG_ERROR(HILOG_MODULE_APP, "SendRequestToAms failed.");
67     return IPC_REQUEST_ERROR;
68 }
69 
StartAbility(const Want * want) const70 int32_t AbilityMsClient::StartAbility(const Want *want) const
71 {
72     if (want == nullptr || want->element == nullptr || !Initialize()) {
73         return PARAM_CHECK_ERROR;
74     }
75 
76     if (identity_ == nullptr) {
77         return PARAM_CHECK_ERROR;
78     }
79 
80     // The data and info will be freed in the service
81     auto *data = static_cast<StartAbilityData *>(AdapterMalloc(sizeof(StartAbilityData)));
82     if (data == nullptr) {
83         return MEMORY_MALLOC_ERROR;
84     }
85     Want *info = static_cast<Want *>(AdapterMalloc(sizeof(Want)));
86     if (info == nullptr) {
87         return MEMORY_MALLOC_ERROR;
88     }
89     info->element = nullptr;
90     info->data = nullptr;
91     info->dataLength = 0;
92     info->appPath = nullptr;
93     info->mission = want->mission;
94     info->actions = nullptr;
95     info->entities = nullptr;
96     SetWantElement(info, *(want->element));
97     if (want->data != nullptr) {
98         HILOG_INFO(HILOG_MODULE_APP, "start ability with input data");
99         SetWantData(info, want->data, want->dataLength);
100     } else {
101         SetWantData(info, nullptr, 0);
102         HILOG_INFO(HILOG_MODULE_APP, "start ability with no data");
103     }
104     data->want = info;
105     data->curTask = LOS_CurTaskIDGet();
106     Request request = {
107         .msgId = START_ABILITY,
108         .len = sizeof(StartAbilityData),
109         .data = data,
110         .msgValue = 0,
111     };
112     return SendRequestToAms(request);
113 }
114 
TerminateAbility(uint64_t token) const115 int32_t AbilityMsClient::TerminateAbility(uint64_t token) const
116 {
117     if (identity_ == nullptr) {
118         return PARAM_CHECK_ERROR;
119     }
120     Request request = {
121         .msgId = TERMINATE_ABILITY,
122         .len = 0,
123         .data = nullptr,
124         .msgValue = static_cast<uint32_t>(token & TRANSACTION_MSG_TOKEN_MASK),
125     };
126     return SendRequestToAms(request);
127 }
128 
TerminateMission(uint32_t mission) const129 int32_t AbilityMsClient::TerminateMission(uint32_t mission) const
130 {
131     Request request = {
132         .msgId = TERMINATE_MISSION,
133         .len = 0,
134         .data = nullptr,
135         .msgValue = mission,
136     };
137     return SendRequestToAms(request);
138 }
139 
TerminateAll(const char * excludedBundleName) const140 int32_t AbilityMsClient::TerminateAll(const char* excludedBundleName) const
141 {
142     if (identity_ == nullptr) {
143         return PARAM_CHECK_ERROR;
144     }
145     void *data = nullptr;
146     if (excludedBundleName != nullptr) {
147         data = Utils::Strdup(excludedBundleName);
148     }
149     Request request = {
150         .msgId = TERMINATE_ALL,
151         .len = 0,
152         .data = data,
153         .msgValue = 0,
154     };
155     return SendRequestToAms(request);
156 }
157 
SchedulerLifecycleDone(uint64_t token,int32_t state) const158 int32_t AbilityMsClient::SchedulerLifecycleDone(uint64_t token, int32_t state) const
159 {
160     if (identity_ == nullptr) {
161         return PARAM_CHECK_ERROR;
162     }
163     Request request = {
164         .msgId = ABILITY_TRANSACTION_DONE,
165         .len = 0,
166         .data = nullptr,
167         .msgValue = static_cast<uint32_t>((token & TRANSACTION_MSG_TOKEN_MASK) |
168                                           (state << TRANSACTION_MSG_STATE_OFFSET)),
169     };
170     return SendRequestToAms(request);
171 }
172 
ForceStopBundle(uint64_t token) const173 int32_t AbilityMsClient::ForceStopBundle(uint64_t token) const
174 {
175     if (identity_ == nullptr) {
176         return PARAM_CHECK_ERROR;
177     }
178     Request request = {
179         .msgId = TERMINATE_APP,
180         .len = 0,
181         .data = nullptr,
182         .msgValue = static_cast<uint32_t>(token & TRANSACTION_MSG_TOKEN_MASK),
183     };
184     return SendRequestToAms(request);
185 }
186 
GetTopAbility() const187 ElementName *AbilityMsClient::GetTopAbility() const
188 {
189     if (!Initialize()) {
190         return nullptr;
191     }
192     return amsProxy_->GetTopAbility();
193 }
194 
ForceStop(const char * bundleName) const195 int32_t AbilityMsClient::ForceStop(const char *bundleName) const
196 {
197     if (identity_ == nullptr) {
198         return PARAM_CHECK_ERROR;
199     }
200     Want *want = static_cast<Want *>(AdapterMalloc(sizeof(Want)));
201     if (want == nullptr) {
202         return MEMORY_MALLOC_ERROR;
203     }
204     want->element = reinterpret_cast<ElementName *>(AdapterMalloc(sizeof(ElementName)));
205     if (want->element == nullptr) {
206         return MEMORY_MALLOC_ERROR;
207     }
208     HILOG_INFO(HILOG_MODULE_APP, "ForceStop with bundleName");
209     want->element->deviceId = nullptr;
210     want->element->bundleName = Utils::Strdup(bundleName);
211     want->element->abilityName = nullptr;
212     want->data = nullptr;
213     want->dataLength = 0;
214     want->appPath = nullptr;
215     want->actions = nullptr;
216     want->entities = nullptr;
217     SetWantData(want, nullptr, 0);
218     Request request = {
219         .msgId = TERMINATE_APP_BY_BUNDLENAME,
220         .len = sizeof(Want),
221         .data = want,
222     };
223     return SendRequestToAms(request);
224 }
225 
ForceStop(const Want * want) const226 int32_t AbilityMsClient::ForceStop(const Want *want) const
227 {
228     if (identity_ == nullptr) {
229         return PARAM_CHECK_ERROR;
230     }
231     if (want == nullptr || want->element == nullptr || want->element->bundleName == nullptr) {
232         return PARAM_CHECK_ERROR;
233     }
234     Want *info = static_cast<Want *>(AdapterMalloc(sizeof(Want)));
235     if (info == nullptr) {
236         return MEMORY_MALLOC_ERROR;
237     }
238     info->element = nullptr;
239     info->data = nullptr;
240     info->dataLength = 0;
241     info->appPath = nullptr;
242     SetWantElement(info, *(want->element));
243     SetWantData(info, want->data, want->dataLength);
244     if (want->data != nullptr) {
245         HILOG_INFO(HILOG_MODULE_APP, "ForceStop with data");
246     } else {
247         HILOG_INFO(HILOG_MODULE_APP, "ForceStop with no data");
248     }
249     Request request = {
250         .msgId = TERMINATE_APP_BY_BUNDLENAME,
251         .len = sizeof(Want),
252         .data = info,
253     };
254     return SendRequestToAms(request);
255 }
256 
AddAbilityRecordObserver(AbilityRecordObserver * observer)257 int32_t AbilityMsClient::AddAbilityRecordObserver(AbilityRecordObserver *observer)
258 {
259     if (identity_ == nullptr) {
260         return PARAM_CHECK_ERROR;
261     }
262     Request request = {
263         .msgId = ADD_ABILITY_RECORD_OBSERVER,
264         .len = 0,
265         .data = nullptr,
266         .msgValue = reinterpret_cast<uint32>(observer),
267     };
268 
269     return SendRequestToAms(request);
270 }
271 
RemoveAbilityRecordObserver(AbilityRecordObserver * observer)272 int32_t AbilityMsClient::RemoveAbilityRecordObserver(AbilityRecordObserver *observer)
273 {
274     if (identity_ == nullptr) {
275         return PARAM_CHECK_ERROR;
276     }
277     Request request = {
278         .msgId = REMOVE_ABILITY_RECORD_OBSERVER,
279         .len = 0,
280         .data = nullptr,
281         .msgValue = reinterpret_cast<uint32>(observer),
282     };
283 
284     return SendRequestToAms(request);
285 }
286 
GetMissionInfos(uint32_t maxNum) const287 MissionInfoList *AbilityMsClient::GetMissionInfos(uint32_t maxNum) const
288 {
289     if (!Initialize()) {
290         return nullptr;
291     }
292     return static_cast<MissionInfoList *>(amsProxy_->GetMissionInfos(maxNum));
293 }
294 
SetServiceIdentity(const Identity * identity)295 void AbilityMsClient::SetServiceIdentity(const Identity *identity)
296 {
297     identity_ = identity;
298 }
299 } // namespace AbilitySlite
300 } // namespace OHOS
301