• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.health.connect.TimeInstantRangeFilter
19 import android.util.Log
20 import androidx.lifecycle.LiveData
21 import androidx.lifecycle.MutableLiveData
22 import androidx.lifecycle.ViewModel
23 import androidx.lifecycle.viewModelScope
24 import com.android.healthconnect.controller.deletion.api.DeleteAllDataUseCase
25 import com.android.healthconnect.controller.deletion.api.DeleteAppDataUseCase
26 import com.android.healthconnect.controller.deletion.api.DeleteCategoryUseCase
27 import com.android.healthconnect.controller.deletion.api.DeleteEntryUseCase
28 import com.android.healthconnect.controller.deletion.api.DeletePermissionTypeUseCase
29 import dagger.hilt.android.lifecycle.HiltViewModel
30 import java.time.Instant
31 import javax.inject.Inject
32 import kotlinx.coroutines.launch
33 
34 @HiltViewModel
35 class DeletionViewModel
36 @Inject
37 constructor(
38     private val deleteAllDataUseCase: DeleteAllDataUseCase,
39     private val deleteCategoryUseCase: DeleteCategoryUseCase,
40     private val deletePermissionTypeUseCase: DeletePermissionTypeUseCase,
41     private val deleteEntryUseCase: DeleteEntryUseCase,
42     private val deleteAppDataUseCase: DeleteAppDataUseCase
43 ) : ViewModel() {
44 
45     companion object {
46         private const val TAG = "DeletionViewModel"
47     }
48 
49     private val _deletionParameters = MutableLiveData(DeletionParameters())
50     private var _removePermissions = false
51 
52     val deletionParameters: LiveData<DeletionParameters>
53         get() = _deletionParameters
54 
55     val showTimeRangeDialogFragment: Boolean
56         get() = currentDeletionParameters().showTimeRangePickerDialog
57 
currentDeletionParametersnull58     private fun currentDeletionParameters() = _deletionParameters.value!!
59 
60     fun setRemovePermissions(boolean: Boolean) {
61         _removePermissions = boolean
62     }
63 
setDeletionTypenull64     fun setDeletionType(deletionType: DeletionType) {
65         val showTimeRangePickerDialog =
66             when (deletionType) {
67                 is DeletionType.DeleteDataEntry -> false
68                 else -> true
69             }
70         _deletionParameters.value =
71             currentDeletionParameters()
72                 .copy(
73                     showTimeRangePickerDialog = showTimeRangePickerDialog,
74                     deletionType = deletionType)
75     }
76 
setChosenRangenull77     fun setChosenRange(chosenRange: ChosenRange) {
78         _deletionParameters.value = _deletionParameters.value?.copy(chosenRange = chosenRange)
79     }
80 
setEndTimenull81     fun setEndTime(endTime: Instant) {
82         _deletionParameters.value =
83             _deletionParameters.value?.copy(endTimeMs = endTime.toEpochMilli())
84     }
85 
setStartTimenull86     fun setStartTime(startTime: Instant) {
87         _deletionParameters.value =
88             _deletionParameters.value?.copy(startTimeMs = startTime.toEpochMilli())
89     }
90 
91     private var _categoriesReloadNeeded = MutableLiveData(false)
92     private val _appPermissionReloadNeeded = MutableLiveData(false)
93 
94     // Whether the categories screen needs to be reloaded after category data deletion.
95     val categoriesReloadNeeded: LiveData<Boolean>
96         get() = _categoriesReloadNeeded
97 
98     val appPermissionReloadNeeded: LiveData<Boolean>
99         get() = _appPermissionReloadNeeded
100 
setDeletionStatenull101     private fun setDeletionState(newState: DeletionState) {
102         _deletionParameters.value = currentDeletionParameters().copy(deletionState = newState)
103     }
104 
deletenull105     fun delete() {
106         viewModelScope.launch {
107             setDeletionState(DeletionState.STATE_DELETION_STARTED)
108 
109             try {
110 
111                 setDeletionState(DeletionState.STATE_PROGRESS_INDICATOR_STARTED)
112 
113                 val timeRangeFilter =
114                     TimeInstantRangeFilter.Builder()
115                         .setStartTime(currentDeletionParameters().getStartTimeInstant())
116                         .setEndTime(currentDeletionParameters().getEndTimeInstant())
117                         .build()
118 
119                 when (val deletionType = currentDeletionParameters().deletionType) {
120                     is DeletionType.DeleteDataEntry -> {
121                         _deletionParameters.value?.let { deleteEntryUseCase.invoke(deletionType) }
122                     }
123                     is DeletionType.DeletionTypeAllData -> {
124                         _deletionParameters.value?.let {
125                             deleteAllDataUseCase.invoke(timeRangeFilter)
126                             _categoriesReloadNeeded.postValue(true)
127                         }
128                     }
129                     is DeletionType.DeletionTypeCategoryData -> {
130                         deletionParameters.value?.let {
131                             deleteCategoryUseCase.invoke(deletionType, timeRangeFilter)
132                             _categoriesReloadNeeded.postValue(true)
133                         }
134                     }
135                     is DeletionType.DeletionTypeHealthPermissionTypeData -> {
136                         deletionParameters.value?.let {
137                             deletePermissionTypeUseCase.invoke(deletionType, timeRangeFilter)
138                         }
139                     }
140                     is DeletionType.DeletionTypeAppData -> {
141                         deletionParameters.value?.let {
142                             deleteAppDataUseCase.invoke(
143                                 deletionType, timeRangeFilter, _removePermissions)
144                             if (_removePermissions) {
145                                 _appPermissionReloadNeeded.value = true
146                             }
147                         }
148                     }
149                     else -> {}
150                 }
151                 setDeletionState(DeletionState.STATE_DELETION_SUCCESSFUL)
152             } catch (error: Exception) {
153                 Log.e(TAG, "Failed to delete data ${currentDeletionParameters()}", error)
154 
155                 setDeletionState(DeletionState.STATE_DELETION_FAILED)
156             } finally {
157                 setDeletionState(DeletionState.STATE_PROGRESS_INDICATOR_CAN_END)
158             }
159         }
160     }
161 }
162