blob: ce0032e619e725c99fd97ebb46593ddc31661644 [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;
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000037import com.android.systemui.broadcast.BroadcastDispatcher;
Dave Mankofff4736812019-10-18 17:25:50 -040038import com.android.systemui.dagger.qualifiers.MainHandler;
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;
49import javax.inject.Singleton;
Jason Monk340b0e52017-03-08 14:57:56 -050050
Jason Monk196d6392018-12-20 13:25:34 -050051
52/**
53 */
54@Singleton
Jason Monk340b0e52017-03-08 14:57:56 -050055public class TunerServiceImpl extends TunerService {
56
57 private static final String TUNER_VERSION = "sysui_tuner_version";
58
Jason Monk248c44b2018-04-23 12:51:36 -040059 private static final int CURRENT_TUNER_VERSION = 4;
60
61 // Things that use the tunable infrastructure but are now real user settings and
62 // shouldn't be reset with tuner settings.
63 private static final String[] RESET_BLACKLIST = new String[] {
64 QSTileHost.TILES_SETTING,
Jason Monk960625a2018-05-15 12:50:57 -040065 Settings.Secure.DOZE_ALWAYS_ON
Jason Monk248c44b2018-04-23 12:51:36 -040066 };
Jason Monk340b0e52017-03-08 14:57:56 -050067
68 private final Observer mObserver = new Observer();
69 // Map of Uris we listen on to their settings keys.
70 private final ArrayMap<Uri, String> mListeningUris = new ArrayMap<>();
71 // Map of settings keys to the listener.
72 private final HashMap<String, Set<Tunable>> mTunableLookup = new HashMap<>();
73 // Set of all tunables, used for leak detection.
74 private final HashSet<Tunable> mTunables = LeakDetector.ENABLED ? new HashSet<>() : null;
75 private final Context mContext;
Jason Monk1e968b82018-12-21 11:33:02 -050076 private final LeakDetector mLeakDetector;
Jason Monk340b0e52017-03-08 14:57:56 -050077
78 private ContentResolver mContentResolver;
79 private int mCurrentUser;
80 private CurrentUserTracker mUserTracker;
81
Jason Monk196d6392018-12-20 13:25:34 -050082 /**
83 */
84 @Inject
Dave Mankofff4736812019-10-18 17:25:50 -040085 public TunerServiceImpl(Context context, @MainHandler Handler mainHandler,
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000086 LeakDetector leakDetector, BroadcastDispatcher broadcastDispatcher) {
Jason Monk340b0e52017-03-08 14:57:56 -050087 mContext = context;
88 mContentResolver = mContext.getContentResolver();
Jason Monk1e968b82018-12-21 11:33:02 -050089 mLeakDetector = leakDetector;
Jason Monk340b0e52017-03-08 14:57:56 -050090
91 for (UserInfo user : UserManager.get(mContext).getUsers()) {
92 mCurrentUser = user.getUserHandle().getIdentifier();
93 if (getValue(TUNER_VERSION, 0) != CURRENT_TUNER_VERSION) {
Amin Shaikh4197a292019-07-02 09:45:58 -040094 upgradeTuner(getValue(TUNER_VERSION, 0), CURRENT_TUNER_VERSION, mainHandler);
Jason Monk340b0e52017-03-08 14:57:56 -050095 }
96 }
97
98 mCurrentUser = ActivityManager.getCurrentUser();
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000099 mUserTracker = new CurrentUserTracker(broadcastDispatcher) {
Jason Monk340b0e52017-03-08 14:57:56 -0500100 @Override
101 public void onUserSwitched(int newUserId) {
102 mCurrentUser = newUserId;
103 reloadAll();
104 reregisterAll();
105 }
106 };
107 mUserTracker.startTracking();
108 }
109
110 @Override
111 public void destroy() {
112 mUserTracker.stopTracking();
113 }
114
Amin Shaikh4197a292019-07-02 09:45:58 -0400115 private void upgradeTuner(int oldVersion, int newVersion, Handler mainHandler) {
Jason Monk340b0e52017-03-08 14:57:56 -0500116 if (oldVersion < 1) {
117 String blacklistStr = getValue(StatusBarIconController.ICON_BLACKLIST);
118 if (blacklistStr != null) {
119 ArraySet<String> iconBlacklist =
120 StatusBarIconController.getIconBlacklist(blacklistStr);
121
122 iconBlacklist.add("rotate");
123 iconBlacklist.add("headset");
124
125 Settings.Secure.putStringForUser(mContentResolver,
126 StatusBarIconController.ICON_BLACKLIST,
127 TextUtils.join(",", iconBlacklist), mCurrentUser);
128 }
129 }
Jason Monkf87aba02018-01-22 12:54:15 -0500130 if (oldVersion < 2) {
131 setTunerEnabled(mContext, false);
132 }
Jason Monk248c44b2018-04-23 12:51:36 -0400133 // 3 Removed because of a revert.
134 if (oldVersion < 4) {
135 // Delay this so that we can wait for everything to be registered first.
Tetsutoki Shiozawa36896632018-07-17 15:22:49 +0900136 final int user = mCurrentUser;
Amin Shaikh4197a292019-07-02 09:45:58 -0400137 mainHandler.postDelayed(
Tetsutoki Shiozawa36896632018-07-17 15:22:49 +0900138 () -> clearAllFromUser(user), 5000);
Jason Monk248c44b2018-04-23 12:51:36 -0400139 }
Jason Monk340b0e52017-03-08 14:57:56 -0500140 setValue(TUNER_VERSION, newVersion);
141 }
142
143 @Override
144 public String getValue(String setting) {
145 return Settings.Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
146 }
147
148 @Override
149 public void setValue(String setting, String value) {
150 Settings.Secure.putStringForUser(mContentResolver, setting, value, mCurrentUser);
151 }
152
153 @Override
154 public int getValue(String setting, int def) {
155 return Settings.Secure.getIntForUser(mContentResolver, setting, def, mCurrentUser);
156 }
157
158 @Override
159 public String getValue(String setting, String def) {
160 String ret = Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
161 if (ret == null) return def;
162 return ret;
163 }
164
165 @Override
166 public void setValue(String setting, int value) {
167 Settings.Secure.putIntForUser(mContentResolver, setting, value, mCurrentUser);
168 }
169
170 @Override
171 public void addTunable(Tunable tunable, String... keys) {
172 for (String key : keys) {
173 addTunable(tunable, key);
174 }
175 }
176
177 private void addTunable(Tunable tunable, String key) {
178 if (!mTunableLookup.containsKey(key)) {
179 mTunableLookup.put(key, new ArraySet<Tunable>());
180 }
181 mTunableLookup.get(key).add(tunable);
182 if (LeakDetector.ENABLED) {
183 mTunables.add(tunable);
Jason Monk1e968b82018-12-21 11:33:02 -0500184 mLeakDetector.trackCollection(mTunables, "TunerService.mTunables");
Jason Monk340b0e52017-03-08 14:57:56 -0500185 }
186 Uri uri = Settings.Secure.getUriFor(key);
187 if (!mListeningUris.containsKey(uri)) {
188 mListeningUris.put(uri, key);
189 mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
190 }
191 // Send the first state.
Lucas Dupin8968f6a2019-08-09 17:41:15 -0700192 String value = DejankUtils.whitelistIpcs(() -> Settings.Secure
193 .getStringForUser(mContentResolver, key, mCurrentUser));
Jason Monk340b0e52017-03-08 14:57:56 -0500194 tunable.onTuningChanged(key, value);
195 }
196
197 @Override
198 public void removeTunable(Tunable tunable) {
199 for (Set<Tunable> list : mTunableLookup.values()) {
200 list.remove(tunable);
201 }
202 if (LeakDetector.ENABLED) {
203 mTunables.remove(tunable);
204 }
205 }
206
207 protected void reregisterAll() {
208 if (mListeningUris.size() == 0) {
209 return;
210 }
211 mContentResolver.unregisterContentObserver(mObserver);
212 for (Uri uri : mListeningUris.keySet()) {
213 mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
214 }
215 }
216
217 private void reloadSetting(Uri uri) {
218 String key = mListeningUris.get(uri);
219 Set<Tunable> tunables = mTunableLookup.get(key);
220 if (tunables == null) {
221 return;
222 }
223 String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
224 for (Tunable tunable : tunables) {
225 tunable.onTuningChanged(key, value);
226 }
227 }
228
229 private void reloadAll() {
230 for (String key : mTunableLookup.keySet()) {
231 String value = Settings.Secure.getStringForUser(mContentResolver, key,
232 mCurrentUser);
233 for (Tunable tunable : mTunableLookup.get(key)) {
234 tunable.onTuningChanged(key, value);
235 }
236 }
237 }
238
239 @Override
240 public void clearAll() {
Tetsutoki Shiozawa36896632018-07-17 15:22:49 +0900241 clearAllFromUser(mCurrentUser);
242 }
243
244 public void clearAllFromUser(int user) {
Jason Monk340b0e52017-03-08 14:57:56 -0500245 // A couple special cases.
246 Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null);
247 Intent intent = new Intent(DemoMode.ACTION_DEMO);
248 intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT);
249 mContext.sendBroadcast(intent);
250
251 for (String key : mTunableLookup.keySet()) {
Jason Monk248c44b2018-04-23 12:51:36 -0400252 if (ArrayUtils.contains(RESET_BLACKLIST, key)) {
253 continue;
254 }
Tetsutoki Shiozawa36896632018-07-17 15:22:49 +0900255 Settings.Secure.putStringForUser(mContentResolver, key, null, user);
Jason Monk340b0e52017-03-08 14:57:56 -0500256 }
257 }
258
259 private class Observer extends ContentObserver {
260 public Observer() {
261 super(new Handler(Looper.getMainLooper()));
262 }
263
264 @Override
265 public void onChange(boolean selfChange, Uri uri, int userId) {
266 if (userId == ActivityManager.getCurrentUser()) {
267 reloadSetting(uri);
268 }
269 }
270 }
271}