1 /*
<lambda>null2  * Copyright 2022 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 package androidx.graphics.surface
18 
19 import android.graphics.Rect
20 import android.graphics.Region
21 import android.hardware.HardwareBuffer
22 import android.hardware.SyncFence
23 import android.os.Build
24 import android.view.AttachedSurfaceControl
25 import android.view.SurfaceControl
26 import android.view.SurfaceControl.Transaction
27 import android.view.SurfaceView
28 import androidx.annotation.RequiresApi
29 import androidx.hardware.SyncFenceCompat
30 import androidx.hardware.SyncFenceImpl
31 import androidx.hardware.SyncFenceV33
32 import java.util.concurrent.Executor
33 
34 /** Implementation of [SurfaceControlImpl] that wraps the SDK's [SurfaceControl] API. */
35 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
36 internal class SurfaceControlV33 internal constructor(internal val surfaceControl: SurfaceControl) :
37     SurfaceControlImpl {
38 
39     /** See [SurfaceControlImpl.isValid] */
40     override fun isValid(): Boolean = surfaceControl.isValid
41 
42     /** See [SurfaceControlImpl.release] */
43     override fun release() {
44         surfaceControl.release()
45     }
46 
47     /** See [SurfaceControlImpl.Builder] */
48     class Builder : SurfaceControlImpl.Builder {
49 
50         private val builder = SurfaceControl.Builder()
51 
52         /** See [SurfaceControlImpl.Builder.setParent] */
53         override fun setParent(surfaceView: SurfaceView): SurfaceControlImpl.Builder {
54             builder.setParent(surfaceView.surfaceControl)
55             return this
56         }
57 
58         /** See [SurfaceControlImpl.Builder.setParent] */
59         override fun setParent(surfaceControl: SurfaceControlCompat): SurfaceControlImpl.Builder {
60             builder.setParent(surfaceControl.scImpl.asFrameworkSurfaceControl())
61             return this
62         }
63 
64         /** See [SurfaceControlImpl.Builder.setName] */
65         override fun setName(name: String): Builder {
66             builder.setName(name)
67             return this
68         }
69 
70         /** See [SurfaceControlImpl.Builder.build] */
71         override fun build(): SurfaceControlImpl = SurfaceControlV33(builder.build())
72     }
73 
74     /** See [SurfaceControlImpl.Transaction] */
75     class Transaction : SurfaceControlImpl.Transaction {
76 
77         private val mTransaction = SurfaceControl.Transaction()
78 
79         /** See [SurfaceControlImpl.Transaction.setOpaque] */
80         override fun setOpaque(
81             surfaceControl: SurfaceControlImpl,
82             isOpaque: Boolean
83         ): SurfaceControlImpl.Transaction {
84             mTransaction.setOpaque(surfaceControl.asFrameworkSurfaceControl(), isOpaque)
85             return this
86         }
87 
88         /** See [SurfaceControlImpl.Transaction.setVisibility] */
89         override fun setVisibility(
90             surfaceControl: SurfaceControlImpl,
91             visible: Boolean
92         ): SurfaceControlImpl.Transaction {
93             mTransaction.setVisibility(surfaceControl.asFrameworkSurfaceControl(), visible)
94             return this
95         }
96 
97         /** See [SurfaceControlImpl.Transaction.setBuffer] */
98         override fun setBuffer(
99             surfaceControl: SurfaceControlImpl,
100             buffer: HardwareBuffer?,
101             fence: SyncFenceImpl?,
102             releaseCallback: ((SyncFenceCompat) -> Unit)?
103         ): Transaction {
104             mTransaction.setBuffer(
105                 surfaceControl.asFrameworkSurfaceControl(),
106                 buffer,
107                 fence?.asSyncFence()
108             ) { syncFence ->
109                 releaseCallback?.invoke(SyncFenceCompat(syncFence))
110             }
111             return this
112         }
113 
114         /** See [SurfaceControlImpl.Transaction.setLayer] */
115         override fun setLayer(
116             surfaceControl: SurfaceControlImpl,
117             z: Int
118         ): SurfaceControlImpl.Transaction {
119             mTransaction.setLayer(surfaceControl.asFrameworkSurfaceControl(), z)
120             return this
121         }
122 
123         /** See [SurfaceControlImpl.Transaction.reparent] */
124         override fun reparent(
125             surfaceControl: SurfaceControlImpl,
126             newParent: SurfaceControlImpl?
127         ): Transaction {
128             mTransaction.reparent(
129                 surfaceControl.asFrameworkSurfaceControl(),
130                 newParent?.asFrameworkSurfaceControl()
131             )
132             return this
133         }
134 
135         /** See [SurfaceControlImpl.Transaction.reparent] */
136         override fun reparent(
137             surfaceControl: SurfaceControlImpl,
138             attachedSurfaceControl: AttachedSurfaceControl
139         ): SurfaceControlImpl.Transaction {
140             val reparentTransaction =
141                 attachedSurfaceControl.buildReparentTransaction(
142                     surfaceControl.asFrameworkSurfaceControl()
143                 )
144             if (reparentTransaction != null) {
145                 mTransaction.merge(reparentTransaction)
146             }
147             return this
148         }
149 
150         /** See [SurfaceControlImpl.Transaction.addTransactionCommittedListener] */
151         override fun addTransactionCommittedListener(
152             executor: Executor,
153             listener: SurfaceControlCompat.TransactionCommittedListener
154         ): SurfaceControlImpl.Transaction {
155             mTransaction.addTransactionCommittedListener(executor) {
156                 listener.onTransactionCommitted()
157             }
158             return this
159         }
160 
161         /** See [SurfaceControlImpl.Transaction.setDamageRegion] */
162         override fun setDamageRegion(
163             surfaceControl: SurfaceControlImpl,
164             region: Region?
165         ): SurfaceControlImpl.Transaction {
166             mTransaction.setDamageRegion(surfaceControl.asFrameworkSurfaceControl(), region)
167             return this
168         }
169 
170         /** See [SurfaceControlImpl.Transaction.setAlpha] */
171         override fun setAlpha(
172             surfaceControl: SurfaceControlImpl,
173             alpha: Float
174         ): SurfaceControlImpl.Transaction {
175             mTransaction.setAlpha(surfaceControl.asFrameworkSurfaceControl(), alpha)
176             return this
177         }
178 
179         /** See [SurfaceControlImpl.Transaction.setCrop] */
180         override fun setCrop(
181             surfaceControl: SurfaceControlImpl,
182             crop: Rect?
183         ): SurfaceControlImpl.Transaction {
184             mTransaction.setCrop(surfaceControl.asFrameworkSurfaceControl(), crop)
185             return this
186         }
187 
188         /** See [SurfaceControlImpl.Transaction.setPosition] */
189         override fun setPosition(
190             surfaceControl: SurfaceControlImpl,
191             x: Float,
192             y: Float
193         ): SurfaceControlImpl.Transaction {
194             mTransaction.setPosition(surfaceControl.asFrameworkSurfaceControl(), x, y)
195             return this
196         }
197 
198         /** See [SurfaceControlImpl.Transaction.setScale] */
199         override fun setScale(
200             surfaceControl: SurfaceControlImpl,
201             scaleX: Float,
202             scaleY: Float
203         ): SurfaceControlImpl.Transaction {
204             mTransaction.setScale(surfaceControl.asFrameworkSurfaceControl(), scaleX, scaleY)
205             return this
206         }
207 
208         /** See [SurfaceControlImpl.Transaction.setBufferTransform] */
209         override fun setBufferTransform(
210             surfaceControl: SurfaceControlImpl,
211             @SurfaceControlCompat.Companion.BufferTransform transformation: Int
212         ): SurfaceControlImpl.Transaction {
213             mTransaction.setBufferTransform(
214                 surfaceControl.asFrameworkSurfaceControl(),
215                 transformation
216             )
217             return this
218         }
219 
220         /** See [SurfaceControlCompat.Transaction.setExtendedRangeBrightness] */
221         @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
222         override fun setExtendedRangeBrightness(
223             surfaceControl: SurfaceControlImpl,
224             currentBufferRatio: Float,
225             desiredRatio: Float
226         ): SurfaceControlImpl.Transaction {
227             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
228                 SurfaceControlTransactionVerificationHelperV34.setExtendedRangeBrightness(
229                     mTransaction,
230                     surfaceControl.asFrameworkSurfaceControl(),
231                     currentBufferRatio,
232                     desiredRatio
233                 )
234                 return this
235             } else {
236                 throw UnsupportedOperationException(
237                     "Configuring the extended range brightness is only available on Android U+"
238                 )
239             }
240         }
241 
242         /** See [SurfaceControlCompat.Transaction.setDataSpace] */
243         override fun setDataSpace(
244             surfaceControl: SurfaceControlImpl,
245             dataSpace: Int
246         ): SurfaceControlImpl.Transaction {
247             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
248                 SurfaceControlTransactionVerificationHelperV33.setDataSpace(
249                     mTransaction,
250                     surfaceControl.asFrameworkSurfaceControl(),
251                     dataSpace
252                 )
253             } else {
254                 throw UnsupportedOperationException(
255                     "Configuring the data space is only available on Android T+"
256                 )
257             }
258             return this
259         }
260 
261         override fun setFrameRate(
262             scImpl: SurfaceControlImpl,
263             frameRate: Float,
264             compatibility: Int,
265             changeFrameRateStrategy: Int
266         ): Transaction {
267             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
268                 SurfaceControlVerificationHelperV31.setFrameRate(
269                     mTransaction,
270                     scImpl.asFrameworkSurfaceControl(),
271                     frameRate,
272                     compatibility,
273                     changeFrameRateStrategy
274                 )
275             } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
276                 SurfaceControlVerificationHelperV30.setFrameRate(
277                     mTransaction,
278                     scImpl.asFrameworkSurfaceControl(),
279                     frameRate,
280                     compatibility
281                 )
282             }
283             return this
284         }
285 
286         override fun clearFrameRate(scImpl: SurfaceControlImpl): SurfaceControlImpl.Transaction {
287             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
288                 SurfaceControlVerificationHelperV34.clearFrameRate(
289                     mTransaction,
290                     scImpl.asFrameworkSurfaceControl()
291                 )
292             }
293             return this
294         }
295 
296         /** See [SurfaceControlImpl.Transaction.commit] */
297         override fun commit() {
298             mTransaction.apply()
299         }
300 
301         /** See [SurfaceControlImpl.Transaction.close] */
302         override fun close() {
303             mTransaction.close()
304         }
305 
306         /** See [SurfaceControlImpl.Transaction.commitTransactionOnDraw] */
307         override fun commitTransactionOnDraw(attachedSurfaceControl: AttachedSurfaceControl) {
308             attachedSurfaceControl.applyTransactionOnDraw(mTransaction)
309         }
310 
311         private fun SyncFenceImpl.asSyncFence(): SyncFence =
312             if (this is SyncFenceV33) {
313                 mSyncFence
314             } else {
315                 throw IllegalArgumentException(
316                     "Expected SyncFenceCompat implementation for API level 33"
317                 )
318             }
319     }
320 
321     private companion object {
322         fun SurfaceControlImpl.asFrameworkSurfaceControl(): SurfaceControl =
323             if (this is SurfaceControlV33) {
324                 surfaceControl
325             } else {
326                 throw IllegalArgumentException("Parent implementation is not for Android T")
327             }
328     }
329 }
330 
331 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
332 private object SurfaceControlTransactionVerificationHelperV34 {
333 
setExtendedRangeBrightnessnull334     fun setExtendedRangeBrightness(
335         transaction: Transaction,
336         surfaceControl: SurfaceControl,
337         currentBufferRatio: Float,
338         desiredRatio: Float
339     ) {
340         transaction.setExtendedRangeBrightness(surfaceControl, currentBufferRatio, desiredRatio)
341     }
342 }
343 
344 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
345 private object SurfaceControlTransactionVerificationHelperV33 {
346 
setDataSpacenull347     fun setDataSpace(transaction: Transaction, surfaceControl: SurfaceControl, dataspace: Int) {
348         transaction.setDataSpace(surfaceControl, dataspace)
349     }
350 }
351 
352 @RequiresApi(Build.VERSION_CODES.S)
353 private object SurfaceControlVerificationHelperV31 {
setFrameRatenull354     fun setFrameRate(
355         transaction: Transaction,
356         surfaceControl: SurfaceControl,
357         frameRate: Float,
358         compatibility: Int,
359         strategy: Int
360     ) {
361         transaction.setFrameRate(surfaceControl, frameRate, compatibility, strategy)
362     }
363 }
364 
365 @RequiresApi(Build.VERSION_CODES.R)
366 private object SurfaceControlVerificationHelperV30 {
setFrameRatenull367     fun setFrameRate(
368         transaction: Transaction,
369         surfaceControl: SurfaceControl,
370         frameRate: Float,
371         compatibility: Int
372     ) {
373         transaction.setFrameRate(surfaceControl, frameRate, compatibility)
374     }
375 }
376 
377 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
378 private object SurfaceControlVerificationHelperV34 {
379 
clearFrameRatenull380     fun clearFrameRate(transaction: Transaction, surfaceControl: SurfaceControl) {
381         transaction.clearFrameRate(surfaceControl)
382     }
383 }
384