/* * Copyright (C) 2025 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. */ package com.android.eyedropper.touchscreen import android.content.Intent import android.graphics.Bitmap import android.os.Bundle import android.util.Log import android.view.Display import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.activity.viewModels import androidx.compose.material3.MaterialTheme import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.lifecycleScope import com.android.eyedropper.EyeDropperController import com.android.eyedropper.ui.touchscreen.TouchscreenMainScreen import com.android.eyedropper.ui.touchscreen.TouchscreenViewModel import com.android.eyedropper.util.ScreenCaptureHelper import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject import kotlinx.coroutines.Deferred import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.launch private const val TAG = "TouchscreenController" // TouchscreenControllerActivity too long // TODO: b/435295269 - Hardcoding as single display for now until touchscreen multi-display done private const val DISPLAY_ID = Display.DEFAULT_DISPLAY @AndroidEntryPoint(ComponentActivity::class) class TouchscreenControllerActivity : Hilt_TouchscreenControllerActivity(), EyeDropperController { private lateinit var deferredScreenshotBitmap: Deferred private val viewModel: TouchscreenViewModel by viewModels() @Inject lateinit var screenCaptureHelper: ScreenCaptureHelper override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) showUiOverlay( ::onColorSelected, ::onSelectionCanceled, ) } override fun showUiOverlay(onSelectColor: (Int) -> Unit, onAbort: () -> Unit) { enableEdgeToEdge() lifecycleScope.launch { if (viewModel.androidBitmap == null ) { Log.d(TAG, "Viewmodel has no bitmap, capturing screenshot....") deferredScreenshotBitmap = lifecycleScope.async(Dispatchers.IO) { screenCaptureHelper.captureScreenshotAsync(DISPLAY_ID) } viewModel.initialize( deferredScreenshotBitmap.await(), onSelectColor, onAbort ) } else { Log.d( TAG, "Viewmodel already has bitmap, " + "but need to reset callbacks for new activity instance" ) viewModel.initialize( viewModel.androidBitmap!!, onSelectColor, onAbort ) } setContent { if (viewModel.isInitialized.collectAsStateWithLifecycle().value) { MaterialTheme { TouchscreenMainScreen(viewModel) } } } } } override fun removeUiOverlay() { } /** * Returns color to [MainActivity]. Passed to and called by [TouchscreenViewModel]. */ private fun onColorSelected(colorInt: Int) { setResult(RESULT_OK, Intent().apply { putExtra(Intent.EXTRA_COLOR, colorInt) }) finish() } /** * Reports cancellation to [MainActivity]. Passed to and called by [TouchscreenViewModel]. */ private fun onSelectionCanceled() { Log.d(TAG, "Selection cancelled") setResult(RESULT_CANCELED) finish() } }