1 /*
2  * Copyright (c) 2022-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 "idle_time.h"
17 
18 #include "hilog_tag_wrapper.h"
19 #include "transaction/rs_interfaces.h"
20 
21 namespace OHOS {
22 namespace AppExecFwk {
23 namespace {
24 constexpr int64_t MS_PER_NS = 1000000;
25 constexpr int32_t MAX_PERIOD_COUNT = 10;
26 }
27 
IdleTime(const std::shared_ptr<EventHandler> & eventHandler,IdleTimeCallback idleTimeCallback)28 IdleTime::IdleTime(const std::shared_ptr<EventHandler> &eventHandler, IdleTimeCallback idleTimeCallback)
29 {
30     eventHandler_ = eventHandler;
31     callback_ = idleTimeCallback;
32 }
33 
GetSysTimeNs()34 int64_t IdleTime::GetSysTimeNs()
35 {
36     auto now = std::chrono::steady_clock::now().time_since_epoch();
37     return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
38 }
39 
InitVSyncReceiver()40 void IdleTime::InitVSyncReceiver()
41 {
42     if (needStop_) {
43         return;
44     }
45 
46     if (receiver_ == nullptr) {
47         auto& rsClient = Rosen::RSInterfaces::GetInstance();
48         receiver_ = rsClient.CreateVSyncReceiver("ABILITY", eventHandler_);
49         if (receiver_ == nullptr) {
50             TAG_LOGE(AAFwkTag::APPKIT, "Create VSync receiver failed");
51             return;
52         }
53         receiver_->Init();
54     }
55 }
56 
EventTask()57 void IdleTime::EventTask()
58 {
59     if (receiver_ == nullptr) {
60         TAG_LOGE(AAFwkTag::APPKIT, "no VSyncReceiver");
61         return;
62     }
63 
64     if (callback_ == nullptr) {
65         TAG_LOGE(AAFwkTag::APPKIT, "no callback_");
66         return;
67     }
68 
69     int64_t period = 0;
70     int64_t lastVSyncTime = 0;
71     VsyncError err = receiver_->GetVSyncPeriodAndLastTimeStamp(period, lastVSyncTime, true);
72     TAG_LOGD(AAFwkTag::APPKIT, "EventTask period %{public}" PRId64 ", lastVSyncTime is %{public}" PRId64, period,
73         lastVSyncTime);
74     int64_t occurTimestamp = GetSysTimeNs();
75     if (GSERROR_OK == err && period > 0 && lastVSyncTime > 0 && occurTimestamp > lastVSyncTime) {
76         int64_t elapsedTime = occurTimestamp - lastVSyncTime;
77         int64_t idleTime = period - (elapsedTime % period) ;
78         int64_t cycle = elapsedTime / period ;
79         TAG_LOGD(
80             AAFwkTag::APPKIT, "EventTask idleTime %{public}" PRId64 ", cycle is %{public}" PRId64, idleTime, cycle);
81         if (idleTime > 0 && cycle < MAX_PERIOD_COUNT) {
82             TAG_LOGD(AAFwkTag::APPKIT, "callback_");
83             callback_(idleTime / MS_PER_NS);
84         }
85     }
86     PostTask();
87 }
88 
PostTask()89 void IdleTime::PostTask()
90 {
91     if (needStop_) {
92         return;
93     }
94 
95     if (eventHandler_ == nullptr) {
96         TAG_LOGE(AAFwkTag::APPKIT, "eventHandler_ is nullptr");
97         return;
98     }
99     std::weak_ptr<IdleTime> weak(shared_from_this());
100     auto task = [weak]() {
101         auto idleTime = weak.lock();
102         if (idleTime == nullptr) {
103             TAG_LOGE(AAFwkTag::APPKIT, "idleTime is nullptr");
104             return;
105         }
106         idleTime->EventTask();
107     };
108     eventHandler_->PostTask(task, "IdleTime:PostTask", 0, EventQueue::Priority::IDLE);
109 }
110 
Start()111 void IdleTime::Start()
112 {
113     InitVSyncReceiver();
114     PostTask();
115 }
116 
SetNeedStop(bool needStop)117 void IdleTime::SetNeedStop(bool needStop)
118 {
119     needStop_ = needStop;
120 }
121 
GetNeedStop()122 bool IdleTime::GetNeedStop()
123 {
124     return needStop_;
125 }
126 
GetIdleNotifyFunc()127 IdleNotifyStatusCallback IdleTime::GetIdleNotifyFunc()
128 {
129     IdleNotifyStatusCallback cb = [this](bool needStop) {
130         if (this->GetNeedStop() == needStop) {
131             return;
132         }
133 
134         this->SetNeedStop(needStop);
135         if (needStop == false) {
136             this->Start();
137         }
138     };
139     return cb;
140 }
141 } // AppExecFwk
142 } // namespace OHOS