Merge "Add default values for ExerciseUpdate's nullables" into androidx-main
diff --git a/health/health-services-client/api/1.0.0-beta01.txt b/health/health-services-client/api/1.0.0-beta01.txt
index 00892ec..137fe7b 100644
--- a/health/health-services-client/api/1.0.0-beta01.txt
+++ b/health/health-services-client/api/1.0.0-beta01.txt
@@ -533,7 +533,7 @@
   }
 
   public final class ExerciseUpdate {
-    ctor public ExerciseUpdate(java.time.Instant? startTime, java.time.Duration? updateDurationFromBoot, androidx.health.services.client.data.DataPointContainer latestMetrics, java.util.Set<? extends androidx.health.services.client.data.ExerciseGoal<? extends java.lang.Number>> latestAchievedGoals, java.util.Set<androidx.health.services.client.data.MilestoneMarkerSummary> latestMilestoneMarkerSummaries, androidx.health.services.client.data.ExerciseConfig? exerciseConfig, androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? activeDurationCheckpoint, androidx.health.services.client.data.ExerciseStateInfo exerciseStateInfo);
+    ctor public ExerciseUpdate(androidx.health.services.client.data.DataPointContainer latestMetrics, java.util.Set<? extends androidx.health.services.client.data.ExerciseGoal<? extends java.lang.Number>> latestAchievedGoals, java.util.Set<androidx.health.services.client.data.MilestoneMarkerSummary> latestMilestoneMarkerSummaries, androidx.health.services.client.data.ExerciseStateInfo exerciseStateInfo, optional androidx.health.services.client.data.ExerciseConfig? exerciseConfig, optional androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? activeDurationCheckpoint, optional java.time.Duration? updateDurationFromBoot, optional java.time.Instant? startTime);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.IntervalDataPoint<?> dataPoint);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.SampleDataPoint<?> dataPoint);
     method public androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? getActiveDurationCheckpoint();
diff --git a/health/health-services-client/api/current.txt b/health/health-services-client/api/current.txt
index 00892ec..137fe7b 100644
--- a/health/health-services-client/api/current.txt
+++ b/health/health-services-client/api/current.txt
@@ -533,7 +533,7 @@
   }
 
   public final class ExerciseUpdate {
-    ctor public ExerciseUpdate(java.time.Instant? startTime, java.time.Duration? updateDurationFromBoot, androidx.health.services.client.data.DataPointContainer latestMetrics, java.util.Set<? extends androidx.health.services.client.data.ExerciseGoal<? extends java.lang.Number>> latestAchievedGoals, java.util.Set<androidx.health.services.client.data.MilestoneMarkerSummary> latestMilestoneMarkerSummaries, androidx.health.services.client.data.ExerciseConfig? exerciseConfig, androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? activeDurationCheckpoint, androidx.health.services.client.data.ExerciseStateInfo exerciseStateInfo);
+    ctor public ExerciseUpdate(androidx.health.services.client.data.DataPointContainer latestMetrics, java.util.Set<? extends androidx.health.services.client.data.ExerciseGoal<? extends java.lang.Number>> latestAchievedGoals, java.util.Set<androidx.health.services.client.data.MilestoneMarkerSummary> latestMilestoneMarkerSummaries, androidx.health.services.client.data.ExerciseStateInfo exerciseStateInfo, optional androidx.health.services.client.data.ExerciseConfig? exerciseConfig, optional androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? activeDurationCheckpoint, optional java.time.Duration? updateDurationFromBoot, optional java.time.Instant? startTime);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.IntervalDataPoint<?> dataPoint);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.SampleDataPoint<?> dataPoint);
     method public androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? getActiveDurationCheckpoint();
