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 "idle_time.h"
17
18 #include "hilog_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 HILOG_ERROR("Create VSync receiver failed.");
51 return;
52 }
53 receiver_->Init();
54 }
55 }
56
EventTask()57 void IdleTime::EventTask()
58 {
59 if (receiver_ == nullptr) {
60 HILOG_ERROR("no VSyncReceiver.");
61 return;
62 }
63
64 if (callback_ == nullptr) {
65 HILOG_ERROR("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 HILOG_DEBUG("EventTask period %{public}" PRId64 ", lastVSyncTime is %{public}" PRId64, period, lastVSyncTime);
73 int64_t occurTimestamp = GetSysTimeNs();
74 if (GSERROR_OK == err && period > 0 && lastVSyncTime > 0 && occurTimestamp > lastVSyncTime) {
75 int64_t elapsedTime = occurTimestamp - lastVSyncTime;
76 int64_t idleTime = period - (elapsedTime % period) ;
77 int64_t cycle = elapsedTime / period ;
78 HILOG_DEBUG("EventTask idleTime %{public}" PRId64 ", cycle is %{public}" PRId64, idleTime, cycle);
79 if (idleTime > 0 && cycle < MAX_PERIOD_COUNT) {
80 HILOG_DEBUG("callback_");
81 callback_(idleTime / MS_PER_NS);
82 }
83 }
84 PostTask();
85 }
86
PostTask()87 void IdleTime::PostTask()
88 {
89 if (needStop_) {
90 return;
91 }
92
93 if (eventHandler_ == nullptr) {
94 HILOG_ERROR("eventHandler_ is nullptr.");
95 return;
96 }
97 std::weak_ptr<IdleTime> weak(shared_from_this());
98 auto task = [weak]() {
99 auto idleTime = weak.lock();
100 if (idleTime == nullptr) {
101 HILOG_ERROR("idleTime is nullptr.");
102 return;
103 }
104 idleTime->EventTask();
105 };
106 eventHandler_->PostTask(task, "IdleTime:PostTask", 0, EventQueue::Priority::IDLE);
107 }
108
Start()109 void IdleTime::Start()
110 {
111 InitVSyncReceiver();
112 PostTask();
113 }
114
SetNeedStop(bool needStop)115 void IdleTime::SetNeedStop(bool needStop)
116 {
117 needStop_ = needStop;
118 }
119
GetNeedStop()120 bool IdleTime::GetNeedStop()
121 {
122 return needStop_;
123 }
124
GetIdleNotifyFunc()125 IdleNotifyStatusCallback IdleTime::GetIdleNotifyFunc()
126 {
127 IdleNotifyStatusCallback cb = [this](bool needStop) {
128 if (this->GetNeedStop() == needStop) {
129 return;
130 }
131
132 this->SetNeedStop(needStop);
133 if (needStop == false) {
134 this->Start();
135 }
136 };
137 return cb;
138 }
139 } // AppExecFwk
140 } // namespace OHOS