1 /*
2  * Copyright (C) 2024 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 static android.health.connect.Constants.DEFAULT_INT;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.health.connect.HealthConnectManager;
24 import android.health.connect.exportimport.ImportStatus;
25 import android.health.connect.exportimport.ScheduledExportSettings;
26 import android.health.connect.exportimport.ScheduledExportStatus;
27 import android.net.Uri;
28 
29 import com.android.server.healthconnect.storage.datatypehelpers.PreferenceHelper;
30 
31 import java.time.Instant;
32 
33 /**
34  * Stores the settings for the scheduled export service.
35  *
36  * @hide
37  */
38 public final class ExportImportSettingsStorage {
39     // Scheduled Export Settings
40     private static final String EXPORT_URI_PREFERENCE_KEY = "export_uri_key";
41     private static final String EXPORT_PERIOD_PREFERENCE_KEY = "export_period_key";
42 
43     // Scheduled Export State
44     private static final String LAST_SUCCESSFUL_EXPORT_PREFERENCE_KEY =
45             "last_successful_export_key";
46     private static final String LAST_EXPORT_ERROR_PREFERENCE_KEY = "last_export_error_key";
47 
48     // Import State
49     private static final String IMPORT_ONGOING_PREFERENCE_KEY = "import_ongoing_key";
50     private static final String LAST_IMPORT_ERROR_PREFERENCE_KEY = "last_import_error_key";
51 
52     /**
53      * Configures the settings for the scheduled export of Health Connect data.
54      *
55      * @param settings Settings to use for the scheduled export. Use null to clear the settings.
56      */
configure(@ullable ScheduledExportSettings settings)57     public static void configure(@Nullable ScheduledExportSettings settings) {
58         if (settings != null) {
59             configureNonNull(settings);
60         } else {
61             clear();
62         }
63     }
64 
65     /** Configures the settings for the scheduled export of Health Connect data. */
configureNonNull(@onNull ScheduledExportSettings settings)66     private static void configureNonNull(@NonNull ScheduledExportSettings settings) {
67         if (settings.getUri() != null) {
68             PreferenceHelper.getInstance()
69                     .insertOrReplacePreference(
70                             EXPORT_URI_PREFERENCE_KEY, settings.getUri().toString());
71         }
72 
73         if (settings.getPeriodInDays() != DEFAULT_INT) {
74             String periodInDays = String.valueOf(settings.getPeriodInDays());
75             PreferenceHelper.getInstance()
76                     .insertOrReplacePreference(EXPORT_PERIOD_PREFERENCE_KEY, periodInDays);
77         }
78     }
79 
80     /** Clears the settings for the scheduled export of Health Connect data. */
clear()81     private static void clear() {
82         PreferenceHelper.getInstance().removeKey(EXPORT_URI_PREFERENCE_KEY);
83         PreferenceHelper.getInstance().removeKey(EXPORT_PERIOD_PREFERENCE_KEY);
84     }
85 
86     /** Gets scheduled export URI for exporting Health Connect data. */
getUri()87     public static Uri getUri() {
88         String result = PreferenceHelper.getInstance().getPreference(EXPORT_URI_PREFERENCE_KEY);
89         if (result == null) throw new IllegalArgumentException("Export URI cannot be null.");
90         return Uri.parse(result);
91     }
92 
93     /** Gets scheduled export period for exporting Health Connect data. */
getScheduledExportPeriodInDays()94     public static int getScheduledExportPeriodInDays() {
95         String result = PreferenceHelper.getInstance().getPreference(EXPORT_PERIOD_PREFERENCE_KEY);
96 
97         if (result == null) return 0;
98         return Integer.parseInt(result);
99     }
100 
101     /** Set the last successful export time for the currently configured export. */
setLastSuccessfulExport(Instant instant)102     public static void setLastSuccessfulExport(Instant instant) {
103         PreferenceHelper.getInstance()
104                 .insertOrReplacePreference(
105                         LAST_SUCCESSFUL_EXPORT_PREFERENCE_KEY,
106                         String.valueOf(instant.toEpochMilli()));
107         PreferenceHelper.getInstance().removeKey(LAST_EXPORT_ERROR_PREFERENCE_KEY);
108     }
109 
110     /** Set errors during the last failed export attempt. */
setLastExportError(@ealthConnectManager.DataExportError int error)111     public static void setLastExportError(@HealthConnectManager.DataExportError int error) {
112         PreferenceHelper.getInstance()
113                 .insertOrReplacePreference(LAST_EXPORT_ERROR_PREFERENCE_KEY, String.valueOf(error));
114     }
115 
116     /** Get the status of the currently scheduled export. */
getScheduledExportStatus()117     public static ScheduledExportStatus getScheduledExportStatus() {
118         PreferenceHelper prefHelper = PreferenceHelper.getInstance();
119         String lastExportTime = prefHelper.getPreference(LAST_SUCCESSFUL_EXPORT_PREFERENCE_KEY);
120         String lastExportError = prefHelper.getPreference(LAST_EXPORT_ERROR_PREFERENCE_KEY);
121         String periodInDays = prefHelper.getPreference(EXPORT_PERIOD_PREFERENCE_KEY);
122 
123         return new ScheduledExportStatus(
124                 lastExportTime == null
125                         ? null
126                         : Instant.ofEpochMilli(Long.parseLong(lastExportTime)),
127                 lastExportError == null
128                         ? HealthConnectManager.DATA_EXPORT_ERROR_NONE
129                         : Integer.parseInt(lastExportError),
130                 periodInDays == null ? 0 : Integer.parseInt(periodInDays));
131     }
132 
133     /** Set to true when an import starts and to false when a data import completes */
setImportOngoing(boolean importOngoing)134     public static void setImportOngoing(boolean importOngoing) {
135         PreferenceHelper.getInstance()
136                 .insertOrReplacePreference(
137                         IMPORT_ONGOING_PREFERENCE_KEY, String.valueOf(importOngoing));
138     }
139 
140     /** Set errors during the last failed import attempt. */
setLastImportError(@mportStatus.DataImportError int error)141     public static void setLastImportError(@ImportStatus.DataImportError int error) {
142         PreferenceHelper.getInstance()
143                 .insertOrReplacePreference(LAST_IMPORT_ERROR_PREFERENCE_KEY, String.valueOf(error));
144     }
145 
146     /** Get the status of the last data import. */
getImportStatus()147     public static ImportStatus getImportStatus() {
148         PreferenceHelper prefHelper = PreferenceHelper.getInstance();
149         String lastImportError = prefHelper.getPreference(LAST_IMPORT_ERROR_PREFERENCE_KEY);
150         boolean importOngoing =
151                 Boolean.parseBoolean(prefHelper.getPreference(IMPORT_ONGOING_PREFERENCE_KEY));
152 
153         return new ImportStatus(
154                 lastImportError == null
155                         ? ImportStatus.DATA_IMPORT_ERROR_NONE
156                         : Integer.parseInt(lastImportError),
157                 importOngoing);
158     }
159 }
160