diff --git a/health/health-services-client/api/public_plus_experimental_1.0.0-beta01.txt b/health/health-services-client/api/public_plus_experimental_1.0.0-beta01.txt
index 00892ec..137fe7b 100644
--- a/health/health-services-client/api/public_plus_experimental_1.0.0-beta01.txt
+++ b/health/health-services-client/api/public_plus_experimental_1.0.0-beta01.txt
@@ -533,7 +533,7 @@
   }
 
   public final class ExerciseUpdate {
-    ctor public ExerciseUpdate(java.time.Instant? startTime, java.time.Duration? updateDurationFromBoot, androidx.health.services.client.data.DataPointContainer latestMetrics, java.util.Set<? extends androidx.health.services.client.data.ExerciseGoal<? extends java.lang.Number>> latestAchievedGoals, java.util.Set<androidx.health.services.client.data.MilestoneMarkerSummary> latestMilestoneMarkerSummaries, androidx.health.services.client.data.ExerciseConfig? exerciseConfig, androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? activeDurationCheckpoint, androidx.health.services.client.data.ExerciseStateInfo exerciseStateInfo);
+    ctor public ExerciseUpdate(androidx.health.services.client.data.DataPointContainer latestMetrics, java.util.Set<? extends androidx.health.services.client.data.ExerciseGoal<? extends java.lang.Number>> latestAchievedGoals, java.util.Set<androidx.health.services.client.data.MilestoneMarkerSummary> latestMilestoneMarkerSummaries, androidx.health.services.client.data.ExerciseStateInfo exerciseStateInfo, optional androidx.health.services.client.data.ExerciseConfig? exerciseConfig, optional androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? activeDurationCheckpoint, optional java.time.Duration? updateDurationFromBoot, optional java.time.Instant? startTime);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.IntervalDataPoint<?> dataPoint);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.SampleDataPoint<?> dataPoint);
     method public androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? getActiveDurationCheckpoint();
diff --git a/health/health-services-client/api/public_plus_experimental_current.txt b/health/health-services-client/api/public_plus_experimental_current.txt
index 00892ec..137fe7b 100644
--- a/health/health-services-client/api/public_plus_experimental_current.txt
+++ b/health/health-services-client/api/public_plus_experimental_current.txt
@@ -533,7 +533,7 @@
   }
 
   public final class ExerciseUpdate {
-    ctor public ExerciseUpdate(java.time.Instant? startTime, java.time.Duration? updateDurationFromBoot, androidx.health.services.client.data.DataPointContainer latestMetrics, java.util.Set<? extends androidx.health.services.client.data.ExerciseGoal<? extends java.lang.Number>> latestAchievedGoals, java.util.Set<androidx.health.services.client.data.MilestoneMarkerSummary> latestMilestoneMarkerSummaries, androidx.health.services.client.data.ExerciseConfig? exerciseConfig, androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? activeDurationCheckpoint, androidx.health.services.client.data.ExerciseStateInfo exerciseStateInfo);
+    ctor public ExerciseUpdate(androidx.health.services.client.data.DataPointContainer latestMetrics, java.util.Set<? extends androidx.health.services.client.data.ExerciseGoal<? extends java.lang.Number>> latestAchievedGoals, java.util.Set<androidx.health.services.client.data.MilestoneMarkerSummary> latestMilestoneMarkerSummaries, androidx.health.services.client.data.ExerciseStateInfo exerciseStateInfo, optional androidx.health.services.client.data.ExerciseConfig? exerciseConfig, optional androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? activeDurationCheckpoint, optional java.time.Duration? updateDurationFromBoot, optional java.time.Instant? startTime);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.IntervalDataPoint<?> dataPoint);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.SampleDataPoint<?> dataPoint);
     method public androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? getActiveDurationCheckpoint();
diff --git a/health/health-services-client/api/restricted_1.0.0-beta01.txt b/health/health-services-client/api/restricted_1.0.0-beta01.txt
index 00892ec..137fe7b 100644
--- a/health/health-services-client/api/restricted_1.0.0-beta01.txt
+++ b/health/health-services-client/api/restricted_1.0.0-beta01.txt
@@ -533,7 +533,7 @@
   }
 
   public final class ExerciseUpdate {
-    ctor public ExerciseUpdate(java.time.Instant? startTime, java.time.Duration? updateDurationFromBoot, androidx.health.services.client.data.DataPointContainer latestMetrics, java.util.Set<? extends androidx.health.services.client.data.ExerciseGoal<? extends java.lang.Number>> latestAchievedGoals, java.util.Set<androidx.health.services.client.data.MilestoneMarkerSummary> latestMilestoneMarkerSummaries, androidx.health.services.client.data.ExerciseConfig? exerciseConfig, androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? activeDurationCheckpoint, androidx.health.services.client.data.ExerciseStateInfo exerciseStateInfo);
+    ctor public ExerciseUpdate(androidx.health.services.client.data.DataPointContainer latestMetrics, java.util.Set<? extends androidx.health.services.client.data.ExerciseGoal<? extends java.lang.Number>> latestAchievedGoals, java.util.Set<androidx.health.services.client.data.MilestoneMarkerSummary> latestMilestoneMarkerSummaries, androidx.health.services.client.data.ExerciseStateInfo exerciseStateInfo, optional androidx.health.services.client.data.ExerciseConfig? exerciseConfig, optional androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? activeDurationCheckpoint, optional java.time.Duration? updateDurationFromBoot, optional java.time.Instant? startTime);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.IntervalDataPoint<?> dataPoint);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.SampleDataPoint<?> dataPoint);
     method public androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? getActiveDurationCheckpoint();
