1 /*
2 * Copyright (c) 2022 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 "system_dialog_scheduler.h"
16
17 #include <regex>
18
19 #include "ability_constants.h"
20 #include "ability_util.h"
21 #include "app_scheduler.h"
22 #include "display_manager.h"
23 #include "errors.h"
24 #include "hilog_wrapper.h"
25 #include "in_process_call_wrapper.h"
26 #include "locale_config.h"
27 #include "parameters.h"
28 #include "resource_manager.h"
29 #include "ui_service_mgr_client.h"
30
31 namespace OHOS {
32 namespace AAFwk {
33 const int32_t UI_SELECTOR_DIALOG_WIDTH = 328 * 2;
34 const int32_t UI_SELECTOR_DIALOG_HEIGHT = 350 * 2;
35 const int32_t UI_SELECTOR_DIALOG_HEIGHT_NARROW = 350 * 2;
36 const int32_t UI_SELECTOR_DIALOG_WIDTH_NARROW = 328 * 2;
37 const int32_t UI_SELECTOR_DIALOG_PHONE_H1 = 240 * 2;
38 const int32_t UI_SELECTOR_DIALOG_PHONE_H2 = 340 * 2;
39 const int32_t UI_SELECTOR_DIALOG_PHONE_H3 = 350 * 2;
40 const int32_t UI_SELECTOR_DIALOG_PC_H0 = 1;
41 const int32_t UI_SELECTOR_DIALOG_PC_H2 = (70 * 2 + 85 + 2) * 2;
42 const int32_t UI_SELECTOR_DIALOG_PC_H3 = (70 * 3 + 85 + 2) * 2;
43 const int32_t UI_SELECTOR_DIALOG_PC_H4 = (70 * 4 + 85 + 2) * 2;
44 const int32_t UI_SELECTOR_DIALOG_PC_H5 = (70 * 4 + 85 + 38) * 2;
45
46 const int32_t UI_TIPS_DIALOG_WIDTH = 328 * 2;
47 const int32_t UI_TIPS_DIALOG_HEIGHT = 135 * 2;
48 const int32_t UI_TIPS_DIALOG_HEIGHT_NARROW = 135 * 2;
49 const int32_t UI_TIPS_DIALOG_WIDTH_NARROW = 328 * 2;
50
51 const int32_t UI_ANR_DIALOG_WIDTH = 328 * 2;
52 const int32_t UI_ANR_DIALOG_HEIGHT = 192 * 2;
53 const std::string APP_NAME = "appName";
54 const std::string DEVICE_TYPE = "deviceType";
55 const std::string OFF_SET_X = "offsetX";
56 const std::string OFF_SET_Y = "offsetY";
57 const std::string WIDTH = "width";
58 const std::string HEIGHT = "height";
59
60 const int32_t UI_HALF = 2;
61 const int32_t UI_DEFAULT_BUTTOM_CLIP = 100;
62 const int32_t UI_WIDTH_780DP = 1560;
63 const int32_t UI_DEFAULT_WIDTH = 2560;
64 const int32_t UI_DEFAULT_HEIGHT = 1600;
65
66 const std::string STR_PHONE = "phone";
67 const std::string STR_PC = "pc";
68 const std::string DIALOG_NAME_ANR = "dialog_anr_service";
69 const std::string DIALOG_NAME_TIPS = "dialog_tips_service";
70 const std::string DIALOG_SELECTOR_NAME = "dialog_selector_service";
71
72 const std::string BUNDLE_NAME = "bundleName";
73 const std::string BUNDLE_NAME_DIALOG = "com.ohos.amsdialog";
74 const std::string DIALOG_PARAMS = "params";
75 const std::string DIALOG_POSITION = "position";
76 const std::string ABILITY_NAME_ANR_DIALOG = "AnrDialog";
77 const std::string ABILITY_NAME_TIPS_DIALOG = "TipsDialog";
78 const std::string ABILITY_NAME_SELECTOR_DIALOG = "SelectorDialog";
79
80 const int32_t LINE_NUMS_ZERO = 0;
81 const int32_t LINE_NUMS_TWO = 2;
82 const int32_t LINE_NUMS_THREE = 3;
83 const int32_t LINE_NUMS_FOUR = 4;
84 const int32_t LINE_NUMS_EIGHT = 8;
85
GetANRDialogWant(int userId,int pid,AAFwk::Want & want)86 bool SystemDialogScheduler::GetANRDialogWant(int userId, int pid, AAFwk::Want &want)
87 {
88 HILOG_DEBUG("GetANRDialogWant start");
89 AppExecFwk::ApplicationInfo appInfo;
90 bool debug;
91 auto appScheduler = DelayedSingleton<AppScheduler>::GetInstance();
92 if (appScheduler->GetApplicationInfoByProcessID(pid, appInfo, debug) != ERR_OK) {
93 HILOG_ERROR("Get application info failed.");
94 return false;
95 }
96
97 std::string appName {""};
98 GetAppNameFromResource(appInfo.labelId, appInfo.bundleName, userId, appName);
99 DialogPosition position;
100 GetDialogPositionAndSize(DialogType::DIALOG_ANR, position);
101 std::string params = GetAnrParams(position, appName);
102
103 want.SetElementName(BUNDLE_NAME_DIALOG, ABILITY_NAME_ANR_DIALOG);
104 want.SetParam(BUNDLE_NAME, appInfo.bundleName);
105 want.SetParam(DIALOG_POSITION, GetDialogPositionParams(position));
106 want.SetParam(DIALOG_PARAMS, params);
107 return true;
108 }
109
GetAnrParams(const DialogPosition position,const std::string & appName) const110 const std::string SystemDialogScheduler::GetAnrParams(const DialogPosition position, const std::string &appName) const
111 {
112 nlohmann::json anrData;
113 anrData[APP_NAME] = appName;
114 anrData[DEVICE_TYPE] = deviceType_;
115 if (!position.wideScreen) {
116 anrData[OFF_SET_X] = position.window_offsetX;
117 anrData[OFF_SET_Y] = position.window_offsetY;
118 anrData[WIDTH] = position.window_width;
119 anrData[HEIGHT] = position.window_height;
120 }
121 return anrData.dump();
122 }
123
GetTipsDialogWant()124 Want SystemDialogScheduler::GetTipsDialogWant()
125 {
126 HILOG_DEBUG("GetTipsDialogWant start");
127
128 DialogPosition position;
129 GetDialogPositionAndSize(DialogType::DIALOG_TIPS, position);
130
131 nlohmann::json jsonObj;
132 jsonObj[DEVICE_TYPE] = deviceType_;
133 const std::string params = jsonObj.dump();
134
135 AAFwk::Want want;
136 want.SetElementName(BUNDLE_NAME_DIALOG, ABILITY_NAME_TIPS_DIALOG);
137 want.SetParam(DIALOG_POSITION, GetDialogPositionParams(position));
138 want.SetParam(DIALOG_PARAMS, params);
139 return want;
140 }
141
GetSelectorDialogWant(const std::vector<DialogAppInfo> & dialogAppInfos,Want & targetWant)142 Want SystemDialogScheduler::GetSelectorDialogWant(const std::vector<DialogAppInfo> &dialogAppInfos, Want &targetWant)
143 {
144 HILOG_DEBUG("GetSelectorDialogWant start");
145 DialogPosition position;
146 GetDialogPositionAndSize(DialogType::DIALOG_SELECTOR, position, static_cast<int>(dialogAppInfos.size()));
147 std::string params = GetSelectorParams(dialogAppInfos);
148
149 targetWant.SetElementName(BUNDLE_NAME_DIALOG, ABILITY_NAME_SELECTOR_DIALOG);
150 targetWant.SetParam(DIALOG_POSITION, GetDialogPositionParams(position));
151 targetWant.SetParam(DIALOG_PARAMS, params);
152
153 return targetWant;
154 }
155
GetSelectorParams(const std::vector<DialogAppInfo> & infos) const156 const std::string SystemDialogScheduler::GetSelectorParams(const std::vector<DialogAppInfo> &infos) const
157 {
158 if (infos.empty()) {
159 HILOG_WARN("Invalid abilityInfos.");
160 return {};
161 }
162
163 nlohmann::json jsonObject;
164 jsonObject[DEVICE_TYPE] = deviceType_;
165
166 nlohmann::json hapListObj = nlohmann::json::array();
167 for (const auto &aInfo : infos) {
168 nlohmann::json aObj;
169 aObj["label"] = std::to_string(aInfo.labelId);
170 aObj["icon"] = std::to_string(aInfo.iconId);
171 aObj["bundle"] = aInfo.bundleName;
172 aObj["ability"] = aInfo.abilityName;
173 aObj["module"] = aInfo.moduleName;
174 hapListObj.emplace_back(aObj);
175 }
176 jsonObject["hapList"] = hapListObj;
177
178 return jsonObject.dump();
179 }
180
GetDialogPositionParams(const DialogPosition position) const181 const std::string SystemDialogScheduler::GetDialogPositionParams(const DialogPosition position) const
182 {
183 nlohmann::json dialogPositionData;
184 dialogPositionData[OFF_SET_X] = position.offsetX;
185 dialogPositionData[OFF_SET_Y] = position.offsetY;
186 dialogPositionData[WIDTH] = position.width;
187 dialogPositionData[HEIGHT] = position.height;
188 return dialogPositionData.dump();
189 }
190
InitDialogPosition(DialogType type,DialogPosition & position) const191 void SystemDialogScheduler::InitDialogPosition(DialogType type, DialogPosition &position) const
192 {
193 position.wideScreen = (deviceType_ == STR_PC);
194 position.align = (deviceType_ == STR_PHONE) ? DialogAlign::BOTTOM : DialogAlign::CENTER;
195 auto display = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
196
197 switch (type) {
198 case DialogType::DIALOG_ANR:
199 if (position.wideScreen) {
200 position.width = UI_ANR_DIALOG_WIDTH;
201 position.height = UI_ANR_DIALOG_HEIGHT;
202 position.width_narrow = UI_ANR_DIALOG_WIDTH;
203 position.height_narrow = UI_ANR_DIALOG_HEIGHT;
204 position.align = DialogAlign::CENTER;
205 } else {
206 position.width = display->GetWidth();
207 position.height = display->GetHeight();
208 position.width_narrow = display->GetWidth();
209 position.height_narrow = display->GetHeight();
210 position.window_width = UI_ANR_DIALOG_WIDTH;
211 position.window_height = UI_ANR_DIALOG_HEIGHT;
212 position.align = DialogAlign::CENTER;
213 }
214 break;
215 case DialogType::DIALOG_SELECTOR:
216 position.width = UI_SELECTOR_DIALOG_WIDTH;
217 position.height = UI_SELECTOR_DIALOG_HEIGHT;
218 position.width_narrow = UI_SELECTOR_DIALOG_WIDTH_NARROW;
219 position.height_narrow = UI_SELECTOR_DIALOG_HEIGHT_NARROW;
220 break;
221 case DialogType::DIALOG_TIPS:
222 position.width = UI_TIPS_DIALOG_WIDTH;
223 position.height = UI_TIPS_DIALOG_HEIGHT;
224 position.width_narrow = UI_TIPS_DIALOG_WIDTH_NARROW;
225 position.height_narrow = UI_TIPS_DIALOG_HEIGHT_NARROW;
226 break;
227 default:
228 position.width = UI_DEFAULT_WIDTH;
229 position.height = UI_DEFAULT_HEIGHT;
230 position.width_narrow = UI_DEFAULT_WIDTH;
231 position.height_narrow = UI_DEFAULT_HEIGHT;
232 break;
233 }
234 }
235
DialogPositionAdaptive(DialogPosition & position,int lineNums) const236 void SystemDialogScheduler::DialogPositionAdaptive(DialogPosition &position, int lineNums) const
237 {
238 if (position.wideScreen) {
239 if (lineNums == LINE_NUMS_TWO) {
240 position.height = UI_SELECTOR_DIALOG_PC_H2;
241 } else if (lineNums == LINE_NUMS_THREE) {
242 position.height = UI_SELECTOR_DIALOG_PC_H3;
243 } else if (lineNums == LINE_NUMS_FOUR) {
244 position.height = UI_SELECTOR_DIALOG_PC_H4;
245 } else if (lineNums > LINE_NUMS_FOUR) {
246 position.height = UI_SELECTOR_DIALOG_PC_H5;
247 } else {
248 position.height = UI_SELECTOR_DIALOG_PC_H0;
249 }
250 } else {
251 position.height = (lineNums > LINE_NUMS_EIGHT) ? UI_SELECTOR_DIALOG_PHONE_H3 :
252 (lineNums > LINE_NUMS_THREE ? UI_SELECTOR_DIALOG_PHONE_H2 :
253 (lineNums > LINE_NUMS_ZERO ? UI_SELECTOR_DIALOG_PHONE_H1 : position.height));
254 }
255 }
256
GetDialogPositionAndSize(DialogType type,DialogPosition & position,int lineNums) const257 void SystemDialogScheduler::GetDialogPositionAndSize(DialogType type, DialogPosition &position, int lineNums) const
258 {
259 InitDialogPosition(type, position);
260
261 auto display = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
262 if (display == nullptr) {
263 HILOG_WARN("share dialog GetDefaultDisplay fail, try again.");
264 display = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
265 }
266 if (display != nullptr) {
267 HILOG_INFO("display width: %{public}d, height: %{public}d", display->GetWidth(), display->GetHeight());
268 if (display->GetWidth() < UI_WIDTH_780DP) {
269 HILOG_INFO("show dialog narrow.");
270 position.width = position.width_narrow;
271 position.height = position.height_narrow;
272 }
273
274 if (type == DialogType::DIALOG_SELECTOR) {
275 DialogPositionAdaptive(position, lineNums);
276 }
277 switch (position.align) {
278 case DialogAlign::CENTER:
279 if (position.wideScreen) {
280 position.offsetX = (display->GetWidth() - position.width) / UI_HALF;
281 position.offsetY = (display->GetHeight() - position.height) / UI_HALF;
282 } else {
283 position.window_width = position.window_width / UI_HALF;
284 position.window_height = position.window_height / UI_HALF;
285 position.offsetX = LINE_NUMS_ZERO;
286 position.offsetY = LINE_NUMS_ZERO;
287 }
288 break;
289 case DialogAlign::BOTTOM:
290 position.offsetX = (display->GetWidth() - position.width) / UI_HALF;
291 position.offsetY = display->GetHeight() - position.height - UI_DEFAULT_BUTTOM_CLIP;
292 break;
293 default:
294 position.offsetX = (display->GetWidth() - position.width) / UI_HALF;
295 position.offsetY = (display->GetHeight() - position.height - UI_DEFAULT_BUTTOM_CLIP) / UI_HALF;
296 break;
297 }
298 } else {
299 HILOG_WARN("share dialog get display fail, use default wide.");
300 if (type == DialogType::DIALOG_SELECTOR) {
301 DialogPositionAdaptive(position, lineNums);
302 }
303 position.offsetX = (UI_DEFAULT_WIDTH - position.width) / UI_HALF;
304 position.offsetY = UI_DEFAULT_HEIGHT - position.height - UI_DEFAULT_BUTTOM_CLIP;
305 }
306 }
307
GetAppNameFromResource(int32_t labelId,const std::string & bundleName,int32_t userId,std::string & appName)308 void SystemDialogScheduler::GetAppNameFromResource(int32_t labelId,
309 const std::string &bundleName, int32_t userId, std::string &appName)
310 {
311 std::shared_ptr<Global::Resource::ResourceManager> resourceManager(Global::Resource::CreateResourceManager());
312 if (resourceManager == nullptr) {
313 HILOG_ERROR("resourceManager init failed!");
314 return;
315 }
316
317 AppExecFwk::BundleInfo bundleInfo;
318 auto bms = GetBundleManager();
319 CHECK_POINTER(bms);
320 if (!IN_PROCESS_CALL(
321 bms->GetBundleInfo(bundleName, AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, bundleInfo, userId))) {
322 HILOG_ERROR("Failed to get bundle info.");
323 return;
324 }
325 std::unique_ptr<Global::Resource::ResConfig> resConfig(Global::Resource::CreateResConfig());
326 UErrorCode status = U_ZERO_ERROR;
327 icu::Locale locale = icu::Locale::forLanguageTag(Global::I18n::LocaleConfig::GetSystemLanguage(), status);
328 resConfig->SetLocaleInfo(locale);
329 resourceManager->UpdateResConfig(*resConfig);
330
331 std::regex pattern(std::string(AbilityRuntime::Constants::ABS_CODE_PATH) +
332 std::string(AbilityRuntime::Constants::FILE_SEPARATOR) + bundleInfo.name);
333 for (auto hapModuleInfo : bundleInfo.hapModuleInfos) {
334 std::string loadPath;
335 if (system::GetBoolParameter(AbilityRuntime::Constants::COMPRESS_PROPERTY, false) &&
336 !hapModuleInfo.hapPath.empty()) {
337 loadPath = hapModuleInfo.hapPath;
338 } else {
339 loadPath = hapModuleInfo.resourcePath;
340 }
341 if (loadPath.empty()) {
342 continue;
343 }
344 HILOG_DEBUG("GetAppNameFromResource loadPath: %{public}s", loadPath.c_str());
345 if (!resourceManager->AddResource(loadPath.c_str())) {
346 HILOG_ERROR("ResourceManager add %{public}s resource path failed!", bundleInfo.name.c_str());
347 }
348 }
349 resourceManager->GetStringById(static_cast<uint32_t>(labelId), appName);
350 HILOG_DEBUG("Get app display info, labelId: %{public}d, appname: %{public}s", labelId, appName.c_str());
351 }
352
GetBundleManager()353 sptr<AppExecFwk::IBundleMgr> SystemDialogScheduler::GetBundleManager()
354 {
355 if (iBundleManager_ == nullptr) {
356 auto bundleObj =
357 OHOS::DelayedSingleton<SaMgrClient>::GetInstance()->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
358 if (bundleObj == nullptr) {
359 HILOG_ERROR("Failed to get bundle manager service.");
360 return nullptr;
361 }
362 iBundleManager_ = iface_cast<AppExecFwk::IBundleMgr>(bundleObj);
363 }
364 return iBundleManager_;
365 }
366 } // namespace AAFwk
367 } // namespace OHOS
368