1 /*
2  * Copyright (C) 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 "request_running_task_count.h"
17 
18 #include <fcntl.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22 
23 #include <cstdint>
24 #include <memory>
25 
26 #include "download_server_ipc_interface_code.h"
27 #include "iremote_broker.h"
28 #include "parcel_helper.h"
29 #include "request_manager_impl.h"
30 #include "runcount_notify_stub.h"
31 
32 namespace OHOS::Request {
33 using namespace OHOS::HiviewDFX;
34 // impl FwkIRunningTaskObserver
FwkIRunningTaskObserver(std::shared_ptr<IRunningTaskObserver> ob)35 FwkIRunningTaskObserver::FwkIRunningTaskObserver(std::shared_ptr<IRunningTaskObserver> ob)
36 {
37     pInnerOb_ = ob;
38 }
39 
UpdateRunningTaskCount()40 void FwkIRunningTaskObserver::UpdateRunningTaskCount()
41 {
42     pInnerOb_->OnRunningTaskCountUpdate(FwkRunningTaskCountManager::GetInstance()->GetCount());
43 }
44 
GetInnerObserver()45 std::shared_ptr<IRunningTaskObserver> FwkIRunningTaskObserver::GetInnerObserver()
46 {
47     return pInnerOb_;
48 }
49 
50 // impl FwkRunningTaskCountManager
GetInstance()51 std::unique_ptr<FwkRunningTaskCountManager> &FwkRunningTaskCountManager::GetInstance()
52 {
53     static std::unique_ptr<FwkRunningTaskCountManager> instance(new FwkRunningTaskCountManager());
54     return instance;
55 }
56 
GetCount()57 int FwkRunningTaskCountManager::GetCount()
58 {
59     return count_;
60 }
61 
SetCount(int runCount)62 void FwkRunningTaskCountManager::SetCount(int runCount)
63 {
64     std::lock_guard<std::mutex> lock(countLock_);
65     count_ = runCount;
66 }
67 
AttachObserver(std::shared_ptr<IRunningTaskObserver> ob)68 void FwkRunningTaskCountManager::AttachObserver(std::shared_ptr<IRunningTaskObserver> ob)
69 {
70     auto pNewFwkOb = std::make_shared<FwkIRunningTaskObserver>(ob);
71     std::lock_guard<std::mutex> lock(observersLock_);
72     observers_.push_back(pNewFwkOb);
73     REQUEST_HILOGD("Fwk runcount manager has push observer, now has %{public}d observers",
74         static_cast<int32_t>(observers_.size()));
75 }
76 
DetachObserver(std::shared_ptr<IRunningTaskObserver> ob)77 void FwkRunningTaskCountManager::DetachObserver(std::shared_ptr<IRunningTaskObserver> ob)
78 {
79     int32_t eraseCnt = 0;
80     std::lock_guard<std::mutex> lock(observersLock_);
81     auto it = observers_.begin();
82     while (it != observers_.end()) {
83         if ((*it)->GetInnerObserver().get() == ob.get()) {
84             // Just erase shared_ptr from vector, no need to delete.
85             it = observers_.erase(it);
86             eraseCnt++;
87         } else {
88             it++;
89         }
90     }
91 
92     if (!eraseCnt) {
93         REQUEST_HILOGE("Detach observer failed, not found the unsubscribe ob in obervers");
94         return;
95     }
96 }
97 
HasObserver()98 bool FwkRunningTaskCountManager::HasObserver()
99 {
100     return !observers_.empty();
101 }
102 
SaIsOnline()103 bool FwkRunningTaskCountManager::SaIsOnline()
104 {
105     return saIsOnline_.load();
106 }
107 
SetSaStatus(bool isOnline)108 void FwkRunningTaskCountManager::SetSaStatus(bool isOnline)
109 {
110     saIsOnline_.store(isOnline);
111 }
112 
NotifyAllObservers()113 void FwkRunningTaskCountManager::NotifyAllObservers()
114 {
115     REQUEST_HILOGD("Notify runcount to %{public}d observers.", static_cast<int32_t>(observers_.size()));
116     std::lock_guard<std::mutex> observer_lock(observersLock_);
117     auto it = observers_.begin();
118     while (it != observers_.end()) {
119         (*it)->UpdateRunningTaskCount();
120         it++;
121     }
122 }
123 
124 // impl Sub && UnSub
SubscribeRunningTaskCount(std::shared_ptr<IRunningTaskObserver> ob)125 int32_t SubscribeRunningTaskCount(std::shared_ptr<IRunningTaskObserver> ob)
126 {
127     if (FwkRunningTaskCountManager::GetInstance()->HasObserver()) {
128         FwkRunningTaskCountManager::GetInstance()->AttachObserver(ob);
129         ob->OnRunningTaskCountUpdate(FwkRunningTaskCountManager::GetInstance()->GetCount());
130         return E_OK;
131     }
132 
133     FwkRunningTaskCountManager::GetInstance()->AttachObserver(ob);
134     auto listener = RunCountNotifyStub::GetInstance();
135     RequestManagerImpl::GetInstance()->SubscribeSA();
136     int32_t ret = RequestManagerImpl::GetInstance()->SubRunCount(listener);
137     if (ret != E_OK) {
138         // IPC is failed, but observer has attached.
139         REQUEST_HILOGE("Subscribe running task count failed, ret: %{public}d.", ret);
140         return ret;
141     }
142     if (!FwkRunningTaskCountManager::GetInstance()->SaIsOnline()) {
143         ob->OnRunningTaskCountUpdate(0);
144     }
145     return E_OK;
146 }
147 
UnsubscribeRunningTaskCount(std::shared_ptr<IRunningTaskObserver> ob)148 void UnsubscribeRunningTaskCount(std::shared_ptr<IRunningTaskObserver> ob)
149 {
150     FwkRunningTaskCountManager::GetInstance()->DetachObserver(ob);
151     if (FwkRunningTaskCountManager::GetInstance()->HasObserver()) {
152         REQUEST_HILOGD("Unsubscribe running task count success.");
153         return;
154     }
155 
156     int32_t ret = RequestManagerImpl::GetInstance()->UnsubRunCount();
157     RequestManagerImpl::GetInstance()->UnsubscribeSA();
158     if (ret != E_OK) {
159         REQUEST_HILOGE("Unsubscribe running task count failed, ret: %{public}d.", ret);
160     }
161 }
162 
163 } // namespace OHOS::Request