Skip to content

Commit 65d22c6

Browse files
Pablo Guardioladzinad
andauthored
Backport Copilot feature to release-v2.7 (#6776)
* cherry-pick #6387 * cherry-pick #6456 * NAVAND-750: introduce HistoryRecordingSessionState * invoke HistoryRecordingStateChangeObserver#onShouldStartRecording with current state * [NOT WORKING] HistoryRecorderHandle.buildCompositeRecorder is missing from NN v111 as it was introduced as part of NN v119 add multiple history recorders support (needed for copilot) (#6509) * bump nn dependency version to 111.1.0 * add copilot feature (#6572) * follow up to improve copilot kdocs (#6591) * use mapbox navigation app lifecycle owner instead of process lifecycle owner to support android auto and remove android x lifecycle process dependency not necessary anymore (#6609) * [copilot] start recording as soon as on should start recording is called to include deferred events as part of the current history file session (#6655) * [copilot] make sure created from attachments api is the same as startedAt (#6660) * use either mapbox navigation app lifecycle owner or process lifecycle owner based on if mapbox navigation app is set up or not respectively to support both use cases in which mapbox navigation app is or is not integrated from the client side and add is copilot initialized check to prevent issues if apis are misused (#6690) * fix conflicts * fix changelog Co-authored-by: Dzina Dybouskaya <32109537+dzinad@users.noreply.github.com> Co-authored-by: Dzina Dybouskaya <dzina.dybouskaya@mapbox.com>
1 parent 0aab8e0 commit 65d22c6

File tree

77 files changed

+6060
-317
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+6060
-317
lines changed

CHANGELOG.md

Lines changed: 67 additions & 66 deletions
Large diffs are not rendered by default.

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ libnavigation-util \
66
libnavigator \
77
libtrip-notification \
88
libnavigation-core \
9+
libnavigation-copilot \
910

1011
CORE_MODULES = $(RELEASED_CORE_MODULES)
1112

@@ -123,6 +124,7 @@ core-check-api: assemble-core-release
123124
./gradlew :libnavigator:checkApi -PhidePackage=com.mapbox.navigation.navigator.internal
124125
./gradlew :libtrip-notification:checkApi -PhidePackage=com.mapbox.navigation.trip.notification.internal
125126
./gradlew :libnavigation-core:checkApi -PhidePackage=com.mapbox.navigation.core.internal
127+
./gradlew :libnavigation-copilot:checkApi -PhidePackage=com.mapbox.navigation.copilot.internal
126128

127129
.PHONY: core-update-api
128130
core-update-api: assemble-core-release
@@ -133,6 +135,7 @@ core-update-api: assemble-core-release
133135
./gradlew :libnavigator:updateApi -PhidePackage=com.mapbox.navigation.navigator.internal
134136
./gradlew :libtrip-notification:updateApi -PhidePackage=com.mapbox.navigation.trip.notification.internal
135137
./gradlew :libnavigation-core:updateApi -PhidePackage=com.mapbox.navigation.core.internal
138+
./gradlew :libnavigation-copilot:updateApi -PhidePackage=com.mapbox.navigation.copilot.internal
136139

137140
.PHONY: assemble-ui-debug
138141
assemble-ui-debug:

gradle/dependencies.gradle

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ ext {
1313
// version which we should use in this build
1414
def mapboxNavigatorVersion = System.getenv("FORCE_MAPBOX_NAVIGATION_NATIVE_VERSION")
1515
if (mapboxNavigatorVersion == null || mapboxNavigatorVersion == '') {
16-
mapboxNavigatorVersion = '111.0.0'
16+
mapboxNavigatorVersion = '111.1.0'
1717
}
1818
println("Navigation Native version: " + mapboxNavigatorVersion)
1919

@@ -37,6 +37,7 @@ ext {
3737
androidXAnnotationVersion : '1.2.0',
3838
androidXFragmentVersion : '1.4.0',
3939
androidXDataStore : '1.0.0',
40+
androidXWorkManager : '2.7.1',
4041
cardViewVersion : '1.0.0',
4142
recyclerViewVersion : '1.1.0',
4243
materialDesignVersion : '1.1.0',
@@ -133,11 +134,13 @@ ext {
133134
androidXFragment : "androidx.fragment:fragment-ktx:${version.androidXFragmentVersion}",
134135
androidXArchCoreTesting : "androidx.arch.core:core-testing:${version.androidXArchCoreVersion}",
135136
androidXDataStore : "androidx.datastore:datastore-preferences:${version.androidXDataStore}",
137+
androidXWorkManager : "androidx.work:work-runtime-ktx:${version.androidXWorkManager}",
136138

137139
// lifecycle
138140
androidXLifecycleRuntime : "androidx.lifecycle:lifecycle-runtime-ktx:${version.androidXLifecycle}",
139141
androidXLifecycleLivedata : "androidx.lifecycle:lifecycle-livedata-ktx:${version.androidXLifecycle}",
140142
androidXLifecycleViewmodel: "androidx.lifecycle:lifecycle-viewmodel-ktx:${version.androidXLifecycle}",
143+
androidXLifecycleProcess : "androidx.lifecycle:lifecycle-process:${version.androidXLifecycle}",
141144
androidXLifecycleTesting : "androidx.lifecycle:lifecycle-runtime-testing:${version.androidXLifecycle}",
142145

143146
// square crew

gradle/publish.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ def sdkNameMap = [:]
5353
sdkNameMap["libnavigation-android"] = "mobile-navigation-android"
5454
sdkNameMap["libnavigation-base"] = "mobile-navigation-base"
5555
sdkNameMap["libnavigation-core"] = "mobile-navigation-core"
56+
sdkNameMap["libnavigation-copilot"] = "mobile-navigation-copilot"
5657
sdkNameMap["libnavigation-metrics"] = "mobile-navigation-metrics"
5758
sdkNameMap["libnavigator"] = "mobile-navigation-navigator"
5859
sdkNameMap["libtrip-notification"] = "mobile-navigation-notification"
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package com.mapbox.navigation.instrumentation_tests.core
2+
3+
import android.location.Location
4+
import com.mapbox.api.directions.v5.models.RouteOptions
5+
import com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI
6+
import com.mapbox.navigation.base.extensions.applyDefaultNavigationOptions
7+
import com.mapbox.navigation.base.extensions.applyLanguageAndVoiceUnitOptions
8+
import com.mapbox.navigation.base.options.NavigationOptions
9+
import com.mapbox.navigation.base.route.NavigationRoute
10+
import com.mapbox.navigation.base.route.RouterOrigin
11+
import com.mapbox.navigation.core.DeveloperMetadata
12+
import com.mapbox.navigation.core.DeveloperMetadataObserver
13+
import com.mapbox.navigation.core.MapboxNavigation
14+
import com.mapbox.navigation.core.MapboxNavigationProvider
15+
import com.mapbox.navigation.core.directions.session.RoutesExtra
16+
import com.mapbox.navigation.core.internal.HistoryRecordingSessionState
17+
import com.mapbox.navigation.core.internal.HistoryRecordingStateChangeObserver
18+
import com.mapbox.navigation.core.internal.extensions.registerHistoryRecordingStateChangeObserver
19+
import com.mapbox.navigation.instrumentation_tests.activity.EmptyTestActivity
20+
import com.mapbox.navigation.instrumentation_tests.utils.MapboxNavigationRule
21+
import com.mapbox.navigation.instrumentation_tests.utils.coroutines.clearNavigationRoutesAndWaitForUpdate
22+
import com.mapbox.navigation.instrumentation_tests.utils.coroutines.routesUpdates
23+
import com.mapbox.navigation.instrumentation_tests.utils.coroutines.sdkTest
24+
import com.mapbox.navigation.instrumentation_tests.utils.coroutines.setNavigationRoutesAndAwaitError
25+
import com.mapbox.navigation.instrumentation_tests.utils.history.MapboxHistoryTestRule
26+
import com.mapbox.navigation.instrumentation_tests.utils.routes.MockRoute
27+
import com.mapbox.navigation.instrumentation_tests.utils.routes.RoutesProvider
28+
import com.mapbox.navigation.testing.ui.BaseTest
29+
import com.mapbox.navigation.testing.ui.utils.getMapboxAccessTokenFromResources
30+
import com.mapbox.navigation.testing.ui.utils.runOnMainSync
31+
import kotlinx.coroutines.flow.filter
32+
import kotlinx.coroutines.flow.first
33+
import org.junit.Assert.assertEquals
34+
import org.junit.Before
35+
import org.junit.Rule
36+
import org.junit.Test
37+
38+
@OptIn(ExperimentalPreviewMapboxNavigationAPI::class)
39+
class CopilotIntegrationTest : BaseTest<EmptyTestActivity>(EmptyTestActivity::class.java) {
40+
41+
private lateinit var mapboxNavigation: MapboxNavigation
42+
private lateinit var mockRoute: MockRoute
43+
private lateinit var routes: List<NavigationRoute>
44+
45+
@get:Rule
46+
val mapboxNavigationRule = MapboxNavigationRule()
47+
48+
@get:Rule
49+
val mapboxHistoryTestRule = MapboxHistoryTestRule()
50+
51+
override fun setupMockLocation(): Location {
52+
mockRoute = RoutesProvider.dc_very_short(activity)
53+
routes = NavigationRoute.create(
54+
mockRoute.routeResponse,
55+
RouteOptions.builder()
56+
.applyDefaultNavigationOptions()
57+
.applyLanguageAndVoiceUnitOptions(activity)
58+
.baseUrl(mockWebServerRule.baseUrl)
59+
.coordinatesList(mockRoute.routeWaypoints).build(),
60+
RouterOrigin.Offboard
61+
)
62+
return mockLocationUpdatesRule.generateLocationUpdate {
63+
latitude = mockRoute.routeWaypoints.first().latitude()
64+
longitude = mockRoute.routeWaypoints.first().longitude()
65+
}
66+
}
67+
68+
@Before
69+
fun setUp() {
70+
runOnMainSync {
71+
mapboxNavigation = MapboxNavigationProvider.create(
72+
NavigationOptions.Builder(activity)
73+
.accessToken(getMapboxAccessTokenFromResources(activity))
74+
.build()
75+
)
76+
mapboxHistoryTestRule.historyRecorder = mapboxNavigation.historyRecorder
77+
}
78+
}
79+
80+
@Test
81+
fun copilotObserverReceivesSameIdsAsDeveloperMetadata() = sdkTest {
82+
val collectedDeveloperMetadatas = mutableListOf<DeveloperMetadata>()
83+
val developerMetadataObserver = DeveloperMetadataObserver {
84+
collectedDeveloperMetadatas.add(it)
85+
}
86+
val startedSessionObserverIds = mutableListOf<String>()
87+
val historyRecordingStateObserver = object : HistoryRecordingStateChangeObserver {
88+
override fun onShouldStartRecording(state: HistoryRecordingSessionState) {
89+
startedSessionObserverIds.add(state.sessionId)
90+
}
91+
override fun onShouldStopRecording(state: HistoryRecordingSessionState) {
92+
}
93+
94+
override fun onShouldCancelRecording(state: HistoryRecordingSessionState) {
95+
}
96+
}
97+
mapboxNavigation.registerDeveloperMetadataObserver(developerMetadataObserver)
98+
mockWebServerRule.requestHandlers.addAll(mockRoute.mockRequestHandlers)
99+
mapboxNavigation.historyRecorder.startRecording()
100+
mapboxNavigation.registerHistoryRecordingStateChangeObserver(historyRecordingStateObserver)
101+
102+
transitionFromIdleToFreeDrive()
103+
transitionFromFreeDriveToActiveGuidance()
104+
transitionFromActiveGuidanceToFreeDrive()
105+
transitionFromFreeDriveToStubActiveGuidanceAndBackToFreeDrive()
106+
transitionFromFreeDriveToIdle()
107+
108+
val collectedIds = collectedDeveloperMetadatas.map { it.copilotSessionId }
109+
// first and last are idle: not recorded by HistoryRecordingStateChangeObserver
110+
assertEquals(startedSessionObserverIds, collectedIds.drop(1).dropLast(1))
111+
}
112+
113+
private fun transitionFromIdleToFreeDrive() {
114+
mapboxNavigation.startTripSession()
115+
}
116+
117+
private suspend fun transitionFromFreeDriveToActiveGuidance() {
118+
mapboxNavigation.setNavigationRoutes(routes)
119+
mapboxNavigation.routesUpdates()
120+
.filter { it.reason == RoutesExtra.ROUTES_UPDATE_REASON_NEW }
121+
.first()
122+
}
123+
124+
private suspend fun transitionFromActiveGuidanceToFreeDrive() {
125+
mapboxNavigation.clearNavigationRoutesAndWaitForUpdate()
126+
}
127+
128+
private suspend fun transitionFromFreeDriveToStubActiveGuidanceAndBackToFreeDrive() {
129+
mapboxNavigation.setNavigationRoutesAndAwaitError(routes, 6)
130+
}
131+
132+
private fun transitionFromFreeDriveToIdle() {
133+
mapboxNavigation.stopTripSession()
134+
}
135+
}

0 commit comments

Comments
 (0)