1340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk/*
2340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * Copyright (C) 2015 The Android Open Source Project
3340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk *
4340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * Licensed under the Apache License, Version 2.0 (the "License");
5340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * you may not use this file except in compliance with the License.
6340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * You may obtain a copy of the License at
7340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk *
8340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk *      http://www.apache.org/licenses/LICENSE-2.0
9340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk *
10340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * Unless required by applicable law or agreed to in writing, software
11340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * distributed under the License is distributed on an "AS IS" BASIS,
12340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * See the License for the specific language governing permissions and
14340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * limitations under the License
15340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk */
16340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkpackage com.android.systemui.tuner;
17340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
18340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport android.app.ActivityManager;
19340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport android.content.ContentResolver;
20340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport android.content.Context;
21340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport android.content.Intent;
22340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport android.content.pm.UserInfo;
23340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport android.database.ContentObserver;
24340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport android.net.Uri;
25340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport android.os.Handler;
26340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport android.os.Looper;
27340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport android.os.UserManager;
28340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport android.provider.Settings;
29340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport android.provider.Settings.Secure;
30340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport android.text.TextUtils;
31340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport android.util.ArrayMap;
32340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport android.util.ArraySet;
33340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
34248c44b915c6c11b76d6387311ac63f208d6196bJason Monkimport com.android.internal.util.ArrayUtils;
35340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport com.android.systemui.DemoMode;
36340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport com.android.systemui.Dependency;
37248c44b915c6c11b76d6387311ac63f208d6196bJason Monkimport com.android.systemui.qs.QSTileHost;
38340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport com.android.systemui.settings.CurrentUserTracker;
39340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport com.android.systemui.statusbar.phone.StatusBarIconController;
40340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport com.android.systemui.util.leak.LeakDetector;
41340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
42340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport java.util.HashMap;
43340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport java.util.HashSet;
44340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport java.util.Set;
45340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
46340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
47340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkpublic class TunerServiceImpl extends TunerService {
48340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
49340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private static final String TUNER_VERSION = "sysui_tuner_version";
50340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
51248c44b915c6c11b76d6387311ac63f208d6196bJason Monk    private static final int CURRENT_TUNER_VERSION = 4;
52248c44b915c6c11b76d6387311ac63f208d6196bJason Monk
53248c44b915c6c11b76d6387311ac63f208d6196bJason Monk    // Things that use the tunable infrastructure but are now real user settings and
54248c44b915c6c11b76d6387311ac63f208d6196bJason Monk    // shouldn't be reset with tuner settings.
55248c44b915c6c11b76d6387311ac63f208d6196bJason Monk    private static final String[] RESET_BLACKLIST = new String[] {
56248c44b915c6c11b76d6387311ac63f208d6196bJason Monk            QSTileHost.TILES_SETTING,
57960625ae9e6add5c8d090ad76c672122e42f7277Jason Monk            Settings.Secure.DOZE_ALWAYS_ON
58248c44b915c6c11b76d6387311ac63f208d6196bJason Monk    };
59340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
60340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private final Observer mObserver = new Observer();
61340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    // Map of Uris we listen on to their settings keys.
62340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private final ArrayMap<Uri, String> mListeningUris = new ArrayMap<>();
63340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    // Map of settings keys to the listener.
64340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private final HashMap<String, Set<Tunable>> mTunableLookup = new HashMap<>();
65340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    // Set of all tunables, used for leak detection.
66340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private final HashSet<Tunable> mTunables = LeakDetector.ENABLED ? new HashSet<>() : null;
67340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private final Context mContext;
68340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
69340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private ContentResolver mContentResolver;
70340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private int mCurrentUser;
71340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private CurrentUserTracker mUserTracker;
72340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
73340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    public TunerServiceImpl(Context context) {
74340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        mContext = context;
75340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        mContentResolver = mContext.getContentResolver();
76340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
77340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        for (UserInfo user : UserManager.get(mContext).getUsers()) {
78340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            mCurrentUser = user.getUserHandle().getIdentifier();
79340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            if (getValue(TUNER_VERSION, 0) != CURRENT_TUNER_VERSION) {
80340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk                upgradeTuner(getValue(TUNER_VERSION, 0), CURRENT_TUNER_VERSION);
81340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            }
82340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }
83340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
84340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        mCurrentUser = ActivityManager.getCurrentUser();
85340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        mUserTracker = new CurrentUserTracker(mContext) {
86340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            @Override
87340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            public void onUserSwitched(int newUserId) {
88340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk                mCurrentUser = newUserId;
89340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk                reloadAll();
90340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk                reregisterAll();
91340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            }
92340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        };
93340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        mUserTracker.startTracking();
94340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
95340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
96340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    @Override
97340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    public void destroy() {
98340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        mUserTracker.stopTracking();
99340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
100340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
101340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private void upgradeTuner(int oldVersion, int newVersion) {
102340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        if (oldVersion < 1) {
103340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            String blacklistStr = getValue(StatusBarIconController.ICON_BLACKLIST);
104340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            if (blacklistStr != null) {
105340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk                ArraySet<String> iconBlacklist =
106340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk                        StatusBarIconController.getIconBlacklist(blacklistStr);
107340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
108340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk                iconBlacklist.add("rotate");
109340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk                iconBlacklist.add("headset");
110340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
111340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk                Settings.Secure.putStringForUser(mContentResolver,
112340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk                        StatusBarIconController.ICON_BLACKLIST,
113340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk                        TextUtils.join(",", iconBlacklist), mCurrentUser);
114340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            }
115340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }
116f87aba0a8392c9d9ec6e2e1dcfcaf61c6f2cb29eJason Monk        if (oldVersion < 2) {
117f87aba0a8392c9d9ec6e2e1dcfcaf61c6f2cb29eJason Monk            setTunerEnabled(mContext, false);
118f87aba0a8392c9d9ec6e2e1dcfcaf61c6f2cb29eJason Monk        }
119248c44b915c6c11b76d6387311ac63f208d6196bJason Monk        // 3 Removed because of a revert.
120248c44b915c6c11b76d6387311ac63f208d6196bJason Monk        if (oldVersion < 4) {
121248c44b915c6c11b76d6387311ac63f208d6196bJason Monk            // Delay this so that we can wait for everything to be registered first.
122248c44b915c6c11b76d6387311ac63f208d6196bJason Monk            new Handler(Dependency.get(Dependency.BG_LOOPER)).postDelayed(() -> clearAll(), 5000);
123248c44b915c6c11b76d6387311ac63f208d6196bJason Monk        }
124340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        setValue(TUNER_VERSION, newVersion);
125340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
126340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
127340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    @Override
128340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    public String getValue(String setting) {
129340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        return Settings.Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
130340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
131340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
132340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    @Override
133340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    public void setValue(String setting, String value) {
134340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk         Settings.Secure.putStringForUser(mContentResolver, setting, value, mCurrentUser);
135340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
136340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
137340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    @Override
138340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    public int getValue(String setting, int def) {
139340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        return Settings.Secure.getIntForUser(mContentResolver, setting, def, mCurrentUser);
140340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
141340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
142340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    @Override
143340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    public String getValue(String setting, String def) {
144340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        String ret = Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
145340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        if (ret == null) return def;
146340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        return ret;
147340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
148340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
149340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    @Override
150340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    public void setValue(String setting, int value) {
151340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk         Settings.Secure.putIntForUser(mContentResolver, setting, value, mCurrentUser);
152340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
153340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
154340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    @Override
155340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    public void addTunable(Tunable tunable, String... keys) {
156340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        for (String key : keys) {
157340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            addTunable(tunable, key);
158340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }
159340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
160340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
161340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private void addTunable(Tunable tunable, String key) {
162340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        if (!mTunableLookup.containsKey(key)) {
163340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            mTunableLookup.put(key, new ArraySet<Tunable>());
164340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }
165340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        mTunableLookup.get(key).add(tunable);
166340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        if (LeakDetector.ENABLED) {
167340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            mTunables.add(tunable);
168340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            Dependency.get(LeakDetector.class).trackCollection(mTunables, "TunerService.mTunables");
169340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }
170340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        Uri uri = Settings.Secure.getUriFor(key);
171340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        if (!mListeningUris.containsKey(uri)) {
172340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            mListeningUris.put(uri, key);
173340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
174340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }
175340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        // Send the first state.
176340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
177340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        tunable.onTuningChanged(key, value);
178340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
179340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
180340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    @Override
181340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    public void removeTunable(Tunable tunable) {
182340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        for (Set<Tunable> list : mTunableLookup.values()) {
183340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            list.remove(tunable);
184340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }
185340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        if (LeakDetector.ENABLED) {
186340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            mTunables.remove(tunable);
187340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }
188340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
189340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
190340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    protected void reregisterAll() {
191340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        if (mListeningUris.size() == 0) {
192340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            return;
193340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }
194340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        mContentResolver.unregisterContentObserver(mObserver);
195340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        for (Uri uri : mListeningUris.keySet()) {
196340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
197340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }
198340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
199340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
200340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private void reloadSetting(Uri uri) {
201340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        String key = mListeningUris.get(uri);
202340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        Set<Tunable> tunables = mTunableLookup.get(key);
203340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        if (tunables == null) {
204340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            return;
205340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }
206340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
207340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        for (Tunable tunable : tunables) {
208340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            tunable.onTuningChanged(key, value);
209340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }
210340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
211340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
212340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private void reloadAll() {
213340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        for (String key : mTunableLookup.keySet()) {
214340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            String value = Settings.Secure.getStringForUser(mContentResolver, key,
215340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk                    mCurrentUser);
216340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            for (Tunable tunable : mTunableLookup.get(key)) {
217340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk                tunable.onTuningChanged(key, value);
218340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            }
219340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }
220340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
221340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
222340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    @Override
223340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    public void clearAll() {
224340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        // A couple special cases.
225340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null);
226340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        Intent intent = new Intent(DemoMode.ACTION_DEMO);
227340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT);
228340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        mContext.sendBroadcast(intent);
229340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
230340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        for (String key : mTunableLookup.keySet()) {
231248c44b915c6c11b76d6387311ac63f208d6196bJason Monk            if (ArrayUtils.contains(RESET_BLACKLIST, key)) {
232248c44b915c6c11b76d6387311ac63f208d6196bJason Monk                continue;
233248c44b915c6c11b76d6387311ac63f208d6196bJason Monk            }
234340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            Settings.Secure.putString(mContentResolver, key, null);
235340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }
236340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
237340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
238340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private class Observer extends ContentObserver {
239340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        public Observer() {
240340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            super(new Handler(Looper.getMainLooper()));
241340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }
242340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
243340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        @Override
244340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        public void onChange(boolean selfChange, Uri uri, int userId) {
245340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            if (userId == ActivityManager.getCurrentUser()) {
246340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk                reloadSetting(uri);
247340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            }
248340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }
249340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
250340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk}
251