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