1 /*
2  * Copyright (C) 2020 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 package com.android.cts.mockspellchecker
17 
18 import android.content.ContentProvider
19 import android.content.ContentResolver
20 import android.content.ContentValues
21 import android.content.Context
22 import android.database.Cursor
23 import android.database.MatrixCursor
24 import android.net.Uri
25 import android.util.Base64
26 
27 private const val PREFS_FILE_NAME = "prefs.xml"
28 private const val COLUMN_NAME = "value"
29 
30 /**
31  * ContentProvider to access MockSpellChecker's shared preferences.
32  *
33  * <p>Please use the companion object methods to interact with this ContentProvider. The companion
34  * object methods can be used from other processes.
35  *
36  * <p>This class supports ByteArray value only.
37  */
38 class SharedPrefsProvider : ContentProvider() {
39 
<lambda>null40     override fun onCreate(): Boolean = withLog("SharedPrefsProvider.onCreate") { true }
41 
getTypenull42     override fun getType(uri: Uri): String? = null
43 
44     override fun query(
45         uri: Uri,
46         projection: Array<String>?,
47         selection: String?,
48         selectionArgs: Array<String>?,
49         sortOrder: String?
50     ): Cursor? = withLog("SharedPrefsProvider.query: $uri") {
51         val context = context ?: return null
52         val prefs = getSharedPreferences(context)
53         val bytes = Base64.decode(prefs.getString(uri.path, ""), Base64.DEFAULT)
54         val cursor = MatrixCursor(arrayOf(COLUMN_NAME))
55         cursor.addRow(arrayOf(bytes))
56         return cursor
57     }
58 
insertnull59     override fun insert(uri: Uri, values: ContentValues?): Uri? =
60             withLog("SharedPrefsProvider.insert: $uri") { null }
61 
updatenull62     override fun update(
63         uri: Uri,
64         values: ContentValues?,
65         selection: String?,
66         selectionArgs: Array<String>?
67     ): Int = withLog("SharedPrefsProvider.update: $uri") {
68         val context = context ?: return 0
69         if (values == null) return 0
70         val prefs = getSharedPreferences(context)
71         val bytes = values.getAsByteArray(COLUMN_NAME)
72         val str = Base64.encodeToString(bytes, Base64.DEFAULT)
73         prefs.edit().putString(uri.path, str).apply()
74         return 1
75     }
76 
deletenull77     override fun delete(
78         uri: Uri,
79         selection: String?,
80         selectionArgs: Array<String>?
81     ): Int = withLog("SharedPrefsProvider.delete: $uri") {
82         val context = context ?: return 0
83         val prefs = getSharedPreferences(context)
84         prefs.edit().remove(uri.path).apply()
85         return 1
86     }
87 
getSharedPreferencesnull88     private fun getSharedPreferences(context: Context) =
89         context.getSharedPreferences(PREFS_FILE_NAME, Context.MODE_PRIVATE)
90 
91     companion object {
92         /** Returns the data for the key. */
93         fun get(resolver: ContentResolver, key: String): ByteArray {
94             val cursor = resolver.query(uriFor(key), arrayOf(COLUMN_NAME), null, null)
95             return if (cursor != null && cursor.moveToNext()) {
96                 cursor.getBlob(0)
97             } else {
98                 ByteArray(0)
99             }
100         }
101 
102         /** Stores the data for the key. */
103         fun put(resolver: ContentResolver, key: String, value: ByteArray) {
104             val values = ContentValues()
105             values.put(COLUMN_NAME, value)
106             resolver.update(uriFor(key), values, null)
107         }
108 
109         /** Deletes the data for the key. */
110         fun delete(resolver: ContentResolver, key: String) {
111             resolver.delete(uriFor(key), null)
112         }
113 
114         private fun uriFor(key: String): Uri = Uri.parse("content://$AUTHORITY/$key")
115     }
116 }
117