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 &lt; 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, &quot;operation&quot;, 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&lt;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 &lt;R> ListenableFuture&lt;R> registerListener("
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~">
+        errorLine1="    protected ListenableFuture&lt;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&lt;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&lt;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 &lt;R> ListenableFuture&lt;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&lt;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&lt;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 &lt;R> ListenableFuture&lt;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&lt;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&lt;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 &lt;R> ListenableFuture&lt;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&lt;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&lt;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 &lt;R> ListenableFuture&lt;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&lt;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&lt;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 &lt;R> ListenableFuture&lt;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&lt;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&lt;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 &lt;R> ListenableFuture&lt;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&lt;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&lt;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 &lt;R> ListenableFuture&lt;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&lt;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&lt;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&lt;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&lt;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&lt;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"));
     }
 }