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