pc nas stub

Co-Authored-By: Shangben
Signed-off-by: renjh5496 <renjianhao@h-partners.com>
This commit is contained in:
renjh5496
2026-05-07 16:41:40 +08:00
parent a5dec106f2
commit 9778162817
29 changed files with 987 additions and 1 deletions
+1
View File
@@ -88,6 +88,7 @@ ohos_shared_library("ability_runtime") {
"ability_base:ability_base_want",
"ability_base:want",
"c_utils:utils",
"eventhandler:libeventhandler",
"ffrt:libffrt",
"hilog:libhilog",
"image_framework:image_native",
@@ -15,9 +15,13 @@
#include "modular_object_extension_context.h"
#include <memory>
#include <new>
#include "ability_business_error_utils.h"
#include "ability_manager_client.h"
#include "hilog_tag_wrapper.h"
#include "ipc_error_code.h"
#include "modular_object_extension_context_impl.h"
#include "modular_object_extension_types.h"
#include "start_options_impl.h"
@@ -29,6 +33,16 @@ using namespace OHOS::AAFwk;
using namespace OHOS::AbilityRuntime;
namespace {
constexpr const char *REQUEST_TASK_NAME = "ModObjExtRequest";
constexpr const char *DESTROY_TASK_NAME = "ModObjExtDestroy";
struct IPCRemoteStubUserData {
std::weak_ptr<AppExecFwk::EventHandler> handler;
OH_OnRemoteRequestCallback requestCallback = nullptr;
OH_OnRemoteDestroyCallback destroyCallback = nullptr;
void *userData = nullptr;
};
AbilityRuntime_ErrorCode CheckMoeContext(OH_AbilityRuntime_ModObjExtensionContextHandle context,
std::shared_ptr<OHOS::AbilityRuntime::Context> &contextPtr)
{
@@ -62,6 +76,67 @@ AbilityRuntime_ErrorCode TransformWant(const AbilityBase_Want *want, Want &abili
}
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
std::unique_ptr<IPCRemoteStubUserData> CreateIPCRemoteStubUserData(
const std::shared_ptr<AppExecFwk::EventHandler> &handler,
OH_OnRemoteRequestCallback requestCallback, OH_OnRemoteDestroyCallback destroyCallback,
void *userData)
{
std::unique_ptr<IPCRemoteStubUserData> callbackInfo(new (std::nothrow) IPCRemoteStubUserData());
if (callbackInfo == nullptr) {
return nullptr;
}
callbackInfo->handler = handler;
callbackInfo->requestCallback = requestCallback;
callbackInfo->destroyCallback = destroyCallback;
callbackInfo->userData = userData;
return callbackInfo;
}
int OnRemoteRequestOnHandler(uint32_t code, const OHIPCParcel *data, OHIPCParcel *reply, void *userData)
{
auto *callbackInfo = static_cast<IPCRemoteStubUserData *>(userData);
if (callbackInfo == nullptr || callbackInfo->requestCallback == nullptr) {
return OH_IPC_INNER_ERROR;
}
auto handler = callbackInfo->handler.lock();
if (handler == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "event handler not exist");
return OH_IPC_INNER_ERROR;
}
int32_t result = OH_IPC_INNER_ERROR;
auto task = [&callbackInfo, &result, code, data, reply]() {
result = callbackInfo->requestCallback(code, data, reply, callbackInfo->userData);
};
if (!handler->PostSyncTask(task, REQUEST_TASK_NAME)) {
TAG_LOGE(AAFwkTag::APPKIT, "post request task failed");
return OH_IPC_INNER_ERROR;
}
return result;
}
void OnRemoteDestroyOnHandler(void *userData)
{
std::unique_ptr<IPCRemoteStubUserData> callbackInfo(static_cast<IPCRemoteStubUserData *>(userData));
if (callbackInfo == nullptr) {
return;
}
if (callbackInfo->destroyCallback == nullptr) {
return;
}
auto handler = callbackInfo->handler.lock();
if (handler == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "event handler not exist");
return;
}
auto task = [&callbackInfo]() {
callbackInfo->destroyCallback(callbackInfo->userData);
};
if (!handler->PostSyncTask(task, DESTROY_TASK_NAME)) {
TAG_LOGE(AAFwkTag::APPKIT, "post destroy task failed");
return;
}
}
} // namespace
#ifdef __cplusplus
@@ -138,6 +213,43 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_TerminateSelf(
return ConvertToCommonBusinessErrorCode(err);
}
OHIPCRemoteStub* OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub(
OH_AbilityRuntime_ModObjExtensionContextHandle context, const char *descriptor,
OH_OnRemoteRequestCallback requestCallback, OH_OnRemoteDestroyCallback destroyCallback, void *userData)
{
if (descriptor == nullptr || requestCallback == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid create stub params");
return nullptr;
}
std::shared_ptr<OHOS::AbilityRuntime::Context> contextPtr;
auto ret = CheckMoeContext(context, contextPtr);
if (ret != ABILITY_RUNTIME_ERROR_CODE_NO_ERROR) {
return nullptr;
}
auto moeContext = std::static_pointer_cast<ModularObjectExtensionContext>(contextPtr);
auto callbackInfo = CreateIPCRemoteStubUserData(
moeContext->GetEventHandler(), requestCallback, destroyCallback, userData);
if (callbackInfo == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "create callback info failed");
return nullptr;
}
auto *stub = OH_IPCRemoteStub_Create(descriptor, OnRemoteRequestOnHandler,
OnRemoteDestroyOnHandler, callbackInfo.get());
if (stub == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "create remote stub failed");
return nullptr;
}
callbackInfo.release();
return stub;
}
void OH_AbilityRuntime_ModObjExtensionContext_DestroyIPCRemoteStub(
OH_AbilityRuntime_ModObjExtensionContextHandle context, OHIPCRemoteStub *stub)
{
(void)context;
OH_IPCRemoteStub_Destroy(stub);
}
#ifdef __cplusplus
} // extern "C"
#endif
@@ -17,6 +17,7 @@
#include <new>
#include "ability_handler.h"
#include "hilog_tag_wrapper.h"
#include "ipc_inner_object.h"
#include "native_runtime.h"
@@ -53,6 +54,7 @@ void ModularObjectExtension::Init(const std::shared_ptr<AbilityLocalRecord> &rec
moeContext_->type = AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT;
auto context = GetContext();
if (context != nullptr) {
context->SetEventHandler(std::static_pointer_cast<AppExecFwk::EventHandler>(handler));
moeContext_->context = context->weak_from_this();
}
moeInstance_->context = moeContext_;
@@ -24,6 +24,17 @@ namespace AbilityRuntime {
const size_t ModularObjectExtensionContext::CONTEXT_TYPE_ID(
std::hash<const char*> {} ("ModularObjectExtensionContext"));
void ModularObjectExtensionContext::SetEventHandler(
const std::shared_ptr<AppExecFwk::EventHandler> &handler)
{
handler_ = handler;
}
std::shared_ptr<AppExecFwk::EventHandler> ModularObjectExtensionContext::GetEventHandler() const
{
return handler_.lock();
}
ErrCode ModularObjectExtensionContext::StartSelfUIAbility(const AAFwk::Want &want) const
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
@@ -157,6 +157,41 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_StartSelfUIAbi
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_TerminateSelf(
OH_AbilityRuntime_ModObjExtensionContextHandle context);
/**
* @brief Creates an <b>OHIPCRemoteStub</b> object with callbacks running on the extension's designated thread.
* The requestCallback and destroyCallback are invoked serially on the thread determined by the
* extension's {@link OH_AbilityRuntime_ThreadMode}. After calling
* {@link OH_AbilityRuntime_ModObjExtensionContext_DestroyIPCRemoteStub}, no new requestCallback
* invocations will occur, and any in-flight requestCallback will complete before destroyCallback is invoked.
*
* The caller is responsible for destroying the returned object by calling
* {@link OH_AbilityRuntime_ModObjExtensionContext_DestroyIPCRemoteStub} to avoid memory leaks.
*
* @param context Represents a pointer to a modular object extension ability context.
* @param descriptor Pointer to the descriptor of the <b>OHIPCRemoteStub</b> object to create. It cannot be NULL.
* The string is copied internally during creation, so the caller may release the descriptor
* after this function returns.
* @param requestCallback Callback used to process the data request. It cannot be NULL.
* @param destroyCallback Callback to be invoked when the object is destroyed. It can be NULL.
* @param userData Pointer to the user data. It can be NULL. Must remain valid before the object is destroyed.
* @return Returns the pointer to the <b>OHIPCRemoteStub</b> object created if the operation is successful;
* returns NULL otherwise.
* @since 26.0.0
*/
OHIPCRemoteStub* OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub(
OH_AbilityRuntime_ModObjExtensionContextHandle context, const char *descriptor,
OH_OnRemoteRequestCallback requestCallback, OH_OnRemoteDestroyCallback destroyCallback, void *userData);
/**
* @brief Destroys an <b>OHIPCRemoteStub</b> object.
*
* @param context Represents a pointer to a modular object extension ability context.
* @param stub Pointer to the <b>OHIPCRemoteStub</b> object to destroy.
* @since 26.0.0
*/
void OH_AbilityRuntime_ModObjExtensionContext_DestroyIPCRemoteStub(
OH_AbilityRuntime_ModObjExtensionContextHandle context, OHIPCRemoteStub *stub);
#ifdef __cplusplus
}
#endif
@@ -16,6 +16,9 @@
#ifndef OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_CONTEXT_IMPL_H
#define OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_CONTEXT_IMPL_H
#include <memory>
#include "event_handler.h"
#include "extension_context.h"
#include "start_options.h"
#include "want.h"
@@ -27,6 +30,10 @@ public:
ModularObjectExtensionContext() = default;
~ModularObjectExtensionContext() override = default;
void SetEventHandler(const std::shared_ptr<AppExecFwk::EventHandler> &handler);
std::shared_ptr<AppExecFwk::EventHandler> GetEventHandler() const;
ErrCode StartSelfUIAbility(const AAFwk::Want &want) const;
ErrCode StartSelfUIAbilityWithStartOptions(const AAFwk::Want &want, const AAFwk::StartOptions &startOptions) const;
@@ -40,6 +47,9 @@ protected:
{
return contextTypeId == CONTEXT_TYPE_ID || ExtensionContext::IsContext(contextTypeId);
}
private:
std::weak_ptr<AppExecFwk::EventHandler> handler_;
};
} // namespace AbilityRuntime
} // namespace OHOS
+1
View File
@@ -352,6 +352,7 @@ group("unittest") {
"modular_object_ability_connection_test:unittest",
"modular_object_extension_context_capi_test:unittest",
"modular_object_extension_test:unittest",
"modular_object_extension_context_impl_event_handler_test:unittest",
"modular_object_extension_context_impl_test:unittest",
"data_ability_manager_test:unittest",
"data_ability_observer_proxy_test:unittest",
@@ -16,6 +16,10 @@
#ifndef MOCK_IPC_CPARCEL_H
#define MOCK_IPC_CPARCEL_H
struct OHIPCParcel {
int dummy;
};
struct OHIPCRemoteStub {
int dummy;
};
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MOCK_IPC_CREMOTE_OBJECT_H
#define MOCK_IPC_CREMOTE_OBJECT_H
#include <cstdint>
#include "ipc_cparcel.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef int (*OH_OnRemoteRequestCallback)(uint32_t code, const OHIPCParcel *data,
OHIPCParcel *reply, void *userData);
typedef void (*OH_OnRemoteDestroyCallback)(void *userData);
OHIPCRemoteStub* OH_IPCRemoteStub_Create(const char *descriptor, OH_OnRemoteRequestCallback requestCallback,
OH_OnRemoteDestroyCallback destroyCallback, void *userData);
void OH_IPCRemoteStub_Destroy(OHIPCRemoteStub *stub);
#ifdef __cplusplus
}
#endif
#endif // MOCK_IPC_CREMOTE_OBJECT_H
@@ -0,0 +1,21 @@
/*
* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MOCK_IPC_ERROR_CODE_H
#define MOCK_IPC_ERROR_CODE_H
constexpr int OH_IPC_INNER_ERROR = -1;
#endif // MOCK_IPC_ERROR_CODE_H
@@ -16,11 +16,29 @@
#ifndef MOCK_TYPES_H
#define MOCK_TYPES_H
#include <functional>
#include <memory>
namespace OHOS {
namespace AAFwk {
class Want {};
class StartOptions {};
} // namespace AAFwk
namespace AppExecFwk {
class EventHandler {
public:
bool PostSyncTask(const std::function<void()> &task, const char *name)
{
(void)name;
if (!task) {
return false;
}
task();
return true;
}
};
} // namespace AppExecFwk
} // namespace OHOS
#endif // MOCK_TYPES_H
@@ -17,6 +17,7 @@
#define MOCK_MODULAR_OBJECT_EXTENSION_CONTEXT_H
#include "ability_runtime_common.h"
#include "ipc_cremote_object.h"
struct AbilityBase_Want;
typedef struct AbilityBase_Want AbilityBase_Want;
@@ -42,6 +43,13 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_StartSelfUIAbi
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_TerminateSelf(
OH_AbilityRuntime_ModObjExtensionContextHandle context);
OHIPCRemoteStub* OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub(
OH_AbilityRuntime_ModObjExtensionContextHandle context, const char *descriptor,
OH_OnRemoteRequestCallback requestCallback, OH_OnRemoteDestroyCallback destroyCallback, void *userData);
void OH_AbilityRuntime_ModObjExtensionContext_DestroyIPCRemoteStub(
OH_AbilityRuntime_ModObjExtensionContextHandle context, OHIPCRemoteStub *stub);
#ifdef __cplusplus
}
#endif
@@ -29,6 +29,12 @@ public:
static ErrCode g_startSelfWithOptionsResult;
static ErrCode g_terminateResult;
std::shared_ptr<OHOS::AppExecFwk::EventHandler> GetEventHandler() const
{
static auto handler = std::make_shared<OHOS::AppExecFwk::EventHandler>();
return handler;
}
ErrCode StartSelfUIAbility(const AAFwk::Want &want) const { return g_startSelfResult; }
ErrCode StartSelfUIAbilityWithStartOptions(const AAFwk::Want &want,
const AAFwk::StartOptions &options) const { return g_startSelfWithOptionsResult; }
@@ -15,6 +15,8 @@
#include <gtest/gtest.h>
#include <cstring>
#include "modular_object_extension_context.h"
#include "modular_object_extension_types.h"
#include "modular_object_extension_context_impl.h"
@@ -37,6 +39,33 @@ ErrCode ModularObjectExtensionContext::g_terminateResult = ERR_OK;
int OHOS::AAFwk::CWantManager::g_transformResult = 0;
AbilityRuntime_ErrorCode g_checkWantResult = ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
namespace {
bool g_remoteStubCreateSuccess = true;
int g_remoteStubDestroyCount = 0;
OHIPCRemoteStub *g_lastDestroyedStub = nullptr;
const char *g_lastCreateDescriptor = nullptr;
OH_OnRemoteRequestCallback g_lastRequestCallback = nullptr;
OH_OnRemoteDestroyCallback g_lastDestroyCallback = nullptr;
void *g_lastRemoteStubUserData = nullptr;
OHIPCRemoteStub g_mockRemoteStub {};
} // namespace
extern "C" OHIPCRemoteStub* OH_IPCRemoteStub_Create(const char *descriptor,
OH_OnRemoteRequestCallback requestCallback, OH_OnRemoteDestroyCallback destroyCallback, void *userData)
{
g_lastCreateDescriptor = descriptor;
g_lastRequestCallback = requestCallback;
g_lastDestroyCallback = destroyCallback;
g_lastRemoteStubUserData = userData;
return g_remoteStubCreateSuccess ? &g_mockRemoteStub : nullptr;
}
extern "C" void OH_IPCRemoteStub_Destroy(OHIPCRemoteStub *stub)
{
g_lastDestroyedStub = stub;
++g_remoteStubDestroyCount;
}
AbilityRuntime_ErrorCode CheckWant(AbilityBase_Want *want)
{
return g_checkWantResult;
@@ -53,10 +82,33 @@ public:
OHOS::AbilityRuntime::ModularObjectExtensionContext::g_terminateResult = ERR_OK;
OHOS::AAFwk::CWantManager::g_transformResult = 0;
g_checkWantResult = ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
g_remoteStubCreateSuccess = true;
g_remoteStubDestroyCount = 0;
g_lastDestroyedStub = nullptr;
g_lastCreateDescriptor = nullptr;
g_lastRequestCallback = nullptr;
g_lastDestroyCallback = nullptr;
g_lastRemoteStubUserData = nullptr;
}
void TearDown() override {}
};
namespace {
int MockRemoteRequest(uint32_t code, const OHIPCParcel *data, OHIPCParcel *reply, void *userData)
{
(void)code;
(void)data;
(void)reply;
(void)userData;
return 0;
}
void MockRemoteDestroy(void *userData)
{
(void)userData;
}
} // namespace
// ==================== GetBaseContext ====================
HWTEST_F(ModularObjectExtensionContextCapiTest, GetBaseContext_NullContext_001, TestSize.Level1)
@@ -326,3 +378,120 @@ HWTEST_F(ModularObjectExtensionContextCapiTest, TerminateSelf_Error_001, TestSiz
EXPECT_EQ(ret, ABILITY_RUNTIME_ERROR_CODE_INTERNAL);
GTEST_LOG_(INFO) << "TerminateSelf_Error_001 end";
}
// ==================== CreateIPCRemoteStub ====================
HWTEST_F(ModularObjectExtensionContextCapiTest, CreateIPCRemoteStub_NullDescriptor_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "CreateIPCRemoteStub_NullDescriptor_001 start";
auto stub = OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub(
nullptr, nullptr, MockRemoteRequest, MockRemoteDestroy, nullptr);
EXPECT_EQ(stub, nullptr);
GTEST_LOG_(INFO) << "CreateIPCRemoteStub_NullDescriptor_001 end";
}
HWTEST_F(ModularObjectExtensionContextCapiTest, CreateIPCRemoteStub_NullRequestCallback_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "CreateIPCRemoteStub_NullRequestCallback_001 start";
auto stub = OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub(
nullptr, "descriptor", nullptr, MockRemoteDestroy, nullptr);
EXPECT_EQ(stub, nullptr);
GTEST_LOG_(INFO) << "CreateIPCRemoteStub_NullRequestCallback_001 end";
}
HWTEST_F(ModularObjectExtensionContextCapiTest, CreateIPCRemoteStub_WrongType_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "CreateIPCRemoteStub_WrongType_001 start";
auto ctx = std::make_shared<OH_AbilityRuntime_ModularObjectExtensionContext>();
ctx->type = OHOS::AppExecFwk::ExtensionAbilityType::SERVICE;
auto cppCtx = std::make_shared<OHOS::AbilityRuntime::ModularObjectExtensionContext>();
ctx->context = cppCtx;
auto stub = OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub(
ctx.get(), "descriptor", MockRemoteRequest, MockRemoteDestroy, nullptr);
EXPECT_EQ(stub, nullptr);
GTEST_LOG_(INFO) << "CreateIPCRemoteStub_WrongType_001 end";
}
HWTEST_F(ModularObjectExtensionContextCapiTest, CreateIPCRemoteStub_ExpiredContext_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "CreateIPCRemoteStub_ExpiredContext_001 start";
auto ctx = std::make_shared<OH_AbilityRuntime_ModularObjectExtensionContext>();
ctx->type = OHOS::AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT;
auto stub = OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub(
ctx.get(), "descriptor", MockRemoteRequest, MockRemoteDestroy, nullptr);
EXPECT_EQ(stub, nullptr);
GTEST_LOG_(INFO) << "CreateIPCRemoteStub_ExpiredContext_001 end";
}
HWTEST_F(ModularObjectExtensionContextCapiTest, CreateIPCRemoteStub_CreateFail_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "CreateIPCRemoteStub_CreateFail_001 start";
auto ctx = std::make_shared<OH_AbilityRuntime_ModularObjectExtensionContext>();
ctx->type = OHOS::AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT;
auto cppCtx = std::make_shared<OHOS::AbilityRuntime::ModularObjectExtensionContext>();
ctx->context = cppCtx;
g_remoteStubCreateSuccess = false;
auto stub = OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub(
ctx.get(), "descriptor", MockRemoteRequest, MockRemoteDestroy, nullptr);
EXPECT_EQ(stub, nullptr);
EXPECT_STREQ(g_lastCreateDescriptor, "descriptor");
EXPECT_NE(g_lastRequestCallback, nullptr);
EXPECT_NE(g_lastDestroyCallback, nullptr);
EXPECT_NE(g_lastRemoteStubUserData, nullptr);
GTEST_LOG_(INFO) << "CreateIPCRemoteStub_CreateFail_001 end";
}
HWTEST_F(ModularObjectExtensionContextCapiTest, CreateIPCRemoteStub_Success_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "CreateIPCRemoteStub_Success_001 start";
int userData = 42;
auto ctx = std::make_shared<OH_AbilityRuntime_ModularObjectExtensionContext>();
ctx->type = OHOS::AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT;
auto cppCtx = std::make_shared<OHOS::AbilityRuntime::ModularObjectExtensionContext>();
ctx->context = cppCtx;
auto stub = OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub(
ctx.get(), "descriptor", MockRemoteRequest, MockRemoteDestroy, &userData);
EXPECT_EQ(stub, &g_mockRemoteStub);
EXPECT_STREQ(g_lastCreateDescriptor, "descriptor");
EXPECT_NE(g_lastRequestCallback, nullptr);
EXPECT_NE(g_lastDestroyCallback, nullptr);
EXPECT_NE(g_lastRemoteStubUserData, nullptr);
GTEST_LOG_(INFO) << "CreateIPCRemoteStub_Success_001 end";
}
// ==================== DestroyIPCRemoteStub ====================
HWTEST_F(ModularObjectExtensionContextCapiTest, DestroyIPCRemoteStub_NullStub_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "DestroyIPCRemoteStub_NullStub_001 start";
OH_AbilityRuntime_ModObjExtensionContext_DestroyIPCRemoteStub(nullptr, nullptr);
EXPECT_EQ(g_remoteStubDestroyCount, 1);
EXPECT_EQ(g_lastDestroyedStub, nullptr);
GTEST_LOG_(INFO) << "DestroyIPCRemoteStub_NullStub_001 end";
}
HWTEST_F(ModularObjectExtensionContextCapiTest, DestroyIPCRemoteStub_Success_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "DestroyIPCRemoteStub_Success_001 start";
OHIPCRemoteStub stub {};
OH_AbilityRuntime_ModObjExtensionContext_DestroyIPCRemoteStub(nullptr, &stub);
EXPECT_EQ(g_remoteStubDestroyCount, 1);
EXPECT_EQ(g_lastDestroyedStub, &stub);
GTEST_LOG_(INFO) << "DestroyIPCRemoteStub_Success_001 end";
}
HWTEST_F(ModularObjectExtensionContextCapiTest, DestroyIPCRemoteStub_ContextAndStubNotNull_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "DestroyIPCRemoteStub_ContextAndStubNotNull_001 start";
auto ctx = std::make_shared<OH_AbilityRuntime_ModularObjectExtensionContext>();
ctx->type = OHOS::AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT;
auto cppCtx = std::make_shared<OHOS::AbilityRuntime::ModularObjectExtensionContext>();
ctx->context = cppCtx;
OHIPCRemoteStub stub {};
OH_AbilityRuntime_ModObjExtensionContext_DestroyIPCRemoteStub(ctx.get(), &stub);
EXPECT_EQ(g_remoteStubDestroyCount, 1);
EXPECT_EQ(g_lastDestroyedStub, &stub);
GTEST_LOG_(INFO) << "DestroyIPCRemoteStub_ContextAndStubNotNull_001 end";
}
@@ -0,0 +1,45 @@
# Copyright (c) 2026 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/ohos.gni")
import("//build/test.gni")
import("//foundation/ability/ability_runtime/ability_runtime.gni")
ohos_unittest("modular_object_extension_context_impl_event_handler_test") {
module_out_path = "ability_runtime/ability_runtime/modular_object_extension_context_impl_event_handler_test"
sanitize = {
cfi = true
cfi_cross_dso = true
debug = false
blocklist = "../../cfi_blocklist.txt"
}
sources = [
"modular_object_extension_context_impl_event_handler_test.cpp",
"${ability_runtime_path}/frameworks/native/ability/native/modular_object_extension/modular_object_extension_context_impl.cpp",
]
include_dirs = [
"mock/include",
]
external_deps = [
"c_utils:utils",
"googletest:gtest_main",
"hilog:libhilog",
"hitrace:hitrace_meter",
"ipc:ipc_core",
]
}
group("unittest") {
testonly = true
deps = [ ":modular_object_extension_context_impl_event_handler_test" ]
}
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MOCK_ABILITY_MANAGER_CLIENT_H
#define MOCK_ABILITY_MANAGER_CLIENT_H
#endif // MOCK_ABILITY_MANAGER_CLIENT_H
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MOCK_ERRORS_H
#define MOCK_ERRORS_H
#include <cstdint>
using ErrCode = int32_t;
constexpr ErrCode ERR_OK = 0;
#endif // MOCK_ERRORS_H
@@ -0,0 +1,112 @@
/*
* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MOCK_EXTENSION_CONTEXT_H
#define MOCK_EXTENSION_CONTEXT_H
#include <memory>
#include "iremote_broker.h"
#include "refbase.h"
#include "iremote_object.h"
#include "errors.h"
namespace OHOS {
namespace AbilityRuntime {
class Context : public std::enable_shared_from_this<Context> {
public:
Context() = default;
virtual ~Context() = default;
};
} // namespace AbilityRuntime
namespace AppExecFwk {
class EventHandler : public std::enable_shared_from_this<EventHandler> {
public:
virtual ~EventHandler() = default;
};
} // namespace AppExecFwk
namespace AAFwk {
class Want {};
class StartOptions {};
class AbilityManagerClient {
public:
static std::shared_ptr<AbilityManagerClient> GetInstance()
{
static auto instance = std::make_shared<AbilityManagerClient>();
return instance;
}
ErrCode StartSelfUIAbility(const Want &want)
{
return g_startSelfUIAbilityResult;
}
ErrCode StartSelfUIAbilityWithToken(const Want &want, const sptr<IRemoteObject> &token)
{
return g_startSelfUIAbilityResult;
}
ErrCode StartSelfUIAbilityWithStartOptions(const Want &want, const StartOptions &options)
{
return g_startSelfUIAbilityWithStartOptionsResult;
}
ErrCode StartSelfUIAbilityWithStartOptionsAndToken(
const Want &want, const StartOptions &options, const sptr<IRemoteObject> &token)
{
return g_startSelfUIAbilityWithStartOptionsResult;
}
ErrCode TerminateAbility(const sptr<IRemoteObject> &token, int32_t resultCode, const Want *resultWant)
{
g_terminateCalled = true;
g_lastToken = token.GetRefPtr();
return g_terminateResult;
}
static ErrCode g_startSelfUIAbilityResult;
static ErrCode g_startSelfUIAbilityWithStartOptionsResult;
static ErrCode g_terminateResult;
static bool g_terminateCalled;
static IRemoteObject *g_lastToken;
static void Reset()
{
g_startSelfUIAbilityResult = ERR_OK;
g_startSelfUIAbilityWithStartOptionsResult = ERR_OK;
g_terminateResult = ERR_OK;
g_terminateCalled = false;
g_lastToken = nullptr;
}
};
} // namespace AAFwk
namespace AbilityRuntime {
class ExtensionContext : public Context {
public:
sptr<IRemoteObject> token_;
};
} // namespace AbilityRuntime
} // namespace OHOS
#endif // MOCK_EXTENSION_CONTEXT_H
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_AAFWK_HILOG_TAG_WRAPPER_H
#define OHOS_AAFWK_HILOG_TAG_WRAPPER_H
namespace OHOS::AAFwk {
enum class AAFwkLogTag : uint32_t {
DEFAULT = 0xD001300,
};
}
using AAFwkTag = OHOS::AAFwk::AAFwkLogTag;
#define TAG_LOGD(tag, fmt, ...) ((void)0)
#define TAG_LOGI(tag, fmt, ...) ((void)0)
#define TAG_LOGW(tag, fmt, ...) ((void)0)
#define TAG_LOGE(tag, fmt, ...) ((void)0)
#define TAG_LOGF(tag, fmt, ...) ((void)0)
#endif
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MOCK_HITRACE_METER_H
#define MOCK_HITRACE_METER_H
#define HITRACE_METER_NAME(tag, name)
#define HITRACE_TAG_ABILITY_MANAGER 0
#endif // MOCK_HITRACE_METER_H
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MOCK_MODULAR_OBJECT_EXTENSION_CONTEXT_IMPL_H
#define MOCK_MODULAR_OBJECT_EXTENSION_CONTEXT_IMPL_H
#include <cstddef>
#include <memory>
#include "extension_context.h"
namespace OHOS {
namespace AbilityRuntime {
class ModularObjectExtensionContext : public ExtensionContext {
public:
static const size_t CONTEXT_TYPE_ID;
// Pure declarations — definitions come from real .cpp (linked via BUILD.gn)
void SetEventHandler(const std::shared_ptr<AppExecFwk::EventHandler> &handler);
std::shared_ptr<AppExecFwk::EventHandler> GetEventHandler() const;
// Pure declarations — definitions come from real .cpp (linked via BUILD.gn)
ErrCode StartSelfUIAbility(const AAFwk::Want &want) const;
ErrCode StartSelfUIAbilityWithStartOptions(const AAFwk::Want &want,
const AAFwk::StartOptions &startOptions) const;
ErrCode TerminateSelf();
bool IsContext(size_t contextTypeId) { return contextTypeId == CONTEXT_TYPE_ID; }
private:
std::weak_ptr<AppExecFwk::EventHandler> handler_;
};
} // namespace AbilityRuntime
} // namespace OHOS
#endif // MOCK_MODULAR_OBJECT_EXTENSION_CONTEXT_IMPL_H
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MOCK_WANT_H
#define MOCK_WANT_H
typedef struct AbilityBase_Element {
char *bundleName;
char *moduleName;
char *abilityName;
} AbilityBase_Element;
typedef struct AbilityBase_Want AbilityBase_Want;
#endif // MOCK_WANT_H
@@ -0,0 +1,113 @@
/*
* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gtest/gtest.h>
#include "modular_object_extension_context_impl.h"
#include "extension_context.h"
using namespace testing::ext;
namespace OHOS {
class MockRemoteObject : public IRemoteObject {
public:
explicit MockRemoteObject(std::u16string desc) : IRemoteObject(desc) {}
int GetObjectRefCount() override { return 1; }
int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override
{
return 0;
}
bool AddDeathRecipient(const sptr<DeathRecipient> &recipient) override { return true; }
bool RemoveDeathRecipient(const sptr<DeathRecipient> &recipient) override { return true; }
int Dump(int fd, const std::vector<std::u16string> &args) override { return 0; }
};
} // namespace OHOS
namespace OHOS {
namespace AbilityRuntime {
class ModularObjectExtensionContextImplEventHandlerTest : public testing::Test {
public:
static void SetUpTestCase() {}
static void TearDownTestCase() {}
void SetUp() override {}
void TearDown() override {}
};
class MockEventHandler : public AppExecFwk::EventHandler {
};
// ==================== SetEventHandler / GetEventHandler ====================
// These tests target the REAL implementation in:
// frameworks/native/ability/native/modular_object_extension/modular_object_extension_context_impl.cpp
HWTEST_F(ModularObjectExtensionContextImplEventHandlerTest, GetEventHandler_DefaultNull_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "GetEventHandler_DefaultNull_001 start";
auto context = std::make_shared<ModularObjectExtensionContext>();
EXPECT_EQ(context->GetEventHandler(), nullptr);
GTEST_LOG_(INFO) << "GetEventHandler_DefaultNull_001 end";
}
HWTEST_F(ModularObjectExtensionContextImplEventHandlerTest, SetEventHandler_GetSameHandler_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "SetEventHandler_GetSameHandler_001 start";
auto context = std::make_shared<ModularObjectExtensionContext>();
auto handler = std::make_shared<MockEventHandler>();
context->SetEventHandler(handler);
EXPECT_EQ(context->GetEventHandler(), handler);
GTEST_LOG_(INFO) << "SetEventHandler_GetSameHandler_001 end";
}
HWTEST_F(ModularObjectExtensionContextImplEventHandlerTest, GetEventHandler_HandlerExpired_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "GetEventHandler_HandlerExpired_001 start";
auto context = std::make_shared<ModularObjectExtensionContext>();
auto handler = std::make_shared<MockEventHandler>();
context->SetEventHandler(handler);
handler.reset();
EXPECT_EQ(context->GetEventHandler(), nullptr);
GTEST_LOG_(INFO) << "GetEventHandler_HandlerExpired_001 end";
}
HWTEST_F(ModularObjectExtensionContextImplEventHandlerTest, SetEventHandler_NullHandler_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "SetEventHandler_NullHandler_001 start";
auto context = std::make_shared<ModularObjectExtensionContext>();
context->SetEventHandler(nullptr);
EXPECT_EQ(context->GetEventHandler(), nullptr);
GTEST_LOG_(INFO) << "SetEventHandler_NullHandler_001 end";
}
HWTEST_F(ModularObjectExtensionContextImplEventHandlerTest, SetEventHandler_Overwrite_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "SetEventHandler_Overwrite_001 start";
auto context = std::make_shared<ModularObjectExtensionContext>();
auto handler1 = std::make_shared<MockEventHandler>();
auto handler2 = std::make_shared<MockEventHandler>();
context->SetEventHandler(handler1);
EXPECT_EQ(context->GetEventHandler(), handler1);
context->SetEventHandler(handler2);
EXPECT_EQ(context->GetEventHandler(), handler2);
handler1.reset();
EXPECT_NE(context->GetEventHandler(), nullptr);
GTEST_LOG_(INFO) << "SetEventHandler_Overwrite_001 end";
}
} // namespace AbilityRuntime
} // namespace OHOS
@@ -33,6 +33,13 @@ public:
} // namespace AbilityRuntime
namespace AppExecFwk {
class EventHandler : public std::enable_shared_from_this<EventHandler> {
public:
virtual ~EventHandler() = default;
};
} // namespace AppExecFwk
namespace AAFwk {
class Want {};
@@ -86,6 +93,13 @@ namespace AbilityRuntime {
class ExtensionContext : public Context {
public:
sptr<IRemoteObject> token_;
protected:
virtual bool IsContext(size_t contextTypeId)
{
(void)contextTypeId;
return false;
}
};
} // namespace AbilityRuntime
@@ -26,6 +26,16 @@ class ModularObjectExtensionContext : public ExtensionContext {
public:
static const size_t CONTEXT_TYPE_ID;
void SetEventHandler(const std::shared_ptr<AppExecFwk::EventHandler> &handler)
{
handler_ = handler;
}
std::shared_ptr<AppExecFwk::EventHandler> GetEventHandler() const
{
return handler_.lock();
}
ErrCode StartSelfUIAbility(const AAFwk::Want &want) const
{
return AAFwk::AbilityManagerClient::GetInstance()->StartSelfUIAbility(want);
@@ -43,6 +53,9 @@ public:
}
bool IsContext(size_t contextTypeId) { return contextTypeId == CONTEXT_TYPE_ID; }
private:
std::weak_ptr<AppExecFwk::EventHandler> handler_;
};
} // namespace AbilityRuntime
@@ -64,6 +64,40 @@ public:
void TearDown() override {}
};
class MockEventHandler : public AppExecFwk::EventHandler {
};
// ==================== EventHandler ====================
HWTEST_F(ModularObjectExtensionContextImplTest, GetEventHandler_DefaultNull_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "GetEventHandler_DefaultNull_001 start";
auto context = std::make_shared<ModularObjectExtensionContext>();
EXPECT_EQ(context->GetEventHandler(), nullptr);
GTEST_LOG_(INFO) << "GetEventHandler_DefaultNull_001 end";
}
HWTEST_F(ModularObjectExtensionContextImplTest, SetEventHandler_GetSameHandler_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "SetEventHandler_GetSameHandler_001 start";
auto context = std::make_shared<ModularObjectExtensionContext>();
auto handler = std::make_shared<MockEventHandler>();
context->SetEventHandler(handler);
EXPECT_EQ(context->GetEventHandler(), handler);
GTEST_LOG_(INFO) << "SetEventHandler_GetSameHandler_001 end";
}
HWTEST_F(ModularObjectExtensionContextImplTest, GetEventHandler_HandlerExpired_001, TestSize.Level1)
{
GTEST_LOG_(INFO) << "GetEventHandler_HandlerExpired_001 start";
auto context = std::make_shared<ModularObjectExtensionContext>();
auto handler = std::make_shared<MockEventHandler>();
context->SetEventHandler(handler);
handler.reset();
EXPECT_EQ(context->GetEventHandler(), nullptr);
GTEST_LOG_(INFO) << "GetEventHandler_HandlerExpired_001 end";
}
// ==================== StartSelfUIAbility ====================
HWTEST_F(ModularObjectExtensionContextImplTest, StartSelfUIAbility_Success_001, TestSize.Level1)
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MOCK_ABILITY_HANDLER_H
#define MOCK_ABILITY_HANDLER_H
#include <memory>
namespace OHOS {
namespace AppExecFwk {
class EventHandler : public std::enable_shared_from_this<EventHandler> {
public:
virtual ~EventHandler() = default;
};
} // namespace AppExecFwk
namespace AbilityRuntime {
class AbilityHandler : public AppExecFwk::EventHandler {
public:
~AbilityHandler() override = default;
};
} // namespace AbilityRuntime
} // namespace OHOS
#endif // MOCK_ABILITY_HANDLER_H
@@ -18,6 +18,7 @@
#include <memory>
#include <string>
#include "ability_handler.h"
#include "mock_types.h"
#include "refbase.h"
#include "iremote_object.h"
@@ -27,7 +28,6 @@ namespace AbilityRuntime {
class AbilityLocalRecord {};
class OHOSApplication {};
class AbilityHandler {};
struct AbilityInfo {
std::string srcEntrance;
@@ -26,6 +26,11 @@ namespace AbilityRuntime {
class ModularObjectExtensionContext : public Context {
public:
ModularObjectExtensionContext() = default;
void SetEventHandler(const std::shared_ptr<AppExecFwk::EventHandler> &handler)
{
(void)handler;
}
};
} // namespace AbilityRuntime