TunerService.java revision de850bbcaa61c1874b803f2086443febbafd81a4
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 */ 16package com.android.systemui.tuner; 17 18import android.app.ActivityManager; 19import android.content.BroadcastReceiver; 20import android.content.ComponentName; 21import android.content.ContentResolver; 22import android.content.Context; 23import android.content.DialogInterface; 24import android.content.DialogInterface.OnClickListener; 25import android.content.Intent; 26import android.content.pm.PackageManager; 27import android.content.pm.PackageManager.NameNotFoundException; 28import android.content.pm.UserInfo; 29import android.database.ContentObserver; 30import android.net.Uri; 31import android.os.Handler; 32import android.os.Looper; 33import android.os.UserHandle; 34import android.os.UserManager; 35import android.provider.Settings; 36import android.provider.Settings.Secure; 37import android.text.TextUtils; 38import android.util.ArrayMap; 39import android.util.ArraySet; 40 41import com.android.systemui.BatteryMeterDrawable; 42import com.android.systemui.DemoMode; 43import com.android.systemui.Dependency; 44import com.android.systemui.R; 45import com.android.systemui.SystemUI; 46import com.android.systemui.SystemUIApplication; 47import com.android.systemui.settings.CurrentUserTracker; 48import com.android.systemui.statusbar.phone.StatusBarIconController; 49import com.android.systemui.statusbar.phone.SystemUIDialog; 50 51import java.util.HashMap; 52import java.util.Set; 53 54 55public class TunerService { 56 57 public static final String ACTION_CLEAR = "com.android.systemui.action.CLEAR_TUNER"; 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 private final Context mContext; 69 70 private ContentResolver mContentResolver; 71 private int mCurrentUser; 72 private CurrentUserTracker mUserTracker; 73 74 public TunerService(Context context) { 75 mContext = context; 76 mContentResolver = mContext.getContentResolver(); 77 78 for (UserInfo user : UserManager.get(mContext).getUsers()) { 79 mCurrentUser = user.getUserHandle().getIdentifier(); 80 if (getValue(TUNER_VERSION, 0) != CURRENT_TUNER_VERSION) { 81 upgradeTuner(getValue(TUNER_VERSION, 0), CURRENT_TUNER_VERSION); 82 } 83 } 84 85 mCurrentUser = ActivityManager.getCurrentUser(); 86 mUserTracker = new CurrentUserTracker(mContext) { 87 @Override 88 public void onUserSwitched(int newUserId) { 89 mCurrentUser = newUserId; 90 reloadAll(); 91 reregisterAll(); 92 } 93 }; 94 mUserTracker.startTracking(); 95 } 96 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 setValue(TUNER_VERSION, newVersion); 117 } 118 119 public String getValue(String setting) { 120 return Settings.Secure.getStringForUser(mContentResolver, setting, mCurrentUser); 121 } 122 123 public void setValue(String setting, String value) { 124 Settings.Secure.putStringForUser(mContentResolver, setting, value, mCurrentUser); 125 } 126 127 public int getValue(String setting, int def) { 128 return Settings.Secure.getIntForUser(mContentResolver, setting, def, mCurrentUser); 129 } 130 131 public String getValue(String setting, String def) { 132 String ret = Secure.getStringForUser(mContentResolver, setting, mCurrentUser); 133 if (ret == null) return def; 134 return ret; 135 } 136 137 public void setValue(String setting, int value) { 138 Settings.Secure.putIntForUser(mContentResolver, setting, value, mCurrentUser); 139 } 140 141 public void addTunable(Tunable tunable, String... keys) { 142 for (String key : keys) { 143 addTunable(tunable, key); 144 } 145 } 146 147 private void addTunable(Tunable tunable, String key) { 148 if (!mTunableLookup.containsKey(key)) { 149 mTunableLookup.put(key, new ArraySet<Tunable>()); 150 } 151 mTunableLookup.get(key).add(tunable); 152 Uri uri = Settings.Secure.getUriFor(key); 153 if (!mListeningUris.containsKey(uri)) { 154 mListeningUris.put(uri, key); 155 mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser); 156 } 157 // Send the first state. 158 String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser); 159 tunable.onTuningChanged(key, value); 160 } 161 162 public void removeTunable(Tunable tunable) { 163 for (Set<Tunable> list : mTunableLookup.values()) { 164 list.remove(tunable); 165 } 166 } 167 168 protected void reregisterAll() { 169 if (mListeningUris.size() == 0) { 170 return; 171 } 172 mContentResolver.unregisterContentObserver(mObserver); 173 for (Uri uri : mListeningUris.keySet()) { 174 mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser); 175 } 176 } 177 178 public void reloadSetting(Uri uri) { 179 String key = mListeningUris.get(uri); 180 Set<Tunable> tunables = mTunableLookup.get(key); 181 if (tunables == null) { 182 return; 183 } 184 String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser); 185 for (Tunable tunable : tunables) { 186 tunable.onTuningChanged(key, value); 187 } 188 } 189 190 private void reloadAll() { 191 for (String key : mTunableLookup.keySet()) { 192 String value = Settings.Secure.getStringForUser(mContentResolver, key, 193 mCurrentUser); 194 for (Tunable tunable : mTunableLookup.get(key)) { 195 tunable.onTuningChanged(key, value); 196 } 197 } 198 } 199 200 public void clearAll() { 201 // A couple special cases. 202 Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null); 203 Settings.System.putString(mContentResolver, BatteryMeterDrawable.SHOW_PERCENT_SETTING, null); 204 Intent intent = new Intent(DemoMode.ACTION_DEMO); 205 intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT); 206 mContext.sendBroadcast(intent); 207 208 for (String key : mTunableLookup.keySet()) { 209 Settings.Secure.putString(mContentResolver, key, null); 210 } 211 } 212 213 public static final void showResetRequest(final Context context, final Runnable onDisabled) { 214 SystemUIDialog dialog = new SystemUIDialog(context); 215 dialog.setShowForAllUsers(true); 216 dialog.setMessage(R.string.remove_from_settings_prompt); 217 dialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.cancel), 218 (OnClickListener) null); 219 dialog.setButton(DialogInterface.BUTTON_POSITIVE, 220 context.getString(R.string.guest_exit_guest_dialog_remove), new OnClickListener() { 221 @Override 222 public void onClick(DialogInterface dialog, int which) { 223 // Tell the tuner (in main SysUI process) to clear all its settings. 224 context.sendBroadcast(new Intent(TunerService.ACTION_CLEAR)); 225 // Disable access to tuner. 226 TunerService.setTunerEnabled(context, false); 227 // Make them sit through the warning dialog again. 228 Settings.Secure.putInt(context.getContentResolver(), 229 TunerFragment.SETTING_SEEN_TUNER_WARNING, 0); 230 if (onDisabled != null) { 231 onDisabled.run(); 232 } 233 } 234 }); 235 dialog.show(); 236 } 237 238 public static final void setTunerEnabled(Context context, boolean enabled) { 239 userContext(context).getPackageManager().setComponentEnabledSetting( 240 new ComponentName(context, TunerActivity.class), 241 enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED 242 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 243 PackageManager.DONT_KILL_APP); 244 245 userContext(context).getPackageManager().setComponentEnabledSetting( 246 new ComponentName(context, TunerActivity.ACTIVITY_ALIAS_NAME), 247 enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED 248 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 249 PackageManager.DONT_KILL_APP); 250 } 251 252 public static final boolean isTunerEnabled(Context context) { 253 return userContext(context).getPackageManager().getComponentEnabledSetting( 254 new ComponentName(context, TunerActivity.class)) 255 == PackageManager.COMPONENT_ENABLED_STATE_ENABLED; 256 } 257 258 private static Context userContext(Context context) { 259 try { 260 return context.createPackageContextAsUser(context.getPackageName(), 0, 261 new UserHandle(ActivityManager.getCurrentUser())); 262 } catch (NameNotFoundException e) { 263 return context; 264 } 265 } 266 267 private class Observer extends ContentObserver { 268 public Observer() { 269 super(new Handler(Looper.getMainLooper())); 270 } 271 272 @Override 273 public void onChange(boolean selfChange, Uri uri, int userId) { 274 if (userId == ActivityManager.getCurrentUser()) { 275 reloadSetting(uri); 276 } 277 } 278 } 279 280 public interface Tunable { 281 void onTuningChanged(String key, String newValue); 282 } 283 284 public static class ClearReceiver extends BroadcastReceiver { 285 @Override 286 public void onReceive(Context context, Intent intent) { 287 if (ACTION_CLEAR.equals(intent.getAction())) { 288 Dependency.get(TunerService.class).clearAll(); 289 } 290 } 291 } 292} 293