!16843 merge ani_0925 into master

add setMissionWindowIcon

Created-by: yue-chy
Commit-by: yuechunyang
Merged-by: openharmony_ci
Description: **IssueNo**:
https://gitcode.com/openharmony/window_window_manager/issues/12134
**Description**:
Add setMissionWindowIcon
**稳定性自检:**
| 自检项                                                       | 自检结果  |
| ------------------------------------------------------------ | -------- |
| 涉及跨进程调用的相关操作需要抛至主线程或加锁防止并发              |   完成   |
| 成员变量进行赋值或创建需要排查并发                               |   完成   |
| 谨慎在lambda表达式中使用引用捕获                                |   完成   |
| 谨慎在未经拷贝的情况下使用外部传入的string、C字符串               |   完成   |
| map\vector\list\set等stl模板类使用时需要排查并发                |   完成   |
| 谨慎考虑加锁范围                                               |   完成   |
| 在IPC通信中谨慎使用同步通信方式                                 |   完成   |
| 禁止传递this指针至其他模块或线程(特别是eventhandler任务)        |   完成   |
| 禁止将外部传入的裸指针在内部直接构造智能指针                      |   完成   |
| 禁止多个独立创建的智能指针管理同一地址                           |   完成   |
| 禁止在析构函数中抛异步任务                                      |   完成   |
| 禁止js对象在非js线程(例如在IPC线程)创建、使用或销毁             |   完成   |
| 禁止在对外接口中未经判空直接使用外部传入的指针                    |   完成   |
| 禁止接口返回局部变量引用                                        |   完成   |
| 禁止在信号函数中加锁                                            |   完成   |
| 禁止在关键流程(SA启动、应用启动等主流程)执行耗时的操作           |   完成   |
| 禁止将同一个cpp编译在不同的so中                                 |   完成   |

**安全编码自检:**
| 自检项                                                          | 自检结果 |
| -------------------------------------------------------------- | -------- |
| 裸指针避免通过隐式转换构造为sptr                                 |   完成   |
| json对象在取值之前必须先判断类型,避免类型不匹配                   |   完成   |
| 序列化时必须对传入的数组大小进行校验,避免出现超大数组              |   完成   |
| 避免使用未明确位宽的整型,选择使用int8_t、uint8_t等类型            |   完成   |
| 外部传入的路径要做规范化校验,对路径中的.、..、../等特殊字符严格校验 |   完成   |
| 指针变量、表示资源描述符的变量、bool变量必须赋初值                  |   完成   |
| readParcelable获取的对象使用前需要判空                            |   完成   |
| 分配和释放内存的函数需要成对出现                                   |   完成   |
| 申请内存后异常退出前需要及时进行内存释放                            |   完成   |
| 内存申请前必须对内存大小进行合法性校验                              |   完成   |
| 内存分配后必须判断是否成功                                         |   完成   |
| 禁止使用realloc、alloca函数                                       |   完成   |
| 禁止打印文件路径、口令等敏感信息,如有需要,使用private修饰          |   完成   |
| 禁止打印内存地址                                                  |   完成   |
| 整数之间运算时必须严格检查,确保不会出现溢出、反转、除0               |   完成   |
| 禁止对有符号整数进行位操作符运算                                    |   完成   |
| 禁止对指针进行逻辑或位运算                                         |   完成   |
| 循环次数如果收外部数据控制,需要检验其合法性                         |   完成   |
| 禁止使用内存操作类危险函数,需要使用安全函数                         |   完成   |
| 谨慎使用不可重入函数                                               |   完成   |
| 必须检查安全函数的返回值,并进行正确处理                             |   完成   |
| 禁止仅通过TokenType类型判断绕过权限校验                             |   完成   |

