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