Home | History | Annotate | Download | only in tuner
      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 
     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
     97     public void destroy() {
     98         mUserTracker.stopTracking();
     99     }
    100 
    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
    128     public String getValue(String setting) {
    129         return Settings.Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
    130     }
    131 
    132     @Override
    133     public void setValue(String setting, String value) {
    134          Settings.Secure.putStringForUser(mContentResolver, setting, value, mCurrentUser);
    135     }
    136 
    137     @Override
    138     public int getValue(String setting, int def) {
    139         return Settings.Secure.getIntForUser(mContentResolver, setting, def, mCurrentUser);
    140     }
    141 
    142     @Override
    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
    150     public void setValue(String setting, int value) {
    151          Settings.Secure.putIntForUser(mContentResolver, setting, value, mCurrentUser);
    152     }
    153 
    154     @Override
    155     public void addTunable(Tunable tunable, String... keys) {
    156         for (String key : keys) {
    157             addTunable(tunable, key);
    158         }
    159     }
    160 
    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
    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 
    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 
    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 
    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
    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 {
    239         public Observer() {
    240             super(new Handler(Looper.getMainLooper()));
    241         }
    242 
    243         @Override
    244         public void onChange(boolean selfChange, Uri uri, int userId) {
    245             if (userId == ActivityManager.getCurrentUser()) {
    246                 reloadSetting(uri);
    247             }
    248         }
    249     }
    250 }
    251