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