1 /*
2  * Copyright (c) 2022 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 "dms_callback_task.h"
17 
18 #include "dtbschedmgr_log.h"
19 #include "distributed_sched_service.h"
20 #include "parcel_helper.h"
21 
22 namespace OHOS {
23 namespace DistributedSchedule {
24 using namespace OHOS::AppExecFwk;
25 
26 namespace {
27 constexpr int64_t CALLBACK_DELAY_TIME = 30000;
28 const std::string TAG = "DmsCallbackTask";
29 }
30 
Init(const DmsCallbackTaskInitCallbackFunc & callback)31 void DmsCallbackTask::Init(const DmsCallbackTaskInitCallbackFunc& callback)
32 {
33     auto runner = EventRunner::Create("dsched_callback");
34     dmsCallbackHandler_ = std::make_shared<DmsCallbackHandler>(runner, shared_from_this(), callback);
35 }
36 
GenerateTaskId()37 int64_t DmsCallbackTask::GenerateTaskId()
38 {
39     std::lock_guard<std::mutex> autoLock(taskMutex_);
40     int64_t currValue = currTaskId_.load(std::memory_order_relaxed);
41     if (currTaskId_++ == INT64_MAX) {
42         currTaskId_ = 1;
43     }
44     return currValue;
45 }
46 
PushCallback(int64_t taskId,const sptr<IRemoteObject> & callback,const std::string & deviceId,LaunchType launchType,const OHOS::AAFwk::Want & want)47 int32_t DmsCallbackTask::PushCallback(int64_t taskId, const sptr<IRemoteObject>& callback,
48     const std::string& deviceId, LaunchType launchType, const OHOS::AAFwk::Want& want)
49 {
50     HILOGI("PushCallback taskId:%{public}" PRId64, taskId);
51     if (taskId <= 0) {
52         HILOGE("PushCallback taskId invalid!");
53         return INVALID_PARAMETERS_ERR;
54     }
55 
56     if (launchType == LaunchType::FREEINSTALL_START) {
57         if (callback == nullptr) {
58             HILOGE("PushCallback callback null!");
59             return INVALID_PARAMETERS_ERR;
60         }
61     }
62 
63     if (dmsCallbackHandler_ == nullptr) {
64         HILOGE("PushCallback not initialized!");
65         return INVALID_PARAMETERS_ERR;
66     }
67 
68     std::lock_guard<std::mutex> autoLock(callbackMapMutex_);
69     auto iterTask = callbackMap_.find(taskId);
70     if (iterTask != callbackMap_.end()) {
71         HILOGE("PushCallback taskId:%{public}" PRId64 " exist!", taskId);
72         return INVALID_PARAMETERS_ERR;
73     }
74 
75     bool ret = dmsCallbackHandler_->SendEvent(taskId, 0, CALLBACK_DELAY_TIME);
76     if (!ret) {
77         HILOGE("PushCallback SendEvent failed!");
78         return INVALID_PARAMETERS_ERR;
79     }
80 
81     CallbackTaskItem item {
82         .callback = callback,
83         .taskId = taskId,
84         .launchType = launchType,
85         .deviceId = deviceId,
86         .want = want,
87     };
88     (void)callbackMap_.emplace(taskId, item);
89     return ERR_OK;
90 }
91 
PopCallback(int64_t taskId)92 CallbackTaskItem DmsCallbackTask::PopCallback(int64_t taskId)
93 {
94     std::lock_guard<std::mutex> autoLock(callbackMapMutex_);
95     auto iter = callbackMap_.find(taskId);
96     CallbackTaskItem item = {};
97     if (iter == callbackMap_.end()) {
98         HILOGW("PopCallback not found taskId:%{public}" PRId64 "!", taskId);
99         return item;
100     }
101     item = iter->second;
102     (void)callbackMap_.erase(iter);
103     if (dmsCallbackHandler_ != nullptr) {
104         dmsCallbackHandler_->RemoveEvent(taskId);
105     }
106     return item;
107 }
108 
PopContinuationMissionMap(int64_t taskId)109 void DmsCallbackTask::PopContinuationMissionMap(int64_t taskId)
110 {
111     std::lock_guard<std::mutex> autoLock(callbackMapMutex_);
112     uint32_t ret = continuationMissionMap_.erase(taskId);
113     if (ret != 1) {
114         HILOGW("GetContinuaionMissionId not found taskId:%{public}" PRId64 "!", taskId);
115     }
116 }
117 
GetContinuaionMissionId(int64_t taskId)118 int64_t DmsCallbackTask::GetContinuaionMissionId(int64_t taskId)
119 {
120     if (taskId <= 0) {
121         return INVALID_PARAMETERS_ERR;
122     }
123 
124     std::lock_guard<std::mutex> autoLock(callbackMapMutex_);
125     auto iter = continuationMissionMap_.find(taskId);
126     if (iter == continuationMissionMap_.end()) {
127         HILOGW("GetContinuaionMissionId not found taskId:%{public}" PRId64 "!", taskId);
128         return INVALID_PARAMETERS_ERR;
129     }
130     HILOGI("GetContinuaionMissionId end, taskId :%{public}" PRId64 ".", taskId);
131     return iter->second;
132 }
133 
SetContinuationMissionMap(int64_t taskId,int32_t missionId)134 void DmsCallbackTask::SetContinuationMissionMap(int64_t taskId, int32_t missionId)
135 {
136     HILOGI("taskId = %{public}" PRId64 ", missionId = %{public}d.", taskId, missionId);
137     if (taskId <= 0 || missionId <= 0) {
138         HILOGD("param invalid");
139         return;
140     }
141     std::lock_guard<std::mutex> autoLock(callbackMapMutex_);
142     auto itreator = continuationMissionMap_.find(taskId);
143     if (itreator != continuationMissionMap_.end()) {
144         HILOGD("taskId = %{public}" PRId64 ".", taskId);
145         return;
146     }
147     continuationMissionMap_[taskId] = missionId;
148 }
149 
GetLaunchType(int64_t taskId)150 LaunchType DmsCallbackTask::GetLaunchType(int64_t taskId)
151 {
152     if (taskId <= 0) {
153         HILOGD("GetLaunchType param taskId invalid");
154         return LaunchType::FREEINSTALL_START;
155     }
156     std::lock_guard<std::mutex> autoLock(callbackMapMutex_);
157     auto iterTask = callbackMap_.find(taskId);
158     if (iterTask == callbackMap_.end()) {
159         HILOGE("GetLaunchType not found taskId : %{public}" PRId64 "!", taskId);
160         return LaunchType::FREEINSTALL_START;
161     }
162     CallbackTaskItem item = iterTask->second;
163     return item.launchType;
164 }
165 
NotifyDeviceOffline(const std::string & deviceId)166 void DmsCallbackTask::NotifyDeviceOffline(const std::string& deviceId)
167 {
168     HILOGI("%{public}s begin.", __func__);
169     std::lock_guard<std::mutex> autoLock(callbackMapMutex_);
170     for (auto it = callbackMap_.begin(); it != callbackMap_.end();) {
171         if (it->second.deviceId == deviceId) {
172             if (dmsCallbackHandler_ != nullptr) {
173                 dmsCallbackHandler_->RemoveEvent(it->second.taskId);
174             }
175             DistributedSchedService::GetInstance().NotifyFreeInstallResult(it->second, DEVICE_OFFLINE_ERR);
176             it = callbackMap_.erase(it);
177         } else {
178             it++;
179         }
180     }
181 }
182 
ProcessEvent(const InnerEvent::Pointer & event)183 void DmsCallbackTask::DmsCallbackHandler::ProcessEvent(const InnerEvent::Pointer& event)
184 {
185     if (event == nullptr) {
186         HILOGE("ProcessEvent event nullptr!");
187         return;
188     }
189 
190     auto eventId = event->GetInnerEventId();
191     int64_t taskId = static_cast<int64_t>(eventId);
192     if (taskId <= 0) {
193         HILOGW("ProcessEvent taskId invalid!");
194         return;
195     }
196 
197     if (callback_ != nullptr) {
198         callback_(taskId);
199     }
200 }
201 }  // namespace DistributedSchedule
202 }  // namespace OHOS
203