[go: nahoru, domu]

Merge "Split out Flow.Spotting into its own record type." into androidx-main
diff --git a/health/connect/connect-client/api/current.txt b/health/connect/connect-client/api/current.txt
index 7b2b08d..081ecbd 100644
--- a/health/connect/connect-client/api/current.txt
+++ b/health/connect/connect-client/api/current.txt
@@ -722,23 +722,23 @@
   }
 
   public final class MenstruationFlowRecord implements androidx.health.connect.client.records.Record {
-    ctor public MenstruationFlowRecord(java.time.Instant time, java.time.ZoneOffset? zoneOffset, optional String? flow, optional androidx.health.connect.client.records.metadata.Metadata metadata);
-    method public String? getFlow();
+    ctor public MenstruationFlowRecord(java.time.Instant time, java.time.ZoneOffset? zoneOffset, optional int flow, optional androidx.health.connect.client.records.metadata.Metadata metadata);
+    method public int getFlow();
     method public androidx.health.connect.client.records.metadata.Metadata getMetadata();
     method public java.time.Instant getTime();
     method public java.time.ZoneOffset? getZoneOffset();
-    property public final String? flow;
+    property public final int flow;
     property public androidx.health.connect.client.records.metadata.Metadata metadata;
     property public java.time.Instant time;
     property public java.time.ZoneOffset? zoneOffset;
+    field public static final androidx.health.connect.client.records.MenstruationFlowRecord.Companion Companion;
+    field public static final int FLOW_HEAVY = 3; // 0x3
+    field public static final int FLOW_LIGHT = 1; // 0x1
+    field public static final int FLOW_MEDIUM = 2; // 0x2
+    field public static final int FLOW_UNKNOWN = 0; // 0x0
   }
 
