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 "ability_test_helper.h"
17 
18 #include <ability_kit_command.h>
19 #include <ability_manager.h>
20 #include <ability_service_interface.h>
21 #include <appexecfwk_errors.h>
22 #include <bundle_manager.h>
23 #include <cstring>
24 #include <ctime>
25 #include <ohos_errno.h>
26 #include <samgr_lite.h>
27 #include <semaphore.h>
28 #include <want_utils.h>
29 
30 namespace OHOS {
31     constexpr uint32_t WAIT_TIMEOUT = 30;
32     constexpr char ABILITY_STATE[] = "Ability State: [";
33     constexpr char NO_ABILITY[] = "Ability not found";
34     constexpr char SLICE_STACK[] = "\n   [";
35     constexpr char SLICE_STATE[] = "] State: [";
36 
37     static sem_t g_sem;
38     static bool g_result = false;
39     static std::string g_resultString;
40 
41     SvcIdentity AbilityTestHelper::identity_ = {};
42     IClientProxy *AbilityTestHelper::proxy_ = nullptr;
43     IpcObjectStub AbilityTestHelper::objectStub_ = {};
44 
Initialize()45     void AbilityTestHelper::Initialize()
46     {
47         objectStub_.func = AbilityCallback;
48         objectStub_.args = nullptr;
49         objectStub_.isRemote = false;
50         identity_.handle = IPC_INVALID_HANDLE;
51         identity_.token = SERVICE_TYPE_ANONYMOUS;
52         identity_.cookie = reinterpret_cast<uintptr_t>(&objectStub_);
53 
54         proxy_ = GetAbilityInnerFeature();
55         if (proxy_ == nullptr) {
56             exit(-1);
57         }
58         sleep(1);
59     }
60 
UnInitialize()61     void AbilityTestHelper::UnInitialize()
62     {
63         sleep(1);
64     }
65 
InstallCallback(const uint8_t resultCode,const void * resultMessage)66     void AbilityTestHelper::InstallCallback(const uint8_t resultCode, const void *resultMessage)
67     {
68         std::string strMessage = reinterpret_cast<const char *>(resultMessage);
69         if (!strMessage.empty()) {
70             printf("install resultMessage is %s\n", strMessage.c_str());
71         }
72 
73         g_result = (resultCode == ERR_OK);
74         SemPost();
75     }
76 
UninstallCallback(const uint8_t resultCode,const void * resultMessage)77     void AbilityTestHelper::UninstallCallback(const uint8_t resultCode, const void *resultMessage)
78     {
79         std::string strMessage = reinterpret_cast<const char *>(resultMessage);
80         if (!strMessage.empty()) {
81             printf("[INFO] [AbilityTestHelper] uninstall resultMessage is %s\n", strMessage.c_str());
82         }
83 
84         g_result = (resultCode == ERR_OK);
85         SemPost();
86     }
87 
AbilityCallback(uint32_t code,IpcIo * data,IpcIo * reply,MessageOption option)88     int32_t AbilityTestHelper::AbilityCallback(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option)
89     {
90         switch (code) {
91             case SCHEDULER_APP_INIT: {
92                 ElementName element = {};
93                 DeserializeElement(&element, data);
94                 int32_t ret = 0;
95                 ReadInt32(data, &ret);
96                 printf("ams call back, start %s.%s ret = %d\n", element.bundleName, element.abilityName, ret);
97                 ClearElement(&element);
98                 g_result = (ret == EC_SUCCESS);
99                 break;
100             }
101             case SCHEDULER_DUMP_ABILITY: {
102                 size_t len = 0;
103                 g_resultString = reinterpret_cast<char *>(ReadString(data, &len));
104                 break;
105             }
106             default: {
107                 printf("ams call back error, funcId: %u\n", code);
108                 break;
109             }
110         }
111 
112         SemPost();
113         return 0;
114     }
115 
TestInstall(const std::string & hap)116     bool AbilityTestHelper::TestInstall(const std::string &hap)
117     {
118         InstallParam installParam = {
119             .installLocation = 1,
120             .keepData = false
121         };
122         if (!Install(hap.c_str(), &installParam, InstallCallback)) {
123             printf("[ERROR] [AbilityTestHelper] Install hap failed!\n");
124             exit(-1);
125         }
126         g_result = true;
127         SemWait();
128         return g_result;
129     }
130 
TestUnInstall(const std::string & bundleName)131     bool AbilityTestHelper::TestUnInstall(const std::string &bundleName)
132     {
133         InstallParam installParam = {
134             .installLocation = 1,
135             .keepData = false
136         };
137         bool ret = Uninstall(bundleName.c_str(), &installParam, UninstallCallback);
138         SemWait();
139         return ret;
140     }
141 
TestStartAbility(const Want & want)142     bool AbilityTestHelper::TestStartAbility(const Want &want)
143     {
144         SetWantSvcIdentity(const_cast<Want *>(&want), identity_);
145         int32_t ret = StartAbility(&want);
146         g_result = (ERR_OK == ret);
147         SemWait();
148         sleep(1);
149         return g_result;
150     }
151 
TestTerminateApp(const std::string & bundleName)152     bool AbilityTestHelper::TestTerminateApp(const std::string &bundleName)
153     {
154         IpcIo req;
155         char data[MAX_IO_SIZE];
156         IpcIoInit(&req, data, MAX_IO_SIZE, 0);
157         WriteString(&req, bundleName.c_str());
158         int32_t ret = proxy_->Invoke(proxy_, TERMINATE_APP, &req, nullptr, nullptr);
159         sleep(2); // 2:出让CPU
160         return ret == EC_SUCCESS;
161     }
162 
GetAbilityState(const ElementName & elementName)163     State AbilityTestHelper::GetAbilityState(const ElementName &elementName)
164     {
165         TestDumpAbility(elementName);
166 
167         auto position = g_resultString.find(ABILITY_STATE);
168         if (position != std::string::npos) {
169             return static_cast<State>(g_resultString[position + strlen(ABILITY_STATE)] - '0');
170         }
171 
172         if (g_resultString.find(NO_ABILITY) != std::string::npos) {
173             return STATE_INITIAL;
174         }
175         printf("[ERROR] [AbilityTestHelper] Failed to GetAbilityState\n");
176         return STATE_UNINITIALIZED;
177     }
178 
GetSliceStack(const ElementName & elementName)179     std::list<std::shared_ptr<SliceRecord>> AbilityTestHelper::GetSliceStack(const ElementName &elementName)
180     {
181         TestDumpAbility(elementName);
182         std::list<std::shared_ptr<SliceRecord>> sliceList;
183         std::string::size_type begin;
184         std::string::size_type end = 0;
185 
186         while (((begin = g_resultString.find(SLICE_STACK, end)) != std::string::npos) &&
187             ((end = g_resultString.find(SLICE_STATE, begin)) != std::string::npos)) {
188             auto record = std::make_shared<SliceRecord>();
189             record->name = g_resultString.substr(begin + strlen(SLICE_STACK), end);
190             record->state = static_cast<State>(g_resultString[end + strlen(SLICE_STATE)] - '0');
191             sliceList.push_back(record);
192         }
193 
194         return sliceList;
195     }
196 
GetAbilityInnerFeature()197     IClientProxy *AbilityTestHelper::GetAbilityInnerFeature()
198     {
199         IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(AMS_SERVICE, AMS_INNER_FEATURE);
200         if (iUnknown == nullptr) {
201             printf("ams inner unknown is null\n");
202             return nullptr;
203         }
204         IClientProxy *innerProxy = nullptr;
205         (void)iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)&innerProxy);
206         if (innerProxy == nullptr) {
207             printf("ams inner feature is null\n");
208             return nullptr;
209         }
210         return innerProxy;
211     }
212 
TestDumpAbility(const ElementName & elementName)213     void AbilityTestHelper::TestDumpAbility(const ElementName &elementName)
214     {
215         IpcIo req;
216         char data[MAX_IO_SIZE];
217         IpcIoInit(&req, data, MAX_IO_SIZE, 2); // 2:IPC初始化
218         Want want = {};
219         SetWantElement(&want, elementName);
220         SetWantSvcIdentity(&want, identity_);
221         if (!SerializeWant(&req, &want)) {
222             printf("SerializeWant failed\n");
223             ClearWant(&want);
224             exit(-1);
225         }
226         ClearWant(&want);
227         proxy_->Invoke(proxy_, DUMP_ABILITY, &req, nullptr, nullptr);
228         SemWait();
229 
230         printf("[Dump]\n%s\n", g_resultString.c_str());
231     }
232 
SemWait()233     void AbilityTestHelper::SemWait()
234     {
235         printf("waiting callback\n");
236         sem_init(&g_sem, 0, 0);
237         struct timespec ts = {};
238         clock_gettime(CLOCK_REALTIME, &ts);
239         ts.tv_sec += WAIT_TIMEOUT;
240         sem_timedwait(&g_sem, &ts);
241     }
242 
SemPost()243     void AbilityTestHelper::SemPost()
244     {
245         printf("receive callback\n");
246         sem_post(&g_sem);
247     }
248 }
249 
250