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