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 #include "HistogramController.h"
29
30 extern int32_t load_png_image(const char *filepath, buffer_handle_t buffer);
31
32 using ::aidl::com::google::hardware::pixel::display::Display;
33
PixelDisplayInit(ExynosDisplay * exynos_display,const std::string_view instance_str)34 void PixelDisplayInit(ExynosDisplay *exynos_display, const std::string_view instance_str) {
35 ABinderProcess_setThreadPoolMaxThreadCount(0);
36
37 std::shared_ptr<Display> display = ndk::SharedRefBase::make<Display>(exynos_display);
38 const std::string instance = std::string() + Display::descriptor + "/" + std::string(instance_str).c_str();
39 binder_status_t status =
40 AServiceManager_addService(display->asBinder().get(), instance.c_str());
41 LOG(INFO) << instance.c_str() << " service start...";
42 CHECK(status == STATUS_OK);
43
44 ABinderProcess_startThreadPool();
45 }
46
readCompensationImage(const aidl::android::hardware::common::NativeHandle & handle,const std::string & imageName)47 int32_t readCompensationImage(const aidl::android::hardware::common::NativeHandle &handle,
48 const std::string &imageName) {
49 ALOGI("setCompensationImageHandle, imageName = %s", imageName.c_str());
50
51 std::string shadowCompensationImage("/mnt/vendor/persist/display/");
52 shadowCompensationImage.append(imageName);
53
54 native_handle_t *clone = makeFromAidl(handle);
55
56 return load_png_image(shadowCompensationImage.c_str(), static_cast<buffer_handle_t>(clone));
57 }
58
59 namespace aidl {
60 namespace com {
61 namespace google {
62 namespace hardware {
63 namespace pixel {
64 namespace display {
65
66 // ----------------------------------------------------------------------------
67
isHbmSupported(bool * _aidl_return)68 ndk::ScopedAStatus Display::isHbmSupported(bool *_aidl_return) {
69 *_aidl_return = false;
70 return ndk::ScopedAStatus::ok();
71 }
72
setHbmState(HbmState state)73 ndk::ScopedAStatus Display::setHbmState(HbmState state) {
74 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
75 }
76
getHbmState(HbmState * _aidl_return)77 ndk::ScopedAStatus Display::getHbmState(HbmState *_aidl_return) {
78 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
79 }
80
isLbeSupported(bool * _aidl_return)81 ndk::ScopedAStatus Display::isLbeSupported(bool *_aidl_return) {
82 if (mDisplay) {
83 *_aidl_return = mDisplay->isLbeSupported();
84 return ndk::ScopedAStatus::ok();
85 }
86 *_aidl_return = false;
87 return ndk::ScopedAStatus::ok();
88 }
89
setLbeState(LbeState state)90 ndk::ScopedAStatus Display::setLbeState(LbeState state) {
91 if (mDisplay) {
92 mDisplay->setLbeState(state);
93 return ndk::ScopedAStatus::ok();
94 }
95 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
96 }
97
setLbeAmbientLight(int ambientLux)98 ndk::ScopedAStatus Display::setLbeAmbientLight(int ambientLux) {
99 if (mDisplay) {
100 mDisplay->setLbeAmbientLight(ambientLux);
101 return ndk::ScopedAStatus::ok();
102 }
103 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
104 }
105
getLbeState(LbeState * _aidl_return)106 ndk::ScopedAStatus Display::getLbeState(LbeState *_aidl_return) {
107 if (mDisplay) {
108 *_aidl_return = mDisplay->getLbeState();
109 return ndk::ScopedAStatus::ok();
110 }
111 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
112 }
113
isLhbmSupported(bool * _aidl_return)114 ndk::ScopedAStatus Display::isLhbmSupported(bool *_aidl_return) {
115 if (mDisplay) {
116 *_aidl_return = mDisplay->isLhbmSupported();
117 return ndk::ScopedAStatus::ok();
118 }
119 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
120 }
121
setLhbmState(bool enabled)122 ndk::ScopedAStatus Display::setLhbmState(bool enabled) {
123 if (mDisplay && mDisplay->isLhbmSupported()) {
124 int32_t ret = mDisplay->setLhbmState(enabled);
125 if (!ret)
126 return ndk::ScopedAStatus::ok();
127 else if (ret == TIMED_OUT)
128 return ndk::ScopedAStatus::fromExceptionCode(STATUS_TIMED_OUT);
129 }
130 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
131 }
132
getLhbmState(bool * _aidl_return)133 ndk::ScopedAStatus Display::getLhbmState(bool *_aidl_return) {
134 if (mDisplay && mDisplay->isLhbmSupported()) {
135 *_aidl_return = mDisplay->getLhbmState();
136 return ndk::ScopedAStatus::ok();
137 }
138 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
139 }
140
setPeakRefreshRate(int rate)141 ndk::ScopedAStatus Display::setPeakRefreshRate(int rate) {
142 if (mDisplay && mDisplay->mOperationRateManager) {
143 mDisplay->mOperationRateManager->onPeakRefreshRate(rate);
144 return ndk::ScopedAStatus::ok();
145 }
146 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
147 }
148
setLowPowerMode(bool enabled)149 ndk::ScopedAStatus Display::setLowPowerMode(bool enabled) {
150 if (mDisplay && mDisplay->mOperationRateManager) {
151 mDisplay->mOperationRateManager->onLowPowerMode(enabled);
152 return ndk::ScopedAStatus::ok();
153 }
154 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
155 }
156
isOperationRateSupported(bool * _aidl_return)157 ndk::ScopedAStatus Display::isOperationRateSupported(bool *_aidl_return) {
158 if (mDisplay) {
159 *_aidl_return = mDisplay->isOperationRateSupported();
160 return ndk::ScopedAStatus::ok();
161 }
162 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
163 }
164
setCompensationImageHandle(const NativeHandle & native_handle,const std::string & imageName,int * _aidl_return)165 ndk::ScopedAStatus Display::setCompensationImageHandle(const NativeHandle &native_handle,
166 const std::string &imageName,
167 int *_aidl_return) {
168 if (mDisplay && mDisplay->isColorCalibratedByDevice()) {
169 *_aidl_return = readCompensationImage(native_handle, imageName);
170 } else {
171 *_aidl_return = -1;
172 }
173 return ndk::ScopedAStatus::ok();
174 }
175
setMinIdleRefreshRate(int fps,int * _aidl_return)176 ndk::ScopedAStatus Display::setMinIdleRefreshRate(int fps, int *_aidl_return) {
177 if (mDisplay) {
178 *_aidl_return = mDisplay->setMinIdleRefreshRate(fps, VrrThrottleRequester::PIXEL_DISP);
179 return ndk::ScopedAStatus::ok();
180 }
181 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
182 }
183
setRefreshRateThrottle(int delayMs,int * _aidl_return)184 ndk::ScopedAStatus Display::setRefreshRateThrottle(int delayMs, int *_aidl_return) {
185 if (mDisplay) {
186 if (delayMs < 0) {
187 *_aidl_return = BAD_VALUE;
188 ALOGW("%s fail: delayMs(%d) is less than 0", __func__, delayMs);
189 return ndk::ScopedAStatus::ok();
190 }
191
192 *_aidl_return =
193 mDisplay->setRefreshRateThrottleNanos(std::chrono::duration_cast<
194 std::chrono::nanoseconds>(
195 std::chrono::milliseconds(delayMs))
196 .count(),
197 VrrThrottleRequester::PIXEL_DISP);
198 return ndk::ScopedAStatus::ok();
199 }
200 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
201 }
202
runMediator(const RoiRect & roi,const Weight & weight,const HistogramPos & pos,std::vector<char16_t> * histogrambuffer)203 bool Display::runMediator(const RoiRect &roi, const Weight &weight, const HistogramPos &pos,
204 std::vector<char16_t> *histogrambuffer) {
205 bool isConfigChanged;
206 histogram::HistogramMediator::HistogramConfig pendingConfig(roi, weight, pos);
207
208 {
209 std::scoped_lock lock(mMediator.mConfigMutex);
210 isConfigChanged = mMediator.mConfig != pendingConfig;
211
212 if (isConfigChanged &&
213 mMediator.setRoiWeightThreshold(roi, weight, pos) != HistogramErrorCode::NONE) {
214 ALOGE("histogram error, SET_ROI_WEIGHT_THRESHOLD ERROR\n");
215 return false;
216 }
217
218 mMediator.mConfig = pendingConfig;
219 }
220
221 if (!mMediator.histRequested() &&
222 mMediator.requestHist() == HistogramErrorCode::ENABLE_HIST_ERROR) {
223 ALOGE("histogram error, ENABLE_HIST ERROR\n");
224 }
225
226 /*
227 * DPU driver maintains always-on histogram engine state with up to date histogram data.
228 * Therefore we don't have explicitly to trigger onRefresh in case histogram configuration
229 * does not change.
230 */
231 if (isConfigChanged) {
232 mDisplay->mDevice->onRefresh(mDisplay->mDisplayId);
233 }
234
235 if (mMediator.collectRoiLuma(histogrambuffer) != HistogramErrorCode::NONE) {
236 ALOGE("histogram error, COLLECT_ROI_LUMA ERROR\n");
237 return false;
238 }
239 return true;
240 }
241
histogramSample(const RoiRect & roi,const Weight & weight,HistogramPos pos,Priority pri,std::vector<char16_t> * histogrambuffer,HistogramErrorCode * _aidl_return)242 ndk::ScopedAStatus Display::histogramSample(const RoiRect &roi, const Weight &weight,
243 HistogramPos pos, Priority pri,
244 std::vector<char16_t> *histogrambuffer,
245 HistogramErrorCode *_aidl_return) {
246 if (!mDisplay) {
247 ALOGI("mDisplay is NULL \n");
248 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
249 }
250 if (histogrambuffer == nullptr) {
251 ALOGE("histogrambuffer is null");
252 *_aidl_return = HistogramErrorCode::BAD_HIST_DATA;
253 return ndk::ScopedAStatus::ok();
254 }
255 if (mDisplay->isPowerModeOff() == true) {
256 *_aidl_return = HistogramErrorCode::DISPLAY_POWEROFF; // panel is off
257 return ndk::ScopedAStatus::ok();
258 }
259 if (mDisplay->isSecureContentPresenting() == true) {
260 *_aidl_return = HistogramErrorCode::DRM_PLAYING; // panel is playing DRM content
261 return ndk::ScopedAStatus::ok();
262 }
263 if ((roi.left < 0) || (roi.top < 0) || ((roi.right - roi.left) <= 0) ||
264 ((roi.bottom - roi.top) <= 0)) {
265 *_aidl_return = HistogramErrorCode::BAD_ROI;
266 ALOGE("histogram error, BAD_ROI (%d, %d, %d, %d) \n", roi.left, roi.top, roi.right,
267 roi.bottom);
268 return ndk::ScopedAStatus::ok();
269 }
270 if ((weight.weightR + weight.weightG + weight.weightB) != (histogram::WEIGHT_SUM)) {
271 *_aidl_return = HistogramErrorCode::BAD_WEIGHT;
272 ALOGE("histogram error, BAD_WEIGHT(%d, %d, %d)\n", weight.weightR, weight.weightG,
273 weight.weightB);
274 return ndk::ScopedAStatus::ok();
275 }
276 if (pos != HistogramPos::POST && pos != HistogramPos::PRE) {
277 *_aidl_return = HistogramErrorCode::BAD_POSITION;
278 ALOGE("histogram error, BAD_POSITION(%d)\n", (int)pos);
279 return ndk::ScopedAStatus::ok();
280 }
281 if (pri != Priority::NORMAL && pri != Priority::PRIORITY) {
282 *_aidl_return = HistogramErrorCode::BAD_PRIORITY;
283 ALOGE("histogram error, BAD_PRIORITY(%d)\n", (int)pri);
284 return ndk::ScopedAStatus::ok();
285 }
286 RoiRect roiCaled = mMediator.calRoi(roi); // fit roi coordinates to RRS
287 runMediator(roiCaled, weight, pos, histogrambuffer);
288 if (mDisplay->isSecureContentPresenting() == true) {
289 /* clear data to avoid leakage */
290 std::fill(histogrambuffer->begin(), histogrambuffer->end(), 0);
291 histogrambuffer->clear();
292 *_aidl_return = HistogramErrorCode::DRM_PLAYING; // panel is playing DRM content
293 return ndk::ScopedAStatus::ok();
294 }
295
296 *_aidl_return = HistogramErrorCode::NONE;
297 return ndk::ScopedAStatus::ok();
298 }
299
getPanelCalibrationStatus(PanelCalibrationStatus * _aidl_return)300 ndk::ScopedAStatus Display::getPanelCalibrationStatus(PanelCalibrationStatus *_aidl_return){
301 if (mDisplay) {
302 *_aidl_return = mDisplay->getPanelCalibrationStatus();
303 return ndk::ScopedAStatus::ok();
304 }
305 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
306 }
307
isDbmSupported(bool * _aidl_return)308 ndk::ScopedAStatus Display::isDbmSupported(bool *_aidl_return) {
309 if (!mDisplay) {
310 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
311 }
312 *_aidl_return = mDisplay->isDbmSupported();
313 return ndk::ScopedAStatus::ok();
314 }
315
setDbmState(bool enabled)316 ndk::ScopedAStatus Display::setDbmState(bool enabled) {
317 if (!mDisplay) {
318 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
319 }
320 mDisplay->setDbmState(enabled);
321 return ndk::ScopedAStatus::ok();
322 }
323
getHistogramCapability(HistogramCapability * _aidl_return)324 ndk::ScopedAStatus Display::getHistogramCapability(HistogramCapability *_aidl_return) {
325 if (mDisplay && mDisplay->mHistogramController) {
326 return mDisplay->mHistogramController->getHistogramCapability(_aidl_return);
327 }
328 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
329 }
330
registerHistogram(const ndk::SpAIBinder & token,const HistogramConfig & histogramConfig,HistogramErrorCode * _aidl_return)331 ndk::ScopedAStatus Display::registerHistogram(const ndk::SpAIBinder &token,
332 const HistogramConfig &histogramConfig,
333 HistogramErrorCode *_aidl_return) {
334 if (mDisplay && mDisplay->mHistogramController) {
335 return mDisplay->mHistogramController->registerHistogram(token, histogramConfig,
336 _aidl_return);
337 }
338 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
339 }
340
queryHistogram(const ndk::SpAIBinder & token,std::vector<char16_t> * histogramBuffer,HistogramErrorCode * _aidl_return)341 ndk::ScopedAStatus Display::queryHistogram(const ndk::SpAIBinder &token,
342 std::vector<char16_t> *histogramBuffer,
343 HistogramErrorCode *_aidl_return) {
344 if (mDisplay && mDisplay->mHistogramController) {
345 return mDisplay->mHistogramController->queryHistogram(token, histogramBuffer, _aidl_return);
346 }
347 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
348 }
349
reconfigHistogram(const ndk::SpAIBinder & token,const HistogramConfig & histogramConfig,HistogramErrorCode * _aidl_return)350 ndk::ScopedAStatus Display::reconfigHistogram(const ndk::SpAIBinder &token,
351 const HistogramConfig &histogramConfig,
352 HistogramErrorCode *_aidl_return) {
353 if (mDisplay && mDisplay->mHistogramController) {
354 return mDisplay->mHistogramController->reconfigHistogram(token, histogramConfig,
355 _aidl_return);
356 }
357 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
358 }
359
unregisterHistogram(const ndk::SpAIBinder & token,HistogramErrorCode * _aidl_return)360 ndk::ScopedAStatus Display::unregisterHistogram(const ndk::SpAIBinder &token,
361 HistogramErrorCode *_aidl_return) {
362 if (mDisplay && mDisplay->mHistogramController) {
363 return mDisplay->mHistogramController->unregisterHistogram(token, _aidl_return);
364 }
365 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
366 }
367
368 } // namespace display
369 } // namespace pixel
370 } // namespace hardware
371 } // namespace google
372 } // namespace com
373 } // namespace aidl
374