• 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");
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.datatypehelpers;
18 
19 import static com.android.server.healthconnect.storage.request.UpsertTableRequest.TYPE_STRING;
20 import static com.android.server.healthconnect.storage.utils.StorageUtils.TEXT_NOT_NULL_UNIQUE;
21 import static com.android.server.healthconnect.storage.utils.StorageUtils.TEXT_NULL;
22 
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.content.ContentValues;
26 import android.database.Cursor;
27 import android.database.sqlite.SQLiteDatabase;
28 import android.util.Pair;
29 
30 import com.android.server.healthconnect.storage.TransactionManager;
31 import com.android.server.healthconnect.storage.request.CreateTableRequest;
32 import com.android.server.healthconnect.storage.request.DeleteTableRequest;
33 import com.android.server.healthconnect.storage.request.ReadTableRequest;
34 import com.android.server.healthconnect.storage.request.UpsertTableRequest;
35 import com.android.server.healthconnect.storage.utils.StorageUtils;
36 
37 import java.util.ArrayList;
38 import java.util.Collections;
39 import java.util.HashMap;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.concurrent.ConcurrentHashMap;
43 
44 /**
45  * A helper class to store user preferences, set in UI APK for the platform.
46  *
47  * @hide
48  */
49 public final class PreferenceHelper {
50     private static final String TABLE_NAME = "preference_table";
51     private static final String KEY_COLUMN_NAME = "key";
52     public static final List<Pair<String, Integer>> UNIQUE_COLUMN_INFO =
53             Collections.singletonList(new Pair<>(KEY_COLUMN_NAME, TYPE_STRING));
54     private static final String VALUE_COLUMN_NAME = "value";
55     private static volatile PreferenceHelper sPreferenceHelper;
56     private volatile ConcurrentHashMap<String, String> mPreferences;
57 
PreferenceHelper()58     private PreferenceHelper() {}
59 
60     /** Note: Overrides existing preference (if it exists) with the new value */
insertOrReplacePreference(String key, String value)61     public synchronized void insertOrReplacePreference(String key, String value) {
62         TransactionManager.getInitialisedInstance()
63                 .insertOrReplace(
64                         new UpsertTableRequest(
65                                 TABLE_NAME, getContentValues(key, value), UNIQUE_COLUMN_INFO));
66         getPreferences().put(key, value);
67     }
68 
69     /** Removes key entry from the table */
removeKey(String id)70     public synchronized void removeKey(String id) {
71         TransactionManager.getInitialisedInstance()
72                 .delete(new DeleteTableRequest(TABLE_NAME).setId(KEY_COLUMN_NAME, id));
73         getPreferences().remove(id);
74     }
75 
76     /** Inserts multiple preferences together in a transaction */
insertOrReplacePreferencesTransaction( HashMap<String, String> keyValues)77     public synchronized void insertOrReplacePreferencesTransaction(
78             HashMap<String, String> keyValues) {
79         List<UpsertTableRequest> requests = new ArrayList<>();
80         keyValues.forEach(
81                 (key, value) ->
82                         requests.add(
83                                 new UpsertTableRequest(
84                                         TABLE_NAME,
85                                         getContentValues(key, value),
86                                         UNIQUE_COLUMN_INFO)));
87         TransactionManager.getInitialisedInstance().insertOrReplaceAll(requests);
88         getPreferences().putAll(keyValues);
89     }
90 
91     @NonNull
getCreateTableRequest()92     public CreateTableRequest getCreateTableRequest() {
93         return new CreateTableRequest(TABLE_NAME, getColumnInfo());
94     }
95 
96     @Nullable
getPreference(String key)97     public String getPreference(String key) {
98         return getPreferences().get(key);
99     }
100 
clearCache()101     public synchronized void clearCache() {
102         mPreferences = null;
103     }
104 
105     /** Fetch preferences into memory. */
initializePreferences()106     public void initializePreferences() {
107         populatePreferences();
108     }
109 
getPreferences()110     private Map<String, String> getPreferences() {
111         if (mPreferences == null) {
112             populatePreferences();
113         }
114         return mPreferences;
115     }
116 
117     @NonNull
getContentValues(String key, String value)118     private ContentValues getContentValues(String key, String value) {
119         ContentValues contentValues = new ContentValues();
120         contentValues.put(KEY_COLUMN_NAME, key);
121         contentValues.put(VALUE_COLUMN_NAME, value);
122         return contentValues;
123     }
124 
populatePreferences()125     private synchronized void populatePreferences() {
126         if (mPreferences != null) {
127             return;
128         }
129 
130         mPreferences = new ConcurrentHashMap<>();
131         final TransactionManager transactionManager = TransactionManager.getInitialisedInstance();
132         try (Cursor cursor = transactionManager.read(new ReadTableRequest(TABLE_NAME))) {
133             while (cursor.moveToNext()) {
134                 String key = StorageUtils.getCursorString(cursor, KEY_COLUMN_NAME);
135                 String value = StorageUtils.getCursorString(cursor, VALUE_COLUMN_NAME);
136                 mPreferences.put(key, value);
137             }
138         }
139     }
140 
141     @NonNull
getColumnInfo()142     private List<Pair<String, String>> getColumnInfo() {
143         ArrayList<Pair<String, String>> columnInfo = new ArrayList<>();
144         columnInfo.add(new Pair<>(KEY_COLUMN_NAME, TEXT_NOT_NULL_UNIQUE));
145         columnInfo.add(new Pair<>(VALUE_COLUMN_NAME, TEXT_NULL));
146 
147         return columnInfo;
148     }
149 
onUpgrade(int oldVersion, int newVersion, SQLiteDatabase db)150     public void onUpgrade(int oldVersion, int newVersion, SQLiteDatabase db) {}
151 
getInstance()152     public static synchronized PreferenceHelper getInstance() {
153         if (sPreferenceHelper == null) {
154             sPreferenceHelper = new PreferenceHelper();
155         }
156 
157         return sPreferenceHelper;
158     }
159 }
160