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