diff --git a/app/build.gradle b/app/build.gradle index 6aae3f8de..0a162ca1b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -89,7 +89,7 @@ android { resValue "string", "DEFAULT_PROFILE", "profile_8" resValue "string", "applicationId", "org.obd.graphs.my.giulia.performance_monitor" applicationId "org.obd.graphs.my.giulia.performance_monitor" - versionCode 90 + versionCode 92 } giulia { diff --git a/app/src/main/java/org/obd/graphs/ui/SurfaceRendererFragment.kt b/app/src/main/java/org/obd/graphs/ui/SurfaceRendererFragment.kt index 2a4fca28a..e59020351 100644 --- a/app/src/main/java/org/obd/graphs/ui/SurfaceRendererFragment.kt +++ b/app/src/main/java/org/obd/graphs/ui/SurfaceRendererFragment.kt @@ -45,10 +45,10 @@ import org.obd.graphs.bl.datalogger.DataLoggerRepository import org.obd.graphs.bl.query.Query import org.obd.graphs.getPowerPreferences import org.obd.graphs.registerReceiver -import org.obd.graphs.renderer.Fps -import org.obd.graphs.renderer.ScreenSettings -import org.obd.graphs.renderer.SurfaceRenderer -import org.obd.graphs.renderer.SurfaceRendererType +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.renderer.api.ScreenSettings +import org.obd.graphs.renderer.api.SurfaceRenderer +import org.obd.graphs.renderer.api.SurfaceRendererType import org.obd.graphs.sendBroadcastEvent import org.obd.graphs.ui.common.SurfaceController diff --git a/app/src/main/java/org/obd/graphs/ui/common/SurfaceController.kt b/app/src/main/java/org/obd/graphs/ui/common/SurfaceController.kt index 4ecf2a0ab..6f943c7af 100644 --- a/app/src/main/java/org/obd/graphs/ui/common/SurfaceController.kt +++ b/app/src/main/java/org/obd/graphs/ui/common/SurfaceController.kt @@ -22,7 +22,7 @@ import android.util.Log import android.view.Surface import android.view.SurfaceHolder import androidx.annotation.MainThread -import org.obd.graphs.renderer.SurfaceRenderer +import org.obd.graphs.renderer.api.SurfaceRenderer private const val LOG_KEY = "SurfaceController" diff --git a/app/src/main/java/org/obd/graphs/ui/drag_racing/DragRacingRendererFragment.kt b/app/src/main/java/org/obd/graphs/ui/drag_racing/DragRacingRendererFragment.kt index e933ceef5..aa1b3c4a9 100644 --- a/app/src/main/java/org/obd/graphs/ui/drag_racing/DragRacingRendererFragment.kt +++ b/app/src/main/java/org/obd/graphs/ui/drag_racing/DragRacingRendererFragment.kt @@ -19,8 +19,8 @@ package org.obd.graphs.ui.drag_racing import org.obd.graphs.R import org.obd.graphs.bl.query.Query import org.obd.graphs.bl.query.QueryStrategyType -import org.obd.graphs.renderer.ScreenSettings -import org.obd.graphs.renderer.SurfaceRendererType +import org.obd.graphs.renderer.api.ScreenSettings +import org.obd.graphs.renderer.api.SurfaceRendererType import org.obd.graphs.ui.SurfaceRendererFragment internal class DragRacingRendererFragment : SurfaceRendererFragment( diff --git a/app/src/main/java/org/obd/graphs/ui/drag_racing/DragRacingSettings.kt b/app/src/main/java/org/obd/graphs/ui/drag_racing/DragRacingSettings.kt index 099692652..e1dc5824d 100644 --- a/app/src/main/java/org/obd/graphs/ui/drag_racing/DragRacingSettings.kt +++ b/app/src/main/java/org/obd/graphs/ui/drag_racing/DragRacingSettings.kt @@ -18,14 +18,14 @@ package org.obd.graphs.ui.drag_racing import org.obd.graphs.preferences.Prefs import org.obd.graphs.preferences.getS -import org.obd.graphs.renderer.DragRacingScreenSettings -import org.obd.graphs.renderer.ScreenSettings +import org.obd.graphs.renderer.api.DragRacingScreenSettings +import org.obd.graphs.renderer.api.ScreenSettings class DragRacingSettings: ScreenSettings { private val dragRacingScreenSettings = DragRacingScreenSettings() - override fun getDragRacingScreenSettings(): DragRacingScreenSettings = dragRacingScreenSettings.apply { + override fun getDragRacingScreenSettings(): DragRacingScreenSettings = dragRacingScreenSettings.apply { metricsFrequencyReadEnabled = Prefs.getBoolean("pref.drag_racing.metrics_reading.display_frequency.enabled", true) vehicleSpeedDisplayDebugEnabled = Prefs.getBoolean("pref.drag_racing.debug.vehicle_speed_measurement", false) displayMetricsExtendedEnabled= Prefs.getBoolean("pref.profile.2_0_GME_extension.enabled", false) diff --git a/app/src/main/java/org/obd/graphs/ui/gauge/GaugeRendererFragment.kt b/app/src/main/java/org/obd/graphs/ui/gauge/GaugeRendererFragment.kt index 2f4d7fb38..937a5ab31 100644 --- a/app/src/main/java/org/obd/graphs/ui/gauge/GaugeRendererFragment.kt +++ b/app/src/main/java/org/obd/graphs/ui/gauge/GaugeRendererFragment.kt @@ -24,7 +24,7 @@ import android.widget.Button import org.obd.graphs.R import org.obd.graphs.bl.datalogger.DataLoggerRepository import org.obd.graphs.bl.query.Query -import org.obd.graphs.renderer.SurfaceRendererType +import org.obd.graphs.renderer.api.SurfaceRendererType import org.obd.graphs.ui.SurfaceRendererFragment import org.obd.graphs.ui.common.COLOR_PHILIPPINE_GREEN import org.obd.graphs.ui.common.COLOR_TRANSPARENT diff --git a/app/src/main/java/org/obd/graphs/ui/gauge/GaugeSettings.kt b/app/src/main/java/org/obd/graphs/ui/gauge/GaugeSettings.kt index 2561085ad..136895121 100644 --- a/app/src/main/java/org/obd/graphs/ui/gauge/GaugeSettings.kt +++ b/app/src/main/java/org/obd/graphs/ui/gauge/GaugeSettings.kt @@ -20,8 +20,8 @@ import org.obd.graphs.bl.query.Query import org.obd.graphs.preferences.Prefs import org.obd.graphs.preferences.getS import org.obd.graphs.preferences.isEnabled -import org.obd.graphs.renderer.GaugeRendererSettings -import org.obd.graphs.renderer.ScreenSettings +import org.obd.graphs.renderer.api.GaugeRendererSettings +import org.obd.graphs.renderer.api.ScreenSettings import org.obd.graphs.ui.common.COLOR_RAINBOW_INDIGO class GaugeSettings( diff --git a/app/src/main/java/org/obd/graphs/ui/giulia/GiuliaRendererFragment.kt b/app/src/main/java/org/obd/graphs/ui/giulia/GiuliaRendererFragment.kt index a15c695bb..9de6f53b7 100644 --- a/app/src/main/java/org/obd/graphs/ui/giulia/GiuliaRendererFragment.kt +++ b/app/src/main/java/org/obd/graphs/ui/giulia/GiuliaRendererFragment.kt @@ -23,8 +23,8 @@ import android.view.ViewGroup import android.widget.Button import org.obd.graphs.R import org.obd.graphs.bl.query.Query -import org.obd.graphs.renderer.ScreenSettings -import org.obd.graphs.renderer.SurfaceRendererType +import org.obd.graphs.renderer.api.ScreenSettings +import org.obd.graphs.renderer.api.SurfaceRendererType import org.obd.graphs.ui.SurfaceRendererFragment import org.obd.graphs.ui.common.COLOR_PHILIPPINE_GREEN import org.obd.graphs.ui.common.COLOR_TRANSPARENT diff --git a/app/src/main/java/org/obd/graphs/ui/giulia/GiuliaSettings.kt b/app/src/main/java/org/obd/graphs/ui/giulia/GiuliaSettings.kt index ec65d8be1..1f6de8726 100644 --- a/app/src/main/java/org/obd/graphs/ui/giulia/GiuliaSettings.kt +++ b/app/src/main/java/org/obd/graphs/ui/giulia/GiuliaSettings.kt @@ -19,8 +19,8 @@ package org.obd.graphs.ui.giulia import org.obd.graphs.bl.query.Query import org.obd.graphs.preferences.Prefs import org.obd.graphs.preferences.getS -import org.obd.graphs.renderer.GiuliaRendererSettings -import org.obd.graphs.renderer.ScreenSettings +import org.obd.graphs.renderer.api.GiuliaRendererSettings +import org.obd.graphs.renderer.api.ScreenSettings class GiuliaSettings( private val query: Query, diff --git a/app/src/main/java/org/obd/graphs/ui/performance/PerformanceRendererFragment.kt b/app/src/main/java/org/obd/graphs/ui/performance/PerformanceRendererFragment.kt index de538970c..e38532806 100644 --- a/app/src/main/java/org/obd/graphs/ui/performance/PerformanceRendererFragment.kt +++ b/app/src/main/java/org/obd/graphs/ui/performance/PerformanceRendererFragment.kt @@ -19,8 +19,8 @@ package org.obd.graphs.ui.performance import org.obd.graphs.R import org.obd.graphs.bl.query.Query import org.obd.graphs.bl.query.QueryStrategyType -import org.obd.graphs.renderer.ScreenSettings -import org.obd.graphs.renderer.SurfaceRendererType +import org.obd.graphs.renderer.api.ScreenSettings +import org.obd.graphs.renderer.api.SurfaceRendererType import org.obd.graphs.ui.SurfaceRendererFragment internal class PerformanceRendererFragment : SurfaceRendererFragment( diff --git a/app/src/main/java/org/obd/graphs/ui/performance/PerformanceSettings.kt b/app/src/main/java/org/obd/graphs/ui/performance/PerformanceSettings.kt index 0784e0ab9..1f4655128 100644 --- a/app/src/main/java/org/obd/graphs/ui/performance/PerformanceSettings.kt +++ b/app/src/main/java/org/obd/graphs/ui/performance/PerformanceSettings.kt @@ -18,8 +18,8 @@ package org.obd.graphs.ui.performance import org.obd.graphs.preferences.Prefs import org.obd.graphs.preferences.getS -import org.obd.graphs.renderer.PerformanceScreenSettings -import org.obd.graphs.renderer.ScreenSettings +import org.obd.graphs.renderer.api.PerformanceScreenSettings +import org.obd.graphs.renderer.api.ScreenSettings class PerformanceSettings : ScreenSettings { private val settings = PerformanceScreenSettings() diff --git a/app/src/main/java/org/obd/graphs/ui/trip_info/TripInfoRendererFragment.kt b/app/src/main/java/org/obd/graphs/ui/trip_info/TripInfoRendererFragment.kt index 710ff9376..1d7e65fe9 100644 --- a/app/src/main/java/org/obd/graphs/ui/trip_info/TripInfoRendererFragment.kt +++ b/app/src/main/java/org/obd/graphs/ui/trip_info/TripInfoRendererFragment.kt @@ -19,8 +19,8 @@ package org.obd.graphs.ui.trip_info import org.obd.graphs.R import org.obd.graphs.bl.query.Query import org.obd.graphs.bl.query.QueryStrategyType -import org.obd.graphs.renderer.ScreenSettings -import org.obd.graphs.renderer.SurfaceRendererType +import org.obd.graphs.renderer.api.ScreenSettings +import org.obd.graphs.renderer.api.SurfaceRendererType import org.obd.graphs.ui.SurfaceRendererFragment internal class TripInfoRendererFragment : SurfaceRendererFragment( diff --git a/app/src/main/java/org/obd/graphs/ui/trip_info/TripInfoSettings.kt b/app/src/main/java/org/obd/graphs/ui/trip_info/TripInfoSettings.kt index 4a83b0505..5eb42de53 100644 --- a/app/src/main/java/org/obd/graphs/ui/trip_info/TripInfoSettings.kt +++ b/app/src/main/java/org/obd/graphs/ui/trip_info/TripInfoSettings.kt @@ -18,8 +18,8 @@ package org.obd.graphs.ui.trip_info import org.obd.graphs.preferences.Prefs import org.obd.graphs.preferences.getS -import org.obd.graphs.renderer.ScreenSettings -import org.obd.graphs.renderer.TripInfoScreenSettings +import org.obd.graphs.renderer.api.ScreenSettings +import org.obd.graphs.renderer.api.TripInfoScreenSettings class TripInfoSettings: ScreenSettings { diff --git a/automotive/src/main/java/org/obd/graphs/aa/CarSession.kt b/automotive/src/main/java/org/obd/graphs/aa/CarSession.kt index f4e6e6418..ebaccd69f 100644 --- a/automotive/src/main/java/org/obd/graphs/aa/CarSession.kt +++ b/automotive/src/main/java/org/obd/graphs/aa/CarSession.kt @@ -20,16 +20,20 @@ import android.content.Intent import android.content.res.Configuration import androidx.car.app.Screen import androidx.car.app.Session +import androidx.car.app.connection.CarConnection import org.obd.graphs.aa.screen.CarScreen import org.obd.graphs.aa.screen.CarScreenFactory +import org.obd.graphs.aa.screen.nav.GOTO_LAST_VSITED_SCREEN_EVENT +import org.obd.graphs.aa.screen.nav.START_DATA_LOGGING_EVENT import org.obd.graphs.bl.collector.MetricsCollector +import org.obd.graphs.bl.datalogger.DataLoggerRepository import org.obd.graphs.preferences.initPrefs -import org.obd.graphs.renderer.Fps +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.sendBroadcastEvent import org.obd.graphs.setCarContext internal class CarSession : Session() { - - private val settings by lazy { CarSettings(carContext) } + private val settings by lazy { CarSettings(carContext) } private val metricsCollector = MetricsCollector.instance() private val fps: Fps = Fps() private lateinit var screen: CarScreen @@ -38,6 +42,7 @@ internal class CarSession : Session() { setCarContext(carContext) initPrefs(carContext) screen = CarScreenFactory.instance(carContext, settings, metricsCollector, fps) + CarConnection(carContext).type.observe(this, ::onConnectionStateUpdated) return screen } @@ -45,4 +50,18 @@ internal class CarSession : Session() { super.onCarConfigurationChanged(newConfiguration) screen.onCarConfigurationChanged() } + + private fun onConnectionStateUpdated(connectionState: Int) { + when (connectionState) { + CarConnection.CONNECTION_TYPE_PROJECTION -> { + if (settings.isLoadLastVisitedScreenEnabled()) { + sendBroadcastEvent(GOTO_LAST_VSITED_SCREEN_EVENT) + } + + if (settings.isAutomaticConnectEnabled() && !DataLoggerRepository.isRunning()) { + sendBroadcastEvent(START_DATA_LOGGING_EVENT) + } + } + } + } } diff --git a/automotive/src/main/java/org/obd/graphs/aa/CarSettings.kt b/automotive/src/main/java/org/obd/graphs/aa/CarSettings.kt index 568efec86..fa68957e9 100644 --- a/automotive/src/main/java/org/obd/graphs/aa/CarSettings.kt +++ b/automotive/src/main/java/org/obd/graphs/aa/CarSettings.kt @@ -25,7 +25,18 @@ import org.obd.graphs.PREF_DYNAMIC_SELECTOR_ENABLED import org.obd.graphs.ViewPreferencesSerializer import org.obd.graphs.bl.datalogger.dataLoggerSettings import org.obd.graphs.preferences.* -import org.obd.graphs.renderer.* +import org.obd.graphs.renderer.api.ColorTheme +import org.obd.graphs.renderer.api.DragRacingScreenSettings +import org.obd.graphs.renderer.api.DynamicSelectorMode +import org.obd.graphs.renderer.api.GaugeProgressBarType +import org.obd.graphs.renderer.api.GaugeRendererSettings +import org.obd.graphs.renderer.api.GiuliaRendererSettings +import org.obd.graphs.renderer.api.Identity +import org.obd.graphs.renderer.api.PerformanceScreenSettings +import org.obd.graphs.renderer.api.RoutinesScreenSettings +import org.obd.graphs.renderer.api.ScreenSettings +import org.obd.graphs.renderer.api.SurfaceRendererType +import org.obd.graphs.renderer.api.TripInfoScreenSettings import org.obd.graphs.runAsync import org.obd.graphs.ui.common.COLOR_DYNAMIC_SELECTOR_ECO import org.obd.graphs.ui.common.COLOR_DYNAMIC_SELECTOR_NORMAL @@ -124,7 +135,7 @@ class CarSettings(private val carContext: CarContext) : ScreenSettings { } - override fun getRoutinesScreenSettings(): RoutinesScreenSettings = routinesScreenSettings.apply { + override fun getRoutinesScreenSettings(): RoutinesScreenSettings = routinesScreenSettings.apply { viewEnabled = Prefs.getBoolean("pref.aa.routines.enabled", true) } @@ -190,9 +201,6 @@ class CarSettings(private val carContext: CarContext) : ScreenSettings { override fun isScaleEnabled(): Boolean = Prefs.getBoolean("pref.aa.virtual_screens.scale.enabled", true) - override fun getHeightPixels(): Int = carContext.resources.displayMetrics.heightPixels - override fun getWidthPixels(): Int = carContext.resources.displayMetrics.widthPixels - override fun getMaxColumns(): Int = Prefs.getS("pref.aa.max_pids_in_column.${getCurrentVirtualScreenId(giuliaRendererSettings.dataPrefs)}", DEFAULT_ITEMS_IN_COLUMN).toInt() diff --git a/automotive/src/main/java/org/obd/graphs/aa/screen/CarScreen.kt b/automotive/src/main/java/org/obd/graphs/aa/screen/CarScreen.kt index 15d7c4458..e04123198 100644 --- a/automotive/src/main/java/org/obd/graphs/aa/screen/CarScreen.kt +++ b/automotive/src/main/java/org/obd/graphs/aa/screen/CarScreen.kt @@ -19,7 +19,6 @@ package org.obd.graphs.aa.screen import android.util.Log import androidx.car.app.CarContext import androidx.car.app.Screen -import androidx.car.app.connection.CarConnection import androidx.car.app.model.ActionStrip import androidx.car.app.model.CarColor import androidx.lifecycle.DefaultLifecycleObserver @@ -34,8 +33,8 @@ import org.obd.graphs.aa.toast import org.obd.graphs.bl.collector.MetricsCollector import org.obd.graphs.bl.datalogger.DataLoggerRepository import org.obd.graphs.bl.datalogger.WorkflowStatus -import org.obd.graphs.renderer.Fps -import org.obd.graphs.renderer.Identity +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.renderer.api.Identity import org.obd.graphs.sendBroadcastEvent const val GIULIA_VIRTUAL_SCREEN_1_SETTINGS_CHANGED = "pref.aa.pids.profile_1.event.changed" @@ -54,9 +53,7 @@ internal abstract class CarScreen( DefaultLifecycleObserver { open fun getFeatureDescription(): List = emptyList() - abstract fun actionStartDataLogging() - - protected open fun gotoScreen(identity: Identity) {} + abstract fun startDataLogging() protected open fun updateLastVisitedScreen(identity: Identity) { settings.setLastVisitedScreen(identity) @@ -77,10 +74,6 @@ internal abstract class CarScreen( }, ) - protected fun registerConnectionStateReceiver() { - CarConnection(carContext).type.observe(this, ::onConnectionStateUpdated) - } - protected fun actionStopDataLogging() { Log.i(LOG_TAG, "Stopping data logging process") withDataLogger { @@ -115,7 +108,7 @@ internal abstract class CarScreen( R.drawable.actions_connect, mapColor(settings.getColorTheme().actionsBtnConnectColor), ) { - actionStartDataLogging() + startDataLogging() }, ) } @@ -167,20 +160,4 @@ internal abstract class CarScreen( fps.start() } } - - private fun onConnectionStateUpdated(connectionState: Int) { - when (connectionState) { - CarConnection.CONNECTION_TYPE_PROJECTION -> { - if (settings.isLoadLastVisitedScreenEnabled()) { - Log.i(LOG_TAG, "Load last visited screen flag is enabled. Loading last visited screen....") - gotoScreen(settings.getLastVisitedScreen()) - } - - if (settings.isAutomaticConnectEnabled() && !DataLoggerRepository.isRunning()) { - Log.i(LOG_TAG, "Auto connection enabled. Auto start data logging.....") - actionStartDataLogging() - } - } - } - } } diff --git a/automotive/src/main/java/org/obd/graphs/aa/screen/CarScreenFactory.kt b/automotive/src/main/java/org/obd/graphs/aa/screen/CarScreenFactory.kt index 5c5642bd4..d48d20915 100644 --- a/automotive/src/main/java/org/obd/graphs/aa/screen/CarScreenFactory.kt +++ b/automotive/src/main/java/org/obd/graphs/aa/screen/CarScreenFactory.kt @@ -22,7 +22,7 @@ import org.obd.graphs.aa.ScreenTemplateType import org.obd.graphs.aa.screen.iot.IotTemplateCarScreen import org.obd.graphs.aa.screen.nav.NavTemplateCarScreen import org.obd.graphs.bl.collector.MetricsCollector -import org.obd.graphs.renderer.Fps +import org.obd.graphs.renderer.api.Fps internal interface CarScreenFactory { diff --git a/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/DragRacingScreenBehavior.kt b/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/DragRacingScreenBehavior.kt new file mode 100644 index 000000000..4237a41ea --- /dev/null +++ b/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/DragRacingScreenBehavior.kt @@ -0,0 +1,39 @@ + /** + * Copyright 2019-2026, Tomasz Żebrowski + * + *

Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You 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 org.obd.graphs.aa.screen.behaviour + +import android.content.Context +import org.obd.graphs.bl.collector.MetricsCollector +import org.obd.graphs.bl.query.QueryStrategyType +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.renderer.api.ScreenSettings +import org.obd.graphs.renderer.api.SurfaceRendererType + +internal class DragRacingScreenBehavior( + context: Context, + metricsCollector: MetricsCollector, + settings: Map, + fps: Fps, +) : ScreenBehavior(context, metricsCollector, settings[SurfaceRendererType.DRAG_RACING]!!, fps, SurfaceRendererType.DRAG_RACING) { + override fun queryStrategyType() = QueryStrategyType.DRAG_RACING_QUERY + + override fun applyFilters(metricsCollector: MetricsCollector) { + query.setStrategy(queryStrategyType()) + metricsCollector.applyFilter(enabled = query.getIDs()) + query.update(metricsCollector.getMetrics().map { p -> p.source.command.pid.id }.toSet()) + } +} diff --git a/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/GaugeScreenBehavior.kt b/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/GaugeScreenBehavior.kt new file mode 100644 index 000000000..2919dfb74 --- /dev/null +++ b/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/GaugeScreenBehavior.kt @@ -0,0 +1,54 @@ + /** + * Copyright 2019-2026, Tomasz Żebrowski + * + *

Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You 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 org.obd.graphs.aa.screen.behaviour + +import android.content.Context +import org.obd.graphs.bl.collector.MetricsCollector +import org.obd.graphs.bl.datalogger.dataLoggerSettings +import org.obd.graphs.bl.query.QueryStrategyType +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.renderer.api.ScreenSettings +import org.obd.graphs.renderer.api.SurfaceRendererType + +internal class GaugeScreenBehavior( + context: Context, + metricsCollector: MetricsCollector, + settings: Map, + fps: Fps, +) : ScreenBehavior(context, metricsCollector, settings[SurfaceRendererType.GAUGE]!!, fps, SurfaceRendererType.GAUGE) { + + override fun queryStrategyType(): QueryStrategyType = + if (dataLoggerSettings.instance().adapter.individualQueryStrategyEnabled) { + QueryStrategyType.INDIVIDUAL_QUERY + } else { + QueryStrategyType.SHARED_QUERY + } + + override fun getSelectedPIDs(): Set = rendererSettings(settings).selectedPIDs + + override fun getSortOrder(): Map? = rendererSettings(settings).getPIDsSortOrder() + + override fun getCurrentVirtualScreen(): Int = rendererSettings(settings).getVirtualScreen() + + override fun setCurrentVirtualScreen( + id: Int, + ) { + rendererSettings(settings).setVirtualScreen(id) + } + + private fun rendererSettings(settings: ScreenSettings) = settings.getGaugeRendererSetting() +} diff --git a/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/GiuliaScreenBehavior.kt b/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/GiuliaScreenBehavior.kt new file mode 100644 index 000000000..b10665a65 --- /dev/null +++ b/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/GiuliaScreenBehavior.kt @@ -0,0 +1,51 @@ + /** + * Copyright 2019-2026, Tomasz Żebrowski + * + *

Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You 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 org.obd.graphs.aa.screen.behaviour + +import android.content.Context +import org.obd.graphs.bl.collector.MetricsCollector +import org.obd.graphs.bl.datalogger.dataLoggerSettings +import org.obd.graphs.bl.query.QueryStrategyType +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.renderer.api.ScreenSettings +import org.obd.graphs.renderer.api.SurfaceRendererType + +internal class GiuliaScreenBehavior( + context: Context, + metricsCollector: MetricsCollector, + settings: Map, + fps: Fps, +) : ScreenBehavior(context, metricsCollector, settings[SurfaceRendererType.GIULIA]!!, fps, SurfaceRendererType.GIULIA) { + override fun queryStrategyType(): QueryStrategyType = + if (dataLoggerSettings.instance().adapter.individualQueryStrategyEnabled) { + QueryStrategyType.INDIVIDUAL_QUERY + } else { + QueryStrategyType.SHARED_QUERY + } + + override fun getSelectedPIDs(): Set = rendererSettings(settings).selectedPIDs + + override fun getSortOrder(): Map? = rendererSettings(settings).getPIDsSortOrder() + + override fun getCurrentVirtualScreen(): Int = rendererSettings(settings).getVirtualScreen() + + override fun setCurrentVirtualScreen(id: Int) { + rendererSettings(settings).setVirtualScreen(id) + } + + private fun rendererSettings(settings: ScreenSettings) = settings.getGiuliaRendererSetting() +} diff --git a/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/PerformanceScreenBehavior.kt b/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/PerformanceScreenBehavior.kt new file mode 100644 index 000000000..3af8e8848 --- /dev/null +++ b/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/PerformanceScreenBehavior.kt @@ -0,0 +1,39 @@ + /** + * Copyright 2019-2026, Tomasz Żebrowski + * + *

Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You 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 org.obd.graphs.aa.screen.behaviour + +import android.content.Context +import org.obd.graphs.bl.collector.MetricsCollector +import org.obd.graphs.bl.query.QueryStrategyType +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.renderer.api.ScreenSettings +import org.obd.graphs.renderer.api.SurfaceRendererType + +internal class PerformanceScreenBehavior( + context: Context, + metricsCollector: MetricsCollector, + settings: Map, + fps: Fps, +) : ScreenBehavior(context, metricsCollector, settings[SurfaceRendererType.PERFORMANCE]!!, fps, SurfaceRendererType.PERFORMANCE) { + override fun queryStrategyType() = QueryStrategyType.PERFORMANCE_QUERY + + override fun applyFilters(metricsCollector: MetricsCollector) { + query.setStrategy(queryStrategyType()) + metricsCollector.applyFilter(enabled = query.getIDs()) + query.update(metricsCollector.getMetrics().map { p -> p.source.command.pid.id }.toSet()) + } +} diff --git a/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/ScreenBehavior.kt b/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/ScreenBehavior.kt new file mode 100644 index 000000000..af063e8cb --- /dev/null +++ b/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/ScreenBehavior.kt @@ -0,0 +1,84 @@ + /** + * Copyright 2019-2026, Tomasz Żebrowski + * + *

Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You 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 org.obd.graphs.aa.screen.behaviour + +import android.content.Context +import org.obd.graphs.bl.collector.MetricsCollector +import org.obd.graphs.bl.query.Query +import org.obd.graphs.bl.query.QueryStrategyType +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.renderer.api.ScreenSettings +import org.obd.graphs.renderer.api.SurfaceRenderer +import org.obd.graphs.renderer.api.SurfaceRendererType + +abstract class ScreenBehavior( + context: Context, + metricsCollector: MetricsCollector, + protected val settings: ScreenSettings, + fps: Fps, + surfaceRendererType: SurfaceRendererType, +) { + private val surfaceRenderer = + SurfaceRenderer.allocate( + context, + settings, + metricsCollector, + fps, + surfaceRendererType = surfaceRendererType, + ) + + protected val query = Query.instance() + + fun getQuery(metricsCollector: MetricsCollector): Query { + applyFilters(metricsCollector) + return query + } + + fun getSurfaceRenderer(): SurfaceRenderer = surfaceRenderer + + abstract fun queryStrategyType(): QueryStrategyType + + protected open fun getSelectedPIDs(): Set = emptySet() + + protected open fun getSortOrder(): Map? = null + + open fun getCurrentVirtualScreen(): Int = -1 + + open fun setCurrentVirtualScreen(id: Int) { + } + + protected open fun applyFilters(metricsCollector: MetricsCollector) { + query.setStrategy(queryStrategyType()) + val selectedPIDs = getSelectedPIDs() + val sortOrder = getSortOrder() + + when (queryStrategyType()) { + QueryStrategyType.INDIVIDUAL_QUERY -> { + metricsCollector.applyFilter(enabled = selectedPIDs, order = sortOrder) + query.update(metricsCollector.getMetrics().map { p -> p.source.command.pid.id }.toSet()) + } + + QueryStrategyType.SHARED_QUERY -> { + val queryIds = query.getIDs() + val intersection = selectedPIDs.filter { queryIds.contains(it) }.toSet() + metricsCollector.applyFilter(enabled = intersection, order = sortOrder) + } + + else -> {} + } + } +} diff --git a/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/ScreenBehaviorController.kt b/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/ScreenBehaviorController.kt new file mode 100644 index 000000000..88b0ef07e --- /dev/null +++ b/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/ScreenBehaviorController.kt @@ -0,0 +1,61 @@ + /** + * Copyright 2019-2026, Tomasz Żebrowski + * + *

Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You 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 org.obd.graphs.aa.screen.behaviour + +import android.content.Context +import org.obd.graphs.bl.collector.MetricsCollector +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.renderer.api.Identity +import org.obd.graphs.renderer.api.ScreenSettings +import org.obd.graphs.renderer.api.SurfaceRendererType + +class ScreenBehaviorController( + context: Context, + metricsCollector: MetricsCollector, + settings: Map, + fps: Fps, +) { + private val gaugeScreenBehavior: GaugeScreenBehavior = GaugeScreenBehavior(context, metricsCollector, settings, fps) + + private val tripInfoScreenBehavior: TripInfoScreenBehavior = TripInfoScreenBehavior(context, metricsCollector, settings, fps) + + private val giuliaScreenBehavior: GiuliaScreenBehavior = GiuliaScreenBehavior(context, metricsCollector, settings, fps) + + private val dragRacingScreenBehavior: DragRacingScreenBehavior = + DragRacingScreenBehavior(context, metricsCollector, settings, fps) + + private val performanceScreenBehavior: PerformanceScreenBehavior = + PerformanceScreenBehavior(context, metricsCollector, settings, fps) + + fun recycle() { + gaugeScreenBehavior.getSurfaceRenderer().recycle() + tripInfoScreenBehavior.getSurfaceRenderer().recycle() + giuliaScreenBehavior.getSurfaceRenderer().recycle() + dragRacingScreenBehavior.getSurfaceRenderer().recycle() + performanceScreenBehavior.getSurfaceRenderer().recycle() + } + + fun getScreenBehavior(screenId: Identity): ScreenBehavior? = + when (screenId) { + SurfaceRendererType.GIULIA -> giuliaScreenBehavior + SurfaceRendererType.GAUGE -> gaugeScreenBehavior + SurfaceRendererType.DRAG_RACING -> dragRacingScreenBehavior + SurfaceRendererType.PERFORMANCE -> performanceScreenBehavior + SurfaceRendererType.TRIP_INFO -> tripInfoScreenBehavior + else -> null + } +} diff --git a/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/TripInfoScreenBehavior.kt b/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/TripInfoScreenBehavior.kt new file mode 100644 index 000000000..bf70f4209 --- /dev/null +++ b/automotive/src/main/java/org/obd/graphs/aa/screen/behaviour/TripInfoScreenBehavior.kt @@ -0,0 +1,39 @@ + /** + * Copyright 2019-2026, Tomasz Żebrowski + * + *

Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You 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 org.obd.graphs.aa.screen.behaviour + +import android.content.Context +import org.obd.graphs.bl.collector.MetricsCollector +import org.obd.graphs.bl.query.QueryStrategyType +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.renderer.api.ScreenSettings +import org.obd.graphs.renderer.api.SurfaceRendererType + +internal class TripInfoScreenBehavior( + context: Context, + metricsCollector: MetricsCollector, + settings: Map, + fps: Fps, +) : ScreenBehavior(context, metricsCollector, settings[SurfaceRendererType.TRIP_INFO]!!, fps, SurfaceRendererType.TRIP_INFO) { + override fun queryStrategyType() = QueryStrategyType.TRIP_INFO_QUERY + + override fun applyFilters(metricsCollector: MetricsCollector) { + query.setStrategy(queryStrategyType()) + metricsCollector.applyFilter(enabled = query.getIDs()) + query.update(metricsCollector.getMetrics().map { p -> p.source.command.pid.id }.toSet()) + } +} diff --git a/automotive/src/main/java/org/obd/graphs/aa/screen/iot/IotTemplateCarScreen.kt b/automotive/src/main/java/org/obd/graphs/aa/screen/iot/IotTemplateCarScreen.kt index 60c85bcff..f067bbaaa 100644 --- a/automotive/src/main/java/org/obd/graphs/aa/screen/iot/IotTemplateCarScreen.kt +++ b/automotive/src/main/java/org/obd/graphs/aa/screen/iot/IotTemplateCarScreen.kt @@ -67,7 +67,7 @@ import org.obd.graphs.bl.query.QueryStrategyType import org.obd.graphs.format import org.obd.graphs.profile.PROFILE_CHANGED_EVENT import org.obd.graphs.registerReceiver -import org.obd.graphs.renderer.DynamicSelectorMode +import org.obd.graphs.renderer.api.DynamicSelectorMode private const val LOG_TAG = "IotTemplateCarScreen" @@ -207,7 +207,7 @@ internal class IotTemplateCarScreen( } } - override fun actionStartDataLogging() { + override fun startDataLogging() { if (dataLoggerSettings.instance().adapter.individualQueryStrategyEnabled) { query.setStrategy(QueryStrategyType.INDIVIDUAL_QUERY) query.update(metricsCollector.getMetrics().map { p -> p.source.command.pid.id }.toSet()) @@ -319,6 +319,5 @@ internal class IotTemplateCarScreen( } DataLoggerRepository.observe(dynamicSelectorModeEventBroadcaster) submitRenderingTask() - registerConnectionStateReceiver() } } diff --git a/automotive/src/main/java/org/obd/graphs/aa/screen/nav/AvailableFeaturesScreen.kt b/automotive/src/main/java/org/obd/graphs/aa/screen/nav/AvailableFeaturesScreen.kt index 01f04afbc..26e99afff 100644 --- a/automotive/src/main/java/org/obd/graphs/aa/screen/nav/AvailableFeaturesScreen.kt +++ b/automotive/src/main/java/org/obd/graphs/aa/screen/nav/AvailableFeaturesScreen.kt @@ -24,7 +24,7 @@ import androidx.core.graphics.drawable.IconCompat import org.obd.graphs.aa.R import org.obd.graphs.aa.screen.createAction import org.obd.graphs.bl.datalogger.* -import org.obd.graphs.renderer.Identity +import org.obd.graphs.renderer.api.Identity private const val LOG_TAG = "AvailableFeaturesScreen" diff --git a/automotive/src/main/java/org/obd/graphs/aa/screen/nav/NavTemplateCarScreen.kt b/automotive/src/main/java/org/obd/graphs/aa/screen/nav/NavTemplateCarScreen.kt index 9bd1e6c4f..3d1895a31 100644 --- a/automotive/src/main/java/org/obd/graphs/aa/screen/nav/NavTemplateCarScreen.kt +++ b/automotive/src/main/java/org/obd/graphs/aa/screen/nav/NavTemplateCarScreen.kt @@ -23,31 +23,60 @@ import android.util.Log import androidx.activity.OnBackPressedCallback import androidx.car.app.CarContext import androidx.car.app.connection.CarConnection -import androidx.car.app.model.* +import androidx.car.app.model.Action +import androidx.car.app.model.Pane +import androidx.car.app.model.PaneTemplate +import androidx.car.app.model.Template import androidx.car.app.navigation.NavigationManager import androidx.car.app.navigation.NavigationManagerCallback import androidx.car.app.navigation.model.NavigationTemplate import androidx.car.app.navigation.model.RoutingInfo import androidx.lifecycle.LifecycleOwner -import org.obd.graphs.* +import org.obd.graphs.MAIN_ACTIVITY_EVENT_DESTROYED +import org.obd.graphs.MAIN_ACTIVITY_EVENT_PAUSE +import org.obd.graphs.SCREEN_REFRESH_EVENT import org.obd.graphs.aa.CarSettings -import org.obd.graphs.aa.screen.* +import org.obd.graphs.aa.screen.CarScreen +import org.obd.graphs.aa.screen.EVENT_DYNAMIC_SELECTOR_MODE_ECO +import org.obd.graphs.aa.screen.EVENT_DYNAMIC_SELECTOR_MODE_NORMAL +import org.obd.graphs.aa.screen.EVENT_DYNAMIC_SELECTOR_MODE_RACE +import org.obd.graphs.aa.screen.EVENT_DYNAMIC_SELECTOR_MODE_SPORT +import org.obd.graphs.aa.screen.dynamicSelectorModeEventBroadcaster +import org.obd.graphs.aa.screen.withDataLogger import org.obd.graphs.aa.toast import org.obd.graphs.bl.collector.MetricsCollector -import org.obd.graphs.bl.datalogger.* +import org.obd.graphs.bl.datalogger.DATA_LOGGER_ADAPTER_NOT_SET_EVENT +import org.obd.graphs.bl.datalogger.DATA_LOGGER_CONNECTED_EVENT +import org.obd.graphs.bl.datalogger.DATA_LOGGER_CONNECTING_EVENT +import org.obd.graphs.bl.datalogger.DATA_LOGGER_ERROR_CONNECT_EVENT +import org.obd.graphs.bl.datalogger.DATA_LOGGER_ERROR_EVENT +import org.obd.graphs.bl.datalogger.DATA_LOGGER_NO_NETWORK_EVENT +import org.obd.graphs.bl.datalogger.DATA_LOGGER_STOPPED_EVENT +import org.obd.graphs.bl.datalogger.DataLoggerRepository +import org.obd.graphs.bl.datalogger.WorkflowStatus +import org.obd.graphs.bl.datalogger.dataLoggerSettings import org.obd.graphs.bl.drag.dragRacingMetricsProcessor -import org.obd.graphs.bl.extra.* +import org.obd.graphs.bl.extra.EVENT_VEHICLE_STATUS_IGNITION_OFF +import org.obd.graphs.bl.extra.EVENT_VEHICLE_STATUS_IGNITION_ON +import org.obd.graphs.bl.extra.EVENT_VEHICLE_STATUS_VEHICLE_ACCELERATING +import org.obd.graphs.bl.extra.EVENT_VEHICLE_STATUS_VEHICLE_DECELERATING +import org.obd.graphs.bl.extra.EVENT_VEHICLE_STATUS_VEHICLE_IDLING +import org.obd.graphs.bl.extra.EVENT_VEHICLE_STATUS_VEHICLE_RUNNING +import org.obd.graphs.bl.extra.vehicleStatusMetricsProcessor import org.obd.graphs.bl.gps.gpsMetricsEmitter import org.obd.graphs.bl.trip.tripManager -import org.obd.graphs.renderer.DynamicSelectorMode -import org.obd.graphs.renderer.Fps -import org.obd.graphs.renderer.Identity import org.obd.graphs.commons.R +import org.obd.graphs.registerReceiver +import org.obd.graphs.renderer.api.DynamicSelectorMode +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.renderer.api.Identity const val SURFACE_DESTROYED_EVENT = "car.event.surface.destroyed" const val SURFACE_AREA_CHANGED_EVENT = "car.event.surface.area_changed" const val SURFACE_BROKEN_EVENT = "car.event.surface_broken.event" const val CHANGE_SCREEN_EVENT = "car.event.screen.change.event" +const val GOTO_LAST_VSITED_SCREEN_EVENT = "car.event.goto_screen.event" +const val START_DATA_LOGGING_EVENT = "car.event.start_data_logging.event" private const val LOG_TAG = "NavTemplateCarScreen" @@ -55,154 +84,165 @@ internal class NavTemplateCarScreen( carContext: CarContext, settings: CarSettings, metricsCollector: MetricsCollector, - fps: Fps + fps: Fps, ) : CarScreen(carContext, settings, metricsCollector, fps) { - private val surfaceRendererScreen = SurfaceRendererScreen(carContext, settings, metricsCollector, fps, parent = this) - private var broadcastReceiver = object : BroadcastReceiver() { - override fun onReceive(context: Context?, intent: Intent?) { - - if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) { - Log.v(LOG_TAG, "Received ${intent?.action} event") - } - - when (intent?.action) { - CHANGE_SCREEN_EVENT -> { - screenManager.popToRoot() + private var broadcastReceiver = + object : BroadcastReceiver() { + override fun onReceive( + context: Context?, + intent: Intent?, + ) { + if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) { + Log.v(LOG_TAG, "Received ${intent?.action} event") + } - screenManager.pushForResult(AvailableFeaturesScreen(carContext, availableFeatures())) { - Log.d(LOG_TAG, "Going to the new screen id=$it") - it?.let { - val newScreen:Identity = it as Identity + when (intent?.action) { + START_DATA_LOGGING_EVENT -> { + Log.i(LOG_TAG, "Auto connection enabled. Auto start data logging.....") + startDataLogging() + } - if (surfaceRendererScreen.isSurfaceRendererScreen(newScreen)) { - updateLastVisitedScreen(newScreen) - } + GOTO_LAST_VSITED_SCREEN_EVENT -> { + Log.i(LOG_TAG, "Loading last visited screen flag is enabled. Loading last visited screen....") + gotoScreen(settings.getLastVisitedScreen()) + } - gotoScreen(newScreen) - } - } - } + CHANGE_SCREEN_EVENT -> { + screenManager.popToRoot() - EVENT_DYNAMIC_SELECTOR_MODE_NORMAL -> settings.dynamicSelectorChangedEvent(DynamicSelectorMode.NORMAL) - EVENT_DYNAMIC_SELECTOR_MODE_RACE -> settings.dynamicSelectorChangedEvent(DynamicSelectorMode.RACE) - EVENT_DYNAMIC_SELECTOR_MODE_ECO -> settings.dynamicSelectorChangedEvent(DynamicSelectorMode.ECO) - EVENT_DYNAMIC_SELECTOR_MODE_SPORT -> settings.dynamicSelectorChangedEvent(DynamicSelectorMode.SPORT) - SCREEN_REFRESH_EVENT -> invalidate() + screenManager.pushForResult(AvailableFeaturesScreen(carContext, availableFeatures())) { + Log.d(LOG_TAG, "Going to the new screen id=$it") + it?.let { + val newScreen: Identity = it as Identity - SURFACE_BROKEN_EVENT -> { - Log.d(LOG_TAG, "Received event about ") - cancelRenderingTask() - carContext.finishCarApp() - } + if (surfaceRendererScreen.isSurfaceRendererScreen(newScreen)) { + updateLastVisitedScreen(newScreen) + } - MAIN_ACTIVITY_EVENT_DESTROYED -> { - Log.v(LOG_TAG, "Main activity has been destroyed.") - invalidate() - } + gotoScreen(newScreen) + } + } + } - MAIN_ACTIVITY_EVENT_PAUSE -> { - Log.v(LOG_TAG, "Main activity is going to the background.") - invalidate() - } + EVENT_DYNAMIC_SELECTOR_MODE_NORMAL -> settings.dynamicSelectorChangedEvent(DynamicSelectorMode.NORMAL) + EVENT_DYNAMIC_SELECTOR_MODE_RACE -> settings.dynamicSelectorChangedEvent(DynamicSelectorMode.RACE) + EVENT_DYNAMIC_SELECTOR_MODE_ECO -> settings.dynamicSelectorChangedEvent(DynamicSelectorMode.ECO) + EVENT_DYNAMIC_SELECTOR_MODE_SPORT -> settings.dynamicSelectorChangedEvent(DynamicSelectorMode.SPORT) + SCREEN_REFRESH_EVENT -> invalidate() - SURFACE_DESTROYED_EVENT -> cancelRenderingTask() + SURFACE_BROKEN_EVENT -> { + Log.d(LOG_TAG, "Received event about ") + cancelRenderingTask() + carContext.finishCarApp() + } - SURFACE_AREA_CHANGED_EVENT -> { - Log.v(LOG_TAG,"Surface area changed") - try { + MAIN_ACTIVITY_EVENT_DESTROYED -> { + Log.v(LOG_TAG, "Main activity has been destroyed.") invalidate() - submitRenderingTask() - }catch (e: Exception){ - Log.w(LOG_TAG,"Failed when received SURFACE_AREA_CHANGED_EVENT event",e) } - } - DATA_LOGGER_CONNECTING_EVENT -> { - surfaceRendererScreen.renderFrame() - try { - metricsCollector.reset() + MAIN_ACTIVITY_EVENT_PAUSE -> { + Log.v(LOG_TAG, "Main activity is going to the background.") invalidate() - } catch (e: Exception){ - Log.w(LOG_TAG,"Failed when received DATA_LOGGER_CONNECTING_EVENT event",e) } - } - DATA_LOGGER_NO_NETWORK_EVENT -> toast.show(carContext, R.string.main_activity_toast_connection_no_network) + SURFACE_DESTROYED_EVENT -> cancelRenderingTask() - DATA_LOGGER_ERROR_EVENT -> { - try { - invalidate() - toast.show(carContext, R.string.main_activity_toast_connection_error) - } catch (e: Exception){ - Log.w(LOG_TAG,"Failed when received DATA_LOGGER_ERROR_EVENT event",e) + SURFACE_AREA_CHANGED_EVENT -> { + Log.v(LOG_TAG, "Surface area changed") + try { + invalidate() + submitRenderingTask() + } catch (e: Exception) { + Log.w(LOG_TAG, "Failed when received SURFACE_AREA_CHANGED_EVENT event", e) + } } - } - DATA_LOGGER_STOPPED_EVENT -> { - - try { - cancelRenderingTask() - invalidate() + DATA_LOGGER_CONNECTING_EVENT -> { surfaceRendererScreen.renderFrame() - navigationManager().navigationEnded() - toast.show(carContext, R.string.main_activity_toast_connection_stopped) + try { + metricsCollector.reset() + invalidate() + } catch (e: Exception) { + Log.w(LOG_TAG, "Failed when received DATA_LOGGER_CONNECTING_EVENT event", e) + } + } + + DATA_LOGGER_NO_NETWORK_EVENT -> toast.show(carContext, R.string.main_activity_toast_connection_no_network) - } catch (e: Exception){ - Log.w(LOG_TAG,"Failed when received DATA_LOGGER_STOPPED_EVENT event",e) + DATA_LOGGER_ERROR_EVENT -> { + try { + invalidate() + toast.show(carContext, R.string.main_activity_toast_connection_error) + } catch (e: Exception) { + Log.w(LOG_TAG, "Failed when received DATA_LOGGER_ERROR_EVENT event", e) + } } - } - DATA_LOGGER_CONNECTED_EVENT -> { - try { - renderingThread.start() - fps.start() - navigationManager().navigationStarted() - toast.show(carContext, R.string.main_activity_toast_connection_established) - invalidate() + DATA_LOGGER_STOPPED_EVENT -> { + try { + cancelRenderingTask() + invalidate() + surfaceRendererScreen.renderFrame() + navigationManager().navigationEnded() + toast.show(carContext, R.string.main_activity_toast_connection_stopped) + } catch (e: Exception) { + Log.w(LOG_TAG, "Failed when received DATA_LOGGER_STOPPED_EVENT event", e) + } + } - }catch (e: Exception){ - Log.w(LOG_TAG,"Failed when received DATA_LOGGER_ERROR_CONNECT_EVENT event",e) + DATA_LOGGER_CONNECTED_EVENT -> { + try { + renderingThread.start() + fps.start() + navigationManager().navigationStarted() + toast.show(carContext, R.string.main_activity_toast_connection_established) + invalidate() + } catch (e: Exception) { + Log.w(LOG_TAG, "Failed when received DATA_LOGGER_ERROR_CONNECT_EVENT event", e) + } } - } - DATA_LOGGER_ERROR_CONNECT_EVENT -> { - try { - invalidate() - toast.show(carContext, R.string.main_activity_toast_connection_connect_error) - }catch (e: Exception){ - Log.w(LOG_TAG,"Failed when received DATA_LOGGER_ERROR_CONNECT_EVENT event",e) + DATA_LOGGER_ERROR_CONNECT_EVENT -> { + try { + invalidate() + toast.show(carContext, R.string.main_activity_toast_connection_connect_error) + } catch (e: Exception) { + Log.w(LOG_TAG, "Failed when received DATA_LOGGER_ERROR_CONNECT_EVENT event", e) + } } - } - DATA_LOGGER_ADAPTER_NOT_SET_EVENT -> { - try { - invalidate() - toast.show(carContext, R.string.main_activity_toast_adapter_is_not_selected) - }catch (e: Exception){ - Log.w(LOG_TAG,"Failed when received DATA_LOGGER_ADAPTER_NOT_SET_EVENT event",e) + DATA_LOGGER_ADAPTER_NOT_SET_EVENT -> { + try { + invalidate() + toast.show(carContext, R.string.main_activity_toast_adapter_is_not_selected) + } catch (e: Exception) { + Log.w(LOG_TAG, "Failed when received DATA_LOGGER_ADAPTER_NOT_SET_EVENT event", e) + } } - } - EVENT_VEHICLE_STATUS_IGNITION_OFF -> { - if (dataLoggerSettings.instance().vehicleStatusDisconnectWhenOff){ - Log.i(LOG_TAG,"Received vehicle status OFF event. Closing the session.") - withDataLogger { - stop() + EVENT_VEHICLE_STATUS_IGNITION_OFF -> { + if (dataLoggerSettings.instance().vehicleStatusDisconnectWhenOff) { + Log.i(LOG_TAG, "Received vehicle status OFF event. Closing the session.") + withDataLogger { + stop() + } } } } } - } - private inline fun availableFeatures(): MutableList = mutableListOf().apply { - addAll(surfaceRendererScreen.getFeatureDescription()) - addAll(RoutinesScreen(carContext, settings, metricsCollector, fps).getFeatureDescription()) + private inline fun availableFeatures(): MutableList = + mutableListOf().apply { + addAll(surfaceRendererScreen.getFeatureDescription()) + addAll(RoutinesScreen(carContext, settings, metricsCollector, fps).getFeatureDescription()) + } } - } - override fun gotoScreen(identity: Identity) { + fun gotoScreen(identity: Identity) { + Log.d(LOG_TAG, "Goto screen: $identity") if (surfaceRendererScreen.isSurfaceRendererScreen(identity)) { surfaceRendererScreen.switchSurfaceRenderer(identity) invalidate() @@ -249,11 +289,13 @@ internal class NavTemplateCarScreen( it.addAction(EVENT_VEHICLE_STATUS_VEHICLE_ACCELERATING) it.addAction(EVENT_VEHICLE_STATUS_VEHICLE_DECELERATING) it.addAction(EVENT_VEHICLE_STATUS_IGNITION_ON) + it.addAction(GOTO_LAST_VSITED_SCREEN_EVENT) + it.addAction(START_DATA_LOGGING_EVENT) } } - override fun actionStartDataLogging() { - surfaceRendererScreen.actionStartDataLogging() + override fun startDataLogging() { + surfaceRendererScreen.startDataLogging() } override fun onCarConfigurationChanged() { @@ -271,7 +313,7 @@ internal class NavTemplateCarScreen( super.onPause(owner) lifecycle.removeObserver(surfaceRendererScreen.getLifecycleObserver()) surfaceRendererScreen.onPause(owner) - } + } override fun onDestroy(owner: LifecycleOwner) { super.onDestroy(owner) @@ -283,31 +325,38 @@ internal class NavTemplateCarScreen( override fun renderAction() { surfaceRendererScreen.renderFrame() } - override fun onGetTemplate(): Template = try { - settings.initItemsSortOrder() - if (settings.isConnectionDialogEnabled() && DataLoggerRepository.status() == WorkflowStatus.Connecting) { - NavigationTemplate.Builder() - .setNavigationInfo(RoutingInfo.Builder().setLoading(true).build()) - .setActionStrip(getHorizontalActionStrip()) + override fun onGetTemplate(): Template = + try { + settings.initItemsSortOrder() + + if (settings.isConnectionDialogEnabled() && DataLoggerRepository.status() == WorkflowStatus.Connecting) { + NavigationTemplate + .Builder() + .setNavigationInfo(RoutingInfo.Builder().setLoading(true).build()) + .setActionStrip(getHorizontalActionStrip()) + .build() + } else { + surfaceRendererScreen.onGetTemplate() + } + } catch (e: Exception) { + Log.e(LOG_TAG, "Failed to build template", e) + PaneTemplate + .Builder(Pane.Builder().setLoading(true).build()) + .setHeaderAction(Action.BACK) + .setTitle(carContext.getString(org.obd.graphs.aa.R.string.pref_aa_car_error)) .build() - } else { - surfaceRendererScreen.onGetTemplate() } - } catch (e: Exception) { - Log.e(LOG_TAG, "Failed to build template", e) - PaneTemplate.Builder(Pane.Builder().setLoading(true).build()) - .setHeaderAction(Action.BACK) - .setTitle(carContext.getString(org.obd.graphs.aa.R.string.pref_aa_car_error)) - .build() - } init { - carContext.onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) { - override fun handleOnBackPressed() { - screenManager.pop() - } - }) + carContext.onBackPressedDispatcher.addCallback( + this, + object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + screenManager.pop() + } + }, + ) lifecycle.addObserver(this) @@ -330,7 +379,6 @@ internal class NavTemplateCarScreen( navigationManager().setNavigationManagerCallback( object : NavigationManagerCallback { override fun onStopNavigation() { - try { renderingThread.stop() surfaceRendererScreen.renderFrame() @@ -340,9 +388,8 @@ internal class NavTemplateCarScreen( Log.e(LOG_TAG, "Failed to stop DL threads", e) } } - }) - - registerConnectionStateReceiver() + }, + ) } private fun navigationManager() = carContext.getCarService(NavigationManager::class.java) diff --git a/automotive/src/main/java/org/obd/graphs/aa/screen/nav/RoutinesScreen.kt b/automotive/src/main/java/org/obd/graphs/aa/screen/nav/RoutinesScreen.kt index e4783db6a..5ed553e3e 100644 --- a/automotive/src/main/java/org/obd/graphs/aa/screen/nav/RoutinesScreen.kt +++ b/automotive/src/main/java/org/obd/graphs/aa/screen/nav/RoutinesScreen.kt @@ -59,8 +59,8 @@ import org.obd.graphs.bl.datalogger.WorkflowStatus import org.obd.graphs.bl.query.Query import org.obd.graphs.bl.query.QueryStrategyType import org.obd.graphs.registerReceiver -import org.obd.graphs.renderer.Fps -import org.obd.graphs.renderer.Identity +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.renderer.api.Identity import org.obd.metrics.pid.PIDsGroup import org.obd.metrics.pid.PidDefinition @@ -207,7 +207,7 @@ internal class RoutinesScreen( carContext.unregisterReceiver(broadcastReceiver) } - override fun actionStartDataLogging() { + override fun startDataLogging() { withDataLogger { start(query) } diff --git a/automotive/src/main/java/org/obd/graphs/aa/screen/nav/SurfaceRendererController.kt b/automotive/src/main/java/org/obd/graphs/aa/screen/nav/SurfaceRendererController.kt index 3556f130f..ac32edee1 100644 --- a/automotive/src/main/java/org/obd/graphs/aa/screen/nav/SurfaceRendererController.kt +++ b/automotive/src/main/java/org/obd/graphs/aa/screen/nav/SurfaceRendererController.kt @@ -29,125 +29,109 @@ import androidx.car.app.SurfaceContainer import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner import org.obd.graphs.aa.CarSettings -import org.obd.graphs.bl.collector.MetricsCollector -import org.obd.graphs.bl.query.Query -import org.obd.graphs.renderer.Fps -import org.obd.graphs.renderer.SurfaceRenderer -import org.obd.graphs.renderer.SurfaceRendererType +import org.obd.graphs.renderer.api.SurfaceRenderer import org.obd.graphs.sendBroadcastEvent -private const val LOG_KEY = "SurfaceController" - +private const val LOG_TAG = "SurfaceController" class SurfaceRendererController( private val carContext: CarContext, private val settings: CarSettings, - private val metricsCollector: MetricsCollector, - private val fps: Fps, - private val query: Query + surfaceRenderer: SurfaceRenderer?, ) : DefaultLifecycleObserver { - private var surfaceRenderer: SurfaceRenderer = - SurfaceRenderer.allocate(carContext, settings, metricsCollector, fps, SurfaceRendererType.GIULIA) + private var activeSurfaceRenderer: SurfaceRenderer? = surfaceRenderer private var surface: Surface? = null private var visibleArea: Rect? = null private var surfaceLocked = false - private val surfaceCallback: SurfaceCallback = object : SurfaceCallback { - - override fun onSurfaceAvailable(surfaceContainer: SurfaceContainer) { - synchronized(this@SurfaceRendererController) { - Log.i(LOG_KEY, "Surface is now available") - surface?.release() - surface = surfaceContainer.surface - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - val frameRate = settings.getSurfaceFrameRate() + 5f - Log.i(LOG_KEY, "Setting surface Frame Rate to=$frameRate") - surface?.setFrameRate(frameRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT) + private val surfaceCallback: SurfaceCallback = + object : SurfaceCallback { + override fun onSurfaceAvailable(surfaceContainer: SurfaceContainer) { + synchronized(this@SurfaceRendererController) { + Log.i(LOG_TAG, "Surface is now available") + surface?.release() + surface = surfaceContainer.surface + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + val frameRate = settings.getSurfaceFrameRate() + 5f + Log.i(LOG_TAG, "Setting surface Frame Rate to=$frameRate") + surface?.setFrameRate(frameRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT) + } } - surfaceRenderer.applyMetricsFilter(query) } - } - override fun onVisibleAreaChanged(visibleArea: Rect) { - synchronized(this@SurfaceRendererController) { - Log.i(LOG_KEY, "Surface visible area changed: w=${visibleArea.width()} h=${visibleArea.height()},l=${visibleArea.left}") - this@SurfaceRendererController.visibleArea = visibleArea + override fun onVisibleAreaChanged(visibleArea: Rect) { + synchronized(this@SurfaceRendererController) { + Log.i(LOG_TAG, "Surface visible area changed: w=${visibleArea.width()} h=${visibleArea.height()},l=${visibleArea.left}") + this@SurfaceRendererController.visibleArea = visibleArea - sendBroadcastEvent(SURFACE_AREA_CHANGED_EVENT) - renderFrame() + sendBroadcastEvent(SURFACE_AREA_CHANGED_EVENT) + renderFrame() + } } - } - override fun onStableAreaChanged(stableArea: Rect) { - synchronized(this@SurfaceRendererController) { - Log.i(LOG_KEY, "Surface stable area changed: w=${stableArea.width()} h=${stableArea.height()}") - sendBroadcastEvent(SURFACE_AREA_CHANGED_EVENT) - renderFrame() + override fun onStableAreaChanged(stableArea: Rect) { + synchronized(this@SurfaceRendererController) { + Log.i(LOG_TAG, "Surface stable area changed: w=${stableArea.width()} h=${stableArea.height()}") + sendBroadcastEvent(SURFACE_AREA_CHANGED_EVENT) + renderFrame() + } } - } - override fun onSurfaceDestroyed(surfaceContainer: SurfaceContainer) { - synchronized(this@SurfaceRendererController) { - Log.i(LOG_KEY, "Surface destroyed") - surface?.release() - surface = null - sendBroadcastEvent(SURFACE_DESTROYED_EVENT) + override fun onSurfaceDestroyed(surfaceContainer: SurfaceContainer) { + synchronized(this@SurfaceRendererController) { + Log.i(LOG_TAG, "Surface destroyed") + surface?.release() + surface = null + sendBroadcastEvent(SURFACE_DESTROYED_EVENT) + } } } - } override fun onCreate(owner: LifecycleOwner) { super.onCreate(owner) - Log.i(LOG_KEY, "SurfaceRenderer created") - surface?.release() - surface = null + Log.i(LOG_TAG, "SurfaceRenderer created") try { carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback) - } catch (e: androidx.car.app.HostException){ - Log.w(LOG_KEY, "Failed to set surface callback",e) + } catch (e: androidx.car.app.HostException) { + Log.w(LOG_TAG, "Failed to set surface callback", e) } } override fun onDestroy(owner: LifecycleOwner) { super.onDestroy(owner) - Log.d(LOG_KEY, "SurfaceRenderer destroyed (onDestroy) ") - surface?.release() - surface = null + Log.d(LOG_TAG, "SurfaceRenderer destroyed (onDestroy)") + synchronized(this) { + surface?.release() + surface = null + activeSurfaceRenderer = null + } } override fun onPause(owner: LifecycleOwner) { super.onPause(owner) - Log.d(LOG_KEY, "SurfaceRenderer destroyed (onPause)") - surface?.release() - surface = null + Log.d(LOG_TAG, "SurfaceRenderer paused (onPause)") } - - fun allocateSurfaceRenderer(surfaceRendererType: SurfaceRendererType) { - Log.i(LOG_KEY, "Allocating Surface renderer, type=$surfaceRendererType") - surfaceRenderer.recycle() - surfaceRenderer = - SurfaceRenderer.allocate(carContext, settings, metricsCollector, fps, surfaceRendererType = surfaceRendererType) - surfaceRenderer.applyMetricsFilter(query) - renderFrame() + fun updateSurfaceRenderer(surfaceRenderer: SurfaceRenderer?) { + activeSurfaceRenderer = surfaceRenderer } @MainThread fun renderFrame() { + synchronized(this) { surface?.let { var canvas: Canvas? = null if (it.isValid && !surfaceLocked) { try { canvas = it.lockHardwareCanvas() surfaceLocked = true - surfaceRenderer.onDraw( + activeSurfaceRenderer?.onDraw( canvas = canvas, - drawArea = visibleArea + drawArea = visibleArea, ) - } catch (e: Throwable) { - Log.e(LOG_KEY, "Exception was thrown during surface locking.", e) + Log.e(LOG_TAG, "Exception was thrown during surface locking.", e) surface = null sendBroadcastEvent(SURFACE_BROKEN_EVENT) } finally { @@ -156,7 +140,7 @@ class SurfaceRendererController( it.unlockCanvasAndPost(c) } } catch (e: Throwable) { - Log.e(LOG_KEY, "Exception was thrown during surface un-locking.", e) + Log.e(LOG_TAG, "Exception was thrown during surface un-locking.", e) sendBroadcastEvent(SURFACE_BROKEN_EVENT) } @@ -164,6 +148,6 @@ class SurfaceRendererController( } } } - + } } } diff --git a/automotive/src/main/java/org/obd/graphs/aa/screen/nav/SurfaceRendererScreen.kt b/automotive/src/main/java/org/obd/graphs/aa/screen/nav/SurfaceRendererScreen.kt index 21e0a30ba..4420acfec 100644 --- a/automotive/src/main/java/org/obd/graphs/aa/screen/nav/SurfaceRendererScreen.kt +++ b/automotive/src/main/java/org/obd/graphs/aa/screen/nav/SurfaceRendererScreen.kt @@ -37,18 +37,16 @@ import org.obd.graphs.aa.screen.GIULIA_VIRTUAL_SCREEN_1_SETTINGS_CHANGED import org.obd.graphs.aa.screen.GIULIA_VIRTUAL_SCREEN_2_SETTINGS_CHANGED import org.obd.graphs.aa.screen.GIULIA_VIRTUAL_SCREEN_3_SETTINGS_CHANGED import org.obd.graphs.aa.screen.GIULIA_VIRTUAL_SCREEN_4_SETTINGS_CHANGED +import org.obd.graphs.aa.screen.behaviour.ScreenBehaviorController import org.obd.graphs.aa.screen.createAction import org.obd.graphs.aa.screen.withDataLogger import org.obd.graphs.bl.collector.MetricsCollector -import org.obd.graphs.bl.datalogger.dataLoggerSettings -import org.obd.graphs.bl.query.Query -import org.obd.graphs.bl.query.QueryStrategyType import org.obd.graphs.profile.PROFILE_CHANGED_EVENT import org.obd.graphs.profile.PROFILE_RESET_EVENT import org.obd.graphs.registerReceiver -import org.obd.graphs.renderer.Fps -import org.obd.graphs.renderer.Identity -import org.obd.graphs.renderer.SurfaceRendererType +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.renderer.api.Identity +import org.obd.graphs.renderer.api.SurfaceRendererType const val GAUGE_VIRTUAL_SCREEN_1_SETTINGS_CHANGED = "pref.aa.gauge.pids.profile_1.event.changed" const val GAUGE_VIRTUAL_SCREEN_2_SETTINGS_CHANGED = "pref.aa.gauge.pids.profile_2.event.changed" @@ -61,8 +59,7 @@ private const val AA_PERFORMANCE_PID_SELECTION_CHANGED_EVENT = "pref.aa.performa private enum class DefaultScreen( private val code: Int, ) : Identity { - NOT_SET(-1), - ; + NOT_SET(-1); override fun id(): Int = this.code } @@ -77,10 +74,21 @@ internal class SurfaceRendererScreen( fps: Fps, private val parent: NavTemplateCarScreen, ) : CarScreen(carContext, settings, metricsCollector, fps) { - private val query = Query.instance() + + private val screenBehaviorController = ScreenBehaviorController( + carContext, + metricsCollector, + mapOf(SurfaceRendererType.GAUGE to settings, + SurfaceRendererType.GIULIA to settings, + SurfaceRendererType.TRIP_INFO to settings, + SurfaceRendererType.DRAG_RACING to settings, + SurfaceRendererType.PERFORMANCE to settings), + fps) private var screenId: Identity = SurfaceRendererType.GIULIA - private val surfaceRendererController = SurfaceRendererController(carContext, settings, metricsCollector, fps, query) + private val surfaceRendererController = SurfaceRendererController(carContext, + settings, + screenBehaviorController.getScreenBehavior(SurfaceRendererType.GIULIA)?.getSurfaceRenderer()) private var broadcastReceiver = object : BroadcastReceiver() { @@ -89,24 +97,16 @@ internal class SurfaceRendererScreen( intent: Intent?, ) { when (intent?.action) { - AA_VIRTUAL_SCREEN_RENDERER_CHANGED_EVENT -> surfaceRendererController.allocateSurfaceRenderer(getSurfaceRendererType()) - - SCREEN_REFRESH_EVENT -> { - updateQuery() - renderFrame() - } - - AA_TRIP_INFO_PID_SELECTION_CHANGED_EVENT, AA_PERFORMANCE_PID_SELECTION_CHANGED_EVENT -> { - updateQuery() - renderFrame() + AA_VIRTUAL_SCREEN_RENDERER_CHANGED_EVENT -> { + switchSurfaceRenderer(getSurfaceRendererType()) } - AA_HIGH_FREQ_PID_SELECTION_CHANGED_EVENT -> { - updateQuery() - renderFrame() - } - - LOW_FREQ_PID_SELECTION_CHANGED_EVENT -> { + SCREEN_REFRESH_EVENT, + AA_TRIP_INFO_PID_SELECTION_CHANGED_EVENT, + AA_PERFORMANCE_PID_SELECTION_CHANGED_EVENT, + AA_HIGH_FREQ_PID_SELECTION_CHANGED_EVENT, + LOW_FREQ_PID_SELECTION_CHANGED_EVENT, + -> { updateQuery() renderFrame() } @@ -119,22 +119,25 @@ internal class SurfaceRendererScreen( PROFILE_CHANGED_EVENT -> { settings.handleProfileChanged() updateQuery() - surfaceRendererController.allocateSurfaceRenderer(getSurfaceRendererType()) + switchSurfaceRenderer(getSurfaceRendererType()) renderFrame() } PROFILE_RESET_EVENT -> { updateQuery() - surfaceRendererController.allocateSurfaceRenderer(getSurfaceRendererType()) + switchSurfaceRenderer(getSurfaceRendererType()) renderFrame() } } } private fun handlePIDsListChangedEvent(id: Int) { - if (getCurrentVirtualScreen() == id) { - setCurrentVirtualScreen(id) + val behavior = screenBehaviorController.getScreenBehavior(screenId) ?: return + + if (behavior.getCurrentVirtualScreen() == id) { + behavior.setCurrentVirtualScreen(id = id) } + updateQuery() renderFrame() } @@ -146,107 +149,47 @@ internal class SurfaceRendererScreen( screenId = DefaultScreen.NOT_SET } - fun switchSurfaceRenderer(screenId: Identity) { - this.screenId = screenId - Log.i(LOG_TAG, "Switch to new surface renderer screen: ${this.screenId} and updating query...") - - when (this.screenId as SurfaceRendererType) { - SurfaceRendererType.GIULIA, SurfaceRendererType.GAUGE -> { - metricsCollector.applyFilter(enabled = getSelectedPIDs()) + fun switchSurfaceRenderer(newScreenId: Identity) { + this.screenId = newScreenId + if (newScreenId is SurfaceRendererType) { - if (dataLoggerSettings.instance().adapter.individualQueryStrategyEnabled) { - query.setStrategy(QueryStrategyType.INDIVIDUAL_QUERY) - query.update(metricsCollector.getMetrics().map { p -> p.source.command.pid.id }.toSet()) - } else { - query.setStrategy(QueryStrategyType.SHARED_QUERY) - } - withDataLogger { - updateQuery(query = query) - } - surfaceRendererController.allocateSurfaceRenderer(screenId as SurfaceRendererType) + if (Log.isLoggable(LOG_TAG,Log.DEBUG)) { + Log.d(LOG_TAG, "[${Thread.currentThread()}] Switch to new surface renderer screen: ${this.screenId} and updating query...") } - SurfaceRendererType.DRAG_RACING -> { - withDataLogger { - updateQuery( - query = - query.apply { - setStrategy(QueryStrategyType.DRAG_RACING_QUERY) - }, - ) - } + val surfaceRenderer = screenBehaviorController.getScreenBehavior(newScreenId)?.getSurfaceRenderer() + surfaceRendererController.updateSurfaceRenderer(surfaceRenderer) - surfaceRendererController.allocateSurfaceRenderer(surfaceRendererType = SurfaceRendererType.DRAG_RACING) - } + val behavior = screenBehaviorController.getScreenBehavior(newScreenId) ?: return + val query = behavior.getQuery(metricsCollector) - SurfaceRendererType.TRIP_INFO -> { - withDataLogger { - updateQuery( - query = - query.apply { - setStrategy(QueryStrategyType.TRIP_INFO_QUERY) - }, - ) - } - surfaceRendererController.allocateSurfaceRenderer(surfaceRendererType = SurfaceRendererType.TRIP_INFO) - } - - SurfaceRendererType.PERFORMANCE -> { - withDataLogger { - updateQuery( - query = - query.apply { - setStrategy(QueryStrategyType.PERFORMANCE_QUERY) - }, - ) - } - surfaceRendererController.allocateSurfaceRenderer(surfaceRendererType = SurfaceRendererType.PERFORMANCE) + withDataLogger { + updateQuery(query = query) } } - renderFrame() } - override fun actionStartDataLogging() { - when (screenId) { - SurfaceRendererType.GIULIA, SurfaceRendererType.GAUGE -> { - if (dataLoggerSettings.instance().adapter.individualQueryStrategyEnabled) { - query.setStrategy(QueryStrategyType.INDIVIDUAL_QUERY) - query.update(metricsCollector.getMetrics().map { p -> p.source.command.pid.id }.toSet()) - } else { - query.setStrategy(QueryStrategyType.SHARED_QUERY) - } - withDataLogger { - start(query) - } - } + private fun updateQuery() { - SurfaceRendererType.DRAG_RACING -> - withDataLogger { - start( - query.apply { - setStrategy(QueryStrategyType.DRAG_RACING_QUERY) - }, - ) - } + val behavior = screenBehaviorController.getScreenBehavior(screenId) ?: return + val query = behavior.getQuery(metricsCollector) - SurfaceRendererType.TRIP_INFO -> - withDataLogger { - start( - query.apply { - setStrategy(QueryStrategyType.TRIP_INFO_QUERY) - }, - ) - } + if (Log.isLoggable(LOG_TAG,Log.DEBUG)) { + Log.d(LOG_TAG, "[${Thread.currentThread()}] Update Query ($screenId): ${query.getIDs()}") + } - SurfaceRendererType.PERFORMANCE -> - withDataLogger { - start( - query.apply { - setStrategy(QueryStrategyType.PERFORMANCE_QUERY) - }, - ) - } + withDataLogger { + updateQuery(query) + } + } + + override fun startDataLogging() { + val behavior = screenBehaviorController.getScreenBehavior(screenId) ?: return + val query = behavior.getQuery(metricsCollector) + + withDataLogger { + start(query) } } @@ -338,89 +281,9 @@ internal class SurfaceRendererScreen( override fun onDestroy(owner: LifecycleOwner) { carContext.unregisterReceiver(broadcastReceiver) + screenBehaviorController.recycle() } - private fun updateQuery() { - if (isSurfaceRendererScreen(screenId)) { - val selectedPIDs = getSelectedPIDs() - - metricsCollector.applyFilter(enabled = selectedPIDs) - - if (screenId == SurfaceRendererType.DRAG_RACING) { - Log.i(LOG_TAG, "Updating query for DRAG_RACING_SCREEN_ID screen") - - query.setStrategy(QueryStrategyType.DRAG_RACING_QUERY) - metricsCollector.applyFilter(enabled = query.getIDs()) - Log.i(LOG_TAG, "User selection PIDs=${query.getIDs()}") - withDataLogger { - updateQuery(query) - } - } else if (screenId == SurfaceRendererType.TRIP_INFO) { - Log.i(LOG_TAG, "Updating query for TRIP_INFO_SCREEN_ID screen") - - query.setStrategy(QueryStrategyType.TRIP_INFO_QUERY) - metricsCollector.applyFilter(enabled = query.getIDs()) - Log.i(LOG_TAG, "User selection PIDs=${query.getIDs()}") - withDataLogger { - updateQuery(query) - } - } else if (screenId == SurfaceRendererType.PERFORMANCE) { - Log.i(LOG_TAG, "Updating query for DYNAMIC_SCREEN_ID screen") - - query.setStrategy(QueryStrategyType.PERFORMANCE_QUERY) - metricsCollector.applyFilter(enabled = query.getIDs()) - Log.i(LOG_TAG, "User selection PIDs=${query.getIDs()}") - withDataLogger { - updateQuery(query) - } - } else if (dataLoggerSettings.instance().adapter.individualQueryStrategyEnabled) { - Log.i(LOG_TAG, "Updating query for individualQueryStrategyEnabled") - - metricsCollector.applyFilter(enabled = selectedPIDs, order = sortOrder()) - - query.setStrategy(QueryStrategyType.INDIVIDUAL_QUERY) - query.update(metricsCollector.getMetrics().map { p -> p.source.command.pid.id }.toSet()) - Log.i(LOG_TAG, "User selection PIDs=$selectedPIDs") - withDataLogger { - updateQuery(query) - } - } else { - Log.i(LOG_TAG, "Updating query to SHARED_QUERY strategy") - - query.setStrategy(QueryStrategyType.SHARED_QUERY) - val query = query.getIDs() - val intersection = selectedPIDs.filter { query.contains(it) }.toSet() - - Log.i(LOG_TAG, "Query=$query,user selection=$selectedPIDs, intersection=$intersection") - - metricsCollector.applyFilter(enabled = intersection, order = sortOrder()) - } - } else { - Log.i(LOG_TAG, "Do not update the query. It's not surface renderer screen.") - } - } - - private fun setCurrentVirtualScreen(id: Int) = - when (screenId) { - SurfaceRendererType.GIULIA -> settings.getGiuliaRendererSetting().setVirtualScreen(id) - SurfaceRendererType.GAUGE -> settings.getGaugeRendererSetting().setVirtualScreen(id) - else -> {} - } - - private fun getCurrentVirtualScreen() = - when (screenId) { - SurfaceRendererType.GIULIA -> settings.getGiuliaRendererSetting().getVirtualScreen() - SurfaceRendererType.GAUGE -> settings.getGaugeRendererSetting().getVirtualScreen() - else -> -1 - } - - private fun getSelectedPIDs(): Set = - if (screenId == SurfaceRendererType.GIULIA) { - settings.getGiuliaRendererSetting().selectedPIDs - } else { - settings.getGaugeRendererSetting().selectedPIDs - } - private fun getVerticalActionStrip(): ActionStrip? { var added = false var builder = ActionStrip.Builder() @@ -433,9 +296,10 @@ internal class SurfaceRendererScreen( ).forEach { (k, v) -> if (settings.isVirtualScreenEnabled(k)) { added = true + val behavior = screenBehaviorController.getScreenBehavior(screenId) val color = - if (getCurrentVirtualScreen() == k) { + if (behavior?.getCurrentVirtualScreen() == k) { CarColor.GREEN } else { mapColor(settings.getColorTheme().actionsBtnVirtualScreensColor) @@ -445,7 +309,7 @@ internal class SurfaceRendererScreen( builder.addAction( createAction(carContext, v, color) { parent.invalidate() - setCurrentVirtualScreen(k) + behavior?.setCurrentVirtualScreen(id = k) updateQuery() renderFrame() }, @@ -462,11 +326,4 @@ internal class SurfaceRendererScreen( private fun getSurfaceRendererType(): SurfaceRendererType = if (screenId is SurfaceRendererType) screenId as SurfaceRendererType else SurfaceRendererType.GIULIA - - private fun sortOrder(): Map? = - if (this.screenId == SurfaceRendererType.GIULIA) { - settings.getGiuliaRendererSetting().getPIDsSortOrder() - } else { - settings.getGaugeRendererSetting().getPIDsSortOrder() - } } diff --git a/datalogger/src/main/java/org/obd/graphs/bl/collector/InMemoryCarMetricsCollector.kt b/datalogger/src/main/java/org/obd/graphs/bl/collector/InMemoryCarMetricsCollector.kt index 04713c7b1..e6486ca88 100644 --- a/datalogger/src/main/java/org/obd/graphs/bl/collector/InMemoryCarMetricsCollector.kt +++ b/datalogger/src/main/java/org/obd/graphs/bl/collector/InMemoryCarMetricsCollector.kt @@ -20,111 +20,116 @@ import android.util.Log import org.obd.graphs.bl.datalogger.DataLoggerRepository import org.obd.graphs.bl.datalogger.Pid import org.obd.metrics.api.model.ObdMetric -import java.util.* -import kotlin.Comparator +import java.util.concurrent.ConcurrentHashMap -private const val LOG_KEY = "InMemoryCollector" +private const val LOG_TAG = "InMemoryCollector" internal class InMemoryCarMetricsCollector : MetricsCollector { + private val metrics = ConcurrentHashMap() + + @Volatile + private var visibleMetrics: List = emptyList() - private var metrics: SortedMap = TreeMap() private val metricBuilder = MetricsBuilder() - override fun getMetrics(enabled: Boolean): List = metrics.values.filter { it.enabled == enabled } + override fun getMetrics(enabled: Boolean): List = if (enabled) visibleMetrics else metrics.values.filter { !it.enabled } override fun reset() { - metrics.forEach { (_, v) -> - v.inLowerAlertRisedHist = false - v.inUpperAlertRisedHist = false + metrics.values.forEach { + it.inLowerAlertRisedHist = false + it.inUpperAlertRisedHist = false } } - override fun getMetric(id: Pid, enabled: Boolean): Metric? = - if (metrics.containsKey(id.id) && metrics[id.id]!!.enabled) { - metrics[id.id] - } else { - null - } + override fun getMetric( + id: Pid, + enabled: Boolean, + ): Metric? { + val metric = metrics[id.id] + return if (metric != null && metric.enabled == enabled) metric else null + } - override fun applyFilter(enabled: Set, order: Map?) { - Log.i(LOG_KEY, "Updating visible PIDs=$enabled with order=$order") + @Synchronized + override fun applyFilter( + enabled: Set, + order: Map?, + ) { + Log.i(LOG_TAG, "Updating visible PIDs=$enabled with order=$order") - if (metrics.isEmpty() || !metrics.keys.containsAll(enabled)) { + val missingPids = enabled.filter { !metrics.containsKey(it) } - if (Log.isLoggable(LOG_KEY, Log.DEBUG)) { - Log.d(LOG_KEY, "Rebuilding metrics configuration for: $enabled != ${metrics.keys}") + if (missingPids.isNotEmpty()) { + if (Log.isLoggable(LOG_TAG, Log.DEBUG)) { + Log.d(LOG_TAG, "Rebuilding metrics configuration for missing PIDs: $missingPids") } - metricBuilder.buildFor(enabled).forEach { - val key = it.pid.id - - if (metrics.keys.indexOf(key) ==-1) { - Log.i(LOG_KEY, "Adding PID($key = ${it.pid.description}) to metrics map.") - metrics[key] = it - } - } - } else { - if (Log.isLoggable(LOG_KEY, Log.DEBUG)) { - Log.d(LOG_KEY, "Its okay. All PIDs are available. Metrics ${metrics.keys} contains $enabled") + metricBuilder.buildFor(missingPids.toSet()).forEach { + Log.i(LOG_TAG, "Adding PID(${it.pid.id} = ${it.pid.description}) to metrics map.") + metrics[it.pid.id] = it } } - if (order != null && order.isNotEmpty()) { - metrics = metrics.toSortedMap(comparator(order)) - } - metrics.forEach { (k, v) -> v.enabled = enabled.contains(k) } - } - - override fun append(input: ObdMetric?, forceAppend: Boolean) { - input?.let { metric -> - val key = metric.command.pid.id + val comparator = + Comparator { m1, m2 -> + if (order != null) { + val order1 = order[m1.pid.id] ?: Int.MAX_VALUE + val order2 = order[m2.pid.id] ?: Int.MAX_VALUE - if (forceAppend && !metrics.containsKey(key)) { - metrics[key] = metricBuilder.buildFor(metric) - Log.i(LOG_KEY, "Adding PID($key = ${metric.command.pid.description}) to metrics map.") + if (order1 != Int.MAX_VALUE || order2 != Int.MAX_VALUE) { + return@Comparator order1.compareTo(order2) + } + } + m1.pid.id.compareTo(m2.pid.id) } - metrics[metric.command.pid.id]?.let { - it.source = metric + visibleMetrics = + metrics.values + .filter { it.enabled } + .sortedWith(comparator) - it.value = metric.value - val hist = DataLoggerRepository.findHistogramFor(metric) - val rate = DataLoggerRepository.findRateFor(metric) + Log.d(LOG_TAG, "[${Thread.currentThread().id}] Updating visible PIDs: ${visibleMetrics.map { it.pid.id }}") + } - if (metric.isLowerAlert) { - it.inLowerAlertRisedHist = metric.isLowerAlert - } + override fun append( + input: ObdMetric?, + forceAppend: Boolean, + ) { + if (input == null) return - if (metric.isUpperAlert) { - it.inUpperAlertRisedHist = metric.isUpperAlert - } + val key = input.command.pid.id - rate.ifPresent { r -> - it.rate = r.value - } + // Fast O(1) lookup + if (forceAppend && !metrics.containsKey(key)) { + metrics[key] = metricBuilder.buildFor(input) + Log.i(LOG_TAG, "Adding PID($key = ${input.command.pid.description}) to metrics map.") + } - hist.mean?.let { mean -> - it.mean = mean - } + // Update the metric properties in place + metrics[key]?.let { metric -> + metric.source = input + metric.value = input.value - hist.max.let { max -> - it.max = max - } + if (input.isLowerAlert) { + metric.inLowerAlertRisedHist = true + } - hist.min.let { min -> - it.min = min - } + if (input.isUpperAlert) { + metric.inUpperAlertRisedHist = true } - } - } - private fun comparator(order: Map): Comparator = Comparator { m1, m2 -> - if (order.containsKey(m1) && order.containsKey(m2)) { - order[m1]!!.compareTo(order[m2]!!) - } else { - m1.compareTo(m2) + + DataLoggerRepository.findRateFor(input).ifPresent { r -> + metric.rate = r.value + } + + val hist = DataLoggerRepository.findHistogramFor(input) + hist.mean?.let { mean -> + metric.mean = mean + } + metric.max = hist.max + metric.min = hist.min } } } diff --git a/datalogger/src/main/java/org/obd/graphs/bl/query/QueryStrategyOrchestrator.kt b/datalogger/src/main/java/org/obd/graphs/bl/query/QueryStrategyOrchestrator.kt index 3c61178cd..bfa2b4233 100644 --- a/datalogger/src/main/java/org/obd/graphs/bl/query/QueryStrategyOrchestrator.kt +++ b/datalogger/src/main/java/org/obd/graphs/bl/query/QueryStrategyOrchestrator.kt @@ -23,7 +23,7 @@ import org.obd.graphs.preferences.Prefs import org.obd.graphs.preferences.getLongSet import org.obd.graphs.runAsync -private const val LOG_KEY = "QueryOrchestrator" +private const val LOG_TAG = "QueryOrchestrator" internal class QueryStrategyOrchestrator : java.io.Serializable, @@ -47,14 +47,13 @@ internal class QueryStrategyOrchestrator : override fun getIDs(): MutableSet { val pids = strategies[strategy]?.getPIDs() ?: mutableSetOf() - // decorate with Vehicle Status PID if (dataLoggerSettings.instance().vehicleStatusPanelEnabled || dataLoggerSettings.instance().vehicleStatusDisconnectWhenOff ) { pids.add(Pid.VEHICLE_STATUS_PID_ID.id) } - if (Log.isLoggable(LOG_KEY, Log.DEBUG)) { - Log.d(LOG_KEY, "Gets PIDs '$pids' for current strategy $strategy") + if (Log.isLoggable(LOG_TAG, Log.DEBUG)) { + Log.d(LOG_TAG, "${Thread.currentThread().id}, ${hashCode()}] Gets PIDs '$pids' for current strategy $strategy") } return pids } @@ -62,12 +61,13 @@ internal class QueryStrategyOrchestrator : override fun getStrategy(): QueryStrategyType = strategy override fun setStrategy(queryStrategyType: QueryStrategyType): Query { - Log.d(LOG_KEY, "Sets new strategy $queryStrategyType") + Log.d(LOG_TAG, "${Thread.currentThread().id}, ${hashCode()}] Sets new strategy $queryStrategyType") this.strategy = queryStrategyType return this } override fun update(newPIDs: Set): Query { + Log.d(LOG_TAG, "[${Thread.currentThread().id}, ${hashCode()}] updateQuery $strategy: $newPIDs") strategies[strategy]?.update(newPIDs) return this } @@ -78,16 +78,16 @@ internal class QueryStrategyOrchestrator : val intersection = selection.filter { query.contains(it) }.toSet() Log.i( - LOG_KEY, - "Individual query enabled:${isIndividualQuerySelected()}, " + + LOG_TAG, + "${Thread.currentThread().id}, ${hashCode()}] Individual query enabled:${isIndividualQuerySelected()}, " + " key:$filter, query=$query,selection=$selection, intersection=$intersection", ) return if (isIndividualQuerySelected()) { - Log.i(LOG_KEY, "Returning selection=$selection") + Log.i(LOG_TAG, "Returning selection=$selection") selection } else { - Log.i(LOG_KEY, "Returning intersection=$intersection") + Log.i(LOG_TAG, "Returning intersection=$intersection") intersection } } diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/AbstractDrawer.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/AbstractDrawer.kt index 2583efa02..0c893399a 100644 --- a/screen_renderer/src/main/java/org/obd/graphs/renderer/AbstractDrawer.kt +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/AbstractDrawer.kt @@ -17,6 +17,7 @@ package org.obd.graphs.renderer import android.content.Context +import android.content.res.Configuration import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Canvas @@ -34,6 +35,9 @@ import org.obd.graphs.commons.R import org.obd.graphs.format import org.obd.graphs.mapRange import org.obd.graphs.profile.profile +import org.obd.graphs.renderer.api.ColorTheme +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.renderer.api.ScreenSettings import kotlin.math.max private const val STATUS_KEY_FONT_SIZE = 12f @@ -47,7 +51,7 @@ const val MARGIN_END = 30 @Suppress("NOTHING_TO_INLINE") internal abstract class AbstractDrawer( - context: Context, + protected val context: Context, protected val settings: ScreenSettings, ) { private val statusPaint = Paint() @@ -59,6 +63,10 @@ internal abstract class AbstractDrawer( strokeCap = Paint.Cap.BUTT } + + + protected fun isLandscape() = context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE + protected val alertingLegendPaint = Paint(Paint.ANTI_ALIAS_FLAG) protected val valuePaint = Paint(Paint.ANTI_ALIAS_FLAG) protected val titlePaint = Paint(Paint.ANTI_ALIAS_FLAG) diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/CoreSurfaceRenderer.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/AbstractSurfaceRenderer.kt similarity index 89% rename from screen_renderer/src/main/java/org/obd/graphs/renderer/CoreSurfaceRenderer.kt rename to screen_renderer/src/main/java/org/obd/graphs/renderer/AbstractSurfaceRenderer.kt index f757a599a..a6538fded 100644 --- a/screen_renderer/src/main/java/org/obd/graphs/renderer/CoreSurfaceRenderer.kt +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/AbstractSurfaceRenderer.kt @@ -16,13 +16,15 @@ */ package org.obd.graphs.renderer +import android.content.Context import android.graphics.Canvas import android.graphics.Color import android.graphics.Rect +import org.obd.graphs.renderer.api.SurfaceRenderer -const val MARGIN_TOP = 8 + const val MARGIN_TOP = 8 -internal abstract class CoreSurfaceRenderer : SurfaceRenderer { +internal abstract class AbstractSurfaceRenderer(protected val context: Context) : SurfaceRenderer { protected var scrollOffset: Float = 0f protected val scrollBarWidth = 6f diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/Fps.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/api/Fps.kt similarity index 97% rename from screen_renderer/src/main/java/org/obd/graphs/renderer/Fps.kt rename to screen_renderer/src/main/java/org/obd/graphs/renderer/api/Fps.kt index b92827132..b86c815a4 100644 --- a/screen_renderer/src/main/java/org/obd/graphs/renderer/Fps.kt +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/api/Fps.kt @@ -14,7 +14,7 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.obd.graphs.renderer +package org.obd.graphs.renderer.api import org.obd.graphs.round import java.util.* diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/api/Identity.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/api/Identity.kt new file mode 100644 index 000000000..7040613af --- /dev/null +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/api/Identity.kt @@ -0,0 +1,21 @@ + /** + * Copyright 2019-2026, Tomasz Żebrowski + * + *

Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You 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 org.obd.graphs.renderer.api + +interface Identity { + fun id(): Int +} diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/ScreenSettings.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/api/ScreenSettings.kt similarity index 95% rename from screen_renderer/src/main/java/org/obd/graphs/renderer/ScreenSettings.kt rename to screen_renderer/src/main/java/org/obd/graphs/renderer/api/ScreenSettings.kt index be2e604c0..b11ffa0e1 100644 --- a/screen_renderer/src/main/java/org/obd/graphs/renderer/ScreenSettings.kt +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/api/ScreenSettings.kt @@ -14,10 +14,9 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.obd.graphs.renderer +package org.obd.graphs.renderer.api import android.graphics.Color -import org.obd.graphs.getContext import org.obd.graphs.ui.common.COLOR_CARDINAL import org.obd.graphs.ui.common.COLOR_DYNAMIC_SELECTOR_SPORT import org.obd.graphs.ui.common.COLOR_RAINBOW_INDIGO @@ -128,10 +127,6 @@ interface ScreenSettings { fun isScaleEnabled(): Boolean = true - fun getHeightPixels(): Int = getContext()!!.resources.displayMetrics.heightPixels - - fun getWidthPixels(): Int = getContext()!!.resources.displayMetrics.widthPixels - fun isProgressGradientEnabled(): Boolean = false fun getBackgroundColor(): Int = Color.BLACK diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/SurfaceRenderer.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/api/SurfaceRenderer.kt similarity index 82% rename from screen_renderer/src/main/java/org/obd/graphs/renderer/SurfaceRenderer.kt rename to screen_renderer/src/main/java/org/obd/graphs/renderer/api/SurfaceRenderer.kt index 6f3c7158e..6a0e0fc49 100644 --- a/screen_renderer/src/main/java/org/obd/graphs/renderer/SurfaceRenderer.kt +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/api/SurfaceRenderer.kt @@ -14,13 +14,12 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.obd.graphs.renderer +package org.obd.graphs.renderer.api import android.content.Context import android.graphics.Canvas import android.graphics.Rect import org.obd.graphs.bl.collector.MetricsCollector -import org.obd.graphs.bl.query.Query import org.obd.graphs.renderer.drag.DragRacingSurfaceRenderer import org.obd.graphs.renderer.performance.PerformanceSurfaceRenderer import org.obd.graphs.renderer.gauge.GaugeSurfaceRenderer @@ -28,26 +27,7 @@ import org.obd.graphs.renderer.giulia.GiuliaSurfaceRenderer import org.obd.graphs.renderer.trip.TripInfoSurfaceRenderer -interface Identity { - fun id(): Int -} - -enum class SurfaceRendererType(private val code: Int) : Identity { - GIULIA(0), - GAUGE(4), - DRAG_RACING(1), - TRIP_INFO(3), - PERFORMANCE(5); - - override fun id(): Int = this.code - - companion object { - fun fromInt(value: Int) = SurfaceRendererType.values().first { it.code == value } - } -} - -interface SurfaceRenderer { - fun applyMetricsFilter(query: Query) + interface SurfaceRenderer { fun onDraw(canvas: Canvas, drawArea: Rect?) fun recycle() fun updateScrollOffset(scrollOffset: Float) diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/api/SurfaceRendererType.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/api/SurfaceRendererType.kt new file mode 100644 index 000000000..5faa3f525 --- /dev/null +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/api/SurfaceRendererType.kt @@ -0,0 +1,34 @@ + /** + * Copyright 2019-2026, Tomasz Żebrowski + * + *

Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You 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 org.obd.graphs.renderer.api + +enum class SurfaceRendererType( + private val code: Int, +) : Identity { + GIULIA(0), + GAUGE(4), + DRAG_RACING(1), + TRIP_INFO(3), + PERFORMANCE(5), + ; + + override fun id(): Int = this.code + + companion object { + fun fromInt(value: Int) = SurfaceRendererType.values().first { it.code == value } + } +} diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/break_boosting/BreakBoostingDrawer.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/break_boosting/BreakBoostingDrawer.kt index e0410dc8c..6e9088303 100644 --- a/screen_renderer/src/main/java/org/obd/graphs/renderer/break_boosting/BreakBoostingDrawer.kt +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/break_boosting/BreakBoostingDrawer.kt @@ -17,18 +17,16 @@ package org.obd.graphs.renderer.break_boosting import android.content.Context -import android.content.res.Configuration import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Canvas import android.graphics.Rect import org.obd.graphs.bl.collector.Metric import org.obd.graphs.bl.drag.DragRacingService -import org.obd.graphs.getContext import org.obd.graphs.renderer.AbstractDrawer -import org.obd.graphs.renderer.BreakBoostingSettings -import org.obd.graphs.renderer.GaugeProgressBarType -import org.obd.graphs.renderer.ScreenSettings +import org.obd.graphs.renderer.api.BreakBoostingSettings +import org.obd.graphs.renderer.api.GaugeProgressBarType +import org.obd.graphs.renderer.api.ScreenSettings import org.obd.graphs.renderer.gauge.DrawerSettings import org.obd.graphs.renderer.gauge.GaugeDrawer @@ -56,7 +54,7 @@ internal class BreakBoostingDrawer(context: Context, settings: ScreenSettings) : drawGaugesBreakBoosting(area, canvas, pTop - 30, gas = gas, torque = torque) } - fun isBreakBoosting(breakBoostingSettings: BreakBoostingSettings, gas: Metric?,torque: Metric?) = + fun isBreakBoosting(breakBoostingSettings: BreakBoostingSettings, gas: Metric?, torque: Metric?) = breakBoostingSettings.viewEnabled && DragRacingService.registry.getResult().readyToRace && settings.getDragRacingScreenSettings().displayMetricsEnabled && @@ -102,9 +100,6 @@ internal class BreakBoostingDrawer(context: Context, settings: ScreenSettings) : } } - - private fun isLandscape() = getContext()!!.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE - private fun drawGauge( metric: Metric?, canvas: Canvas, diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/drag/DragRacingDrawer.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/drag/DragRacingDrawer.kt index b706c7cc4..06f2b154a 100644 --- a/screen_renderer/src/main/java/org/obd/graphs/renderer/drag/DragRacingDrawer.kt +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/drag/DragRacingDrawer.kt @@ -17,7 +17,6 @@ package org.obd.graphs.renderer.drag import android.content.Context -import android.content.res.Configuration import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Canvas @@ -30,11 +29,10 @@ import org.obd.graphs.bl.drag.DragRacingEntry import org.obd.graphs.bl.drag.DragRacingResults import org.obd.graphs.bl.drag.DragRacingService import org.obd.graphs.bl.drag.VALUE_NOT_SET -import org.obd.graphs.getContext import org.obd.graphs.mapRange import org.obd.graphs.renderer.AbstractDrawer -import org.obd.graphs.renderer.GaugeProgressBarType -import org.obd.graphs.renderer.ScreenSettings +import org.obd.graphs.renderer.api.GaugeProgressBarType +import org.obd.graphs.renderer.api.ScreenSettings import org.obd.graphs.renderer.break_boosting.BreakBoostingDrawer import org.obd.graphs.renderer.gauge.DrawerSettings import org.obd.graphs.renderer.gauge.GaugeDrawer @@ -372,8 +370,6 @@ internal class DragRacingDrawer( } } - private fun isLandscape() = getContext()!!.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE - private fun drawGauge( drawer: GaugeDrawer, metric: Metric?, diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/drag/DragRacingSurfaceRenderer.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/drag/DragRacingSurfaceRenderer.kt index 15ce349aa..33b81d471 100644 --- a/screen_renderer/src/main/java/org/obd/graphs/renderer/drag/DragRacingSurfaceRenderer.kt +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/drag/DragRacingSurfaceRenderer.kt @@ -20,20 +20,15 @@ import android.content.Context import android.graphics.Canvas import android.graphics.Color import android.graphics.Rect -import android.util.Log import org.obd.graphs.bl.collector.Metric import org.obd.graphs.bl.collector.MetricsCollector import org.obd.graphs.bl.datalogger.Pid import org.obd.graphs.bl.datalogger.dataLoggerSettings import org.obd.graphs.bl.drag.DragRacingService -import org.obd.graphs.bl.query.Query -import org.obd.graphs.bl.query.QueryStrategyType -import org.obd.graphs.renderer.CoreSurfaceRenderer -import org.obd.graphs.renderer.Fps +import org.obd.graphs.renderer.AbstractSurfaceRenderer +import org.obd.graphs.renderer.api.Fps import org.obd.graphs.renderer.MARGIN_TOP -import org.obd.graphs.renderer.ScreenSettings - -private const val LOG_TAG = "DragRacingSurfaceRenderer" +import org.obd.graphs.renderer.api.ScreenSettings internal data class DragRaceDetails( var ambientTemp: Metric? = null, @@ -49,15 +44,10 @@ internal class DragRacingSurfaceRenderer( private val settings: ScreenSettings, private val metricsCollector: MetricsCollector, private val fps: Fps, -) : CoreSurfaceRenderer() { +) : AbstractSurfaceRenderer(context) { private val dragRaceDetails = DragRaceDetails() private val dragRacingDrawer = DragRacingDrawer(context, settings) - override fun applyMetricsFilter(query: Query) { - metricsCollector.applyFilter( - enabled = query.getIDs(), - ) - } override fun onDraw( canvas: Canvas, @@ -126,8 +116,4 @@ internal class DragRacingSurfaceRenderer( dragRacingDrawer.recycle() } - init { - Log.i(LOG_TAG, "Init Drag Racing Surface Renderer") - applyMetricsFilter(Query.instance(QueryStrategyType.DRAG_RACING_QUERY)) - } } diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/gauge/GaugeDrawer.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/gauge/GaugeDrawer.kt index 061d638a5..9758a9a81 100644 --- a/screen_renderer/src/main/java/org/obd/graphs/renderer/gauge/GaugeDrawer.kt +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/gauge/GaugeDrawer.kt @@ -32,12 +32,11 @@ import android.graphics.Typeface import org.obd.graphs.bl.collector.Metric import org.obd.graphs.commons.R import org.obd.graphs.format -import org.obd.graphs.getContext import org.obd.graphs.isNumber import org.obd.graphs.mapRange import org.obd.graphs.renderer.AbstractDrawer -import org.obd.graphs.renderer.GaugeProgressBarType -import org.obd.graphs.renderer.ScreenSettings +import org.obd.graphs.renderer.api.GaugeProgressBarType +import org.obd.graphs.renderer.api.ScreenSettings import org.obd.graphs.round import org.obd.graphs.toFloat import org.obd.graphs.ui.common.COLOR_WHITE @@ -284,7 +283,7 @@ internal class GaugeDrawer( ) backgroundGradientPaint.shader = gradient - val cornerRadius = 8f * getContext()!!.resources.displayMetrics.density + val cornerRadius = 8f * context.resources.displayMetrics.density canvas.drawRoundRect(destRect, cornerRadius, cornerRadius, backgroundGradientPaint) } @@ -835,7 +834,7 @@ internal class GaugeDrawer( ): Float = (area.width() * area.height()).mapRange( 8875f, - (settings.getHeightPixels() * settings.getWidthPixels()) * 0.9f, + (getHeightPixels() * getWidthPixels()) * 0.9f, targetMin, targetMax, ) @@ -863,4 +862,9 @@ internal class GaugeDrawer( } else { value.toString() } + + + private fun getHeightPixels(): Int = context.resources.displayMetrics.heightPixels + private fun getWidthPixels(): Int = context.resources.displayMetrics.widthPixels + } diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/gauge/GaugeSurfaceRenderer.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/gauge/GaugeSurfaceRenderer.kt index e4079894c..2b2399b8b 100644 --- a/screen_renderer/src/main/java/org/obd/graphs/renderer/gauge/GaugeSurfaceRenderer.kt +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/gauge/GaugeSurfaceRenderer.kt @@ -24,13 +24,10 @@ import android.graphics.Rect import android.graphics.RectF import org.obd.graphs.bl.collector.Metric import org.obd.graphs.bl.collector.MetricsCollector -import org.obd.graphs.bl.datalogger.dataLoggerSettings -import org.obd.graphs.bl.query.Query -import org.obd.graphs.getContext -import org.obd.graphs.renderer.CoreSurfaceRenderer -import org.obd.graphs.renderer.Fps +import org.obd.graphs.renderer.AbstractSurfaceRenderer +import org.obd.graphs.renderer.api.Fps import org.obd.graphs.renderer.MARGIN_TOP -import org.obd.graphs.renderer.ScreenSettings +import org.obd.graphs.renderer.api.ScreenSettings import kotlin.math.max import kotlin.math.min @@ -39,7 +36,22 @@ internal class GaugeSurfaceRenderer( private val settings: ScreenSettings, private val metricsCollector: MetricsCollector, private val fps: Fps, -) : CoreSurfaceRenderer() { +) : AbstractSurfaceRenderer(context) { + private var lastAreaWidth = 0 + private var lastAreaHeight = 0 + private var lastItemCount = 0 + + private var cachedColumns = 1 + private var cachedGaugeWidth = 0f + private var cachedRowHeight = 0f + private var cachedStartX = 0f + private var cachedContentHeight = 0f + private var cachedMaxScroll = 0f + + private val cachedBorderRects = mutableMapOf() + private val cachedCenteredLefts = mutableMapOf() + private val cachedCenteredTops = mutableMapOf() + private val gaugeDrawer = GaugeDrawer( settings = settings, @@ -59,16 +71,6 @@ internal class GaugeSurfaceRenderer( ), ) - override fun applyMetricsFilter(query: Query) { - val gaugeSettings = settings.getGaugeRendererSetting() - if (dataLoggerSettings.instance().adapter.individualQueryStrategyEnabled) { - metricsCollector.applyFilter(enabled = gaugeSettings.selectedPIDs, order = gaugeSettings.getPIDsSortOrder()) - } else { - val ids = query.getIDs() - val intersection = gaugeSettings.selectedPIDs.filter { ids.contains(it) }.toSet() - metricsCollector.applyFilter(enabled = intersection, order = gaugeSettings.getPIDsSortOrder()) - } - } override fun getTop(area: Rect): Float = if (settings.isStatusPanelEnabled()) { @@ -104,6 +106,9 @@ internal class GaugeSurfaceRenderer( override fun recycle() { gaugeDrawer.recycle() + cachedBorderRects.clear() + cachedCenteredTops.clear() + cachedCenteredLefts.clear() } private fun drawGrid( @@ -119,90 +124,46 @@ internal class GaugeSurfaceRenderer( if (count <= 0) return val isAA = settings.isAA() - val isLandscape = getContext()!!.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE - - val drawer = if (isAA) gaugeDrawer else mobileDrawer - val drawBorder = !isAA - val labelCenterYPadding = if (isAA && count <= 2) 22f else 20f - - val columns = columns(isAA, count) + val isLandscape = context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE - val cellWidth = area.width() / columns.toFloat() - val availableHeight = area.height().toFloat() - val itemMargin = 6f - - var gaugeWidth = gaugeWidth(isAA, cellWidth, count, isLandscape, columns, availableHeight, itemMargin) - val rowHeight = rowHeight(isAA, availableHeight, isLandscape, columns, gaugeWidth, itemMargin) - val startX = startX(area, isAA, count) + updateCacheIfNeeded(area, count, isAA, isLandscape, topOffset) - val totalRows = kotlin.math.ceil(count / columns.toDouble()).toInt() - val contentHeight = totalRows * rowHeight + scrollOffset = scrollOffset.coerceIn(0f, cachedMaxScroll) val viewportHeight = area.height().toFloat() - val maxScroll = max(0f, contentHeight - viewportHeight) - scrollOffset = if (count <= 1 || isAA) 0f else scrollOffset.coerceIn(0f, maxScroll) - val startRow = kotlin.math - .floor(scrollOffset / rowHeight) + .floor(scrollOffset / cachedRowHeight) .toInt() .coerceAtLeast(0) - val endRow = - kotlin.math - .floor((scrollOffset + viewportHeight - 1f) / rowHeight) - .toInt() - .coerceAtMost(totalRows - 1) + kotlin.math.floor((scrollOffset + viewportHeight - 1f) / cachedRowHeight).toInt().coerceAtMost( + kotlin.math.ceil(count / cachedColumns.toDouble()).toInt() - 1, + ) - val startIndex = startRow * columns - val endIndex = min(count - 1, (endRow * columns) + (columns - 1)) + val startIndex = startRow * cachedColumns + val endIndex = min(count - 1, (endRow * cachedColumns) + (cachedColumns - 1)) + + val drawer = if (isAA) gaugeDrawer else mobileDrawer + val drawBorder = !isAA + val labelCenterYPadding = if (isAA && count <= 2) 22f else 20f canvas.save() canvas.clipRect(area) canvas.translate(0f, -scrollOffset) - val displayScrollbar = drawScrollbar && contentHeight > viewportHeight - for (i in startIndex..endIndex) { val metric = metrics[i] - val row = i / columns - val col = i % columns - - val aaLeftPadding = if (isAA) col * (gaugeWidth - 10f) else 0f - val cellLeft = if (isAA) startX + aaLeftPadding else startX + (col * cellWidth) - - val aaTopOffset = if (isAA && row > 0) -8f else 0f - val cellTop = topOffset + (row * rowHeight) + aaTopOffset - - val currentCellWidth = if (columns == 1 && !isAA) area.width().toFloat() else cellWidth - - var centeredLeft = if (isAA) cellLeft else cellLeft + (currentCellWidth - gaugeWidth) / 2f - if (displayScrollbar){ - centeredLeft += scrollBarWidth - gaugeWidth -= scrollBarWidth/2 - } - val centeredTop = - if (!isAA && - count == 1 && - isLandscape - ) { - cellTop + (availableHeight - gaugeWidth) / 2f - } else if (isAA) { - cellTop - } else { - cellTop + itemMargin - } - val borderRect = RectF(centeredLeft, centeredTop, centeredLeft + gaugeWidth, centeredTop + gaugeWidth) drawer.drawGauge( canvas = canvas, - left = centeredLeft, - top = centeredTop, - width = gaugeWidth, + left = cachedCenteredLefts[i]!!, + top = cachedCenteredTops[i]!!, + width = cachedGaugeWidth, metric = metric, labelCenterYPadding = labelCenterYPadding, drawBorder = drawBorder, - borderArea = borderRect, + borderArea = cachedBorderRects[i]!!, drawModule = !isAA, drawMetricRate = drawMetricsRate, ) @@ -210,8 +171,8 @@ internal class GaugeSurfaceRenderer( canvas.restore() - if (displayScrollbar) { - drawScrollbar(contentHeight, viewportHeight, maxScroll, area, canvas) + if (drawScrollbar && cachedContentHeight > viewportHeight) { + drawScrollbar(cachedContentHeight, viewportHeight, cachedMaxScroll, area, canvas) } } @@ -316,4 +277,65 @@ internal class GaugeSurfaceRenderer( maxItems <= 4 -> 0.75f else -> 1.02f } + + private fun updateCacheIfNeeded( + area: Rect, + count: Int, + isAA: Boolean, + isLandscape: Boolean, + topOffset: Float, + ) { + if (lastAreaWidth == area.width() && lastAreaHeight == area.height() && lastItemCount == count) { + return + } + + lastAreaWidth = area.width() + lastAreaHeight = area.height() + lastItemCount = count + + cachedColumns = columns(isAA, count) + val cellWidth = area.width() / cachedColumns.toFloat() + val availableHeight = area.height().toFloat() + val itemMargin = 6f + + cachedGaugeWidth = gaugeWidth(isAA, cellWidth, count, isLandscape, cachedColumns, availableHeight, itemMargin) + cachedRowHeight = rowHeight(isAA, availableHeight, isLandscape, cachedColumns, cachedGaugeWidth, itemMargin) + cachedStartX = startX(area, isAA, count) + + val totalRows = kotlin.math.ceil(count / cachedColumns.toDouble()).toInt() + cachedContentHeight = topOffset + (totalRows * cachedRowHeight) + 20f + cachedMaxScroll = max(0f, cachedContentHeight - availableHeight) + + cachedBorderRects.clear() + cachedCenteredLefts.clear() + cachedCenteredTops.clear() + + for (i in 0 until count) { + val row = i / cachedColumns + val col = i % cachedColumns + + val aaLeftPadding = if (isAA) col * (cachedGaugeWidth - 10f) else 0f + val cellLeft = if (isAA) cachedStartX + aaLeftPadding else cachedStartX + (col * cellWidth) + val cellTop = topOffset + (row * cachedRowHeight) + + val currentCellWidth = if (cachedColumns == 1 && !isAA) area.width().toFloat() else cellWidth + + val centeredLeft = if (isAA) cellLeft else cellLeft + (currentCellWidth - cachedGaugeWidth) / 2f + val centeredTop = + if (!isAA && + count == 1 && + isLandscape + ) { + cellTop + (availableHeight - cachedGaugeWidth) / 2f + } else if (isAA) { + cellTop + } else { + cellTop + itemMargin + } + + cachedCenteredLefts[i] = centeredLeft + cachedCenteredTops[i] = centeredTop + cachedBorderRects[i] = RectF(centeredLeft, centeredTop, centeredLeft + cachedGaugeWidth, centeredTop + cachedGaugeWidth) + } + } } diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/giulia/GiuliaDrawer.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/giulia/GiuliaDrawer.kt index 5d562d54b..9061f1cd0 100644 --- a/screen_renderer/src/main/java/org/obd/graphs/renderer/giulia/GiuliaDrawer.kt +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/giulia/GiuliaDrawer.kt @@ -26,7 +26,7 @@ import org.obd.graphs.format import org.obd.graphs.isNumber import org.obd.graphs.mapRange import org.obd.graphs.renderer.AbstractDrawer -import org.obd.graphs.renderer.ScreenSettings +import org.obd.graphs.renderer.api.ScreenSettings import org.obd.graphs.toFloat private const val FOOTER_SIZE_RATIO = 1.3f diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/giulia/GiuliaSurfaceRenderer.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/giulia/GiuliaSurfaceRenderer.kt index 5722caedd..14f6319a3 100644 --- a/screen_renderer/src/main/java/org/obd/graphs/renderer/giulia/GiuliaSurfaceRenderer.kt +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/giulia/GiuliaSurfaceRenderer.kt @@ -23,13 +23,11 @@ import android.graphics.Rect import android.util.Log import org.obd.graphs.bl.collector.Metric import org.obd.graphs.bl.collector.MetricsCollector -import org.obd.graphs.bl.datalogger.dataLoggerSettings -import org.obd.graphs.bl.query.Query import org.obd.graphs.mapRange -import org.obd.graphs.renderer.CoreSurfaceRenderer -import org.obd.graphs.renderer.Fps +import org.obd.graphs.renderer.AbstractSurfaceRenderer import org.obd.graphs.renderer.MARGIN_TOP -import org.obd.graphs.renderer.ScreenSettings +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.renderer.api.ScreenSettings import kotlin.math.max import kotlin.math.min import kotlin.math.round @@ -46,21 +44,10 @@ internal class GiuliaSurfaceRenderer( context: Context, private val settings: ScreenSettings, private val metricsCollector: MetricsCollector, - private val fps: Fps -) : CoreSurfaceRenderer() { + private val fps: Fps, +) : AbstractSurfaceRenderer(context) { private val giuliaDrawer = GiuliaDrawer(context, settings) - override fun applyMetricsFilter(query: Query) { - val giuliaSettings = settings.getGiuliaRendererSetting() - if (dataLoggerSettings.instance().adapter.individualQueryStrategyEnabled) { - metricsCollector.applyFilter(enabled = giuliaSettings.selectedPIDs, order = giuliaSettings.getPIDsSortOrder()) - } else { - val ids = query.getIDs() - val intersection = giuliaSettings.selectedPIDs.filter { ids.contains(it) }.toSet() - metricsCollector.applyFilter(enabled = intersection, order = giuliaSettings.getPIDsSortOrder()) - } - } - override fun onDraw( canvas: Canvas, drawArea: Rect?, diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/performance/PerformanceDrawer.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/performance/PerformanceDrawer.kt index 62e8f01a6..3f823dca8 100644 --- a/screen_renderer/src/main/java/org/obd/graphs/renderer/performance/PerformanceDrawer.kt +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/performance/PerformanceDrawer.kt @@ -20,8 +20,8 @@ import android.content.Context import android.graphics.* import org.obd.graphs.bl.collector.Metric import org.obd.graphs.renderer.AbstractDrawer -import org.obd.graphs.renderer.GaugeProgressBarType -import org.obd.graphs.renderer.ScreenSettings +import org.obd.graphs.renderer.api.GaugeProgressBarType +import org.obd.graphs.renderer.api.ScreenSettings import org.obd.graphs.renderer.gauge.DrawerSettings import org.obd.graphs.renderer.gauge.GaugeDrawer import org.obd.graphs.renderer.trip.TripInfoDrawer diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/performance/PerformanceSurfaceRenderer.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/performance/PerformanceSurfaceRenderer.kt index 4942b8c01..7d81e1b59 100644 --- a/screen_renderer/src/main/java/org/obd/graphs/renderer/performance/PerformanceSurfaceRenderer.kt +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/performance/PerformanceSurfaceRenderer.kt @@ -20,37 +20,24 @@ import android.content.Context import android.graphics.Canvas import android.graphics.Color import android.graphics.Rect -import android.util.Log import org.obd.graphs.bl.collector.MetricsCollector import org.obd.graphs.bl.datalogger.Pid -import org.obd.graphs.bl.query.Query -import org.obd.graphs.bl.query.QueryStrategyType -import org.obd.graphs.renderer.CoreSurfaceRenderer -import org.obd.graphs.renderer.Fps +import org.obd.graphs.renderer.AbstractSurfaceRenderer import org.obd.graphs.renderer.MARGIN_TOP -import org.obd.graphs.renderer.ScreenSettings +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.renderer.api.ScreenSettings import org.obd.graphs.renderer.break_boosting.BreakBoostingDrawer -private const val LOG_TAG = "PerformanceSurfaceRenderer" - internal class PerformanceSurfaceRenderer( context: Context, private val settings: ScreenSettings, private val metricsCollector: MetricsCollector, private val fps: Fps, -) : CoreSurfaceRenderer() { +) : AbstractSurfaceRenderer(context) { private val performanceInfoDetails = PerformanceInfoDetails() private val performanceDrawer = PerformanceDrawer(context, settings) private val breakBoostingDrawer = BreakBoostingDrawer(context, settings) - override fun applyMetricsFilter(query: Query) { - Log.d(LOG_TAG, "Query strategy ${query.getStrategy()}, selected id's: ${query.getIDs()}") - - metricsCollector.applyFilter( - enabled = query.getIDs(), - ) - } - override fun onDraw( canvas: Canvas, drawArea: Rect?, @@ -117,9 +104,4 @@ internal class PerformanceSurfaceRenderer( override fun recycle() { performanceDrawer.recycle() } - - init { - Log.i(LOG_TAG, "Init Performance Surface renderer") - applyMetricsFilter(Query.instance(QueryStrategyType.PERFORMANCE_QUERY)) - } } diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/trip/TripInfoDrawer.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/trip/TripInfoDrawer.kt index 747af0b83..b6d13c6da 100644 --- a/screen_renderer/src/main/java/org/obd/graphs/renderer/trip/TripInfoDrawer.kt +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/trip/TripInfoDrawer.kt @@ -28,7 +28,7 @@ import org.obd.graphs.format import org.obd.graphs.mapRange import org.obd.graphs.renderer.AbstractDrawer import org.obd.graphs.renderer.MARGIN_END -import org.obd.graphs.renderer.ScreenSettings +import org.obd.graphs.renderer.api.ScreenSettings import org.obd.graphs.toFloat private const val CURRENT_MIN = 22f diff --git a/screen_renderer/src/main/java/org/obd/graphs/renderer/trip/TripInfoSurfaceRenderer.kt b/screen_renderer/src/main/java/org/obd/graphs/renderer/trip/TripInfoSurfaceRenderer.kt index ceaaa8ae9..3e83cda5f 100644 --- a/screen_renderer/src/main/java/org/obd/graphs/renderer/trip/TripInfoSurfaceRenderer.kt +++ b/screen_renderer/src/main/java/org/obd/graphs/renderer/trip/TripInfoSurfaceRenderer.kt @@ -20,36 +20,28 @@ import android.content.Context import android.graphics.Canvas import android.graphics.Color import android.graphics.Rect -import android.util.Log import org.obd.graphs.bl.collector.MetricsCollector import org.obd.graphs.bl.datalogger.Pid -import org.obd.graphs.bl.query.* -import org.obd.graphs.renderer.* - -private const val LOG_TAG = "TripInfoSurfaceRenderer" +import org.obd.graphs.renderer.AbstractSurfaceRenderer +import org.obd.graphs.renderer.MARGIN_TOP +import org.obd.graphs.renderer.api.Fps +import org.obd.graphs.renderer.api.ScreenSettings internal class TripInfoSurfaceRenderer( context: Context, private val settings: ScreenSettings, private val metricsCollector: MetricsCollector, private val fps: Fps, -) : CoreSurfaceRenderer() { - +) : AbstractSurfaceRenderer(context) { private val tripInfo = TripInfoDetails() private val tripInfoDrawer = TripInfoDrawer(context, settings) - override fun applyMetricsFilter(query: Query) { - Log.d(LOG_TAG,"Query strategy ${query.getStrategy()}, selected ids: ${query.getIDs()}") - - metricsCollector.applyFilter( - enabled = query.getIDs() - ) - } - override fun onDraw(canvas: Canvas, drawArea: Rect?) { - + override fun onDraw( + canvas: Canvas, + drawArea: Rect?, + ) { drawArea?.let { - tripInfoDrawer.drawBackground(canvas, it) val area = getArea(it, canvas) @@ -70,37 +62,32 @@ internal class TripInfoSurfaceRenderer( area = area, left = left, top = top, - tripInfo = tripInfo.apply { - airTemp = metricsCollector.getMetric(Pid.POST_IC_AIR_TEMP_PID_ID) - totalMisfires = metricsCollector.getMetric(Pid.TOTAL_MISFIRES_PID_ID) - ambientTemp = metricsCollector.getMetric(Pid.AMBIENT_TEMP_PID_ID) - atmPressure = metricsCollector.getMetric(Pid.ATM_PRESSURE_PID_ID) - fuellevel = metricsCollector.getMetric(Pid.FUEL_LEVEL_PID_ID) - fuelConsumption = metricsCollector.getMetric(Pid.FUEL_CONSUMPTION_PID_ID) - coolantTemp = metricsCollector.getMetric(Pid.COOLANT_TEMP_PID_ID) - exhaustTemp = metricsCollector.getMetric(Pid.EXHAUST_TEMP_PID_ID) - oilTemp = metricsCollector.getMetric(Pid.OIL_TEMP_PID_ID) - gearboxOilTemp = metricsCollector.getMetric(Pid.GEARBOX_OIL_TEMP_PID_ID) - oilLevel = metricsCollector.getMetric(Pid.OIL_LEVEL_PID_ID) - torque = metricsCollector.getMetric(Pid.ENGINE_TORQUE_PID_ID) - intakePressure = metricsCollector.getMetric(Pid.INTAKE_PRESSURE_PID_ID) - distance = metricsCollector.getMetric(Pid.DISTANCE_PID_ID) - ibs = metricsCollector.getMetric(Pid.IBS_PID_ID) - batteryVoltage = metricsCollector.getMetric(Pid.BATTERY_VOLTAGE_PID_ID) - oilPressure = metricsCollector.getMetric(Pid.OIL_PRESSURE_PID_ID) - oilDegradation = metricsCollector.getMetric(Pid.OIL_DEGRADATION_PID_ID) - } + tripInfo = + tripInfo.apply { + airTemp = metricsCollector.getMetric(Pid.POST_IC_AIR_TEMP_PID_ID) + totalMisfires = metricsCollector.getMetric(Pid.TOTAL_MISFIRES_PID_ID) + ambientTemp = metricsCollector.getMetric(Pid.AMBIENT_TEMP_PID_ID) + atmPressure = metricsCollector.getMetric(Pid.ATM_PRESSURE_PID_ID) + fuellevel = metricsCollector.getMetric(Pid.FUEL_LEVEL_PID_ID) + fuelConsumption = metricsCollector.getMetric(Pid.FUEL_CONSUMPTION_PID_ID) + coolantTemp = metricsCollector.getMetric(Pid.COOLANT_TEMP_PID_ID) + exhaustTemp = metricsCollector.getMetric(Pid.EXHAUST_TEMP_PID_ID) + oilTemp = metricsCollector.getMetric(Pid.OIL_TEMP_PID_ID) + gearboxOilTemp = metricsCollector.getMetric(Pid.GEARBOX_OIL_TEMP_PID_ID) + oilLevel = metricsCollector.getMetric(Pid.OIL_LEVEL_PID_ID) + torque = metricsCollector.getMetric(Pid.ENGINE_TORQUE_PID_ID) + intakePressure = metricsCollector.getMetric(Pid.INTAKE_PRESSURE_PID_ID) + distance = metricsCollector.getMetric(Pid.DISTANCE_PID_ID) + ibs = metricsCollector.getMetric(Pid.IBS_PID_ID) + batteryVoltage = metricsCollector.getMetric(Pid.BATTERY_VOLTAGE_PID_ID) + oilPressure = metricsCollector.getMetric(Pid.OIL_PRESSURE_PID_ID) + oilDegradation = metricsCollector.getMetric(Pid.OIL_DEGRADATION_PID_ID) + }, ) } } - override fun recycle() { tripInfoDrawer.recycle() } - - init { - Log.i(LOG_TAG,"Init Trip Info Surface renderer") - applyMetricsFilter(Query.instance(QueryStrategyType.TRIP_INFO_QUERY)) - } }