Merge branch 'master' of git@gitcode.com:jusiyao/ability_ability_runtime.git into 'master'

# Conflicts:
#   conflict interfaces/inner_api/app_manager/include/appmgr/app_mgr_ipc_interface_code.h
Co-Authored-By:jsy
This commit is contained in:
jusiyao
2026-04-22 14:13:29 +08:00
249 changed files with 13657 additions and 427 deletions
@@ -263,6 +263,10 @@ int32_t AgentManagerService::GetCallerAgentCardByAgentId(const std::string &agen
int32_t AgentManagerService::RegisterAgentCard(const AgentCard &card)
{
if (!AAFwk::PermissionVerification::GetInstance()->JudgeCallerIsAllowedToUseSystemAPI()) {
TAG_LOGE(AAFwkTag::SER_ROUTER, "caller no system-app, can not use system-api");
return AAFwk::ERR_NOT_SYSTEM_APP;
}
if (!AAFwk::PermissionVerification::GetInstance()->VerifyCallingPermission(
AAFwk::PermissionConstants::PERMISSION_MODIFY_AGENT_CARD)) {
TAG_LOGE(AAFwkTag::SER_ROUTER, "Permission verification failed");
@@ -273,6 +277,10 @@ int32_t AgentManagerService::RegisterAgentCard(const AgentCard &card)
int32_t AgentManagerService::UpdateAgentCard(const AgentCard &card)
{
if (!AAFwk::PermissionVerification::GetInstance()->JudgeCallerIsAllowedToUseSystemAPI()) {
TAG_LOGE(AAFwkTag::SER_ROUTER, "caller no system-app, can not use system-api");
return AAFwk::ERR_NOT_SYSTEM_APP;
}
if (!AAFwk::PermissionVerification::GetInstance()->VerifyCallingPermission(
AAFwk::PermissionConstants::PERMISSION_MODIFY_AGENT_CARD)) {
TAG_LOGE(AAFwkTag::SER_ROUTER, "Permission verification failed");
@@ -283,6 +291,10 @@ int32_t AgentManagerService::UpdateAgentCard(const AgentCard &card)
int32_t AgentManagerService::DeleteAgentCard(const std::string &bundleName, const std::string &agentId)
{
if (!AAFwk::PermissionVerification::GetInstance()->JudgeCallerIsAllowedToUseSystemAPI()) {
TAG_LOGE(AAFwkTag::SER_ROUTER, "caller no system-app, can not use system-api");
return AAFwk::ERR_NOT_SYSTEM_APP;
}
if (!AAFwk::PermissionVerification::GetInstance()->VerifyCallingPermission(
AAFwk::PermissionConstants::PERMISSION_MODIFY_AGENT_CARD)) {
TAG_LOGE(AAFwkTag::SER_ROUTER, "Permission verification failed");
+3 -2
View File
@@ -127,10 +127,11 @@
"sub_component": [
"//foundation/ability/ability_runtime/agent_runtime_framework/interfaces/inner_api:agent_fwk",
"//foundation/ability/ability_runtime/agent_runtime_framework/services:agent_services_target",
"//foundation/ability/ability_runtime/cli_tool_framework/interfaces/cli_tool:cli_tool_client",
"//foundation/ability/ability_runtime/cli_tool_framework/services/climgr:climgr",
"//foundation/ability/ability_runtime/cli_tool_framework/etc/profile:aimgr_cfg",
"//foundation/ability/ability_runtime/cli_tool_framework/etc/profile:aimgr_trust",
"//foundation/ability/ability_runtime/cli_tool_framework/frameworks:cli_tool_framework_packages",
"//foundation/ability/ability_runtime/cli_tool_framework/interfaces/cli_tool:cli_tool_client",
"//foundation/ability/ability_runtime/cli_tool_framework/services/climgr:climgr",
"//foundation/ability/ability_runtime/services:ams_target",
"//foundation/ability/ability_runtime/services/sa_profile:ams_sa_profile",
"//foundation/ability/ability_runtime/services/quickfixmgr:quick_fix.cfg",
+21
View File
@@ -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.
import("//build/ohos.gni")
import("//foundation/ability/ability_runtime/ability_runtime.gni")
group("cli_tool_framework_packages") {
deps = [
"${cli_tool_framework_path}/frameworks/js/napi/cli_tool_manager:clitoolmanager_napi",
]
}
@@ -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.
import("//build/ohos.gni")
import("//foundation/ability/ability_runtime/ability_runtime.gni")
ohos_shared_library("clitoolmanager_napi") {
sanitize = {
cfi = true
cfi_cross_dso = true
debug = false
}
include_dirs = [
"include",
"${ability_runtime_path}/interfaces/kits/native/ability/ability_runtime",
"${cli_tool_framework_path}/interfaces/cli_tool/include",
]
sources = [
"src/cli_tool_manager_module.cpp",
"src/js_cli_manager.cpp",
"src/js_cli_manager_utils.cpp",
]
deps = [
"${ability_runtime_innerkits_path}/error_utils:ability_runtime_error_util",
"${ability_runtime_innerkits_path}/runtime:runtime",
"${ability_runtime_napi_path}/inner/napi_common:napi_common",
"${cli_tool_framework_path}/interfaces/cli_tool:cli_tool_client",
]
external_deps = [
"ability_base:base",
"c_utils:utils",
"hilog:libhilog",
"napi:ace_napi",
]
relative_install_dir = "module/app/cli_tool"
subsystem_name = "ability"
part_name = "ability_runtime"
}
@@ -0,0 +1,82 @@
/*
* 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 OHOS_CLI_TOOL_JS_CLI_MANAGER_H
#define OHOS_CLI_TOOL_JS_CLI_MANAGER_H
#include <memory>
#include <string>
#include <map>
#include "native_engine/native_engine.h"
#include "refbase.h"
namespace OHOS {
namespace CliTool {
/**
* @class JSCliManager
* @brief JS API wrapper for CLI tool management functionality.
*
* Provides native methods for executing CLI tools.
*/
class JSCliManager final {
public:
JSCliManager() {}
~JSCliManager() {}
/**
* @brief Finalizer for the JSCliManager object.
*
* @param env The N-API environment.
* @param data The pointer to the JSCliManager instance.
* @param hint The hint data.
*/
static void Finalizer(napi_env env, void *data, void *hint);
/**
* @brief Native method for executing a CLI tool.
*
* @param env The N-API environment.
* @param info The N-API callback info.
* @return Returns the N-API value.
*/
static napi_value ExecTool(napi_env env, napi_callback_info info);
private:
/**
* @brief Implementation for executing a CLI tool.
*
* @param env The N-API environment.
* @param argc The argument count.
* @param argv The argument values.
* @return Returns the N-API value.
*/
napi_value OnExecTool(napi_env env, size_t argc, napi_value *argv);
};
/**
* @brief Initialize the JSCliManager module.
*
* @param env The N-API environment.
* @param exportObj The export object.
* @return Returns the N-API value.
*/
napi_value JSCliManagerInit(napi_env env, napi_value exportObj);
} // namespace CliTool
} // namespace OHOS
#endif // OHOS_CLI_TOOL_JS_CLI_MANAGER_H
@@ -0,0 +1,68 @@
/*
* 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 OHOS_CLI_TOOL_JS_CLI_MANAGER_UTILS_H
#define OHOS_CLI_TOOL_JS_CLI_MANAGER_UTILS_H
#include <map>
#include <string>
#include "cli_session_info.h"
#include "exec_options.h"
#include "exec_result.h"
#include "native_engine/native_engine.h"
namespace OHOS {
namespace CliTool {
/**
* @brief Unwrap a string map from JavaScript object.
* @param env The N-API environment.
* @param obj The JavaScript object.
* @param values Output key-value pairs.
* @return Returns true on success, false otherwise.
*/
bool UnwrapStringMap(napi_env env, napi_value obj,
std::map<std::string, std::string> &values);
/**
* @brief Unwrap ExecOptions from JavaScript object.
* @param env The N-API environment.
* @param obj The JavaScript object.
* @param options Output ExecOptions.
* @return Returns true on success, false otherwise.
*/
bool UnwrapExecOptions(napi_env env, napi_value obj, ExecOptions &options);
/**
* @brief Create JavaScript CliSessionInfo object.
* @param env The N-API environment.
* @param session The CliSessionInfo structure.
* @return Returns the JavaScript object.
*/
napi_value CreateJsCliSessionInfo(napi_env env, const CliSessionInfo &session);
/**
* @brief Create JavaScript error from native error code.
* @param env The N-API environment.
* @param errCode The native error code.
* @return Returns the JavaScript error object.
*/
napi_value CreateCliJsErrorByNativeErr(napi_env env, int32_t errCode);
} // namespace CliTool
} // namespace OHOS
#endif // OHOS_CLI_TOOL_JS_CLI_MANAGER_UTILS_H
@@ -0,0 +1,29 @@
/*
* 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 "native_engine/native_engine.h"
#include "js_cli_manager.h"
static napi_module _module = {
.nm_version = 0,
.nm_filename = "app/cli_tool/cli_tool_manager_napi.so/cli_tool_manager.js",
.nm_register_func = OHOS::CliTool::JSCliManagerInit,
.nm_modname = "app.cliTool.cliToolManager",
};
extern "C" __attribute__((constructor)) void NAPI_app_cliTool_cliToolManager_AutoRegister(void)
{
napi_module_register(&_module);
}
@@ -0,0 +1,137 @@
/*
* 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 "js_cli_manager.h"
#include <map>
#include <string>
#include <ctime>
#include "hilog_tag_wrapper.h"
#include "js_cli_manager_utils.h"
#include "js_error_utils.h"
#include "js_runtime_utils.h"
#include "napi/native_api.h"
#include "napi_common_util.h"
#include "cli_tool_mgr_client.h"
using namespace OHOS::AbilityRuntime;
namespace OHOS {
namespace CliTool {
namespace {
constexpr int32_t INDEX_ZERO = 0;
constexpr int32_t INDEX_ONE = 1;
constexpr int32_t INDEX_TWO = 2;
constexpr int32_t INDEX_THREE = 3;
} // namespace
void JSCliManager::Finalizer(napi_env env, void *data, void *hint)
{
TAG_LOGD(AAFwkTag::CLI_TOOL, "JSCliManager::Finalizer is called");
std::unique_ptr<JSCliManager>(static_cast<JSCliManager*>(data));
}
napi_value JSCliManager::ExecTool(napi_env env, napi_callback_info info)
{
GET_CB_INFO_AND_CALL(env, info, JSCliManager, OnExecTool);
}
napi_value JSCliManager::OnExecTool(napi_env env, size_t argc, napi_value *argv)
{
TAG_LOGD(AAFwkTag::CLI_TOOL, "JSCliManager::OnExecTool called");
HandleEscape handleEscape(env);
if (argc < INDEX_THREE) {
ThrowTooFewParametersError(env);
return CreateJsUndefined(env);
}
std::string name;
if (!AppExecFwk::UnwrapStringFromJS2(env, argv[INDEX_ZERO], name) || name.empty()) {
ThrowInvalidParamError(env, "Tool name is required");
return CreateJsUndefined(env);
}
std::map<std::string, std::string> args;
if (!UnwrapStringMap(env, argv[INDEX_ONE], args)) {
ThrowInvalidParamError(env, "Tool args is required");
return CreateJsUndefined(env);
}
std::string challenge;
if (!AppExecFwk::UnwrapStringFromJS2(env, argv[INDEX_TWO], challenge)) {
ThrowInvalidParamError(env, "Tool challenge is required");
return CreateJsUndefined(env);
}
ExecOptions options;
if (argc > INDEX_THREE && argv[INDEX_THREE] != nullptr) {
if (!UnwrapExecOptions(env, argv[INDEX_THREE], options)) {
ThrowInvalidParamError(env, "Tool options is required");
return CreateJsUndefined(env);
}
}
auto innerErrCode = std::make_shared<int32_t>(ERR_OK);
auto session = std::make_shared<CliSessionInfo>();
NapiAsyncTask::ExecuteCallback execute = [innerErrCode, name, args, challenge, options, session]() {
*innerErrCode = CliToolMGRClient::GetInstance().ExecTool(name, args, challenge, options, *session);
};
NapiAsyncTask::CompleteCallback complete = [innerErrCode, session](
napi_env env, NapiAsyncTask &task, int32_t status) {
HandleScope handleScope(env);
if (*innerErrCode != ERR_OK) {
task.Reject(env, CreateCliJsErrorByNativeErr(env, *innerErrCode));
return;
}
napi_value jsSession = CreateJsCliSessionInfo(env, *session);
if (jsSession == nullptr) {
task.Reject(env, CreateJsUndefined(env));
return;
}
task.ResolveWithNoError(env, jsSession);
};
napi_value asyncResult = nullptr;
NapiAsyncTask::Schedule("JsCliManager::OnExecTool", env,
CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &asyncResult));
return handleEscape.Escape(asyncResult);
}
napi_value JSCliManagerInit(napi_env env, napi_value exportObj)
{
TAG_LOGD(AAFwkTag::CLI_TOOL, "Init JSCliManager");
if (env == nullptr || exportObj == nullptr) {
TAG_LOGW(AAFwkTag::CLI_TOOL, "Null env or exportObj");
return nullptr;
}
std::unique_ptr<JSCliManager> jsCliManager = std::make_unique<JSCliManager>();
napi_wrap(env, exportObj, jsCliManager.release(), JSCliManager::Finalizer, nullptr, nullptr);
const char *moduleName = "JsCliManager";
BindNativeFunction(env, exportObj, "execTool", moduleName, JSCliManager::ExecTool);
TAG_LOGD(AAFwkTag::CLI_TOOL, "JSCliManagerInit end");
return CreateJsUndefined(env);
}
} // namespace CliTool
} // namespace OHOS
@@ -0,0 +1,239 @@
/*
* 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 "js_cli_manager_utils.h"
#include <map>
#include "hilog_tag_wrapper.h"
#include "js_error_utils.h"
#include "js_runtime_utils.h"
#include "napi/native_api.h"
#include "napi_common_util.h"
#include "ability_runtime_error_util.h"
using namespace OHOS::AbilityRuntime;
namespace OHOS {
namespace CliTool {
namespace {
constexpr int32_t TIME_OUT = 30 * 1000;
}
bool UnwrapStringMap(napi_env env, napi_value obj,
std::map<std::string, std::string> &values)
{
if (obj == nullptr) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Input object is null");
return false;
}
napi_valuetype valueType = napi_undefined;
napi_status status = napi_typeof(env, obj, &valueType);
if (status != napi_ok || valueType != napi_object) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Input is not an object");
return false;
}
napi_value propertyNames = nullptr;
if (napi_get_property_names(env, obj, &propertyNames) != napi_ok) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Failed to get property names");
return false;
}
uint32_t propertyCount = 0;
if (napi_get_array_length(env, propertyNames, &propertyCount) != napi_ok) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Failed to get array length");
return false;
}
values.clear();
for (uint32_t i = 0; i < propertyCount; i++) {
napi_value key = nullptr;
if (napi_get_element(env, propertyNames, i, &key) != napi_ok) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Failed to get element");
return false;
}
std::string keyStr;
if (!AppExecFwk::UnwrapStringFromJS2(env, key, keyStr)) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Failed to unwrap key");
return false;
}
napi_value value = nullptr;
if (napi_get_named_property(env, obj, keyStr.c_str(), &value) != napi_ok) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Failed to get value");
return false;
}
std::string valueStr;
if (!AppExecFwk::UnwrapStringFromJS2(env, value, valueStr)) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Failed to unwrap value");
return false;
}
values.emplace(std::make_pair(keyStr, valueStr));
}
return true;
}
bool UnwrapExecOptions(napi_env env, napi_value obj, ExecOptions &options)
{
if (obj == nullptr) {
// Use default options
options.background = false;
options.yieldMs = 0;
options.timeout = TIME_OUT;
options.workingDir = "";
return true;
}
napi_valuetype valueType = napi_undefined;
napi_status status = napi_typeof(env, obj, &valueType);
if (status != napi_ok || valueType != napi_object) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Input is not an object");
return false;
}
// Extract background (optional)
napi_value backgroundProp = nullptr;
if (napi_get_named_property(env, obj, "background", &backgroundProp) != napi_ok) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "invalid background property");
return false;
}
if (!AppExecFwk::UnwrapBoolFromJS2(env, backgroundProp, options.background)) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "unwrap background failed");
return false;
}
// Extract yieldMs (optional)
napi_value yieldMsProp = nullptr;
if (napi_get_named_property(env, obj, "yieldMs", &yieldMsProp) != napi_ok) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "invalid yieldMs property");
return false;
}
if (!AppExecFwk::UnwrapInt32FromJS2(env, yieldMsProp, options.yieldMs)) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "unwrap yieldMs failed");
return false;
}
// Extract timeout (optional)
napi_value timeoutProp = nullptr;
if (napi_get_named_property(env, obj, "timeout", &timeoutProp) != napi_ok) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "invalid timeout property");
return false;
}
if (!AppExecFwk::UnwrapInt32FromJS2(env, timeoutProp, options.timeout)) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "unwrap timeout failed");
return false;
}
// Extract workingDir (optional)
napi_value workingDirProp = nullptr;
if (napi_get_named_property(env, obj, "workingDir", &workingDirProp) != napi_ok) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "invalid workingDir property");
return false;
}
if (!AppExecFwk::UnwrapStringFromJS2(env, workingDirProp, options.workingDir)) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "unwrap workingDir failed");
return false;
}
// Extract env (optional)
napi_value envProp = nullptr;
if (napi_get_named_property(env, obj, "env", &envProp) != napi_ok) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "invalid env property");
return false;
}
if (!UnwrapStringMap(env, envProp, options.env)) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "unwrap env failed");
return false;
}
return true;
}
napi_value CreateJsCliSessionInfo(napi_env env, const CliSessionInfo &session)
{
napi_value jsObj = nullptr;
napi_status status = napi_create_object(env, &jsObj);
if (status != napi_ok) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Failed to create JS object");
return nullptr;
}
// Set sessionId
napi_value jsSessionId = AppExecFwk::WrapStringToJS(env, session.sessionId);
napi_set_named_property(env, jsObj, "sessionId", jsSessionId);
// Set toolName
napi_value jsToolName = AppExecFwk::WrapStringToJS(env, session.toolName);
napi_set_named_property(env, jsObj, "toolName", jsToolName);
// Set status
napi_value jsStatus = AppExecFwk::WrapStringToJS(env, session.status);
napi_set_named_property(env, jsObj, "status", jsStatus);
// Set startTime
napi_value jsStartTime = AppExecFwk::WrapInt64ToJS(env, session.startTime);
napi_set_named_property(env, jsObj, "startTime", jsStartTime);
// Set endTime
napi_value jsEndTime = AppExecFwk::WrapInt64ToJS(env, session.endTime);
napi_set_named_property(env, jsObj, "endTime", jsEndTime);
// Set result if present
if (session.result != nullptr) {
napi_value jsResult = nullptr;
status = napi_create_object(env, &jsResult);
if (status == napi_ok) {
// Set exitCode
napi_value jsExitCode = AppExecFwk::WrapInt32ToJS(env, session.result->exitCode);
napi_set_named_property(env, jsResult, "exitCode", jsExitCode);
// Set outputText
napi_value jsOutputText = AppExecFwk::WrapStringToJS(env, session.result->outputText);
napi_set_named_property(env, jsResult, "outputText", jsOutputText);
// Set errorText
napi_value jsErrorText = AppExecFwk::WrapStringToJS(env, session.result->errorText);
napi_set_named_property(env, jsResult, "errorText", jsErrorText);
// Set signalNumber
napi_value jsSignalNumber = AppExecFwk::WrapInt32ToJS(env, session.result->signalNumber);
napi_set_named_property(env, jsResult, "signalNumber", jsSignalNumber);
// Set timedOut
napi_value jsTimedOut = AppExecFwk::WrapBoolToJS(env, session.result->timedOut);
napi_set_named_property(env, jsResult, "timedOut", jsTimedOut);
// Set executionTime
napi_value jsExecutionTime = AppExecFwk::WrapInt64ToJS(env, session.result->executionTime);
napi_set_named_property(env, jsResult, "executionTime", jsExecutionTime);
napi_set_named_property(env, jsObj, "result", jsResult);
}
}
return jsObj;
}
napi_value CreateCliJsErrorByNativeErr(napi_env env, int32_t errCode)
{
return CreateJsErrorByNativeErr(env, errCode);
}
} // namespace CliTool
} // namespace OHOS
@@ -49,8 +49,12 @@ ohos_shared_library("cli_tool_client") {
output_values = get_target_outputs(":cli_tool_manager_interface")
sources = [
"src/cli_session_info.cpp",
"src/cli_tool_mgr_client.cpp",
"src/exec_options.cpp",
"src/exec_result.cpp",
"src/tool_info.cpp",
"src/tool_summary.cpp",
]
sources += filter_include(output_values, [ "*.cpp" ])
defines = [ "AMS_LOG_TAG = \"CliToolManager\"" ]
@@ -13,5 +13,16 @@
* limitations under the License.
*/
sequenceable ToolInfo..OHOS.CliTool.ToolInfo;
sequenceable OHOS.CliTool.ToolSummary;
sequenceable ExecOptions..OHOS.CliTool.ExecOptions;
sequenceable CliSessionInfo..OHOS.CliTool.CliSessionInfo;
interface OHOS.CliTool.ICliToolManager {
void GetAllToolSummaries([out] ToolSummary[] summaries);
void GetToolInfoByName([in] String name, [out] ToolInfo tool);
void GetAllToolInfos([out] ToolInfo[] tools);
void RegisterTool([in] ToolInfo tool);
void ExecTool([in] String cliName, [in] OrderedMap<String, String> args,
[in] String challenge, [in] ExecOptions options, [out] CliSessionInfo session);
}
@@ -0,0 +1,46 @@
/*
* 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 OHOS_ABILITY_RUNTIME_CLI_SESSION_INFO_H
#define OHOS_ABILITY_RUNTIME_CLI_SESSION_INFO_H
#include <string>
#include "exec_result.h"
#include "parcel.h"
namespace OHOS {
namespace CliTool {
/**
* @struct CliSessionInfo
* @brief Information about a CLI tool execution session.
*/
class CliSessionInfo : public Parcelable {
public:
std::string sessionId;
std::string toolName;
std::string status; // "running", "completed", "failed"
int64_t startTime;
int64_t endTime;
std::shared_ptr<ExecResult> result; // optional, only when status="completed"
CliSessionInfo() = default;
bool Marshalling(Parcel &parcel) const;
static CliSessionInfo *Unmarshalling(Parcel &parcel);
};
} // namespace CliTool
} // namespace OHOS
#endif // OHOS_ABILITY_RUNTIME_CLI_SESSION_INFO_H
@@ -18,6 +18,8 @@
#include <mutex>
#include "cli_session_info.h"
#include "exec_options.h"
#include "icli_tool_manager.h"
namespace OHOS {
@@ -41,6 +43,50 @@ public:
*/
~CliToolMGRClient() = default;
/**
* @brief Get all tool summaries (lightweight for listing)
* @param summaries Output vector of ToolSummary
* @return ErrCode ERR_OK on success
*/
ErrCode GetAllToolSummaries(std::vector<ToolSummary> &summaries);
/**
* @brief Get tool information by name
* @param name Tool name
* @param tool Output ToolInfo
* @return ErrCode ERR_OK on success
*/
ErrCode GetToolInfoByName(const std::string &name, ToolInfo &tool);
/**
* @brief Get all tool infos
* @param tools Output vector of ToolInfo
* @return ErrCode ERR_OK on success
*/
ErrCode GetAllToolInfos(std::vector<ToolInfo> &tools);
/**
* @brief Register a CLI tool
* @param tool ToolInfo to register
* @return ErrCode ERR_OK on success
*/
ErrCode RegisterTool(const ToolInfo &tool);
/**
* @brief Execute a CLI tool with key-value pairs (convenience method).
* @param name The CLI tool name.
* @param args The tool arguments as key-value pairs.
* @param challenge Optional challenge string.
* @param options Execution options.
* @param session Output session information.
* @return Returns ERR_OK on success, error code otherwise.
*/
int32_t ExecTool(const std::string &name,
const std::map<std::string, std::string> &args,
const std::string &challenge,
const ExecOptions &options,
CliSessionInfo &session);
private:
CliToolMGRClient() = default;
DISALLOW_COPY_AND_MOVE(CliToolMGRClient);
@@ -53,7 +99,7 @@ private:
private:
DISALLOW_COPY_AND_MOVE(CliSaDeathRecipient);
};
sptr<ICliToolManager> GetCliToolManager();
ErrCode Connect();
/**
@@ -0,0 +1,43 @@
/*
* 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 OHOS_ABILITY_RUNTIME_EXEC_OPTIONS_H
#define OHOS_ABILITY_RUNTIME_EXEC_OPTIONS_H
#include <map>
#include <string>
#include "parcel.h"
namespace OHOS {
namespace CliTool {
/**
* @struct ExecOptions
* @brief Options for executing CLI tools.
*/
class ExecOptions : public Parcelable {
public:
bool background;
int32_t yieldMs;
int32_t timeout;
std::map<std::string, std::string> env;
std::string workingDir;
bool Marshalling(Parcel &parcel) const;
static ExecOptions *Unmarshalling(Parcel &parcel);
};
} // namespace CliTool
} // namespace OHOS
#endif // OHOS_ABILITY_RUNTIME_EXEC_OPTIONS_H
@@ -0,0 +1,42 @@
/*
* 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 OHOS_ABILITY_RUNTIME_EXEC_RESULT_H
#define OHOS_ABILITY_RUNTIME_EXEC_RESULT_H
#include <string>
#include "parcel.h"
namespace OHOS {
namespace CliTool {
/**
* @brief Tool execution result
*/
class ExecResult : public Parcelable {
public:
int32_t exitCode;
std::string outputText;
std::string errorText;
int32_t signalNumber;
bool timedOut;
int64_t executionTime;
bool Marshalling(Parcel &parcel) const;
static ExecResult *Unmarshalling(Parcel &parcel);
};
} // namespace CliTool
} // namespace OHOS
#endif // OHOS_ABILITY_RUNTIME_EXEC_RESULT_H
@@ -16,6 +16,8 @@
#ifndef OHOS_ABILITY_RUNTIME_TOOL_INFO_H
#define OHOS_ABILITY_RUNTIME_TOOL_INFO_H
#include "tool_summary.h"
#include <iremote_broker.h>
#include <iremote_object.h>
#include <map>
@@ -24,6 +26,8 @@
#include <string>
#include <vector>
#include "exec_result.h"
namespace OHOS {
namespace CliTool {
/**
@@ -55,22 +59,6 @@ public:
}
};
/**
* @brief Tool summary information (lightweight for listing)
*/
class ToolSummary : public Parcelable {
public:
std::string name;
std::string version;
std::string description;
ToolSummary() = default;
~ToolSummary() = default;
bool Marshalling(Parcel &parcel) const override;
static ToolSummary *Unmarshalling(Parcel &parcel);
};
/**
* @brief Tool information structure (full version)
*/
@@ -99,62 +87,6 @@ public:
static ToolInfo *Unmarshalling(Parcel &parcel);
};
/**
* @brief Tool execution options
*/
class ExecOptions : public Parcelable {
public:
bool background = false; // true: async, false: sync with yieldMs timeout
int32_t yieldMs = 30000; // foreground wait timeout (only when background=false)
int32_t timeout = 0; // total execution timeout (0 = use tool default)
std::map<std::string, std::string> env;
std::string workingDir;
ExecOptions() = default;
~ExecOptions() = default;
bool Marshalling(Parcel &parcel) const override;
static ExecOptions *Unmarshalling(Parcel &parcel);
};
/**
* @brief Tool execution result
*/
class ExecResult : public Parcelable {
public:
int32_t exitCode = 0;
std::string outputText;
std::string errorText;
int32_t signalNumber = 0;
bool timedOut = false;
int64_t executionTime = 0;
ExecResult() = default;
~ExecResult() = default;
bool Marshalling(Parcel &parcel) const override;
static ExecResult *Unmarshalling(Parcel &parcel);
};
/**
* @brief Session information
*/
class SessionInfo : public Parcelable {
public:
std::string sessionId;
std::string toolName;
std::string status; // "running", "completed", "failed"
int64_t startTime = 0;
int64_t endTime = 0;
std::shared_ptr<ExecResult> result; // optional, only when status="completed"
SessionInfo() = default;
~SessionInfo() = default;
bool Marshalling(Parcel &parcel) const override;
static SessionInfo *Unmarshalling(Parcel &parcel);
};
/**
* @brief Tool event (for async mode)
*/
@@ -0,0 +1,43 @@
/*
* 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 OHOS_ABILITY_RUNTIME_TOOL_SUMMARY_H
#define OHOS_ABILITY_RUNTIME_TOOL_SUMMARY_H
#include <iremote_broker.h>
#include <parcel.h>
#include <string>
namespace OHOS {
namespace CliTool {
/**
* @brief Tool summary information (lightweight for listing)
*/
class ToolSummary : public Parcelable {
public:
std::string name;
std::string version;
std::string description;
ToolSummary() = default;
~ToolSummary() = default;
bool Marshalling(Parcel &parcel) const override;
static ToolSummary *Unmarshalling(Parcel &parcel);
};
} // namespace CliTool
} // namespace OHOS
#endif // OHOS_ABILITY_RUNTIME_TOOL_SUMMARY_H
@@ -0,0 +1,87 @@
/*
* 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 "cli_session_info.h"
namespace OHOS {
namespace CliTool {
bool CliSessionInfo::Marshalling(Parcel &parcel) const
{
if (!parcel.WriteString(sessionId)) {
return false;
}
if (!parcel.WriteString(toolName)) {
return false;
}
if (!parcel.WriteString(status)) {
return false;
}
if (!parcel.WriteInt64(startTime)) {
return false;
}
if (!parcel.WriteInt64(endTime)) {
return false;
}
// Write result presence flag
bool hasResult = (result != nullptr);
if (!parcel.WriteBool(hasResult)) {
return false;
}
if (hasResult && !result->Marshalling(parcel)) {
return false;
}
return true;
}
CliSessionInfo *CliSessionInfo::Unmarshalling(Parcel &parcel)
{
auto *info = new (std::nothrow) CliSessionInfo();
if (info && !parcel.ReadString(info->sessionId)) {
delete info;
return nullptr;
}
if (!parcel.ReadString(info->toolName)) {
delete info;
return nullptr;
}
if (!parcel.ReadString(info->status)) {
delete info;
return nullptr;
}
if (!parcel.ReadInt64(info->startTime)) {
delete info;
return nullptr;
}
if (!parcel.ReadInt64(info->endTime)) {
delete info;
return nullptr;
}
bool hasResult = false;
if (!parcel.ReadBool(hasResult)) {
delete info;
return nullptr;
}
if (hasResult) {
ExecResult *resultPtr = ExecResult::Unmarshalling(parcel);
if (resultPtr == nullptr) {
delete info;
return nullptr;
}
info->result = std::shared_ptr<ExecResult>(resultPtr);
}
return info;
}
} // namespace CliTool
} // namespace OHOS
@@ -84,6 +84,20 @@ void CliToolMGRClient::CliSaDeathRecipient::OnRemoteDied(const wptr<IRemoteObjec
CliToolMGRClient::GetInstance().ResetProxy(remote);
}
int32_t CliToolMGRClient::ExecTool(const std::string &name,
const std::map<std::string, std::string> &args,
const std::string &challenge,
const ExecOptions &options,
CliSessionInfo &session)
{
auto proxy = GetCliToolManager();
if (proxy == nullptr) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "connect failed");
return AAFwk::GET_CLI_TOOL_MGR_SERVICE_FAILED;
}
return proxy->ExecTool(name, args, challenge, options, session);
}
void CliToolMGRClient::ResetProxy(const wptr<IRemoteObject>& remote)
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
@@ -98,5 +112,49 @@ void CliToolMGRClient::ResetProxy(const wptr<IRemoteObject>& remote)
proxy_ = nullptr;
}
}
ErrCode CliToolMGRClient::GetAllToolSummaries(std::vector<ToolSummary> &summaries)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
auto proxy = GetCliToolManager();
if (proxy == nullptr) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "proxy is null");
return AAFwk::GET_CLI_TOOL_MGR_SERVICE_FAILED;
}
return proxy->GetAllToolSummaries(summaries);
}
ErrCode CliToolMGRClient::GetToolInfoByName(const std::string &name, ToolInfo &tool)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
auto proxy = GetCliToolManager();
if (proxy == nullptr) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "proxy is null");
return AAFwk::GET_CLI_TOOL_MGR_SERVICE_FAILED;
}
return proxy->GetToolInfoByName(name, tool);
}
ErrCode CliToolMGRClient::GetAllToolInfos(std::vector<ToolInfo> &tools)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
auto proxy = GetCliToolManager();
if (proxy == nullptr) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "proxy is null");
return AAFwk::GET_CLI_TOOL_MGR_SERVICE_FAILED;
}
return proxy->GetAllToolInfos(tools);
}
ErrCode CliToolMGRClient::RegisterTool(const ToolInfo &tool)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
auto proxy = GetCliToolManager();
if (proxy == nullptr) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "proxy is null");
return AAFwk::GET_CLI_TOOL_MGR_SERVICE_FAILED;
}
return proxy->RegisterTool(tool);
}
} // namespace CliTool
} // namespace OHOS
@@ -0,0 +1,88 @@
/*
* 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 "exec_options.h"
namespace OHOS {
namespace CliTool {
bool ExecOptions::Marshalling(Parcel &parcel) const
{
if (!parcel.WriteBool(background)) {
return false;
}
if (!parcel.WriteInt32(yieldMs)) {
return false;
}
if (!parcel.WriteInt32(timeout)) {
return false;
}
if (!parcel.WriteUint32(static_cast<uint32_t>(env.size()))) {
return false;
}
for (const auto &[key, value] : env) {
if (!parcel.WriteString(key)) {
return false;
}
if (!parcel.WriteString(value)) {
return false;
}
}
if (!parcel.WriteString(workingDir)) {
return false;
}
return true;
}
ExecOptions *ExecOptions::Unmarshalling(Parcel &parcel)
{
auto *options = new (std::nothrow) ExecOptions();
if (options && !parcel.ReadBool(options->background)) {
delete options;
return nullptr;
}
if (!parcel.ReadInt32(options->yieldMs)) {
delete options;
return nullptr;
}
if (!parcel.ReadInt32(options->timeout)) {
delete options;
return nullptr;
}
uint32_t envSize = 0;
if (!parcel.ReadUint32(envSize)) {
delete options;
return nullptr;
}
for (uint32_t i = 0; i < envSize; i++) {
std::string key;
std::string value;
if (!parcel.ReadString(key)) {
delete options;
return nullptr;
}
if (!parcel.ReadString(value)) {
delete options;
return nullptr;
}
options->env[key] = value;
}
if (!parcel.ReadString(options->workingDir)) {
delete options;
return nullptr;
}
return options;
}
} // namespace CliTool
} // namespace OHOS
@@ -0,0 +1,73 @@
/*
* 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 "exec_result.h"
namespace OHOS {
namespace CliTool {
bool ExecResult::Marshalling(Parcel &parcel) const
{
if (!parcel.WriteInt32(exitCode)) {
return false;
}
if (!parcel.WriteString(outputText)) {
return false;
}
if (!parcel.WriteString(errorText)) {
return false;
}
if (!parcel.WriteInt32(signalNumber)) {
return false;
}
if (!parcel.WriteBool(timedOut)) {
return false;
}
if (!parcel.WriteInt64(executionTime)) {
return false;
}
return true;
}
ExecResult *ExecResult::Unmarshalling(Parcel &parcel)
{
auto *result = new (std::nothrow) ExecResult();
if (result && !parcel.ReadInt32(result->exitCode)) {
delete result;
return nullptr;
}
if (!parcel.ReadString(result->outputText)) {
delete result;
return nullptr;
}
if (!parcel.ReadString(result->errorText)) {
delete result;
return nullptr;
}
if (!parcel.ReadInt32(result->signalNumber)) {
delete result;
return nullptr;
}
if (!parcel.ReadBool(result->timedOut)) {
delete result;
return nullptr;
}
if (!parcel.ReadInt64(result->executionTime)) {
delete result;
return nullptr;
}
return result;
}
} // namespace CliTool
} // namespace OHOS
@@ -17,30 +17,6 @@
namespace OHOS {
namespace CliTool {
// ToolSummary implementation
bool ToolSummary::Marshalling(Parcel &parcel) const
{
return parcel.WriteString(name) &&
parcel.WriteString(version) &&
parcel.WriteString(description);
}
ToolSummary *ToolSummary::Unmarshalling(Parcel &parcel)
{
auto *summary = new (std::nothrow) ToolSummary();
if (summary == nullptr) {
return nullptr;
}
if (!parcel.ReadString(summary->name) ||
!parcel.ReadString(summary->version) ||
!parcel.ReadString(summary->description)) {
delete summary;
return nullptr;
}
return summary;
}
// ToolInfo implementation
bool ToolInfo::Marshalling(Parcel &parcel) const
@@ -91,105 +67,6 @@ ToolInfo *ToolInfo::Unmarshalling(Parcel &parcel)
return tool;
}
// ExecOptions implementation
bool ExecOptions::Marshalling(Parcel &parcel) const
{
return parcel.WriteBool(background) &&
parcel.WriteInt32(yieldMs) &&
parcel.WriteInt32(timeout) &&
parcel.WriteString(workingDir);
}
ExecOptions *ExecOptions::Unmarshalling(Parcel &parcel)
{
auto *options = new (std::nothrow) ExecOptions();
if (options == nullptr) {
return nullptr;
}
if (!parcel.ReadBool(options->background) ||
!parcel.ReadInt32(options->yieldMs) ||
!parcel.ReadInt32(options->timeout) ||
!parcel.ReadString(options->workingDir)) {
delete options;
return nullptr;
}
return options;
}
// ExecResult implementation
bool ExecResult::Marshalling(Parcel &parcel) const
{
return parcel.WriteInt32(exitCode) &&
parcel.WriteString(outputText) &&
parcel.WriteString(errorText) &&
parcel.WriteInt32(signalNumber) &&
parcel.WriteBool(timedOut) &&
parcel.WriteInt64(executionTime);
}
ExecResult *ExecResult::Unmarshalling(Parcel &parcel)
{
auto *result = new (std::nothrow) ExecResult();
if (result == nullptr) {
return nullptr;
}
if (!parcel.ReadInt32(result->exitCode) ||
!parcel.ReadString(result->outputText) ||
!parcel.ReadString(result->errorText) ||
!parcel.ReadInt32(result->signalNumber) ||
!parcel.ReadBool(result->timedOut) ||
!parcel.ReadInt64(result->executionTime)) {
delete result;
return nullptr;
}
return result;
}
// SessionInfo implementation
bool SessionInfo::Marshalling(Parcel &parcel) const
{
return parcel.WriteString(sessionId) &&
parcel.WriteString(toolName) &&
parcel.WriteString(status) &&
parcel.WriteInt64(startTime) &&
parcel.WriteInt64(endTime) &&
parcel.WriteBool(result != nullptr) &&
(result == nullptr || parcel.WriteParcelable(result.get()));
}
SessionInfo *SessionInfo::Unmarshalling(Parcel &parcel)
{
auto *session = new (std::nothrow) SessionInfo();
if (session == nullptr) {
return nullptr;
}
bool hasResult = false;
if (!parcel.ReadString(session->sessionId) ||
!parcel.ReadString(session->toolName) ||
!parcel.ReadString(session->status) ||
!parcel.ReadInt64(session->startTime) ||
!parcel.ReadInt64(session->endTime) ||
!parcel.ReadBool(hasResult)) {
delete session;
return nullptr;
}
if (hasResult) {
session->result.reset(ExecResult::Unmarshalling(parcel));
if (session->result == nullptr) {
delete session;
return nullptr;
}
}
return session;
}
// ToolEvent implementation
bool ToolEvent::Marshalling(Parcel &parcel) const
{
@@ -0,0 +1,66 @@
/*
* 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 "tool_summary.h"
#include "hilog_tag_wrapper.h"
namespace OHOS {
namespace CliTool {
bool ToolSummary::Marshalling(Parcel &parcel) const
{
if (!parcel.WriteString(name)) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Write name failed");
return false;
}
if (!parcel.WriteString(version)) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Write version failed");
return false;
}
if (!parcel.WriteString(description)) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Write description failed");
return false;
}
return true;
}
ToolSummary *ToolSummary::Unmarshalling(Parcel &parcel)
{
auto *summary = new (std::nothrow) ToolSummary();
if (summary == nullptr) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Failed to allocate ToolSummary");
return nullptr;
}
if (!parcel.ReadString(summary->name)) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Read name failed");
delete summary;
return nullptr;
}
if (!parcel.ReadString(summary->version)) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Read version failed");
delete summary;
return nullptr;
}
if (!parcel.ReadString(summary->description)) {
TAG_LOGE(AAFwkTag::CLI_TOOL, "Read description failed");
delete summary;
return nullptr;
}
return summary;
}
} // namespace CliTool
} // namespace OHOS
+1 -1
View File
@@ -47,7 +47,7 @@ ohos_shared_library("climgr") {
external_deps = [
"c_utils:utils",
"hilog:libhilog",
"ipc:ipc_core",
"ipc:ipc_single",
"json:nlohmann_json_static",
"kv_store:distributeddata_inner",
"safwk:system_ability_fwk",
@@ -35,22 +35,32 @@ public:
/**
* @brief Query all available tools
*/
int32_t QueryTools(std::vector<ToolInfo> &tools);
int32_t GetAllToolInfos(std::vector<ToolInfo> &tools) override;
/**
* @brief Query tool summaries (lightweight for listing)
*/
int32_t QueryToolSummaries(std::vector<ToolSummary> &summaries);
int32_t GetAllToolSummaries(std::vector<ToolSummary> &summaries) override;
/**
* @brief Get tool information by name
*/
int32_t GetToolInfoByName(const std::string &name, ToolInfo &tool);
int32_t GetToolInfoByName(const std::string &name, ToolInfo &tool) override;
/**
* @brief Register a CLI tool
*/
int32_t RegisterCliTool(const ToolInfo &tool);
int32_t RegisterTool(const ToolInfo &tool) override;
/**
* @brief Execute a CLI tool.
* Implements the ICliToolManager interface method.
*/
int32_t ExecTool(const std::string &cliName,
const std::map<std::string, std::string> &args,
const std::string &challenge,
const ExecOptions &options,
CliSessionInfo &session) override;
protected:
void OnStart() override;
@@ -35,9 +35,9 @@ constexpr int32_t CHECK_INTERVAL = 100000; // 100ms
constexpr int32_t MAX_TIMES = 5; // 5 * 100ms = 500ms
constexpr const char* DEFAULT_REGISTRY_PATH = "/system/bin/cli_tool/cli_tool.json";
constexpr const char* KV_STORE_APP_ID = "cli_tools_storage";
constexpr const char* KV_STORE_APP_ID = "cli_tools_db";
constexpr const char* KV_STORE_STORE_ID = "cli_tools_store";
constexpr const char* CLI_TOOLS_STORAGE_DIR = "/data/service/el1/public/database/ability_manager_service";
constexpr const char* CLI_TOOLS_STORAGE_DIR = "/data/service/el1/public/database/cli_tool";
const DistributedKv::AppId APP_ID { KV_STORE_APP_ID };
const DistributedKv::StoreId STORE_ID { KV_STORE_STORE_ID };
@@ -60,17 +60,18 @@ void CliToolManagerService::OnStart()
void CliToolManagerService::OnStop()
{
TAG_LOGI(AAFwkTag::CLI_TOOL, "climgr stop");
}
int32_t CliToolManagerService::QueryTools(std::vector<ToolInfo> &tools)
int32_t CliToolManagerService::GetAllToolInfos(std::vector<ToolInfo> &tools)
{
TAG_LOGI(AAFwkTag::CLI_TOOL, "QueryTools called");
TAG_LOGI(AAFwkTag::CLI_TOOL, "GetAllToolInfos called");
return CliToolDataManager::GetInstance().GetAllTools(tools);
}
int32_t CliToolManagerService::QueryToolSummaries(std::vector<ToolSummary> &summaries)
int32_t CliToolManagerService::GetAllToolSummaries(std::vector<ToolSummary> &summaries)
{
TAG_LOGI(AAFwkTag::CLI_TOOL, "QueryToolSummaries called");
TAG_LOGI(AAFwkTag::CLI_TOOL, "GetAllToolSummaries called");
return CliToolDataManager::GetInstance().QueryToolSummaries(summaries);
}
@@ -80,10 +81,20 @@ int32_t CliToolManagerService::GetToolInfoByName(const std::string &name, ToolIn
return CliToolDataManager::GetInstance().GetToolByName(name, tool);
}
int32_t CliToolManagerService::RegisterCliTool(const ToolInfo &tool)
int32_t CliToolManagerService::RegisterTool(const ToolInfo &tool)
{
TAG_LOGI(AAFwkTag::CLI_TOOL, "RegisterCliTool called, tool name='%{public}s'", tool.name.c_str());
TAG_LOGI(AAFwkTag::CLI_TOOL, "RegisterTool called, tool name='%{public}s'", tool.name.c_str());
return CliToolDataManager::GetInstance().RegisterTool(tool);
}
int32_t CliToolManagerService::ExecTool(const std::string &cliName,
const std::map<std::string, std::string> &args,
const std::string &challenge,
const ExecOptions &options,
CliSessionInfo &session)
{
TAG_LOGI(AAFwkTag::CLI_TOOL, "ExecTool called: %{public}s", cliName.c_str());
return 0;
}
} // namespace CliTool
} // namespace OHOS
+15 -2
View File
@@ -42,8 +42,9 @@ ohos_shared_library("ability_runtime") {
include_dirs = [
"include",
"${ability_runtime_path}/interfaces/inner_api/",
"${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/",
"${ability_runtime_path}/interfaces/inner_api",
"${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime",
"${ability_runtime_path}/interfaces/kits/native/ability/native/modular_object_extension",
]
configs = [
@@ -55,21 +56,31 @@ ohos_shared_library("ability_runtime") {
sources = [
"src/ability_business_error_utils.cpp",
"src/application_context.cpp",
"src/connect_options.cpp",
"src/context.cpp",
"src/load_ability_callback_impl.cpp",
"src/modular_object_extension_ability.cpp",
"src/modular_object_extension_context.cpp",
"src/c_modular_object_connection_callback.cpp",
"src/modular_object_extension_manager.cpp",
"src/modular_object_connection_manager.cpp",
"src/modular_object_ability_connection.cpp",
"src/c_modular_object_utils.cpp",
"src/start_options.cpp",
"src/start_options_impl.cpp",
"src/want_utils.cpp",
]
deps = [
"${ability_runtime_innerkits_path}/ability_manager:ability_connect_callback_stub",
"${ability_runtime_innerkits_path}/ability_manager:ability_manager",
"${ability_runtime_innerkits_path}/ability_manager:ability_start_options",
"${ability_runtime_innerkits_path}/ability_manager:process_options",
"${ability_runtime_innerkits_path}/ability_manager:start_window_option",
"${ability_runtime_innerkits_path}/app_manager:app_manager",
"${ability_runtime_innerkits_path}/page_config_manager:page_config_manager",
"${ability_runtime_native_path}/ability:ability_context_native",
"${ability_runtime_native_path}/ability/native:modular_object_extension",
"${ability_runtime_native_path}/appkit:app_context",
]
@@ -83,6 +94,7 @@ ohos_shared_library("ability_runtime") {
"image_framework:pixelmap",
"ipc:ipc_capi",
"ipc:ipc_core",
"ipc:ipc_napi",
"napi:ace_napi",
"samgr:samgr_proxy",
]
@@ -91,6 +103,7 @@ ohos_shared_library("ability_runtime") {
external_deps += [
"graphic_2d:color_manager",
"image_framework:image",
"window_manager:libwm",
"window_manager:window_animation_utils",
]
defines = [
@@ -0,0 +1,87 @@
/*
* 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 OHOS_ABILITY_RUNTIME_C_MODULAR_OBJECT_CONNECTION_CALLBACK_H
#define OHOS_ABILITY_RUNTIME_C_MODULAR_OBJECT_CONNECTION_CALLBACK_H
#include <map>
#include <mutex>
#include "ability_connect_callback.h"
#include "connect_options_impl.h"
namespace OHOS {
namespace AbilityRuntime {
struct ModularObjectConnectionKey {
int64_t id;
};
struct ModularObjectConnectionKeyCompare {
bool operator()(const ModularObjectConnectionKey &key1, const ModularObjectConnectionKey &key2) const
{
return key1.id < key2.id;
}
};
class CModularObjectConnectionCallback;
namespace CModularObjectConnectionUtils {
/**
* @brief Insert connection callback into global registry.
* @param callback The callback object to insert.
* @return Returns the connection ID.
*/
int64_t InsertConnection(sptr<CModularObjectConnectionCallback> callback);
/**
* @brief Remove connection callback from global registry.
* @param connectionId The connection ID to remove.
*/
void RemoveConnectionCallback(int64_t connectionId);
/**
* @brief Find connection callback by ID.
* @param connectionId The connection ID to find.
* @param callback Output parameter for the found callback.
*/
void FindConnection(int64_t connectionId, sptr<CModularObjectConnectionCallback> &callback);
} // namespace CModularObjectConnectionUtils
/**
* @brief C connection callback for ModularObjectExtension.
* Handles OnAbilityConnectDone/OnAbilityDisconnectDone and invokes user C callbacks.
*/
class CModularObjectConnectionCallback : public AbilityConnectCallback {
public:
CModularObjectConnectionCallback(
const std::shared_ptr<OH_AbilityRuntime_ConnectOptionsState> &state);
~CModularObjectConnectionCallback() override = default;
void OnAbilityConnectDone(const AppExecFwk::ElementName &element,
const sptr<IRemoteObject> &remoteObject, int resultCode) override;
void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override;
void SetConnectionId(int64_t id) { connectionId_ = id; }
int64_t GetConnectionId() const { return connectionId_; }
private:
int64_t connectionId_ = 0;
std::weak_ptr<OH_AbilityRuntime_ConnectOptionsState> state_;
};
} // namespace AbilityRuntime
} // namespace OHOS
#endif // OHOS_ABILITY_RUNTIME_C_MODULAR_OBJECT_CONNECTION_CALLBACK_H
@@ -0,0 +1,44 @@
/*
* 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 OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_UTILS_H
#define OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_UTILS_H
#include <string>
#include "ability_runtime_common.h"
#include "connect_options_impl.h"
#include "context.h"
#include "element_name.h"
#include "iremote_object.h"
namespace OHOS {
namespace AbilityRuntime {
class CModularObjectUtils {
public:
static AbilityRuntime_ErrorCode ConvertConnectBusinessErrorCode(int32_t errCode);
static bool BuildElement(const AppExecFwk::ElementName &elementName, AbilityBase_Element &element);
static void DestroyElement(AbilityBase_Element &element);
static bool CopyToCString(const std::string &src, char *&dst);
static AbilityRuntime_ErrorCode TransformWant(AbilityBase_Want *want, AAFwk::Want &abilityWant);
static AbilityRuntime_ErrorCode CheckContextAndToken(AbilityRuntime_ContextHandle context,
sptr<IRemoteObject> &token);
static void NotifyFailed(std::shared_ptr<OH_AbilityRuntime_ConnectOptionsState> state,
int32_t businessErrorCode);
};
} // namespace AbilityRuntime
} // namespace OHOS
#endif // OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_UTILS_H
@@ -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 ABILITY_RUNTIME_CONNECT_OPTIONS_IMPL_H
#define ABILITY_RUNTIME_CONNECT_OPTIONS_IMPL_H
#include <memory>
#include <mutex>
#include "connect_options.h"
struct OH_AbilityRuntime_ConnectOptionsState {
std::mutex mutex;
bool alive = true;
OH_AbilityRuntime_ConnectOptions *owner = nullptr;
OH_AbilityRuntime_ConnectOptions_OnConnectCallback onConnectCallback = nullptr;
OH_AbilityRuntime_ConnectOptions_OnDisconnectCallback onDisconnectCallback = nullptr;
OH_AbilityRuntime_ConnectOptions_OnFailedCallback onFailedCallback = nullptr;
};
struct OH_AbilityRuntime_ConnectOptions {
std::shared_ptr<OH_AbilityRuntime_ConnectOptionsState> state;
};
#endif // ABILITY_RUNTIME_CONNECT_OPTIONS_IMPL_H
@@ -0,0 +1,63 @@
/*
* 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 OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_ABILITY_CONNECTION_H
#define OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_ABILITY_CONNECTION_H
#include <mutex>
#include "ability_connection.h"
namespace OHOS {
namespace AbilityRuntime {
/**
* @class ModularObjectAbilityConnection
* @brief Connection class for ModularObjectExtension.
*
* Inherits from AbilityConnection and uses ModularObjectConnectionManager
* for connection lifecycle management instead of ConnectionManager.
*/
class ModularObjectAbilityConnection : public AbilityConnection {
public:
ModularObjectAbilityConnection() = default;
~ModularObjectAbilityConnection() override = default;
/**
* @brief Called when ability connection is done.
*
* @param element Service ability's ElementName.
* @param remoteObject The session proxy of service ability.
* @param resultCode ERR_OK on success, others on failure.
*/
void OnAbilityConnectDone(
const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode) override;
/**
* @brief Called when ability disconnection is done.
*
* @param element Service ability's ElementName.
* @param resultCode ERR_OK on success, others on failure.
*/
void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override;
private:
std::mutex modularMutex_;
};
} // namespace AbilityRuntime
} // namespace OHOS
#endif // OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_ABILITY_CONNECTION_H
@@ -0,0 +1,121 @@
/*
* 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 OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_CONNECTION_MANAGER_H
#define OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_CONNECTION_MANAGER_H
#include <map>
#include <mutex>
#include <vector>
#include "ability_connect_callback.h"
#include "errors.h"
#include "iremote_object.h"
#include "modular_object_ability_connection.h"
#include "operation.h"
#include "want.h"
namespace OHOS {
namespace AbilityRuntime {
/**
* @brief Connection info key for ModularObjectExtension.
* Key consists of: abilityConnection + connectReceiver.
*/
struct ModularObjectConnectionInfo {
sptr<ModularObjectAbilityConnection> abilityConnection;
AAFwk::Operation connectReceiver;
ModularObjectConnectionInfo(const sptr<ModularObjectAbilityConnection> &connection,
const AAFwk::Operation &receiver)
: abilityConnection(connection), connectReceiver(receiver)
{}
bool operator<(const ModularObjectConnectionInfo &that) const
{
if (abilityConnection < that.abilityConnection) {
return true;
}
if (connectReceiver.GetBundleName() < that.connectReceiver.GetBundleName()) {
return true;
}
if (connectReceiver.GetBundleName() == that.connectReceiver.GetBundleName() &&
connectReceiver.GetModuleName() < that.connectReceiver.GetModuleName()) {
return true;
}
if (connectReceiver.GetBundleName() == that.connectReceiver.GetBundleName() &&
connectReceiver.GetModuleName() == that.connectReceiver.GetModuleName() &&
connectReceiver.GetAbilityName() < that.connectReceiver.GetAbilityName()) {
return true;
}
return false;
}
};
/**
* @brief Manages connections to ModularObjectExtension instances.
*
* Key difference from ConnectionManager: NO connection reuse.
* Each connect call creates a new connection.
*/
class ModularObjectConnectionManager {
public:
~ModularObjectConnectionManager() = default;
ModularObjectConnectionManager(const ModularObjectConnectionManager &) = delete;
ModularObjectConnectionManager &operator=(const ModularObjectConnectionManager &) = delete;
static ModularObjectConnectionManager &GetInstance();
/**
* @brief Connect to ModularObjectExtension - always creates new connection.
* @param want The Want containing target ability info.
* @param callback The connection callback.
*/
ErrCode ConnectModularObjectExtension(const AAFwk::Want &want,
const sptr<AbilityConnectCallback> &callback);
/**
* @brief Disconnect from ModularObjectExtension by callback.
* @param callback The connection callback to disconnect.
*/
ErrCode DisconnectModularObjectExtension(const sptr<AbilityConnectCallback> &callback);
/**
* @brief Remove connection record by connection object.
* @param connection The connection to remove.
* @return true if removed, false otherwise.
*/
bool RemoveConnection(const sptr<ModularObjectAbilityConnection> &connection);
/**
* @brief Check if service exists and disconnect if not found.
* @param element The service element name.
* @param connection The connection to check.
* @return true if service does not exist and was disconnected, false if found.
*/
bool DisconnectNonexistentService(const AppExecFwk::ElementName &element,
const sptr<ModularObjectAbilityConnection> &connection);
private:
ModularObjectConnectionManager() = default;
std::mutex connectionMutex_;
std::map<ModularObjectConnectionInfo, std::vector<sptr<AbilityConnectCallback>>> connectionRecords_;
};
} // namespace AbilityRuntime
} // namespace OHOS
#endif // OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_CONNECTION_MANAGER_H
@@ -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.
*/
#ifndef ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_TYPES_H
#define ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_TYPES_H
#include <memory>
#include "extension_ability_info.h"
#include "modular_object_extension_ability.h"
#include "native_extension/context_impl.h"
#include "native_extension/extension_ability_impl.h"
#ifdef __cplusplus
extern "C" {
#endif
struct OH_AbilityRuntime_ModularObjectExtensionContext : public AbilityRuntime_Context {
};
struct OH_AbilityRuntime_ModularObjectExtensionInstance : public AbilityRuntime_ExtensionInstance {
std::shared_ptr<OH_AbilityRuntime_ModularObjectExtensionContext> context;
OH_AbilityRuntime_ModObjExtensionAbility_OnCreateFunc onCreateFunc = nullptr;
OH_AbilityRuntime_ModObjExtensionAbility_OnDestroyFunc onDestroyFunc = nullptr;
OH_AbilityRuntime_ModObjExtensionAbility_OnConnectFunc onConnectFunc = nullptr;
OH_AbilityRuntime_ModObjExtensionAbility_OnDisconnectFunc onDisconnectFunc = nullptr;
};
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_TYPES_H
@@ -0,0 +1,166 @@
/*
* 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 "c_modular_object_connection_callback.h"
#include <algorithm>
#include <cinttypes>
#include "c_modular_object_utils.h"
#include "hilog_tag_wrapper.h"
#include "ipc_inner_object.h"
#include "modular_object_connection_manager.h"
#include "modular_object_extension_types.h"
#include "want_manager.h"
namespace OHOS {
namespace AbilityRuntime {
namespace {
static std::map<ModularObjectConnectionKey, sptr<CModularObjectConnectionCallback>,
ModularObjectConnectionKeyCompare> g_connectCallbacks;
static std::recursive_mutex g_connectCallbacksLock;
static int64_t g_serialNumber = 0;
} // namespace
namespace CModularObjectConnectionUtils {
int64_t InsertConnection(sptr<CModularObjectConnectionCallback> callback)
{
std::lock_guard<std::recursive_mutex> lock(g_connectCallbacksLock);
if (callback == nullptr) {
TAG_LOGE(AAFwkTag::EXT, "null callback");
return -1;
}
int64_t connectId = g_serialNumber;
ModularObjectConnectionKey key;
key.id = g_serialNumber;
callback->SetConnectionId(connectId);
g_connectCallbacks.emplace(key, callback);
if (g_serialNumber < INT64_MAX) {
g_serialNumber++;
} else {
g_serialNumber = 0;
}
TAG_LOGD(AAFwkTag::EXT, "Connection inserted, id: %{public}" PRId64, connectId);
return connectId;
}
void RemoveConnectionCallback(int64_t connectionId)
{
sptr<CModularObjectConnectionCallback> callback;
std::lock_guard<std::recursive_mutex> lock(g_connectCallbacksLock);
auto item = std::find_if(g_connectCallbacks.begin(), g_connectCallbacks.end(),
[&connectionId](const auto &obj) { return connectionId == obj.first.id; });
if (item != g_connectCallbacks.end()) {
callback = item->second;
g_connectCallbacks.erase(item);
} else {
TAG_LOGW(AAFwkTag::EXT, "Connection not found, id: %{public}" PRId64, connectionId);
}
}
void FindConnection(int64_t connectionId, sptr<CModularObjectConnectionCallback> &callback)
{
std::lock_guard<std::recursive_mutex> lock(g_connectCallbacksLock);
auto item = std::find_if(g_connectCallbacks.begin(), g_connectCallbacks.end(),
[&connectionId](const auto &obj) { return connectionId == obj.first.id; });
if (item != g_connectCallbacks.end()) {
callback = item->second;
}
}
} // namespace CModularObjectConnectionUtils
CModularObjectConnectionCallback::CModularObjectConnectionCallback(
const std::shared_ptr<OH_AbilityRuntime_ConnectOptionsState> &state)
: state_(state)
{}
void CModularObjectConnectionCallback::OnAbilityConnectDone(const AppExecFwk::ElementName &element,
const sptr<IRemoteObject> &remoteObject, int resultCode)
{
TAG_LOGD(AAFwkTag::EXT, "ConnectDone:%{public}s, %{public}d", element.GetAbilityName().c_str(), resultCode);
if (remoteObject == nullptr) {
return;
}
auto state = state_.lock();
if (state == nullptr) {
return;
}
OH_AbilityRuntime_ConnectOptions_OnConnectCallback callback = nullptr;
OH_AbilityRuntime_ConnectOptions *owner = nullptr;
{
std::lock_guard<std::mutex> guard(state->mutex);
if (!state->alive) {
return;
}
callback = state->onConnectCallback;
owner = state->owner;
}
if (callback == nullptr) {
return;
}
AbilityBase_Element cElement;
if (!CModularObjectUtils::BuildElement(element, cElement)) {
CModularObjectUtils::NotifyFailed(state, ABILITY_RUNTIME_ERROR_CODE_INTERNAL);
return;
}
sptr<IRemoteObject> remoteObjectCopy = remoteObject;
OHIPCRemoteProxy *proxy = CreateIPCRemoteProxy(remoteObjectCopy);
if (proxy == nullptr) {
CModularObjectUtils::DestroyElement(cElement);
CModularObjectUtils::NotifyFailed(state, ABILITY_RUNTIME_ERROR_CODE_INTERNAL);
return;
}
callback(owner, &cElement, proxy);
CModularObjectUtils::DestroyElement(cElement);
}
void CModularObjectConnectionCallback::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element,
int resultCode)
{
TAG_LOGD(AAFwkTag::EXT, "DisconnectDone:%{public}s, %{public}d", element.GetAbilityName().c_str(), resultCode);
auto state = state_.lock();
if (state == nullptr) {
TAG_LOGW(AAFwkTag::EXT, "state null");
CModularObjectConnectionUtils::RemoveConnectionCallback(connectionId_);
return;
}
OH_AbilityRuntime_ConnectOptions_OnDisconnectCallback callback = nullptr;
OH_AbilityRuntime_ConnectOptions *owner = nullptr;
{
std::lock_guard<std::mutex> guard(state->mutex);
if (state->alive) {
callback = state->onDisconnectCallback;
owner = state->owner;
} else {
TAG_LOGW(AAFwkTag::EXT, "state not alive");
}
}
if (callback == nullptr) {
TAG_LOGW(AAFwkTag::EXT, "callback null");
return;
}
AbilityBase_Element cElement;
if (CModularObjectUtils::BuildElement(element, cElement)) {
callback(owner, &cElement);
CModularObjectUtils::DestroyElement(cElement);
} else {
CModularObjectUtils::NotifyFailed(state, ABILITY_RUNTIME_ERROR_CODE_INTERNAL);
}
}
} // namespace AbilityRuntime
} // namespace OHOS
@@ -0,0 +1,160 @@
/*
* 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 "c_modular_object_utils.h"
#include "ability_business_error_utils.h"
#include "ability_manager_errors.h"
#include "hilog_tag_wrapper.h"
#include "native_extension/context_impl.h"
#include "securec.h"
#include "want_manager.h"
#include "want_utils.h"
using namespace OHOS::AAFwk;
namespace OHOS {
namespace AbilityRuntime {
AbilityRuntime_ErrorCode CModularObjectUtils::ConvertConnectBusinessErrorCode(int32_t errCode)
{
switch (errCode) {
case ABILITY_VISIBLE_FALSE_DENY_REQUEST:
return ABILITY_RUNTIME_ERROR_CODE_VISIBILITY_VERIFICATION_FAILED;
case ERR_STATIC_CFG_PERMISSION:
return ABILITY_RUNTIME_ERROR_CODE_STATIC_CFG_PERMISSION;
case ERR_CROSS_USER:
return ABILITY_RUNTIME_ERROR_CODE_CROSS_USER_OPERATION;
case ERR_CHECK_CALL_FROM_BACKGROUND_FAILED:
return ABILITY_RUNTIME_ERROR_CODE_NO_RUNNING_ABILITIES_WITH_UI;
case ERR_FREQ_START_ABILITY:
return ABILITY_RUNTIME_ERROR_CODE_UPPER_RATE_LIMIT;
case ERR_REACH_UPPER_LIMIT:
case ERR_UPPER_LIMIT:
return ABILITY_RUNTIME_ERROR_CODE_UPPER_CONNECTION_NUMBER_LIMIT;
case ERR_MODULAR_OBJECT_DISABLED:
return ABILITY_RUNTIME_ERROR_CODE_MODULAR_OBJECT_EXTENSION_DISABLED;
case ERR_NO_RUNNING_ABILITIES_WITH_UI:
return ABILITY_RUNTIME_ERROR_CODE_NO_RUNNING_ABILITIES_WITH_UI;
default:
return ConvertToCommonBusinessErrorCode(errCode);
}
}
bool CModularObjectUtils::BuildElement(const AppExecFwk::ElementName &elementName, AbilityBase_Element &element)
{
element.bundleName = nullptr;
element.moduleName = nullptr;
element.abilityName = nullptr;
if (!CopyToCString(elementName.GetBundleName(), element.bundleName)) {
return false;
}
if (!CopyToCString(elementName.GetModuleName(), element.moduleName)) {
delete[] element.bundleName;
element.bundleName = nullptr;
return false;
}
if (!CopyToCString(elementName.GetAbilityName(), element.abilityName)) {
delete[] element.bundleName;
delete[] element.moduleName;
element.bundleName = nullptr;
element.moduleName = nullptr;
return false;
}
return true;
}
void CModularObjectUtils::DestroyElement(AbilityBase_Element &element)
{
delete[] element.bundleName;
delete[] element.moduleName;
delete[] element.abilityName;
element.bundleName = nullptr;
element.moduleName = nullptr;
element.abilityName = nullptr;
}
bool CModularObjectUtils::CopyToCString(const std::string &src, char *&dst)
{
dst = new (std::nothrow) char[src.size() + 1];
if (dst == nullptr) {
return false;
}
if (strcpy_s(dst, src.size() + 1, src.c_str()) != EOK) {
delete[] dst;
dst = nullptr;
return false;
}
return true;
}
AbilityRuntime_ErrorCode CModularObjectUtils::TransformWant(AbilityBase_Want *want, AAFwk::Want &abilityWant)
{
auto ret = CheckWant(want);
if (ret != ABILITY_RUNTIME_ERROR_CODE_NO_ERROR) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid want");
return ret;
}
auto errCode = CWantManager::TransformToWant(*want, false, abilityWant);
if (errCode != ABILITY_BASE_ERROR_CODE_NO_ERROR) {
TAG_LOGE(AAFwkTag::APPKIT, "transform want failed: %{public}d", errCode);
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
AbilityRuntime_ErrorCode CModularObjectUtils::CheckContextAndToken(AbilityRuntime_ContextHandle context,
sptr<IRemoteObject> &token)
{
if (context == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null context");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
auto contextPtr = context->context.lock();
if (contextPtr == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "context not exist");
return ABILITY_RUNTIME_ERROR_CODE_CONTEXT_NOT_EXIST;
}
token = contextPtr->GetToken();
if (token == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null token");
return ABILITY_RUNTIME_ERROR_CODE_CONTEXT_NOT_EXIST;
}
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
void CModularObjectUtils::NotifyFailed(std::shared_ptr<OH_AbilityRuntime_ConnectOptionsState> state,
int32_t businessErrorCode)
{
if (state == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "state null");
return;
}
OH_AbilityRuntime_ConnectOptions_OnFailedCallback callback = nullptr;
OH_AbilityRuntime_ConnectOptions *owner = nullptr;
{
std::lock_guard<std::mutex> guard(state->mutex);
if (!state->alive) {
return;
}
callback = state->onFailedCallback;
owner = state->owner;
}
if (callback != nullptr) {
callback(owner, static_cast<AbilityRuntime_ErrorCode>(businessErrorCode));
}
}
} // namespace AbilityRuntime
} // namespace OHOS
@@ -0,0 +1,132 @@
/*
* 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 "connect_options.h"
#include <new>
#include "connect_options_impl.h"
#include "hilog_tag_wrapper.h"
namespace {
std::shared_ptr<OH_AbilityRuntime_ConnectOptionsState> GetState(OH_AbilityRuntime_ConnectOptions *connectOptions)
{
if (connectOptions == nullptr || connectOptions->state == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid connectOptions");
return nullptr;
}
return connectOptions->state;
}
} // namespace
#ifdef __cplusplus
extern "C" {
#endif
OH_AbilityRuntime_ConnectOptions* OH_AbilityRuntime_CreateConnectOptions(void)
{
auto connectOptions = new (std::nothrow) OH_AbilityRuntime_ConnectOptions();
if (connectOptions == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null connectOptions");
return nullptr;
}
auto state = std::make_shared<OH_AbilityRuntime_ConnectOptionsState>();
if (state == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null state");
delete connectOptions;
return nullptr;
}
state->owner = connectOptions;
connectOptions->state = state;
return connectOptions;
}
AbilityRuntime_ErrorCode OH_AbilityRuntime_DestroyConnectOptions(OH_AbilityRuntime_ConnectOptions *connectOptions)
{
auto state = GetState(connectOptions);
if (state == nullptr) {
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
{
std::lock_guard<std::mutex> guard(state->mutex);
state->alive = false;
state->owner = nullptr;
state->onConnectCallback = nullptr;
state->onDisconnectCallback = nullptr;
state->onFailedCallback = nullptr;
}
delete connectOptions;
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
AbilityRuntime_ErrorCode OH_AbilityRuntime_ConnectOptions_SetOnConnectCallback(
OH_AbilityRuntime_ConnectOptions *connectOptions,
OH_AbilityRuntime_ConnectOptions_OnConnectCallback onConnectCallback)
{
auto state = GetState(connectOptions);
if (state == nullptr || onConnectCallback == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid params");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
std::lock_guard<std::mutex> guard(state->mutex);
if (!state->alive) {
TAG_LOGE(AAFwkTag::APPKIT, "connect options already destroyed");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
state->onConnectCallback = onConnectCallback;
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
AbilityRuntime_ErrorCode OH_AbilityRuntime_ConnectOptions_SetOnDisconnectCallback(
OH_AbilityRuntime_ConnectOptions *connectOptions,
OH_AbilityRuntime_ConnectOptions_OnDisconnectCallback onDisconnectCallback)
{
auto state = GetState(connectOptions);
if (state == nullptr || onDisconnectCallback == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid params");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
std::lock_guard<std::mutex> guard(state->mutex);
if (!state->alive) {
TAG_LOGE(AAFwkTag::APPKIT, "connect options already destroyed");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
state->onDisconnectCallback = onDisconnectCallback;
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
AbilityRuntime_ErrorCode OH_AbilityRuntime_ConnectOptions_SetOnFailedCallback(
OH_AbilityRuntime_ConnectOptions *connectOptions,
OH_AbilityRuntime_ConnectOptions_OnFailedCallback onFailedCallback)
{
auto state = GetState(connectOptions);
if (state == nullptr || onFailedCallback == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid params");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
std::lock_guard<std::mutex> guard(state->mutex);
if (!state->alive) {
TAG_LOGE(AAFwkTag::APPKIT, "connect options already destroyed");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
state->onFailedCallback = onFailedCallback;
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
#ifdef __cplusplus
} // extern "C"
#endif
@@ -0,0 +1,95 @@
/*
* 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 "modular_object_ability_connection.h"
#include <unistd.h>
#include "connection_manager.h"
#include "hilog_tag_wrapper.h"
#include "modular_object_connection_manager.h"
namespace OHOS {
namespace AbilityRuntime {
namespace {
constexpr int32_t DIED = -1;
} // namespace
void ModularObjectAbilityConnection::OnAbilityConnectDone(
const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode)
{
TAG_LOGI(AAFwkTag::EXT,
"OnAbilityConnectDone, bundleName:%{public}s, abilityName:%{public}s, resultCode:%{public}d",
element.GetBundleName().c_str(), element.GetAbilityName().c_str(), resultCode);
std::vector<sptr<AbilityConnectCallback>> callbacks;
{
std::lock_guard<std::mutex> lock(modularMutex_);
callbacks = GetCallbackList();
if (callbacks.empty()) {
TAG_LOGW(AAFwkTag::EXT, "empty callbackList");
return;
}
SetRemoteObject(remoteObject);
SetResultCode(resultCode);
SetConnectionState(CONNECTION_STATE_CONNECTED);
}
sptr<ModularObjectAbilityConnection> connection(this);
if (ModularObjectConnectionManager::GetInstance().DisconnectNonexistentService(element, connection)) {
TAG_LOGW(AAFwkTag::EXT, "No need onConnect callback");
return;
}
auto item = callbacks.begin();
while (item != callbacks.end()) {
(*item)->OnAbilityConnectDone(element, remoteObject, resultCode);
item++;
}
}
void ModularObjectAbilityConnection::OnAbilityDisconnectDone(
const AppExecFwk::ElementName &element, int resultCode)
{
TAG_LOGI(AAFwkTag::EXT,
"OnAbilityDisconnectDone, bundleName:%{public}s, abilityName:%{public}s, resultCode:%{public}d",
element.GetBundleName().c_str(), element.GetAbilityName().c_str(), resultCode);
std::vector<sptr<AbilityConnectCallback>> callbacks;
{
std::lock_guard<std::mutex> lock(modularMutex_);
SetConnectionState(CONNECTION_STATE_DISCONNECTED);
callbacks = GetCallbackList();
if (callbacks.empty()) {
TAG_LOGE(AAFwkTag::EXT, "empty callbackList");
return;
}
}
// if resultCode < 0 that means the service is dead
if (resultCode == DIED) {
sptr<ModularObjectAbilityConnection> connection(this);
ModularObjectConnectionManager::GetInstance().RemoveConnection(connection);
resultCode = DIED + 1;
}
auto item = callbacks.begin();
while (item != callbacks.end()) {
(*item)->OnAbilityDisconnectDone(element, resultCode);
item++;
}
SetRemoteObject(nullptr);
}
} // namespace AbilityRuntime
} // namespace OHOS
@@ -0,0 +1,149 @@
/*
* 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 "modular_object_connection_manager.h"
#include "ability_manager_client.h"
#include "hilog_tag_wrapper.h"
#include "modular_object_ability_connection.h"
namespace OHOS {
namespace AbilityRuntime {
ModularObjectConnectionManager &ModularObjectConnectionManager::GetInstance()
{
static ModularObjectConnectionManager instance;
return instance;
}
ErrCode ModularObjectConnectionManager::ConnectModularObjectExtension(const AAFwk::Want &want,
const sptr<AbilityConnectCallback> &callback)
{
if (callback == nullptr) {
TAG_LOGE(AAFwkTag::EXT, "Invalid callback");
return ERR_INVALID_VALUE;
}
sptr<ModularObjectAbilityConnection> abilityConnection = sptr<ModularObjectAbilityConnection>::MakeSptr();
if (abilityConnection == nullptr) {
TAG_LOGE(AAFwkTag::EXT, "Failed to create connection");
return ERR_INVALID_VALUE;
}
abilityConnection->AddConnectCallback(callback);
abilityConnection->SetConnectionState(CONNECTION_STATE_CONNECTING);
ModularObjectConnectionInfo info(abilityConnection, want.GetOperation());
{
std::lock_guard<std::mutex> guard(connectionMutex_);
auto &callbacks = connectionRecords_[info];
callbacks.push_back(callback);
}
ErrCode ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbilityWithExtensionType(
want, abilityConnection, nullptr, AAFwk::DEFAULT_INVAL_VALUE,
AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT);
if (ret != ERR_OK) {
TAG_LOGE(AAFwkTag::EXT, "Connect failed: %{public}d", ret);
std::lock_guard<std::mutex> guard(connectionMutex_);
connectionRecords_.erase(info);
return ret;
}
return ERR_OK;
}
ErrCode ModularObjectConnectionManager::DisconnectModularObjectExtension(
const sptr<AbilityConnectCallback> &callback)
{
if (callback == nullptr) {
TAG_LOGE(AAFwkTag::EXT, "Invalid callback");
return ERR_INVALID_VALUE;
}
sptr<AbilityConnection> abilityConnection;
{
std::lock_guard<std::mutex> guard(connectionMutex_);
for (auto iter = connectionRecords_.begin(); iter != connectionRecords_.end(); ++iter) {
auto &callbacks = iter->second;
auto cbIter = std::find(callbacks.begin(), callbacks.end(), callback);
if (cbIter != callbacks.end()) {
abilityConnection = iter->first.abilityConnection;
callbacks.erase(cbIter);
if (callbacks.empty()) {
connectionRecords_.erase(iter);
}
break;
}
}
}
if (abilityConnection == nullptr) {
TAG_LOGE(AAFwkTag::EXT, "Connection not found");
return AAFwk::CONNECTION_NOT_EXIST;
}
ErrCode ret = AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(abilityConnection);
if (ret != ERR_OK) {
TAG_LOGE(AAFwkTag::EXT, "Disconnect failed: %{public}d", ret);
}
return ret;
}
bool ModularObjectConnectionManager::RemoveConnection(
const sptr<ModularObjectAbilityConnection> &connection)
{
std::lock_guard<std::mutex> lock(connectionMutex_);
TAG_LOGD(AAFwkTag::EXT, "connectionRecordsSize: %{public}zu", connectionRecords_.size());
bool isDisconnect = false;
auto iter = connectionRecords_.begin();
while (iter != connectionRecords_.end()) {
ModularObjectConnectionInfo connectionInfo = iter->first;
if (connectionInfo.abilityConnection == connection) {
TAG_LOGD(AAFwkTag::EXT, "Remove connection");
iter = connectionRecords_.erase(iter);
isDisconnect = true;
} else {
++iter;
}
}
return isDisconnect;
}
bool ModularObjectConnectionManager::DisconnectNonexistentService(
const AppExecFwk::ElementName &element,
const sptr<ModularObjectAbilityConnection> &connection)
{
bool exist = false;
std::map<ModularObjectConnectionInfo, std::vector<sptr<AbilityConnectCallback>>> connectionRecords;
{
std::lock_guard<std::mutex> lock(connectionMutex_);
connectionRecords = connectionRecords_;
}
TAG_LOGD(AAFwkTag::EXT, "connectionRecordsSize: %{public}zu", connectionRecords.size());
for (auto &&record : connectionRecords) {
ModularObjectConnectionInfo connectionInfo = record.first;
if (connectionInfo.abilityConnection == connection &&
connectionInfo.connectReceiver.GetBundleName() == element.GetBundleName()) {
TAG_LOGD(AAFwkTag::EXT, "find connection");
exist = true;
break;
}
}
if (!exist) {
TAG_LOGE(AAFwkTag::EXT, "ext need disconnect");
AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(connection);
return true;
}
return false;
}
} // namespace AbilityRuntime
} // namespace OHOS
@@ -0,0 +1,150 @@
/*
* 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 "modular_object_extension_ability.h"
#include "hilog_tag_wrapper.h"
#include "modular_object_extension_types.h"
namespace {
AbilityRuntime_ErrorCode CheckMoeInstance(OH_AbilityRuntime_ModObjExtensionInstanceHandle instance,
OH_AbilityRuntime_ModularObjectExtensionInstance **moeInstance)
{
if (instance == nullptr || moeInstance == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid params");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
auto *inner = reinterpret_cast<OH_AbilityRuntime_ModularObjectExtensionInstance *>(instance);
if (inner->type != OHOS::AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid extension type");
return ABILITY_RUNTIME_ERROR_CODE_INCORRECT_ABILITY_TYPE;
}
*moeInstance = inner;
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
} // namespace
#ifdef __cplusplus
extern "C" {
#endif
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionAbility_RegisterOnCreateFunc(
OH_AbilityRuntime_ModObjExtensionInstanceHandle instance,
OH_AbilityRuntime_ModObjExtensionAbility_OnCreateFunc onCreateFunc)
{
if (onCreateFunc == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null onCreateFunc");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
OH_AbilityRuntime_ModularObjectExtensionInstance *inner = nullptr;
auto ret = CheckMoeInstance(instance, &inner);
if (ret != ABILITY_RUNTIME_ERROR_CODE_NO_ERROR) {
return ret;
}
inner->onCreateFunc = onCreateFunc;
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionAbility_RegisterOnDestroyFunc(
OH_AbilityRuntime_ModObjExtensionInstanceHandle instance,
OH_AbilityRuntime_ModObjExtensionAbility_OnDestroyFunc onDestroyFunc)
{
if (onDestroyFunc == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null onDestroyFunc");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
OH_AbilityRuntime_ModularObjectExtensionInstance *inner = nullptr;
auto ret = CheckMoeInstance(instance, &inner);
if (ret != ABILITY_RUNTIME_ERROR_CODE_NO_ERROR) {
return ret;
}
inner->onDestroyFunc = onDestroyFunc;
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionAbility_RegisterOnConnectFunc(
OH_AbilityRuntime_ModObjExtensionInstanceHandle instance,
OH_AbilityRuntime_ModObjExtensionAbility_OnConnectFunc onConnectFunc)
{
if (onConnectFunc == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null onConnectFunc");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
OH_AbilityRuntime_ModularObjectExtensionInstance *inner = nullptr;
auto ret = CheckMoeInstance(instance, &inner);
if (ret != ABILITY_RUNTIME_ERROR_CODE_NO_ERROR) {
return ret;
}
inner->onConnectFunc = onConnectFunc;
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionAbility_RegisterOnDisconnectFunc(
OH_AbilityRuntime_ModObjExtensionInstanceHandle instance,
OH_AbilityRuntime_ModObjExtensionAbility_OnDisconnectFunc onDisconnectFunc)
{
if (onDisconnectFunc == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null onDisconnectFunc");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
OH_AbilityRuntime_ModularObjectExtensionInstance *inner = nullptr;
auto ret = CheckMoeInstance(instance, &inner);
if (ret != ABILITY_RUNTIME_ERROR_CODE_NO_ERROR) {
return ret;
}
inner->onDisconnectFunc = onDisconnectFunc;
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionAbility_GetContextFromInstance(
OH_AbilityRuntime_ModObjExtensionInstanceHandle instance, OH_AbilityRuntime_ModObjExtensionContextHandle *context)
{
if (context == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null context");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
OH_AbilityRuntime_ModularObjectExtensionInstance *inner = nullptr;
auto ret = CheckMoeInstance(instance, &inner);
if (ret != ABILITY_RUNTIME_ERROR_CODE_NO_ERROR) {
return ret;
}
if (inner->context == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null inner context");
return ABILITY_RUNTIME_ERROR_CODE_CONTEXT_NOT_EXIST;
}
*context = inner->context.get();
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionAbility_GetInstanceFromBase(
AbilityRuntime_ExtensionInstanceHandle baseExtensionInstance,
OH_AbilityRuntime_ModObjExtensionInstanceHandle* modObjExtensionInstance)
{
if (baseExtensionInstance == nullptr || modObjExtensionInstance == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid params");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
if (baseExtensionInstance->type != OHOS::AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid extension type");
return ABILITY_RUNTIME_ERROR_CODE_INCORRECT_ABILITY_TYPE;
}
*modObjExtensionInstance = reinterpret_cast<OH_AbilityRuntime_ModObjExtensionInstanceHandle>(baseExtensionInstance);
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
#ifdef __cplusplus
} // extern "C"
#endif
@@ -0,0 +1,143 @@
/*
* 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 "modular_object_extension_context.h"
#include "ability_business_error_utils.h"
#include "ability_manager_client.h"
#include "hilog_tag_wrapper.h"
#include "modular_object_extension_context_impl.h"
#include "modular_object_extension_types.h"
#include "start_options_impl.h"
#include "want_manager.h"
#include "want_utils.h"
using namespace OHOS;
using namespace OHOS::AAFwk;
using namespace OHOS::AbilityRuntime;
namespace {
AbilityRuntime_ErrorCode CheckMoeContext(OH_AbilityRuntime_ModObjExtensionContextHandle context,
std::shared_ptr<OHOS::AbilityRuntime::Context> &contextPtr)
{
if (context == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null context");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
if (context->type != AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid extension type");
return ABILITY_RUNTIME_ERROR_CODE_INCORRECT_ABILITY_TYPE;
}
contextPtr = context->context.lock();
if (contextPtr == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "context not exist");
return ABILITY_RUNTIME_ERROR_CODE_CONTEXT_NOT_EXIST;
}
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
AbilityRuntime_ErrorCode TransformWant(const AbilityBase_Want *want, Want &abilityWant)
{
auto ret = CheckWant(const_cast<AbilityBase_Want *>(want));
if (ret != ABILITY_RUNTIME_ERROR_CODE_NO_ERROR) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid want");
return ret;
}
auto errCode = CWantManager::TransformToWant(*want, false, abilityWant);
if (errCode != ABILITY_BASE_ERROR_CODE_NO_ERROR) {
TAG_LOGE(AAFwkTag::APPKIT, "transform want failed: %{public}d", errCode);
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
} // namespace
#ifdef __cplusplus
extern "C" {
#endif
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_GetBaseContext(
OH_AbilityRuntime_ModObjExtensionContextHandle modObjExtensionContext, AbilityRuntime_ContextHandle* baseContext)
{
if (modObjExtensionContext == nullptr || baseContext == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid params");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
if (modObjExtensionContext->type != AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid extension type");
return ABILITY_RUNTIME_ERROR_CODE_INCORRECT_ABILITY_TYPE;
}
*baseContext = static_cast<AbilityRuntime_ContextHandle>(modObjExtensionContext);
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_StartSelfUIAbility(
OH_AbilityRuntime_ModObjExtensionContextHandle context, const AbilityBase_Want *want)
{
std::shared_ptr<OHOS::AbilityRuntime::Context> contextPtr;
auto ret = CheckMoeContext(context, contextPtr);
if (ret != ABILITY_RUNTIME_ERROR_CODE_NO_ERROR) {
return ret;
}
Want abilityWant;
ret = TransformWant(want, abilityWant);
if (ret != ABILITY_RUNTIME_ERROR_CODE_NO_ERROR) {
return ret;
}
auto moeContext = std::static_pointer_cast<OHOS::AbilityRuntime::ModularObjectExtensionContext>(contextPtr);
auto err = moeContext->StartSelfUIAbility(abilityWant);
return ConvertToAPI17BusinessErrorCode(err);
}
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_StartSelfUIAbilityWithStartOptions(
OH_AbilityRuntime_ModObjExtensionContextHandle context, const AbilityBase_Want *want,
const AbilityRuntime_StartOptions *options)
{
if (options == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null options");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
std::shared_ptr<OHOS::AbilityRuntime::Context> contextPtr;
auto ret = CheckMoeContext(context, contextPtr);
if (ret != ABILITY_RUNTIME_ERROR_CODE_NO_ERROR) {
return ret;
}
Want abilityWant;
ret = TransformWant(want, abilityWant);
if (ret != ABILITY_RUNTIME_ERROR_CODE_NO_ERROR) {
return ret;
}
auto startOptions = const_cast<AbilityRuntime_StartOptions *>(options)->GetInnerStartOptions();
auto moeContext = std::static_pointer_cast<OHOS::AbilityRuntime::ModularObjectExtensionContext>(contextPtr);
auto err = moeContext->StartSelfUIAbilityWithStartOptions(abilityWant, startOptions);
return ConvertToAPI17BusinessErrorCode(err);
}
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_TerminateSelf(
OH_AbilityRuntime_ModObjExtensionContextHandle context)
{
std::shared_ptr<OHOS::AbilityRuntime::Context> contextPtr;
auto ret = CheckMoeContext(context, contextPtr);
if (ret != ABILITY_RUNTIME_ERROR_CODE_NO_ERROR) {
return ret;
}
auto moeContext = std::static_pointer_cast<OHOS::AbilityRuntime::ModularObjectExtensionContext>(contextPtr);
auto err = moeContext->TerminateSelf();
return ConvertToCommonBusinessErrorCode(err);
}
#ifdef __cplusplus
} // extern "C"
#endif
@@ -15,11 +15,24 @@
#include "ability_runtime/modular_object_extension_manager.h"
#include "modular_object_extension_manager.h"
#include <cinttypes>
#include <new>
#include <string>
#include "ability_business_error_utils.h"
#include "ability_manager_client.h"
#include "ability_manager/include/modular_object_extension_info.h"
#include "connect_options_impl.h"
#include "c_modular_object_connection_callback.h"
#include "c_modular_object_utils.h"
#include "hilog_tag_wrapper.h"
#include "want_manager.h"
#include "modular_object_connection_manager.h"
using namespace OHOS;
using namespace OHOS::AAFwk;
using namespace OHOS::AbilityRuntime;
struct OH_AbilityRuntime_AllModularObjectExtensionInfos {
std::vector<OHOS::AAFwk::ModularObjectExtensionInfo> allMoeInfos;
@@ -29,11 +42,73 @@ struct OH_AbilityRuntime_AllModularObjectExtensionInfos {
extern "C" {
#endif
AbilityRuntime_ErrorCode OH_AbilityRuntime_ConnectModularObjectExtensionAbility(AbilityBase_Want *want,
OH_AbilityRuntime_ConnectOptions *connectOptions, int64_t *connectionId)
{
TAG_LOGD(AAFwkTag::EXT, "Connect Moe");
if (connectOptions == nullptr || connectionId == nullptr) {
TAG_LOGE(AAFwkTag::EXT, "invalid params");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
if (connectOptions->state == nullptr) {
TAG_LOGE(AAFwkTag::EXT, "null connectOptions state");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
{
std::lock_guard<std::mutex> guard(connectOptions->state->mutex);
if (!connectOptions->state->alive) {
TAG_LOGE(AAFwkTag::EXT, "connect options already destroyed");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
}
Want abilityWant;
auto ret = CModularObjectUtils::TransformWant(want, abilityWant);
if (ret != ABILITY_RUNTIME_ERROR_CODE_NO_ERROR) {
return ret;
}
auto callback = sptr<CModularObjectConnectionCallback>::MakeSptr(connectOptions->state);
if (callback == nullptr) {
TAG_LOGE(AAFwkTag::EXT, "Failed to create connect callback");
return ABILITY_RUNTIME_ERROR_CODE_INTERNAL;
}
int64_t newConnectionId = CModularObjectConnectionUtils::InsertConnection(callback);
if (newConnectionId < 0) {
TAG_LOGE(AAFwkTag::EXT, "Failed to insert connection");
return ABILITY_RUNTIME_ERROR_CODE_INTERNAL;
}
int32_t innerRet = ModularObjectConnectionManager::GetInstance().ConnectModularObjectExtension(
abilityWant, callback);
if (innerRet != ERR_OK) {
CModularObjectConnectionUtils::RemoveConnectionCallback(newConnectionId);
return CModularObjectUtils::ConvertConnectBusinessErrorCode(innerRet);
}
*connectionId = newConnectionId;
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
AbilityRuntime_ErrorCode OH_AbilityRuntime_DisconnectModularObjectExtensionAbility(int64_t connectionId)
{
TAG_LOGD(AAFwkTag::EXT, "Disonnect Moe");
sptr<CModularObjectConnectionCallback> callback;
CModularObjectConnectionUtils::FindConnection(connectionId, callback);
if (callback == nullptr) {
TAG_LOGE(AAFwkTag::EXT, "Connection not found, id: %{public}" PRId64, connectionId);
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
int32_t innerRet = ModularObjectConnectionManager::GetInstance().DisconnectModularObjectExtension(callback);
return CModularObjectUtils::ConvertConnectBusinessErrorCode(innerRet);
}
AbilityRuntime_ErrorCode OH_AbilityRuntime_ReleaseAllExtensionInfos(
OH_AbilityRuntime_AllModObjExtensionInfosHandle *allExtensionInfos)
{
if (!allExtensionInfos || !*allExtensionInfos) {
TAG_LOGD(AAFwkTag::APPKIT, "null parameter");
TAG_LOGD(AAFwkTag::EXT, "null parameter");
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
}
delete *allExtensionInfos;
@@ -45,7 +120,7 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_GetModularObjectExtensionInfoLaunchMo
OH_AbilityRuntime_ModObjExtensionInfoHandle extensionInfo, OH_AbilityRuntime_LaunchMode *launchMode)
{
if (!extensionInfo || !launchMode) {
TAG_LOGE(AAFwkTag::APPKIT, "null parameter");
TAG_LOGE(AAFwkTag::EXT, "null parameter");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
auto info = reinterpret_cast<OHOS::AAFwk::ModularObjectExtensionInfo*>(extensionInfo);
@@ -57,7 +132,7 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_GetModularObjectExtensionInfoProcessM
OH_AbilityRuntime_ModObjExtensionInfoHandle extensionInfo, OH_AbilityRuntime_ProcessMode *processMode)
{
if (!extensionInfo || !processMode) {
TAG_LOGE(AAFwkTag::APPKIT, "null parameter");
TAG_LOGE(AAFwkTag::EXT, "null parameter");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
auto info = reinterpret_cast<OHOS::AAFwk::ModularObjectExtensionInfo*>(extensionInfo);
@@ -69,7 +144,7 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_GetModularObjectExtensionInfoThreadMo
OH_AbilityRuntime_ModObjExtensionInfoHandle extensionInfo, OH_AbilityRuntime_ThreadMode *threadMode)
{
if (!extensionInfo || !threadMode) {
TAG_LOGE(AAFwkTag::APPKIT, "null parameter");
TAG_LOGE(AAFwkTag::EXT, "null parameter");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
auto info = reinterpret_cast<OHOS::AAFwk::ModularObjectExtensionInfo*>(extensionInfo);
@@ -81,21 +156,21 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_GetModularObjectExtensionInfoElementN
OH_AbilityRuntime_ModObjExtensionInfoHandle extensionInfo, AbilityBase_Element *element)
{
if (!extensionInfo || !element) {
TAG_LOGE(AAFwkTag::APPKIT, "null parameter");
TAG_LOGE(AAFwkTag::EXT, "null parameter");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
auto info = reinterpret_cast<OHOS::AAFwk::ModularObjectExtensionInfo*>(extensionInfo);
char* newBundleName = strdup(info->bundleName.c_str());
if (!newBundleName) {
TAG_LOGE(AAFwkTag::APPKIT, "strdup bundleName failed");
TAG_LOGE(AAFwkTag::EXT, "strdup bundleName failed");
return ABILITY_RUNTIME_ERROR_CODE_INTERNAL;
}
char* newModuleName = strdup(info->moduleName.c_str());
if (!newModuleName) {
free(newBundleName);
TAG_LOGE(AAFwkTag::APPKIT, "strdup moduleName failed");
TAG_LOGE(AAFwkTag::EXT, "strdup moduleName failed");
return ABILITY_RUNTIME_ERROR_CODE_INTERNAL;
}
@@ -103,7 +178,7 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_GetModularObjectExtensionInfoElementN
if (!newAbilityName) {
free(newBundleName);
free(newModuleName);
TAG_LOGE(AAFwkTag::APPKIT, "strdup abilityName failed");
TAG_LOGE(AAFwkTag::EXT, "strdup abilityName failed");
return ABILITY_RUNTIME_ERROR_CODE_INTERNAL;
}
@@ -117,7 +192,7 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_GetModularObjectExtensionInfoDisableS
OH_AbilityRuntime_ModObjExtensionInfoHandle extensionInfo, bool *isDisabled)
{
if (!extensionInfo || !isDisabled) {
TAG_LOGE(AAFwkTag::APPKIT, "null parameter");
TAG_LOGE(AAFwkTag::EXT, "null parameter");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
auto info = reinterpret_cast<OHOS::AAFwk::ModularObjectExtensionInfo*>(extensionInfo);
@@ -129,7 +204,7 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_AcquireSelfModularObjectExtensionInfo
OH_AbilityRuntime_AllModObjExtensionInfosHandle *outOwnedAllExtensionInfos)
{
if (!outOwnedAllExtensionInfos) {
TAG_LOGE(AAFwkTag::APPKIT, "null parameter");
TAG_LOGE(AAFwkTag::EXT, "null parameter");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
@@ -138,7 +213,7 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_AcquireSelfModularObjectExtensionInfo
std::vector<OHOS::AAFwk::ModularObjectExtensionInfo> dataList;
auto ret = OHOS::AAFwk::AbilityManagerClient::GetInstance()->QuerySelfModularObjectExtensionInfos(dataList);
if (ret != OHOS::ERR_OK) {
TAG_LOGE(AAFwkTag::APPKIT, "get modular object extension info inner error: %{public}d", ret);
TAG_LOGE(AAFwkTag::EXT, "get modular object extension info inner error: %{public}d", ret);
return ConvertToCommonBusinessErrorCode(ret);
}
infos->allMoeInfos = dataList;
@@ -150,7 +225,7 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_GetCountFromAllModObjExtensionInfos(
OH_AbilityRuntime_AllModObjExtensionInfosHandle allExtensionInfos, size_t *count)
{
if (!allExtensionInfos || !count) {
TAG_LOGE(AAFwkTag::APPKIT, "null parameter");
TAG_LOGE(AAFwkTag::EXT, "null parameter");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
*count = allExtensionInfos->allMoeInfos.size();
@@ -162,17 +237,17 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_GetModObjExtensionInfoByIndex(
OH_AbilityRuntime_ModObjExtensionInfoHandle *extensionInfo)
{
if (!allExtensionInfos || !extensionInfo) {
TAG_LOGE(AAFwkTag::APPKIT, "null parameter");
TAG_LOGE(AAFwkTag::EXT, "null parameter");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
if (index >= allExtensionInfos->allMoeInfos.size()) {
TAG_LOGE(AAFwkTag::APPKIT, "index out of range");
TAG_LOGE(AAFwkTag::EXT, "index out of range");
return ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID;
}
*extensionInfo =
reinterpret_cast<OH_AbilityRuntime_ModObjExtensionInfoHandle>(&(allExtensionInfos->allMoeInfos[index]));
if (*extensionInfo == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "Failed to get extension info for index %zu", index);
TAG_LOGE(AAFwkTag::EXT, "Failed to get extension info for index %zu", index);
return ABILITY_RUNTIME_ERROR_CODE_INTERNAL;
}
return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR;
@@ -295,7 +295,7 @@ void BindNativeFunction(ani_env *aniEnv)
ani_native_function {"nativeCreateSystemHspModuleResourceManager", "C{std.core.String}C{std.core.String}"
":C{@ohos.resourceManager.resourceManager.ResourceManager}",
reinterpret_cast<void *>(ContextUtil::NativeCreateSystemHspModuleResourceManager)},
ani_native_function {"nativeContextType",
ani_native_function {"nativeIsContextOf",
"C{@ohos.app.ability.contextConstant.contextConstant.ContextType}:z",
reinterpret_cast<void *>(ContextUtil::ContextType)},
};
@@ -134,12 +134,12 @@ public:
EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_MAIN_THREAD);
return result;
}
if (IsRefUndefined(env, function)) {
if (IsNull(env, function)) {
TAG_LOGE(AAFwkTag::JSNAPI, "invalid func");
EtsErrorUtil::ThrowInvalidNumParametersError(env);
return result;
}
if (IsNull(env, function)) {
if (IsRefUndefined(env, function)) {
function = nullptr;
}
std::lock_guard<std::mutex> lock(g_defaultHandlerMtx);
@@ -362,7 +362,7 @@ public:
return result;
}
if (function == nullptr) {
if (IsRefUndefined(env, function)) {
env->GlobalReference_Delete(g_freezeObserver.ref);
g_freezeObserver.ref = nullptr;
g_freezeObserver = {};
@@ -373,7 +373,9 @@ public:
}
return result;
}
if (!ValidateFunction(env, function)) {
if (IsNull(env, function)) {
TAG_LOGE(AAFwkTag::JSNAPI, "invalid func");
EtsErrorUtil::ThrowInvalidNumParametersError(env);
return result;
}
ani_object observer = static_cast<ani_object>(g_freezeObserver.ref);
@@ -427,7 +429,7 @@ public:
{
ani_object result{};
std::lock_guard<std::mutex> lock(g_unhandledRejectionMtx);
if (function == nullptr) {
if (IsRefUndefined(env, function)) {
for (auto& iter : g_unhandledRejectionObservers) {
env->GlobalReference_Delete(iter);
}
@@ -435,7 +437,9 @@ public:
return result;
}
if (!ValidateFunction(env, function)) {
if (IsNull(env, function)) {
TAG_LOGE(AAFwkTag::JSNAPI, "invalid func");
EtsErrorUtil::ThrowInvalidNumParametersError(env);
return result;
}
+3 -3
View File
@@ -86,7 +86,7 @@ export default class Context extends BaseContext {
destroyRegister.unregister(unregisterToken);
}
public native nativeContextType(contextType: contextConstant.ContextType): boolean;
public native nativeIsContextOf(contextType: contextConstant.ContextType): boolean;
public native getApplicationContextSync(): ApplicationContext;
public native createModuleResourceManagerSync(bundleName: string, moduleName: string): resmgr.ResourceManager;
@@ -144,8 +144,8 @@ export default class Context extends BaseContext {
});
}
contextType(contextType: contextConstant.ContextType): boolean {
return this.nativeContextType(contextType);
isContextOf(contextType: contextConstant.ContextType): boolean {
return this.nativeIsContextOf(contextType);
}
createDisplayContext(displayId: long): Context {
@@ -226,7 +226,7 @@ class ApplicationContext {
this.__context_impl__.eventHub = eventHub;
}
contextType(contextType) {
isContextOf(contextType) {
if (typeof (contextType) !== 'number') {
return false;
}
+1 -1
View File
@@ -230,7 +230,7 @@ class Context {
this.__context_impl__.eventHub = eventHub;
}
contextType(contextType) {
isContextOf(contextType) {
if (typeof (contextType) !== 'number') {
return false;
}
@@ -1016,10 +1016,15 @@ private:
ThrowError(env, AbilityErrorCode::ERROR_CODE_MAIN_THREAD);
return CreateJsUndefined(env);
}
if (CheckTypeForNapiValue(env, function, napi_null) ||CheckTypeForNapiValue(env, function, napi_undefined)) {
if (CheckTypeForNapiValue(env, function, napi_null)) {
TAG_LOGE(AAFwkTag::JSNAPI, "null function.");
ThrowInvalidNumParametersError(env);
return CreateJsUndefined(env);
}
if (CheckTypeForNapiValue(env, function, napi_undefined)) {
TAG_LOGI(AAFwkTag::JSNAPI, "Get defaultHandler undefined");
function = nullptr;
}
std::lock_guard<std::mutex> lock(defaultHandlerMtx);
napi_value object = nullptr;
if (defaultHandler.ref == nullptr) {
@@ -1052,10 +1057,10 @@ private:
return CreateJsUndefined(env);
}
if (CheckTypeForNapiValue(env, function, napi_null) || CheckTypeForNapiValue(env, function, napi_undefined)) {
TAG_LOGE(AAFwkTag::JSNAPI, "CheckTypeForNapiValue failed");
ThrowInvalidNumParametersError(env);
return CreateJsUndefined(env);
if (CheckTypeForNapiValue(env, function, napi_undefined) ||
CheckTypeForNapiValue(env, function, napi_null)) {
TAG_LOGW(AAFwkTag::JSNAPI, "null or undefined function.");
function = nullptr;
}
std::lock_guard<std::mutex> lock(defaultLeakMtx);
napi_value oldObserverFunc = nullptr;
@@ -1462,7 +1467,7 @@ private:
return res;
}
if (function == nullptr) {
if (function == nullptr || CheckTypeForNapiValue(env, function, napi_undefined)) {
NAPI_CALL(env, napi_delete_reference(env, freezeObserver.ref));
freezeObserver = {};
if (freezeCallbackRegistered) {
@@ -1472,8 +1477,10 @@ private:
}
return res;
}
if (!ValidateFunction(env, function)) {
return nullptr;
if (CheckTypeForNapiValue(env, function, napi_null)) {
TAG_LOGE(AAFwkTag::JSNAPI, "null function.");
ThrowInvalidNumParametersError(env);
return CreateJsUndefined(env);
}
napi_value observer = nullptr;
NAPI_CALL(env, napi_get_reference_value(env, freezeObserver.ref, &observer));
@@ -1583,8 +1590,10 @@ private:
return res;
}
napi_value function = argv[INDEX_ONE];
if (!ValidateFunction(env, function)) {
return res;
if (function == nullptr || CheckTypeForNapiValue(env, function, napi_null)) {
TAG_LOGE(AAFwkTag::JSNAPI, "null function.");
ThrowInvalidNumParametersError(env);
return CreateJsUndefined(env);
}
for (auto& iter : unhandledRejectionObservers) {
napi_value observer = nullptr;
+122
View File
@@ -2382,6 +2382,7 @@ group("extension_module") {
":embedded_ui_extension_module",
":service_extension_module",
":ui_extension_module",
":modular_object_extension_module",
]
if (ability_runtime_action_extension) {
deps += [ ":action_extension_module" ]
@@ -3899,3 +3900,124 @@ ohos_shared_library("app_service_extension_module") {
subsystem_name = "ability"
part_name = "ability_runtime"
}
config("modular_object_extension_config") {
visibility = [ ":*" ]
include_dirs = [
"${ability_runtime_path}/interfaces/inner_api",
"${ability_runtime_path}/interfaces/inner_api/runtime/include",
"${ability_runtime_path}/interfaces/kits/native/ability/native/modular_object_extension",
"${ability_runtime_path}/interfaces/kits/native/ability/native",
"${ability_runtime_path}/interfaces/kits/native/ability/ability_runtime",
"${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context",
"${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime",
"${ability_runtime_ndk_path}",
"${ability_runtime_ndk_path}/ability_runtime",
"${ability_runtime_path}/frameworks/c/ability_runtime/include",
]
}
ohos_shared_library("modular_object_extension") {
sanitize = {
integer_overflow = true
ubsan = true
boundary_sanitize = true
cfi = true
cfi_cross_dso = true
cfi_vcall_icall_only = true
debug = false
}
branch_protector_ret = "pac_ret"
configs = [
":modular_object_extension_config",
"${ability_runtime_services_path}/common:optimize_config",
]
defines = [ "AMS_LOG_TAG = \"Ability\"" ]
defines += [ "AMS_LOG_DOMAIN = 0xD001300" ]
sources = [
"${ability_runtime_native_path}/ability/native/modular_object_extension/modular_object_extension.cpp",
"${ability_runtime_native_path}/ability/native/modular_object_extension/modular_object_extension_context_impl.cpp",
]
deps = [
":abilitykit_native",
":abilitykit_utils",
":extensionkit_native",
"${ability_runtime_innerkits_path}/ability_manager:ability_connect_callback_stub",
"${ability_runtime_innerkits_path}/ability_manager:ability_manager",
"${ability_runtime_innerkits_path}/ability_manager:ability_start_options",
"${ability_runtime_innerkits_path}/runtime:runtime",
"${ability_runtime_native_path}/ability:ability_context_native",
"${ability_runtime_native_path}/ability/native:ability_business_error",
"${ability_runtime_native_path}/appkit:app_context",
]
external_deps = [
"ability_base:ability_base_want",
"ability_base:configuration",
"ability_base:want",
"c_utils:utils",
"eventhandler:libeventhandler",
"hilog:libhilog",
"hitrace:hitrace_meter",
"ipc:ipc_capi",
"ipc:ipc_core",
"ipc:ipc_napi",
"napi:ace_napi",
]
innerapi_tags = [ "platformsdk" ]
subsystem_name = "ability"
part_name = "ability_runtime"
}
ohos_shared_library("modular_object_extension_module") {
sanitize = {
integer_overflow = true
ubsan = true
boundary_sanitize = true
cfi = true
cfi_cross_dso = true
cfi_vcall_icall_only = true
debug = false
}
branch_protector_ret = "pac_ret"
sources = [ "${ability_runtime_native_path}/ability/native/modular_object_extension/modular_object_extension_module_loader.cpp" ]
configs = [
":modular_object_extension_config",
"${ability_runtime_services_path}/common:optimize_config",
]
deps = [
":modular_object_extension",
"${ability_runtime_innerkits_path}/runtime:runtime",
]
external_deps = [
"ability_base:configuration",
"ability_base:session_info",
"bundle_framework:appexecfwk_base",
"bundle_framework:appexecfwk_core",
"c_utils:utils",
"eventhandler:libeventhandler",
"hilog:libhilog",
"ipc:ipc_capi",
"ipc:ipc_core",
"ipc:ipc_napi",
"json:nlohmann_json_static",
"napi:ace_napi",
]
if (ability_runtime_graphics) {
external_deps += [ "window_manager:libwm" ]
}
relative_install_dir = "extensionability/"
subsystem_name = "ability"
part_name = "ability_runtime"
}
@@ -63,6 +63,7 @@ constexpr static char CALLER_INFO_QUERY_EXTENSION[] = "CallerInfoQueryExtension"
constexpr static char ASSET_ACCELERATION_EXTENSION[] = "AssetAccelerationExtension";
constexpr static char SELECTION_EXTENSION[] = "SelectionExtensionAbility";
constexpr static char CONTENT_EMBED_EXTENSION[] = "ContentEmbedExtension";
constexpr static char MODULAR_OBJECT_EXTENSION[] = "ModularObjectExtension";
}
const std::map<AppExecFwk::ExtensionAbilityType, std::string> UI_EXTENSION_NAME_MAP = {
@@ -183,6 +184,8 @@ void ExtensionAbilityThread::CreateExtensionAbilityName(
#endif // SUPPORT_GRAPHICS
else if (abilityInfo->extensionAbilityType == AppExecFwk::ExtensionAbilityType::CONTENT_EMBED) {
abilityName = CONTENT_EMBED_EXTENSION;
} else if (abilityInfo->extensionAbilityType == AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT) {
abilityName = MODULAR_OBJECT_EXTENSION;
}
}
@@ -0,0 +1,203 @@
/*
* 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 "modular_object_extension.h"
#include <new>
#include "hilog_tag_wrapper.h"
#include "ipc_inner_object.h"
#include "native_runtime.h"
#include "securec.h"
#include "want_manager.h"
namespace OHOS {
namespace AbilityRuntime {
namespace {
constexpr char PATH_SEPARATOR = '/';
}
ModularObjectExtension* ModularObjectExtension::Create()
{
return new ModularObjectExtension();
}
void ModularObjectExtension::Init(const std::shared_ptr<AbilityLocalRecord> &record,
const std::shared_ptr<OHOSApplication> &application,
std::shared_ptr<AbilityHandler> &handler,
const sptr<IRemoteObject> &token)
{
ExtensionBase<ModularObjectExtensionContext>::Init(record, application, handler, token);
moeInstance_ = std::make_shared<OH_AbilityRuntime_ModularObjectExtensionInstance>();
moeInstance_->type = AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT;
moeInstance_->extension = weak_from_this();
moeContext_ = std::make_shared<OH_AbilityRuntime_ModularObjectExtensionContext>();
if (moeContext_ == nullptr) {
TAG_LOGE(AAFwkTag::EXT, "failed to create modular object extension context");
return;
}
moeContext_->type = AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT;
auto context = GetContext();
if (context != nullptr) {
moeContext_->context = context->weak_from_this();
}
moeInstance_->context = moeContext_;
if (!LoadNativeExtensionModule()) {
TAG_LOGE(AAFwkTag::EXT, "failed to load modular object native extension module");
}
}
std::shared_ptr<ModularObjectExtensionContext> ModularObjectExtension::CreateAndInitContext(
const std::shared_ptr<AbilityLocalRecord> &record,
const std::shared_ptr<OHOSApplication> &application,
std::shared_ptr<AbilityHandler> &handler,
const sptr<IRemoteObject> &token)
{
return ExtensionBase<ModularObjectExtensionContext>::CreateAndInitContext(record, application, handler, token);
}
void ModularObjectExtension::OnStart(const AAFwk::Want &want)
{
if (moeInstance_ == nullptr || moeInstance_->onCreateFunc == nullptr) {
return;
}
AbilityBase_Want cWant;
AbilityBase_Element element;
if (!BuildCWant(want, cWant, element)) {
TAG_LOGE(AAFwkTag::EXT, "failed to build c want for OnStart");
return;
}
moeInstance_->onCreateFunc(moeInstance_.get(), &cWant);
DestroyElement(element);
}
void ModularObjectExtension::OnStop()
{
if (moeInstance_ != nullptr && moeInstance_->onDestroyFunc != nullptr) {
moeInstance_->onDestroyFunc(moeInstance_.get());
}
}
sptr<IRemoteObject> ModularObjectExtension::OnConnect(const AAFwk::Want &want)
{
Extension::OnConnect(want);
if (moeInstance_ == nullptr || moeInstance_->onConnectFunc == nullptr) {
return nullptr;
}
AbilityBase_Want cWant;
AbilityBase_Element element;
if (!BuildCWant(want, cWant, element)) {
TAG_LOGE(AAFwkTag::EXT, "failed to build c want for OnConnect");
return nullptr;
}
OHIPCRemoteStub *stub = moeInstance_->onConnectFunc(moeInstance_.get(), &cWant);
DestroyElement(element);
if (stub == nullptr || stub->remote == nullptr) {
TAG_LOGE(AAFwkTag::EXT, "invalid remote stub returned from OnConnect callback");
return nullptr;
}
return stub->remote;
}
void ModularObjectExtension::OnDisconnect(const AAFwk::Want &want)
{
Extension::OnDisconnect(want);
if (moeInstance_ != nullptr && moeInstance_->onDisconnectFunc != nullptr) {
moeInstance_->onDisconnectFunc(moeInstance_.get());
}
}
bool ModularObjectExtension::LoadNativeExtensionModule()
{
if (moeInstance_ == nullptr || abilityInfo_ == nullptr) {
return false;
}
if (abilityInfo_->srcEntrance.empty()) {
TAG_LOGE(AAFwkTag::EXT, "srcEntrance is empty");
return false;
}
std::string srcPath = abilityInfo_->moduleName + PATH_SEPARATOR + abilityInfo_->srcEntrance;
std::string bundleModuleName = abilityInfo_->bundleName + PATH_SEPARATOR + abilityInfo_->moduleName;
size_t pos = srcPath.find_last_of(PATH_SEPARATOR);
std::string fileName = pos == std::string::npos ? srcPath : srcPath.substr(pos + 1);
return NativeRuntime::LoadModule(bundleModuleName, fileName, abilityInfo_->name, *moeInstance_);
}
bool ModularObjectExtension::BuildCWant(const AAFwk::Want &want, AbilityBase_Want &cWant,
AbilityBase_Element &element) const
{
auto ret = AAFwk::CWantManager::TransformToCWantWithoutElement(want, false, cWant);
if (ret != ABILITY_BASE_ERROR_CODE_NO_ERROR) {
return false;
}
element.bundleName = nullptr;
element.moduleName = nullptr;
element.abilityName = nullptr;
if (!BuildElement(want.GetElement(), element)) {
return false;
}
cWant.element = element;
return true;
}
bool ModularObjectExtension::BuildElement(const AppExecFwk::ElementName &elementName, AbilityBase_Element &element)
{
auto copyField = [](const std::string &src, char *&dst) -> bool {
dst = new (std::nothrow) char[src.size() + 1];
if (dst == nullptr) {
return false;
}
if (strcpy_s(dst, src.size() + 1, src.c_str()) != EOK) {
delete[] dst;
dst = nullptr;
return false;
}
return true;
};
if (!copyField(elementName.GetBundleName(), element.bundleName)) {
return false;
}
if (!copyField(elementName.GetModuleName(), element.moduleName)) {
delete[] element.bundleName;
element.bundleName = nullptr;
return false;
}
if (!copyField(elementName.GetAbilityName(), element.abilityName)) {
delete[] element.bundleName;
delete[] element.moduleName;
element.bundleName = nullptr;
element.moduleName = nullptr;
return false;
}
return true;
}
void ModularObjectExtension::DestroyElement(AbilityBase_Element &element)
{
delete[] element.bundleName;
delete[] element.moduleName;
delete[] element.abilityName;
element.bundleName = nullptr;
element.moduleName = nullptr;
element.abilityName = nullptr;
}
} // namespace AbilityRuntime
} // namespace OHOS
@@ -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.
*/
#include "modular_object_extension_context_impl.h"
#include "ability_manager_client.h"
#include "hilog_tag_wrapper.h"
#include "hitrace_meter.h"
namespace OHOS {
namespace AbilityRuntime {
const size_t ModularObjectExtensionContext::CONTEXT_TYPE_ID(
std::hash<const char*> {} ("ModularObjectExtensionContext"));
ErrCode ModularObjectExtensionContext::StartSelfUIAbility(const AAFwk::Want &want) const
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
return AAFwk::AbilityManagerClient::GetInstance()->StartSelfUIAbility(want);
}
ErrCode ModularObjectExtensionContext::StartSelfUIAbilityWithStartOptions(const AAFwk::Want &want,
const AAFwk::StartOptions &startOptions) const
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
return AAFwk::AbilityManagerClient::GetInstance()->StartSelfUIAbilityWithStartOptions(want, startOptions);
}
ErrCode ModularObjectExtensionContext::TerminateSelf()
{
return AAFwk::AbilityManagerClient::GetInstance()->TerminateAbility(token_, -1, nullptr);
}
} // namespace AbilityRuntime
} // namespace OHOS
@@ -0,0 +1,43 @@
/*
* 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 "modular_object_extension_module_loader.h"
#include <string>
#include "modular_object_extension.h"
namespace OHOS::AbilityRuntime {
ModularObjectExtensionModuleLoader::ModularObjectExtensionModuleLoader() = default;
ModularObjectExtensionModuleLoader::~ModularObjectExtensionModuleLoader() = default;
Extension *ModularObjectExtensionModuleLoader::Create(const std::unique_ptr<Runtime> &runtime) const
{
return ModularObjectExtension::Create();
}
std::map<std::string, std::string> ModularObjectExtensionModuleLoader::GetParams()
{
std::map<std::string, std::string> params;
params.insert(std::pair<std::string, std::string>("type", "39"));
params.insert(std::pair<std::string, std::string>("name", "modularObject"));
return params;
}
extern "C" __attribute__((visibility("default"))) void* OHOS_EXTENSION_GetExtensionModule()
{
return &ModularObjectExtensionModuleLoader::GetInstance();
}
} // namespace OHOS::AbilityRuntime
@@ -49,6 +49,11 @@ void GetHapSoPath(const HapModuleInfo &hapInfo, AppLibPathMap &appLibPaths, bool
TAG_LOGD(
AAFwkTag::APPKIT, "appLibPathKey: %{private}s, lib path: %{private}s", appLibPathKey.c_str(), libPath.c_str());
appLibPaths[appLibPathKey].emplace_back(libPath);
for (const auto &dir : hapInfo.librarySupportDirectory) {
std::string supportLibPath = libPath + "/" + dir;
TAG_LOGD(AAFwkTag::APPKIT, "supportLibPath: %{public}s", supportLibPath.c_str());
appLibPaths[appLibPathKey].emplace_back(supportLibPath);
}
}
void GetHspNativeLibPath(const BaseSharedBundleInfo &hspInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp)
@@ -109,6 +114,11 @@ void GetPatchNativeLibPath(const HapModuleInfo &hapInfo, std::string &patchNativ
TAG_LOGD(AAFwkTag::APPKIT, "appLibPathKey: %{public}s, patch lib path: %{private}s", appLibPathKey.c_str(),
patchLibPath.c_str());
appLibPaths[appLibPathKey].emplace_back(patchLibPath);
for (const auto &dir : hapInfo.librarySupportDirectory) {
std::string supportLibPath = patchLibPath + "/" + dir;
TAG_LOGD(AAFwkTag::APPKIT, "supportLibPath: %{public}s", supportLibPath.c_str());
appLibPaths[appLibPathKey].emplace_back(supportLibPath);
}
}
void GetLibrarySupportDirectory(
@@ -53,6 +53,11 @@ void GetEtsHapSoPath(const HapModuleInfo &hapInfo, AppLibPathMap &appLibPaths, b
TAG_LOGD(
AAFwkTag::APPKIT, "appLibPathKey: %{private}s, lib path: %{private}s", appLibPathKey.c_str(), libPath.c_str());
appLibPaths[appLibPathKey].emplace_back(libPath);
for (const auto &dir : hapInfo.librarySupportDirectory) {
std::string supportLibPath = libPath + "/" + dir;
TAG_LOGD(AAFwkTag::APPKIT, "supportLibPath: %{public}s", supportLibPath.c_str());
appLibPaths[appLibPathKey].emplace_back(supportLibPath);
}
std::string appLibAbcPathKey = APP_ABC_LIB_PATH_KEY_PREFIX + hapInfo.moduleName + APP_ABC_LIB_PATH_KEY_SUFFIX;
abcPathsToBundleModuleNameMap[appLibAbcPathKey] = appLibPathKey;
@@ -123,6 +128,11 @@ void GetEtsPatchNativeLibPath(const HapModuleInfo &hapInfo, std::string &patchNa
TAG_LOGD(AAFwkTag::APPKIT, "appLibPathKey: %{public}s, patch lib path: %{private}s", appLibPathKey.c_str(),
patchLibPath.c_str());
appLibPaths[appLibPathKey].emplace_back(patchLibPath);
for (const auto &dir : hapInfo.librarySupportDirectory) {
std::string supportLibPath = patchLibPath + "/" + dir;
TAG_LOGD(AAFwkTag::APPKIT, "supportLibPath: %{public}s", supportLibPath.c_str());
appLibPaths[appLibPathKey].emplace_back(supportLibPath);
}
std::string appLibAbcPathKey = APP_ABC_LIB_PATH_KEY_PREFIX + hapInfo.moduleName + APP_ABC_LIB_PATH_KEY_SUFFIX;
abcPathsToBundleModuleNameMap[appLibAbcPathKey] = appLibPathKey;
}
@@ -1138,6 +1138,10 @@ enum {
*/
ERR_NOT_SUPPORT_SCREEN = 2099411,
ERR_MODULAR_OBJECT_DISABLED = 2099412,
ERR_NO_RUNNING_ABILITIES_WITH_UI = 2099413,
/**
* Native error(3000000) for target bundle not exist.
*/
@@ -294,6 +294,18 @@ public:
*/
virtual AppMgrResultCode GetProcessRunningInfosByUserId(std::vector<RunningProcessInfo> &info, int32_t userId);
/**
* GetProcessRunningInfosByAccessTokenId, call GetProcessRunningInfosByAccessTokenId()
* through proxy project. Obtains information about application processes that are
* running on the device by accessTokenId.
*
* @param accessTokenId, accessTokenId.
* @param info, Running process information list.
* @return ERR_OK ,return back successothers fail.
*/
virtual AppMgrResultCode GetProcessRunningInfosByAccessTokenId(uint32_t accessTokenId,
std::vector<RunningProcessInfo> &info);
/**
* GetProcessRunningInformation, call GetProcessRunningInformation() through proxy project.
* Obtains information about current application processes which is running on the device.
@@ -280,6 +280,18 @@ public:
*/
virtual int GetProcessRunningInfosByUserId(std::vector<RunningProcessInfo> &info, int32_t userId) = 0;
/**
* GetProcessRunningInfosByAccessTokenId, call GetProcessRunningInfosByAccessTokenId()
* through proxy project. Obtains information about application processes
* that are running on the device by accessTokenId.
*
* @param accessTokenId, accessTokenId.
* @param info, Running process information list.
* @return ERR_OK ,return back successothers fail.
*/
virtual int32_t GetProcessRunningInfosByAccessTokenId(uint32_t accessTokenId,
std::vector<RunningProcessInfo> &info) = 0;
/**
* GetProcessRunningInformation, call GetProcessRunningInformation() through proxy project.
* Obtains information about current application process which is running on the device.
@@ -155,7 +155,8 @@ enum class AppMgrInterfaceCode {
GET_ALL_ABILITY_INFOS = 130,
DUMP_MEM_PROCESS = 131,
UPDATE_FREEZE_EXCLUDED_PID = 132,
SET_TERMINATE_TIMEOUT_FLAG = 133
GET_PROCESS_RUNNING_INFOS_BY_ACCESS_TOKEN_ID = 133,
SET_TERMINATE_TIMEOUT_FLAG = 134
};
} // AppExecFwk
} // OHOS
@@ -218,6 +218,18 @@ public:
*/
virtual int32_t GetProcessRunningInfosByUserId(std::vector<RunningProcessInfo> &info, int32_t userId) override;
/**
* GetProcessRunningInfosByAccessTokenId, call GetProcessRunningInfosByAccessTokenId()
* through proxy project. Obtains information about application processes
* that are running on the device by accessTokenId.
*
* @param accessTokenId, accessTokenId.
* @param info, Running process information list.
* @return ERR_OK ,return back successothers fail.
*/
virtual int32_t GetProcessRunningInfosByAccessTokenId(uint32_t accessTokenId,
std::vector<RunningProcessInfo> &info) override;
/**
* GetProcessRunningInformation, call GetProcessRunningInformation() through proxy project.
* Obtains information about current application process which is running on the device.
@@ -76,6 +76,7 @@ private:
int32_t HandleGetAllRunningProcesses(MessageParcel &data, MessageParcel &reply);
int32_t HandleGetRunningProcessesByBundleType(MessageParcel &data, MessageParcel &reply);
int32_t HandleGetProcessRunningInfosByUserId(MessageParcel &data, MessageParcel &reply);
int32_t HandleGetProcessRunningInfosByAccessTokenId(MessageParcel &data, MessageParcel &reply);
int32_t HandleGetProcessRunningInformation(MessageParcel &data, MessageParcel &reply);
int32_t HandleGetAllRenderProcesses(MessageParcel &data, MessageParcel &reply);
int32_t HandlePreloadModuleFinished(MessageParcel &data, MessageParcel &reply);
@@ -65,6 +65,7 @@ struct RunningProcessInfo : public Parcelable {
bool isPreload = false;
std::int32_t pid_;
std::int32_t uid_;
std::uint32_t accessTokenId_ = 0;
std::int32_t bundleType = 0;
std::int32_t appCloneIndex = -1;
std::int32_t rssValue = 0;
@@ -531,6 +531,20 @@ AppMgrResultCode AppMgrClient::GetProcessRunningInfosByUserId(std::vector<Runnin
return AppMgrResultCode::ERROR_SERVICE_NOT_CONNECTED;
}
AppMgrResultCode AppMgrClient::GetProcessRunningInfosByAccessTokenId(uint32_t accessTokenId,
std::vector<RunningProcessInfo> &info)
{
sptr<IAppMgr> service = iface_cast<IAppMgr>(mgrHolder_->GetRemoteObject());
if (service != nullptr) {
int32_t result = service->GetProcessRunningInfosByAccessTokenId(accessTokenId, info);
if (result == ERR_OK) {
return AppMgrResultCode::RESULT_OK;
}
return AppMgrResultCode::ERROR_SERVICE_NOT_READY;
}
return AppMgrResultCode::ERROR_SERVICE_NOT_CONNECTED;
}
AppMgrResultCode AppMgrClient::GetProcessRunningInformation(AppExecFwk::RunningProcessInfo &info)
{
sptr<IAppMgr> service = iface_cast<IAppMgr>(mgrHolder_->GetRemoteObject());
@@ -448,6 +448,30 @@ int32_t AppMgrProxy::GetProcessRunningInfosByUserId(std::vector<RunningProcessIn
return result;
}
int32_t AppMgrProxy::GetProcessRunningInfosByAccessTokenId(uint32_t accessTokenId,
std::vector<RunningProcessInfo> &info)
{
MessageParcel data;
MessageParcel reply;
MessageOption option(MessageOption::TF_SYNC);
if (!WriteInterfaceToken(data)) {
return ERR_FLATTEN_OBJECT;
}
PARCEL_UTIL_WRITE_RET_INT(data, Uint32, accessTokenId);
if (!SendTransactCmd(AppMgrInterfaceCode::GET_PROCESS_RUNNING_INFOS_BY_ACCESS_TOKEN_ID, data, reply)) {
return ERR_NULL_OBJECT;
}
auto error = GetParcelableInfos<RunningProcessInfo>(reply, info);
if (error != NO_ERROR) {
TAG_LOGE(AAFwkTag::APPMGR, "GetParcelableInfos fail, error: %{public}d", error);
return error;
}
int result = reply.ReadInt32();
return result;
}
int32_t AppMgrProxy::GetProcessRunningInformation(RunningProcessInfo &info)
{
MessageParcel data;
@@ -43,6 +43,7 @@ namespace AppExecFwk {
constexpr int32_t CYCLE_LIMIT = 1000;
constexpr int32_t MAX_PROCESS_STATE_COUNT = 1000;
constexpr int32_t MAX_BACKGROUND_APP_COUNT = 1000;
constexpr int32_t MAX_PROCESS_INFO_COUNT = 1024;
AppMgrStub::AppMgrStub() {}
@@ -133,6 +134,8 @@ int32_t AppMgrStub::OnRemoteRequestInnerFirst(uint32_t code, MessageParcel &data
return HandleNotifyProcMemoryLevel(data, reply);
case static_cast<uint32_t>(AppMgrInterfaceCode::APP_GET_RUNNING_PROCESSES_BY_USER_ID):
return HandleGetProcessRunningInfosByUserId(data, reply);
case static_cast<uint32_t>(AppMgrInterfaceCode::GET_PROCESS_RUNNING_INFOS_BY_ACCESS_TOKEN_ID):
return HandleGetProcessRunningInfosByAccessTokenId(data, reply);
case static_cast<uint32_t>(AppMgrInterfaceCode::APP_ADD_ABILITY_STAGE_INFO_DONE):
return HandleAddAbilityStageDone(data, reply);
case static_cast<uint32_t>(AppMgrInterfaceCode::STARTUP_RESIDENT_PROCESS):
@@ -736,6 +739,26 @@ int32_t AppMgrStub::HandleGetProcessRunningInfosByUserId(MessageParcel &data, Me
return NO_ERROR;
}
int32_t AppMgrStub::HandleGetProcessRunningInfosByAccessTokenId(MessageParcel &data, MessageParcel &reply)
{
HITRACE_METER(HITRACE_TAG_APP);
uint32_t accessTokenId = data.ReadUint32();
std::vector<RunningProcessInfo> info;
auto result = GetProcessRunningInfosByAccessTokenId(accessTokenId, info);
int32_t writeSize = std::min(static_cast<int32_t>(info.size()), MAX_PROCESS_INFO_COUNT);
reply.WriteInt32(writeSize);
for (int32_t i = 0; i < writeSize; ++i) {
if (!reply.WriteParcelable(&info[i])) {
return ERR_INVALID_VALUE;
}
}
if (!reply.WriteInt32(result)) {
return ERR_INVALID_VALUE;
}
TAG_LOGD(AAFwkTag::APPMGR, "AppMgrStub::HandleGetProcessRunningInfosByAccessTokenId end");
return NO_ERROR;
}
int32_t AppMgrStub::HandleGetAllRenderProcesses(MessageParcel &data, MessageParcel &reply)
{
HITRACE_METER(HITRACE_TAG_APP);
@@ -38,6 +38,9 @@ bool RunningProcessInfo::ReadFromParcel(Parcel &parcel)
int32_t uidData;
READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, uidData);
uid_ = static_cast<int32_t>(uidData);
uint32_t accessTokenIdData;
READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Uint32, parcel, accessTokenIdData);
accessTokenId_ = accessTokenIdData;
int32_t stateData;
READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, stateData);
state_ = static_cast<AppProcessState>(stateData);
@@ -98,6 +101,7 @@ bool RunningProcessInfo::Marshalling(Parcel &parcel) const
WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(processName_));
WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, static_cast<int32_t>(pid_));
WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, static_cast<int32_t>(uid_));
WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Uint32, parcel, accessTokenId_);
WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, static_cast<int32_t>(state_));
WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Bool, parcel, isContinuousTask);
WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Bool, parcel, isKeepAlive);
@@ -71,6 +71,21 @@ typedef enum {
* @since 15
*/
ABILITY_RUNTIME_ERROR_CODE_INCORRECT_ABILITY_TYPE = 16000002,
/**
* @error Cannot start an invisible component.
* @since 26.0.0
*/
ABILITY_RUNTIME_ERROR_CODE_VISIBILITY_VERIFICATION_FAILED = 16000004,
/**
* @error The specified process does not have the permission.
* @since 26.0.0
*/
ABILITY_RUNTIME_ERROR_CODE_STATIC_CFG_PERMISSION = 16000005,
/**
* @error Cross-user operations are not allowed.
* @since 26.0.0
*/
ABILITY_RUNTIME_ERROR_CODE_CROSS_USER_OPERATION = 16000006,
/**
* @error The crowdtesting application expires.
* @since 15
@@ -153,6 +168,26 @@ typedef enum {
* @since 21
*/
ABILITY_RUNTIME_ERROR_CODE_MAIN_THREAD_NOT_SUPPORTED = 16000134,
/**
* @error The target application does not have running abilities with UI.
* @since 26.0.0
*/
ABILITY_RUNTIME_ERROR_CODE_NO_RUNNING_ABILITIES_WITH_UI = 16000160,
/**
* @error The API call frequency is too high and exceeds the rate control limit.
* @since 26.0.0
*/
ABILITY_RUNTIME_ERROR_CODE_UPPER_RATE_LIMIT = 16000161,
/**
* @error The number of connection exceeds limit.
* @since 26.0.0
*/
ABILITY_RUNTIME_ERROR_CODE_UPPER_CONNECTION_NUMBER_LIMIT = 16000162,
/**
* @error The modular object extension is disabled.
* @since 26.0.0
*/
ABILITY_RUNTIME_ERROR_CODE_MODULAR_OBJECT_EXTENSION_DISABLED = 16000163,
} AbilityRuntime_ErrorCode;
#ifdef __cplusplus
@@ -0,0 +1,173 @@
/*
* 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.
*/
/**
* @addtogroup AbilityRuntime
* @{
*
* @brief Provides the definition of the C interface for the modular object extension manager.
*
* @since 26.0.0
*/
/**
* @file connect_options.h
*
* @brief Declares the connection options.
*
* @library libability_runtime.so
* @kit AbilityKit
* @syscap SystemCapability.Ability.AbilityRuntime.Core
* @since 26.0.0
*/
#ifndef ABILITY_RUNTIME_CONNECT_OPTIONS_H
#define ABILITY_RUNTIME_CONNECT_OPTIONS_H
#include <stdint.h>
#include "ability_runtime_common.h"
#include "ipc_cparcel.h"
#include "want.h"
#ifdef __cplusplus
extern "C" {
#endif
struct AbilityBase_Want;
typedef struct AbilityBase_Want AbilityBase_Want;
struct AbilityBase_Element;
typedef struct AbilityBase_Element AbilityBase_Element;
/**
* @brief Defines the OH_AbilityRuntime_ConnectOptions structure type.
*
* @since 26.0.0
*/
typedef struct OH_AbilityRuntime_ConnectOptions OH_AbilityRuntime_ConnectOptions;
/**
* @brief The callback interface is invoked when the connection succeeds.
*
* @param connectOptions Represents a pointer to an {@link
* OH_AbilityRuntime_ConnectOptions} instance.
* @param element Represents the element name of the modular object extension ability.
* @param proxy Represents the remote object instance.
*
* @since 26.0.0
*/
typedef void (*OH_AbilityRuntime_ConnectOptions_OnConnectCallback)(
OH_AbilityRuntime_ConnectOptions *connectOptions, AbilityBase_Element *element, OHIPCRemoteProxy *proxy);
/**
* @brief The callback interface is invoked when the disconnection occurs.
*
* @param connectOptions Represents a pointer to an {@link
* OH_AbilityRuntime_ConnectOptions} instance.
* @param element Represents the element name of the modular object extension ability.
*
* @since 26.0.0
*/
typedef void (*OH_AbilityRuntime_ConnectOptions_OnDisconnectCallback)(
OH_AbilityRuntime_ConnectOptions *connectOptions, AbilityBase_Element *element);
/**
* @brief The callback interface is invoked when the connection fails.
*
* @param connectOptions Represents a pointer to an {@link
* OH_AbilityRuntime_ConnectOptions} instance.
* @param code Represents the error code of the failure.
*
* @since 26.0.0
*/
typedef void (*OH_AbilityRuntime_ConnectOptions_OnFailedCallback)(
OH_AbilityRuntime_ConnectOptions *connectOptions, AbilityRuntime_ErrorCode code);
/**
* @brief Creates a ConnectOptions object.
*
*
* @return Returns a newly created OH_AbilityRuntime_ConnectOptions object.
* The caller is responsible for destroying the returned object by calling
* {@link OH_AbilityRuntime_DestroyConnectOptions} to avoid memory leaks.
* @since 26.0.0
*/
OH_AbilityRuntime_ConnectOptions* OH_AbilityRuntime_CreateConnectOptions();
/**
* @brief Destroys the specified ConnectOptions.
*
* @param connectOptions The ConnectOptions object to be destroyed.
* @return The error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} if the operation is successful.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} if the connectOptions is invalid.
* @since 26.0.0
*/
AbilityRuntime_ErrorCode OH_AbilityRuntime_DestroyConnectOptions(OH_AbilityRuntime_ConnectOptions *connectOptions);
/**
* @brief Set the callback {@link OH_AbilityRuntime_ConnectOptions_OnConnectCallback} in
* {@link OH_AbilityRuntime_ConnectOptions}.
*
* @param connectOptions Pointer to an {@link OH_AbilityRuntime_ConnectOptions} instance to be set.
* @param onConnectCallback Represents {@link OH_AbilityRuntime_ConnectOptions_OnConnectCallback} instance
* which will be set in.
* @return Returns a specific error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} - success.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} - parameter check failed.
* @since 26.0.0
*/
AbilityRuntime_ErrorCode OH_AbilityRuntime_ConnectOptions_SetOnConnectCallback(
OH_AbilityRuntime_ConnectOptions *connectOptions,
OH_AbilityRuntime_ConnectOptions_OnConnectCallback onConnectCallback);
/**
* @brief Set the callback {@link OH_AbilityRuntime_ConnectOptions_OnDisconnectCallback} in
* {@link OH_AbilityRuntime_ConnectOptions}.
*
* @param connectOptions Pointer to an {@link OH_AbilityRuntime_ConnectOptions} instance to be set.
* @param onDisconnectCallback Represents {@link OH_AbilityRuntime_ConnectOptions_OnDisconnectCallback} instance
* which will be set in.
* @return Returns a specific error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} - success.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} - parameter check failed.
* @since 26.0.0
*/
AbilityRuntime_ErrorCode OH_AbilityRuntime_ConnectOptions_SetOnDisconnectCallback(
OH_AbilityRuntime_ConnectOptions *connectOptions,
OH_AbilityRuntime_ConnectOptions_OnDisconnectCallback onDisconnectCallback);
/**
* @brief Set the callback {@link OH_AbilityRuntime_ConnectOptions_OnFailedCallback} in
* {@link OH_AbilityRuntime_ConnectOptions}.
*
* @param connectOptions Pointer to an {@link OH_AbilityRuntime_ConnectOptions} instance to be set.
* @param onFailedCallback Represents {@link OH_AbilityRuntime_ConnectOptions_OnFailedCallback} instance
* which will be set in.
* @return Returns a specific error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} - success.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} - parameter check failed.
* @since 26.0.0
*/
AbilityRuntime_ErrorCode OH_AbilityRuntime_ConnectOptions_SetOnFailedCallback(
OH_AbilityRuntime_ConnectOptions *connectOptions,
OH_AbilityRuntime_ConnectOptions_OnFailedCallback onFailedCallback);
#ifdef __cplusplus
}
#endif
/** @} */
#endif // ABILITY_RUNTIME_CONNECT_OPTIONS_H
@@ -0,0 +1,210 @@
/*
* 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.
*/
/**
* @addtogroup AbilityRuntime
* @{
*
* @brief Provides the definition of the C interface for the modular object extension ability.
*
* @since 26.0.0
*/
/**
* @file modular_object_extension_ability.h
*
* @brief Declares the modular object extension ability.
*
* @library libmodular_object_extension.so
* @kit AbilityKit
* @syscap SystemCapability.Ability.AbilityRuntime.Core
* @since 26.0.0
*/
#ifndef ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_ABILITY_H
#define ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_ABILITY_H
#include "ability_runtime_common.h"
#include "extension_ability.h"
#include "ipc_cparcel.h"
#include "modular_object_extension_context.h"
#include "want.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Defines the struct for OH_AbilityRuntime_ModObjExtensionInstance.
*
* @since 26.0.0
*/
typedef struct OH_AbilityRuntime_ModularObjectExtensionInstance OH_AbilityRuntime_ModObjExtensionInstance;
/**
* @brief Defines the pointer to OH_AbilityRuntime_ModObjExtensionInstance.
*
* @since 26.0.0
*/
typedef OH_AbilityRuntime_ModObjExtensionInstance* OH_AbilityRuntime_ModObjExtensionInstanceHandle;
/**
* @brief Callback invoked when a modular object extension is started for initialization.
*
* @param instance Points to an {@link OH_AbilityRuntime_ModObjExtensionInstance} instance.
* @param want Indicates the want of created modular object extension.
* For details, see {@link AbilityBase_Want}.
*
* @since 26.0.0
*/
typedef void (*OH_AbilityRuntime_ModObjExtensionAbility_OnCreateFunc)(
OH_AbilityRuntime_ModObjExtensionInstanceHandle instance, AbilityBase_Want *want);
/**
* @brief Callback invoked before a modular object extension is destroyed.
*
* @param instance Points to an {@link OH_AbilityRuntime_ModObjExtensionInstance} instance.
*
* @since 26.0.0
*/
typedef void (*OH_AbilityRuntime_ModObjExtensionAbility_OnDestroyFunc)(
OH_AbilityRuntime_ModObjExtensionInstanceHandle instance);
/**
* @brief Callback invoked when a modular object extension is connected to an ability.
*
* @param instance Points to an {@link OH_AbilityRuntime_ModObjExtensionInstance} instance.
* @param want Indicates the want of created modular object extension.
*
* @since 26.0.0
*/
typedef OHIPCRemoteStub* (*OH_AbilityRuntime_ModObjExtensionAbility_OnConnectFunc)(
OH_AbilityRuntime_ModObjExtensionInstanceHandle instance, AbilityBase_Want *want);
/**
* @brief Callback invoked when all abilities connected to a modular object extension are
* disconnected.
*
* @param instance Points to an {@link OH_AbilityRuntime_ModObjExtensionInstance} instance.
*
* @since 26.0.0
*/
typedef void (*OH_AbilityRuntime_ModObjExtensionAbility_OnDisconnectFunc)(
OH_AbilityRuntime_ModObjExtensionInstanceHandle instance);
/**
* @brief Registers the function {@link OH_AbilityRuntime_ModObjExtensionAbility_OnCreateFunc} with
* {@link OH_AbilityRuntime_ModObjExtensionInstance}.
*
* @param instance Points to an {@link OH_AbilityRuntime_ModObjExtensionInstance} instance.
* @param onCreateFunc Represents the onCreate callback function.
* @return Returns a specific error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} - success.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} - parameter check failed.
* {@link ABILITY_RUNTIME_ERROR_CODE_NOT_SUPPORTED} - device not supported.
* @since 26.0.0
*/
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionAbility_RegisterOnCreateFunc(
OH_AbilityRuntime_ModObjExtensionInstanceHandle instance,
OH_AbilityRuntime_ModObjExtensionAbility_OnCreateFunc onCreateFunc);
/**
* @brief Registers the function {@link OH_AbilityRuntime_ModObjExtensionAbility_OnDestroyFunc} with
* {@link OH_AbilityRuntime_ModObjExtensionInstance}.
*
* @param instance Points to an {@link OH_AbilityRuntime_ModObjExtensionInstance} instance.
* @param onDestroyFunc Represents the onDestroy callback function.
* @return Returns a specific error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} - success.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} - parameter check failed.
* {@link ABILITY_RUNTIME_ERROR_CODE_NOT_SUPPORTED} - device not supported.
* @since 26.0.0
*/
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionAbility_RegisterOnDestroyFunc(
OH_AbilityRuntime_ModObjExtensionInstanceHandle instance,
OH_AbilityRuntime_ModObjExtensionAbility_OnDestroyFunc onDestroyFunc);
/**
* @brief Registers the function {@link OH_AbilityRuntime_ModObjExtensionAbility_OnConnectFunc} with
* {@link OH_AbilityRuntime_ModObjExtensionInstance}.
*
* @param instance Points to an {@link OH_AbilityRuntime_ModObjExtensionInstance} instance.
* @param onConnectFunc Represents the onConnect callback function.
* @return Returns a specific error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} - success.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} - parameter check failed.
* {@link ABILITY_RUNTIME_ERROR_CODE_NOT_SUPPORTED} - device not supported.
* @since 26.0.0
*/
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionAbility_RegisterOnConnectFunc(
OH_AbilityRuntime_ModObjExtensionInstanceHandle instance,
OH_AbilityRuntime_ModObjExtensionAbility_OnConnectFunc onConnectFunc);
/**
* @brief Registers the function {@link OH_AbilityRuntime_ModObjExtensionAbility_OnDisconnectFunc} with
* {@link OH_AbilityRuntime_ModObjExtensionInstance}.
*
* @param instance Points to an {@link OH_AbilityRuntime_ModObjExtensionInstance} instance.
* @param onDisconnectFunc Represents the onDisconnect callback function.
* @return Returns a specific error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} - success.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} - parameter check failed.
* {@link ABILITY_RUNTIME_ERROR_CODE_NOT_SUPPORTED} - device not supported.
* @since 26.0.0
*/
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionAbility_RegisterOnDisconnectFunc(
OH_AbilityRuntime_ModObjExtensionInstanceHandle instance,
OH_AbilityRuntime_ModObjExtensionAbility_OnDisconnectFunc onDisconnectFunc);
/**
* @brief Gets the extension context from the modular object extension instance.
*
* @param instance Points to an {@link OH_AbilityRuntime_ModObjExtensionInstance} instance.
* @param context Represents a pointer to the modular object extension ability context.
* @return Returns a specific error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} - success.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} - parameter check failed.
* {@link ABILITY_RUNTIME_ERROR_CODE_NOT_SUPPORTED} - device not supported.
* @since 26.0.0
*/
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionAbility_GetContextFromInstance(
OH_AbilityRuntime_ModObjExtensionInstanceHandle instance, OH_AbilityRuntime_ModObjExtensionContextHandle* context);
/**
* @brief Gets the modular object extension instance from a base extension instance.
*
* @param baseExtensionInstance Represents a pointer to a {@link
* AbilityRuntime_ExtensionInstance} base extension instance.
* @param modObjExtensionInstance Represents a pointer to an {@link
* OH_AbilityRuntime_ModObjExtensionInstanceHandle} instance that is an output parameter.
* @return Returns a specific error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} - success.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} - parameter check failed.
* {@link ABILITY_RUNTIME_ERROR_CODE_NOT_SUPPORTED} - device not supported.
* {@link ABILITY_RUNTIME_ERROR_CODE_INCORRECT_ABILITY_TYPE} - if the ability instance is not
* a modular object extension.
* @since 26.0.0
*/
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionAbility_GetInstanceFromBase(
AbilityRuntime_ExtensionInstanceHandle baseExtensionInstance,
OH_AbilityRuntime_ModObjExtensionInstanceHandle* modObjExtensionInstance);
#ifdef __cplusplus
}
#endif
/** @} */
#endif // ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_ABILITY_H
@@ -0,0 +1,165 @@
/*
* 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.
*/
/**
* @addtogroup AbilityRuntime
* @{
*
* @brief Provides the definition of the C interface for the modular object extension context.
*
* @since 26.0.0
*/
/**
* @file modular_object_extension_context.h
*
* @brief Declares the modular object extension context.
*
* @library libmodular_object_extension.so
* @kit AbilityKit
* @syscap SystemCapability.Ability.AbilityRuntime.Core
* @since 26.0.0
*/
#ifndef ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_CONTEXT_H
#define ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_CONTEXT_H
#include "ability_runtime_common.h"
#include "context.h"
#include "ipc_cremote_object.h"
#include "start_options.h"
#include "want.h"
#ifdef __cplusplus
extern "C" {
#endif
struct AbilityBase_Want;
typedef struct AbilityBase_Want AbilityBase_Want;
/**
* @brief Defines a pointer type to OH_AbilityRuntime_ModObjExtensionContextHandle.
*
* @since 26.0.0
*/
typedef struct OH_AbilityRuntime_ModularObjectExtensionContext* OH_AbilityRuntime_ModObjExtensionContextHandle;
/**
* @brief Gets the base context from the modular object extension context.
*
* @param modObjExtensionContext Represents a pointer to a modular object extension ability context.
* @param baseContext Represents a pointer to a {@link AbilityRuntime_ContextHandle} base extension ability context.
* @return Returns a specific error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} - success.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} - parameter check failed.
* {@link ABILITY_RUNTIME_ERROR_CODE_NOT_SUPPORTED} - device not supported.
* @since 26.0.0
*/
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_GetBaseContext(
OH_AbilityRuntime_ModObjExtensionContextHandle modObjExtensionContext, AbilityRuntime_ContextHandle* baseContext);
/**
* @brief Starts the self UIAbility.
*
* @permission ohos.permission.NDK_START_SELF_UI_ABILITY
* @param context Represents a pointer to a modular object extension ability context.
* @param want The arguments passed to start the self UIAbility.
* For details, see {@link AbilityBase_Want}.
* @return Returns a specific error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} - if the call is successful.
* {@link ABILITY_RUNTIME_ERROR_CODE_PERMISSION_DENIED} - if the caller has no correct permission.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} - if the arguments provided is invalid.
* {@link ABILITY_RUNTIME_ERROR_CODE_NOT_SUPPORTED} - if the device does not support starting self UIAbility.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_SUCH_ABILITY} - if the target ability does not exist.
* {@link ABILITY_RUNTIME_ERROR_CODE_INCORRECT_ABILITY_TYPE} - if the ability type is incorrect.
* {@link ABILITY_RUNTIME_ERROR_CODE_CROWDTEST_EXPIRED} - if the crowdtesting application expires.
* {@link ABILITY_RUNTIME_ERROR_CODE_WUKONG_MODE} - if the ability cannot be started in Wukong mode.
* {@link ABILITY_RUNTIME_ERROR_CODE_CONTROLLED} - if the app is controlled.
* {@link ABILITY_RUNTIME_ERROR_CODE_EDM_CONTROLLED} - if the app is controlled by EDM.
* {@link ABILITY_RUNTIME_ERROR_CODE_CROSS_APP} - if the caller tries to start a different application.
* {@link ABILITY_RUNTIME_ERROR_CODE_INTERNAL} - if an internal error occurs.
* {@link ABILITY_RUNTIME_ERROR_CODE_NOT_TOP_ABILITY} - if the caller is not top ability.
* {@link ABILITY_RUNTIME_ERROR_CODE_MULTI_APP_NOT_SUPPORTED} - if the app clone or multi-instance is
not supported.
* {@link ABILITY_RUNTIME_ERROR_CODE_INVALID_APP_INSTANCE_KEY} - if the app instance key is invalid.
* {@link ABILITY_RUNTIME_ERROR_CODE_UPPER_LIMIT_REACHED} - if the number of app instances has reached
the limit.
* {@link ABILITY_RUNTIME_ERROR_MULTI_INSTANCE_NOT_SUPPORTED} - if multi-instance is not supported.
* {@link ABILITY_RUNTIME_ERROR_CODE_APP_INSTANCE_KEY_NOT_SUPPORTED} - if the APP_INSTANCE_KEY cannot
be specified.
* @since 26.0.0
*/
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_StartSelfUIAbility(
OH_AbilityRuntime_ModObjExtensionContextHandle context, const AbilityBase_Want *want);
/**
* @brief Starts the self UIAbility with start options.
*
* @permission ohos.permission.NDK_START_SELF_UI_ABILITY
* @param context Represents a pointer to a modular object extension ability context.
* @param want The arguments passed to start the self UIAbility.
* For details, see {@link AbilityBase_Want}.
* @param options The start options passed to start the self UIAbility.
* For details, see {@link AbilityRuntime_StartOptions}.
* @return Returns a specific error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} - if the call is successful.
* {@link ABILITY_RUNTIME_ERROR_CODE_PERMISSION_DENIED} - if the caller has no correct permission.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} - if the arguments provided are invalid.
* {@link ABILITY_RUNTIME_ERROR_CODE_NOT_SUPPORTED} - if the device does not support starting self UIAbility.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_SUCH_ABILITY} - if the target ability does not exist.
* {@link ABILITY_RUNTIME_ERROR_CODE_INCORRECT_ABILITY_TYPE} - if the ability type is incorrect.
* {@link ABILITY_RUNTIME_ERROR_CODE_CROWDTEST_EXPIRED} - if the crowdtesting application expires.
* {@link ABILITY_RUNTIME_ERROR_CODE_WUKONG_MODE} - if the ability cannot be started in Wukong mode.
* {@link ABILITY_RUNTIME_ERROR_CODE_CONTROLLED} - if the app is controlled.
* {@link ABILITY_RUNTIME_ERROR_CODE_EDM_CONTROLLED} - if the app is controlled by EDM.
* {@link ABILITY_RUNTIME_ERROR_CODE_CROSS_APP} - if the caller tries to start a different application.
* {@link ABILITY_RUNTIME_ERROR_CODE_INTERNAL} - if an internal error occurs.
* {@link ABILITY_RUNTIME_ERROR_CODE_NOT_TOP_ABILITY} - if the caller is not a foreground process.
* {@link ABILITY_RUNTIME_ERROR_VISIBILITY_SETTING_DISABLED} - if setting visibility is disabled.
* {@link ABILITY_RUNTIME_ERROR_CODE_MULTI_APP_NOT_SUPPORTED} - if the app clone or multi-instance is
not supported.
* {@link ABILITY_RUNTIME_ERROR_CODE_INVALID_APP_INSTANCE_KEY} - if the app instance key is invalid.
* {@link ABILITY_RUNTIME_ERROR_CODE_UPPER_LIMIT_REACHED} - if the number of app instances has reached
the limit.
* {@link ABILITY_RUNTIME_ERROR_MULTI_INSTANCE_NOT_SUPPORTED} - if multi-instance is not supported.
* {@link ABILITY_RUNTIME_ERROR_CODE_APP_INSTANCE_KEY_NOT_SUPPORTED} - if the APP_INSTANCE_KEY cannot
be specified.
* @since 26.0.0
*/
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_StartSelfUIAbilityWithStartOptions(
OH_AbilityRuntime_ModObjExtensionContextHandle context, const AbilityBase_Want *want,
const AbilityRuntime_StartOptions *options);
/**
* @brief Destroys the modular object extension.
*
* @param context Represents a pointer to a modular object extension ability context.
* @return Returns a specific error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} - if the call is successful.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} - if the arguments provided are invalid.
* {@link ABILITY_RUNTIME_ERROR_CODE_NOT_SUPPORTED} - if the device does not support starting self UIAbility.
* {@link ABILITY_RUNTIME_ERROR_CODE_WUKONG_MODE} - if the ability cannot be started in Wukong mode.
* {@link ABILITY_RUNTIME_ERROR_CODE_CONTEXT_NOT_EXIST} - if the context does not exist.
* {@link ABILITY_RUNTIME_ERROR_CODE_INTERNAL} - if an internal error occurs.
* @since 26.0.0
*/
AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_TerminateSelf(
OH_AbilityRuntime_ModObjExtensionContextHandle context);
#ifdef __cplusplus
}
#endif
/** @} */
#endif // ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_CONTEXT_H
@@ -27,7 +27,7 @@
*
* @brief Declares the modular object extension manager.
*
* @library libmodular_object_extension.so
* @library libability_runtime.so
* @kit AbilityKit
* @syscap SystemCapability.Ability.AbilityRuntime.Core
* @since 26.0.0
@@ -37,7 +37,10 @@
#define ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_MANAGER_H
#include <stddef.h>
#include "ability_runtime_common.h"
#include "connect_options.h"
#include "context.h"
#include "want_manager.h"
#ifdef __cplusplus
@@ -180,7 +183,7 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_GetModularObjectExtensionInfoElementN
* @brief Gets the disable state of modular object extension.
*
* @param extensionInfo The modular object extension info.
* @param isDisabled Whether the extension is disabled by the application itself.
* @param isDisabled Whether the extension is disabled.
* @return Returns a specific error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} if the operation is successful.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} if the arguments provided are invalid.
@@ -191,7 +194,6 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_GetModularObjectExtensionInfoDisableS
/**
* @brief Acquires all modular object extension infos within the self application.
*
* @param outOwnedAllExtensionInfos Information about all extensions within the self application.
* @return Returns a specific error code.
@@ -245,6 +247,53 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_GetModObjExtensionInfoByIndex(
OH_AbilityRuntime_AllModObjExtensionInfosHandle allExtensionInfos, size_t index,
OH_AbilityRuntime_ModObjExtensionInfoHandle *extensionInfo);
/**
* @brief Connect to a modular object extension ability
*
* @param want Indicates the service extension to connect.
* For details, see {@link AbilityBase_Want}.
* @param connectOptions Indicates the connection options.
* @param connectionId Indicates the connection id that is a output param.
* @return Returns a specific error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} - if the call is successful.
* {@link ABILITY_RUNTIME_ERROR_CODE_PERMISSION_DENIED} - if the caller has no correct permission.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} - if the arguments provided are invalid.
* {@link ABILITY_RUNTIME_ERROR_CODE_NOT_SUPPORTED} - if the device does not support connecting modular
* object extension ability.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_SUCH_ABILITY} - if the target ability does not exist.
* {@link ABILITY_RUNTIME_ERROR_CODE_INCORRECT_ABILITY_TYPE} - if the ability type is incorrect.
* {@link ABILITY_RUNTIME_ERROR_CODE_VISIBILITY_VERIFICATION_FAILED} - Cannot start an invisible component.
* {@link ABILITY_RUNTIME_ERROR_CODE_STATIC_CFG_PERMISSION} - The specified process does not have
the permission.
* {@link ABILITY_RUNTIME_ERROR_CODE_CROSS_USER_OPERATION} - Cross-user operations are not allowed.
* {@link ABILITY_RUNTIME_ERROR_CODE_CROWDTEST_EXPIRED} - if the crowdtesting application expires.
* {@link ABILITY_RUNTIME_ERROR_CODE_INTERNAL} - if an internal error occurs.
* {@link ABILITY_RUNTIME_ERROR_CODE_NOT_TOP_ABILITY} - if the caller is not a foreground process.
* {@lin ABILITY_RUNTIME_ERROR_CODE_UPPER_LIMIT_REACHED} - The number of ability instances is more than five.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_RUNNING_ABILITIES_WITH_UI} - if the target application does not have
* running abilities with UI.
* {@link ABILITY_RUNTIME_ERROR_CODE_UPPER_RATE_LIMIT} - The API call frequency is too high and
* exceeds 20 times per second.
* {@link ABILITY_RUNTIME_ERROR_CODE_UPPER_CONNECTION_NUMBER_LIMIT} - The number of connections exceeds five.
* @since 26.0.0
*/
AbilityRuntime_ErrorCode OH_AbilityRuntime_ConnectModularObjectExtensionAbility(AbilityBase_Want *want,
OH_AbilityRuntime_ConnectOptions *connectOptions, int64_t *connectionId);
/**
* @brief Disconnect the modular object extension ability
*
* @param connectionId Indicates the connection ID.
* @return Returns a specific error code.
* {@link ABILITY_RUNTIME_ERROR_CODE_NO_ERROR} - if the call is successful.
* {@link ABILITY_RUNTIME_ERROR_CODE_PARAM_INVALID} - if the arguments provided are invalid.
* {@link ABILITY_RUNTIME_ERROR_CODE_NOT_SUPPORTED} - if the device does not support disconnecting modular
* object extension ability.
* {@link ABILITY_RUNTIME_ERROR_CODE_INTERNAL} - if an internal error occurs.
* @since 26.0.0
*/
AbilityRuntime_ErrorCode OH_AbilityRuntime_DisconnectModularObjectExtensionAbility(int64_t connectionId);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,78 @@
/*
* 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 OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_H
#define OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_H
#include "extension_base.h"
#include "modular_object_extension_context_impl.h"
#include "modular_object_extension_types.h"
#ifdef __cplusplus
extern "C" {
#endif
struct AbilityBase_Want;
typedef struct AbilityBase_Want AbilityBase_Want;
struct AbilityBase_Element;
typedef struct AbilityBase_Element AbilityBase_Element;
#ifdef __cplusplus
} // extern "C"
#endif
namespace OHOS {
namespace AbilityRuntime {
class ModularObjectExtension : public ExtensionBase<ModularObjectExtensionContext> {
public:
ModularObjectExtension() = default;
~ModularObjectExtension() override = default;
std::shared_ptr<ModularObjectExtensionContext> CreateAndInitContext(
const std::shared_ptr<AbilityLocalRecord> &record,
const std::shared_ptr<OHOSApplication> &application,
std::shared_ptr<AbilityHandler> &handler,
const sptr<IRemoteObject> &token) override;
void Init(const std::shared_ptr<AbilityLocalRecord> &record,
const std::shared_ptr<OHOSApplication> &application,
std::shared_ptr<AbilityHandler> &handler,
const sptr<IRemoteObject> &token) override;
static ModularObjectExtension* Create();
void OnStart(const AAFwk::Want &want) override;
void OnStop() override;
sptr<IRemoteObject> OnConnect(const AAFwk::Want &want) override;
void OnDisconnect(const AAFwk::Want &want) override;
private:
bool LoadNativeExtensionModule();
bool BuildCWant(const AAFwk::Want &want, AbilityBase_Want &cWant, AbilityBase_Element &element) const;
static bool BuildElement(const AppExecFwk::ElementName &elementName, AbilityBase_Element &element);
static void DestroyElement(AbilityBase_Element &element);
std::shared_ptr<OH_AbilityRuntime_ModularObjectExtensionInstance> moeInstance_;
std::shared_ptr<OH_AbilityRuntime_ModularObjectExtensionContext> moeContext_;
};
} // namespace AbilityRuntime
} // namespace OHOS
#endif // OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_H
@@ -0,0 +1,46 @@
/*
* 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 OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_CONTEXT_IMPL_H
#define OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_CONTEXT_IMPL_H
#include "extension_context.h"
#include "start_options.h"
#include "want.h"
namespace OHOS {
namespace AbilityRuntime {
class ModularObjectExtensionContext : public ExtensionContext {
public:
ModularObjectExtensionContext() = default;
~ModularObjectExtensionContext() override = default;
ErrCode StartSelfUIAbility(const AAFwk::Want &want) const;
ErrCode StartSelfUIAbilityWithStartOptions(const AAFwk::Want &want, const AAFwk::StartOptions &startOptions) const;
ErrCode TerminateSelf();
static const size_t CONTEXT_TYPE_ID;
protected:
bool IsContext(size_t contextTypeId) override
{
return contextTypeId == CONTEXT_TYPE_ID || ExtensionContext::IsContext(contextTypeId);
}
};
} // namespace AbilityRuntime
} // namespace OHOS
#endif // OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_CONTEXT_IMPL_H
@@ -0,0 +1,33 @@
/*
* 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 OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_MODULE_LOADER_H
#define OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_MODULE_LOADER_H
#include "extension_module_loader.h"
namespace OHOS::AbilityRuntime {
class ModularObjectExtensionModuleLoader
: public ExtensionModuleLoader, public Singleton<ModularObjectExtensionModuleLoader> {
DECLARE_SINGLETON(ModularObjectExtensionModuleLoader);
public:
Extension *Create(const std::unique_ptr<Runtime>& runtime) const override;
std::map<std::string, std::string> GetParams() override;
};
} // namespace OHOS::AbilityRuntime
#endif // OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_MODULE_LOADER_H
+5
View File
@@ -583,18 +583,23 @@ ohos_shared_library("modular_object") {
]
deps = [
"${ability_runtime_innerkits_path}/ability_manager:ability_manager",
"${ability_runtime_innerkits_path}/app_manager:app_manager",
"${ability_runtime_innerkits_path}/deps_wrapper:ability_deps_wrapper",
"${ability_runtime_native_path}/appkit:appkit_manager_helper",
"${ability_runtime_services_path}/common:app_util",
]
external_deps = [
"ability_base:want",
"c_utils:utils",
"common_event_service:cesfwk_innerkits",
"eventhandler:libeventhandler",
"ffrt:libffrt",
"hilog:libhilog",
"hitrace:hitrace_meter",
"hisysevent:libhisysevent",
"ipc:ipc_core",
"safwk:system_ability_fwk",
"samgr:samgr_proxy",
]
+3
View File
@@ -190,6 +190,9 @@ abilityms_files = [
"src/kiosk_status.cpp",
"src/kiosk_manager.cpp",
"src/utils/udmf_utils.cpp",
#modular_object utils
"src/modular_object_utils.cpp",
]
if (ability_runtime_graphics) {
@@ -1536,6 +1536,8 @@ public:
virtual int GetProcessRunningInfos(std::vector<AppExecFwk::RunningProcessInfo> &info) override;
virtual int GetAllIntentExemptionInfo(std::vector<AppExecFwk::IntentExemptionInfo> &info) override;
int GetProcessRunningInfosByUserId(std::vector<AppExecFwk::RunningProcessInfo> &info, int32_t userId);
int GetProcessRunningInfosByAccessTokenId(uint32_t accessTokenId,
std::vector<AppExecFwk::RunningProcessInfo> &info);
void GetAbilityRunningInfo(std::vector<AbilityRunningInfo> &info, std::shared_ptr<AbilityRecord> abilityRecord);
void GetExtensionRunningInfo(std::shared_ptr<BaseExtensionRecord> &abilityRecord, const int32_t userId,
std::vector<ExtensionRunningInfo> &info);
@@ -2618,7 +2620,11 @@ public:
virtual int32_t PreloadApplication(const std::string &bundleName, int32_t userId, int32_t appIndex) override;
int StartAbilityWithRemoveIntentFlag(const StartAbilityWrapParam &param);
std::shared_ptr<UIAbilityLifecycleManager> GetUIAbilityManagerByUserId(int32_t userId) const;
std::shared_ptr<UIExtensionAbilityManager> GetUIExtensionAbilityManagerByUserId(int32_t userId);
// MSG 0 - 20 represents timeout message
static constexpr uint32_t LOAD_TIMEOUT_MSG = 0;
static constexpr uint32_t ACTIVE_TIMEOUT_MSG = 1;
@@ -2993,7 +2999,6 @@ private:
std::unordered_map<int, std::shared_ptr<UIExtensionAbilityManager>> GetUIExtensionAbilityManagers();
std::shared_ptr<UIExtensionAbilityManager> GetCurrentUIExtensionAbilityManager();
std::shared_ptr<UIExtensionAbilityManager> GetUIExtensionAbilityManagerByUserId(int32_t userId);
std::shared_ptr<UIExtensionAbilityManager> GetUIExtensionAbilityManagerByToken(const sptr<IRemoteObject> &token);
std::shared_ptr<UIExtensionAbilityManager> GetUIExtensionAbilityManagerByAbilityRecordId(
const int64_t &abilityRecordId);
@@ -3010,7 +3015,6 @@ private:
std::shared_ptr<MissionListManagerInterface> GetCurrentMissionListManager();
std::unordered_map<int, std::shared_ptr<UIAbilityLifecycleManager>> GetUIAbilityManagers();
std::shared_ptr<UIAbilityLifecycleManager> GetCurrentUIAbilityManager();
std::shared_ptr<UIAbilityLifecycleManager> GetUIAbilityManagerByUserId(int32_t userId) const;
std::shared_ptr<UIAbilityLifecycleManager> GetUIAbilityManagerByUid(int32_t uid);
bool JudgeSelfCalled(const std::shared_ptr<AbilityRecord> &abilityRecord);
bool IsAppSelfCalled(const std::shared_ptr<AbilityRecord> &abilityRecord);
@@ -3516,7 +3520,7 @@ private:
bool IsAllowAttachOrDetachAppDebug(AppExecFwk::ApplicationInfo &appInfo);
bool IsExitReasonValid(const ExitReasonCompability &reason);
void RecordRecoveryExitReason(bool isAppRecovery, int32_t callerPid, int32_t callerUid);
void RecordAppRestartExitReason(bool isAppRecovery, int32_t callerPid, int32_t callerUid);
void SetAppDeathRecipient(const sptr<IRemoteObject>& abilityToken);
void HandleAppDiedForRecovery(const sptr<IRemoteObject>& remote, const AbilityInfo& abilityInfo,
int32_t pid, int32_t uid, int32_t userId);
@@ -35,15 +35,6 @@ struct RecordExitReasonParams {
bool fromKillWithReason = false;
};
struct AppReasonInfo {
int32_t userId = -1;
std::string bundleName = "";
int32_t appIndex = -1;
AppReasonInfo() = default;
AppReasonInfo(int32_t userId, const std::string &bundleName, int32_t appIndex)
: userId(userId), bundleName(bundleName), appIndex(appIndex) {}
};
class AppExitReasonHelper {
public:
explicit AppExitReasonHelper(std::shared_ptr<SubManagersHelper> subManagersHelper);
@@ -65,13 +56,10 @@ public:
int32_t AddBundleExitReason(const std::string &bundleName, int32_t userId, int32_t appIndex,
const ExitReasonCompability &exitReason);
int32_t RecordAppWithReason(int32_t pid, int32_t uid, const ExitReasonCompability &exitReason);
void RecordAppsWithReasonByUserId(int32_t userId, const ExitReasonCompability &exitReason,
void RecordAppsWithReasonByProcessInfoList(const ExitReasonCompability &exitReason,
const std::vector<AppExecFwk::RunningProcessInfo> &processInfoList);
void RecordInvalidKillId(int32_t pid, const ExitReasonCompability &params,
const std::string &bundleName = "", int32_t userId = 0);
int32_t RecordAppWithReasonByAccessTokenId(int32_t userId, uint32_t accessTokenId,
const ExitReasonCompability &exitReasonCompability,
const std::vector<AppExecFwk::RunningProcessInfo> &processInfoList);
private:
int32_t RecordProcessExitReason(const int32_t pid, const std::string bundleName, const int32_t uid,
@@ -83,11 +71,11 @@ private:
bool IsExitReasonValid(const ExitReason &exitReason);
int32_t GetActiveAbilityListWithPid(int32_t uid, std::vector<std::string> &abilityList, int32_t pid);
void GetRunningProcessInfo(int32_t pid, int32_t userId, const std::string &bundleName,
AppExecFwk::RunningProcessInfo &processInfo);
AppExecFwk::RunningProcessInfo &processInfo, int32_t appIndex = DEFAULT_INVAL_VALUE);
int32_t AddProcessExitReason(const RecordExitReasonParams &params);
std::vector<AppExecFwk::RunningProcessInfo> GetRunningProcessInfos(int32_t userId, const std::string &bundleName);
int32_t RecordAppWithReasonInner(const AppReasonInfo &appInfo, const ExitReasonCompability &exitReasonCompability,
int32_t RecordAppWithReasonInner(const ExitReasonCompability &exitReasonCompability,
const AppExecFwk::RunningProcessInfo &processInfo);
std::shared_ptr<SubManagersHelper> subManagersHelper_;
@@ -522,6 +522,18 @@ public:
* @return ERR_OK ,return back successothers fail.
*/
int GetProcessRunningInfosByUserId(std::vector<AppExecFwk::RunningProcessInfo> &info, int32_t userId);
/**
* GetProcessRunningInfosByAccessTokenId, call GetProcessRunningInfosByAccessTokenId() through proxy project.
* Obtains information about application processes that are running on the device by accessTokenId.
*
* @param accessTokenId, accessTokenId in Application record.
* @param info, Running process info.
* @return ERR_OK ,return back successothers fail.
*/
int32_t GetProcessRunningInfosByAccessTokenId(uint32_t accessTokenId,
std::vector<AppExecFwk::RunningProcessInfo> &info);
std::string ConvertAppState(const AppState &state);
/**
@@ -87,6 +87,13 @@ public:
*/
int32_t GetActiveUIExtensionList(const std::string &bundleName, std::vector<std::string> &extensionList);
/**
* @brief Get extensionList by uid.
* @param uid The application uid.
* @param extensionList UIExtensionAbility name list.
*/
int32_t GetActiveUIExtensionListByUid(int32_t uid, std::vector<std::string> &extensionList);
int32_t StartAbility(const AAFwk::AbilityRequest &abilityRequest);
int32_t CreateExtensionRecord(const AAFwk::AbilityRequest &abilityRequest, const std::string &hostBundleName,
@@ -18,6 +18,7 @@
#include <singleton.h>
#include "modular_object_extension_info.h"
#include "want.h"
namespace OHOS {
namespace AbilityRuntime {
@@ -30,4 +31,4 @@ public:
}
}
#endif // OHOS_MODULAR_OBJECT_MANAGER_H
#endif // OHOS_MODULAR_OBJECT_MANAGER_H
@@ -0,0 +1,50 @@
/*
* 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 OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_UTILS_H
#define OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_UTILS_H
#include <string>
#include <vector>
#include "ability_record/ability_request.h"
#include "modular_object_extension_info.h"
namespace OHOS {
namespace AAFwk {
class ModularObjectUtils {
public:
ModularObjectUtils() = delete;
static int32_t CheckPermission(const AbilityRequest &abilityRequest);
private:
static int32_t CheckExtensionEnabled(const ModularObjectExtensionInfo &info, const AbilityRequest &abilityRequest);
static int32_t CheckCallerForeground();
static int32_t CheckAppDistributionType(const std::string &callerAppDistributionType,
const std::string &targetAppDistributionType);
static bool HasRunningUIAbilityOrExtension(int32_t targetUid, int32_t userId);
static int32_t CheckTargetHasRunningAbility(int32_t targetUid, int32_t userId,
const std::string &targetBundleName);
static int32_t GetTargetExtensionInfoFromDb(const std::string &bundleName, const std::string &abilityName,
int32_t appIndex, int32_t validUserId, ModularObjectExtensionInfo &targetExtensionInfo);
static int32_t GetCallerAppInfo(AppExecFwk::ApplicationInfo &callerAppInfo);
};
} // namespace AAFwk
} // namespace OHOS
#endif // OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_UTILS_H
@@ -116,6 +116,13 @@ public:
*/
int32_t GetActiveUIExtensionList(const std::string &bundleName, std::vector<std::string> &extensionList);
/**
* @brief Get extensionList by uid.
* @param uid The application uid.
* @param extensionList UIExtensionAbility name list.
*/
int32_t GetActiveUIExtensionListByUid(int32_t uid, std::vector<std::string> &extensionList);
void BackgroundAbilityWindowLocked(const std::shared_ptr<BaseExtensionRecord> &abilityRecord,
const sptr<SessionInfo> &sessionInfo);
@@ -81,6 +81,8 @@
#include "mock_session_manager_service.h"
#include "modal_system_dialog/modal_system_dialog_ui_extension.h"
#include "modal_system_ui_extension.h"
#include "modular_object_manager.h"
#include "modular_object_utils.h"
#include "multi_app_utils.h"
#include "os_account_manager_wrapper.h"
#include "permission_constants.h"
@@ -235,6 +237,7 @@ constexpr size_t INDEX_ONE = 1;
constexpr size_t INDEX_TWO = 2;
constexpr size_t ARGC_THREE = 3;
constexpr size_t INDEX_FOUR = 4;
constexpr int32_t DEFAULT_KILL_ID = -1;
constexpr static char WANT_PARAMS_VIEW_DATA_KEY[] = "ohos.ability.params.viewData";
constexpr const char* WANT_PARAMS_HOST_WINDOW_ID_KEY = "ohos.extra.param.key.hostwindowid";
@@ -3592,7 +3595,7 @@ int32_t AbilityManagerService::RecordAppWithReasonByUserId(int32_t userId,
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
CHECK_POINTER_AND_RETURN(appExitReasonHelper_, ERR_NULL_APP_EXIT_REASON_HELPER);
if (IPCSkeleton::GetCallingPid() != getprocpid()) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "%{public}s: calling pid is not local process", __func__);
TAG_LOGE(AAFwkTag::ABILITYMGR, "calling pid is not local process");
return CHECK_PERMISSION_FAILED;
}
if (!IsExitReasonValid(exitReasonCompability)) {
@@ -3612,7 +3615,7 @@ int32_t AbilityManagerService::RecordAppWithReasonByUserId(int32_t userId,
return ERR_OK;
}
appExitReasonHelper_->RecordAppsWithReasonByUserId(userId, exitReasonCompability, processInfoList);
appExitReasonHelper_->RecordAppsWithReasonByProcessInfoList(exitReasonCompability, processInfoList);
return ERR_OK;
}
@@ -3625,28 +3628,20 @@ int32_t AbilityManagerService::RecordAppWithReasonByAccessTokenId(uint32_t acces
TAG_LOGE(AAFwkTag::ABILITYMGR, "exit reason is invalid");
return ERR_INVALID_VALUE;
}
Security::AccessToken::HapTokenInfo hapInfo;
int32_t ret = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(accessTokenId, hapInfo);
if (ret != ERR_OK) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "GetHapTokenInfo failed: %{public}d", ret);
return ret;
}
int32_t userId = hapInfo.userID;
std::vector<AppExecFwk::RunningProcessInfo> processInfoList;
ret = IN_PROCESS_CALL(GetProcessRunningInfosByUserId(processInfoList, userId));
int32_t ret = IN_PROCESS_CALL(GetProcessRunningInfosByAccessTokenId(accessTokenId, processInfoList));
if (ret != ERR_OK) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "GetProcessRunningInfosByUserId failed: %{public}d", ret);
TAG_LOGE(AAFwkTag::ABILITYMGR, "GetProcessRunningInfosByAccessTokenId failed: %{public}d", ret);
return ret;
}
if (processInfoList.empty()) {
TAG_LOGW(AAFwkTag::ABILITYMGR, "no process info for userId: %{public}d", userId);
TAG_LOGW(AAFwkTag::ABILITYMGR, "no process info for accessTokenId: %{public}d", accessTokenId);
return ERR_OK;
}
appExitReasonHelper_->RecordAppWithReasonByAccessTokenId(userId, accessTokenId, exitReasonCompability,
processInfoList);
appExitReasonHelper_->RecordAppsWithReasonByProcessInfoList(exitReasonCompability, processInfoList);
return ERR_OK;
}
@@ -8707,8 +8702,9 @@ bool AbilityManagerService::CheckPermissionForKillCollaborator()
int AbilityManagerService::KillProcess(const std::string &bundleName, bool clearPageStack, int32_t appIndex,
const std::string& reason)
{
TAG_LOGI(AAFwkTag::ABILITYMGR, "Kill process, bundleName: %{public}s, clearPageStack: %{public}d",
bundleName.c_str(), clearPageStack);
TAG_LOGI(AAFwkTag::ABILITYMGR, "Kill process, bundleName: %{public}s, clearPageStack: %{public}d"
"callingUid: %{public}d, callingPid: %{public}d", bundleName.c_str(), clearPageStack,
IPCSkeleton::GetCallingUid(), IPCSkeleton::GetCallingPid());
// check permission first
auto isAllowKillProcessForCollaborator = CheckPermissionForKillCollaborator();
if (!isAllowKillProcessForCollaborator &&
@@ -10408,6 +10404,12 @@ int AbilityManagerService::GetProcessRunningInfosByUserId(
return DelayedSingleton<AppScheduler>::GetInstance()->GetProcessRunningInfosByUserId(info, userId);
}
int AbilityManagerService::GetProcessRunningInfosByAccessTokenId(uint32_t accessTokenId,
std::vector<AppExecFwk::RunningProcessInfo> &info)
{
return DelayedSingleton<AppScheduler>::GetInstance()->GetProcessRunningInfosByAccessTokenId(accessTokenId, info);
}
void AbilityManagerService::ClearUserData(int32_t userId)
{
TAG_LOGD(AAFwkTag::ABILITYMGR, "%{public}s", __func__);
@@ -12425,6 +12427,9 @@ int AbilityManagerService::CheckCallOtherExtensionPermission(const AbilityReques
if (extensionType == AppExecFwk::ExtensionAbilityType::CALLER_INFO_QUERY) {
return CheckCallerInfoQueryExtensionPermission(abilityRequest);
}
if (extensionType == AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT) {
return ModularObjectUtils::CheckPermission(abilityRequest);
}
TAG_LOGE(AAFwkTag::ABILITYMGR, "not SA, can't start other extension");
return CHECK_PERMISSION_FAILED;
}
@@ -13543,7 +13548,12 @@ int32_t AbilityManagerService::KillProcessWithReasonInner(int32_t pid, const Exi
return ERR_KILL_APP_WHILE_STARTING;
}
CHECK_POINTER_AND_RETURN(appExitReasonHelper_, ERR_NULL_OBJECT);
auto ret = IN_PROCESS_CALL(appExitReasonHelper_->RecordProcessExitReason(pid, reason, true));
ExitReason modifiedReason(reason.reason, reason.subReason, reason.exitMsg);
modifiedReason.killId = (reason.killId == DEFAULT_KILL_ID) ?
HiviewDFX::ProcessKillReason::KillEventId::REASON_KILL_APPLICATION : reason.killId;
modifiedReason.shouldKillForeground = reason.shouldKillForeground;
modifiedReason.shouldSkipKillInStartup = reason.shouldSkipKillInStartup;
auto ret = IN_PROCESS_CALL(appExitReasonHelper_->RecordProcessExitReason(pid, modifiedReason, true));
if (ret != ERR_OK) {
TAG_LOGW(AAFwkTag::ABILITYMGR, "RecordAppExitReason failed, ret:%{public}d", ret);
}
@@ -14913,19 +14923,14 @@ int32_t AbilityManagerService::GetUIExtensionSessionInfo(const sptr<IRemoteObjec
return ERR_OK;
}
void AbilityManagerService::RecordRecoveryExitReason(bool isAppRecovery, int32_t callerPid, int32_t callerUid)
void AbilityManagerService::RecordAppRestartExitReason(bool isAppRecovery, int32_t callerPid, int32_t callerUid)
{
if (!isAppRecovery) {
if (isAppRecovery) {
return;
}
int32_t killId = HiviewDFX::ProcessKillReason::KillEventId::REASON_RESTART;
std::string killReason = HiviewDFX::ProcessKillReason::GetKillReason(killId);
AAFwk::ExitReasonCompability exitReason = {REASON_JS_ERROR, "Kill Reason:" + killReason};
exitReason.killId = killId;
AAFwk::ExitReasonCompability exitReason(killId);
auto result = IN_PROCESS_CALL(RecordAppWithReason(callerPid, callerUid, exitReason));
TAG_LOGI(AAFwkTag::ABILITYMGR, "Record result=%{public}d, send event [FRAMEWORK,PROCESS_KILL,APP_RECOVERY], "
"callerPid=%{public}d, callerUid=%{public}d, killReason=%{public}s",
result, callerPid, callerUid, killReason.c_str());
}
int32_t AbilityManagerService::RestartApp(const AAFwk::Want &want, bool isAppRecovery)
@@ -14955,6 +14960,7 @@ int32_t AbilityManagerService::RestartApp(const AAFwk::Want &want, bool isAppRec
SignRestartAppFlagParam param =
{ userId, callerUid, processInfo.instanceKey, processInfo.appMode, isAppRecovery, false };
RecordAppRestartExitReason(isAppRecovery, callerPid, callerUid);
result = SignRestartAppFlag(param);
if (!isAppRecovery && result != ERR_OK) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "signRestartAppFlag error");
@@ -38,42 +38,47 @@ AppExitReasonHelper::AppExitReasonHelper(std::shared_ptr<SubManagersHelper> subM
int32_t AppExitReasonHelper::RecordAppWithReason(int32_t pid, int32_t uid, const ExitReasonCompability &exitReason)
{
std::string bundleName;
int32_t appIndex = 0;
auto ret = IN_PROCESS_CALL(AbilityUtil::GetBundleManagerHelper()->GetNameAndIndexForUid(uid, bundleName, appIndex));
if (ret != ERR_OK) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "GetNameAndIndexForUid failed, ret: %{public}d", ret);
return ret;
int32_t userId = DEFAULT_INVAL_VALUE;
int32_t appIndex = DEFAULT_INVAL_VALUE;
if (pid == NO_PID) {
auto ret = IN_PROCESS_CALL(AbilityUtil::GetBundleManagerHelper()->GetNameAndIndexForUid(
uid, bundleName, appIndex));
if (ret != ERR_OK) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "GetNameAndIndexForUid failed, ret: %{public}d", ret);
return ret;
}
int32_t getOsAccountRet = DelayedSingleton<AppExecFwk::OsAccountManagerWrapper>::GetInstance()->
GetOsAccountLocalIdFromUid(uid, userId);
if (getOsAccountRet != ERR_OK) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "get GetOsAccountLocalIdFromUid failed. ret: %{public}d", getOsAccountRet);
return getOsAccountRet;
}
}
AppExecFwk::RunningProcessInfo processInfo;
int32_t userId = -1;
int32_t getOsAccountRet = DelayedSingleton<AppExecFwk::OsAccountManagerWrapper>::GetInstance()->
GetOsAccountLocalIdFromUid(uid, userId);
if (getOsAccountRet != ERR_OK) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "get GetOsAccountLocalIdFromUid failed. ret: %{public}d", getOsAccountRet);
return getOsAccountRet;
}
GetRunningProcessInfo(pid, userId, bundleName, processInfo);
TAG_LOGD(AAFwkTag::ABILITYMGR, "RecordAppWithReason inPid: %{public}d, processPid: %{public}d",
GetRunningProcessInfo(pid, userId, bundleName, processInfo, appIndex);
TAG_LOGD(AAFwkTag::ABILITYMGR, "RecordAppWithReason inputPid: %{public}d, processPid: %{public}d",
pid, processInfo.pid_);
AppReasonInfo appInfo(userId, bundleName, appIndex);
return RecordAppWithReasonInner(appInfo, exitReason, processInfo);
return RecordAppWithReasonInner(exitReason, processInfo);
}
int32_t AppExitReasonHelper::RecordAppWithReasonInner(const AppReasonInfo &appInfo,
const ExitReasonCompability &exitReasonCompability, const AppExecFwk::RunningProcessInfo &processInfo)
int32_t AppExitReasonHelper::RecordAppWithReasonInner(const ExitReasonCompability &exitReasonCompability,
const AppExecFwk::RunningProcessInfo &processInfo)
{
if (processInfo.pid_ <= 0 && processInfo.uid_ <= 0) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "processInfo is invalid");
if (processInfo.pid_ <= 0 || processInfo.uid_ <= 0 || processInfo.bundleNames.empty()) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "processInfo is invalid, pid: %{public}d, uid: %{public}d, "
"bundleNames empty: %{public}d", processInfo.pid_, processInfo.uid_, processInfo.bundleNames.empty());
return ERR_INVALID_VALUE;
}
std::string bundleName = processInfo.bundleNames.front();
ExitReason exitReason(exitReasonCompability.reason, exitReasonCompability.subReason,
exitReasonCompability.exitMsg);
exitReason.killId = exitReasonCompability.killId;
int32_t extensionResultCode = RecordProcessExtensionExitReason(
processInfo.pid_, appInfo.bundleName, exitReason, processInfo, false);
processInfo.pid_, bundleName, exitReason, processInfo, false);
if (extensionResultCode != ERR_OK) {
TAG_LOGI(AAFwkTag::ABILITYMGR, "not record extension reason: %{public}d", extensionResultCode);
}
@@ -93,97 +98,33 @@ int32_t AppExitReasonHelper::RecordAppWithReasonInner(const AppReasonInfo &appIn
TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityLists empty");
return ERR_GET_ACTIVE_ABILITY_LIST_EMPTY;
}
uint32_t accessTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(appInfo.userId, appInfo.bundleName,
appInfo.appIndex);
uint32_t accessTokenId = processInfo.accessTokenId_;
TAG_LOGD(AAFwkTag::ABILITYMGR,
"userId: %{public}d, bundleName: %{public}s, accessTokenId: %{public}u",
appInfo.userId, appInfo.bundleName.c_str(), accessTokenId);
"bundleName: %{public}s, accessTokenId: %{public}u", bundleName.c_str(), accessTokenId);
return DelayedSingleton<AbilityRuntime::AppExitReasonDataManager>::GetInstance()->SetAppExitReason(
appInfo.bundleName, accessTokenId, abilityList, exitReason, processInfo, false);
bundleName, accessTokenId, abilityList, exitReason, processInfo, false);
}
void AppExitReasonHelper::RecordAppsWithReasonByUserId(int32_t userId, const ExitReasonCompability &exitReason,
void AppExitReasonHelper::RecordAppsWithReasonByProcessInfoList(const ExitReasonCompability &exitReason,
const std::vector<AppExecFwk::RunningProcessInfo> &processInfoList)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
TAG_LOGD(AAFwkTag::ABILITYMGR, "userId: %{public}d, processInfo count: %{public}zu",
userId, processInfoList.size());
int32_t appIndex;
int32_t uid;
int32_t pid;
int32_t innerResult = ERR_OK;
std::string bundleName;
for (const auto &processInfo : processInfoList) {
if (processInfo.pid_ <= 0 && processInfo.uid_ <= 0) {
continue;
}
uid = processInfo.uid_;
pid = processInfo.pid_;
TAG_LOGD(AAFwkTag::ABILITYMGR, "RecordAppsWithReasonByUserId uid: %{public}d, pid: %{public}d", uid, pid);
auto ret = IN_PROCESS_CALL(AbilityUtil::GetBundleManagerHelper()->GetNameAndIndexForUid(
uid, bundleName, appIndex));
if (ret != ERR_OK) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "GetNameAndIndexForUid failed, ret: %{public}d", ret);
continue;
}
AppReasonInfo appInfo(userId, bundleName, appIndex);
innerResult = RecordAppWithReasonInner(appInfo, exitReason, processInfo);
TAG_LOGD(AAFwkTag::ABILITYMGR, "RecordAppsWithReasonByProcessInfoList uid: %{public}d, pid: %{public}d",
processInfo.uid_, processInfo.pid_);
innerResult = RecordAppWithReasonInner(exitReason, processInfo);
if (innerResult != ERR_OK) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "RecordAppWithReasonInner failed for uid:%{public}d, userId:%{public}d,"
" ret: %{public}d",
uid, userId, innerResult);
TAG_LOGE(AAFwkTag::ABILITYMGR, "RecordAppWithReasonInner failed for uid:%{public}d, ret: %{public}d",
processInfo.uid_, innerResult);
continue;
}
}
}
int32_t AppExitReasonHelper::RecordAppWithReasonByAccessTokenId(int32_t userId, uint32_t accessTokenId,
const ExitReasonCompability &exitReasonCompability,
const std::vector<AppExecFwk::RunningProcessInfo> &processInfoList)
{
std::string bundleName;
int32_t appIndex;
int32_t uid;
int32_t pid;
int32_t innerResult = ERR_OK;
for (const auto &processInfo : processInfoList) {
if (processInfo.pid_ <= 0 && processInfo.uid_ <= 0) {
continue;
}
uid = processInfo.uid_;
pid = processInfo.pid_;
TAG_LOGD(AAFwkTag::ABILITYMGR, "RecordAppWithReasonByAccessTokenId uid: %{public}d, pid: %{public}d", uid, pid);
innerResult = IN_PROCESS_CALL(AbilityUtil::GetBundleManagerHelper()->GetNameAndIndexForUid(
uid, bundleName, appIndex));
if (innerResult != ERR_OK) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "GetNameAndIndexForUid failed, ret: %{public}d", innerResult);
continue;
}
uint32_t currentAccessTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(uid, bundleName, appIndex);
TAG_LOGD(AAFwkTag::ABILITYMGR, "process uid: %{public}d, calculated accessTokenId: %{public}u, "
"expected accessTokenId: %{public}u", uid, currentAccessTokenId, accessTokenId);
if (currentAccessTokenId != accessTokenId) {
TAG_LOGD(AAFwkTag::ABILITYMGR, "accessTokenId mismatch, skip process");
continue;
}
AppReasonInfo appInfo(userId, bundleName, appIndex);
innerResult = RecordAppWithReasonInner(appInfo, exitReasonCompability, processInfo);
if (innerResult != ERR_OK) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "RecordAppWithReasonInner failed for uid:%{public}d, userId:%{public}d, "
"ret: %{public}d", uid, userId, innerResult);
continue;
}
}
return innerResult;
}
int32_t AppExitReasonHelper::RecordAppExitReason(const ExitReason &exitReason)
{
if (!IsExitReasonValid(exitReason)) {
@@ -318,7 +259,7 @@ int32_t AppExitReasonHelper::RecordAppExitReason(const std::string &bundleName,
"userId: %{public}d, bundleName: %{public}s, appIndex: %{public}d", userId, bundleName.c_str(), appIndex);
uint32_t accessTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(userId, bundleName, appIndex);
AppExecFwk::RunningProcessInfo processInfo;
GetRunningProcessInfo(NO_PID, userId, bundleName, processInfo);
GetRunningProcessInfo(NO_PID, userId, bundleName, processInfo, appIndex);
int32_t pid = processInfo.pid_ == DEFAULT_PROCESS_RUNNING_INFO_PID ? NO_PID : processInfo.pid_;
return RecordProcessExitReason(pid, bundleName, uid, accessTokenId, exitReason, processInfo, false);
}
@@ -433,7 +374,7 @@ int32_t AppExitReasonHelper::AddAppExitReason(const std::string &bundleName, int
"userId: %{public}d, bundleName: %{public}s, appIndex: %{public}d", userId, bundleName.c_str(), appIndex);
uint32_t accessTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(userId, bundleName, appIndex);
AppExecFwk::RunningProcessInfo processInfo;
GetRunningProcessInfo(pid, userId, bundleName, processInfo);
GetRunningProcessInfo(pid, userId, bundleName, processInfo, appIndex);
RecordExitReasonParams params;
params.pid = pid;
params.uid = uid;
@@ -602,7 +543,7 @@ int32_t AppExitReasonHelper::RecordUIAbilityExitReason(const pid_t pid, const st
}
void AppExitReasonHelper::GetRunningProcessInfo(int32_t pid, int32_t userId, const std::string &bundleName,
AppExecFwk::RunningProcessInfo &processInfo)
AppExecFwk::RunningProcessInfo &processInfo, int32_t appIndex)
{
if (pid != NO_PID) {
DelayedSingleton<AppScheduler>::GetInstance()->GetRunningProcessInfoByPid(static_cast<pid_t>(pid),
@@ -612,6 +553,13 @@ void AppExitReasonHelper::GetRunningProcessInfo(int32_t pid, int32_t userId, con
std::vector<AppExecFwk::RunningProcessInfo> infoList = GetRunningProcessInfos(userId, bundleName);
if (infoList.size() == 1) {
processInfo = infoList.front();
} else if (infoList.size() > 1 && appIndex != DEFAULT_INVAL_VALUE) {
for (const auto &info : infoList) {
if (info.appCloneIndex == appIndex) {
processInfo = info;
return;
}
}
}
}
@@ -510,6 +510,13 @@ int AppScheduler::GetProcessRunningInfosByUserId(std::vector<AppExecFwk::Running
return static_cast<int>(appMgrClient_->GetProcessRunningInfosByUserId(info, userId));
}
int AppScheduler::GetProcessRunningInfosByAccessTokenId(uint32_t accessTokenId,
std::vector<AppExecFwk::RunningProcessInfo> &info)
{
CHECK_POINTER_AND_RETURN(appMgrClient_, INNER_ERR);
return static_cast<int>(appMgrClient_->GetProcessRunningInfosByAccessTokenId(accessTokenId, info));
}
std::string AppScheduler::ConvertAppState(const AppState &state)
{
return StateUtils::AppStateToStrMap(state);
@@ -193,6 +193,23 @@ int32_t ExtensionRecordManager::GetActiveUIExtensionList(
return ERR_OK;
}
int32_t ExtensionRecordManager::GetActiveUIExtensionListByUid(
int32_t uid, std::vector<std::string> &extensionList)
{
TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
std::lock_guard<std::mutex> lock(mutex_);
for (const auto &it : extensionRecords_) {
if (it.second == nullptr || it.second->abilityRecord_ == nullptr ||
uid != it.second->abilityRecord_->GetUid()) {
continue;
}
extensionList.push_back(it.second->abilityRecord_->GetAbilityInfo().moduleName + SEPARATOR +
it.second->abilityRecord_->GetAbilityInfo().name);
}
return ERR_OK;
}
int32_t ExtensionRecordManager::GetOrCreateExtensionRecord(const AAFwk::AbilityRequest &abilityRequest,
const std::string &hostBundleName, std::shared_ptr<AAFwk::BaseExtensionRecord> &abilityRecord, bool &isLoaded)
{
@@ -14,9 +14,11 @@
*/
#include "modular_object_manager.h"
#include "ability_manager_errors.h"
#include "hilog_tag_wrapper.h"
#include "modular_object_rdb_storage_mgr.h"
#include "os_account_manager_wrapper.h"
using namespace OHOS::AAFwk;
namespace OHOS {
namespace AbilityRuntime {
@@ -30,4 +32,4 @@ int32_t ModularObjectManager::QuerySelfModularObjectExtensionInfos(int32_t userI
return DelayedSingleton<ModularObjectExtensionRdbStorageMgr>::GetInstance()->QueryData(key, infos);
}
}
}
}
@@ -0,0 +1,233 @@
/*
* 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 "modular_object_utils.h"
#include <singleton.h>
#include "ability_manager_errors.h"
#include "ability_manager_service.h"
#include "ability_util.h"
#include "app_mgr_client.h"
#include "app_utils.h"
#include "bundle_mgr_helper.h"
#include "hilog_tag_wrapper.h"
#include "ipc_skeleton.h"
#include "modular_object_rdb_storage_mgr.h"
#include "os_account_manager_wrapper.h"
#include "parameters.h"
#include "running_process_info.h"
#include "scene_board_judgement.h"
using namespace OHOS::AppExecFwk;
namespace OHOS {
namespace AAFwk {
int32_t ModularObjectUtils::CheckPermission(const AbilityRequest &abilityRequest)
{
if (!AppUtils::GetInstance().IsSupportModularObjectExtension()) {
TAG_LOGE(AAFwkTag::EXT, "device not supported");
return ERR_CAPABILITY_NOT_SUPPORT;
}
int32_t validUserId = abilityRequest.userId;
auto element = abilityRequest.want.GetElement();
std::string bundleName = element.GetBundleName();
std::string abilityName = element.GetAbilityName();
int32_t appIndex = abilityRequest.want.GetIntParam(Want::PARAM_APP_CLONE_INDEX_KEY, 0);
ModularObjectExtensionInfo targetExtensionInfo;
auto ret = GetTargetExtensionInfoFromDb(bundleName, abilityName, appIndex, validUserId, targetExtensionInfo);
if (ret != ERR_OK) {
return ret;
}
ret = CheckExtensionEnabled(targetExtensionInfo, abilityRequest);
if (ret != ERR_OK) {
return ret;
}
ret = CheckCallerForeground();
if (ret != ERR_OK) {
return ret;
}
AppExecFwk::ApplicationInfo callerAppInfo;
ret = GetCallerAppInfo(callerAppInfo);
if (ret != ERR_OK) {
return ret;
}
const auto &targetAppInfo = abilityRequest.appInfo;
ret = CheckAppDistributionType(callerAppInfo.appDistributionType, targetAppInfo.appDistributionType);
if (ret != ERR_OK) {
return ret;
}
return CheckTargetHasRunningAbility(targetAppInfo.uid, validUserId, bundleName);
}
int32_t ModularObjectUtils::CheckExtensionEnabled(const ModularObjectExtensionInfo &info,
const AbilityRequest &abilityRequest)
{
if (info.isDisabled && IPCSkeleton::GetCallingUid() != abilityRequest.uid) {
TAG_LOGE(AAFwkTag::EXT, "Extension is disabled: %{public}s/%{public}s. targetUid:%{public}d",
info.bundleName.c_str(), info.abilityName.c_str(), abilityRequest.uid);
return ERR_MODULAR_OBJECT_DISABLED;
}
return ERR_OK;
}
int32_t ModularObjectUtils::CheckCallerForeground()
{
pid_t callingPid = IPCSkeleton::GetCallingPid();
AppExecFwk::RunningProcessInfo processInfo;
auto ret = IN_PROCESS_CALL(
DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->GetRunningProcessInfoByPid(
callingPid, processInfo));
if (ret != ERR_OK) {
TAG_LOGE(AAFwkTag::EXT, "GetRunningProcessInfoByPid fail:%{public}d", ret);
return ret;
}
if (processInfo.state_ != AppExecFwk::AppProcessState::APP_STATE_FOREGROUND) {
TAG_LOGE(AAFwkTag::EXT, "Caller not foreground, callingPid: %{public}d, state: %{public}d",
callingPid, static_cast<int32_t>(processInfo.state_));
return NOT_TOP_ABILITY;
}
if (processInfo.isPreForeground) {
TAG_LOGE(AAFwkTag::EXT, "Caller is preForeground");
return NOT_TOP_ABILITY;
}
return ERR_OK;
}
int32_t ModularObjectUtils::CheckAppDistributionType(const std::string &callerAppDistributionType,
const std::string &targetAppDistributionType)
{
bool isDeveloperMode = system::GetBoolParameter("const.security.developermode.state", false);
if (isDeveloperMode) {
TAG_LOGD(AAFwkTag::EXT, "Developer mode, allow");
return ERR_OK;
}
if (callerAppDistributionType == "none") {
TAG_LOGE(AAFwkTag::EXT, "Caller appDistributionType is none, not allowed");
return ERR_PERMISSION_DENIED;
}
if (targetAppDistributionType == "none") {
TAG_LOGE(AAFwkTag::EXT, "Target appDistributionType is none, not allowed");
return ERR_PERMISSION_DENIED;
}
return ERR_OK;
}
bool ModularObjectUtils::HasRunningUIAbilityOrExtension(int32_t targetUid, int32_t userId)
{
auto service = DelayedSingleton<AbilityManagerService>::GetInstance();
if (service == nullptr) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "service is null");
return false;
}
std::vector<std::string> abilityList;
if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
auto uiAbilityManager = service->GetUIAbilityManagerByUserId(userId);
if (uiAbilityManager) {
uiAbilityManager->GetActiveAbilityList(targetUid, abilityList);
}
} else {
auto missionListManager = service->GetMissionListManagerByUserId(userId);
if (missionListManager) {
missionListManager->GetActiveAbilityList(targetUid, abilityList);
}
}
if (!abilityList.empty()) {
TAG_LOGD(AAFwkTag::ABILITYMGR, "Found running UIAbility for uid: %{public}d", targetUid);
return true;
}
auto uiExtManager = service->GetUIExtensionAbilityManagerByUserId(userId);
if (uiExtManager) {
std::vector<std::string> extensionList;
uiExtManager->GetActiveUIExtensionListByUid(targetUid, extensionList);
if (!extensionList.empty()) {
TAG_LOGD(AAFwkTag::ABILITYMGR, "Found running UIExtension for uid: %{public}d", targetUid);
return true;
}
}
TAG_LOGI(AAFwkTag::ABILITYMGR, "No UIAbility or UIExt for uid: %{public}d", targetUid);
return false;
}
int32_t ModularObjectUtils::CheckTargetHasRunningAbility(
int32_t targetUid, int32_t userId, const std::string &targetBundleName)
{
if (!HasRunningUIAbilityOrExtension(targetUid, userId)) {
TAG_LOGE(AAFwkTag::EXT,
"Target has no running UIAbility or UIExtension, uid: %{public}d, bundle: %{public}s",
targetUid, targetBundleName.c_str());
return ERR_NO_RUNNING_ABILITIES_WITH_UI;
}
return ERR_OK;
}
int32_t ModularObjectUtils::GetTargetExtensionInfoFromDb(const std::string &bundleName,
const std::string &abilityName, int32_t appIndex, int32_t validUserId,
ModularObjectExtensionInfo &targetExtensionInfo)
{
std::string key = std::to_string(validUserId) + "_" + bundleName + "_" + std::to_string(appIndex);
std::vector<ModularObjectExtensionInfo> infos;
auto ret = DelayedSingleton<ModularObjectExtensionRdbStorageMgr>::GetInstance()->QueryData(key, infos);
if (ret != ERR_OK) {
TAG_LOGE(AAFwkTag::EXT, "QueryData failed, ret: %{public}d", ret);
return ret;
}
bool found = false;
for (const auto &info : infos) {
if (info.bundleName == bundleName && info.abilityName == abilityName) {
targetExtensionInfo = info;
found = true;
break;
}
}
if (!found) {
TAG_LOGE(AAFwkTag::EXT, "Extension not found: %{public}s/%{public}s", bundleName.c_str(), abilityName.c_str());
return INNER_ERR;
}
return ERR_OK;
}
int32_t ModularObjectUtils::GetCallerAppInfo(AppExecFwk::ApplicationInfo &callerAppInfo)
{
int32_t callingUid = IPCSkeleton::GetCallingUid();
auto bundleMgrHelper = DelayedSingleton<AppExecFwk::BundleMgrHelper>::GetInstance();
CHECK_POINTER_AND_RETURN(bundleMgrHelper, INNER_ERR);
std::string callerBundleName;
int32_t callerAppIndex = 0;
auto ret = IN_PROCESS_CALL(bundleMgrHelper->GetNameAndIndexForUid(callingUid, callerBundleName, callerAppIndex));
if (ret != ERR_OK) {
TAG_LOGE(AAFwkTag::EXT, "Get caller info failed, callingUid: %{public}d, ret: %{public}d", callingUid, ret);
return INNER_ERR;
}
int32_t callerUserId = -1;
auto osAccountRet = DelayedSingleton<AppExecFwk::OsAccountManagerWrapper>::GetInstance()
->GetOsAccountLocalIdFromUid(callingUid, callerUserId);
if (osAccountRet != 0) {
TAG_LOGE(AAFwkTag::EXT, "Get caller userId failed, callingUid: %{public}d", callingUid);
return INNER_ERR;
}
if (!IN_PROCESS_CALL(bundleMgrHelper->GetApplicationInfoWithAppIndex(
callerBundleName, callerAppIndex, callerUserId, callerAppInfo))) {
TAG_LOGE(AAFwkTag::EXT, "Get caller appInfo failed, bundle: %{public}s", callerBundleName.c_str());
return INNER_ERR;
}
return ERR_OK;
}
} // namespace AAFwk
} // namespace OHOS
@@ -961,7 +961,7 @@ void UIAbilityLifecycleManager::HandleAbilitiesRequestDone(int32_t requestId, in
abilitiesRequestMap_.erase(it);
auto callerRecord = Token::GetAbilityRecordByToken(abilitiesRequest->callerToken);
if (callerRecord == nullptr) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "startUIAbilities callerRecord not exist.");
TAG_LOGW(AAFwkTag::ABILITYMGR, "startUIAbilities callerRecord not exist.");
return;
}
callerRecord->NotifyAbilitiesRequestDone(abilitiesRequest->requestKey,
@@ -983,7 +983,7 @@ void UIAbilityLifecycleManager::HandleAbilitiesRequestDone(int32_t requestId, in
abilitiesRequestMap_.erase(it);
auto callerRecord = Token::GetAbilityRecordByToken(abilitiesRequest->callerToken);
if (callerRecord == nullptr) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "startUIAbilities callerRecord not exist.");
TAG_LOGW(AAFwkTag::ABILITYMGR, "startUIAbilities callerRecord not exist.");
return;
}
callerRecord->NotifyAbilitiesRequestDone(abilitiesRequest->requestKey, ret);
@@ -316,6 +316,13 @@ int32_t UIExtensionAbilityManager::GetActiveUIExtensionList(
return uiExtensionAbilityRecordMgr_->GetActiveUIExtensionList(bundleName, extensionList);
}
int32_t UIExtensionAbilityManager::GetActiveUIExtensionListByUid(
int32_t uid, std::vector<std::string> &extensionList)
{
CHECK_POINTER_AND_RETURN(uiExtensionAbilityRecordMgr_, ERR_NULL_OBJECT);
return uiExtensionAbilityRecordMgr_->GetActiveUIExtensionListByUid(uid, extensionList);
}
bool UIExtensionAbilityManager::IsUIExtensionFocused(uint32_t uiExtensionTokenId, const sptr<IRemoteObject>& focusToken)
{
TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
+13
View File
@@ -239,6 +239,19 @@ public:
*/
virtual int32_t GetProcessRunningInfosByUserId(std::vector<RunningProcessInfo> &info, int32_t userId) override;
/**
* GetProcessRunningInfosByAccessTokenId, call GetProcessRunningInfosByAccessTokenId()
* through proxy project. Obtains information about application processes
* that are running on the device by accessTokenId.
*
* @param accessTokenId, accessTokenId.
* @param info, Running process information list.
*
* @return Returns ERR_OK on success, others on failure.
*/
virtual int32_t GetProcessRunningInfosByAccessTokenId(uint32_t accessTokenId,
std::vector<RunningProcessInfo> &info) override;
/**
* GetProcessRunningInformation, call GetProcessRunningInformation() through proxy project.
* Obtains information about current application process which is running on the device.
@@ -561,6 +561,18 @@ public:
*/
virtual int32_t GetProcessRunningInfosByUserId(std::vector<RunningProcessInfo> &info, int32_t userId);
/**
* GetProcessRunningInfosByAccessTokenId, Obtains information about application processes
* that are running on the device by accessTokenId.
*
* @param accessTokenId, accessTokenId.
* @param info, Running process information list.
*
* @return ERR_OK ,return back successothers fail.
*/
virtual int32_t GetProcessRunningInfosByAccessTokenId(uint32_t accessTokenId,
std::vector<RunningProcessInfo> &info);
/**
* GetProcessRunningInformation, Obtains information about current application process
* which is running on the device.
@@ -1084,7 +1096,6 @@ public:
int32_t NotifyAppMgrRecordExitReasonCompability(
int32_t pid, int32_t killId, const std::string &killMsg, const std::string &innerMsg);
#ifdef APP_MGR_KILL_REASON_TAG
void RecordAppWithReason(int32_t pid, int32_t uid, int32_t killId);
void RecordAppWithReasonByUserId(int32_t userId, int32_t killId);
#endif
@@ -231,6 +231,13 @@ public:
*/
int32_t GetUid() const;
/**
* @brief Obtains the application accessTokenId.
*
* @return Returns the application accessTokenId.
*/
uint32_t GetAccessTokenId() const;
/**
* @brief Setting the application uid.
*
+13
View File
@@ -604,6 +604,19 @@ int32_t AppMgrService::GetProcessRunningInfosByUserId(std::vector<RunningProcess
return appMgrServiceInner_->GetProcessRunningInfosByUserId(info, userId);
}
int32_t AppMgrService::GetProcessRunningInfosByAccessTokenId(uint32_t accessTokenId,
std::vector<RunningProcessInfo> &info)
{
if (!IsReady()) {
return ERR_INVALID_OPERATION;
}
if (IPCSkeleton::GetCallingPid() != getprocpid()) {
TAG_LOGE(AAFwkTag::APPMGR, "calling pid is not local process");
return ERR_PERMISSION_DENIED;
}
return appMgrServiceInner_->GetProcessRunningInfosByAccessTokenId(accessTokenId, info);
}
int32_t AppMgrService::GetProcessRunningInformation(RunningProcessInfo &info)
{
if (!IsReady()) {
+16 -6
View File
@@ -3952,6 +3952,21 @@ int32_t AppMgrServiceInner::GetProcessRunningInfosByUserId(std::vector<RunningPr
return ERR_OK;
}
int32_t AppMgrServiceInner::GetProcessRunningInfosByAccessTokenId(uint32_t accessTokenId,
std::vector<RunningProcessInfo> &info)
{
for (const auto &item : appRunningManager_->GetAppRunningRecordMap()) {
const auto &appRecord = item.second;
if (!appRecord || !appRecord->GetSpawned()) {
continue;
}
if (appRecord->GetAccessTokenId() == accessTokenId) {
GetRunningProcesses(appRecord, info);
}
}
return ERR_OK;
}
int32_t AppMgrServiceInner::GetProcessRunningInformation(RunningProcessInfo &info)
{
if (!appRunningManager_) {
@@ -4153,6 +4168,7 @@ void AppMgrServiceInner::GetRunningProcess(const std::shared_ptr<AppRunningRecor
info.processName_ = appRecord->GetProcessName();
info.pid_ = appRecord->GetPid();
info.uid_ = appRecord->GetUid();
info.accessTokenId_ = appRecord->GetAccessTokenId();
info.state_ = static_cast<AppProcessState>(appRecord->GetState());
info.isContinuousTask = appRecord->IsContinuousTask();
info.isKeepAlive = appRecord->IsKeepAliveApp();
@@ -9062,12 +9078,6 @@ void AppMgrServiceInner::RecordAppfreezeKillReason(int32_t pid, const FaultData
AbilityManagerClient::GetInstance()->KillAppWithReason(pid, exitReason);
}
void AppMgrServiceInner::RecordAppWithReason(int32_t pid, int32_t uid, int32_t killId)
{
AAFwk::ExitReasonCompability exitReasonCompability(killId);
AbilityManagerClient::GetInstance()->RecordAppWithReason(pid, uid, exitReasonCompability);
}
void AppMgrServiceInner::RecordAppWithReasonByUserId(int32_t userId, int32_t killId)
{
AAFwk::ExitReasonCompability exitReasonCompability(killId);
+1 -4
View File
@@ -761,10 +761,6 @@ std::shared_ptr<AppRunningRecord> AppRunningManager::OnRemoteDied(const wptr<IRe
TAG_LOGI(AAFwkTag::APPMGR, "pname: %{public}s, pid: %{public}d", appRecord->GetProcessName().c_str(),
priorityObject->GetPid());
if (appMgrServiceInner != nullptr) {
#ifdef APP_MGR_KILL_REASON_TAG
appMgrServiceInner->RecordAppWithReason(priorityObject->GetPid(), appRecord->GetUid(),
HiviewDFX::ProcessKillReason::KillEventId::REASON_ON_REMOTE_DIED);
#endif
appMgrServiceInner->KillProcessByPid(priorityObject->GetPid(), "OnRemoteDied");
}
AbilityRuntime::FreezeUtil::GetInstance().DeleteAppLifecycleEvent(priorityObject->GetPid());
@@ -1108,6 +1104,7 @@ int32_t AppRunningManager::AssignRunningProcessInfoByAppRecord(
info.processName_ = appRecord->GetProcessName();
info.pid_ = appRecord->GetPid();
info.uid_ = appRecord->GetUid();
info.accessTokenId_ = appRecord->GetAccessTokenId();
info.bundleNames.emplace_back(appRecord->GetBundleName());
info.state_ = static_cast<AppExecFwk::AppProcessState>(appRecord->GetState());
info.isContinuousTask = appRecord->IsContinuousTask();
@@ -208,6 +208,14 @@ int32_t AppRunningRecord::GetUid() const
return mainUid_;
}
uint32_t AppRunningRecord::GetAccessTokenId() const
{
if (appInfo_ != nullptr) {
return appInfo_->accessTokenId;
}
return 0;
}
void AppRunningRecord::SetUid(const int32_t uid)
{
mainUid_ = uid;
@@ -26,7 +26,7 @@ namespace SupportSystemAbilityPermission {
constexpr std::array SUPPORTED_UIDS{1002, 1003, 1004, 1007, 1010, 1013, 1014,
1016, 1017, 1019, 1021, 1022, 1023, 1024, 1027, 1028, 1029, 1032, 1036, 1037, 1043, 1047,
1048, 1065, 1077, 1080, 1088, 1089, 1097, 1098, 1100, 1101, 1102, 1103, 1112, 1113,
1114, 1115, 1201, 1202, 1250, 2000, 2001, 3001, 3006, 3007, 3009, 3010, 3011, 3012, 3013, 3019, 3020,
1114, 1115, 1201, 1202, 1250, 2001, 3001, 3006, 3007, 3009, 3010, 3011, 3012, 3013, 3019, 3020,
3021, 3022, 3023, 3024, 3025, 3026, 3027, 3028, 3029, 3030, 3031, 3032, 3033, 3034, 3035, 3036, 3037, 3038,
3039, 3040, 3041, 3042, 3043, 3044, 3045, 3047, 3048, 3049, 3053, 3056,
3058, 3059, 3060, 3061, 3062, 3064, 3065, 3068, 3070, 3071, 3072, 3073, 3074, 3075, 3077,
@@ -45,6 +45,8 @@ public:
MOCK_METHOD1(NotifyProcMemoryLevel, int32_t(const std::map<pid_t, MemoryLevel> &procLevelMap));
MOCK_METHOD2(DumpHeapMemory, int(const int32_t pid, OHOS::AppExecFwk::MallocInfo &mallocInfo));
MOCK_METHOD2(GetProcessRunningInfosByUserId, int(std::vector<RunningProcessInfo>& info, int32_t userId));
MOCK_METHOD2(GetProcessRunningInfosByAccessTokenId, int32_t(uint32_t accessTokenId,
std::vector<RunningProcessInfo>& info));
MOCK_METHOD4(StartUserTestProcess, int(const AAFwk::Want& want, const sptr<IRemoteObject>& observer,
const BundleInfo& bundleInfo, int32_t userId));
MOCK_METHOD3(FinishUserTest, int(const std::string& msg, const int64_t& resultCode,

Some files were not shown because too many files have changed in this diff Show More