blob: abaa628145d6a6ca21458eb764b891238aaed655 [file] [log] [blame]
Jason Monk5e745172015-06-02 19:14:44 -04001/*
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;
Jason Monk431ad732015-07-16 08:58:15 -040019import android.content.BroadcastReceiver;
20import android.content.ComponentName;
Jason Monk5e745172015-06-02 19:14:44 -040021import android.content.ContentResolver;
22import android.content.Context;
Jason Monk431ad732015-07-16 08:58:15 -040023import android.content.DialogInterface;
24import android.content.DialogInterface.OnClickListener;
25import android.content.Intent;
26import android.content.pm.PackageManager;
Jason Monk540542b2015-08-11 14:18:14 -040027import android.content.pm.PackageManager.NameNotFoundException;
Jason Monk5e745172015-06-02 19:14:44 -040028import android.database.ContentObserver;
29import android.net.Uri;
30import android.os.Handler;
31import android.os.Looper;
Jason Monk540542b2015-08-11 14:18:14 -040032import android.os.UserHandle;
Jason Monk5e745172015-06-02 19:14:44 -040033import android.provider.Settings;
34import android.util.ArrayMap;
Jason Monk51c444b2016-01-06 16:32:29 -050035import android.util.ArraySet;
Jason Monkabe19742015-09-29 09:47:06 -040036import com.android.systemui.BatteryMeterDrawable;
Jason Monk431ad732015-07-16 08:58:15 -040037import com.android.systemui.DemoMode;
38import com.android.systemui.R;
Jason Monk5e745172015-06-02 19:14:44 -040039import com.android.systemui.SystemUI;
40import com.android.systemui.SystemUIApplication;
41import com.android.systemui.settings.CurrentUserTracker;
Jason Monk431ad732015-07-16 08:58:15 -040042import com.android.systemui.statusbar.phone.SystemUIDialog;
Jason Monk5e745172015-06-02 19:14:44 -040043
Jason Monk5e745172015-06-02 19:14:44 -040044import java.util.HashMap;
Jason Monk51c444b2016-01-06 16:32:29 -050045import java.util.Set;
Jason Monk5e745172015-06-02 19:14:44 -040046
47
48public class TunerService extends SystemUI {
49
Jason Monk431ad732015-07-16 08:58:15 -040050 public static final String ACTION_CLEAR = "com.android.systemui.action.CLEAR_TUNER";
51
Jason Monk5e745172015-06-02 19:14:44 -040052 private final Observer mObserver = new Observer();
53 // Map of Uris we listen on to their settings keys.
54 private final ArrayMap<Uri, String> mListeningUris = new ArrayMap<>();
55 // Map of settings keys to the listener.
Jason Monk51c444b2016-01-06 16:32:29 -050056 private final HashMap<String, Set<Tunable>> mTunableLookup = new HashMap<>();
Jason Monk5e745172015-06-02 19:14:44 -040057
58 private ContentResolver mContentResolver;
59 private int mCurrentUser;
60 private CurrentUserTracker mUserTracker;
61
62 @Override
63 public void start() {
64 mContentResolver = mContext.getContentResolver();
65 putComponent(TunerService.class, this);
66
67 mCurrentUser = ActivityManager.getCurrentUser();
68 mUserTracker = new CurrentUserTracker(mContext) {
69 @Override
70 public void onUserSwitched(int newUserId) {
71 mCurrentUser = newUserId;
72 reloadAll();
73 reregisterAll();
74 }
75 };
76 mUserTracker.startTracking();
77 }
78
Jason Monkf0c6f642016-01-20 22:24:50 -050079 public String getValue(String setting) {
80 return Settings.Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
81 }
82
83 public void setValue(String setting, String value) {
84 Settings.Secure.putStringForUser(mContentResolver, setting, value, mCurrentUser);
85 }
86
87 public int getValue(String setting, int def) {
88 return Settings.Secure.getIntForUser(mContentResolver, setting, def, mCurrentUser);
89 }
90
91 public void setValue(String setting, int value) {
92 Settings.Secure.putIntForUser(mContentResolver, setting, value, mCurrentUser);
93 }
94
Jason Monk5e745172015-06-02 19:14:44 -040095 public void addTunable(Tunable tunable, String... keys) {
96 for (String key : keys) {
97 addTunable(tunable, key);
98 }
99 }
100
101 private void addTunable(Tunable tunable, String key) {
102 if (!mTunableLookup.containsKey(key)) {
Jason Monk51c444b2016-01-06 16:32:29 -0500103 mTunableLookup.put(key, new ArraySet<Tunable>());
Jason Monk5e745172015-06-02 19:14:44 -0400104 }
105 mTunableLookup.get(key).add(tunable);
106 Uri uri = Settings.Secure.getUriFor(key);
107 if (!mListeningUris.containsKey(uri)) {
108 mListeningUris.put(uri, key);
109 mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
110 }
111 // Send the first state.
112 String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
113 tunable.onTuningChanged(key, value);
114 }
115
116 public void removeTunable(Tunable tunable) {
Jason Monk51c444b2016-01-06 16:32:29 -0500117 for (Set<Tunable> list : mTunableLookup.values()) {
Jason Monk5e745172015-06-02 19:14:44 -0400118 list.remove(tunable);
119 }
120 }
121
122 protected void reregisterAll() {
123 if (mListeningUris.size() == 0) {
124 return;
125 }
126 mContentResolver.unregisterContentObserver(mObserver);
127 for (Uri uri : mListeningUris.keySet()) {
128 mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
129 }
130 }
131
132 public void reloadSetting(Uri uri) {
133 String key = mListeningUris.get(uri);
Jason Monk51c444b2016-01-06 16:32:29 -0500134 Set<Tunable> tunables = mTunableLookup.get(key);
Jason Monk72def0d2015-11-10 16:03:06 -0500135 if (tunables == null) {
136 return;
137 }
Jason Monk5e745172015-06-02 19:14:44 -0400138 String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
Jason Monk72def0d2015-11-10 16:03:06 -0500139 for (Tunable tunable : tunables) {
Jason Monk5e745172015-06-02 19:14:44 -0400140 tunable.onTuningChanged(key, value);
141 }
142 }
143
144 private void reloadAll() {
145 for (String key : mTunableLookup.keySet()) {
146 String value = Settings.Secure.getStringForUser(mContentResolver, key,
147 mCurrentUser);
148 for (Tunable tunable : mTunableLookup.get(key)) {
149 tunable.onTuningChanged(key, value);
150 }
151 }
152 }
153
Jason Monk431ad732015-07-16 08:58:15 -0400154 public void clearAll() {
155 // A couple special cases.
156 Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null);
Jason Monkabe19742015-09-29 09:47:06 -0400157 Settings.System.putString(mContentResolver, BatteryMeterDrawable.SHOW_PERCENT_SETTING, null);
Jason Monk431ad732015-07-16 08:58:15 -0400158 Intent intent = new Intent(DemoMode.ACTION_DEMO);
159 intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT);
160 mContext.sendBroadcast(intent);
161
162 for (String key : mTunableLookup.keySet()) {
163 Settings.Secure.putString(mContentResolver, key, null);
164 }
165 }
166
Jason Monk5e745172015-06-02 19:14:44 -0400167 // Only used in other processes, such as the tuner.
168 private static TunerService sInstance;
169
170 public static TunerService get(Context context) {
Jason Monkd5a204f2015-12-21 08:50:01 -0500171 TunerService service = null;
172 if (context.getApplicationContext() instanceof SystemUIApplication) {
173 SystemUIApplication sysUi = (SystemUIApplication) context.getApplicationContext();
174 service = sysUi.getComponent(TunerService.class);
175 }
Jason Monk5e745172015-06-02 19:14:44 -0400176 if (service == null) {
177 // Can't get it as a component, must in the tuner, lets just create one for now.
178 return getStaticService(context);
179 }
180 return service;
181 }
182
183 private static TunerService getStaticService(Context context) {
184 if (sInstance == null) {
185 sInstance = new TunerService();
186 sInstance.mContext = context.getApplicationContext();
187 sInstance.mComponents = new HashMap<>();
188 sInstance.start();
189 }
190 return sInstance;
191 }
192
Jason Monk431ad732015-07-16 08:58:15 -0400193 public static final void showResetRequest(final Context context, final Runnable onDisabled) {
194 SystemUIDialog dialog = new SystemUIDialog(context);
Jason Monk540542b2015-08-11 14:18:14 -0400195 dialog.setShowForAllUsers(true);
Jason Monk431ad732015-07-16 08:58:15 -0400196 dialog.setMessage(R.string.remove_from_settings_prompt);
197 dialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.cancel),
198 (OnClickListener) null);
199 dialog.setButton(DialogInterface.BUTTON_POSITIVE,
200 context.getString(R.string.guest_exit_guest_dialog_remove), new OnClickListener() {
201 @Override
202 public void onClick(DialogInterface dialog, int which) {
203 // Tell the tuner (in main SysUI process) to clear all its settings.
204 context.sendBroadcast(new Intent(TunerService.ACTION_CLEAR));
205 // Disable access to tuner.
206 TunerService.setTunerEnabled(context, false);
207 // Make them sit through the warning dialog again.
208 Settings.Secure.putInt(context.getContentResolver(),
209 TunerFragment.SETTING_SEEN_TUNER_WARNING, 0);
210 if (onDisabled != null) {
211 onDisabled.run();
212 }
213 }
214 });
215 dialog.show();
216 }
217
218 public static final void setTunerEnabled(Context context, boolean enabled) {
Jason Monk540542b2015-08-11 14:18:14 -0400219 userContext(context).getPackageManager().setComponentEnabledSetting(
Jason Monk431ad732015-07-16 08:58:15 -0400220 new ComponentName(context, TunerActivity.class),
221 enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
222 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
223 PackageManager.DONT_KILL_APP);
224 }
225
226 public static final boolean isTunerEnabled(Context context) {
Jason Monk540542b2015-08-11 14:18:14 -0400227 return userContext(context).getPackageManager().getComponentEnabledSetting(
Jason Monk431ad732015-07-16 08:58:15 -0400228 new ComponentName(context, TunerActivity.class))
229 == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
230 }
231
Jason Monk540542b2015-08-11 14:18:14 -0400232 private static Context userContext(Context context) {
233 try {
234 return context.createPackageContextAsUser(context.getPackageName(), 0,
235 new UserHandle(ActivityManager.getCurrentUser()));
236 } catch (NameNotFoundException e) {
237 return context;
238 }
239 }
240
Jason Monk5e745172015-06-02 19:14:44 -0400241 private class Observer extends ContentObserver {
242 public Observer() {
243 super(new Handler(Looper.getMainLooper()));
244 }
245
246 @Override
247 public void onChange(boolean selfChange, Uri uri, int userId) {
248 if (userId == ActivityManager.getCurrentUser()) {
249 reloadSetting(uri);
250 }
251 }
252 }
253
254 public interface Tunable {
255 void onTuningChanged(String key, String newValue);
256 }
Jason Monk431ad732015-07-16 08:58:15 -0400257
258 public static class ClearReceiver extends BroadcastReceiver {
259 @Override
260 public void onReceive(Context context, Intent intent) {
261 if (ACTION_CLEAR.equals(intent.getAction())) {
262 get(context).clearAll();
263 }
264 }
265 }
Jason Monk5e745172015-06-02 19:14:44 -0400266}