• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
<lambda>null2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * ```
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * ```
10  *
11  * Unless required by applicable law or agreed to in writing, software distributed under the License
12  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13  * or implied. See the License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 package com.android.healthconnect.testapps.toolbox.seed
17 
18 import android.content.Context
19 import android.health.connect.HealthConnectManager
20 import android.health.connect.datatypes.DataOrigin
21 import android.health.connect.datatypes.Device
22 import android.health.connect.datatypes.HeartRateRecord
23 import android.health.connect.datatypes.HeightRecord
24 import android.health.connect.datatypes.MenstruationFlowRecord
25 import android.health.connect.datatypes.MenstruationFlowRecord.MenstruationFlowType
26 import android.health.connect.datatypes.MenstruationPeriodRecord
27 import android.health.connect.datatypes.Metadata
28 import android.health.connect.datatypes.Record
29 import android.health.connect.datatypes.StepsRecord
30 import android.health.connect.datatypes.WeightRecord
31 import android.health.connect.datatypes.units.Length
32 import android.health.connect.datatypes.units.Mass
33 import android.os.Build.MANUFACTURER
34 import android.os.Build.MODEL
35 import com.android.healthconnect.testapps.toolbox.utils.GeneralUtils.Companion.insertRecords
36 import java.time.Duration.ofDays
37 import java.time.Duration.ofMinutes
38 import java.time.Instant
39 import java.time.temporal.ChronoUnit
40 import java.util.Random
41 import kotlinx.coroutines.runBlocking
42 
43 class SeedData(private val context: Context, private val manager: HealthConnectManager) {
44 
45     companion object {
46         const val NUMBER_OF_SERIES_RECORDS_TO_INSERT = 200L
47     }
48 
49     fun seedData() {
50         runBlocking {
51             try {
52                 seedMenstruationData()
53                 seedStepsData()
54                 seedHeartRateData(10)
55             } catch (ex: Exception) {
56                 throw ex
57             }
58         }
59     }
60 
61     private suspend fun seedStepsData() {
62         val start = Instant.now().truncatedTo(ChronoUnit.DAYS)
63         val records =
64             (1L..50).map { count ->
65                 getStepsRecord(count, start.plus(ofMinutes(count)))
66             }
67 
68         insertRecords(records, manager)
69     }
70 
71     private suspend fun seedMenstruationData() {
72         val today = Instant.now()
73         val periodRecord =
74             MenstruationPeriodRecord.Builder(getMetaData(), today.minus(ofDays(5L)), today).build()
75         val flowRecords =
76             (-5..0).map { days ->
77                 MenstruationFlowRecord.Builder(
78                         getMetaData(),
79                         today.plus(ofDays(days.toLong())),
80                         MenstruationFlowType.FLOW_MEDIUM)
81                     .build()
82             }
83         insertRecords(
84             buildList {
85                 add(periodRecord)
86                 addAll(flowRecords)
87             },
88             manager)
89     }
90 
91     suspend fun seedHeartRateData(numberOfRecordsPerBatch: Long) {
92         val start = Instant.now().truncatedTo(ChronoUnit.DAYS)
93         val random = Random()
94         val records =
95             (1L..numberOfRecordsPerBatch).map { timeOffset ->
96                 val hrSamples = ArrayList<Pair<Long, Instant>>()
97                 repeat(10) { i ->
98                     hrSamples.add(
99                         Pair(getValidHeartRate(random), start.plus(ofMinutes(timeOffset + i))))
100                 }
101                 getHeartRateRecord(
102                     hrSamples,
103                     start.plus(ofMinutes(timeOffset)),
104                     start.plus(ofMinutes(timeOffset + 100)))
105             }
106         insertRecords(records, manager)
107     }
108 
109     private fun getHeartRateRecord(
110         heartRateValues: List<Pair<Long, Instant>>,
111         start: Instant,
112         end: Instant,
113     ): HeartRateRecord {
114         return HeartRateRecord.Builder(
115                 getMetaData(),
116                 start,
117                 end,
118                 heartRateValues.map { HeartRateRecord.HeartRateSample(it.first, it.second) })
119             .build()
120     }
121 
122     private fun getValidHeartRate(random: Random): Long {
123         return (random.nextInt(20) + 80).toLong()
124     }
125 
126     private fun getStepsRecord(count: Long, time: Instant): StepsRecord {
127         return StepsRecord.Builder(getMetaData(), time, time.plusSeconds(30), count).build()
128     }
129 
130     private fun getMetaData(): Metadata {
131         val device: Device =
132             Device.Builder().setManufacturer(MANUFACTURER).setModel(MODEL).setType(1).build()
133         val dataOrigin = DataOrigin.Builder().setPackageName(context.packageName).build()
134         return Metadata.Builder().setDevice(device).setDataOrigin(dataOrigin).build()
135     }
136 }
137