1 /*
2  * Copyright (c) 2023-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 #include "modal_system_ui_extension.h"
17 
18 #include <memory>
19 
20 #include <ability_manager_client.h>
21 #include <ffrt.h>
22 #include <iremote_object.h>
23 #include <message_parcel.h>
24 
25 #include "window_manager_hilog.h"
26 
27 using namespace OHOS::AAFwk;
28 
29 namespace OHOS {
30 namespace Rosen {
31 namespace {
32 constexpr int32_t INVALID_USERID = -1;
33 constexpr int32_t MESSAGE_PARCEL_KEY_SIZE = 3;
34 constexpr int32_t VALUE_TYPE_STRING = 9;
35 constexpr uint64_t DISCONNECT_ABILITY_DELAY_TIME_MICROSECONDS = 5000000;
36 } // namespace
37 
ModalSystemUiExtension()38 ModalSystemUiExtension::ModalSystemUiExtension() {}
39 
~ModalSystemUiExtension()40 ModalSystemUiExtension::~ModalSystemUiExtension()
41 {
42     dialogConnectionCallback_ = nullptr;
43 }
44 
CreateModalUIExtension(const AAFwk::Want & want)45 bool ModalSystemUiExtension::CreateModalUIExtension(const AAFwk::Want& want)
46 {
47     auto abilityManagerClient = AbilityManagerClient::GetInstance();
48     if (abilityManagerClient == nullptr) {
49         TLOGE(WmsLogTag::WMS_UIEXT, "AbilityManagerClient is nullptr");
50         return false;
51     }
52 
53     AAFwk::Want systemUIWant;
54     systemUIWant.SetElementName("com.ohos.sceneboard", "com.ohos.sceneboard.systemdialog");
55     dialogConnectionCallback_ = sptr<DialogAbilityConnection>::MakeSptr(want);
56     auto result = abilityManagerClient->ConnectAbility(systemUIWant, dialogConnectionCallback_, INVALID_USERID);
57     if (result != ERR_OK) {
58         TLOGE(WmsLogTag::WMS_UIEXT, "ConnectAbility failed, result = %{public}d", result);
59         return false;
60     }
61     TLOGI(WmsLogTag::WMS_UIEXT, "ConnectAbility success");
62     return true;
63 }
64 
ToString(const AAFwk::WantParams & wantParams)65 std::string ModalSystemUiExtension::ToString(const AAFwk::WantParams& wantParams)
66 {
67     std::string result;
68     if (wantParams.Size() != 0) {
69         result += "{";
70         for (auto it : wantParams.GetParams()) {
71             int typeId = AAFwk::WantParams::GetDataType(it.second);
72             result += "\"" + it.first + "\":";
73             if (typeId == VALUE_TYPE_STRING && AAFwk::WantParams::GetStringByType(it.second, typeId)[0] != '{') {
74                 result += "\"" + AAFwk::WantParams::GetStringByType(it.second, typeId) + "\"";
75             } else {
76                 result += AAFwk::WantParams::GetStringByType(it.second, typeId);
77             }
78             if (it != *wantParams.GetParams().rbegin()) {
79                 result += ",";
80             }
81         }
82         result += "}";
83     } else {
84         result += "{}";
85     }
86     return result;
87 }
88 
SendWant(const sptr<IRemoteObject> & remoteObject)89 bool ModalSystemUiExtension::DialogAbilityConnection::SendWant(const sptr<IRemoteObject>& remoteObject)
90 {
91     MessageParcel data;
92     MessageParcel reply;
93     MessageOption option(MessageOption::TF_ASYNC);
94     if (!data.WriteInt32(MESSAGE_PARCEL_KEY_SIZE)) {
95         TLOGE(WmsLogTag::WMS_UIEXT, "write message parcel key size failed");
96         return false;
97     }
98     if (!data.WriteString16(u"bundleName") || !data.WriteString16(Str8ToStr16(want_.GetElement().GetBundleName()))) {
99         TLOGE(WmsLogTag::WMS_UIEXT, "write bundleName failed");
100         return false;
101     }
102     if (!data.WriteString16(u"abilityName") || !data.WriteString16(Str8ToStr16(want_.GetElement().GetAbilityName()))) {
103         TLOGE(WmsLogTag::WMS_UIEXT, "write abilityName failed");
104         return false;
105     }
106     if (!data.WriteString16(u"parameters") ||
107         !data.WriteString16(Str8ToStr16(ModalSystemUiExtension::ToString(want_.GetParams())))) {
108         TLOGE(WmsLogTag::WMS_UIEXT, "write parameters failed");
109         return false;
110     }
111     int32_t ret = remoteObject->SendRequest(AAFwk::IAbilityConnection::ON_ABILITY_CONNECT_DONE, data, reply, option);
112     if (ret != ERR_OK) {
113         TLOGE(WmsLogTag::WMS_UIEXT, "show dialog failed");
114         return false;
115     }
116     return true;
117 }
118 
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)119 void ModalSystemUiExtension::DialogAbilityConnection::OnAbilityConnectDone(
120     const AppExecFwk::ElementName& element, const sptr<IRemoteObject>& remoteObject, int resultCode)
121 {
122     TLOGI(WmsLogTag::WMS_UIEXT, "called");
123     if (remoteObject == nullptr) {
124         TLOGE(WmsLogTag::WMS_UIEXT, "remoteObject is nullptr");
125         return;
126     }
127     if (!SendWant(remoteObject)) {
128         return;
129     }
130     auto task = [weakThis = wptr(this)] {
131         auto connection = weakThis.promote();
132         if (!connection) {
133             TLOGI(WmsLogTag::WMS_UIEXT, "session is null or already disconnected");
134             return;
135         }
136         auto abilityManagerClient = AbilityManagerClient::GetInstance();
137         if (abilityManagerClient == nullptr) {
138             TLOGE(WmsLogTag::WMS_UIEXT, "AbilityManagerClient is nullptr");
139             return;
140         }
141         auto result = abilityManagerClient->DisconnectAbility(connection);
142         if (result != ERR_OK) {
143             TLOGE(WmsLogTag::WMS_UIEXT, "DisconnectAbility failed, result = %{public}d", result);
144         } else {
145             TLOGI(WmsLogTag::WMS_UIEXT, "DisconnectAbility success");
146         }
147     };
148     ffrt::task_handle handle = ffrt::submit_h(std::move(task),
149         ffrt::task_attr().delay(DISCONNECT_ABILITY_DELAY_TIME_MICROSECONDS));
150     if (handle == nullptr) {
151         TLOGE(WmsLogTag::WMS_UIEXT, "Failed to post task");
152     }
153 }
154 
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)155 void ModalSystemUiExtension::DialogAbilityConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName& element,
156     int resultCode)
157 {
158     TLOGI(WmsLogTag::WMS_UIEXT, "called");
159 }
160 } // namespace Rosen
161 } // namespace OHOS