1 /* 2 * Copyright (C) 2022 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 com.android.server.healthconnect.storage; 18 19 import android.annotation.NonNull; 20 import android.content.Context; 21 import android.util.Slog; 22 23 import com.android.server.healthconnect.storage.datatypehelpers.AccessLogsHelper; 24 import com.android.server.healthconnect.storage.datatypehelpers.ActivityDateHelper; 25 import com.android.server.healthconnect.storage.datatypehelpers.AppInfoHelper; 26 import com.android.server.healthconnect.storage.datatypehelpers.ChangeLogsHelper; 27 import com.android.server.healthconnect.storage.datatypehelpers.ChangeLogsRequestHelper; 28 import com.android.server.healthconnect.storage.datatypehelpers.HealthDataCategoryPriorityHelper; 29 import com.android.server.healthconnect.storage.datatypehelpers.PreferenceHelper; 30 import com.android.server.healthconnect.storage.request.DeleteTableRequest; 31 import com.android.server.healthconnect.storage.request.DeleteTransactionRequest; 32 import com.android.server.healthconnect.storage.utils.RecordHelperProvider; 33 34 import java.util.ArrayList; 35 import java.util.List; 36 37 /** 38 * A service that is run periodically to handle deletion of stale entries in HC DB. 39 * 40 * @hide 41 */ 42 public class AutoDeleteService { 43 private static final String AUTO_DELETE_DURATION_RECORDS_KEY = 44 "auto_delete_duration_records_key"; 45 private static final String TAG = "HealthConnectAutoDelete"; 46 47 /** Gets auto delete period for automatically deleting record entries */ getRecordRetentionPeriodInDays()48 public static int getRecordRetentionPeriodInDays() { 49 String result = 50 PreferenceHelper.getInstance().getPreference(AUTO_DELETE_DURATION_RECORDS_KEY); 51 52 if (result == null) return 0; 53 return Integer.parseInt(result); 54 } 55 56 /** Sets auto delete period for automatically deleting record entries */ setRecordRetentionPeriodInDays(int days)57 public static void setRecordRetentionPeriodInDays(int days) { 58 PreferenceHelper.getInstance() 59 .insertOrReplacePreference(AUTO_DELETE_DURATION_RECORDS_KEY, String.valueOf(days)); 60 } 61 62 /** Starts the Auto Deletion process. */ startAutoDelete(@onNull Context context)63 public static void startAutoDelete(@NonNull Context context) { 64 try { 65 // Only do transactional operations here - as this job might get cancelled for several 66 // reasons, such as: User switch, low battery etc. 67 deleteStaleRecordEntries(); 68 deleteStaleChangeLogEntries(); 69 deleteStaleAccessLogEntries(); 70 // Update the recordTypesUsed by packages if required after the deletion of records. 71 AppInfoHelper.getInstance().syncAppInfoRecordTypesUsed(); 72 // Re-sync activity dates table 73 ActivityDateHelper.reSyncForAllRecords(); 74 // Sync health data priority list table 75 HealthDataCategoryPriorityHelper.getInstance().reSyncHealthDataPriorityTable(context); 76 } catch (Exception e) { 77 Slog.e(TAG, "Auto delete run failed", e); 78 // Don't rethrow as that will crash system_server 79 } 80 } 81 deleteStaleRecordEntries()82 private static void deleteStaleRecordEntries() { 83 String recordAutoDeletePeriodString = 84 PreferenceHelper.getInstance().getPreference(AUTO_DELETE_DURATION_RECORDS_KEY); 85 int recordAutoDeletePeriod = 86 recordAutoDeletePeriodString == null 87 ? 0 88 : Integer.parseInt(recordAutoDeletePeriodString); 89 if (recordAutoDeletePeriod != 0) { 90 // 0 represents that no period is set,to delete only if not 0 else don't do anything 91 List<DeleteTableRequest> deleteTableRequests = new ArrayList<>(); 92 RecordHelperProvider.getRecordHelpers() 93 .values() 94 .forEach( 95 (recordHelper) -> { 96 DeleteTableRequest request = 97 recordHelper.getDeleteRequestForAutoDelete( 98 recordAutoDeletePeriod); 99 deleteTableRequests.add(request); 100 }); 101 try { 102 TransactionManager.getInitialisedInstance() 103 .deleteAll(new DeleteTransactionRequest(deleteTableRequests)); 104 } catch (Exception exception) { 105 Slog.e(TAG, "Auto delete for records failed", exception); 106 // Don't rethrow as that will crash system_server 107 } 108 } 109 } 110 deleteStaleChangeLogEntries()111 private static void deleteStaleChangeLogEntries() { 112 try { 113 TransactionManager.getInitialisedInstance() 114 .deleteWithoutChangeLogs( 115 List.of( 116 ChangeLogsHelper.getDeleteRequestForAutoDelete(), 117 ChangeLogsRequestHelper.getDeleteRequestForAutoDelete())); 118 } catch (Exception exception) { 119 Slog.e(TAG, "Auto delete for Change logs failed", exception); 120 // Don't rethrow as that will crash system_server 121 } 122 } 123 deleteStaleAccessLogEntries()124 private static void deleteStaleAccessLogEntries() { 125 try { 126 TransactionManager.getInitialisedInstance() 127 .deleteWithoutChangeLogs( 128 List.of(AccessLogsHelper.getDeleteRequestForAutoDelete())); 129 } catch (Exception exception) { 130 Slog.e(TAG, "Auto delete for Access logs failed", exception); 131 // Don't rethrow as that will crash system_server 132 } 133 } 134 } 135