• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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