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