diff --git a/health/health-services-client/api/restricted_current.txt b/health/health-services-client/api/restricted_current.txt
index 00892ec..137fe7b 100644
--- a/health/health-services-client/api/restricted_current.txt
+++ b/health/health-services-client/api/restricted_current.txt
@@ -533,7 +533,7 @@
   }
 
   public final class ExerciseUpdate {
-    ctor public ExerciseUpdate(java.time.Instant? startTime, java.time.Duration? updateDurationFromBoot, androidx.health.services.client.data.DataPointContainer latestMetrics, java.util.Set<? extends androidx.health.services.client.data.ExerciseGoal<? extends java.lang.Number>> latestAchievedGoals, java.util.Set<androidx.health.services.client.data.MilestoneMarkerSummary> latestMilestoneMarkerSummaries, androidx.health.services.client.data.ExerciseConfig? exerciseConfig, androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? activeDurationCheckpoint, androidx.health.services.client.data.ExerciseStateInfo exerciseStateInfo);
+    ctor public ExerciseUpdate(androidx.health.services.client.data.DataPointContainer latestMetrics, java.util.Set<? extends androidx.health.services.client.data.ExerciseGoal<? extends java.lang.Number>> latestAchievedGoals, java.util.Set<androidx.health.services.client.data.MilestoneMarkerSummary> latestMilestoneMarkerSummaries, androidx.health.services.client.data.ExerciseStateInfo exerciseStateInfo, optional androidx.health.services.client.data.ExerciseConfig? exerciseConfig, optional androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? activeDurationCheckpoint, optional java.time.Duration? updateDurationFromBoot, optional java.time.Instant? startTime);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.IntervalDataPoint<?> dataPoint);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.SampleDataPoint<?> dataPoint);
     method public androidx.health.services.client.data.ExerciseUpdate.ActiveDurationCheckpoint? getActiveDurationCheckpoint();
