TunerServiceImpl.java revision 248c44b915c6c11b76d6387311ac63f208d6196b
1/* 2 * Copyright (C) 2015 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 */ 16package com.android.systemui.tuner; 17 18import android.app.ActivityManager; 19import android.content.ContentResolver; 20import android.content.Context; 21import android.content.Intent; 22import android.content.pm.UserInfo; 23import android.database.ContentObserver; 24import android.net.Uri; 25import android.os.Handler; 26import android.os.Looper; 27import android.os.UserManager; 28import android.provider.Settings; 29import android.provider.Settings.Secure; 30import android.text.TextUtils; 31import android.util.ArrayMap; 32import android.util.ArraySet; 33 34import com.android.internal.util.ArrayUtils; 35import com.android.systemui.DemoMode; 36import com.android.systemui.Dependency; 37import com.android.systemui.qs.QSTileHost; 38import com.android.systemui.settings.CurrentUserTracker; 39import com.android.systemui.statusbar.phone.StatusBarIconController; 40import com.android.systemui.util.leak.LeakDetector; 41 42import java.util.HashMap; 43import java.util.HashSet; 44import java.util.Set; 45 46 47public class TunerServiceImpl extends TunerService { 48 49 private static final String TUNER_VERSION = "sysui_tuner_version"; 50 51 private static final int CURRENT_TUNER_VERSION = 4; 52 53 // Things that use the tunable infrastructure but are now real user settings and 54 // shouldn't be reset with tuner settings. 55 private static final String[] RESET_BLACKLIST = new String[] { 56 QSTileHost.TILES_SETTING, 57 }; 58 59 private final Observer mObserver = new Observer(); 60 // Map of Uris we listen on to their settings keys. 61 private final ArrayMap<Uri, String> mListeningUris = new ArrayMap<>(); 62 // Map of settings keys to the listener. 63 private final HashMap<String, Set<Tunable>> mTunableLookup = new HashMap<>(); 64 // Set of all tunables, used for leak detection. 65 private final HashSet<Tunable> mTunables = LeakDetector.ENABLED ? new HashSet<>() : null; 66 private final Context mContext; 67 68 private ContentResolver mContentResolver; 69 private int mCurrentUser; 70 private CurrentUserTracker mUserTracker; 71 72 public TunerServiceImpl(Context context) { 73 mContext = context; 74 mContentResolver = mContext.getContentResolver(); 75 76 for (UserInfo user : UserManager.get(mContext).getUsers()) { 77 mCurrentUser = user.getUserHandle().getIdentifier(); 78 if (getValue(TUNER_VERSION, 0) != CURRENT_TUNER_VERSION) { 79 upgradeTuner(getValue(TUNER_VERSION, 0), CURRENT_TUNER_VERSION); 80 } 81 } 82 83 mCurrentUser = ActivityManager.getCurrentUser(); 84 mUserTracker = new CurrentUserTracker(mContext) { 85 @Override 86 public void onUserSwitched(int newUserId) { 87 mCurrentUser = newUserId; 88 reloadAll(); 89 reregisterAll(); 90 } 91 }; 92 mUserTracker.startTracking(); 93 } 94 95 @Override 96 public void destroy() { 97 mUserTracker.stopTracking(); 98 } 99 100 private void upgradeTuner(int oldVersion, int newVersion) { 101 if (oldVersion < 1) { 102 String blacklistStr = getValue(StatusBarIconController.ICON_BLACKLIST); 103 if (blacklistStr != null) { 104 ArraySet<String> iconBlacklist = 105 StatusBarIconController.getIconBlacklist(blacklistStr); 106 107 iconBlacklist.add("rotate"); 108 iconBlacklist.add("headset"); 109 110 Settings.Secure.putStringForUser(mContentResolver, 111 StatusBarIconController.ICON_BLACKLIST, 112 TextUtils.join(",", iconBlacklist), mCurrentUser); 113 } 114 } 115 if (oldVersion < 2) { 116 setTunerEnabled(mContext, false); 117 } 118 // 3 Removed because of a revert. 119 if (oldVersion < 4) { 120 // Delay this so that we can wait for everything to be registered first. 121 new Handler(Dependency.get(Dependency.BG_LOOPER)).postDelayed(() -> clearAll(), 5000); 122 } 123 setValue(TUNER_VERSION, newVersion); 124 } 125 126 @Override 127 public String getValue(String setting) { 128 return Settings.Secure.getStringForUser(mContentResolver, setting, mCurrentUser); 129 } 130 131 @Override 132 public void setValue(String setting, String value) { 133 Settings.Secure.putStringForUser(mContentResolver, setting, value, mCurrentUser); 134 } 135 136 @Override 137 public int getValue(String setting, int def) { 138 return Settings.Secure.getIntForUser(mContentResolver, setting, def, mCurrentUser); 139 } 140 141 @Override 142 public String getValue(String setting, String def) { 143 String ret = Secure.getStringForUser(mContentResolver, setting, mCurrentUser); 144 if (ret == null) return def; 145 return ret; 146 } 147 148 @Override 149 public void setValue(String setting, int value) { 150 Settings.Secure.putIntForUser(mContentResolver, setting, value, mCurrentUser); 151 } 152 153 @Override 154 public void addTunable(Tunable tunable, String... keys) { 155 for (String key : keys) { 156 addTunable(tunable, key); 157 } 158 } 159 160 private void addTunable(Tunable tunable, String key) { 161 if (!mTunableLookup.containsKey(key)) { 162 mTunableLookup.put(key, new ArraySet<Tunable>()); 163 } 164 mTunableLookup.get(key).add(tunable); 165 if (LeakDetector.ENABLED) { 166 mTunables.add(tunable); 167 Dependency.get(LeakDetector.class).trackCollection(mTunables, "TunerService.mTunables"); 168 } 169 Uri uri = Settings.Secure.getUriFor(key); 170 if (!mListeningUris.containsKey(uri)) { 171 mListeningUris.put(uri, key); 172 mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser); 173 } 174 // Send the first state. 175 String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser); 176 tunable.onTuningChanged(key, value); 177 } 178 179 @Override 180 public void removeTunable(Tunable tunable) { 181 for (Set<Tunable> list : mTunableLookup.values()) { 182 list.remove(tunable); 183 } 184 if (LeakDetector.ENABLED) { 185 mTunables.remove(tunable); 186 } 187 } 188 189 protected void reregisterAll() { 190 if (mListeningUris.size() == 0) { 191 return; 192 } 193 mContentResolver.unregisterContentObserver(mObserver); 194 for (Uri uri : mListeningUris.keySet()) { 195 mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser); 196 } 197 } 198 199 private void reloadSetting(Uri uri) { 200 String key = mListeningUris.get(uri); 201 Set<Tunable> tunables = mTunableLookup.get(key); 202 if (tunables == null) { 203 return; 204 } 205 String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser); 206 for (Tunable tunable : tunables) { 207 tunable.onTuningChanged(key, value); 208 } 209 } 210 211 private void reloadAll() { 212 for (String key : mTunableLookup.keySet()) { 213 String value = Settings.Secure.getStringForUser(mContentResolver, key, 214 mCurrentUser); 215 for (Tunable tunable : mTunableLookup.get(key)) { 216 tunable.onTuningChanged(key, value); 217 } 218 } 219 } 220 221 @Override 222 public void clearAll() { 223 // A couple special cases. 224 Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null); 225 Intent intent = new Intent(DemoMode.ACTION_DEMO); 226 intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT); 227 mContext.sendBroadcast(intent); 228 229 for (String key : mTunableLookup.keySet()) { 230 if (ArrayUtils.contains(RESET_BLACKLIST, key)) { 231 continue; 232 } 233 Settings.Secure.putString(mContentResolver, key, null); 234 } 235 } 236 237 private class Observer extends ContentObserver { 238 public Observer() { 239 super(new Handler(Looper.getMainLooper())); 240 } 241 242 @Override 243 public void onChange(boolean selfChange, Uri uri, int userId) { 244 if (userId == ActivityManager.getCurrentUser()) { 245 reloadSetting(uri); 246 } 247 } 248 } 249} 250