summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Auto Companion <no-reply@google.com>2023-09-25 23:29:25 -0700
committerAlexandre Walsh <alwa@google.com>2023-10-05 20:43:56 +0000
commitd6307bddcdb3f87798901252e2559c98d36aa64d (patch)
tree8b2b79c6ed85220ed63533ece0fb788151efda07
parent0531a2714f556a295ab410ada44ec4898718efae (diff)
downloadCompanionDeviceSupport-d6307bddcdb3f87798901252e2559c98d36aa64d.tar.gz
Companion SDK version: 2.0.1 Compatible Android Mobile Version: 1.0.0 Compatible IOS Mobile Version: 1.0.0 Release-Id: aae-companiondevice-android_20230925.01_RC00 Change-Id: I9dd6116e5dbf3fa93f19206142863bba68a2cb49
-rw-r--r--companiondevice/build.gradle6
-rw-r--r--libs/connecteddevice/res/values/config.xml4
-rw-r--r--libs/connecteddevice/src/com/google/android/connecteddevice/api/FeatureConnector.kt20
-rw-r--r--libs/connecteddevice/src/com/google/android/connecteddevice/api/SafeConnector.kt19
-rw-r--r--libs/connecteddevice/src/com/google/android/connecteddevice/core/MultiProtocolDeviceController.kt10
-rw-r--r--libs/connecteddevice/src/com/google/android/connecteddevice/metrics/CompanionStatsLog.java46
-rw-r--r--libs/connecteddevice/src/com/google/android/connecteddevice/metrics/EventMetricLogger.kt116
-rw-r--r--libs/connecteddevice/src/com/google/android/connecteddevice/service/ConnectedDeviceService.java3
-rw-r--r--libs/connecteddevice/tests/unit/src/com/google/android/connecteddevice/api/FeatureConnectorTest.kt194
9 files changed, 321 insertions, 97 deletions
diff --git a/companiondevice/build.gradle b/companiondevice/build.gradle
index cbf8085..1abf7c7 100644
--- a/companiondevice/build.gradle
+++ b/companiondevice/build.gradle
@@ -8,13 +8,13 @@ buildscript {
}
android {
- compileSdkVersion 33
+ compileSdkVersion 34
defaultConfig {
applicationId "com.google.android.companiondevicesupport"
minSdkVersion 29
- targetSdkVersion 33
- versionCode 2161
+ targetSdkVersion 34
+ versionCode 2197
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
diff --git a/libs/connecteddevice/res/values/config.xml b/libs/connecteddevice/res/values/config.xml
index 910e553..ee45330 100644
--- a/libs/connecteddevice/res/values/config.xml
+++ b/libs/connecteddevice/res/values/config.xml
@@ -17,8 +17,8 @@
<resources>
<!-- Current version of the SDK -->
- <string name="hu_companion_sdk_version" translatable="false">2.0.0</string>
- <integer name="hu_companion_binder_version" translatable="false">0</integer>
+ <string name="hu_companion_sdk_version" translatable="false">2.0.1</string>
+ <integer name="hu_companion_binder_version" translatable="false">1</integer>
<!-- Mobile SDK of later version should be compatible with the HU SDK. -->
<string name="compatible_min_mobile_version_android" translatable="false">1.0.0</string>
<string name="compatible_min_mobile_version_ios" translatable="false">1.0.0</string>
diff --git a/libs/connecteddevice/src/com/google/android/connecteddevice/api/FeatureConnector.kt b/libs/connecteddevice/src/com/google/android/connecteddevice/api/FeatureConnector.kt
index 4f61708..2631c56 100644
--- a/libs/connecteddevice/src/com/google/android/connecteddevice/api/FeatureConnector.kt
+++ b/libs/connecteddevice/src/com/google/android/connecteddevice/api/FeatureConnector.kt
@@ -59,7 +59,6 @@ import java.util.concurrent.locks.ReentrantLock
class FeatureConnector(
private val context: Context,
override val featureId: ParcelUuid,
- override val callback: SafeConnector.Callback,
private val minSupportedVersion: Int = 0
) : SafeConnector {
@@ -75,6 +74,11 @@ class FeatureConnector(
private val queryIdGenerator = QueryIdGenerator()
+ override lateinit var callback: SafeConnector.Callback
+
+ override val isConnected: Boolean
+ get() = coordinatorProxy != null && !waitingForConnection.get()
+
override val connectedDevices: List<String>
get() = coordinatorProxy?.getConnectedDevices() ?: emptyList()
@@ -128,6 +132,10 @@ class FeatureConnector(
loge("Incompatible companion platform version. Aborting.")
return
}
+ if (!this@FeatureConnector::callback.isInitialized) {
+ loge("FeatureConnector callback was not initialized. Aborting.")
+ return
+ }
coordinatorProxy =
when {
platformVersion > 0 ->
@@ -169,8 +177,9 @@ class FeatureConnector(
}
}
- init {
- logd("Initiating connection to companion platform.")
+ override fun connect(callback: SafeConnector.Callback) {
+ logd("Initiating connection to companion platform and initializing callback.")
+ this.callback = callback
bindToService(ACTION_QUERY_API_VERSION, versionCheckConnection)
}
@@ -220,7 +229,7 @@ class FeatureConnector(
}
}
- override fun cleanUp() {
+ override fun disconnect() {
logd("Disconnecting from the companion platform.")
coordinatorProxy?.cleanUp()
coordinatorProxy = null
@@ -240,7 +249,7 @@ class FeatureConnector(
private fun onServiceDisconnected() {
logd("Service has disconnected. Cleaning up.")
- cleanUp()
+ disconnect()
}
private fun onNullBinding() {
@@ -411,6 +420,7 @@ class FeatureConnector(
/** A generator of unique IDs for queries. */
private class QueryIdGenerator {
private val messageId = AtomicInteger(0)
+
fun next(): Int {
val current = messageId.getAndIncrement()
messageId.compareAndSet(Int.MAX_VALUE, 0)
diff --git a/libs/connecteddevice/src/com/google/android/connecteddevice/api/SafeConnector.kt b/libs/connecteddevice/src/com/google/android/connecteddevice/api/SafeConnector.kt
index 43d7309..513a47e 100644
--- a/libs/connecteddevice/src/com/google/android/connecteddevice/api/SafeConnector.kt
+++ b/libs/connecteddevice/src/com/google/android/connecteddevice/api/SafeConnector.kt
@@ -32,18 +32,23 @@ interface SafeConnector {
val featureId: ParcelUuid
/** [Callback] for connection events. */
- val callback: Callback
+ var callback: Callback
/** List of ids for the currently connected devices. */
val connectedDevices: List<String>
+ /** Whether this [SafeConnector] is currently connected and ready for interaction. */
+ val isConnected: Boolean
+
+ /** Establishes a connection to the companion platform. */
+ fun connect(callback: Callback)
+
/**
- * Cleans up services and feature coordinators attached to the companion platform.
- * Calling cleanUp will disconnect the feature from the platform and prevent it from receiving
- * Companion related events. Expectation is that cleanUp will only be called before the
- * SafeConnector object is disposed.
- */
- fun cleanUp()
+ * Cleans up services and feature coordinators attached to the companion platform. Will disconnect
+ * the feature from the platform and prevent it from receiving Companion-related events.
+ * Expectation is that disconnect will only be called before the SafeConnector object is disposed.
+ */
+ fun disconnect()
/** Sends message to a device. */
fun sendMessage(deviceId: String, message: ByteArray)
diff --git a/libs/connecteddevice/src/com/google/android/connecteddevice/core/MultiProtocolDeviceController.kt b/libs/connecteddevice/src/com/google/android/connecteddevice/core/MultiProtocolDeviceController.kt
index bec3c8e..6436fda 100644
--- a/libs/connecteddevice/src/com/google/android/connecteddevice/core/MultiProtocolDeviceController.kt
+++ b/libs/connecteddevice/src/com/google/android/connecteddevice/core/MultiProtocolDeviceController.kt
@@ -164,7 +164,7 @@ constructor(
val driverDevices = storage.driverAssociatedDevices
for (device in driverDevices) {
if (device.isConnectionEnabled) {
- initiateConnectionToDevice(UUID.fromString(device.deviceId))
+ initiateConnectionToDevice(UUID.fromString(device.deviceId))
}
}
if (!enablePassenger) {
@@ -174,7 +174,7 @@ constructor(
logd(TAG, "Initiating connections with passenger devices.")
val passengerDevices = storage.passengerAssociatedDevices
for (device in passengerDevices) {
- initiateConnectionToDevice(UUID.fromString(device.deviceId))
+ initiateConnectionToDevice(UUID.fromString(device.deviceId))
}
}
}
@@ -406,6 +406,7 @@ constructor(
) =
object : IDiscoveryCallback.Stub() {
override fun onDeviceConnected(protocolId: String) {
+ metricLogger.pushConnectedEvent()
logd(
TAG,
"New connection protocol connected for $deviceId. id: $protocolId, protocol: $protocol"
@@ -443,6 +444,7 @@ constructor(
}
override fun onDiscoveryStartedSuccessfully() {
+ metricLogger.pushDiscoveryStartedEvent()
logd(TAG, "Connection discovery started successfully.")
}
@@ -507,6 +509,7 @@ constructor(
}
override fun onDiscoveryStartedSuccessfully() {
+ metricLogger.pushAssociationStartedEvent()
associationCallback.aliveOrNull()?.onAssociationStartSuccess(response)
?: run {
loge(
@@ -629,6 +632,7 @@ constructor(
}
private fun handleAssociationError(error: Int, device: ConnectedRemoteDevice) {
+ metricLogger.pushCompanionErrorEvent(error, duringAssociation = device.callback != null)
device.callback?.aliveOrNull()?.onAssociationError(error)
?: run {
loge(
@@ -664,7 +668,7 @@ constructor(
callback.onSecureChannelEstablished(connectedDevice)
}
EventLog.onSecureChannelEstablished()
- metricLogger.onSecureChannelEstablished()
+ metricLogger.pushSecureChannelEstablishedEvent()
}
override fun onEstablishSecureChannelFailure(error: ChannelError) {
diff --git a/libs/connecteddevice/src/com/google/android/connecteddevice/metrics/CompanionStatsLog.java b/libs/connecteddevice/src/com/google/android/connecteddevice/metrics/CompanionStatsLog.java
index 08c2c19..11e7dab 100644
--- a/libs/connecteddevice/src/com/google/android/connecteddevice/metrics/CompanionStatsLog.java
+++ b/libs/connecteddevice/src/com/google/android/connecteddevice/metrics/CompanionStatsLog.java
@@ -17,6 +17,13 @@ public final class CompanionStatsLog {
*/
public static final int COMPANION_STATUS_CHANGED = 210401;
+ /**
+ * CompanionErrorReported companion_error_reported<br>
+ * Usage: StatsLog.write(StatsLog.COMPANION_ERROR_REPORTED, int uid, int companion_error, boolean
+ * during_association);<br>
+ */
+ public static final int COMPANION_ERROR_REPORTED = 210402;
+
// Constants for enum values.
// Values for CompanionStatusChanged.companion_status
@@ -29,6 +36,28 @@ public final class CompanionStatsLog {
4;
public static final int COMPANION_STATUS_CHANGED__COMPANION_STATUS__DISCONNECTED = 5;
+ // Values for CompanionErrorReported.companion_error
+ public static final int COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_UNSPECIFIED = 0;
+ public static final int
+ COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_HANDSHAKE = 1;
+ public static final int COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_MSG = 2;
+ public static final int
+ COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_DEVICE_ID = 3;
+ public static final int
+ COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_VERIFICATION = 4;
+ public static final int
+ COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_CHANNEL_STATE = 5;
+ public static final int
+ COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_ENCRYPTION_KEY = 6;
+ public static final int COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_STORAGE_FAILURE =
+ 7;
+ public static final int
+ COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_SECURITY_KEY = 8;
+ public static final int
+ COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INSECURE_RECIPIENT_ID_DETECTED = 9;
+ public static final int
+ COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_UNEXPECTED_DISCONNECTION = 10;
+
// Annotation constants.
public static final byte ANNOTATION_ID_IS_UID = StatsLog.ANNOTATION_ID_IS_UID;
public static final byte ANNOTATION_ID_TRUNCATE_TIMESTAMP =
@@ -43,10 +72,27 @@ public final class CompanionStatsLog {
public static final byte ANNOTATION_ID_STATE_NESTED = StatsLog.ANNOTATION_ID_STATE_NESTED;
// Write methods
+ public static void write(int code, int arg1, int arg2, boolean arg3) {
+ final StatsEvent.Builder builder = StatsEvent.newBuilder();
+ builder.setAtomId(code);
+ builder.writeInt(arg1);
+ if (COMPANION_ERROR_REPORTED == code) {
+ builder.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true);
+ }
+ builder.writeInt(arg2);
+ builder.writeBoolean(arg3);
+
+ builder.usePooledBuffer();
+ StatsLog.write(builder.build());
+ }
+
public static void write(int code, int arg1, int arg2, long arg3) {
final StatsEvent.Builder builder = StatsEvent.newBuilder();
builder.setAtomId(code);
builder.writeInt(arg1);
+ if (COMPANION_STATUS_CHANGED == code) {
+ builder.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true);
+ }
builder.writeInt(arg2);
builder.writeLong(arg3);
diff --git a/libs/connecteddevice/src/com/google/android/connecteddevice/metrics/EventMetricLogger.kt b/libs/connecteddevice/src/com/google/android/connecteddevice/metrics/EventMetricLogger.kt
index bd3b013..a7a7a54 100644
--- a/libs/connecteddevice/src/com/google/android/connecteddevice/metrics/EventMetricLogger.kt
+++ b/libs/connecteddevice/src/com/google/android/connecteddevice/metrics/EventMetricLogger.kt
@@ -1,19 +1,119 @@
package com.google.android.connecteddevice.metrics
import android.content.Context
-import android.os.Build
+import com.google.android.connecteddevice.model.Errors
+import android.os.RemoteException
+import com.google.android.connecteddevice.util.SafeLog.loge
+import java.time.Duration
+import java.time.Instant
/** Logger to report Companion events to statsd */
class EventMetricLogger(private val context: Context) {
private val uid = context.packageManager.getPackageUid(context.packageName, 0)
- fun onSecureChannelEstablished() {
- // TODO(b/273968556): unable to find related System API on Android Q build.
- if(Build.VERSION.SDK_INT < Build.VERSION_CODES.R ) return
- CompanionStatsLog.write(
- CompanionStatsLog.COMPANION_STATUS_CHANGED,
- uid,
+ /** The time when association or reconnect discovery get started. */
+ private var discoveryStartedTime = Instant.EPOCH
+ private var connectedTime = Instant.EPOCH
+ private val defaultDuration = Duration.ZERO
+
+ /** Pushes the association discovery started event to statsd. */
+ fun pushAssociationStartedEvent() {
+ pushEventsWithoutException(
+ CompanionStatsLog.COMPANION_STATUS_CHANGED__COMPANION_STATUS__ASSOCIATION_STARTED,
+ defaultDuration
+ )
+ }
+
+ /** Pushes the reconnection discovery started event to statsd. */
+ fun pushDiscoveryStartedEvent() {
+ discoveryStartedTime = Instant.now()
+ pushEventsWithoutException(
+ CompanionStatsLog.COMPANION_STATUS_CHANGED__COMPANION_STATUS__DISCOVERY_STARTED,
+ defaultDuration
+ )
+ }
+
+ /** Pushes device get reconnected event to statsd. */
+ fun pushConnectedEvent() {
+ connectedTime = Instant.now()
+ pushEventsWithoutException(
+ CompanionStatsLog.COMPANION_STATUS_CHANGED__COMPANION_STATUS__CONNECTED,
+ Duration.between(discoveryStartedTime, connectedTime)
+ )
+ }
+
+ /** Pushes the secure channel established event to statsd. */
+ fun pushSecureChannelEstablishedEvent() {
+ pushEventsWithoutException(
CompanionStatsLog.COMPANION_STATUS_CHANGED__COMPANION_STATUS__SECURE_CHANNEL_ESTABLISHED,
- 0
+ Duration.between(connectedTime, Instant.now())
)
}
+
+ /** Pushes device disconnected event to statsd. */
+ fun pushDisconnectedEvent() {
+ pushEventsWithoutException(
+ CompanionStatsLog.COMPANION_STATUS_CHANGED__COMPANION_STATUS__DISCONNECTED,
+ defaultDuration
+ )
+ }
+
+ // TODO(b/298248724): Reports more errors.
+ fun pushCompanionErrorEvent(error: Int, duringAssociation: Boolean = false) {
+ val errorId =
+ when (error) {
+ Errors.DEVICE_ERROR_INVALID_HANDSHAKE ->
+ CompanionStatsLog
+ .COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_HANDSHAKE
+ Errors.DEVICE_ERROR_INVALID_MSG ->
+ CompanionStatsLog.COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_MSG
+ Errors.DEVICE_ERROR_INVALID_DEVICE_ID ->
+ CompanionStatsLog
+ .COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_DEVICE_ID
+ Errors.DEVICE_ERROR_INVALID_VERIFICATION ->
+ CompanionStatsLog
+ .COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_VERIFICATION
+ Errors.DEVICE_ERROR_INVALID_CHANNEL_STATE ->
+ CompanionStatsLog
+ .COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_CHANNEL_STATE
+ Errors.DEVICE_ERROR_INVALID_ENCRYPTION_KEY ->
+ CompanionStatsLog
+ .COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_ENCRYPTION_KEY
+ Errors.DEVICE_ERROR_STORAGE_FAILURE ->
+ CompanionStatsLog.COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_STORAGE_FAILURE
+ Errors.DEVICE_ERROR_INVALID_SECURITY_KEY ->
+ CompanionStatsLog
+ .COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_SECURITY_KEY
+ Errors.DEVICE_ERROR_INSECURE_RECIPIENT_ID_DETECTED ->
+ CompanionStatsLog
+ .COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INSECURE_RECIPIENT_ID_DETECTED
+ Errors.DEVICE_ERROR_UNEXPECTED_DISCONNECTION ->
+ CompanionStatsLog
+ .COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_UNEXPECTED_DISCONNECTION
+ else ->
+ CompanionStatsLog.COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_UNSPECIFIED
+ }
+ try {
+ CompanionStatsLog.write(
+ CompanionStatsLog.COMPANION_ERROR_REPORTED,
+ uid,
+ errorId,
+ duringAssociation
+ )
+ } catch (e: NoClassDefFoundError) {
+ loge(TAG, "Encounter error when pushing Companion error events to statsd; skip.")
+ }
+ }
+
+ private fun pushEventsWithoutException(eventId: Int, duration: Duration) {
+ try {
+ CompanionStatsLog.write(
+ CompanionStatsLog.COMPANION_STATUS_CHANGED, uid, eventId, duration.toMillis())
+ } catch (e: NoClassDefFoundError) {
+ loge(TAG, "Encounter error when pushing Companion events to statsd; skip.")
+ }
+ }
+
+ companion object {
+ private const val TAG = "EventMetricLogger"
+ }
}
diff --git a/libs/connecteddevice/src/com/google/android/connecteddevice/service/ConnectedDeviceService.java b/libs/connecteddevice/src/com/google/android/connecteddevice/service/ConnectedDeviceService.java
index bd36f00..6dc294f 100644
--- a/libs/connecteddevice/src/com/google/android/connecteddevice/service/ConnectedDeviceService.java
+++ b/libs/connecteddevice/src/com/google/android/connecteddevice/service/ConnectedDeviceService.java
@@ -232,7 +232,8 @@ public final class ConnectedDeviceService extends TrunkService {
return;
}
writer.printf(
- "Companion SDK version is %s", getResources().getString(R.string.hu_companion_sdk_version));
+ "Companion SDK version is %s\n",
+ getResources().getString(R.string.hu_companion_sdk_version));
}
private void cleanup() {
diff --git a/libs/connecteddevice/tests/unit/src/com/google/android/connecteddevice/api/FeatureConnectorTest.kt b/libs/connecteddevice/tests/unit/src/com/google/android/connecteddevice/api/FeatureConnectorTest.kt
index 5486665..c691605 100644
--- a/libs/connecteddevice/tests/unit/src/com/google/android/connecteddevice/api/FeatureConnectorTest.kt
+++ b/libs/connecteddevice/tests/unit/src/com/google/android/connecteddevice/api/FeatureConnectorTest.kt
@@ -28,6 +28,7 @@ import com.google.common.truth.Truth.assertThat
import com.google.protobuf.ExtensionRegistryLite
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
@@ -64,11 +65,23 @@ class FeatureConnectorTest {
private val testCoordinatorProxy = spy(TestCompanionApiProxy(true, listOf(testDeviceId)))
+ private lateinit var versionZeroConnector: FeatureConnector
+ private lateinit var versionOneConnector: FeatureConnector
+ private lateinit var versionTwoConnector: FeatureConnector
+
+ @Before
+ fun setUp() {
+ versionZeroConnector = FeatureConnector(context, testFeatureId, minSupportedVersion = 0)
+ versionOneConnector = FeatureConnector(context, testFeatureId, minSupportedVersion = 1)
+ versionTwoConnector = FeatureConnector(context, testFeatureId, minSupportedVersion = 2)
+ }
+
@Test
- fun onInit_negativeVersions_aborts() {
+ fun onConnect_negativeVersions_aborts() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = -1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, -1)
+ val connector = FeatureConnector(context, testFeatureId, minSupportedVersion = -1)
+ connector.connect(mockCallback)
assertThat(context.bindingActions)
.containsExactly(ACTION_QUERY_API_VERSION, ACTION_BIND_FEATURE_COORDINATOR)
@@ -76,10 +89,11 @@ class FeatureConnectorTest {
}
@Test
- fun onInit_clientV1_platformV0_bindToFeatureCoordinator() {
+ fun onConnect_clientV1_platformV0_bindToFeatureCoordinator() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 0
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
assertThat(connector.coordinatorProxy is LegacyApiProxy).isTrue()
assertThat(context.bindingActions)
@@ -87,10 +101,11 @@ class FeatureConnectorTest {
}
@Test
- fun onInit_clientV1_platformV1_bindToFeatureCoordinator() {
+ fun onConnect_clientV1_platformV1_bindToFeatureCoordinator() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
assertThat(connector.coordinatorProxy is SafeApiProxy).isTrue()
assertThat(context.bindingActions)
@@ -98,10 +113,11 @@ class FeatureConnectorTest {
}
@Test
- fun onInit_clientV1_platformV2_bindToFeatureCoordinator() {
+ fun onConnect_clientV1_platformV2_bindToFeatureCoordinator() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 2
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
assertThat(connector.coordinatorProxy is SafeApiProxy).isTrue()
assertThat(context.bindingActions)
@@ -109,10 +125,11 @@ class FeatureConnectorTest {
}
@Test
- fun onInit_clientV2_platformV0_bindToFeatureCoordinator() {
+ fun onConnect_clientV2_platformV0_bindToFeatureCoordinator() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 0
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 2)
+ val connector = versionTwoConnector
+ connector.connect(mockCallback)
assertThat(connector.coordinatorProxy is LegacyApiProxy).isTrue()
assertThat(context.bindingActions)
@@ -120,11 +137,12 @@ class FeatureConnectorTest {
}
@Test
- fun onInit_clientV1_platformV1_incorrectServiceIssuesApiNotSupportedCallback() {
+ fun onConnect_clientV1_platformV1_incorrectServiceIssuesApiNotSupportedCallback() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
val incorrectServiceContext = IncorrectServiceContext(mockPackageManager)
- val connector = FeatureConnector(incorrectServiceContext, testFeatureId, mockCallback, 1)
+ val connector = FeatureConnector(incorrectServiceContext, testFeatureId, 1)
+ connector.connect(mockCallback)
assertThat(connector.coordinatorProxy).isNull()
assertThat(connector.platformVersion).isNull()
@@ -133,10 +151,11 @@ class FeatureConnectorTest {
}
@Test
- fun onInit_clientV2_platformV1_issuesApiNotSupportedCallback() {
+ fun onConnect_clientV2_platformV1_issuesApiNotSupportedCallback() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 2)
+ val connector = versionTwoConnector
+ connector.connect(mockCallback)
assertThat(connector.coordinatorProxy).isNull()
assertThat(connector.platformVersion).isNull()
@@ -145,10 +164,11 @@ class FeatureConnectorTest {
}
@Test
- fun onInit_clientV2_platformV2_bindToFeatureCoordinator() {
+ fun onConnect_clientV2_platformV2_bindToFeatureCoordinator() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 2
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 2)
+ val connector = versionTwoConnector
+ connector.connect(mockCallback)
assertThat(connector.coordinatorProxy is SafeApiProxy).isTrue()
assertThat(context.bindingActions)
@@ -156,10 +176,11 @@ class FeatureConnectorTest {
}
@Test
- fun onInit_clientV2_platformV3_bindToFeatureCoordinator() {
+ fun onConnect_clientV2_platformV3_bindToFeatureCoordinator() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 3
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 2)
+ val connector = versionTwoConnector
+ connector.connect(mockCallback)
assertThat(connector.coordinatorProxy is SafeApiProxy).isTrue()
assertThat(context.bindingActions)
@@ -182,17 +203,19 @@ class FeatureConnectorTest {
}
setQueryIntentServicesAnswer(nullIntentAnswer)
mockPlatformVersion = 0
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
assertThat(connector.coordinatorProxy).isNull()
verify(mockCallback).onFailedToConnect()
}
@Test
- fun onSuccessfulInit_doesNotRetryBind() {
+ fun onSuccessfulConnect_doesNotRetryBind() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
assertThat(connector.bindAttempts == 0).isTrue()
assertThat(context.bindingActions)
@@ -205,7 +228,8 @@ class FeatureConnectorTest {
mockPlatformVersion = 1
val failingContext = FailingContext(mockPackageManager)
val shadowLooper = Shadows.shadowOf(Looper.getMainLooper())
- val connector = FeatureConnector(failingContext, testFeatureId, mockCallback, 1)
+ val connector = FeatureConnector(failingContext, testFeatureId, 1)
+ connector.connect(mockCallback)
repeat(FeatureConnector.MAX_BIND_ATTEMPTS) { shadowLooper.runToEndOfTasks() }
@@ -220,7 +244,8 @@ class FeatureConnectorTest {
mockPlatformVersion = 0
val flakyContext = FailingLegacyContext(mockPackageManager)
val shadowLooper = Shadows.shadowOf(Looper.getMainLooper())
- val connector = FeatureConnector(flakyContext, testFeatureId, mockCallback, 1)
+ val connector = FeatureConnector(flakyContext, testFeatureId, 1)
+ connector.connect(mockCallback)
repeat(FeatureConnector.MAX_BIND_ATTEMPTS) { shadowLooper.runToEndOfTasks() }
@@ -237,7 +262,8 @@ class FeatureConnectorTest {
mockPlatformVersion = 0
val flakyContext = FlakyLegacyContext(mockPackageManager)
val shadowLooper = Shadows.shadowOf(Looper.getMainLooper())
- val connector = FeatureConnector(flakyContext, testFeatureId, mockCallback, 1)
+ val connector = FeatureConnector(flakyContext, testFeatureId, 1)
+ connector.connect(mockCallback)
// Should repeat once for version query bind attempt, then reset, then MAX_BIND_ATTEMPTS times
// for feature coordinator bind attempt.
@@ -261,7 +287,8 @@ class FeatureConnectorTest {
fun onDisconnected_invokedOnVersionCheckServiceDisconnected() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.versionCheckConnection.onServiceDisconnected(
ComponentName(PACKAGE_NAME, VERSION_NAME)
@@ -273,7 +300,8 @@ class FeatureConnectorTest {
fun onDisconnected_invokedOnVersionCheckDeadBinding() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.versionCheckConnection.onBindingDied(ComponentName(PACKAGE_NAME, VERSION_NAME))
verify(mockCallback).onDisconnected()
@@ -283,7 +311,8 @@ class FeatureConnectorTest {
fun onDisconnected_invokedOnFeatureCoordinatorServiceDisconnected() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.featureCoordinatorConnection.onServiceDisconnected(
ComponentName(PACKAGE_NAME, FC_NAME)
@@ -295,7 +324,8 @@ class FeatureConnectorTest {
fun onFailedToConnect_invokedOnFeatureCoordinatorNullBinding() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.featureCoordinatorConnection.onNullBinding(ComponentName(PACKAGE_NAME, FC_NAME))
verify(mockCallback).onFailedToConnect()
@@ -305,7 +335,8 @@ class FeatureConnectorTest {
fun onDisconnected_invokedOnFeatureCoordinatorDeadBinding() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.featureCoordinatorConnection.onBindingDied(ComponentName(PACKAGE_NAME, FC_NAME))
verify(mockCallback).onDisconnected()
@@ -315,7 +346,8 @@ class FeatureConnectorTest {
fun onConnected_invokedAfterSuccessfulBind() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
assertThat(connector.coordinatorProxy is SafeApiProxy).isTrue()
verify(mockCallback).onConnected()
@@ -325,7 +357,8 @@ class FeatureConnectorTest {
fun onConnected_invokedAfterSuccessfulLegacyBind() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 0
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
assertThat(connector.coordinatorProxy is LegacyApiProxy).isTrue()
verify(mockCallback).onConnected()
@@ -335,7 +368,8 @@ class FeatureConnectorTest {
fun sendMessage_sendsMessage() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.coordinatorProxy = testCoordinatorProxy
connector.sendMessage(testDeviceId, testMessage)
@@ -346,7 +380,8 @@ class FeatureConnectorTest {
fun onMessageFailedToSend_invokedOnNullProxy() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.coordinatorProxy = null
connector.sendMessage(testDeviceId, testMessage)
@@ -357,7 +392,8 @@ class FeatureConnectorTest {
fun onMessageFailedToSend_invokedWhenDeviceNotFound() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.coordinatorProxy = testCoordinatorProxy
val unexpectedDevice = UUID.randomUUID().toString()
connector.sendMessage(unexpectedDevice, testMessage)
@@ -371,7 +407,8 @@ class FeatureConnectorTest {
fun onMessageFailedToSend_invokedWhenSendMessageFails() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
val coordinatorProxy = TestCompanionApiProxy(false, listOf(testDeviceId))
connector.coordinatorProxy = coordinatorProxy
connector.sendMessage(testDeviceId, testMessage)
@@ -383,7 +420,8 @@ class FeatureConnectorTest {
fun sendMessage_onMessageFailedToSend_invokedOnVersionMismatch() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 0
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.sendMessage(testDeviceId, testMessage)
verify(mockCallback).onMessageFailedToSend(testDeviceId, testMessage, isTransient = false)
@@ -393,7 +431,8 @@ class FeatureConnectorTest {
fun sendQuery_sendsQueryToOwnFeatureId() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.coordinatorProxy = testCoordinatorProxy
val request = ByteUtils.randomBytes(10)
val parameters = ByteUtils.randomBytes(10)
@@ -412,7 +451,8 @@ class FeatureConnectorTest {
fun sendQuery_addsCallbackToCallbacksMap() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.coordinatorProxy = testCoordinatorProxy
val request = ByteUtils.randomBytes(10)
val parameters = ByteUtils.randomBytes(10)
@@ -426,7 +466,8 @@ class FeatureConnectorTest {
fun sendQuery_onQueryFailedToSend_invokedOnNullProxy() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.coordinatorProxy = null
val request = ByteUtils.randomBytes(10)
val parameters = ByteUtils.randomBytes(10)
@@ -440,7 +481,8 @@ class FeatureConnectorTest {
fun sendQuery_onQueryFailedToSend_invokedOnDeviceIdNotFound() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.coordinatorProxy = testCoordinatorProxy
val request = ByteUtils.randomBytes(10)
val parameters = ByteUtils.randomBytes(10)
@@ -454,7 +496,8 @@ class FeatureConnectorTest {
fun respondToQuery_doesNotSendResponseWithNullProxy() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.coordinatorProxy = null
val response = ByteUtils.randomBytes(10)
connector.respondToQuery(testDeviceId, 1, success = true, response)
@@ -466,7 +509,8 @@ class FeatureConnectorTest {
fun respondToQuery_doesNotSendResponseWithUnrecognizedQueryId() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.coordinatorProxy = testCoordinatorProxy
val nonExistentQueryId = 0
val response = ByteUtils.randomBytes(10)
@@ -481,7 +525,8 @@ class FeatureConnectorTest {
mockPlatformVersion = 1
val queryId = 1
val response = ByteUtils.randomBytes(10)
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.coordinatorProxy = testCoordinatorProxy
testCoordinatorProxy.queryResponseRecipients.put(queryId, testFeatureId)
connector.respondToQuery(testDeviceId, queryId, success = true, response)
@@ -499,7 +544,8 @@ class FeatureConnectorTest {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
val queryId = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.coordinatorProxy = testCoordinatorProxy
testCoordinatorProxy.queryResponseRecipients.put(queryId, testFeatureId)
connector.respondToQuery(testDeviceId, queryId, success = true, null)
@@ -516,7 +562,8 @@ class FeatureConnectorTest {
fun respondToQuery_onMessageFailedToSend_invokedWhenSendMessageFailed() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
val proxy = spy(TestCompanionApiProxy(false, listOf(testDeviceId)))
connector.coordinatorProxy = proxy
val queryId = 1
@@ -531,7 +578,8 @@ class FeatureConnectorTest {
fun retrieveCompanionApplicationName_sendsAppNameQueryToSystemFeature() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
connector.coordinatorProxy = testCoordinatorProxy
val callback = mock<SafeConnector.AppNameCallback>()
@@ -551,7 +599,8 @@ class FeatureConnectorTest {
fun retrieveCompanionApplicationName_onMessageFailedToSend_invokedWhenSendMessageFailed() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
val proxy = spy(TestCompanionApiProxy(false, listOf(testDeviceId)))
connector.coordinatorProxy = proxy
val appNameCallback = mock<SafeConnector.AppNameCallback>()
@@ -564,7 +613,8 @@ class FeatureConnectorTest {
fun retrieveAssociatedDevices_worksWithSafeListener() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
val mockListener = mock<ISafeOnAssociatedDevicesRetrievedListener>()
connector.coordinatorProxy = testCoordinatorProxy
@@ -577,7 +627,8 @@ class FeatureConnectorTest {
fun retrieveAssociatedDevices_worksWithLegacyListener() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 0
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
val mockListener = mock<IOnAssociatedDevicesRetrievedListener>()
connector.coordinatorProxy = testCoordinatorProxy
@@ -590,7 +641,8 @@ class FeatureConnectorTest {
fun retrieveAssociatedDevices_returnsSilentlyOnNullCoordinator() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
val mockListener = mock<ISafeOnAssociatedDevicesRetrievedListener>()
connector.coordinatorProxy = null
@@ -600,65 +652,71 @@ class FeatureConnectorTest {
}
@Test
- fun onCleanUp_cleansUpFeatureCoordinator() {
+ fun disconnect_cleansUpFeatureCoordinator() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
assertThat(connector.coordinatorProxy).isNotNull()
- connector.cleanUp()
+ connector.disconnect()
assertThat(connector.coordinatorProxy).isNull()
}
@Test
- fun onCleanUp_cleansUpFeatureCoordinator_legacyPlatform() {
+ fun disconnect_cleansUpFeatureCoordinator_legacyPlatform() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 0
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
assertThat(connector.coordinatorProxy).isNotNull()
- connector.cleanUp()
+ connector.disconnect()
assertThat(connector.coordinatorProxy).isNull()
}
@Test
- fun onCleanUp_callsCallbackDisconnected() {
+ fun disconnect_callsCallbackDisconnected() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
- connector.cleanUp()
+ connector.disconnect()
verify(mockCallback).onDisconnected()
}
@Test
- fun onCleanUp_callsCallbackDisconnected_legacyPlatform() {
+ fun disconnect_callsCallbackDisconnected_legacyPlatform() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 0
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
- connector.cleanUp()
+ connector.disconnect()
verify(mockCallback).onDisconnected()
}
@Test
- fun onCleanUp_unbindsFromContext() {
+ fun disconnect_unbindsFromContext() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 1
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
- connector.cleanUp()
+ connector.disconnect()
assertThat(context.unbindServiceConnection)
.containsExactly(connector.featureCoordinatorConnection)
}
@Test
- fun onCleanUp_unbindsFromContext_legacyPlatform() {
+ fun disconnect_unbindsFromContext_legacyPlatform() {
setQueryIntentServicesAnswer(defaultServiceAnswer)
mockPlatformVersion = 0
- val connector = FeatureConnector(context, testFeatureId, mockCallback, 1)
+ val connector = versionOneConnector
+ connector.connect(mockCallback)
- connector.cleanUp()
+ connector.disconnect()
assertThat(context.unbindServiceConnection)
.containsExactly(connector.featureCoordinatorConnection)
}