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 int MAX_BUFFER_SIZE_PER = 1024; // 1024 byte 33 constexpr char ABILITY_STATE[] = "Ability State: ["; 34 constexpr char NO_ABILITY[] = "Ability not found"; 35 constexpr char SLICE_STACK[] = "\n ["; 36 constexpr char SLICE_STATE[] = "] State: ["; 37 38 static sem_t g_sem; 39 static bool g_result = false; 40 static std::string g_resultString; 41 42 SvcIdentity AbilityTestHelper::identity_ = {}; 43 IClientProxy *AbilityTestHelper::proxy_ = nullptr; 44 Initialize()45 void AbilityTestHelper::Initialize() 46 { 47 if (RegisterIpcCallback(AbilityCallback, 0, IPC_WAIT_FOREVER, &identity_, nullptr) != 0) 48 { 49 printf("registerIpcCallback failed\n"); 50 exit(-1); 51 } 52 proxy_ = GetAbilityInnerFeature(); 53 if (proxy_ == nullptr) 54 { 55 exit(-1); 56 } 57 sleep(1); 58 } 59 UnInitialize()60 void AbilityTestHelper::UnInitialize() 61 { 62 UnregisterIpcCallback(identity_); 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 { 71 printf("install resultMessage is %s\n", strMessage.c_str()); 72 } 73 74 g_result = (resultCode == ERR_OK); 75 SemPost(); 76 } 77 UninstallCallback(const uint8_t resultCode,const void * resultMessage)78 void AbilityTestHelper::UninstallCallback(const uint8_t resultCode, const void *resultMessage) 79 { 80 std::string strMessage = reinterpret_cast<const char *>(resultMessage); 81 if (!strMessage.empty()) 82 { 83 printf("[INFO] [AbilityTestHelper] uninstall resultMessage is %s\n", strMessage.c_str()); 84 } 85 86 g_result = (resultCode == ERR_OK); 87 SemPost(); 88 } 89 AbilityCallback(const IpcContext * context,void * ipcMsg,IpcIo * data,void * arg)90 int32_t AbilityTestHelper::AbilityCallback(const IpcContext* context, void *ipcMsg, IpcIo *data, void *arg) 91 { 92 if (ipcMsg == nullptr) 93 { 94 printf("ams call back error, ipcMsg is null\n"); 95 return -1; 96 } 97 98 uint32_t funcId = 0; 99 GetCode(ipcMsg, &funcId); 100 uint32_t flag = 0; 101 GetFlag(ipcMsg, &flag); 102 if (flag == LITEIPC_FLAG_ONEWAY) 103 { 104 FreeBuffer(nullptr, ipcMsg); 105 } 106 switch (funcId) 107 { 108 case SCHEDULER_APP_INIT: { 109 ElementName element = {}; 110 DeserializeElement(&element, data); 111 int ret = IpcIoPopInt32(data); 112 printf("ams call back, start %s.%s ret = %d\n", element.bundleName, element.abilityName, ret); 113 ClearElement(&element); 114 g_result = (ret == EC_SUCCESS); 115 break; 116 } 117 case SCHEDULER_DUMP_ABILITY: { 118 BuffPtr *buff = IpcIoPopDataBuff(data); 119 if ((buff == nullptr) || (buff->buff == nullptr)) 120 { 121 printf("ams call back error, buff is empty\n"); 122 return false; 123 } 124 g_resultString = static_cast<char *>(buff->buff); 125 FreeBuffer(nullptr, buff->buff); 126 break; 127 } 128 default: { 129 printf("ams call back error, funcId: %u\n", funcId); 130 break; 131 } 132 } 133 134 SemPost(); 135 return 0; 136 } 137 TestInstall(const std::string & hap)138 bool AbilityTestHelper::TestInstall(const std::string &hap) 139 { 140 InstallParam installParam = { 141 .installLocation = 1, 142 .keepData = false 143 }; 144 if (!Install(hap.c_str(), &installParam, InstallCallback)) 145 { 146 printf("[ERROR] [AbilityTestHelper] Install hap failed!\n"); 147 exit(-1); 148 } 149 g_result = true; 150 SemWait(); 151 return g_result; 152 } 153 TestUnInstall(const std::string & bundleName)154 bool AbilityTestHelper::TestUnInstall(const std::string &bundleName) 155 { 156 InstallParam installParam = { 157 .installLocation = 1, 158 .keepData = false 159 }; 160 bool ret = Uninstall(bundleName.c_str(), &installParam, UninstallCallback); 161 SemWait(); 162 return ret; 163 } 164 TestStartAbility(const Want & want)165 bool AbilityTestHelper::TestStartAbility(const Want &want) 166 { 167 SetWantSvcIdentity(const_cast<Want *>(&want), identity_); 168 int32_t ret = StartAbility(&want); 169 g_result = (ERR_OK == ret); 170 SemWait(); 171 sleep(1); 172 return g_result; 173 } 174 TestTerminateApp(const std::string & bundleName)175 bool AbilityTestHelper::TestTerminateApp(const std::string &bundleName) 176 { 177 IpcIo req; 178 char data[IPC_IO_DATA_MAX]; 179 IpcIoInit(&req, data, IPC_IO_DATA_MAX, 0); 180 IpcIoPushString(&req, bundleName.c_str()); 181 int32_t ret = proxy_->Invoke(proxy_, TERMINATE_APP, &req, nullptr, nullptr); 182 sleep(2); 183 return ret == EC_SUCCESS; 184 } 185 GetAbilityState(const ElementName & elementName)186 State AbilityTestHelper::GetAbilityState(const ElementName &elementName) 187 { 188 TestDumpAbility(elementName); 189 190 auto position = g_resultString.find(ABILITY_STATE); 191 if (position != std::string::npos) 192 { 193 return static_cast<State>(g_resultString[position + strlen(ABILITY_STATE)] - '0'); 194 } 195 196 if (g_resultString.find(NO_ABILITY) != std::string::npos) 197 { 198 return STATE_INITIAL; 199 } 200 printf("[ERROR] [AbilityTestHelper] Failed to GetAbilityState\n"); 201 return STATE_UNINITIALIZED; 202 } 203 GetSliceStack(const ElementName & elementName)204 std::list<std::shared_ptr<SliceRecord>> AbilityTestHelper::GetSliceStack(const ElementName &elementName) 205 { 206 TestDumpAbility(elementName); 207 std::list<std::shared_ptr<SliceRecord>> sliceList; 208 std::string::size_type begin; 209 std::string::size_type end = 0; 210 211 while (((begin = g_resultString.find(SLICE_STACK, end)) != std::string::npos) && 212 ((end = g_resultString.find(SLICE_STATE, begin)) != std::string::npos)) { 213 auto record = std::make_shared<SliceRecord>(); 214 record->name = g_resultString.substr(begin + strlen(SLICE_STACK), end); 215 record->state = static_cast<State>(g_resultString[end + strlen(SLICE_STATE)] - '0'); 216 sliceList.push_back(record); 217 } 218 219 return sliceList; 220 } 221 GetAbilityInnerFeature()222 IClientProxy *AbilityTestHelper::GetAbilityInnerFeature() 223 { 224 IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(AMS_SERVICE, AMS_INNER_FEATURE); 225 if (iUnknown == nullptr) 226 { 227 printf("ams inner unknown is null\n"); 228 return nullptr; 229 } 230 IClientProxy *innerProxy = nullptr; 231 (void)iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)&innerProxy); 232 if (innerProxy == nullptr) 233 { 234 printf("ams inner feature is null\n"); 235 return nullptr; 236 } 237 return innerProxy; 238 } 239 TestDumpAbility(const ElementName & elementName)240 void AbilityTestHelper::TestDumpAbility(const ElementName &elementName) 241 { 242 IpcIo req; 243 char data[IPC_IO_DATA_MAX]; 244 IpcIoInit(&req, data, IPC_IO_DATA_MAX, 2); 245 Want want = {}; 246 SetWantElement(&want, elementName); 247 SetWantSvcIdentity(&want, identity_); 248 if (!SerializeWant(&req, &want)) 249 { 250 printf("SerializeWant failed\n"); 251 ClearWant(&want); 252 exit(-1); 253 } 254 ClearWant(&want); 255 proxy_->Invoke(proxy_, DUMP_ABILITY, &req, nullptr, nullptr); 256 SemWait(); 257 258 printf("[Dump]\n%s\n", g_resultString.c_str()); 259 } 260 SemWait()261 void AbilityTestHelper::SemWait() 262 { 263 printf("waiting callback\n"); 264 sem_init(&g_sem, 0, 0); 265 struct timespec ts = {}; 266 clock_gettime(CLOCK_REALTIME, &ts); 267 ts.tv_sec += WAIT_TIMEOUT; 268 sem_timedwait(&g_sem, &ts); 269 } 270 SemPost()271 void AbilityTestHelper::SemPost() 272 { 273 printf("receive callback\n"); 274 sem_post(&g_sem); 275 } 276 } 277 278