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