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 
17 package com.android.tv.settings.system.development;
18 
19 import android.Manifest;
20 import android.app.Activity;
21 import android.app.ActivityManager;
22 import android.app.AppOpsManager;
23 import android.app.admin.DevicePolicyManager;
24 import android.app.backup.IBackupManager;
25 import android.content.BroadcastReceiver;
26 import android.content.ComponentName;
27 import android.content.ContentResolver;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.IntentFilter;
31 import android.content.pm.ApplicationInfo;
32 import android.content.pm.PackageManager;
33 import android.content.pm.ResolveInfo;
34 import android.hardware.usb.UsbManager;
35 import android.net.wifi.WifiManager;
36 import android.os.BatteryManager;
37 import android.os.Build;
38 import android.os.Bundle;
39 import android.os.IBinder;
40 import android.os.Parcel;
41 import android.os.RemoteException;
42 import android.os.ServiceManager;
43 import android.os.StrictMode;
44 import android.os.SystemProperties;
45 import android.os.UserManager;
46 import android.provider.Settings;
47 import android.service.persistentdata.PersistentDataBlockManager;
48 import android.sysprop.AdbProperties;
49 import android.sysprop.DisplayProperties;
50 import android.text.TextUtils;
51 import android.util.Log;
52 import android.view.IWindowManager;
53 import android.view.LayoutInflater;
54 import android.view.ThreadedRenderer;
55 import android.view.View;
56 import android.view.ViewGroup;
57 import android.view.accessibility.AccessibilityManager;
58 import android.widget.Toast;
59 
60 import androidx.preference.ListPreference;
61 import androidx.preference.Preference;
62 import androidx.preference.PreferenceGroup;
63 import androidx.preference.PreferenceScreen;
64 import androidx.preference.SwitchPreference;
65 
66 import com.android.internal.app.LocalePicker;
67 import com.android.internal.logging.nano.MetricsProto;
68 import com.android.settingslib.core.ConfirmationDialogController;
69 import com.android.settingslib.development.DevelopmentSettingsEnabler;
70 import com.android.settingslib.development.SystemPropPoker;
71 import com.android.tv.settings.R;
72 import com.android.tv.settings.SettingsPreferenceFragment;
73 import com.android.tv.settings.system.development.audio.AudioDebug;
74 import com.android.tv.settings.system.development.audio.AudioMetrics;
75 import com.android.tv.settings.system.development.audio.AudioReaderException;
76 
77 import java.util.ArrayList;
78 import java.util.HashSet;
79 import java.util.List;
80 import java.util.Optional;
81 
82 /**
83  * Displays preferences for application developers.
84  */
85 public class DevelopmentFragment extends SettingsPreferenceFragment
86         implements Preference.OnPreferenceChangeListener,
87         EnableDevelopmentDialog.Callback, OemUnlockDialog.Callback, AdbDialog.Callback {
88     private static final String TAG = "DevelopmentSettings";
89 
90     private static final String ENABLE_DEVELOPER = "development_settings_enable";
91     private static final String ENABLE_ADB = "enable_adb";
92     private static final String CLEAR_ADB_KEYS = "clear_adb_keys";
93     private static final String ENABLE_TERMINAL = "enable_terminal";
94     private static final String KEEP_SCREEN_ON = "keep_screen_on";
95     private static final String BT_HCI_SNOOP_LOG = "bt_hci_snoop_log";
96     private static final String BTSNOOP_LOG_MODE_PROPERTY = "persist.bluetooth.btsnooplogmode";
97     private static final String ENABLE_OEM_UNLOCK = "oem_unlock_enable";
98     private static final String HDCP_CHECKING_KEY = "hdcp_checking";
99     private static final String HDCP_CHECKING_PROPERTY = "persist.sys.hdcp_checking";
100     private static final String LOCAL_BACKUP_PASSWORD = "local_backup_password";
101     private static final String BUGREPORT = "bugreport";
102     private static final String BUGREPORT_IN_POWER_KEY = "bugreport_in_power";
103     private static final String RUNNING_APPS = "running_apps";
104 
105     private static final String DEBUG_APP_KEY = "debug_app";
106     private static final String WAIT_FOR_DEBUGGER_KEY = "wait_for_debugger";
107     private static final String MOCK_LOCATION_APP_KEY = "mock_location_app";
108     private static final String VERIFY_APPS_OVER_USB_KEY = "verify_apps_over_usb";
109     private static final String DEBUG_VIEW_ATTRIBUTES =  "debug_view_attributes";
110     private static final String FORCE_ALLOW_ON_EXTERNAL_KEY = "force_allow_on_external";
111     private static final String STRICT_MODE_KEY = "strict_mode";
112     private static final String POINTER_LOCATION_KEY = "pointer_location";
113     private static final String SHOW_TOUCHES_KEY = "show_touches";
114     private static final String SHOW_SCREEN_UPDATES_KEY = "show_screen_updates";
115     private static final String DISABLE_OVERLAYS_KEY = "disable_overlays";
116     private static final String SIMULATE_COLOR_SPACE = "simulate_color_space";
117     private static final String USB_AUDIO_KEY = "usb_audio";
118     private static final String RECORD_AUDIO_KEY = "record_audio";
119     private static final String PLAY_RECORDED_AUDIO_KEY = "play_recorded_audio";
120     private static final String SAVE_RECORDED_AUDIO_KEY = "save_recorded_audio";
121     private static final String TIME_TO_START_READ_KEY = "time_to_start_read";
122     private static final String TIME_TO_VALID_AUDIO_KEY = "time_to_valid_audio";
123     private static final String EMPTY_AUDIO_DURATION_KEY = "empty_audio_duration";
124     private static final String FORCE_MSAA_KEY = "force_msaa";
125     private static final String TRACK_FRAME_TIME_KEY = "track_frame_time";
126     private static final String SHOW_NON_RECTANGULAR_CLIP_KEY = "show_non_rect_clip";
127     private static final String SHOW_HW_SCREEN_UPDATES_KEY = "show_hw_screen_udpates";
128     private static final String SHOW_HW_LAYERS_UPDATES_KEY = "show_hw_layers_udpates";
129     private static final String DEBUG_HW_OVERDRAW_KEY = "debug_hw_overdraw";
130     private static final String DEBUG_LAYOUT_KEY = "debug_layout";
131     private static final String FORCE_RTL_LAYOUT_KEY = "force_rtl_layout_all_locales";
132     private static final String WINDOW_ANIMATION_SCALE_KEY = "window_animation_scale";
133     private static final String TRANSITION_ANIMATION_SCALE_KEY = "transition_animation_scale";
134     private static final String ANIMATOR_DURATION_SCALE_KEY = "animator_duration_scale";
135     private static final String OVERLAY_DISPLAY_DEVICES_KEY = "overlay_display_devices";
136     private static final String DEBUG_DEBUGGING_CATEGORY_KEY = "debug_debugging_category";
137 
138     private static final String WIFI_DISPLAY_CERTIFICATION_KEY = "wifi_display_certification";
139     private static final String WIFI_VERBOSE_LOGGING_KEY = "wifi_verbose_logging";
140     private static final String USB_CONFIGURATION_KEY = "select_usb_configuration";
141     private static final String MOBILE_DATA_ALWAYS_ON = "mobile_data_always_on";
142     private static final String KEY_COLOR_MODE = "color_mode";
143     private static final String FORCE_RESIZABLE_KEY = "force_resizable_activities";
144 
145     private static final String INACTIVE_APPS_KEY = "inactive_apps";
146 
147     private static final String OPENGL_TRACES_KEY = "enable_opengl_traces";
148 
149     private static final String IMMEDIATELY_DESTROY_ACTIVITIES_KEY
150             = "immediately_destroy_activities";
151     private static final String APP_PROCESS_LIMIT_KEY = "app_process_limit";
152 
153     private static final String SHOW_ALL_ANRS_KEY = "show_all_anrs";
154 
155     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
156 
157     private static final String TERMINAL_APP_PACKAGE = "com.android.terminal";
158 
159     private static final String KEY_CONVERT_FBE = "convert_to_file_encryption";
160 
161     private static final int RESULT_DEBUG_APP = 1000;
162     private static final int RESULT_MOCK_LOCATION_APP = 1001;
163 
164     private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
165 
166     private static String DEFAULT_LOG_RING_BUFFER_SIZE_IN_BYTES = "262144"; // 256K
167 
168     private static final int[] MOCK_LOCATION_APP_OPS = new int[] {AppOpsManager.OP_MOCK_LOCATION};
169 
170     private static final String STATE_SHOWING_DIALOG_KEY = "showing_dialog_key";
171 
172     private String mPendingDialogKey;
173 
174     private IWindowManager mWindowManager;
175     private IBackupManager mBackupManager;
176     private DevicePolicyManager mDpm;
177     private UserManager mUm;
178     private WifiManager mWifiManager;
179     private ContentResolver mContentResolver;
180 
181     private boolean mLastEnabledState;
182     private boolean mHaveDebugSettings;
183 
184     private SwitchPreference mEnableDeveloper;
185     private SwitchPreference mEnableAdb;
186     private Preference mClearAdbKeys;
187     private SwitchPreference mEnableTerminal;
188     private Preference mBugreport;
189     private SwitchPreference mKeepScreenOn;
190     private ListPreference mBtHciSnoopLog;
191     private SwitchPreference mEnableOemUnlock;
192     private SwitchPreference mDebugViewAttributes;
193     private SwitchPreference mForceAllowOnExternal;
194 
195     private PreferenceScreen mPassword;
196     private String mDebugApp;
197     private Preference mDebugAppPref;
198 
199     private String mMockLocationApp;
200     private Preference mMockLocationAppPref;
201 
202     private SwitchPreference mWaitForDebugger;
203     private SwitchPreference mVerifyAppsOverUsb;
204     private SwitchPreference mWifiDisplayCertification;
205     private SwitchPreference mWifiVerboseLogging;
206     private SwitchPreference mMobileDataAlwaysOn;
207 
208     private SwitchPreference mStrictMode;
209     private SwitchPreference mPointerLocation;
210     private SwitchPreference mShowTouches;
211     private SwitchPreference mShowScreenUpdates;
212     private SwitchPreference mDisableOverlays;
213     private SwitchPreference mForceMsaa;
214     private SwitchPreference mShowHwScreenUpdates;
215     private SwitchPreference mShowHwLayersUpdates;
216     private SwitchPreference mDebugLayout;
217     private SwitchPreference mForceRtlLayout;
218     private ListPreference mDebugHwOverdraw;
219     private LogdSizePreferenceController mLogdSizeController;
220     private LogpersistPreferenceController mLogpersistController;
221     private ListPreference mUsbConfiguration;
222     private ListPreference mTrackFrameTime;
223     private ListPreference mShowNonRectClip;
224     private ListPreference mWindowAnimationScale;
225     private ListPreference mTransitionAnimationScale;
226     private ListPreference mAnimatorDurationScale;
227     private ListPreference mOverlayDisplayDevices;
228     private ListPreference mOpenGLTraces;
229 
230     private ListPreference mSimulateColorSpace;
231 
232     private SwitchPreference mUSBAudio;
233 
234     private SwitchPreference mRecordAudio;
235     private Preference mPlayRecordedAudio;
236     private Preference mSaveAudio;
237     private Preference mTimeToStartRead;
238     private Preference mTimeToValidAudio;
239     private Preference mEmptyAudioDuration;
240 
241     private SwitchPreference mImmediatelyDestroyActivities;
242 
243     private ListPreference mAppProcessLimit;
244 
245     private SwitchPreference mShowAllANRs;
246 
247     private ColorModePreference mColorModePreference;
248 
249     private SwitchPreference mForceResizable;
250 
251     private final ArrayList<Preference> mAllPrefs = new ArrayList<>();
252 
253     private final ArrayList<SwitchPreference> mResetSwitchPrefs
254             = new ArrayList<>();
255 
256     private final HashSet<Preference> mDisabledPrefs = new HashSet<>();
257 
258     private boolean mUnavailable;
259 
260     private AudioDebug mAudioDebug;
261 
newInstance()262     public static DevelopmentFragment newInstance() {
263         return new DevelopmentFragment();
264     }
265 
266     @Override
getMetricsCategory()267     public int getMetricsCategory() {
268         return MetricsProto.MetricsEvent.DEVELOPMENT;
269     }
270 
271     @Override
onCreate(Bundle icicle)272     public void onCreate(Bundle icicle) {
273 
274         if (icicle != null) {
275             // Don't show this in onCreate since we might be on the back stack
276             mPendingDialogKey = icicle.getString(STATE_SHOWING_DIALOG_KEY);
277         }
278 
279         mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
280         mBackupManager = IBackupManager.Stub.asInterface(
281                 ServiceManager.getService(Context.BACKUP_SERVICE));
282         mDpm = (DevicePolicyManager) getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
283         mUm = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
284 
285         mWifiManager = (WifiManager) getActivity().getSystemService(Context.WIFI_SERVICE);
286 
287         mContentResolver = getActivity().getContentResolver();
288 
289         mAudioDebug = new AudioDebug(getActivity(),
290                 (boolean successful) -> onAudioRecorded(successful),
291                 (AudioMetrics.Data data) -> updateAudioRecordingMetrics(data));
292 
293         super.onCreate(icicle);
294     }
295 
296     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)297     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
298         mLogdSizeController = new LogdSizePreferenceController(getActivity());
299         mLogpersistController = new LogpersistPreferenceController(getActivity(), getLifecycle());
300 
301         if (!mUm.isAdminUser()
302                 || mUm.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES)
303                 || Settings.Global.getInt(mContentResolver,
304                 Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
305             // Block access to developer options if the user is not the owner, if user policy
306             // restricts it, or if the device has not been provisioned
307             mUnavailable = true;
308             addPreferencesFromResource(R.xml.development_prefs_not_available);
309             return;
310         }
311 
312         addPreferencesFromResource(R.xml.development_prefs);
313         final PreferenceScreen preferenceScreen = getPreferenceScreen();
314 
315         // Don't add to prefs lists or it'll disable itself when switched off
316         mEnableDeveloper = (SwitchPreference) findPreference(ENABLE_DEVELOPER);
317 
318         final PreferenceGroup debugDebuggingCategory = (PreferenceGroup)
319                 findPreference(DEBUG_DEBUGGING_CATEGORY_KEY);
320         mEnableAdb = findAndInitSwitchPref(ENABLE_ADB);
321         mClearAdbKeys = findPreference(CLEAR_ADB_KEYS);
322         if (!AdbProperties.secure().orElse(false)) {
323             if (debugDebuggingCategory != null) {
324                 debugDebuggingCategory.removePreference(mClearAdbKeys);
325             }
326         }
327         mAllPrefs.add(mClearAdbKeys);
328         mEnableTerminal = findAndInitSwitchPref(ENABLE_TERMINAL);
329         if (!isPackageInstalled(getActivity(), TERMINAL_APP_PACKAGE)) {
330             if (debugDebuggingCategory != null) {
331                 debugDebuggingCategory.removePreference(mEnableTerminal);
332             }
333             mEnableTerminal = null;
334         }
335 
336         mBugreport = findPreference(BUGREPORT);
337         mLogdSizeController.displayPreference(preferenceScreen);
338         mLogpersistController.displayPreference(preferenceScreen);
339 
340         mKeepScreenOn = findAndInitSwitchPref(KEEP_SCREEN_ON);
341         mBtHciSnoopLog = addListPreference(BT_HCI_SNOOP_LOG);
342         mEnableOemUnlock = findAndInitSwitchPref(ENABLE_OEM_UNLOCK);
343         if (!showEnableOemUnlockPreference()) {
344             removePreference(mEnableOemUnlock);
345             mEnableOemUnlock = null;
346         }
347 
348         // TODO: implement UI for TV
349         removePreference(RUNNING_APPS);
350 
351         mDebugViewAttributes = findAndInitSwitchPref(DEBUG_VIEW_ATTRIBUTES);
352         mForceAllowOnExternal = findAndInitSwitchPref(FORCE_ALLOW_ON_EXTERNAL_KEY);
353         mPassword = (PreferenceScreen) findPreference(LOCAL_BACKUP_PASSWORD);
354         // We don't have a backup password activity on TV
355         mPassword.setVisible(false);
356         mAllPrefs.add(mPassword);
357 
358         if (!mUm.isAdminUser()) {
359             disableForUser(mEnableAdb);
360             disableForUser(mClearAdbKeys);
361             disableForUser(mEnableTerminal);
362             disableForUser(mPassword);
363         }
364 
365         mDebugAppPref = findPreference(DEBUG_APP_KEY);
366         mAllPrefs.add(mDebugAppPref);
367         mWaitForDebugger = findAndInitSwitchPref(WAIT_FOR_DEBUGGER_KEY);
368 
369         mMockLocationAppPref = findPreference(MOCK_LOCATION_APP_KEY);
370         mAllPrefs.add(mMockLocationAppPref);
371 
372         mVerifyAppsOverUsb = findAndInitSwitchPref(VERIFY_APPS_OVER_USB_KEY);
373         if (!showVerifierSetting()) {
374             if (debugDebuggingCategory != null) {
375                 debugDebuggingCategory.removePreference(mVerifyAppsOverUsb);
376             } else {
377                 mVerifyAppsOverUsb.setEnabled(false);
378             }
379         }
380         mStrictMode = findAndInitSwitchPref(STRICT_MODE_KEY);
381         mPointerLocation = findAndInitSwitchPref(POINTER_LOCATION_KEY);
382         mShowTouches = findAndInitSwitchPref(SHOW_TOUCHES_KEY);
383         mShowScreenUpdates = findAndInitSwitchPref(SHOW_SCREEN_UPDATES_KEY);
384         mDisableOverlays = findAndInitSwitchPref(DISABLE_OVERLAYS_KEY);
385         mForceMsaa = findAndInitSwitchPref(FORCE_MSAA_KEY);
386         mTrackFrameTime = addListPreference(TRACK_FRAME_TIME_KEY);
387         mShowNonRectClip = addListPreference(SHOW_NON_RECTANGULAR_CLIP_KEY);
388         mShowHwScreenUpdates = findAndInitSwitchPref(SHOW_HW_SCREEN_UPDATES_KEY);
389         mShowHwLayersUpdates = findAndInitSwitchPref(SHOW_HW_LAYERS_UPDATES_KEY);
390         mDebugLayout = findAndInitSwitchPref(DEBUG_LAYOUT_KEY);
391         mForceRtlLayout = findAndInitSwitchPref(FORCE_RTL_LAYOUT_KEY);
392         mDebugHwOverdraw = addListPreference(DEBUG_HW_OVERDRAW_KEY);
393         mWifiDisplayCertification = findAndInitSwitchPref(WIFI_DISPLAY_CERTIFICATION_KEY);
394         mWifiVerboseLogging = findAndInitSwitchPref(WIFI_VERBOSE_LOGGING_KEY);
395         mMobileDataAlwaysOn = findAndInitSwitchPref(MOBILE_DATA_ALWAYS_ON);
396         mUsbConfiguration = addListPreference(USB_CONFIGURATION_KEY);
397 
398         mWindowAnimationScale = addListPreference(WINDOW_ANIMATION_SCALE_KEY);
399         mTransitionAnimationScale = addListPreference(TRANSITION_ANIMATION_SCALE_KEY);
400         mAnimatorDurationScale = addListPreference(ANIMATOR_DURATION_SCALE_KEY);
401         mOverlayDisplayDevices = addListPreference(OVERLAY_DISPLAY_DEVICES_KEY);
402         mOpenGLTraces = addListPreference(OPENGL_TRACES_KEY);
403         mSimulateColorSpace = addListPreference(SIMULATE_COLOR_SPACE);
404         mUSBAudio = findAndInitSwitchPref(USB_AUDIO_KEY);
405         mRecordAudio = findAndInitSwitchPref(RECORD_AUDIO_KEY);
406         mPlayRecordedAudio = findPreference(PLAY_RECORDED_AUDIO_KEY);
407         mPlayRecordedAudio.setVisible(false);
408         mSaveAudio = findPreference(SAVE_RECORDED_AUDIO_KEY);
409         mSaveAudio.setVisible(false);
410         mTimeToStartRead = findPreference(TIME_TO_START_READ_KEY);
411         mTimeToStartRead.setVisible(false);
412         mTimeToValidAudio = findPreference(TIME_TO_VALID_AUDIO_KEY);
413         mTimeToValidAudio.setVisible(false);
414         mEmptyAudioDuration = findPreference(EMPTY_AUDIO_DURATION_KEY);
415         mEmptyAudioDuration.setVisible(false);
416         mForceResizable = findAndInitSwitchPref(FORCE_RESIZABLE_KEY);
417 
418         mImmediatelyDestroyActivities = (SwitchPreference) findPreference(
419                 IMMEDIATELY_DESTROY_ACTIVITIES_KEY);
420         mAllPrefs.add(mImmediatelyDestroyActivities);
421         mResetSwitchPrefs.add(mImmediatelyDestroyActivities);
422 
423         mAppProcessLimit = addListPreference(APP_PROCESS_LIMIT_KEY);
424 
425         mShowAllANRs = (SwitchPreference) findPreference(
426                 SHOW_ALL_ANRS_KEY);
427         mAllPrefs.add(mShowAllANRs);
428         mResetSwitchPrefs.add(mShowAllANRs);
429 
430         Preference hdcpChecking = findPreference(HDCP_CHECKING_KEY);
431         if (hdcpChecking != null) {
432             mAllPrefs.add(hdcpChecking);
433             removePreferenceForProduction(hdcpChecking);
434         }
435 
436         // TODO: implement UI for TV
437         removePreference(KEY_CONVERT_FBE);
438 /*
439         // Please import android.sysprop.CryptoProperties when you uncomment this block.
440         PreferenceScreen convertFbePreference =
441                 (PreferenceScreen) findPreference(KEY_CONVERT_FBE);
442 
443         try {
444             IBinder service = ServiceManager.getService("mount");
445             IMountService mountService = IMountService.Stub.asInterface(service);
446             if (!mountService.isConvertibleToFBE()) {
447                 removePreference(KEY_CONVERT_FBE);
448             } else if (CryptoProperties.type().orElse(CryptoProperties.type_values.NONE) ==
449                        CryptoProperties.type_values.FILE) {
450                 convertFbePreference.setEnabled(false);
451                 convertFbePreference.setSummary(getResources()
452                         .getString(R.string.convert_to_file_encryption_done));
453             }
454         } catch(RemoteException e) {
455             removePreference(KEY_CONVERT_FBE);
456         }
457 */
458 
459         mColorModePreference = (ColorModePreference) findPreference(KEY_COLOR_MODE);
460         mColorModePreference.updateCurrentAndSupported();
461         if (mColorModePreference.getColorModeCount() < 2) {
462             removePreference(KEY_COLOR_MODE);
463             mColorModePreference = null;
464         }
465     }
466 
removePreference(String key)467     private void removePreference(String key) {
468         final Preference preference = findPreference(key);
469         if (preference != null) {
470             getPreferenceScreen().removePreference(preference);
471         }
472     }
473 
addListPreference(String prefKey)474     private ListPreference addListPreference(String prefKey) {
475         ListPreference pref = (ListPreference) findPreference(prefKey);
476         mAllPrefs.add(pref);
477         pref.setOnPreferenceChangeListener(this);
478         return pref;
479     }
480 
disableForUser(Preference pref)481     private void disableForUser(Preference pref) {
482         if (pref != null) {
483             pref.setEnabled(false);
484             mDisabledPrefs.add(pref);
485         }
486     }
487 
findAndInitSwitchPref(String key)488     private SwitchPreference findAndInitSwitchPref(String key) {
489         SwitchPreference pref = (SwitchPreference) findPreference(key);
490         if (pref == null) {
491             throw new IllegalArgumentException("Cannot find preference with key = " + key);
492         }
493         mAllPrefs.add(pref);
494         mResetSwitchPrefs.add(pref);
495         return pref;
496     }
497 
498     @Override
onActivityCreated(Bundle savedInstanceState)499     public void onActivityCreated(Bundle savedInstanceState) {
500         super.onActivityCreated(savedInstanceState);
501 
502         if (mUnavailable) {
503             if (mEnableDeveloper != null) {
504                 mEnableDeveloper.setEnabled(false);
505             }
506         }
507     }
508 
removePreferenceForProduction(Preference preference)509     private boolean removePreferenceForProduction(Preference preference) {
510         if ("user".equals(Build.TYPE)) {
511             removePreference(preference);
512             return true;
513         }
514         return false;
515     }
516 
removePreference(Preference preference)517     private void removePreference(Preference preference) {
518         getPreferenceScreen().removePreference(preference);
519         mAllPrefs.remove(preference);
520         mResetSwitchPrefs.remove(preference);
521     }
522 
setPrefsEnabledState(boolean enabled)523     private void setPrefsEnabledState(boolean enabled) {
524         for (final Preference pref : mAllPrefs) {
525             pref.setEnabled(enabled && !mDisabledPrefs.contains(pref));
526         }
527         mLogdSizeController.enablePreference(enabled);
528         mLogpersistController.enablePreference(enabled);
529         updateAllOptions();
530     }
531 
532     @Override
onResume()533     public void onResume() {
534         super.onResume();
535 
536         if (mUnavailable) {
537             return;
538         }
539 
540         if (mDpm.getMaximumTimeToLock(null) > 0) {
541             // A DeviceAdmin has specified a maximum time until the device
542             // will lock...  in this case we can't allow the user to turn
543             // on "stay awake when plugged in" because that would defeat the
544             // restriction.
545             mDisabledPrefs.add(mKeepScreenOn);
546         } else {
547             mDisabledPrefs.remove(mKeepScreenOn);
548         }
549 
550         mLastEnabledState = DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(getContext());
551         mEnableDeveloper.setChecked(mLastEnabledState);
552         setPrefsEnabledState(mLastEnabledState);
553 
554         if (mHaveDebugSettings && !mLastEnabledState) {
555             // Overall debugging is disabled, but there are some debug
556             // settings that are enabled.  This is an invalid state.  Switch
557             // to debug settings being enabled, so the user knows there is
558             // stuff enabled and can turn it all off if they want.
559             DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(getContext(), true);
560             mLastEnabledState = true;
561             mEnableDeveloper.setChecked(mLastEnabledState);
562             setPrefsEnabledState(mLastEnabledState);
563         }
564 
565         if (mColorModePreference != null) {
566             mColorModePreference.startListening();
567             mColorModePreference.updateCurrentAndSupported();
568         }
569 
570         if (mPendingDialogKey != null) {
571             recreateDialogForKey(mPendingDialogKey);
572             mPendingDialogKey = null;
573         }
574     }
575 
576     @Override
onPause()577     public void onPause() {
578         super.onPause();
579         if (mColorModePreference != null) {
580             mColorModePreference.stopListening();
581         }
582 
583         mAudioDebug.cancelRecording();
584     }
585 
586     @Override
onSaveInstanceState(Bundle outState)587     public void onSaveInstanceState(Bundle outState) {
588         super.onSaveInstanceState(outState);
589         outState.putString(STATE_SHOWING_DIALOG_KEY, getKeyForShowingDialog());
590     }
591 
592     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)593     public View onCreateView(LayoutInflater inflater, ViewGroup container,
594             Bundle savedInstanceState) {
595         IntentFilter filter = new IntentFilter();
596         filter.addAction(UsbManager.ACTION_USB_STATE);
597         if (getActivity().registerReceiver(mUsbReceiver, filter) == null) {
598             updateUsbConfigurationValues();
599         }
600         return super.onCreateView(inflater, container, savedInstanceState);
601     }
602 
603     @Override
onDestroyView()604     public void onDestroyView() {
605         super.onDestroyView();
606 
607         getActivity().unregisterReceiver(mUsbReceiver);
608     }
609 
610     @Override
onDestroy()611     public void onDestroy() {
612         super.onDestroy();
613         dismissDialogs();
614     }
615 
updateSwitchPreference(SwitchPreference switchPreference, boolean value)616     void updateSwitchPreference(SwitchPreference switchPreference, boolean value) {
617         switchPreference.setChecked(value);
618         mHaveDebugSettings |= value;
619     }
620 
updateAllOptions()621     private void updateAllOptions() {
622         final Context context = getActivity();
623         final ContentResolver cr = context.getContentResolver();
624         mHaveDebugSettings = false;
625         updateSwitchPreference(mEnableAdb, Settings.Global.getInt(cr,
626                 Settings.Global.ADB_ENABLED, 0) != 0);
627         if (mEnableTerminal != null) {
628             updateSwitchPreference(mEnableTerminal,
629                     context.getPackageManager().getApplicationEnabledSetting(TERMINAL_APP_PACKAGE)
630                             == PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
631         }
632         updateSwitchPreference(mKeepScreenOn, Settings.Global.getInt(cr,
633                 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0) != 0);
634         if (mEnableOemUnlock != null) {
635             updateSwitchPreference(mEnableOemUnlock, isOemUnlockEnabled(getActivity()));
636             mEnableOemUnlock.setEnabled(isOemUnlockAllowed());
637         }
638         updateSwitchPreference(mDebugViewAttributes, Settings.Global.getInt(cr,
639                 Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0);
640         updateSwitchPreference(mForceAllowOnExternal, Settings.Global.getInt(cr,
641                 Settings.Global.FORCE_ALLOW_ON_EXTERNAL, 0) != 0);
642         updateBluetoothHciSnoopLogValues();
643         updateHdcpValues();
644         updatePasswordSummary();
645         updateDebuggerOptions();
646         updateMockLocation();
647         updateStrictModeVisualOptions();
648         updatePointerLocationOptions();
649         updateShowTouchesOptions();
650         updateFlingerOptions();
651         updateMsaaOptions();
652         updateTrackFrameTimeOptions();
653         updateShowNonRectClipOptions();
654         updateShowHwScreenUpdatesOptions();
655         updateShowHwLayersUpdatesOptions();
656         updateDebugHwOverdrawOptions();
657         updateDebugLayoutOptions();
658         updateAnimationScaleOptions();
659         updateOverlayDisplayDevicesOptions();
660         updateOpenGLTracesOptions();
661         updateImmediatelyDestroyActivitiesOptions();
662         updateAppProcessLimitOptions();
663         updateShowAllANRsOptions();
664         updateVerifyAppsOverUsbOptions();
665         updateBugreportOptions();
666         updateForceRtlOptions();
667         mLogdSizeController.updateLogdSizeValues();
668         mLogpersistController.updateLogpersistValues();
669         updateWifiDisplayCertificationOptions();
670         updateWifiVerboseLoggingOptions();
671         updateMobileDataAlwaysOnOptions();
672         updateSimulateColorSpace();
673         updateUSBAudioOptions();
674         updateForceResizableOptions();
675     }
676 
resetDangerousOptions()677     private void resetDangerousOptions() {
678         SystemPropPoker.getInstance().blockPokes();
679         for (final SwitchPreference cb : mResetSwitchPrefs) {
680             if (cb.isChecked()) {
681                 cb.setChecked(false);
682                 onPreferenceTreeClick(cb);
683             }
684         }
685         resetDebuggerOptions();
686         mLogpersistController.writeLogpersistOption(null, true);
687         mLogdSizeController.writeLogdSizeOption(null);
688         writeAnimationScaleOption(0, mWindowAnimationScale, null);
689         writeAnimationScaleOption(1, mTransitionAnimationScale, null);
690         writeAnimationScaleOption(2, mAnimatorDurationScale, null);
691         // Only poke the color space setting if we control it.
692         if (usingDevelopmentColorSpace()) {
693             writeSimulateColorSpace(-1);
694         }
695         writeOverlayDisplayDevicesOptions(null);
696         writeAppProcessLimitOptions(null);
697         mHaveDebugSettings = false;
698         updateAllOptions();
699         SystemPropPoker.getInstance().unblockPokes();
700         SystemPropPoker.getInstance().poke();
701     }
702 
updateBluetoothHciSnoopLogValues()703     private void updateBluetoothHciSnoopLogValues() {
704         ListPreference bluetoothSnoopLog = (ListPreference) findPreference(BT_HCI_SNOOP_LOG);
705         if (bluetoothSnoopLog != null) {
706             String currentValue = SystemProperties.get(BTSNOOP_LOG_MODE_PROPERTY);
707             String[] values = getResources().getStringArray(R.array.bt_hci_snoop_log_values);
708             String[] summaries = getResources().getStringArray(R.array.bt_hci_snoop_log_entries);
709             int disabledIndex = 0; // defaults to DISABLED
710             updateListPreference(bluetoothSnoopLog, currentValue, values, summaries, disabledIndex);
711         }
712     }
713 
updateListPreference(ListPreference preference, String currentValue, String[] values, String[] summaries, int index)714     private void updateListPreference(ListPreference preference, String currentValue,
715             String[] values, String[] summaries, int index) {
716         for (int i = 0; i < values.length; i++) {
717             if (currentValue.equals(values[i])) {
718                 index = i;
719                 break;
720             }
721         }
722         preference.setValue(values[index]);
723         preference.setSummary(summaries[index]);
724         preference.setOnPreferenceChangeListener(this);
725     }
726 
updateHdcpValues()727     private void updateHdcpValues() {
728         ListPreference hdcpChecking = (ListPreference) findPreference(HDCP_CHECKING_KEY);
729         if (hdcpChecking != null) {
730             String currentValue = SystemProperties.get(HDCP_CHECKING_PROPERTY);
731             String[] values = getResources().getStringArray(R.array.hdcp_checking_values);
732             String[] summaries = getResources().getStringArray(R.array.hdcp_checking_summaries);
733             int index = 1; // Defaults to drm-only. Needs to match with R.array.hdcp_checking_values
734             updateListPreference(hdcpChecking, currentValue, values, summaries, index);
735         }
736     }
737 
updatePasswordSummary()738     private void updatePasswordSummary() {
739         try {
740             if (mBackupManager.hasBackupPassword()) {
741                 mPassword.setSummary(R.string.local_backup_password_summary_change);
742             } else {
743                 mPassword.setSummary(R.string.local_backup_password_summary_none);
744             }
745         } catch (RemoteException e) {
746             // ignore
747         }
748     }
749 
writeBtHciSnoopLogOptions(Object newValue)750     private void writeBtHciSnoopLogOptions(Object newValue) {
751         SystemProperties.set(BTSNOOP_LOG_MODE_PROPERTY,
752                 newValue == null ? "" : newValue.toString());
753         updateBluetoothHciSnoopLogValues();
754         SystemPropPoker.getInstance().poke();
755     }
756 
writeDebuggerOptions()757     private void writeDebuggerOptions() {
758         try {
759             ActivityManager.getService().setDebugApp(
760                     mDebugApp, mWaitForDebugger.isChecked(), true);
761         } catch (RemoteException ex) {
762             // ignore
763         }
764     }
765 
writeMockLocation()766     private void writeMockLocation() {
767         AppOpsManager appOpsManager =
768                 (AppOpsManager) getActivity().getSystemService(Context.APP_OPS_SERVICE);
769 
770         // Disable the app op of the previous mock location app if such.
771         List<AppOpsManager.PackageOps> packageOps =
772                 appOpsManager.getPackagesForOps(MOCK_LOCATION_APP_OPS);
773         if (packageOps != null) {
774             // Should be one but in case we are in a bad state due to use of command line tools.
775             for (AppOpsManager.PackageOps packageOp : packageOps) {
776                 if (packageOp.getOps().get(0).getMode() != AppOpsManager.MODE_ERRORED) {
777                     String oldMockLocationApp = packageOp.getPackageName();
778                     try {
779                         ApplicationInfo ai = getActivity().getPackageManager().getApplicationInfo(
780                                 oldMockLocationApp, PackageManager.GET_DISABLED_COMPONENTS);
781                         appOpsManager.setMode(AppOpsManager.OP_MOCK_LOCATION, ai.uid,
782                                 oldMockLocationApp, AppOpsManager.MODE_ERRORED);
783                     } catch (PackageManager.NameNotFoundException e) {
784                         /* ignore */
785                     }
786                 }
787             }
788         }
789 
790         // Enable the app op of the new mock location app if such.
791         if (!TextUtils.isEmpty(mMockLocationApp)) {
792             try {
793                 ApplicationInfo ai = getActivity().getPackageManager().getApplicationInfo(
794                         mMockLocationApp, PackageManager.GET_DISABLED_COMPONENTS);
795                 appOpsManager.setMode(AppOpsManager.OP_MOCK_LOCATION, ai.uid,
796                         mMockLocationApp, AppOpsManager.MODE_ALLOWED);
797             } catch (PackageManager.NameNotFoundException e) {
798                 /* ignore */
799             }
800         }
801     }
802 
resetDebuggerOptions()803     private static void resetDebuggerOptions() {
804         try {
805             ActivityManager.getService().setDebugApp(
806                     null, false, true);
807         } catch (RemoteException ex) {
808             // ignore
809         }
810     }
811 
updateDebuggerOptions()812     private void updateDebuggerOptions() {
813         mDebugApp = Settings.Global.getString(mContentResolver, Settings.Global.DEBUG_APP);
814         updateSwitchPreference(mWaitForDebugger, Settings.Global.getInt(mContentResolver,
815                 Settings.Global.WAIT_FOR_DEBUGGER, 0) != 0);
816         if (mDebugApp != null && mDebugApp.length() > 0) {
817             String label;
818             try {
819                 ApplicationInfo ai = getActivity().getPackageManager().getApplicationInfo(mDebugApp,
820                         PackageManager.GET_DISABLED_COMPONENTS);
821                 CharSequence lab = getActivity().getPackageManager().getApplicationLabel(ai);
822                 label = lab != null ? lab.toString() : mDebugApp;
823             } catch (PackageManager.NameNotFoundException e) {
824                 label = mDebugApp;
825             }
826             mDebugAppPref.setSummary(getResources().getString(R.string.debug_app_set, label));
827             mWaitForDebugger.setEnabled(true);
828             mHaveDebugSettings = true;
829         } else {
830             mDebugAppPref.setSummary(getResources().getString(R.string.debug_app_not_set));
831             mWaitForDebugger.setEnabled(false);
832         }
833     }
834 
updateMockLocation()835     private void updateMockLocation() {
836         AppOpsManager appOpsManager =
837                 (AppOpsManager) getActivity().getSystemService(Context.APP_OPS_SERVICE);
838 
839         List<AppOpsManager.PackageOps> packageOps =
840                 appOpsManager.getPackagesForOps(MOCK_LOCATION_APP_OPS);
841         if (packageOps != null) {
842             for (AppOpsManager.PackageOps packageOp : packageOps) {
843                 if (packageOp.getOps().get(0).getMode() == AppOpsManager.MODE_ALLOWED) {
844                     mMockLocationApp = packageOps.get(0).getPackageName();
845                     break;
846                 }
847             }
848         }
849 
850         if (!TextUtils.isEmpty(mMockLocationApp)) {
851             String label = mMockLocationApp;
852             try {
853                 ApplicationInfo ai = getActivity().getPackageManager().getApplicationInfo(
854                         mMockLocationApp, PackageManager.GET_DISABLED_COMPONENTS);
855                 CharSequence appLabel = getActivity().getPackageManager().getApplicationLabel(ai);
856                 if (appLabel != null) {
857                     label = appLabel.toString();
858                 }
859             } catch (PackageManager.NameNotFoundException e) {
860                 /* ignore */
861             }
862 
863             mMockLocationAppPref.setSummary(getString(R.string.mock_location_app_set, label));
864             mHaveDebugSettings = true;
865         } else {
866             mMockLocationAppPref.setSummary(getString(R.string.mock_location_app_not_set));
867         }
868     }
869 
updateVerifyAppsOverUsbOptions()870     private void updateVerifyAppsOverUsbOptions() {
871         updateSwitchPreference(mVerifyAppsOverUsb,
872                 Settings.Global.getInt(mContentResolver,
873                 Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) != 0);
874         mVerifyAppsOverUsb.setEnabled(enableVerifierSetting());
875     }
876 
writeVerifyAppsOverUsbOptions()877     private void writeVerifyAppsOverUsbOptions() {
878         Settings.Global.putInt(mContentResolver, Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB,
879                 mVerifyAppsOverUsb.isChecked() ? 1 : 0);
880     }
881 
enableVerifierSetting()882     private boolean enableVerifierSetting() {
883         if (Settings.Global.getInt(mContentResolver, Settings.Global.ADB_ENABLED, 0) == 0) {
884             return false;
885         }
886         final PackageManager pm = getActivity().getPackageManager();
887         final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
888         verification.setType(PACKAGE_MIME_TYPE);
889         verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
890         final List<ResolveInfo> receivers = pm.queryBroadcastReceivers(verification, 0);
891         return !receivers.isEmpty();
892     }
893 
showVerifierSetting()894     private boolean showVerifierSetting() {
895         return Settings.Global.getInt(mContentResolver,
896                 Settings.Global.PACKAGE_VERIFIER_SETTING_VISIBLE, 1) > 0;
897     }
898 
showEnableOemUnlockPreference()899     private static boolean showEnableOemUnlockPreference() {
900         return !SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP).equals("");
901     }
902 
isOemUnlockAllowed()903     private boolean isOemUnlockAllowed() {
904         return !mUm.hasUserRestriction(UserManager.DISALLOW_OEM_UNLOCK);
905     }
906 
updateBugreportOptions()907     private void updateBugreportOptions() {
908         boolean enabled = "1".equals(SystemProperties.get("ro.debuggable"))
909                 || mEnableDeveloper.isChecked();
910         mBugreport.setEnabled(enabled);
911         final ComponentName componentName = new ComponentName("com.android.shell",
912                 "com.android.shell.BugreportStorageProvider");
913         getActivity().getPackageManager().setComponentEnabledSetting(componentName,
914                 enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
915                         : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
916                 0);
917     }
918 
919     /**
920      * Take bug report and show notification.
921      * @param activity
922      */
captureBugReport(Activity activity)923     public static void captureBugReport(Activity activity) {
924         Toast.makeText(activity, R.string.capturing_bugreport, Toast.LENGTH_SHORT).show();
925         try {
926             ActivityManager.getService().requestFullBugReport();
927         } catch (RemoteException e) {
928             Log.e(TAG, "Error taking bugreport", e);
929         }
930     }
931 
932     // Returns the current state of the system property that controls
933     // strictmode flashes.  One of:
934     //    0: not explicitly set one way or another
935     //    1: on
936     //    2: off
currentStrictModeActiveIndex()937     private static int currentStrictModeActiveIndex() {
938         if (TextUtils.isEmpty(SystemProperties.get(StrictMode.VISUAL_PROPERTY))) {
939             return 0;
940         }
941         boolean enabled = SystemProperties.getBoolean(StrictMode.VISUAL_PROPERTY, false);
942         return enabled ? 1 : 2;
943     }
944 
writeStrictModeVisualOptions()945     private void writeStrictModeVisualOptions() {
946         try {
947             mWindowManager.setStrictModeVisualIndicatorPreference(mStrictMode.isChecked()
948                     ? "1" : "");
949         } catch (RemoteException e) {
950             // ignore
951         }
952     }
953 
updateStrictModeVisualOptions()954     private void updateStrictModeVisualOptions() {
955         updateSwitchPreference(mStrictMode, currentStrictModeActiveIndex() == 1);
956     }
957 
writePointerLocationOptions()958     private void writePointerLocationOptions() {
959         Settings.System.putInt(mContentResolver,
960                 Settings.System.POINTER_LOCATION, mPointerLocation.isChecked() ? 1 : 0);
961     }
962 
updatePointerLocationOptions()963     private void updatePointerLocationOptions() {
964         updateSwitchPreference(mPointerLocation,
965                 Settings.System.getInt(mContentResolver, Settings.System.POINTER_LOCATION, 0) != 0);
966     }
967 
writeShowTouchesOptions()968     private void writeShowTouchesOptions() {
969         Settings.System.putInt(mContentResolver,
970                 Settings.System.SHOW_TOUCHES, mShowTouches.isChecked() ? 1 : 0);
971     }
972 
updateShowTouchesOptions()973     private void updateShowTouchesOptions() {
974         updateSwitchPreference(mShowTouches,
975                 Settings.System.getInt(mContentResolver, Settings.System.SHOW_TOUCHES, 0) != 0);
976     }
977 
updateFlingerOptions()978     private void updateFlingerOptions() {
979         // magic communication with surface flinger.
980         try {
981             IBinder flinger = ServiceManager.getService("SurfaceFlinger");
982             if (flinger != null) {
983                 Parcel data = Parcel.obtain();
984                 Parcel reply = Parcel.obtain();
985                 data.writeInterfaceToken("android.ui.ISurfaceComposer");
986                 flinger.transact(1010, data, reply, 0);
987                 @SuppressWarnings("unused")
988                 int showCpu = reply.readInt();
989                 @SuppressWarnings("unused")
990                 int enableGL = reply.readInt();
991                 int showUpdates = reply.readInt();
992                 updateSwitchPreference(mShowScreenUpdates, showUpdates != 0);
993                 @SuppressWarnings("unused")
994                 int showBackground = reply.readInt();
995                 int disableOverlays = reply.readInt();
996                 updateSwitchPreference(mDisableOverlays, disableOverlays != 0);
997                 reply.recycle();
998                 data.recycle();
999             }
1000         } catch (RemoteException ex) {
1001             // ignore
1002         }
1003     }
1004 
writeShowUpdatesOption()1005     private void writeShowUpdatesOption() {
1006         try {
1007             IBinder flinger = ServiceManager.getService("SurfaceFlinger");
1008             if (flinger != null) {
1009                 Parcel data = Parcel.obtain();
1010                 data.writeInterfaceToken("android.ui.ISurfaceComposer");
1011                 final int showUpdates = mShowScreenUpdates.isChecked() ? 1 : 0;
1012                 data.writeInt(showUpdates);
1013                 flinger.transact(1002, data, null, 0);
1014                 data.recycle();
1015 
1016                 updateFlingerOptions();
1017             }
1018         } catch (RemoteException ex) {
1019             // ignore
1020         }
1021     }
1022 
writeDisableOverlaysOption()1023     private void writeDisableOverlaysOption() {
1024         try {
1025             IBinder flinger = ServiceManager.getService("SurfaceFlinger");
1026             if (flinger != null) {
1027                 Parcel data = Parcel.obtain();
1028                 data.writeInterfaceToken("android.ui.ISurfaceComposer");
1029                 final int disableOverlays = mDisableOverlays.isChecked() ? 1 : 0;
1030                 data.writeInt(disableOverlays);
1031                 flinger.transact(1008, data, null, 0);
1032                 data.recycle();
1033 
1034                 updateFlingerOptions();
1035             }
1036         } catch (RemoteException ex) {
1037             // ignore
1038         }
1039     }
1040 
updateMsaaOptions()1041     private void updateMsaaOptions() {
1042         updateSwitchPreference(mForceMsaa, DisplayProperties.debug_force_msaa().orElse(false));
1043     }
1044 
writeMsaaOptions()1045     private void writeMsaaOptions() {
1046         DisplayProperties.debug_force_msaa(mForceMsaa.isChecked());
1047         SystemPropPoker.getInstance().poke();
1048     }
1049 
updateTrackFrameTimeOptions()1050     private void updateTrackFrameTimeOptions() {
1051         String value = SystemProperties.get(ThreadedRenderer.PROFILE_PROPERTY);
1052         if (value == null) {
1053             value = "";
1054         }
1055 
1056         CharSequence[] values = mTrackFrameTime.getEntryValues();
1057         for (int i = 0; i < values.length; i++) {
1058             if (value.contentEquals(values[i])) {
1059                 mTrackFrameTime.setValueIndex(i);
1060                 mTrackFrameTime.setSummary(mTrackFrameTime.getEntries()[i]);
1061                 return;
1062             }
1063         }
1064         mTrackFrameTime.setValueIndex(0);
1065         mTrackFrameTime.setSummary(mTrackFrameTime.getEntries()[0]);
1066     }
1067 
writeTrackFrameTimeOptions(Object newValue)1068     private void writeTrackFrameTimeOptions(Object newValue) {
1069         SystemProperties.set(ThreadedRenderer.PROFILE_PROPERTY,
1070                 newValue == null ? "" : newValue.toString());
1071         SystemPropPoker.getInstance().poke();
1072         updateTrackFrameTimeOptions();
1073     }
1074 
updateShowNonRectClipOptions()1075     private void updateShowNonRectClipOptions() {
1076         String value = SystemProperties.get(
1077                 ThreadedRenderer.DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY);
1078         if (value == null) {
1079             value = "hide";
1080         }
1081 
1082         CharSequence[] values = mShowNonRectClip.getEntryValues();
1083         for (int i = 0; i < values.length; i++) {
1084             if (value.contentEquals(values[i])) {
1085                 mShowNonRectClip.setValueIndex(i);
1086                 mShowNonRectClip.setSummary(mShowNonRectClip.getEntries()[i]);
1087                 return;
1088             }
1089         }
1090         mShowNonRectClip.setValueIndex(0);
1091         mShowNonRectClip.setSummary(mShowNonRectClip.getEntries()[0]);
1092     }
1093 
writeShowNonRectClipOptions(Object newValue)1094     private void writeShowNonRectClipOptions(Object newValue) {
1095         SystemProperties.set(ThreadedRenderer.DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY,
1096                 newValue == null ? "" : newValue.toString());
1097         SystemPropPoker.getInstance().poke();
1098         updateShowNonRectClipOptions();
1099     }
1100 
updateShowHwScreenUpdatesOptions()1101     private void updateShowHwScreenUpdatesOptions() {
1102         updateSwitchPreference(mShowHwScreenUpdates,
1103                 SystemProperties.getBoolean(ThreadedRenderer.DEBUG_DIRTY_REGIONS_PROPERTY, false));
1104     }
1105 
writeShowHwScreenUpdatesOptions()1106     private void writeShowHwScreenUpdatesOptions() {
1107         SystemProperties.set(ThreadedRenderer.DEBUG_DIRTY_REGIONS_PROPERTY,
1108                 mShowHwScreenUpdates.isChecked() ? "true" : null);
1109         SystemPropPoker.getInstance().poke();
1110     }
1111 
updateShowHwLayersUpdatesOptions()1112     private void updateShowHwLayersUpdatesOptions() {
1113         updateSwitchPreference(mShowHwLayersUpdates, SystemProperties.getBoolean(
1114                 ThreadedRenderer.DEBUG_SHOW_LAYERS_UPDATES_PROPERTY, false));
1115     }
1116 
writeShowHwLayersUpdatesOptions()1117     private void writeShowHwLayersUpdatesOptions() {
1118         SystemProperties.set(ThreadedRenderer.DEBUG_SHOW_LAYERS_UPDATES_PROPERTY,
1119                 mShowHwLayersUpdates.isChecked() ? "true" : null);
1120         SystemPropPoker.getInstance().poke();
1121     }
1122 
updateDebugHwOverdrawOptions()1123     private void updateDebugHwOverdrawOptions() {
1124         String value = SystemProperties.get(ThreadedRenderer.DEBUG_OVERDRAW_PROPERTY);
1125         if (value == null) {
1126             value = "";
1127         }
1128 
1129         CharSequence[] values = mDebugHwOverdraw.getEntryValues();
1130         for (int i = 0; i < values.length; i++) {
1131             if (value.contentEquals(values[i])) {
1132                 mDebugHwOverdraw.setValueIndex(i);
1133                 mDebugHwOverdraw.setSummary(mDebugHwOverdraw.getEntries()[i]);
1134                 return;
1135             }
1136         }
1137         mDebugHwOverdraw.setValueIndex(0);
1138         mDebugHwOverdraw.setSummary(mDebugHwOverdraw.getEntries()[0]);
1139     }
1140 
writeDebugHwOverdrawOptions(Object newValue)1141     private void writeDebugHwOverdrawOptions(Object newValue) {
1142         SystemProperties.set(ThreadedRenderer.DEBUG_OVERDRAW_PROPERTY,
1143                 newValue == null ? "" : newValue.toString());
1144         SystemPropPoker.getInstance().poke();
1145         updateDebugHwOverdrawOptions();
1146     }
1147 
updateDebugLayoutOptions()1148     private void updateDebugLayoutOptions() {
1149         updateSwitchPreference(mDebugLayout,
1150                 DisplayProperties.debug_layout().orElse(false));
1151     }
1152 
writeDebugLayoutOptions()1153     private void writeDebugLayoutOptions() {
1154         DisplayProperties.debug_layout(mDebugLayout.isChecked());
1155         SystemPropPoker.getInstance().poke();
1156     }
1157 
updateSimulateColorSpace()1158     private void updateSimulateColorSpace() {
1159         final boolean enabled = Settings.Secure.getInt(
1160                 mContentResolver, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0) != 0;
1161         if (enabled) {
1162             final String mode = Integer.toString(Settings.Secure.getInt(
1163                     mContentResolver, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER,
1164                     AccessibilityManager.DALTONIZER_DISABLED));
1165             mSimulateColorSpace.setValue(mode);
1166             final int index = mSimulateColorSpace.findIndexOfValue(mode);
1167             if (index < 0) {
1168                 // We're using a mode controlled by accessibility preferences.
1169                 mSimulateColorSpace.setSummary(getString(R.string.daltonizer_type_overridden,
1170                         getString(R.string.accessibility_display_daltonizer_preference_title)));
1171             } else {
1172                 mSimulateColorSpace.setSummary("%s");
1173             }
1174         } else {
1175             mSimulateColorSpace.setValue(
1176                     Integer.toString(AccessibilityManager.DALTONIZER_DISABLED));
1177         }
1178     }
1179 
1180     /**
1181      * @return <code>true</code> if the color space preference is currently
1182      *         controlled by development settings
1183      */
usingDevelopmentColorSpace()1184     private boolean usingDevelopmentColorSpace() {
1185         final boolean enabled = Settings.Secure.getInt(
1186                 mContentResolver, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0) != 0;
1187         if (enabled) {
1188             final String mode = Integer.toString(Settings.Secure.getInt(
1189                     mContentResolver, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER,
1190                     AccessibilityManager.DALTONIZER_DISABLED));
1191             final int index = mSimulateColorSpace.findIndexOfValue(mode);
1192             if (index >= 0) {
1193                 // We're using a mode controlled by developer preferences.
1194                 return true;
1195             }
1196         }
1197         return false;
1198     }
1199 
writeSimulateColorSpace(Object value)1200     private void writeSimulateColorSpace(Object value) {
1201         final int newMode = Integer.parseInt(value.toString());
1202         if (newMode < 0) {
1203             Settings.Secure.putInt(mContentResolver,
1204                     Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0);
1205         } else {
1206             Settings.Secure.putInt(mContentResolver,
1207                     Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 1);
1208             Settings.Secure.putInt(mContentResolver,
1209                     Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, newMode);
1210         }
1211     }
1212 
updateUSBAudioOptions()1213     private void updateUSBAudioOptions() {
1214         updateSwitchPreference(mUSBAudio, Settings.Secure.getInt(mContentResolver,
1215                 Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED, 0) != 0);
1216     }
1217 
writeUSBAudioOptions()1218     private void writeUSBAudioOptions() {
1219         Settings.Secure.putInt(mContentResolver,
1220                 Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED,
1221                 mUSBAudio.isChecked() ? 1 : 0);
1222     }
1223 
writeRecordAudioOptions()1224     private void writeRecordAudioOptions() {
1225         if (mRecordAudio.isChecked()) {
1226             try {
1227                 mAudioDebug.startRecording();
1228             } catch (AudioReaderException e) {
1229                 mRecordAudio.setChecked(false);
1230                 Toast errorToast = Toast.makeText(getContext(),
1231                         getString(R.string.show_audio_recording_start_failed), Toast.LENGTH_SHORT);
1232                 errorToast.show();
1233                 Log.e(TAG, "Unable to start recording audio from the microphone", e);
1234             }
1235         } else {
1236             mAudioDebug.stopRecording();
1237         }
1238     }
1239 
1240     /** Called when audio recording is finished. Updates UI component states. */
onAudioRecorded(boolean successful)1241     private void onAudioRecorded(boolean successful) {
1242         mPlayRecordedAudio.setVisible(successful);
1243         mSaveAudio.setVisible(successful);
1244         mRecordAudio.setChecked(false);
1245 
1246         if (!successful) {
1247             Toast errorToast = Toast.makeText(getContext(),
1248                     getString(R.string.show_audio_recording_failed), Toast.LENGTH_SHORT);
1249             errorToast.show();
1250         }
1251     }
1252 
1253     /** Updates displayed audio recording metrics */
updateAudioRecordingMetrics(AudioMetrics.Data data)1254     private void updateAudioRecordingMetrics(AudioMetrics.Data data) {
1255         updateAudioRecordingMetric(mTimeToStartRead, data.timeToStartReadMs);
1256         updateAudioRecordingMetric(mTimeToValidAudio, data.timeToValidAudioMs);
1257         updateAudioRecordingMetric(mEmptyAudioDuration, data.emptyAudioDurationMs);
1258     }
1259 
updateAudioRecordingMetric(Preference preference, Optional<Long> ts)1260     private static void updateAudioRecordingMetric(Preference preference, Optional<Long> ts) {
1261         ts.ifPresent(x -> preference.setVisible(true));
1262         if (preference.isVisible()) {
1263             preference.setSummary(AudioMetrics.msTimestampToString(ts));
1264         }
1265     }
1266 
playRecordedAudio()1267     private void playRecordedAudio() {
1268         mAudioDebug.playAudio();
1269     }
1270 
saveRecordedAudio()1271     private void saveRecordedAudio() {
1272         mAudioDebug.writeAudioToFile();
1273     }
1274 
updateForceResizableOptions()1275     private void updateForceResizableOptions() {
1276         updateSwitchPreference(mForceResizable,
1277                 Settings.Global.getInt(mContentResolver,
1278                 Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0);
1279     }
1280 
writeForceResizableOptions()1281     private void writeForceResizableOptions() {
1282         Settings.Global.putInt(mContentResolver,
1283                 Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES,
1284                 mForceResizable.isChecked() ? 1 : 0);
1285     }
1286 
updateForceRtlOptions()1287     private void updateForceRtlOptions() {
1288         updateSwitchPreference(mForceRtlLayout,
1289                 Settings.Global.getInt(mContentResolver,
1290                         Settings.Global.DEVELOPMENT_FORCE_RTL, 0) != 0);
1291     }
1292 
writeForceRtlOptions()1293     private void writeForceRtlOptions() {
1294         boolean value = mForceRtlLayout.isChecked();
1295         Settings.Global.putInt(mContentResolver,
1296                 Settings.Global.DEVELOPMENT_FORCE_RTL, value ? 1 : 0);
1297         DisplayProperties.debug_force_rtl(value);
1298         LocalePicker.updateLocale(
1299                 getActivity().getResources().getConfiguration().getLocales().get(0));
1300     }
1301 
updateWifiDisplayCertificationOptions()1302     private void updateWifiDisplayCertificationOptions() {
1303         updateSwitchPreference(mWifiDisplayCertification, Settings.Global.getInt(
1304                 mContentResolver, Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON, 0) != 0);
1305     }
1306 
writeWifiDisplayCertificationOptions()1307     private void writeWifiDisplayCertificationOptions() {
1308         Settings.Global.putInt(mContentResolver,
1309                 Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON,
1310                 mWifiDisplayCertification.isChecked() ? 1 : 0);
1311     }
1312 
updateWifiVerboseLoggingOptions()1313     private void updateWifiVerboseLoggingOptions() {
1314         boolean enabled = mWifiManager != null && mWifiManager.isVerboseLoggingEnabled();
1315         updateSwitchPreference(mWifiVerboseLogging, enabled);
1316     }
1317 
writeWifiVerboseLoggingOptions()1318     private void writeWifiVerboseLoggingOptions() {
1319         if (mWifiManager != null) {
1320             mWifiManager.setVerboseLoggingEnabled(mWifiVerboseLogging.isChecked());
1321         }
1322     }
1323 
updateMobileDataAlwaysOnOptions()1324     private void updateMobileDataAlwaysOnOptions() {
1325         updateSwitchPreference(mMobileDataAlwaysOn, Settings.Global.getInt(mContentResolver,
1326                 Settings.Global.MOBILE_DATA_ALWAYS_ON, 0) != 0);
1327     }
1328 
writeMobileDataAlwaysOnOptions()1329     private void writeMobileDataAlwaysOnOptions() {
1330         Settings.Global.putInt(mContentResolver, Settings.Global.MOBILE_DATA_ALWAYS_ON,
1331                 mMobileDataAlwaysOn.isChecked() ? 1 : 0);
1332     }
1333 
updateUsbConfigurationValues()1334     private void updateUsbConfigurationValues() {
1335         if (mUsbConfiguration != null) {
1336             UsbManager manager = (UsbManager) getActivity().getSystemService(Context.USB_SERVICE);
1337 
1338             String[] values = getResources().getStringArray(R.array.usb_configuration_values);
1339             String[] titles = getResources().getStringArray(R.array.usb_configuration_titles);
1340             int index = 0;
1341             long functions = manager.getCurrentFunctions();
1342             for (int i = 0; i < titles.length; i++) {
1343                 if ((functions & UsbManager.usbFunctionsFromString(values[i])) != 0) {
1344                     index = i;
1345                     break;
1346                 }
1347             }
1348             mUsbConfiguration.setValue(values[index]);
1349             mUsbConfiguration.setSummary(titles[index]);
1350             mUsbConfiguration.setOnPreferenceChangeListener(this);
1351         }
1352     }
1353 
writeUsbConfigurationOption(Object newValue)1354     private void writeUsbConfigurationOption(Object newValue) {
1355         UsbManager manager = (UsbManager) getActivity().getSystemService(Context.USB_SERVICE);
1356         String function = newValue.toString();
1357         manager.setCurrentFunctions(UsbManager.usbFunctionsFromString(function));
1358     }
1359 
writeImmediatelyDestroyActivitiesOptions()1360     private void writeImmediatelyDestroyActivitiesOptions() {
1361         try {
1362             ActivityManager.getService().setAlwaysFinish(
1363                     mImmediatelyDestroyActivities.isChecked());
1364         } catch (RemoteException ex) {
1365             // ignore
1366         }
1367     }
1368 
updateImmediatelyDestroyActivitiesOptions()1369     private void updateImmediatelyDestroyActivitiesOptions() {
1370         updateSwitchPreference(mImmediatelyDestroyActivities, Settings.Global.getInt(
1371                 mContentResolver, Settings.Global.ALWAYS_FINISH_ACTIVITIES, 0) != 0);
1372     }
1373 
updateAnimationScaleValue(int which, ListPreference pref)1374     private void updateAnimationScaleValue(int which, ListPreference pref) {
1375         try {
1376             float scale = mWindowManager.getAnimationScale(which);
1377             if (scale != 1) {
1378                 mHaveDebugSettings = true;
1379             }
1380             CharSequence[] values = pref.getEntryValues();
1381             for (int i=0; i<values.length; i++) {
1382                 float val = Float.parseFloat(values[i].toString());
1383                 if (scale <= val) {
1384                     pref.setValueIndex(i);
1385                     pref.setSummary(pref.getEntries()[i]);
1386                     return;
1387                 }
1388             }
1389             pref.setValueIndex(values.length-1);
1390             pref.setSummary(pref.getEntries()[0]);
1391         } catch (RemoteException e) {
1392             // ignore
1393         }
1394     }
1395 
updateAnimationScaleOptions()1396     private void updateAnimationScaleOptions() {
1397         updateAnimationScaleValue(0, mWindowAnimationScale);
1398         updateAnimationScaleValue(1, mTransitionAnimationScale);
1399         updateAnimationScaleValue(2, mAnimatorDurationScale);
1400     }
1401 
writeAnimationScaleOption(int which, ListPreference pref, Object newValue)1402     private void writeAnimationScaleOption(int which, ListPreference pref, Object newValue) {
1403         try {
1404             float scale = newValue != null ? Float.parseFloat(newValue.toString()) : 1;
1405             mWindowManager.setAnimationScale(which, scale);
1406             updateAnimationScaleValue(which, pref);
1407         } catch (RemoteException e) {
1408             // ignore
1409         }
1410     }
1411 
updateOverlayDisplayDevicesOptions()1412     private void updateOverlayDisplayDevicesOptions() {
1413         String value = Settings.Global.getString(mContentResolver,
1414                 Settings.Global.OVERLAY_DISPLAY_DEVICES);
1415         if (value == null) {
1416             value = "";
1417         }
1418 
1419         CharSequence[] values = mOverlayDisplayDevices.getEntryValues();
1420         for (int i = 0; i < values.length; i++) {
1421             if (value.contentEquals(values[i])) {
1422                 mOverlayDisplayDevices.setValueIndex(i);
1423                 mOverlayDisplayDevices.setSummary(mOverlayDisplayDevices.getEntries()[i]);
1424                 return;
1425             }
1426         }
1427         mOverlayDisplayDevices.setValueIndex(0);
1428         mOverlayDisplayDevices.setSummary(mOverlayDisplayDevices.getEntries()[0]);
1429     }
1430 
writeOverlayDisplayDevicesOptions(Object newValue)1431     private void writeOverlayDisplayDevicesOptions(Object newValue) {
1432         Settings.Global.putString(mContentResolver, Settings.Global.OVERLAY_DISPLAY_DEVICES,
1433                 (String)newValue);
1434         updateOverlayDisplayDevicesOptions();
1435     }
1436 
updateOpenGLTracesOptions()1437     private void updateOpenGLTracesOptions() {
1438         String value = DisplayProperties.debug_opengl_trace().orElse("");
1439 
1440         CharSequence[] values = mOpenGLTraces.getEntryValues();
1441         for (int i = 0; i < values.length; i++) {
1442             if (value.contentEquals(values[i])) {
1443                 mOpenGLTraces.setValueIndex(i);
1444                 mOpenGLTraces.setSummary(mOpenGLTraces.getEntries()[i]);
1445                 return;
1446             }
1447         }
1448         mOpenGLTraces.setValueIndex(0);
1449         mOpenGLTraces.setSummary(mOpenGLTraces.getEntries()[0]);
1450     }
1451 
writeOpenGLTracesOptions(Object newValue)1452     private void writeOpenGLTracesOptions(Object newValue) {
1453         DisplayProperties.debug_opengl_trace(newValue == null ? "" : newValue.toString());
1454         SystemPropPoker.getInstance().poke();
1455         updateOpenGLTracesOptions();
1456     }
1457 
updateAppProcessLimitOptions()1458     private void updateAppProcessLimitOptions() {
1459         try {
1460             int limit = ActivityManager.getService().getProcessLimit();
1461             CharSequence[] values = mAppProcessLimit.getEntryValues();
1462             for (int i=0; i<values.length; i++) {
1463                 int val = Integer.parseInt(values[i].toString());
1464                 if (val >= limit) {
1465                     if (i != 0) {
1466                         mHaveDebugSettings = true;
1467                     }
1468                     mAppProcessLimit.setValueIndex(i);
1469                     mAppProcessLimit.setSummary(mAppProcessLimit.getEntries()[i]);
1470                     return;
1471                 }
1472             }
1473             mAppProcessLimit.setValueIndex(0);
1474             mAppProcessLimit.setSummary(mAppProcessLimit.getEntries()[0]);
1475         } catch (RemoteException e) {
1476             // ignore
1477         }
1478     }
1479 
writeAppProcessLimitOptions(Object newValue)1480     private void writeAppProcessLimitOptions(Object newValue) {
1481         try {
1482             int limit = newValue != null ? Integer.parseInt(newValue.toString()) : -1;
1483             ActivityManager.getService().setProcessLimit(limit);
1484             updateAppProcessLimitOptions();
1485         } catch (RemoteException e) {
1486             // ignore
1487         }
1488     }
1489 
writeShowAllANRsOptions()1490     private void writeShowAllANRsOptions() {
1491         Settings.Secure.putInt(mContentResolver, Settings.Secure.ANR_SHOW_BACKGROUND,
1492                 mShowAllANRs.isChecked() ? 1 : 0);
1493     }
1494 
updateShowAllANRsOptions()1495     private void updateShowAllANRsOptions() {
1496         updateSwitchPreference(mShowAllANRs, Settings.Secure.getInt(
1497                 mContentResolver, Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0);
1498     }
1499 
1500     @Override
onOemUnlockConfirm()1501     public void onOemUnlockConfirm() {
1502         mEnableOemUnlock.setChecked(true);
1503         setOemUnlockEnabled(getActivity(), true);
1504         updateAllOptions();
1505     }
1506 
1507     @Override
onEnableDevelopmentConfirm()1508     public void onEnableDevelopmentConfirm() {
1509         mEnableDeveloper.setChecked(true);
1510         DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(getContext(), true);
1511         mLastEnabledState = true;
1512         setPrefsEnabledState(true);
1513     }
1514 
1515     @Override
onEnableAdbConfirm()1516     public void onEnableAdbConfirm() {
1517         Settings.Global.putInt(mContentResolver, Settings.Global.ADB_ENABLED, 1);
1518         mEnableAdb.setChecked(true);
1519         updateVerifyAppsOverUsbOptions();
1520     }
1521 
1522     @Override
onActivityResult(int requestCode, int resultCode, Intent data)1523     public void onActivityResult(int requestCode, int resultCode, Intent data) {
1524         if (requestCode == RESULT_DEBUG_APP) {
1525             if (resultCode == Activity.RESULT_OK) {
1526                 mDebugApp = data.getAction();
1527                 writeDebuggerOptions();
1528                 updateDebuggerOptions();
1529             }
1530         } else if (requestCode == RESULT_MOCK_LOCATION_APP) {
1531             if (resultCode == Activity.RESULT_OK) {
1532                 mMockLocationApp = data.getAction();
1533                 writeMockLocation();
1534                 updateMockLocation();
1535             }
1536         } else {
1537             super.onActivityResult(requestCode, resultCode, data);
1538         }
1539     }
1540 
1541     @Override
onPreferenceTreeClick(Preference preference)1542     public boolean onPreferenceTreeClick(Preference preference) {
1543         if (ActivityManager.isUserAMonkey()) {
1544             return false;
1545         }
1546 
1547         if (preference == mEnableDeveloper) {
1548             if (mEnableDeveloper.isChecked()) {
1549                 // Pass to super to launch the dialog, then uncheck until the dialog
1550                 // result comes back
1551                 super.onPreferenceTreeClick(preference);
1552                 mEnableDeveloper.setChecked(false);
1553             } else {
1554                 resetDangerousOptions();
1555                 DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(getContext(), false);
1556                 mLastEnabledState = false;
1557                 setPrefsEnabledState(false);
1558             }
1559         } else if (preference == mBugreport) {
1560             captureBugReport(this.getActivity());
1561         } else if (preference == mEnableAdb) {
1562             if (mEnableAdb.isChecked()) {
1563                 // Pass to super to launch the dialog, then uncheck until the dialog
1564                 // result comes back
1565                 super.onPreferenceTreeClick(preference);
1566                 mEnableAdb.setChecked(false);
1567             } else {
1568                 Settings.Global.putInt(mContentResolver, Settings.Global.ADB_ENABLED, 0);
1569                 mVerifyAppsOverUsb.setEnabled(false);
1570                 mVerifyAppsOverUsb.setChecked(false);
1571             }
1572         } else if (preference == mEnableTerminal) {
1573             final PackageManager pm = getActivity().getPackageManager();
1574             pm.setApplicationEnabledSetting(TERMINAL_APP_PACKAGE,
1575                     mEnableTerminal.isChecked() ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
1576                             : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0);
1577         } else if (preference == mKeepScreenOn) {
1578             Settings.Global.putInt(mContentResolver, Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
1579                     mKeepScreenOn.isChecked() ?
1580                             (BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB)
1581                             : 0);
1582         } else if (preference == mEnableOemUnlock) {
1583             if (mEnableOemUnlock.isChecked()) {
1584                 // Pass to super to launch the dialog, then uncheck until the dialog
1585                 // result comes back
1586                 super.onPreferenceTreeClick(preference);
1587                 mEnableOemUnlock.setChecked(false);
1588             } else {
1589                 setOemUnlockEnabled(getActivity(), false);
1590             }
1591         } else if (preference == mMockLocationAppPref) {
1592             Intent intent = new Intent(getActivity(), AppPicker.class);
1593             intent.putExtra(AppPicker.EXTRA_REQUESTIING_PERMISSION,
1594                     Manifest.permission.ACCESS_MOCK_LOCATION);
1595             startActivityForResult(intent, RESULT_MOCK_LOCATION_APP);
1596         } else if (preference == mDebugViewAttributes) {
1597             Settings.Global.putInt(mContentResolver, Settings.Global.DEBUG_VIEW_ATTRIBUTES,
1598                     mDebugViewAttributes.isChecked() ? 1 : 0);
1599         } else if (preference == mForceAllowOnExternal) {
1600             Settings.Global.putInt(mContentResolver, Settings.Global.FORCE_ALLOW_ON_EXTERNAL,
1601                     mForceAllowOnExternal.isChecked() ? 1 : 0);
1602         } else if (preference == mDebugAppPref) {
1603             Intent intent = new Intent(getActivity(), AppPicker.class);
1604             intent.putExtra(AppPicker.EXTRA_DEBUGGABLE, true);
1605             startActivityForResult(intent, RESULT_DEBUG_APP);
1606         } else if (preference == mWaitForDebugger) {
1607             writeDebuggerOptions();
1608         } else if (preference == mVerifyAppsOverUsb) {
1609             writeVerifyAppsOverUsbOptions();
1610         } else if (preference == mStrictMode) {
1611             writeStrictModeVisualOptions();
1612         } else if (preference == mPointerLocation) {
1613             writePointerLocationOptions();
1614         } else if (preference == mShowTouches) {
1615             writeShowTouchesOptions();
1616         } else if (preference == mShowScreenUpdates) {
1617             writeShowUpdatesOption();
1618         } else if (preference == mDisableOverlays) {
1619             writeDisableOverlaysOption();
1620         } else if (preference == mImmediatelyDestroyActivities) {
1621             writeImmediatelyDestroyActivitiesOptions();
1622         } else if (preference == mShowAllANRs) {
1623             writeShowAllANRsOptions();
1624         } else if (preference == mForceMsaa) {
1625             writeMsaaOptions();
1626         } else if (preference == mShowHwScreenUpdates) {
1627             writeShowHwScreenUpdatesOptions();
1628         } else if (preference == mShowHwLayersUpdates) {
1629             writeShowHwLayersUpdatesOptions();
1630         } else if (preference == mDebugLayout) {
1631             writeDebugLayoutOptions();
1632         } else if (preference == mForceRtlLayout) {
1633             writeForceRtlOptions();
1634         } else if (preference == mWifiDisplayCertification) {
1635             writeWifiDisplayCertificationOptions();
1636         } else if (preference == mWifiVerboseLogging) {
1637             writeWifiVerboseLoggingOptions();
1638         } else if (preference == mMobileDataAlwaysOn) {
1639             writeMobileDataAlwaysOnOptions();
1640         } else if (preference == mUSBAudio) {
1641             writeUSBAudioOptions();
1642         } else if (preference == mForceResizable) {
1643             writeForceResizableOptions();
1644         } else if (preference == mRecordAudio) {
1645             writeRecordAudioOptions();
1646         } else if (preference == mSaveAudio) {
1647             saveRecordedAudio();
1648         } else if (preference == mPlayRecordedAudio) {
1649             playRecordedAudio();
1650         } else {
1651             return super.onPreferenceTreeClick(preference);
1652         }
1653 
1654         return false;
1655     }
1656 
1657     @Override
onPreferenceChange(Preference preference, Object newValue)1658     public boolean onPreferenceChange(Preference preference, Object newValue) {
1659         if (HDCP_CHECKING_KEY.equals(preference.getKey())) {
1660             SystemProperties.set(HDCP_CHECKING_PROPERTY, newValue.toString());
1661             updateHdcpValues();
1662             SystemPropPoker.getInstance().poke();
1663             return true;
1664         } else if (preference == mUsbConfiguration) {
1665             writeUsbConfigurationOption(newValue);
1666             return true;
1667         } else if (preference == mWindowAnimationScale) {
1668             writeAnimationScaleOption(0, mWindowAnimationScale, newValue);
1669             return true;
1670         } else if (preference == mTransitionAnimationScale) {
1671             writeAnimationScaleOption(1, mTransitionAnimationScale, newValue);
1672             return true;
1673         } else if (preference == mAnimatorDurationScale) {
1674             writeAnimationScaleOption(2, mAnimatorDurationScale, newValue);
1675             return true;
1676         } else if (preference == mOverlayDisplayDevices) {
1677             writeOverlayDisplayDevicesOptions(newValue);
1678             return true;
1679         } else if (preference == mOpenGLTraces) {
1680             writeOpenGLTracesOptions(newValue);
1681             return true;
1682         } else if (preference == mTrackFrameTime) {
1683             writeTrackFrameTimeOptions(newValue);
1684             return true;
1685         } else if (preference == mDebugHwOverdraw) {
1686             writeDebugHwOverdrawOptions(newValue);
1687             return true;
1688         } else if (preference == mShowNonRectClip) {
1689             writeShowNonRectClipOptions(newValue);
1690             return true;
1691         } else if (preference == mAppProcessLimit) {
1692             writeAppProcessLimitOptions(newValue);
1693             return true;
1694         } else if (preference == mSimulateColorSpace) {
1695             writeSimulateColorSpace(newValue);
1696             return true;
1697         } else if (preference == mBtHciSnoopLog) {
1698             writeBtHciSnoopLogOptions(newValue);
1699             return true;
1700         }
1701         return false;
1702     }
1703 
1704     /**
1705      * Iterates through preference controllers that show confirmation dialogs and returns the
1706      * preference key for the first currently showing dialog. Ideally there should only ever be one.
1707      * @return Preference key, or null if no dialog is showing
1708      */
getKeyForShowingDialog()1709     private String getKeyForShowingDialog() {
1710         // TODO: iterate through a fragment-wide list of PreferenceControllers and just pick out the
1711         // ConfirmationDialogController objects
1712         final List<ConfirmationDialogController> dialogControllers = new ArrayList<>(2);
1713         dialogControllers.add(mLogpersistController);
1714         for (ConfirmationDialogController dialogController : dialogControllers) {
1715             if (dialogController.isConfirmationDialogShowing()) {
1716                 return dialogController.getPreferenceKey();
1717             }
1718         }
1719         return null;
1720     }
1721 
1722     /**
1723      * Re-show the dialog we lost previously
1724      * @param preferenceKey Key for the preference the dialog is for
1725      */
recreateDialogForKey(String preferenceKey)1726     private void recreateDialogForKey(String preferenceKey) {
1727         // TODO: iterate through a fragment-wide list of PreferenceControllers and just pick out the
1728         // ConfirmationDialogController objects
1729         final List<ConfirmationDialogController> dialogControllers = new ArrayList<>(2);
1730         dialogControllers.add(mLogpersistController);
1731         for (ConfirmationDialogController dialogController : dialogControllers) {
1732             if (TextUtils.equals(preferenceKey, dialogController.getPreferenceKey())) {
1733                 dialogController.showConfirmationDialog(findPreference(preferenceKey));
1734             }
1735         }
1736     }
1737 
dismissDialogs()1738     private void dismissDialogs() {
1739         mLogpersistController.dismissConfirmationDialog();
1740     }
1741 
1742     private BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
1743         @Override
1744         public void onReceive(Context context, Intent intent) {
1745             updateUsbConfigurationValues();
1746         }
1747     };
1748 
isPackageInstalled(Context context, String packageName)1749     private static boolean isPackageInstalled(Context context, String packageName) {
1750         try {
1751             return context.getPackageManager().getPackageInfo(packageName, 0) != null;
1752         } catch (PackageManager.NameNotFoundException e) {
1753             return false;
1754         }
1755     }
1756 
1757     /**
1758      * Returns whether or not this device is able to be OEM unlocked.
1759      */
isOemUnlockEnabled(Context context)1760     static boolean isOemUnlockEnabled(Context context) {
1761         PersistentDataBlockManager manager =(PersistentDataBlockManager)
1762                 context.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
1763         return manager.getOemUnlockEnabled();
1764     }
1765 
1766     /**
1767      * Allows enabling or disabling OEM unlock on this device. OEM unlocked
1768      * devices allow users to flash other OSes to them.
1769      */
setOemUnlockEnabled(Context context, boolean enabled)1770     static void setOemUnlockEnabled(Context context, boolean enabled) {
1771         try {
1772             PersistentDataBlockManager manager = (PersistentDataBlockManager)
1773                     context.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
1774             manager.setOemUnlockEnabled(enabled);
1775         } catch (SecurityException e) {
1776             Log.e(TAG, "Fail to set oem unlock.", e);
1777         }
1778     }
1779 }
1780