Simplify aggregation extension methods.
Use AggregateRequest/ReadRecordsRequest instead of separate parameters and delete
unnecessary overloads.
Bug: 326414908
Test: Updated tests
Change-Id: Ic8456d04c3537111a5a1c735b42df1ce1ebadd79
diff --git a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/BloodPressureAggregationExtensionsTest.kt b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/BloodPressureAggregationExtensionsTest.kt
index 5d7f993..6d5ea0a 100644
--- a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/BloodPressureAggregationExtensionsTest.kt
+++ b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/BloodPressureAggregationExtensionsTest.kt
@@ -26,6 +26,7 @@
import androidx.health.connect.client.records.BloodPressureRecord
import androidx.health.connect.client.records.NutritionRecord
import androidx.health.connect.client.records.metadata.DataOrigin
+import androidx.health.connect.client.request.AggregateRequest
import androidx.health.connect.client.time.TimeRangeFilter
import androidx.health.connect.client.units.millimetersOfMercury
import androidx.test.core.app.ApplicationProvider
@@ -90,9 +91,7 @@
assertThrows(IllegalStateException::class.java) {
runBlocking {
healthConnectClient.aggregateBloodPressure(
- metrics,
- TimeRangeFilter.none(),
- emptySet()
+ AggregateRequest(metrics, TimeRangeFilter.none(), emptySet())
)
}
}
@@ -111,7 +110,9 @@
)
val aggregationResult =
- healthConnectClient.aggregateBloodPressure(metrics, TimeRangeFilter.none(), emptySet())
+ healthConnectClient.aggregateBloodPressure(
+ AggregateRequest(metrics, TimeRangeFilter.none(), emptySet())
+ )
metrics.forEach { assertThat(it in aggregationResult).isFalse() }
assertThat(aggregationResult.dataOrigins).isEmpty()
@@ -156,9 +157,11 @@
val aggregationResult =
healthConnectClient.aggregateBloodPressure(
- setOf(BloodPressureRecord.SYSTOLIC_MAX),
- TimeRangeFilter.none(),
- emptySet()
+ AggregateRequest(
+ setOf(BloodPressureRecord.SYSTOLIC_MAX),
+ TimeRangeFilter.none(),
+ emptySet()
+ )
)
assertThat(aggregationResult[BloodPressureRecord.SYSTOLIC_MAX])
@@ -187,16 +190,18 @@
val aggregationResult =
healthConnectClient.aggregateBloodPressure(
- setOf(
- BloodPressureRecord.DIASTOLIC_AVG,
- BloodPressureRecord.DIASTOLIC_MAX,
- BloodPressureRecord.DIASTOLIC_MIN,
- BloodPressureRecord.SYSTOLIC_AVG,
- BloodPressureRecord.SYSTOLIC_MAX,
- BloodPressureRecord.SYSTOLIC_MIN,
- ),
- TimeRangeFilter.none(),
- emptySet()
+ AggregateRequest(
+ setOf(
+ BloodPressureRecord.DIASTOLIC_AVG,
+ BloodPressureRecord.DIASTOLIC_MAX,
+ BloodPressureRecord.DIASTOLIC_MIN,
+ BloodPressureRecord.SYSTOLIC_AVG,
+ BloodPressureRecord.SYSTOLIC_MAX,
+ BloodPressureRecord.SYSTOLIC_MIN,
+ ),
+ TimeRangeFilter.none(),
+ emptySet()
+ )
)
assertEquals(
@@ -231,13 +236,15 @@
val aggregationResult =
healthConnectClient.aggregateBloodPressure(
- setOf(
- BloodPressureRecord.DIASTOLIC_AVG,
- BloodPressureRecord.SYSTOLIC_MAX,
- BloodPressureRecord.SYSTOLIC_MIN,
- ),
- TimeRangeFilter.none(),
- emptySet()
+ AggregateRequest(
+ setOf(
+ BloodPressureRecord.DIASTOLIC_AVG,
+ BloodPressureRecord.SYSTOLIC_MAX,
+ BloodPressureRecord.SYSTOLIC_MIN,
+ ),
+ TimeRangeFilter.none(),
+ emptySet()
+ )
)
assertEquals(
@@ -293,9 +300,7 @@
val aggregationResult =
healthConnectClient.aggregateBloodPressure(
- emptySet(),
- TimeRangeFilter.none(),
- emptySet()
+ AggregateRequest(emptySet(), TimeRangeFilter.none(), emptySet())
)
setOf(
@@ -349,12 +354,14 @@
val aggregationResult =
healthConnectClient.aggregateBloodPressure(
- setOf(BloodPressureRecord.DIASTOLIC_MIN),
- TimeRangeFilter.between(
- START_TIME + 30.seconds,
- START_TIME + 6.minutes + 45.seconds
- ),
- emptySet()
+ AggregateRequest(
+ setOf(BloodPressureRecord.DIASTOLIC_MIN),
+ TimeRangeFilter.between(
+ START_TIME + 30.seconds,
+ START_TIME + 6.minutes + 45.seconds
+ ),
+ emptySet()
+ )
)
assertThat(aggregationResult[BloodPressureRecord.DIASTOLIC_MIN])
@@ -383,12 +390,14 @@
val aggregationResult =
healthConnectClient.aggregateBloodPressure(
- setOf(BloodPressureRecord.DIASTOLIC_AVG, BloodPressureRecord.SYSTOLIC_AVG),
- TimeRangeFilter.between(
- START_TIME + 1.minutes,
- START_TIME + 1.minutes + 59.seconds
- ),
- emptySet()
+ AggregateRequest(
+ setOf(BloodPressureRecord.DIASTOLIC_AVG, BloodPressureRecord.SYSTOLIC_AVG),
+ TimeRangeFilter.between(
+ START_TIME + 1.minutes,
+ START_TIME + 1.minutes + 59.seconds
+ ),
+ emptySet()
+ )
)
assertThat(BloodPressureRecord.DIASTOLIC_AVG in aggregationResult).isFalse()
@@ -436,18 +445,20 @@
val aggregationResult =
healthConnectClient.aggregateBloodPressure(
- setOf(BloodPressureRecord.DIASTOLIC_MIN, BloodPressureRecord.SYSTOLIC_AVG),
- TimeRangeFilter.between(
- LocalDateTime.ofInstant(
- START_TIME + 2.hours + 30.seconds,
- ZoneOffset.ofHours(-2)
+ AggregateRequest(
+ setOf(BloodPressureRecord.DIASTOLIC_MIN, BloodPressureRecord.SYSTOLIC_AVG),
+ TimeRangeFilter.between(
+ LocalDateTime.ofInstant(
+ START_TIME + 2.hours + 30.seconds,
+ ZoneOffset.ofHours(-2)
+ ),
+ LocalDateTime.ofInstant(
+ START_TIME + 2.hours + 6.minutes + 45.seconds,
+ ZoneOffset.ofHours(-2)
+ )
),
- LocalDateTime.ofInstant(
- START_TIME + 2.hours + 6.minutes + 45.seconds,
- ZoneOffset.ofHours(-2)
- )
- ),
- emptySet()
+ emptySet()
+ )
)
assertThat(aggregationResult[BloodPressureRecord.DIASTOLIC_MIN])
@@ -473,9 +484,11 @@
val aggregationResult =
healthConnectClient.aggregateBloodPressure(
- setOf(BloodPressureRecord.SYSTOLIC_AVG),
- TimeRangeFilter.none(),
- setOf(DataOrigin(context.packageName))
+ AggregateRequest(
+ setOf(BloodPressureRecord.SYSTOLIC_AVG),
+ TimeRangeFilter.none(),
+ setOf(DataOrigin(context.packageName))
+ )
)
assertThat(aggregationResult[BloodPressureRecord.SYSTOLIC_AVG])
@@ -498,9 +511,11 @@
val aggregationResult =
healthConnectClient.aggregateBloodPressure(
- setOf(BloodPressureRecord.SYSTOLIC_AVG),
- TimeRangeFilter.after(START_TIME + 2.minutes),
- emptySet()
+ AggregateRequest(
+ setOf(BloodPressureRecord.SYSTOLIC_AVG),
+ TimeRangeFilter.after(START_TIME + 2.minutes),
+ emptySet()
+ )
)
assertThat(BloodPressureRecord.SYSTOLIC_AVG in aggregationResult).isFalse()
@@ -522,9 +537,11 @@
val aggregationResult =
healthConnectClient.aggregateBloodPressure(
- setOf(BloodPressureRecord.SYSTOLIC_AVG),
- TimeRangeFilter.none(),
- setOf(DataOrigin("some random package name"))
+ AggregateRequest(
+ setOf(BloodPressureRecord.SYSTOLIC_AVG),
+ TimeRangeFilter.none(),
+ setOf(DataOrigin("some random package name"))
+ )
)
assertThat(BloodPressureRecord.SYSTOLIC_AVG in aggregationResult).isFalse()
diff --git a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/HealthConnectClientAggregationExtensionsTest.kt b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/HealthConnectClientAggregationExtensionsTest.kt
index b48b88b..1175e34 100644
--- a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/HealthConnectClientAggregationExtensionsTest.kt
+++ b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/HealthConnectClientAggregationExtensionsTest.kt
@@ -34,6 +34,7 @@
import androidx.health.connect.client.records.StepsRecord
import androidx.health.connect.client.records.metadata.DataOrigin
import androidx.health.connect.client.request.AggregateRequest
+import androidx.health.connect.client.request.ReadRecordsRequest
import androidx.health.connect.client.time.TimeRangeFilter
import androidx.health.connect.client.units.Velocity
import androidx.health.connect.client.units.grams
@@ -308,7 +309,9 @@
val count =
healthConnectClient
- .readRecordsFlow(StepsRecord::class, TimeRangeFilter.none(), emptySet())
+ .readRecordsFlow(
+ ReadRecordsRequest(StepsRecord::class, TimeRangeFilter.none(), emptySet())
+ )
.fold(0) { currentCount, records -> currentCount + records.size }
assertThat(count).isEqualTo(10_000L)
@@ -322,12 +325,14 @@
val count =
healthConnectClient
.readRecordsFlow(
- StepsRecord::class,
- TimeRangeFilter.between(
- START_TIME + 10_000.seconds,
- START_TIME + 90_000.seconds
- ),
- emptySet()
+ ReadRecordsRequest(
+ StepsRecord::class,
+ TimeRangeFilter.between(
+ START_TIME + 10_000.seconds,
+ START_TIME + 90_000.seconds
+ ),
+ emptySet()
+ )
)
.fold(0) { currentCount, records -> currentCount + records.size }
@@ -342,9 +347,11 @@
val count =
healthConnectClient
.readRecordsFlow(
- StepsRecord::class,
- TimeRangeFilter.none(),
- setOf(DataOrigin(context.packageName))
+ ReadRecordsRequest(
+ StepsRecord::class,
+ TimeRangeFilter.none(),
+ setOf(DataOrigin(context.packageName))
+ )
)
.fold(0) { currentCount, records -> currentCount + records.size }
@@ -358,9 +365,11 @@
val count =
healthConnectClient
.readRecordsFlow(
- StepsRecord::class,
- TimeRangeFilter.none(),
- setOf(DataOrigin("some random package name"))
+ ReadRecordsRequest(
+ StepsRecord::class,
+ TimeRangeFilter.none(),
+ setOf(DataOrigin("some random package name"))
+ )
)
.fold(0) { currentCount, records -> currentCount + records.size }
diff --git a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/NutritionAggregationExtensionsTest.kt b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/NutritionAggregationExtensionsTest.kt
index a197010..0e6d629 100644
--- a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/NutritionAggregationExtensionsTest.kt
+++ b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/NutritionAggregationExtensionsTest.kt
@@ -24,6 +24,7 @@
import androidx.health.connect.client.permission.HealthPermission
import androidx.health.connect.client.records.NutritionRecord
import androidx.health.connect.client.records.metadata.DataOrigin
+import androidx.health.connect.client.request.AggregateRequest
import androidx.health.connect.client.time.TimeRangeFilter
import androidx.health.connect.client.units.Mass
import androidx.test.core.app.ApplicationProvider
@@ -72,7 +73,9 @@
@Test
fun aggregateNutritionTransFatTotal_noData() = runTest {
val aggregationResult =
- healthConnectClient.aggregateNutritionTransFatTotal(TimeRangeFilter.none(), emptySet())
+ healthConnectClient.aggregateNutritionTransFatTotal(
+ AggregateRequest(emptySet(), TimeRangeFilter.none(), emptySet())
+ )
assertThat(NutritionRecord.TRANS_FAT_TOTAL in aggregationResult).isFalse()
assertThat(aggregationResult.dataOrigins).isEmpty()
@@ -121,7 +124,9 @@
)
val aggregationResult =
- healthConnectClient.aggregateNutritionTransFatTotal(TimeRangeFilter.none(), emptySet())
+ healthConnectClient.aggregateNutritionTransFatTotal(
+ AggregateRequest(emptySet(), TimeRangeFilter.none(), emptySet())
+ )
assertThat(aggregationResult[NutritionRecord.TRANS_FAT_TOTAL]).isEqualTo(Mass.grams(1.7))
assertThat(aggregationResult.dataOrigins).containsExactly(DataOrigin(context.packageName))
@@ -171,11 +176,14 @@
val aggregationResult =
healthConnectClient.aggregateNutritionTransFatTotal(
- TimeRangeFilter.between(
- START_TIME + 30.seconds,
- START_TIME + 6.minutes + 45.seconds
- ),
- emptySet()
+ AggregateRequest(
+ emptySet(),
+ TimeRangeFilter.between(
+ START_TIME + 30.seconds,
+ START_TIME + 6.minutes + 45.seconds
+ ),
+ emptySet()
+ )
)
assertThat(aggregationResult[NutritionRecord.TRANS_FAT_TOTAL])
@@ -207,8 +215,11 @@
val aggregationResult =
healthConnectClient.aggregateNutritionTransFatTotal(
- TimeRangeFilter.between(START_TIME + 1.minutes, START_TIME + 2.minutes),
- emptySet()
+ AggregateRequest(
+ emptySet(),
+ TimeRangeFilter.between(START_TIME + 1.minutes, START_TIME + 2.minutes),
+ emptySet()
+ )
)
assertThat(NutritionRecord.TRANS_FAT_TOTAL in aggregationResult).isFalse()
@@ -239,8 +250,11 @@
val aggregationResult =
healthConnectClient.aggregateNutritionTransFatTotal(
- TimeRangeFilter.between(START_TIME, START_TIME + 2.minutes),
- emptySet()
+ AggregateRequest(
+ emptySet(),
+ TimeRangeFilter.between(START_TIME, START_TIME + 2.minutes),
+ emptySet()
+ )
)
assertThat(aggregationResult[NutritionRecord.TRANS_FAT_TOTAL])
@@ -266,8 +280,11 @@
val aggregationResult =
healthConnectClient.aggregateNutritionTransFatTotal(
- TimeRangeFilter.between(START_TIME + 15.seconds, START_TIME + 45.seconds),
- emptySet()
+ AggregateRequest(
+ emptySet(),
+ TimeRangeFilter.between(START_TIME + 15.seconds, START_TIME + 45.seconds),
+ emptySet()
+ )
)
assertThat(aggregationResult[NutritionRecord.TRANS_FAT_TOTAL])
@@ -320,11 +337,14 @@
val aggregationResult =
healthConnectClient.aggregateNutritionTransFatTotal(
- TimeRangeFilter.between(
- LocalDateTime.ofInstant(START_TIME + 30.seconds, ZoneOffset.UTC),
- LocalDateTime.ofInstant(START_TIME + 6.minutes + 45.seconds, ZoneOffset.UTC)
- ),
- emptySet()
+ AggregateRequest(
+ emptySet(),
+ TimeRangeFilter.between(
+ LocalDateTime.ofInstant(START_TIME + 30.seconds, ZoneOffset.UTC),
+ LocalDateTime.ofInstant(START_TIME + 6.minutes + 45.seconds, ZoneOffset.UTC)
+ ),
+ emptySet()
+ )
)
assertThat(aggregationResult[NutritionRecord.TRANS_FAT_TOTAL])
@@ -349,17 +369,20 @@
val aggregationResult =
healthConnectClient.aggregateNutritionTransFatTotal(
- TimeRangeFilter.between(
- LocalDateTime.ofInstant(
- START_TIME - 2.hours + 15.seconds,
- ZoneOffset.ofHours(2)
+ AggregateRequest(
+ emptySet(),
+ TimeRangeFilter.between(
+ LocalDateTime.ofInstant(
+ START_TIME - 2.hours + 15.seconds,
+ ZoneOffset.ofHours(2)
+ ),
+ LocalDateTime.ofInstant(
+ START_TIME - 2.hours + 45.seconds,
+ ZoneOffset.ofHours(2)
+ )
),
- LocalDateTime.ofInstant(
- START_TIME - 2.hours + 45.seconds,
- ZoneOffset.ofHours(2)
- )
- ),
- emptySet()
+ emptySet()
+ )
)
assertThat(aggregationResult[NutritionRecord.TRANS_FAT_TOTAL])
@@ -385,8 +408,11 @@
val aggregationResult =
healthConnectClient.aggregateNutritionTransFatTotal(
- TimeRangeFilter.none(),
- setOf(DataOrigin(context.packageName))
+ AggregateRequest(
+ emptySet(),
+ TimeRangeFilter.none(),
+ setOf(DataOrigin(context.packageName))
+ )
)
assertThat(aggregationResult[NutritionRecord.TRANS_FAT_TOTAL]).isEqualTo(Mass.grams(0.5))
@@ -409,8 +435,11 @@
val aggregationResult =
healthConnectClient.aggregateNutritionTransFatTotal(
- TimeRangeFilter.after(START_TIME + 2.minutes),
- emptySet()
+ AggregateRequest(
+ emptySet(),
+ TimeRangeFilter.after(START_TIME + 2.minutes),
+ emptySet()
+ )
)
assertThat(NutritionRecord.TRANS_FAT_TOTAL in aggregationResult).isFalse()
@@ -433,11 +462,14 @@
val aggregationResult =
healthConnectClient.aggregateNutritionTransFatTotal(
- TimeRangeFilter.between(
- LocalDateTime.ofInstant(START_TIME, ZoneOffset.UTC),
- LocalDateTime.ofInstant(START_TIME + 60.minutes, ZoneOffset.UTC)
- ),
- emptySet()
+ AggregateRequest(
+ emptySet(),
+ TimeRangeFilter.between(
+ LocalDateTime.ofInstant(START_TIME, ZoneOffset.UTC),
+ LocalDateTime.ofInstant(START_TIME + 60.minutes, ZoneOffset.UTC)
+ ),
+ emptySet()
+ )
)
assertThat(NutritionRecord.TRANS_FAT_TOTAL in aggregationResult).isFalse()
@@ -460,8 +492,11 @@
val aggregationResult =
healthConnectClient.aggregateNutritionTransFatTotal(
- TimeRangeFilter.none(),
- setOf(DataOrigin("some random package name"))
+ AggregateRequest(
+ emptySet(),
+ TimeRangeFilter.none(),
+ setOf(DataOrigin("some random package name"))
+ )
)
assertThat(NutritionRecord.TRANS_FAT_TOTAL in aggregationResult).isFalse()
diff --git a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/SeriesRecordAggregationExtensionsTest.kt b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/SeriesRecordAggregationExtensionsTest.kt
index 5e42b96..3d67fb7 100644
--- a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/SeriesRecordAggregationExtensionsTest.kt
+++ b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/SeriesRecordAggregationExtensionsTest.kt
@@ -585,15 +585,16 @@
assertThrows(IllegalStateException::class.java) {
runBlocking {
healthConnectClient.aggregateSeriesRecord(
- recordType = StepsCadenceRecord::class,
- aggregateMetrics =
+ StepsCadenceRecord::class,
+ AggregateRequest(
setOf(
SpeedRecord.SPEED_AVG,
StepsCadenceRecord.RATE_MAX,
StepsCadenceRecord.RATE_MIN
),
- timeRangeFilter = TimeRangeFilter.none(),
- dataOriginFilter = emptySet()
+ TimeRangeFilter.none(),
+ emptySet()
+ )
) {
samples.map { SampleInfo(time = it.time, value = it.rate) }
}
@@ -607,14 +608,15 @@
runBlocking {
healthConnectClient.aggregateSeriesRecord(
recordType = HeartRateRecord::class,
- aggregateMetrics =
+ AggregateRequest(
setOf(
HeartRateRecord.BPM_AVG,
HeartRateRecord.BPM_MAX,
HeartRateRecord.BPM_MIN
),
- timeRangeFilter = TimeRangeFilter.none(),
- dataOriginFilter = emptySet()
+ TimeRangeFilter.none(),
+ emptySet()
+ )
) {
samples.map { SampleInfo(time = it.time, value = it.beatsPerMinute.toDouble()) }
}
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/HealthConnectClientUpsideDownImpl.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/HealthConnectClientUpsideDownImpl.kt
index e6f24bb..72298c5 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/HealthConnectClientUpsideDownImpl.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/HealthConnectClientUpsideDownImpl.kt
@@ -45,7 +45,7 @@
import androidx.health.connect.client.feature.HealthConnectFeaturesPlatformImpl
import androidx.health.connect.client.impl.platform.aggregate.AGGREGATE_METRICS_ADDED_IN_SDK_EXT_10
import androidx.health.connect.client.impl.platform.aggregate.aggregateFallback
-import androidx.health.connect.client.impl.platform.aggregate.platformMetrics
+import androidx.health.connect.client.impl.platform.aggregate.isPlatformSupportedMetric
import androidx.health.connect.client.impl.platform.aggregate.plus
import androidx.health.connect.client.impl.platform.records.toPlatformRecord
import androidx.health.connect.client.impl.platform.records.toPlatformRecordClass
@@ -222,7 +222,7 @@
val fallbackResponse = aggregateFallback(request)
- if (request.platformMetrics.isEmpty()) {
+ if (request.metrics.none { it.isPlatformSupportedMetric() }) {
return fallbackResponse
}
@@ -236,7 +236,7 @@
)
}
}
- .toSdkResponse(request.platformMetrics)
+ .toSdkResponse(request.metrics.filter { it.isPlatformSupportedMetric() }.toSet())
return platformResponse + fallbackResponse
}
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/AggregationExtensions.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/AggregationExtensions.kt
index 787968d..31f7abb 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/AggregationExtensions.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/AggregationExtensions.kt
@@ -30,21 +30,18 @@
import androidx.health.connect.client.records.StepsCadenceRecord
import androidx.health.connect.client.request.AggregateRequest
-internal val AggregateRequest.platformMetrics: Set<AggregateMetric<*>>
- get() {
- if (SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 10) {
- return metrics
- }
- return metrics.filterNot { it in AGGREGATE_METRICS_ADDED_IN_SDK_EXT_10 }.toSet()
- }
+internal fun AggregateRequest.withFilteredMetrics(predicate: (AggregateMetric<*>) -> Boolean) =
+ AggregateRequest(metrics.filter(predicate).toSet(), timeRangeFilter, dataOriginFilter)
-internal val AggregateRequest.fallbackMetrics: Set<AggregateMetric<*>>
- get() {
- if (SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 10) {
- return emptySet()
- }
- return metrics.filter { it in AGGREGATE_METRICS_ADDED_IN_SDK_EXT_10 }.toSet()
+// Only check against aggregate metrics added in sdk extension 10, to address b/326414908
+// Metrics added later on will be present dependent on feature availability
+internal fun AggregateMetric<*>.isPlatformSupportedMetric(): Boolean {
+ return if (SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 10) {
+ true
+ } else {
+ this !in AGGREGATE_METRICS_ADDED_IN_SDK_EXT_10
}
+}
internal operator fun AggregationResult.plus(other: AggregationResult): AggregationResult {
return AggregationResult(
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/BloodPressureAggregationExtensions.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/BloodPressureAggregationExtensions.kt
index 5051700..bad2c991 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/BloodPressureAggregationExtensions.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/BloodPressureAggregationExtensions.kt
@@ -24,7 +24,8 @@
import androidx.health.connect.client.aggregate.AggregationResult
import androidx.health.connect.client.records.BloodPressureRecord
import androidx.health.connect.client.records.metadata.DataOrigin
-import androidx.health.connect.client.time.TimeRangeFilter
+import androidx.health.connect.client.request.AggregateRequest
+import androidx.health.connect.client.request.ReadRecordsRequest
import androidx.health.connect.client.units.Pressure
import kotlin.math.max
import kotlin.math.min
@@ -40,25 +41,17 @@
)
internal suspend fun HealthConnectClient.aggregateBloodPressure(
- bloodPressureMetrics: Set<AggregateMetric<*>>,
- timeRangeFilter: TimeRangeFilter,
- dataOriginFilter: Set<DataOrigin>
-) =
- aggregateBloodPressure(
- timeRangeFilter,
- dataOriginFilter,
- BloodPressureAggregator(bloodPressureMetrics)
- )
-
-private suspend fun HealthConnectClient.aggregateBloodPressure(
- timeRangeFilter: TimeRangeFilter,
- dataOriginFilter: Set<DataOrigin>,
- aggregator: Aggregator<BloodPressureRecord>
+ aggregateRequest: AggregateRequest
): AggregationResult {
- readRecordsFlow(BloodPressureRecord::class, timeRangeFilter, dataOriginFilter).collect { records
- ->
- records.forEach { aggregator += it }
- }
+ val aggregator = BloodPressureAggregator(aggregateRequest.metrics)
+ readRecordsFlow(
+ ReadRecordsRequest(
+ BloodPressureRecord::class,
+ aggregateRequest.timeRangeFilter,
+ aggregateRequest.dataOriginFilter
+ )
+ )
+ .collect { records -> records.forEach { aggregator += it } }
return aggregator.getResult()
}
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/HealthConnectClientAggregationExtensions.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/HealthConnectClientAggregationExtensions.kt
index 9d81152..1adb5f6 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/HealthConnectClientAggregationExtensions.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/HealthConnectClientAggregationExtensions.kt
@@ -20,7 +20,6 @@
import androidx.annotation.RequiresApi
import androidx.health.connect.client.HealthConnectClient
-import androidx.health.connect.client.aggregate.AggregateMetric
import androidx.health.connect.client.aggregate.AggregationResult
import androidx.health.connect.client.impl.converters.datatype.RECORDS_CLASS_NAME_MAP
import androidx.health.connect.client.impl.platform.toInstantWithDefaultZoneFallback
@@ -32,7 +31,6 @@
import androidx.health.connect.client.records.Record
import androidx.health.connect.client.records.SpeedRecord
import androidx.health.connect.client.records.StepsCadenceRecord
-import androidx.health.connect.client.records.metadata.DataOrigin
import androidx.health.connect.client.request.AggregateRequest
import androidx.health.connect.client.request.ReadRecordsRequest
import androidx.health.connect.client.time.TimeRangeFilter
@@ -60,12 +58,7 @@
for (recordType in AGGREGATION_FALLBACK_RECORD_TYPES) {
aggregationResult +=
- aggregate(
- recordType,
- request.fallbackMetrics,
- request.timeRangeFilter,
- request.dataOriginFilter
- )
+ aggregate(recordType, request.withFilteredMetrics { !it.isPlatformSupportedMetric() })
}
return aggregationResult
@@ -73,51 +66,45 @@
private suspend fun <T : Record> HealthConnectClient.aggregate(
recordType: KClass<T>,
- metrics: Set<AggregateMetric<*>>,
- timeRangeFilter: TimeRangeFilter,
- dataOriginFilter: Set<DataOrigin>
+ request: AggregateRequest,
): AggregationResult {
val dataTypeName = RECORDS_CLASS_NAME_MAP[recordType]
- val recordTypeMetrics = metrics.filter { it.dataTypeName == dataTypeName }.toSet()
+ val recordTypeRequest = request.withFilteredMetrics { it.dataTypeName == dataTypeName }
- if (recordTypeMetrics.isEmpty()) {
+ if (recordTypeRequest.metrics.isEmpty()) {
return emptyAggregationResult()
}
return when (recordType) {
- BloodPressureRecord::class ->
- aggregateBloodPressure(recordTypeMetrics, timeRangeFilter, dataOriginFilter)
+ BloodPressureRecord::class -> aggregateBloodPressure(recordTypeRequest)
CyclingPedalingCadenceRecord::class ->
- aggregateCyclingPedalingCadence(recordTypeMetrics, timeRangeFilter, dataOriginFilter)
- NutritionRecord::class -> aggregateNutritionTransFatTotal(timeRangeFilter, dataOriginFilter)
- SpeedRecord::class -> aggregateSpeed(recordTypeMetrics, timeRangeFilter, dataOriginFilter)
+ aggregateSeriesRecord(CyclingPedalingCadenceRecord::class, recordTypeRequest) {
+ samples.map { SampleInfo(it.time, it.revolutionsPerMinute) }
+ }
+ NutritionRecord::class -> aggregateNutritionTransFatTotal(recordTypeRequest)
+ SpeedRecord::class ->
+ aggregateSeriesRecord(SpeedRecord::class, recordTypeRequest) {
+ samples.map { SampleInfo(it.time, it.speed.inMetersPerSecond) }
+ }
StepsCadenceRecord::class ->
- aggregateStepsCadence(recordTypeMetrics, timeRangeFilter, dataOriginFilter)
+ aggregateSeriesRecord(StepsCadenceRecord::class, recordTypeRequest) {
+ samples.map { SampleInfo(it.time, it.rate) }
+ }
else -> error("Invalid record type for aggregation fallback: $recordType")
}
}
-/** Reads all existing records that satisfy [timeRangeFilter] and [dataOriginFilter]. */
-suspend fun <T : Record> HealthConnectClient.readRecordsFlow(
- recordType: KClass<T>,
- timeRangeFilter: TimeRangeFilter,
- dataOriginFilter: Set<DataOrigin>
+/** Reads all existing records that satisfy [request]. */
+fun <T : Record> HealthConnectClient.readRecordsFlow(
+ request: ReadRecordsRequest<T>
): Flow<List<T>> {
return flow {
- var pageToken: String? = null
+ var currentRequest = request
do {
- val response =
- readRecords(
- ReadRecordsRequest(
- recordType = recordType,
- timeRangeFilter = timeRangeFilter,
- dataOriginFilter = dataOriginFilter,
- pageToken = pageToken
- )
- )
+ val response = readRecords(currentRequest)
emit(response.records)
- pageToken = response.pageToken
- } while (pageToken != null)
+ currentRequest = currentRequest.withPageToken(response.pageToken)
+ } while (currentRequest.pageToken != null)
}
}
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/NutritionAggregationExtensions.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/NutritionAggregationExtensions.kt
index 56a255c..927132ad 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/NutritionAggregationExtensions.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/NutritionAggregationExtensions.kt
@@ -29,23 +29,28 @@
import androidx.health.connect.client.records.IntervalRecord
import androidx.health.connect.client.records.NutritionRecord
import androidx.health.connect.client.records.metadata.DataOrigin
+import androidx.health.connect.client.request.AggregateRequest
+import androidx.health.connect.client.request.ReadRecordsRequest
import androidx.health.connect.client.time.TimeRangeFilter
import java.time.Instant
import kotlin.math.max
internal suspend fun HealthConnectClient.aggregateNutritionTransFatTotal(
- timeRangeFilter: TimeRangeFilter,
- dataOriginFilter: Set<DataOrigin>
-) = aggregateNutrition(timeRangeFilter, dataOriginFilter, TransFatTotalAggregator(timeRangeFilter))
-
-private suspend fun HealthConnectClient.aggregateNutrition(
- timeRangeFilter: TimeRangeFilter,
- dataOriginFilter: Set<DataOrigin>,
- aggregator: Aggregator<NutritionRecord>
+ aggregateRequest: AggregateRequest
): AggregationResult {
- readRecordsFlow(NutritionRecord::class, timeRangeFilter.withBufferedStart(), dataOriginFilter)
+ val aggregator = TransFatTotalAggregator(aggregateRequest.timeRangeFilter)
+
+ readRecordsFlow(
+ ReadRecordsRequest(
+ NutritionRecord::class,
+ aggregateRequest.timeRangeFilter.withBufferedStart(),
+ aggregateRequest.dataOriginFilter
+ )
+ )
.collect { records ->
- records.filter { it.overlaps(timeRangeFilter) }.forEach { aggregator += it }
+ records
+ .filter { it.overlaps(aggregateRequest.timeRangeFilter) }
+ .forEach { aggregator += it }
}
return aggregator.getResult()
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/SeriesRecordAggregationExtensions.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/SeriesRecordAggregationExtensions.kt
index 012c46d..958797e 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/SeriesRecordAggregationExtensions.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/SeriesRecordAggregationExtensions.kt
@@ -30,6 +30,8 @@
import androidx.health.connect.client.records.SpeedRecord
import androidx.health.connect.client.records.StepsCadenceRecord
import androidx.health.connect.client.records.metadata.DataOrigin
+import androidx.health.connect.client.request.AggregateRequest
+import androidx.health.connect.client.request.ReadRecordsRequest
import androidx.health.connect.client.time.TimeRangeFilter
import java.time.Instant
import java.time.ZoneOffset
@@ -59,74 +61,21 @@
)
)
-internal suspend fun HealthConnectClient.aggregateCyclingPedalingCadence(
- metrics: Set<AggregateMetric<*>>,
- timeRangeFilter: TimeRangeFilter,
- dataOriginFilter: Set<DataOrigin>
-) =
- aggregateSeriesRecord(
- recordType = CyclingPedalingCadenceRecord::class,
- aggregateMetrics = metrics,
- timeRangeFilter = timeRangeFilter,
- dataOriginFilter = dataOriginFilter
- ) {
- samples.map { SampleInfo(time = it.time, value = it.revolutionsPerMinute) }
- }
-
-internal suspend fun HealthConnectClient.aggregateSpeed(
- metrics: Set<AggregateMetric<*>>,
- timeRangeFilter: TimeRangeFilter,
- dataOriginFilter: Set<DataOrigin>
-) =
- aggregateSeriesRecord(
- recordType = SpeedRecord::class,
- aggregateMetrics = metrics,
- timeRangeFilter = timeRangeFilter,
- dataOriginFilter = dataOriginFilter
- ) {
- samples.map { SampleInfo(time = it.time, value = it.speed.inMetersPerSecond) }
- }
-
-internal suspend fun HealthConnectClient.aggregateStepsCadence(
- metrics: Set<AggregateMetric<*>>,
- timeRangeFilter: TimeRangeFilter,
- dataOriginFilter: Set<DataOrigin>
-) =
- aggregateSeriesRecord(
- recordType = StepsCadenceRecord::class,
- aggregateMetrics = metrics,
- timeRangeFilter = timeRangeFilter,
- dataOriginFilter = dataOriginFilter
- ) {
- samples.map { SampleInfo(time = it.time, value = it.rate) }
- }
-
-@VisibleForTesting
internal suspend fun <T : SeriesRecord<*>> HealthConnectClient.aggregateSeriesRecord(
recordType: KClass<T>,
- aggregateMetrics: Set<AggregateMetric<*>>,
- timeRangeFilter: TimeRangeFilter,
- dataOriginFilter: Set<DataOrigin>,
- getSampleInfo: T.() -> List<SampleInfo>
-) =
- aggregateSeriesRecord(
- recordType,
- timeRangeFilter,
- dataOriginFilter,
- SeriesAggregator(recordType, aggregateMetrics),
- getSampleInfo
- )
-
-private suspend fun <T : SeriesRecord<*>> HealthConnectClient.aggregateSeriesRecord(
- recordType: KClass<T>,
- timeRangeFilter: TimeRangeFilter,
- dataOriginFilter: Set<DataOrigin>,
- aggregator: Aggregator<RecordInfo>,
+ aggregateRequest: AggregateRequest,
getSampleInfo: T.() -> List<SampleInfo>
): AggregationResult {
val readRecordsFlow =
- readRecordsFlow(recordType, timeRangeFilter.withBufferedStart(), dataOriginFilter)
+ readRecordsFlow(
+ ReadRecordsRequest(
+ recordType,
+ aggregateRequest.timeRangeFilter.withBufferedStart(),
+ aggregateRequest.dataOriginFilter
+ )
+ )
+ val aggregator = SeriesAggregator(recordType, aggregateRequest.metrics)
readRecordsFlow.collect { records ->
records
.asSequence()
@@ -136,7 +85,7 @@
samples =
it.getSampleInfo().filter { sample ->
sample.isWithin(
- timeRangeFilter = timeRangeFilter,
+ timeRangeFilter = aggregateRequest.timeRangeFilter,
zoneOffset = it.startZoneOffset
)
}
@@ -207,7 +156,6 @@
@VisibleForTesting
internal data class RecordInfo(val dataOrigin: DataOrigin, val samples: List<SampleInfo>)
-@VisibleForTesting
internal data class SampleInfo(val time: Instant, val value: Double) {
fun isWithin(timeRangeFilter: TimeRangeFilter, zoneOffset: ZoneOffset?): Boolean {
if (timeRangeFilter.useLocalTime()) {
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/request/RequestConverters.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/request/RequestConverters.kt
index b12909e..1bf55fc 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/request/RequestConverters.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/request/RequestConverters.kt
@@ -42,7 +42,7 @@
import androidx.health.connect.client.impl.platform.aggregate.TEMPERATURE_DELTA_METRIC_TYPE_MAP
import androidx.health.connect.client.impl.platform.aggregate.VELOCITY_AGGREGATION_METRIC_TYPE_MAP
import androidx.health.connect.client.impl.platform.aggregate.VOLUME_AGGREGATION_METRIC_TYPE_MAP
-import androidx.health.connect.client.impl.platform.aggregate.platformMetrics
+import androidx.health.connect.client.impl.platform.aggregate.isPlatformSupportedMetric
import androidx.health.connect.client.impl.platform.records.toPlatformDataOrigin
import androidx.health.connect.client.impl.platform.records.toPlatformRecordClass
import androidx.health.connect.client.records.Record
@@ -116,7 +116,9 @@
return AggregateRecordsRequest.Builder<Any>(timeRangeFilter.toPlatformTimeRangeFilter())
.apply {
dataOriginFilter.forEach { addDataOriginsFilter(it.toPlatformDataOrigin()) }
- platformMetrics.forEach { addAggregationType(it.toAggregationType()) }
+ metrics
+ .filter { it.isPlatformSupportedMetric() }
+ .forEach { addAggregationType(it.toAggregationType()) }
}
.build()
}
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/request/ReadRecordsRequest.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/request/ReadRecordsRequest.kt
index 6810ac0..f0120f9 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/request/ReadRecordsRequest.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/request/ReadRecordsRequest.kt
@@ -104,6 +104,19 @@
require(pageSize > 0) { "pageSize must be positive." }
}
+ @OptIn(ExperimentalDeduplicationApi::class)
+ internal fun withPageToken(newPageToken: String?): ReadRecordsRequest<T> {
+ return ReadRecordsRequest(
+ recordType = recordType,
+ timeRangeFilter = timeRangeFilter,
+ dataOriginFilter = dataOriginFilter,
+ ascendingOrder = ascendingOrder,
+ pageSize = pageSize,
+ pageToken = newPageToken,
+ deduplicateStrategy = deduplicateStrategy
+ )
+ }
+
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false