• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 <string>
17 
18 #include "ability_manager_client.h"
19 #include "ani.h"
20 #include "ani_common_start_options.h"
21 #include <ani_signature_builder.h>
22 #include "app_log_wrapper.h"
23 #include "business_error_ani.h"
24 #include "common_fun_ani.h"
25 #include "common_func.h"
26 #include "ipc_skeleton.h"
27 #include "js_launcher_service.h"
28 #include "launcher_ability_info.h"
29 #include "napi_constants.h"
30 #include "shortcut_info.h"
31 #include "start_options.h"
32 
33 namespace OHOS {
34 namespace AppExecFwk {
35 namespace {
36 constexpr int32_t EMPTY_USER_ID = -500;
37 constexpr const char* NS_NAME_LAUNCHERMANAGER = "@ohos.bundle.launcherBundleManager.launcherBundleManager";
38 
39 const std::map<int32_t, int32_t> START_SHORTCUT_RES_MAP = {
40     { ERR_OK, ERR_OK },
41     { ERR_PERMISSION_DENIED, ERR_BUNDLE_MANAGER_PERMISSION_DENIED },
42     { ERR_NOT_SYSTEM_APP, ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED }
43 };
44 } // namespace
45 
AniStartShortcut(ani_env * env,ani_object aniShortcutInfo,ani_object aniStartOptions)46 static void AniStartShortcut(ani_env *env, ani_object aniShortcutInfo, ani_object aniStartOptions)
47 {
48     APP_LOGD("ani StartShortcut called");
49     ShortcutInfo shortcutInfo;
50     if (!CommonFunAni::ParseShortcutInfo(env, aniShortcutInfo, shortcutInfo)) {
51         APP_LOGE("parse shortcutInfo failed");
52         BusinessErrorAni::ThrowError(env, ERROR_PARAM_CHECK_ERROR, PARSE_SHORTCUT_INFO_FAILED);
53         return;
54     }
55     if (shortcutInfo.intents.empty()) {
56         APP_LOGW("intents is empty");
57         BusinessErrorAni::ThrowError(env, ERROR_PARAM_CHECK_ERROR, ERROR_EMPTY_WANT);
58         return;
59     }
60     AAFwk::Want want;
61     ElementName element;
62     element.SetBundleName(shortcutInfo.intents[0].targetBundle);
63     element.SetModuleName(shortcutInfo.intents[0].targetModule);
64     element.SetAbilityName(shortcutInfo.intents[0].targetClass);
65     want.SetElement(element);
66     std::for_each(shortcutInfo.intents[0].parameters.begin(), shortcutInfo.intents[0].parameters.end(),
67         [&want](const auto& item) { want.SetParam(item.first, item.second); });
68 
69     want.SetParam(AAFwk::Want::PARAM_APP_CLONE_INDEX_KEY, shortcutInfo.appIndex);
70     auto abilityManagerClient = AAFwk::AbilityManagerClient::GetInstance();
71     if (abilityManagerClient == nullptr) {
72         APP_LOGI("abilityManagerClient is nullptr");
73         return;
74     }
75     StartOptions startOptions;
76     if (aniStartOptions != nullptr) {
77         if (!UnwrapStartOptions(env, aniStartOptions, startOptions)) {
78             APP_LOGE("ParseStartOptions error");
79             BusinessErrorAni::ThrowError(env, ERROR_PARAM_CHECK_ERROR, PARSE_START_OPTIONS_FAILED);
80             return;
81         }
82     }
83     ErrCode result = abilityManagerClient->StartShortcut(want, startOptions);
84     auto iter = START_SHORTCUT_RES_MAP.find(result);
85     result = iter == START_SHORTCUT_RES_MAP.end() ? ERR_BUNDLE_MANAGER_START_SHORTCUT_FAILED : iter->second;
86     if (result != ERR_OK) {
87         APP_LOGE("StartShortcut failed, result: %{public}d", result);
88         BusinessErrorAni::ThrowCommonError(
89             env, CommonFunc::ConvertErrCode(result), START_SHORTCUT, Constants::PERMISSION_START_SHORTCUT);
90     }
91 }
92 
AniGetShortcutInfo(ani_env * env,ani_string aniBundleName,ani_double aniUserId,ani_boolean aniIsSync)93 static ani_object AniGetShortcutInfo(ani_env *env,
94     ani_string aniBundleName, ani_double aniUserId, ani_boolean aniIsSync)
95 {
96     APP_LOGD("ani GetShortcutInfo called");
97     std::string bundleName;
98     if (!CommonFunAni::ParseString(env, aniBundleName, bundleName)) {
99         APP_LOGE("parse bundleName failed");
100         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, BUNDLE_NAME, TYPE_STRING);
101         return nullptr;
102     }
103     int32_t userId = EMPTY_USER_ID;
104     if (!CommonFunAni::TryCastDoubleTo(aniUserId, &userId)) {
105         APP_LOGW("try cast userId failed");
106     }
107     if (userId == EMPTY_USER_ID) {
108         userId = Constants::UNSPECIFIED_USERID;
109     }
110     bool isSync = CommonFunAni::AniBooleanToBool(aniIsSync);
111     auto launcherService = JSLauncherService::GetLauncherService();
112     if (launcherService == nullptr) {
113         APP_LOGE("launcherService is nullptr");
114         BusinessErrorAni::ThrowCommonError(env, ERROR_BUNDLE_SERVICE_EXCEPTION,
115             isSync ? GET_SHORTCUT_INFO_SYNC : GET_SHORTCUT_INFO, Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED);
116         return nullptr;
117     }
118 
119     std::vector<ShortcutInfo> shortcutInfos;
120     ErrCode ret = launcherService->GetShortcutInfoV9(bundleName, shortcutInfos, userId);
121     if (ret != ERR_OK) {
122         APP_LOGE("GetShortcutInfoV9 failed, ret %{public}d", ret);
123         BusinessErrorAni::ThrowCommonError(env, CommonFunc::ConvertErrCode(ret),
124             isSync ? GET_SHORTCUT_INFO_SYNC : GET_SHORTCUT_INFO, Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED);
125         return nullptr;
126     }
127     ani_object shortcutInfosObject =
128         CommonFunAni::ConvertAniArray(env, shortcutInfos, CommonFunAni::ConvertShortcutInfo);
129     if (shortcutInfosObject == nullptr) {
130         APP_LOGE("nullptr shortcutInfosObject");
131         return nullptr;
132     }
133     return shortcutInfosObject;
134 }
135 
AniGetLauncherAbilityInfo(ani_env * env,ani_string aniBundleName,ani_double aniUserId,ani_boolean aniIsSync)136 static ani_object AniGetLauncherAbilityInfo(ani_env *env,
137     ani_string aniBundleName, ani_double aniUserId, ani_boolean aniIsSync)
138 {
139     APP_LOGD("ani GetLauncherAbilityInfo called");
140     std::string bundleName;
141     if (!CommonFunAni::ParseString(env, aniBundleName, bundleName)) {
142         APP_LOGE("parse bundleName failed");
143         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, BUNDLE_NAME, TYPE_STRING);
144         return nullptr;
145     }
146     int32_t userId = Constants::UNSPECIFIED_USERID;
147     if (!CommonFunAni::TryCastDoubleTo(aniUserId, &userId)) {
148         APP_LOGE("try cast userId failed");
149         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, USER_ID, TYPE_NUMBER);
150         return nullptr;
151     }
152     bool isSync = CommonFunAni::AniBooleanToBool(aniIsSync);
153 
154     auto launcherService = JSLauncherService::GetLauncherService();
155     if (launcherService == nullptr) {
156         APP_LOGE("launcherService is nullptr");
157         BusinessErrorAni::ThrowCommonError(env, ERROR_BUNDLE_SERVICE_EXCEPTION,
158             isSync ? GET_LAUNCHER_ABILITY_INFO_SYNC : GET_LAUNCHER_ABILITY_INFO,
159             Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED);
160         return nullptr;
161     }
162 
163     std::vector<LauncherAbilityInfo> launcherAbilityInfos;
164     ErrCode ret = ERR_OK;
165     if (isSync) {
166         ret = launcherService->GetLauncherAbilityInfoSync(bundleName, userId, launcherAbilityInfos);
167     } else {
168         ret = launcherService->GetLauncherAbilityByBundleName(bundleName, userId, launcherAbilityInfos);
169     }
170     if (ret != ERR_OK) {
171         APP_LOGE("GetLauncherAbilityInfo failed ret:%{public}d, bundleName:%{public}s, userId:%{public}d",
172             ret, bundleName.c_str(), userId);
173         BusinessErrorAni::ThrowCommonError(env, CommonFunc::ConvertErrCode(ret),
174             isSync ? GET_LAUNCHER_ABILITY_INFO_SYNC : GET_LAUNCHER_ABILITY_INFO,
175             Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED);
176         return nullptr;
177     }
178 
179     ani_object launcherAbilityInfosObject = CommonFunAni::ConvertAniArray(
180         env, launcherAbilityInfos, CommonFunAni::ConvertLauncherAbilityInfo);
181     if (launcherAbilityInfosObject == nullptr) {
182         APP_LOGE("nullptr launcherAbilityInfosObject");
183     }
184 
185     return launcherAbilityInfosObject;
186 }
187 
AniGetAllLauncherAbilityInfo(ani_env * env,ani_double aniUserId)188 static ani_object AniGetAllLauncherAbilityInfo(ani_env *env, ani_double aniUserId)
189 {
190     APP_LOGD("ani GetAllLauncherAbilityInfo called");
191     int32_t userId = 0;
192     if (!CommonFunAni::TryCastDoubleTo(aniUserId, &userId)) {
193         APP_LOGE("try cast userId failed");
194         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, USER_ID, TYPE_NUMBER);
195         return nullptr;
196     }
197 
198     auto launcherService = JSLauncherService::GetLauncherService();
199     if (launcherService == nullptr) {
200         APP_LOGE("launcherService is nullptr");
201         BusinessErrorAni::ThrowCommonError(env, ERROR_BUNDLE_SERVICE_EXCEPTION,
202             GET_ALL_LAUNCHER_ABILITY_INFO, Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED);
203         return nullptr;
204     }
205 
206     std::vector<LauncherAbilityInfo> launcherAbilityInfos;
207     ErrCode ret = launcherService->GetAllLauncherAbility(userId, launcherAbilityInfos);
208     if (ret != ERR_OK) {
209         APP_LOGE("GetAllLauncherAbility failed ret:%{public}d,userId:%{public}d", ret, userId);
210         BusinessErrorAni::ThrowCommonError(env, CommonFunc::ConvertErrCode(ret),
211             GET_ALL_LAUNCHER_ABILITY_INFO, Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED);
212         return nullptr;
213     }
214 
215     ani_object launcherAbilityInfosObject = CommonFunAni::ConvertAniArray(
216         env, launcherAbilityInfos, CommonFunAni::ConvertLauncherAbilityInfo);
217     if (launcherAbilityInfosObject == nullptr) {
218         APP_LOGE("nullptr launcherAbilityInfosObject");
219     }
220 
221     return launcherAbilityInfosObject;
222 }
223 
224 extern "C" {
ANI_Constructor(ani_vm * vm,uint32_t * result)225 ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
226 {
227     APP_LOGI("ANI_Constructor launcherBundleManager called");
228     ani_env* env;
229     ani_status status = vm->GetEnv(ANI_VERSION_1, &env);
230     RETURN_ANI_STATUS_IF_NOT_OK(status, "Unsupported ANI_VERSION_1");
231 
232     arkts::ani_signature::Namespace nsName = arkts::ani_signature::Builder::BuildNamespace(NS_NAME_LAUNCHERMANAGER);
233     ani_namespace kitNs = nullptr;
234     status = env->FindNamespace(nsName.Descriptor().c_str(), &kitNs);
235     if (status != ANI_OK) {
236         APP_LOGE("FindNamespace: %{public}s fail with %{public}d", NS_NAME_LAUNCHERMANAGER, status);
237         return status;
238     }
239 
240     std::array methods = {
241         ani_native_function { "startShortcutNative", nullptr, reinterpret_cast<void*>(AniStartShortcut) },
242         ani_native_function { "getShortcutInfoNative", nullptr, reinterpret_cast<void*>(AniGetShortcutInfo) },
243         ani_native_function { "getLauncherAbilityInfoNative", nullptr,
244             reinterpret_cast<void*>(AniGetLauncherAbilityInfo) },
245         ani_native_function { "getAllLauncherAbilityInfoNative", nullptr,
246             reinterpret_cast<void*>(AniGetAllLauncherAbilityInfo) },
247     };
248 
249     status = env->Namespace_BindNativeFunctions(kitNs, methods.data(), methods.size());
250     if (status != ANI_OK) {
251         APP_LOGE("Namespace_BindNativeFunctions: %{public}s fail with %{public}d", NS_NAME_LAUNCHERMANAGER, status);
252         return status;
253     }
254 
255     *result = ANI_VERSION_1;
256 
257     APP_LOGI("ANI_Constructor finished");
258 
259     return ANI_OK;
260 }
261 } // extern "C"
262 } // namespace AppExecFwk
263 } // namespace OHOS