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.database.ContentObserver; 29 import android.net.Uri; 30 import android.os.Handler; 31 import android.os.Looper; 32 import android.os.UserHandle; 33 import android.provider.Settings; 34 import android.util.ArrayMap; 35 36 import com.android.systemui.BatteryMeterView; 37 import com.android.systemui.DemoMode; 38 import com.android.systemui.R; 39 import com.android.systemui.SystemUI; 40 import com.android.systemui.SystemUIApplication; 41 import com.android.systemui.settings.CurrentUserTracker; 42 import com.android.systemui.statusbar.phone.SystemUIDialog; 43 44 import java.util.ArrayList; 45 import java.util.HashMap; 46 import java.util.List; 47 48 49 public class TunerService extends SystemUI { 50 51 public static final String ACTION_CLEAR = "com.android.systemui.action.CLEAR_TUNER"; 52 53 private final Observer mObserver = new Observer(); 54 // Map of Uris we listen on to their settings keys. 55 private final ArrayMap<Uri, String> mListeningUris = new ArrayMap<>(); 56 // Map of settings keys to the listener. 57 private final HashMap<String, List<Tunable>> mTunableLookup = new HashMap<>(); 58 59 private ContentResolver mContentResolver; 60 private int mCurrentUser; 61 private CurrentUserTracker mUserTracker; 62 63 @Override start()64 public void start() { 65 mContentResolver = mContext.getContentResolver(); 66 putComponent(TunerService.class, this); 67 68 mCurrentUser = ActivityManager.getCurrentUser(); 69 mUserTracker = new CurrentUserTracker(mContext) { 70 @Override 71 public void onUserSwitched(int newUserId) { 72 mCurrentUser = newUserId; 73 reloadAll(); 74 reregisterAll(); 75 } 76 }; 77 mUserTracker.startTracking(); 78 } 79 addTunable(Tunable tunable, String... keys)80 public void addTunable(Tunable tunable, String... keys) { 81 for (String key : keys) { 82 addTunable(tunable, key); 83 } 84 } 85 addTunable(Tunable tunable, String key)86 private void addTunable(Tunable tunable, String key) { 87 if (!mTunableLookup.containsKey(key)) { 88 mTunableLookup.put(key, new ArrayList<Tunable>()); 89 } 90 mTunableLookup.get(key).add(tunable); 91 Uri uri = Settings.Secure.getUriFor(key); 92 if (!mListeningUris.containsKey(uri)) { 93 mListeningUris.put(uri, key); 94 mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser); 95 } 96 // Send the first state. 97 String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser); 98 tunable.onTuningChanged(key, value); 99 } 100 removeTunable(Tunable tunable)101 public void removeTunable(Tunable tunable) { 102 for (List<Tunable> list : mTunableLookup.values()) { 103 list.remove(tunable); 104 } 105 } 106 reregisterAll()107 protected void reregisterAll() { 108 if (mListeningUris.size() == 0) { 109 return; 110 } 111 mContentResolver.unregisterContentObserver(mObserver); 112 for (Uri uri : mListeningUris.keySet()) { 113 mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser); 114 } 115 } 116 reloadSetting(Uri uri)117 public void reloadSetting(Uri uri) { 118 String key = mListeningUris.get(uri); 119 String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser); 120 for (Tunable tunable : mTunableLookup.get(key)) { 121 tunable.onTuningChanged(key, value); 122 } 123 } 124 reloadAll()125 private void reloadAll() { 126 for (String key : mTunableLookup.keySet()) { 127 String value = Settings.Secure.getStringForUser(mContentResolver, key, 128 mCurrentUser); 129 for (Tunable tunable : mTunableLookup.get(key)) { 130 tunable.onTuningChanged(key, value); 131 } 132 } 133 } 134 clearAll()135 public void clearAll() { 136 // A couple special cases. 137 Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null); 138 Settings.System.putString(mContentResolver, BatteryMeterView.SHOW_PERCENT_SETTING, null); 139 Intent intent = new Intent(DemoMode.ACTION_DEMO); 140 intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT); 141 mContext.sendBroadcast(intent); 142 143 for (String key : mTunableLookup.keySet()) { 144 Settings.Secure.putString(mContentResolver, key, null); 145 } 146 } 147 148 // Only used in other processes, such as the tuner. 149 private static TunerService sInstance; 150 get(Context context)151 public static TunerService get(Context context) { 152 SystemUIApplication sysUi = (SystemUIApplication) context.getApplicationContext(); 153 TunerService service = sysUi.getComponent(TunerService.class); 154 if (service == null) { 155 // Can't get it as a component, must in the tuner, lets just create one for now. 156 return getStaticService(context); 157 } 158 return service; 159 } 160 getStaticService(Context context)161 private static TunerService getStaticService(Context context) { 162 if (sInstance == null) { 163 sInstance = new TunerService(); 164 sInstance.mContext = context.getApplicationContext(); 165 sInstance.mComponents = new HashMap<>(); 166 sInstance.start(); 167 } 168 return sInstance; 169 } 170 showResetRequest(final Context context, final Runnable onDisabled)171 public static final void showResetRequest(final Context context, final Runnable onDisabled) { 172 SystemUIDialog dialog = new SystemUIDialog(context); 173 dialog.setShowForAllUsers(true); 174 dialog.setMessage(R.string.remove_from_settings_prompt); 175 dialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.cancel), 176 (OnClickListener) null); 177 dialog.setButton(DialogInterface.BUTTON_POSITIVE, 178 context.getString(R.string.guest_exit_guest_dialog_remove), new OnClickListener() { 179 @Override 180 public void onClick(DialogInterface dialog, int which) { 181 // Tell the tuner (in main SysUI process) to clear all its settings. 182 context.sendBroadcast(new Intent(TunerService.ACTION_CLEAR)); 183 // Disable access to tuner. 184 TunerService.setTunerEnabled(context, false); 185 // Make them sit through the warning dialog again. 186 Settings.Secure.putInt(context.getContentResolver(), 187 TunerFragment.SETTING_SEEN_TUNER_WARNING, 0); 188 if (onDisabled != null) { 189 onDisabled.run(); 190 } 191 } 192 }); 193 dialog.show(); 194 } 195 setTunerEnabled(Context context, boolean enabled)196 public static final void setTunerEnabled(Context context, boolean enabled) { 197 userContext(context).getPackageManager().setComponentEnabledSetting( 198 new ComponentName(context, TunerActivity.class), 199 enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED 200 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 201 PackageManager.DONT_KILL_APP); 202 } 203 isTunerEnabled(Context context)204 public static final boolean isTunerEnabled(Context context) { 205 return userContext(context).getPackageManager().getComponentEnabledSetting( 206 new ComponentName(context, TunerActivity.class)) 207 == PackageManager.COMPONENT_ENABLED_STATE_ENABLED; 208 } 209 userContext(Context context)210 private static Context userContext(Context context) { 211 try { 212 return context.createPackageContextAsUser(context.getPackageName(), 0, 213 new UserHandle(ActivityManager.getCurrentUser())); 214 } catch (NameNotFoundException e) { 215 return context; 216 } 217 } 218 219 private class Observer extends ContentObserver { Observer()220 public Observer() { 221 super(new Handler(Looper.getMainLooper())); 222 } 223 224 @Override onChange(boolean selfChange, Uri uri, int userId)225 public void onChange(boolean selfChange, Uri uri, int userId) { 226 if (userId == ActivityManager.getCurrentUser()) { 227 reloadSetting(uri); 228 } 229 } 230 } 231 232 public interface Tunable { onTuningChanged(String key, String newValue)233 void onTuningChanged(String key, String newValue); 234 } 235 236 public static class ClearReceiver extends BroadcastReceiver { 237 @Override onReceive(Context context, Intent intent)238 public void onReceive(Context context, Intent intent) { 239 if (ACTION_CLEAR.equals(intent.getAction())) { 240 get(context).clearAll(); 241 } 242 } 243 } 244 } 245