1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // TODO(b/129481165): remove the #pragma below and fix conversion issues
18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wconversion"
20 
21 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
22 
23 #include "DispSyncSource.h"
24 
25 #include <android-base/stringprintf.h>
26 #include <utils/Trace.h>
27 #include <mutex>
28 
29 #include "DispSync.h"
30 #include "EventThread.h"
31 
32 namespace android {
33 using base::StringAppendF;
34 
DispSyncSource(DispSync * dispSync,nsecs_t phaseOffset,bool traceVsync,const char * name)35 DispSyncSource::DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
36                                const char* name)
37       : mName(name),
38         mValue(base::StringPrintf("VSYNC-%s", name), 0),
39         mTraceVsync(traceVsync),
40         mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
41         mDispSync(dispSync),
42         mPhaseOffset(base::StringPrintf("VsyncOffset-%s", name), phaseOffset) {}
43 
setVSyncEnabled(bool enable)44 void DispSyncSource::setVSyncEnabled(bool enable) {
45     std::lock_guard lock(mVsyncMutex);
46     if (enable) {
47         status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
48                                                    static_cast<DispSync::Callback*>(this),
49                                                    mLastCallbackTime);
50         if (err != NO_ERROR) {
51             ALOGE("error registering vsync callback: %s (%d)", strerror(-err), err);
52         }
53         // ATRACE_INT(mVsyncOnLabel.c_str(), 1);
54     } else {
55         status_t err = mDispSync->removeEventListener(static_cast<DispSync::Callback*>(this),
56                                                       &mLastCallbackTime);
57         if (err != NO_ERROR) {
58             ALOGE("error unregistering vsync callback: %s (%d)", strerror(-err), err);
59         }
60         // ATRACE_INT(mVsyncOnLabel.c_str(), 0);
61     }
62     mEnabled = enable;
63 }
64 
setCallback(VSyncSource::Callback * callback)65 void DispSyncSource::setCallback(VSyncSource::Callback* callback) {
66     std::lock_guard lock(mCallbackMutex);
67     mCallback = callback;
68 }
69 
setPhaseOffset(nsecs_t phaseOffset)70 void DispSyncSource::setPhaseOffset(nsecs_t phaseOffset) {
71     std::lock_guard lock(mVsyncMutex);
72     const nsecs_t period = mDispSync->getPeriod();
73 
74     // Normalize phaseOffset to [-period, period)
75     const int numPeriods = phaseOffset / period;
76     phaseOffset -= numPeriods * period;
77     if (mPhaseOffset == phaseOffset) {
78         return;
79     }
80 
81     mPhaseOffset = phaseOffset;
82 
83     // If we're not enabled, we don't need to mess with the listeners
84     if (!mEnabled) {
85         return;
86     }
87 
88     status_t err =
89             mDispSync->changePhaseOffset(static_cast<DispSync::Callback*>(this), mPhaseOffset);
90     if (err != NO_ERROR) {
91         ALOGE("error changing vsync offset: %s (%d)", strerror(-err), err);
92     }
93 }
94 
onDispSyncEvent(nsecs_t when,nsecs_t expectedVSyncTimestamp)95 void DispSyncSource::onDispSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp) {
96     VSyncSource::Callback* callback;
97     {
98         std::lock_guard lock(mCallbackMutex);
99         callback = mCallback;
100     }
101 
102     if (mTraceVsync) {
103         mValue = (mValue + 1) % 2;
104     }
105 
106     if (callback != nullptr) {
107         callback->onVSyncEvent(when, expectedVSyncTimestamp);
108     }
109 }
110 
dump(std::string & result) const111 void DispSyncSource::dump(std::string& result) const {
112     std::lock_guard lock(mVsyncMutex);
113     StringAppendF(&result, "DispSyncSource: %s(%s)\n", mName, mEnabled ? "enabled" : "disabled");
114     mDispSync->dump(result);
115 }
116 
117 } // namespace android
118 
119 // TODO(b/129481165): remove the #pragma below and fix conversion issues
120 #pragma clang diagnostic pop // ignored "-Wconversion"
121