• 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.DejankUtils;
36 import com.android.systemui.DemoMode;
37 import com.android.systemui.broadcast.BroadcastDispatcher;
38 import com.android.systemui.dagger.qualifiers.Main;
39 import com.android.systemui.qs.QSTileHost;
40 import com.android.systemui.settings.CurrentUserTracker;
41 import com.android.systemui.statusbar.phone.StatusBarIconController;
42 import com.android.systemui.util.leak.LeakDetector;
43 
44 import java.util.HashSet;
45 import java.util.Set;
46 import java.util.concurrent.ConcurrentHashMap;
47 
48 import javax.inject.Inject;
49 import javax.inject.Singleton;
50 
51 
52 /**
53  */
54 @Singleton
55 public class TunerServiceImpl extends TunerService {
56 
57     private static final String TUNER_VERSION = "sysui_tuner_version";
58 
59     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,
65             Settings.Secure.DOZE_ALWAYS_ON,
66             Settings.Secure.MEDIA_CONTROLS_RESUME
67     };
68 
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 ConcurrentHashMap<String, Set<Tunable>> mTunableLookup =
74             new ConcurrentHashMap<>();
75     // Set of all tunables, used for leak detection.
76     private final HashSet<Tunable> mTunables = LeakDetector.ENABLED ? new HashSet<>() : null;
77     private final Context mContext;
78     private final LeakDetector mLeakDetector;
79 
80     private ContentResolver mContentResolver;
81     private int mCurrentUser;
82     private CurrentUserTracker mUserTracker;
83 
84     /**
85      */
86     @Inject
TunerServiceImpl(Context context, @Main Handler mainHandler, LeakDetector leakDetector, BroadcastDispatcher broadcastDispatcher)87     public TunerServiceImpl(Context context, @Main Handler mainHandler,
88             LeakDetector leakDetector, BroadcastDispatcher broadcastDispatcher) {
89         mContext = context;
90         mContentResolver = mContext.getContentResolver();
91         mLeakDetector = leakDetector;
92 
93         for (UserInfo user : UserManager.get(mContext).getUsers()) {
94             mCurrentUser = user.getUserHandle().getIdentifier();
95             if (getValue(TUNER_VERSION, 0) != CURRENT_TUNER_VERSION) {
96                 upgradeTuner(getValue(TUNER_VERSION, 0), CURRENT_TUNER_VERSION, mainHandler);
97             }
98         }
99 
100         mCurrentUser = ActivityManager.getCurrentUser();
101         mUserTracker = new CurrentUserTracker(broadcastDispatcher) {
102             @Override
103             public void onUserSwitched(int newUserId) {
104                 mCurrentUser = newUserId;
105                 reloadAll();
106                 reregisterAll();
107             }
108         };
109         mUserTracker.startTracking();
110     }
111 
112     @Override
destroy()113     public void destroy() {
114         mUserTracker.stopTracking();
115     }
116 
upgradeTuner(int oldVersion, int newVersion, Handler mainHandler)117     private void upgradeTuner(int oldVersion, int newVersion, Handler mainHandler) {
118         if (oldVersion < 1) {
119             String blacklistStr = getValue(StatusBarIconController.ICON_BLACKLIST);
120             if (blacklistStr != null) {
121                 ArraySet<String> iconBlacklist =
122                         StatusBarIconController.getIconBlacklist(mContext, blacklistStr);
123 
124                 iconBlacklist.add("rotate");
125                 iconBlacklist.add("headset");
126 
127                 Settings.Secure.putStringForUser(mContentResolver,
128                         StatusBarIconController.ICON_BLACKLIST,
129                         TextUtils.join(",", iconBlacklist), mCurrentUser);
130             }
131         }
132         if (oldVersion < 2) {
133             setTunerEnabled(mContext, false);
134         }
135         // 3 Removed because of a revert.
136         if (oldVersion < 4) {
137             // Delay this so that we can wait for everything to be registered first.
138             final int user = mCurrentUser;
139             mainHandler.postDelayed(
140                     () -> clearAllFromUser(user), 5000);
141         }
142         setValue(TUNER_VERSION, newVersion);
143     }
144 
145     @Override
getValue(String setting)146     public String getValue(String setting) {
147         return Settings.Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
148     }
149 
150     @Override
setValue(String setting, String value)151     public void setValue(String setting, String value) {
152          Settings.Secure.putStringForUser(mContentResolver, setting, value, mCurrentUser);
153     }
154 
155     @Override
getValue(String setting, int def)156     public int getValue(String setting, int def) {
157         return Settings.Secure.getIntForUser(mContentResolver, setting, def, mCurrentUser);
158     }
159 
160     @Override
getValue(String setting, String def)161     public String getValue(String setting, String def) {
162         String ret = Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
163         if (ret == null) return def;
164         return ret;
165     }
166 
167     @Override
setValue(String setting, int value)168     public void setValue(String setting, int value) {
169          Settings.Secure.putIntForUser(mContentResolver, setting, value, mCurrentUser);
170     }
171 
172     @Override
addTunable(Tunable tunable, String... keys)173     public void addTunable(Tunable tunable, String... keys) {
174         for (String key : keys) {
175             addTunable(tunable, key);
176         }
177     }
178 
addTunable(Tunable tunable, String key)179     private void addTunable(Tunable tunable, String key) {
180         if (!mTunableLookup.containsKey(key)) {
181             mTunableLookup.put(key, new ArraySet<Tunable>());
182         }
183         mTunableLookup.get(key).add(tunable);
184         if (LeakDetector.ENABLED) {
185             mTunables.add(tunable);
186             mLeakDetector.trackCollection(mTunables, "TunerService.mTunables");
187         }
188         Uri uri = Settings.Secure.getUriFor(key);
189         if (!mListeningUris.containsKey(uri)) {
190             mListeningUris.put(uri, key);
191             mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
192         }
193         // Send the first state.
194         String value = DejankUtils.whitelistIpcs(() -> Settings.Secure
195                 .getStringForUser(mContentResolver, key, mCurrentUser));
196         tunable.onTuningChanged(key, value);
197     }
198 
199     @Override
removeTunable(Tunable tunable)200     public void removeTunable(Tunable tunable) {
201         for (Set<Tunable> list : mTunableLookup.values()) {
202             list.remove(tunable);
203         }
204         if (LeakDetector.ENABLED) {
205             mTunables.remove(tunable);
206         }
207     }
208 
reregisterAll()209     protected void reregisterAll() {
210         if (mListeningUris.size() == 0) {
211             return;
212         }
213         mContentResolver.unregisterContentObserver(mObserver);
214         for (Uri uri : mListeningUris.keySet()) {
215             mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
216         }
217     }
218 
reloadSetting(Uri uri)219     private void reloadSetting(Uri uri) {
220         String key = mListeningUris.get(uri);
221         Set<Tunable> tunables = mTunableLookup.get(key);
222         if (tunables == null) {
223             return;
224         }
225         String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
226         for (Tunable tunable : tunables) {
227             tunable.onTuningChanged(key, value);
228         }
229     }
230 
reloadAll()231     private void reloadAll() {
232         for (String key : mTunableLookup.keySet()) {
233             String value = Settings.Secure.getStringForUser(mContentResolver, key,
234                     mCurrentUser);
235             for (Tunable tunable : mTunableLookup.get(key)) {
236                 tunable.onTuningChanged(key, value);
237             }
238         }
239     }
240 
241     @Override
clearAll()242     public void clearAll() {
243         clearAllFromUser(mCurrentUser);
244     }
245 
clearAllFromUser(int user)246     public void clearAllFromUser(int user) {
247         // A couple special cases.
248         Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null);
249         Intent intent = new Intent(DemoMode.ACTION_DEMO);
250         intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT);
251         mContext.sendBroadcast(intent);
252 
253         for (String key : mTunableLookup.keySet()) {
254             if (ArrayUtils.contains(RESET_BLACKLIST, key)) {
255                 continue;
256             }
257             Settings.Secure.putStringForUser(mContentResolver, key, null, user);
258         }
259     }
260 
261     private class Observer extends ContentObserver {
Observer()262         public Observer() {
263             super(new Handler(Looper.getMainLooper()));
264         }
265 
266         @Override
onChange(boolean selfChange, java.util.Collection<Uri> uris, int flags, int userId)267         public void onChange(boolean selfChange, java.util.Collection<Uri> uris,
268                 int flags, int userId) {
269             if (userId == ActivityManager.getCurrentUser()) {
270                 for (Uri u : uris) {
271                     reloadSetting(u);
272                 }
273             }
274         }
275 
276     }
277 }
278