From 2e767b213b6a443aa1db1867a2af43e15564cbbc Mon Sep 17 00:00:00 2001 From: Walter Huf Date: Sun, 4 Aug 2024 17:43:17 -0700 Subject: [PATCH 1/3] Accept any J29 HMI that logs in with BMW cert --- app/src/main/java/me/hufman/androidautoidrive/CarProber.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/me/hufman/androidautoidrive/CarProber.kt b/app/src/main/java/me/hufman/androidautoidrive/CarProber.kt index 1413ab6bb..21060c380 100644 --- a/app/src/main/java/me/hufman/androidautoidrive/CarProber.kt +++ b/app/src/main/java/me/hufman/androidautoidrive/CarProber.kt @@ -158,6 +158,12 @@ class CarProber(val securityAccess: SecurityAccess, val settings: AppSettings, v success = true break } + if (hmiType?.startsWith("J29") == true && (brand == "bmw" || brand == "mini")) { + // the car has ENTWICKLER_MENUE active and ignores the brand restriction on the cert + setConnectedState(host, port, brand) + success = true + break + } if (brand == "j29") { setConnectedState(host, port, "j29") success = true From 1de5d9918f2374746c15d5d6c0c6ab5d52c584ff Mon Sep 17 00:00:00 2001 From: Walter Huf Date: Sun, 4 Aug 2024 22:20:15 -0700 Subject: [PATCH 2/3] Add support for Entwickler J29s --- .../androidautoidrive/MainScreenshotTest.kt | 46 +++++++++++++++++++ .../hufman/androidautoidrive/MockScenario.kt | 2 + .../androidautoidrive/CarInformation.kt | 34 ++++++++++---- .../hufman/androidautoidrive/MainService.kt | 1 + .../viewmodels/CarCapabilitiesViewModel.kt | 7 +-- .../phoneui/viewmodels/CarSummaryModel.kt | 1 + .../viewmodels/ConnectionStatusModel.kt | 8 +++- .../viewmodels/NavigationStatusModel.kt | 3 +- app/src/main/res/drawable/logo_toyota.xml | 18 ++++++++ .../res/layout/fragment_car_capabilities.xml | 6 ++- app/src/main/res/values/strings.xml | 3 +- .../phoneui/CarCapabilitiesModelTest.kt | 38 ++++++++++++++- .../phoneui/NavigationStatusModelTest.kt | 14 ++++++ 13 files changed, 163 insertions(+), 18 deletions(-) create mode 100644 app/src/main/res/drawable/logo_toyota.xml diff --git a/app/src/androidTest/java/me/hufman/androidautoidrive/MainScreenshotTest.kt b/app/src/androidTest/java/me/hufman/androidautoidrive/MainScreenshotTest.kt index 10253ea46..4ef2d0208 100644 --- a/app/src/androidTest/java/me/hufman/androidautoidrive/MainScreenshotTest.kt +++ b/app/src/androidTest/java/me/hufman/androidautoidrive/MainScreenshotTest.kt @@ -286,6 +286,7 @@ class MainScreenshotTest { @Test fun j29Connection() { whenever(mockScenario.connectionDebugging.isJ29Installed) doReturn true + whenever(mockScenario.carInfo.connectionBrand) doReturn "j29" whenever(mockScenario.carInfo.capabilities) doReturn mapOf( "hmi.type" to "J29 ID6L", "hmi.version" to "NBTevo_ID5_2111", @@ -326,4 +327,49 @@ class MainScreenshotTest { )) screenshot("navigation_j29") } + + @Test + fun j29EntwicklerConnection() { + whenever(mockScenario.connectionDebugging.isJ29Installed) doReturn true + whenever(mockScenario.carInfo.connectionBrand) doReturn "bmw" + whenever(mockScenario.carInfo.capabilities) doReturn mapOf( + "hmi.type" to "J29 ID6L", + "hmi.version" to "NBTevo_ID5_2111", + "navi" to "true", + "tts" to "true", + "vehicle.type" to "J29" + ) + whenever(mockScenario.navigationStatusModel.isConnected) doReturn true + whenever(mockScenario.navigationStatusModel.searchStatus) doReturnMutableContexted {""} + + // real viewmodels need to be updated for the above mocked data + updateViewModels() + + await().untilAsserted { onView(withId(R.id.drawer_layout)) + .perform(DrawerActions.open()) + .check(matches(isOpen())) } + onView(withId(R.id.nav_view)).perform(NavigationViewActions + .navigateTo( + R.id.nav_overview + )) + screenshot("home_j29_entwickler") + + await().untilAsserted { onView(withId(R.id.drawer_layout)) + .perform(DrawerActions.open()) + .check(matches(isOpen())) } + onView(withId(R.id.nav_view)).perform(NavigationViewActions + .navigateTo( + R.id.nav_connection + )) + screenshot("connection_j29_entwickler") + + await().untilAsserted { onView(withId(R.id.drawer_layout)) + .perform(DrawerActions.open()) + .check(matches(isOpen())) } + onView(withId(R.id.nav_view)).perform(NavigationViewActions + .navigateTo( + R.id.nav_navigation + )) + screenshot("navigation_j29_entwickler") + } } \ No newline at end of file diff --git a/app/src/androidTest/java/me/hufman/androidautoidrive/MockScenario.kt b/app/src/androidTest/java/me/hufman/androidautoidrive/MockScenario.kt index 56c606fb4..0ed89a426 100644 --- a/app/src/androidTest/java/me/hufman/androidautoidrive/MockScenario.kt +++ b/app/src/androidTest/java/me/hufman/androidautoidrive/MockScenario.kt @@ -41,6 +41,7 @@ class MockScenario(context: Context) { on {carBrand} doReturn "BMW" } val carInfo = mock { + on {connectionBrand} doReturn "bmw" on {capabilities} doReturn mapOf( "hmi.type" to "BMW ID5", "hmi.version" to "NBTevo_ID5_1903", @@ -51,6 +52,7 @@ class MockScenario(context: Context) { } val musicAppMode = mock { on {heuristicAudioContext()} doReturn true + on {shouldRequestAudioContext()} doReturn true on {shouldId5Playback()} doReturn true } val carSummaryViewModel = CarSummaryModel(carInfo, MutableLiveData(false)) diff --git a/app/src/main/java/me/hufman/androidautoidrive/CarInformation.kt b/app/src/main/java/me/hufman/androidautoidrive/CarInformation.kt index a73f528e8..f6259fbaa 100644 --- a/app/src/main/java/me/hufman/androidautoidrive/CarInformation.kt +++ b/app/src/main/java/me/hufman/androidautoidrive/CarInformation.kt @@ -37,6 +37,7 @@ open class CarInformation { val listeners: Map = _listeners var isConnected = false + var connectionBrand: String? = null var currentCapabilities: Map = emptyMap() var cachedCapabilities: Map = emptyMap() @@ -121,12 +122,17 @@ open class CarInformation { open val isConnected: Boolean get() = CarInformation.isConnected + open val connectionBrand: String? + get() = CarInformation.connectionBrand + open val capabilities: Map get() = if (currentCapabilities.isEmpty()) { cachedCapabilities } else { currentCapabilities } + val currentCapabilities: Map + get() = CarInformation.currentCapabilities open val cdsData: CDSData = CarInformation.cdsData open val cachedCdsData: CDSData = CarInformation.cachedCdsData @@ -142,11 +148,16 @@ open class CarInformationUpdater(val appSettings: MutableAppSettings): CarInform onCarCapabilities() } } + override var connectionBrand: String? + get() = super.connectionBrand + set(value) { + CarInformation.connectionBrand = value + } override var capabilities: Map get() = super.capabilities set(value) { - currentCapabilities = value + CarInformation.currentCapabilities = value cachedCapabilities = value.filterKeys { CACHED_CAPABILITY_KEYS.contains(it) } onCarCapabilities() } @@ -192,25 +203,30 @@ class CarCapabilitiesSummarized(val carInformation: CarInformation) { val isJ29: Boolean get() = carInformation.capabilities["hmi.type"]?.startsWith("J29") == true + val isHmiSupported: Boolean + get() = carInformation.connectionBrand?.uppercase() == "BMW" || carInformation.connectionBrand?.uppercase() == "MINI" + val isHmiNotSupported: Boolean + get() = carInformation.connectionBrand?.uppercase() == "J29" + val isPopupSupported: Boolean - get() = !isJ29 + get() = isHmiSupported val isPopupNotSupported: Boolean - get() = isJ29 + get() = isHmiNotSupported val isTtsSupported: Boolean - get() = !isJ29 && carInformation.capabilities["tts"]?.lowercase(Locale.ROOT) == "true" + get() = isHmiSupported && carInformation.capabilities["tts"]?.lowercase(Locale.ROOT) == "true" val isTtsNotSupported: Boolean - get() = isJ29 || carInformation.capabilities["tts"]?.lowercase(Locale.ROOT) == "false" + get() = isHmiNotSupported || carInformation.capabilities["tts"]?.lowercase(Locale.ROOT) == "false" val isNaviSupported: Boolean - get() = !isJ29 && carInformation.capabilities["navi"]?.lowercase(Locale.ROOT) == "true" + get() = isHmiSupported && carInformation.capabilities["navi"]?.lowercase(Locale.ROOT) == "true" val isNaviNotSupported: Boolean - get() = isJ29 || carInformation.capabilities["navi"]?.lowercase(Locale.ROOT) == "false" + get() = isHmiNotSupported || carInformation.capabilities["navi"]?.lowercase(Locale.ROOT) == "false" val mapWidescreenSupported: Boolean - get() = !isJ29 && (carInformation.capabilities["hmi.display-width"]?.toIntOrNull() ?: 0) >= 1000 + get() = isHmiSupported && (carInformation.capabilities["hmi.display-width"]?.toIntOrNull() ?: 0) >= 1000 val mapWidescreenUnsupported: Boolean - get() = isJ29 || (carInformation.capabilities["hmi.display-width"]?.toIntOrNull() ?: 9999) < 1000 + get() = isHmiNotSupported || (carInformation.capabilities["hmi.display-width"]?.toIntOrNull() ?: 9999) < 1000 val mapWidescreenCrashes: Boolean get() = carInformation.capabilities["hmi.version"]?.lowercase(Locale.ROOT)?.startsWith("entryevo_") == true val isF20orF21: Boolean diff --git a/app/src/main/java/me/hufman/androidautoidrive/MainService.kt b/app/src/main/java/me/hufman/androidautoidrive/MainService.kt index 9e8ded75c..b34893988 100644 --- a/app/src/main/java/me/hufman/androidautoidrive/MainService.kt +++ b/app/src/main/java/me/hufman/androidautoidrive/MainService.kt @@ -362,6 +362,7 @@ class MainService: Service() { scheduleShutdownTimeout() handler.post(btfetchUuidsWithSdp) } + carInformationUpdater.connectionBrand = iDriveConnectionReceiver.brand carInformationUpdater.isConnected = iDriveConnectionReceiver.isConnected && securityAccess.isConnected() } } diff --git a/app/src/main/java/me/hufman/androidautoidrive/phoneui/viewmodels/CarCapabilitiesViewModel.kt b/app/src/main/java/me/hufman/androidautoidrive/phoneui/viewmodels/CarCapabilitiesViewModel.kt index bae95e851..2a9f0d05a 100644 --- a/app/src/main/java/me/hufman/androidautoidrive/phoneui/viewmodels/CarCapabilitiesViewModel.kt +++ b/app/src/main/java/me/hufman/androidautoidrive/phoneui/viewmodels/CarCapabilitiesViewModel.kt @@ -80,11 +80,12 @@ class CarCapabilitiesViewModel(val carInformation: CarInformation, val musicAppM val summarized = CarCapabilitiesSummarized(carInformation) // only these brands of cars support RHMI apps - val carBrandSupported = summarized.isBmw || summarized.isMini + // check the cert brand, in case of friendly J29s + val carBrandSupported = carInformation.connectionBrand?.uppercase() == "BMW" || carInformation.connectionBrand?.uppercase() == "MINI" _isCarConnected.value = carInformation.capabilities.isNotEmpty() && carBrandSupported _isJ29Connected.value = summarized.isJ29 - _isAudioContextSupported.value = !summarized.isJ29 && musicAppMode.heuristicAudioContext() + _isAudioContextSupported.value = carBrandSupported && musicAppMode.heuristicAudioContext() if (carBrandSupported && musicAppMode.heuristicAudioContext()) { _audioContextStatus.value = { getString(R.string.txt_capabilities_audiocontext_yes) } _audioContextHint.value = { "" } @@ -98,7 +99,7 @@ class CarCapabilitiesViewModel(val carInformation: CarInformation, val musicAppM } } - _isAudioStateSupported.value = !summarized.isJ29 && musicAppMode.supportsId5Playback() + _isAudioStateSupported.value = carBrandSupported && musicAppMode.supportsId5Playback() if (carBrandSupported && musicAppMode.supportsId5Playback()) { _audioStateStatus.value = { getString(R.string.txt_capabilities_audiostate_yes) } _audioStateHint.value = { "" } diff --git a/app/src/main/java/me/hufman/androidautoidrive/phoneui/viewmodels/CarSummaryModel.kt b/app/src/main/java/me/hufman/androidautoidrive/phoneui/viewmodels/CarSummaryModel.kt index 712ef1c4c..ea7fd0147 100644 --- a/app/src/main/java/me/hufman/androidautoidrive/phoneui/viewmodels/CarSummaryModel.kt +++ b/app/src/main/java/me/hufman/androidautoidrive/phoneui/viewmodels/CarSummaryModel.kt @@ -50,6 +50,7 @@ class CarSummaryModel(carInfoOverride: CarInformation? = null, val showAdvancedS when (brand) { "BMW" -> _carLogo.value = { ContextCompat.getDrawable(this, R.drawable.logo_bmw) } "MINI" -> _carLogo.value = { ContextCompat.getDrawable(this, R.drawable.logo_mini) } + "J29" -> _carLogo.value = { ContextCompat.getDrawable(this, R.drawable.logo_toyota) } else -> _carLogo.value = { null } } diff --git a/app/src/main/java/me/hufman/androidautoidrive/phoneui/viewmodels/ConnectionStatusModel.kt b/app/src/main/java/me/hufman/androidautoidrive/phoneui/viewmodels/ConnectionStatusModel.kt index 74904affa..91d290231 100644 --- a/app/src/main/java/me/hufman/androidautoidrive/phoneui/viewmodels/ConnectionStatusModel.kt +++ b/app/src/main/java/me/hufman/androidautoidrive/phoneui/viewmodels/ConnectionStatusModel.kt @@ -182,11 +182,17 @@ class ConnectionStatusModel(val connection: CarConnectionDebugging, val carInfo: } // current car overview - val brand = if (connection.isBCLConnected) connection.carBrand?.uppercase(Locale.ROOT) else null + val brand = if (connection.isBCLConnected) { + // hmi.type will say the actual car brand, after loading + // but connection carBrand is just based on the auth cert + carInfo.currentCapabilities["hmi.type"]?.split(' ')?.first() ?: + connection.carBrand?.uppercase(Locale.ROOT) + } else null _carBrand.value = brand when (brand) { "BMW" -> _carLogo.value = { ContextCompat.getDrawable(this, R.drawable.logo_bmw) } "MINI" -> _carLogo.value = { ContextCompat.getDrawable(this, R.drawable.logo_mini) } + "J29" -> _carLogo.value = { ContextCompat.getDrawable(this, R.drawable.logo_toyota) } else -> _carLogo.value = { null } } diff --git a/app/src/main/java/me/hufman/androidautoidrive/phoneui/viewmodels/NavigationStatusModel.kt b/app/src/main/java/me/hufman/androidautoidrive/phoneui/viewmodels/NavigationStatusModel.kt index 1654d202c..5445b2380 100644 --- a/app/src/main/java/me/hufman/androidautoidrive/phoneui/viewmodels/NavigationStatusModel.kt +++ b/app/src/main/java/me/hufman/androidautoidrive/phoneui/viewmodels/NavigationStatusModel.kt @@ -92,8 +92,7 @@ class NavigationStatusModel(val carInformation: CarInformation, fun update() { // only these brands of cars support the RHMI app necessary to trigger car nav - val carBrandSupported = carInformation.capabilities["hmi.type"]?.startsWith("BMW") == true || - carInformation.capabilities["hmi.type"]?.startsWith("MINI") == true + val carBrandSupported = carInformation.connectionBrand?.uppercase() == "BMW" || carInformation.connectionBrand?.uppercase() == "MINI" _isConnected.value = carInformation.isConnected && carBrandSupported val capabilities = carInformation.capabilities diff --git a/app/src/main/res/drawable/logo_toyota.xml b/app/src/main/res/drawable/logo_toyota.xml new file mode 100644 index 000000000..c6521c272 --- /dev/null +++ b/app/src/main/res/drawable/logo_toyota.xml @@ -0,0 +1,18 @@ + + + + + diff --git a/app/src/main/res/layout/fragment_car_capabilities.xml b/app/src/main/res/layout/fragment_car_capabilities.xml index 801b408b4..f52ffedfb 100644 --- a/app/src/main/res/layout/fragment_car_capabilities.xml +++ b/app/src/main/res/layout/fragment_car_capabilities.xml @@ -167,11 +167,15 @@ + android:visibility="@{viewModel.isJ29Connected() && !viewModel.isCarConnected()}"> + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bb22b2de3..b4597b8cc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -206,7 +206,8 @@ The app is ready to connect to a BMW The app is ready to connect to a Mini The app is ready to connect to a Toyota Supra - Toyota support is very limited, currently only providing car data + Toyota support is very limited, only providing car data by default + To enable full support in the Toyota Supra, use BimmerCode to code ENTWICKLER_MENUE to aktiv Not ready to connect to a BMW: Not ready to connect to a Mini: BMW Connected 6.5 is installed, which sometimes doesn\'t start the car connection. Try downgrading to 6.4 or upgrading to MyBMW if you encounter problems diff --git a/app/src/test/java/me/hufman/androidautoidrive/phoneui/CarCapabilitiesModelTest.kt b/app/src/test/java/me/hufman/androidautoidrive/phoneui/CarCapabilitiesModelTest.kt index adabd3ca9..6d2b915e0 100644 --- a/app/src/test/java/me/hufman/androidautoidrive/phoneui/CarCapabilitiesModelTest.kt +++ b/app/src/test/java/me/hufman/androidautoidrive/phoneui/CarCapabilitiesModelTest.kt @@ -24,6 +24,7 @@ class CarCapabilitiesModelTest { @Test fun testNoCapabilities() { val carInfo = mock { + on { connectionBrand } doReturn "mini" on { capabilities } doReturn mapOf() } val musicAppMode = mock { @@ -47,6 +48,7 @@ class CarCapabilitiesModelTest { @Test fun testId4Usb() { val carInfo = mock { + on { connectionBrand } doReturn "mini" on { capabilities } doReturn mapOf("hmi.type" to "MINI ID4", "tts" to "true", "navi" to "false") } val musicAppMode = mock { @@ -91,6 +93,7 @@ class CarCapabilitiesModelTest { @Test fun testId4UsbContext() { val carInfo = mock { + on { connectionBrand } doReturn "mini" on { capabilities } doReturn mapOf("hmi.type" to "MINI ID4", "tts" to "true", "navi" to "false") } val musicAppMode = mock { @@ -123,6 +126,7 @@ class CarCapabilitiesModelTest { @Test fun testId5() { val carInfo = mock { + on { connectionBrand } doReturn "mini" on { capabilities } doReturn mapOf("hmi.type" to "MINI ID5", "tts" to "false", "navi" to "true") } val musicAppMode = mock { @@ -167,6 +171,7 @@ class CarCapabilitiesModelTest { @Test fun testId5NoContext() { val carInfo = mock { + on { connectionBrand } doReturn "mini" on { capabilities } doReturn mapOf("hmi.type" to "MINI ID5", "tts" to "false", "navi" to "true") } val musicAppMode = mock { @@ -203,6 +208,7 @@ class CarCapabilitiesModelTest { @Test fun testId5Spotify() { val carInfo = mock { + on { connectionBrand } doReturn "mini" on { capabilities } doReturn mapOf("hmi.type" to "MINI ID5", "tts" to "false", "navi" to "true") } val musicAppMode = mock { @@ -239,6 +245,7 @@ class CarCapabilitiesModelTest { @Test fun testId5Classic() { val carInfo = mock { + on { connectionBrand } doReturn "mini" on { capabilities } doReturn mapOf("hmi.type" to "MINI ID5", "tts" to "false", "navi" to "true") } val musicAppMode = mock { @@ -266,7 +273,8 @@ class CarCapabilitiesModelTest { @Test fun testJ29() { val carInfo = mock { - on { capabilities } doReturn mapOf("hmi.type" to "J29 ID6L") + on { connectionBrand } doReturn "j29" + on { capabilities } doReturn mapOf("hmi.type" to "J29 ID6L", "tts" to "true", "navi" to "false") } val musicAppMode = mock { on { heuristicAudioContext() } doReturn true @@ -289,4 +297,32 @@ class CarCapabilitiesModelTest { assertEquals(true, viewModel.isNaviNotSupported.value) } + + @Test + fun testJ29_entwickler() { + val carInfo = mock { + on { connectionBrand } doReturn "bmw" + on { capabilities } doReturn mapOf("hmi.type" to "J29 ID6L", "tts" to "true", "navi" to "false") + } + val musicAppMode = mock { + on { heuristicAudioContext() } doReturn true + on { shouldRequestAudioContext() } doReturn true + on { isId4() } doReturn false + on { supportsId5Playback() } doReturn true + on { shouldId5Playback() } doReturn false + on { isNewSpotifyInstalled() } doReturn true + } + val viewModel = CarCapabilitiesViewModel(carInfo, musicAppMode).apply { update() } + assertEquals(true, viewModel.isCarConnected.value) + assertEquals(true, viewModel.isJ29Connected.value) + assertEquals(true, viewModel.isAudioContextSupported.value) + assertEquals(true, viewModel.isAudioStateSupported.value) + assertEquals(true, viewModel.isPopupSupported.value) + assertEquals(false, viewModel.isPopupNotSupported.value) + assertEquals(true, viewModel.isTtsSupported.value) + assertEquals(false, viewModel.isTtsNotSupported.value) + assertEquals(false, viewModel.isNaviSupported.value) + assertEquals(true, viewModel.isNaviNotSupported.value) + + } } \ No newline at end of file diff --git a/app/src/test/java/me/hufman/androidautoidrive/phoneui/NavigationStatusModelTest.kt b/app/src/test/java/me/hufman/androidautoidrive/phoneui/NavigationStatusModelTest.kt index 3ec1ac6d2..d2e07159b 100644 --- a/app/src/test/java/me/hufman/androidautoidrive/phoneui/NavigationStatusModelTest.kt +++ b/app/src/test/java/me/hufman/androidautoidrive/phoneui/NavigationStatusModelTest.kt @@ -28,6 +28,7 @@ class NavigationStatusModelTest { val cdsData = CDSDataProvider() val carInformation = mock { on { isConnected } doAnswer { isConnected } + on { connectionBrand } doReturn "bmw" on { capabilities } doReturn capabilities on { cdsData } doReturn cdsData } @@ -46,6 +47,7 @@ class NavigationStatusModelTest { @Test fun testJ29IsNotConnected() { + whenever(carInformation.connectionBrand) doReturn "j29" capabilities["hmi.type"] = "J29 ID6L" val model = NavigationStatusModel(carInformation, MutableLiveData(false), MutableLiveData(false), MutableLiveData(null)).apply { update() } assertEquals(false, model.isConnected.value) @@ -55,6 +57,18 @@ class NavigationStatusModelTest { assertEquals(false, model.isConnected.value) } + @Test + fun testJ29Entwickler() { + whenever(carInformation.connectionBrand) doReturn "bmw" + capabilities["hmi.type"] = "J29 ID6L" + val model = NavigationStatusModel(carInformation, MutableLiveData(false), MutableLiveData(false), MutableLiveData(null)).apply { update() } + assertEquals(false, model.isConnected.value) + + isConnected = true + model.update() + assertEquals(true, model.isConnected.value) + } + @Test fun testNaviSupported() { val model = NavigationStatusModel(carInformation, MutableLiveData(false), MutableLiveData(false), MutableLiveData(null)).apply { update() } From d7a89ff2cc06e351e644530d70d38f1c01e110a1 Mon Sep 17 00:00:00 2001 From: Walter Huf Date: Mon, 5 Aug 2024 07:13:24 -0700 Subject: [PATCH 3/3] Grant bluetooth and notification perms in screenshots --- .../java/me/hufman/androidautoidrive/MockScenario.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/androidTest/java/me/hufman/androidautoidrive/MockScenario.kt b/app/src/androidTest/java/me/hufman/androidautoidrive/MockScenario.kt index 0ed89a426..3c9bc9250 100644 --- a/app/src/androidTest/java/me/hufman/androidautoidrive/MockScenario.kt +++ b/app/src/androidTest/java/me/hufman/androidautoidrive/MockScenario.kt @@ -122,6 +122,8 @@ class MockScenario(context: Context) { on {hasSmsPermission} doReturn true on {hasLocationPermission} doReturn true on {hasBackgroundPermission} doReturn true + on {hasBluetoothConnectPermission} doReturn true + on {hasPostNotificationsPermission} doReturn true } // https://stackoverflow.com/a/60119030/169035