1 /*
2 * Copyright (C) 2023 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 #define private public
16 #define protected public
17 #include "enable_ime_data_parser.h"
18 #include "full_ime_info_manager.h"
19 #include "settings_data_utils.h"
20 #include "user_session_manager.h"
21 #undef private
22
23 #include <unistd.h>
24
25 #include <csignal>
26 #include <cstdint>
27 #include <sstream>
28 #include <string>
29 #include <vector>
30
31 #include "accesstoken_kit.h"
32 #include "datashare_helper.h"
33 #include "global.h"
34 #include "if_system_ability_manager.h"
35 #include "input_method_controller.h"
36 #include "iservice_registry.h"
37 #include "nativetoken_kit.h"
38 #include "os_account_manager.h"
39 #include "scope_utils.h"
40 #include "system_ability.h"
41 #include "system_ability_definition.h"
42 #include "tdd_util.h"
43 #include "token_setproc.h"
44
45 namespace OHOS {
46 namespace MiscServices {
47 using namespace OHOS::Security::AccessToken;
48 using namespace OHOS::AccountSA;
49 using namespace Rosen;
50 constexpr int32_t INVALID_USER_ID = -1;
51 constexpr int32_t MAIN_USER_ID = 100;
52 constexpr const uint16_t EACH_LINE_LENGTH = 500;
53 constexpr int32_t PERMISSION_NUM = 4;
54 constexpr int32_t FIRST_PARAM_INDEX = 0;
55 constexpr int32_t SECOND_PARAM_INDEX = 1;
56 constexpr int32_t THIRD_PARAM_INDEX = 2;
57 constexpr int32_t FOURTH_PARAM_INDEX = 3;
58 static constexpr int32_t MAX_TIMEOUT_WAIT_FOCUS = 2000;
59 uint64_t TddUtil::selfTokenID_ = 0;
60 int32_t TddUtil::userID_ = INVALID_USER_ID;
61 std::string TddUtil::currentBundleNameMock_;
62 sptr<Window> TddUtil::WindowManager::window_ = nullptr;
63 int32_t TddUtil::WindowManager::currentWindowId_ = 0;
64 uint64_t TddUtil::WindowManager::windowTokenId_ = 0;
65 std::shared_ptr<BlockData<bool>> FocusChangedListenerTestImpl::isFocused_ =
66 std::make_shared<BlockData<bool>>(MAX_TIMEOUT_WAIT_FOCUS, false);
67 std::shared_ptr<BlockData<bool>> FocusChangedListenerTestImpl::unFocused_ =
68 std::make_shared<BlockData<bool>>(MAX_TIMEOUT_WAIT_FOCUS, false);
OnFocused(const sptr<Rosen::FocusChangeInfo> & focusChangeInfo)69 void FocusChangedListenerTestImpl::OnFocused(const sptr<Rosen::FocusChangeInfo> &focusChangeInfo)
70 {
71 IMSA_HILOGI("get onFocus information from window manager.");
72 if (focusChangeInfo->windowId_ == TddUtil::WindowManager::currentWindowId_) {
73 getFocus_ = true;
74 isFocused_->SetValue(getFocus_);
75 unFocused_->Clear(false);
76 }
77 }
78
OnUnfocused(const sptr<Rosen::FocusChangeInfo> & focusChangeInfo)79 void FocusChangedListenerTestImpl::OnUnfocused(const sptr<Rosen::FocusChangeInfo> &focusChangeInfo)
80 {
81 IMSA_HILOGI("get unfocus information from window manager.");
82 if (focusChangeInfo->windowId_ == TddUtil::WindowManager::currentWindowId_) {
83 getFocus_ = false;
84 isFocused_->Clear(false);
85 bool unFocus = !getFocus_;
86 unFocused_->SetValue(unFocus);
87 }
88 }
89
GetCurrentUserId()90 int32_t TddUtil::GetCurrentUserId()
91 {
92 if (userID_ != INVALID_USER_ID) {
93 return userID_;
94 }
95 int32_t userId = -1;
96 auto ret = OsAccountManager::GetForegroundOsAccountLocalId(userId);
97 if (ret != ErrorCode::NO_ERROR) {
98 IMSA_HILOGE("GetForegroundOsAccountLocalId failed");
99 return MAIN_USER_ID;
100 }
101 return userId;
102 }
StorageSelfTokenID()103 void TddUtil::StorageSelfTokenID()
104 {
105 selfTokenID_ = GetSelfTokenID();
106 }
107
AllocTestTokenID(bool isSystemApp,const std::string & bundleName,const std::vector<std::string> & premission)108 uint64_t TddUtil::AllocTestTokenID(
109 bool isSystemApp, const std::string &bundleName, const std::vector<std::string> &premission)
110 {
111 IMSA_HILOGI("bundleName: %{public}s", bundleName.c_str());
112 HapInfoParams infoParams = { .userID = GetCurrentUserId(),
113 .bundleName = bundleName,
114 .instIndex = 0,
115 .appIDDesc = bundleName,
116 .isSystemApp = isSystemApp };
117 std::vector<PermissionStateFull> permStateList;
118 for (const auto &prem : premission) {
119 PermissionStateFull permissionState = { .permissionName = prem,
120 .isGeneral = true,
121 .resDeviceID = { "local" },
122 .grantStatus = { PermissionState::PERMISSION_GRANTED },
123 .grantFlags = { 1 } };
124 permStateList.push_back(permissionState);
125 }
126 HapPolicyParams policyParams = {
127 .apl = APL_NORMAL, .domain = bundleName, .permList = {}, .permStateList = permStateList
128 };
129 if (premission.empty()) {
130 policyParams = { .apl = APL_NORMAL, .domain = bundleName, .permList = {}, .permStateList = {} };
131 }
132 auto tokenInfo = AccessTokenKit::AllocHapToken(infoParams, policyParams);
133 return tokenInfo.tokenIDEx;
134 }
135
GetTestTokenID(const std::string & bundleName)136 uint64_t TddUtil::GetTestTokenID(const std::string &bundleName)
137 {
138 HapInfoParams infoParams = { .userID = GetUserIdByBundleName(bundleName, GetCurrentUserId()),
139 .bundleName = bundleName,
140 .instIndex = 0,
141 .appIDDesc = "ohos.inputmethod_test.demo" };
142 return AccessTokenKit::GetHapTokenID(infoParams.userID, infoParams.bundleName, infoParams.instIndex);
143 }
144
DeleteTestTokenID(uint64_t tokenId)145 void TddUtil::DeleteTestTokenID(uint64_t tokenId)
146 {
147 AccessTokenKit::DeleteToken(tokenId);
148 }
149
SetTestTokenID(uint64_t tokenId)150 void TddUtil::SetTestTokenID(uint64_t tokenId)
151 {
152 auto ret = SetSelfTokenID(tokenId);
153 IMSA_HILOGI("SetSelfTokenID ret: %{public}d", ret);
154 }
155
RestoreSelfTokenID()156 void TddUtil::RestoreSelfTokenID()
157 {
158 auto ret = SetSelfTokenID(selfTokenID_);
159 IMSA_HILOGI("SetSelfTokenID ret = %{public}d", ret);
160 }
161
GetCurrentTokenID()162 uint64_t TddUtil::GetCurrentTokenID()
163 {
164 return GetSelfTokenID();
165 }
166
GetUid(const std::string & bundleName)167 int32_t TddUtil::GetUid(const std::string &bundleName)
168 {
169 auto bundleMgr = GetBundleMgr();
170 if (bundleMgr == nullptr) {
171 IMSA_HILOGE("bundleMgr nullptr");
172 return -1;
173 }
174 auto uid = bundleMgr->GetUidByBundleName(bundleName, GetCurrentUserId());
175 if (uid == -1) {
176 IMSA_HILOGE("failed to get information and the parameters may be wrong.");
177 return -1;
178 }
179 IMSA_HILOGI("bundleName: %{public}s, uid: %{public}d", bundleName.c_str(), uid);
180 return uid;
181 }
182
SetSelfUid(int32_t uid)183 void TddUtil::SetSelfUid(int32_t uid)
184 {
185 setuid(uid);
186 IMSA_HILOGI("set uid to: %{public}d", uid);
187 }
188
ExecuteCmd(const std::string & cmd,std::string & result)189 bool TddUtil::ExecuteCmd(const std::string &cmd, std::string &result)
190 {
191 char buff[EACH_LINE_LENGTH] = { 0x00 };
192 std::stringstream output;
193 FILE *ptr = popen(cmd.c_str(), "r");
194 if (ptr != nullptr) {
195 IMSA_HILOGI("Execute cmd: %{public}s", cmd.c_str());
196 while (fgets(buff, sizeof(buff), ptr) != nullptr) {
197 output << buff;
198 }
199 pclose(ptr);
200 ptr = nullptr;
201 } else {
202 return false;
203 }
204 result = output.str();
205 return true;
206 }
207
GetImsaPid()208 pid_t TddUtil::GetImsaPid()
209 {
210 auto currentToken = GetSelfTokenID();
211 GrantNativePermission();
212 auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
213 SystemProcessInfo info;
214 int32_t ret = saMgr->GetSystemProcessInfo(INPUT_METHOD_SYSTEM_ABILITY_ID, info);
215 if (ret != ErrorCode::NO_ERROR) {
216 IMSA_HILOGE("failed to get sa info, ret: %{public}d", ret);
217 return -1;
218 }
219 SetSelfTokenID(currentToken);
220 return info.pid;
221 }
222
KillImsaProcess()223 bool TddUtil::KillImsaProcess()
224 {
225 pid_t pid = GetImsaPid();
226 if (pid == -1) {
227 IMSA_HILOGE("failed to get pid");
228 return false;
229 }
230 auto ret = kill(pid, SIGTERM);
231 if (ret != 0) {
232 IMSA_HILOGE("Kill failed, ret: %{public}d", ret);
233 return false;
234 }
235 IMSA_HILOGI("Kill [%{public}d] success", pid);
236 return true;
237 }
238
GetBundleMgr()239 sptr<OHOS::AppExecFwk::IBundleMgr> TddUtil::GetBundleMgr()
240 {
241 sptr<ISystemAbilityManager> systemAbilityManager =
242 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
243 if (systemAbilityManager == nullptr) {
244 IMSA_HILOGE("systemAbilityManager is nullptr");
245 return nullptr;
246 }
247 sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
248 if (remoteObject == nullptr) {
249 IMSA_HILOGE("remoteObject is nullptr");
250 return nullptr;
251 }
252 return iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
253 }
254
GetUserIdByBundleName(const std::string & bundleName,const int currentUserId)255 int TddUtil::GetUserIdByBundleName(const std::string &bundleName, const int currentUserId)
256 {
257 auto bundleMgr = TddUtil::GetBundleMgr();
258 if (bundleMgr == nullptr) {
259 IMSA_HILOGE("Get bundleMgr failed.");
260 return -1;
261 }
262 auto uid = bundleMgr->GetUidByBundleName(bundleName, currentUserId);
263 if (uid == -1) {
264 IMSA_HILOGE("failed to get information and the parameters may be wrong.");
265 return -1;
266 }
267 // 200000 means userId = uid / 200000.
268 return uid / 200000;
269 }
270
GrantNativePermission()271 void TddUtil::GrantNativePermission()
272 {
273 const char **perms = new const char *[PERMISSION_NUM];
274 perms[FIRST_PARAM_INDEX] = "ohos.permission.MANAGE_SECURE_SETTINGS";
275 perms[SECOND_PARAM_INDEX] = "ohos.permission.CONNECT_IME_ABILITY";
276 perms[THIRD_PARAM_INDEX] = "ohos.permission.MANAGE_SETTINGS";
277 perms[FOURTH_PARAM_INDEX] = "ohos.permission.INJECT_INPUT_EVENT";
278 TokenInfoParams infoInstance = {
279 .dcapsNum = 0,
280 .permsNum = PERMISSION_NUM,
281 .aclsNum = 0,
282 .dcaps = nullptr,
283 .perms = perms,
284 .acls = nullptr,
285 .processName = "imf_test",
286 .aplStr = "system_core",
287 };
288 uint64_t tokenId = GetAccessTokenId(&infoInstance);
289 int res = SetSelfTokenID(tokenId);
290 if (res == 0) {
291 IMSA_HILOGI("SetSelfTokenID success!");
292 } else {
293 IMSA_HILOGE("SetSelfTokenID fail!");
294 }
295 AccessTokenKit::ReloadNativeTokenInfo();
296 delete[] perms;
297 }
298
PushEnableImeValue(const std::string & key,const std::string & value)299 void TddUtil::PushEnableImeValue(const std::string &key, const std::string &value)
300 {
301 IMSA_HILOGI("key: %{public}s, value: %{public}s", key.c_str(), value.c_str());
302 auto helper = SettingsDataUtils::GetInstance()->CreateDataShareHelper(SETTING_URI_PROXY);
303 if (helper == nullptr) {
304 IMSA_HILOGE("helper is nullptr.");
305 return;
306 }
307 DataShare::DataShareValueObject keyObj(key);
308 DataShare::DataShareValueObject valueObj(value);
309 DataShare::DataShareValuesBucket bucket;
310 bucket.Put(SETTING_COLUMN_KEYWORD, keyObj);
311 bucket.Put(SETTING_COLUMN_VALUE, valueObj);
312 DataShare::DataSharePredicates predicates;
313 predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
314 Uri uri(SettingsDataUtils::GetInstance()->GenerateTargetUri(SETTING_URI_PROXY, key));
315 if (helper->Update(uri, predicates, bucket) <= 0) {
316 int index = helper->Insert(uri, bucket);
317 IMSA_HILOGI("no data exists, insert ret index: %{public}d", index);
318 } else {
319 IMSA_HILOGI("data exits");
320 }
321 bool ret = SettingsDataUtils::GetInstance()->ReleaseDataShareHelper(helper);
322 IMSA_HILOGI("ReleaseDataShareHelper isSuccess: %{public}d", ret);
323 }
324
GetEnableData(std::string & value)325 int32_t TddUtil::GetEnableData(std::string &value)
326 {
327 auto ret =
328 SettingsDataUtils::GetInstance()->GetStringValue(SETTING_URI_PROXY, EnableImeDataParser::ENABLE_IME, value);
329 if (ret == ErrorCode::NO_ERROR) {
330 IMSA_HILOGI("success, value: %{public}s", value.c_str());
331 }
332 IMSA_HILOGI("GetStringValue ret: %{public}d", ret);
333 return ret;
334 }
335
InitWindow(bool isShow)336 void TddUtil::InitWindow(bool isShow)
337 {
338 WindowManager::RegisterFocusChangeListener();
339 WindowManager::CreateWindow();
340 if (!isShow) {
341 return;
342 }
343 WindowManager::ShowWindow();
344 bool isFocused = FocusChangedListenerTestImpl::isFocused_->GetValue();
345 IMSA_HILOGI("getFocus end, isFocused = %{public}d", isFocused);
346 }
347
DestroyWindow()348 void TddUtil::DestroyWindow()
349 {
350 WindowManager::HideWindow();
351 WindowManager::DestroyWindow();
352 }
353
GetFocused()354 bool TddUtil::GetFocused()
355 {
356 WindowManager::ShowWindow();
357 bool isFocused = FocusChangedListenerTestImpl::isFocused_->GetValue();
358 IMSA_HILOGI("getFocus end, isFocused = %{public}d", isFocused);
359 return isFocused;
360 }
361
GetUnfocused()362 bool TddUtil::GetUnfocused()
363 {
364 WindowManager::HideWindow();
365 bool unFocused = FocusChangedListenerTestImpl::unFocused_->GetValue();
366 IMSA_HILOGI("unFocused end, unFocused = %{public}d", unFocused);
367 return unFocused;
368 }
369
InitCurrentImePermissionInfo()370 void TddUtil::InitCurrentImePermissionInfo()
371 {
372 auto userId = GetCurrentUserId();
373 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
374 if (session == nullptr) {
375 UserSessionManager::GetInstance().AddUserSession(userId);
376 }
377 session = UserSessionManager::GetInstance().GetUserSession(userId);
378 if (session == nullptr) {
379 IMSA_HILOGE("session is nullptr.");
380 return;
381 }
382 std::shared_ptr<Property> property = nullptr;
383 InputMethodController::GetInstance()->GetDefaultInputMethod(property);
384 if (property == nullptr) {
385 IMSA_HILOGI("default ime is nullptr.");
386 return;
387 }
388 currentBundleNameMock_ = property->name;
389 session->InitImeData({ property->name, property->id });
390 ImeCfgManager::GetInstance().imeConfigs_ = { { userId, property->name + "/" + property->id, "", false } };
391 }
392
CreateWindow()393 void TddUtil::WindowManager::CreateWindow()
394 {
395 if (windowTokenId_ == 0) {
396 windowTokenId_ = AllocTestTokenID(true, "TestWindow", {});
397 }
398 TokenScope scope(windowTokenId_);
399 std::string windowName = "inputmethod_test_window";
400 sptr<WindowOption> winOption = new OHOS::Rosen::WindowOption();
401 winOption->SetWindowType(WindowType::WINDOW_TYPE_FLOAT);
402 winOption->SetFocusable(true);
403 std::shared_ptr<AbilityRuntime::Context> context = nullptr;
404 WMError wmError = WMError::WM_OK;
405 window_ = Window::Create(windowName, winOption, context, wmError);
406 if (window_ == nullptr) {
407 IMSA_HILOGE("failed to create window, ret: %{public}d", wmError);
408 return;
409 }
410 IMSA_HILOGI("Create window ret:%{public}d", wmError);
411 currentWindowId_ = window_->GetWindowId();
412 }
413
ShowWindow()414 void TddUtil::WindowManager::ShowWindow()
415 {
416 if (window_ == nullptr) {
417 IMSA_HILOGE("window is not exist.");
418 return;
419 }
420 TokenScope scope(windowTokenId_);
421 auto ret = window_->Show();
422 IMSA_HILOGI("Show window end, ret = %{public}d", ret);
423 }
424
HideWindow()425 void TddUtil::WindowManager::HideWindow()
426 {
427 if (window_ == nullptr) {
428 IMSA_HILOGE("window is not exist.");
429 return;
430 }
431 TokenScope scope(windowTokenId_);
432 auto ret = window_->Hide();
433 IMSA_HILOGI("Hide window end, ret = %{public}d", ret);
434 }
435
DestroyWindow()436 void TddUtil::WindowManager::DestroyWindow()
437 {
438 if (window_ == nullptr) {
439 IMSA_HILOGE("window_ nullptr");
440 return;
441 }
442 TokenScope scope(windowTokenId_);
443 auto wmError = window_->Destroy();
444 IMSA_HILOGI("Destroy window ret: %{public}d", wmError);
445 }
446
RegisterFocusChangeListener()447 void TddUtil::WindowManager::RegisterFocusChangeListener()
448 {
449 auto listener = new (std::nothrow) FocusChangedListenerTestImpl();
450 WMError ret = Rosen::WindowManager::GetInstance().RegisterFocusChangedListener(listener);
451 IMSA_HILOGI("register focus changed listener ret: %{public}d", ret);
452 }
453 } // namespace MiscServices
454 } // namespace OHOS
455