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