• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "mission/notification/dms_continue_recommend_manager.h"
17 
18 #include <sys/prctl.h>
19 
20 #include "bundle/bundle_manager_internal.h"
21 #include "dfx/dms_hianalytics_report.h"
22 #include "distributed_sched_utils.h"
23 #include "dtbschedmgr_device_info_storage.h"
24 #include "dtbschedmgr_log.h"
25 #include "mission/distributed_bm_storage.h"
26 
27 namespace OHOS {
28 namespace DistributedSchedule {
29 namespace {
30 const std::string TAG = "DMSContinueRecomMgr";
31 constexpr int32_t STATE_ACTIVE = 0;
32 constexpr int32_t STATE_INACTIVE = 1;
33 }
34 
Init(int32_t currentAccountId)35 void DMSContinueRecomMgr::Init(int32_t currentAccountId)
36 {
37     HILOGI("Init start");
38     {
39         std::unique_lock<std::mutex> lock(hasInitMutex_);
40         if (hasInit_) {
41             HILOGW("DMSContinueRecomMgr has inited");
42             return;
43         }
44         hasInit_ = true;
45     }
46     if (eventHandler_ != nullptr) {
47         HILOGI("Already inited, end.");
48         return;
49     }
50     {
51         accountId_ = currentAccountId;
52         eventThread_ = std::thread(&DMSContinueRecomMgr::StartEvent, this);
53         std::unique_lock<std::mutex> lock(eventMutex_);
54         eventCon_.wait(lock, [this] {
55             return eventHandler_ != nullptr;
56         });
57     }
58     HILOGI("Init end");
59 }
60 
StartEvent()61 void DMSContinueRecomMgr::StartEvent()
62 {
63     HILOGI("StartEvent start");
64     prctl(PR_SET_NAME, TAG.c_str());
65     auto runner = AppExecFwk::EventRunner::Create(false);
66     {
67         std::lock_guard<std::mutex> lock(eventMutex_);
68         eventHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
69     }
70     eventCon_.notify_one();
71     CHECK_POINTER_RETURN(runner, "runner");
72     runner->Run();
73     HILOGI("StartEvent end");
74 }
75 
~DMSContinueRecomMgr()76 DMSContinueRecomMgr::~DMSContinueRecomMgr()
77 {
78     HILOGI("~DMSContinueRecomMgr, accountId: %{public}d.", accountId_);
79     UnInit();
80 }
81 
UnInit()82 void DMSContinueRecomMgr::UnInit()
83 {
84     HILOGI("UnInit start");
85     {
86         std::unique_lock<std::mutex> lock(hasInitMutex_);
87         if (!hasInit_) {
88             HILOGW("DMSContinueRecomMgr has uninited");
89             return;
90         }
91         hasInit_ = false;
92     }
93     CHECK_POINTER_RETURN(eventHandler_, "eventHandler_");
94     if (eventHandler_->GetEventRunner() != nullptr) {
95         eventHandler_->GetEventRunner()->Stop();
96         if (eventThread_.joinable()) {
97             eventThread_.join();
98         }
99         eventHandler_ = nullptr;
100     }
101     HILOGI("UnInit end");
102 }
103 
OnDeviceChanged()104 void DMSContinueRecomMgr::OnDeviceChanged()
105 {
106     HILOGI("OnDeviceChanged called");
107     int32_t missionId = GetCurrentMissionId();
108     if (missionId <= 0) {
109         HILOGW("GetCurrentMissionId failed, ret %{public}d", missionId);
110         return;
111     }
112     OnMissionStatusChanged(missionId, MISSION_EVENT_FOCUSED);
113 }
114 
OnMissionStatusChanged(int32_t missionId,MissionEventType type)115 void DMSContinueRecomMgr::OnMissionStatusChanged(int32_t missionId, MissionEventType type)
116 {
117     MissionStatus status;
118     int32_t ret = DmsContinueConditionMgr::GetInstance().GetMissionStatus(accountId_, missionId, status);
119     if (ret != ERR_OK) {
120         HILOGE("GetMissionStatus failed, ret: %{public}d, missionId %{public}d, type: %{public}s",
121             ret, missionId, DmsContinueConditionMgr::GetInstance().TypeEnumToString(type).c_str());
122         return;
123     }
124 
125     auto feedfunc = [this, status, type]() {
126         PublishContinueRecommend(status, type);
127     };
128     CHECK_POINTER_RETURN(eventHandler_, "eventHandler_");
129     eventHandler_->PostTask(feedfunc);
130 }
131 
PublishContinueRecommend(const MissionStatus & status,MissionEventType type)132 void DMSContinueRecomMgr::PublishContinueRecommend(const MissionStatus& status, MissionEventType type)
133 {
134     auto typeStr = DmsContinueConditionMgr::GetInstance().TypeEnumToString(type);
135     HILOGI("start, missionId: %{public}d, type: %{public}s", status.missionId, typeStr.c_str());
136 
137     if (!DmsContinueConditionMgr::GetInstance().CheckSystemSendCondition() ||
138         !DmsContinueConditionMgr::GetInstance().CheckMissionSendCondition(status, type)) {
139         HILOGE("CheckBroadcastCondition %{public}s failed! status: %{public}s",
140             typeStr.c_str(), status.ToString().c_str());
141         return;
142     }
143 
144     ContinueRecommendInfo info;
145     if (!GetRecommendInfo(status, type, info)) {
146         HILOGE("GetRecommendInfo failed, status: %{public}s", status.ToString().c_str());
147         return;
148     }
149 
150     int32_t ret = DmsHiAnalyticsReport::PublishRecommendInfo(info);
151     if (ret != ERR_OK) {
152         HILOGE("PublishRecommendInfo failed, ret: %{public}d, status: %{public}s", ret, status.ToString().c_str());
153     }
154     HILOGI("end, info: %{public}s", info.ToString().c_str());
155     return;
156 }
157 
GetRecommendInfo(const MissionStatus & status,MissionEventType type,ContinueRecommendInfo & info)158 bool DMSContinueRecomMgr::GetRecommendInfo(
159     const MissionStatus& status, MissionEventType type, ContinueRecommendInfo& info)
160 {
161     HILOGD("start, missionId: %{public}d", status.missionId);
162     info.state_ = (type == MISSION_EVENT_FOCUSED || type == MISSION_EVENT_ACTIVE) ? STATE_ACTIVE : STATE_INACTIVE;
163     info.srcBundleName_ = status.bundleName;
164     info.userId_ = accountId_;
165 
166     AppExecFwk::AbilityInfo abilityInfo;
167     int32_t result = BundleManagerInternal::GetLocalAbilityInfo(
168         status.bundleName, status.moduleName, status.abilityName, abilityInfo);
169     if (result != ERR_OK) {
170         HILOGW("GetLocalAbilityInfo failed.");
171         return false;
172     }
173     if (!abilityInfo.continueType.empty()) {
174         info.continueType_ = abilityInfo.continueType[0];
175     }
176 
177     std::map<std::string, DmsBundleInfo> availableList;
178     bool ret = GetAvailableRecommendList(status.bundleName, availableList);
179     if (ret && info.state_ == STATE_ACTIVE) {
180         for (auto iter = availableList.begin(); iter != availableList.end(); iter++) {
181             ContinueCandidate candidate;
182             candidate.deviceId_ = iter->first;
183             candidate.dstBundleName_ = iter->second.bundleName;
184             info.candidates_.push_back(candidate);
185         }
186     }
187     HILOGD("end");
188     return true;
189 }
190 
GetAvailableRecommendList(const std::string & bundleName,std::map<std::string,DmsBundleInfo> & availableList)191 bool DMSContinueRecomMgr::GetAvailableRecommendList(const std::string& bundleName,
192     std::map<std::string, DmsBundleInfo>& availableList)
193 {
194     HILOGD("called, bundleName: %{public}s", bundleName.c_str());
195     std::vector<std::string> networkIdList = DtbschedmgrDeviceInfoStorage::GetInstance().GetNetworkIdList();
196     for (const std::string& networkId : networkIdList) {
197         DmsBundleInfo sameBundleInfo;
198         if (DmsBmStorage::GetInstance()->GetDistributedBundleInfo(networkId, bundleName, sameBundleInfo) &&
199             sameBundleInfo.bundleName == bundleName) {
200             availableList[networkId] = sameBundleInfo;
201             continue;
202         }
203 
204         HILOGW("get same bundle %{public}s on networkId %{public}s failed, try diff bundle.",
205             bundleName.c_str(), GetAnonymStr(networkId).c_str());
206 
207         AppExecFwk::AppProvisionInfo appProvisionInfo;
208         std::string localDeveloperId;
209         if (BundleManagerInternal::GetAppProvisionInfo4CurrentUser(bundleName, appProvisionInfo)) {
210             localDeveloperId = appProvisionInfo.developerId;
211         }
212         std::vector<DmsBundleInfo> bundleInfoList;
213         if (!DmsBmStorage::GetInstance()->GetDistributeInfosByNetworkId(networkId, bundleInfoList)) {
214             HILOGW("get bundle list on networkId %{public}s failed.", GetAnonymStr(networkId).c_str());
215             continue;
216         }
217         for (const auto& diffBundleInfo : bundleInfoList) {
218             if (diffBundleInfo.developerId == localDeveloperId &&
219                 IsContinuableWithDiffBundle(bundleName, diffBundleInfo)) {
220                 availableList[networkId] = diffBundleInfo;
221                 break;
222             }
223         }
224     }
225     return true;
226 }
227 
IsContinuableWithDiffBundle(const std::string & bundleName,const DmsBundleInfo & info)228 bool DMSContinueRecomMgr::IsContinuableWithDiffBundle(const std::string& bundleName, const DmsBundleInfo& info)
229 {
230     for (const auto& abilityInfo: info.dmsAbilityInfos) {
231         auto contiName = abilityInfo.continueBundleName;
232         if (std::find(contiName.begin(), contiName.end(), bundleName) != contiName.end()) {
233             return true;
234         }
235     }
236     return false;
237 }
238 }  // namespace DistributedSchedule
239 }  // namespace OHOS
240