1 /*
2 * Copyright (c) 2024 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 #ifdef APP_NO_RESPONSE_DIALOG
17 #include "modal_system_app_freeze_uiextension.h"
18
19 #include <chrono>
20 #include <mutex>
21
22 #include "ability_record.h"
23 #include "hilog_tag_wrapper.h"
24 #include "hitrace_meter.h"
25 #include "in_process_call_wrapper.h"
26 #include "scene_board_judgement.h"
27 #include "session_manager_lite.h"
28 #include "window_visibility_info.h"
29
30 using namespace OHOS::AAFwk;
31 using namespace OHOS::Rosen;
32
33 namespace OHOS {
34 namespace AppExecFwk {
35 const std::string UIEXTENSION_TYPE_KEY = "ability.want.params.uiExtensionType";
36 const std::string UIEXTENSION_SYS_COMMON_UI = "sysDialog/common";
37 const std::string APP_FREEZE_PID = "APP_FREEZE_PID";
38 const std::string FREEZE_WINDOW_POSX = "FREEZE_WINDOW_POSX";
39 const std::string FREEZE_WINDOW_POSY = "FREEZE_WINDOW_POSY";
40 const std::string FREEZE_WINDOW_WIDTH = "FREEZE_WINDOW_WIDTH";
41 const std::string FREEZE_WINDOW_HEIGHT = "FREEZE_WINDOW_HEIGHT";
42 const std::string START_BUNDLE_NAME = "startBundleName";
43 const std::string APP_FREEZE_TOKEN = "freezeToken";
44 constexpr int32_t INVALID_USERID = -1;
45 constexpr int32_t MESSAGE_PARCEL_KEY_SIZE = 3;
46 constexpr uint32_t COMMAND_START_DIALOG = 1;
47 constexpr char INVALID_PID[] = "-1";
48 constexpr uint64_t TIMEOUT_INTERVAL_MS = 8000;
49
GetInstance()50 ModalSystemAppFreezeUIExtension &ModalSystemAppFreezeUIExtension::GetInstance()
51 {
52 static ModalSystemAppFreezeUIExtension instance;
53 return instance;
54 }
55
~ModalSystemAppFreezeUIExtension()56 ModalSystemAppFreezeUIExtension::~ModalSystemAppFreezeUIExtension()
57 {}
58
ProcessAppFreeze(bool focusFlag,const FaultData & faultData,std::string pid,std::string bundleName,std::function<void ()> callback,bool isDialogExist)59 void ModalSystemAppFreezeUIExtension::ProcessAppFreeze(bool focusFlag, const FaultData &faultData, std::string pid,
60 std::string bundleName, std::function<void()> callback, bool isDialogExist)
61 {
62 const std::string SCENE_BAOARD_NAME = "com.ohos.sceneboard";
63 if ((bundleName == SCENE_BAOARD_NAME || faultData.waitSaveState) && callback) {
64 callback();
65 return;
66 }
67 FaultDataType faultType = faultData.faultType;
68 std::string name = faultData.errorObject.name;
69 bool isAppFreezeDialog = name == AppFreezeType::THREAD_BLOCK_6S || name == AppFreezeType::APP_INPUT_BLOCK ||
70 name == AppFreezeType::BUSSINESS_THREAD_BLOCK_6S;
71 uint64_t now =
72 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch())
73 .count();
74 bool timeout = now - lastFreezeTime > TIMEOUT_INTERVAL_MS;
75 TAG_LOGI(AAFwkTag::ABILITYMGR,
76 "%{public}s is %{public}s.pid:%{public}s lastFreezePid:%{public}s", bundleName.c_str(),
77 focusFlag ? "focus" : "not focus", pid.c_str(), lastFreezePid.c_str());
78 bool isPullUpBox =
79 isAppFreezeDialog && (pid != lastFreezePid || (pid == lastFreezePid && timeout && !isDialogExist));
80 bool updateTypeName = name == AppFreezeType::THREAD_BLOCK_6S || name == AppFreezeType::BUSSINESS_THREAD_BLOCK_6S;
81 if (pid == lastFreezePid && updateTypeName) {
82 lastFreezeTime = now;
83 }
84 if (focusFlag && isPullUpBox) {
85 CreateModalUIExtension(pid, bundleName);
86 } else if (callback && (faultType != FaultDataType::APP_FREEZE || !isAppFreezeDialog)) {
87 callback();
88 }
89 if (!isDialogExist && !focusFlag && lastFreezePid == pid) {
90 lastFreezePid = INVALID_PID;
91 lastFocusStatus = false;
92 }
93 }
94
CreateModalUIExtension(std::string & pid,std::string & bundleName)95 bool ModalSystemAppFreezeUIExtension::CreateModalUIExtension(std::string& pid, std::string& bundleName)
96 {
97 TAG_LOGD(AAFwkTag::ABILITYMGR, "Create Modal UIExtension Called");
98 sptr<IRemoteObject> token;
99 AAFwk::Want want;
100 std::unique_lock<std::mutex> lockAssertResult(appFreezeResultMutex_);
101 if (!CreateSystemDialogWant(pid, bundleName, token, want)) {
102 return false;
103 }
104 auto abilityManagerClient = AAFwk::AbilityManagerClient::GetInstance();
105 if (abilityManagerClient == nullptr) {
106 TAG_LOGE(AAFwkTag::ABILITYMGR, "null abilityManagerClient");
107 return false;
108 }
109 auto result = IN_PROCESS_CALL(abilityManagerClient->StartExtensionAbility(want, token));
110 if (result != ERR_OK) {
111 TAG_LOGE(AAFwkTag::ABILITYMGR, "StartExtensionAbility failed, result = %{public}d", result);
112 return false;
113 }
114 lastFreezePid = pid;
115 lastFocusStatus = true;
116 lastFreezeTime = std::chrono::duration_cast<std::chrono::milliseconds>(
117 std::chrono::steady_clock::now().time_since_epoch()).count();
118 TAG_LOGI(AAFwkTag::ABILITYMGR, "success, result = %{public}d", result);
119 return true;
120 }
121
CreateSystemDialogWant(std::string & pid,std::string & bundleName,sptr<IRemoteObject> token,AAFwk::Want & want)122 bool ModalSystemAppFreezeUIExtension::CreateSystemDialogWant(
123 std::string& pid, std::string& bundleName, sptr<IRemoteObject> token, AAFwk::Want &want)
124 {
125 want.SetElementName(APP_NO_RESPONSE_BUNDLENAME, APP_NO_RESPONSE_ABILITY);
126 want.SetParam(UIEXTENSION_TYPE_KEY, UIEXTENSION_SYS_COMMON_UI);
127 want.SetParam(APP_FREEZE_PID, pid);
128 want.SetParam(START_BUNDLE_NAME, bundleName);
129
130 auto sceneSessionManager = Rosen::SessionManagerLite::GetInstance().GetSceneSessionManagerLiteProxy();
131 if (!sceneSessionManager) {
132 TAG_LOGE(AAFwkTag::ABILITYMGR, "sceneSessionManager is null proxy!");
133 return false;
134 }
135 auto ret = static_cast<int>(sceneSessionManager->GetFocusSessionToken(token));
136 if (ret != ERR_OK) {
137 TAG_LOGE(AAFwkTag::ABILITYMGR, "Get focus session token err: %{public}d", ret);
138 return false;
139 }
140 want.SetParam(APP_FREEZE_TOKEN, token);
141 std::vector<sptr<Rosen::WindowVisibilityInfo>> infos;
142 ret = static_cast<int>(sceneSessionManager->GetVisibilityWindowInfo(infos));
143 if (ret != ERR_OK) {
144 TAG_LOGE(AAFwkTag::ABILITYMGR, "Get visibility window info err: %{public}d", ret);
145 return false;
146 }
147
148 int32_t posX = 0;
149 int32_t posY = 0;
150 int32_t width = 10;
151 int32_t height = 10;
152 int32_t focusPid = -1;
153 for (const auto &info : infos) {
154 if (info != nullptr) {
155 if (info->IsFocused()) {
156 posX = info->rect_.posX_;
157 posY = info->rect_.posY_;
158 width = info->rect_.width_;
159 height = info->rect_.height_;
160 focusPid = info->pid_;
161 break;
162 }
163 }
164 }
165 if ((focusPid == -1) || (std::to_string(focusPid) != pid)) {
166 TAG_LOGE(AAFwkTag::ABILITYMGR, "fucused window pid is %{public}d, not freeze pid!", focusPid);
167 return false;
168 }
169 want.SetParam(FREEZE_WINDOW_POSX, std::to_string(posX));
170 want.SetParam(FREEZE_WINDOW_POSY, std::to_string(posY));
171 want.SetParam(FREEZE_WINDOW_WIDTH, std::to_string(width));
172 want.SetParam(FREEZE_WINDOW_HEIGHT, std::to_string(height));
173 return true;
174 }
175
176 } // namespace AppExecFwk
177 } // namespace OHOS
178 #endif // APP_NO_RESPONSE_DIALOG
179