• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 #pragma once
18 
19 #include <aidl/android/hardware/graphics/common/Rect.h>
20 #include <aidl/com/google/hardware/pixel/display/HistogramCapability.h>
21 #include <aidl/com/google/hardware/pixel/display/HistogramConfig.h>
22 #include <aidl/com/google/hardware/pixel/display/HistogramErrorCode.h>
23 #include <aidl/com/google/hardware/pixel/display/HistogramSamplePos.h>
24 #include <aidl/com/google/hardware/pixel/display/Weight.h>
25 #include <android-base/thread_annotations.h>
26 #include <drm/samsung_drm.h>
27 #include <utils/String8.h>
28 
29 #include <condition_variable>
30 #include <list>
31 #include <memory>
32 #include <mutex>
33 #include <shared_mutex>
34 #include <unordered_map>
35 
36 #include "ExynosDisplay.h"
37 #include "ExynosDisplayDrmInterface.h"
38 #include "drmcrtc.h"
39 
40 #define HIST_BLOB_CH_LOG(LEVEL, blobId, channelId, msg, ...)              \
41     ALOG##LEVEL("[%s,pid=%d,blob#%u,chan#%d] HistogramDevice::%s: " msg,  \
42                 ((mDisplay) ? (mDisplay->mDisplayName.c_str()) : "NULL"), \
43                 AIBinder_getCallingPid(), blobId, channelId, __func__, ##__VA_ARGS__)
44 
45 #define HIST_BLOB_LOG(LEVEL, blobId, msg, ...)                            \
46     ALOG##LEVEL("[%s,pid=%d,blob#%u] HistogramDevice::%s: " msg,          \
47                 ((mDisplay) ? (mDisplay->mDisplayName.c_str()) : "NULL"), \
48                 AIBinder_getCallingPid(), blobId, __func__, ##__VA_ARGS__)
49 
50 #define HIST_CH_LOG(LEVEL, channelId, msg, ...)                           \
51     ALOG##LEVEL("[%s,pid=%d,chan#%d] HistogramDevice::%s: " msg,          \
52                 ((mDisplay) ? (mDisplay->mDisplayName.c_str()) : "NULL"), \
53                 AIBinder_getCallingPid(), channelId, __func__, ##__VA_ARGS__)
54 
55 #define HIST_LOG(LEVEL, msg, ...)                                         \
56     ALOG##LEVEL("[%s,pid=%d] HistogramDevice::%s: " msg,                  \
57                 ((mDisplay) ? (mDisplay->mDisplayName.c_str()) : "NULL"), \
58                 AIBinder_getCallingPid(), __func__, ##__VA_ARGS__)
59 
60 #define SCOPED_HIST_LOCK(mutex)   \
61     std::scoped_lock lock(mutex); \
62     ATRACE_NAME(#mutex);
63 
64 using namespace android;
65 
66 class HistogramDevice {
67 public:
68     using HistogramCapability = aidl::com::google::hardware::pixel::display::HistogramCapability;
69     using HistogramConfig = aidl::com::google::hardware::pixel::display::HistogramConfig;
70     using HistogramErrorCode = aidl::com::google::hardware::pixel::display::HistogramErrorCode;
71     using HistogramRoiRect = aidl::android::hardware::graphics::common::Rect;
72     using HistogramSamplePos = aidl::com::google::hardware::pixel::display::HistogramSamplePos;
73     using HistogramWeights = aidl::com::google::hardware::pixel::display::Weight;
74     using ContextHistogramIoctl_t = ExynosDisplayDrmInterface::ContextHistogramIoctl_t;
75     using HistogramChannelIoctl_t = ExynosDisplayDrmInterface::HistogramChannelIoctl_t;
76 
77     class PropertyBlob;
78 
79     /* For blocking roi and roi, (0, 0, 0, 0) means disabled */
80     static constexpr HistogramRoiRect DISABLED_ROI = {0, 0, 0, 0};
81 
82     /* Histogram weight constraint: weightR + weightG + weightB = WEIGHT_SUM */
83     static constexpr size_t WEIGHT_SUM = 1024;
84 
85     static constexpr size_t HISTOGRAM_BINS_SIZE = 256;
86 
87     /* OPR_R, OPR_G, OPR_B */
88     static constexpr int kOPRConfigsCount = 3;
89 
90     struct BlobInfo {
91         const int mDisplayActiveH, mDisplayActiveV;
92         const std::shared_ptr<PropertyBlob> mBlob;
BlobInfoBlobInfo93         BlobInfo(const int displayActiveH, const int displayActiveV,
94                  const std::shared_ptr<PropertyBlob>& drmConfigBlob)
95               : mDisplayActiveH(displayActiveH),
96                 mDisplayActiveV(displayActiveV),
97                 mBlob(drmConfigBlob) {}
98     };
99 
100     struct ConfigInfo {
101         enum class Status_t : uint8_t {
102             INITIALIZED, // Not in the inactive list and no channel assigned
103             IN_INACTIVE_LIST,
104             HAS_CHANNEL_ASSIGNED,
105         };
106 
107         const HistogramConfig mRequestedConfig;
108         Status_t mStatus = Status_t::INITIALIZED;
109         int mChannelId = -1;
110         std::list<const BlobInfo> mBlobsList;
111         std::list<std::weak_ptr<ConfigInfo>>::iterator mInactiveListIt;
ConfigInfoConfigInfo112         ConfigInfo(const HistogramConfig& histogramConfig) : mRequestedConfig(histogramConfig) {}
113         void dump(String8& result, const char* prefix = "") const;
114     };
115 
116     /* Histogram channel status */
117     enum class ChannelStatus_t : uint32_t {
118         /* occupied by the driver for specific usage such as LHBM */
119         RESERVED = 0,
120 
121         /* channel is off */
122         DISABLED,
123 
124         /* channel config is ready and requires to be added into an atomic commit */
125         CONFIG_PENDING,
126 
127         /* channel config (blob) is added to an atomic commit but not committed yet */
128         CONFIG_BLOB_ADDED,
129 
130         /* channel config is committed to drm driver successfully */
131         CONFIG_COMMITTED,
132 
133         /* channel config has error */
134         CONFIG_ERROR,
135 
136         /* channel is released and requires an atomic commit to cleanup completely */
137         DISABLE_PENDING,
138 
139         /* channel is released and the cleanup blob is added but not committed yet */
140         DISABLE_BLOB_ADDED,
141 
142         /* channel disable has error */
143         DISABLE_ERROR,
144     };
145 
146     struct ChannelInfo {
147         /* track the channel status */
148         ChannelStatus_t mStatus;
149         std::weak_ptr<ConfigInfo> mConfigInfo;
150 
ChannelInfoChannelInfo151         ChannelInfo() : mStatus(ChannelStatus_t::DISABLED) {}
152         ChannelInfo(const ChannelInfo& other) = default;
153     };
154 
155     struct TokenInfo {
156         /* The binderdied callback would call unregisterHistogram (member function of this object)
157          * to release resource. */
158         HistogramDevice* const mHistogramDevice;
159 
160         /* The binderdied callback would call unregisterHistogram with this token to release
161          * resource. */
162         const ndk::SpAIBinder mToken;
163 
164         /* The process id of the client that calls registerHistogram. */
165         const pid_t mPid;
166 
167         /* The shared pointer to the ConfigInfo. */
168         std::shared_ptr<ConfigInfo> mConfigInfo;
169 
TokenInfoTokenInfo170         TokenInfo(HistogramDevice* histogramDevice, const ndk::SpAIBinder& token, pid_t pid)
171               : mHistogramDevice(histogramDevice), mToken(token), mPid(pid) {}
172         void dump(String8& result, const char* prefix = "") const;
173     };
174 
175     enum class CollectStatus_t : uint8_t {
176         NOT_STARTED = 0,
177         COLLECTING,
178         COLLECTED,
179     };
180 
181     struct BlobIdData {
182         mutable std::mutex mDataCollectingMutex;
183         uint16_t mData[HISTOGRAM_BIN_COUNT] GUARDED_BY(mDataCollectingMutex);
184         CollectStatus_t mCollectStatus GUARDED_BY(mDataCollectingMutex) =
185                 CollectStatus_t::NOT_STARTED;
186         std::condition_variable mDataCollecting_cv GUARDED_BY(mDataCollectingMutex);
187     };
188 
189     /**
190      * HistogramDevice
191      *
192      * Construct the HistogramDevice to mange histogram channel.
193      *
194      * @display display pointer which would be stored in mDisplay.
195      * @channelCount number of the histogram channels in the system.
196      * @reservedChannels a list of channel id that are reserved by the driver.
197      */
198     explicit HistogramDevice(ExynosDisplay* const display, const uint8_t channelCount,
199                              const std::vector<uint8_t> reservedChannels);
200 
201     /**
202      * ~HistogramDevice
203      *
204      * Destruct the HistogramDevice.
205      */
206     virtual ~HistogramDevice();
207 
208     /**
209      * initDrm
210      *
211      * Get histogram info from crtc property and initialize the mHistogramCapability.
212      *     1. The available histogram channel bitmask.
213      *     2. Determine kernel support multi channel property or not.
214      *
215      * @device drm device object which will be used to create the config blob.
216      * @crtc drm crtc object which would contain histogram related information.
217      */
218     void initDrm(DrmDevice& device, const DrmCrtc& crtc)
219             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
220 
221     /**
222      * getHistogramCapability
223      *
224      * Return the histogram capability for the system.
225      *
226      * @histogramCapability: describe the histogram capability for the system.
227      * @return ok() when the interface is supported and arguments are valid, else otherwise.
228      */
229     ndk::ScopedAStatus getHistogramCapability(HistogramCapability* histogramCapability) const
230             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
231 
232     /**
233      * registerHistogram
234      *
235      * Register the histogram sampling config, and queue into the mInactiveConfigItList. Scheduler
236      * will help to apply the config if possible. If the display is not turned on, just store the
237      * histogram config. Otherwise, trigger the onRefresh call to force the config take effect, and
238      * then the DPU hardware will continuously sample the histogram data.
239      *
240      * @token binder object created by the client whose lifetime should be equal to the client. When
241      * the binder object is destructed, the unregisterHistogram would be called automatically. Token
242      * serves as the handle in every histogram operation.
243      * @histogramConfig histogram config from the client.
244      * @histogramErrorCode NONE when no error, or else otherwise. Client should retry when failed.
245      * @return ok() when the interface is supported, or EX_UNSUPPORTED_OPERATION when the interface
246      * is not supported yet.
247      */
248     ndk::ScopedAStatus registerHistogram(const ndk::SpAIBinder& token,
249                                          const HistogramConfig& histogramConfig,
250                                          HistogramErrorCode* histogramErrorCode)
251             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
252 
253     /**
254      * queryHistogram
255      *
256      * Query the histogram data from the corresponding channel of the token.
257      *
258      * @token is the handle registered via registerHistogram which would be used to identify the
259      * channel.
260      * @histogramBuffer 256 * 16 bits buffer to store the luma counts return by the histogram
261      * hardware.
262      * @histogramErrorCode NONE when no error, or else otherwise. Client should examine this
263      * errorcode.
264      * @return ok() when the interface is supported, or EX_UNSUPPORTED_OPERATION when the interface
265      * is not supported yet.
266      */
267     ndk::ScopedAStatus queryHistogram(const ndk::SpAIBinder& token,
268                                       std::vector<char16_t>* histogramBuffer,
269                                       HistogramErrorCode* histogramErrorCode)
270             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
271 
272     /**
273      * reconfigHistogram
274      *
275      * Change the histogram config for the corresponding channel of the token.
276      *
277      * @token is the handle registered via registerHistogram which would be used to identify the
278      * channel.
279      * @histogramConfig histogram config from the client.
280      * @histogramErrorCode NONE when no error, or else otherwise. Client should examine this
281      * errorcode.
282      * @return ok() when the interface is supported, or EX_UNSUPPORTED_OPERATION when the interface
283      * is not supported yet.
284      */
285     ndk::ScopedAStatus reconfigHistogram(const ndk::SpAIBinder& token,
286                                          const HistogramConfig& histogramConfig,
287                                          HistogramErrorCode* histogramErrorCode)
288             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
289 
290     /**
291      * unregisterHistogram
292      *
293      * Release the corresponding channel of the token and add the channel id to free channel list.
294      *
295      * @token is the handle registered via registerHistogram which would be used to identify the
296      * channel.
297      * @histogramErrorCode NONE when no error, or else otherwise. Client should examine this
298      * errorcode.
299      * @return ok() when the interface is supported, or EX_UNSUPPORTED_OPERATION when the interface
300      * is not supported yet.
301      */
302     ndk::ScopedAStatus unregisterHistogram(const ndk::SpAIBinder& token,
303                                            HistogramErrorCode* histogramErrorCode)
304             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
305 
306     /**
307      * queryOPR
308      *
309      * Query the linear space OPR.
310      *
311      * @oprVals will store the [OPR_R, OPR_G, OPR_B], 0 <= OPR_R, OPR_G, OPR_B <= 1
312      */
queryOPR(std::array<double,kOPRConfigsCount> & oprVals)313     virtual ndk::ScopedAStatus queryOPR(std::array<double, kOPRConfigsCount>& oprVals)
314             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex) {
315         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
316     }
317 
318     /**
319      * handleDrmEvent
320      *
321      * Handle the histogram blob drm event (EXYNOS_DRM_HISTOGRAM_CHANNEL_EVENT) and copy the
322      * histogram data from event struct to channel info.
323      *
324      * @event histogram blob drm event pointer (struct exynos_drm_histogram_channel_event *)
325      */
326     void handleDrmEvent(void* event) EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
327 
328     /**
329      * handleContextDrmEvent
330      *
331      * Handle the histogram blob drm event (EXYNOS_DRM_CONTEXT_HISTOGRAM_EVENT) and copy the
332      * histogram data from event struct to blobIdData.
333      *
334      * @event context histogram event pointer (struct exynos_drm_context_histogram_event *)
335      */
336     void handleContextDrmEvent(void* event)
337             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
338 
339     /**
340      * prepareAtomicCommit
341      *
342      * Prepare the histogram atomic commit for each channel (see prepareChannelCommit).
343      *
344      * @drmReq drm atomic request object
345      */
346     void prepareAtomicCommit(ExynosDisplayDrmInterface::DrmModeAtomicReq& drmReq)
347             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
348 
349     /**
350      * postAtomicCommit
351      *
352      * After the atomic commit is done, update the channel status as below.
353      * Channel_Status:
354      *     CONFIG_BLOB_ADDED  -> CONFIG_COMMITTED
355      *     DISABLE_BLOB_ADDED -> DISABLED
356      */
357     void postAtomicCommit() EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
358 
postAtomicCommitCleanup()359     virtual void postAtomicCommitCleanup()
360             EXCLUDES(mHistogramMutex, mInitDrmDoneMutex, mBlobIdDataMutex) {}
361 
errorToStatus(const HistogramErrorCode histogramErrorCode)362     inline ndk::ScopedAStatus errorToStatus(const HistogramErrorCode histogramErrorCode) const {
363         return ndk::ScopedAStatus::
364                 fromServiceSpecificErrorWithMessage(static_cast<int>(histogramErrorCode),
365                                                     aidl::com::google::hardware::pixel::display::
366                                                             toString(histogramErrorCode)
367                                                                     .c_str());
368     }
369 
370     /**
371      * dump
372      *
373      * Dump histogram information.
374      *
375      * @result histogram dump information would be appended to this string
376      */
377     void dump(String8& result) const EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
378 
379 protected:
380     mutable std::shared_mutex mHistogramCapabilityMutex;
381     HistogramCapability mHistogramCapability;
382 
383     ExynosDisplay* const mDisplay;
384     DrmDevice* mDrmDevice = nullptr;
385 
386     mutable std::mutex mHistogramMutex;
387     std::unordered_map<AIBinder*, TokenInfo> mTokenInfoMap GUARDED_BY(mHistogramMutex);
388     std::list<const uint8_t> mFreeChannels GUARDED_BY(mHistogramMutex); // free channel list
389     std::set<const uint8_t> mUsedChannels GUARDED_BY(mHistogramMutex);  // all - free - reserved
390     std::vector<ChannelInfo> mChannels GUARDED_BY(mHistogramMutex);
391     std::list<std::weak_ptr<ConfigInfo>> mInactiveConfigItList GUARDED_BY(mHistogramMutex);
392 
393     mutable std::mutex mBlobIdDataMutex;
394     std::unordered_map<uint32_t, const std::shared_ptr<BlobIdData>> mBlobIdDataMap
395             GUARDED_BY(mBlobIdDataMutex);
396 
397     mutable std::mutex mInitDrmDoneMutex;
398     bool mInitDrmDone GUARDED_BY(mInitDrmDoneMutex) = false;
399     mutable std::condition_variable mInitDrmDone_cv GUARDED_BY(mInitDrmDoneMutex);
400 
401     /* Death recipient for the binderdied callback, would be deleted in the destructor */
402     AIBinder_DeathRecipient* mDeathRecipient = nullptr;
403 
404     /**
405      * initChannels
406      *
407      * Allocate channelCount channels and initialize the channel status for every channel.
408      *
409      * @channelCount number of channels in the system including the reserved channels.
410      * @reservedChannels a list of channel id that are reserved by the driver.
411      */
412     void initChannels(const uint8_t channelCount, const std::vector<uint8_t>& reservedChannels)
413             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
414 
415     /**
416      * initHistogramCapability
417      *
418      * Initialize the histogramCapability which would be queried by the client (see
419      * getHistogramCapability).
420      *
421      * @supportMultiChannel true if the kernel support multi channel property, false otherwise.
422      */
423     void initHistogramCapability(const bool supportMultiChannel)
424             EXCLUDES(mHistogramMutex, mBlobIdDataMutex);
425 
426     /**
427      * initPlatformHistogramCapability
428      *
429      * Initialize platform specific histogram capability.
430      */
initPlatformHistogramCapability()431     virtual void initPlatformHistogramCapability() {}
432 
433     /**
434      * waitInitDrmDone
435      *
436      * Wait until the initDrm is finished, or when the timeout expires.
437      *
438      * @return true if initDrm is finished, or false when the timeout expires.
439      */
440     bool waitInitDrmDone() const EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
441 
442     /**
443      * replaceConfigInfo
444      *
445      * If histogramConfig is not nullptr, the configInfo pointer will point to the generated
446      * ConfigInfo of the histogramConfig. Otherwise, histogramConfig is reset to the nullptr.
447      * For the original ConfigInfo, every created blob will be released.
448      *
449      * @configInfo is the reference to the shared_ptr of ConfigInfo that will be updated depends on
450      * histogramConfig.
451      * @histogramConfig is the new requested config or nullptr to clear the configInfo ptr.
452      */
453     void replaceConfigInfo(std::shared_ptr<ConfigInfo>& configInfo,
454                            const HistogramConfig* histogramConfig) REQUIRES(mHistogramMutex)
455             EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex);
456 
457     /**
458      * searchTokenInfo
459      *
460      * Search the corresponding TokenInfo of the token object.
461      *
462      * @token is the key to be searched.
463      * @tokenInfo is the result pointer to the corresponding TokenInfo.
464      */
465     HistogramErrorCode searchTokenInfo(const ndk::SpAIBinder& token, TokenInfo*& tokenInfo)
466             REQUIRES(mHistogramMutex) EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex);
467 
468     /**
469      * swapInConfigInfo
470      *
471      * Move the configInfo from the mInactiveConfigItList to the first free channel. Caller should
472      * ensure mFreeChannels is not empty.
473      *
474      * @configInfo is the config to be moved from inactive list to the histogram channel.
475      * @return is the iterator of the next object in the mInactiveConfigItList after deletion.
476      */
477     std::list<std::weak_ptr<ConfigInfo>>::iterator swapInConfigInfo(
478             std::shared_ptr<ConfigInfo>& configInfo) REQUIRES(mHistogramMutex)
479             EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex);
480 
481     /**
482      * swapOutConfigInfo
483      *
484      * Swap out the configInfo from the specified histogram channel to mInactiveConfigItList.
485      *
486      * @channelId histogram channel to be swapped out
487      */
488     void swapOutConfigInfo(uint8_t channelId) REQUIRES(mHistogramMutex)
489             EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex);
490 
491     /**
492      * addConfigToInactiveList
493      *
494      * Add the configInfo (status is NOT_READY) into mInactiveConfigItList.
495      *
496      * @configInfo operated configino
497      */
498     void addConfigToInactiveList(const std::shared_ptr<ConfigInfo>& configInfo,
499                                  bool addToFront = false) REQUIRES(mHistogramMutex)
500             EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex);
501 
502     /**
503      * scheduler
504      *
505      * Move every configInfo from the mInactiveConfigItList to the idle histogram channel until no
506      * idle channel exists.
507      *
508      * @return true if there is any configInfo moved to histogram channel, false otherwise.
509      */
510     bool scheduler() REQUIRES(mHistogramMutex) EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex);
511 
512     /**
513      * searchOrCreateBlobIdData
514      *
515      * Search the corresponding blobIdData of blobId from mBlobIdDataMap.
516      *
517      * @blobId is the blob id to be searched in mBlobIdDataMap.
518      * @create is true if the caller would like to create blobIdData when doesn't exist.
519      * @blobIdData stores the pointer to the blobIdData if any, else point to nullptr.
520      */
521     void searchOrCreateBlobIdData(uint32_t blobId, bool create,
522                                   std::shared_ptr<BlobIdData>& blobIdData)
523             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
524 
525     /**
526      * getChanIdBlobId
527      *
528      * Convert the token into the channelId and the blobId. ChannelId means the current applied
529      * channel (-1 if config is inactive) of the config registered by token. BlobId is the first
530      * blob id in the mBlobsList. Caller should check the histogram before using the channelId and
531      * blobId.
532      *
533      * @token is the token object registered by registerHistogram.
534      * @histogramErrorCode stores any error during query.
535      * @channelId is the channel id.
536      * @blobId is the blob id.
537      */
538     void getChanIdBlobId(const ndk::SpAIBinder& token, HistogramErrorCode* histogramErrorCode,
539                          int& channelId, uint32_t& blobId)
540             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
541 
542     /**
543      * getHistogramData
544      *
545      * Get the histogram data by sending ioctl request which will allocate the drm event for
546      * histogram, and wait on the condition variable until the drm event is handled or timeout. Copy
547      * the histogram data from blobIdData->data to histogramBuffer.
548      *
549      * @token is the handle registered by the registerHistogram.
550      * @histogramBuffer AIDL created buffer which will be sent back to the client.
551      * @histogramErrorCode::NONE when success, or else otherwise.
552      */
553     void getHistogramData(const ndk::SpAIBinder& token, std::vector<char16_t>* histogramBuffer,
554                           HistogramErrorCode* histogramErrorCode)
555             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
556 
557     /**
558      * requestBlobIdData
559      *
560      * Request the drm event of the blobId via sending the ioctl which increases the ref_cnt of the
561      * blobId event request. Set the query status of blobIdData to COLLECTING.
562      *
563      * @moduleDisplayInterface display drm interface pointer
564      * @histogramErrorCode::NONE when success, or else otherwise.
565      * @channelId is the channel id of the request
566      * @blobId is the blob id of the request
567      * @blobIdData is the histogram data query related struct of the blobId
568      */
569     void requestBlobIdData(ExynosDisplayDrmInterface* const moduleDisplayInterface,
570                            HistogramErrorCode* histogramErrorCode, const int channelId,
571                            const uint32_t blobId, const std::shared_ptr<BlobIdData>& blobIdData)
572             REQUIRES(blobIdData->mDataCollectingMutex)
573                     EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
574 
575     /**
576      * receiveBlobIdData
577      *
578      * Wait for the drm event of the blobId, and copy the data into histogramBuffer if no error.
579      * Note: It may take for a while, this function should be called without any mutex held except
580      * the mDataCollectingMutex.
581      *
582      * @moduleDisplayInterface display drm interface pointer
583      * @histogramBuffer AIDL created buffer which will be sent back to the client.
584      * @histogramErrorCode::NONE when success, or else otherwise.
585      * @channelId is the channel id of the request
586      * @blobId is the blob id of the request
587      * @blobIdData is the histogram data query related struct of the blobId
588      * @lock is the unique lock of the data query request.
589      */
590     std::cv_status receiveBlobIdData(ExynosDisplayDrmInterface* const moduleDisplayInterface,
591                                      std::vector<char16_t>* histogramBuffer,
592                                      HistogramErrorCode* histogramErrorCode, const int channelId,
593                                      const uint32_t blobId,
594                                      const std::shared_ptr<BlobIdData>& blobIdData,
595                                      std::unique_lock<std::mutex>& lock)
596             REQUIRES(blobIdData->mDataCollectingMutex)
597                     EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
598 
599     /**
600      * checkQueryResult
601      *
602      * Check the query result of the receiveBlobIdData. If there is any error, store to the
603      * histogramErrorCode and clear the histogramBuffer.
604      * Note: It may take for a while, no mutex should be held from the caller.
605      *
606      * @histogramBuffer AIDL created buffer which will be sent back to the client.
607      * @histogramErrorCode::NONE when success, or else otherwise.
608      * @channelId is the channel id of the request
609      * @blobId is the blob id of the request
610      * @cv_status represents if the timeout occurs in receiveBlobIdData
611      */
612     void checkQueryResult(std::vector<char16_t>* histogramBuffer,
613                           HistogramErrorCode* histogramErrorCode, const int channelId,
614                           const uint32_t blobId, const std::cv_status cv_status) const
615             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
616 
617     /**
618      * _handleDrmEvent
619      *
620      * Internal function to handle the drm event, notify all the threads that wait on the specific
621      * drm event with blob id.
622      *
623      * @event histogram event get from kernel
624      * @blobId blob id of the histogram event
625      * @buffer buffer that contains histogram data
626      */
627     void _handleDrmEvent(void* event, uint32_t blobId, char16_t* buffer)
628             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
629 
630     /**
631      * parseDrmEvent
632      *
633      * Parse the histogram drm event. This function should get the histogram channel id
634      * and the histogram buffer address from the event struct.
635      *
636      * @event histogram drm event struct.
637      * @channelId stores the extracted channel id from the event.
638      * @buffer stores the extracted buffer address from the event.
639      * @return NO_ERROR on success, else otherwise.
640      */
641     int parseDrmEvent(const void* const event, uint32_t& channelId, char16_t*& buffer) const
642             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
643 
644     /**
645      * parseContextDrmEvent
646      *
647      * Parse the context histogram drm event. This function should get the histogram blob id
648      * and the histogram buffer address from the event struct.
649      *
650      * @event histogram drm event struct.
651      * @blobId stores the extracted blob id from the event.
652      * @buffer stores the extracted buffer address from the event.
653      * @return NO_ERROR on success, else otherwise.
654      */
655     int parseContextDrmEvent(const void* const event, uint32_t& blobId, char16_t*& buffer) const
656             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
657 
658     /**
659      * cleanupChannelInfo
660      *
661      * Cleanup the channel info and set status to DISABLE_PENDING which means need to wait
662      * for the atomic commit to release the kernel and hardware channel resources.
663      *
664      * @channelId the channel id to be cleanup.
665      * @return next iterator of mUsedChannels after deletion.
666      */
667     std::set<const uint8_t>::iterator cleanupChannelInfo(const uint8_t channelId)
668             REQUIRES(mHistogramMutex) EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex);
669 
670     /**
671      * setChannelConfigBlob
672      *
673      * Check and detect if the histogram channel config blob needs change due to RRS. Send the
674      * config blob commit by setHistogramChannelConfigBlob.
675      *
676      * Case RRS detected:
677      *        CONFIG_COMMITTED / CONFIG_PENDING -> CONFIG_BLOB_ADDED
678      * Case RRS not detected:
679      *        CONFIG_COMMITTED -> CONFIG_COMMITTED
680      *        CONFIG_PENDING -> CONFIG_BLOB_ADDED
681      *
682      * @drmReq drm atomic request object
683      * @channelId histogram channel id
684      * @moduleDisplayInterface display drm interface pointer
685      * @displayActiveH current display active horizontal size (in pixel)
686      * @displayActiveV current display active vertical size (in pixel)
687      * @configInfo is the reference to the shared_ptr of ConfigInfo that will be updated depends on
688      * histogramConfig.
689      */
690     void setChannelConfigBlob(ExynosDisplayDrmInterface::DrmModeAtomicReq& drmReq,
691                               const uint8_t channelId,
692                               ExynosDisplayDrmInterface* const moduleDisplayInterface,
693                               const int displayActiveH, const int displayActiveV,
694                               const std::shared_ptr<ConfigInfo>& configInfo)
695             REQUIRES(mHistogramMutex) EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex);
696 
697     /**
698      * clearChannelConfigBlob
699      *
700      * Call clearHistogramChannelConfigBlob to disable the histogram channel.
701      *     Case #1: success, channel status: DISABLE_PENDING -> DISABLE_BLOB_ADDED.
702      *     Case #2: failed, channel status: DISABLE_PENDING -> DISABLE_ERROR.
703      *
704      * @drmReq drm atomic request object
705      * @channelId histogram channel id
706      * @moduleDisplayInterface display drm interface pointer
707      */
708     void clearChannelConfigBlob(ExynosDisplayDrmInterface::DrmModeAtomicReq& drmReq,
709                                 const uint8_t channelId,
710                                 ExynosDisplayDrmInterface* const moduleDisplayInterface)
711             REQUIRES(mHistogramMutex) EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex);
712 
713     /**
714      * getMatchBlobId
715      *
716      * Traverse the blobsList to find any BlobInfo matched the active size
717      * (displayActiveHxdisplayActiveV). Once found, move the BlobInfo to the front of the list which
718      * means the active blob.
719      *
720      * @blobsList contains the BlobInfo list to be searched from.
721      * @displayActiveH current display active horizontal size (in pixel)
722      * @displayActiveV current display active vertical size (in pixel)
723      * @return the blob id if found, 0 otherwise.
724      */
725     uint32_t getMatchBlobId(std::list<const BlobInfo>& blobsList, const int displayActiveH,
726                             const int displayActiveV, bool& isPositionChanged) const
727             REQUIRES(mHistogramMutex) EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex);
728 
729     /**
730      * getActiveBlobId
731      *
732      * Get the current active blob id from the blobsList. The active blob is the first blob in the
733      * list.
734      *
735      * @return the first blod id from the blobsList if any, else return 0.
736      */
737     uint32_t getActiveBlobId(const std::list<const BlobInfo>& blobsList) const
738             REQUIRES(mHistogramMutex) EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex);
739 
740     /**
741      * createDrmConfig
742      *
743      * Allocate and initialize the histogram config for the drm driver. PropertyBlob class will use
744      * this config to createPropertyBlob.
745      *
746      * @histogramConfig HistogramConfig that is requested from the client
747      * @displayActiveH current display active horizontal size (in pixel)
748      * @displayActiveV current display active vertical size (in pixel)
749      * @drmConfig shared pointer to the allocated histogram config struct.
750      * @drmConfigLength size of the histogram config.
751      * @return NO_ERROR on success, else otherwise
752      */
753     int createDrmConfig(const HistogramConfig& histogramConfig, const int displayActiveH,
754                         const int displayActiveV, std::shared_ptr<void>& drmConfig,
755                         size_t& drmConfigLength) const
756             EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex);
757 
758     /**
759      * createDrmConfigBlob
760      *
761      * Create the drmConfigBlob for the requeste histogramConfig.
762      *
763      * @histogramConfig HistogramConfig that is requested from the client
764      * @displayActiveH current display active horizontal size (in pixel)
765      * @displayActiveV current display active vertical size (in pixel)
766      * @drmConfigBlob shared pointer to the created drmConfigBlob.
767      */
768     int createDrmConfigBlob(const HistogramConfig& histogramConfig, const int displayActiveH,
769                             const int displayActiveV,
770                             std::shared_ptr<PropertyBlob>& drmConfigBlob) const
771             EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex);
772 
773     void resetConfigInfoStatus(std::shared_ptr<ConfigInfo>& configInfo) REQUIRES(mHistogramMutex)
774             EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex);
775 
776     std::pair<int, int> snapDisplayActiveSize() const
777             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
778 
779     /**
780      * convertRoi
781      *
782      * Linear transform the requested roi (based on panel full resolution) into the working roi
783      * (active resolution).
784      *
785      * @moduleDisplayInterface the displayInterface which contains the full resolution info
786      * @requestedRoi requested roi
787      * @workingRoi converted roi from the requested roi
788      * @return NO_ERROR on success, else otherwise
789      */
790     int convertRoi(const HistogramRoiRect& requestedRoi, HistogramRoiRect& workingRoi,
791                    const int displayActiveH, const int displayActiveV, const char* roiType) const
792             EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex);
793 
794     void dumpHistogramCapability(String8& result) const
795             EXCLUDES(mInitDrmDoneMutex, mHistogramMutex, mBlobIdDataMutex);
796 
dumpInternalConfigs(String8 & result)797     virtual void dumpInternalConfigs(String8& result) const REQUIRES(mHistogramMutex)
798             EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex) {}
799 
800     void dumpChannel(TableBuilder& tb, const uint8_t channelId) const REQUIRES(mHistogramMutex)
801             EXCLUDES(mInitDrmDoneMutex, mBlobIdDataMutex);
802 
803     ndk::ScopedAStatus validateHistogramRequest(const ndk::SpAIBinder& token,
804                                                 const HistogramConfig& histogramConfig,
805                                                 HistogramErrorCode* histogramErrorCode) const;
806     HistogramErrorCode validateHistogramConfig(const HistogramConfig& histogramConfig) const;
807     HistogramErrorCode validateHistogramRoi(const HistogramRoiRect& roi, const char* roiType) const;
808     HistogramErrorCode validateHistogramWeights(const HistogramWeights& weights) const;
809     HistogramErrorCode validateHistogramSamplePos(const HistogramSamplePos& samplePos) const;
810     HistogramErrorCode validateHistogramBlockingRoi(
811             const std::optional<HistogramRoiRect>& blockingRoi) const;
812 
813     int calculateThreshold(const HistogramRoiRect& roi, const int displayActiveH,
814                            const int displayActiveV) const;
815 
816     static std::string toString(const ChannelStatus_t& status);
817     static std::string toString(const HistogramRoiRect& roi);
818     static std::string toString(const HistogramWeights& weights);
819     static std::string toString(const HistogramConfig& config);
820 };
821 
822 // PropertyBlob is the RAII class to manage the histogram PropertyBlob creation and deletion.
823 class HistogramDevice::PropertyBlob {
824 public:
825     /**
826      * PropertyBlob
827      *
828      * Construct the PropertyBlob to mange the histogram PropertyBlob.
829      *
830      * @drmDevice the object to call the CreatePropertyBlob.
831      * @blobData pointer to the buffer that contains requested property blob data to be created.
832      * @blobLength size of the buffer pointed by blobData.
833      */
834     PropertyBlob(DrmDevice* const drmDevice, const void* const blobData, const size_t blobLength);
835 
836     /**
837      * ~PropertyBlob
838      *
839      * Destruct the PropertyBlob and release the allocated blob in constructor.
840      */
841     ~PropertyBlob();
842 
843     /**
844      * getId
845      *
846      * @return blobId of this PropertyBlob
847      */
848     uint32_t getId() const;
849 
850     /**
851      * getError
852      *
853      * @return any error in the constructor if any, otherwise return 0.
854      */
855     int getError() const;
856 
857 private:
858     DrmDevice* const mDrmDevice;
859     uint32_t mBlobId = 0;
860     int mError = NO_ERROR;
861 };
862