1 /*
2 * Copyright (C) 2021 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 #include "pixel-display.h"
18
19 #include <aidlcommonsupport/NativeHandle.h>
20 #include <android-base/logging.h>
21 #include <android/binder_manager.h>
22 #include <android/binder_process.h>
23 #include <sys/types.h>
24 #include <utils/Errors.h>
25
26 #include "ExynosDisplay.h"
27 #include "ExynosPrimaryDisplay.h"
28
29 extern int32_t load_png_image(const char *filepath, buffer_handle_t buffer);
30
31 using ::aidl::com::google::hardware::pixel::display::Display;
32
PixelDisplayInit(ExynosDisplay * exynos_display,const std::string_view instance_str)33 void PixelDisplayInit(ExynosDisplay *exynos_display, const std::string_view instance_str) {
34 ABinderProcess_setThreadPoolMaxThreadCount(0);
35
36 std::shared_ptr<Display> display = ndk::SharedRefBase::make<Display>(exynos_display);
37 const std::string instance = std::string() + Display::descriptor + "/" + std::string(instance_str).c_str();
38 binder_status_t status =
39 AServiceManager_addService(display->asBinder().get(), instance.c_str());
40 LOG(INFO) << instance.c_str() << " service start...";
41 CHECK(status == STATUS_OK);
42
43 ABinderProcess_startThreadPool();
44 }
45
readCompensationImage(const aidl::android::hardware::common::NativeHandle & handle,const std::string & imageName)46 int32_t readCompensationImage(const aidl::android::hardware::common::NativeHandle &handle,
47 const std::string &imageName) {
48 ALOGI("setCompensationImageHandle, imageName = %s", imageName.c_str());
49
50 std::string shadowCompensationImage("/mnt/vendor/persist/display/");
51 shadowCompensationImage.append(imageName);
52
53 native_handle_t *clone = makeFromAidl(handle);
54
55 return load_png_image(shadowCompensationImage.c_str(), static_cast<buffer_handle_t>(clone));
56 }
57
58 namespace aidl {
59 namespace com {
60 namespace google {
61 namespace hardware {
62 namespace pixel {
63 namespace display {
64
65 // ----------------------------------------------------------------------------
66
isHbmSupported(bool * _aidl_return)67 ndk::ScopedAStatus Display::isHbmSupported(bool *_aidl_return) {
68 *_aidl_return = false;
69 return ndk::ScopedAStatus::ok();
70 }
71
setHbmState(HbmState state)72 ndk::ScopedAStatus Display::setHbmState(HbmState state) {
73 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
74 }
75
getHbmState(HbmState * _aidl_return)76 ndk::ScopedAStatus Display::getHbmState(HbmState *_aidl_return) {
77 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
78 }
79
isLbeSupported(bool * _aidl_return)80 ndk::ScopedAStatus Display::isLbeSupported(bool *_aidl_return) {
81 if (mDisplay) {
82 *_aidl_return = mDisplay->isLbeSupported();
83 return ndk::ScopedAStatus::ok();
84 }
85 *_aidl_return = false;
86 return ndk::ScopedAStatus::ok();
87 }
88
setLbeState(LbeState state)89 ndk::ScopedAStatus Display::setLbeState(LbeState state) {
90 if (mDisplay) {
91 mDisplay->setLbeState(state);
92 return ndk::ScopedAStatus::ok();
93 }
94 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
95 }
96
setLbeAmbientLight(int ambientLux)97 ndk::ScopedAStatus Display::setLbeAmbientLight(int ambientLux) {
98 if (mDisplay) {
99 mDisplay->setLbeAmbientLight(ambientLux);
100 return ndk::ScopedAStatus::ok();
101 }
102 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
103 }
104
getLbeState(LbeState * _aidl_return)105 ndk::ScopedAStatus Display::getLbeState(LbeState *_aidl_return) {
106 if (mDisplay) {
107 *_aidl_return = mDisplay->getLbeState();
108 return ndk::ScopedAStatus::ok();
109 }
110 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
111 }
112
isLhbmSupported(bool * _aidl_return)113 ndk::ScopedAStatus Display::isLhbmSupported(bool *_aidl_return) {
114 if (mDisplay) {
115 *_aidl_return = mDisplay->isLhbmSupported();
116 return ndk::ScopedAStatus::ok();
117 }
118 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
119 }
120
setLhbmState(bool enabled)121 ndk::ScopedAStatus Display::setLhbmState(bool enabled) {
122 if (mDisplay && mDisplay->isLhbmSupported()) {
123 int32_t ret = mDisplay->setLhbmState(enabled);
124 if (!ret)
125 return ndk::ScopedAStatus::ok();
126 else if (ret == TIMED_OUT)
127 return ndk::ScopedAStatus::fromExceptionCode(STATUS_TIMED_OUT);
128 }
129 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
130 }
131
getLhbmState(bool * _aidl_return)132 ndk::ScopedAStatus Display::getLhbmState(bool *_aidl_return) {
133 if (mDisplay && mDisplay->isLhbmSupported()) {
134 *_aidl_return = mDisplay->getLhbmState();
135 return ndk::ScopedAStatus::ok();
136 }
137 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
138 }
139
setCompensationImageHandle(const NativeHandle & native_handle,const std::string & imageName,int * _aidl_return)140 ndk::ScopedAStatus Display::setCompensationImageHandle(const NativeHandle &native_handle,
141 const std::string &imageName,
142 int *_aidl_return) {
143 if (mDisplay && mDisplay->isColorCalibratedByDevice()) {
144 *_aidl_return = readCompensationImage(native_handle, imageName);
145 } else {
146 *_aidl_return = -1;
147 }
148 return ndk::ScopedAStatus::ok();
149 }
150
setMinIdleRefreshRate(int fps,int * _aidl_return)151 ndk::ScopedAStatus Display::setMinIdleRefreshRate(int fps, int *_aidl_return) {
152 if (mDisplay) {
153 *_aidl_return = mDisplay->setMinIdleRefreshRate(fps);
154 return ndk::ScopedAStatus::ok();
155 }
156 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
157 }
158
setRefreshRateThrottle(int delayMs,int * _aidl_return)159 ndk::ScopedAStatus Display::setRefreshRateThrottle(int delayMs, int *_aidl_return) {
160 if (mDisplay) {
161 if (delayMs < 0) {
162 *_aidl_return = BAD_VALUE;
163 ALOGW("%s fail: delayMs(%d) is less than 0", __func__, delayMs);
164 return ndk::ScopedAStatus::ok();
165 }
166
167 *_aidl_return =
168 mDisplay->setRefreshRateThrottleNanos(std::chrono::duration_cast<
169 std::chrono::nanoseconds>(
170 std::chrono::milliseconds(delayMs))
171 .count(),
172 VrrThrottleRequester::PIXEL_DISP);
173 return ndk::ScopedAStatus::ok();
174 }
175 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
176 }
177
runMediator(const RoiRect roi,const Weight weight,const HistogramPos pos,std::vector<char16_t> * histogrambuffer)178 bool Display::runMediator(const RoiRect roi, const Weight weight, const HistogramPos pos,
179 std::vector<char16_t> *histogrambuffer) {
180 if (mMediator.setRoiWeightThreshold(roi, weight, pos) != HistogramErrorCode::NONE) {
181 ALOGE("histogram error, SET_ROI_WEIGHT_THRESHOLD ERROR\n");
182 return false;
183 }
184 if (!mMediator.histRequested() &&
185 mMediator.requestHist() == HistogramErrorCode::ENABLE_HIST_ERROR) {
186 ALOGE("histogram error, ENABLE_HIST ERROR\n");
187 }
188 if (mMediator.getFrameCount() != mMediator.getSampleFrameCounter()) {
189 mDisplay->mDevice->onRefresh(mDisplay->mDisplayId); // DRM not busy & sampled frame changed
190 }
191 if (mMediator.collectRoiLuma(histogrambuffer) != HistogramErrorCode::NONE) {
192 ALOGE("histogram error, COLLECT_ROI_LUMA ERROR\n");
193 return false;
194 }
195 return true;
196 }
197
histogramSample(const RoiRect & roi,const Weight & weight,HistogramPos pos,Priority pri,std::vector<char16_t> * histogrambuffer,HistogramErrorCode * _aidl_return)198 ndk::ScopedAStatus Display::histogramSample(const RoiRect &roi, const Weight &weight,
199 HistogramPos pos, Priority pri,
200 std::vector<char16_t> *histogrambuffer,
201 HistogramErrorCode *_aidl_return) {
202 if (!mDisplay) {
203 ALOGI("mDisplay is NULL \n");
204 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
205 }
206 if (histogrambuffer == nullptr) {
207 ALOGE("histogrambuffer is null");
208 *_aidl_return = HistogramErrorCode::BAD_HIST_DATA;
209 return ndk::ScopedAStatus::ok();
210 }
211 if (mMediator.isDisplayPowerOff() == true) {
212 *_aidl_return = HistogramErrorCode::DISPLAY_POWEROFF; // panel is off
213 return ndk::ScopedAStatus::ok();
214 }
215 if (mMediator.isSecureContentPresenting() == true) {
216 *_aidl_return = HistogramErrorCode::DRM_PLAYING; // panel is playing DRM content
217 return ndk::ScopedAStatus::ok();
218 }
219 if ((roi.left < 0) || (roi.top < 0) || ((roi.right - roi.left) <= 0) ||
220 ((roi.bottom - roi.top) <= 0)) {
221 *_aidl_return = HistogramErrorCode::BAD_ROI;
222 ALOGE("histogram error, BAD_ROI (%d, %d, %d, %d) \n", roi.left, roi.top, roi.right,
223 roi.bottom);
224 return ndk::ScopedAStatus::ok();
225 }
226 if ((weight.weightR + weight.weightG + weight.weightB) != (histogram::WEIGHT_SUM)) {
227 *_aidl_return = HistogramErrorCode::BAD_WEIGHT;
228 ALOGE("histogram error, BAD_WEIGHT(%d, %d, %d)\n", weight.weightR, weight.weightG,
229 weight.weightB);
230 return ndk::ScopedAStatus::ok();
231 }
232 if (pos != HistogramPos::POST && pos != HistogramPos::PRE) {
233 *_aidl_return = HistogramErrorCode::BAD_POSITION;
234 ALOGE("histogram error, BAD_POSITION(%d)\n", (int)pos);
235 return ndk::ScopedAStatus::ok();
236 }
237 if (pri != Priority::NORMAL && pri != Priority::PRIORITY) {
238 *_aidl_return = HistogramErrorCode::BAD_PRIORITY;
239 ALOGE("histogram error, BAD_PRIORITY(%d)\n", (int)pri);
240 return ndk::ScopedAStatus::ok();
241 }
242 RoiRect roiCaled = mMediator.calRoi(roi); // fit roi coordinates to RRS
243 runMediator(roiCaled, weight, pos, histogrambuffer);
244 if (mMediator.isSecureContentPresenting() == true) {
245 /* clear data to avoid leakage */
246 std::fill(histogrambuffer->begin(), histogrambuffer->end(), 0);
247 histogrambuffer->clear();
248 *_aidl_return = HistogramErrorCode::DRM_PLAYING; // panel is playing DRM content
249 return ndk::ScopedAStatus::ok();
250 }
251
252 *_aidl_return = HistogramErrorCode::NONE;
253 return ndk::ScopedAStatus::ok();
254 }
255
getPanelCalibrationStatus(PanelCalibrationStatus * _aidl_return)256 ndk::ScopedAStatus Display::getPanelCalibrationStatus(PanelCalibrationStatus *_aidl_return){
257 if (mDisplay) {
258 *_aidl_return = mDisplay->getPanelCalibrationStatus();
259 return ndk::ScopedAStatus::ok();
260 }
261 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
262 }
263
isDbmSupported(bool * _aidl_return)264 ndk::ScopedAStatus Display::isDbmSupported(bool *_aidl_return) {
265 if (!mDisplay) {
266 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
267 }
268 *_aidl_return = mDisplay->isDbmSupported();
269 return ndk::ScopedAStatus::ok();
270 }
271
setDbmState(bool enabled)272 ndk::ScopedAStatus Display::setDbmState(bool enabled) {
273 if (!mDisplay) {
274 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
275 }
276 mDisplay->setDbmState(enabled);
277 return ndk::ScopedAStatus::ok();
278 }
279
280 } // namespace display
281 } // namespace pixel
282 } // namespace hardware
283 } // namespace google
284 } // namespace com
285 } // namespace aidl
286