ASurfaceControl: add SurfaceControl to NDK (1/2)
Add the NDK API for apps to use SurfaceControl for low level compositing
using SurfaceFlinger.
Test: atest CtsViewTestCases:android.view.cts.ASurfaceControlTest
Bug: 80477568, 111656650
Change-Id: If2c85a4427f422e41feeadbee0b64de7eb5c925e
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 5cfb09b..c342d82 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -49,6 +49,7 @@
"sharedmem.cpp",
"storage_manager.cpp",
"surface_texture.cpp",
+ "surface_control.cpp",
"system_fonts.cpp",
"trace.cpp",
],
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 537aed4..8be8eda 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -205,6 +205,9 @@
AStorageManager_mountObb;
AStorageManager_new;
AStorageManager_unmountObb;
+ ASurfaceControl_create; # introduced=29
+ ASurfaceControl_createFromWindow; # introduced=29
+ ASurfaceControl_destroy; # introduced=29
ASurfaceTexture_acquireANativeWindow; # introduced=28
ASurfaceTexture_attachToGLContext; # introduced=28
ASurfaceTexture_detachFromGLContext; # introduced=28
@@ -213,6 +216,16 @@
ASurfaceTexture_getTransformMatrix; # introduced=28
ASurfaceTexture_release; # introduced=28
ASurfaceTexture_updateTexImage; # introduced=28
+ ASurfaceTransaction_apply; # introduced=29
+ ASurfaceTransaction_create; # introduced=29
+ ASurfaceTransaction_delete; # introduced=29
+ ASurfaceTransaction_setBuffer; # introduced=29
+ ASurfaceTransaction_setBufferTransparency; # introduced=29
+ ASurfaceTransaction_setDamageRegion; # introduced=29
+ ASurfaceTransaction_setGeometry; # introduced=29
+ ASurfaceTransaction_setOnComplete; # introduced=29
+ ASurfaceTransaction_setVisibility; # introduced=29
+ ASurfaceTransaction_setZOrder; # introduced=29
ASystemFontIterator_open; # introduced=29
ASystemFontIterator_close; # introduced=29
ASystemFontIterator_next; # introduced=29
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
new file mode 100644
index 0000000..ead5b0b
--- /dev/null
+++ b/native/android/surface_control.cpp
@@ -0,0 +1,232 @@
+/*
+ * 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/native_window.h>
+#include <android/surface_control.h>
+
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+#include <gui/SurfaceControl.h>
+
+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");
+
+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;
+ }
+
+ uint32_t flags = ISurfaceComposerClient::eFXSurfaceBufferState;
+ sp<SurfaceControl> 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<Surface*>(window));
+ 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);
+ if (!surfaceControl) {
+ return nullptr;
+ }
+
+ SurfaceControl_acquire(surfaceControl.get());
+ return reinterpret_cast<ASurfaceControl*>(surfaceControl.get());
+}
+
+void ASurfaceControl_destroy(ASurfaceControl* aSurfaceControl) {
+ sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+
+ Transaction().reparent(surfaceControl, nullptr).apply();
+ SurfaceControl_release(surfaceControl.get());
+}
+
+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;
+}
+
+void ASurfaceTransaction_apply(ASurfaceTransaction* aSurfaceTransaction) {
+ CHECK_NOT_NULL(aSurfaceTransaction);
+
+ Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+ transaction->apply();
+}
+
+void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* aSurfaceTransaction, void* context,
+ ASurfaceTransaction_OnComplete func) {
+ CHECK_NOT_NULL(aSurfaceTransaction);
+ CHECK_NOT_NULL(context);
+ CHECK_NOT_NULL(func);
+
+ TransactionCompletedCallbackTakesContext callback = [func](void* callback_context,
+ const TransactionStats& stats) {
+ int fence = (stats.presentFence) ? stats.presentFence->dup() : -1;
+ (*func)(callback_context, fence);
+ };
+
+ Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+ transaction->addTransactionCompletedCallback(callback, context);
+}
+
+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 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(reinterpret_cast<GraphicBuffer*>(buffer));
+
+ transaction->setBuffer(surfaceControl, graphic_buffer);
+ if (fence_fd != -1) {
+ sp<Fence> fence = new Fence(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> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+ Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+ transaction->setCrop(surfaceControl, static_cast<const Rect&>(source));
+ transaction->setFrame(surfaceControl, static_cast<const Rect&>(destination));
+ transaction->setTransform(surfaceControl, transform);
+}
+
+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.merge(static_cast<const Rect&>(rects[i]));
+ }
+
+ transaction->setSurfaceDamageRegion(surfaceControl, region);
+}