diff --git a/health/health-services-client/src/main/java/androidx/health/services/client/data/ExerciseUpdate.kt b/health/health-services-client/src/main/java/androidx/health/services/client/data/ExerciseUpdate.kt
index 9d58a6d..243938b 100644
--- a/health/health-services-client/src/main/java/androidx/health/services/client/data/ExerciseUpdate.kt
+++ b/health/health-services-client/src/main/java/androidx/health/services/client/data/ExerciseUpdate.kt
@@ -28,15 +28,6 @@
 /** Contains the latest updated state and metrics for the current exercise. */
 @Suppress("ParcelCreator")
 public class ExerciseUpdate(
-    /**
-     * Returns the time at which the exercise was started or `null` if the exercise is in prepare
-     * phase and hasn't started yet.
-     */
-    public val startTime: Instant?,
-
-    /** The duration since boot when this ExerciseUpdate was created. */
-    private val updateDurationFromBoot: Duration?,
-
     /** Returns the list of the latest [DataPoint]s. */
     public val latestMetrics: DataPointContainer,
 
@@ -51,10 +42,16 @@
     public val latestMilestoneMarkerSummaries: Set<MilestoneMarkerSummary>,
 
     /**
+     * Returns the [ExerciseStateInfo] containing the current [ExerciseState] and
+     * [ExerciseEndReason], if applicable.
+     */
+    public val exerciseStateInfo: ExerciseStateInfo,
+
+    /**
      * Returns the [ExerciseConfig] used by the exercise when the [ExerciseUpdate] was dispatched
      * and returns `null` if the exercise is in prepare phase and hasn't been started yet.
      */
-    public val exerciseConfig: ExerciseConfig?,
+    public val exerciseConfig: ExerciseConfig? = null,
 
     /**
      * Returns the [ActiveDurationCheckpoint] which can be used to determine the active duration of
@@ -62,39 +59,42 @@
      * application timers against this to ensure their view of the active duration matches the view
      * of Health Services.
      */
-    public val activeDurationCheckpoint: ActiveDurationCheckpoint?,
+    public val activeDurationCheckpoint: ActiveDurationCheckpoint? = null,
+
+    /** The duration since boot when this ExerciseUpdate was created. */
+    private val updateDurationFromBoot: Duration? = null,
 
     /**
-     * Returns the [ExerciseStateInfo] containing the current [ExerciseState] and
-     * [ExerciseEndReason], if applicable.
+     * Returns the time at which the exercise was started or `null` if the exercise is in prepare
+     * phase and hasn't started yet.
      */
-    public val exerciseStateInfo: ExerciseStateInfo,
+    public val startTime: Instant? = null,
 ) {
     /** @hide */
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     public constructor(
         proto: DataProto.ExerciseUpdate
     ) : this(
-        if (proto.hasStartTimeEpochMs()) Instant.ofEpochMilli(proto.startTimeEpochMs) else null,
-        if (proto.hasUpdateDurationFromBootMs()) {
-            Duration.ofMillis(proto.updateDurationFromBootMs)
-        } else {
-            null
-        },
         exerciseUpdateProtoToDataPointContainer(proto),
         proto.latestAchievedGoalsList.map { ExerciseGoal.fromProto(it.exerciseGoal) }.toSet(),
         proto.mileStoneMarkerSummariesList.map { MilestoneMarkerSummary(it) }.toSet(),
+        ExerciseStateInfo(
+            ExerciseState.fromProto(proto.state)
+                ?: throw IllegalArgumentException("Invalid ExerciseState: ${proto.state}"),
+            ExerciseEndReason.fromProto(proto.exerciseEndReason)
+        ),
         if (proto.hasExerciseConfig()) ExerciseConfig(proto.exerciseConfig) else null,
         if (proto.hasActiveDurationCheckpoint()) {
             ActiveDurationCheckpoint.fromProto(proto.activeDurationCheckpoint)
         } else {
             null
         },
-        ExerciseStateInfo(
-            ExerciseState.fromProto(proto.state)
-                ?: throw IllegalStateException("Invalid ExerciseState: ${proto.state}"),
-            ExerciseEndReason.fromProto(proto.exerciseEndReason)
-        ),
+        if (proto.hasUpdateDurationFromBootMs()) {
+            Duration.ofMillis(proto.updateDurationFromBootMs)
+        } else {
+            null
+        },
+        if (proto.hasStartTimeEpochMs()) Instant.ofEpochMilli(proto.startTimeEpochMs) else null,
     )
 
     /**
diff --git a/health/health-services-client/src/test/java/androidx/health/services/client/data/ExerciseUpdateTest.kt b/health/health-services-client/src/test/java/androidx/health/services/client/data/ExerciseUpdateTest.kt
index 591f8fd..e5c0a69 100644
--- a/health/health-services-client/src/test/java/androidx/health/services/client/data/ExerciseUpdateTest.kt
+++ b/health/health-services-client/src/test/java/androidx/health/services/client/data/ExerciseUpdateTest.kt
@@ -40,8 +40,6 @@
             DataTypeCondition(CALORIES_TOTAL, 125.0, GREATER_THAN_OR_EQUAL)
         )
         val proto = ExerciseUpdate(
-            startTime = 10.instant(),
-            updateDurationFromBoot = 42.duration(),
             latestMetrics = DataPointContainer(
                 listOf(DataPoints.calories(130.0, 15.duration(), 35.duration()))
             ),
@@ -57,6 +55,7 @@
                     )
                 )
             ),
+            exerciseStateInfo = ExerciseStateInfo(ExerciseState.ACTIVE, ExerciseEndReason.UNKNOWN),
             exerciseConfig = ExerciseConfig(
                 WALKING,
                 setOf(CALORIES_TOTAL),
@@ -65,7 +64,8 @@
                 exerciseGoals = listOf(goal)
             ),
             activeDurationCheckpoint = ActiveDurationCheckpoint(42.instant(), 30.duration()),
-            exerciseStateInfo = ExerciseStateInfo(ExerciseState.ACTIVE, ExerciseEndReason.UNKNOWN)
+            updateDurationFromBoot = 42.duration(),
+            startTime = 10.instant()
         ).proto
 
         val update = ExerciseUpdate(proto)