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 #include "ani_static_subscriber_extension_context.h"
16
17 #include "ability_manager_client.h"
18 #include "ani_common_want.h"
19 #include "ani_common_start_options.h"
20 #include "ets_extension_context.h"
21 #include "event_log_wrapper.h"
22 #include "native_engine/native_engine.h"
23 #include "ani_event_errors_utils.h"
24
25 namespace OHOS {
26 namespace EventManagerFwkAni {
27 namespace {
28 using namespace OHOS::EventFwk;
29 using namespace OHOS::AbilityRuntime;
30
31 class StsStaticSubscriberExtensionContext final {
32 public:
GetInstance()33 static StsStaticSubscriberExtensionContext& GetInstance()
34 {
35 static StsStaticSubscriberExtensionContext instance;
36 return instance;
37 }
38
39 void StartAbilityInner([[maybe_unused]] ani_env *env,
40 [[maybe_unused]] ani_object aniObj, ani_object wantObj);
41 static StaticSubscriberExtensionContext* GetAbilityContext(ani_env *env, ani_object obj);
42
43 private:
44 explicit StsStaticSubscriberExtensionContext() = default;
45 ~StsStaticSubscriberExtensionContext() = default;
46 };
47
48 constexpr const char* STATIC_SUBSCRIBER_EXTENSION_CONTEXT_CLASS_NAME =
49 "L@ohos/application/StaticSubscriberExtensionContext/StaticSubscriberExtensionContext;";
50 }
51
StartAbility(ani_env * env,ani_object aniObj,ani_object wantObj)52 static void StartAbility([[maybe_unused]] ani_env *env,
53 [[maybe_unused]] ani_object aniObj, ani_object wantObj)
54 {
55 EVENT_LOGD("StartAbility");
56 StsStaticSubscriberExtensionContext::GetInstance().StartAbilityInner(env, aniObj, wantObj);
57 }
58
StartAbilityInner(ani_env * env,ani_object aniObj,ani_object wantObj)59 void StsStaticSubscriberExtensionContext::StartAbilityInner([[maybe_unused]] ani_env *env,
60 [[maybe_unused]] ani_object aniObj, ani_object wantObj)
61 {
62 EVENT_LOGD("StartAbilityInner");
63 AAFwk::Want want;
64 ErrCode innerErrCode = ERR_OK;
65 if (!AppExecFwk::UnwrapWant(env, wantObj, want)) {
66 EVENT_LOGE("UnwrapWant filed");
67 OHOS::EventManagerFwkAni::ThrowError(env, ERROR_CODE_INVALID_PARAM);
68 return;
69 }
70 auto context = StsStaticSubscriberExtensionContext::GetAbilityContext(env, aniObj);
71 if (context == nullptr) {
72 EVENT_LOGE("GetAbilityContext is nullptr");
73 OHOS::EventManagerFwkAni::ThrowError(env, ERROR_CODE_INVALID_CONTEXT);
74 return;
75 }
76 innerErrCode = context->StartAbility(want);
77 if (innerErrCode != ERR_OK) {
78 EVENT_LOGE("StartAbility failed, code = %{public}d", innerErrCode);
79 OHOS::EventManagerFwkAni::ThrowErrorByNativeError(env, innerErrCode);
80 }
81 }
82
GetAbilityContext(ani_env * env,ani_object obj)83 StaticSubscriberExtensionContext* StsStaticSubscriberExtensionContext::GetAbilityContext(ani_env *env, ani_object obj)
84 {
85 EVENT_LOGD("GetAbilityContext");
86 ani_class cls = nullptr;
87 ani_long nativeContextLong;
88 ani_field contextField = nullptr;
89 ani_status status = ANI_ERROR;
90 if (env == nullptr) {
91 EVENT_LOGD("null env");
92 return nullptr;
93 }
94 if ((status = env->FindClass(STATIC_SUBSCRIBER_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) {
95 EVENT_LOGD("GetAbilityContext find class status: %{public}d", status);
96 return nullptr;
97 }
98 if ((status = env->Class_FindField(cls, "nativeStaticSubscriberExtensionContext", &contextField)) != ANI_OK) {
99 EVENT_LOGD("GetAbilityContext find field status: %{public}d", status);
100 return nullptr;
101 }
102 if ((status = env->Object_GetField_Long(obj, contextField, &nativeContextLong)) != ANI_OK) {
103 EVENT_LOGD("GetAbilityContext get filed status: %{public}d", status);
104 return nullptr;
105 }
106 return (StaticSubscriberExtensionContext*)nativeContextLong;
107 }
108
CreateStaticSubscriberExtensionContext(ani_env * env,std::shared_ptr<StaticSubscriberExtensionContext> context,const std::shared_ptr<OHOS::AppExecFwk::OHOSApplication> & application)109 ani_object CreateStaticSubscriberExtensionContext(ani_env *env,
110 std::shared_ptr<StaticSubscriberExtensionContext> context,
111 const std::shared_ptr<OHOS::AppExecFwk::OHOSApplication> &application)
112 {
113 if (env == nullptr) {
114 EVENT_LOGE("null env");
115 return nullptr;
116 }
117 std::shared_ptr<OHOS::AppExecFwk::AbilityInfo> abilityInfo = nullptr;
118 if (context) {
119 abilityInfo = context->GetAbilityInfo();
120 }
121 ani_class cls = nullptr;
122 ani_object contextObj = nullptr;
123 ani_field field = nullptr;
124 ani_method method = nullptr;
125 ani_status status = ANI_ERROR;
126 if ((status = env->FindClass(STATIC_SUBSCRIBER_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) {
127 EVENT_LOGE("find class status : %{public}d", status);
128 return nullptr;
129 }
130 std::array functions = {
131 ani_native_function { "nativeStartAbilitySync", "L@ohos/app/ability/Want/Want;:V",
132 reinterpret_cast<void*>(StartAbility) },
133 };
134 if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) {
135 EVENT_LOGE("bind method status : %{public}d", status);
136 return nullptr;
137 }
138 if ((status = env->Class_FindMethod(cls, "<ctor>", ":V", &method)) != ANI_OK) {
139 EVENT_LOGE("find Method status: %{public}d", status);
140 return nullptr;
141 }
142 if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) {
143 EVENT_LOGE("new Object status: %{public}d", status);
144 return nullptr;
145 }
146 if ((status = env->Class_FindField(cls, "nativeStaticSubscriberExtensionContext", &field)) != ANI_OK) {
147 EVENT_LOGE("find field status: %{public}d", status);
148 return nullptr;
149 }
150 ani_long nativeContextLong = (ani_long)context.get();
151 if ((status = env->Object_SetField_Long(contextObj, field, nativeContextLong)) != ANI_OK) {
152 EVENT_LOGE("set field status: %{public}d", status);
153 return nullptr;
154 }
155 if (application == nullptr) {
156 EVENT_LOGE("application null");
157 return nullptr;
158 }
159 OHOS::AbilityRuntime::CreateEtsExtensionContext(env, cls, contextObj, context, context->GetAbilityInfo());
160 return contextObj;
161 }
162 } // EventManagerFwkAni
163 } // OHOS