• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.deviceconfig.db;
18 
19 import android.content.ContentValues;
20 import android.database.Cursor;
21 import android.database.sqlite.SQLiteDatabase;
22 import android.text.TextUtils;
23 
24 import com.android.server.deviceconfig.db.DeviceConfigDbHelper.Contract.DeviceConfigEntry;
25 
26 import java.util.HashMap;
27 import java.util.Map;
28 
29 /**
30  * @hide
31  */
32 public class DeviceConfigDbAdapter {
33 
34     private final SQLiteDatabase mDb;
35 
DeviceConfigDbAdapter(SQLiteDatabase db)36     public DeviceConfigDbAdapter(SQLiteDatabase db) {
37         mDb = db;
38     }
39 
getValuesForNamespace(String namespace, String... keys)40     public Map<String, String> getValuesForNamespace(String namespace, String... keys) {
41 
42         String[] projection = {
43                 DeviceConfigEntry.COLUMN_NAME_KEY,
44                 DeviceConfigEntry.COLUMN_NAME_VALUE
45         };
46 
47         String selection;
48         String[] selectionArgs;
49         if (keys != null && keys.length > 0) {
50             selection = DeviceConfigEntry.COLUMN_NAME_NAMESPACE + " = ? "
51                     + "and " + DeviceConfigEntry.COLUMN_NAME_KEY + " in ( ? ) ";
52             String keySelection = TextUtils.join(",", keys);
53             selectionArgs = new String[]{namespace, keySelection};
54         } else {
55             selection = DeviceConfigEntry.COLUMN_NAME_NAMESPACE + " = ?";
56             selectionArgs = new String[]{namespace};
57         }
58         Cursor cursor = mDb.query(
59                 DeviceConfigEntry.TABLE_NAME,
60                 projection,
61                 selection,
62                 selectionArgs,
63                 null,
64                 null,
65                 null
66         );
67 
68         Map<String, String> map = new HashMap<>(cursor.getCount());
69         while (cursor.moveToNext()) {
70             String key = cursor.getString(
71                     cursor.getColumnIndexOrThrow(DeviceConfigEntry.COLUMN_NAME_KEY));
72             String value = cursor.getString(
73                     cursor.getColumnIndexOrThrow(DeviceConfigEntry.COLUMN_NAME_VALUE));
74             map.put(key, value);
75         }
76         cursor.close();
77         return map;
78     }
79 
80     /**
81      *
82      * @return true if the data was inserted or updated in the database
83      */
insertOrUpdateValue_inTransaction(String namespace, String key, String value)84     private boolean insertOrUpdateValue_inTransaction(String namespace, String key, String value) {
85         // TODO(b/265948914): see if this is the most performant way to either insert or update a record
86         ContentValues values = new ContentValues();
87         values.put(DeviceConfigEntry.COLUMN_NAME_NAMESPACE, namespace);
88         values.put(DeviceConfigEntry.COLUMN_NAME_KEY, key);
89         values.put(DeviceConfigEntry.COLUMN_NAME_VALUE, value);
90 
91         String where = DeviceConfigEntry.COLUMN_NAME_NAMESPACE + " = ? "
92                 + "and " + DeviceConfigEntry.COLUMN_NAME_VALUE + " = ? ";
93 
94         String[] whereArgs = {namespace, key};
95         int updatedRows = mDb.update(DeviceConfigEntry.TABLE_NAME, values, where, whereArgs);
96         if (updatedRows == 0) {
97             // this is a new row, we need to insert it
98             long id = mDb.insert(DeviceConfigEntry.TABLE_NAME, null, values);
99             return id != -1;
100         }
101         return updatedRows > 0;
102     }
103 
104     /**
105      * Set or update the values in the map into the namespace.
106      *
107      * @return true if all values were set. Returns true if the map is empty.
108      */
setValues(String namespace, Map<String, String> map)109     public boolean setValues(String namespace, Map<String, String> map) {
110         if (map.size() == 0) {
111             return true;
112         }
113         boolean allSucceeded = true;
114         try {
115             mDb.beginTransaction();
116             for (Map.Entry<String, String> entry : map.entrySet()) {
117                 // TODO(b/265948914) probably should call yieldIfContendedSafely in this loop
118                 allSucceeded &= insertOrUpdateValue_inTransaction(namespace, entry.getKey(),
119                         entry.getValue());
120             }
121             mDb.setTransactionSuccessful();
122         } finally {
123             mDb.endTransaction();
124         }
125         return allSucceeded;
126     }
127 
128     /**
129      *
130      * @return true if the value was set
131      */
setValue(String namespace, String key, String value, boolean makeDefault)132     public boolean setValue(String namespace, String key, String value, boolean makeDefault) {
133         HashMap<String, String> map = new HashMap<>();
134         map.put(key, value);
135         return setValues(namespace, map);
136         // TODO(b/265948914) implement make default!
137     }
138 
139     /**
140      *
141      * @return true if any value was deleted
142      */
deleteValue(String namespace, String key)143     public boolean deleteValue(String namespace, String key) {
144         String where = DeviceConfigEntry.COLUMN_NAME_NAMESPACE + " = ? "
145                 + "and " + DeviceConfigEntry.COLUMN_NAME_KEY + " = ? ";
146         String[] whereArgs = { namespace, key };
147         int count = mDb.delete(DeviceConfigEntry.TABLE_NAME, where, whereArgs);
148         return count > 0;
149     }
150 }
151