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.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 
     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
    100     public void destroy() {
    101         mUserTracker.stopTracking();
    102     }
    103 
    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
    123     public String getValue(String setting) {
    124         return Settings.Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
    125     }
    126 
    127     @Override
    128     public void setValue(String setting, String value) {
    129          Settings.Secure.putStringForUser(mContentResolver, setting, value, mCurrentUser);
    130     }
    131 
    132     @Override
    133     public int getValue(String setting, int def) {
    134         return Settings.Secure.getIntForUser(mContentResolver, setting, def, mCurrentUser);
    135     }
    136 
    137     @Override
    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
    145     public void setValue(String setting, int value) {
    146          Settings.Secure.putIntForUser(mContentResolver, setting, value, mCurrentUser);
    147     }
    148 
    149     @Override
    150     public void addTunable(Tunable tunable, String... keys) {
    151         for (String key : keys) {
    152             addTunable(tunable, key);
    153         }
    154     }
    155 
    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
    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 
    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 
    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 
    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
    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 {
    231         public Observer() {
    232             super(new Handler(Looper.getMainLooper()));
    233         }
    234 
    235         @Override
    236         public void onChange(boolean selfChange, Uri uri, int userId) {
    237             if (userId == ActivityManager.getCurrentUser()) {
    238                 reloadSetting(uri);
    239             }
    240         }
    241     }
    242 }
    243