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 "hilog_tag_wrapper.h"
23 #include "hitrace_meter.h"
24 #include "in_process_call_wrapper.h"
25 #include "scene_board_judgement.h"
26
27 namespace OHOS {
28 namespace AppExecFwk {
29 const std::string UIEXTENSION_TYPE_KEY = "ability.want.params.uiExtensionType";
30 const std::string UIEXTENSION_SYS_COMMON_UI = "sysDialog/common";
31 const std::string APP_FREEZE_PID = "APP_FREEZE_PID";
32 const std::string START_BUNDLE_NAME = "startBundleName";
33 constexpr int32_t INVALID_USERID = -1;
34 constexpr int32_t MESSAGE_PARCEL_KEY_SIZE = 3;
35 constexpr uint32_t COMMAND_START_DIALOG = 1;
36 constexpr char INVALID_PID[] = "-1";
37 constexpr uint64_t TIMEOUT_INTERVAL_MS = 8000;
38
GetInstance()39 ModalSystemAppFreezeUIExtension &ModalSystemAppFreezeUIExtension::GetInstance()
40 {
41 static ModalSystemAppFreezeUIExtension instance;
42 return instance;
43 }
44
~ModalSystemAppFreezeUIExtension()45 ModalSystemAppFreezeUIExtension::~ModalSystemAppFreezeUIExtension()
46 {
47 dialogConnectionCallback_ = nullptr;
48 }
49
GetConnection()50 sptr<ModalSystemAppFreezeUIExtension::AppFreezeDialogConnection> ModalSystemAppFreezeUIExtension::GetConnection()
51 {
52 if (dialogConnectionCallback_ == nullptr) {
53 std::lock_guard lock(dialogConnectionMutex_);
54 if (dialogConnectionCallback_ == nullptr) {
55 dialogConnectionCallback_ = new (std::nothrow) AppFreezeDialogConnection();
56 }
57 }
58
59 return dialogConnectionCallback_;
60 }
61
ProcessAppFreeze(bool focusFlag,const FaultData & faultData,std::string pid,std::string bundleName,std::function<void ()> callback,bool isDialogExist)62 void ModalSystemAppFreezeUIExtension::ProcessAppFreeze(bool focusFlag, const FaultData &faultData, std::string pid,
63 std::string bundleName, std::function<void()> callback, bool isDialogExist)
64 {
65 const std::string SCENE_BAOARD_NAME = "com.ohos.sceneboard";
66 if ((bundleName == SCENE_BAOARD_NAME || faultData.waitSaveState) && callback) {
67 callback();
68 return;
69 }
70 FaultDataType faultType = faultData.faultType;
71 std::string name = faultData.errorObject.name;
72 bool isAppFreezeDialog = name == AppFreezeType::THREAD_BLOCK_6S || name == AppFreezeType::APP_INPUT_BLOCK ||
73 name == AppFreezeType::BUSSINESS_THREAD_BLOCK_6S;
74 uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::
75 now().time_since_epoch()).count();
76 bool timeout = now - lastFreezeTime > TIMEOUT_INTERVAL_MS;
77 TAG_LOGI(AAFwkTag::ABILITYMGR,
78 "%{public}s is %{public}s.pid:%{public}s lastFreezePid:%{public}s,timeout %{public}lu", bundleName.c_str(),
79 focusFlag ? "focus" : "not focus", pid.c_str(), lastFreezePid.c_str(), now - lastFreezeTime);
80 bool isPullUpBox =
81 isAppFreezeDialog && (pid != lastFreezePid || (pid == lastFreezePid && timeout && !isDialogExist));
82 bool updateTypeName = name == AppFreezeType::THREAD_BLOCK_6S || name == AppFreezeType::BUSSINESS_THREAD_BLOCK_6S;
83 if (pid == lastFreezePid && updateTypeName) {
84 lastFreezeTime = now;
85 }
86 if (focusFlag && isPullUpBox) {
87 std::string appNoResponseBundleName = APP_NO_RESPONSE_BUNDLENAME;
88 if (appNoResponseBundleName == "com.ohos.taskmanager") {
89 callback();
90 } else {
91 CreateModalUIExtension(pid, bundleName);
92 }
93 } else if (callback && (faultType != FaultDataType::APP_FREEZE || !isAppFreezeDialog)) {
94 callback();
95 }
96 if (!isDialogExist && !focusFlag && lastFreezePid == pid) {
97 lastFreezePid = INVALID_PID;
98 lastFocusStatus = false;
99 }
100 }
101
CreateModalUIExtension(std::string pid,std::string bundleName)102 bool ModalSystemAppFreezeUIExtension::CreateModalUIExtension(std::string pid, std::string bundleName)
103 {
104 TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
105 AAFwk::Want want = CreateSystemDialogWant(pid, bundleName);
106 std::unique_lock<std::mutex> lockAssertResult(appFreezeResultMutex_);
107 auto callback = GetConnection();
108 if (callback == nullptr) {
109 TAG_LOGE(AAFwkTag::ABILITYMGR, "null callback");
110 return false;
111 }
112 callback->SetReqeustAppFreezeDialogWant(want);
113 auto abilityManagerClient = AAFwk::AbilityManagerClient::GetInstance();
114 if (abilityManagerClient == nullptr) {
115 TAG_LOGE(AAFwkTag::ABILITYMGR, "null abilityManagerClient");
116 return false;
117 }
118 AAFwk::Want systemUIWant;
119 if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
120 systemUIWant.SetElementName("com.ohos.sceneboard", "com.ohos.sceneboard.systemdialog");
121 } else {
122 systemUIWant.SetElementName("com.ohos.systemui", "com.ohos.systemui.dialog");
123 }
124 IN_PROCESS_CALL_WITHOUT_RET(abilityManagerClient->DisconnectAbility(callback));
125 auto result = IN_PROCESS_CALL(abilityManagerClient->ConnectAbility(systemUIWant, callback, INVALID_USERID));
126 if (result != ERR_OK) {
127 TAG_LOGE(AAFwkTag::ABILITYMGR,
128 "fail, result = %{public}d", result);
129 return false;
130 }
131 lastFreezePid = pid;
132 lastFocusStatus = true;
133 lastFreezeTime = std::chrono::duration_cast<std::chrono::milliseconds>(
134 std::chrono::steady_clock::now().time_since_epoch()).count();
135 TAG_LOGI(AAFwkTag::ABILITYMGR,
136 "success, result = %{public}d", result);
137 return true;
138 }
139
CreateSystemDialogWant(std::string pid,std::string bundleName)140 AAFwk::Want ModalSystemAppFreezeUIExtension::CreateSystemDialogWant(std::string pid, std::string bundleName)
141 {
142 AAFwk::Want want;
143 want.SetElementName(APP_NO_RESPONSE_BUNDLENAME, APP_NO_RESPONSE_ABILITY);
144 want.SetParam(UIEXTENSION_TYPE_KEY, UIEXTENSION_SYS_COMMON_UI);
145 want.SetParam(APP_FREEZE_PID, pid);
146 want.SetParam(START_BUNDLE_NAME, bundleName);
147 return want;
148 }
149
SetReqeustAppFreezeDialogWant(const AAFwk::Want & want)150 void ModalSystemAppFreezeUIExtension::AppFreezeDialogConnection::SetReqeustAppFreezeDialogWant(const AAFwk::Want &want)
151 {
152 want_ = want;
153 }
154
WriteWantElement(MessageParcel & data)155 bool ModalSystemAppFreezeUIExtension::AppFreezeDialogConnection::WriteWantElement(MessageParcel &data)
156 {
157 if (!data.WriteString16(u"bundleName")) {
158 TAG_LOGE(AAFwkTag::ABILITYMGR, "write bundleName failed");
159 return false;
160 }
161 if (!data.WriteString16(Str8ToStr16(want_.GetElement().GetBundleName()))) {
162 TAG_LOGE(AAFwkTag::ABILITYMGR, "write element bundlename failed");
163 return false;
164 }
165 if (!data.WriteString16(u"abilityName")) {
166 TAG_LOGE(AAFwkTag::ABILITYMGR, "write abilityName failed");
167 return false;
168 }
169 if (!data.WriteString16(Str8ToStr16(want_.GetElement().GetAbilityName()))) {
170 TAG_LOGE(AAFwkTag::ABILITYMGR, "write element abilityName failed");
171 return false;
172 }
173 return true;
174 }
175
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remote,int resultCode)176 void ModalSystemAppFreezeUIExtension::AppFreezeDialogConnection::OnAbilityConnectDone(
177 const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remote, int resultCode)
178 {
179 TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
180 if (remote == nullptr) {
181 TAG_LOGE(AAFwkTag::ABILITYMGR, "null remote");
182 return;
183 }
184
185 MessageParcel data;
186 MessageParcel reply;
187 MessageOption option;
188 if (!data.WriteInt32(MESSAGE_PARCEL_KEY_SIZE)) {
189 TAG_LOGE(AAFwkTag::ABILITYMGR, "write MESSAGE_PARCEL_KEY_SIZE failed");
190 return;
191 }
192 if (!WriteWantElement(data)) {
193 TAG_LOGE(AAFwkTag::ABILITYMGR, "write element failed");
194 return;
195 }
196 if (!data.WriteString16(u"parameters")) {
197 TAG_LOGE(AAFwkTag::ABILITYMGR, "write parameters failed");
198 return;
199 }
200 nlohmann::json param;
201 param[UIEXTENSION_TYPE_KEY.c_str()] = want_.GetStringParam(UIEXTENSION_TYPE_KEY);
202 param[APP_FREEZE_PID.c_str()] = want_.GetStringParam(APP_FREEZE_PID);
203 param[START_BUNDLE_NAME.c_str()] = want_.GetStringParam(START_BUNDLE_NAME);
204 std::string paramStr = param.dump();
205 if (!data.WriteString16(Str8ToStr16(paramStr))) {
206 TAG_LOGE(AAFwkTag::ABILITYMGR, "write paramStr failed");
207 return;
208 }
209 uint32_t code = !Rosen::SceneBoardJudgement::IsSceneBoardEnabled() ?
210 COMMAND_START_DIALOG :
211 AAFwk::IAbilityConnection::ON_ABILITY_CONNECT_DONE;
212 TAG_LOGI(AAFwkTag::ABILITYMGR, "show dialog");
213 auto ret = remote->SendRequest(code, data, reply, option);
214 if (ret != ERR_OK) {
215 TAG_LOGE(AAFwkTag::ABILITYMGR, "show dialog fail");
216 return;
217 }
218 }
219
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)220 void ModalSystemAppFreezeUIExtension::AppFreezeDialogConnection::OnAbilityDisconnectDone(
221 const AppExecFwk::ElementName &element, int resultCode)
222 {
223 TAG_LOGI(AAFwkTag::ABILITYMGR, "call");
224 }
225 } // namespace AppExecFwk
226 } // namespace OHOS
227 #endif // APP_NO_RESPONSE_DIALOG
228