diff --git a/frameworks/js/napi/wantagent/napi_want_agent.cpp b/frameworks/js/napi/wantagent/napi_want_agent.cpp index b43adac824..587c364f07 100644 --- a/frameworks/js/napi/wantagent/napi_want_agent.cpp +++ b/frameworks/js/napi/wantagent/napi_want_agent.cpp @@ -1363,6 +1363,8 @@ napi_value WantAgentOperationTypeInit(napi_env env) CreateJsValue(env, static_cast(NUMBER_OF_PARAMETERS_FOUR))); napi_set_named_property(env, objValue, "START_FOREGROUND_SERVICE", CreateJsValue(env, static_cast(NUMBER_OF_PARAMETERS_FIVE))); + napi_set_named_property(env, objValue, "START_SERVICE_EXTENSION", + CreateJsValue(env, static_cast(NUMBER_OF_PARAMETERS_SIX))); return objValue; } diff --git a/interfaces/inner_api/wantagent/include/pending_want.h b/interfaces/inner_api/wantagent/include/pending_want.h index 20bb4ff4f9..11209c1daf 100644 --- a/interfaces/inner_api/wantagent/include/pending_want.h +++ b/interfaces/inner_api/wantagent/include/pending_want.h @@ -164,6 +164,11 @@ public: int requestCode, const std::shared_ptr &want, unsigned int flags, std::shared_ptr &pendingWant); + static ErrCode GetServiceExtension( + const std::shared_ptr &context, + int requestCode, const std::shared_ptr &want, unsigned int flags, + std::shared_ptr &pendingWant); + /** * Retrieve a PendingWant that will start a foreground service. * diff --git a/interfaces/inner_api/wantagent/include/want_agent_constant.h b/interfaces/inner_api/wantagent/include/want_agent_constant.h index a571a07e31..43d8f1a1d8 100644 --- a/interfaces/inner_api/wantagent/include/want_agent_constant.h +++ b/interfaces/inner_api/wantagent/include/want_agent_constant.h @@ -122,7 +122,9 @@ public: /// /// Starts a foreground ability without a UI. /// - START_FOREGROUND_SERVICE + START_FOREGROUND_SERVICE, + + START_SERVICE_EXTENSION }; private: diff --git a/interfaces/inner_api/wantagent/src/pending_want.cpp b/interfaces/inner_api/wantagent/src/pending_want.cpp index b55ea04bf1..0a35fce631 100644 --- a/interfaces/inner_api/wantagent/src/pending_want.cpp +++ b/interfaces/inner_api/wantagent/src/pending_want.cpp @@ -182,6 +182,15 @@ ErrCode PendingWant::GetService( WantAgentConstant::OperationType::START_SERVICE, pendingWant); } +ErrCode PendingWant::GetServiceExtension( + const std::shared_ptr &context, + int requestCode, const std::shared_ptr &want, unsigned int flags, + std::shared_ptr &pendingWant) +{ + return BuildServicePendingWant(context, requestCode, want, flags, + WantAgentConstant::OperationType::START_SERVICE_EXTENSION, pendingWant); +} + ErrCode PendingWant::GetForegroundService( const std::shared_ptr &context, int requestCode, const std::shared_ptr &want, unsigned int flags, diff --git a/interfaces/inner_api/wantagent/src/want_agent_helper.cpp b/interfaces/inner_api/wantagent/src/want_agent_helper.cpp index a3c441a4eb..7727d3e507 100644 --- a/interfaces/inner_api/wantagent/src/want_agent_helper.cpp +++ b/interfaces/inner_api/wantagent/src/want_agent_helper.cpp @@ -132,6 +132,9 @@ ErrCode WantAgentHelper::GetWantAgent( case WantAgentConstant::OperationType::SEND_COMMON_EVENT: result = PendingWant::GetCommonEvent(context, requestCode, wants[0], flags, pendingWant); break; + case WantAgentConstant::OperationType::START_SERVICE_EXTENSION: + result = PendingWant::GetServiceExtension(context, requestCode, wants[0], flags, pendingWant); + break; default: TAG_LOGE(AAFwkTag::WANTAGENT, "operation type is error"); result = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER; diff --git a/services/abilitymgr/include/pending_want_manager.h b/services/abilitymgr/include/pending_want_manager.h index d9cb53343e..451c2466c4 100644 --- a/services/abilitymgr/include/pending_want_manager.h +++ b/services/abilitymgr/include/pending_want_manager.h @@ -64,7 +64,12 @@ enum class OperationType { /** * Starts a foreground ability without a UI. */ - START_FOREGROUND_SERVICE + START_FOREGROUND_SERVICE, + + /** + * Starts a service extension. + */ + START_SERVICE_EXTENSION }; enum class Flags { @@ -149,6 +154,7 @@ public: void CancelWantSenderLocked(PendingWantRecord &record, bool cleanAbility); int32_t PendingWantStartAbility(const Want &want, const sptr &startOptions, const sptr &callerToken, int32_t requestCode, const int32_t callerUid, int32_t callerTokenId); + int32_t PendingWantStartServiceExtension(Want &want, const sptr &callerToken); int32_t PendingWantStartAbilitys(const std::vector &wantsInfo, const sptr &startOptions, const sptr &callerToken, int32_t requestCode, const int32_t callerUid, int32_t callerTokenId); int32_t DeviceIdDetermine(const Want &want, const sptr &startOptions, diff --git a/services/abilitymgr/src/pending_want_manager.cpp b/services/abilitymgr/src/pending_want_manager.cpp index 8a3d09e7ce..e39503cfdd 100644 --- a/services/abilitymgr/src/pending_want_manager.cpp +++ b/services/abilitymgr/src/pending_want_manager.cpp @@ -48,6 +48,12 @@ sptr PendingWantManager::GetWantSender(int32_t callingUid, int32_t } } + if (wantSenderInfo.type == static_cast(OperationType::START_SERVICE_EXTENSION) && !isSystemApp && + !AAFwk::PermissionVerification::GetInstance()->IsSACall()) { + TAG_LOGE(AAFwkTag::WANTAGENT, "non-system app called"); + return nullptr; + } + WantSenderInfo info = wantSenderInfo; return GetWantSenderLocked(callingUid, uid, wantSenderInfo.userId, info, callerToken, appIndex); } @@ -288,6 +294,19 @@ int32_t PendingWantManager::PendingWantStartAbility(const Want &want, const sptr return result; } +int32_t PendingWantManager::PendingWantStartServiceExtension(Want &want, const sptr &callerToken) +{ + TAG_LOGI(AAFwkTag::WANTAGENT, "called"); + if (!PermissionVerification::GetInstance()->IsSystemAppCall() + && !PermissionVerification::GetInstance()->IsSACall()) { + TAG_LOGE(AAFwkTag::WANTAGENT, "non-system app called"); + return ERR_INVALID_VALUE; + } + //reset flags + want.SetFlags(0); + return DelayedSingleton::GetInstance()->StartExtensionAbility(want, callerToken); +} + int32_t PendingWantManager::PendingWantStartAbilitys(const std::vector &wantsInfo, const sptr &startOptions, const sptr &callerToken, int32_t requestCode, const int32_t callerUid, int32_t callerTokenId) diff --git a/services/abilitymgr/src/pending_want_record.cpp b/services/abilitymgr/src/pending_want_record.cpp index 9c4ff07a01..1d72fdb396 100644 --- a/services/abilitymgr/src/pending_want_record.cpp +++ b/services/abilitymgr/src/pending_want_record.cpp @@ -106,6 +106,9 @@ int32_t PendingWantRecord::SenderInner(SenderInfo &senderInfo) case static_cast(OperationType::SEND_COMMON_EVENT): res = pendingWantManager->PendingWantPublishCommonEvent(want, senderInfo, callerUid_, callerTokenId_); break; + case static_cast(OperationType::START_SERVICE_EXTENSION): + res = pendingWantManager->PendingWantStartServiceExtension(want, callerToken_); + break; default: break; } diff --git a/test/unittest/pending_want_test/pending_want_test.cpp b/test/unittest/pending_want_test/pending_want_test.cpp index 58a974938f..bc80ab98a3 100644 --- a/test/unittest/pending_want_test/pending_want_test.cpp +++ b/test/unittest/pending_want_test/pending_want_test.cpp @@ -1398,4 +1398,38 @@ HWTEST_F(PendingWantTest, PendingWant_7300, Function | MediumTest | Level1) EXPECT_EQ(callBackCancelListenerConnt, 0); callBackCancelListenerConnt = 0; } + +/* + * @tc.number : PendingWant_7400 + * @tc.name : PendingWant GetServiceExtension + * @tc.desc : 1.Get pendingWant (want is nullptr) + */ +HWTEST_F(PendingWantTest, PendingWant_7400, Function | MediumTest | Level1) +{ + int requestCode = 10; + std::shared_ptr want; + unsigned int flags = 1; + flags |= FLAG_ONE_SHOT; + std::shared_ptr pendingWant = nullptr; + PendingWant::GetServiceExtension(GetAppContext(), requestCode, want, flags, pendingWant); + EXPECT_NE(pendingWant, nullptr); +} + +/* + * @tc.number : PendingWant_7500 + * @tc.name : PendingWant GetServiceExtension + * @tc.desc : 1.Get pendingWant (context is nullptr) + */ +HWTEST_F(PendingWantTest, PendingWant_7500, Function | MediumTest | Level1) +{ + int requestCode = 10; + std::shared_ptr want = std::make_shared(); + ElementName element("device", "bundleName", "abilityName"); + want->SetElement(element); + unsigned int flags = 1; + flags |= FLAG_NO_CREATE; + std::shared_ptr pendingWant = nullptr; + PendingWant::GetServiceExtension(nullptr, requestCode, want, flags, pendingWant); + EXPECT_EQ(pendingWant, nullptr); +} } // namespace OHOS::AbilityRuntime::WantAgent