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 #include "ability_manager_client.h"
16 #include "assert_fault_proxy.h"
17 #include "hilog_tag_wrapper.h"
18 #include "scene_board_judgement.h"
19 #include "task_handler_wrap.h"
20
21 namespace OHOS {
22 namespace AbilityRuntime {
23 namespace {
24 constexpr char ASSERT_FAULT_DETAIL[] = "assertFaultDialogDetail";
25 constexpr char UIEXTENSION_TYPE_KEY[] = "ability.want.params.uiExtensionType";
26 constexpr int32_t INVALID_USERID = -1;
27 constexpr int32_t MESSAGE_PARCEL_KEY_SIZE = 3;
28 constexpr uint32_t COMMAND_START_DIALOG = 1;
29 }
AssertFaultProxy(const sptr<IRemoteObject> & impl)30 AssertFaultProxy::AssertFaultProxy(const sptr<IRemoteObject> &impl) : IRemoteProxy<IAssertFaultInterface>(impl)
31 {}
32
NotifyDebugAssertResult(AAFwk::UserStatus status)33 void AssertFaultProxy::NotifyDebugAssertResult(AAFwk::UserStatus status)
34 {
35 TAG_LOGD(AAFwkTag::ABILITYMGR, "Notify user action result to assert fault application.");
36 MessageParcel data;
37 if (!data.WriteInterfaceToken(AssertFaultProxy::GetDescriptor())) {
38 TAG_LOGE(AAFwkTag::ABILITYMGR, "Write interface token failed.");
39 return;
40 }
41
42 if (!data.WriteInt32(static_cast<int32_t>(status))) {
43 TAG_LOGE(AAFwkTag::ABILITYMGR, "Write status failed.");
44 return;
45 }
46
47 auto remote = Remote();
48 if (remote == nullptr) {
49 TAG_LOGE(AAFwkTag::ABILITYMGR, "Get remote failed.");
50 return;
51 }
52
53 MessageParcel reply;
54 MessageOption option(MessageOption::TF_ASYNC);
55 if (remote->SendRequest(MessageCode::NOTIFY_DEBUG_ASSERT_RESULT, data, reply, option) != NO_ERROR) {
56 TAG_LOGE(AAFwkTag::ABILITYMGR, "Remote send request failed.");
57 }
58
59 ModalSystemAssertUIExtension::GetInstance().DisconnectSystemUI();
60 }
61
AssertFaultRemoteDeathRecipient(RemoteDiedHandler handler)62 AssertFaultRemoteDeathRecipient::AssertFaultRemoteDeathRecipient(RemoteDiedHandler handler) : handler_(handler)
63 {}
64
OnRemoteDied(const wptr<IRemoteObject> & remote)65 void AssertFaultRemoteDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
66 {
67 if (handler_ == nullptr) {
68 TAG_LOGE(AAFwkTag::ABILITYMGR, "Callback is nullptr.");
69 return;
70 }
71 handler_(remote);
72 }
73
GetInstance()74 ModalSystemAssertUIExtension &ModalSystemAssertUIExtension::GetInstance()
75 {
76 static ModalSystemAssertUIExtension instance;
77 return instance;
78 }
79
~ModalSystemAssertUIExtension()80 ModalSystemAssertUIExtension::~ModalSystemAssertUIExtension()
81 {
82 dialogConnectionCallback_ = nullptr;
83 }
84
GetConnection()85 sptr<ModalSystemAssertUIExtension::AssertDialogConnection> ModalSystemAssertUIExtension::GetConnection()
86 {
87 if (dialogConnectionCallback_ == nullptr) {
88 std::lock_guard lock(dialogConnectionMutex_);
89 if (dialogConnectionCallback_ == nullptr) {
90 dialogConnectionCallback_ = new (std::nothrow) AssertDialogConnection();
91 }
92 }
93
94 return dialogConnectionCallback_;
95 }
96
CreateModalUIExtension(const AAFwk::Want & want)97 bool ModalSystemAssertUIExtension::CreateModalUIExtension(const AAFwk::Want &want)
98 {
99 TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
100 std::unique_lock<std::mutex> lockAssertResult(assertResultMutex_);
101 if (reqeustCount_++ != 0) {
102 TAG_LOGD(AAFwkTag::ABILITYMGR, "Task busy, waiting for processing.");
103 assertResultCV_.wait(lockAssertResult);
104 }
105 auto callback = GetConnection();
106 if (callback == nullptr) {
107 TAG_LOGE(AAFwkTag::ABILITYMGR, "Callback is nullptr.");
108 TryNotifyOneWaitingThread();
109 return false;
110 }
111 callback->SetReqeustAssertDialogWant(want);
112 auto abilityManagerClient = AAFwk::AbilityManagerClient::GetInstance();
113 if (abilityManagerClient == nullptr) {
114 TAG_LOGE(AAFwkTag::ABILITYMGR, "ConnectSystemUi AbilityManagerClient is nullptr");
115 TryNotifyOneWaitingThread();
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 auto result = abilityManagerClient->ConnectAbility(systemUIWant, callback, INVALID_USERID);
125 if (result != ERR_OK) {
126 TAG_LOGE(AAFwkTag::ABILITYMGR, "ConnectSystemUi ConnectAbility dialog failed, result = %{public}d", result);
127 TryNotifyOneWaitingThread();
128 return false;
129 }
130 return true;
131 }
132
DisconnectSystemUI()133 bool ModalSystemAssertUIExtension::DisconnectSystemUI()
134 {
135 TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
136 bool retVal = true;
137 do {
138 auto abilityManagerClient = AAFwk::AbilityManagerClient::GetInstance();
139 if (abilityManagerClient == nullptr) {
140 TAG_LOGE(AAFwkTag::ABILITYMGR, "AbilityManagerClient is nullptr");
141 retVal = false;
142 break;
143 }
144 auto callback = GetConnection();
145 if (callback == nullptr) {
146 TAG_LOGE(AAFwkTag::ABILITYMGR, "Callback is nullptr.");
147 retVal = false;
148 break;
149 }
150 auto result = abilityManagerClient->DisconnectAbility(callback);
151 if (result != ERR_OK) {
152 TAG_LOGE(AAFwkTag::ABILITYMGR, "DisconnectAbility dialog failed, result = %{public}d", result);
153 retVal = false;
154 break;
155 }
156 } while (false);
157
158 return retVal;
159 }
160
TryNotifyOneWaitingThreadInner()161 void ModalSystemAssertUIExtension::TryNotifyOneWaitingThreadInner()
162 {
163 std::unique_lock<std::mutex> lockAssertResult(assertResultMutex_);
164 if (--reqeustCount_ > 0) {
165 TAG_LOGD(AAFwkTag::ABILITYMGR, "Notify waiting Thread count is %{public}d.", reqeustCount_);
166 assertResultCV_.notify_one();
167 return;
168 }
169 reqeustCount_ = 0;
170 TAG_LOGD(AAFwkTag::ABILITYMGR, "Counter reset to 0.");
171 }
172
TryNotifyOneWaitingThread()173 void ModalSystemAssertUIExtension::TryNotifyOneWaitingThread()
174 {
175 auto handler = AAFwk::TaskHandlerWrap::GetFfrtHandler();
176 if (handler != nullptr) {
177 auto notifyTask = [] () {
178 ModalSystemAssertUIExtension::GetInstance().TryNotifyOneWaitingThreadInner();
179 };
180 handler->SubmitTask(notifyTask, "TryNotifyOneWaitingThread");
181 }
182 }
183
SetReqeustAssertDialogWant(const AAFwk::Want & want)184 void ModalSystemAssertUIExtension::AssertDialogConnection::SetReqeustAssertDialogWant(const AAFwk::Want &want)
185 {
186 want_ = want;
187 }
188
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remote,int resultCode)189 void ModalSystemAssertUIExtension::AssertDialogConnection::OnAbilityConnectDone(
190 const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remote, int resultCode)
191 {
192 TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
193 if (remote == nullptr) {
194 TAG_LOGE(AAFwkTag::ABILITYMGR, "Input remote object is nullptr.");
195 return;
196 }
197
198 MessageParcel data;
199 MessageParcel reply;
200 MessageOption option;
201 data.WriteInt32(MESSAGE_PARCEL_KEY_SIZE);
202 data.WriteString16(u"bundleName");
203 data.WriteString16(Str8ToStr16(want_.GetElement().GetBundleName()));
204 data.WriteString16(u"abilityName");
205 data.WriteString16(Str8ToStr16(want_.GetElement().GetAbilityName()));
206 data.WriteString16(u"parameters");
207 nlohmann::json param;
208 param[UIEXTENSION_TYPE_KEY] = want_.GetStringParam(UIEXTENSION_TYPE_KEY);
209 param[ASSERT_FAULT_DETAIL] = want_.GetStringParam(ASSERT_FAULT_DETAIL);
210 param[AAFwk::Want::PARAM_ASSERT_FAULT_SESSION_ID] =
211 want_.GetStringParam(AAFwk::Want::PARAM_ASSERT_FAULT_SESSION_ID);
212 std::string paramStr = param.dump();
213 data.WriteString16(Str8ToStr16(paramStr));
214 uint32_t code = !Rosen::SceneBoardJudgement::IsSceneBoardEnabled() ? COMMAND_START_DIALOG :
215 AAFwk::IAbilityConnection::ON_ABILITY_CONNECT_DONE;
216 auto ret = remote->SendRequest(code, data, reply, option);
217 if (ret != ERR_OK) {
218 TAG_LOGE(AAFwkTag::ABILITYMGR, "Show dialog is failed");
219 return;
220 }
221 }
222
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)223 void ModalSystemAssertUIExtension::AssertDialogConnection::OnAbilityDisconnectDone(
224 const AppExecFwk::ElementName &element, int resultCode)
225 {
226 TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
227 ModalSystemAssertUIExtension::GetInstance().TryNotifyOneWaitingThread();
228 }
229 } // namespace AbilityRuntime
230 } // namespace OHOS