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 
17 package android.health.connect.datatypes.validation;
18 
19 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_ARM_CURL;
20 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_BACK_EXTENSION;
21 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_BALL_SLAM;
22 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_BARBELL_SHOULDER_PRESS;
23 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_BENCH_PRESS;
24 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_BENCH_SIT_UP;
25 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_BIKING;
26 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_BIKING_STATIONARY;
27 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_BURPEE;
28 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_CRUNCH;
29 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_DEADLIFT;
30 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_DOUBLE_ARM_TRICEPS_EXTENSION;
31 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_DUMBBELL_CURL_LEFT_ARM;
32 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_DUMBBELL_CURL_RIGHT_ARM;
33 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_DUMBBELL_FRONT_RAISE;
34 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_DUMBBELL_LATERAL_RAISE;
35 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_DUMBBELL_ROW;
36 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_DUMBBELL_TRICEPS_EXTENSION_LEFT_ARM;
37 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_DUMBBELL_TRICEPS_EXTENSION_RIGHT_ARM;
38 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_DUMBBELL_TRICEPS_EXTENSION_TWO_ARM;
39 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_ELLIPTICAL;
40 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_FORWARD_TWIST;
41 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_FRONT_RAISE;
42 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING;
43 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_HIP_THRUST;
44 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_HULA_HOOP;
45 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_JUMPING_JACK;
46 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_JUMP_ROPE;
47 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_KETTLEBELL_SWING;
48 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_LATERAL_RAISE;
49 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_LAT_PULL_DOWN;
50 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_LEG_CURL;
51 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_LEG_EXTENSION;
52 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_LEG_PRESS;
53 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_LEG_RAISE;
54 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_LUNGE;
55 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_MOUNTAIN_CLIMBER;
56 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_OTHER_WORKOUT;
57 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_PAUSE;
58 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_PILATES;
59 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_PLANK;
60 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_PULL_UP;
61 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_PUNCH;
62 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_REST;
63 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_ROWING_MACHINE;
64 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_RUNNING;
65 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_RUNNING_TREADMILL;
66 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_SHOULDER_PRESS;
67 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_SINGLE_ARM_TRICEPS_EXTENSION;
68 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_SIT_UP;
69 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_SQUAT;
70 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_STAIR_CLIMBING;
71 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_STAIR_CLIMBING_MACHINE;
72 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_STRETCHING;
73 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_SWIMMING_BACKSTROKE;
74 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_SWIMMING_BREASTSTROKE;
75 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_SWIMMING_BUTTERFLY;
76 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_SWIMMING_FREESTYLE;
77 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_SWIMMING_MIXED;
78 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_SWIMMING_OPEN_WATER;
79 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_SWIMMING_OTHER;
80 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_SWIMMING_POOL;
81 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_UNKNOWN;
82 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_UPPER_TWIST;
83 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_WALKING;
84 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_WEIGHTLIFTING;
85 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_WHEELCHAIR;
86 import static android.health.connect.datatypes.ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_YOGA;
87 import static android.health.connect.datatypes.ExerciseSegmentType.isKnownSegmentType;
88 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_BIKING;
89 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_BIKING_STATIONARY;
90 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_BOOT_CAMP;
91 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_CALISTHENICS;
92 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_ELLIPTICAL;
93 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_EXERCISE_CLASS;
94 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_GYMNASTICS;
95 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING;
96 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_HIKING;
97 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_OTHER_WORKOUT;
98 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_PILATES;
99 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_ROWING_MACHINE;
100 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_RUNNING;
101 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_RUNNING_TREADMILL;
102 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_STAIR_CLIMBING;
103 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_STAIR_CLIMBING_MACHINE;
104 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_STRENGTH_TRAINING;
105 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_SWIMMING_OPEN_WATER;
106 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_SWIMMING_POOL;
107 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_UNKNOWN;
108 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_WALKING;
109 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_WEIGHTLIFTING;
110 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_WHEELCHAIR;
111 import static android.health.connect.datatypes.ExerciseSessionType.EXERCISE_SESSION_TYPE_YOGA;
112 import static android.health.connect.datatypes.ExerciseSessionType.isKnownSessionType;
113 
114 import android.health.connect.datatypes.ExerciseRoute;
115 import android.health.connect.datatypes.ExerciseSegment;
116 import android.util.ArrayMap;
117 import android.util.ArraySet;
118 import android.util.Slog;
119 
120 import java.time.Instant;
121 import java.util.List;
122 import java.util.Map;
123 import java.util.Set;
124 
125 /**
126  * Class to validate compatibility between {@link
127  * android.health.connect.datatypes.ExerciseSessionRecord} type and child {@link
128  * android.health.connect.datatypes.ExerciseSegment} types.
129  *
130  * @hide
131  */
132 public final class ExerciseSessionTypesValidation {
133     private static final String TAG = "ExerciseSessionsValidations";
134 
135     private static final Set<Integer> UNIVERSAL_SEGMENTS =
136             Set.of(
137                     EXERCISE_SEGMENT_TYPE_OTHER_WORKOUT,
138                     EXERCISE_SEGMENT_TYPE_PAUSE,
139                     EXERCISE_SEGMENT_TYPE_REST,
140                     EXERCISE_SEGMENT_TYPE_STRETCHING,
141                     EXERCISE_SEGMENT_TYPE_UNKNOWN);
142 
143     private static final Set<Integer> UNIVERSAL_SESSIONS =
144             Set.of(
145                     EXERCISE_SESSION_TYPE_BOOT_CAMP,
146                     EXERCISE_SESSION_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING,
147                     EXERCISE_SESSION_TYPE_OTHER_WORKOUT,
148                     EXERCISE_SESSION_TYPE_UNKNOWN);
149 
150     private static final Set<Integer> EXERCISES =
151             Set.of(
152                     EXERCISE_SEGMENT_TYPE_ARM_CURL,
153                     EXERCISE_SEGMENT_TYPE_BACK_EXTENSION,
154                     EXERCISE_SEGMENT_TYPE_BALL_SLAM,
155                     EXERCISE_SEGMENT_TYPE_BARBELL_SHOULDER_PRESS,
156                     EXERCISE_SEGMENT_TYPE_BENCH_PRESS,
157                     EXERCISE_SEGMENT_TYPE_BENCH_SIT_UP,
158                     EXERCISE_SEGMENT_TYPE_BURPEE,
159                     EXERCISE_SEGMENT_TYPE_CRUNCH,
160                     EXERCISE_SEGMENT_TYPE_DEADLIFT,
161                     EXERCISE_SEGMENT_TYPE_DOUBLE_ARM_TRICEPS_EXTENSION,
162                     EXERCISE_SEGMENT_TYPE_DUMBBELL_CURL_LEFT_ARM,
163                     EXERCISE_SEGMENT_TYPE_DUMBBELL_CURL_RIGHT_ARM,
164                     EXERCISE_SEGMENT_TYPE_DUMBBELL_FRONT_RAISE,
165                     EXERCISE_SEGMENT_TYPE_DUMBBELL_LATERAL_RAISE,
166                     EXERCISE_SEGMENT_TYPE_DUMBBELL_ROW,
167                     EXERCISE_SEGMENT_TYPE_DUMBBELL_TRICEPS_EXTENSION_LEFT_ARM,
168                     EXERCISE_SEGMENT_TYPE_DUMBBELL_TRICEPS_EXTENSION_RIGHT_ARM,
169                     EXERCISE_SEGMENT_TYPE_DUMBBELL_TRICEPS_EXTENSION_TWO_ARM,
170                     EXERCISE_SEGMENT_TYPE_FORWARD_TWIST,
171                     EXERCISE_SEGMENT_TYPE_FRONT_RAISE,
172                     EXERCISE_SEGMENT_TYPE_HIP_THRUST,
173                     EXERCISE_SEGMENT_TYPE_HULA_HOOP,
174                     EXERCISE_SEGMENT_TYPE_JUMPING_JACK,
175                     EXERCISE_SEGMENT_TYPE_JUMP_ROPE,
176                     EXERCISE_SEGMENT_TYPE_KETTLEBELL_SWING,
177                     EXERCISE_SEGMENT_TYPE_LATERAL_RAISE,
178                     EXERCISE_SEGMENT_TYPE_LAT_PULL_DOWN,
179                     EXERCISE_SEGMENT_TYPE_LEG_CURL,
180                     EXERCISE_SEGMENT_TYPE_LEG_EXTENSION,
181                     EXERCISE_SEGMENT_TYPE_LEG_PRESS,
182                     EXERCISE_SEGMENT_TYPE_LEG_RAISE,
183                     EXERCISE_SEGMENT_TYPE_LUNGE,
184                     EXERCISE_SEGMENT_TYPE_MOUNTAIN_CLIMBER,
185                     EXERCISE_SEGMENT_TYPE_PLANK,
186                     EXERCISE_SEGMENT_TYPE_PULL_UP,
187                     EXERCISE_SEGMENT_TYPE_PUNCH,
188                     EXERCISE_SEGMENT_TYPE_SHOULDER_PRESS,
189                     EXERCISE_SEGMENT_TYPE_SINGLE_ARM_TRICEPS_EXTENSION,
190                     EXERCISE_SEGMENT_TYPE_SIT_UP,
191                     EXERCISE_SEGMENT_TYPE_SQUAT,
192                     EXERCISE_SEGMENT_TYPE_UPPER_TWIST,
193                     EXERCISE_SEGMENT_TYPE_WEIGHTLIFTING);
194 
195     private static final Set<Integer> SWIMMING =
196             Set.of(
197                     EXERCISE_SEGMENT_TYPE_SWIMMING_BACKSTROKE,
198                     EXERCISE_SEGMENT_TYPE_SWIMMING_BREASTSTROKE,
199                     EXERCISE_SEGMENT_TYPE_SWIMMING_FREESTYLE,
200                     EXERCISE_SEGMENT_TYPE_SWIMMING_BUTTERFLY,
201                     EXERCISE_SEGMENT_TYPE_SWIMMING_MIXED,
202                     EXERCISE_SEGMENT_TYPE_SWIMMING_OTHER);
203 
204     private static final Map<Integer, Set<Integer>> SESSION_TO_SEGMENT_MAPPING = new ArrayMap<>();
205 
206     static {
SESSION_TO_SEGMENT_MAPPING.put( EXERCISE_SESSION_TYPE_BIKING, Set.of(EXERCISE_SEGMENT_TYPE_BIKING))207         SESSION_TO_SEGMENT_MAPPING.put(
208                 EXERCISE_SESSION_TYPE_BIKING, Set.of(EXERCISE_SEGMENT_TYPE_BIKING));
209 
SESSION_TO_SEGMENT_MAPPING.put( EXERCISE_SESSION_TYPE_BIKING_STATIONARY, Set.of(EXERCISE_SEGMENT_TYPE_BIKING_STATIONARY))210         SESSION_TO_SEGMENT_MAPPING.put(
211                 EXERCISE_SESSION_TYPE_BIKING_STATIONARY,
212                 Set.of(EXERCISE_SEGMENT_TYPE_BIKING_STATIONARY));
213 
SESSION_TO_SEGMENT_MAPPING.put(EXERCISE_SESSION_TYPE_CALISTHENICS, EXERCISES)214         SESSION_TO_SEGMENT_MAPPING.put(EXERCISE_SESSION_TYPE_CALISTHENICS, EXERCISES);
215 
SESSION_TO_SEGMENT_MAPPING.put( EXERCISE_SESSION_TYPE_ELLIPTICAL, Set.of(EXERCISE_SEGMENT_TYPE_ELLIPTICAL))216         SESSION_TO_SEGMENT_MAPPING.put(
217                 EXERCISE_SESSION_TYPE_ELLIPTICAL, Set.of(EXERCISE_SEGMENT_TYPE_ELLIPTICAL));
218 
SESSION_TO_SEGMENT_MAPPING.put( EXERCISE_SESSION_TYPE_EXERCISE_CLASS, Set.of( EXERCISE_SEGMENT_TYPE_YOGA, EXERCISE_SEGMENT_TYPE_BIKING_STATIONARY, EXERCISE_SEGMENT_TYPE_PILATES, EXERCISE_SEGMENT_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING))219         SESSION_TO_SEGMENT_MAPPING.put(
220                 EXERCISE_SESSION_TYPE_EXERCISE_CLASS,
221                 Set.of(
222                         EXERCISE_SEGMENT_TYPE_YOGA,
223                         EXERCISE_SEGMENT_TYPE_BIKING_STATIONARY,
224                         EXERCISE_SEGMENT_TYPE_PILATES,
225                         EXERCISE_SEGMENT_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING));
SESSION_TO_SEGMENT_MAPPING.put(EXERCISE_SESSION_TYPE_GYMNASTICS, EXERCISES)226         SESSION_TO_SEGMENT_MAPPING.put(EXERCISE_SESSION_TYPE_GYMNASTICS, EXERCISES);
227 
SESSION_TO_SEGMENT_MAPPING.put( EXERCISE_SESSION_TYPE_HIKING, Set.of(EXERCISE_SEGMENT_TYPE_WALKING, EXERCISE_SEGMENT_TYPE_WHEELCHAIR))228         SESSION_TO_SEGMENT_MAPPING.put(
229                 EXERCISE_SESSION_TYPE_HIKING,
230                 Set.of(EXERCISE_SEGMENT_TYPE_WALKING, EXERCISE_SEGMENT_TYPE_WHEELCHAIR));
231 
SESSION_TO_SEGMENT_MAPPING.put( EXERCISE_SESSION_TYPE_PILATES, Set.of(EXERCISE_SEGMENT_TYPE_PILATES))232         SESSION_TO_SEGMENT_MAPPING.put(
233                 EXERCISE_SESSION_TYPE_PILATES, Set.of(EXERCISE_SEGMENT_TYPE_PILATES));
234 
SESSION_TO_SEGMENT_MAPPING.put( EXERCISE_SESSION_TYPE_ROWING_MACHINE, Set.of(EXERCISE_SEGMENT_TYPE_ROWING_MACHINE))235         SESSION_TO_SEGMENT_MAPPING.put(
236                 EXERCISE_SESSION_TYPE_ROWING_MACHINE, Set.of(EXERCISE_SEGMENT_TYPE_ROWING_MACHINE));
237 
SESSION_TO_SEGMENT_MAPPING.put( EXERCISE_SESSION_TYPE_RUNNING, Set.of(EXERCISE_SEGMENT_TYPE_RUNNING, EXERCISE_SEGMENT_TYPE_WALKING))238         SESSION_TO_SEGMENT_MAPPING.put(
239                 EXERCISE_SESSION_TYPE_RUNNING,
240                 Set.of(EXERCISE_SEGMENT_TYPE_RUNNING, EXERCISE_SEGMENT_TYPE_WALKING));
241 
SESSION_TO_SEGMENT_MAPPING.put( EXERCISE_SESSION_TYPE_RUNNING_TREADMILL, Set.of(EXERCISE_SEGMENT_TYPE_RUNNING_TREADMILL))242         SESSION_TO_SEGMENT_MAPPING.put(
243                 EXERCISE_SESSION_TYPE_RUNNING_TREADMILL,
244                 Set.of(EXERCISE_SEGMENT_TYPE_RUNNING_TREADMILL));
245 
SESSION_TO_SEGMENT_MAPPING.put( EXERCISE_SESSION_TYPE_STAIR_CLIMBING, Set.of(EXERCISE_SEGMENT_TYPE_STAIR_CLIMBING))246         SESSION_TO_SEGMENT_MAPPING.put(
247                 EXERCISE_SESSION_TYPE_STAIR_CLIMBING, Set.of(EXERCISE_SEGMENT_TYPE_STAIR_CLIMBING));
248 
SESSION_TO_SEGMENT_MAPPING.put( EXERCISE_SESSION_TYPE_STAIR_CLIMBING_MACHINE, Set.of(EXERCISE_SEGMENT_TYPE_STAIR_CLIMBING_MACHINE))249         SESSION_TO_SEGMENT_MAPPING.put(
250                 EXERCISE_SESSION_TYPE_STAIR_CLIMBING_MACHINE,
251                 Set.of(EXERCISE_SEGMENT_TYPE_STAIR_CLIMBING_MACHINE));
252 
SESSION_TO_SEGMENT_MAPPING.put(EXERCISE_SESSION_TYPE_STRENGTH_TRAINING, EXERCISES)253         SESSION_TO_SEGMENT_MAPPING.put(EXERCISE_SESSION_TYPE_STRENGTH_TRAINING, EXERCISES);
254 
255         Set<Integer> openSwimming = new ArraySet<>(SWIMMING);
256         openSwimming.add(EXERCISE_SEGMENT_TYPE_SWIMMING_OPEN_WATER);
SESSION_TO_SEGMENT_MAPPING.put(EXERCISE_SESSION_TYPE_SWIMMING_OPEN_WATER, openSwimming)257         SESSION_TO_SEGMENT_MAPPING.put(EXERCISE_SESSION_TYPE_SWIMMING_OPEN_WATER, openSwimming);
258 
259         Set<Integer> poolSwimming = new ArraySet<>(SWIMMING);
260         poolSwimming.add(EXERCISE_SEGMENT_TYPE_SWIMMING_POOL);
SESSION_TO_SEGMENT_MAPPING.put(EXERCISE_SESSION_TYPE_SWIMMING_POOL, poolSwimming)261         SESSION_TO_SEGMENT_MAPPING.put(EXERCISE_SESSION_TYPE_SWIMMING_POOL, poolSwimming);
262 
SESSION_TO_SEGMENT_MAPPING.put( EXERCISE_SESSION_TYPE_WALKING, Set.of(EXERCISE_SEGMENT_TYPE_WALKING))263         SESSION_TO_SEGMENT_MAPPING.put(
264                 EXERCISE_SESSION_TYPE_WALKING, Set.of(EXERCISE_SEGMENT_TYPE_WALKING));
265 
SESSION_TO_SEGMENT_MAPPING.put(EXERCISE_SESSION_TYPE_WEIGHTLIFTING, EXERCISES)266         SESSION_TO_SEGMENT_MAPPING.put(EXERCISE_SESSION_TYPE_WEIGHTLIFTING, EXERCISES);
267 
SESSION_TO_SEGMENT_MAPPING.put( EXERCISE_SESSION_TYPE_WHEELCHAIR, Set.of(EXERCISE_SEGMENT_TYPE_WHEELCHAIR))268         SESSION_TO_SEGMENT_MAPPING.put(
269                 EXERCISE_SESSION_TYPE_WHEELCHAIR, Set.of(EXERCISE_SEGMENT_TYPE_WHEELCHAIR));
270 
SESSION_TO_SEGMENT_MAPPING.put( EXERCISE_SESSION_TYPE_YOGA, Set.of(EXERCISE_SEGMENT_TYPE_YOGA))271         SESSION_TO_SEGMENT_MAPPING.put(
272                 EXERCISE_SESSION_TYPE_YOGA, Set.of(EXERCISE_SEGMENT_TYPE_YOGA));
273     }
274 
275     /**
276      * Validates that session type is compatible with segments types. Skips checks if the session or
277      * segment type is not known with the current module version.
278      *
279      * @hide
280      */
validateSessionAndSegmentsTypes( int sessionType, List<ExerciseSegment> segments)281     public static void validateSessionAndSegmentsTypes(
282             int sessionType, List<ExerciseSegment> segments) {
283         if (!isKnownSessionType(sessionType)) {
284             Slog.w(TAG, "Unknown exercise session type: " + sessionType);
285             return;
286         }
287 
288         int segmentType;
289         for (ExerciseSegment segment : segments) {
290             segmentType = segment.getSegmentType();
291 
292             if (!isKnownSegmentType(segmentType)) {
293                 Slog.w(TAG, "Unknown exercise segment type: " + segmentType);
294                 continue;
295             }
296 
297             // Both segment and session types are known, check their compatibility
298             if (!UNIVERSAL_SESSIONS.contains(sessionType)) {
299                 if (UNIVERSAL_SEGMENTS.contains(segmentType)) {
300                     continue;
301                 }
302 
303                 if (!(SESSION_TO_SEGMENT_MAPPING.containsKey(sessionType)
304                         && SESSION_TO_SEGMENT_MAPPING.get(sessionType).contains(segmentType))) {
305                     throw new IllegalArgumentException(
306                             "Invalid exercise segment type for given exercise session type");
307                 }
308             }
309         }
310     }
311 
312     /**
313      * Validates that all {@link ExerciseRoute} locations timestamps are within session start and
314      * end time interval.
315      *
316      * @hide
317      */
validateExerciseRouteTimestamps( Instant sessionStartTime, Instant sessionEndTime, ExerciseRoute route)318     public static void validateExerciseRouteTimestamps(
319             Instant sessionStartTime, Instant sessionEndTime, ExerciseRoute route) {
320         if (route == null) {
321             return;
322         }
323 
324         for (ExerciseRoute.Location location : route.getRouteLocations()) {
325             if (location.getTime().isAfter(sessionEndTime)
326                     || location.getTime().isBefore(sessionStartTime)) {
327                 throw new IllegalArgumentException(
328                         "Exercise route timestamp must be within session interval, got start time: "
329                                 + sessionStartTime
330                                 + ", session end time: "
331                                 + sessionEndTime
332                                 + ", route location time: "
333                                 + location.getTime());
334             }
335         }
336     }
337 }
338