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 }