0
0
mirror of https://github.com/florisboard/florisboard.git synced 2024-09-19 19:42:20 +02:00

Add extended benchmark and improve app startup

This commit is contained in:
Patrick Goldinger 2022-05-21 13:35:18 +02:00
parent 0408d437e1
commit 4e2a43a6cd
4 changed files with 75 additions and 13 deletions

View File

@ -21,7 +21,6 @@ import android.content.res.Configuration
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.layout.Column
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
@ -70,7 +69,6 @@ val LocalNavController = staticCompositionLocalOf<NavController> {
class FlorisAppActivity : ComponentActivity() {
private val prefs by florisPreferenceModel()
private var isDatastoreReady by mutableStateOf(false)
private var appTheme by mutableStateOf(AppTheme.AUTO)
private var showAppIcon = true
private var resourcesContext by mutableStateOf(this as Context)
@ -79,8 +77,10 @@ class FlorisAppActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
installSplashScreen()
prefs.datastoreReadyStatus.observe(this) {
isDatastoreReady = it
prefs.datastoreReadyStatus.observe(this) { ready ->
if (ready) {
AppVersionUtils.updateVersionOnInstallAndLastUse(this, prefs)
}
}
prefs.advanced.settingsTheme.observe(this) {
appTheme = it
@ -96,7 +96,6 @@ class FlorisAppActivity : ComponentActivity() {
}
}
AppVersionUtils.updateVersionOnInstallAndLastUse(this, prefs)
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
@ -129,7 +128,6 @@ class FlorisAppActivity : ComponentActivity() {
}
}
@OptIn(ExperimentalAnimationApi::class)
@Composable
private fun AppContent() {
val navController = rememberNavController()

View File

@ -25,6 +25,7 @@ import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.app.LocalNavController
@ -32,6 +33,7 @@ import dev.patrickgold.florisboard.app.Routes
import dev.patrickgold.florisboard.app.florisPreferenceModel
import dev.patrickgold.florisboard.lib.compose.FlorisCanvasIcon
import dev.patrickgold.florisboard.lib.compose.LocalPreviewFieldController
import dev.patrickgold.florisboard.lib.util.InputMethodUtils
import dev.patrickgold.jetpref.datastore.model.observeAsState
@Composable
@ -40,6 +42,8 @@ fun SplashScreen() = Box(
contentAlignment = Alignment.Center,
) {
val prefs by florisPreferenceModel()
val context = LocalContext.current
val isModelLoaded by prefs.datastoreReadyStatus.observeAsState()
val isImeSetUp by prefs.internal.isImeSetUp.observeAsState()
val navController = LocalNavController.current
@ -51,7 +55,9 @@ fun SplashScreen() = Box(
LaunchedEffect(isModelLoaded) {
if (isModelLoaded) {
navController.navigate(if (isImeSetUp) Routes.Settings.Home else Routes.Setup.Screen) {
val isConfigured = isImeSetUp ||
(InputMethodUtils.isFlorisboardEnabled(context) && InputMethodUtils.isFlorisboardSelected(context))
navController.navigate(if (isConfigured) Routes.Settings.Home else Routes.Setup.Screen) {
popUpTo(Routes.Splash.Screen) {
inclusive = true
}

View File

@ -31,6 +31,16 @@ private const val DELIMITER = ':'
private const val IME_SERVICE_CLASS_NAME = "dev.patrickgold.florisboard.FlorisImeService"
object InputMethodUtils {
fun isFlorisboardEnabled(context: Context): Boolean {
val enabledImeList = AndroidSettings.Secure.getString(context, Settings.Secure.ENABLED_INPUT_METHODS)
return enabledImeList != null && parseIsFlorisboardEnabled(context, enabledImeList)
}
fun isFlorisboardSelected(context: Context): Boolean {
val selectedIme = AndroidSettings.Secure.getString(context, Settings.Secure.DEFAULT_INPUT_METHOD)
return selectedIme != null && parseIsFlorisboardSelected(context, selectedIme)
}
@Composable
fun observeIsFlorisboardEnabled(
context: Context = LocalContext.current.applicationContext,

View File

@ -1,4 +1,5 @@
/*
* Copyright 2022 The Android Open Source Project
* Copyright (C) 2022 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -16,27 +17,74 @@
package dev.patrickgold.florisboard.benchmark
import androidx.benchmark.macro.BaselineProfileMode
import androidx.benchmark.macro.CompilationMode
import androidx.benchmark.macro.StartupMode
import androidx.benchmark.macro.StartupTimingMetric
import androidx.benchmark.macro.junit4.MacrobenchmarkRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class StartupBenchmark {
/**
* Run this benchmark from Studio to see startup measurements, and captured system traces
* for investigating your app's performance from a cold state.
*/
@RunWith(AndroidJUnit4ClassRunner::class)
class ColdStartupBenchmark : AbstractStartupBenchmark(StartupMode.COLD)
/**
* Run this benchmark from Studio to see startup measurements, and captured system traces
* for investigating your app's performance from a warm state.
*/
@RunWith(AndroidJUnit4ClassRunner::class)
class WarmStartupBenchmark : AbstractStartupBenchmark(StartupMode.WARM)
/**
* Run this benchmark from Studio to see startup measurements, and captured system traces
* for investigating your app's performance from a hot state.
*/
@RunWith(AndroidJUnit4ClassRunner::class)
class HotStartupBenchmark : AbstractStartupBenchmark(StartupMode.HOT)
/**
* Base class for benchmarks with different startup modes.
* Enables app startups from various states of baseline profile or [CompilationMode]s.
*
* Original source of this test: https://github.com/android/nowinandroid/blob/b4a2f35ed23b2cf40fe90311bdac2688d9cb69e2/benchmark/src/main/java/com/google/samples/apps/nowinandroid/startup/StartupBenchmark.kt
*/
abstract class AbstractStartupBenchmark(private val startupMode: StartupMode) {
@get:Rule
val benchmarkRule = MacrobenchmarkRule()
@Test
fun startup() = benchmarkRule.measureRepeated(
fun startupNoCompilation() = startup(CompilationMode.None())
@Test
fun startupBaselineProfileDisabled() = startup(
CompilationMode.Partial(baselineProfileMode = BaselineProfileMode.Disable, warmupIterations = 1)
)
@Test
fun startupBaselineProfile() = startup(CompilationMode.Partial(baselineProfileMode = BaselineProfileMode.Require))
@Test
fun startupFullCompilation() = startup(CompilationMode.Full())
private fun startup(compilationMode: CompilationMode) = benchmarkRule.measureRepeated(
packageName = "dev.patrickgold.florisboard",
metrics = listOf(StartupTimingMetric()),
compilationMode = compilationMode,
iterations = 10,
startupMode = StartupMode.COLD,
startupMode = startupMode,
setupBlock = {
pressHome()
device.executeShellCommand("ime enable dev.patrickgold.florisboard/.FlorisImeService")
device.executeShellCommand("ime set dev.patrickgold.florisboard/.FlorisImeService")
}
) {
pressHome()
startActivityAndWait()
device.waitForIdle(5000)
}
}