blob: a55e2cf38e391034c27fd2d68c222464fbdc0afe [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
Amin Shaikh4197a292019-07-02 09:45:58 -040018import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
Jason Monk1e968b82018-12-21 11:33:02 -050019
Jason Monk340b0e52017-03-08 14:57:56 -050020import android.app.ActivityManager;
Jason Monk340b0e52017-03-08 14:57:56 -050021import android.content.ContentResolver;
22import android.content.Context;
Jason Monk340b0e52017-03-08 14:57:56 -050023import android.content.Intent;
Jason Monk340b0e52017-03-08 14:57:56 -050024import android.content.pm.UserInfo;
25import android.database.ContentObserver;
26import android.net.Uri;
27import android.os.Handler;
28import android.os.Looper;
Jason Monk340b0e52017-03-08 14:57:56 -050029import android.os.UserManager;
30import android.provider.Settings;
31import android.provider.Settings.Secure;
32import android.text.TextUtils;
33import android.util.ArrayMap;
34import android.util.ArraySet;
35
Jason Monk248c44b2018-04-23 12:51:36 -040036import com.android.internal.util.ArrayUtils;
Lucas Dupin8968f6a2019-08-09 17:41:15 -070037import com.android.systemui.DejankUtils;
Jason Monk340b0e52017-03-08 14:57:56 -050038import com.android.systemui.DemoMode;
Jason Monk248c44b2018-04-23 12:51:36 -040039import com.android.systemui.qs.QSTileHost;
Jason Monk340b0e52017-03-08 14:57:56 -050040import com.android.systemui.settings.CurrentUserTracker;
41import com.android.systemui.statusbar.phone.StatusBarIconController;
Jason Monk340b0e52017-03-08 14:57:56 -050042import com.android.systemui.util.leak.LeakDetector;
43
44import java.util.HashMap;
45import java.util.HashSet;
46import java.util.Set;
47
Jason Monk196d6392018-12-20 13:25:34 -050048import javax.inject.Inject;
Jason Monk1e968b82018-12-21 11:33:02 -050049import javax.inject.Named;
Jason Monk196d6392018-12-20 13:25:34 -050050import javax.inject.Singleton;
Jason Monk340b0e52017-03-08 14:57:56 -050051
Jason Monk196d6392018-12-20 13:25:34 -050052
53/**
54 */
55@Singleton
Jason Monk340b0e52017-03-08 14:57:56 -050056public class TunerServiceImpl extends TunerService {
57
58 private static final String TUNER_VERSION = "sysui_tuner_version";
59
Jason Monk248c44b2018-04-23 12:51:36 -040060 private static final int CURRENT_TUNER_VERSION = 4;
61
62 // Things that use the tunable infrastructure but are now real user settings and
63 // shouldn't be reset with tuner settings.
64 private static final String[] RESET_BLACKLIST = new String[] {
65 QSTileHost.TILES_SETTING,
Jason Monk960625a2018-05-15 12:50:57 -040066 Settings.Secure.DOZE_ALWAYS_ON
Jason Monk248c44b2018-04-23 12:51:36 -040067 };
Jason Monk340b0e52017-03-08 14:57:56 -050068
69 private final Observer mObserver = new Observer();
70 // Map of Uris we listen on to their settings keys.
71 private final ArrayMap<Uri, String> mListeningUris = new ArrayMap<>();
72 // Map of settings keys to the listener.
73 private final HashMap<String, Set<Tunable>> mTunableLookup = new HashMap<>();
74 // Set of all tunables, used for leak detection.
75 private final HashSet<Tunable> mTunables = LeakDetector.ENABLED ? new HashSet<>() : null;
76 private final Context mContext;
Jason Monk1e968b82018-12-21 11:33:02 -050077 private final LeakDetector mLeakDetector;
Jason Monk340b0e52017-03-08 14:57:56 -050078
79 private ContentResolver mContentResolver;
80 private int mCurrentUser;
81 private CurrentUserTracker mUserTracker;
82
Jason Monk196d6392018-12-20 13:25:34 -050083 /**
84 */
85 @Inject
Amin Shaikh4197a292019-07-02 09:45:58 -040086 public TunerServiceImpl(Context context, @Named(MAIN_HANDLER_NAME) Handler mainHandler,
Jason Monk1e968b82018-12-21 11:33:02 -050087 LeakDetector leakDetector) {
Jason Monk340b0e52017-03-08 14:57:56 -050088 mContext = context;
89 mContentResolver = mContext.getContentResolver();
Jason Monk1e968b82018-12-21 11:33:02 -050090 mLeakDetector = leakDetector;
Jason Monk340b0e52017-03-08 14:57:56 -050091
92 for (UserInfo user : UserManager.get(mContext).getUsers()) {
93 mCurrentUser = user.getUserHandle().getIdentifier();
94 if (getValue(TUNER_VERSION, 0) != CURRENT_TUNER_VERSION) {
Amin Shaikh4197a292019-07-02 09:45:58 -040095 upgradeTuner(getValue(TUNER_VERSION, 0), CURRENT_TUNER_VERSION, mainHandler);
Jason Monk340b0e52017-03-08 14:57:56 -050096 }
97 }
98
99 mCurrentUser = ActivityManager.getCurrentUser();
100 mUserTracker = new CurrentUserTracker(mContext) {
101 @Override
102 public void onUserSwitched(int newUserId) {
103 mCurrentUser = newUserId;
104 reloadAll();
105 reregisterAll();
106 }
107 };
108 mUserTracker.startTracking();
109 }
110
111 @Override
112 public void destroy() {
113 mUserTracker.stopTracking();
114 }
115
Amin Shaikh4197a292019-07-02 09:45:58 -0400116 private void upgradeTuner(int oldVersion, int newVersion, Handler mainHandler) {
Jason Monk340b0e52017-03-08 14:57:56 -0500117 if (oldVersion < 1) {
118 String blacklistStr = getValue(StatusBarIconController.ICON_BLACKLIST);
119 if (blacklistStr != null) {
120 ArraySet<String> iconBlacklist =
121 StatusBarIconController.getIconBlacklist(blacklistStr);
122
123 iconBlacklist.add("rotate");
124 iconBlacklist.add("headset");
125
126 Settings.Secure.putStringForUser(mContentResolver,
127 StatusBarIconController.ICON_BLACKLIST,
128 TextUtils.join(",", iconBlacklist), mCurrentUser);
129 }
130 }
Jason Monkf87aba02018-01-22 12:54:15 -0500131 if (oldVersion < 2) {
132 setTunerEnabled(mContext, false);
133 }
Jason Monk248c44b2018-04-23 12:51:36 -0400134 // 3 Removed because of a revert.
135 if (oldVersion < 4) {
136 // Delay this so that we can wait for everything to be registered first.
Tetsutoki Shiozawa36896632018-07-17 15:22:49 +0900137 final int user = mCurrentUser;
Amin Shaikh4197a292019-07-02 09:45:58 -0400138 mainHandler.postDelayed(
Tetsutoki Shiozawa36896632018-07-17 15:22:49 +0900139 () -> clearAllFromUser(user), 5000);
Jason Monk248c44b2018-04-23 12:51:36 -0400140 }
Jason Monk340b0e52017-03-08 14:57:56 -0500141 setValue(TUNER_VERSION, newVersion);
142 }
143
144 @Override
145 public String getValue(String setting) {
146 return Settings.Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
147 }
148
149 @Override
150 public void setValue(String setting, String value) {
151 Settings.Secure.putStringForUser(mContentResolver, setting, value, mCurrentUser);
152 }
153
154 @Override
155 public int getValue(String setting, int def) {
156 return Settings.Secure.getIntForUser(mContentResolver, setting, def, mCurrentUser);
157 }
158
159 @Override
160 public String getValue(String setting, String def) {
161 String ret = Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
162 if (ret == null) return def;
163 return ret;
164 }
165
166 @Override
167 public void setValue(String setting, int value) {
168 Settings.Secure.putIntForUser(mContentResolver, setting, value, mCurrentUser);
169 }
170
171 @Override
172 public void addTunable(Tunable tunable, String... keys) {
173 for (String key : keys) {
174 addTunable(tunable, key);
175 }
176 }
177
178 private void addTunable(Tunable tunable, String key) {
179 if (!mTunableLookup.containsKey(key)) {
180 mTunableLookup.put(key, new ArraySet<Tunable>());
181 }
182 mTunableLookup.get(key).add(tunable);
183 if (LeakDetector.ENABLED) {
184 mTunables.add(tunable);
Jason Monk1e968b82018-12-21 11:33:02 -0500185 mLeakDetector.trackCollection(mTunables, "TunerService.mTunables");
Jason Monk340b0e52017-03-08 14:57:56 -0500186 }
187 Uri uri = Settings.Secure.getUriFor(key);
188 if (!mListeningUris.containsKey(uri)) {
189 mListeningUris.put(uri, key);
190 mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
191 }
192 // Send the first state.
Lucas Dupin8968f6a2019-08-09 17:41:15 -0700193 String value = DejankUtils.whitelistIpcs(() -> Settings.Secure
194 .getStringForUser(mContentResolver, key, mCurrentUser));
Jason Monk340b0e52017-03-08 14:57:56 -0500195 tunable.onTuningChanged(key, value);
196 }
197
198 @Override
199 public void removeTunable(Tunable tunable) {
200 for (Set<Tunable> list : mTunableLookup.values()) {
201 list.remove(tunable);
202 }
203 if (LeakDetector.ENABLED) {
204 mTunables.remove(tunable);
205 }
206 }
207
208 protected void reregisterAll() {
209 if (mListeningUris.size() == 0) {
210 return;
211 }
212 mContentResolver.unregisterContentObserver(mObserver);
213 for (Uri uri : mListeningUris.keySet()) {
214 mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
215 }
216 }
217
218 private void reloadSetting(Uri uri) {
219 String key = mListeningUris.get(uri);
220 Set<Tunable> tunables = mTunableLookup.get(key);
221 if (tunables == null) {
222 return;
223 }
224 String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
225 for (Tunable tunable : tunables) {
226 tunable.onTuningChanged(key, value);
227 }
228 }
229
230 private void reloadAll() {
231 for (String key : mTunableLookup.keySet()) {
232 String value = Settings.Secure.getStringForUser(mContentResolver, key,
233 mCurrentUser);
234 for (Tunable tunable : mTunableLookup.get(key)) {
235 tunable.onTuningChanged(key, value);
236 }
237 }
238 }
239
240 @Override
241 public void clearAll() {
Tetsutoki Shiozawa36896632018-07-17 15:22:49 +0900242 clearAllFromUser(mCurrentUser);
243 }
244
245 public void clearAllFromUser(int user) {
Jason Monk340b0e52017-03-08 14:57:56 -0500246 // A couple special cases.
247 Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null);
248 Intent intent = new Intent(DemoMode.ACTION_DEMO);
249 intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT);
250 mContext.sendBroadcast(intent);
251
252 for (String key : mTunableLookup.keySet()) {
Jason Monk248c44b2018-04-23 12:51:36 -0400253 if (ArrayUtils.contains(RESET_BLACKLIST, key)) {
254 continue;
255 }
Tetsutoki Shiozawa36896632018-07-17 15:22:49 +0900256 Settings.Secure.putStringForUser(mContentResolver, key, null, user);
Jason Monk340b0e52017-03-08 14:57:56 -0500257 }
258 }
259
260 private class Observer extends ContentObserver {
261 public Observer() {
262 super(new Handler(Looper.getMainLooper()));
263 }
264
265 @Override
266 public void onChange(boolean selfChange, Uri uri, int userId) {
267 if (userId == ActivityManager.getCurrentUser()) {
268 reloadSetting(uri);
269 }
270 }
271 }
272}