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.HealthPermissionStrings 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 data class DeletionParameters( 28 var chosenRange: ChosenRange = ChosenRange.DELETE_RANGE_LAST_24_HOURS, 29 val startTimeMs: Long = -1L, 30 val endTimeMs: Long = -1L, 31 var deletionType: DeletionType = DeletionType.DeletionTypeAllData(), 32 val deletionState: DeletionState = DeletionState.STATE_NO_DELETION_IN_PROGRESS, 33 val showTimeRangePickerDialog: Boolean = true 34 ) : Parcelable { 35 36 constructor( 37 parcel: Parcel 38 ) : this( 39 ChosenRange.valueOf( 40 parcel.readString() ?: ChosenRange.DELETE_RANGE_LAST_24_HOURS.toString()), 41 parcel.readLong(), 42 parcel.readLong(), 43 parcel.readParcelable(DeletionType::class.java.classLoader, DeletionType::class.java) 44 ?: DeletionType.DeletionTypeAllData(), 45 DeletionState.valueOf( 46 parcel.readString() ?: DeletionState.STATE_NO_DELETION_IN_PROGRESS.toString()), 47 parcel.readByte() != 0.toByte()) 48 describeContentsnull49 override fun describeContents(): Int { 50 return 0 51 } 52 writeToParcelnull53 override fun writeToParcel(parcel: Parcel, flags: Int) { 54 parcel.writeString(this.chosenRange.toString()) 55 parcel.writeLong(startTimeMs) 56 parcel.writeLong(endTimeMs) 57 parcel.writeString(this.deletionType.toString()) 58 parcel.writeString(this.deletionState.toString()) 59 parcel.writeByte(if (showTimeRangePickerDialog) 1 else 0) 60 } 61 62 companion object CREATOR : Parcelable.Creator<DeletionParameters> { createFromParcelnull63 override fun createFromParcel(parcel: Parcel): DeletionParameters { 64 return DeletionParameters(parcel) 65 } 66 newArraynull67 override fun newArray(size: Int): Array<DeletionParameters?> { 68 return arrayOfNulls(size) 69 } 70 } 71 72 @StringRes getPermissionTypeLabelnull73 fun getPermissionTypeLabel(): Int { 74 check(deletionType.hasPermissionType) { 75 "Permission type label not supported for this Deletion parameter" 76 } 77 78 val healthPermissionType = 79 if (deletionType is DeletionType.DeletionTypeHealthPermissionTypeData) 80 (deletionType as DeletionType.DeletionTypeHealthPermissionTypeData) 81 .healthPermissionType 82 else 83 (deletionType as DeletionType.DeletionTypeHealthPermissionTypeFromApp) 84 .healthPermissionType 85 86 return HealthPermissionStrings.fromPermissionType(healthPermissionType).lowercaseLabel 87 } 88 89 @StringRes getCategoryLabelnull90 fun getCategoryLabel(): Int { 91 check(deletionType.hasCategory) { 92 "Category label not supported for this Deletion parameter" 93 } 94 95 val category = (deletionType as DeletionType.DeletionTypeCategoryData).category 96 97 return category.lowercaseTitle() 98 } 99 getAppNamenull100 fun getAppName(): String { 101 check(deletionType.hasAppData) { "App name not supported for this Deletion parameter" } 102 103 val appName = 104 if (deletionType is DeletionType.DeletionTypeAppData) 105 (deletionType as DeletionType.DeletionTypeAppData).appName 106 else (deletionType as DeletionType.DeletionTypeHealthPermissionTypeFromApp).appName 107 108 return appName 109 } 110 getStartTimeInstantnull111 fun getStartTimeInstant(): Instant { 112 val endTime = getEndTimeInstant() 113 114 return when (chosenRange) { 115 ChosenRange.DELETE_RANGE_LAST_24_HOURS -> endTime.minus(ofDays(1)) 116 ChosenRange.DELETE_RANGE_LAST_7_DAYS -> endTime.minus(ofDays(7)) 117 ChosenRange.DELETE_RANGE_LAST_30_DAYS -> endTime.minus(ofDays(30)) 118 ChosenRange.DELETE_RANGE_ALL_DATA -> Instant.EPOCH 119 } 120 } 121 getEndTimeInstantnull122 fun getEndTimeInstant(): Instant { 123 if (chosenRange == ChosenRange.DELETE_RANGE_ALL_DATA) { 124 // Deleting all data should include all time as it's possible for apps 125 // to write data in the future 126 return Instant.ofEpochMilli(Long.MAX_VALUE) 127 } 128 129 return Instant.ofEpochMilli(endTimeMs) 130 } 131 } 132 133 enum class ChosenRange { 134 DELETE_RANGE_LAST_24_HOURS, 135 DELETE_RANGE_LAST_7_DAYS, 136 DELETE_RANGE_LAST_30_DAYS, 137 DELETE_RANGE_ALL_DATA 138 } 139 140 enum class DeletionState { 141 STATE_NO_DELETION_IN_PROGRESS, 142 STATE_DELETION_STARTED, 143 STATE_PROGRESS_INDICATOR_STARTED, 144 STATE_PROGRESS_INDICATOR_CAN_END, 145 STATE_DELETION_SUCCESSFUL, 146 STATE_DELETION_FAILED 147 } 148