1/*
2 * Copyright (c) 2023 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 "app_utils.h"
17#include "json_utils.h"
18#include "hilog_tag_wrapper.h"
19#include "nlohmann/json.hpp"
20#include "parameters.h"
21#ifdef SUPPORT_GRAPHICS
22#include "scene_board_judgement.h"
23#endif // SUPPORT_GRAPHICS
24
25
26namespace OHOS {
27namespace AAFwk {
28namespace {
29constexpr const char* BUNDLE_NAME_LAUNCHER = "com.ohos.launcher";
30constexpr const char* BUNDLE_NAME_SCENEBOARD = "com.ohos.sceneboard";
31constexpr const char* LAUNCHER_ABILITY_NAME = "com.ohos.launcher.MainAbility";
32constexpr const char* SCENEBOARD_ABILITY_NAME = "com.ohos.sceneboard.MainAbility";
33constexpr const char* INHERIT_WINDOW_SPLIT_SCREEN_MODE = "persist.sys.abilityms.inherit_window_split_screen_mode";
34constexpr const char* SUPPORT_ANCO_APP = "persist.sys.abilityms.support_anco_app";
35constexpr const char* TIMEOUT_UNIT_TIME_RATIO = "persist.sys.abilityms.timeout_unit_time_ratio";
36constexpr const char* SELECTOR_DIALOG_POSSION = "persist.sys.abilityms.selector_dialog_possion";
37constexpr const char* START_SPECIFIED_PROCESS = "persist.sys.abilityms.start_specified_process";
38constexpr const char* USE_MULTI_RENDER_PROCESS = "persist.sys.abilityms.use_multi_render_process";
39constexpr const char* LIMIT_MAXIMUM_OF_RENDER_PROCESS = "persist.sys.abilityms.limit_maximum_of_render_process";
40constexpr const char* GRANT_PERSIST_URI_PERMISSION = "persist.sys.abilityms.grant_persist_uri_permission";
41constexpr const char* START_OPTIONS_WITH_ANIMATION = "persist.sys.abilityms.start_options_with_animation";
42constexpr const char* MULTI_PROCESS_MODEL = "persist.sys.abilityms.multi_process_model";
43constexpr const char* START_OPTIONS_WITH_PROCESS_OPTION = "persist.sys.abilityms.start_options_with_process_option";
44constexpr const char* MOVE_UI_ABILITY_TO_BACKGROUND_API_ENABLE =
45    "persist.sys.abilityms.move_ui_ability_to_background_api_enable";
46constexpr const char* CONFIG_PATH = "/etc/ability_runtime/resident_process_in_extreme_memory.json";
47constexpr const char* RESIDENT_PROCESS_IN_EXTREME_MEMORY = "residentProcessInExtremeMemory";
48constexpr const char* BUNDLE_NAME = "bundleName";
49constexpr const char* ABILITY_NAME = "abilityName";
50constexpr const char* KEY_IDENTIFIER = "identifier";
51constexpr const char* ALLOW_NATIVE_CHILD_PROCESS_APPS_CONFIG_PATH =
52    "/etc/ability_runtime/allow_native_child_process_apps.json";
53constexpr const char* KEY_ALLOW_NATIVE_CHILD_PROCESS_APPS = "allowNativeChildProcessApps";
54constexpr const char* LAUNCH_EMBEDED_UI_ABILITY = "const.abilityms.launch_embeded_ui_ability";
55const std::string SUPPROT_NATIVE_CHILD_PROCESS = "persist.sys.abilityms.start_native_child_process";
56const std::string LIMIT_MAXIMUM_EXTENSIONS_OF_PER_PROCESS =
57    "const.sys.abilityms.limit_maximum_extensions_of_per_process";
58const std::string LIMIT_MAXIMUM_EXTENSIONS_OF_PER_DEVICE =
59    "const.sys.abilityms.limit_maximum_extensions_of_per_device";
60const std::string CACHE_EXTENSION_TYPES = "const.sys.abilityms.cache_extension";
61constexpr const char* START_ABILITY_WITHOUT_CALLERTOKEN = "/system/etc/start_ability_without_caller_token.json";
62constexpr const char* START_ABILITY_WITHOUT_CALLERTOKEN_PATH =
63    "/etc/ability_runtime/start_ability_without_caller_token.json";
64constexpr const char* START_ABILITY_WITHOUT_CALLERTOKEN_TITLE = "startAbilityWithoutCallerToken";
65constexpr const char* BROKER_DELEGATE_BUNDLE_NAME = "const.sys.abilityms.broker_delegate_bundle_name";
66constexpr const char* COLLABORATOR_BROKER_UID = "const.sys.abilityms.collaborator_broker_uid";
67constexpr const char* COLLABORATOR_BROKER_RESERVE_UID = "const.sys.abilityms.collaborator_broker_reserve_uid";
68constexpr const char* MAX_CHILD_PROCESS = "const.max_native_child_process";
69constexpr const char* SUPPORT_MULTI_INSTANCE = "const.abilityms.support_multi_instance";
70constexpr const char* MIGRATE_CLIENT_BUNDLE_NAME = "const.sys.abilityms.migrate_client_bundle_name";
71}
72
73AppUtils::~AppUtils() {}
74
75AppUtils::AppUtils()
76{
77    #ifdef SUPPORT_GRAPHICS
78    if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
79        isSceneBoard_ = true;
80    }
81    #endif // SUPPORT_GRAPHICS
82}
83
84AppUtils &AppUtils::GetInstance()
85{
86    static AppUtils utils;
87    return utils;
88}
89
90bool AppUtils::IsLauncher(const std::string &bundleName) const
91{
92    if (isSceneBoard_) {
93        return bundleName == BUNDLE_NAME_SCENEBOARD;
94    }
95
96    return bundleName == BUNDLE_NAME_LAUNCHER;
97}
98
99bool AppUtils::IsLauncherAbility(const std::string &abilityName) const
100{
101    if (isSceneBoard_) {
102        return abilityName == SCENEBOARD_ABILITY_NAME;
103    }
104
105    return abilityName == LAUNCHER_ABILITY_NAME;
106}
107
108bool AppUtils::IsInheritWindowSplitScreenMode()
109{
110    if (!isInheritWindowSplitScreenMode_.isLoaded) {
111        isInheritWindowSplitScreenMode_.value = system::GetBoolParameter(INHERIT_WINDOW_SPLIT_SCREEN_MODE, true);
112        isInheritWindowSplitScreenMode_.isLoaded = true;
113    }
114    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", isInheritWindowSplitScreenMode_.value);
115    return isInheritWindowSplitScreenMode_.value;
116}
117
118bool AppUtils::IsSupportAncoApp()
119{
120    if (!isSupportAncoApp_.isLoaded) {
121        isSupportAncoApp_.value = system::GetBoolParameter(SUPPORT_ANCO_APP, false);
122        isSupportAncoApp_.isLoaded = true;
123    }
124    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", isSupportAncoApp_.value);
125    return isSupportAncoApp_.value;
126}
127
128int32_t AppUtils::GetTimeoutUnitTimeRatio()
129{
130    if (!timeoutUnitTimeRatio_.isLoaded) {
131        timeoutUnitTimeRatio_.value = system::GetIntParameter<int32_t>(TIMEOUT_UNIT_TIME_RATIO, 1);
132        timeoutUnitTimeRatio_.isLoaded = true;
133    }
134    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", timeoutUnitTimeRatio_.value);
135    return timeoutUnitTimeRatio_.value;
136}
137
138bool AppUtils::IsSelectorDialogDefaultPossion()
139{
140    if (!isSelectorDialogDefaultPossion_.isLoaded) {
141        isSelectorDialogDefaultPossion_.value = system::GetBoolParameter(SELECTOR_DIALOG_POSSION, true);
142        isSelectorDialogDefaultPossion_.isLoaded = true;
143    }
144    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", isSelectorDialogDefaultPossion_.value);
145    return isSelectorDialogDefaultPossion_.value;
146}
147
148bool AppUtils::IsStartSpecifiedProcess()
149{
150    if (!isStartSpecifiedProcess_.isLoaded) {
151        isStartSpecifiedProcess_.value = system::GetBoolParameter(START_SPECIFIED_PROCESS, false);
152        isStartSpecifiedProcess_.isLoaded = true;
153    }
154    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", isStartSpecifiedProcess_.value);
155    return isStartSpecifiedProcess_.value;
156}
157
158bool AppUtils::IsUseMultiRenderProcess()
159{
160    if (!isUseMultiRenderProcess_.isLoaded) {
161        isUseMultiRenderProcess_.value = system::GetBoolParameter(USE_MULTI_RENDER_PROCESS, true);
162        isUseMultiRenderProcess_.isLoaded = true;
163    }
164    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", isUseMultiRenderProcess_.value);
165    return isUseMultiRenderProcess_.value;
166}
167
168bool AppUtils::IsLimitMaximumOfRenderProcess()
169{
170    if (!isLimitMaximumOfRenderProcess_.isLoaded) {
171        isLimitMaximumOfRenderProcess_.value = system::GetBoolParameter(LIMIT_MAXIMUM_OF_RENDER_PROCESS, true);
172        isLimitMaximumOfRenderProcess_.isLoaded = true;
173    }
174    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", isLimitMaximumOfRenderProcess_.value);
175    return isLimitMaximumOfRenderProcess_.value;
176}
177
178bool AppUtils::IsGrantPersistUriPermission()
179{
180    if (!isGrantPersistUriPermission_.isLoaded) {
181        isGrantPersistUriPermission_.value = system::GetBoolParameter(GRANT_PERSIST_URI_PERMISSION, false);
182        isGrantPersistUriPermission_.isLoaded = true;
183    }
184    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", isGrantPersistUriPermission_.value);
185    return isGrantPersistUriPermission_.value;
186}
187
188bool AppUtils::IsStartOptionsWithAnimation()
189{
190    if (!isStartOptionsWithAnimation_.isLoaded) {
191        isStartOptionsWithAnimation_.value = system::GetBoolParameter(START_OPTIONS_WITH_ANIMATION, false);
192        isStartOptionsWithAnimation_.isLoaded = true;
193    }
194    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", isStartOptionsWithAnimation_.value);
195    return isStartOptionsWithAnimation_.value;
196}
197
198bool AppUtils::IsMultiProcessModel()
199{
200    if (!isMultiProcessModel_.isLoaded) {
201        isMultiProcessModel_.value = system::GetBoolParameter(MULTI_PROCESS_MODEL, false);
202        isMultiProcessModel_.isLoaded = true;
203    }
204    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", isMultiProcessModel_.value);
205    return isMultiProcessModel_.value;
206}
207
208bool AppUtils::IsStartOptionsWithProcessOptions()
209{
210    if (!isStartOptionsWithProcessOptions_.isLoaded) {
211        isStartOptionsWithProcessOptions_.value = system::GetBoolParameter(START_OPTIONS_WITH_PROCESS_OPTION, false);
212        isStartOptionsWithProcessOptions_.isLoaded = true;
213    }
214    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", isStartOptionsWithProcessOptions_.value);
215    return isStartOptionsWithProcessOptions_.value;
216}
217
218bool AppUtils::EnableMoveUIAbilityToBackgroundApi()
219{
220    if (!enableMoveUIAbilityToBackgroundApi_.isLoaded) {
221        enableMoveUIAbilityToBackgroundApi_.value =
222            system::GetBoolParameter(MOVE_UI_ABILITY_TO_BACKGROUND_API_ENABLE, true);
223        enableMoveUIAbilityToBackgroundApi_.isLoaded = true;
224    }
225    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", enableMoveUIAbilityToBackgroundApi_.value);
226    return enableMoveUIAbilityToBackgroundApi_.value;
227}
228
229bool AppUtils::IsLaunchEmbededUIAbility()
230{
231    if (!isLaunchEmbededUIAbility_.isLoaded) {
232        isLaunchEmbededUIAbility_.value = system::GetBoolParameter(LAUNCH_EMBEDED_UI_ABILITY, false);
233        isLaunchEmbededUIAbility_.isLoaded = true;
234    }
235    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", isLaunchEmbededUIAbility_.value);
236    return isLaunchEmbededUIAbility_.value;
237}
238
239bool AppUtils::IsSupportNativeChildProcess()
240{
241    if (!isSupportNativeChildProcess_.isLoaded) {
242        isSupportNativeChildProcess_.value = system::GetBoolParameter(SUPPROT_NATIVE_CHILD_PROCESS, false);
243        isSupportNativeChildProcess_.isLoaded = true;
244    }
245    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", isSupportNativeChildProcess_.value);
246    return isSupportNativeChildProcess_.value;
247}
248
249bool AppUtils::IsAllowResidentInExtremeMemory(const std::string& bundleName, const std::string& abilityName)
250{
251    std::lock_guard lock(residentProcessInExtremeMemoryMutex_);
252    if (!residentProcessInExtremeMemory_.isLoaded) {
253        LoadResidentProcessInExtremeMemory();
254        residentProcessInExtremeMemory_.isLoaded = true;
255    }
256    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", isSupportNativeChildProcess_.value);
257    for (auto &element : residentProcessInExtremeMemory_.value) {
258        if (bundleName == element.first &&
259            (abilityName == "" || abilityName == element.second)) {
260            return true;
261        }
262    }
263    return false;
264}
265
266void AppUtils::LoadResidentProcessInExtremeMemory()
267{
268    nlohmann::json object;
269    if (!JsonUtils::GetInstance().LoadConfiguration(CONFIG_PATH, object)) {
270        TAG_LOGE(AAFwkTag::ABILITYMGR, "resident process failed");
271        return;
272    }
273    if (!object.contains(RESIDENT_PROCESS_IN_EXTREME_MEMORY)) {
274        TAG_LOGE(AAFwkTag::ABILITYMGR, "resident process invalid");
275        return;
276    }
277
278    for (auto &item : object.at(RESIDENT_PROCESS_IN_EXTREME_MEMORY).items()) {
279        const nlohmann::json& jsonObject = item.value();
280        if (!jsonObject.contains(BUNDLE_NAME) || !jsonObject.at(BUNDLE_NAME).is_string()) {
281            TAG_LOGE(AAFwkTag::ABILITYMGR, "load bundleName failed");
282            return;
283        }
284        if (!jsonObject.contains(ABILITY_NAME) || !jsonObject.at(ABILITY_NAME).is_string()) {
285            TAG_LOGE(AAFwkTag::ABILITYMGR, "load abilityName failed");
286            return;
287        }
288        std::string bundleName = jsonObject.at(BUNDLE_NAME).get<std::string>();
289        std::string abilityName = jsonObject.at(ABILITY_NAME).get<std::string>();
290        residentProcessInExtremeMemory_.value.emplace_back(std::make_pair(bundleName, abilityName));
291    }
292}
293
294bool AppUtils::IsAllowNativeChildProcess(const std::string &appIdentifier)
295{
296    TAG_LOGD(AAFwkTag::DEFAULT, "appId:%{private}s", appIdentifier.c_str());
297    if (!allowStartNativeProcessApps_.isLoaded) {
298        LoadAllowNativeChildProcessApps();
299        allowStartNativeProcessApps_.isLoaded = true;
300    }
301    auto &apps = allowStartNativeProcessApps_.value;
302    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}zu", apps.size());
303    return std::find(apps.begin(), apps.end(), appIdentifier) != apps.end();
304}
305
306void AppUtils::LoadAllowNativeChildProcessApps()
307{
308    nlohmann::json object;
309    if (!JsonUtils::GetInstance().LoadConfiguration(ALLOW_NATIVE_CHILD_PROCESS_APPS_CONFIG_PATH, object)) {
310        TAG_LOGE(AAFwkTag::ABILITYMGR, "load child process config failed");
311        return;
312    }
313    if (!object.contains(KEY_ALLOW_NATIVE_CHILD_PROCESS_APPS)) {
314        TAG_LOGE(AAFwkTag::ABILITYMGR, "get key invalid");
315        return;
316    }
317
318    for (auto &item : object.at(KEY_ALLOW_NATIVE_CHILD_PROCESS_APPS).items()) {
319        const nlohmann::json& jsonObject = item.value();
320        if (!jsonObject.contains(KEY_IDENTIFIER) || !jsonObject.at(KEY_IDENTIFIER).is_string()) {
321            TAG_LOGE(AAFwkTag::ABILITYMGR, "load identifier failed");
322            return;
323        }
324        std::string identifier = jsonObject.at(KEY_IDENTIFIER).get<std::string>();
325        allowStartNativeProcessApps_.value.emplace_back(identifier);
326    }
327}
328
329int32_t AppUtils::GetLimitMaximumExtensionsPerProc()
330{
331    if (!limitMaximumExtensionsPerProc_.isLoaded) {
332        limitMaximumExtensionsPerProc_.value =
333            system::GetIntParameter<int32_t>(LIMIT_MAXIMUM_EXTENSIONS_OF_PER_PROCESS, DEFAULT_MAX_EXT_PER_PROC);
334        limitMaximumExtensionsPerProc_.isLoaded = true;
335    }
336    TAG_LOGD(AAFwkTag::DEFAULT, "limitMaximumExtensionsPerProc: %{public}d", limitMaximumExtensionsPerProc_.value);
337    return limitMaximumExtensionsPerProc_.value;
338}
339
340int32_t AppUtils::GetLimitMaximumExtensionsPerDevice()
341{
342    if (!limitMaximumExtensionsPerDevice_.isLoaded) {
343        limitMaximumExtensionsPerDevice_.value =
344            system::GetIntParameter<int32_t>(LIMIT_MAXIMUM_EXTENSIONS_OF_PER_DEVICE, DEFAULT_MAX_EXT_PER_DEV);
345        limitMaximumExtensionsPerDevice_.isLoaded = true;
346    }
347    TAG_LOGD(AAFwkTag::DEFAULT, "limitMaximumExtensionsPerDevice: %{public}d", limitMaximumExtensionsPerDevice_.value);
348    return limitMaximumExtensionsPerDevice_.value;
349}
350
351std::string AppUtils::GetCacheExtensionTypeList()
352{
353    std::string cacheExtAbilityTypeList = system::GetParameter(CACHE_EXTENSION_TYPES, "260");
354    TAG_LOGD(AAFwkTag::DEFAULT, "cacheExtAbilityTypeList is %{public}s", cacheExtAbilityTypeList.c_str());
355    return cacheExtAbilityTypeList;
356}
357
358bool AppUtils::IsAllowStartAbilityWithoutCallerToken(const std::string& bundleName, const std::string& abilityName)
359{
360    std::lock_guard lock(startAbilityWithoutCallerTokenMutex_);
361    if (!startAbilityWithoutCallerToken_.isLoaded) {
362        LoadStartAbilityWithoutCallerToken();
363        startAbilityWithoutCallerToken_.isLoaded = true;
364    }
365    TAG_LOGD(AAFwkTag::DEFAULT, "isLoaded: %{public}d", startAbilityWithoutCallerToken_.isLoaded);
366    for (auto &element : startAbilityWithoutCallerToken_.value) {
367        if (bundleName == element.first && abilityName == element.second) {
368            TAG_LOGI(AAFwkTag::DEFAULT, "call");
369            return true;
370        }
371    }
372    return false;
373}
374
375void AppUtils::LoadStartAbilityWithoutCallerToken()
376{
377    nlohmann::json object;
378    if (!JsonUtils::GetInstance().LoadConfiguration(
379        START_ABILITY_WITHOUT_CALLERTOKEN_PATH, object, START_ABILITY_WITHOUT_CALLERTOKEN)) {
380        TAG_LOGE(AAFwkTag::DEFAULT, "token list failed");
381        return;
382    }
383    if (!object.contains(START_ABILITY_WITHOUT_CALLERTOKEN_TITLE)) {
384        TAG_LOGE(AAFwkTag::DEFAULT, "token config invalid");
385        return;
386    }
387
388    for (auto &item : object.at(START_ABILITY_WITHOUT_CALLERTOKEN_TITLE).items()) {
389        const nlohmann::json& jsonObject = item.value();
390        if (!jsonObject.contains(BUNDLE_NAME) || !jsonObject.at(BUNDLE_NAME).is_string()) {
391            TAG_LOGE(AAFwkTag::DEFAULT, "load bundleName failed");
392            return;
393        }
394        if (!jsonObject.contains(ABILITY_NAME) || !jsonObject.at(ABILITY_NAME).is_string()) {
395            TAG_LOGE(AAFwkTag::DEFAULT, "load abilityName failed");
396            return;
397        }
398        std::string bundleName = jsonObject.at(BUNDLE_NAME).get<std::string>();
399        std::string abilityName = jsonObject.at(ABILITY_NAME).get<std::string>();
400        startAbilityWithoutCallerToken_.value.emplace_back(std::make_pair(bundleName, abilityName));
401    }
402}
403
404std::string AppUtils::GetBrokerDelegateBundleName()
405{
406    if (!brokerDelegateBundleName_.isLoaded) {
407        brokerDelegateBundleName_.value = system::GetParameter(BROKER_DELEGATE_BUNDLE_NAME, "");
408        brokerDelegateBundleName_.isLoaded = true;
409    }
410    TAG_LOGD(AAFwkTag::DEFAULT, "shellAssistantBundleName_ is %{public}s", brokerDelegateBundleName_.value.c_str());
411    return brokerDelegateBundleName_.value;
412}
413
414int32_t AppUtils::GetCollaboratorBrokerUID()
415{
416    if (!collaboratorBrokerUid_.isLoaded) {
417        collaboratorBrokerUid_.value = system::GetIntParameter(COLLABORATOR_BROKER_UID, DEFAULT_INVALID_VALUE);
418        collaboratorBrokerUid_.isLoaded = true;
419    }
420    TAG_LOGD(AAFwkTag::DEFAULT, "collaboratorBrokerUid_ is %{public}d", collaboratorBrokerUid_.value);
421    return collaboratorBrokerUid_.value;
422}
423
424int32_t AppUtils::GetCollaboratorBrokerReserveUID()
425{
426    if (!collaboratorBrokerReserveUid_.isLoaded) {
427        collaboratorBrokerReserveUid_.value = system::GetIntParameter(COLLABORATOR_BROKER_RESERVE_UID,
428            DEFAULT_INVALID_VALUE);
429        collaboratorBrokerReserveUid_.isLoaded = true;
430    }
431    TAG_LOGD(AAFwkTag::DEFAULT, "collaboratorBrokerReserveUid_ is %{public}d", collaboratorBrokerReserveUid_.value);
432    return collaboratorBrokerReserveUid_.value;
433}
434
435int32_t AppUtils::MaxChildProcess()
436{
437    if (!maxChildProcess_.isLoaded) {
438        maxChildProcess_.value =
439            system::GetIntParameter<int32_t>(MAX_CHILD_PROCESS, DEFAULT_MAX_CHILD_PROCESS);
440        maxChildProcess_.isLoaded = true;
441    }
442    TAG_LOGD(AAFwkTag::DEFAULT, "MaxChildProcess: %{public}d", maxChildProcess_.value);
443    return maxChildProcess_.value;
444}
445
446bool AppUtils::IsSupportMultiInstance()
447{
448    if (!isSupportMultiInstance_.isLoaded) {
449        isSupportMultiInstance_.value = system::GetBoolParameter(SUPPORT_MULTI_INSTANCE, false);
450        isSupportMultiInstance_.isLoaded = true;
451    }
452    TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", isSupportMultiInstance_.value);
453    return isSupportMultiInstance_.value;
454}
455
456std::string AppUtils::GetMigrateClientBundleName()
457{
458    if (!migrateClientBundleName_.isLoaded) {
459        migrateClientBundleName_.value = system::GetParameter(MIGRATE_CLIENT_BUNDLE_NAME, "");
460        migrateClientBundleName_.isLoaded = true;
461    }
462    TAG_LOGD(AAFwkTag::DEFAULT, "migrateClientBundleName_ is %{public}s", migrateClientBundleName_.value.c_str());
463    return migrateClientBundleName_.value;
464}
465}  // namespace AAFwk
466}  // namespace OHOS
467