DevelopmentSettings.java revision 19ba3202634762e4670827568b79b45f5793b1ca
1/*
2 * Copyright (C) 2008 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
17package com.android.settings.development;
18
19import android.Manifest;
20import android.app.Activity;
21import android.app.ActivityManager;
22import android.app.AlertDialog;
23import android.app.AppOpsManager;
24import android.app.AppOpsManager.PackageOps;
25import android.app.Dialog;
26import android.app.backup.IBackupManager;
27import android.bluetooth.BluetoothA2dp;
28import android.bluetooth.BluetoothAdapter;
29import android.bluetooth.BluetoothCodecConfig;
30import android.bluetooth.BluetoothCodecStatus;
31import android.bluetooth.BluetoothHeadset;
32import android.bluetooth.BluetoothProfile;
33import android.content.BroadcastReceiver;
34import android.content.ContentResolver;
35import android.content.Context;
36import android.content.DialogInterface;
37import android.content.Intent;
38import android.content.IntentFilter;
39import android.content.pm.ApplicationInfo;
40import android.content.pm.IShortcutService;
41import android.content.pm.PackageManager;
42import android.content.pm.PackageManager.NameNotFoundException;
43import android.content.res.Resources;
44import android.hardware.usb.IUsbManager;
45import android.hardware.usb.UsbManager;
46import android.net.wifi.WifiManager;
47import android.os.AsyncTask;
48import android.os.BatteryManager;
49import android.os.Build;
50import android.os.Bundle;
51import android.os.IBinder;
52import android.os.Parcel;
53import android.os.RemoteException;
54import android.os.ServiceManager;
55import android.os.StrictMode;
56import android.os.SystemProperties;
57import android.os.UserManager;
58import android.os.storage.IStorageManager;
59import android.provider.SearchIndexableResource;
60import android.provider.Settings;
61import android.service.oemlock.OemLockManager;
62import android.support.annotation.VisibleForTesting;
63import android.support.v14.preference.SwitchPreference;
64import android.support.v4.content.LocalBroadcastManager;
65import android.support.v7.preference.ListPreference;
66import android.support.v7.preference.Preference;
67import android.support.v7.preference.Preference.OnPreferenceChangeListener;
68import android.support.v7.preference.PreferenceGroup;
69import android.support.v7.preference.PreferenceScreen;
70import android.telephony.TelephonyManager;
71import android.text.TextUtils;
72import android.util.Log;
73import android.view.IWindowManager;
74import android.view.LayoutInflater;
75import android.view.ThreadedRenderer;
76import android.view.View;
77import android.view.ViewGroup;
78import android.view.accessibility.AccessibilityManager;
79import android.webkit.IWebViewUpdateService;
80import android.webkit.WebViewFactory;
81import android.widget.Switch;
82import android.widget.Toast;
83
84import com.android.internal.app.LocalePicker;
85import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
86import com.android.settings.R;
87import com.android.settings.RestrictedSettingsFragment;
88import com.android.settings.SettingsActivity;
89import com.android.settings.Utils;
90import com.android.settings.dashboard.DashboardFeatureProvider;
91import com.android.settings.overlay.FeatureFactory;
92import com.android.settings.password.ChooseLockSettingsHelper;
93import com.android.settings.search.BaseSearchIndexProvider;
94import com.android.settings.search.Indexable;
95import com.android.settings.webview.WebViewAppPreferenceController;
96import com.android.settings.widget.SwitchBar;
97import com.android.settingslib.RestrictedLockUtils;
98import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
99import com.android.settingslib.RestrictedSwitchPreference;
100import com.android.settingslib.development.AbstractEnableAdbPreferenceController;
101import com.android.settingslib.drawer.CategoryKey;
102
103import java.util.ArrayList;
104import java.util.Arrays;
105import java.util.HashSet;
106import java.util.List;
107
108/*
109 * Displays preferences for application developers.
110 */
111public class DevelopmentSettings extends RestrictedSettingsFragment
112        implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
113        OnPreferenceChangeListener, SwitchBar.OnSwitchChangeListener, Indexable {
114    private static final String TAG = "DevelopmentSettings";
115
116    /**
117     * Preference file were development settings prefs are stored.
118     */
119    public static final String PREF_FILE = "development";
120
121    /**
122     * Whether to show the development settings to the user.  Default is false.
123     */
124    public static final String PREF_SHOW = "show";
125
126    private static final String CLEAR_ADB_KEYS = "clear_adb_keys";
127    private static final String ENABLE_TERMINAL = "enable_terminal";
128    private static final String KEEP_SCREEN_ON = "keep_screen_on";
129    private static final String BT_HCI_SNOOP_LOG = "bt_hci_snoop_log";
130    private static final String ENABLE_OEM_UNLOCK = "oem_unlock_enable";
131    private static final String HDCP_CHECKING_KEY = "hdcp_checking";
132    private static final String HDCP_CHECKING_PROPERTY = "persist.sys.hdcp_checking";
133    private static final String LOCAL_BACKUP_PASSWORD = "local_backup_password";
134    private static final String HARDWARE_UI_PROPERTY = "persist.sys.ui.hw";
135    private static final String MSAA_PROPERTY = "debug.egl.force_msaa";
136    private static final String OPENGL_TRACES_PROPERTY = "debug.egl.trace";
137    private static final String TUNER_UI_KEY = "tuner_ui";
138    private static final String COLOR_TEMPERATURE_PROPERTY = "persist.sys.debug.color_temp";
139
140    private static final String DEBUG_APP_KEY = "debug_app";
141    private static final String WAIT_FOR_DEBUGGER_KEY = "wait_for_debugger";
142    private static final String MOCK_LOCATION_APP_KEY = "mock_location_app";
143    private static final String DEBUG_VIEW_ATTRIBUTES = "debug_view_attributes";
144    private static final String FORCE_ALLOW_ON_EXTERNAL_KEY = "force_allow_on_external";
145    private static final String STRICT_MODE_KEY = "strict_mode";
146    private static final String POINTER_LOCATION_KEY = "pointer_location";
147    private static final String SHOW_TOUCHES_KEY = "show_touches";
148    private static final String SHOW_SCREEN_UPDATES_KEY = "show_screen_updates";
149    private static final String DISABLE_OVERLAYS_KEY = "disable_overlays";
150    private static final String SIMULATE_COLOR_SPACE = "simulate_color_space";
151    private static final String USB_AUDIO_KEY = "usb_audio";
152    private static final String FORCE_HARDWARE_UI_KEY = "force_hw_ui";
153    private static final String FORCE_MSAA_KEY = "force_msaa";
154    private static final String TRACK_FRAME_TIME_KEY = "track_frame_time";
155    private static final String SHOW_NON_RECTANGULAR_CLIP_KEY = "show_non_rect_clip";
156    private static final String SHOW_HW_SCREEN_UPDATES_KEY = "show_hw_screen_udpates";
157    private static final String SHOW_HW_LAYERS_UPDATES_KEY = "show_hw_layers_udpates";
158    private static final String DEBUG_HW_OVERDRAW_KEY = "debug_hw_overdraw";
159    private static final String DEBUG_HW_RENDERER_KEY = "debug_hw_renderer";
160    private static final String DEBUG_LAYOUT_KEY = "debug_layout";
161    private static final String FORCE_RTL_LAYOUT_KEY = "force_rtl_layout_all_locales";
162    private static final String WINDOW_ANIMATION_SCALE_KEY = "window_animation_scale";
163    private static final String TRANSITION_ANIMATION_SCALE_KEY = "transition_animation_scale";
164    private static final String ANIMATOR_DURATION_SCALE_KEY = "animator_duration_scale";
165    private static final String OVERLAY_DISPLAY_DEVICES_KEY = "overlay_display_devices";
166    private static final String DEBUG_DEBUGGING_CATEGORY_KEY = "debug_debugging_category";
167    private static final String SELECT_LOGD_SIZE_KEY = "select_logd_size";
168    private static final String SELECT_LOGD_SIZE_PROPERTY = "persist.logd.size";
169    private static final String SELECT_LOGD_TAG_PROPERTY = "persist.log.tag";
170    // Tricky, isLoggable only checks for first character, assumes silence
171    private static final String SELECT_LOGD_TAG_SILENCE = "Settings";
172    private static final String SELECT_LOGD_SNET_TAG_PROPERTY = "persist.log.tag.snet_event_log";
173    private static final String SELECT_LOGD_RUNTIME_SNET_TAG_PROPERTY = "log.tag.snet_event_log";
174    private static final String SELECT_LOGD_DEFAULT_SIZE_PROPERTY = "ro.logd.size";
175    private static final String SELECT_LOGD_DEFAULT_SIZE_VALUE = "262144";
176    private static final String SELECT_LOGD_SVELTE_DEFAULT_SIZE_VALUE = "65536";
177    // 32768 is merely a menu marker, 64K is our lowest log buffer size we replace it with.
178    private static final String SELECT_LOGD_MINIMUM_SIZE_VALUE = "65536";
179    private static final String SELECT_LOGD_OFF_SIZE_MARKER_VALUE = "32768";
180    private static final String SELECT_LOGPERSIST_KEY = "select_logpersist";
181    private static final String SELECT_LOGPERSIST_PROPERTY = "persist.logd.logpersistd";
182    private static final String ACTUAL_LOGPERSIST_PROPERTY = "logd.logpersistd";
183    private static final String SELECT_LOGPERSIST_PROPERTY_SERVICE = "logcatd";
184    private static final String SELECT_LOGPERSIST_PROPERTY_CLEAR = "clear";
185    private static final String SELECT_LOGPERSIST_PROPERTY_STOP = "stop";
186    private static final String SELECT_LOGPERSIST_PROPERTY_BUFFER =
187            "persist.logd.logpersistd.buffer";
188    private static final String ACTUAL_LOGPERSIST_PROPERTY_BUFFER = "logd.logpersistd.buffer";
189    private static final String ACTUAL_LOGPERSIST_PROPERTY_ENABLE = "logd.logpersistd.enable";
190
191    private static final String WIFI_DISPLAY_CERTIFICATION_KEY = "wifi_display_certification";
192    private static final String WIFI_VERBOSE_LOGGING_KEY = "wifi_verbose_logging";
193    private static final String WIFI_AGGRESSIVE_HANDOVER_KEY = "wifi_aggressive_handover";
194    private static final String WIFI_ALLOW_SCAN_WITH_TRAFFIC_KEY = "wifi_allow_scan_with_traffic";
195    private static final String USB_CONFIGURATION_KEY = "select_usb_configuration";
196    private static final String MOBILE_DATA_ALWAYS_ON = "mobile_data_always_on";
197    private static final String TETHERING_HARDWARE_OFFLOAD = "tethering_hardware_offload";
198    private static final String KEY_COLOR_MODE = "picture_color_mode";
199    private static final String FORCE_RESIZABLE_KEY = "force_resizable_activities";
200    private static final String COLOR_TEMPERATURE_KEY = "color_temperature";
201
202    private static final String BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_KEY =
203            "bluetooth_show_devices_without_names";
204    private static final String BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY =
205            "persist.bluetooth.showdeviceswithoutnames";
206    private static final String BLUETOOTH_DISABLE_ABSOLUTE_VOLUME_KEY =
207            "bluetooth_disable_absolute_volume";
208    private static final String BLUETOOTH_DISABLE_ABSOLUTE_VOLUME_PROPERTY =
209            "persist.bluetooth.disableabsvol";
210    private static final String BLUETOOTH_AVRCP_VERSION_PROPERTY =
211                                    "persist.bluetooth.avrcpversion";
212    private static final String BLUETOOTH_ENABLE_INBAND_RINGING_PROPERTY =
213                                    "persist.bluetooth.enableinbandringing";
214    private static final String BLUETOOTH_BTSNOOP_ENABLE_PROPERTY =
215                                    "persist.bluetooth.btsnoopenable";
216
217    private static final String BLUETOOTH_ENABLE_INBAND_RINGING_KEY = "bluetooth_enable_inband_ringing";
218    private static final String BLUETOOTH_SELECT_AVRCP_VERSION_KEY = "bluetooth_select_avrcp_version";
219    private static final String BLUETOOTH_SELECT_A2DP_CODEC_KEY = "bluetooth_select_a2dp_codec";
220    private static final String BLUETOOTH_SELECT_A2DP_SAMPLE_RATE_KEY = "bluetooth_select_a2dp_sample_rate";
221    private static final String BLUETOOTH_SELECT_A2DP_BITS_PER_SAMPLE_KEY = "bluetooth_select_a2dp_bits_per_sample";
222    private static final String BLUETOOTH_SELECT_A2DP_CHANNEL_MODE_KEY = "bluetooth_select_a2dp_channel_mode";
223    private static final String BLUETOOTH_SELECT_A2DP_LDAC_PLAYBACK_QUALITY_KEY = "bluetooth_select_a2dp_ldac_playback_quality";
224
225    private static final String INACTIVE_APPS_KEY = "inactive_apps";
226
227    private static final String IMMEDIATELY_DESTROY_ACTIVITIES_KEY
228            = "immediately_destroy_activities";
229    private static final String APP_PROCESS_LIMIT_KEY = "app_process_limit";
230
231    private static final String BACKGROUND_CHECK_KEY = "background_check";
232
233    private static final String SHOW_ALL_ANRS_KEY = "show_all_anrs";
234
235    private static final String SHOW_NOTIFICATION_CHANNEL_WARNINGS_KEY = "show_notification_channel_warnings";
236
237    private static final String TERMINAL_APP_PACKAGE = "com.android.terminal";
238
239    private static final String KEY_CONVERT_FBE = "convert_to_file_encryption";
240
241    private static final String OTA_DISABLE_AUTOMATIC_UPDATE_KEY = "ota_disable_automatic_update";
242
243    private static final int RESULT_DEBUG_APP = 1000;
244    private static final int RESULT_MOCK_LOCATION_APP = 1001;
245
246    private static final String FLASH_LOCKED_PROP = "ro.boot.flash.locked";
247
248    private static final String SHORTCUT_MANAGER_RESET_KEY = "reset_shortcut_manager_throttling";
249
250    private static final int REQUEST_CODE_ENABLE_OEM_UNLOCK = 0;
251
252    private static final int[] MOCK_LOCATION_APP_OPS = new int[]{AppOpsManager.OP_MOCK_LOCATION};
253
254    private IWindowManager mWindowManager;
255    private IBackupManager mBackupManager;
256    private IWebViewUpdateService mWebViewUpdateService;
257    private UserManager mUm;
258    private WifiManager mWifiManager;
259    private OemLockManager mOemLockManager;
260    private TelephonyManager mTelephonyManager;
261
262    private SwitchBar mSwitchBar;
263
264    private boolean mHaveDebugSettings;
265    private boolean mDontPokeProperties;
266    private EnableAdbPreferenceController mEnableAdbController;
267    private Preference mClearAdbKeys;
268    private SwitchPreference mEnableTerminal;
269    private RestrictedSwitchPreference mKeepScreenOn;
270    private SwitchPreference mBtHciSnoopLog;
271    private RestrictedSwitchPreference mEnableOemUnlock;
272    private SwitchPreference mDebugViewAttributes;
273    private SwitchPreference mForceAllowOnExternal;
274
275    private Preference mPassword;
276    private String mDebugApp;
277    private Preference mDebugAppPref;
278
279    private String mMockLocationApp;
280    private Preference mMockLocationAppPref;
281
282    private SwitchPreference mWaitForDebugger;
283    private VerifyAppsOverUsbPreferenceController mVerifyAppsOverUsbController;
284    private SwitchPreference mWifiDisplayCertification;
285    private SwitchPreference mWifiVerboseLogging;
286    private SwitchPreference mWifiAggressiveHandover;
287    private SwitchPreference mMobileDataAlwaysOn;
288    private SwitchPreference mTetheringHardwareOffload;
289    private SwitchPreference mBluetoothShowDevicesWithoutNames;
290    private SwitchPreference mBluetoothDisableAbsVolume;
291    private SwitchPreference mBluetoothEnableInbandRinging;
292
293    private BluetoothA2dp mBluetoothA2dp;
294    private final Object mBluetoothA2dpLock = new Object();
295    private ListPreference mBluetoothSelectAvrcpVersion;
296    private ListPreference mBluetoothSelectA2dpCodec;
297    private ListPreference mBluetoothSelectA2dpSampleRate;
298    private ListPreference mBluetoothSelectA2dpBitsPerSample;
299    private ListPreference mBluetoothSelectA2dpChannelMode;
300    private ListPreference mBluetoothSelectA2dpLdacPlaybackQuality;
301
302    private SwitchPreference mOtaDisableAutomaticUpdate;
303    private SwitchPreference mWifiAllowScansWithTraffic;
304    private SwitchPreference mStrictMode;
305    private SwitchPreference mPointerLocation;
306    private SwitchPreference mShowTouches;
307    private SwitchPreference mShowScreenUpdates;
308    private SwitchPreference mDisableOverlays;
309    private SwitchPreference mForceHardwareUi;
310    private SwitchPreference mForceMsaa;
311    private SwitchPreference mShowHwScreenUpdates;
312    private SwitchPreference mShowHwLayersUpdates;
313    private SwitchPreference mDebugLayout;
314    private SwitchPreference mForceRtlLayout;
315    private ListPreference mDebugHwOverdraw;
316    private ListPreference mDebugHwRenderer;
317    private ListPreference mLogdSize;
318    private ListPreference mLogpersist;
319    private ListPreference mUsbConfiguration;
320    private ListPreference mTrackFrameTime;
321    private ListPreference mShowNonRectClip;
322    private ListPreference mWindowAnimationScale;
323    private ListPreference mTransitionAnimationScale;
324    private ListPreference mAnimatorDurationScale;
325    private ListPreference mOverlayDisplayDevices;
326
327    private WebViewAppPreferenceController mWebViewAppPrefController;
328
329    private ListPreference mSimulateColorSpace;
330
331    private SwitchPreference mUSBAudio;
332    private SwitchPreference mImmediatelyDestroyActivities;
333
334    private ListPreference mAppProcessLimit;
335
336    private SwitchPreference mShowAllANRs;
337
338    private SwitchPreference mShowNotificationChannelWarnings;
339
340    private ColorModePreference mColorModePreference;
341
342    private SwitchPreference mForceResizable;
343
344    private SwitchPreference mColorTemperaturePreference;
345
346    private final ArrayList<Preference> mAllPrefs = new ArrayList<>();
347
348    private final ArrayList<SwitchPreference> mResetSwitchPrefs = new ArrayList<>();
349
350    private final HashSet<Preference> mDisabledPrefs = new HashSet<>();
351    // To track whether a confirmation dialog was clicked.
352    private boolean mDialogClicked;
353    private Dialog mEnableDialog;
354
355    private Dialog mAdbKeysDialog;
356    private boolean mUnavailable;
357
358    private boolean mLogpersistCleared;
359    private Dialog mLogpersistClearDialog;
360    private DashboardFeatureProvider mDashboardFeatureProvider;
361    private DevelopmentSettingsEnabler mSettingsEnabler;
362    private DevelopmentSwitchBarController mSwitchBarController;
363    private BugReportPreferenceController mBugReportController;
364    private BugReportInPowerPreferenceController mBugReportInPowerController;
365    private TelephonyMonitorPreferenceController mTelephonyMonitorController;
366    private CameraHalHdrplusPreferenceController mCameraHalHdrplusController;
367
368    private BroadcastReceiver mEnableAdbReceiver;
369
370    public DevelopmentSettings() {
371        super(UserManager.DISALLOW_DEBUGGING_FEATURES);
372    }
373
374    @Override
375    public int getMetricsCategory() {
376        return MetricsEvent.DEVELOPMENT;
377    }
378
379    @Override
380    public void onAttach(Context context) {
381        super.onAttach(context);
382        mSettingsEnabler = new DevelopmentSettingsEnabler(context, getLifecycle());
383        mDashboardFeatureProvider = FeatureFactory.getFactory(context)
384                .getDashboardFeatureProvider(context);
385    }
386
387    @Override
388    public void onCreate(Bundle icicle) {
389        super.onCreate(icicle);
390
391        mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
392        mBackupManager = IBackupManager.Stub.asInterface(
393                ServiceManager.getService(Context.BACKUP_SERVICE));
394        mWebViewUpdateService = WebViewFactory.getUpdateService();
395        mOemLockManager = (OemLockManager) getSystemService(Context.OEM_LOCK_SERVICE);
396        mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
397
398        mUm = (UserManager) getSystemService(Context.USER_SERVICE);
399
400        mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
401
402        mBugReportController = new BugReportPreferenceController(getActivity());
403        mBugReportInPowerController = new BugReportInPowerPreferenceController(getActivity());
404        mTelephonyMonitorController = new TelephonyMonitorPreferenceController(getActivity());
405        mWebViewAppPrefController = new WebViewAppPreferenceController(getActivity());
406        mVerifyAppsOverUsbController = new VerifyAppsOverUsbPreferenceController(getActivity());
407        mCameraHalHdrplusController = new CameraHalHdrplusPreferenceController(getActivity());
408
409        setIfOnlyAvailableForAdmins(true);
410        if (isUiRestricted() || !Utils.isDeviceProvisioned(getActivity())) {
411            // Block access to developer options if the user is not the owner, if user policy
412            // restricts it, or if the device has not been provisioned
413            mUnavailable = true;
414            addPreferencesFromResource(R.xml.placeholder_prefs);
415            return;
416        }
417
418        addPreferencesFromResource(R.xml.development_prefs);
419
420        final PreferenceGroup debugDebuggingCategory = (PreferenceGroup)
421                findPreference(DEBUG_DEBUGGING_CATEGORY_KEY);
422        mEnableAdbController = new EnableAdbPreferenceController(getActivity());
423        mClearAdbKeys = findPreference(CLEAR_ADB_KEYS);
424        if (!SystemProperties.getBoolean("ro.adb.secure", false)) {
425            if (debugDebuggingCategory != null) {
426                debugDebuggingCategory.removePreference(mClearAdbKeys);
427            }
428        }
429        mAllPrefs.add(mClearAdbKeys);
430        mEnableTerminal = findAndInitSwitchPref(ENABLE_TERMINAL);
431        if (!isPackageInstalled(getActivity(), TERMINAL_APP_PACKAGE)) {
432            debugDebuggingCategory.removePreference(mEnableTerminal);
433            mEnableTerminal = null;
434        }
435
436        mBugReportController.displayPreference(getPreferenceScreen());
437        mBugReportInPowerController.displayPreference(getPreferenceScreen());
438        mTelephonyMonitorController.displayPreference(getPreferenceScreen());
439        mWebViewAppPrefController.displayPreference(getPreferenceScreen());
440        mCameraHalHdrplusController.displayPreference(getPreferenceScreen());
441        mEnableAdbController.displayPreference(getPreferenceScreen());
442
443        mKeepScreenOn = (RestrictedSwitchPreference) findAndInitSwitchPref(KEEP_SCREEN_ON);
444        mBtHciSnoopLog = findAndInitSwitchPref(BT_HCI_SNOOP_LOG);
445        mEnableOemUnlock = (RestrictedSwitchPreference) findAndInitSwitchPref(ENABLE_OEM_UNLOCK);
446        if (!showEnableOemUnlockPreference(getActivity())) {
447            removePreference(mEnableOemUnlock);
448            mEnableOemUnlock = null;
449        }
450
451        mDebugViewAttributes = findAndInitSwitchPref(DEBUG_VIEW_ATTRIBUTES);
452        mForceAllowOnExternal = findAndInitSwitchPref(FORCE_ALLOW_ON_EXTERNAL_KEY);
453        mPassword = findPreference(LOCAL_BACKUP_PASSWORD);
454        mAllPrefs.add(mPassword);
455
456        if (!mUm.isAdminUser()) {
457            disableForUser(mClearAdbKeys);
458            disableForUser(mEnableTerminal);
459            disableForUser(mPassword);
460        }
461
462        mDebugAppPref = findPreference(DEBUG_APP_KEY);
463        mAllPrefs.add(mDebugAppPref);
464        mWaitForDebugger = findAndInitSwitchPref(WAIT_FOR_DEBUGGER_KEY);
465
466        mMockLocationAppPref = findPreference(MOCK_LOCATION_APP_KEY);
467        mAllPrefs.add(mMockLocationAppPref);
468
469        mVerifyAppsOverUsbController.displayPreference(getPreferenceScreen());
470
471        mStrictMode = findAndInitSwitchPref(STRICT_MODE_KEY);
472        mPointerLocation = findAndInitSwitchPref(POINTER_LOCATION_KEY);
473        mShowTouches = findAndInitSwitchPref(SHOW_TOUCHES_KEY);
474        mShowScreenUpdates = findAndInitSwitchPref(SHOW_SCREEN_UPDATES_KEY);
475        mDisableOverlays = findAndInitSwitchPref(DISABLE_OVERLAYS_KEY);
476        mForceHardwareUi = findAndInitSwitchPref(FORCE_HARDWARE_UI_KEY);
477        mForceMsaa = findAndInitSwitchPref(FORCE_MSAA_KEY);
478        mTrackFrameTime = addListPreference(TRACK_FRAME_TIME_KEY);
479        mShowNonRectClip = addListPreference(SHOW_NON_RECTANGULAR_CLIP_KEY);
480        mShowHwScreenUpdates = findAndInitSwitchPref(SHOW_HW_SCREEN_UPDATES_KEY);
481        mShowHwLayersUpdates = findAndInitSwitchPref(SHOW_HW_LAYERS_UPDATES_KEY);
482        mDebugLayout = findAndInitSwitchPref(DEBUG_LAYOUT_KEY);
483        mForceRtlLayout = findAndInitSwitchPref(FORCE_RTL_LAYOUT_KEY);
484        mDebugHwOverdraw = addListPreference(DEBUG_HW_OVERDRAW_KEY);
485        mDebugHwRenderer = addListPreference(DEBUG_HW_RENDERER_KEY);
486        mWifiDisplayCertification = findAndInitSwitchPref(WIFI_DISPLAY_CERTIFICATION_KEY);
487        mWifiVerboseLogging = findAndInitSwitchPref(WIFI_VERBOSE_LOGGING_KEY);
488        mWifiAggressiveHandover = findAndInitSwitchPref(WIFI_AGGRESSIVE_HANDOVER_KEY);
489        mWifiAllowScansWithTraffic = findAndInitSwitchPref(WIFI_ALLOW_SCAN_WITH_TRAFFIC_KEY);
490        mMobileDataAlwaysOn = findAndInitSwitchPref(MOBILE_DATA_ALWAYS_ON);
491        mTetheringHardwareOffload = findAndInitSwitchPref(TETHERING_HARDWARE_OFFLOAD);
492        mLogdSize = addListPreference(SELECT_LOGD_SIZE_KEY);
493        if ("1".equals(SystemProperties.get("ro.debuggable", "0"))) {
494            mLogpersist = addListPreference(SELECT_LOGPERSIST_KEY);
495        } else {
496            mLogpersist = (ListPreference) findPreference(SELECT_LOGPERSIST_KEY);
497            if (mLogpersist != null) {
498                mLogpersist.setEnabled(false);
499                if (debugDebuggingCategory != null) {
500                    debugDebuggingCategory.removePreference(mLogpersist);
501                }
502            }
503            mLogpersist = null;
504        }
505        mUsbConfiguration = addListPreference(USB_CONFIGURATION_KEY);
506        mBluetoothShowDevicesWithoutNames =
507                findAndInitSwitchPref(BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_KEY);
508        mBluetoothDisableAbsVolume = findAndInitSwitchPref(BLUETOOTH_DISABLE_ABSOLUTE_VOLUME_KEY);
509        mBluetoothEnableInbandRinging = findAndInitSwitchPref(BLUETOOTH_ENABLE_INBAND_RINGING_KEY);
510        if (!BluetoothHeadset.isInbandRingingSupported(getContext())) {
511            removePreference(mBluetoothEnableInbandRinging);
512            mBluetoothEnableInbandRinging = null;
513        }
514
515        mBluetoothSelectAvrcpVersion = addListPreference(BLUETOOTH_SELECT_AVRCP_VERSION_KEY);
516        mBluetoothSelectA2dpCodec = addListPreference(BLUETOOTH_SELECT_A2DP_CODEC_KEY);
517        mBluetoothSelectA2dpSampleRate = addListPreference(BLUETOOTH_SELECT_A2DP_SAMPLE_RATE_KEY);
518        mBluetoothSelectA2dpBitsPerSample = addListPreference(BLUETOOTH_SELECT_A2DP_BITS_PER_SAMPLE_KEY);
519        mBluetoothSelectA2dpChannelMode = addListPreference(BLUETOOTH_SELECT_A2DP_CHANNEL_MODE_KEY);
520        mBluetoothSelectA2dpLdacPlaybackQuality = addListPreference(BLUETOOTH_SELECT_A2DP_LDAC_PLAYBACK_QUALITY_KEY);
521        initBluetoothConfigurationValues();
522
523        mWindowAnimationScale = addListPreference(WINDOW_ANIMATION_SCALE_KEY);
524        mTransitionAnimationScale = addListPreference(TRANSITION_ANIMATION_SCALE_KEY);
525        mAnimatorDurationScale = addListPreference(ANIMATOR_DURATION_SCALE_KEY);
526        mOverlayDisplayDevices = addListPreference(OVERLAY_DISPLAY_DEVICES_KEY);
527        mSimulateColorSpace = addListPreference(SIMULATE_COLOR_SPACE);
528        mUSBAudio = findAndInitSwitchPref(USB_AUDIO_KEY);
529        mForceResizable = findAndInitSwitchPref(FORCE_RESIZABLE_KEY);
530
531        mImmediatelyDestroyActivities = (SwitchPreference) findPreference(
532                IMMEDIATELY_DESTROY_ACTIVITIES_KEY);
533        mAllPrefs.add(mImmediatelyDestroyActivities);
534        mResetSwitchPrefs.add(mImmediatelyDestroyActivities);
535
536        mAppProcessLimit = addListPreference(APP_PROCESS_LIMIT_KEY);
537
538        mShowAllANRs = (SwitchPreference) findPreference(
539                SHOW_ALL_ANRS_KEY);
540        mAllPrefs.add(mShowAllANRs);
541        mResetSwitchPrefs.add(mShowAllANRs);
542
543        mShowNotificationChannelWarnings = (SwitchPreference) findPreference(
544                SHOW_NOTIFICATION_CHANNEL_WARNINGS_KEY);
545        mAllPrefs.add(mShowNotificationChannelWarnings);
546        mResetSwitchPrefs.add(mShowNotificationChannelWarnings);
547
548        Preference hdcpChecking = findPreference(HDCP_CHECKING_KEY);
549        if (hdcpChecking != null) {
550            mAllPrefs.add(hdcpChecking);
551            removePreferenceForProduction(hdcpChecking);
552        }
553
554        Preference convertFbePreference = findPreference(KEY_CONVERT_FBE);
555
556        try {
557            IBinder service = ServiceManager.getService("mount");
558            IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
559            if (!storageManager.isConvertibleToFBE()) {
560                removePreference(KEY_CONVERT_FBE);
561            } else if ("file".equals(SystemProperties.get("ro.crypto.type", "none"))) {
562                convertFbePreference.setEnabled(false);
563                convertFbePreference.setSummary(getResources()
564                        .getString(R.string.convert_to_file_encryption_done));
565            }
566        } catch (RemoteException e) {
567            removePreference(KEY_CONVERT_FBE);
568        }
569
570        mOtaDisableAutomaticUpdate = findAndInitSwitchPref(OTA_DISABLE_AUTOMATIC_UPDATE_KEY);
571
572        mColorModePreference = (ColorModePreference) findPreference(KEY_COLOR_MODE);
573        mColorModePreference.updateCurrentAndSupported();
574        if (mColorModePreference.getColorModeCount() < 2 ||
575                getContext().getDisplay().isWideColorGamut()) {
576            removePreference(KEY_COLOR_MODE);
577            mColorModePreference = null;
578        }
579
580        mColorTemperaturePreference = (SwitchPreference) findPreference(COLOR_TEMPERATURE_KEY);
581        if (getResources().getBoolean(R.bool.config_enableColorTemperature)) {
582            mAllPrefs.add(mColorTemperaturePreference);
583            mResetSwitchPrefs.add(mColorTemperaturePreference);
584        } else {
585            removePreference(COLOR_TEMPERATURE_KEY);
586            mColorTemperaturePreference = null;
587        }
588
589        addDashboardCategoryPreferences();
590    }
591
592    @VisibleForTesting
593    void addDashboardCategoryPreferences() {
594        final PreferenceScreen screen = getPreferenceScreen();
595        final List<Preference> tilePrefs = mDashboardFeatureProvider.getPreferencesForCategory(
596                getActivity(), getPrefContext(), getMetricsCategory(),
597                CategoryKey.CATEGORY_SYSTEM_DEVELOPMENT);
598        if (tilePrefs != null) {
599            for (Preference preference : tilePrefs) {
600                screen.addPreference(preference);
601            }
602        }
603    }
604
605    private ListPreference addListPreference(String prefKey) {
606        ListPreference pref = (ListPreference) findPreference(prefKey);
607        mAllPrefs.add(pref);
608        pref.setOnPreferenceChangeListener(this);
609        return pref;
610    }
611
612    private void disableForUser(Preference pref) {
613        if (pref != null) {
614            pref.setEnabled(false);
615            mDisabledPrefs.add(pref);
616        }
617    }
618
619    private SwitchPreference findAndInitSwitchPref(String key) {
620        SwitchPreference pref = (SwitchPreference) findPreference(key);
621        if (pref == null) {
622            throw new IllegalArgumentException("Cannot find preference with key = " + key);
623        }
624        mAllPrefs.add(pref);
625        mResetSwitchPrefs.add(pref);
626        return pref;
627    }
628
629    @Override
630    public void onActivityCreated(Bundle savedInstanceState) {
631        super.onActivityCreated(savedInstanceState);
632
633        mSwitchBar = ((SettingsActivity) getActivity()).getSwitchBar();
634        mSwitchBarController = new DevelopmentSwitchBarController(
635                this /* DevelopmentSettings */, mSwitchBar, !mUnavailable,  getLifecycle());
636    }
637
638    private boolean removePreferenceForProduction(Preference preference) {
639        if ("user".equals(Build.TYPE)) {
640            removePreference(preference);
641            return true;
642        }
643        return false;
644    }
645
646    private void removePreference(Preference preference) {
647        getPreferenceScreen().removePreference(preference);
648        mAllPrefs.remove(preference);
649        mResetSwitchPrefs.remove(preference);
650    }
651
652    private void setPrefsEnabledState(boolean enabled) {
653        for (int i = 0; i < mAllPrefs.size(); i++) {
654            Preference pref = mAllPrefs.get(i);
655            pref.setEnabled(enabled && !mDisabledPrefs.contains(pref));
656        }
657        mEnableAdbController.enablePreference(enabled);
658        mBugReportInPowerController.enablePreference(enabled);
659        mTelephonyMonitorController.enablePreference(enabled);
660        mWebViewAppPrefController.enablePreference(enabled);
661        mCameraHalHdrplusController.enablePreference(enabled);
662        updateAllOptions();
663    }
664
665    @Override
666    public void onResume() {
667        super.onResume();
668
669        if (mUnavailable) {
670            // Show error message
671            if (!isUiRestrictedByOnlyAdmin()) {
672                getEmptyTextView().setText(R.string.development_settings_not_available);
673            }
674            getPreferenceScreen().removeAll();
675            return;
676        }
677
678        // A DeviceAdmin has specified a maximum time until the device
679        // will lock...  in this case we can't allow the user to turn
680        // on "stay awake when plugged in" because that would defeat the
681        // restriction.
682        final EnforcedAdmin admin = RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(
683                getActivity());
684        mKeepScreenOn.setDisabledByAdmin(admin);
685        if (admin == null) {
686            mDisabledPrefs.remove(mKeepScreenOn);
687        } else {
688            mDisabledPrefs.add(mKeepScreenOn);
689        }
690
691        final boolean lastEnabledState = mSettingsEnabler.getLastEnabledState();
692        mSwitchBar.setChecked(lastEnabledState);
693        setPrefsEnabledState(lastEnabledState);
694
695        if (mHaveDebugSettings && !lastEnabledState) {
696            // Overall debugging is disabled, but there are some debug
697            // settings that are enabled.  This is an invalid state.  Switch
698            // to debug settings being enabled, so the user knows there is
699            // stuff enabled and can turn it all off if they want.
700            mSettingsEnabler.enableDevelopmentSettings();
701            mSwitchBar.setChecked(lastEnabledState);
702            setPrefsEnabledState(lastEnabledState);
703        }
704        mSwitchBar.show();
705
706        if (mColorModePreference != null) {
707            mColorModePreference.startListening();
708            mColorModePreference.updateCurrentAndSupported();
709        }
710    }
711
712    @Override
713    public void onPause() {
714        super.onPause();
715        if (mColorModePreference != null) {
716            mColorModePreference.stopListening();
717        }
718    }
719
720    @Override
721    public View onCreateView(LayoutInflater inflater, ViewGroup container,
722            Bundle savedInstanceState) {
723        IntentFilter filter = new IntentFilter();
724        filter.addAction(UsbManager.ACTION_USB_STATE);
725        if (getActivity().registerReceiver(mUsbReceiver, filter) == null) {
726            updateUsbConfigurationValues();
727        }
728
729        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
730        if (adapter != null) {
731            adapter.getProfileProxy(getActivity(),
732                                    mBluetoothA2dpServiceListener,
733                                    BluetoothProfile.A2DP);
734        }
735        filter = new IntentFilter();
736        filter.addAction(BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED);
737        if (getActivity().registerReceiver(mBluetoothA2dpReceiver, filter) == null) {
738            updateBluetoothA2dpConfigurationValues();
739        }
740
741        mEnableAdbReceiver = new BroadcastReceiver() {
742            @Override
743            public void onReceive(Context context, Intent intent) {
744                mVerifyAppsOverUsbController.updatePreference();
745                updateBugreportOptions();
746            }
747        };
748        LocalBroadcastManager.getInstance(getContext())
749                .registerReceiver(mEnableAdbReceiver, new IntentFilter(
750                        AbstractEnableAdbPreferenceController.ACTION_ENABLE_ADB_STATE_CHANGED));
751
752        return super.onCreateView(inflater, container, savedInstanceState);
753    }
754
755    @Override
756    public void onDestroyView() {
757        super.onDestroyView();
758
759        if (mUnavailable) {
760            return;
761        }
762        getActivity().unregisterReceiver(mUsbReceiver);
763        getActivity().unregisterReceiver(mBluetoothA2dpReceiver);
764        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
765        if (adapter != null) {
766            adapter.closeProfileProxy(BluetoothProfile.A2DP, mBluetoothA2dp);
767            mBluetoothA2dp = null;
768        }
769
770        if (mEnableAdbReceiver != null) {
771            LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(mEnableAdbReceiver);
772            mEnableAdbReceiver = null;
773        }
774    }
775
776    void updateSwitchPreference(SwitchPreference switchPreference, boolean value) {
777        switchPreference.setChecked(value);
778        mHaveDebugSettings |= value;
779    }
780
781    private void updateAllOptions() {
782        final Context context = getActivity();
783        final ContentResolver cr = context.getContentResolver();
784        mHaveDebugSettings = false;
785        final Preference enableAdb = findPreference(mEnableAdbController.getPreferenceKey());
786        mEnableAdbController.updateState(enableAdb);
787        mHaveDebugSettings |= mEnableAdbController.haveDebugSettings();
788        if (mEnableTerminal != null) {
789            updateSwitchPreference(mEnableTerminal,
790                    context.getPackageManager().getApplicationEnabledSetting(TERMINAL_APP_PACKAGE)
791                            == PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
792        }
793        mHaveDebugSettings |= mBugReportInPowerController.updatePreference();
794        mHaveDebugSettings |= mTelephonyMonitorController.updatePreference();
795        mHaveDebugSettings |= mCameraHalHdrplusController.updatePreference();
796        updateSwitchPreference(mKeepScreenOn, Settings.Global.getInt(cr,
797                Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0) != 0);
798        updateSwitchPreference(mBtHciSnoopLog, SystemProperties.getBoolean(
799                BLUETOOTH_BTSNOOP_ENABLE_PROPERTY, false));
800        updateSwitchPreference(mDebugViewAttributes, Settings.Global.getInt(cr,
801                Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0);
802        updateSwitchPreference(mForceAllowOnExternal, Settings.Global.getInt(cr,
803                Settings.Global.FORCE_ALLOW_ON_EXTERNAL, 0) != 0);
804        updateHdcpValues();
805        updatePasswordSummary();
806        updateDebuggerOptions();
807        updateMockLocation();
808        updateStrictModeVisualOptions();
809        updatePointerLocationOptions();
810        updateShowTouchesOptions();
811        updateFlingerOptions();
812        updateHardwareUiOptions();
813        updateMsaaOptions();
814        updateTrackFrameTimeOptions();
815        updateShowNonRectClipOptions();
816        updateShowHwScreenUpdatesOptions();
817        updateShowHwLayersUpdatesOptions();
818        updateDebugHwOverdrawOptions();
819        updateDebugHwRendererOptions();
820        updateDebugLayoutOptions();
821        updateAnimationScaleOptions();
822        updateOverlayDisplayDevicesOptions();
823        updateImmediatelyDestroyActivitiesOptions();
824        updateAppProcessLimitOptions();
825        updateShowAllANRsOptions();
826        updateShowNotificationChannelWarningsOptions();
827        mVerifyAppsOverUsbController.updatePreference();
828        updateOtaDisableAutomaticUpdateOptions();
829        updateBugreportOptions();
830        updateForceRtlOptions();
831        updateLogdSizeValues();
832        updateLogpersistValues();
833        updateWifiDisplayCertificationOptions();
834        updateWifiVerboseLoggingOptions();
835        updateWifiAggressiveHandoverOptions();
836        updateWifiAllowScansWithTrafficOptions();
837        updateMobileDataAlwaysOnOptions();
838        updateTetheringHardwareOffloadOptions();
839        updateSimulateColorSpace();
840        updateUSBAudioOptions();
841        updateForceResizableOptions();
842        Preference webViewAppPref = findPreference(mWebViewAppPrefController.getPreferenceKey());
843        mWebViewAppPrefController.updateState(webViewAppPref);
844        updateOemUnlockOptions();
845        if (mColorTemperaturePreference != null) {
846            updateColorTemperature();
847        }
848        updateBluetoothShowDevicesWithoutUserFriendlyNameOptions();
849        updateBluetoothDisableAbsVolumeOptions();
850        updateBluetoothEnableInbandRingingOptions();
851        updateBluetoothA2dpConfigurationValues();
852    }
853
854    private void resetDangerousOptions() {
855        mDontPokeProperties = true;
856        for (int i = 0; i < mResetSwitchPrefs.size(); i++) {
857            SwitchPreference cb = mResetSwitchPrefs.get(i);
858            if (cb.isChecked()) {
859                cb.setChecked(false);
860                onPreferenceTreeClick(cb);
861            }
862        }
863        mBugReportInPowerController.resetPreference();
864        mEnableAdbController.resetPreference();
865        resetDebuggerOptions();
866        writeLogpersistOption(null, true);
867        writeLogdSizeOption(null);
868        writeAnimationScaleOption(0, mWindowAnimationScale, null);
869        writeAnimationScaleOption(1, mTransitionAnimationScale, null);
870        writeAnimationScaleOption(2, mAnimatorDurationScale, null);
871        // Only poke the color space setting if we control it.
872        if (usingDevelopmentColorSpace()) {
873            writeSimulateColorSpace(-1);
874        }
875        writeOverlayDisplayDevicesOptions(null);
876        writeAppProcessLimitOptions(null);
877        mHaveDebugSettings = false;
878        updateAllOptions();
879        mDontPokeProperties = false;
880        pokeSystemProperties();
881    }
882
883    private void updateHdcpValues() {
884        ListPreference hdcpChecking = (ListPreference) findPreference(HDCP_CHECKING_KEY);
885        if (hdcpChecking != null) {
886            String currentValue = SystemProperties.get(HDCP_CHECKING_PROPERTY);
887            String[] values = getResources().getStringArray(R.array.hdcp_checking_values);
888            String[] summaries = getResources().getStringArray(R.array.hdcp_checking_summaries);
889            int index = 1; // Defaults to drm-only. Needs to match with R.array.hdcp_checking_values
890            for (int i = 0; i < values.length; i++) {
891                if (currentValue.equals(values[i])) {
892                    index = i;
893                    break;
894                }
895            }
896            hdcpChecking.setValue(values[index]);
897            hdcpChecking.setSummary(summaries[index]);
898            hdcpChecking.setOnPreferenceChangeListener(this);
899        }
900    }
901
902    private void updatePasswordSummary() {
903        try {
904            if (mBackupManager.hasBackupPassword()) {
905                mPassword.setSummary(R.string.local_backup_password_summary_change);
906            } else {
907                mPassword.setSummary(R.string.local_backup_password_summary_none);
908            }
909        } catch (RemoteException e) {
910            // Not much we can do here
911        }
912    }
913
914    private void writeBtHciSnoopLogOptions() {
915        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
916        SystemProperties.set(BLUETOOTH_BTSNOOP_ENABLE_PROPERTY,
917                Boolean.toString(mBtHciSnoopLog.isChecked()));
918    }
919
920    private void writeDebuggerOptions() {
921        try {
922            ActivityManager.getService().setDebugApp(
923                    mDebugApp, mWaitForDebugger.isChecked(), true);
924        } catch (RemoteException ex) {
925        }
926    }
927
928    private void writeMockLocation() {
929        AppOpsManager appOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
930
931        // Disable the app op of the previous mock location app if such.
932        List<PackageOps> packageOps = appOpsManager.getPackagesForOps(MOCK_LOCATION_APP_OPS);
933        if (packageOps != null) {
934            // Should be one but in case we are in a bad state due to use of command line tools.
935            for (PackageOps packageOp : packageOps) {
936                if (packageOp.getOps().get(0).getMode() != AppOpsManager.MODE_ERRORED) {
937                    String oldMockLocationApp = packageOp.getPackageName();
938                    try {
939                        ApplicationInfo ai = getActivity().getPackageManager().getApplicationInfo(
940                                oldMockLocationApp, PackageManager.GET_DISABLED_COMPONENTS);
941                        appOpsManager.setMode(AppOpsManager.OP_MOCK_LOCATION, ai.uid,
942                                oldMockLocationApp, AppOpsManager.MODE_ERRORED);
943                    } catch (NameNotFoundException e) {
944                        /* ignore */
945                    }
946                }
947            }
948        }
949
950        // Enable the app op of the new mock location app if such.
951        if (!TextUtils.isEmpty(mMockLocationApp)) {
952            try {
953                ApplicationInfo ai = getActivity().getPackageManager().getApplicationInfo(
954                        mMockLocationApp, PackageManager.GET_DISABLED_COMPONENTS);
955                appOpsManager.setMode(AppOpsManager.OP_MOCK_LOCATION, ai.uid,
956                        mMockLocationApp, AppOpsManager.MODE_ALLOWED);
957            } catch (NameNotFoundException e) {
958                /* ignore */
959            }
960        }
961    }
962
963    private static void resetDebuggerOptions() {
964        try {
965            ActivityManager.getService().setDebugApp(
966                    null, false, true);
967        } catch (RemoteException ex) {
968        }
969    }
970
971    private void updateDebuggerOptions() {
972        mDebugApp = Settings.Global.getString(
973                getActivity().getContentResolver(), Settings.Global.DEBUG_APP);
974        updateSwitchPreference(mWaitForDebugger, Settings.Global.getInt(
975                getActivity().getContentResolver(), Settings.Global.WAIT_FOR_DEBUGGER, 0) != 0);
976        if (mDebugApp != null && mDebugApp.length() > 0) {
977            String label;
978            try {
979                ApplicationInfo ai = getActivity().getPackageManager().getApplicationInfo(mDebugApp,
980                        PackageManager.GET_DISABLED_COMPONENTS);
981                CharSequence lab = getActivity().getPackageManager().getApplicationLabel(ai);
982                label = lab != null ? lab.toString() : mDebugApp;
983            } catch (PackageManager.NameNotFoundException e) {
984                label = mDebugApp;
985            }
986            mDebugAppPref.setSummary(getResources().getString(R.string.debug_app_set, label));
987            mWaitForDebugger.setEnabled(true);
988            mHaveDebugSettings = true;
989        } else {
990            mDebugAppPref.setSummary(getResources().getString(R.string.debug_app_not_set));
991            mWaitForDebugger.setEnabled(false);
992        }
993    }
994
995    private void updateMockLocation() {
996        AppOpsManager appOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
997
998        List<PackageOps> packageOps = appOpsManager.getPackagesForOps(MOCK_LOCATION_APP_OPS);
999        if (packageOps != null) {
1000            for (PackageOps packageOp : packageOps) {
1001                if (packageOp.getOps().get(0).getMode() == AppOpsManager.MODE_ALLOWED) {
1002                    mMockLocationApp = packageOps.get(0).getPackageName();
1003                    break;
1004                }
1005            }
1006        }
1007
1008        if (!TextUtils.isEmpty(mMockLocationApp)) {
1009            String label = mMockLocationApp;
1010            try {
1011                ApplicationInfo ai = getActivity().getPackageManager().getApplicationInfo(
1012                        mMockLocationApp, PackageManager.GET_DISABLED_COMPONENTS);
1013                CharSequence appLabel = getPackageManager().getApplicationLabel(ai);
1014                if (appLabel != null) {
1015                    label = appLabel.toString();
1016                }
1017            } catch (PackageManager.NameNotFoundException e) {
1018                /* ignore */
1019            }
1020
1021            mMockLocationAppPref.setSummary(getString(R.string.mock_location_app_set, label));
1022            mHaveDebugSettings = true;
1023        } else {
1024            mMockLocationAppPref.setSummary(getString(R.string.mock_location_app_not_set));
1025        }
1026    }
1027
1028    private void updateOtaDisableAutomaticUpdateOptions() {
1029        // We use the "disabled status" in code, but show the opposite text
1030        // "Automatic system updates" on screen. So a value 0 indicates the
1031        // automatic update is enabled.
1032        updateSwitchPreference(mOtaDisableAutomaticUpdate, Settings.Global.getInt(
1033                getActivity().getContentResolver(),
1034                Settings.Global.OTA_DISABLE_AUTOMATIC_UPDATE, 0) != 1);
1035    }
1036
1037    private void writeOtaDisableAutomaticUpdateOptions() {
1038        // We use the "disabled status" in code, but show the opposite text
1039        // "Automatic system updates" on screen. So a value 0 indicates the
1040        // automatic update is enabled.
1041        Settings.Global.putInt(getActivity().getContentResolver(),
1042                Settings.Global.OTA_DISABLE_AUTOMATIC_UPDATE,
1043                mOtaDisableAutomaticUpdate.isChecked() ? 0 : 1);
1044    }
1045
1046    private static boolean showEnableOemUnlockPreference(Context context) {
1047        return context.getSystemService(Context.OEM_LOCK_SERVICE) != null;
1048    }
1049
1050    private boolean enableOemUnlockPreference() {
1051        return !isBootloaderUnlocked() && mOemLockManager.canUserAllowOemUnlock();
1052    }
1053
1054    private void updateOemUnlockOptions() {
1055        if (mEnableOemUnlock != null) {
1056            updateSwitchPreference(mEnableOemUnlock, mOemLockManager.isOemUnlockAllowed());
1057            updateOemUnlockSettingDescription();
1058            // Showing mEnableOemUnlock preference as device has persistent data block.
1059            mEnableOemUnlock.setDisabledByAdmin(null);
1060            mEnableOemUnlock.setEnabled(enableOemUnlockPreference());
1061            if (mEnableOemUnlock.isEnabled()) {
1062                // Check restriction, disable mEnableOemUnlock and apply policy transparency.
1063                mEnableOemUnlock.checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET);
1064            }
1065            if (mEnableOemUnlock.isEnabled()) {
1066                // Check restriction, disable mEnableOemUnlock and apply policy transparency.
1067                mEnableOemUnlock.checkRestrictionAndSetDisabled(UserManager.DISALLOW_OEM_UNLOCK);
1068            }
1069        }
1070    }
1071
1072    private void updateBugreportOptions() {
1073        mBugReportController.enablePreference(true);
1074        mBugReportInPowerController.updateBugreportOptions();
1075    }
1076
1077    // Returns the current state of the system property that controls
1078    // strictmode flashes.  One of:
1079    //    0: not explicitly set one way or another
1080    //    1: on
1081    //    2: off
1082    private static int currentStrictModeActiveIndex() {
1083        if (TextUtils.isEmpty(SystemProperties.get(StrictMode.VISUAL_PROPERTY))) {
1084            return 0;
1085        }
1086        boolean enabled = SystemProperties.getBoolean(StrictMode.VISUAL_PROPERTY, false);
1087        return enabled ? 1 : 2;
1088    }
1089
1090    private void writeStrictModeVisualOptions() {
1091        try {
1092            mWindowManager.setStrictModeVisualIndicatorPreference(mStrictMode.isChecked()
1093                    ? "1" : "");
1094        } catch (RemoteException e) {
1095        }
1096    }
1097
1098    private void updateStrictModeVisualOptions() {
1099        updateSwitchPreference(mStrictMode, currentStrictModeActiveIndex() == 1);
1100    }
1101
1102    private void writePointerLocationOptions() {
1103        Settings.System.putInt(getActivity().getContentResolver(),
1104                Settings.System.POINTER_LOCATION, mPointerLocation.isChecked() ? 1 : 0);
1105    }
1106
1107    private void updatePointerLocationOptions() {
1108        updateSwitchPreference(mPointerLocation,
1109                Settings.System.getInt(getActivity().getContentResolver(),
1110                        Settings.System.POINTER_LOCATION, 0) != 0);
1111    }
1112
1113    private void writeShowTouchesOptions() {
1114        Settings.System.putInt(getActivity().getContentResolver(),
1115                Settings.System.SHOW_TOUCHES, mShowTouches.isChecked() ? 1 : 0);
1116    }
1117
1118    private void updateShowTouchesOptions() {
1119        updateSwitchPreference(mShowTouches,
1120                Settings.System.getInt(getActivity().getContentResolver(),
1121                        Settings.System.SHOW_TOUCHES, 0) != 0);
1122    }
1123
1124    private void updateFlingerOptions() {
1125        // magic communication with surface flinger.
1126        try {
1127            IBinder flinger = ServiceManager.getService("SurfaceFlinger");
1128            if (flinger != null) {
1129                Parcel data = Parcel.obtain();
1130                Parcel reply = Parcel.obtain();
1131                data.writeInterfaceToken("android.ui.ISurfaceComposer");
1132                flinger.transact(1010, data, reply, 0);
1133                @SuppressWarnings("unused")
1134                int showCpu = reply.readInt();
1135                @SuppressWarnings("unused")
1136                int enableGL = reply.readInt();
1137                int showUpdates = reply.readInt();
1138                updateSwitchPreference(mShowScreenUpdates, showUpdates != 0);
1139                @SuppressWarnings("unused")
1140                int showBackground = reply.readInt();
1141                int disableOverlays = reply.readInt();
1142                updateSwitchPreference(mDisableOverlays, disableOverlays != 0);
1143                reply.recycle();
1144                data.recycle();
1145            }
1146        } catch (RemoteException ex) {
1147        }
1148    }
1149
1150    private void writeShowUpdatesOption() {
1151        try {
1152            IBinder flinger = ServiceManager.getService("SurfaceFlinger");
1153            if (flinger != null) {
1154                Parcel data = Parcel.obtain();
1155                data.writeInterfaceToken("android.ui.ISurfaceComposer");
1156                final int showUpdates = mShowScreenUpdates.isChecked() ? 1 : 0;
1157                data.writeInt(showUpdates);
1158                flinger.transact(1002, data, null, 0);
1159                data.recycle();
1160
1161                updateFlingerOptions();
1162            }
1163        } catch (RemoteException ex) {
1164        }
1165    }
1166
1167    private void writeDisableOverlaysOption() {
1168        try {
1169            IBinder flinger = ServiceManager.getService("SurfaceFlinger");
1170            if (flinger != null) {
1171                Parcel data = Parcel.obtain();
1172                data.writeInterfaceToken("android.ui.ISurfaceComposer");
1173                final int disableOverlays = mDisableOverlays.isChecked() ? 1 : 0;
1174                data.writeInt(disableOverlays);
1175                flinger.transact(1008, data, null, 0);
1176                data.recycle();
1177
1178                updateFlingerOptions();
1179            }
1180        } catch (RemoteException ex) {
1181        }
1182    }
1183
1184    private void updateHardwareUiOptions() {
1185        updateSwitchPreference(mForceHardwareUi,
1186                SystemProperties.getBoolean(HARDWARE_UI_PROPERTY, false));
1187    }
1188
1189    private void writeHardwareUiOptions() {
1190        SystemProperties.set(HARDWARE_UI_PROPERTY, mForceHardwareUi.isChecked() ? "true" : "false");
1191        pokeSystemProperties();
1192    }
1193
1194    private void updateMsaaOptions() {
1195        updateSwitchPreference(mForceMsaa, SystemProperties.getBoolean(MSAA_PROPERTY, false));
1196    }
1197
1198    private void writeMsaaOptions() {
1199        SystemProperties.set(MSAA_PROPERTY, mForceMsaa.isChecked() ? "true" : "false");
1200        pokeSystemProperties();
1201    }
1202
1203    private void updateTrackFrameTimeOptions() {
1204        String value = SystemProperties.get(ThreadedRenderer.PROFILE_PROPERTY);
1205        if (value == null) {
1206            value = "";
1207        }
1208
1209        CharSequence[] values = mTrackFrameTime.getEntryValues();
1210        for (int i = 0; i < values.length; i++) {
1211            if (value.contentEquals(values[i])) {
1212                mTrackFrameTime.setValueIndex(i);
1213                mTrackFrameTime.setSummary(mTrackFrameTime.getEntries()[i]);
1214                return;
1215            }
1216        }
1217        mTrackFrameTime.setValueIndex(0);
1218        mTrackFrameTime.setSummary(mTrackFrameTime.getEntries()[0]);
1219    }
1220
1221    private void writeTrackFrameTimeOptions(Object newValue) {
1222        SystemProperties.set(ThreadedRenderer.PROFILE_PROPERTY,
1223                newValue == null ? "" : newValue.toString());
1224        pokeSystemProperties();
1225        updateTrackFrameTimeOptions();
1226    }
1227
1228    private void updateShowNonRectClipOptions() {
1229        String value = SystemProperties.get(
1230                ThreadedRenderer.DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY);
1231        if (value == null) {
1232            value = "hide";
1233        }
1234
1235        CharSequence[] values = mShowNonRectClip.getEntryValues();
1236        for (int i = 0; i < values.length; i++) {
1237            if (value.contentEquals(values[i])) {
1238                mShowNonRectClip.setValueIndex(i);
1239                mShowNonRectClip.setSummary(mShowNonRectClip.getEntries()[i]);
1240                return;
1241            }
1242        }
1243        mShowNonRectClip.setValueIndex(0);
1244        mShowNonRectClip.setSummary(mShowNonRectClip.getEntries()[0]);
1245    }
1246
1247    private void writeShowNonRectClipOptions(Object newValue) {
1248        SystemProperties.set(ThreadedRenderer.DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY,
1249                newValue == null ? "" : newValue.toString());
1250        pokeSystemProperties();
1251        updateShowNonRectClipOptions();
1252    }
1253
1254    private void updateShowHwScreenUpdatesOptions() {
1255        updateSwitchPreference(mShowHwScreenUpdates,
1256                SystemProperties.getBoolean(ThreadedRenderer.DEBUG_DIRTY_REGIONS_PROPERTY, false));
1257    }
1258
1259    private void writeShowHwScreenUpdatesOptions() {
1260        SystemProperties.set(ThreadedRenderer.DEBUG_DIRTY_REGIONS_PROPERTY,
1261                mShowHwScreenUpdates.isChecked() ? "true" : null);
1262        pokeSystemProperties();
1263    }
1264
1265    private void updateShowHwLayersUpdatesOptions() {
1266        updateSwitchPreference(mShowHwLayersUpdates, SystemProperties.getBoolean(
1267                ThreadedRenderer.DEBUG_SHOW_LAYERS_UPDATES_PROPERTY, false));
1268    }
1269
1270    private void writeShowHwLayersUpdatesOptions() {
1271        SystemProperties.set(ThreadedRenderer.DEBUG_SHOW_LAYERS_UPDATES_PROPERTY,
1272                mShowHwLayersUpdates.isChecked() ? "true" : null);
1273        pokeSystemProperties();
1274    }
1275
1276    private void updateDebugHwOverdrawOptions() {
1277        String value = SystemProperties.get(ThreadedRenderer.DEBUG_OVERDRAW_PROPERTY);
1278        if (value == null) {
1279            value = "";
1280        }
1281
1282        CharSequence[] values = mDebugHwOverdraw.getEntryValues();
1283        for (int i = 0; i < values.length; i++) {
1284            if (value.contentEquals(values[i])) {
1285                mDebugHwOverdraw.setValueIndex(i);
1286                mDebugHwOverdraw.setSummary(mDebugHwOverdraw.getEntries()[i]);
1287                return;
1288            }
1289        }
1290        mDebugHwOverdraw.setValueIndex(0);
1291        mDebugHwOverdraw.setSummary(mDebugHwOverdraw.getEntries()[0]);
1292    }
1293
1294    private void writeDebugHwOverdrawOptions(Object newValue) {
1295        SystemProperties.set(ThreadedRenderer.DEBUG_OVERDRAW_PROPERTY,
1296                newValue == null ? "" : newValue.toString());
1297        pokeSystemProperties();
1298        updateDebugHwOverdrawOptions();
1299    }
1300
1301    private void updateDebugHwRendererOptions() {
1302        String value = SystemProperties.get(ThreadedRenderer.DEBUG_RENDERER_PROPERTY);
1303        if (value == null) {
1304            value = "";
1305        }
1306
1307        CharSequence[] values = mDebugHwRenderer.getEntryValues();
1308        for (int i = 0; i < values.length; i++) {
1309            if (value.contentEquals(values[i])) {
1310                mDebugHwRenderer.setValueIndex(i);
1311                mDebugHwRenderer.setSummary(mDebugHwRenderer.getEntries()[i]);
1312                return;
1313            }
1314        }
1315        mDebugHwRenderer.setValueIndex(0);
1316        mDebugHwRenderer.setSummary(mDebugHwRenderer.getEntries()[0]);
1317    }
1318
1319    private void writeDebugHwRendererOptions(Object newValue) {
1320        SystemProperties.set(ThreadedRenderer.DEBUG_RENDERER_PROPERTY,
1321                newValue == null ? "" : newValue.toString());
1322        pokeSystemProperties();
1323        updateDebugHwRendererOptions();
1324    }
1325
1326    private void updateDebugLayoutOptions() {
1327        updateSwitchPreference(mDebugLayout,
1328                SystemProperties.getBoolean(View.DEBUG_LAYOUT_PROPERTY, false));
1329    }
1330
1331    private void writeDebugLayoutOptions() {
1332        SystemProperties.set(View.DEBUG_LAYOUT_PROPERTY,
1333                mDebugLayout.isChecked() ? "true" : "false");
1334        pokeSystemProperties();
1335    }
1336
1337    private void updateSimulateColorSpace() {
1338        final ContentResolver cr = getContentResolver();
1339        final boolean enabled = Settings.Secure.getInt(
1340                cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0) != 0;
1341        if (enabled) {
1342            final String mode = Integer.toString(Settings.Secure.getInt(
1343                    cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER,
1344                    AccessibilityManager.DALTONIZER_DISABLED));
1345            mSimulateColorSpace.setValue(mode);
1346            final int index = mSimulateColorSpace.findIndexOfValue(mode);
1347            if (index < 0) {
1348                // We're using a mode controlled by accessibility preferences.
1349                mSimulateColorSpace.setSummary(getString(R.string.daltonizer_type_overridden,
1350                        getString(R.string.accessibility_display_daltonizer_preference_title)));
1351            } else {
1352                mSimulateColorSpace.setSummary("%s");
1353            }
1354        } else {
1355            mSimulateColorSpace.setValue(
1356                    Integer.toString(AccessibilityManager.DALTONIZER_DISABLED));
1357        }
1358    }
1359
1360    /**
1361     * @return <code>true</code> if the color space preference is currently
1362     * controlled by development settings
1363     */
1364    private boolean usingDevelopmentColorSpace() {
1365        final ContentResolver cr = getContentResolver();
1366        final boolean enabled = Settings.Secure.getInt(
1367                cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0) != 0;
1368        if (enabled) {
1369            final String mode = Integer.toString(Settings.Secure.getInt(
1370                    cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER,
1371                    AccessibilityManager.DALTONIZER_DISABLED));
1372            final int index = mSimulateColorSpace.findIndexOfValue(mode);
1373            if (index >= 0) {
1374                // We're using a mode controlled by developer preferences.
1375                return true;
1376            }
1377        }
1378        return false;
1379    }
1380
1381    private void writeSimulateColorSpace(Object value) {
1382        final ContentResolver cr = getContentResolver();
1383        final int newMode = Integer.parseInt(value.toString());
1384        if (newMode < 0) {
1385            Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0);
1386        } else {
1387            Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 1);
1388            Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, newMode);
1389        }
1390    }
1391
1392    private void updateColorTemperature() {
1393        updateSwitchPreference(mColorTemperaturePreference,
1394                SystemProperties.getBoolean(COLOR_TEMPERATURE_PROPERTY, false));
1395    }
1396
1397    private void writeColorTemperature() {
1398        SystemProperties.set(COLOR_TEMPERATURE_PROPERTY,
1399                mColorTemperaturePreference.isChecked() ? "1" : "0");
1400        pokeSystemProperties();
1401        Toast.makeText(getActivity(), R.string.color_temperature_toast, Toast.LENGTH_LONG).show();
1402    }
1403
1404    private void updateUSBAudioOptions() {
1405        updateSwitchPreference(mUSBAudio, Settings.Secure.getInt(getContentResolver(),
1406                Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED, 0) != 0);
1407    }
1408
1409    private void writeUSBAudioOptions() {
1410        Settings.Secure.putInt(getContentResolver(),
1411                Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED,
1412                mUSBAudio.isChecked() ? 1 : 0);
1413    }
1414
1415    private void updateForceResizableOptions() {
1416        updateSwitchPreference(mForceResizable, Settings.Global.getInt(getContentResolver(),
1417                Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0);
1418    }
1419
1420    private void writeForceResizableOptions() {
1421        Settings.Global.putInt(getContentResolver(),
1422                Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES,
1423                mForceResizable.isChecked() ? 1 : 0);
1424    }
1425
1426    private void updateForceRtlOptions() {
1427        updateSwitchPreference(mForceRtlLayout,
1428                Settings.Global.getInt(getActivity().getContentResolver(),
1429                        Settings.Global.DEVELOPMENT_FORCE_RTL, 0) != 0);
1430    }
1431
1432    private void writeForceRtlOptions() {
1433        boolean value = mForceRtlLayout.isChecked();
1434        Settings.Global.putInt(getActivity().getContentResolver(),
1435                Settings.Global.DEVELOPMENT_FORCE_RTL, value ? 1 : 0);
1436        SystemProperties.set(Settings.Global.DEVELOPMENT_FORCE_RTL, value ? "1" : "0");
1437        LocalePicker.updateLocales(getActivity().getResources().getConfiguration().getLocales());
1438    }
1439
1440    private void updateWifiDisplayCertificationOptions() {
1441        updateSwitchPreference(mWifiDisplayCertification, Settings.Global.getInt(
1442                getActivity().getContentResolver(),
1443                Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON, 0) != 0);
1444    }
1445
1446    private void writeWifiDisplayCertificationOptions() {
1447        Settings.Global.putInt(getActivity().getContentResolver(),
1448                Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON,
1449                mWifiDisplayCertification.isChecked() ? 1 : 0);
1450    }
1451
1452    private void updateWifiVerboseLoggingOptions() {
1453        boolean enabled = mWifiManager.getVerboseLoggingLevel() > 0;
1454        updateSwitchPreference(mWifiVerboseLogging, enabled);
1455    }
1456
1457    private void writeWifiVerboseLoggingOptions() {
1458        mWifiManager.enableVerboseLogging(mWifiVerboseLogging.isChecked() ? 1 : 0);
1459    }
1460
1461    private void updateWifiAggressiveHandoverOptions() {
1462        boolean enabled = mWifiManager.getAggressiveHandover() > 0;
1463        updateSwitchPreference(mWifiAggressiveHandover, enabled);
1464    }
1465
1466    private void writeWifiAggressiveHandoverOptions() {
1467        mWifiManager.enableAggressiveHandover(mWifiAggressiveHandover.isChecked() ? 1 : 0);
1468    }
1469
1470    private void updateWifiAllowScansWithTrafficOptions() {
1471        boolean enabled = mWifiManager.getAllowScansWithTraffic() > 0;
1472        updateSwitchPreference(mWifiAllowScansWithTraffic, enabled);
1473    }
1474
1475    private void writeWifiAllowScansWithTrafficOptions() {
1476        mWifiManager.setAllowScansWithTraffic(mWifiAllowScansWithTraffic.isChecked() ? 1 : 0);
1477    }
1478
1479    private void updateBluetoothShowDevicesWithoutUserFriendlyNameOptions() {
1480        updateSwitchPreference(mBluetoothShowDevicesWithoutNames,
1481                SystemProperties.getBoolean(
1482                        BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY, false));
1483    }
1484
1485    private void writeBluetoothShowDevicesWithoutUserFriendlyNameOptions() {
1486        SystemProperties.set(BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY,
1487                mBluetoothShowDevicesWithoutNames.isChecked() ? "true" : "false");
1488    }
1489
1490    private void updateBluetoothDisableAbsVolumeOptions() {
1491        updateSwitchPreference(mBluetoothDisableAbsVolume,
1492                SystemProperties.getBoolean(BLUETOOTH_DISABLE_ABSOLUTE_VOLUME_PROPERTY, false));
1493    }
1494
1495    private void writeBluetoothDisableAbsVolumeOptions() {
1496        SystemProperties.set(BLUETOOTH_DISABLE_ABSOLUTE_VOLUME_PROPERTY,
1497                mBluetoothDisableAbsVolume.isChecked() ? "true" : "false");
1498    }
1499
1500    private void updateBluetoothEnableInbandRingingOptions() {
1501        if (mBluetoothEnableInbandRinging != null) {
1502            updateSwitchPreference(mBluetoothEnableInbandRinging,
1503                SystemProperties.getBoolean(BLUETOOTH_ENABLE_INBAND_RINGING_PROPERTY, true));
1504        }
1505    }
1506
1507    private void writeBluetoothEnableInbandRingingOptions() {
1508        if (mBluetoothEnableInbandRinging != null) {
1509            SystemProperties.set(BLUETOOTH_ENABLE_INBAND_RINGING_PROPERTY,
1510                mBluetoothEnableInbandRinging.isChecked() ? "true" : "false");
1511        }
1512    }
1513
1514    private void updateMobileDataAlwaysOnOptions() {
1515        updateSwitchPreference(mMobileDataAlwaysOn, Settings.Global.getInt(
1516                getActivity().getContentResolver(),
1517                Settings.Global.MOBILE_DATA_ALWAYS_ON, 1) != 0);
1518    }
1519
1520    private void writeMobileDataAlwaysOnOptions() {
1521        Settings.Global.putInt(getActivity().getContentResolver(),
1522                Settings.Global.MOBILE_DATA_ALWAYS_ON,
1523                mMobileDataAlwaysOn.isChecked() ? 1 : 0);
1524    }
1525
1526    private void updateTetheringHardwareOffloadOptions() {
1527        updateSwitchPreference(mTetheringHardwareOffload, Settings.Global.getInt(
1528                getActivity().getContentResolver(),
1529                Settings.Global.TETHER_OFFLOAD_DISABLED, 0) != 1);
1530    }
1531
1532    private void writeTetheringHardwareOffloadOptions() {
1533        Settings.Global.putInt(getActivity().getContentResolver(),
1534                Settings.Global.TETHER_OFFLOAD_DISABLED,
1535                mTetheringHardwareOffload.isChecked() ? 0 : 1);
1536    }
1537
1538    private String defaultLogdSizeValue() {
1539        String defaultValue = SystemProperties.get(SELECT_LOGD_DEFAULT_SIZE_PROPERTY);
1540        if ((defaultValue == null) || (defaultValue.length() == 0)) {
1541            if (SystemProperties.get("ro.config.low_ram").equals("true")) {
1542                defaultValue = SELECT_LOGD_SVELTE_DEFAULT_SIZE_VALUE;
1543            } else {
1544                defaultValue = SELECT_LOGD_DEFAULT_SIZE_VALUE;
1545            }
1546        }
1547        return defaultValue;
1548    }
1549
1550    private void updateLogdSizeValues() {
1551        if (mLogdSize != null) {
1552            String currentTag = SystemProperties.get(SELECT_LOGD_TAG_PROPERTY);
1553            String currentValue = SystemProperties.get(SELECT_LOGD_SIZE_PROPERTY);
1554            if ((currentTag != null) && currentTag.startsWith(SELECT_LOGD_TAG_SILENCE)) {
1555                currentValue = SELECT_LOGD_OFF_SIZE_MARKER_VALUE;
1556            }
1557            if (mLogpersist != null) {
1558                String currentLogpersistEnable
1559                        = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY_ENABLE);
1560                if ((currentLogpersistEnable == null)
1561                        || !currentLogpersistEnable.equals("true")
1562                        || currentValue.equals(SELECT_LOGD_OFF_SIZE_MARKER_VALUE)) {
1563                    writeLogpersistOption(null, true);
1564                    mLogpersist.setEnabled(false);
1565                } else if (mSettingsEnabler.getLastEnabledState()) {
1566                    mLogpersist.setEnabled(true);
1567                }
1568            }
1569            if ((currentValue == null) || (currentValue.length() == 0)) {
1570                currentValue = defaultLogdSizeValue();
1571            }
1572            String[] values = getResources().getStringArray(R.array.select_logd_size_values);
1573            String[] titles = getResources().getStringArray(R.array.select_logd_size_titles);
1574            int index = 2; // punt to second entry if not found
1575            if (SystemProperties.get("ro.config.low_ram").equals("true")) {
1576                mLogdSize.setEntries(R.array.select_logd_size_lowram_titles);
1577                titles = getResources().getStringArray(R.array.select_logd_size_lowram_titles);
1578                index = 1;
1579            }
1580            String[] summaries = getResources().getStringArray(R.array.select_logd_size_summaries);
1581            for (int i = 0; i < titles.length; i++) {
1582                if (currentValue.equals(values[i])
1583                        || currentValue.equals(titles[i])) {
1584                    index = i;
1585                    break;
1586                }
1587            }
1588            mLogdSize.setValue(values[index]);
1589            mLogdSize.setSummary(summaries[index]);
1590            mLogdSize.setOnPreferenceChangeListener(this);
1591        }
1592    }
1593
1594    private void writeLogdSizeOption(Object newValue) {
1595        boolean disable = (newValue != null) &&
1596                (newValue.toString().equals(SELECT_LOGD_OFF_SIZE_MARKER_VALUE));
1597        String currentTag = SystemProperties.get(SELECT_LOGD_TAG_PROPERTY);
1598        if (currentTag == null) {
1599            currentTag = "";
1600        }
1601        // filter clean and unstack all references to our setting
1602        String newTag = currentTag.replaceAll(
1603                ",+" + SELECT_LOGD_TAG_SILENCE, "").replaceFirst(
1604                "^" + SELECT_LOGD_TAG_SILENCE + ",*", "").replaceAll(
1605                ",+", ",").replaceFirst(
1606                ",+$", "");
1607        if (disable) {
1608            newValue = SELECT_LOGD_MINIMUM_SIZE_VALUE;
1609            // Make sure snet_event_log get through first, but do not override
1610            String snetValue = SystemProperties.get(SELECT_LOGD_SNET_TAG_PROPERTY);
1611            if ((snetValue == null) || (snetValue.length() == 0)) {
1612                snetValue = SystemProperties.get(SELECT_LOGD_RUNTIME_SNET_TAG_PROPERTY);
1613                if ((snetValue == null) || (snetValue.length() == 0)) {
1614                    SystemProperties.set(SELECT_LOGD_SNET_TAG_PROPERTY, "I");
1615                }
1616            }
1617            // Silence all log sources, security logs notwithstanding
1618            if (newTag.length() != 0) {
1619                newTag = "," + newTag;
1620            }
1621            // Stack settings, stack to help preserve original value
1622            newTag = SELECT_LOGD_TAG_SILENCE + newTag;
1623        }
1624        if (!newTag.equals(currentTag)) {
1625            SystemProperties.set(SELECT_LOGD_TAG_PROPERTY, newTag);
1626        }
1627        String defaultValue = defaultLogdSizeValue();
1628        final String size = ((newValue != null) && (newValue.toString().length() != 0)) ?
1629                newValue.toString() : defaultValue;
1630        SystemProperties.set(SELECT_LOGD_SIZE_PROPERTY, defaultValue.equals(size) ? "" : size);
1631        SystemProperties.set("ctl.start", "logd-reinit");
1632        pokeSystemProperties();
1633        updateLogdSizeValues();
1634    }
1635
1636    private void updateLogpersistValues() {
1637        if (mLogpersist == null) {
1638            return;
1639        }
1640        String currentValue = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY);
1641        if (currentValue == null) {
1642            currentValue = "";
1643        }
1644        String currentBuffers = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY_BUFFER);
1645        if ((currentBuffers == null) || (currentBuffers.length() == 0)) {
1646            currentBuffers = "all";
1647        }
1648        int index = 0;
1649        if (currentValue.equals(SELECT_LOGPERSIST_PROPERTY_SERVICE)) {
1650            index = 1;
1651            if (currentBuffers.equals("kernel")) {
1652                index = 3;
1653            } else if (!currentBuffers.equals("all") &&
1654                    !currentBuffers.contains("radio") &&
1655                    currentBuffers.contains("security") &&
1656                    currentBuffers.contains("kernel")) {
1657                index = 2;
1658                if (!currentBuffers.contains("default")) {
1659                    String[] contains = {"main", "events", "system", "crash"};
1660                    for (int i = 0; i < contains.length; i++) {
1661                        if (!currentBuffers.contains(contains[i])) {
1662                            index = 1;
1663                            break;
1664                        }
1665                    }
1666                }
1667            }
1668        }
1669        mLogpersist.setValue(
1670                getResources().getStringArray(R.array.select_logpersist_values)[index]);
1671        mLogpersist.setSummary(
1672                getResources().getStringArray(R.array.select_logpersist_summaries)[index]);
1673        mLogpersist.setOnPreferenceChangeListener(this);
1674        if (index != 0) {
1675            mLogpersistCleared = false;
1676        } else if (!mLogpersistCleared) {
1677            // would File.delete() directly but need to switch uid/gid to access
1678            SystemProperties.set(ACTUAL_LOGPERSIST_PROPERTY, SELECT_LOGPERSIST_PROPERTY_CLEAR);
1679            pokeSystemProperties();
1680            mLogpersistCleared = true;
1681        }
1682    }
1683
1684    private void setLogpersistOff(boolean update) {
1685        SystemProperties.set(SELECT_LOGPERSIST_PROPERTY_BUFFER, "");
1686        // deal with trampoline of empty properties
1687        SystemProperties.set(ACTUAL_LOGPERSIST_PROPERTY_BUFFER, "");
1688        SystemProperties.set(SELECT_LOGPERSIST_PROPERTY, "");
1689        SystemProperties.set(ACTUAL_LOGPERSIST_PROPERTY,
1690                update ? "" : SELECT_LOGPERSIST_PROPERTY_STOP);
1691        pokeSystemProperties();
1692        if (update) {
1693            updateLogpersistValues();
1694        } else {
1695            for (int i = 0; i < 3; i++) {
1696                String currentValue = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY);
1697                if ((currentValue == null) || currentValue.equals("")) {
1698                    break;
1699                }
1700                try {
1701                    Thread.sleep(100);
1702                } catch (InterruptedException e) {
1703                }
1704            }
1705        }
1706    }
1707
1708    private void writeLogpersistOption(Object newValue, boolean skipWarning) {
1709        if (mLogpersist == null) {
1710            return;
1711        }
1712        String currentTag = SystemProperties.get(SELECT_LOGD_TAG_PROPERTY);
1713        if ((currentTag != null) && currentTag.startsWith(SELECT_LOGD_TAG_SILENCE)) {
1714            newValue = null;
1715            skipWarning = true;
1716        }
1717
1718        if ((newValue == null) || newValue.toString().equals("")) {
1719            if (skipWarning) {
1720                mLogpersistCleared = false;
1721            } else if (!mLogpersistCleared) {
1722                // if transitioning from on to off, pop up an are you sure?
1723                String currentValue = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY);
1724                if ((currentValue != null) &&
1725                        currentValue.equals(SELECT_LOGPERSIST_PROPERTY_SERVICE)) {
1726                    if (mLogpersistClearDialog != null) dismissDialogs();
1727                    mLogpersistClearDialog = new AlertDialog.Builder(getActivity()).setMessage(
1728                            getActivity().getResources().getString(
1729                                    R.string.dev_logpersist_clear_warning_message))
1730                            .setTitle(R.string.dev_logpersist_clear_warning_title)
1731                            .setPositiveButton(android.R.string.yes, this)
1732                            .setNegativeButton(android.R.string.no, this)
1733                            .show();
1734                    mLogpersistClearDialog.setOnDismissListener(this);
1735                    return;
1736                }
1737            }
1738            setLogpersistOff(true);
1739            return;
1740        }
1741
1742        String currentBuffer = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY_BUFFER);
1743        if ((currentBuffer != null) && !currentBuffer.equals(newValue.toString())) {
1744            setLogpersistOff(false);
1745        }
1746        SystemProperties.set(SELECT_LOGPERSIST_PROPERTY_BUFFER, newValue.toString());
1747        SystemProperties.set(SELECT_LOGPERSIST_PROPERTY, SELECT_LOGPERSIST_PROPERTY_SERVICE);
1748        pokeSystemProperties();
1749        for (int i = 0; i < 3; i++) {
1750            String currentValue = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY);
1751            if ((currentValue != null)
1752                    && currentValue.equals(SELECT_LOGPERSIST_PROPERTY_SERVICE)) {
1753                break;
1754            }
1755            try {
1756                Thread.sleep(100);
1757            } catch (InterruptedException e) {
1758            }
1759        }
1760        updateLogpersistValues();
1761    }
1762
1763    private void updateUsbConfigurationValues() {
1764        if (mUsbConfiguration != null) {
1765            UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
1766
1767            String[] values = getResources().getStringArray(R.array.usb_configuration_values);
1768            String[] titles = getResources().getStringArray(R.array.usb_configuration_titles);
1769            int index = 0;
1770            for (int i = 0; i < titles.length; i++) {
1771                if (manager.isFunctionEnabled(values[i])) {
1772                    index = i;
1773                    break;
1774                }
1775            }
1776            mUsbConfiguration.setValue(values[index]);
1777            mUsbConfiguration.setSummary(titles[index]);
1778            mUsbConfiguration.setOnPreferenceChangeListener(this);
1779        }
1780    }
1781
1782    private void writeUsbConfigurationOption(Object newValue) {
1783        UsbManager manager = (UsbManager) getActivity().getSystemService(Context.USB_SERVICE);
1784        String function = newValue.toString();
1785        if (function.equals("none")) {
1786            manager.setCurrentFunction(function, false);
1787        } else {
1788            manager.setCurrentFunction(function, true);
1789        }
1790    }
1791
1792    private void initBluetoothConfigurationValues() {
1793        String[] values;
1794        String[] summaries;
1795        int index;
1796
1797        // Init the AVRCP Version - Default
1798        values = getResources().getStringArray(R.array.bluetooth_avrcp_version_values);
1799        summaries = getResources().getStringArray(R.array.bluetooth_avrcp_versions);
1800        String value = SystemProperties.get(BLUETOOTH_AVRCP_VERSION_PROPERTY, values[0]);
1801        index = mBluetoothSelectAvrcpVersion.findIndexOfValue(value);
1802        mBluetoothSelectAvrcpVersion.setValue(values[index]);
1803        mBluetoothSelectAvrcpVersion.setSummary(summaries[index]);
1804
1805        // Init the Codec Type - Default
1806        values = getResources().getStringArray(R.array.bluetooth_a2dp_codec_values);
1807        summaries = getResources().getStringArray(R.array.bluetooth_a2dp_codec_summaries);
1808        index = 0;
1809        mBluetoothSelectA2dpCodec.setValue(values[index]);
1810        mBluetoothSelectA2dpCodec.setSummary(summaries[index]);
1811
1812        // Init the Sample Rate - Default
1813        values = getResources().getStringArray(R.array.bluetooth_a2dp_codec_sample_rate_values);
1814        summaries = getResources().getStringArray(R.array.bluetooth_a2dp_codec_sample_rate_summaries);
1815        index = 0;
1816        mBluetoothSelectA2dpSampleRate.setValue(values[index]);
1817        mBluetoothSelectA2dpSampleRate.setSummary(summaries[index]);
1818
1819        // Init the Bits Per Sample - Default
1820        values = getResources().getStringArray(R.array.bluetooth_a2dp_codec_bits_per_sample_values);
1821        summaries = getResources().getStringArray(R.array.bluetooth_a2dp_codec_bits_per_sample_summaries);
1822        index = 0;
1823        mBluetoothSelectA2dpBitsPerSample.setValue(values[index]);
1824        mBluetoothSelectA2dpBitsPerSample.setSummary(summaries[index]);
1825
1826        // Init the Channel Mode - Default
1827        values = getResources().getStringArray(R.array.bluetooth_a2dp_codec_channel_mode_values);
1828        summaries = getResources().getStringArray(R.array.bluetooth_a2dp_codec_channel_mode_summaries);
1829        index = 0;
1830        mBluetoothSelectA2dpChannelMode.setValue(values[index]);
1831        mBluetoothSelectA2dpChannelMode.setSummary(summaries[index]);
1832
1833        // Init the LDAC Playback Quality - ABR
1834        values = getResources().getStringArray(R.array.bluetooth_a2dp_codec_ldac_playback_quality_values);
1835        summaries = getResources().getStringArray(R.array.bluetooth_a2dp_codec_ldac_playback_quality_summaries);
1836        index = 3;
1837        mBluetoothSelectA2dpLdacPlaybackQuality.setValue(values[index]);
1838        mBluetoothSelectA2dpLdacPlaybackQuality.setSummary(summaries[index]);
1839    }
1840
1841    private void writeBluetoothAvrcpVersion(Object newValue) {
1842        SystemProperties.set(BLUETOOTH_AVRCP_VERSION_PROPERTY, newValue.toString());
1843        int index = mBluetoothSelectAvrcpVersion.findIndexOfValue(newValue.toString());
1844        if (index >= 0) {
1845            String[] titles = getResources().getStringArray(R.array.bluetooth_avrcp_versions);
1846            mBluetoothSelectAvrcpVersion.setSummary(titles[index]);
1847        }
1848    }
1849
1850    private void updateBluetoothA2dpConfigurationValues() {
1851        int index;
1852        String[] summaries;
1853        BluetoothCodecStatus codecStatus = null;
1854        BluetoothCodecConfig codecConfig = null;
1855        BluetoothCodecConfig[] codecsLocalCapabilities = null;
1856        BluetoothCodecConfig[] codecsSelectableCapabilities = null;
1857        String streaming;
1858        Resources resources = null;
1859
1860        synchronized (mBluetoothA2dpLock) {
1861            if (mBluetoothA2dp != null) {
1862                codecStatus = mBluetoothA2dp.getCodecStatus();
1863                if (codecStatus != null) {
1864                    codecConfig = codecStatus.getCodecConfig();
1865                    codecsLocalCapabilities = codecStatus.getCodecsLocalCapabilities();
1866                    codecsSelectableCapabilities = codecStatus.getCodecsSelectableCapabilities();
1867                }
1868            }
1869        }
1870        if (codecConfig == null) {
1871            return;
1872        }
1873
1874        try {
1875            resources = getResources();
1876        } catch (IllegalStateException e) {
1877            return;
1878        }
1879        if (resources == null) {
1880            return;
1881        }
1882
1883        // Update the Codec Type
1884        index = -1;
1885        switch (codecConfig.getCodecType()) {
1886        case BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC:
1887            index = 1;
1888            break;
1889        case BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC:
1890            index = 2;
1891            break;
1892        case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX:
1893            index = 3;
1894            break;
1895        case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD:
1896            index = 4;
1897            break;
1898        case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC:
1899            index = 5;
1900            break;
1901        case BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID:
1902        default:
1903            break;
1904        }
1905        if (index >= 0 && mBluetoothSelectA2dpCodec != null) {
1906            summaries = resources.getStringArray(R.array.bluetooth_a2dp_codec_summaries);
1907            streaming = resources.getString(R.string.bluetooth_select_a2dp_codec_streaming_label, summaries[index]);
1908            mBluetoothSelectA2dpCodec.setSummary(streaming);
1909        }
1910
1911        // Update the Sample Rate
1912        index = -1;
1913        switch (codecConfig.getSampleRate()) {
1914        case BluetoothCodecConfig.SAMPLE_RATE_44100:
1915            index = 1;
1916            break;
1917        case BluetoothCodecConfig.SAMPLE_RATE_48000:
1918            index = 2;
1919            break;
1920        case BluetoothCodecConfig.SAMPLE_RATE_88200:
1921            index = 3;
1922            break;
1923        case BluetoothCodecConfig.SAMPLE_RATE_96000:
1924            index = 4;
1925            break;
1926        case BluetoothCodecConfig.SAMPLE_RATE_176400:
1927        case BluetoothCodecConfig.SAMPLE_RATE_192000:
1928        case BluetoothCodecConfig.SAMPLE_RATE_NONE:
1929        default:
1930            break;
1931        }
1932        if (index >= 0 && mBluetoothSelectA2dpSampleRate != null) {
1933            summaries = resources.getStringArray(R.array.bluetooth_a2dp_codec_sample_rate_summaries);
1934            streaming = resources.getString(R.string.bluetooth_select_a2dp_codec_streaming_label, summaries[index]);
1935             mBluetoothSelectA2dpSampleRate.setSummary(streaming);
1936        }
1937
1938        // Update the Bits Per Sample
1939        index = -1;
1940        switch (codecConfig.getBitsPerSample()) {
1941        case BluetoothCodecConfig.BITS_PER_SAMPLE_16:
1942            index = 1;
1943            break;
1944        case BluetoothCodecConfig.BITS_PER_SAMPLE_24:
1945            index = 2;
1946            break;
1947        case BluetoothCodecConfig.BITS_PER_SAMPLE_32:
1948            index = 3;
1949            break;
1950        case BluetoothCodecConfig.BITS_PER_SAMPLE_NONE:
1951        default:
1952            break;
1953        }
1954        if (index >= 0 && mBluetoothSelectA2dpBitsPerSample != null) {
1955            summaries = resources.getStringArray(R.array.bluetooth_a2dp_codec_bits_per_sample_summaries);
1956            streaming = resources.getString(R.string.bluetooth_select_a2dp_codec_streaming_label, summaries[index]);
1957            mBluetoothSelectA2dpBitsPerSample.setSummary(streaming);
1958        }
1959
1960        // Update the Channel Mode
1961        index = -1;
1962        switch (codecConfig.getChannelMode()) {
1963        case BluetoothCodecConfig.CHANNEL_MODE_MONO:
1964            index = 1;
1965            break;
1966        case BluetoothCodecConfig.CHANNEL_MODE_STEREO:
1967            index = 2;
1968            break;
1969        case BluetoothCodecConfig.CHANNEL_MODE_NONE:
1970        default:
1971            break;
1972        }
1973        if (index >= 0 && mBluetoothSelectA2dpChannelMode != null) {
1974            summaries = resources.getStringArray(R.array.bluetooth_a2dp_codec_channel_mode_summaries);
1975            streaming = resources.getString(R.string.bluetooth_select_a2dp_codec_streaming_label, summaries[index]);
1976             mBluetoothSelectA2dpChannelMode.setSummary(streaming);
1977        }
1978
1979        // Update the LDAC Playback Quality
1980        // The actual values are 0, 1, 2 - those are extracted
1981        // as mod-10 remainders of a larger value.
1982        // The reason is because within BluetoothCodecConfig we cannot use
1983        // a codec-specific value of zero.
1984        index = (int)codecConfig.getCodecSpecific1();
1985        if (index > 0) {
1986            index %= 10;
1987        } else {
1988            index = -1;
1989        }
1990        switch (index) {
1991        case 0:
1992        case 1:
1993        case 2:
1994        case 3:
1995            break;
1996        default:
1997            index = -1;
1998            break;
1999        }
2000        if (index >= 0 && mBluetoothSelectA2dpLdacPlaybackQuality != null) {
2001            summaries = resources.getStringArray(R.array.bluetooth_a2dp_codec_ldac_playback_quality_summaries);
2002            streaming = resources.getString(R.string.bluetooth_select_a2dp_codec_streaming_label, summaries[index]);
2003            mBluetoothSelectA2dpLdacPlaybackQuality.setSummary(streaming);
2004        }
2005    }
2006
2007    private void writeBluetoothConfigurationOption(Preference preference,
2008                                                   Object newValue) {
2009        String[] summaries;
2010        int index;
2011        int codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID;
2012        int codecPriorityValue = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT;
2013        int sampleRateValue = BluetoothCodecConfig.SAMPLE_RATE_NONE;
2014        int bitsPerSampleValue = BluetoothCodecConfig.BITS_PER_SAMPLE_NONE;
2015        int channelModeValue = BluetoothCodecConfig.CHANNEL_MODE_NONE;
2016        long codecSpecific1Value = 0;
2017        long codecSpecific2Value = 0;
2018        long codecSpecific3Value = 0;
2019        long codecSpecific4Value = 0;
2020
2021        // Codec Type
2022        String codecType = mBluetoothSelectA2dpCodec.getValue();
2023        if (preference == mBluetoothSelectA2dpCodec) {
2024            codecType = newValue.toString();
2025            index = mBluetoothSelectA2dpCodec.findIndexOfValue(newValue.toString());
2026            if (index >= 0) {
2027                summaries = getResources().getStringArray(R.array.bluetooth_a2dp_codec_summaries);
2028                mBluetoothSelectA2dpCodec.setSummary(summaries[index]);
2029            }
2030        }
2031        index = mBluetoothSelectA2dpCodec.findIndexOfValue(codecType);
2032        switch (index) {
2033        case 0:
2034            // Reset the priority of the current codec to default
2035            String oldValue = mBluetoothSelectA2dpCodec.getValue();
2036            switch (mBluetoothSelectA2dpCodec.findIndexOfValue(oldValue)) {
2037            case 0:
2038                break;      // No current codec
2039            case 1:
2040                codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC;
2041                break;
2042            case 2:
2043                codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC;
2044                break;
2045            case 3:
2046                codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX;
2047                break;
2048            case 4:
2049                codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD;
2050                break;
2051            case 5:
2052                codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC;
2053                break;
2054            default:
2055                break;
2056            }
2057            break;
2058        case 1:
2059            codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC;
2060            codecPriorityValue = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST;
2061            break;
2062        case 2:
2063            codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC;
2064            codecPriorityValue = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST;
2065            break;
2066        case 3:
2067            codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX;
2068            codecPriorityValue = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST;
2069            break;
2070        case 4:
2071            codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD;
2072            codecPriorityValue = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST;
2073            break;
2074        case 5:
2075            codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC;
2076            codecPriorityValue = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST;
2077            break;
2078        case 6:
2079        synchronized (mBluetoothA2dpLock) {
2080            if (mBluetoothA2dp != null) {
2081                mBluetoothA2dp.enableOptionalCodecs();
2082            }
2083        }
2084        return;
2085        case 7:
2086        synchronized (mBluetoothA2dpLock) {
2087            if (mBluetoothA2dp != null) {
2088                mBluetoothA2dp.disableOptionalCodecs();
2089            }
2090        }
2091        return;
2092        default:
2093            break;
2094        }
2095
2096        // Sample Rate
2097        String sampleRate = mBluetoothSelectA2dpSampleRate.getValue();
2098        if (preference == mBluetoothSelectA2dpSampleRate) {
2099            sampleRate = newValue.toString();
2100            index = mBluetoothSelectA2dpSampleRate.findIndexOfValue(newValue.toString());
2101            if (index >= 0) {
2102                summaries = getResources().getStringArray(R.array.bluetooth_a2dp_codec_sample_rate_summaries);
2103                mBluetoothSelectA2dpSampleRate.setSummary(summaries[index]);
2104            }
2105        }
2106        index = mBluetoothSelectA2dpSampleRate.findIndexOfValue(sampleRate);
2107        switch (index) {
2108        case 0:
2109            // Reset to default
2110            break;
2111        case 1:
2112            sampleRateValue = BluetoothCodecConfig.SAMPLE_RATE_44100;
2113            break;
2114        case 2:
2115            sampleRateValue = BluetoothCodecConfig.SAMPLE_RATE_48000;
2116            break;
2117        case 3:
2118            sampleRateValue = BluetoothCodecConfig.SAMPLE_RATE_88200;
2119            break;
2120        case 4:
2121            sampleRateValue = BluetoothCodecConfig.SAMPLE_RATE_96000;
2122            break;
2123        default:
2124            break;
2125        }
2126
2127        // Bits Per Sample
2128        String bitsPerSample = mBluetoothSelectA2dpBitsPerSample.getValue();
2129        if (preference == mBluetoothSelectA2dpBitsPerSample) {
2130            bitsPerSample = newValue.toString();
2131            index = mBluetoothSelectA2dpBitsPerSample.findIndexOfValue(newValue.toString());
2132            if (index >= 0) {
2133                summaries = getResources().getStringArray(R.array.bluetooth_a2dp_codec_bits_per_sample_summaries);
2134                mBluetoothSelectA2dpBitsPerSample.setSummary(summaries[index]);
2135            }
2136        }
2137        index = mBluetoothSelectA2dpBitsPerSample.findIndexOfValue(bitsPerSample);
2138        switch (index) {
2139        case 0:
2140            // Reset to default
2141            break;
2142        case 1:
2143            bitsPerSampleValue = BluetoothCodecConfig.BITS_PER_SAMPLE_16;
2144            break;
2145        case 2:
2146            bitsPerSampleValue = BluetoothCodecConfig.BITS_PER_SAMPLE_24;
2147            break;
2148        case 3:
2149            bitsPerSampleValue = BluetoothCodecConfig.BITS_PER_SAMPLE_32;
2150            break;
2151        default:
2152            break;
2153        }
2154
2155        // Channel Mode
2156        String channelMode = mBluetoothSelectA2dpChannelMode.getValue();
2157        if (preference == mBluetoothSelectA2dpChannelMode) {
2158            channelMode = newValue.toString();
2159            index = mBluetoothSelectA2dpChannelMode.findIndexOfValue(newValue.toString());
2160            if (index >= 0) {
2161                summaries = getResources().getStringArray(R.array.bluetooth_a2dp_codec_channel_mode_summaries);
2162                mBluetoothSelectA2dpChannelMode.setSummary(summaries[index]);
2163            }
2164        }
2165        index = mBluetoothSelectA2dpChannelMode.findIndexOfValue(channelMode);
2166        switch (index) {
2167        case 0:
2168            // Reset to default
2169            break;
2170        case 1:
2171            channelModeValue = BluetoothCodecConfig.CHANNEL_MODE_MONO;
2172            break;
2173        case 2:
2174            channelModeValue = BluetoothCodecConfig.CHANNEL_MODE_STEREO;
2175            break;
2176        default:
2177            break;
2178        }
2179
2180        // LDAC Playback Quality
2181        String ldacPlaybackQuality = mBluetoothSelectA2dpLdacPlaybackQuality.getValue();
2182        if (preference == mBluetoothSelectA2dpLdacPlaybackQuality) {
2183            ldacPlaybackQuality = newValue.toString();
2184            index = mBluetoothSelectA2dpLdacPlaybackQuality.findIndexOfValue(newValue.toString());
2185            if (index >= 0) {
2186                summaries = getResources().getStringArray(R.array.bluetooth_a2dp_codec_ldac_playback_quality_summaries);
2187                mBluetoothSelectA2dpLdacPlaybackQuality.setSummary(summaries[index]);
2188            }
2189        }
2190        index = mBluetoothSelectA2dpLdacPlaybackQuality.findIndexOfValue(ldacPlaybackQuality);
2191        switch (index) {
2192        case 0:
2193        case 1:
2194        case 2:
2195        case 3:
2196            codecSpecific1Value = 1000 + index;
2197            break;
2198        default:
2199            break;
2200        }
2201
2202        BluetoothCodecConfig codecConfig =
2203            new BluetoothCodecConfig(codecTypeValue, codecPriorityValue,
2204                                     sampleRateValue, bitsPerSampleValue,
2205                                     channelModeValue, codecSpecific1Value,
2206                                     codecSpecific2Value, codecSpecific3Value,
2207                                     codecSpecific4Value);
2208
2209        synchronized (mBluetoothA2dpLock) {
2210            if (mBluetoothA2dp != null) {
2211                mBluetoothA2dp.setCodecConfigPreference(codecConfig);
2212            }
2213        }
2214    }
2215
2216    private void writeImmediatelyDestroyActivitiesOptions() {
2217        try {
2218            ActivityManager.getService().setAlwaysFinish(
2219                    mImmediatelyDestroyActivities.isChecked());
2220        } catch (RemoteException ex) {
2221        }
2222    }
2223
2224    private void updateImmediatelyDestroyActivitiesOptions() {
2225        updateSwitchPreference(mImmediatelyDestroyActivities, Settings.Global.getInt(
2226                getActivity().getContentResolver(), Settings.Global.ALWAYS_FINISH_ACTIVITIES, 0)
2227                != 0);
2228    }
2229
2230    private void updateAnimationScaleValue(int which, ListPreference pref) {
2231        try {
2232            float scale = mWindowManager.getAnimationScale(which);
2233            if (scale != 1) {
2234                mHaveDebugSettings = true;
2235            }
2236            CharSequence[] values = pref.getEntryValues();
2237            for (int i = 0; i < values.length; i++) {
2238                float val = Float.parseFloat(values[i].toString());
2239                if (scale <= val) {
2240                    pref.setValueIndex(i);
2241                    pref.setSummary(pref.getEntries()[i]);
2242                    return;
2243                }
2244            }
2245            pref.setValueIndex(values.length - 1);
2246            pref.setSummary(pref.getEntries()[0]);
2247        } catch (RemoteException e) {
2248        }
2249    }
2250
2251    private void updateAnimationScaleOptions() {
2252        updateAnimationScaleValue(0, mWindowAnimationScale);
2253        updateAnimationScaleValue(1, mTransitionAnimationScale);
2254        updateAnimationScaleValue(2, mAnimatorDurationScale);
2255    }
2256
2257    private void writeAnimationScaleOption(int which, ListPreference pref, Object newValue) {
2258        try {
2259            float scale = newValue != null ? Float.parseFloat(newValue.toString()) : 1;
2260            mWindowManager.setAnimationScale(which, scale);
2261            updateAnimationScaleValue(which, pref);
2262        } catch (RemoteException e) {
2263        }
2264    }
2265
2266    private void updateOverlayDisplayDevicesOptions() {
2267        String value = Settings.Global.getString(getActivity().getContentResolver(),
2268                Settings.Global.OVERLAY_DISPLAY_DEVICES);
2269        if (value == null) {
2270            value = "";
2271        }
2272
2273        CharSequence[] values = mOverlayDisplayDevices.getEntryValues();
2274        for (int i = 0; i < values.length; i++) {
2275            if (value.contentEquals(values[i])) {
2276                mOverlayDisplayDevices.setValueIndex(i);
2277                mOverlayDisplayDevices.setSummary(mOverlayDisplayDevices.getEntries()[i]);
2278                return;
2279            }
2280        }
2281        mOverlayDisplayDevices.setValueIndex(0);
2282        mOverlayDisplayDevices.setSummary(mOverlayDisplayDevices.getEntries()[0]);
2283    }
2284
2285    private void writeOverlayDisplayDevicesOptions(Object newValue) {
2286        Settings.Global.putString(getActivity().getContentResolver(),
2287                Settings.Global.OVERLAY_DISPLAY_DEVICES, (String) newValue);
2288        updateOverlayDisplayDevicesOptions();
2289    }
2290
2291    private void updateAppProcessLimitOptions() {
2292        try {
2293            int limit = ActivityManager.getService().getProcessLimit();
2294            CharSequence[] values = mAppProcessLimit.getEntryValues();
2295            for (int i = 0; i < values.length; i++) {
2296                int val = Integer.parseInt(values[i].toString());
2297                if (val >= limit) {
2298                    if (i != 0) {
2299                        mHaveDebugSettings = true;
2300                    }
2301                    mAppProcessLimit.setValueIndex(i);
2302                    mAppProcessLimit.setSummary(mAppProcessLimit.getEntries()[i]);
2303                    return;
2304                }
2305            }
2306            mAppProcessLimit.setValueIndex(0);
2307            mAppProcessLimit.setSummary(mAppProcessLimit.getEntries()[0]);
2308        } catch (RemoteException e) {
2309        }
2310    }
2311
2312    private void writeAppProcessLimitOptions(Object newValue) {
2313        try {
2314            int limit = newValue != null ? Integer.parseInt(newValue.toString()) : -1;
2315            ActivityManager.getService().setProcessLimit(limit);
2316            updateAppProcessLimitOptions();
2317        } catch (RemoteException e) {
2318        }
2319    }
2320
2321    private void writeShowAllANRsOptions() {
2322        Settings.Secure.putInt(getActivity().getContentResolver(),
2323                Settings.Secure.ANR_SHOW_BACKGROUND,
2324                mShowAllANRs.isChecked() ? 1 : 0);
2325    }
2326
2327    private void updateShowAllANRsOptions() {
2328        updateSwitchPreference(mShowAllANRs, Settings.Secure.getInt(
2329                getActivity().getContentResolver(), Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0);
2330    }
2331
2332    private void writeShowNotificationChannelWarningsOptions() {
2333        Settings.Global.putInt(getActivity().getContentResolver(),
2334                Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS,
2335                mShowNotificationChannelWarnings.isChecked() ? 1 : 0);
2336    }
2337
2338    private void updateShowNotificationChannelWarningsOptions() {
2339        final int defaultWarningEnabled = Build.IS_DEBUGGABLE ? 1 : 0;
2340        updateSwitchPreference(mShowNotificationChannelWarnings, Settings.Global.getInt(
2341                getActivity().getContentResolver(),
2342                Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, defaultWarningEnabled) != 0);
2343    }
2344
2345    private void confirmEnableOemUnlock() {
2346        DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
2347            @Override
2348            public void onClick(DialogInterface dialog, int which) {
2349                if (which == DialogInterface.BUTTON_POSITIVE) {
2350                    mOemLockManager.setOemUnlockAllowedByUser(true);
2351                }
2352            }
2353        };
2354
2355        DialogInterface.OnDismissListener onDismissListener =
2356                new DialogInterface.OnDismissListener() {
2357                    @Override
2358                    public void onDismiss(DialogInterface dialog) {
2359                        if (getActivity() == null) {
2360                            return;
2361                        }
2362                        updateAllOptions();
2363                    }
2364                };
2365
2366        new AlertDialog.Builder(getActivity())
2367                .setTitle(R.string.confirm_enable_oem_unlock_title)
2368                .setMessage(R.string.confirm_enable_oem_unlock_text)
2369                .setPositiveButton(R.string.enable_text, onClickListener)
2370                .setNegativeButton(android.R.string.cancel, null)
2371                .setOnDismissListener(onDismissListener)
2372                .create()
2373                .show();
2374    }
2375
2376    @Override
2377    public void onSwitchChanged(Switch switchView, boolean isChecked) {
2378        if (switchView != mSwitchBar.getSwitch()) {
2379            return;
2380        }
2381        final boolean lastEnabledState = mSettingsEnabler.getLastEnabledState();
2382        if (isChecked != lastEnabledState) {
2383            if (isChecked) {
2384                mDialogClicked = false;
2385                if (mEnableDialog != null) dismissDialogs();
2386                mEnableDialog = new AlertDialog.Builder(getActivity()).setMessage(
2387                        getActivity().getResources().getString(
2388                                R.string.dev_settings_warning_message))
2389                        .setTitle(R.string.dev_settings_warning_title)
2390                        .setPositiveButton(android.R.string.yes, this)
2391                        .setNegativeButton(android.R.string.no, this)
2392                        .show();
2393                mEnableDialog.setOnDismissListener(this);
2394            } else {
2395                resetDangerousOptions();
2396                mSettingsEnabler.disableDevelopmentSettings();
2397                setPrefsEnabledState(false);
2398            }
2399        }
2400    }
2401
2402    @Override
2403    public void onActivityResult(int requestCode, int resultCode, Intent data) {
2404        if (requestCode == RESULT_DEBUG_APP) {
2405            if (resultCode == Activity.RESULT_OK) {
2406                mDebugApp = data.getAction();
2407                writeDebuggerOptions();
2408                updateDebuggerOptions();
2409            }
2410        } else if (requestCode == RESULT_MOCK_LOCATION_APP) {
2411            if (resultCode == Activity.RESULT_OK) {
2412                mMockLocationApp = data.getAction();
2413                writeMockLocation();
2414                updateMockLocation();
2415            }
2416        } else if (requestCode == REQUEST_CODE_ENABLE_OEM_UNLOCK) {
2417            if (resultCode == Activity.RESULT_OK) {
2418                if (mEnableOemUnlock.isChecked()) {
2419                    confirmEnableOemUnlock();
2420                } else {
2421                    mOemLockManager.setOemUnlockAllowedByUser(false);
2422                }
2423            }
2424        } else {
2425            super.onActivityResult(requestCode, resultCode, data);
2426        }
2427    }
2428
2429    @Override
2430    public boolean onPreferenceTreeClick(Preference preference) {
2431        if (Utils.isMonkeyRunning()) {
2432            return false;
2433        }
2434
2435        if (mBugReportInPowerController.handlePreferenceTreeClick(preference)) {
2436            return true;
2437        }
2438
2439        if (mTelephonyMonitorController.handlePreferenceTreeClick(preference)) {
2440            return true;
2441        }
2442
2443        if (mWebViewAppPrefController.handlePreferenceTreeClick(preference)) {
2444            return true;
2445        }
2446
2447        if (mVerifyAppsOverUsbController.handlePreferenceTreeClick(preference)) {
2448            return true;
2449        }
2450
2451        if (mCameraHalHdrplusController.handlePreferenceTreeClick(preference)) {
2452            return true;
2453        }
2454
2455        if (mEnableAdbController.handlePreferenceTreeClick(preference)) {
2456            return true;
2457        }
2458
2459        if (preference == mClearAdbKeys) {
2460            if (mAdbKeysDialog != null) dismissDialogs();
2461            mAdbKeysDialog = new AlertDialog.Builder(getActivity())
2462                    .setMessage(R.string.adb_keys_warning_message)
2463                    .setPositiveButton(android.R.string.ok, this)
2464                    .setNegativeButton(android.R.string.cancel, null)
2465                    .show();
2466        } else if (preference == mEnableTerminal) {
2467            final PackageManager pm = getActivity().getPackageManager();
2468            pm.setApplicationEnabledSetting(TERMINAL_APP_PACKAGE,
2469                    mEnableTerminal.isChecked() ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
2470                            : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0);
2471        } else if (preference == mKeepScreenOn) {
2472            Settings.Global.putInt(getActivity().getContentResolver(),
2473                    Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
2474                    mKeepScreenOn.isChecked() ?
2475                            (BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB
2476                                    | BatteryManager.BATTERY_PLUGGED_WIRELESS) : 0);
2477        } else if (preference == mBtHciSnoopLog) {
2478            writeBtHciSnoopLogOptions();
2479        } else if (preference == mEnableOemUnlock && mEnableOemUnlock.isEnabled()) {
2480            if (mEnableOemUnlock.isChecked()) {
2481                if (!showKeyguardConfirmation(getResources(), REQUEST_CODE_ENABLE_OEM_UNLOCK)) {
2482                    confirmEnableOemUnlock();
2483                }
2484            } else {
2485                mOemLockManager.setOemUnlockAllowedByUser(false);
2486            }
2487        } else if (preference == mMockLocationAppPref) {
2488            Intent intent = new Intent(getActivity(), AppPicker.class);
2489            intent.putExtra(AppPicker.EXTRA_REQUESTIING_PERMISSION,
2490                    Manifest.permission.ACCESS_MOCK_LOCATION);
2491            startActivityForResult(intent, RESULT_MOCK_LOCATION_APP);
2492        } else if (preference == mDebugViewAttributes) {
2493            Settings.Global.putInt(getActivity().getContentResolver(),
2494                    Settings.Global.DEBUG_VIEW_ATTRIBUTES,
2495                    mDebugViewAttributes.isChecked() ? 1 : 0);
2496        } else if (preference == mForceAllowOnExternal) {
2497            Settings.Global.putInt(getActivity().getContentResolver(),
2498                    Settings.Global.FORCE_ALLOW_ON_EXTERNAL,
2499                    mForceAllowOnExternal.isChecked() ? 1 : 0);
2500        } else if (preference == mDebugAppPref) {
2501            Intent intent = new Intent(getActivity(), AppPicker.class);
2502            intent.putExtra(AppPicker.EXTRA_DEBUGGABLE, true);
2503            startActivityForResult(intent, RESULT_DEBUG_APP);
2504        } else if (preference == mWaitForDebugger) {
2505            writeDebuggerOptions();
2506        } else if (preference == mOtaDisableAutomaticUpdate) {
2507            writeOtaDisableAutomaticUpdateOptions();
2508        } else if (preference == mStrictMode) {
2509            writeStrictModeVisualOptions();
2510        } else if (preference == mPointerLocation) {
2511            writePointerLocationOptions();
2512        } else if (preference == mShowTouches) {
2513            writeShowTouchesOptions();
2514        } else if (preference == mShowScreenUpdates) {
2515            writeShowUpdatesOption();
2516        } else if (preference == mDisableOverlays) {
2517            writeDisableOverlaysOption();
2518        } else if (preference == mImmediatelyDestroyActivities) {
2519            writeImmediatelyDestroyActivitiesOptions();
2520        } else if (preference == mShowAllANRs) {
2521            writeShowAllANRsOptions();
2522        } else if (preference == mShowNotificationChannelWarnings) {
2523            writeShowNotificationChannelWarningsOptions();
2524        } else if (preference == mForceHardwareUi) {
2525            writeHardwareUiOptions();
2526        } else if (preference == mForceMsaa) {
2527            writeMsaaOptions();
2528        } else if (preference == mShowHwScreenUpdates) {
2529            writeShowHwScreenUpdatesOptions();
2530        } else if (preference == mShowHwLayersUpdates) {
2531            writeShowHwLayersUpdatesOptions();
2532        } else if (preference == mDebugLayout) {
2533            writeDebugLayoutOptions();
2534        } else if (preference == mForceRtlLayout) {
2535            writeForceRtlOptions();
2536        } else if (preference == mWifiDisplayCertification) {
2537            writeWifiDisplayCertificationOptions();
2538        } else if (preference == mWifiVerboseLogging) {
2539            writeWifiVerboseLoggingOptions();
2540        } else if (preference == mWifiAggressiveHandover) {
2541            writeWifiAggressiveHandoverOptions();
2542        } else if (preference == mWifiAllowScansWithTraffic) {
2543            writeWifiAllowScansWithTrafficOptions();
2544        } else if (preference == mMobileDataAlwaysOn) {
2545            writeMobileDataAlwaysOnOptions();
2546        } else if (preference == mTetheringHardwareOffload) {
2547            writeTetheringHardwareOffloadOptions();
2548        } else if (preference == mColorTemperaturePreference) {
2549            writeColorTemperature();
2550        } else if (preference == mUSBAudio) {
2551            writeUSBAudioOptions();
2552        } else if (preference == mForceResizable) {
2553            writeForceResizableOptions();
2554        } else if (preference == mBluetoothShowDevicesWithoutNames) {
2555            writeBluetoothShowDevicesWithoutUserFriendlyNameOptions();
2556        } else if (preference == mBluetoothDisableAbsVolume) {
2557            writeBluetoothDisableAbsVolumeOptions();
2558        } else if (preference == mBluetoothEnableInbandRinging) {
2559            writeBluetoothEnableInbandRingingOptions();
2560        } else if (SHORTCUT_MANAGER_RESET_KEY.equals(preference.getKey())) {
2561            resetShortcutManagerThrottling();
2562        } else {
2563            return super.onPreferenceTreeClick(preference);
2564        }
2565
2566        return false;
2567    }
2568
2569    private boolean showKeyguardConfirmation(Resources resources, int requestCode) {
2570        return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(
2571                requestCode, resources.getString(R.string.oem_unlock_enable));
2572    }
2573
2574    @Override
2575    public boolean onPreferenceChange(Preference preference, Object newValue) {
2576        if (HDCP_CHECKING_KEY.equals(preference.getKey())) {
2577            SystemProperties.set(HDCP_CHECKING_PROPERTY, newValue.toString());
2578            updateHdcpValues();
2579            pokeSystemProperties();
2580            return true;
2581        } else if (preference == mBluetoothSelectAvrcpVersion) {
2582           writeBluetoothAvrcpVersion(newValue);
2583           return true;
2584        } else if ((preference == mBluetoothSelectA2dpCodec) ||
2585                   (preference == mBluetoothSelectA2dpSampleRate) ||
2586                   (preference == mBluetoothSelectA2dpBitsPerSample) ||
2587                   (preference == mBluetoothSelectA2dpChannelMode) ||
2588                   (preference == mBluetoothSelectA2dpLdacPlaybackQuality)) {
2589            writeBluetoothConfigurationOption(preference, newValue);
2590            return true;
2591        } else if (preference == mLogdSize) {
2592            writeLogdSizeOption(newValue);
2593            return true;
2594        } else if (preference == mLogpersist) {
2595            writeLogpersistOption(newValue, false);
2596            return true;
2597        } else if (preference == mUsbConfiguration) {
2598            writeUsbConfigurationOption(newValue);
2599            return true;
2600        } else if (preference == mWindowAnimationScale) {
2601            writeAnimationScaleOption(0, mWindowAnimationScale, newValue);
2602            return true;
2603        } else if (preference == mTransitionAnimationScale) {
2604            writeAnimationScaleOption(1, mTransitionAnimationScale, newValue);
2605            return true;
2606        } else if (preference == mAnimatorDurationScale) {
2607            writeAnimationScaleOption(2, mAnimatorDurationScale, newValue);
2608            return true;
2609        } else if (preference == mOverlayDisplayDevices) {
2610            writeOverlayDisplayDevicesOptions(newValue);
2611            return true;
2612        } else if (preference == mTrackFrameTime) {
2613            writeTrackFrameTimeOptions(newValue);
2614            return true;
2615        } else if (preference == mDebugHwOverdraw) {
2616            writeDebugHwOverdrawOptions(newValue);
2617            return true;
2618        } else if (preference == mDebugHwRenderer) {
2619            writeDebugHwRendererOptions(newValue);
2620            return true;
2621        } else if (preference == mShowNonRectClip) {
2622            writeShowNonRectClipOptions(newValue);
2623            return true;
2624        } else if (preference == mAppProcessLimit) {
2625            writeAppProcessLimitOptions(newValue);
2626            return true;
2627        } else if (preference == mSimulateColorSpace) {
2628            writeSimulateColorSpace(newValue);
2629            return true;
2630        }
2631        return false;
2632    }
2633
2634    private void dismissDialogs() {
2635        mEnableAdbController.dismissDialogs();
2636        if (mAdbKeysDialog != null) {
2637            mAdbKeysDialog.dismiss();
2638            mAdbKeysDialog = null;
2639        }
2640        if (mEnableDialog != null) {
2641            mEnableDialog.dismiss();
2642            mEnableDialog = null;
2643        }
2644        if (mLogpersistClearDialog != null) {
2645            mLogpersistClearDialog.dismiss();
2646            mLogpersistClearDialog = null;
2647        }
2648    }
2649
2650    public void onClick(DialogInterface dialog, int which) {
2651        if (dialog == mAdbKeysDialog) {
2652            if (which == DialogInterface.BUTTON_POSITIVE) {
2653                try {
2654                    IBinder b = ServiceManager.getService(Context.USB_SERVICE);
2655                    IUsbManager service = IUsbManager.Stub.asInterface(b);
2656                    service.clearUsbDebuggingKeys();
2657                } catch (RemoteException e) {
2658                    Log.e(TAG, "Unable to clear adb keys", e);
2659                }
2660            }
2661        } else if (dialog == mEnableDialog) {
2662            if (which == DialogInterface.BUTTON_POSITIVE) {
2663                mDialogClicked = true;
2664                mSettingsEnabler.enableDevelopmentSettings();
2665                setPrefsEnabledState(true);
2666            } else {
2667                // Reset the toggle
2668                mSwitchBar.setChecked(false);
2669            }
2670        } else if (dialog == mLogpersistClearDialog) {
2671            if (which == DialogInterface.BUTTON_POSITIVE) {
2672                setLogpersistOff(true);
2673            } else {
2674                updateLogpersistValues();
2675            }
2676        }
2677    }
2678
2679    public void onDismiss(DialogInterface dialog) {
2680        // Assuming that onClick gets called first
2681        if (dialog == mEnableDialog) {
2682            if (!mDialogClicked) {
2683                mSwitchBar.setChecked(false);
2684            }
2685            mEnableDialog = null;
2686        } else if (dialog == mLogpersistClearDialog) {
2687            mLogpersistClearDialog = null;
2688        }
2689    }
2690
2691    @Override
2692    public void onDestroy() {
2693        dismissDialogs();
2694        super.onDestroy();
2695    }
2696
2697    void pokeSystemProperties() {
2698        if (!mDontPokeProperties) {
2699            //noinspection unchecked
2700            (new SystemPropPoker()).execute();
2701        }
2702    }
2703
2704    private BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
2705        @Override
2706        public void onReceive(Context context, Intent intent) {
2707            updateUsbConfigurationValues();
2708        }
2709    };
2710
2711    private BroadcastReceiver mBluetoothA2dpReceiver = new BroadcastReceiver() {
2712        @Override
2713        public void onReceive(Context context, Intent intent) {
2714            Log.d(TAG, "mBluetoothA2dpReceiver.onReceive intent=" + intent);
2715            String action = intent.getAction();
2716
2717            if (BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED.equals(action)) {
2718                BluetoothCodecStatus codecStatus =
2719                    (BluetoothCodecStatus)intent.getParcelableExtra(BluetoothCodecStatus.EXTRA_CODEC_STATUS);
2720                Log.d(TAG, "Received BluetoothCodecStatus=" + codecStatus);
2721                updateBluetoothA2dpConfigurationValues();
2722            }
2723        }
2724    };
2725
2726    private BluetoothProfile.ServiceListener mBluetoothA2dpServiceListener =
2727        new BluetoothProfile.ServiceListener() {
2728            public void onServiceConnected(int profile,
2729                                           BluetoothProfile proxy) {
2730                synchronized (mBluetoothA2dpLock) {
2731                    mBluetoothA2dp = (BluetoothA2dp) proxy;
2732                }
2733                updateBluetoothA2dpConfigurationValues();
2734            }
2735
2736            public void onServiceDisconnected(int profile) {
2737                synchronized (mBluetoothA2dpLock) {
2738                    mBluetoothA2dp = null;
2739                }
2740                updateBluetoothA2dpConfigurationValues();
2741            }
2742        };
2743
2744    public static class SystemPropPoker extends AsyncTask<Void, Void, Void> {
2745        @Override
2746        protected Void doInBackground(Void... params) {
2747            String[] services = ServiceManager.listServices();
2748            for (String service : services) {
2749                IBinder obj = ServiceManager.checkService(service);
2750                if (obj != null) {
2751                    Parcel data = Parcel.obtain();
2752                    try {
2753                        obj.transact(IBinder.SYSPROPS_TRANSACTION, data, null, 0);
2754                    } catch (RemoteException e) {
2755                    } catch (Exception e) {
2756                        Log.i(TAG, "Someone wrote a bad service '" + service
2757                                + "' that doesn't like to be poked: " + e);
2758                    }
2759                    data.recycle();
2760                }
2761            }
2762            return null;
2763        }
2764    }
2765
2766    private static boolean isPackageInstalled(Context context, String packageName) {
2767        try {
2768            return context.getPackageManager().getPackageInfo(packageName, 0) != null;
2769        } catch (NameNotFoundException e) {
2770            return false;
2771        }
2772    }
2773
2774
2775    /**
2776     * For Search.
2777     */
2778    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
2779            new BaseSearchIndexProvider() {
2780
2781                @Override
2782                protected boolean isPageSearchEnabled(Context context) {
2783                    return context.getSharedPreferences(DevelopmentSettings.PREF_FILE,
2784                            Context.MODE_PRIVATE).getBoolean(
2785                            DevelopmentSettings.PREF_SHOW,
2786                            android.os.Build.TYPE.equals("eng"));
2787                }
2788
2789                @Override
2790                public List<SearchIndexableResource> getXmlResourcesToIndex(
2791                        Context context, boolean enabled) {
2792
2793                    final SearchIndexableResource sir = new SearchIndexableResource(context);
2794                    sir.xmlResId = R.xml.development_prefs;
2795                    return Arrays.asList(sir);
2796                }
2797
2798                @Override
2799                public List<String> getNonIndexableKeys(Context context) {
2800                    final List<String> keys = super.getNonIndexableKeys(context);
2801
2802                    if (!showEnableOemUnlockPreference(context)) {
2803                        keys.add(ENABLE_OEM_UNLOCK);
2804                    }
2805                    return keys;
2806                }
2807            };
2808
2809    private void resetShortcutManagerThrottling() {
2810        final IShortcutService service = IShortcutService.Stub.asInterface(
2811                ServiceManager.getService(Context.SHORTCUT_SERVICE));
2812        if (service != null) {
2813            try {
2814                service.resetThrottling();
2815                Toast.makeText(getActivity(), R.string.reset_shortcut_manager_throttling_complete,
2816                        Toast.LENGTH_SHORT).show();
2817            } catch (RemoteException e) {
2818                Log.e(TAG, "Failed to reset rate limiting", e);
2819            }
2820        }
2821    }
2822
2823    private void updateOemUnlockSettingDescription() {
2824        if (mEnableOemUnlock != null) {
2825            int oemUnlockSummary = R.string.oem_unlock_enable_summary;
2826            if (isBootloaderUnlocked()) {
2827                oemUnlockSummary = R.string.oem_unlock_enable_disabled_summary_bootloader_unlocked;
2828            } else if (isSimLockedDevice()) {
2829                oemUnlockSummary = R.string.oem_unlock_enable_disabled_summary_sim_locked_device;
2830            } else if (!mOemLockManager.canUserAllowOemUnlock()) {
2831                // If the device isn't SIM-locked but OEM unlock is disallowed by some party, this
2832                // means either some other carrier restriction is in place or the device hasn't been
2833                // able to confirm which restrictions (SIM-lock or otherwise) apply.
2834                oemUnlockSummary =
2835                        R.string.oem_unlock_enable_disabled_summary_connectivity_or_locked;
2836            }
2837            mEnableOemUnlock.setSummary(getString(oemUnlockSummary));
2838        }
2839    }
2840
2841    /** Returns {@code true} if the device is SIM-locked. Otherwise, returns {@code false}. */
2842    private boolean isSimLockedDevice() {
2843        int phoneCount = mTelephonyManager.getPhoneCount();
2844        for (int i = 0; i < phoneCount; i++) {
2845            if (mTelephonyManager.getAllowedCarriers(i).size() > 0) {
2846                return true;
2847            }
2848        }
2849        return false;
2850    }
2851
2852    /**
2853     * Returns {@code true} if the bootloader has been unlocked. Otherwise, returns {code false}.
2854     */
2855    private boolean isBootloaderUnlocked() {
2856        return mOemLockManager.isDeviceOemUnlocked();
2857    }
2858
2859
2860}
2861