1 /*
2 * Copyright (c) 2021 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 "ui_service_mgr_client.h"
17
18 #include "dialog_callback_stub.h"
19 #include "hilog_wrapper.h"
20 #include "if_system_ability_manager.h"
21 #include "ipc_skeleton.h"
22 #include "iservice_registry.h"
23 #include "string_ex.h"
24 #include "system_ability_definition.h"
25
26 // external dependence
27 #include "ability_manager_client.h"
28 #include "display_manager.h"
29
30 namespace OHOS {
31 namespace Ace {
32 constexpr int UI_MGR_SERVICE_SA_ID = 7001;
33 constexpr int UI_DIALOG_PICKER_WIDTH = 519 * 2; // 519 vp
34 constexpr int UI_DIALOG_PICKER_HEIGHT = 256 * 2; // 256 vp
35 constexpr int UI_DIALOG_PICKER_WIDTH_NARROW = 360 * 2; // 360 vp
36 constexpr int UI_DIALOG_PICKER_HEIGHT_NARROW = 347 * 2; // 347 vp
37 constexpr int UI_DEFAULT_WIDTH = 2560;
38 constexpr int UI_DEFAULT_HEIGHT = 1600;
39 constexpr int UI_DEFAULT_BUTTOM_CLIP = 50 * 2; // 48vp
40 constexpr int UI_WIDTH_780DP = 780 * 2; // 780vp
41 constexpr int UI_HALF = 2;
42 std::shared_ptr<UIServiceMgrClient> UIServiceMgrClient::instance_ = nullptr;
43 std::mutex UIServiceMgrClient::mutex_;
44
GetInstance()45 std::shared_ptr<UIServiceMgrClient> UIServiceMgrClient::GetInstance()
46 {
47 if (instance_ == nullptr) {
48 std::lock_guard<std::mutex> lock_l(mutex_);
49 if (instance_ == nullptr) {
50 instance_ = std::make_shared<UIServiceMgrClient>();
51 }
52 }
53 return instance_;
54 }
55
UIServiceMgrClient()56 UIServiceMgrClient::UIServiceMgrClient()
57 {}
58
~UIServiceMgrClient()59 UIServiceMgrClient::~UIServiceMgrClient()
60 {}
61
RegisterCallBack(const AAFwk::Want & want,const sptr<IUIService> & uiService)62 ErrCode UIServiceMgrClient::RegisterCallBack(const AAFwk::Want& want, const sptr<IUIService>& uiService)
63 {
64 if (remoteObject_ == nullptr) {
65 ErrCode err = Connect();
66 if (err != ERR_OK) {
67 HILOG_ERROR("%{private}s:fail to connect UIMgrService", __func__);
68 return UI_SERVICE_NOT_CONNECTED;
69 }
70 }
71 sptr<IUIServiceMgr> doms = iface_cast<IUIServiceMgr>(remoteObject_);
72 return doms->RegisterCallBack(want, uiService);
73 }
74
UnregisterCallBack(const AAFwk::Want & want)75 ErrCode UIServiceMgrClient::UnregisterCallBack(const AAFwk::Want& want)
76 {
77 if (remoteObject_ == nullptr) {
78 ErrCode err = Connect();
79 if (err != ERR_OK) {
80 HILOG_ERROR("%{private}s:fail to connect UIMgrService", __func__);
81 return UI_SERVICE_NOT_CONNECTED;
82 }
83 }
84 sptr<IUIServiceMgr> doms = iface_cast<IUIServiceMgr>(remoteObject_);
85 return doms->UnregisterCallBack(want);
86 }
87
Push(const AAFwk::Want & want,const std::string & name,const std::string & jsonPath,const std::string & data,const std::string & extraData)88 ErrCode UIServiceMgrClient::Push(const AAFwk::Want& want, const std::string& name, const std::string& jsonPath,
89 const std::string& data, const std::string& extraData)
90 {
91 if (remoteObject_ == nullptr) {
92 ErrCode err = Connect();
93 if (err != ERR_OK) {
94 HILOG_ERROR("%{private}s:fail to connect UIMgrService", __func__);
95 return UI_SERVICE_NOT_CONNECTED;
96 }
97 }
98 sptr<IUIServiceMgr> doms = iface_cast<IUIServiceMgr>(remoteObject_);
99 return doms->Push(want, name, jsonPath, data, extraData);
100 }
101
Request(const AAFwk::Want & want,const std::string & name,const std::string & data)102 ErrCode UIServiceMgrClient::Request(const AAFwk::Want& want, const std::string& name, const std::string& data)
103 {
104 if (remoteObject_ == nullptr) {
105 ErrCode err = Connect();
106 if (err != ERR_OK) {
107 HILOG_ERROR("%{private}s:fail to connect UIMgrService", __func__);
108 return UI_SERVICE_NOT_CONNECTED;
109 }
110 }
111 sptr<IUIServiceMgr> doms = iface_cast<IUIServiceMgr>(remoteObject_);
112 return doms->Request(want, name, data);
113 }
114
ReturnRequest(const AAFwk::Want & want,const std::string & source,const std::string & data,const std::string & extraData)115 ErrCode UIServiceMgrClient::ReturnRequest(const AAFwk::Want& want, const std::string& source,
116 const std::string& data, const std::string& extraData)
117 {
118 if (remoteObject_ == nullptr) {
119 ErrCode err = Connect();
120 if (err != ERR_OK) {
121 HILOG_ERROR("%{private}s:fail to connect UIMgrService", __func__);
122 return UI_SERVICE_NOT_CONNECTED;
123 }
124 }
125 sptr<IUIServiceMgr> doms = iface_cast<IUIServiceMgr>(remoteObject_);
126 return doms->ReturnRequest(want, source, data, extraData);
127 }
128
ShowDialog(const std::string & name,const std::string & params,OHOS::Rosen::WindowType windowType,int x,int y,int width,int height,DialogCallback callback,int * id)129 ErrCode UIServiceMgrClient::ShowDialog(const std::string& name,
130 const std::string& params,
131 OHOS::Rosen::WindowType windowType,
132 int x,
133 int y,
134 int width,
135 int height,
136 DialogCallback callback,
137 int* id)
138 {
139 if (remoteObject_ == nullptr) {
140 ErrCode err = Connect();
141 if (err != ERR_OK) {
142 HILOG_ERROR("%{private}s:fail to connect UIMgrService", __func__);
143 return UI_SERVICE_NOT_CONNECTED;
144 }
145 }
146 const sptr<DialogCallbackStub> dialogCallbackStub(new (std::nothrow)DialogCallbackStub(callback));
147 sptr<IUIServiceMgr> doms = iface_cast<IUIServiceMgr>(remoteObject_);
148 if (doms == nullptr) {
149 HILOG_ERROR("doms is nullptr");
150 return UI_SERVICE_GET_PROXY_FAILED;
151 }
152 return doms->ShowDialog(name, params, windowType, x, y, width, height, dialogCallbackStub, id);
153 }
154
CancelDialog(int32_t id)155 ErrCode UIServiceMgrClient::CancelDialog(int32_t id)
156 {
157 if (id < 0) {
158 HILOG_INFO("invalid parameter");
159 return UI_SERVICE_INVALID_PARAMETER;
160 }
161
162 if (remoteObject_ == nullptr) {
163 ErrCode err = Connect();
164 if (err != ERR_OK) {
165 HILOG_ERROR("%{private}s:fail to connect UIMgrService", __func__);
166 return UI_SERVICE_NOT_CONNECTED;
167 }
168 }
169
170 sptr<IUIServiceMgr> doms = iface_cast<IUIServiceMgr>(remoteObject_);
171 if (doms == nullptr) {
172 HILOG_ERROR("doms is nullptr");
173 return UI_SERVICE_GET_PROXY_FAILED;
174 }
175 return doms->CancelDialog(id);
176 }
177
ShowAppPickerDialog(const AAFwk::Want & want,const std::vector<AppExecFwk::AbilityInfo> & abilityInfos,int32_t userId)178 ErrCode UIServiceMgrClient::ShowAppPickerDialog(
179 const AAFwk::Want& want, const std::vector<AppExecFwk::AbilityInfo>& abilityInfos, int32_t userId)
180 {
181 if (abilityInfos.size() == 0) {
182 HILOG_WARN("abilityInfos size is zero");
183 return UI_SERVICE_INVALID_PARAMETER;
184 }
185 int32_t offsetX = 0;
186 int32_t offsetY = 0;
187 int32_t width = UI_DIALOG_PICKER_WIDTH;
188 int32_t height = UI_DIALOG_PICKER_HEIGHT;
189 bool wideScreen = true;
190 GetDisplayPosition(offsetX, offsetY, width, height, wideScreen);
191 const std::string param = GetPickerDialogParam(want, abilityInfos, wideScreen);
192 HILOG_DEBUG("share dialog position:[%{public}d,%{public}d,%{public}d,%{public}d],str: %{public}s",
193 offsetX, offsetY, width, height, param.c_str());
194 const std::string jsBundleName = "dialog_picker_service";
195 return ShowDialog(jsBundleName, param, OHOS::Rosen::WindowType::WINDOW_TYPE_SYSTEM_ALARM_WINDOW, offsetX, offsetY,
196 width, height, [want, userId](int32_t id, const std::string& event, const std::string& params) mutable {
197 HILOG_DEBUG("dialog callback: event: %{public}s, params: %{public}s", event.c_str(), params.c_str());
198 if (event == "SHARE_EVENT") {
199 std::string bundleName;
200 std::string abilityName;
201 auto pos = params.find(";");
202 if (pos != std::string::npos) {
203 bundleName = params.substr(0, pos);
204 abilityName = params.substr(pos + 1, params.length() - (pos + 1));
205 }
206 AAFwk::Want shareWant = want;
207 shareWant.SetAction("");
208 shareWant.SetElementName(bundleName, abilityName);
209 auto abilityClient = AAFwk::AbilityManagerClient::GetInstance();
210 if (abilityClient != nullptr) {
211 HILOG_INFO("dialog callback: %{public}s-%{public}s", bundleName.c_str(), abilityName.c_str());
212 abilityClient->StartAbility(shareWant, AAFwk::DEFAULT_INVAL_VALUE, userId);
213 }
214 }
215 Ace::UIServiceMgrClient::GetInstance()->CancelDialog(id);
216 });
217 }
218
219 /**
220 * Connect ui_service manager service.
221 *
222 * @return Returns ERR_OK on success, others on failure.
223 */
Connect()224 ErrCode UIServiceMgrClient::Connect()
225 {
226 std::lock_guard<std::mutex> lock(mutex_);
227 if (remoteObject_ != nullptr) {
228 return ERR_OK;
229 }
230 sptr<ISystemAbilityManager> systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
231 if (systemManager == nullptr) {
232 HILOG_ERROR("%{private}s:fail to get Registry", __func__);
233 return GET_UI_SERVICE_FAILED;
234 }
235 remoteObject_ = systemManager->GetSystemAbility(UI_MGR_SERVICE_SA_ID);
236 if (remoteObject_ == nullptr) {
237 HILOG_ERROR("%{private}s:fail to connect UIMgrService", __func__);
238 return GET_UI_SERVICE_FAILED;
239 }
240 HILOG_DEBUG("connect UIMgrService success");
241 return ERR_OK;
242 }
243
GetPickerDialogParam(const AAFwk::Want & want,const std::vector<AppExecFwk::AbilityInfo> & abilityInfos,bool wideScreen) const244 const std::string UIServiceMgrClient::GetPickerDialogParam(
245 const AAFwk::Want& want, const std::vector<AppExecFwk::AbilityInfo>& abilityInfos, bool wideScreen) const
246 {
247 auto type = want.GetStringParam("ability.picker.type");
248 auto text = want.GetStringParam("ability.picker.text");
249 auto uri = want.GetStringParam("ability.picker.uri");
250 auto fileNames = want.GetStringArrayParam("ability.picker.fileNames");
251 auto fileSizes = want.GetIntArrayParam("ability.picker.fileSizes");
252
253 std::string param = "{"; // json head
254 if (!wideScreen) {
255 param += "\"deviceType\": \"phone\",";
256 }
257 param += "\"previewCard\": { \"type\": \"";
258 param += type;
259 param += "\", \"icon\": \"";
260 param += "";
261 param += "\", \"mainText\": \"";
262 param += text;
263 param += "\", \"subText\": \"";
264 param += uri;
265 param += "\", \"fileList\": [";
266 for (int i = 0; i < (int)fileNames.size() && i < (int)fileSizes.size(); i++) {
267 param += "{";
268 param += "\"name\": \"";
269 param += fileNames[i];
270 param += "\", \"size\": ";
271 param += std::to_string(fileSizes[i]);
272 param += "}";
273 if (i != (int)fileNames.size() - 1 && i != (int)fileSizes.size() - 1) {
274 param += ",";
275 }
276 }
277 param += "]},";
278 param += "\"hapList\": [";
279 for (int i = 0; i < (int)abilityInfos.size(); i++) {
280 const auto& abilityInfo = abilityInfos[i];
281 param += "{ \"name\": \"";
282 param += std::to_string(abilityInfo.labelId); // or string abilityInfo.label
283 param += "\", \"icon\": \"";
284 param += std::to_string(abilityInfo.iconId); // or string abilityInfo.icon
285 param += "\", \"bundle\": \"";
286 param += abilityInfo.bundleName;
287 param += "\", \"ability\": \"";
288 param += abilityInfo.name;
289 param += "\" }";
290 if (i != (int)abilityInfos.size() - 1) {
291 param += ",";
292 }
293 }
294 param += "]";
295 param += "}"; // json tail
296 return param;
297 }
298
GetDisplayPosition(int32_t & offsetX,int32_t & offsetY,int32_t & width,int32_t & height,bool & wideScreen)299 void UIServiceMgrClient::GetDisplayPosition(
300 int32_t& offsetX, int32_t& offsetY, int32_t& width, int32_t& height, bool& wideScreen)
301 {
302 wideScreen = true;
303 auto display = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
304 if (display == nullptr) {
305 HILOG_WARN("share dialog GetDefaultDisplay fail, try again.");
306 display = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
307 }
308
309 if (display != nullptr) {
310 if (display->GetWidth() < UI_WIDTH_780DP) {
311 HILOG_INFO("share dialog narrow.");
312 wideScreen = false;
313 width = UI_DIALOG_PICKER_WIDTH_NARROW;
314 height = UI_DIALOG_PICKER_HEIGHT_NARROW;
315 }
316 offsetX = (display->GetWidth() - width) / UI_HALF;
317 offsetY = display->GetHeight() - height - UI_DEFAULT_BUTTOM_CLIP;
318 } else {
319 HILOG_WARN("share dialog get display fail, use default wide.");
320 offsetX = (UI_DEFAULT_WIDTH - width) / UI_HALF;
321 offsetY = UI_DEFAULT_HEIGHT - height - UI_DEFAULT_BUTTOM_CLIP;
322 }
323 }
324 } // namespace Ace
325 } // namespace OHOS
326