• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.health.connect.datatypes;
17 
18 import static android.health.connect.datatypes.validation.ValidationUtils.validateIntDefValue;
19 
20 import android.annotation.IntDef;
21 import android.annotation.NonNull;
22 import android.health.connect.internal.datatypes.SexualActivityRecordInternal;
23 
24 import java.lang.annotation.Retention;
25 import java.lang.annotation.RetentionPolicy;
26 import java.time.Instant;
27 import java.time.ZoneOffset;
28 import java.util.Objects;
29 import java.util.Set;
30 
31 /**
32  * Captures an occurrence of sexual activity. Each record is a single occurrence. ProtectionUsed
33  * field is optional.
34  */
35 @Identifier(recordIdentifier = RecordTypeIdentifier.RECORD_TYPE_SEXUAL_ACTIVITY)
36 public final class SexualActivityRecord extends InstantRecord {
37 
38     private final int mProtectionUsed;
39 
40     /**
41      * @param metadata Metadata to be associated with the record. See {@link Metadata}.
42      * @param time Start time of this activity
43      * @param zoneOffset Zone offset of the user when the activity started
44      * @param protectionUsed ProtectionUsed of this activity
45      * @param skipValidation Boolean flag to skip validation of record values.
46      */
SexualActivityRecord( @onNull Metadata metadata, @NonNull Instant time, @NonNull ZoneOffset zoneOffset, @SexualActivityProtectionUsed.SexualActivityProtectionUsedTypes int protectionUsed, boolean skipValidation)47     private SexualActivityRecord(
48             @NonNull Metadata metadata,
49             @NonNull Instant time,
50             @NonNull ZoneOffset zoneOffset,
51             @SexualActivityProtectionUsed.SexualActivityProtectionUsedTypes int protectionUsed,
52             boolean skipValidation) {
53         super(metadata, time, zoneOffset, skipValidation);
54         Objects.requireNonNull(metadata);
55         Objects.requireNonNull(time);
56         Objects.requireNonNull(zoneOffset);
57         validateIntDefValue(
58                 protectionUsed,
59                 SexualActivityProtectionUsed.VALID_TYPES,
60                 SexualActivityProtectionUsed.class.getSimpleName());
61         mProtectionUsed = protectionUsed;
62     }
63 
64     /**
65      * @return protectionUsed
66      */
67     @SexualActivityProtectionUsed.SexualActivityProtectionUsedTypes
getProtectionUsed()68     public int getProtectionUsed() {
69         return mProtectionUsed;
70     }
71 
72     /** Identifier for sexual activity protection used */
73     public static final class SexualActivityProtectionUsed {
74         public static final int PROTECTION_USED_UNKNOWN = 0;
75         public static final int PROTECTION_USED_PROTECTED = 1;
76         public static final int PROTECTION_USED_UNPROTECTED = 2;
77 
78         /**
79          * Valid set of values for this IntDef. Update this set when add new type or deprecate
80          * existing type.
81          *
82          * @hide
83          */
84         public static final Set<Integer> VALID_TYPES =
85                 Set.of(
86                         PROTECTION_USED_UNKNOWN,
87                         PROTECTION_USED_PROTECTED,
88                         PROTECTION_USED_UNPROTECTED);
89 
SexualActivityProtectionUsed()90         SexualActivityProtectionUsed() {}
91 
92         /** @hide */
93         @IntDef({PROTECTION_USED_UNKNOWN, PROTECTION_USED_PROTECTED, PROTECTION_USED_UNPROTECTED})
94         @Retention(RetentionPolicy.SOURCE)
95         public @interface SexualActivityProtectionUsedTypes {}
96     }
97 
98     /**
99      * Indicates whether some other object is "equal to" this one.
100      *
101      * @param o the reference object with which to compare.
102      * @return {@code true} if this object is the same as the obj
103      */
104     @Override
equals(Object o)105     public boolean equals(Object o) {
106         if (this == o) return true;
107         if (!super.equals(o)) return false;
108         SexualActivityRecord that = (SexualActivityRecord) o;
109         return getProtectionUsed() == that.getProtectionUsed();
110     }
111 
112     /** Returns a hash code value for the object. */
113     @Override
hashCode()114     public int hashCode() {
115         return Objects.hash(super.hashCode(), getProtectionUsed());
116     }
117 
118     /** Builder class for {@link SexualActivityRecord} */
119     public static final class Builder {
120         private final Metadata mMetadata;
121         private final Instant mTime;
122         private ZoneOffset mZoneOffset;
123         private final int mProtectionUsed;
124 
125         /**
126          * @param metadata Metadata to be associated with the record. See {@link Metadata}.
127          * @param time Start time of this activity
128          * @param protectionUsed Whether protection was used during sexual activity. Optional field,
129          *     null if unknown. Allowed values: Protection.
130          */
Builder( @onNull Metadata metadata, @NonNull Instant time, @SexualActivityProtectionUsed.SexualActivityProtectionUsedTypes int protectionUsed)131         public Builder(
132                 @NonNull Metadata metadata,
133                 @NonNull Instant time,
134                 @SexualActivityProtectionUsed.SexualActivityProtectionUsedTypes
135                         int protectionUsed) {
136             Objects.requireNonNull(metadata);
137             Objects.requireNonNull(time);
138             mMetadata = metadata;
139             mTime = time;
140             mProtectionUsed = protectionUsed;
141             mZoneOffset = ZoneOffset.systemDefault().getRules().getOffset(time);
142         }
143 
144         /** Sets the zone offset of the user when the activity happened */
145         @NonNull
setZoneOffset(@onNull ZoneOffset zoneOffset)146         public Builder setZoneOffset(@NonNull ZoneOffset zoneOffset) {
147             Objects.requireNonNull(zoneOffset);
148             mZoneOffset = zoneOffset;
149             return this;
150         }
151 
152         /** Sets the zone offset of this record to system default. */
153         @NonNull
clearZoneOffset()154         public Builder clearZoneOffset() {
155             mZoneOffset = RecordUtils.getDefaultZoneOffset();
156             return this;
157         }
158 
159         /**
160          * @return Object of {@link SexualActivityRecord} without validating the values.
161          * @hide
162          */
163         @NonNull
buildWithoutValidation()164         public SexualActivityRecord buildWithoutValidation() {
165             return new SexualActivityRecord(mMetadata, mTime, mZoneOffset, mProtectionUsed, true);
166         }
167 
168         /**
169          * @return Object of {@link SexualActivityRecord}
170          */
171         @NonNull
build()172         public SexualActivityRecord build() {
173             return new SexualActivityRecord(mMetadata, mTime, mZoneOffset, mProtectionUsed, false);
174         }
175     }
176 
177     /** @hide */
178     @Override
toRecordInternal()179     public SexualActivityRecordInternal toRecordInternal() {
180         SexualActivityRecordInternal recordInternal =
181                 (SexualActivityRecordInternal)
182                         new SexualActivityRecordInternal()
183                                 .setUuid(getMetadata().getId())
184                                 .setPackageName(getMetadata().getDataOrigin().getPackageName())
185                                 .setLastModifiedTime(
186                                         getMetadata().getLastModifiedTime().toEpochMilli())
187                                 .setClientRecordId(getMetadata().getClientRecordId())
188                                 .setClientRecordVersion(getMetadata().getClientRecordVersion())
189                                 .setManufacturer(getMetadata().getDevice().getManufacturer())
190                                 .setModel(getMetadata().getDevice().getModel())
191                                 .setDeviceType(getMetadata().getDevice().getType())
192                                 .setRecordingMethod(getMetadata().getRecordingMethod());
193         recordInternal.setTime(getTime().toEpochMilli());
194         recordInternal.setZoneOffset(getZoneOffset().getTotalSeconds());
195         recordInternal.setProtectionUsed(mProtectionUsed);
196         return recordInternal;
197     }
198 }
199