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