-  public static final class MenstruationFlowRecord.Flow {
-    field public static final String HEAVY = "heavy";
-    field public static final androidx.health.connect.client.records.MenstruationFlowRecord.Flow INSTANCE;
-    field public static final String LIGHT = "light";
-    field public static final String MEDIUM = "medium";
-    field public static final String SPOTTING = "spotting";
+  public static final class MenstruationFlowRecord.Companion {
   }
 
   public final class NutritionRecord implements androidx.health.connect.client.records.Record {
diff --git a/health/connect/connect-client/api/public_plus_experimental_current.txt b/health/connect/connect-client/api/public_plus_experimental_current.txt
index 7b2b08d..081ecbd 100644
--- a/health/connect/connect-client/api/public_plus_experimental_current.txt
+++ b/health/connect/connect-client/api/public_plus_experimental_current.txt
@@ -722,23 +722,23 @@
   }
 
   public final class MenstruationFlowRecord implements androidx.health.connect.client.records.Record {
-    ctor public MenstruationFlowRecord(java.time.Instant time, java.time.ZoneOffset? zoneOffset, optional String? flow, optional androidx.health.connect.client.records.metadata.Metadata metadata);
-    method public String? getFlow();
+    ctor public MenstruationFlowRecord(java.time.Instant time, java.time.ZoneOffset? zoneOffset, optional int flow, optional androidx.health.connect.client.records.metadata.Metadata metadata);
+    method public int getFlow();
     method public androidx.health.connect.client.records.metadata.Metadata getMetadata();
     method public java.time.Instant getTime();
     method public java.time.ZoneOffset? getZoneOffset();
-    property public final String? flow;
+    property public final int flow;
     property public androidx.health.connect.client.records.metadata.Metadata metadata;
     property public java.time.Instant time;
     property public java.time.ZoneOffset? zoneOffset;
+    field public static final androidx.health.connect.client.records.MenstruationFlowRecord.Companion Companion;
+    field public static final int FLOW_HEAVY = 3; // 0x3
+    field public static final int FLOW_LIGHT = 1; // 0x1
+    field public static final int FLOW_MEDIUM = 2; // 0x2
+    field public static final int FLOW_UNKNOWN = 0; // 0x0
   }
 
-  public static final class MenstruationFlowRecord.Flow {
-    field public static final String HEAVY = "heavy";
-    field public static final androidx.health.connect.client.records.MenstruationFlowRecord.Flow INSTANCE;
-    field public static final String LIGHT = "light";
-    field public static final String MEDIUM = "medium";
-    field public static final String SPOTTING = "spotting";
+  public static final class MenstruationFlowRecord.Companion {
   }
 
   public final class NutritionRecord implements androidx.health.connect.client.records.Record {
diff --git a/health/connect/connect-client/api/restricted_current.txt b/health/connect/connect-client/api/restricted_current.txt
index 4cb4ac9..a9c1a0f 100644
--- a/health/connect/connect-client/api/restricted_current.txt
+++ b/health/connect/connect-client/api/restricted_current.txt
@@ -740,23 +740,23 @@
   }
 
   public final class MenstruationFlowRecord implements androidx.health.connect.client.records.InstantaneousRecord {
-    ctor public MenstruationFlowRecord(java.time.Instant time, java.time.ZoneOffset? zoneOffset, optional String? flow, optional androidx.health.connect.client.records.metadata.Metadata metadata);
-    method public String? getFlow();
+    ctor public MenstruationFlowRecord(java.time.Instant time, java.time.ZoneOffset? zoneOffset, optional int flow, optional androidx.health.connect.client.records.metadata.Metadata metadata);
+    method public int getFlow();
     method public androidx.health.connect.client.records.metadata.Metadata getMetadata();
     method public java.time.Instant getTime();
     method public java.time.ZoneOffset? getZoneOffset();
-    property public final String? flow;
+    property public final int flow;
     property public androidx.health.connect.client.records.metadata.Metadata metadata;
     property public java.time.Instant time;
     property public java.time.ZoneOffset? zoneOffset;
+    field public static final androidx.health.connect.client.records.MenstruationFlowRecord.Companion Companion;
+    field public static final int FLOW_HEAVY = 3; // 0x3
+    field public static final int FLOW_LIGHT = 1; // 0x1
+    field public static final int FLOW_MEDIUM = 2; // 0x2
+    field public static final int FLOW_UNKNOWN = 0; // 0x0
   }
 
-  public static final class MenstruationFlowRecord.Flow {
-    field public static final String HEAVY = "heavy";
-    field public static final androidx.health.connect.client.records.MenstruationFlowRecord.Flow INSTANCE;
-    field public static final String LIGHT = "light";
-    field public static final String MEDIUM = "medium";
-    field public static final String SPOTTING = "spotting";
+  public static final class MenstruationFlowRecord.Companion {
   }
 
   public final class NutritionRecord implements androidx.health.connect.client.records.IntervalRecord {
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/converters/datatype/RecordsTypeNameMap.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/converters/datatype/RecordsTypeNameMap.kt
index f5a6f70..6321e59 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/converters/datatype/RecordsTypeNameMap.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/converters/datatype/RecordsTypeNameMap.kt
@@ -49,6 +49,7 @@
 import androidx.health.connect.client.records.HeightRecord
 import androidx.health.connect.client.records.HipCircumferenceRecord
 import androidx.health.connect.client.records.HydrationRecord
+import androidx.health.connect.client.records.IntermenstrualBleedingRecord
 import androidx.health.connect.client.records.LeanBodyMassRecord
 import androidx.health.connect.client.records.MenstruationFlowRecord
 import androidx.health.connect.client.records.NutritionRecord
@@ -119,6 +120,7 @@
         "SleepSession" to SleepSessionRecord::class,
         "SleepStage" to SleepStageRecord::class,
         "SpeedSeries" to SpeedRecord::class, // Keep legacy Series suffix
+        "IntermenstrualBleeding" to IntermenstrualBleedingRecord::class,
         "Steps" to StepsRecord::class,
         "StepsCadenceSeries" to StepsCadenceRecord::class, // Keep legacy Series suffix
         "SwimmingStrokes" to SwimmingStrokesRecord::class,
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/converters/records/ProtoToRecordConverters.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/converters/records/ProtoToRecordConverters.kt
index 80ac8cc..8330756 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/converters/records/ProtoToRecordConverters.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/converters/records/ProtoToRecordConverters.kt
@@ -52,6 +52,7 @@
 import androidx.health.connect.client.records.HeightRecord
 import androidx.health.connect.client.records.HipCircumferenceRecord
 import androidx.health.connect.client.records.HydrationRecord
+import androidx.health.connect.client.records.IntermenstrualBleedingRecord
 import androidx.health.connect.client.records.LeanBodyMassRecord
 import androidx.health.connect.client.records.MealType
 import androidx.health.connect.client.records.MenstruationFlowRecord
@@ -328,7 +329,12 @@
                 )
             "Menstruation" ->
                 MenstruationFlowRecord(
-                    flow = getEnum("flow"),
+                    flow =
+                        mapEnum(
+                            "flow",
+                            MenstruationFlowRecord.FLOW_TYPE_STRING_TO_INT_MAP,
+                            MenstruationFlowRecord.FLOW_UNKNOWN
+                        ),
                     time = time,
                     zoneOffset = zoneOffset,
                     metadata = metadata
@@ -630,6 +636,12 @@
                     endZoneOffset = endZoneOffset,
                     metadata = metadata
                 )
+            "IntermenstrualBleeding" ->
+                IntermenstrualBleedingRecord(
+                    time = time,
+                    zoneOffset = zoneOffset,
+                    metadata = metadata
+                )
             "Steps" ->
                 StepsRecord(
                     count = getLong("count"),
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/converters/records/RecordToProtoConverters.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/converters/records/RecordToProtoConverters.kt
index 575dfc8..aa31176 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/converters/records/RecordToProtoConverters.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/converters/records/RecordToProtoConverters.kt
@@ -52,6 +52,7 @@
 import androidx.health.connect.client.records.HeightRecord
 import androidx.health.connect.client.records.HipCircumferenceRecord
 import androidx.health.connect.client.records.HydrationRecord
+import androidx.health.connect.client.records.IntermenstrualBleedingRecord
 import androidx.health.connect.client.records.LeanBodyMassRecord
 import androidx.health.connect.client.records.MealType
 import androidx.health.connect.client.records.MenstruationFlowRecord
@@ -246,6 +247,8 @@
                 .setDataType(protoDataType("HeartRateVariabilityTinn"))
                 .apply { putValues("heartRateVariability", doubleVal(heartRateVariabilityMillis)) }
                 .build()
+        is IntermenstrualBleedingRecord ->
+            instantaneousProto().setDataType(protoDataType("IntermenstrualBleeding")).build()
         is LeanBodyMassRecord ->
             instantaneousProto()
                 .setDataType(protoDataType("LeanBodyMass"))
@@ -254,7 +257,11 @@
         is MenstruationFlowRecord ->
             instantaneousProto()
                 .setDataType(protoDataType("Menstruation"))
-                .apply { flow?.let { putValues("flow", enumVal(it)) } }
+                .apply {
+                    enumValFromInt(flow, MenstruationFlowRecord.FLOW_TYPE_INT_TO_STRING_MAP)?.let {
+                        putValues("flow", it)
+                    }
+                }
                 .build()
         is OvulationTestRecord ->
             instantaneousProto()
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/permission/HealthPermission.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/permission/HealthPermission.kt
index e80113c..2a787eb 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/permission/HealthPermission.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/permission/HealthPermission.kt
@@ -223,6 +223,9 @@
         const val READ_HEART_RATE_VARIABILITY =
             "android.permission.health.READ_HEART_RATE_VARIABILITY"
         @RestrictTo(RestrictTo.Scope.LIBRARY)
+        const val READ_INTERMENSTRUAL_BLEEDING =
+            "android.permission.health.READ_INTERMENSTRUAL_BLEEDING"
+        @RestrictTo(RestrictTo.Scope.LIBRARY)
         const val READ_OXYGEN_SATURATION = "android.permission.health.READ_OXYGEN_SATURATION"
         @RestrictTo(RestrictTo.Scope.LIBRARY)
         const val READ_RESPIRATORY_RATE = "android.permission.health.READ_RESPIRATORY_RATE"
@@ -270,6 +273,9 @@
         @RestrictTo(RestrictTo.Scope.LIBRARY)
         const val WRITE_HIP_CIRCUMFERENCE = "android.permission.health.WRITE_HIP_CIRCUMFERENCE"
         @RestrictTo(RestrictTo.Scope.LIBRARY)
+        const val WRITE_INTERMENSTRUAL_BLEEDING =
+            "android.permission.health.WRITE_INTERMENSTRUAL_BLEEDING"
+        @RestrictTo(RestrictTo.Scope.LIBRARY)
         const val WRITE_LEAN_BODY_MASS = "android.permission.health.WRITE_LEAN_BODY_MASS"
         @RestrictTo(RestrictTo.Scope.LIBRARY)
         const val WRITE_WAIST_CIRCUMFERENCE = "android.permission.health.WRITE_WAIST_CIRCUMFERENCE"
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/IntermenstrualBleedingRecord.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/IntermenstrualBleedingRecord.kt
new file mode 100644
index 0000000..9de56a8
--- /dev/null
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/IntermenstrualBleedingRecord.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.health.connect.client.records
+
+import androidx.annotation.RestrictTo
+import androidx.health.connect.client.records.metadata.Metadata
+import java.time.Instant
+import java.time.ZoneOffset
+
+/** Captures an instance of user's intermenstrual bleeding, also known as spotting. */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+class IntermenstrualBleedingRecord(
+    override val time: Instant,
+    override val zoneOffset: ZoneOffset?,
+    override val metadata: Metadata = Metadata.EMPTY,
+) : InstantaneousRecord {
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (javaClass != other?.javaClass) return false
+
+        other as IntermenstrualBleedingRecord
+
+        if (time != other.time) return false
+        if (zoneOffset != other.zoneOffset) return false
+        if (metadata != other.metadata) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = time.hashCode()
+        result = 31 * result + (zoneOffset?.hashCode() ?: 0)
+        result = 31 * result + metadata.hashCode()
+        return result
+    }
+}
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/MenstruationFlowRecord.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/MenstruationFlowRecord.kt
index c7d2aa5..045e955 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/MenstruationFlowRecord.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/records/MenstruationFlowRecord.kt
@@ -15,25 +15,21 @@
  */
 package androidx.health.connect.client.records
 
+import androidx.annotation.IntDef
 import androidx.annotation.RestrictTo
-import androidx.annotation.StringDef
 import androidx.health.connect.client.records.metadata.Metadata
 import java.time.Instant
 import java.time.ZoneOffset
 
 /**
- * Captures a description of how heavy a user's menstrual flow was (spotting, light, medium, or
+ * Captures a description of how heavy a user's menstrual flow was (light, medium, or
  * heavy). Each record represents a description of how heavy the user's menstrual bleeding was.
  */
 public class MenstruationFlowRecord(
     override val time: Instant,
     override val zoneOffset: ZoneOffset?,
-    /**
-     * How heavy the user's menstrual flow was. Optional field. Allowed values: [Flow].
-     *
-     * @see Flow
-     */
-    @property:Flows public val flow: String? = null,
+    /** How heavy the user's menstrual flow was. Optional field. */
+    @property:Flows public val flow: Int = FLOW_UNKNOWN,
     override val metadata: Metadata = Metadata.EMPTY,
 ) : InstantaneousRecord {
     override fun equals(other: Any?): Boolean {
@@ -49,36 +45,35 @@
     }
 
     override fun hashCode(): Int {
-        var result = 0
-        result = 31 * result + flow.hashCode()
+        var result = flow
         result = 31 * result + time.hashCode()
         result = 31 * result + (zoneOffset?.hashCode() ?: 0)
         result = 31 * result + metadata.hashCode()
         return result
     }
 
-    /** How heavy the user's menstruation flow was. */
-    public object Flow {
-        const val SPOTTING = "spotting"
-        const val LIGHT = "light"
-        const val MEDIUM = "medium"
-        const val HEAVY = "heavy"
-    }
+    companion object {
+        const val FLOW_UNKNOWN = 0
+        const val FLOW_LIGHT = 1
+        const val FLOW_MEDIUM = 2
+        const val FLOW_HEAVY = 3
 
+        @RestrictTo(RestrictTo.Scope.LIBRARY)
+        @JvmField
+        val FLOW_TYPE_STRING_TO_INT_MAP: Map<String, Int> =
+            mapOf("light" to FLOW_LIGHT, "medium" to FLOW_MEDIUM, "heavy" to FLOW_HEAVY)
+
+        @RestrictTo(RestrictTo.Scope.LIBRARY)
+        @JvmField
+        val FLOW_TYPE_INT_TO_STRING_MAP: Map<Int, String> =
+            FLOW_TYPE_STRING_TO_INT_MAP.entries.associateBy({ it.value }, { it.key })
+    }
     /**
      * How heavy the user's menstruation flow was.
      * @suppress
      */
     @Retention(AnnotationRetention.SOURCE)
-    @StringDef(
-        value =
-            [
-                MenstruationFlowRecord.Flow.SPOTTING,
-                MenstruationFlowRecord.Flow.LIGHT,
-                MenstruationFlowRecord.Flow.MEDIUM,
-                MenstruationFlowRecord.Flow.HEAVY,
-            ]
-    )
+    @IntDef(value = [FLOW_UNKNOWN, FLOW_LIGHT, FLOW_MEDIUM, FLOW_HEAVY])
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     annotation class Flows
 }
diff --git a/health/connect/connect-client/src/test/java/androidx/health/connect/client/impl/converters/records/AllRecordsConverterTest.kt b/health/connect/connect-client/src/test/java/androidx/health/connect/client/impl/converters/records/AllRecordsConverterTest.kt
index bcd4c96..0291436 100644
--- a/health/connect/connect-client/src/test/java/androidx/health/connect/client/impl/converters/records/AllRecordsConverterTest.kt
+++ b/health/connect/connect-client/src/test/java/androidx/health/connect/client/impl/converters/records/AllRecordsConverterTest.kt
@@ -50,10 +50,10 @@
 import androidx.health.connect.client.records.HeightRecord
 import androidx.health.connect.client.records.HipCircumferenceRecord
 import androidx.health.connect.client.records.HydrationRecord
+import androidx.health.connect.client.records.IntermenstrualBleedingRecord
 import androidx.health.connect.client.records.LeanBodyMassRecord
 import androidx.health.connect.client.records.MealType
 import androidx.health.connect.client.records.MenstruationFlowRecord
-import androidx.health.connect.client.records.MenstruationFlowRecord.Flow
 import androidx.health.connect.client.records.NutritionRecord
 import androidx.health.connect.client.records.OvulationTestRecord
 import androidx.health.connect.client.records.OxygenSaturationRecord
@@ -468,6 +468,19 @@
     }
 
     @Test
+    fun testIntermenstrualBleeding() {
+        val data =
+            IntermenstrualBleedingRecord(
+                time = START_TIME,
+                zoneOffset = END_ZONE_OFFSET,
+                metadata = TEST_METADATA
+            )
+
+        checkProtoAndRecordTypeNameMatch(data)
+        assertThat(toRecord(data.toProto())).isEqualTo(data)
+    }
+
+    @Test
     fun testLeanBodyMass() {
         val data =
             LeanBodyMassRecord(
@@ -485,7 +498,7 @@
     fun testMenstruation() {
         val data =
             MenstruationFlowRecord(
-                flow = Flow.HEAVY,
+                flow = MenstruationFlowRecord.FLOW_HEAVY,
                 time = START_TIME,
                 zoneOffset = END_ZONE_OFFSET,
                 metadata = TEST_METADATA