**TDD Result**:
![image.png](https://raw.gitcode.com/user-images/assets/4421702/de8c577c-32f5-4547-abcd-5b579d24bf56/image.png 'image.png')
**XTS Result**:
新增接口,不涉及
### 是否已执行L0用例
- [ ] 已验证
- [x] 不涉及。如不涉及,请写明理由
新增接口,不涉及

See merge request: openharmony/ability_ability_runtime!16843
This commit is contained in:
openharmony_ci
2025-10-18 16:00:12 +08:00
15 changed files with 204 additions and 0 deletions
@@ -111,6 +111,8 @@ public:
static EtsAbilityContext *GetEtsAbilityContext(ani_env *env, ani_object aniObj);
static void ConfigurationUpdated(ani_env *env, std::shared_ptr<AppExecFwk::ETSNativeReference> etsContext,
std::shared_ptr<AppExecFwk::Configuration> config);
static void SetMissionWindowIcon(ani_env *env, ani_object aniObj, ani_object pixelMapObj,
ani_object callbackobj);
private:
void InheritWindowMode(ani_env *env, ani_object aniObj, AAFwk::Want &want);
@@ -146,6 +148,8 @@ private:
ani_env *env, ani_object aniObj, ani_string aniAppId, ani_object callbackObj, ani_object optionsObj);
void OnStartSelfUIAbilityInCurrentProcess(ani_env *env, ani_object aniObj,
ani_object wantObj, ani_string aniSpecifiedFlag, ani_object opt, ani_object call);
void OnSetMissionWindowIcon(ani_env *env, ani_object aniObj, ani_object pixelMapObj,
ani_object callbackObj);
void UnWrapOpenLinkOptions(ani_env *env, ani_object optionsObj, AAFwk::OpenLinkOptions &openLinkOptions,
AAFwk::Want &want);
@@ -32,6 +32,9 @@
#include "hilog_tag_wrapper.h"
#include "hitrace_meter.h"
#include "want.h"
#ifdef SUPPORT_GRAPHICS
#include "pixel_map_taihe_ani.h"
#endif
#include "ets_ui_service_proxy.h"
#include "ets_uiservice_ability_connection.h"
#include "ets_ui_ability_servicehost_stub_impl.h"
@@ -404,6 +407,18 @@ void EtsAbilityContext::RequestModalUIExtension(ani_env *env, ani_object aniObj,
etsContext->OnRequestModalUIExtension(env, aniObj, pickerWantObj, callbackobj);
}
void EtsAbilityContext::SetMissionWindowIcon(ani_env *env, ani_object aniObj, ani_object pixelMapObj,
ani_object callbackobj)
{
TAG_LOGD(AAFwkTag::CONTEXT, "SetMissionWindowIcon called");
auto etsContext = GetEtsAbilityContext(env, aniObj);
if (etsContext == nullptr) {
TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext");
return;
}
etsContext->OnSetMissionWindowIcon(env, aniObj, pixelMapObj, callbackobj);
}
void EtsAbilityContext::BackToCallerAbilityWithResult(ani_env *env, ani_object aniObj,
ani_object abilityResultObj, ani_string requestCodeObj, ani_object callBackObj)
{
@@ -926,6 +941,34 @@ void EtsAbilityContext::OnRequestModalUIExtension(ani_env *env, ani_object aniOb
AppExecFwk::AsyncCallback(env, callbackObj, errorObject, nullptr);
}
void EtsAbilityContext::OnSetMissionWindowIcon(ani_env *env, ani_object aniObj, ani_object pixelMapObj,
ani_object callbackObj)
{
ani_object errorObject = nullptr;
#ifdef SUPPORT_SCREEN
auto pixelMap = Media::PixelMapTaiheAni::GetNativePixelMap(env, pixelMapObj);
if (pixelMap == nullptr) {
TAG_LOGE(AAFwkTag::CONTEXT, "pixelMap is nullptr");
errorObject = EtsErrorUtil::CreateErrorByNativeErr(env,
static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INVALID_PARAM));
AppExecFwk::AsyncCallback(env, callbackObj, errorObject, nullptr);
return;
}
auto context = context_.lock();
if (context == nullptr) {
TAG_LOGE(AAFwkTag::CONTEXT, "null context");
errorObject = EtsErrorUtil::CreateErrorByNativeErr(env,
static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
AppExecFwk::AsyncCallback(env, callbackObj, errorObject, nullptr);
return;
}
auto ret = context->SetMissionWindowIcon(pixelMap);
errorObject = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast<int32_t>(ret));
#endif
AppExecFwk::AsyncCallback(env, callbackObj, errorObject, nullptr);
}
void EtsAbilityContext::OnBackToCallerAbilityWithResult(ani_env *env, ani_object aniObj,
ani_object abilityResultObj, ani_string requestCodeObj, ani_object callBackObj)
{
@@ -1797,6 +1840,9 @@ bool BindNativeMethods(ani_env *env, ani_class &cls)
reinterpret_cast<void *>(EtsAbilityContext::StartSelfUIAbilityInCurrentProcessWithOptions) },
ani_native_function { "nativeRestartAppSync", "L@ohos/app/ability/Want/Want;:V",
reinterpret_cast<void*>(EtsAbilityContext::RestartAppWithWindow) },
ani_native_function { "nativeSetMissionWindowIcon",
"L@ohos/multimedia/image/image/PixelMap;Lutils/AbilityUtils/AsyncCallbackWrapper;:V",
reinterpret_cast<void*>(EtsAbilityContext::SetMissionWindowIcon) },
};
if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) {
TAG_LOGE(AAFwkTag::CONTEXT, "Class_BindNativeMethods failed status: %{public}d", status);
@@ -32,6 +32,7 @@ import AtomicServiceOptions from '@ohos.app.ability.AtomicServiceOptions';
import UIServiceProxy from 'application.UIServiceProxy';
import UIServiceExtensionConnectCallback from 'application.UIServiceExtensionConnectCallback';
import dialogRequest from '@ohos.app.ability.dialogRequest';
import image from '@ohos.multimedia.image';
class Cleaner {
public ptr: long = 0;
@@ -146,6 +147,9 @@ export default class UIAbilityContext extends Context {
private native nativeStartSelfUIAbilityInCurrentProcessSync(want: Want, specifiedFlag: string, callback: AsyncCallbackWrapper<void>): void;
private native nativeStartSelfUIAbilityInCurrentProcessSync(want: Want, specifiedFlag: string, options: StartOptions, callback: AsyncCallbackWrapper<void>): void;
private native nativeSetMissionWindowIcon(windowIcon: image.PixelMap, callback: AsyncCallbackWrapper<void>): void;
startAbility(want: Want, callback: AsyncCallback<void>): void {
let myCall = new AsyncCallbackWrapper<void>(callback);
taskpool.execute((): void => {
@@ -591,4 +595,19 @@ export default class UIAbilityContext extends Context {
this.nativeRestartAppSync(want);
}) as Promise<void>;
}
setMissionWindowIcon(windowIcon: image.PixelMap): Promise<void> {
return new Promise<void>((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => {
let syncCall = new AsyncCallbackWrapper<void>((err: BusinessError | null) => {
if (err == null || err.code == 0) {
resolve(undefined);
} else {
reject(err);
}
});
taskpool.execute(() => {
this.nativeSetMissionWindowIcon(windowIcon, syncCall);
});
});
}
}
@@ -197,6 +197,10 @@ class AbilityContext extends Context {
return this.__context_impl__.setMissionIcon(icon, callback);
}
setMissionWindowIcon(windowIcon) {
return this.__context_impl__.setMissionWindowIcon(windowIcon);
}
setAbilityInstanceInfo(label, callback) {
return this.__context_impl__.setAbilityInstanceInfo(label, callback);
}
@@ -34,6 +34,7 @@
#include "string_wrapper.h"
#ifdef SUPPORT_SCREEN
#include "session/host/include/zidl/session_interface.h"
#include "session_manager_lite.h"
#include "scene_board_judgement.h"
#include "ui_content.h"
#endif // SUPPORT_SCREEN
@@ -41,6 +42,19 @@
namespace OHOS {
namespace AbilityRuntime {
namespace {
#ifdef SUPPORT_SCREEN
static std::unordered_map<Rosen::WSError, int32_t> SCB_TO_MISSION_ERROR_CODE_MAP {
{ Rosen::WSError::WS_ERROR_INVALID_PARAM, AAFwk::INVALID_PARAMETERS_ERR },
{ Rosen::WSError::WS_ERROR_DEVICE_NOT_SUPPORT, AAFwk::ERR_CAPABILITY_NOT_SUPPORT },
{ Rosen::WSError::WS_ERROR_INVALID_WINDOW, AAFwk::ERR_MAIN_WINDOW_NOT_EXIST },
{ Rosen::WSError::WS_ERROR_IPC_FAILED, AAFwk::INNER_ERR },
};
#endif // SUPPORT_SCREEN
} // namespace
#ifdef SUPPORT_SCREEN
using OHOS::Rosen::SessionManagerLite;
#endif // SUPPORT_SCREEN
const size_t AbilityContext::CONTEXT_TYPE_ID(std::hash<const char*> {} ("AbilityContext"));
constexpr const char* START_ABILITY_TYPE = "ABILITY_INNER_START_WITH_ACCOUNT";
constexpr const char* UIEXTENSION_TARGET_TYPE_KEY = "ability.want.params.uiExtensionTargetType";
@@ -1012,6 +1026,25 @@ ErrCode AbilityContextImpl::SetMissionIcon(const std::shared_ptr<OHOS::Media::Pi
return err;
}
ErrCode AbilityContextImpl::SetMissionWindowIcon(std::shared_ptr<OHOS::Media::PixelMap> windowIcon)
{
if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
auto sceneSessionManager = SessionManagerLite::GetInstance().GetSceneSessionManagerLiteProxy();
if (sceneSessionManager == nullptr) {
return ERR_INVALID_VALUE;
}
TAG_LOGD(AAFwkTag::ABILITYMGR, "scb call, SetMissionWindowIcon");
auto err = sceneSessionManager->SetSessionIconForThirdParty(token_, windowIcon);
if (SCB_TO_MISSION_ERROR_CODE_MAP.count(err)) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "scb call, SetMissionWindowIcon err");
return SCB_TO_MISSION_ERROR_CODE_MAP[err];
}
return static_cast<int32_t>(err);
}
TAG_LOGE(AAFwkTag::CONTEXT, "device not support scene board");
return AAFwk::ERR_CAPABILITY_NOT_SUPPORT;
}
ErrCode AbilityContextImpl::SetAbilityInstanceInfo(const std::string& label,
std::shared_ptr<OHOS::Media::PixelMap> icon)
{
@@ -958,6 +958,7 @@ ohos_shared_library("ui_ability_ani") {
"hilog:libhilog",
"hisysevent:libhisysevent",
"hitrace:hitrace_meter",
"image_framework:image_taihe",
"ipc:ipc_core",
"ipc:ipc_napi",
"ipc:rpc_taihe",
@@ -474,6 +474,11 @@ napi_value JsAbilityContext::RestartAppWithWindow(napi_env env, napi_callback_in
GET_NAPI_INFO_AND_CALL(env, info, JsAbilityContext, OnRestartAppWithWindow);
}
napi_value JsAbilityContext::SetMissionWindowIcon(napi_env env, napi_callback_info info)
{
GET_NAPI_INFO_AND_CALL(env, info, JsAbilityContext, OnSetMissionWindowIcon);
}
void JsAbilityContext::ClearFailedCallConnection(
const std::weak_ptr<AbilityContext>& abilityContext, const std::shared_ptr<CallerCallBack> &callback)
{
@@ -2419,6 +2424,7 @@ napi_value CreateJsAbilityContext(napi_env env, std::shared_ptr<AbilityContext>
JsAbilityContext::StartSelfUIAbilityInCurrentProcess);
BindNativeFunction(env, object, "restartApp", moduleName,
JsAbilityContext::RestartAppWithWindow);
BindNativeFunction(env, object, "setMissionWindowIcon", moduleName, JsAbilityContext::SetMissionWindowIcon);
return object;
}
@@ -3373,6 +3379,52 @@ napi_value JsAbilityContext::OnRestartAppWithWindow(napi_env env, NapiCallbackIn
return result;
}
napi_value JsAbilityContext::OnSetMissionWindowIcon(napi_env env, NapiCallbackInfo& info)
{
#ifdef SUPPORT_SCREEN
TAG_LOGD(AAFwkTag::CONTEXT, "info.argc: %{public}d", static_cast<int>(info.argc));
if (info.argc < ARGC_ONE) {
TAG_LOGE(AAFwkTag::CONTEXT, "not enough params");
ThrowTooFewParametersError(env);
return CreateJsUndefined(env);
}
auto windowIcon = OHOS::Media::PixelMapNapi::GetPixelMap(env, info.argv[INDEX_ZERO]);
if (!windowIcon) {
TAG_LOGE(AAFwkTag::CONTEXT, "parse windowIcon failed");
ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
return CreateJsUndefined(env);
}
auto innerErrCode = std::make_shared<ErrCode>(ERR_OK);
NapiAsyncTask::ExecuteCallback execute =
[weak = context_, windowIcon, innerErrCode]() {
auto context = weak.lock();
if (!context) {
TAG_LOGW(AAFwkTag::CONTEXT, "null context");
*innerErrCode = AAFwk::ERR_INVALID_CONTEXT;
return;
}
TAG_LOGI(AAFwkTag::CONTEXT, "info.argc: %{public}d", static_cast<int>(windowIcon->GetWidth()));
*innerErrCode = context->SetMissionWindowIcon(windowIcon);
};
NapiAsyncTask::CompleteCallback complete =
[innerErrCode](napi_env env, NapiAsyncTask& task, int32_t status) {
if (*innerErrCode == ERR_OK) {
task.Resolve(env, CreateJsUndefined(env));
return;
}
task.Reject(env, CreateJsErrorByNativeErr(env, *innerErrCode));
};
napi_value result = nullptr;
NapiAsyncTask::ScheduleHighQos("JsAbilityContext::SetMissionWindowIcon",
env, CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result));
return result;
#else
return CreateJsUndefined(env);
#endif
}
int32_t JsAbilityContext::GenerateRequestCode()
{
std::lock_guard lock(requestCodeMutex_);
@@ -428,6 +428,14 @@ public:
*/
virtual ErrCode SetMissionIcon(const std::shared_ptr<OHOS::Media::PixelMap> &icon) = 0;
/**
* @brief Set mission window icon of this ability.
*
* @param windowIcon the window icon of this ability.
* @return Returns ERR_OK if success.
*/
virtual ErrCode SetMissionWindowIcon(std::shared_ptr<OHOS::Media::PixelMap> windowIcon) = 0;
/**
* @brief Set ability label and icon of this ability.
*
@@ -278,6 +278,14 @@ public:
*/
ErrCode SetMissionIcon(const std::shared_ptr<OHOS::Media::PixelMap> &icon) override;
/**
* @brief Set mission window icon of this ability.
*
* @param windowIcon the window icon of this ability.
* @return Returns ERR_OK if success.
*/
ErrCode SetMissionWindowIcon(std::shared_ptr<OHOS::Media::PixelMap> windowIcon) override;
/**
* @brief Set ability label and icon of this ability.
*
@@ -82,6 +82,7 @@ public:
static napi_value DisconnectAppServiceExtensionAbility(napi_env env, napi_callback_info info);
static napi_value StartSelfUIAbilityInCurrentProcess(napi_env env, napi_callback_info info);
static napi_value RestartAppWithWindow(napi_env env, napi_callback_info info);
static napi_value SetMissionWindowIcon(napi_env env, napi_callback_info info);
static void ConfigurationUpdated(napi_env env, std::shared_ptr<NativeReference> &jsContext,
const std::shared_ptr<AppExecFwk::Configuration> &config);
@@ -167,6 +168,7 @@ private:
napi_value ConnectExtensionAbilityCommon(napi_env env, NapiCallbackInfo& info,
AppExecFwk::ExtensionAbilityType extensionType);
napi_value OnStartSelfUIAbilityInCurrentProcess(napi_env env, NapiCallbackInfo &info);
napi_value OnSetMissionWindowIcon(napi_env env, NapiCallbackInfo &info);
static bool UnWrapWant(napi_env env, napi_value argv, AAFwk::Want& want);
static napi_value WrapWant(napi_env env, const AAFwk::Want& want);
@@ -134,6 +134,8 @@ public:
((const std::vector<uint64_t> &windowIds), (std::unordered_map<uint64_t, DisplayId> & windowDisplayIdMap)),
(override));
MOCK_METHOD(WMError, GetParentMainWindowId, (int32_t windowIds, int32_t& mainWindowId), (override));
MOCK_METHOD(WSError, SetSessionIconForThirdParty, (const sptr<IRemoteObject>& token,
const std::shared_ptr<Media::PixelMap>& icon), (override));
};
} // namespace OHOS::Rosen
#endif // MOCK_SCENE_SESSION_MANAGER_LITE_H
@@ -62,6 +62,7 @@ ohos_unittest("ability_context_impl_test") {
"googletest:gmock_main",
"googletest:gtest_main",
"hilog:libhilog",
"image_framework:image_native",
"ipc:ipc_core",
"ipc:ipc_napi",
"napi:ace_napi",
@@ -2804,5 +2804,23 @@ HWTEST_F(AbilityContextImplTest, StartSelfUIAbilityInCurrentProcess_0100, Functi
auto ret = context_->StartSelfUIAbilityInCurrentProcess(want, specifiedFlag, startOptions, false);
EXPECT_EQ(ret, ERR_OK);
}
/**
* @tc.name: Ability_Context_Impl_SetMissionWindowIcon_0100
* @tc.desc: test set mission window icon.
* @tc.type: FUNC
*/
HWTEST_F(AbilityContextImplTest, Ability_Context_Impl_SetMissionWindowIcon_0100, Function | MediumTest | Level1)
{
ASSERT_TRUE(context_ != nullptr);
auto icon = std::make_shared<Media::PixelMap>();
auto ret = context_->SetMissionWindowIcon(icon);
EXPECT_NE(ret, 0);
if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
EXPECT_EQ(ret, ERR_OK);
} else {
EXPECT_EQ(ret, AAFwk::ERR_CAPABILITY_NOT_SUPPORT);
}
}
} // namespace AppExecFwk
} // namespace OHOS
@@ -465,6 +465,10 @@ public:
{
return ERR_OK;
}
virtual ErrCode SetMissionWindowIcon(std::shared_ptr<OHOS::Media::PixelMap> windowIcon)
{
return ERR_OK;
}
virtual ErrCode SetAbilityInstanceInfo(const std::string& label,
std::shared_ptr<OHOS::Media::PixelMap> icon)
{
@@ -134,6 +134,8 @@ public:
((const std::vector<uint64_t> &windowIds), (std::unordered_map<uint64_t, DisplayId> & windowDisplayIdMap)),
(override));
MOCK_METHOD(WMError, GetParentMainWindowId, (int32_t windowIds, int32_t& mainWindowId), (override));
MOCK_METHOD(WSError, SetSessionIconForThirdParty, (const sptr<IRemoteObject>& token,
const std::shared_ptr<Media::PixelMap>& icon), (override));
};
} // namespace OHOS::Rosen
#endif // MOCK_SCENE_SESSION_MANAGER_LITE_H