• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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