!565 协同场景下跨设备组件状态感知

Merge pull request !565 from ql/0403
This commit is contained in:
openharmony_ci 2023-04-08 13:16:48 +00:00 committed by Gitee
commit 4652ea96de
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
16 changed files with 732 additions and 67 deletions

View File

@ -1,4 +1,4 @@
# Copyright (c) 2021-2022 Huawei Device Co., Ltd.
# Copyright (c) 2021-2023 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
@ -44,6 +44,7 @@ ohos_shared_library("distributedschedsvr") {
"src/ability_connection_wrapper_proxy.cpp",
"src/ability_connection_wrapper_stub.cpp",
"src/adapter/dnetwork_adapter.cpp",
"src/app_state_observer.cpp",
"src/bundle/bundle_manager_callback_stub.cpp",
"src/bundle/bundle_manager_internal.cpp",
"src/connect_death_recipient.cpp",
@ -76,6 +77,7 @@ ohos_shared_library("distributedschedsvr") {
"ability_base:want",
"ability_base:zuri",
"ability_runtime:ability_manager",
"ability_runtime:app_manager",
"access_token:libaccesstoken_sdk",
"bundle_framework:appexecfwk_base",
"bundle_framework:appexecfwk_core",

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2023 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_APP_STATE_OBSERVER_H
#define OHOS_APP_STATE_OBSERVER_H
#include "application_state_observer_stub.h"
namespace OHOS {
namespace DistributedSchedule {
class AppStateObserver : public AppExecFwk::ApplicationStateObserverStub {
public:
/**
* Application foreground state changed callback.
*
* @param appStateData Application Process data.
*/
void OnForegroundApplicationChanged(const AppExecFwk::AppStateData& appStateData) override;
/**
* Will be called when the ability state changes.
*
* @param abilityStateData Ability state data.
*/
void OnAbilityStateChanged(const AppExecFwk::AbilityStateData& abilityStateData) override;
/**
* Will be called when the extension state changes.
*
* @param abilityStateData Extension state data.
*/
void OnExtensionStateChanged(const AppExecFwk::AbilityStateData& abilityStateData) override;
/**
* Will be called when the process start.
*
* @param processData Process data.
*/
void OnProcessCreated(const AppExecFwk::ProcessData& processData) override;
/**
* Will be called when the process die.
*
* @param processData Process data.
*/
void OnProcessDied(const AppExecFwk::ProcessData& processData) override;
private:
int32_t count_ = 0;
std::mutex countLock_;
};
} // namespace DistributedSchedule
} // namespace OHOS
#endif // OHOS_APP_STATE_OBSERVER_H

View File

@ -124,8 +124,9 @@ public:
virtual int32_t StartShareFormFromRemote(
const std::string& remoteDeviceId, const OHOS::AppExecFwk::FormShareInfo& formShareInfo) = 0;
#endif
virtual int32_t NotifyStateChangedFromRemote(int32_t abilityState, int32_t missionId,
const AppExecFwk::ElementName& element) = 0;
virtual int32_t GetDistributedComponentList(std::vector<std::string>& distributedComponents) = 0;
virtual int32_t StopRemoteExtensionAbility(
const OHOS::AAFwk::Want& want, int32_t callerUid, uint32_t accessToken, int32_t extensionType) = 0;
virtual int32_t StopExtensionAbilityFromRemote(const OHOS::AAFwk::Want& want,
@ -179,6 +180,7 @@ public:
RELEASE_REMOTE_ABILITY = 151,
START_ABILITY_BY_CALL_FROM_REMOTE = 152,
RELEASE_ABILITY_FROM_REMOTE = 153,
NOTIFY_STATE_CHANGED_FROM_REMOTE = 154,
START_REMOTE_FREE_INSTALL = 200,
// request code for upload distributed component info

View File

@ -85,6 +85,8 @@ public:
int32_t StartShareFormFromRemote(
const std::string& remoteDeviceId, const AppExecFwk::FormShareInfo& formShareInfo) override;
#endif
int32_t NotifyStateChangedFromRemote(int32_t abilityState, int32_t missionId,
const AppExecFwk::ElementName& element) override;
int32_t GetDistributedComponentList(std::vector<std::string>& distributedComponents) override;
virtual int32_t StopRemoteExtensionAbility(
const OHOS::AAFwk::Want& want, int32_t callerUid, uint32_t accessToken, int32_t extensionType) override;

View File

@ -21,6 +21,8 @@
#include <set>
#include <unordered_map>
#include "app_mgr_interface.h"
#include "app_state_observer.h"
#include "distributed_sched_stub.h"
#include "distributed_sched_continuation.h"
#include "dms_callback_task.h"
@ -61,6 +63,19 @@ struct ProcessDiedNotifyInfo {
TargetComponent targetComponent;
};
struct CallInfo {
sptr<IRemoteObject> connect;
std::string remoteDeviceId;
};
struct ObserverInfo {
sptr<AppStateObserver> appStateObserver;
std::string srcDeviceId;
int32_t srcMissionId;
std::string dstBundleName;
std::string dstAbilityName;
};
class DistributedSchedService : public SystemAbility, public DistributedSchedStub {
DECLARE_SYSTEM_ABILITY(DistributedSchedService);
DECLARE_SINGLE_INSTANCE_BASE(DistributedSchedService);
@ -143,6 +158,9 @@ public:
void SetContinuationTimeout(int32_t missionId, int32_t timeout);
void RemoveContinuationTimeout(int32_t missionId);
std::string GetContinuaitonDevice(int32_t missionId);
int32_t NotifyStateChangedFromRemote(int32_t abilityState, int32_t missionId,
const AppExecFwk::ElementName& element) override;
int32_t NotifyStateChanged(int32_t abilityState, AppExecFwk::ElementName& element);
int32_t StopRemoteExtensionAbility(const OHOS::AAFwk::Want& want, int32_t callerUid,
uint32_t accessToken, int32_t extensionType) override;
int32_t StopExtensionAbilityFromRemote(const OHOS::AAFwk::Want& remoteWant, const CallerInfo& callerInfo,
@ -199,6 +217,10 @@ private:
void GetConnectComponentList(std::vector<std::string>& distributedComponents);
void GetCallComponentList(std::vector<std::string>& distributedComponents);
void ProcessFreeInstallOffline(const std::string& deviceId);
bool RegisterAppStateObserver(const OHOS::AAFwk::Want& want, const CallerInfo& callerInfo,
const sptr<IRemoteObject>& callbackWrapper);
void UnregisterAppStateObserver(const sptr<IRemoteObject>& callbackWrapper);
sptr<AppExecFwk::IAppMgr> GetAppManager();
int32_t CheckTargetPermission(const OHOS::AAFwk::Want& want, const CallerInfo& callerInfo,
const AccountInfo& accountInfo, int32_t flag, bool needQueryExtension);
@ -222,6 +244,10 @@ private:
std::mutex callerLock_;
std::map<sptr<IRemoteObject>, std::list<ConnectAbilitySession>> callerMap_;
sptr<IRemoteObject::DeathRecipient> callerDeathRecipientForLocalDevice_;
std::mutex observerLock_;
std::map<sptr<IRemoteObject>, ObserverInfo> observerMap_;
std::mutex callLock_;
std::map<int32_t, CallInfo> callMap_;
};
class ConnectAbilitySession {

View File

@ -66,6 +66,7 @@ private:
int32_t StartRemoteShareFormInner(MessageParcel& data, MessageParcel& reply);
int32_t StartShareFormFromRemoteInner(MessageParcel& data, MessageParcel& reply);
#endif
int32_t NotifyStateChangedFromRemoteInner(MessageParcel& data, MessageParcel& reply);
int32_t GetDistributedComponentListInner(MessageParcel& data, MessageParcel& reply);
bool CheckDmsRequestPermission();
bool CheckCallingUid();

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2023 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 "app_state_observer.h"
#include "distributed_sched_service.h"
#include "dtbschedmgr_log.h"
#include "element_name.h"
namespace OHOS {
namespace DistributedSchedule {
namespace {
const std::string TAG = "AppStateObserver";
constexpr int32_t FOREGROUND = 2;
constexpr int32_t BACKGROUND = 4;
constexpr int32_t NOTIFY_COUNT = 2;
}
void AppStateObserver::OnForegroundApplicationChanged(const AppExecFwk::AppStateData& appStateData)
{
}
void AppStateObserver::OnAbilityStateChanged(const AppExecFwk::AbilityStateData& abilityStateData)
{
HILOGD("OnAbilityStateChanged called.");
if (abilityStateData.abilityState != FOREGROUND && abilityStateData.abilityState != BACKGROUND) {
HILOGD("ability state neither foreground nor background");
return;
}
{
std::lock_guard<std::mutex> autoLock(countLock_);
count_++;
if (count_ != NOTIFY_COUNT) {
HILOGD("ignore first notify");
return;
}
count_ = 0;
}
HILOGD("abilityState = %{public}d", abilityStateData.abilityState);
AppExecFwk::ElementName element("", abilityStateData.bundleName, abilityStateData.abilityName,
abilityStateData.moduleName);
int32_t ret = DistributedSchedService::GetInstance().NotifyStateChanged(abilityStateData.abilityState, element);
HILOGD("notify callee state changed, ret = %{public}d", ret);
}
void AppStateObserver::OnExtensionStateChanged(const AppExecFwk::AbilityStateData& extensionStateData)
{
}
void AppStateObserver::OnProcessCreated(const AppExecFwk::ProcessData& processData)
{
}
void AppStateObserver::OnProcessDied(const AppExecFwk::ProcessData& processData)
{
}
} // namespace DistributedSchedule
} // namespace OHOS

View File

@ -840,6 +840,29 @@ int32_t DistributedSchedProxy::StartShareFormFromRemote(
}
#endif
int32_t DistributedSchedProxy::NotifyStateChangedFromRemote(int32_t abilityState, int32_t missionId,
const AppExecFwk::ElementName& element)
{
sptr<IRemoteObject> remote = Remote();
if (remote == nullptr) {
HILOGE("NotifyStateChangedFromRemote remote service null");
return ERR_NULL_OBJECT;
}
MessageParcel data;
if (!data.WriteInterfaceToken(DMS_PROXY_INTERFACE_TOKEN)) {
HILOGE("WriteInterfaceToken failed");
return ERR_FLATTEN_OBJECT;
}
PARCEL_WRITE_HELPER(data, Int32, abilityState);
PARCEL_WRITE_HELPER(data, Int32, missionId);
if (!data.WriteParcelable(&element)) {
HILOGE("NotifyStateChangedFromRemote write element error.");
return ERR_INVALID_VALUE;
}
MessageParcel reply;
PARCEL_TRANSACT_SYNC_RET_INT(remote, NOTIFY_STATE_CHANGED_FROM_REMOTE, data, reply);
}
int32_t DistributedSchedProxy::GetDistributedComponentList(std::vector<std::string>& distributedComponents)
{
sptr<IRemoteObject> remote = Remote();

View File

@ -82,6 +82,8 @@ const std::string CHANGE_TYPE_KEY = "changeType";
const std::string DMS_HIPLAY_ACTION = "ohos.ability.action.deviceSelect";
const std::string DMS_VERSION_ID = "dmsVersion";
const std::string DMS_VERSION = "4.0.0";
const std::string DMS_MISSION_ID = "dmsMissionId";
constexpr int32_t DEFAULT_DMS_MISSION_ID = -1;
constexpr int32_t BIND_CONNECT_RETRY_TIMES = 3;
constexpr int32_t BIND_CONNECT_TIMEOUT = 500; // 500ms
constexpr int32_t MAX_DISTRIBUTED_CONNECT_NUM = 600;
@ -761,6 +763,7 @@ void DistributedSchedService::ProcessCallerDied(const sptr<IRemoteObject>& conne
HILOGW("ProcessCallerDied connect not found");
}
}
UnregisterAppStateObserver(callbackWrapper);
int32_t result = DistributedSchedAdapter::GetInstance().ReleaseAbility(callbackWrapper, element);
if (result != ERR_OK) {
HILOGW("ProcessCallerDied failed, error: %{public}d", result);
@ -769,16 +772,28 @@ void DistributedSchedService::ProcessCallerDied(const sptr<IRemoteObject>& conne
void DistributedSchedService::HandleLocalCallerDied(const sptr<IRemoteObject>& connect)
{
std::lock_guard<std::mutex> autoLock(callerLock_);
auto it = callerMap_.find(connect);
if (it != callerMap_.end()) {
std::list<ConnectAbilitySession> sessionsList = it->second;
if (!sessionsList.empty()) {
ReportDistributedComponentChange(sessionsList.front().GetCallerInfo(), DISTRIBUTED_COMPONENT_REMOVE,
IDistributedSched::CALL, IDistributedSched::CALLER);
{
std::lock_guard<std::mutex> autoLock(callerLock_);
auto it = callerMap_.find(connect);
if (it != callerMap_.end()) {
std::list<ConnectAbilitySession> sessionsList = it->second;
if (!sessionsList.empty()) {
ReportDistributedComponentChange(sessionsList.front().GetCallerInfo(), DISTRIBUTED_COMPONENT_REMOVE,
IDistributedSched::CALL, IDistributedSched::CALLER);
}
callerMap_.erase(it);
HILOGI("remove connection success");
}
}
{
std::lock_guard<std::mutex> autoLock(callLock_);
for (auto iter = callMap_.begin(); iter != callMap_.end(); iter++) {
if (iter->second.connect == connect) {
callMap_.erase(iter);
HILOGI("remove callMap_ connect success");
break;
}
}
callerMap_.erase(it);
HILOGI("remove connection success");
}
}
@ -788,15 +803,20 @@ void DistributedSchedService::ProcessCalleeDied(const sptr<IRemoteObject>& conne
HILOGE("ProcessCalleeDied connect is null");
return;
}
std::lock_guard<std::mutex> autoLock(calleeLock_);
auto itConnect = calleeMap_.find(connect);
if (itConnect != calleeMap_.end()) {
ReportDistributedComponentChange(itConnect->second, DISTRIBUTED_COMPONENT_REMOVE,
IDistributedSched::CALL, IDistributedSched::CALLEE);
calleeMap_.erase(itConnect);
} else {
HILOGW("ProcessCalleeDied connect not found");
sptr<IRemoteObject> callbackWrapper;
{
std::lock_guard<std::mutex> autoLock(calleeLock_);
auto itConnect = calleeMap_.find(connect);
if (itConnect != calleeMap_.end()) {
ReportDistributedComponentChange(itConnect->second, DISTRIBUTED_COMPONENT_REMOVE,
IDistributedSched::CALL, IDistributedSched::CALLEE);
callbackWrapper = itConnect->second.callbackWrapper;
calleeMap_.erase(itConnect);
} else {
HILOGD("ProcessCalleeDied connect not found");
}
}
UnregisterAppStateObserver(callbackWrapper);
}
int32_t DistributedSchedService::TryStartRemoteAbilityByCall(const OHOS::AAFwk::Want& want,
@ -830,67 +850,101 @@ int32_t DistributedSchedService::TryStartRemoteAbilityByCall(const OHOS::AAFwk::
void DistributedSchedService::SaveCallerComponent(const OHOS::AAFwk::Want& want,
const sptr<IRemoteObject>& connect, const CallerInfo& callerInfo)
{
std::lock_guard<std::mutex> autoLock(callerLock_);
auto itConnect = callerMap_.find(connect);
if (itConnect == callerMap_.end()) {
connect->AddDeathRecipient(callerDeathRecipientForLocalDevice_);
ReportDistributedComponentChange(callerInfo, DISTRIBUTED_COMPONENT_ADD, IDistributedSched::CALL,
IDistributedSched::CALLER);
int32_t missionId = want.GetIntParam(DMS_MISSION_ID, DEFAULT_DMS_MISSION_ID);
HILOGD("Get missionId = %{public}d", missionId);
{
std::lock_guard<std::mutex> autoLock(callLock_);
callMap_[missionId] = {connect, want.GetElement().GetDeviceID()};
HILOGI("add connect success");
}
auto& sessionsList = callerMap_[connect];
std::string remoteDeviceId = want.GetElement().GetDeviceID();
for (auto& session : sessionsList) {
if (remoteDeviceId == session.GetDestinationDeviceId()) {
session.AddElement(want.GetElement());
// already added session for remote device
return;
{
std::lock_guard<std::mutex> autoLock(callerLock_);
auto itConnect = callerMap_.find(connect);
if (itConnect == callerMap_.end()) {
connect->AddDeathRecipient(callerDeathRecipientForLocalDevice_);
ReportDistributedComponentChange(callerInfo, DISTRIBUTED_COMPONENT_ADD, IDistributedSched::CALL,
IDistributedSched::CALLER);
}
auto& sessionsList = callerMap_[connect];
std::string remoteDeviceId = want.GetElement().GetDeviceID();
for (auto& session : sessionsList) {
if (remoteDeviceId == session.GetDestinationDeviceId()) {
session.AddElement(want.GetElement());
// already added session for remote device
return;
}
}
// connect to another remote device, add a new session to list
auto& session = sessionsList.emplace_back(callerInfo.sourceDeviceId, remoteDeviceId, callerInfo);
session.AddElement(want.GetElement());
HILOGD("add connection success");
}
// connect to another remote device, add a new session to list
auto& session = sessionsList.emplace_back(callerInfo.sourceDeviceId, remoteDeviceId, callerInfo);
session.AddElement(want.GetElement());
HILOGD("add connection success");
}
void DistributedSchedService::RemoveCallerComponent(const sptr<IRemoteObject>& connect)
{
std::lock_guard<std::mutex> autoLock(callerLock_);
auto it = callerMap_.find(connect);
if (it != callerMap_.end()) {
connect->RemoveDeathRecipient(callerDeathRecipientForLocalDevice_);
std::list<ConnectAbilitySession> sessionsList = it->second;
if (!sessionsList.empty()) {
ReportDistributedComponentChange(sessionsList.front().GetCallerInfo(), DISTRIBUTED_COMPONENT_REMOVE,
IDistributedSched::CALL, IDistributedSched::CALLER);
{
std::lock_guard<std::mutex> autoLock(callerLock_);
auto it = callerMap_.find(connect);
if (it != callerMap_.end()) {
connect->RemoveDeathRecipient(callerDeathRecipientForLocalDevice_);
std::list<ConnectAbilitySession> sessionsList = it->second;
if (!sessionsList.empty()) {
ReportDistributedComponentChange(sessionsList.front().GetCallerInfo(), DISTRIBUTED_COMPONENT_REMOVE,
IDistributedSched::CALL, IDistributedSched::CALLER);
}
callerMap_.erase(it);
HILOGI("remove connection success");
}
}
{
std::lock_guard<std::mutex> autoLock(callLock_);
for (auto iter = callMap_.begin(); iter != callMap_.end(); iter++) {
if (iter->second.connect == connect) {
callMap_.erase(iter);
HILOGI("remove callMap_ connect success");
break;
}
}
callerMap_.erase(it);
HILOGI("remove connection success");
}
}
void DistributedSchedService::ProcessCalleeOffline(const std::string& deviceId)
{
std::lock_guard<std::mutex> autoLock(callerLock_);
for (auto iter = callerMap_.begin(); iter != callerMap_.end();) {
std::list<ConnectAbilitySession>& sessionsList = iter->second;
auto itSession = std::find_if(sessionsList.begin(), sessionsList.end(), [&deviceId](const auto& session) {
return session.GetDestinationDeviceId() == deviceId;
});
CallerInfo callerInfo;
if (itSession != sessionsList.end()) {
callerInfo = itSession->GetCallerInfo();
sessionsList.erase(itSession);
}
if (sessionsList.empty()) {
if (iter->first != nullptr) {
iter->first->RemoveDeathRecipient(callerDeathRecipientForLocalDevice_);
{
std::lock_guard<std::mutex> autoLock(callerLock_);
for (auto iter = callerMap_.begin(); iter != callerMap_.end();) {
std::list<ConnectAbilitySession>& sessionsList = iter->second;
auto itSession = std::find_if(sessionsList.begin(), sessionsList.end(), [&deviceId](const auto& session) {
return session.GetDestinationDeviceId() == deviceId;
});
CallerInfo callerInfo;
if (itSession != sessionsList.end()) {
callerInfo = itSession->GetCallerInfo();
sessionsList.erase(itSession);
}
if (sessionsList.empty()) {
if (iter->first != nullptr) {
iter->first->RemoveDeathRecipient(callerDeathRecipientForLocalDevice_);
}
ReportDistributedComponentChange(callerInfo, DISTRIBUTED_COMPONENT_REMOVE,
IDistributedSched::CALL, IDistributedSched::CALLER);
callerMap_.erase(iter++);
} else {
iter++;
}
}
}
{
std::lock_guard<std::mutex> autoLock(callLock_);
for (auto iter = callMap_.begin(); iter != callMap_.end();) {
if (iter->second.remoteDeviceId == deviceId) {
iter = callMap_.erase(iter);
HILOGI("remove callMap_ connect success");
} else {
iter++;
}
ReportDistributedComponentChange(callerInfo, DISTRIBUTED_COMPONENT_REMOVE,
IDistributedSched::CALL, IDistributedSched::CALLER);
callerMap_.erase(iter++);
} else {
iter++;
}
}
}
@ -1000,6 +1054,9 @@ int32_t DistributedSchedService::StartAbilityByCallFromRemote(const OHOS::AAFwk:
calleeMap_.emplace(connect, connectInfo);
}
connect->AddDeathRecipient(callerDeathRecipient_);
if (!RegisterAppStateObserver(want, callerInfo, callbackWrapper)) {
HILOGE("RegisterAppStateObserver failed");
}
}
return errCode;
}
@ -1034,6 +1091,7 @@ int32_t DistributedSchedService::ReleaseAbilityFromRemote(const sptr<IRemoteObje
calleeMap_.erase(itConnect);
connect->RemoveDeathRecipient(callerDeathRecipient_);
}
UnregisterAppStateObserver(callbackWrapper);
int32_t result = DistributedSchedAdapter::GetInstance().ReleaseAbility(callbackWrapper, element);
HILOGD("[PerformanceTest] ReleaseAbilityFromRemote end");
if (result != ERR_OK) {
@ -2025,6 +2083,156 @@ int32_t DistributedSchedService::NotifyFreeInstallResult(const CallbackTaskItem
return item.callback->SendRequest(IASS_CALLBACK_ON_REMOTE_FREE_INSTALL_DONE, data, reply, option);
}
bool DistributedSchedService::RegisterAppStateObserver(const OHOS::AAFwk::Want& want, const CallerInfo& callerInfo,
const sptr<IRemoteObject>& callbackWrapper)
{
HILOGD("register app state observer called");
sptr<AppExecFwk::IAppMgr> appObject = GetAppManager();
if (appObject == nullptr) {
HILOGE("failed to get app manager service");
return false;
}
sptr<AppStateObserver> appStateObserver = sptr<AppStateObserver>(new (std::nothrow) AppStateObserver());
std::vector<std::string> bundleNameList = {want.GetElement().GetBundleName()};
int ret = appObject->RegisterApplicationStateObserver(appStateObserver, bundleNameList);
if (ret != ERR_OK) {
HILOGE("failed to register application state observer, ret = %{public}d", ret);
return false;
}
HILOGI("register application state observer success");
{
std::lock_guard<std::mutex> autoLock(observerLock_);
int32_t missionId = want.GetIntParam(DMS_MISSION_ID, DEFAULT_DMS_MISSION_ID);
HILOGD("Get missionId = %{public}d", missionId);
Want* newWant = const_cast<Want*>(&want);
newWant->RemoveParam(DMS_MISSION_ID);
observerMap_[callbackWrapper] = {appStateObserver, callerInfo.sourceDeviceId, missionId,
want.GetElement().GetBundleName(), want.GetElement().GetAbilityName()};
HILOGI("add observerMap_ success");
}
return true;
}
void DistributedSchedService::UnregisterAppStateObserver(const sptr<IRemoteObject>& callbackWrapper)
{
HILOGD("unregister app state observer called");
if (callbackWrapper == nullptr) {
HILOGD("callbackWrapper is nullptr");
return;
}
sptr<AppStateObserver> appStateObserver;
{
std::lock_guard<std::mutex> autoLock(observerLock_);
auto it = observerMap_.find(callbackWrapper);
if (it == observerMap_.end()) {
HILOGE("state observer not found");
return;
}
appStateObserver = it->second.appStateObserver;
observerMap_.erase(it);
HILOGI("remove app state observer success");
}
sptr<AppExecFwk::IAppMgr> appObject = GetAppManager();
if (appObject == nullptr) {
HILOGE("failed to get app manager service");
return;
}
int ret = appObject->UnregisterApplicationStateObserver(appStateObserver);
if (ret != ERR_OK) {
HILOGE("failed to unregister application state observer, ret = %{public}d", ret);
return;
}
HILOGI("unregister application state observer success");
}
sptr<AppExecFwk::IAppMgr> DistributedSchedService::GetAppManager()
{
auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (samgr == nullptr) {
HILOGE("system ability manager is nullptr.");
return nullptr;
}
sptr<AppExecFwk::IAppMgr> appObject =
iface_cast<AppExecFwk::IAppMgr>(samgr->GetSystemAbility(APP_MGR_SERVICE_ID));
if (appObject == nullptr) {
HILOGE("failed to get app manager service");
return nullptr;
}
return appObject;
}
int32_t DistributedSchedService::NotifyStateChanged(int32_t abilityState, AppExecFwk::ElementName& element)
{
std::string srcDeviceId = "";
int32_t missionId = 0;
{
std::lock_guard<std::mutex> autoLock(observerLock_);
for (auto iter = observerMap_.begin(); iter != observerMap_.end(); iter++) {
if (iter->second.dstBundleName == element.GetBundleName() &&
iter->second.dstAbilityName == element.GetAbilityName()) {
srcDeviceId = iter->second.srcDeviceId;
missionId = iter->second.srcMissionId;
HILOGD("get srcDeviceId and missionId success");
break;
}
}
HILOGE("observer not exits");
}
HILOGD("Get missionId = %{public}d", missionId);
std::string localDeviceId;
if (!GetLocalDeviceId(localDeviceId) || !CheckDeviceId(localDeviceId, srcDeviceId)) {
HILOGE("check deviceId failed");
return INVALID_PARAMETERS_ERR;
}
sptr<IDistributedSched> remoteDms = GetRemoteDms(srcDeviceId);
if (remoteDms == nullptr) {
HILOGE("get remoteDms failed");
return INVALID_PARAMETERS_ERR;
}
element.SetDeviceID(localDeviceId);
return remoteDms->NotifyStateChangedFromRemote(abilityState, missionId, element);
}
int32_t DistributedSchedService::NotifyStateChangedFromRemote(int32_t abilityState, int32_t missionId,
const AppExecFwk::ElementName& element)
{
HILOGD("Get missionId = %{public}d", missionId);
sptr<IRemoteObject> connect;
{
std::lock_guard<std::mutex> autoLock(callLock_);
auto itConnect = callMap_.find(missionId);
if (itConnect == callMap_.end()) {
HILOGE("missonId is not in callMap_");
return INVALID_PARAMETERS_ERR;
}
connect = callMap_[missionId].connect;
HILOGD("get connect success");
}
if (connect == nullptr) {
HILOGE("NotifyStateChangedFromRemote connect is null");
return INVALID_PARAMETERS_ERR;
}
MessageParcel data;
if (!data.WriteInterfaceToken(CONNECTION_CALLBACK_INTERFACE_TOKEN)) {
HILOGE("Write interface token failed.");
return INVALID_PARAMETERS_ERR;
}
PARCEL_WRITE_HELPER(data, Parcelable, &element);
PARCEL_WRITE_HELPER(data, Int32, abilityState);
MessageParcel reply;
MessageOption option(MessageOption::TF_ASYNC);
HILOGD("ON_REMOTE_STATE_CHANGED start");
int32_t result = connect->SendRequest(IAbilityConnection::ON_REMOTE_STATE_CHANGED, data, reply, option);
HILOGD("ON_REMOTE_STATE_CHANGED end, %{public}d", result);
return ERR_OK;
}
int32_t DistributedSchedService::CheckTargetPermission(const OHOS::AAFwk::Want& want,
const CallerInfo& callerInfo, const AccountInfo& accountInfo, int32_t flag, bool needQueryExtension)
{

View File

@ -116,6 +116,8 @@ void DistributedSchedStub::InitRemoteFuncsInner()
remoteFuncsMap_[CONTINUE_MISSION] = &DistributedSchedStub::ContinueMissionInner;
remoteFuncsMap_[START_ABILITY_BY_CALL_FROM_REMOTE] = &DistributedSchedStub::StartAbilityByCallFromRemoteInner;
remoteFuncsMap_[RELEASE_ABILITY_FROM_REMOTE] = &DistributedSchedStub::ReleaseAbilityFromRemoteInner;
remoteFuncsMap_[NOTIFY_STATE_CHANGED_FROM_REMOTE] =
&DistributedSchedStub::NotifyStateChangedFromRemoteInner;
#ifdef SUPPORT_DISTRIBUTED_FORM_SHARE
remoteFuncsMap_[START_SHARE_FORM_FROM_REMOTE] = &DistributedSchedStub::StartShareFormFromRemoteInner;
#endif
@ -949,6 +951,26 @@ int32_t DistributedSchedStub::GetDistributedComponentListInner(MessageParcel& da
return ERR_NONE;
}
int32_t DistributedSchedStub::NotifyStateChangedFromRemoteInner(MessageParcel& data, MessageParcel& reply)
{
if (!CheckCallingUid()) {
HILOGW("request DENIED!");
return DMS_PERMISSION_DENIED;
}
int32_t abilityState = 0;
PARCEL_READ_HELPER(data, Int32, abilityState);
int32_t missionId = 0;
PARCEL_READ_HELPER(data, Int32, missionId);
shared_ptr<AppExecFwk::ElementName> element(data.ReadParcelable<AppExecFwk::ElementName>());
if (element == nullptr) {
HILOGE("NotifyStateChangedFromRemoteInner receive element is nullptr");
return ERR_INVALID_VALUE;
}
int32_t result = NotifyStateChangedFromRemote(abilityState, missionId, *element);
HILOGI("result = %{public}d", result);
PARCEL_WRITE_REPLY_NOERROR(reply, Int32, result);
}
int32_t DistributedSchedStub::StartRemoteFreeInstallInner(MessageParcel& data, MessageParcel& reply)
{
if (!DistributedSchedPermission::GetInstance().IsFoundationCall()) {

View File

@ -37,6 +37,7 @@ dsched_external_deps = [
"ability_base:want",
"ability_base:zuri",
"ability_runtime:ability_manager",
"ability_runtime:app_manager",
"access_token:libaccesstoken_sdk",
"access_token:libnativetoken",
"access_token:libtoken_setproc",
@ -90,6 +91,7 @@ dtbschedmgr_sources = [
"${distributed_service}/dtbschedmgr/src/ability_connection_wrapper_proxy.cpp",
"${distributed_service}/dtbschedmgr/src/ability_connection_wrapper_stub.cpp",
"${distributed_service}/dtbschedmgr/src/adapter/dnetwork_adapter.cpp",
"${distributed_service}/dtbschedmgr/src/app_state_observer.cpp",
"${distributed_service}/dtbschedmgr/src/bundle/bundle_manager_callback_stub.cpp",
"${distributed_service}/dtbschedmgr/src/bundle/bundle_manager_internal.cpp",
"${distributed_service}/dtbschedmgr/src/connect_death_recipient.cpp",
@ -174,7 +176,10 @@ ohos_unittest("distributedschedsvrtest") {
ohos_unittest("distributedcalltest") {
module_out_path = module_output_path
sources = [ "unittest/distributed_sched_call_test.cpp" ]
sources = [
"unittest/app_state_observer_test.cpp",
"unittest/distributed_sched_call_test.cpp",
]
sources += dtbschedmgr_sources
configs = [
":test_config",

View File

@ -0,0 +1,115 @@
/*
* Copyright (c) 2022 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 "app_state_observer_test.h"
#include "test_log.h"
using namespace testing;
using namespace testing::ext;
namespace OHOS {
namespace DistributedSchedule {
namespace {
constexpr int32_t FOREGROUND = 2;
constexpr int32_t BACKGROUND = 4;
}
void AppStateObserverTest::SetUpTestCase()
{
DTEST_LOG << "AppStateObserverTest::SetUpTestCase" << std::endl;
}
void AppStateObserverTest::TearDownTestCase()
{
DTEST_LOG << "AppStateObserverTest::TearDownTestCase" << std::endl;
}
void AppStateObserverTest::TearDown()
{
DTEST_LOG << "AppStateObserverTest::TearDown" << std::endl;
}
void AppStateObserverTest::SetUp()
{
DTEST_LOG << "AppStateObserverTest::SetUp" << std::endl;
appStateObserver_ = new AppStateObserver();
}
/**
* @tc.name: OnAbilityStateChanged_001
* @tc.desc: call OnAbilityStateChanged from distributedsched
* @tc.type: FUNC
* @tc.require: I6SJQ6
*/
HWTEST_F(AppStateObserverTest, OnAbilityStateChanged_001, TestSize.Level3)
{
DTEST_LOG << "AppStateObserverTest OnAbilityStateChanged_001 begin" << std::endl;
AppExecFwk::AppStateData appStateData;
appStateObserver_->OnForegroundApplicationChanged(appStateData);
AppExecFwk::AbilityStateData extensionStateData;
appStateObserver_->OnExtensionStateChanged(extensionStateData);
AppExecFwk::ProcessData processData;
appStateObserver_->OnProcessCreated(processData);
appStateObserver_->OnProcessDied(processData);
AppExecFwk::AbilityStateData abilityStateData;
appStateObserver_->OnAbilityStateChanged(abilityStateData);
EXPECT_NE(appStateObserver_, nullptr);
DTEST_LOG << "AppStateObserverTest OnAbilityStateChanged_001 end" << std::endl;
}
/**
* @tc.name: OnAbilityStateChanged_002
* @tc.desc: call OnAbilityStateChanged from distributedsched
* @tc.type: FUNC
* @tc.require: I6SJQ6
*/
HWTEST_F(AppStateObserverTest, OnAbilityStateChanged_002, TestSize.Level3)
{
DTEST_LOG << "AppStateObserverTest OnAbilityStateChanged_001 begin" << std::endl;
AppExecFwk::AbilityStateData abilityStateData;
abilityStateData.abilityState = FOREGROUND;
appStateObserver_->OnAbilityStateChanged(abilityStateData);
EXPECT_NE(appStateObserver_, nullptr);
appStateObserver_->OnAbilityStateChanged(abilityStateData);
EXPECT_NE(appStateObserver_, nullptr);
DTEST_LOG << "AppStateObserverTest OnAbilityStateChanged_001 end" << std::endl;
}
/**
* @tc.name: OnAbilityStateChanged_003
* @tc.desc: call OnAbilityStateChanged from distributedsched
* @tc.type: FUNC
* @tc.require: I6SJQ6
*/
HWTEST_F(AppStateObserverTest, OnAbilityStateChanged_003, TestSize.Level3)
{
DTEST_LOG << "AppStateObserverTest OnAbilityStateChanged_001 begin" << std::endl;
AppExecFwk::AbilityStateData abilityStateData;
abilityStateData.abilityState = BACKGROUND;
appStateObserver_->OnAbilityStateChanged(abilityStateData);
EXPECT_NE(appStateObserver_, nullptr);
appStateObserver_->OnAbilityStateChanged(abilityStateData);
EXPECT_NE(appStateObserver_, nullptr);
DTEST_LOG << "AppStateObserverTest OnAbilityStateChanged_003 end" << std::endl;
}
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2022 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 DMS_TOKEN_CB_TEST_H
#define DMS_TOKEN_CB_TEST_H
#include "gtest/gtest.h"
#define private public
#include "app_state_observer.h"
#undef private
namespace OHOS {
namespace DistributedSchedule {
class AppStateObserverTest : public testing::Test {
public:
static void SetUpTestCase();
static void TearDownTestCase();
void SetUp();
void TearDown();
sptr<AppStateObserver> appStateObserver_;
};
} // namespace DistributedSchedule
} // namespace OHOS
#endif // DMS_TOKEN_CB_TEST_H

View File

@ -62,6 +62,7 @@ namespace {
const string BUNDLE_NAME = "com.ohos.launcher";
const string DMS_IS_CALLER_BACKGROUND = "dmsIsCallerBackGround";
constexpr int32_t SLEEP_TIME = 1000;
constexpr int32_t FOREGROUND = 2;
}
class DistributedSchedServiceTest : public testing::Test {
@ -1493,6 +1494,83 @@ HWTEST_F(DistributedSchedServiceTest, StartAbilityByCallFromRemote_002, TestSize
DTEST_LOG << "DistributedSchedServiceTest StartAbilityByCallFromRemote_002 end" << std::endl;
}
/**
* @tc.name: NotifyStateChangedFromRemote_001
* @tc.desc: call NotifyStateChangedFromRemote with illegal params
* @tc.type: FUNC
* @tc.require: I6SJQ6
*/
HWTEST_F(DistributedSchedServiceTest, NotifyStateChangedFromRemote_001, TestSize.Level1)
{
DTEST_LOG << "DistributedSchedServiceTest NotifyStateChangedFromRemote_001 start" << std::endl;
sptr<IDistributedSched> proxy = GetDms();
if (proxy == nullptr) {
return;
}
AppExecFwk::ElementName element("", BUNDLE_NAME, ABILITY_NAME);
int result1 = proxy->NotifyStateChangedFromRemote(0, 0, element);
DTEST_LOG << "result1:" << result1 << std::endl;
EXPECT_NE(result1, ERR_OK);
DTEST_LOG << "DistributedSchedServiceTest NotifyStateChangedFromRemote_001 end" << std::endl;
}
/**
* @tc.name: NotifyStateChanged_001
* @tc.desc: test NotifyStateChanged
* @tc.type: FUNC
* @tc.require: I6SJQ6
*/
HWTEST_F(DistributedSchedServiceTest, NotifyStateChanged_001, TestSize.Level3)
{
DTEST_LOG << "DistributedSchedServiceTest NotifyStateChanged_001 start" << std::endl;
int32_t abilityState = FOREGROUND;
std::string localDeviceId;
AppExecFwk::ElementName element(localDeviceId, BUNDLE_NAME, ABILITY_NAME);
int32_t ret = DistributedSchedService::GetInstance().NotifyStateChanged(abilityState, element);
DTEST_LOG << "ret:" << ret << std::endl;
EXPECT_EQ(ret, INVALID_PARAMETERS_ERR);
DTEST_LOG << "DistributedSchedServiceTest NotifyStateChanged_001 end" << std::endl;
}
/**
* @tc.name: NotifyStateChangedFromRemote_002
* @tc.desc: test NotifyStateChangedFromRemote
* @tc.type: FUNC
* @tc.require: I6SJQ6
*/
HWTEST_F(DistributedSchedServiceTest, NotifyStateChangedFromRemote_002, TestSize.Level3)
{
DTEST_LOG << "DistributedSchedServiceTest NotifyStateChangedFromRemote_002 start" << std::endl;
std::string localDeviceId;
DtbschedmgrDeviceInfoStorage::GetInstance().GetLocalDeviceId(localDeviceId);
AppExecFwk::ElementName element(localDeviceId, BUNDLE_NAME, ABILITY_NAME);
int ret = DistributedSchedService::GetInstance().NotifyStateChangedFromRemote(0, 0, element);
EXPECT_EQ(ret, INVALID_PARAMETERS_ERR);
DTEST_LOG << "DistributedSchedServiceTest NotifyStateChangedFromRemote_002 end" << std::endl;
}
/**
* @tc.name: NotifyStateChangedFromRemote_003
* @tc.desc: test NotifyStateChangedFromRemote
* @tc.type: FUNC
* @tc.require: I6SJQ6
*/
HWTEST_F(DistributedSchedServiceTest, NotifyStateChangedFromRemote_003, TestSize.Level3)
{
DTEST_LOG << "DistributedSchedServiceTest NotifyStateChangedFromRemote_003 start" << std::endl;
std::string localDeviceId;
DtbschedmgrDeviceInfoStorage::GetInstance().GetLocalDeviceId(localDeviceId);
AppExecFwk::ElementName element(localDeviceId, BUNDLE_NAME, ABILITY_NAME);
sptr<IRemoteObject> connect = nullptr;
DistributedSchedService::GetInstance().callMap_[0] = {connect, localDeviceId};
int ret = DistributedSchedService::GetInstance().NotifyStateChangedFromRemote(0, 0, element);
EXPECT_EQ(ret, INVALID_PARAMETERS_ERR);
DTEST_LOG << "DistributedSchedServiceTest NotifyStateChangedFromRemote_003 end" << std::endl;
}
/**
* @tc.name: ConnectAbilityFromRemote_001
* @tc.desc: test ConnectAbilityFromRemote

View File

@ -172,6 +172,12 @@ int32_t MockDistributedSched::ReleaseAbilityFromRemote(const sptr<IRemoteObject>
return ERR_NONE;
}
int32_t MockDistributedSched::NotifyStateChangedFromRemote(int32_t abilityState, int32_t missionId,
const AppExecFwk::ElementName& element)
{
return ERR_NONE;
}
int32_t MockDistributedSched::GetDistributedComponentList(std::vector<std::string>& distributedComponents)
{
return ERR_NONE;

View File

@ -73,6 +73,8 @@ public:
const CallerInfo& callerInfo, const AccountInfo& accountInfo) override;
int32_t ReleaseAbilityFromRemote(const sptr<IRemoteObject>& connect, const AppExecFwk::ElementName &element,
const CallerInfo& callerInfo) override;
int32_t NotifyStateChangedFromRemote(int32_t abilityState, int32_t missionId,
const AppExecFwk::ElementName& element) override;
int32_t GetDistributedComponentList(std::vector<std::string>& distributedComponents) override;
#ifdef SUPPORT_DISTRIBUTED_FORM_SHARE
int32_t StartRemoteShareForm(const std::string& remoteDeviceId,