1 /*
2  * Copyright 2024 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  *      https://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.devicediagnostics.evaluated
18 
19 import android.app.Activity
20 import android.content.Context
21 import android.graphics.Canvas
22 import android.graphics.Paint
23 import android.os.Bundle
24 import android.util.AttributeSet
25 import android.view.MotionEvent
26 import android.view.View
27 import com.android.devicediagnostics.R
28 import kotlin.time.Duration.Companion.seconds
29 import kotlin.time.ExperimentalTime
30 import kotlin.time.TimeSource
31 import java.util.*
32 
33 const val TOUCH_TEST_RESULT_KEY = "touch_test_result"
34 
35 @OptIn(ExperimentalTime::class)
36 class TouchTestView(context: Context, attrs: AttributeSet) : View(context, attrs, 0) {
37 
<lambda>null38     private val whitePaint = Paint().apply { this.color = getContext().getColor(R.color.white) }
<lambda>null39     private val redPaint = Paint().apply { this.color = getContext().getColor(R.color.red) }
40 
41     private val squareSize = 200 // px
42     private val columns = context.getResources().getDisplayMetrics().widthPixels / squareSize
43     private val rows = context.getResources().getDisplayMetrics().heightPixels / squareSize
44     private val exitTime = 0.05.seconds
45 
46     private val xSize
47         get() = width.toFloat() / columns
48     private val ySize
49         get() = height.toFloat() / rows
50 
<lambda>null51     private var array = Array(columns) {Array(rows) {false} }
52 
53     private val timeSource = TimeSource.Monotonic
54     private var timer = timeSource.markNow()
55 
56 
onDrawnull57     override fun onDraw(canvas: Canvas) {
58         super.onDraw(canvas)
59         for (x in 0 until columns) for (y in 0 until rows) canvas.drawRect(
60             xSize * x,
61             ySize * y,
62             xSize * (x + 1),
63             ySize * (y + 1),
64             if (array[x][y]) whitePaint else redPaint
65         )
66     }
67 
onTouchEventnull68     override fun onTouchEvent(event: MotionEvent?): Boolean {
69         event?.let {
70             when (event.action) {
71                 MotionEvent.ACTION_DOWN -> {
72                     timer = timeSource.markNow()
73                 }
74                 MotionEvent.ACTION_UP ->
75                     if (array.all { it.all { it } })
76                         (context as TouchTestActivity).reportResult(true)
77                     else if (timeSource.markNow() - timer < exitTime)
78                         (context as TouchTestActivity).reportResult(false)
79             }
80             val pointerCount = event.pointerCount
81             for(i in 0 until pointerCount) {
82                 val x = (event.getX(i) / xSize).toInt()
83                 val y = (event.getY(i) / ySize).toInt()
84                 if(!array[x][y]) {
85                     array[x][y] = true
86                     invalidate()
87                 }
88             }
89         }
90         return true
91     }
92 }
93 
94 class TouchTestActivity : Activity() {
onCreatenull95     override fun onCreate(savedInstanceState: Bundle?) {
96         super.onCreate(savedInstanceState)
97         setContentView(R.layout.touch_test)
98     }
99 
reportResultnull100     fun reportResult(result: Boolean) {
101         nextTestActivity(this, TouchTestFinalizeActivity::class.java.name) {
102             it.putExtra(TOUCH_TEST_RESULT_KEY, result)
103         }
104     }
105 }
106