1 /*
2  * Copyright (C) 2021 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 com.android.test.hwui
18 
19 import android.content.Context
20 import android.graphics.BlendMode
21 import android.graphics.Color
22 import android.graphics.Paint
23 import android.graphics.Rect
24 import android.hardware.HardwareBuffer
25 import android.util.AttributeSet
26 import android.view.InputDevice
27 import android.view.MotionEvent
28 import android.view.Surface
29 import android.view.SurfaceHolder
30 import android.view.SurfaceView
31 import android.view.WindowInsets
32 import android.view.WindowInsetsController
33 
34 class FrontBufferedLayer : SurfaceView, SurfaceHolder.Callback {
35     var mRenderer: PenStylusActivity.SingleBufferedCanvas? = null
36 
37     constructor(context: Context) : super(context)
38     constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
39 
40     init {
41         holder.addCallback(this)
42         setZOrderOnTop(true)
43     }
44 
surfaceChangednull45     override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
46         nDestroy(mNativePtr)
47         mNativePtr = nCreate(holder.surface)
48         mRenderer = PenStylusActivity.SingleBufferedCanvas(width, height)
49         clearOverlay()
50 
51         if ((false)) {
52             val canvas = holder.lockCanvas()
53             canvas.drawColor(Color.LTGRAY)
54             holder.unlockCanvasAndPost(canvas)
55         }
56     }
57 
surfaceDestroyednull58     override fun surfaceDestroyed(holder: SurfaceHolder) {
59         mRenderer = null
60         nDestroy(mNativePtr)
61         mNativePtr = 0
62     }
63 
surfaceCreatednull64     override fun surfaceCreated(holder: SurfaceHolder) {
65     }
66 
onAttachedToWindownull67     override fun onAttachedToWindow() {
68         super.onAttachedToWindow()
69         requestUnbufferedDispatch(InputDevice.SOURCE_CLASS_POINTER)
70         this.windowInsetsController?.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_DEFAULT)
71         this.windowInsetsController?.hide(WindowInsets.Type.navigationBars())
72         this.windowInsetsController?.hide(WindowInsets.Type.statusBars())
73     }
74 
clearOverlaynull75     private fun clearOverlay() {
76         mRenderer?.let {
77             it.update(null) {
78                 drawColor(Color.WHITE, BlendMode.SRC)
79             }
80             nUpdateBuffer(mNativePtr, it.mHardwareBuffer)
81         }
82     }
83 
84     private var prevX: Float = 0f
85     private var prevY: Float = 0f
<lambda>null86     private val paint = Paint().also {
87         it.color = Color.BLACK
88         it.strokeWidth = 10f
89         it.isAntiAlias = true
90     }
91 
onTouchEventnull92     override fun onTouchEvent(event: MotionEvent): Boolean {
93         if (!event.isFromSource(InputDevice.SOURCE_STYLUS)) {
94             if (event.action == MotionEvent.ACTION_DOWN) {
95                 clearOverlay()
96             }
97             return true
98         }
99         val action = event.actionMasked
100         if (action == MotionEvent.ACTION_DOWN ||
101                 action == MotionEvent.ACTION_MOVE) {
102             mRenderer?.let {
103                 val left = minOf(prevX, event.x).toInt() - 10
104                 val top = minOf(prevY, event.y).toInt() - 10
105                 val right = maxOf(prevX, event.x).toInt() + 10
106                 val bottom = maxOf(prevY, event.y).toInt() + 10
107                 it.update(Rect(left, top, right, bottom)) {
108                     if (action == MotionEvent.ACTION_MOVE) {
109                         drawLine(prevX, prevY, event.x, event.y, paint)
110                     }
111                     drawCircle(event.x, event.y, 5f, paint)
112                 }
113                 nUpdateBuffer(mNativePtr, it.mHardwareBuffer)
114             }
115             prevX = event.x
116             prevY = event.y
117         }
118         return true
119     }
120 
121     private var mNativePtr: Long = 0
122 
nCreatenull123     private external fun nCreate(surface: Surface): Long
124     private external fun nDestroy(ptr: Long)
125     private external fun nUpdateBuffer(ptr: Long, buffer: HardwareBuffer)
126 
127     companion object {
128         init {
129             System.loadLibrary("hwaccelerationtest_jni")
130         }
131     }
132 }