/* * 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 #include #include #include #include #include #include #include #include #include #include #include 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(name).isValid(), \ "invalid arg passed as " #name " argument"); static_assert(static_cast(ADATASPACE_UNKNOWN) == static_cast(HAL_DATASPACE_UNKNOWN)); static_assert(static_cast(ADATASPACE_SCRGB_LINEAR) == static_cast(HAL_DATASPACE_V0_SCRGB_LINEAR)); static_assert(static_cast(ADATASPACE_SRGB) == static_cast(HAL_DATASPACE_V0_SRGB)); static_assert(static_cast(ADATASPACE_SCRGB) == static_cast(HAL_DATASPACE_V0_SCRGB)); static_assert(static_cast(ADATASPACE_DISPLAY_P3) == static_cast(HAL_DATASPACE_DISPLAY_P3)); static_assert(static_cast(ADATASPACE_BT2020_PQ) == static_cast(HAL_DATASPACE_BT2020_PQ)); Transaction* ASurfaceTransaction_to_Transaction(ASurfaceTransaction* aSurfaceTransaction) { return reinterpret_cast(aSurfaceTransaction); } SurfaceControl* ASurfaceControl_to_SurfaceControl(ASurfaceControl* aSurfaceControl) { return reinterpret_cast(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 client = new SurfaceComposerClient(); if (client->initCheck() != NO_ERROR) { return nullptr; } Surface* surface = static_cast(window); sp parentHandle = surface->getSurfaceControlHandle(); uint32_t flags = ISurfaceComposerClient::eFXSurfaceBufferState; sp 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 { surfaceControl = client->createWithSurfaceParent(String8(debug_name), 0 /* width */, 0 /* height */, // Format is only relevant for buffer queue layers. PIXEL_FORMAT_UNKNOWN /* format */, flags, static_cast(window)); } if (!surfaceControl) { return nullptr; } SurfaceControl_acquire(surfaceControl.get()); return reinterpret_cast(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 = 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(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); } struct ASurfaceControlStats { int64_t acquireTime; sp previousReleaseFence; uint64_t frameNumber; }; void ASurfaceControl_registerSurfaceStatsListener(ASurfaceControl* control, void* context, ASurfaceControl_SurfaceStatsListener func) { SurfaceStatsCallback callback = [func](void* callback_context, nsecs_t, const sp&, const SurfaceStats& surfaceStats) { ASurfaceControlStats aSurfaceControlStats; ASurfaceControl* aSurfaceControl = reinterpret_cast(surfaceStats.surfaceControl.get()); aSurfaceControlStats.acquireTime = surfaceStats.acquireTime; aSurfaceControlStats.previousReleaseFence = surfaceStats.previousReleaseFence; aSurfaceControlStats.frameNumber = surfaceStats.eventStats.frameNumber; (*func)(callback_context, aSurfaceControl, &aSurfaceControlStats); }; TransactionCompletedListener::getInstance()->addSurfaceStatsListener(context, reinterpret_cast(func), ASurfaceControl_to_SurfaceControl(control), callback); } void ASurfaceControl_unregisterSurfaceStatsListener(void* context, ASurfaceControl_SurfaceStatsListener func) { TransactionCompletedListener::getInstance()->removeSurfaceStatsListener(context, reinterpret_cast(func)); } int64_t ASurfaceControlStats_getAcquireTime(ASurfaceControlStats* stats) { return stats->acquireTime; } uint64_t ASurfaceControlStats_getFrameNumber(ASurfaceControlStats* stats) { return stats->frameNumber; } ASurfaceTransaction* ASurfaceTransaction_create() { Transaction* transaction = new Transaction; return reinterpret_cast(transaction); } void ASurfaceTransaction_delete(ASurfaceTransaction* aSurfaceTransaction) { Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); delete transaction; } void ASurfaceTransaction_apply(ASurfaceTransaction* aSurfaceTransaction) { CHECK_NOT_NULL(aSurfaceTransaction); Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); transaction->apply(); } struct ASurfaceTransactionStats { std::unordered_map aSurfaceControlStats; int64_t latchTime; sp 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(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->second.acquireTime; } 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(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& presentFence, const std::vector& surfaceControlStats) { ASurfaceTransactionStats aSurfaceTransactionStats; aSurfaceTransactionStats.latchTime = latchTime; aSurfaceTransactionStats.presentFence = presentFence; aSurfaceTransactionStats.transactionCompleted = true; auto& aSurfaceControlStats = aSurfaceTransactionStats.aSurfaceControlStats; for (const auto& [surfaceControl, latchTime, acquireTime, presentFence, previousReleaseFence, transformHint, frameEvents] : surfaceControlStats) { ASurfaceControl* aSurfaceControl = reinterpret_cast(surfaceControl.get()); aSurfaceControlStats[aSurfaceControl].acquireTime = acquireTime; 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 = ASurfaceControl_to_SurfaceControl(aSurfaceControl); sp 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 = 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 = 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 = ASurfaceControl_to_SurfaceControl(aSurfaceControl); Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); sp graphic_buffer(reinterpret_cast(buffer)); transaction->setBuffer(surfaceControl, graphic_buffer); if (acquire_fence_fd != -1) { sp fence = new Fence(acquire_fence_fd); transaction->setAcquireFence(surfaceControl, 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 = ASurfaceControl_to_SurfaceControl(aSurfaceControl); Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); Rect sourceRect = static_cast(source); Rect destRect = static_cast(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 = ASurfaceControl_to_SurfaceControl(aSurfaceControl); Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); transaction->setCrop(surfaceControl, static_cast(crop)); } void ASurfaceTransaction_setPosition(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl, int32_t x, int32_t y) { CHECK_NOT_NULL(aSurfaceTransaction); CHECK_NOT_NULL(aSurfaceControl); sp 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 = 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 = 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 = 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 = ASurfaceControl_to_SurfaceControl(aSurfaceControl); Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); Region region; for (uint32_t i = 0; i < count; ++i) { region.orSelf(static_cast(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(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 = 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 = ASurfaceControl_to_SurfaceControl(aSurfaceControl); Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); transaction->setDataspace(surfaceControl, static_cast(aDataSpace)); } void ASurfaceTransaction_setHdrMetadata_smpte2086(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl, struct AHdrMetadata_smpte2086* metadata) { CHECK_NOT_NULL(aSurfaceTransaction); CHECK_NOT_NULL(aSurfaceControl); sp 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 = 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_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 = 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(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 = ASurfaceControl_to_SurfaceControl(aSurfaceControl); transaction->setFrameRate(surfaceControl, frameRate, compatibility, changeFrameRateStrategy); } void ASurfaceTransaction_setEnableBackPressure(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl, bool enableBackpressure) { CHECK_NOT_NULL(aSurfaceControl); CHECK_NOT_NULL(aSurfaceTransaction); sp 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& /* presentFence */, const std::vector& surfaceControlStats) { ASurfaceTransactionStats aSurfaceTransactionStats; aSurfaceTransactionStats.latchTime = latchTime; aSurfaceTransactionStats.transactionCompleted = false; auto& aSurfaceControlStats = aSurfaceTransactionStats.aSurfaceControlStats; for (const auto& [surfaceControl, latchTime, acquireTime, presentFence, previousReleaseFence, transformHint, frameEvents] : surfaceControlStats) { ASurfaceControl* aSurfaceControl = reinterpret_cast(surfaceControl.get()); aSurfaceControlStats[aSurfaceControl].acquireTime = acquireTime; } (*func)(callback_context, &aSurfaceTransactionStats); }; Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); transaction->addTransactionCommittedCallback(callback, context); }