1/*
2 * Copyright (c) 2021-2024 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_sched_adapter.h"
17
18#include "datetime_ex.h"
19#include "dfx/dms_hisysevent_report.h"
20#include "distributed_sched_service.h"
21#include "distributed_sched_utils.h"
22#include "dtbschedmgr_device_info_storage.h"
23#include "dtbschedmgr_log.h"
24#include "ipc_skeleton.h"
25#include "ipc_types.h"
26#ifdef SUPPORT_DISTRIBUTED_MISSION_MANAGER
27#include "mission/distributed_sched_mission_manager.h"
28#include "mission/mission_info_converter.h"
29#endif
30#include "os_account_manager.h"
31#include "parcel_helper.h"
32#include "string_ex.h"
33
34namespace OHOS {
35namespace DistributedSchedule {
36using namespace std;
37using namespace AAFwk;
38using namespace AccountSA;
39using namespace AppExecFwk;
40using DstbMissionChangeListener = DistributedMissionChangeListener;
41namespace {
42// set a non-zero value on need later
43constexpr int64_t DEVICE_OFFLINE_DELAY_TIME = 0;
44const std::string TAG = "DistributedSchedAdapter";
45}
46
47IMPLEMENT_SINGLE_INSTANCE(DistributedSchedAdapter);
48
49void DistributedSchedAdapter::Init()
50{
51    if (dmsAdapterHandler_ == nullptr) {
52        shared_ptr<EventRunner> runner = EventRunner::Create("dmsAdapter");
53        if (runner == nullptr) {
54            HILOGE("create runner failed");
55            return;
56        }
57        dmsAdapterHandler_ = make_shared<EventHandler>(runner);
58    }
59}
60
61void DistributedSchedAdapter::UnInit()
62{
63    dmsAdapterHandler_ = nullptr;
64}
65
66int32_t DistributedSchedAdapter::ConnectAbility(const OHOS::AAFwk::Want& want,
67    const sptr<IRemoteObject>& connect, const sptr<IRemoteObject>& callerToken)
68{
69    HILOGD("ConnectAbility");
70    ErrCode errCode = AAFwk::AbilityManagerClient::GetInstance()->Connect();
71    if (errCode != ERR_OK) {
72        HILOGE("connect ability server failed, errCode=%{public}d", errCode);
73        DmsHiSysEventReport::ReportFaultEvent(FaultEvent::CONNECT_REMOTE_ABILITY,
74            EventErrorType::GET_ABILITY_MGR_FAILED);
75        return errCode;
76    }
77    int32_t activeAccountId = -1;
78#ifdef OS_ACCOUNT_PART
79    std::vector<int> ids;
80    errCode = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
81    if (errCode != ERR_OK || ids.empty()) {
82        return INVALID_PARAMETERS_ERR;
83    }
84    activeAccountId = ids[0];
85#endif
86    errCode = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbility(want,
87        iface_cast<AAFwk::IAbilityConnection>(connect), callerToken, activeAccountId);
88    return errCode;
89}
90
91int32_t DistributedSchedAdapter::DisconnectAbility(const sptr<IRemoteObject>& connect)
92{
93    HILOGD("DisconnectAbility");
94    ErrCode errCode = AAFwk::AbilityManagerClient::GetInstance()->Connect();
95    if (errCode != ERR_OK) {
96        HILOGE("connect ability server failed, errCode=%{public}d", errCode);
97        DmsHiSysEventReport::ReportFaultEvent(FaultEvent::DISCONNECT_REMOTE_ABILITY,
98            EventErrorType::GET_ABILITY_MGR_FAILED);
99        return errCode;
100    }
101    ErrCode ret = AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(
102        iface_cast<AAFwk::IAbilityConnection>(connect));
103    return ret;
104}
105
106void DistributedSchedAdapter::DeviceOnline(const std::string& networkId)
107{
108    if (dmsAdapterHandler_ == nullptr) {
109        HILOGE("DeviceOnline dmsAdapterHandler is null");
110        return;
111    }
112
113    if (networkId.empty()) {
114        HILOGW("DeviceOnline networkId is empty");
115        return;
116    }
117
118    HILOGD("process DeviceOnline networkId is %{public}s", GetAnonymStr(networkId).c_str());
119    dmsAdapterHandler_->RemoveTask(networkId);
120}
121
122void DistributedSchedAdapter::DeviceOffline(const std::string& networkId)
123{
124    if (dmsAdapterHandler_ == nullptr) {
125        HILOGE("DeviceOffline dmsAdapterHandler is null");
126        return;
127    }
128
129    if (networkId.empty()) {
130        HILOGW("DeviceOffline networkId is empty");
131        return;
132    }
133    HILOGD("process DeviceOffline networkId is %{public}s", GetAnonymStr(networkId).c_str());
134    auto callback = [networkId, this] () {
135        ProcessDeviceOffline(networkId);
136    };
137    if (!dmsAdapterHandler_->PostTask(callback, networkId, DEVICE_OFFLINE_DELAY_TIME)) {
138        HILOGW("DeviceOffline PostTask failed");
139    }
140}
141
142void DistributedSchedAdapter::ProcessDeviceOffline(const std::string& deviceId)
143{
144    HILOGD("ProcessDeviceOffline");
145    DistributedSchedService::GetInstance().ProcessDeviceOffline(deviceId);
146}
147
148void DistributedSchedAdapter::ProcessConnectDied(const sptr<IRemoteObject>& connect)
149{
150    if (dmsAdapterHandler_ == nullptr) {
151        HILOGE("ProcessConnectDied dmsAdapterHandler is null");
152        return;
153    }
154
155    if (connect == nullptr) {
156        HILOGE("ProcessConnectDied connect is null");
157        return;
158    }
159    HILOGD("process connect died");
160    auto callback = [connect] () {
161        DistributedSchedService::GetInstance().ProcessConnectDied(connect);
162    };
163    if (!dmsAdapterHandler_->PostTask(callback)) {
164        HILOGW("ProcessConnectDied PostTask failed");
165    }
166}
167
168void DistributedSchedAdapter::ProcessCalleeDied(const sptr<IRemoteObject>& connect)
169{
170    if (dmsAdapterHandler_ == nullptr) {
171        HILOGE("ProcessCalleeDied dmsAdapterHandler is null");
172        return;
173    }
174    if (connect == nullptr) {
175        HILOGE("ProcessCalleeDied connect is null");
176        return;
177    }
178    HILOGD("process callee died");
179    auto callback = [connect] () {
180        DistributedSchedService::GetInstance().ProcessCalleeDied(connect);
181    };
182    if (!dmsAdapterHandler_->PostTask(callback)) {
183        HILOGE("ProcessCalleeDied PostTask failed");
184    }
185}
186
187void DistributedSchedAdapter::ProcessCallResult(const sptr<IRemoteObject>& calleeConnect,
188    const sptr<IRemoteObject>& callerConnect)
189{
190    if (dmsAdapterHandler_ == nullptr) {
191        HILOGE("ProcessCallResult dmsAdapterHandler is null");
192        return;
193    }
194    if (calleeConnect == nullptr || callerConnect == nullptr) {
195        HILOGE("ProcessCallResult connect is null");
196        return;
197    }
198    HILOGD("process call result start");
199    auto callback = [calleeConnect, callerConnect] () {
200        DistributedSchedService::GetInstance().ProcessCallResult(calleeConnect, callerConnect);
201    };
202    if (!dmsAdapterHandler_->PostTask(callback)) {
203        HILOGE("ProcessCalleeDied PostTask failed");
204    }
205}
206
207void DistributedSchedAdapter::ProcessCallerDied(const sptr<IRemoteObject>& connect, int32_t deviceType)
208{
209    if (dmsAdapterHandler_ == nullptr) {
210        HILOGE("ProcessCallerDied dmsAdapterHandler is null");
211        return;
212    }
213    if (connect == nullptr) {
214        HILOGE("ProcessCallerDied connect is null");
215        return;
216    }
217    HILOGD("process caller died");
218    auto callback = [connect, deviceType] () {
219        DistributedSchedService::GetInstance().ProcessCallerDied(connect, deviceType);
220    };
221    if (!dmsAdapterHandler_->PostTask(callback)) {
222        HILOGE("ProcessCallerDied PostTask failed");
223    }
224}
225
226int32_t DistributedSchedAdapter::ReleaseAbility(const sptr<IRemoteObject>& connect,
227    const AppExecFwk::ElementName &element)
228{
229    HILOGD("ReleaseAbility called");
230    ErrCode errCode = AAFwk::AbilityManagerClient::GetInstance()->Connect();
231    if (errCode != ERR_OK) {
232        HILOGE("ReleaseAbility:connect ability server failed, errCode=%{public}d", errCode);
233        DmsHiSysEventReport::ReportFaultEvent(FaultEvent::RELEASE_REMOTE_ABILITY,
234            EventErrorType::GET_ABILITY_MGR_FAILED);
235        return errCode;
236    }
237    AppExecFwk::ElementName elementWithoutDeviceId("", element.GetBundleName(), element.GetAbilityName());
238    ErrCode ret = AAFwk::AbilityManagerClient::GetInstance()->ReleaseCall(
239        iface_cast<AAFwk::IAbilityConnection>(connect), elementWithoutDeviceId);
240    return ret;
241}
242
243int32_t DistributedSchedAdapter::StartAbilityByCall(const OHOS::AAFwk::Want& want,
244    const sptr<IRemoteObject>& connect, const sptr<IRemoteObject>& callerToken)
245{
246    HILOGD("ResolveAbility called");
247    ErrCode errCode = AAFwk::AbilityManagerClient::GetInstance()->Connect();
248    if (errCode != ERR_OK) {
249        HILOGE("ResolveAbility:connect ability server failed, errCode=%{public}d", errCode);
250        DmsHiSysEventReport::ReportFaultEvent(FaultEvent::START_REMOTE_ABILITY_BYCALL,
251            EventErrorType::GET_ABILITY_MGR_FAILED);
252        return errCode;
253    }
254    ErrCode ret = AAFwk::AbilityManagerClient::GetInstance()->StartAbilityByCall(want,
255        iface_cast<AAFwk::IAbilityConnection>(connect), callerToken);
256    return ret;
257}
258
259bool DistributedSchedAdapter::InitHichainService()
260{
261    if (hichainGmInstance_ != nullptr) {
262        HILOGD("hichain GmInstance is already exist");
263        return true;
264    }
265    if (InitDeviceAuthService() != ERR_OK) {
266        HILOGE("hichain init DeviceAuthService failed");
267        return false;
268    }
269    hichainGmInstance_ = GetGmInstance();
270    if (hichainGmInstance_ == nullptr) {
271        HILOGE("hichain get GmInstance failed");
272        return false;
273    }
274    return true;
275}
276
277bool DistributedSchedAdapter::CheckAccessToGroup(const std::string& groupId, const std::string& targetBundleName)
278{
279    std::lock_guard<std::mutex> autoLock(hichainLock_);
280    int64_t begin = GetTickCount();
281    if (!InitHichainService()) {
282        return false;
283    }
284    int32_t ret = hichainGmInstance_->checkAccessToGroup(ANY_OS_ACCOUNT, targetBundleName.c_str(),
285        groupId.c_str());
286    HILOGI("[PerformanceTest] checkAccessToGroup spend %{public}" PRId64 " ms", GetTickCount() - begin);
287    if (ret != ERR_OK) {
288        HILOGE("hichain checkAccessToGroup fail, ret %{public}d.", ret);
289        return false;
290    }
291    HILOGD("hichain checkAccessToGroup success");
292    return true;
293}
294
295bool DistributedSchedAdapter::GetRelatedGroups(const std::string& udid, const std::string& bundleName,
296    std::string& returnGroups)
297{
298    std::lock_guard<std::mutex> autoLock(hichainLock_);
299    int64_t begin = GetTickCount();
300    if (!InitHichainService()) {
301        return false;
302    }
303    uint32_t groupNum = 0;
304    char* groupsJsonStr = nullptr;
305    int32_t ret = hichainGmInstance_->getRelatedGroups(ANY_OS_ACCOUNT, bundleName.c_str(), udid.c_str(),
306        &groupsJsonStr, &groupNum);
307    HILOGI("[PerformanceTest] getRelatedGroups spend %{public}" PRId64 " ms", GetTickCount() - begin);
308    if (ret != ERR_OK) {
309        HILOGE("hichain getRelatedGroups failed, ret:%{public}d", ret);
310        return false;
311    }
312    if (groupsJsonStr == nullptr || groupNum == 0) {
313        HILOGE("groupsJsonStr is nullptr");
314        return false;
315    }
316    returnGroups = groupsJsonStr;
317    return true;
318}
319
320#ifdef SUPPORT_DISTRIBUTED_MISSION_MANAGER
321int32_t DistributedSchedAdapter::GetLocalMissionInfos(int32_t numMissions,
322    std::vector<DstbMissionInfo>& missionInfos)
323
324{
325    ErrCode errCode = AAFwk::AbilityManagerClient::GetInstance()->Connect();
326    if (errCode != ERR_OK) {
327        HILOGE("get ability server failed, errCode = %{public}d", errCode);
328        return errCode;
329    }
330    std::vector<MissionInfo> amsMissions;
331    ErrCode ret = AAFwk::AbilityManagerClient::GetInstance()->GetMissionInfos("", numMissions, amsMissions);
332    if (ret != ERR_OK) {
333        HILOGE("GetMissionInfos failed, ret = %{public}d", ret);
334        return ret;
335    }
336    if (amsMissions.empty()) {
337        HILOGI("empty missions");
338        return ERR_OK;
339    }
340    HILOGI("GetMissionInfos size:%{public}zu", amsMissions.size());
341    return MissionInfoConverter::ConvertToDstbMissionInfos(amsMissions, missionInfos);
342}
343
344int32_t DistributedSchedAdapter::RegisterMissionListener(const sptr<IMissionListener>& listener)
345{
346    HILOGD("called.");
347    if (listener == nullptr) {
348        HILOGE("listener is null");
349        return INVALID_PARAMETERS_ERR;
350    }
351    ErrCode errCode = AAFwk::AbilityManagerClient::GetInstance()->Connect();
352    if (errCode != ERR_OK) {
353        HILOGE("get ability server failed, errCode=%{public}d", errCode);
354        return errCode;
355    }
356    ErrCode ret = AAFwk::AbilityManagerClient::GetInstance()->RegisterMissionListener(listener);
357    DmsRadar::GetInstance().RegisterFocusedRes("RegisterMissionListener", ret);
358    if (ret != ERR_OK) {
359        HILOGE("RegisterMissionListener failed, ret=%{public}d", ret);
360        return ret;
361    }
362    return ERR_OK;
363}
364
365int32_t DistributedSchedAdapter::UnRegisterMissionListener(const sptr<IMissionListener>& listener)
366{
367    if (listener == nullptr) {
368        HILOGE("listener is null");
369        return INVALID_PARAMETERS_ERR;
370    }
371    ErrCode errCode = AAFwk::AbilityManagerClient::GetInstance()->Connect();
372    if (errCode != ERR_OK) {
373        HILOGE("get ability server failed, errCode=%{public}d", errCode);
374        return errCode;
375    }
376
377    ErrCode ret = AAFwk::AbilityManagerClient::GetInstance()->UnRegisterMissionListener(listener);
378    if (ret != ERR_OK) {
379        HILOGE("UnRegisterMissionListener failed, ret=%{public}d", ret);
380        return ret;
381    }
382    return ERR_OK;
383}
384
385int32_t DistributedSchedAdapter::GetLocalMissionSnapshotInfo(const std::string& networkId, int32_t missionId,
386    MissionSnapshot& missionSnapshot)
387{
388    int64_t begin = GetTickCount();
389    ErrCode errCode = AAFwk::AbilityManagerClient::GetInstance()->Connect();
390    if (errCode != ERR_OK) {
391        HILOGE("get ability server failed, errCode=%{public}d", errCode);
392        return errCode;
393    }
394    errCode = AAFwk::AbilityManagerClient::GetInstance()->GetMissionSnapshot(networkId,
395        missionId, missionSnapshot);
396    HILOGI("[PerformanceTest] GetMissionSnapshot spend %{public}" PRId64 " ms", GetTickCount() - begin);
397    if (errCode != ERR_OK) {
398        HILOGE("get mission snapshot failed, missionId=%{public}d, errCode=%{public}d", missionId, errCode);
399        return errCode;
400    }
401    if (missionSnapshot.snapshot == nullptr) {
402        HILOGE("pixel map is nullptr!");
403        return ERR_NULL_OBJECT;
404    }
405    HILOGD("pixelMap size:%{public}d", missionSnapshot.snapshot->GetCapacity());
406    return ERR_OK;
407}
408#endif
409} // namespace DistributedSchedule
410} // namespace OHOS
411