|  | /* | 
|  | * Copyright 2018 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> | 
|  | #include <android/native_window.h> | 
|  | #include <android/surface_control.h> | 
|  | #include <android/surface_control_jni.h> | 
|  | #include <android_runtime/android_view_SurfaceControl.h> | 
|  | #include <configstore/Utils.h> | 
|  | #include <gui/HdrMetadata.h> | 
|  | #include <gui/ISurfaceComposer.h> | 
|  | #include <gui/Surface.h> | 
|  | #include <gui/SurfaceComposerClient.h> | 
|  | #include <gui/SurfaceControl.h> | 
|  | #include <private/android/choreographer.h> | 
|  | #include <surface_control_private.h> | 
|  | #include <ui/DynamicDisplayInfo.h> | 
|  | #include <utils/Timers.h> | 
|  |  | 
|  | #include <utility> | 
|  |  | 
|  | using namespace android::hardware::configstore; | 
|  | using namespace android::hardware::configstore::V1_0; | 
|  | using namespace android; | 
|  |  | 
|  | using Transaction = SurfaceComposerClient::Transaction; | 
|  |  | 
|  | #define CHECK_NOT_NULL(name) \ | 
|  | LOG_ALWAYS_FATAL_IF(name == nullptr, "nullptr passed as " #name " argument"); | 
|  |  | 
|  | #define CHECK_VALID_RECT(name)                                     \ | 
|  | LOG_ALWAYS_FATAL_IF(!static_cast<const Rect&>(name).isValid(), \ | 
|  | "invalid arg passed as " #name " argument"); | 
|  |  | 
|  | static_assert(static_cast<int>(ADATASPACE_UNKNOWN) == static_cast<int>(HAL_DATASPACE_UNKNOWN)); | 
|  | static_assert(static_cast<int>(ADATASPACE_SCRGB_LINEAR) == | 
|  | static_cast<int>(HAL_DATASPACE_V0_SCRGB_LINEAR)); | 
|  | static_assert(static_cast<int>(ADATASPACE_SRGB) == static_cast<int>(HAL_DATASPACE_V0_SRGB)); | 
|  | static_assert(static_cast<int>(ADATASPACE_SCRGB) == static_cast<int>(HAL_DATASPACE_V0_SCRGB)); | 
|  | static_assert(static_cast<int>(ADATASPACE_DISPLAY_P3) == | 
|  | static_cast<int>(HAL_DATASPACE_DISPLAY_P3)); | 
|  | static_assert(static_cast<int>(ADATASPACE_BT2020_PQ) == static_cast<int>(HAL_DATASPACE_BT2020_PQ)); | 
|  |  | 
|  | Transaction* ASurfaceTransaction_to_Transaction(ASurfaceTransaction* aSurfaceTransaction) { | 
|  | return reinterpret_cast<Transaction*>(aSurfaceTransaction); | 
|  | } | 
|  |  | 
|  | SurfaceControl* ASurfaceControl_to_SurfaceControl(ASurfaceControl* aSurfaceControl) { | 
|  | return reinterpret_cast<SurfaceControl*>(aSurfaceControl); | 
|  | } | 
|  |  | 
|  | void SurfaceControl_acquire(SurfaceControl* surfaceControl) { | 
|  | // incStrong/decStrong token must be the same, doesn't matter what it is | 
|  | surfaceControl->incStrong((void*)SurfaceControl_acquire); | 
|  | } | 
|  |  | 
|  | void SurfaceControl_release(SurfaceControl* surfaceControl) { | 
|  | // incStrong/decStrong token must be the same, doesn't matter what it is | 
|  | surfaceControl->decStrong((void*)SurfaceControl_acquire); | 
|  | } | 
|  |  | 
|  | ASurfaceControl* ASurfaceControl_createFromWindow(ANativeWindow* window, const char* debug_name) { | 
|  | CHECK_NOT_NULL(window); | 
|  | CHECK_NOT_NULL(debug_name); | 
|  |  | 
|  | sp<SurfaceComposerClient> client = new SurfaceComposerClient(); | 
|  | if (client->initCheck() != NO_ERROR) { | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | Surface* surface = static_cast<Surface*>(window); | 
|  | sp<IBinder> parentHandle = surface->getSurfaceControlHandle(); | 
|  |  | 
|  | int32_t flags = ISurfaceComposerClient::eFXSurfaceBufferState; | 
|  | sp<SurfaceControl> surfaceControl; | 
|  | if (parentHandle) { | 
|  | surfaceControl = | 
|  | client->createSurface(String8(debug_name), 0 /* width */, 0 /* height */, | 
|  | // Format is only relevant for buffer queue layers. | 
|  | PIXEL_FORMAT_UNKNOWN /* format */, flags, parentHandle); | 
|  | } else { | 
|  | // deprecated, this should no longer be used | 
|  | surfaceControl = nullptr; | 
|  | } | 
|  |  | 
|  | if (!surfaceControl) { | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | SurfaceControl_acquire(surfaceControl.get()); | 
|  | return reinterpret_cast<ASurfaceControl*>(surfaceControl.get()); | 
|  | } | 
|  |  | 
|  | ASurfaceControl* ASurfaceControl_create(ASurfaceControl* parent, const char* debug_name) { | 
|  | CHECK_NOT_NULL(parent); | 
|  | CHECK_NOT_NULL(debug_name); | 
|  |  | 
|  | SurfaceComposerClient* client = ASurfaceControl_to_SurfaceControl(parent)->getClient().get(); | 
|  |  | 
|  | SurfaceControl* surfaceControlParent = ASurfaceControl_to_SurfaceControl(parent); | 
|  |  | 
|  | uint32_t flags = ISurfaceComposerClient::eFXSurfaceBufferState; | 
|  | sp<SurfaceControl> surfaceControl = | 
|  | client->createSurface(String8(debug_name), 0 /* width */, 0 /* height */, | 
|  | // Format is only relevant for buffer queue layers. | 
|  | PIXEL_FORMAT_UNKNOWN /* format */, flags, | 
|  | surfaceControlParent->getHandle()); | 
|  | if (!surfaceControl) { | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | SurfaceControl_acquire(surfaceControl.get()); | 
|  | return reinterpret_cast<ASurfaceControl*>(surfaceControl.get()); | 
|  | } | 
|  |  | 
|  | void ASurfaceControl_acquire(ASurfaceControl* aSurfaceControl) { | 
|  | SurfaceControl* surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  |  | 
|  | SurfaceControl_acquire(surfaceControl); | 
|  | } | 
|  |  | 
|  | void ASurfaceControl_release(ASurfaceControl* aSurfaceControl) { | 
|  | SurfaceControl* surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  |  | 
|  | SurfaceControl_release(surfaceControl); | 
|  | } | 
|  |  | 
|  | ASurfaceControl* ASurfaceControl_fromJava(JNIEnv* env, jobject surfaceControlObj) { | 
|  | LOG_ALWAYS_FATAL_IF(!env, "nullptr passed to ASurfaceControl_fromJava as env argument"); | 
|  | LOG_ALWAYS_FATAL_IF(!surfaceControlObj, | 
|  | "nullptr passed to ASurfaceControl_fromJava as surfaceControlObj argument"); | 
|  | SurfaceControl* surfaceControl = | 
|  | android_view_SurfaceControl_getNativeSurfaceControl(env, surfaceControlObj); | 
|  | LOG_ALWAYS_FATAL_IF(!surfaceControl, | 
|  | "surfaceControlObj passed to ASurfaceControl_fromJava is not valid"); | 
|  | SurfaceControl_acquire(surfaceControl); | 
|  | return reinterpret_cast<ASurfaceControl*>(surfaceControl); | 
|  | } | 
|  |  | 
|  | struct ASurfaceControlStats { | 
|  | std::variant<int64_t, sp<Fence>> acquireTimeOrFence; | 
|  | sp<Fence> previousReleaseFence; | 
|  | uint64_t frameNumber; | 
|  | }; | 
|  |  | 
|  | void ASurfaceControl_registerSurfaceStatsListener(ASurfaceControl* control, int32_t id, | 
|  | void* context, | 
|  | ASurfaceControl_SurfaceStatsListener func) { | 
|  | SurfaceStatsCallback callback = [func, id](void* callback_context, nsecs_t, const sp<Fence>&, | 
|  | const SurfaceStats& surfaceStats) { | 
|  | ASurfaceControlStats aSurfaceControlStats; | 
|  |  | 
|  | aSurfaceControlStats.acquireTimeOrFence = surfaceStats.acquireTimeOrFence; | 
|  | aSurfaceControlStats.previousReleaseFence = surfaceStats.previousReleaseFence; | 
|  | aSurfaceControlStats.frameNumber = surfaceStats.eventStats.frameNumber; | 
|  |  | 
|  | (*func)(callback_context, id, &aSurfaceControlStats); | 
|  | }; | 
|  |  | 
|  | TransactionCompletedListener::getInstance()->addSurfaceStatsListener(context, | 
|  | reinterpret_cast<void*>(func), ASurfaceControl_to_SurfaceControl(control), callback); | 
|  | } | 
|  |  | 
|  | void ASurfaceControl_unregisterSurfaceStatsListener(void* context, | 
|  | ASurfaceControl_SurfaceStatsListener func) { | 
|  | TransactionCompletedListener::getInstance()->removeSurfaceStatsListener(context, | 
|  | reinterpret_cast<void*>(func)); | 
|  | } | 
|  |  | 
|  | AChoreographer* ASurfaceControl_getChoreographer(ASurfaceControl* aSurfaceControl) { | 
|  | LOG_ALWAYS_FATAL_IF(aSurfaceControl == nullptr, "aSurfaceControl should not be nullptr"); | 
|  | SurfaceControl* surfaceControl = | 
|  | ASurfaceControl_to_SurfaceControl(reinterpret_cast<ASurfaceControl*>(aSurfaceControl)); | 
|  | if (!surfaceControl->isValid()) { | 
|  | ALOGE("Attempted to get choreographer from invalid surface control"); | 
|  | return nullptr; | 
|  | } | 
|  | SurfaceControl_acquire(surfaceControl); | 
|  | return reinterpret_cast<AChoreographer*>(surfaceControl->getChoreographer().get()); | 
|  | } | 
|  |  | 
|  | int64_t ASurfaceControlStats_getAcquireTime(ASurfaceControlStats* stats) { | 
|  | if (const auto* fence = std::get_if<sp<Fence>>(&stats->acquireTimeOrFence)) { | 
|  | // We got a fence instead of the acquire time due to latch unsignaled. | 
|  | // Ideally the client could just get the acquire time dericly from | 
|  | // the fence instead of calling this function which needs to block. | 
|  | (*fence)->waitForever("ASurfaceControlStats_getAcquireTime"); | 
|  | return (*fence)->getSignalTime(); | 
|  | } | 
|  |  | 
|  | return std::get<int64_t>(stats->acquireTimeOrFence); | 
|  | } | 
|  |  | 
|  | uint64_t ASurfaceControlStats_getFrameNumber(ASurfaceControlStats* stats) { | 
|  | return stats->frameNumber; | 
|  | } | 
|  |  | 
|  | ASurfaceTransaction* ASurfaceTransaction_create() { | 
|  | Transaction* transaction = new Transaction; | 
|  | return reinterpret_cast<ASurfaceTransaction*>(transaction); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_delete(ASurfaceTransaction* aSurfaceTransaction) { | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  | delete transaction; | 
|  | } | 
|  |  | 
|  | ASurfaceTransaction* ASurfaceTransaction_fromJava(JNIEnv* env, jobject transactionObj) { | 
|  | LOG_ALWAYS_FATAL_IF(!env, "nullptr passed to ASurfaceTransaction_fromJava as env argument"); | 
|  | LOG_ALWAYS_FATAL_IF(!transactionObj, | 
|  | "nullptr passed to ASurfaceTransaction_fromJava as transactionObj " | 
|  | "argument"); | 
|  | Transaction* transaction = | 
|  | android_view_SurfaceTransaction_getNativeSurfaceTransaction(env, transactionObj); | 
|  | LOG_ALWAYS_FATAL_IF(!transaction, | 
|  | "surfaceControlObj passed to ASurfaceTransaction_fromJava is not valid"); | 
|  | return reinterpret_cast<ASurfaceTransaction*>(transaction); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_apply(ASurfaceTransaction* aSurfaceTransaction) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  |  | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | transaction->apply(); | 
|  | } | 
|  |  | 
|  | struct ASurfaceTransactionStats { | 
|  | std::unordered_map<ASurfaceControl*, ASurfaceControlStats> aSurfaceControlStats; | 
|  | int64_t latchTime; | 
|  | sp<Fence> presentFence; | 
|  | bool transactionCompleted; | 
|  | }; | 
|  |  | 
|  | int64_t ASurfaceTransactionStats_getLatchTime(ASurfaceTransactionStats* aSurfaceTransactionStats) { | 
|  | CHECK_NOT_NULL(aSurfaceTransactionStats); | 
|  | return aSurfaceTransactionStats->latchTime; | 
|  | } | 
|  |  | 
|  | int ASurfaceTransactionStats_getPresentFenceFd(ASurfaceTransactionStats* aSurfaceTransactionStats) { | 
|  | CHECK_NOT_NULL(aSurfaceTransactionStats); | 
|  | LOG_ALWAYS_FATAL_IF(!aSurfaceTransactionStats->transactionCompleted, | 
|  | "ASurfaceTransactionStats queried from an incomplete transaction callback"); | 
|  |  | 
|  | auto& presentFence = aSurfaceTransactionStats->presentFence; | 
|  | return (presentFence) ? presentFence->dup() : -1; | 
|  | } | 
|  |  | 
|  | void ASurfaceTransactionStats_getASurfaceControls(ASurfaceTransactionStats* aSurfaceTransactionStats, | 
|  | ASurfaceControl*** outASurfaceControls, | 
|  | size_t* outASurfaceControlsSize) { | 
|  | CHECK_NOT_NULL(aSurfaceTransactionStats); | 
|  | CHECK_NOT_NULL(outASurfaceControls); | 
|  | CHECK_NOT_NULL(outASurfaceControlsSize); | 
|  |  | 
|  | size_t size = aSurfaceTransactionStats->aSurfaceControlStats.size(); | 
|  |  | 
|  | SurfaceControl** surfaceControls = new SurfaceControl*[size]; | 
|  | ASurfaceControl** aSurfaceControls = reinterpret_cast<ASurfaceControl**>(surfaceControls); | 
|  |  | 
|  | size_t i = 0; | 
|  | for (auto& [aSurfaceControl, aSurfaceControlStats] : aSurfaceTransactionStats->aSurfaceControlStats) { | 
|  | aSurfaceControls[i] = aSurfaceControl; | 
|  | i++; | 
|  | } | 
|  |  | 
|  | *outASurfaceControls = aSurfaceControls; | 
|  | *outASurfaceControlsSize = size; | 
|  | } | 
|  |  | 
|  | int64_t ASurfaceTransactionStats_getAcquireTime(ASurfaceTransactionStats* aSurfaceTransactionStats, | 
|  | ASurfaceControl* aSurfaceControl) { | 
|  | CHECK_NOT_NULL(aSurfaceTransactionStats); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  |  | 
|  | const auto& aSurfaceControlStats = | 
|  | aSurfaceTransactionStats->aSurfaceControlStats.find(aSurfaceControl); | 
|  | LOG_ALWAYS_FATAL_IF( | 
|  | aSurfaceControlStats == aSurfaceTransactionStats->aSurfaceControlStats.end(), | 
|  | "ASurfaceControl not found"); | 
|  |  | 
|  | return ASurfaceControlStats_getAcquireTime(&aSurfaceControlStats->second); | 
|  | } | 
|  |  | 
|  | int ASurfaceTransactionStats_getPreviousReleaseFenceFd( | 
|  | ASurfaceTransactionStats* aSurfaceTransactionStats, ASurfaceControl* aSurfaceControl) { | 
|  | CHECK_NOT_NULL(aSurfaceTransactionStats); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  | LOG_ALWAYS_FATAL_IF(!aSurfaceTransactionStats->transactionCompleted, | 
|  | "ASurfaceTransactionStats queried from an incomplete transaction callback"); | 
|  |  | 
|  | const auto& aSurfaceControlStats = | 
|  | aSurfaceTransactionStats->aSurfaceControlStats.find(aSurfaceControl); | 
|  | LOG_ALWAYS_FATAL_IF( | 
|  | aSurfaceControlStats == aSurfaceTransactionStats->aSurfaceControlStats.end(), | 
|  | "ASurfaceControl not found"); | 
|  |  | 
|  | auto& previousReleaseFence = aSurfaceControlStats->second.previousReleaseFence; | 
|  | return (previousReleaseFence) ? previousReleaseFence->dup() : -1; | 
|  | } | 
|  |  | 
|  | void ASurfaceTransactionStats_releaseASurfaceControls(ASurfaceControl** aSurfaceControls) { | 
|  | CHECK_NOT_NULL(aSurfaceControls); | 
|  |  | 
|  | SurfaceControl** surfaceControls = reinterpret_cast<SurfaceControl**>(aSurfaceControls); | 
|  | delete[] surfaceControls; | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* aSurfaceTransaction, void* context, | 
|  | ASurfaceTransaction_OnComplete func) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(func); | 
|  |  | 
|  | TransactionCompletedCallbackTakesContext callback = [func](void* callback_context, | 
|  | nsecs_t latchTime, | 
|  | const sp<Fence>& presentFence, | 
|  | const std::vector<SurfaceControlStats>& surfaceControlStats) { | 
|  | ASurfaceTransactionStats aSurfaceTransactionStats; | 
|  |  | 
|  | aSurfaceTransactionStats.latchTime = latchTime; | 
|  | aSurfaceTransactionStats.presentFence = presentFence; | 
|  | aSurfaceTransactionStats.transactionCompleted = true; | 
|  |  | 
|  | auto& aSurfaceControlStats = aSurfaceTransactionStats.aSurfaceControlStats; | 
|  |  | 
|  | for (const auto& [surfaceControl, latchTime, acquireTimeOrFence, presentFence, | 
|  | previousReleaseFence, transformHint, frameEvents, ignore] : surfaceControlStats) { | 
|  | ASurfaceControl* aSurfaceControl = reinterpret_cast<ASurfaceControl*>(surfaceControl.get()); | 
|  | aSurfaceControlStats[aSurfaceControl].acquireTimeOrFence = acquireTimeOrFence; | 
|  | aSurfaceControlStats[aSurfaceControl].previousReleaseFence = previousReleaseFence; | 
|  | } | 
|  |  | 
|  | (*func)(callback_context, &aSurfaceTransactionStats); | 
|  | }; | 
|  |  | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | transaction->addTransactionCompletedCallback(callback, context); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_reparent(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, | 
|  | ASurfaceControl* newParentASurfaceControl) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | sp<SurfaceControl> newParentSurfaceControl = ASurfaceControl_to_SurfaceControl( | 
|  | newParentASurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | transaction->reparent(surfaceControl, newParentSurfaceControl); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setVisibility(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, | 
|  | int8_t visibility) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | switch (visibility) { | 
|  | case ASURFACE_TRANSACTION_VISIBILITY_SHOW: | 
|  | transaction->show(surfaceControl); | 
|  | break; | 
|  | case ASURFACE_TRANSACTION_VISIBILITY_HIDE: | 
|  | transaction->hide(surfaceControl); | 
|  | break; | 
|  | default: | 
|  | LOG_ALWAYS_FATAL("invalid visibility %d", visibility); | 
|  | } | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setZOrder(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, | 
|  | int32_t z_order) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | transaction->setLayer(surfaceControl, z_order); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setBuffer(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, | 
|  | AHardwareBuffer* buffer, int acquire_fence_fd) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | sp<GraphicBuffer> graphic_buffer(GraphicBuffer::fromAHardwareBuffer(buffer)); | 
|  |  | 
|  | std::optional<sp<Fence>> fence = std::nullopt; | 
|  | if (acquire_fence_fd != -1) { | 
|  | fence = new Fence(acquire_fence_fd); | 
|  | } | 
|  | transaction->setBuffer(surfaceControl, graphic_buffer, fence); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setGeometry(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, const ARect& source, | 
|  | const ARect& destination, int32_t transform) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  | CHECK_VALID_RECT(source); | 
|  | CHECK_VALID_RECT(destination); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | Rect sourceRect = static_cast<const Rect&>(source); | 
|  | Rect destRect = static_cast<const Rect&>(destination); | 
|  | // Adjust the source so its top and left are not negative | 
|  | sourceRect.left = std::max(sourceRect.left, 0); | 
|  | sourceRect.top = std::max(sourceRect.top, 0); | 
|  |  | 
|  | if (!sourceRect.isValid()) { | 
|  | sourceRect.makeInvalid(); | 
|  | } | 
|  | transaction->setBufferCrop(surfaceControl, sourceRect); | 
|  | transaction->setDestinationFrame(surfaceControl, destRect); | 
|  | transaction->setTransform(surfaceControl, transform); | 
|  | bool transformToInverseDisplay = (NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY & transform) == | 
|  | NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; | 
|  | transaction->setTransformToDisplayInverse(surfaceControl, transformToInverseDisplay); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setCrop(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, const ARect& crop) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  | CHECK_VALID_RECT(crop); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | transaction->setCrop(surfaceControl, static_cast<const Rect&>(crop)); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setPosition(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, int32_t x, int32_t y) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | transaction->setPosition(surfaceControl, x, y); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setBufferTransform(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, int32_t transform) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | transaction->setTransform(surfaceControl, transform); | 
|  | bool transformToInverseDisplay = (NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY & transform) == | 
|  | NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; | 
|  | transaction->setTransformToDisplayInverse(surfaceControl, transformToInverseDisplay); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setScale(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, float xScale, float yScale) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  | LOG_ALWAYS_FATAL_IF(xScale < 0, "negative value passed in for xScale"); | 
|  | LOG_ALWAYS_FATAL_IF(yScale < 0, "negative value passed in for yScale"); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | transaction->setMatrix(surfaceControl, xScale, 0, 0, yScale); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, | 
|  | int8_t transparency) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | uint32_t flags = (transparency == ASURFACE_TRANSACTION_TRANSPARENCY_OPAQUE) ? | 
|  | layer_state_t::eLayerOpaque : 0; | 
|  | transaction->setFlags(surfaceControl, flags, layer_state_t::eLayerOpaque); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, | 
|  | const ARect rects[], uint32_t count) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | Region region; | 
|  | for (uint32_t i = 0; i < count; ++i) { | 
|  | region.orSelf(static_cast<const Rect&>(rects[i])); | 
|  | } | 
|  |  | 
|  | // Hardware composer interprets a DamageRegion with a single Rect of {0,0,0,0} to be an | 
|  | // undamaged region and {0,0,-1,-1} to be a fully damaged buffer. This is a confusing | 
|  | // distinction for a public api. Instead, default both cases to be a fully damaged buffer. | 
|  | if (count == 1 && region.getBounds().isEmpty()) { | 
|  | transaction->setSurfaceDamageRegion(surfaceControl, Region::INVALID_REGION); | 
|  | return; | 
|  | } | 
|  |  | 
|  | transaction->setSurfaceDamageRegion(surfaceControl, region); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setDesiredPresentTime(ASurfaceTransaction* aSurfaceTransaction, | 
|  | int64_t desiredPresentTime) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  |  | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | transaction->setDesiredPresentTime(static_cast<nsecs_t>(desiredPresentTime)); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setBufferAlpha(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, | 
|  | float alpha) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  |  | 
|  | LOG_ALWAYS_FATAL_IF(alpha < 0.0 || alpha > 1.0, "invalid alpha"); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | transaction->setAlpha(surfaceControl, alpha); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setBufferDataSpace(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, | 
|  | ADataSpace aDataSpace) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  | transaction->setDataspace(surfaceControl, static_cast<ui::Dataspace>(aDataSpace)); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setHdrMetadata_smpte2086(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, | 
|  | struct AHdrMetadata_smpte2086* metadata) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | HdrMetadata hdrMetadata; | 
|  |  | 
|  | if (metadata) { | 
|  | hdrMetadata.smpte2086.displayPrimaryRed.x = metadata->displayPrimaryRed.x; | 
|  | hdrMetadata.smpte2086.displayPrimaryRed.y = metadata->displayPrimaryRed.y; | 
|  | hdrMetadata.smpte2086.displayPrimaryGreen.x = metadata->displayPrimaryGreen.x; | 
|  | hdrMetadata.smpte2086.displayPrimaryGreen.y = metadata->displayPrimaryGreen.y; | 
|  | hdrMetadata.smpte2086.displayPrimaryBlue.x = metadata->displayPrimaryBlue.x; | 
|  | hdrMetadata.smpte2086.displayPrimaryBlue.y = metadata->displayPrimaryBlue.y; | 
|  | hdrMetadata.smpte2086.whitePoint.x = metadata->whitePoint.x; | 
|  | hdrMetadata.smpte2086.whitePoint.y = metadata->whitePoint.y; | 
|  | hdrMetadata.smpte2086.minLuminance = metadata->minLuminance; | 
|  | hdrMetadata.smpte2086.maxLuminance = metadata->maxLuminance; | 
|  |  | 
|  | hdrMetadata.validTypes |= HdrMetadata::SMPTE2086; | 
|  | } else { | 
|  | hdrMetadata.validTypes &= ~HdrMetadata::SMPTE2086; | 
|  | } | 
|  |  | 
|  | transaction->setHdrMetadata(surfaceControl, hdrMetadata); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, | 
|  | struct AHdrMetadata_cta861_3* metadata) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | HdrMetadata hdrMetadata; | 
|  |  | 
|  | if (metadata) { | 
|  | hdrMetadata.cta8613.maxContentLightLevel = metadata->maxContentLightLevel; | 
|  | hdrMetadata.cta8613.maxFrameAverageLightLevel = metadata->maxFrameAverageLightLevel; | 
|  |  | 
|  | hdrMetadata.validTypes |= HdrMetadata::CTA861_3; | 
|  | } else { | 
|  | hdrMetadata.validTypes &= ~HdrMetadata::CTA861_3; | 
|  | } | 
|  |  | 
|  | transaction->setHdrMetadata(surfaceControl, hdrMetadata); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setExtendedRangeBrightness(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, | 
|  | float currentBufferRatio, float desiredRatio) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  |  | 
|  | if (!isfinite(currentBufferRatio) || currentBufferRatio < 1.0f) { | 
|  | LOG_ALWAYS_FATAL("setExtendedRangeBrightness, currentBufferRatio %f isn't finite or >= " | 
|  | "1.0f", | 
|  | currentBufferRatio); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (!isfinite(desiredRatio) || desiredRatio < 1.0f) { | 
|  | LOG_ALWAYS_FATAL("setExtendedRangeBrightness, desiredRatio %f isn't finite or >= 1.0f", | 
|  | desiredRatio); | 
|  | return; | 
|  | } | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | transaction->setExtendedRangeBrightness(surfaceControl, currentBufferRatio, desiredRatio); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setColor(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, | 
|  | float r, float g, float b, float alpha, | 
|  | ADataSpace dataspace) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | half3 color; | 
|  | color.r = r; | 
|  | color.g = g; | 
|  | color.b = b; | 
|  |  | 
|  | transaction->setBackgroundColor(surfaceControl, color, alpha, | 
|  | static_cast<ui::Dataspace>(dataspace)); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setFrameRate(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, float frameRate, | 
|  | int8_t compatibility) { | 
|  | ASurfaceTransaction_setFrameRateWithChangeStrategy( | 
|  | aSurfaceTransaction, aSurfaceControl, frameRate, compatibility, | 
|  | ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setFrameRateWithChangeStrategy(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, | 
|  | float frameRate, int8_t compatibility, | 
|  | int8_t changeFrameRateStrategy) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | transaction->setFrameRate(surfaceControl, frameRate, compatibility, changeFrameRateStrategy); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_clearFrameRate(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | transaction->setFrameRate(surfaceControl, 0, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, | 
|  | ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setEnableBackPressure(ASurfaceTransaction* aSurfaceTransaction, | 
|  | ASurfaceControl* aSurfaceControl, | 
|  | bool enableBackpressure) { | 
|  | CHECK_NOT_NULL(aSurfaceControl); | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  |  | 
|  | sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | const uint32_t flags = enableBackpressure ? | 
|  | layer_state_t::eEnableBackpressure : 0; | 
|  | transaction->setFlags(surfaceControl, flags, layer_state_t::eEnableBackpressure); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setOnCommit(ASurfaceTransaction* aSurfaceTransaction, void* context, | 
|  | ASurfaceTransaction_OnCommit func) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | CHECK_NOT_NULL(func); | 
|  |  | 
|  | TransactionCompletedCallbackTakesContext callback = | 
|  | [func](void* callback_context, nsecs_t latchTime, const sp<Fence>& /* presentFence */, | 
|  | const std::vector<SurfaceControlStats>& surfaceControlStats) { | 
|  | ASurfaceTransactionStats aSurfaceTransactionStats; | 
|  | aSurfaceTransactionStats.latchTime = latchTime; | 
|  | aSurfaceTransactionStats.transactionCompleted = false; | 
|  |  | 
|  | auto& aSurfaceControlStats = aSurfaceTransactionStats.aSurfaceControlStats; | 
|  | for (const auto& [surfaceControl, latchTime, acquireTimeOrFence, presentFence, | 
|  | previousReleaseFence, transformHint, frameEvents, ignore] : | 
|  | surfaceControlStats) { | 
|  | ASurfaceControl* aSurfaceControl = | 
|  | reinterpret_cast<ASurfaceControl*>(surfaceControl.get()); | 
|  | aSurfaceControlStats[aSurfaceControl].acquireTimeOrFence = acquireTimeOrFence; | 
|  | } | 
|  |  | 
|  | (*func)(callback_context, &aSurfaceTransactionStats); | 
|  | }; | 
|  |  | 
|  | Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); | 
|  |  | 
|  | transaction->addTransactionCommittedCallback(callback, context); | 
|  | } | 
|  |  | 
|  | void ASurfaceTransaction_setFrameTimeline(ASurfaceTransaction* aSurfaceTransaction, | 
|  | AVsyncId vsyncId) { | 
|  | CHECK_NOT_NULL(aSurfaceTransaction); | 
|  | const auto startTime = AChoreographer_getStartTimeNanosForVsyncId(vsyncId); | 
|  | FrameTimelineInfo ftInfo; | 
|  | ftInfo.vsyncId = vsyncId; | 
|  | ftInfo.startTimeNanos = startTime; | 
|  | ASurfaceTransaction_to_Transaction(aSurfaceTransaction)->setFrameTimelineInfo(ftInfo); | 
|  | } |