1 /**
2  * 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.controller.deletion
17 
18 import android.os.Parcel
19 import android.os.Parcelable
20 import androidx.annotation.StringRes
21 import com.android.healthconnect.controller.permissions.data.FitnessPermissionStrings
22 import com.android.healthconnect.controller.shared.HealthDataCategoryExtensions.lowercaseTitle
23 import java.time.Duration.ofDays
24 import java.time.Instant
25 
26 /** Represents deletion parameters chosen by the user in the deletion dialogs. */
27 @Deprecated("This won't be used once the NEW_INFORMATION_ARCHITECTURE feature is enabled.")
28 data class DeletionParameters(
29     var chosenRange: ChosenRange = ChosenRange.DELETE_RANGE_LAST_24_HOURS,
30     val startTimeMs: Long = -1L,
31     val endTimeMs: Long = -1L,
32     var deletionType: DeletionType = DeletionType.DeletionTypeAllData(),
33     val deletionState: DeletionState = DeletionState.STATE_NO_DELETION_IN_PROGRESS,
34     val showTimeRangePickerDialog: Boolean = true
35 ) : Parcelable {
36 
37     constructor(
38         parcel: Parcel
39     ) : this(
40         ChosenRange.valueOf(
41             parcel.readString() ?: ChosenRange.DELETE_RANGE_LAST_24_HOURS.toString()),
42         parcel.readLong(),
43         parcel.readLong(),
44         parcel.readParcelable(DeletionType::class.java.classLoader, DeletionType::class.java)
45             ?: DeletionType.DeletionTypeAllData(),
46         DeletionState.valueOf(
47             parcel.readString() ?: DeletionState.STATE_NO_DELETION_IN_PROGRESS.toString()),
48         parcel.readByte() != 0.toByte())
49 
describeContentsnull50     override fun describeContents(): Int {
51         return 0
52     }
53 
writeToParcelnull54     override fun writeToParcel(parcel: Parcel, flags: Int) {
55         parcel.writeString(this.chosenRange.toString())
56         parcel.writeLong(startTimeMs)
57         parcel.writeLong(endTimeMs)
58         parcel.writeString(this.deletionType.toString())
59         parcel.writeString(this.deletionState.toString())
60         parcel.writeByte(if (showTimeRangePickerDialog) 1 else 0)
61     }
62 
63     companion object CREATOR : Parcelable.Creator<DeletionParameters> {
createFromParcelnull64         override fun createFromParcel(parcel: Parcel): DeletionParameters {
65             return DeletionParameters(parcel)
66         }
67 
newArraynull68         override fun newArray(size: Int): Array<DeletionParameters?> {
69             return arrayOfNulls(size)
70         }
71     }
72 
73     @StringRes
getPermissionTypeLabelnull74     fun getPermissionTypeLabel(): Int {
75         check(deletionType.hasPermissionType) {
76             "Permission type label not supported for this Deletion parameter"
77         }
78 
79         val healthPermissionType =
80             if (deletionType is DeletionType.DeletionTypeHealthPermissionTypeData)
81                 (deletionType as DeletionType.DeletionTypeHealthPermissionTypeData)
82                     .healthPermissionType
83             else
84                 (deletionType as DeletionType.DeletionTypeHealthPermissionTypeFromApp)
85                     .healthPermissionType
86 
87         return FitnessPermissionStrings.fromPermissionType(healthPermissionType).lowercaseLabel
88     }
89 
90     @StringRes
getCategoryLabelnull91     fun getCategoryLabel(): Int {
92         check(deletionType.hasCategory) {
93             "Category label not supported for this Deletion parameter"
94         }
95 
96         val category = (deletionType as DeletionType.DeletionTypeCategoryData).category
97 
98         return category.lowercaseTitle()
99     }
100 
getAppNamenull101     fun getAppName(): String {
102         check(deletionType.hasAppData) { "App name not supported for this Deletion parameter" }
103 
104         val appName =
105             if (deletionType is DeletionType.DeletionTypeAppData)
106                 (deletionType as DeletionType.DeletionTypeAppData).appName
107             else (deletionType as DeletionType.DeletionTypeHealthPermissionTypeFromApp).appName
108 
109         return appName
110     }
111 
getStartTimeInstantnull112     fun getStartTimeInstant(): Instant {
113         val endTime = getEndTimeInstant()
114 
115         return when (chosenRange) {
116             ChosenRange.DELETE_RANGE_LAST_24_HOURS -> endTime.minus(ofDays(1))
117             ChosenRange.DELETE_RANGE_LAST_7_DAYS -> endTime.minus(ofDays(7))
118             ChosenRange.DELETE_RANGE_LAST_30_DAYS -> endTime.minus(ofDays(30))
119             ChosenRange.DELETE_RANGE_ALL_DATA -> Instant.EPOCH
120         }
121     }
122 
getEndTimeInstantnull123     fun getEndTimeInstant(): Instant {
124         if (chosenRange == ChosenRange.DELETE_RANGE_ALL_DATA) {
125             // Deleting all data should include all time as it's possible for apps
126             // to write data in the future
127             return Instant.ofEpochMilli(Long.MAX_VALUE)
128         }
129 
130         return Instant.ofEpochMilli(endTimeMs)
131     }
132 }
133 
134 enum class ChosenRange {
135     DELETE_RANGE_LAST_24_HOURS,
136     DELETE_RANGE_LAST_7_DAYS,
137     DELETE_RANGE_LAST_30_DAYS,
138     DELETE_RANGE_ALL_DATA
139 }
140 
141 enum class DeletionState {
142     STATE_NO_DELETION_IN_PROGRESS,
143     STATE_DELETION_STARTED,
144     STATE_PROGRESS_INDICATOR_STARTED,
145     STATE_PROGRESS_INDICATOR_CAN_END,
146     STATE_DELETION_SUCCESSFUL,
147     STATE_DELETION_FAILED
148 }
149