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