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