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 package com.android.systemui.util.settings 17 18 import android.annotation.UserIdInt 19 import android.database.ContentObserver 20 import android.net.Uri 21 import android.os.UserHandle 22 import android.provider.Settings.SettingNotFoundException 23 import com.android.app.tracing.TraceUtils.trace 24 import com.android.systemui.settings.UserTracker 25 import com.android.systemui.util.settings.SettingsProxy.Companion.parseFloat 26 import com.android.systemui.util.settings.SettingsProxy.Companion.parseFloatOrThrow 27 import com.android.systemui.util.settings.SettingsProxy.Companion.parseLongOrThrow 28 import com.android.systemui.util.settings.SettingsProxy.Companion.parseLongOrUseDefault 29 30 /** 31 * Used to interact with per-user Settings.Secure and Settings.System settings (but not 32 * Settings.Global, since those do not vary per-user) 33 * 34 * This interface can be implemented to give instance method (instead of static method) versions of 35 * Settings.Secure and Settings.System. It can be injected into class constructors and then faked or 36 * mocked as needed in tests. 37 * 38 * You can ask for [SecureSettings] or [SystemSettings] to be injected as needed. 39 * 40 * This class also provides [.registerContentObserver] methods, normally found on [ContentResolver] 41 * instances, unifying setting related actions in one place. 42 */ 43 interface UserSettingsProxy : SettingsProxy { 44 /** Returns that [UserTracker] this instance was constructed with. */ 45 val userTracker: UserTracker 46 /** Returns the user id for the associated [ContentResolver]. */ 47 var userId: Int 48 get() = getContentResolver().userId 49 set(_) { 50 throw UnsupportedOperationException( 51 "userId cannot be set in interface, use setter from an implementation instead." 52 ) 53 } 54 55 /** 56 * Returns the actual current user handle when querying with the current user. Otherwise, 57 * returns the passed in user id. 58 */ getRealUserHandlenull59 fun getRealUserHandle(userHandle: Int): Int { 60 return if (userHandle != UserHandle.USER_CURRENT) { 61 userHandle 62 } else userTracker.userId 63 } 64 registerContentObserverSyncnull65 override fun registerContentObserverSync(uri: Uri, settingsObserver: ContentObserver) { 66 registerContentObserverForUserSync(uri, settingsObserver, userId) 67 } 68 69 /** Convenience wrapper around [ContentResolver.registerContentObserver].' */ registerContentObserverSyncnull70 override fun registerContentObserverSync( 71 uri: Uri, 72 notifyForDescendants: Boolean, 73 settingsObserver: ContentObserver 74 ) { 75 registerContentObserverForUserSync(uri, notifyForDescendants, settingsObserver, userId) 76 } 77 78 /** 79 * Convenience wrapper around [ContentResolver.registerContentObserver] 80 * 81 * Implicitly calls [getUriFor] on the passed in name. 82 */ registerContentObserverForUserSyncnull83 fun registerContentObserverForUserSync( 84 name: String, 85 settingsObserver: ContentObserver, 86 userHandle: Int 87 ) { 88 registerContentObserverForUserSync(getUriFor(name), settingsObserver, userHandle) 89 } 90 91 /** Convenience wrapper around [ContentResolver.registerContentObserver] */ registerContentObserverForUserSyncnull92 fun registerContentObserverForUserSync( 93 uri: Uri, 94 settingsObserver: ContentObserver, 95 userHandle: Int 96 ) { 97 registerContentObserverForUserSync(uri, false, settingsObserver, userHandle) 98 } 99 100 /** 101 * Convenience wrapper around [ContentResolver.registerContentObserver] 102 * 103 * Implicitly calls [getUriFor] on the passed in name. 104 */ registerContentObserverForUserSyncnull105 fun registerContentObserverForUserSync( 106 name: String, 107 notifyForDescendants: Boolean, 108 settingsObserver: ContentObserver, 109 userHandle: Int 110 ) { 111 registerContentObserverForUserSync( 112 getUriFor(name), 113 notifyForDescendants, 114 settingsObserver, 115 userHandle 116 ) 117 } 118 119 /** Convenience wrapper around [ContentResolver.registerContentObserver] */ registerContentObserverForUserSyncnull120 fun registerContentObserverForUserSync( 121 uri: Uri, 122 notifyForDescendants: Boolean, 123 settingsObserver: ContentObserver, 124 userHandle: Int 125 ) { 126 trace({ "USP#registerObserver#[$uri]" }) { 127 getContentResolver() 128 .registerContentObserver( 129 uri, 130 notifyForDescendants, 131 settingsObserver, 132 getRealUserHandle(userHandle) 133 ) 134 Unit 135 } 136 } 137 138 /** 139 * Look up a name in the database. 140 * 141 * @param name to look up in the table 142 * @return the corresponding value, or null if not present 143 */ getStringnull144 override fun getString(name: String): String { 145 return getStringForUser(name, userId) 146 } 147 148 /** See [getString]. */ getStringForUsernull149 fun getStringForUser(name: String, userHandle: Int): String 150 151 /** 152 * Store a name/value pair into the database. Values written by this method will be overridden 153 * if a restore happens in the future. 154 * 155 * @param name to store 156 * @param value to associate with the name 157 * @return true if the value was set, false on database errors 158 */ 159 fun putString(name: String, value: String, overrideableByRestore: Boolean): Boolean 160 161 override fun putString(name: String, value: String): Boolean { 162 return putStringForUser(name, value, userId) 163 } 164 165 /** Similar implementation to [putString] for the specified [userHandle]. */ putStringForUsernull166 fun putStringForUser(name: String, value: String, userHandle: Int): Boolean 167 168 /** Similar implementation to [putString] for the specified [userHandle]. */ 169 fun putStringForUser( 170 name: String, 171 value: String, 172 tag: String?, 173 makeDefault: Boolean, 174 @UserIdInt userHandle: Int, 175 overrideableByRestore: Boolean 176 ): Boolean 177 178 override fun getInt(name: String, def: Int): Int { 179 return getIntForUser(name, def, userId) 180 } 181 182 /** Similar implementation to [getInt] for the specified [userHandle]. */ getIntForUsernull183 fun getIntForUser(name: String, def: Int, userHandle: Int): Int { 184 val v = getStringForUser(name, userHandle) 185 return try { 186 v.toInt() 187 } catch (e: NumberFormatException) { 188 def 189 } 190 } 191 192 @Throws(SettingNotFoundException::class) getIntnull193 override fun getInt(name: String) = getIntForUser(name, userId) 194 195 /** Similar implementation to [getInt] for the specified [userHandle]. */ 196 @Throws(SettingNotFoundException::class) 197 fun getIntForUser(name: String, userHandle: Int): Int { 198 val v = getStringForUser(name, userHandle) 199 return try { 200 v.toInt() 201 } catch (e: NumberFormatException) { 202 throw SettingNotFoundException(name) 203 } 204 } 205 putIntnull206 override fun putInt(name: String, value: Int) = putIntForUser(name, value, userId) 207 208 /** Similar implementation to [getInt] for the specified [userHandle]. */ 209 fun putIntForUser(name: String, value: Int, userHandle: Int) = 210 putStringForUser(name, value.toString(), userHandle) 211 212 override fun getBool(name: String, def: Boolean) = getBoolForUser(name, def, userId) 213 214 /** Similar implementation to [getBool] for the specified [userHandle]. */ 215 fun getBoolForUser(name: String, def: Boolean, userHandle: Int) = 216 getIntForUser(name, if (def) 1 else 0, userHandle) != 0 217 218 @Throws(SettingNotFoundException::class) 219 override fun getBool(name: String) = getBoolForUser(name, userId) 220 221 /** Similar implementation to [getBool] for the specified [userHandle]. */ 222 @Throws(SettingNotFoundException::class) 223 fun getBoolForUser(name: String, userHandle: Int): Boolean { 224 return getIntForUser(name, userHandle) != 0 225 } 226 putBoolnull227 override fun putBool(name: String, value: Boolean): Boolean { 228 return putBoolForUser(name, value, userId) 229 } 230 231 /** Similar implementation to [putBool] for the specified [userHandle]. */ putBoolForUsernull232 fun putBoolForUser(name: String, value: Boolean, userHandle: Int) = 233 putIntForUser(name, if (value) 1 else 0, userHandle) 234 235 /** Similar implementation to [getLong] for the specified [userHandle]. */ 236 fun getLongForUser(name: String, def: Long, userHandle: Int): Long { 237 val valString = getStringForUser(name, userHandle) 238 return parseLongOrUseDefault(valString, def) 239 } 240 241 /** Similar implementation to [getLong] for the specified [userHandle]. */ 242 @Throws(SettingNotFoundException::class) getLongForUsernull243 fun getLongForUser(name: String, userHandle: Int): Long { 244 val valString = getStringForUser(name, userHandle) 245 return parseLongOrThrow(name, valString) 246 } 247 248 /** Similar implementation to [putLong] for the specified [userHandle]. */ putLongForUsernull249 fun putLongForUser(name: String, value: Long, userHandle: Int) = 250 putStringForUser(name, value.toString(), userHandle) 251 252 /** Similar implementation to [getFloat] for the specified [userHandle]. */ 253 fun getFloatForUser(name: String, def: Float, userHandle: Int): Float { 254 val v = getStringForUser(name, userHandle) 255 return parseFloat(v, def) 256 } 257 258 /** Similar implementation to [getFloat] for the specified [userHandle]. */ 259 @Throws(SettingNotFoundException::class) getFloatForUsernull260 fun getFloatForUser(name: String, userHandle: Int): Float { 261 val v = getStringForUser(name, userHandle) 262 return parseFloatOrThrow(name, v) 263 } 264 265 /** Similar implementation to [putFloat] for the specified [userHandle]. */ putFloatForUsernull266 fun putFloatForUser(name: String, value: Float, userHandle: Int) = 267 putStringForUser(name, value.toString(), userHandle) 268 } 269