add setMissionWindowIcon

Signed-off-by: yuechunyang <yuechunyang1@h-partners.com>
This commit is contained in:
yuechunyang
2025-10-17 15:45:18 +08:00
parent 07c0ac69f9
commit 6364666cc2
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