1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "distributed_client.h"
17 
18 #include "ability_manager_errors.h"
19 #include "distributed_parcel_helper.h"
20 #include "iservice_registry.h"
21 #include "system_ability_definition.h"
22 
23 namespace OHOS {
24 namespace Rosen {
25 namespace {
26 const std::u16string DMS_PROXY_INTERFACE_TOKEN = u"ohos.distributedschedule.accessToken";
27 }
WM_IMPLEMENT_SINGLE_INSTANCE(DistributedClient)28 WM_IMPLEMENT_SINGLE_INSTANCE(DistributedClient)
29 
30 void DistributedClient::DmsDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
31 {
32     TLOGI(WmsLogTag::DEFAULT, "dms died");
33     DistributedClient::GetInstance().ClearDmsProxy();
34 }
35 
GetDmsProxy()36 sptr<IRemoteObject> DistributedClient::GetDmsProxy()
37 {
38     std::lock_guard<std::mutex> lock(mutex_);
39     if (dmsProxy_ == nullptr) {
40         ConnectDistributedSchedLocked();
41     }
42     return dmsProxy_;
43 }
44 
ConnectDistributedSchedLocked()45 void DistributedClient::ConnectDistributedSchedLocked()
46 {
47     auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
48     if (samgrProxy == nullptr) {
49         TLOGE(WmsLogTag::DEFAULT, "fail to get samgr");
50         return;
51     }
52     auto proxy = samgrProxy->CheckSystemAbility(DISTRIBUTED_SCHED_SA_ID);
53     if (!proxy) {
54         TLOGW(WmsLogTag::DEFAULT, "get dms proxy failed");
55         return;
56     }
57     dmsDeath_ = sptr<DmsDeathRecipient>::MakeSptr();
58     if (proxy->IsProxyObject() && !proxy->AddDeathRecipient(dmsDeath_)) {
59         TLOGE(WmsLogTag::DEFAULT, "failed to add death recipient");
60         return;
61     }
62     dmsProxy_ = proxy;
63     TLOGI(WmsLogTag::DEFAULT, "success");
64 }
65 
ClearDmsProxy()66 void DistributedClient::ClearDmsProxy()
67 {
68     TLOGI(WmsLogTag::DEFAULT, "in");
69     std::lock_guard<std::mutex> lock(mutex_);
70     dmsProxy_ = nullptr;
71     dmsDeath_ = nullptr;
72 }
73 
GetMissionInfos(const std::string & deviceId,int32_t numMissions,std::vector<AAFwk::MissionInfo> & missionInfos)74 int32_t DistributedClient::GetMissionInfos(const std::string& deviceId, int32_t numMissions,
75                                            std::vector<AAFwk::MissionInfo>& missionInfos)
76 {
77     TLOGI(WmsLogTag::DEFAULT, "called");
78     sptr<IRemoteObject> remote = GetDmsProxy();
79     if (remote == nullptr) {
80         TLOGE(WmsLogTag::DEFAULT, "remote system abiity is null");
81         return AAFwk::INVALID_PARAMETERS_ERR;
82     }
83 
84     MessageParcel data;
85     MessageParcel reply;
86     MessageOption option;
87     if (!data.WriteInterfaceToken(DMS_PROXY_INTERFACE_TOKEN)) {
88         return ERR_FLATTEN_OBJECT;
89     }
90     PARCEL_WRITE_HELPER(data, String16, Str8ToStr16(deviceId));
91     PARCEL_WRITE_HELPER(data, Int32, numMissions);
92     int32_t ret = remote->SendRequest(GET_MISSION_INFOS, data, reply, option);
93     if (ret != ERR_NONE) {
94         TLOGW(WmsLogTag::DEFAULT, "sendRequest fail, error: %{public}d", ret);
95         return ret;
96     }
97     return ReadMissionInfosFromParcel(reply, missionInfos) ? ERR_NONE : ERR_FLATTEN_OBJECT;
98 }
99 
GetRemoteMissionSnapshotInfo(const std::string & deviceId,int32_t missionId,AAFwk::MissionSnapshot & missionSnapshot)100 int32_t DistributedClient::GetRemoteMissionSnapshotInfo(const std::string& deviceId, int32_t missionId,
101                                                         AAFwk::MissionSnapshot& missionSnapshot)
102 {
103     if (deviceId.empty()) {
104         TLOGE(WmsLogTag::DEFAULT, "deviceId is null");
105         return ERR_NULL_OBJECT;
106     }
107     sptr<IRemoteObject> remote = GetDmsProxy();
108     if (remote == nullptr) {
109         TLOGE(WmsLogTag::DEFAULT, "remote is null");
110         return AAFwk::INVALID_PARAMETERS_ERR;
111     }
112     MessageParcel data;
113     if (!data.WriteInterfaceToken(DMS_PROXY_INTERFACE_TOKEN)) {
114         return ERR_FLATTEN_OBJECT;
115     }
116     PARCEL_WRITE_HELPER(data, String, deviceId);
117     PARCEL_WRITE_HELPER(data, Int32, missionId);
118     MessageParcel reply;
119     MessageOption option;
120     int32_t error = remote->SendRequest(GET_REMOTE_MISSION_SNAPSHOT_INFO, data, reply, option);
121     if (error != ERR_NONE) {
122         TLOGE(WmsLogTag::DEFAULT, "transact failed, error: %{public}d", error);
123         return error;
124     }
125     std::unique_ptr<AAFwk::MissionSnapshot> missionSnapshotPtr(reply.ReadParcelable<AAFwk::MissionSnapshot>());
126     if (missionSnapshotPtr == nullptr) {
127         TLOGE(WmsLogTag::DEFAULT, "missionSnapshotPtr is null");
128         return ERR_UNKNOWN_OBJECT;
129     }
130     missionSnapshot = *missionSnapshotPtr;
131     return ERR_NONE;
132 }
133 
ReadMissionInfosFromParcel(Parcel & parcel,std::vector<AAFwk::MissionInfo> & missionInfos)134 bool DistributedClient::ReadMissionInfosFromParcel(Parcel& parcel,
135                                                    std::vector<AAFwk::MissionInfo>& missionInfos)
136 {
137     int32_t hasMissions = parcel.ReadInt32();
138     if (hasMissions == 1) {
139         int32_t len = parcel.ReadInt32();
140         TLOGD(WmsLogTag::DEFAULT, "readLength is:%{public}d", len);
141         if (len < 0) {
142             return false;
143         }
144         size_t size = static_cast<size_t>(len);
145         if ((size > parcel.GetReadableBytes()) || (missionInfos.max_size() < size)) {
146             TLOGE(WmsLogTag::DEFAULT, "Failed to read MissionInfo vector, size = %{public}zu", size);
147             return false;
148         }
149         missionInfos.clear();
150         for (size_t i = 0; i < size; i++) {
151             AAFwk::MissionInfo *ptr = parcel.ReadParcelable<AAFwk::MissionInfo>();
152             if (ptr == nullptr) {
153                 TLOGW(WmsLogTag::DEFAULT, "read MissionInfo failed");
154                 return false;
155             }
156             missionInfos.emplace_back(*ptr);
157             delete ptr;
158         }
159     }
160     TLOGI(WmsLogTag::DEFAULT, "info size is:%{public}zu", missionInfos.size());
161     return true;
162 }
163 
SetMissionContinueState(int32_t missionId,const AAFwk::ContinueState & state)164 int32_t DistributedClient::SetMissionContinueState(int32_t missionId, const AAFwk::ContinueState& state)
165 {
166     TLOGI(WmsLogTag::DEFAULT, "Mission id: %{public}d, state: %{public}d", missionId, state);
167     sptr<IRemoteObject> remote = GetDmsProxy();
168     if (remote == nullptr) {
169         TLOGI(WmsLogTag::DEFAULT, "remote system ablity is null");
170         return AAFwk::INVALID_PARAMETERS_ERR;
171     }
172     MessageParcel data;
173     MessageParcel reply;
174     MessageOption option(MessageOption::TF_ASYNC);
175     if (!data.WriteInterfaceToken(DMS_PROXY_INTERFACE_TOKEN)) {
176         return ERR_FLATTEN_OBJECT;
177     }
178     PARCEL_WRITE_HELPER(data, Int32, missionId);
179     PARCEL_WRITE_HELPER(data, Int32, static_cast<int32_t>(state));
180     int32_t error = remote->SendRequest(SET_MISSION_CONTINUE_STATE, data, reply, option);
181     if (error != ERR_NONE) {
182         TLOGE(WmsLogTag::DEFAULT, "transact failed, error: %{public}d", error);
183         return error;
184     }
185     return ERR_NONE;
186 }
187 } // namespace Rosen
188 } // namespace OHOS
189