blob: 2d6027cb324db746c588926a126a8b629862acd0 [file] [log] [blame]
Jason Monk340b0e52017-03-08 14:57:56 -05001/*
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;
Jason Monk340b0e52017-03-08 14:57:56 -050019import android.content.ContentResolver;
20import android.content.Context;
Jason Monk340b0e52017-03-08 14:57:56 -050021import android.content.Intent;
Jason Monk340b0e52017-03-08 14:57:56 -050022import android.content.pm.UserInfo;
23import android.database.ContentObserver;
24import android.net.Uri;
25import android.os.Handler;
26import android.os.Looper;
Jason Monk340b0e52017-03-08 14:57:56 -050027import 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
Jason Monk248c44b2018-04-23 12:51:36 -040034import com.android.internal.util.ArrayUtils;
Lucas Dupin8968f6a2019-08-09 17:41:15 -070035import com.android.systemui.DejankUtils;
Jason Monk340b0e52017-03-08 14:57:56 -050036import com.android.systemui.DemoMode;
Dave Mankofff4736812019-10-18 17:25:50 -040037import com.android.systemui.dagger.qualifiers.MainHandler;
Jason Monk248c44b2018-04-23 12:51:36 -040038import com.android.systemui.qs.QSTileHost;
Jason Monk340b0e52017-03-08 14:57:56 -050039import com.android.systemui.settings.CurrentUserTracker;
40import com.android.systemui.statusbar.phone.StatusBarIconController;
Jason Monk340b0e52017-03-08 14:57:56 -050041import com.android.systemui.util.leak.LeakDetector;
42
43import java.util.HashMap;
44import java.util.HashSet;
45import java.util.Set;
46
Jason Monk196d6392018-12-20 13:25:34 -050047import javax.inject.Inject;
48import javax.inject.Singleton;
Jason Monk340b0e52017-03-08 14:57:56 -050049
Jason Monk196d6392018-12-20 13:25:34 -050050
51/**
52 */
53@Singleton
Jason Monk340b0e52017-03-08 14:57:56 -050054public class TunerServiceImpl extends TunerService {
55
56 private static final String TUNER_VERSION = "sysui_tuner_version";
57
Jason Monk248c44b2018-04-23 12:51:36 -040058 private static final int CURRENT_TUNER_VERSION = 4;
59
60 // Things that use the tunable infrastructure but are now real user settings and
61 // shouldn't be reset with tuner settings.
62 private static final String[] RESET_BLACKLIST = new String[] {
63 QSTileHost.TILES_SETTING,
Jason Monk960625a2018-05-15 12:50:57 -040064 Settings.Secure.DOZE_ALWAYS_ON
Jason Monk248c44b2018-04-23 12:51:36 -040065 };
Jason Monk340b0e52017-03-08 14:57:56 -050066
67 private final Observer mObserver = new Observer();
68 // Map of Uris we listen on to their settings keys.
69 private final ArrayMap<Uri, String> mListeningUris = new ArrayMap<>();
70 // Map of settings keys to the listener.
71 private final HashMap<String, Set<Tunable>> mTunableLookup = new HashMap<>();
72 // Set of all tunables, used for leak detection.
73 private final HashSet<Tunable> mTunables = LeakDetector.ENABLED ? new HashSet<>() : null;
74 private final Context mContext;
Jason Monk1e968b82018-12-21 11:33:02 -050075 private final LeakDetector mLeakDetector;
Jason Monk340b0e52017-03-08 14:57:56 -050076
77 private ContentResolver mContentResolver;
78 private int mCurrentUser;
79 private CurrentUserTracker mUserTracker;
80
Jason Monk196d6392018-12-20 13:25:34 -050081 /**
82 */
83 @Inject
Dave Mankofff4736812019-10-18 17:25:50 -040084 public TunerServiceImpl(Context context, @MainHandler Handler mainHandler,
Jason Monk1e968b82018-12-21 11:33:02 -050085 LeakDetector leakDetector) {
Jason Monk340b0e52017-03-08 14:57:56 -050086 mContext = context;
87 mContentResolver = mContext.getContentResolver();
Jason Monk1e968b82018-12-21 11:33:02 -050088 mLeakDetector = leakDetector;
Jason Monk340b0e52017-03-08 14:57:56 -050089
90 for (UserInfo user : UserManager.get(mContext).getUsers()) {
91 mCurrentUser = user.getUserHandle().getIdentifier();
92 if (getValue(TUNER_VERSION, 0) != CURRENT_TUNER_VERSION) {
Amin Shaikh4197a292019-07-02 09:45:58 -040093 upgradeTuner(getValue(TUNER_VERSION, 0), CURRENT_TUNER_VERSION, mainHandler);
Jason Monk340b0e52017-03-08 14:57:56 -050094 }
95 }
96
97 mCurrentUser = ActivityManager.getCurrentUser();
98 mUserTracker = new CurrentUserTracker(mContext) {
99 @Override
100 public void onUserSwitched(int newUserId) {
101 mCurrentUser = newUserId;
102 reloadAll();
103 reregisterAll();
104 }
105 };
106 mUserTracker.startTracking();
107 }
108
109 @Override
110 public void destroy() {
111 mUserTracker.stopTracking();
112 }
113
Amin Shaikh4197a292019-07-02 09:45:58 -0400114 private void upgradeTuner(int oldVersion, int newVersion, Handler mainHandler) {
Jason Monk340b0e52017-03-08 14:57:56 -0500115 if (oldVersion < 1) {
116 String blacklistStr = getValue(StatusBarIconController.ICON_BLACKLIST);
117 if (blacklistStr != null) {
118 ArraySet<String> iconBlacklist =
119 StatusBarIconController.getIconBlacklist(blacklistStr);
120
121 iconBlacklist.add("rotate");
122 iconBlacklist.add("headset");
123
124 Settings.Secure.putStringForUser(mContentResolver,
125 StatusBarIconController.ICON_BLACKLIST,
126 TextUtils.join(",", iconBlacklist), mCurrentUser);
127 }
128 }
Jason Monkf87aba02018-01-22 12:54:15 -0500129 if (oldVersion < 2) {
130 setTunerEnabled(mContext, false);
131 }
Jason Monk248c44b2018-04-23 12:51:36 -0400132 // 3 Removed because of a revert.
133 if (oldVersion < 4) {
134 // Delay this so that we can wait for everything to be registered first.
Tetsutoki Shiozawa36896632018-07-17 15:22:49 +0900135 final int user = mCurrentUser;
Amin Shaikh4197a292019-07-02 09:45:58 -0400136 mainHandler.postDelayed(
Tetsutoki Shiozawa36896632018-07-17 15:22:49 +0900137 () -> clearAllFromUser(user), 5000);
Jason Monk248c44b2018-04-23 12:51:36 -0400138 }
Jason Monk340b0e52017-03-08 14:57:56 -0500139 setValue(TUNER_VERSION, newVersion);
140 }
141
142 @Override
143 public String getValue(String setting) {
144 return Settings.Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
145 }
146
147 @Override
148 public void setValue(String setting, String value) {
149 Settings.Secure.putStringForUser(mContentResolver, setting, value, mCurrentUser);
150 }
151
152 @Override
153 public int getValue(String setting, int def) {
154 return Settings.Secure.getIntForUser(mContentResolver, setting, def, mCurrentUser);
155 }
156
157 @Override
158 public String getValue(String setting, String def) {
159 String ret = Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
160 if (ret == null) return def;
161 return ret;
162 }
163
164 @Override
165 public void setValue(String setting, int value) {
166 Settings.Secure.putIntForUser(mContentResolver, setting, value, mCurrentUser);
167 }
168
169 @Override
170 public void addTunable(Tunable tunable, String... keys) {
171 for (String key : keys) {
172 addTunable(tunable, key);
173 }
174 }
175
176 private void addTunable(Tunable tunable, String key) {
177 if (!mTunableLookup.containsKey(key)) {
178 mTunableLookup.put(key, new ArraySet<Tunable>());
179 }
180 mTunableLookup.get(key).add(tunable);
181 if (LeakDetector.ENABLED) {
182 mTunables.add(tunable);
Jason Monk1e968b82018-12-21 11:33:02 -0500183 mLeakDetector.trackCollection(mTunables, "TunerService.mTunables");
Jason Monk340b0e52017-03-08 14:57:56 -0500184 }
185 Uri uri = Settings.Secure.getUriFor(key);
186 if (!mListeningUris.containsKey(uri)) {
187 mListeningUris.put(uri, key);
188 mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
189 }
190 // Send the first state.
Lucas Dupin8968f6a2019-08-09 17:41:15 -0700191 String value = DejankUtils.whitelistIpcs(() -> Settings.Secure
192 .getStringForUser(mContentResolver, key, mCurrentUser));
Jason Monk340b0e52017-03-08 14:57:56 -0500193 tunable.onTuningChanged(key, value);
194 }
195
196 @Override
197 public void removeTunable(Tunable tunable) {
198 for (Set<Tunable> list : mTunableLookup.values()) {
199 list.remove(tunable);
200 }
201 if (LeakDetector.ENABLED) {
202 mTunables.remove(tunable);
203 }
204 }
205
206 protected void reregisterAll() {
207 if (mListeningUris.size() == 0) {
208 return;
209 }
210 mContentResolver.unregisterContentObserver(mObserver);
211 for (Uri uri : mListeningUris.keySet()) {
212 mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
213 }
214 }
215
216 private void reloadSetting(Uri uri) {
217 String key = mListeningUris.get(uri);
218 Set<Tunable> tunables = mTunableLookup.get(key);
219 if (tunables == null) {
220 return;
221 }
222 String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
223 for (Tunable tunable : tunables) {
224 tunable.onTuningChanged(key, value);
225 }
226 }
227
228 private void reloadAll() {
229 for (String key : mTunableLookup.keySet()) {
230 String value = Settings.Secure.getStringForUser(mContentResolver, key,
231 mCurrentUser);
232 for (Tunable tunable : mTunableLookup.get(key)) {
233 tunable.onTuningChanged(key, value);
234 }
235 }
236 }
237
238 @Override
239 public void clearAll() {
Tetsutoki Shiozawa36896632018-07-17 15:22:49 +0900240 clearAllFromUser(mCurrentUser);
241 }
242
243 public void clearAllFromUser(int user) {
Jason Monk340b0e52017-03-08 14:57:56 -0500244 // A couple special cases.
245 Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null);
246 Intent intent = new Intent(DemoMode.ACTION_DEMO);
247 intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT);
248 mContext.sendBroadcast(intent);
249
250 for (String key : mTunableLookup.keySet()) {
Jason Monk248c44b2018-04-23 12:51:36 -0400251 if (ArrayUtils.contains(RESET_BLACKLIST, key)) {
252 continue;
253 }
Tetsutoki Shiozawa36896632018-07-17 15:22:49 +0900254 Settings.Secure.putStringForUser(mContentResolver, key, null, user);
Jason Monk340b0e52017-03-08 14:57:56 -0500255 }
256 }
257
258 private class Observer extends ContentObserver {
259 public Observer() {
260 super(new Handler(Looper.getMainLooper()));
261 }
262
263 @Override
264 public void onChange(boolean selfChange, Uri uri, int userId) {
265 if (userId == ActivityManager.getCurrentUser()) {
266 reloadSetting(uri);
267 }
268 }
269 }
270}