diff --git a/LICENSE.md b/LICENSE.md index 00411bb4fa4..88a04bc2a38 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -5,7 +5,7 @@ Mapbox Navigation Android SDK Copyright ©2022 - 2023 Mapbox, Inc. All rights reserved. -The software and files in this repository (collectively, "Software") are licensed under the Mapbox TOS for use only with the relevant Mapbox product(s) listed at www.mapbox.com/pricing. This license allows developers with a current active Mapbox account to use and modify the authorized portions of the Software as needed for use only with the relevant Mapbox product(s) through their Mapbox account in accordance with the Mapbox TOS. This license terminates automatically if a developer no longer has a Mapbox account in good standing or breaches the Mapbox TOS. For the license terms, please see the Mapbox TOS at https://www.mapbox.com/legal/tos/ which incorporates the Mapbox Product Terms at www.mapbox.com/legal/service-terms. If this Software is a SDK, modifications that change or interfere with marked portions of the code related to billing, accounting, or data collection are not authorized and the SDK sends limited de-identified location and usage data which is used in accordance with the Mapbox TOS. [Updated 2023-01] +The software and files in this repository (collectively, "Software") are licensed under the Mapbox TOS for use only with the relevant Mapbox product(s) listed at www.mapbox.com/pricing. This license allows developers with a current active Mapbox account to use and modify the authorized portions of the Software as needed for use only with the relevant Mapbox product(s) through their Mapbox account in accordance with the Mapbox TOS. This license terminates automatically if a developer no longer has a Mapbox account in good standing or breaches the Mapbox TOS. For the license terms, please see the Mapbox TOS at https://www.mapbox.com/legal/tos/ which incorporates the Mapbox Product Terms at www.mapbox.com/legal/service-terms. If this Software is a SDK, modifications that change or interfere with marked portions of the code related to billing, accounting, or data collection are not authorized and the SDK sends limited de-identified location and usage data which is used in accordance with the Mapbox TOS. [Updated 2023-02] --------------------------------------- Mapbox Navigation uses portions of the Gradle License Plugin. diff --git a/changelog/unreleased/features/6868.md b/changelog/unreleased/features/6868.md new file mode 100644 index 00000000000..84330a0cba4 --- /dev/null +++ b/changelog/unreleased/features/6868.md @@ -0,0 +1 @@ +- Introduced `PredictiveCacheOptions.Builder#predictiveCacheMapsOptionsList` as an alternative for deprecated `PredictiveCacheOptions.Builder#predictiveCacheMapsOptions`. This allows to use different `PredictiveCacheLocationOptions` for different zoom level ranges. \ No newline at end of file diff --git a/libnavigation-base/api/current.txt b/libnavigation-base/api/current.txt index 0a3dc23fc8b..3a3d3d272b1 100644 --- a/libnavigation-base/api/current.txt +++ b/libnavigation-base/api/current.txt @@ -542,17 +542,20 @@ package com.mapbox.navigation.base.options { } public final class PredictiveCacheOptions { - method public com.mapbox.navigation.base.options.PredictiveCacheMapsOptions getPredictiveCacheMapsOptions(); + method @Deprecated public com.mapbox.navigation.base.options.PredictiveCacheMapsOptions getPredictiveCacheMapsOptions(); + method public java.util.List getPredictiveCacheMapsOptionsList(); method public com.mapbox.navigation.base.options.PredictiveCacheNavigationOptions getPredictiveCacheNavigationOptions(); method public com.mapbox.navigation.base.options.PredictiveCacheOptions.Builder toBuilder(); - property public final com.mapbox.navigation.base.options.PredictiveCacheMapsOptions predictiveCacheMapsOptions; + property @Deprecated public final com.mapbox.navigation.base.options.PredictiveCacheMapsOptions predictiveCacheMapsOptions; + property public final java.util.List predictiveCacheMapsOptionsList; property public final com.mapbox.navigation.base.options.PredictiveCacheNavigationOptions predictiveCacheNavigationOptions; } public static final class PredictiveCacheOptions.Builder { ctor public PredictiveCacheOptions.Builder(); method public com.mapbox.navigation.base.options.PredictiveCacheOptions build(); - method public com.mapbox.navigation.base.options.PredictiveCacheOptions.Builder predictiveCacheMapsOptions(com.mapbox.navigation.base.options.PredictiveCacheMapsOptions predictiveCacheMapsOptions); + method @Deprecated public com.mapbox.navigation.base.options.PredictiveCacheOptions.Builder predictiveCacheMapsOptions(com.mapbox.navigation.base.options.PredictiveCacheMapsOptions predictiveCacheMapsOptions); + method @kotlin.jvm.Throws(exceptionClasses=IllegalArgumentException::class) public com.mapbox.navigation.base.options.PredictiveCacheOptions.Builder predictiveCacheMapsOptionsList(java.util.List predictiveCacheMapsOptionsList) throws java.lang.IllegalArgumentException; method public com.mapbox.navigation.base.options.PredictiveCacheOptions.Builder predictiveCacheNavigationOptions(com.mapbox.navigation.base.options.PredictiveCacheNavigationOptions predictiveCacheNavigationOptions); } diff --git a/libnavigation-base/src/main/java/com/mapbox/navigation/base/options/PredictiveCacheOptions.kt b/libnavigation-base/src/main/java/com/mapbox/navigation/base/options/PredictiveCacheOptions.kt index 78fab92e94c..8651ee4722d 100644 --- a/libnavigation-base/src/main/java/com/mapbox/navigation/base/options/PredictiveCacheOptions.kt +++ b/libnavigation-base/src/main/java/com/mapbox/navigation/base/options/PredictiveCacheOptions.kt @@ -4,19 +4,31 @@ package com.mapbox.navigation.base.options * PredictiveCacheOptions * * @param predictiveCacheNavigationOptions [PredictiveCacheNavigationOptions] Predictive cache Navigation related options. - * @param predictiveCacheMapsOptions [PredictiveCacheMapsOptions] Predictive cache Maps related options. + * @param predictiveCacheMapsOptionsList List of predictive cache Maps related options ([PredictiveCacheMapsOptions]). + * Use this instead of [predictiveCacheMapsOptions] so that you can specify different + * [PredictiveCacheLocationOptions]s for different zoom level ranges. */ class PredictiveCacheOptions private constructor( val predictiveCacheNavigationOptions: PredictiveCacheNavigationOptions, - val predictiveCacheMapsOptions: PredictiveCacheMapsOptions, + val predictiveCacheMapsOptionsList: List ) { + /** + * Predictive cache Maps related options. If [Builder.predictiveCacheMapsOptionsList] was used, + * returns first element from [predictiveCacheMapsOptionsList]. + * @deprecated use predictiveCacheMapsOptionsList instead to provide different + * [PredictiveCacheLocationOptions]s for different zoom level ranges. + */ + @Deprecated("Use predictiveCacheMapsOptionsList") + val predictiveCacheMapsOptions: PredictiveCacheMapsOptions = + predictiveCacheMapsOptionsList.first() + /** * Get a builder to customize a subset of current options. */ fun toBuilder(): Builder = Builder().apply { predictiveCacheNavigationOptions(predictiveCacheNavigationOptions) - predictiveCacheMapsOptions(predictiveCacheMapsOptions) + predictiveCacheMapsOptionsList(predictiveCacheMapsOptionsList) } /** @@ -29,7 +41,7 @@ class PredictiveCacheOptions private constructor( other as PredictiveCacheOptions if (predictiveCacheNavigationOptions != other.predictiveCacheNavigationOptions) return false - if (predictiveCacheMapsOptions != other.predictiveCacheMapsOptions) return false + if (predictiveCacheMapsOptionsList != other.predictiveCacheMapsOptionsList) return false return true } @@ -39,7 +51,7 @@ class PredictiveCacheOptions private constructor( */ override fun hashCode(): Int { var result = predictiveCacheNavigationOptions.hashCode() - result = 31 * result + predictiveCacheMapsOptions.hashCode() + result = 31 * result + predictiveCacheMapsOptionsList.hashCode() return result } @@ -49,7 +61,7 @@ class PredictiveCacheOptions private constructor( override fun toString(): String { return "PredictiveCacheOptions(" + "predictiveCacheNavigationOptions=$predictiveCacheNavigationOptions, " + - "predictiveCacheMapsOptions=$predictiveCacheMapsOptions" + + "predictiveCacheMapsOptionsList=$predictiveCacheMapsOptionsList" + ")" } @@ -57,8 +69,10 @@ class PredictiveCacheOptions private constructor( * Build a new [PredictiveCacheOptions]. */ class Builder { - private var predictiveCacheNavigationOptions: PredictiveCacheNavigationOptions? = null - private var predictiveCacheMapsOptions: PredictiveCacheMapsOptions? = null + private var predictiveCacheNavigationOptions = + PredictiveCacheNavigationOptions.Builder().build() + private var predictiveCacheMapsOptionsList = + listOf(PredictiveCacheMapsOptions.Builder().build()) /** * Predictive cache Navigation related options. @@ -71,17 +85,40 @@ class PredictiveCacheOptions private constructor( /** * Predictive cache Maps related options. + * @deprecated use predictiveCacheMapsOptionsList instead to provide different + * [PredictiveCacheLocationOptions]s for different zoom level ranges. */ + @Deprecated( + "Use predictiveCacheMapsOptionsList", + ReplaceWith("predictiveCacheMapsOptionsList(listOf(predictiveCacheMapsOptions))") + ) fun predictiveCacheMapsOptions( predictiveCacheMapsOptions: PredictiveCacheMapsOptions - ): Builder = apply { this.predictiveCacheMapsOptions = predictiveCacheMapsOptions } + ): Builder = predictiveCacheMapsOptionsList(listOf(predictiveCacheMapsOptions)) + + /** + * List of predictive cache Maps related options ([PredictiveCacheMapsOptions]). + * Use this instead of [predictiveCacheMapsOptions] so that you can specify different + * [PredictiveCacheLocationOptions]s for different zoom level ranges. + * + * @throws IllegalArgumentException if [predictiveCacheMapsOptionsList] is empty. + */ + @Throws(IllegalArgumentException::class) + fun predictiveCacheMapsOptionsList( + predictiveCacheMapsOptionsList: List + ): Builder = apply { + if (predictiveCacheMapsOptionsList.isEmpty()) { + throw IllegalArgumentException("predictiveCacheMapsOptionsList must not be empty") + } + this.predictiveCacheMapsOptionsList = predictiveCacheMapsOptionsList.toList() + } /** * Build [PredictiveCacheOptions]. */ fun build(): PredictiveCacheOptions = PredictiveCacheOptions( - predictiveCacheNavigationOptions ?: PredictiveCacheNavigationOptions.Builder().build(), - predictiveCacheMapsOptions ?: PredictiveCacheMapsOptions.Builder().build(), + predictiveCacheNavigationOptions, + predictiveCacheMapsOptionsList ) } } diff --git a/libnavigation-base/src/test/java/com/mapbox/navigation/base/options/PredictiveCacheOptionsBuilderTest.kt b/libnavigation-base/src/test/java/com/mapbox/navigation/base/options/PredictiveCacheOptionsBuilderTest.kt new file mode 100644 index 00000000000..6b60fab55c7 --- /dev/null +++ b/libnavigation-base/src/test/java/com/mapbox/navigation/base/options/PredictiveCacheOptionsBuilderTest.kt @@ -0,0 +1,57 @@ +package com.mapbox.navigation.base.options + +import com.mapbox.navigation.testing.BuilderTest +import org.junit.Test +import kotlin.reflect.KClass + +class PredictiveCacheOptionsBuilderTest : + BuilderTest() { + override fun getImplementationClass(): KClass = + PredictiveCacheOptions::class + + override fun getFilledUpBuilder(): PredictiveCacheOptions.Builder = + PredictiveCacheOptions.Builder().apply { + predictiveCacheNavigationOptions( + PredictiveCacheNavigationOptions.Builder().apply { + predictiveCacheLocationOptions( + PredictiveCacheLocationOptions.Builder().apply { + currentLocationRadiusInMeters(300) + routeBufferRadiusInMeters(50) + destinationLocationRadiusInMeters(20) + }.build() + ) + }.build() + ) + predictiveCacheMapsOptionsList( + listOf( + PredictiveCacheMapsOptions.Builder().apply { + predictiveCacheLocationOptions( + PredictiveCacheLocationOptions.Builder().apply { + currentLocationRadiusInMeters(100) + routeBufferRadiusInMeters(2) + destinationLocationRadiusInMeters(15) + }.build() + ) + minZoom(1) + maxZoom(3) + }.build(), + PredictiveCacheMapsOptions.Builder().apply { + predictiveCacheLocationOptions( + PredictiveCacheLocationOptions.Builder().apply { + currentLocationRadiusInMeters(200) + routeBufferRadiusInMeters(3) + destinationLocationRadiusInMeters(18) + }.build() + ) + minZoom(7) + maxZoom(9) + }.build(), + ) + ) + } + + @Test + override fun trigger() { + // trigger, see KDoc + } +} diff --git a/libnavigation-base/src/test/java/com/mapbox/navigation/base/options/PredictiveCacheOptionsDeprecatedBuilderTest.kt b/libnavigation-base/src/test/java/com/mapbox/navigation/base/options/PredictiveCacheOptionsDeprecatedBuilderTest.kt new file mode 100644 index 00000000000..fc4f6fee619 --- /dev/null +++ b/libnavigation-base/src/test/java/com/mapbox/navigation/base/options/PredictiveCacheOptionsDeprecatedBuilderTest.kt @@ -0,0 +1,45 @@ +package com.mapbox.navigation.base.options + +import com.mapbox.navigation.testing.BuilderTest +import org.junit.Test +import kotlin.reflect.KClass + +class PredictiveCacheOptionsDeprecatedBuilderTest : + BuilderTest() { + + override fun getImplementationClass(): KClass = + PredictiveCacheOptions::class + + override fun getFilledUpBuilder(): PredictiveCacheOptions.Builder = + PredictiveCacheOptions.Builder().apply { + predictiveCacheNavigationOptions( + PredictiveCacheNavigationOptions.Builder().apply { + predictiveCacheLocationOptions( + PredictiveCacheLocationOptions.Builder().apply { + currentLocationRadiusInMeters(300) + routeBufferRadiusInMeters(50) + destinationLocationRadiusInMeters(20) + }.build() + ) + }.build() + ) + predictiveCacheMapsOptions( + PredictiveCacheMapsOptions.Builder().apply { + predictiveCacheLocationOptions( + PredictiveCacheLocationOptions.Builder().apply { + currentLocationRadiusInMeters(100) + routeBufferRadiusInMeters(2) + destinationLocationRadiusInMeters(15) + }.build() + ) + minZoom(1) + maxZoom(3) + }.build() + ) + } + + @Test + override fun trigger() { + // trigger, see KDoc + } +} diff --git a/libnavigation-base/src/test/java/com/mapbox/navigation/base/options/PredictiveCacheOptionsTest.kt b/libnavigation-base/src/test/java/com/mapbox/navigation/base/options/PredictiveCacheOptionsTest.kt index 1eeda69dbb3..60e0d6af81a 100644 --- a/libnavigation-base/src/test/java/com/mapbox/navigation/base/options/PredictiveCacheOptionsTest.kt +++ b/libnavigation-base/src/test/java/com/mapbox/navigation/base/options/PredictiveCacheOptionsTest.kt @@ -1,44 +1,80 @@ package com.mapbox.navigation.base.options -import com.mapbox.navigation.testing.BuilderTest +import org.junit.Assert.assertEquals import org.junit.Test -import kotlin.reflect.KClass - -class PredictiveCacheOptionsTest : - BuilderTest() { - override fun getImplementationClass(): KClass = - PredictiveCacheOptions::class - - override fun getFilledUpBuilder(): PredictiveCacheOptions.Builder = - PredictiveCacheOptions.Builder().apply { - predictiveCacheNavigationOptions( - PredictiveCacheNavigationOptions.Builder().apply { - predictiveCacheLocationOptions( - PredictiveCacheLocationOptions.Builder().apply { - currentLocationRadiusInMeters(300) - routeBufferRadiusInMeters(50) - destinationLocationRadiusInMeters(20) - }.build() - ) - }.build() - ) - predictiveCacheMapsOptions( - PredictiveCacheMapsOptions.Builder().apply { - predictiveCacheLocationOptions( - PredictiveCacheLocationOptions.Builder().apply { - currentLocationRadiusInMeters(100) - routeBufferRadiusInMeters(2) - destinationLocationRadiusInMeters(15) - }.build() - ) - minZoom(1) - maxZoom(3) - }.build() - ) - } + +class PredictiveCacheOptionsTest { + + @Test + fun defaultMapsOptionsList() { + val expected = PredictiveCacheMapsOptions.Builder().build() + val actual = PredictiveCacheOptions.Builder().build() + + assertEquals(expected, actual.predictiveCacheMapsOptions) + assertEquals(listOf(expected), actual.predictiveCacheMapsOptionsList) + } + + @Test + fun deprecatedMapsOptions() { + val mapsOptions = PredictiveCacheMapsOptions.Builder().minZoom(12).maxZoom(14).build() + val actual = PredictiveCacheOptions.Builder() + .predictiveCacheMapsOptions(mapsOptions) + .build() + + assertEquals(mapsOptions, actual.predictiveCacheMapsOptions) + assertEquals(listOf(mapsOptions), actual.predictiveCacheMapsOptionsList) + } + + @Test + fun customMapsOptionsList() { + val mapsOptions1 = PredictiveCacheMapsOptions.Builder().minZoom(12).maxZoom(14).build() + val mapsOptions2 = PredictiveCacheMapsOptions.Builder().minZoom(11).maxZoom(13).build() + val actual = PredictiveCacheOptions.Builder() + .predictiveCacheMapsOptionsList(listOf(mapsOptions1, mapsOptions2)) + .build() + + assertEquals(mapsOptions1, actual.predictiveCacheMapsOptions) + assertEquals(listOf(mapsOptions1, mapsOptions2), actual.predictiveCacheMapsOptionsList) + } + + @Test(expected = IllegalArgumentException::class) + fun customEmptyMapsOptionsList() { + PredictiveCacheOptions.Builder() + .predictiveCacheMapsOptionsList(emptyList()) + .build() + } @Test - override fun trigger() { - // trigger, see KDoc + fun customMapsOptionsAfterDeprecatedMapsOptions() { + val deprecatedMapsOptions = PredictiveCacheMapsOptions.Builder() + .minZoom(7) + .maxZoom(9) + .build() + val mapsOptions1 = PredictiveCacheMapsOptions.Builder().minZoom(12).maxZoom(14).build() + val mapsOptions2 = PredictiveCacheMapsOptions.Builder().minZoom(11).maxZoom(13).build() + val actual = PredictiveCacheOptions.Builder() + .predictiveCacheMapsOptions(deprecatedMapsOptions) + .predictiveCacheMapsOptionsList(listOf(mapsOptions1, mapsOptions2)) + .build() + + assertEquals(mapsOptions1, actual.predictiveCacheMapsOptions) + assertEquals(listOf(mapsOptions1, mapsOptions2), actual.predictiveCacheMapsOptionsList) + } + + @Test + fun deprecatedMapsOptionsAfterCustomMapsOptionsList() { + val deprecatedMapsOptions = PredictiveCacheMapsOptions.Builder() + .minZoom(7) + .maxZoom(9) + .build() + val mapsOptions1 = PredictiveCacheMapsOptions.Builder().minZoom(12).maxZoom(14).build() + val mapsOptions2 = PredictiveCacheMapsOptions.Builder().minZoom(11).maxZoom(13).build() + val actual = PredictiveCacheOptions.Builder() + .predictiveCacheMapsOptionsList(listOf(mapsOptions1, mapsOptions2)) + .predictiveCacheMapsOptions(deprecatedMapsOptions) + .build() + + assertEquals(deprecatedMapsOptions, actual.predictiveCacheMapsOptions) + assertEquals(listOf(deprecatedMapsOptions), actual.predictiveCacheMapsOptionsList) } } diff --git a/libnavigation-core/src/main/java/com/mapbox/navigation/core/internal/PredictiveCache.kt b/libnavigation-core/src/main/java/com/mapbox/navigation/core/internal/PredictiveCache.kt index 84d2228b3cc..707e6725396 100644 --- a/libnavigation-core/src/main/java/com/mapbox/navigation/core/internal/PredictiveCache.kt +++ b/libnavigation-core/src/main/java/com/mapbox/navigation/core/internal/PredictiveCache.kt @@ -11,14 +11,14 @@ object PredictiveCache { internal val cachedNavigationPredictiveCacheControllers = mutableSetOf() internal val cachedMapsPredictiveCacheControllers = - mutableMapOf>() + mutableMapOf>>() internal val cachedMapsPredictiveCacheControllersTileVariant = mutableMapOf>() internal val navPredictiveCacheLocationOptions = mutableSetOf() - internal val mapsPredictiveCacheLocationOptions = - mutableMapOf>() + internal val mapsPredictiveCacheLocationOptions = mutableMapOf>>>() internal val mapsPredictiveCacheLocationOptionsTileVariant = mutableMapOf>>() @@ -35,12 +35,11 @@ object PredictiveCache { createNavigationController(it) } mapsOptions.forEach { entry -> - entry.value.let { (descriptor, tileStore, options) -> - createMapsController( + entry.value.let { (tileStore, descriptorsAndOptions) -> + createMapsControllers( mapboxMap = entry.key, - tilesetDescriptor = descriptor, tileStore = tileStore, - predictiveCacheLocationOptions = options + descriptorsAndOptions = descriptorsAndOptions ) } } @@ -69,9 +68,7 @@ object PredictiveCache { } @Deprecated( - "Use createMapsController(" + - "mapboxMap, tileStore, tilesetDescriptor, predictiveCacheLocationOptions" + - ") instead." + "Use createMapsControllers(mapboxMap, tileStore, descriptorsAndOptions) instead." ) fun createMapsController( mapboxMap: Any, @@ -97,23 +94,21 @@ object PredictiveCache { mapsPredictiveCacheLocationOptionsTileVariant[mapboxMap] = locationOptions } - fun createMapsController( + fun createMapsControllers( mapboxMap: Any, tileStore: TileStore, - tilesetDescriptor: TilesetDescriptor, - predictiveCacheLocationOptions: PredictiveCacheLocationOptions + descriptorsAndOptions: List> ) { - val predictiveCacheController = - MapboxNativeNavigatorImpl.createMapsPredictiveCacheController( + val descriptorsToPredictiveCacheControllers = descriptorsAndOptions.map { + it.first to MapboxNativeNavigatorImpl.createMapsPredictiveCacheController( tileStore, - tilesetDescriptor, - predictiveCacheLocationOptions + it.first, + it.second ) + } - cachedMapsPredictiveCacheControllers[mapboxMap] = - Pair(tilesetDescriptor, predictiveCacheController) - mapsPredictiveCacheLocationOptions[mapboxMap] = - Triple(tilesetDescriptor, tileStore, predictiveCacheLocationOptions) + cachedMapsPredictiveCacheControllers[mapboxMap] = descriptorsToPredictiveCacheControllers + mapsPredictiveCacheLocationOptions[mapboxMap] = tileStore to descriptorsAndOptions } @Deprecated("Will be removed with other TileVariant logic") diff --git a/libnavigation-core/src/test/java/com/mapbox/navigation/core/internal/cache/PredictiveCacheTests.kt b/libnavigation-core/src/test/java/com/mapbox/navigation/core/internal/cache/PredictiveCacheTests.kt index 3d6d0cf02fa..4bfb9950a97 100644 --- a/libnavigation-core/src/test/java/com/mapbox/navigation/core/internal/cache/PredictiveCacheTests.kt +++ b/libnavigation-core/src/test/java/com/mapbox/navigation/core/internal/cache/PredictiveCacheTests.kt @@ -1,6 +1,7 @@ package com.mapbox.navigation.core.internal.cache import com.mapbox.common.TileStore +import com.mapbox.common.TilesetDescriptor import com.mapbox.navigation.base.options.PredictiveCacheLocationOptions import com.mapbox.navigation.core.internal.PredictiveCache import com.mapbox.navigation.navigator.internal.MapboxNativeNavigatorImpl @@ -15,6 +16,7 @@ import io.mockk.unmockkObject import io.mockk.verify import org.junit.After import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull import org.junit.Before import org.junit.Test @@ -38,6 +40,9 @@ class PredictiveCacheTests { any() ) } returns mockk() + every { + MapboxNativeNavigatorImpl.createMapsPredictiveCacheController(any(), any(), any()) + } returns mockk() every { MapboxNativeNavigatorImpl.setNativeNavigatorRecreationObserver( @@ -54,7 +59,7 @@ class PredictiveCacheTests { } @Test - fun `size of map controllers is correct`() { + fun `size of deprecated map controllers is correct`() { val map1 = mockk() val map2 = mockk() @@ -69,10 +74,62 @@ class PredictiveCacheTests { assertEquals(3, PredictiveCache.currentMapsPredictiveCacheControllers(map1).size) assertEquals(4, PredictiveCache.currentMapsPredictiveCacheControllers(map2).size) + assertNull(PredictiveCache.cachedMapsPredictiveCacheControllers[map1]) + assertNull(PredictiveCache.cachedMapsPredictiveCacheControllers[map2]) } @Test - fun `size of map controllers is correct after removing`() { + fun `size of map controllers is correct`() { + val map1 = mockk() + val map2 = mockk() + val options1 = mockk(relaxed = true) + val options2 = mockk(relaxed = true) + val tilesetDescriptor1 = mockk() + val tilesetDescriptor2 = mockk() + + PredictiveCache.createMapsControllers( + map1, + tileStore, + listOf(tilesetDescriptor1 to options1, tilesetDescriptor2 to options2) + ) + PredictiveCache.createMapsControllers( + map2, + tileStore, + listOf(tilesetDescriptor2 to options2) + ) + + assertEquals(2, PredictiveCache.cachedMapsPredictiveCacheControllers[map1]!!.size) + assertEquals(1, PredictiveCache.cachedMapsPredictiveCacheControllers[map2]!!.size) + assertEquals(0, PredictiveCache.currentMapsPredictiveCacheControllers(map1).size) + assertEquals(0, PredictiveCache.currentMapsPredictiveCacheControllers(map2).size) + assertNull(PredictiveCache.cachedMapsPredictiveCacheControllersTileVariant[map1]) + assertNull(PredictiveCache.cachedMapsPredictiveCacheControllersTileVariant[map2]) + assertNull(PredictiveCache.mapsPredictiveCacheLocationOptionsTileVariant[map1]) + assertNull(PredictiveCache.mapsPredictiveCacheLocationOptionsTileVariant[map2]) + + PredictiveCache.createMapsControllers( + map1, + tileStore, + listOf(tilesetDescriptor2 to options2) + ) + PredictiveCache.createMapsControllers( + map2, + tileStore, + listOf(tilesetDescriptor1 to options1, tilesetDescriptor2 to options2) + ) + + assertEquals(1, PredictiveCache.cachedMapsPredictiveCacheControllers[map1]!!.size) + assertEquals(2, PredictiveCache.cachedMapsPredictiveCacheControllers[map2]!!.size) + assertEquals(0, PredictiveCache.currentMapsPredictiveCacheControllers(map1).size) + assertEquals(0, PredictiveCache.currentMapsPredictiveCacheControllers(map2).size) + assertNull(PredictiveCache.cachedMapsPredictiveCacheControllersTileVariant[map1]) + assertNull(PredictiveCache.cachedMapsPredictiveCacheControllersTileVariant[map2]) + assertNull(PredictiveCache.mapsPredictiveCacheLocationOptionsTileVariant[map1]) + assertNull(PredictiveCache.mapsPredictiveCacheLocationOptionsTileVariant[map2]) + } + + @Test + fun `size of deprecated map controllers is correct after removing`() { val map = mockk() PredictiveCache.createMapsController(map, tileStore, TILE_VARIANT_1, mockk()) @@ -90,7 +147,7 @@ class PredictiveCacheTests { } @Test - fun `map controllers are empty after removing all`() { + fun `deprecated map controllers are empty after removing all`() { val map = mockk() PredictiveCache.createMapsController(map, tileStore, TILE_VARIANT_1, mockk()) @@ -104,10 +161,36 @@ class PredictiveCacheTests { assertEquals(null, PredictiveCache.cachedMapsPredictiveCacheControllers[map]) } + @Test + fun `map controllers are empty after removing all`() { + val map = mockk() + + val options1 = mockk(relaxed = true) + val options2 = mockk(relaxed = true) + val tilesetDescriptor1 = mockk() + val tilesetDescriptor2 = mockk() + + PredictiveCache.createMapsControllers( + map, + tileStore, + listOf(tilesetDescriptor1 to options1, tilesetDescriptor2 to options2) + ) + + PredictiveCache.removeAllMapControllersFromDescriptors(map) + + assertEquals(0, PredictiveCache.currentMapsPredictiveCacheControllers(map).size) + assertEquals(null, PredictiveCache.mapsPredictiveCacheLocationOptions[map]) + assertEquals(null, PredictiveCache.cachedMapsPredictiveCacheControllers[map]) + } + @Test fun `controllers are recreated when navigator is recreated`() { val navLocationOptions1: PredictiveCacheLocationOptions = mockk() val navLocationOptions2: PredictiveCacheLocationOptions = mockk() + val navLocationOptions3: PredictiveCacheLocationOptions = mockk() + val tilesetDescriptor1 = mockk() + val tilesetDescriptor2 = mockk() + val tilesetDescriptor3 = mockk() every { MapboxNativeNavigatorImpl.createNavigationPredictiveCacheController(navLocationOptions1) @@ -117,6 +200,10 @@ class PredictiveCacheTests { MapboxNativeNavigatorImpl.createNavigationPredictiveCacheController(navLocationOptions2) } returns mockk() + every { + MapboxNativeNavigatorImpl.createNavigationPredictiveCacheController(navLocationOptions3) + } returns mockk() + val map1 = mockk() val map2 = mockk() @@ -131,6 +218,20 @@ class PredictiveCacheTests { PredictiveCache.createMapsController(map2, tileStore, TILE_VARIANT_6, mockk()) PredictiveCache.createMapsController(map2, tileStore, TILE_VARIANT_7, mockk()) + PredictiveCache.createMapsControllers( + map1, + tileStore, + listOf( + tilesetDescriptor1 to navLocationOptions1, + tilesetDescriptor2 to navLocationOptions2 + ) + ) + PredictiveCache.createMapsControllers( + map2, + tileStore, + listOf(tilesetDescriptor3 to navLocationOptions3) + ) + PredictiveCache.createNavigationController(navLocationOptions1) PredictiveCache.createNavigationController(navLocationOptions2) @@ -145,6 +246,11 @@ class PredictiveCacheTests { assertEquals(3, PredictiveCache.mapsPredictiveCacheLocationOptionsTileVariant[map1]?.size) assertEquals(4, PredictiveCache.mapsPredictiveCacheLocationOptionsTileVariant[map2]?.size) + assertEquals(2, PredictiveCache.cachedMapsPredictiveCacheControllers.size) + assertEquals(2, PredictiveCache.cachedMapsPredictiveCacheControllers[map1]!!.size) + assertEquals(2, PredictiveCache.mapsPredictiveCacheLocationOptions.size) + assertEquals(1, PredictiveCache.cachedMapsPredictiveCacheControllers[map2]!!.size) + assertEquals(2, PredictiveCache.cachedNavigationPredictiveCacheControllers.size) assertEquals(2, PredictiveCache.navPredictiveCacheLocationOptions.size) @@ -204,6 +310,30 @@ class PredictiveCacheTests { ) } + verify(exactly = 2) { + MapboxNativeNavigatorImpl.createMapsPredictiveCacheController( + tileStore, + tilesetDescriptor1, + navLocationOptions1 + ) + } + + verify(exactly = 2) { + MapboxNativeNavigatorImpl.createMapsPredictiveCacheController( + tileStore, + tilesetDescriptor2, + navLocationOptions2 + ) + } + + verify(exactly = 2) { + MapboxNativeNavigatorImpl.createMapsPredictiveCacheController( + tileStore, + tilesetDescriptor3, + navLocationOptions3 + ) + } + verify(exactly = 2) { MapboxNativeNavigatorImpl.createNavigationPredictiveCacheController(navLocationOptions1) } @@ -222,8 +352,10 @@ class PredictiveCacheTests { assertEquals(0, PredictiveCache.cachedNavigationPredictiveCacheControllers.size) assertEquals(0, PredictiveCache.cachedMapsPredictiveCacheControllers.size) + assertEquals(0, PredictiveCache.cachedMapsPredictiveCacheControllersTileVariant.size) assertEquals(0, PredictiveCache.navPredictiveCacheLocationOptions.size) assertEquals(0, PredictiveCache.mapsPredictiveCacheLocationOptions.size) + assertEquals(0, PredictiveCache.mapsPredictiveCacheLocationOptionsTileVariant.size) } private companion object { diff --git a/libnavui-maps/src/main/java/com/mapbox/navigation/ui/maps/PredictiveCacheController.kt b/libnavui-maps/src/main/java/com/mapbox/navigation/ui/maps/PredictiveCacheController.kt index e3d2d7271eb..c1903559ab0 100644 --- a/libnavui-maps/src/main/java/com/mapbox/navigation/ui/maps/PredictiveCacheController.kt +++ b/libnavui-maps/src/main/java/com/mapbox/navigation/ui/maps/PredictiveCacheController.kt @@ -345,23 +345,23 @@ class PredictiveCacheController constructor( """.trimIndent() handleError(message) } else { - val descriptorOptions = TilesetDescriptorOptions.Builder() - .styleURI(styleURI) - .minZoom( - predictiveCacheOptions.predictiveCacheMapsOptions.minZoom - ) - .maxZoom( - predictiveCacheOptions.predictiveCacheMapsOptions.maxZoom - ) - .build() + val descriptorsToOptions = + predictiveCacheOptions.predictiveCacheMapsOptionsList.map { options -> + val descriptorOptions = TilesetDescriptorOptions.Builder() + .styleURI(styleURI) + .minZoom(options.minZoom) + .maxZoom(options.maxZoom) + .build() - val tilesetDescriptor = offlineManager.createTilesetDescriptor(descriptorOptions) + val tilesetDescriptor = + offlineManager.createTilesetDescriptor(descriptorOptions) + tilesetDescriptor to options.predictiveCacheLocationOptions + } - PredictiveCache.createMapsController( + PredictiveCache.createMapsControllers( map, tileStore, - tilesetDescriptor, - predictiveCacheOptions.predictiveCacheMapsOptions.predictiveCacheLocationOptions, + descriptorsToOptions ) } } diff --git a/libnavui-maps/src/test/java/com/mapbox/navigation/ui/maps/PredictiveCacheControllerTest.kt b/libnavui-maps/src/test/java/com/mapbox/navigation/ui/maps/PredictiveCacheControllerTest.kt index 3d5c3caaf25..adc33969e1a 100644 --- a/libnavui-maps/src/test/java/com/mapbox/navigation/ui/maps/PredictiveCacheControllerTest.kt +++ b/libnavui-maps/src/test/java/com/mapbox/navigation/ui/maps/PredictiveCacheControllerTest.kt @@ -5,11 +5,13 @@ import com.mapbox.bindgen.Value import com.mapbox.common.TileStore import com.mapbox.common.TilesetDescriptor import com.mapbox.maps.MapboxMap +import com.mapbox.maps.OfflineManagerInterface import com.mapbox.maps.Style import com.mapbox.maps.StyleObjectInfo import com.mapbox.maps.TilesetDescriptorOptions import com.mapbox.maps.plugin.delegates.listeners.OnStyleLoadedListener import com.mapbox.navigation.base.options.PredictiveCacheLocationOptions +import com.mapbox.navigation.base.options.PredictiveCacheMapsOptions import com.mapbox.navigation.base.options.PredictiveCacheOptions import com.mapbox.navigation.core.internal.PredictiveCache import com.mapbox.navigation.testing.LoggingFrontendTestRule @@ -556,40 +558,58 @@ class PredictiveCacheControllerTest { @Test fun `check createMapsController`() { mockkObject(OfflineManagerProvider) { - val predictiveCacheOptions = mockk { - every { - predictiveCacheMapsOptions - } returns mockk { - every { minZoom } returns 40.toByte() - every { maxZoom } returns 50.toByte() - every { predictiveCacheLocationOptions } returns mockk() - } - every { predictiveCacheNavigationOptions } returns mockk { - every { predictiveCacheLocationOptions } returns mockk() - } - } + val locationOptions1 = mockk(relaxed = true) + val locationOptions2 = mockk(relaxed = true) + val predictiveCacheOptions = PredictiveCacheOptions.Builder() + .predictiveCacheMapsOptionsList( + listOf( + PredictiveCacheMapsOptions.Builder() + .minZoom(40.toByte()) + .maxZoom(50.toByte()) + .predictiveCacheLocationOptions(locationOptions1) + .build(), + PredictiveCacheMapsOptions.Builder() + .minZoom(20.toByte()) + .maxZoom(30.toByte()) + .predictiveCacheLocationOptions(locationOptions2) + .build(), + ) + ) + .build() every { PredictiveCache.createNavigationController(any()) } just Runs val mockedTileStore = mockk() every { TileStore.create(any()) } returns mockedTileStore val mockedMapboxMap = mockk(relaxed = true) { every { getResourceOptions().tileStore } returns mockedTileStore } - val slotListTilesetDescriptorOptions = mutableListOf() - val mockTilesetDescriptor: TilesetDescriptor = mockk() - every { - OfflineManagerProvider.provideOfflineManager(any()) - } returns mockk { + val mockTilesetDescriptor1: TilesetDescriptor = mockk() + val mockTilesetDescriptor2: TilesetDescriptor = mockk() + val offlineManagerInterface = mockk { + every { + createTilesetDescriptor( + match { options: TilesetDescriptorOptions -> + options.minZoom == 40.toByte() + } + ) + } returns mockTilesetDescriptor1 every { - createTilesetDescriptor(capture(slotListTilesetDescriptorOptions)) - } returns mockTilesetDescriptor + createTilesetDescriptor( + match { options: TilesetDescriptorOptions -> + options.minZoom == 20.toByte() + } + ) + } returns mockTilesetDescriptor2 } - val slotMapsPredictiveCacheLocationOptions = slot() every { - PredictiveCache.createMapsController( + OfflineManagerProvider.provideOfflineManager(any()) + } returns offlineManagerInterface + val slotDescriptorsToOptions = + slot>>() + every { + PredictiveCache.createMapsControllers( mockedMapboxMap, mockedTileStore, - mockTilesetDescriptor, - capture(slotMapsPredictiveCacheLocationOptions) + capture(slotDescriptorsToOptions) ) } just Runs @@ -600,15 +620,24 @@ class PredictiveCacheControllerTest { styles = listOf("mapbox://test_test", "non_valid://test_test") ) - assertEquals(1, slotListTilesetDescriptorOptions.size) - val slotTilesetDescriptorOptions = slotListTilesetDescriptorOptions.first() - assertEquals(40.toByte(), slotTilesetDescriptorOptions.minZoom) - assertEquals(50.toByte(), slotTilesetDescriptorOptions.maxZoom) - assertEquals("mapbox://test_test", slotTilesetDescriptorOptions.styleURI) - assertEquals( - predictiveCacheOptions.predictiveCacheMapsOptions.predictiveCacheLocationOptions, - slotMapsPredictiveCacheLocationOptions.captured - ) + val slotListTilesetDescriptorOptions = mutableListOf() + verify(exactly = 2) { + offlineManagerInterface.createTilesetDescriptor( + capture(slotListTilesetDescriptorOptions) + ) + } + assertEquals(40.toByte(), slotListTilesetDescriptorOptions[0].minZoom) + assertEquals(50.toByte(), slotListTilesetDescriptorOptions[0].maxZoom) + assertEquals("mapbox://test_test", slotListTilesetDescriptorOptions[0].styleURI) + assertEquals(20.toByte(), slotListTilesetDescriptorOptions[1].minZoom) + assertEquals(30.toByte(), slotListTilesetDescriptorOptions[1].maxZoom) + assertEquals("mapbox://test_test", slotListTilesetDescriptorOptions[1].styleURI) + + assertEquals(2, slotDescriptorsToOptions.captured.size) + assertEquals(mockTilesetDescriptor1, slotDescriptorsToOptions.captured[0].first) + assertEquals(locationOptions1, slotDescriptorsToOptions.captured[0].second) + assertEquals(mockTilesetDescriptor2, slotDescriptorsToOptions.captured[1].first) + assertEquals(locationOptions2, slotDescriptorsToOptions.captured[1].second) // "non_valid://test_test verify(exactly = 1) { errorHandler.onError(any()) } }