• 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 #include "ani_request_enable.h"
16 
17 #include "ani_ans_dialog_callback.h"
18 #include "ans_log_wrapper.h"
19 #include "ets_error_utils.h"
20 #include "notification_helper.h"
21 #include "ani_common_util.h"
22 #include "sts_throw_erro.h"
23 
24 namespace OHOS {
25 namespace NotificationManagerSts {
26 using namespace OHOS::Notification;
GetEnableNotificationInfo(ani_env * env,ani_object content,std::shared_ptr<EnableNotificationInfo> & info)27 bool GetEnableNotificationInfo(ani_env *env, ani_object content, std::shared_ptr<EnableNotificationInfo> &info)
28 {
29     ANS_LOGD("enter");
30     if (content == nullptr) {
31         ANS_LOGD("content is null");
32         return true;
33     }
34     ani_status status = ANI_OK;
35     ani_boolean stageMode = ANI_FALSE;
36     status = OHOS::AbilityRuntime::IsStageContext(env, content, stageMode);
37     ANS_LOGD("status %{public}d, stageMode %{public}d", status, stageMode);
38     if (ANI_OK != status || stageMode != ANI_TRUE) {
39         ANS_LOGE("Only support stage mode");
40         std::string msg = "Incorrect parameter types.Only support stage mode.";
41         OHOS::NotificationSts::ThrowError(env, ERROR_PARAM_INVALID, msg);
42         return false;
43     }
44     info->stageMode = true;
45     info->context = OHOS::AbilityRuntime::GetStageModeContext(env, content);
46     if (info->context != nullptr) {
47         info->callerToken = info->context->GetToken();
48     }
49     return true;
50 }
51 
RequestEnableExecute(std::shared_ptr<EnableNotificationInfo> & info)52 void RequestEnableExecute(std::shared_ptr<EnableNotificationInfo> &info)
53 {
54     ANS_LOGD("enter");
55     sptr<AnsDialogHostClient> client = nullptr;
56     if (!AnsDialogHostClient::CreateIfNullptr(client)) {
57         ANS_LOGD("create client fail");
58         info->errorCode = ERR_ANS_DIALOG_IS_POPPING;
59         return;
60     }
61     if (client == nullptr) {
62         ANS_LOGD("client is nullptr");
63         info->errorCode = ERROR_INTERNAL_ERROR;
64         return;
65     }
66     if (info->context != nullptr) {
67         ANS_LOGD("stage mode");
68         bool canPop = false;
69         std::string bundleName = "";
70         ErrCode errCode = NotificationHelper::CanPopEnableNotificationDialog(client, canPop, bundleName);
71         ANS_LOGI("CanPopEnableNotificationDialog  result , errCode = %{public}d , canPop = %{public}d",
72             errCode, canPop);
73         if (canPop == false) {
74             info->errorCode = errCode;
75             AnsDialogHostClient::Destroy();
76             return;
77         }
78         info->bundleName = bundleName;
79     } else {
80         ANS_LOGD("un stage mode");
81         std::string deviceId {""};
82         info->errorCode = NotificationHelper::RequestEnableNotification(deviceId, client, info->callerToken);
83     }
84     ANS_LOGI("ipcCall done, code is %{public}d.", info->errorCode);
85 }
86 
StsAsyncCompleteCallbackRequestEnableNotification(ani_env * env,std::shared_ptr<EnableNotificationInfo> info)87 void StsAsyncCompleteCallbackRequestEnableNotification(ani_env *env, std::shared_ptr<EnableNotificationInfo> info)
88 {
89     ANS_LOGD("enter");
90     if (env == nullptr || info == nullptr) return;
91     ani_status status;
92     int32_t errorCode = info->errorCode ==
93         ERR_OK ? ERR_OK : NotificationSts::GetExternalCode(info->errorCode);
94     if (errorCode == ERR_OK) {
95         ANS_LOGD("Resolve. errorCode %{public}d", errorCode);
96         ani_object ret = OHOS::AppExecFwk::CreateInt(env, errorCode);
97         if (ret == nullptr) {
98             ANS_LOGD("createInt faild");
99             return;
100         }
101         if (ANI_OK != (status = env->PromiseResolver_Resolve(info->resolver, static_cast<ani_ref>(ret)))) {
102             ANS_LOGD("PromiseResolver_Resolve faild. status %{public}d", status);
103         }
104     } else {
105         std::string errMsg = OHOS::NotificationSts::FindAnsErrMsg(errorCode);
106         ANS_LOGD("reject. errorCode %{public}d errMsg %{public}s", errorCode, errMsg.c_str());
107         ani_error rejection =
108             static_cast<ani_error>(OHOS::AbilityRuntime::EtsErrorUtil::CreateError(env, errorCode, errMsg));
109         if (ANI_OK != (status = env->PromiseResolver_Reject(info->resolver, rejection))) {
110             ANS_LOGD("PromiseResolver_Resolve faild. status %{public}d", status);
111         }
112     }
113 }
114 
CreateUIExtension(std::shared_ptr<EnableNotificationInfo> & info)115 bool CreateUIExtension(std::shared_ptr<EnableNotificationInfo> &info)
116 {
117     ANS_LOGD("enter");
118     if (info->context == nullptr) {
119         ANS_LOGE("Get context failed");
120         return false;
121     }
122     std::shared_ptr<OHOS::AbilityRuntime::AbilityContext> abilityContext =
123         OHOS::AbilityRuntime::Context::ConvertTo<OHOS::AbilityRuntime::AbilityContext>(info->context);
124     if (abilityContext == nullptr) {
125         ANS_LOGE("abilityContext is null");
126         return false;
127     }
128     auto uiContent = abilityContext->GetUIContent();
129     if (uiContent == nullptr) {
130         ANS_LOGE("uiContent is null");
131         return false;
132     }
133     AAFwk::Want want;
134     std::string targetBundleName = "com.ohos.notificationdialog";
135     std::string targetAbilityName = "EnableNotificationDialog";
136     want.SetElementName(targetBundleName, targetAbilityName);
137     std::string typeKey = "ability.want.params.uiExtensionType";
138     std::string typeValue = "sysDialog/common";
139     want.SetParam(typeKey, typeValue);
140     auto uiExtCallback = std::make_shared<ModalExtensionCallback>();
141     uiExtCallback->SetAbilityContext(abilityContext);
142     uiExtCallback->SetBundleName(info->bundleName);
143     OHOS::Ace::ModalUIExtensionCallbacks uiExtensionCallbacks = {
144         .onRelease = std::bind(&ModalExtensionCallback::OnRelease, uiExtCallback, std::placeholders::_1),
145         .onResult = std::bind(&ModalExtensionCallback::OnResult, uiExtCallback,
146             std::placeholders::_1, std::placeholders::_2),
147         .onReceive = std::bind(&ModalExtensionCallback::OnReceive, uiExtCallback, std::placeholders::_1),
148         .onError = std::bind(&ModalExtensionCallback::OnError, uiExtCallback,
149             std::placeholders::_1, std::placeholders::_2, std::placeholders::_3),
150         .onRemoteReady = std::bind(&ModalExtensionCallback::OnRemoteReady, uiExtCallback, std::placeholders::_1),
151         .onDestroy = std::bind(&ModalExtensionCallback::OnDestroy, uiExtCallback),
152     };
153     OHOS::Ace::ModalUIExtensionConfig config;
154     config.isProhibitBack = true;
155     int32_t sessionId = uiContent->CreateModalUIExtension(want, uiExtensionCallbacks, config);
156     ANS_LOGI("Create end, sessionId: %{public}d", sessionId);
157     if (sessionId == 0) {
158         ANS_LOGE("Create component failed, sessionId is 0");
159         return false;
160     }
161     uiExtCallback->SetSessionId(sessionId);
162     return true;
163 }
164 
RequestEnableComplete(ani_env * env,std::shared_ptr<EnableNotificationInfo> & info)165 void RequestEnableComplete(ani_env *env, std::shared_ptr<EnableNotificationInfo> &info)
166 {
167     ANS_LOGD("enter");
168     if (!info->bundleName.empty()) {
169         bool success = CreateUIExtension(info);
170         if (success) {
171             info->errorCode = ERR_ANS_DIALOG_POP_SUCCEEDED;
172         } else {
173             info->errorCode = ERROR_INTERNAL_ERROR;
174             AnsDialogHostClient::Destroy();
175             NotificationHelper::RemoveEnableNotificationDialog();
176         }
177     }
178     if (info->errorCode != ERR_ANS_DIALOG_POP_SUCCEEDED) {
179         ANS_LOGE("error, code is %{public}d.", info->errorCode);
180         AnsDialogHostClient::Destroy();
181         StsAsyncCompleteCallbackRequestEnableNotification(env, info);
182         return;
183     }
184     // Dialog is popped
185     auto StsCallback = std::make_unique<StsAnsDialogCallback>();
186     if (!StsCallback->Init(env, info, StsAsyncCompleteCallbackRequestEnableNotification) ||
187         !AnsDialogHostClient::SetDialogCallbackInterface(std::move(StsCallback))
188     ) {
189         ANS_LOGE("error");
190         AnsDialogHostClient::Destroy();
191         info->errorCode = ERROR_INTERNAL_ERROR;
192         StsAsyncCompleteCallbackRequestEnableNotification(env, info);
193         return;
194     }
195 }
196 
AniRequestEnableNotification(ani_env * env,ani_object content)197 ani_object AniRequestEnableNotification(ani_env *env, ani_object content)
198 {
199     ANS_LOGD("enter");
200     std::shared_ptr<EnableNotificationInfo> info = std::make_shared<EnableNotificationInfo>();
201     if (!GetEnableNotificationInfo(env, content, info)) {
202         ANS_LOGD("GetEnableNotificationInfo");
203         return nullptr;
204     }
205     ani_object aniPromise {};
206     ani_resolver aniResolver {};
207     if (ANI_OK != env->Promise_New(&aniResolver, &aniPromise)) {
208         ANS_LOGD("Promise_New faild");
209         return nullptr;
210     }
211     info->resolver = aniResolver;
212     RequestEnableExecute(info);
213     RequestEnableComplete(env, info);
214     ANS_LOGD("RequestEnableNotification done");
215     return aniPromise;
216 }
217 }
218 }