已合并
Adapt the ANI interface showSystemApnSettings #1312
Adapt the ANI interface showSystemApnSettings #1312
已合并
panjie创建于 24 天前
共 8 个文件变更+326-1
@@ -45,6 +45,14 @@ ohos_static_library("cellular_data_ani_cxx") {
45 "$SUBSYSTEM_DIR/cellular_data/frameworks/native:tel_cellular_data_api",45 "$SUBSYSTEM_DIR/cellular_data/frameworks/native:tel_cellular_data_api",
46 ]46 ]
47 external_deps = [47 external_deps = [
48+ "ability_base:want",
49+ "ability_runtime:ability_manager",
50+ "ability_runtime:ability_context_native",
51+ "ability_runtime:abilitykit_native",
52+ "ability_runtime:ani_base_context",
53+ "ability_runtime:ani_common",
54+ "ability_runtime:ui_extension",
55+ "ace_engine:ace_uicontent",
48 "c_utils:utils",56 "c_utils:utils",
49 "core_service:libtel_common",57 "core_service:libtel_common",
50 "core_service:tel_core_service_api",58 "core_service:tel_core_service_api",
@@ -15,6 +15,7 @@
15 15 
16import { BusinessError } from '@ohos.base'16import { BusinessError } from '@ohos.base'
17import type { AsyncCallback } from '@ohos.base';17import type { AsyncCallback } from '@ohos.base';
18+import type Context from 'application.Context';
18 19 
19export default namespace data {20export default namespace data {
20 loadLibrary("cellular_data_ani")21 loadLibrary("cellular_data_ani")
@@ -383,4 +384,17 @@ export default namespace data {
383 export function getDefaultCellularDataSimId(): int {384 export function getDefaultCellularDataSimId(): int {
384 return nativeGetDefaultCellularDataSimId();385 return nativeGetDefaultCellularDataSimId();
385 }386 }
387+ 
388+ export native function nativeShowSystemApnSettings(context: Context): void;
389+ export function showSystemApnSettings(context: Context): Promise<void> {
390+ return new Promise<void>((resolve, reject) => {
391+ taskpool.execute((): void => {
392+ return nativeShowSystemApnSettings(context);
393+ }).then(() => {
394+ resolve(undefined);
395+ }, (err: Error): void => {
396+ reject(err as BusinessError);
397+ });
398+ });
399+ }
386}400}
@@ -20,9 +20,39 @@
20#include "cxx.h"20#include "cxx.h"
21 21 
22namespace OHOS {22namespace OHOS {
23+namespace Ace {
24+class UIContent;
25+}
26+namespace AAFwk {
27+class Want;
28+}
29+namespace AbilityRuntime {
30+class Context;
31+class AbilityContext;
32+class UIExtensionContext;
33+}
23namespace CellularDataAni {34namespace CellularDataAni {
24struct ArktsError;35struct ArktsError;
25struct ApnInfo;36struct ApnInfo;
37+struct AniEnv;
38+struct AniObject;
39+ 
40+struct AppBaseContext {
41+ std::shared_ptr<OHOS::AbilityRuntime::AbilityContext> abilityContext = nullptr;
42+ std::shared_ptr<OHOS::AbilityRuntime::UIExtensionContext> uiExtensionContext = nullptr;
43+};
44+ 
45+class ModalUICallback {
46+public:
47+ explicit ModalUICallback(std::shared_ptr<AppBaseContext> baseContext);
48+ void OnRelease(int32_t releaseCode);
49+ void SetSessionId(int32_t sessionId);
50+ 
51+private:
52+ int32_t sessionId_ = 0;
53+ std::shared_ptr<AppBaseContext> baseContext_ = nullptr;
54+ void CloseModalUI();
55+};
26 56 
27ArktsError isCellularDataEnabled(bool &dataEnabled);57ArktsError isCellularDataEnabled(bool &dataEnabled);
28ArktsError enableCellularDataSync();58ArktsError enableCellularDataSync();
@@ -39,6 +69,15 @@ int32_t getDefaultCellularDataSimIdSyn();
39ArktsError queryApnIdsSync(const ApnInfo &info, rust::vec<uint32_t> &ret);69ArktsError queryApnIdsSync(const ApnInfo &info, rust::vec<uint32_t> &ret);
40ArktsError queryAllApnsSync(rust::vec<ApnInfo> &ret);70ArktsError queryAllApnsSync(rust::vec<ApnInfo> &ret);
41ArktsError getActiveApnNameSync(rust::String &apnName);71ArktsError getActiveApnNameSync(rust::String &apnName);
72+ArktsError showSystemApnSettingsSync(std::shared_ptr<AbilityRuntime::Context> context);
73+ 
74+bool IsStageContext(AniEnv *env, AniObject *obj);
75+std::shared_ptr<AbilityRuntime::Context> GetStageModeContext(AniEnv **env, AniObject *obj);
76+bool ParseAbilityContext(std::shared_ptr<AbilityRuntime::Context> context,
77+ std::shared_ptr<OHOS::AbilityRuntime::AbilityContext> &abilityContext,
78+ std::shared_ptr<OHOS::AbilityRuntime::UIExtensionContext> &uiExtensionContext);
79+OHOS::Ace::UIContent *GetUIContent(std::shared_ptr<AppBaseContext> &asyncContext);
80+bool StartUiExtensionAbility(OHOS::AAFwk::Want &request, std::shared_ptr<AppBaseContext> &asyncContext);
42} // namespace CellularDataAni81} // namespace CellularDataAni
43} // namespace OHOS82} // namespace OHOS
44#endif83#endif
@@ -12,9 +12,12 @@
12// limitations under the License.12// limitations under the License.
13 13 
14use ani_rs::business_error::BusinessError;14use ani_rs::business_error::BusinessError;
15+use ani_rs::objects::{AniObject, AniRef};
16+use ani_rs::AniEnv;
15 17 
16use crate::bridge;18use crate::bridge;
17use crate::wrapper;19use crate::wrapper;
20+use crate::context::Context;
18 21 
19impl From<i32> for bridge::DataConnectState {22impl From<i32> for bridge::DataConnectState {
20 fn from(value: i32) -> Self {23 fn from(value: i32) -> Self {
@@ -183,4 +186,18 @@ pub fn get_active_apn_name_sync() -> Result<String, BusinessError> {
183 return Err(BusinessError::from(arkts_error));186 return Err(BusinessError::from(arkts_error));
184 }187 }
185 Ok(ret)188 Ok(ret)
189+}
190+ 
191+#[ani_rs::native]
192+pub fn show_system_apn_settings_sync(
193+ env: &AniEnv,
194+ context: AniRef,
195+) -> Result<(), BusinessError> {
196+ let context_obj = AniObject::from(context);
197+ let context_wrapper = Context::new(env, &context_obj);
198+ let arkts_error = wrapper::ffi::showSystemApnSettingsSync(context_wrapper.inner);
199+ if arkts_error.is_error() {
200+ return Err(BusinessError::from(arkts_error));
201+ }
202+ Ok(())
186}203}
@@ -0,0 +1,78 @@
1+// Copyright (c) 2026 Huawei Device Co., Ltd.
2+// Licensed under the Apache License, Version 2.0 (the "License");
3+// you may not use this file except in compliance with the License.
4+// You may obtain a copy of the License at
5+//
6+// http://www.apache.org/licenses/LICENSE-2.0
7+//
8+// Unless required by applicable law or agreed to in writing, software
9+// distributed under the License is distributed on an "AS IS" BASIS,
10+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+// See the License for the specific language governing permissions and
12+// limitations under the License.
13+ 
14+//! Application context utilities and wrapper.
15+//!
16+//! This module provides utilities for accessing application context information
17+//! and file system paths. It wraps the underlying native context implementation
18+//! and provides a safe Rust API.
19+ 
20+use ani_rs::objects::AniObject;
21+use ani_rs::AniEnv;
22+use cxx::SharedPtr;
23+ 
24+use crate::wrapper;
25+ 
26+/// Determines whether the provided environment and object represent a stage context.
27+///
28+/// # Arguments
29+///
30+/// * `env` - The animation environment
31+/// * `ani_object` - The animation object
32+///
33+/// # Safety
34+///
35+/// This function performs pointer casting and calls an unsafe C function.
36+/// The caller must ensure that the provided environment and object are valid
37+/// and properly initialized.
38+#[inline]
39+pub fn is_stage_context(env: &AniEnv, ani_object: &AniObject) -> bool {
40+ // Cast to the appropriate types required by the C++ function
41+ let env = env as *const AniEnv as *mut AniEnv as *mut wrapper::AniEnv;
42+ let ani_object = ani_object as *const AniObject as *mut AniObject as *mut wrapper::AniObject;
43+ unsafe { wrapper::ffi::IsStageContext(env, ani_object) }
44+}
45+ 
46+pub struct Context {
47+ /// Inner C++ context shared pointer
48+ pub inner: SharedPtr<wrapper::ffi::Context>,
49+}
50+ 
51+impl Context {
52+ /// Creates a new Context from animation environment and object.
53+ ///
54+ /// # Arguments
55+ ///
56+ /// * `env` - The animation environment
57+ /// * `ani_object` - The animation object
58+ ///
59+ /// # Safety
60+ ///
61+ /// This function performs pointer casting and calls an unsafe C function.
62+ /// The caller must ensure that the provided environment and object are valid
63+ /// and properly initialized.
64+ pub fn new(env: &AniEnv, ani_object: &AniObject) -> Self {
65+ // Mirror the napi ParseAbilityContext: a non-stage context is invalid.
66+ if !is_stage_context(env, ani_object) {
67+ return Self {
68+ inner: cxx::SharedPtr::null(),
69+ };
70+ }
71+ // Cast to the appropriate types required by the C++ function
72+ let env = env as *const AniEnv as *mut AniEnv as *mut *mut wrapper::AniEnv;
73+ let ani_object =
74+ ani_object as *const AniObject as *mut AniObject as *mut wrapper::AniObject;
75+ let inner = unsafe { wrapper::ffi::GetStageModeContext(env, ani_object) };
76+ Self { inner }
77+ }
78+}
@@ -13,12 +13,18 @@
13 * limitations under the License.13 * limitations under the License.
14 */14 */
15#include "ani_cellular_data.h"15#include "ani_cellular_data.h"
16+#include "ability_context.h"
17+#include "ani_base_context.h"
16#include "cellular_data_client.h"18#include "cellular_data_client.h"
19+#include "core_service_client.h"
17#include "cxx.h"20#include "cxx.h"
21+#include "modal_ui_extension_config.h"
18#include "napi_util.h"22#include "napi_util.h"
19#include "telephony_types.h"23#include "telephony_types.h"
24+#include "ui_content.h"
25+#include "ui_extension_context.h"
26+#include "want.h"
20#include "wrapper.rs.h"27#include "wrapper.rs.h"
21-#include "core_service_client.h"
22 28 
23namespace OHOS {29namespace OHOS {
24using namespace Telephony;30using namespace Telephony;
@@ -27,6 +33,17 @@ static constexpr const char *SET_TELEPHONY_STATE = "ohos.permission.SET_TELEPHON
27static constexpr const char *GET_NETWORK_INFO = "ohos.permission.GET_NETWORK_INFO";33static constexpr const char *GET_NETWORK_INFO = "ohos.permission.GET_NETWORK_INFO";
28static constexpr const char *MANAGE_APN_SETTING = "ohos.permission.MANAGE_APN_SETTING";34static constexpr const char *MANAGE_APN_SETTING = "ohos.permission.MANAGE_APN_SETTING";
29 35 
36+static constexpr const char *SETTINGS_PACKAGE_NAME = "com.huawei.hmos.callsetting";
37+static constexpr const char *SETTINGS_ABILITY_NAME = "GeneralCallSettingDialogAbility";
38+static constexpr const char *UIEXTENSION_TYPE_KEY = "ability.want.params.uiExtensionType";
39+static constexpr const char *UIEXTENSION_TYPE_VALUE = "sysDialog/common";
40+static constexpr const char *DIALOG_REASON_KEY = "dialogReason";
41+static constexpr const char *DIALOG_REASON_VALUE = "SYSTEM_APN_SETTINGS";
42+static constexpr const char *SLOT_ID_KEY = "slotId";
43+static constexpr const char *CONTEXT_TYPE_KEY = "storeKit.ability.contextType";
44+static constexpr const char *UI_ABILITY_CONTEXT_VALUE = "uiAbility";
45+static constexpr const char *UI_EXTENSION_CONTEXT_VALUE = "uiExtension";
46+ 
30static bool IsCellularDataManagerInited()47static bool IsCellularDataManagerInited()
31{48{
32 return CellularDataClient::GetInstance().IsConnect();49 return CellularDataClient::GetInstance().IsConnect();
@@ -289,5 +306,133 @@ ArktsError getActiveApnNameSync(rust::String &apnName)
289 apnName = rust::string(apnNameStr);306 apnName = rust::string(apnNameStr);
290 return ConvertArktsErrorWithPermission(errorCode, "GetActiveApnName", GET_NETWORK_INFO);307 return ConvertArktsErrorWithPermission(errorCode, "GetActiveApnName", GET_NETWORK_INFO);
291}308}
309+ 
310+ModalUICallback::ModalUICallback(std::shared_ptr<AppBaseContext> baseContext)
311+{
312+ baseContext_ = baseContext;
313+}
314+ 
315+OHOS::Ace::UIContent *GetUIContent(std::shared_ptr<AppBaseContext> &asyncContext)
316+{
317+ if (!asyncContext) {
318+ return nullptr;
319+ }
320+ OHOS::Ace::UIContent *uiContent = nullptr;
321+ if (asyncContext->abilityContext != nullptr) {
322+ uiContent = asyncContext->abilityContext->GetUIContent();
323+ } else if (asyncContext->uiExtensionContext != nullptr) {
324+ uiContent = asyncContext->uiExtensionContext->GetUIContent();
325+ }
326+ return uiContent;
327+}
328+ 
329+void ModalUICallback::CloseModalUI()
330+{
331+ auto uiContent = GetUIContent(baseContext_);
332+ if (uiContent == nullptr) {
333+ return;
334+ }
335+ uiContent->CloseModalUIExtension(sessionId_);
336+}
337+ 
338+void ModalUICallback::OnRelease(int32_t releaseCode)
339+{
340+ CloseModalUI();
341+}
342+ 
343+void ModalUICallback::SetSessionId(int32_t sessionId)
344+{
345+ sessionId_ = sessionId;
346+}
347+ 
348+bool StartUiExtensionAbility(OHOS::AAFwk::Want &request, std::shared_ptr<AppBaseContext> &asyncContext)
349+{
350+ auto uiContent = GetUIContent(asyncContext);
351+ if (uiContent == nullptr) {
352+ return false;
353+ }
354+ auto callback = std::make_shared<ModalUICallback>(asyncContext);
355+ OHOS::Ace::ModalUIExtensionCallbacks extensionCallbacks = {
356+ std::bind(&ModalUICallback::OnRelease, callback, std::placeholders::_1)
357+ };
358+ OHOS::Ace::ModalUIExtensionConfig config;
359+ config.isProhibitBack = false;
360+ int32_t sessionId = uiContent->CreateModalUIExtension(request, extensionCallbacks, config);
361+ if (sessionId == 0) {
362+ return false;
363+ }
364+ callback->SetSessionId(sessionId);
365+ return true;
366+}
367+ 
368+bool ParseAbilityContext(std::shared_ptr<AbilityRuntime::Context> context,
369+ std::shared_ptr<AbilityRuntime::AbilityContext> &abilityContext,
370+ std::shared_ptr<AbilityRuntime::UIExtensionContext> &uiExtensionContext)
371+{
372+ if (context == nullptr) {
373+ return false;
374+ }
375+ abilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context);
376+ if (abilityContext != nullptr) {
377+ return true;
378+ }
379+ uiExtensionContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::UIExtensionContext>(context);
380+ if (uiExtensionContext == nullptr) {
381+ return false;
382+ }
383+ return true;
384+}
385+ 
386+ArktsError showSystemApnSettingsSync(std::shared_ptr<AbilityRuntime::Context> context)
387+{
388+ auto loadProductContext = std::make_shared<AppBaseContext>();
389+ if (!ParseAbilityContext(context, loadProductContext->abilityContext,
390+ loadProductContext->uiExtensionContext)) {
391+ return ConvertArktsErrorWithPermission(
392+ ERROR_PARAMETER_TYPE_INVALID, "ShowSystemApnSettings", MANAGE_APN_SETTING);
393+ }
394+ int32_t slotId = CellularDataClient::GetInstance().GetDefaultCellularDataSlotId();
395+ bool isSimActive = DelayedRefSingleton<CoreServiceClient>::GetInstance().IsSimActive(slotId);
396+ if (!isSimActive) {
397+ return ConvertArktsErrorWithPermission(TELEPHONY_ERR_NO_SIM_CARD, "ShowSystemApnSettings", MANAGE_APN_SETTING);
398+ }
399+ OHOS::AAFwk::Want want;
400+ want.SetElementName(std::string(SETTINGS_PACKAGE_NAME), std::string(SETTINGS_ABILITY_NAME));
401+ want.SetParam(std::string(UIEXTENSION_TYPE_KEY), std::string(UIEXTENSION_TYPE_VALUE));
402+ want.SetParam(std::string(DIALOG_REASON_KEY), std::string(DIALOG_REASON_VALUE));
403+ want.SetParam(std::string(SLOT_ID_KEY), slotId);
404+ want.SetParam(std::string(CONTEXT_TYPE_KEY),
405+ loadProductContext->uiExtensionContext != nullptr ?
406+ std::string(UI_EXTENSION_CONTEXT_VALUE) : std::string(UI_ABILITY_CONTEXT_VALUE));
407+ 
408+ if (!StartUiExtensionAbility(want, loadProductContext)) {
409+ return ConvertArktsErrorWithPermission(ERROR_SERVICE_UNAVAILABLE, "ShowSystemApnSettings", MANAGE_APN_SETTING);
410+ }
411+ return ConvertArktsErrorWithPermission(TELEPHONY_ERR_SUCCESS, "ShowSystemApnSettings", MANAGE_APN_SETTING);
412+}
413+ 
414+bool IsStageContext(AniEnv *env, AniObject *obj)
415+{
416+ if (env == nullptr || obj == nullptr) {
417+ return false;
418+ }
419+ ani_env *aniEnv = *reinterpret_cast<ani_env **>(env);
420+ ani_boolean stageMode;
421+ ani_status status = AbilityRuntime::IsStageContext(aniEnv,
422+ *reinterpret_cast<ani_object *>(obj), stageMode);
423+ if (status != ANI_OK) {
424+ return false;
425+ }
426+ return stageMode == 1;
427+}
428+ 
429+std::shared_ptr<AbilityRuntime::Context> GetStageModeContext(AniEnv **env, AniObject *obj)
430+{
431+ if (env == nullptr || *env == nullptr || obj == nullptr) {
432+ return nullptr;
433+ }
434+ return AbilityRuntime::GetStageModeContext(reinterpret_cast<ani_env *>(*env),
435+ *reinterpret_cast<ani_object *>(obj));
436+}
292} // namespace CellularDataAni437} // namespace CellularDataAni
293} // namespace OHOS438} // namespace OHOS
@@ -13,6 +13,7 @@
13 13 
14mod bridge;14mod bridge;
15mod cellulardata;15mod cellulardata;
16+mod context;
16mod wrapper;17mod wrapper;
17 18 
18use ani_rs::ani_constructor;19use ani_rs::ani_constructor;
@@ -35,5 +36,6 @@ ani_constructor!(
35 "nativeQueryApnIds": cellulardata::query_apn_ids_sync,36 "nativeQueryApnIds": cellulardata::query_apn_ids_sync,
36 "nativeQueryAllApns": cellulardata::query_all_apns_sync,37 "nativeQueryAllApns": cellulardata::query_all_apns_sync,
37 "nativeGetActiveApnName": cellulardata::get_active_apn_name_sync,38 "nativeGetActiveApnName": cellulardata::get_active_apn_name_sync,
39+ "nativeShowSystemApnSettings": cellulardata::show_system_apn_settings_sync,
38 ]40 ]
39);41);
@@ -15,6 +15,16 @@ use crate::bridge;
15use ani_rs::business_error::BusinessError;15use ani_rs::business_error::BusinessError;
16use ffi::ArktsError;16use ffi::ArktsError;
17 17 
18+#[repr(transparent)]
19+pub struct AniEnv {
20+ pub inner: ani_rs::AniEnv<'static>,
21+}
22+ 
23+#[repr(transparent)]
24+pub struct AniObject {
25+ pub inner: ani_rs::objects::AniObject<'static>,
26+}
27+ 
18pub const TELEPHONY_SUCCESS: i32 = 8300000;28pub const TELEPHONY_SUCCESS: i32 = 8300000;
19 29 
20impl From<ffi::ApnInfo> for bridge::ApnInfo {30impl From<ffi::ApnInfo> for bridge::ApnInfo {
@@ -83,6 +93,18 @@ pub mod ffi {
83 fn queryApnIdsSync(info: &ApnInfo, ret: &mut Vec<u32>) -> ArktsError;93 fn queryApnIdsSync(info: &ApnInfo, ret: &mut Vec<u32>) -> ArktsError;
84 fn queryAllApnsSync(ret: &mut Vec<ApnInfo>) -> ArktsError;94 fn queryAllApnsSync(ret: &mut Vec<ApnInfo>) -> ArktsError;
85 fn getActiveApnNameSync(ret: &mut String) -> ArktsError;95 fn getActiveApnNameSync(ret: &mut String) -> ArktsError;
96+ fn showSystemApnSettingsSync(context: SharedPtr<Context>) -> ArktsError;
97+ 
98+ unsafe fn IsStageContext(env: *mut AniEnv, ani_object: *mut AniObject) -> bool;
99+ unsafe fn GetStageModeContext(env: *mut *mut AniEnv, ani_object: *mut AniObject) -> SharedPtr<Context>;
100+ 
101+ #[namespace = "OHOS::AbilityRuntime"]
102+ type Context;
103+ }
104+ 
105+ extern "Rust" {
106+ type AniEnv;
107+ type AniObject;
86 }108 }
87}109}
88 110