Merge changes from topic "lightyear" into androidx-main
* changes:
[Androidx Health] Bump the minSdkVersion to 30.
[Androidx Health]: IPC/internal bug fixes.
diff --git a/health/health-services-client/build.gradle b/health/health-services-client/build.gradle
index 7cb9dcc..a2210b0 100644
--- a/health/health-services-client/build.gradle
+++ b/health/health-services-client/build.gradle
@@ -37,7 +37,7 @@
android {
defaultConfig {
- minSdkVersion 26
+ minSdkVersion 30
}
buildFeatures {
aidl = true
diff --git a/health/health-services-client/lint-baseline.xml b/health/health-services-client/lint-baseline.xml
index afadcc9..f02d661 100644
--- a/health/health-services-client/lint-baseline.xml
+++ b/health/health-services-client/lint-baseline.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.2.0-dev" type="baseline" client="gradle" dependencies="false" name="AGP (7.2.0-dev)" variant="all" version="7.2.0-dev">
+<issues format="6" by="lint 7.1.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.1.0-alpha08)" variant="all" version="7.1.0-alpha08">
<issue
id="BanKeepAnnotation"
@@ -92,6 +92,28 @@
<issue
id="BanSynchronizedMethods"
message="Use of synchronized methods is not recommended"
+ errorLine1=" @Synchronized"
+ errorLine2=" ^">
+ <location
+ file="src/main/java/androidx/health/services/client/impl/PassiveMonitoringCallbackStub.kt"
+ line="61"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="BanSynchronizedMethods"
+ message="Use of synchronized methods is not recommended"
+ errorLine1=" @Synchronized"
+ errorLine2=" ^">
+ <location
+ file="src/main/java/androidx/health/services/client/impl/PassiveMonitoringCallbackStub.kt"
+ line="71"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="BanSynchronizedMethods"
+ message="Use of synchronized methods is not recommended"
errorLine1=" private synchronized void handleRetriableDisconnection(Throwable throwable) {"
errorLine2=" ^">
<location
@@ -101,17 +123,6 @@
</issue>
<issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" get() = ServiceBackedMeasureClient.getClient(applicationContext)"
- errorLine2=" ~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ServiceBackedHealthServicesClient.kt"
- line="51"
- column="44"/>
- </issue>
-
- <issue
id="SyntheticAccessor"
message="Access to `private` field `mCurrentVersion` of class `Client` requires synthetic accessor"
errorLine1=" mCurrentVersion ="
@@ -135,57 +146,46 @@
<issue
id="SyntheticAccessor"
- message="Access to `private` field `mCurrentVersion` of class `Client` requires synthetic accessor"
- errorLine1=" mCurrentVersion ="
- errorLine2=" ~~~~~~~~~~~~~~~">
+ message="Access to `private` field `mConnectionManager` of class `Client` requires synthetic accessor"
+ errorLine1=" mConnectionManager.scheduleForExecution("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
<location
file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="139"
+ line="143"
column="29"/>
</issue>
<issue
id="SyntheticAccessor"
- message="Access to `private` field `mCurrentVersion` of class `Client` requires synthetic accessor"
- errorLine1=" if (mCurrentVersion < minApiVersion) {"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="141"
- column="33"/>
- </issue>
-
- <issue
- id="SyntheticAccessor"
- message="Access to `private` field `mCurrentVersion` of class `Client` requires synthetic accessor"
- errorLine1=" mCurrentVersion, minApiVersion));"
- errorLine2=" ~~~~~~~~~~~~~~~">
+ message="Access to `private` field `mConnectionConfiguration` of class `Client` requires synthetic accessor"
+ errorLine1=" new BaseQueueOperation(mConnectionConfiguration));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
line="144"
- column="45"/>
+ column="60"/>
</issue>
<issue
id="SyntheticAccessor"
message="Access to `private` field `mConnectionManager` of class `Client` requires synthetic accessor"
- errorLine1=" mConnectionManager.scheduleForExecution("
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ errorLine1=" mConnectionManager.scheduleForExecution("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
<location
file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="146"
- column="33"/>
+ line="150"
+ column="29"/>
</issue>
<issue
id="SyntheticAccessor"
message="Access to `private` method `createQueueOperation` of class `Client` requires synthetic accessor"
- errorLine1=" createQueueOperation(operation, settableFuture));"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ errorLine1=" createQueueOperation(operation, settableFuture));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="147"
- column="41"/>
+ line="151"
+ column="37"/>
</issue>
<issue
@@ -195,7 +195,7 @@
errorLine2=" ~~~~~~~~~~">
<location
file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="266"
+ line="278"
column="35"/>
</issue>
@@ -233,6 +233,17 @@
</issue>
<issue
+ id="SyntheticAccessor"
+ message="Access to `private` constructor of class `PassiveMonitoringCallbackStub` requires synthetic accessor"
+ errorLine1=" PassiveMonitoringCallbackStub(packageName, callback)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/java/androidx/health/services/client/impl/PassiveMonitoringCallbackStub.kt"
+ line="67"
+ column="17"/>
+ </issue>
+
+ <issue
id="LambdaLast"
message="Functional interface parameters (such as parameter 1, "operation", in androidx.health.services.client.impl.ipc.Client.executeWithVersionCheck) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions"
errorLine1=" RemoteFutureOperation<S, R> operation, int minApiVersion) {"
@@ -422,149 +433,149 @@
<issue
id="UnknownNullness"
message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
- errorLine1=" protected <R> ListenableFuture<R> registerListener("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ errorLine1=" protected ListenableFuture<Integer> getCurrentRemoteVersion(boolean forceRefresh) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="184"
- column="19"/>
- </issue>
-
- <issue
- id="UnknownNullness"
- message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
- errorLine1=" ListenerKey listenerKey, RemoteOperation<S, R> registerListenerOperation) {"
- errorLine2=" ~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="185"
- column="13"/>
- </issue>
-
- <issue
- id="UnknownNullness"
- message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
- errorLine1=" ListenerKey listenerKey, RemoteOperation<S, R> registerListenerOperation) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="185"
- column="38"/>
- </issue>
-
- <issue
- id="UnknownNullness"
- message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
- errorLine1=" protected <R> ListenableFuture<R> registerListener("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="205"
- column="19"/>
- </issue>
-
- <issue
- id="UnknownNullness"
- message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
- errorLine1=" ListenerKey listenerKey, RemoteFutureOperation<S, R> registerListenerOperation) {"
- errorLine2=" ~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="206"
- column="13"/>
- </issue>
-
- <issue
- id="UnknownNullness"
- message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
- errorLine1=" ListenerKey listenerKey, RemoteFutureOperation<S, R> registerListenerOperation) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="206"
- column="38"/>
- </issue>
-
- <issue
- id="UnknownNullness"
- message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
- errorLine1=" protected <R> ListenableFuture<R> unregisterListener("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="223"
- column="19"/>
- </issue>
-
- <issue
- id="UnknownNullness"
- message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
- errorLine1=" ListenerKey listenerKey, RemoteOperation<S, R> unregisterListenerOperation) {"
- errorLine2=" ~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="224"
- column="13"/>
- </issue>
-
- <issue
- id="UnknownNullness"
- message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
- errorLine1=" ListenerKey listenerKey, RemoteOperation<S, R> unregisterListenerOperation) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="224"
- column="38"/>
- </issue>
-
- <issue
- id="UnknownNullness"
- message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
- errorLine1=" protected <R> ListenableFuture<R> unregisterListener("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="241"
- column="19"/>
- </issue>
-
- <issue
- id="UnknownNullness"
- message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
- errorLine1=" ListenerKey listenerKey, RemoteFutureOperation<S, R> unregisterListenerOperation) {"
- errorLine2=" ~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="242"
- column="13"/>
- </issue>
-
- <issue
- id="UnknownNullness"
- message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
- errorLine1=" ListenerKey listenerKey, RemoteFutureOperation<S, R> unregisterListenerOperation) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="242"
- column="38"/>
- </issue>
-
- <issue
- id="UnknownNullness"
- message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
- errorLine1=" protected Exception getApiVersionCheckFailureException(int currentVersion, int minApiVersion) {"
- errorLine2=" ~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
- line="249"
+ line="169"
column="15"/>
</issue>
<issue
id="UnknownNullness"
message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
+ errorLine1=" protected <R> ListenableFuture<R> registerListener("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
+ line="196"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnknownNullness"
+ message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
+ errorLine1=" ListenerKey listenerKey, RemoteOperation<S, R> registerListenerOperation) {"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
+ line="197"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="UnknownNullness"
+ message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
+ errorLine1=" ListenerKey listenerKey, RemoteOperation<S, R> registerListenerOperation) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
+ line="197"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="UnknownNullness"
+ message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
+ errorLine1=" protected <R> ListenableFuture<R> registerListener("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
+ line="217"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnknownNullness"
+ message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
+ errorLine1=" ListenerKey listenerKey, RemoteFutureOperation<S, R> registerListenerOperation) {"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
+ line="218"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="UnknownNullness"
+ message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
+ errorLine1=" ListenerKey listenerKey, RemoteFutureOperation<S, R> registerListenerOperation) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
+ line="218"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="UnknownNullness"
+ message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
+ errorLine1=" protected <R> ListenableFuture<R> unregisterListener("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
+ line="235"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnknownNullness"
+ message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
+ errorLine1=" ListenerKey listenerKey, RemoteOperation<S, R> unregisterListenerOperation) {"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
+ line="236"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="UnknownNullness"
+ message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
+ errorLine1=" ListenerKey listenerKey, RemoteOperation<S, R> unregisterListenerOperation) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
+ line="236"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="UnknownNullness"
+ message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
+ errorLine1=" protected <R> ListenableFuture<R> unregisterListener("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
+ line="253"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnknownNullness"
+ message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
+ errorLine1=" ListenerKey listenerKey, RemoteFutureOperation<S, R> unregisterListenerOperation) {"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
+ line="254"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="UnknownNullness"
+ message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
+ errorLine1=" ListenerKey listenerKey, RemoteFutureOperation<S, R> unregisterListenerOperation) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/java/androidx/health/services/client/impl/ipc/Client.java"
+ line="254"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="UnknownNullness"
+ message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
errorLine1=" public ClientConfiguration(String apiClientName, String servicePackageName, String bindAction) {"
errorLine2=" ~~~~~~">
<location
@@ -635,7 +646,7 @@
errorLine2=" ~~~~~~">
<location
file="src/main/java/androidx/health/services/client/impl/ipc/internal/ConnectionConfiguration.java"
- line="38"
+ line="37"
column="13"/>
</issue>
@@ -646,7 +657,7 @@
errorLine2=" ~~~~~~">
<location
file="src/main/java/androidx/health/services/client/impl/ipc/internal/ConnectionConfiguration.java"
- line="39"
+ line="38"
column="13"/>
</issue>
@@ -657,7 +668,7 @@
errorLine2=" ~~~~~~">
<location
file="src/main/java/androidx/health/services/client/impl/ipc/internal/ConnectionConfiguration.java"
- line="40"
+ line="39"
column="13"/>
</issue>
@@ -668,7 +679,7 @@
errorLine2=" ~~~~~~~~~~~~~~">
<location
file="src/main/java/androidx/health/services/client/impl/ipc/internal/ConnectionConfiguration.java"
- line="41"
+ line="40"
column="13"/>
</issue>
@@ -800,7 +811,7 @@
errorLine2=" ~~~~~~~~~">
<location
file="src/main/java/androidx/health/services/client/impl/ipc/internal/DefaultExecutionTracker.java"
- line="45"
+ line="53"
column="38"/>
</issue>
@@ -905,39 +916,6 @@
<issue
id="UnknownNullness"
- message="Should explicitly declare type here since implicit type does not specify nullness"
- errorLine1=" override val capabilities: ListenableFuture<ExerciseCapabilities>"
- errorLine2=" ~~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ServiceBackedExerciseClient.kt"
- line="160"
- column="18"/>
- </issue>
-
- <issue
- id="UnknownNullness"
- message="Should explicitly declare type here since implicit type does not specify nullness"
- errorLine1=" override val capabilities: ListenableFuture<MeasureCapabilities>"
- errorLine2=" ~~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ServiceBackedMeasureClient.kt"
- line="92"
- column="18"/>
- </issue>
-
- <issue
- id="UnknownNullness"
- message="Should explicitly declare type here since implicit type does not specify nullness"
- errorLine1=" override val capabilities: ListenableFuture<PassiveMonitoringCapabilities>"
- errorLine2=" ~~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/health/services/client/impl/ServiceBackedPassiveMonitoringClient.kt"
- line="95"
- column="18"/>
- </issue>
-
- <issue
- id="UnknownNullness"
message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
errorLine1=" void onConnected(ServiceConnection connection);"
errorLine2=" ~~~~~~~~~~~~~~~~~">
@@ -965,7 +943,7 @@
errorLine2=" ~~~~~~~~~~~~~">
<location
file="src/main/java/androidx/health/services/client/impl/ipc/internal/ServiceConnection.java"
- line="287"
+ line="288"
column="36"/>
</issue>
@@ -976,7 +954,7 @@
errorLine2=" ~~~~~~~">
<location
file="src/main/java/androidx/health/services/client/impl/ipc/internal/ServiceConnection.java"
- line="287"
+ line="288"
column="65"/>
</issue>
@@ -987,7 +965,7 @@
errorLine2=" ~~~~~~~~~~~~~">
<location
file="src/main/java/androidx/health/services/client/impl/ipc/internal/ServiceConnection.java"
- line="320"
+ line="321"
column="39"/>
</issue>
@@ -998,7 +976,7 @@
errorLine2=" ~~~~~~~~~~~~~">
<location
file="src/main/java/androidx/health/services/client/impl/ipc/internal/ServiceConnection.java"
- line="326"
+ line="327"
column="31"/>
</issue>
@@ -1009,7 +987,7 @@
errorLine2=" ~~~~~~~~~~~~~">
<location
file="src/main/java/androidx/health/services/client/impl/ipc/internal/ServiceConnection.java"
- line="332"
+ line="333"
column="31"/>
</issue>
diff --git a/health/health-services-client/src/main/java/androidx/health/services/client/impl/PassiveMonitoringCallbackStub.kt b/health/health-services-client/src/main/java/androidx/health/services/client/impl/PassiveMonitoringCallbackStub.kt
index b89f985..0592190 100644
--- a/health/health-services-client/src/main/java/androidx/health/services/client/impl/PassiveMonitoringCallbackStub.kt
+++ b/health/health-services-client/src/main/java/androidx/health/services/client/impl/PassiveMonitoringCallbackStub.kt
@@ -17,8 +17,10 @@
package androidx.health.services.client.impl
import android.util.Log
+import androidx.annotation.GuardedBy
import androidx.health.services.client.PassiveMonitoringCallback
import androidx.health.services.client.impl.event.PassiveCallbackEvent
+import androidx.health.services.client.impl.ipc.internal.ListenerKey
import androidx.health.services.client.impl.response.PassiveMonitoringUpdateResponse
import androidx.health.services.client.proto.EventsProto.PassiveCallbackEvent.EventCase.EVENT_NOT_SET
import androidx.health.services.client.proto.EventsProto.PassiveCallbackEvent.EventCase.PASSIVE_UPDATE_RESPONSE
@@ -28,9 +30,13 @@
*
* @hide
*/
-internal class PassiveMonitoringCallbackStub
-internal constructor(private val callback: PassiveMonitoringCallback) :
- IPassiveMonitoringCallback.Stub() {
+public class PassiveMonitoringCallbackStub
+private constructor(
+ private val packageName: String,
+ private val callback: PassiveMonitoringCallback
+) : IPassiveMonitoringCallback.Stub() {
+
+ public val listenerKey: ListenerKey = ListenerKey(packageName)
override fun onPassiveCallbackEvent(event: PassiveCallbackEvent) {
val proto = event.proto
@@ -44,6 +50,35 @@
}
}
+ /**
+ * Its important to use the same stub for registration and un-registration, to ensure same
+ * binder object is passed by framework to service side of the IPC.
+ */
+ public class PassiveMonitoringCallbackCache private constructor() {
+ @GuardedBy("this")
+ private val listeners: MutableMap<String, PassiveMonitoringCallbackStub> = HashMap()
+
+ @Synchronized
+ public fun getOrCreate(
+ packageName: String,
+ callback: PassiveMonitoringCallback
+ ): PassiveMonitoringCallbackStub {
+ return listeners.getOrPut(packageName) {
+ PassiveMonitoringCallbackStub(packageName, callback)
+ }
+ }
+
+ @Synchronized
+ public fun remove(packageName: String): PassiveMonitoringCallbackStub? {
+ return listeners.remove(packageName)
+ }
+
+ public companion object {
+ @JvmField
+ public val INSTANCE: PassiveMonitoringCallbackCache = PassiveMonitoringCallbackCache()
+ }
+ }
+
private companion object {
const val TAG = "PassiveCallbackStub"
}
diff --git a/health/health-services-client/src/main/java/androidx/health/services/client/impl/ServiceBackedPassiveMonitoringClient.kt b/health/health-services-client/src/main/java/androidx/health/services/client/impl/ServiceBackedPassiveMonitoringClient.kt
index 5f6b63b..16f9885 100644
--- a/health/health-services-client/src/main/java/androidx/health/services/client/impl/ServiceBackedPassiveMonitoringClient.kt
+++ b/health/health-services-client/src/main/java/androidx/health/services/client/impl/ServiceBackedPassiveMonitoringClient.kt
@@ -18,6 +18,7 @@
import android.content.ComponentName
import android.content.Context
+import androidx.annotation.VisibleForTesting
import androidx.core.content.ContextCompat
import androidx.health.services.client.PassiveMonitoringCallback
import androidx.health.services.client.PassiveMonitoringClient
@@ -26,10 +27,12 @@
import androidx.health.services.client.data.PassiveMonitoringConfig
import androidx.health.services.client.impl.IpcConstants.PASSIVE_API_BIND_ACTION
import androidx.health.services.client.impl.IpcConstants.SERVICE_PACKAGE_NAME
+import androidx.health.services.client.impl.PassiveMonitoringCallbackStub.PassiveMonitoringCallbackCache
import androidx.health.services.client.impl.internal.HsConnectionManager
import androidx.health.services.client.impl.internal.StatusCallback
import androidx.health.services.client.impl.ipc.Client
import androidx.health.services.client.impl.ipc.ClientConfiguration
+import androidx.health.services.client.impl.ipc.internal.ConnectionManager
import androidx.health.services.client.impl.request.BackgroundRegistrationRequest
import androidx.health.services.client.impl.request.CapabilitiesRequest
import androidx.health.services.client.impl.request.FlushRequest
@@ -42,11 +45,16 @@
*
* @hide
*/
-internal class ServiceBackedPassiveMonitoringClient(private val applicationContext: Context) :
+@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+public class ServiceBackedPassiveMonitoringClient(
+ private val applicationContext: Context,
+ private val connectionManager: ConnectionManager =
+ HsConnectionManager.getInstance(applicationContext)
+) :
PassiveMonitoringClient,
Client<IPassiveMonitoringApiService>(
CLIENT_CONFIGURATION,
- HsConnectionManager.getInstance(applicationContext),
+ connectionManager,
{ binder -> IPassiveMonitoringApiService.Stub.asInterface(binder) },
{ service -> service.apiVersion }
) {
@@ -55,17 +63,54 @@
override fun registerDataCallback(
configuration: PassiveMonitoringConfig
- ): ListenableFuture<Void> = registerDataCallbackInternal(configuration, callback = null)
+ ): ListenableFuture<Void> {
+ val callbackStub = PassiveMonitoringCallbackCache.INSTANCE.remove(packageName)
+ // If the client had a previous callback registered, make sure it's cleared.
+ if (callbackStub != null) {
+ return unregisterListener(callbackStub.listenerKey) { service, resultFuture ->
+ service.registerDataCallback(
+ BackgroundRegistrationRequest(configuration),
+ null,
+ StatusCallback(resultFuture)
+ )
+ }
+ }
+
+ return execute { service, resultFuture ->
+ service.registerDataCallback(
+ BackgroundRegistrationRequest(configuration),
+ null,
+ StatusCallback(resultFuture)
+ )
+ }
+ }
override fun registerDataCallback(
configuration: PassiveMonitoringConfig,
callback: PassiveMonitoringCallback
- ): ListenableFuture<Void> = registerDataCallbackInternal(configuration, callback)
+ ): ListenableFuture<Void> {
+ val callbackStub =
+ PassiveMonitoringCallbackCache.INSTANCE.getOrCreate(packageName, callback)
+ return registerListener(callbackStub.listenerKey) { service, resultFuture ->
+ service.registerDataCallback(
+ BackgroundRegistrationRequest(configuration),
+ callbackStub,
+ StatusCallback(resultFuture)
+ )
+ }
+ }
- override fun unregisterDataCallback(): ListenableFuture<Void> =
- execute { service, resultFuture ->
+ override fun unregisterDataCallback(): ListenableFuture<Void> {
+ val callbackStub = PassiveMonitoringCallbackCache.INSTANCE.remove(packageName)
+ if (callbackStub != null) {
+ return unregisterListener(callbackStub.listenerKey) { service, resultFuture ->
+ service.unregisterDataCallback(packageName, StatusCallback(resultFuture))
+ }
+ }
+ return execute { service, resultFuture ->
service.unregisterDataCallback(packageName, StatusCallback(resultFuture))
}
+ }
// TODO(jlannin): Make this take in the BroadcastReceiver directly.
override fun registerPassiveGoalCallback(
@@ -100,23 +145,8 @@
ContextCompat.getMainExecutor(applicationContext)
)
- private fun registerDataCallbackInternal(
- configuration: PassiveMonitoringConfig,
- callback: PassiveMonitoringCallback?
- ): ListenableFuture<Void> = execute { service, resultFuture ->
- // TODO(b/191997620): This should check the package against what was requested and return an
- // error in the event of a mismatch.
- // TODO(jlannin): Maybe we should put the BroadcastReceiver directly in the
- // PassiveMonitoringConfig?
- service.registerDataCallback(
- BackgroundRegistrationRequest(configuration),
- callback?.let { PassiveMonitoringCallbackStub(it) },
- StatusCallback(resultFuture)
- )
- }
-
private companion object {
- private const val CLIENT = "HealthServicesPassiveMonitoringClient"
+ const val CLIENT = "HealthServicesPassiveMonitoringClient"
private val CLIENT_CONFIGURATION =
ClientConfiguration(CLIENT, SERVICE_PACKAGE_NAME, PASSIVE_API_BIND_ACTION)
}
diff --git a/health/health-services-client/src/main/java/androidx/health/services/client/impl/ipc/Client.java b/health/health-services-client/src/main/java/androidx/health/services/client/impl/ipc/Client.java
index 9292b95..3782df9 100644
--- a/health/health-services-client/src/main/java/androidx/health/services/client/impl/ipc/Client.java
+++ b/health/health-services-client/src/main/java/androidx/health/services/client/impl/ipc/Client.java
@@ -20,7 +20,7 @@
import android.os.IInterface;
import android.os.RemoteException;
-import androidx.annotation.Nullable;
+import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
import androidx.health.services.client.impl.ipc.internal.BaseQueueOperation;
@@ -128,43 +128,55 @@
*/
protected <R> ListenableFuture<R> executeWithVersionCheck(
RemoteFutureOperation<S, R> operation, int minApiVersion) {
- if (mCurrentVersion == UNKNOWN_VERSION) {
- SettableFuture<R> settableFuture = SettableFuture.create();
- ListenableFuture<Integer> versionFuture = execute(mRemoteVersionGetter);
- Futures.addCallback(
- versionFuture,
- new FutureCallback<Integer>() {
- @Override
- public void onSuccess(@Nullable Integer remoteVersion) {
- mCurrentVersion =
- remoteVersion == null ? UNKNOWN_VERSION : remoteVersion;
- if (mCurrentVersion < minApiVersion) {
- settableFuture.setException(
- getApiVersionCheckFailureException(
- mCurrentVersion, minApiVersion));
- } else {
- mConnectionManager.scheduleForExecution(
- createQueueOperation(operation, settableFuture));
- }
- }
+ SettableFuture<R> settableFuture = SettableFuture.create();
+ ListenableFuture<Integer> versionFuture =
+ getCurrentRemoteVersion(/* forceRefresh= */ false);
+ Futures.addCallback(
+ versionFuture,
+ new FutureCallback<Integer>() {
+ @Override
+ public void onSuccess(Integer remoteVersion) {
+ if (remoteVersion < minApiVersion) {
+ // This empty operation is executed just to connect to the service.
+ // If we didn't connect it could happen that we won't detect
+ // change in the API version.
+ mConnectionManager.scheduleForExecution(
+ new BaseQueueOperation(mConnectionConfiguration));
- @Override
- public void onFailure(Throwable throwable) {
- settableFuture.setException(throwable);
+ settableFuture.setException(
+ getApiVersionCheckFailureException(
+ remoteVersion, minApiVersion));
+ } else {
+ mConnectionManager.scheduleForExecution(
+ createQueueOperation(operation, settableFuture));
}
+ }
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ settableFuture.setException(throwable);
+ }
+ },
+ MoreExecutors.directExecutor());
+ return settableFuture;
+ }
+
+ /**
+ * Return current version of the backing service implementation.
+ *
+ * <p>If current version is available from earlier calls, it would return the value from cache.
+ */
+ protected ListenableFuture<Integer> getCurrentRemoteVersion(boolean forceRefresh) {
+ if (mCurrentVersion == UNKNOWN_VERSION || forceRefresh) {
+ return Futures.transform(
+ execute(mRemoteVersionGetter),
+ version -> {
+ mCurrentVersion = version;
+ return mCurrentVersion;
},
MoreExecutors.directExecutor());
- return settableFuture;
- } else if (mCurrentVersion >= minApiVersion) {
- return execute(operation);
} else {
- // This empty operation is executed just to connect to the service. If we didn't connect
- // it
- // could happen that we won't detect change in the API version.
- mConnectionManager.scheduleForExecution(
- new BaseQueueOperation(mConnectionConfiguration));
- return Futures.immediateFailedFuture(
- getApiVersionCheckFailureException(mCurrentVersion, minApiVersion));
+ return Futures.immediateFuture(mCurrentVersion);
}
}
@@ -246,7 +258,8 @@
return settableFuture;
}
- protected Exception getApiVersionCheckFailureException(int currentVersion, int minApiVersion) {
+ protected @NonNull Exception getApiVersionCheckFailureException(
+ int currentVersion, int minApiVersion) {
return new ApiVersionException(currentVersion, minApiVersion);
}
diff --git a/health/health-services-client/src/main/java/androidx/health/services/client/impl/ipc/internal/ConnectionConfiguration.java b/health/health-services-client/src/main/java/androidx/health/services/client/impl/ipc/internal/ConnectionConfiguration.java
index 9b6c42b..59965b3 100644
--- a/health/health-services-client/src/main/java/androidx/health/services/client/impl/ipc/internal/ConnectionConfiguration.java
+++ b/health/health-services-client/src/main/java/androidx/health/services/client/impl/ipc/internal/ConnectionConfiguration.java
@@ -20,7 +20,6 @@
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
-import androidx.health.services.client.impl.ipc.ClientConfiguration;
/**
* Internal representation of configuration of IPC service connection.
@@ -50,23 +49,17 @@
return String.format("%s#%s#%s", mClientName, mPackageName, mBindAction);
}
- /** API Client name defined in the {@link ClientConfiguration#getApiClientName()}. */
+ /** Returns name of the service, use for logging and debugging only. */
String getClientName() {
return mClientName;
}
- /**
- * An action used to bind to the remote service. Taken from {@link
- * ClientConfiguration#getBindAction()}.
- */
+ /** Returns the action used to bind to the remote service. */
String getBindAction() {
return mBindAction;
}
- /**
- * Package name of remote service. Taken from {@link
- * ClientConfiguration#getServicePackageName()}.
- */
+ /** Returns the application package of the remote service. */
String getPackageName() {
return mPackageName;
}
diff --git a/health/health-services-client/src/main/java/androidx/health/services/client/impl/ipc/internal/DefaultExecutionTracker.java b/health/health-services-client/src/main/java/androidx/health/services/client/impl/ipc/internal/DefaultExecutionTracker.java
index c8b527e..744ca14 100644
--- a/health/health-services-client/src/main/java/androidx/health/services/client/impl/ipc/internal/DefaultExecutionTracker.java
+++ b/health/health-services-client/src/main/java/androidx/health/services/client/impl/ipc/internal/DefaultExecutionTracker.java
@@ -37,15 +37,25 @@
@Override
public void track(SettableFuture<?> future) {
- mFuturesInProgress.add(future);
- future.addListener(() -> mFuturesInProgress.remove(future), MoreExecutors.directExecutor());
+ synchronized (mFuturesInProgress) {
+ mFuturesInProgress.add(future);
+ }
+ future.addListener(
+ () -> {
+ synchronized (mFuturesInProgress) {
+ mFuturesInProgress.remove(future);
+ }
+ },
+ MoreExecutors.directExecutor());
}
@Override
public void cancelPendingFutures(Throwable throwable) {
- for (SettableFuture<?> future : mFuturesInProgress) {
- future.setException(throwable);
+ synchronized (mFuturesInProgress) {
+ for (SettableFuture<?> future : mFuturesInProgress) {
+ future.setException(throwable);
+ }
+ mFuturesInProgress.clear();
}
- mFuturesInProgress.clear();
}
}
diff --git a/health/health-services-client/src/main/java/androidx/health/services/client/impl/ipc/internal/ServiceConnection.java b/health/health-services-client/src/main/java/androidx/health/services/client/impl/ipc/internal/ServiceConnection.java
index fa432bc..880b852 100644
--- a/health/health-services-client/src/main/java/androidx/health/services/client/impl/ipc/internal/ServiceConnection.java
+++ b/health/health-services-client/src/main/java/androidx/health/services/client/impl/ipc/internal/ServiceConnection.java
@@ -180,7 +180,8 @@
return (200 << retryNumber);
}
- private void clearConnection(Throwable throwable) {
+ @VisibleForTesting
+ void clearConnection(Throwable throwable) {
if (mIsServiceBound) {
try {
mContext.unbindService(this);
@@ -336,6 +337,6 @@
+ mConnectionConfiguration.getClientName()
+ "', binder is null");
// This connection will never be usable, don't bother with retries.
- handleNonRetriableDisconnection(new CancellationException("Null binding"));
+ handleRetriableDisconnection(new CancellationException("Null binding"));
}
}