DevelopmentSettings.java revision 6b24c458139091836486cce774a2e1255668e001
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;
18
19import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
20
21import android.app.ActionBar;
22import android.app.Activity;
23import android.app.ActivityManagerNative;
24import android.app.ActivityThread;
25import android.app.AlertDialog;
26import android.app.Dialog;
27import android.app.DialogFragment;
28import android.app.admin.DevicePolicyManager;
29import android.app.backup.IBackupManager;
30import android.content.ContentResolver;
31import android.content.Context;
32import android.content.DialogInterface;
33import android.content.DialogInterface.OnClickListener;
34import android.content.Intent;
35import android.content.pm.ApplicationInfo;
36import android.content.pm.PackageManager;
37import android.content.pm.ResolveInfo;
38import android.hardware.usb.IUsbManager;
39import android.os.AsyncTask;
40import android.os.BatteryManager;
41import android.os.Build;
42import android.os.Bundle;
43import android.os.IBinder;
44import android.os.Parcel;
45import android.os.RemoteException;
46import android.os.ServiceManager;
47import android.os.StrictMode;
48import android.os.SystemProperties;
49import android.os.UserHandle;
50import android.preference.CheckBoxPreference;
51import android.preference.ListPreference;
52import android.preference.Preference;
53import android.preference.Preference.OnPreferenceChangeListener;
54import android.preference.PreferenceFragment;
55import android.preference.PreferenceGroup;
56import android.preference.PreferenceScreen;
57import android.provider.Settings;
58import android.text.TextUtils;
59import android.util.Log;
60import android.view.Gravity;
61import android.view.HardwareRenderer;
62import android.view.IWindowManager;
63import android.view.View;
64import android.widget.CompoundButton;
65import android.widget.Switch;
66
67import java.util.ArrayList;
68import java.util.HashSet;
69import java.util.List;
70
71/*
72 * Displays preferences for application developers.
73 */
74public class DevelopmentSettings extends PreferenceFragment
75        implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
76                OnPreferenceChangeListener, CompoundButton.OnCheckedChangeListener {
77    private static final String TAG = "DevelopmentSettings";
78
79    /**
80     * Preference file were development settings prefs are stored.
81     */
82    public static final String PREF_FILE = "development";
83
84    /**
85     * Whether to show the development settings to the user.  Default is false.
86     */
87    public static final String PREF_SHOW = "show";
88
89    private static final String ENABLE_ADB = "enable_adb";
90    private static final String CLEAR_ADB_KEYS = "clear_adb_keys";
91    private static final String KEEP_SCREEN_ON = "keep_screen_on";
92    private static final String ALLOW_MOCK_LOCATION = "allow_mock_location";
93    private static final String HDCP_CHECKING_KEY = "hdcp_checking";
94    private static final String HDCP_CHECKING_PROPERTY = "persist.sys.hdcp_checking";
95    private static final String ENFORCE_READ_EXTERNAL = "enforce_read_external";
96    private static final String LOCAL_BACKUP_PASSWORD = "local_backup_password";
97    private static final String HARDWARE_UI_PROPERTY = "persist.sys.ui.hw";
98    private static final String MSAA_PROPERTY = "debug.egl.force_msaa";
99    private static final String BUGREPORT = "bugreport";
100    private static final String BUGREPORT_IN_POWER_KEY = "bugreport_in_power";
101    private static final String OPENGL_TRACES_PROPERTY = "debug.egl.trace";
102
103    private static final String DEBUG_APP_KEY = "debug_app";
104    private static final String WAIT_FOR_DEBUGGER_KEY = "wait_for_debugger";
105    private static final String VERIFY_APPS_OVER_USB_KEY = "verify_apps_over_usb";
106    private static final String STRICT_MODE_KEY = "strict_mode";
107    private static final String POINTER_LOCATION_KEY = "pointer_location";
108    private static final String SHOW_TOUCHES_KEY = "show_touches";
109    private static final String SHOW_SCREEN_UPDATES_KEY = "show_screen_updates";
110    private static final String DISABLE_OVERLAYS_KEY = "disable_overlays";
111    private static final String SHOW_CPU_USAGE_KEY = "show_cpu_usage";
112    private static final String FORCE_HARDWARE_UI_KEY = "force_hw_ui";
113    private static final String FORCE_MSAA_KEY = "force_msaa";
114    private static final String TRACK_FRAME_TIME_KEY = "track_frame_time";
115    private static final String SHOW_NON_RECTANGULAR_CLIP_KEY = "show_non_rect_clip";
116    private static final String SHOW_HW_SCREEN_UPDATES_KEY = "show_hw_screen_udpates";
117    private static final String SHOW_HW_LAYERS_UPDATES_KEY = "show_hw_layers_udpates";
118    private static final String SHOW_HW_OVERDRAW_KEY = "show_hw_overdraw";
119    private static final String DEBUG_LAYOUT_KEY = "debug_layout";
120    private static final String WINDOW_ANIMATION_SCALE_KEY = "window_animation_scale";
121    private static final String TRANSITION_ANIMATION_SCALE_KEY = "transition_animation_scale";
122    private static final String ANIMATOR_DURATION_SCALE_KEY = "animator_duration_scale";
123    private static final String OVERLAY_DISPLAY_DEVICES_KEY = "overlay_display_devices";
124    private static final String DEBUG_DEBUGGING_CATEGORY_KEY = "debug_debugging_category";
125    private static final String OPENGL_TRACES_KEY = "enable_opengl_traces";
126
127    private static final String IMMEDIATELY_DESTROY_ACTIVITIES_KEY
128            = "immediately_destroy_activities";
129    private static final String APP_PROCESS_LIMIT_KEY = "app_process_limit";
130
131    private static final String SHOW_ALL_ANRS_KEY = "show_all_anrs";
132
133    private static final String TAG_CONFIRM_ENFORCE = "confirm_enforce";
134
135    private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
136
137    private static final int RESULT_DEBUG_APP = 1000;
138
139    private IWindowManager mWindowManager;
140    private IBackupManager mBackupManager;
141    private DevicePolicyManager mDpm;
142
143    private Switch mEnabledSwitch;
144    private boolean mLastEnabledState;
145    private boolean mHaveDebugSettings;
146    private boolean mDontPokeProperties;
147
148    private CheckBoxPreference mEnableAdb;
149    private Preference mClearAdbKeys;
150    private Preference mBugreport;
151    private CheckBoxPreference mBugreportInPower;
152    private CheckBoxPreference mKeepScreenOn;
153    private CheckBoxPreference mEnforceReadExternal;
154    private CheckBoxPreference mAllowMockLocation;
155    private PreferenceScreen mPassword;
156
157    private String mDebugApp;
158    private Preference mDebugAppPref;
159    private CheckBoxPreference mWaitForDebugger;
160    private CheckBoxPreference mVerifyAppsOverUsb;
161
162    private CheckBoxPreference mStrictMode;
163    private CheckBoxPreference mPointerLocation;
164    private CheckBoxPreference mShowTouches;
165    private CheckBoxPreference mShowScreenUpdates;
166    private CheckBoxPreference mDisableOverlays;
167    private CheckBoxPreference mShowCpuUsage;
168    private CheckBoxPreference mForceHardwareUi;
169    private CheckBoxPreference mForceMsaa;
170    private CheckBoxPreference mShowHwScreenUpdates;
171    private CheckBoxPreference mShowHwLayersUpdates;
172    private CheckBoxPreference mShowHwOverdraw;
173    private CheckBoxPreference mDebugLayout;
174    private ListPreference mTrackFrameTime;
175    private ListPreference mShowNonRectClip;
176    private ListPreference mWindowAnimationScale;
177    private ListPreference mTransitionAnimationScale;
178    private ListPreference mAnimatorDurationScale;
179    private ListPreference mOverlayDisplayDevices;
180    private ListPreference mOpenGLTraces;
181
182    private CheckBoxPreference mImmediatelyDestroyActivities;
183    private ListPreference mAppProcessLimit;
184
185    private CheckBoxPreference mShowAllANRs;
186
187    private final ArrayList<Preference> mAllPrefs = new ArrayList<Preference>();
188    private final ArrayList<CheckBoxPreference> mResetCbPrefs
189            = new ArrayList<CheckBoxPreference>();
190
191    private final HashSet<Preference> mDisabledPrefs = new HashSet<Preference>();
192
193    // To track whether a confirmation dialog was clicked.
194    private boolean mDialogClicked;
195    private Dialog mEnableDialog;
196    private Dialog mAdbDialog;
197    private Dialog mAdbKeysDialog;
198
199    @Override
200    public void onCreate(Bundle icicle) {
201        super.onCreate(icicle);
202
203        mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
204        mBackupManager = IBackupManager.Stub.asInterface(
205                ServiceManager.getService(Context.BACKUP_SERVICE));
206        mDpm = (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
207
208        addPreferencesFromResource(R.xml.development_prefs);
209
210        mEnableAdb = findAndInitCheckboxPref(ENABLE_ADB);
211        mClearAdbKeys = findPreference(CLEAR_ADB_KEYS);
212        if (!SystemProperties.getBoolean("ro.adb.secure", false)) {
213            PreferenceGroup debugDebuggingCategory = (PreferenceGroup)
214                    findPreference(DEBUG_DEBUGGING_CATEGORY_KEY);
215            if (debugDebuggingCategory != null) {
216                debugDebuggingCategory.removePreference(mClearAdbKeys);
217            }
218        }
219
220        mBugreport = findPreference(BUGREPORT);
221        mBugreportInPower = findAndInitCheckboxPref(BUGREPORT_IN_POWER_KEY);
222        mKeepScreenOn = findAndInitCheckboxPref(KEEP_SCREEN_ON);
223        mEnforceReadExternal = findAndInitCheckboxPref(ENFORCE_READ_EXTERNAL);
224        mAllowMockLocation = findAndInitCheckboxPref(ALLOW_MOCK_LOCATION);
225        mPassword = (PreferenceScreen) findPreference(LOCAL_BACKUP_PASSWORD);
226        mAllPrefs.add(mPassword);
227
228        if (!android.os.Process.myUserHandle().equals(UserHandle.OWNER)) {
229            disableForUser(mEnableAdb);
230            disableForUser(mClearAdbKeys);
231            disableForUser(mPassword);
232        }
233
234        mDebugAppPref = findPreference(DEBUG_APP_KEY);
235        mAllPrefs.add(mDebugAppPref);
236        mWaitForDebugger = findAndInitCheckboxPref(WAIT_FOR_DEBUGGER_KEY);
237        mVerifyAppsOverUsb = findAndInitCheckboxPref(VERIFY_APPS_OVER_USB_KEY);
238        if (!showVerifierSetting()) {
239            PreferenceGroup debugDebuggingCategory = (PreferenceGroup)
240                    findPreference(DEBUG_DEBUGGING_CATEGORY_KEY);
241            if (debugDebuggingCategory != null) {
242                debugDebuggingCategory.removePreference(mVerifyAppsOverUsb);
243            } else {
244                mVerifyAppsOverUsb.setEnabled(false);
245            }
246        }
247        mStrictMode = findAndInitCheckboxPref(STRICT_MODE_KEY);
248        mPointerLocation = findAndInitCheckboxPref(POINTER_LOCATION_KEY);
249        mShowTouches = findAndInitCheckboxPref(SHOW_TOUCHES_KEY);
250        mShowScreenUpdates = findAndInitCheckboxPref(SHOW_SCREEN_UPDATES_KEY);
251        mDisableOverlays = findAndInitCheckboxPref(DISABLE_OVERLAYS_KEY);
252        mShowCpuUsage = findAndInitCheckboxPref(SHOW_CPU_USAGE_KEY);
253        mForceHardwareUi = findAndInitCheckboxPref(FORCE_HARDWARE_UI_KEY);
254        mForceMsaa = findAndInitCheckboxPref(FORCE_MSAA_KEY);
255        mTrackFrameTime = addListPreference(TRACK_FRAME_TIME_KEY);
256        mShowNonRectClip = addListPreference(SHOW_NON_RECTANGULAR_CLIP_KEY);
257        mShowHwScreenUpdates = findAndInitCheckboxPref(SHOW_HW_SCREEN_UPDATES_KEY);
258        mShowHwLayersUpdates = findAndInitCheckboxPref(SHOW_HW_LAYERS_UPDATES_KEY);
259        mShowHwOverdraw = findAndInitCheckboxPref(SHOW_HW_OVERDRAW_KEY);
260        mDebugLayout = findAndInitCheckboxPref(DEBUG_LAYOUT_KEY);
261        mWindowAnimationScale = addListPreference(WINDOW_ANIMATION_SCALE_KEY);
262        mTransitionAnimationScale = addListPreference(TRANSITION_ANIMATION_SCALE_KEY);
263        mAnimatorDurationScale = addListPreference(ANIMATOR_DURATION_SCALE_KEY);
264        mOverlayDisplayDevices = addListPreference(OVERLAY_DISPLAY_DEVICES_KEY);
265        mOpenGLTraces = addListPreference(OPENGL_TRACES_KEY);
266
267        mImmediatelyDestroyActivities = (CheckBoxPreference) findPreference(
268                IMMEDIATELY_DESTROY_ACTIVITIES_KEY);
269        mAllPrefs.add(mImmediatelyDestroyActivities);
270        mResetCbPrefs.add(mImmediatelyDestroyActivities);
271        mAppProcessLimit = addListPreference(APP_PROCESS_LIMIT_KEY);
272
273        mShowAllANRs = (CheckBoxPreference) findPreference(
274                SHOW_ALL_ANRS_KEY);
275        mAllPrefs.add(mShowAllANRs);
276        mResetCbPrefs.add(mShowAllANRs);
277
278        Preference hdcpChecking = findPreference(HDCP_CHECKING_KEY);
279        if (hdcpChecking != null) {
280            mAllPrefs.add(hdcpChecking);
281        }
282        removeHdcpOptionsForProduction();
283    }
284
285    private ListPreference addListPreference(String prefKey) {
286        ListPreference pref = (ListPreference) findPreference(prefKey);
287        mAllPrefs.add(pref);
288        pref.setOnPreferenceChangeListener(this);
289        return pref;
290    }
291
292    private void disableForUser(Preference pref) {
293        if (pref != null) {
294            pref.setEnabled(false);
295            mDisabledPrefs.add(pref);
296        }
297    }
298
299    private CheckBoxPreference findAndInitCheckboxPref(String key) {
300        CheckBoxPreference pref = (CheckBoxPreference) findPreference(key);
301        if (pref == null) {
302            throw new IllegalArgumentException("Cannot find preference with key = " + key);
303        }
304        mAllPrefs.add(pref);
305        mResetCbPrefs.add(pref);
306        return pref;
307    }
308
309    @Override
310    public void onActivityCreated(Bundle savedInstanceState) {
311        super.onActivityCreated(savedInstanceState);
312
313        final Activity activity = getActivity();
314        mEnabledSwitch = new Switch(activity);
315
316        final int padding = activity.getResources().getDimensionPixelSize(
317                R.dimen.action_bar_switch_padding);
318        mEnabledSwitch.setPaddingRelative(0, 0, padding, 0);
319        mEnabledSwitch.setOnCheckedChangeListener(this);
320    }
321
322    @Override
323    public void onStart() {
324        super.onStart();
325        final Activity activity = getActivity();
326        activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
327                ActionBar.DISPLAY_SHOW_CUSTOM);
328        activity.getActionBar().setCustomView(mEnabledSwitch, new ActionBar.LayoutParams(
329                ActionBar.LayoutParams.WRAP_CONTENT,
330                ActionBar.LayoutParams.WRAP_CONTENT,
331                Gravity.CENTER_VERTICAL | Gravity.END));
332    }
333
334    @Override
335    public void onStop() {
336        super.onStop();
337        final Activity activity = getActivity();
338        activity.getActionBar().setDisplayOptions(0, ActionBar.DISPLAY_SHOW_CUSTOM);
339        activity.getActionBar().setCustomView(null);
340    }
341
342    private void removeHdcpOptionsForProduction() {
343        if ("user".equals(Build.TYPE)) {
344            Preference hdcpChecking = findPreference(HDCP_CHECKING_KEY);
345            if (hdcpChecking != null) {
346                // Remove the preference
347                getPreferenceScreen().removePreference(hdcpChecking);
348                mAllPrefs.remove(hdcpChecking);
349            }
350        }
351    }
352
353    private void setPrefsEnabledState(boolean enabled) {
354        for (int i = 0; i < mAllPrefs.size(); i++) {
355            Preference pref = mAllPrefs.get(i);
356            pref.setEnabled(enabled && !mDisabledPrefs.contains(pref));
357        }
358        updateAllOptions();
359    }
360
361    @Override
362    public void onResume() {
363        super.onResume();
364
365        if (mDpm.getMaximumTimeToLock(null) > 0) {
366            // A DeviceAdmin has specified a maximum time until the device
367            // will lock...  in this case we can't allow the user to turn
368            // on "stay awake when plugged in" because that would defeat the
369            // restriction.
370            mDisabledPrefs.add(mKeepScreenOn);
371        } else {
372            mDisabledPrefs.remove(mKeepScreenOn);
373        }
374
375        final ContentResolver cr = getActivity().getContentResolver();
376        mLastEnabledState = Settings.Global.getInt(cr,
377                Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
378        mEnabledSwitch.setChecked(mLastEnabledState);
379        setPrefsEnabledState(mLastEnabledState);
380
381        if (mHaveDebugSettings && !mLastEnabledState) {
382            // Overall debugging is disabled, but there are some debug
383            // settings that are enabled.  This is an invalid state.  Switch
384            // to debug settings being enabled, so the user knows there is
385            // stuff enabled and can turn it all off if they want.
386            Settings.Global.putInt(getActivity().getContentResolver(),
387                    Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
388            mLastEnabledState = true;
389            mEnabledSwitch.setChecked(mLastEnabledState);
390            setPrefsEnabledState(mLastEnabledState);
391        }
392    }
393
394    void updateCheckBox(CheckBoxPreference checkBox, boolean value) {
395        checkBox.setChecked(value);
396        mHaveDebugSettings |= value;
397    }
398
399    private void updateAllOptions() {
400        final Context context = getActivity();
401        final ContentResolver cr = context.getContentResolver();
402        mHaveDebugSettings = false;
403        updateCheckBox(mEnableAdb, Settings.Global.getInt(cr,
404                Settings.Global.ADB_ENABLED, 0) != 0);
405        updateCheckBox(mBugreportInPower, Settings.Secure.getInt(cr,
406                Settings.Secure.BUGREPORT_IN_POWER_MENU, 0) != 0);
407        updateCheckBox(mKeepScreenOn, Settings.Global.getInt(cr,
408                Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0) != 0);
409        updateCheckBox(mEnforceReadExternal, isPermissionEnforced(READ_EXTERNAL_STORAGE));
410        updateCheckBox(mAllowMockLocation, Settings.Secure.getInt(cr,
411                Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0);
412        updateHdcpValues();
413        updatePasswordSummary();
414        updateDebuggerOptions();
415        updateStrictModeVisualOptions();
416        updatePointerLocationOptions();
417        updateShowTouchesOptions();
418        updateFlingerOptions();
419        updateCpuUsageOptions();
420        updateHardwareUiOptions();
421        updateMsaaOptions();
422        updateTrackFrameTimeOptions();
423        updateShowNonRectClipOptions();
424        updateShowHwScreenUpdatesOptions();
425        updateShowHwLayersUpdatesOptions();
426        updateShowHwOverdrawOptions();
427        updateDebugLayoutOptions();
428        updateAnimationScaleOptions();
429        updateOverlayDisplayDevicesOptions();
430        updateOpenGLTracesOptions();
431        updateImmediatelyDestroyActivitiesOptions();
432        updateAppProcessLimitOptions();
433        updateShowAllANRsOptions();
434        updateVerifyAppsOverUsbOptions();
435        updateBugreportOptions();
436    }
437
438    private void resetDangerousOptions() {
439        mDontPokeProperties = true;
440        for (int i=0; i<mResetCbPrefs.size(); i++) {
441            CheckBoxPreference cb = mResetCbPrefs.get(i);
442            if (cb.isChecked()) {
443                cb.setChecked(false);
444                onPreferenceTreeClick(null, cb);
445            }
446        }
447        resetDebuggerOptions();
448        writeAnimationScaleOption(0, mWindowAnimationScale, null);
449        writeAnimationScaleOption(1, mTransitionAnimationScale, null);
450        writeAnimationScaleOption(2, mAnimatorDurationScale, null);
451        writeOverlayDisplayDevicesOptions(null);
452        writeAppProcessLimitOptions(null);
453        mHaveDebugSettings = false;
454        updateAllOptions();
455        mDontPokeProperties = false;
456        pokeSystemProperties();
457    }
458
459    private void updateHdcpValues() {
460        int index = 1; // Defaults to drm-only. Needs to match with R.array.hdcp_checking_values
461        ListPreference hdcpChecking = (ListPreference) findPreference(HDCP_CHECKING_KEY);
462        if (hdcpChecking != null) {
463            String currentValue = SystemProperties.get(HDCP_CHECKING_PROPERTY);
464            String[] values = getResources().getStringArray(R.array.hdcp_checking_values);
465            String[] summaries = getResources().getStringArray(R.array.hdcp_checking_summaries);
466            for (int i = 0; i < values.length; i++) {
467                if (currentValue.equals(values[i])) {
468                    index = i;
469                    break;
470                }
471            }
472            hdcpChecking.setValue(values[index]);
473            hdcpChecking.setSummary(summaries[index]);
474            hdcpChecking.setOnPreferenceChangeListener(this);
475        }
476    }
477
478    private void updatePasswordSummary() {
479        try {
480            if (mBackupManager.hasBackupPassword()) {
481                mPassword.setSummary(R.string.local_backup_password_summary_change);
482            } else {
483                mPassword.setSummary(R.string.local_backup_password_summary_none);
484            }
485        } catch (RemoteException e) {
486            // Not much we can do here
487        }
488    }
489
490    private void writeDebuggerOptions() {
491        try {
492            ActivityManagerNative.getDefault().setDebugApp(
493                mDebugApp, mWaitForDebugger.isChecked(), true);
494        } catch (RemoteException ex) {
495        }
496    }
497
498    private static void resetDebuggerOptions() {
499        try {
500            ActivityManagerNative.getDefault().setDebugApp(
501                    null, false, true);
502        } catch (RemoteException ex) {
503        }
504    }
505
506    private void updateDebuggerOptions() {
507        mDebugApp = Settings.Global.getString(
508                getActivity().getContentResolver(), Settings.Global.DEBUG_APP);
509        updateCheckBox(mWaitForDebugger, Settings.Global.getInt(
510                getActivity().getContentResolver(), Settings.Global.WAIT_FOR_DEBUGGER, 0) != 0);
511        if (mDebugApp != null && mDebugApp.length() > 0) {
512            String label;
513            try {
514                ApplicationInfo ai = getActivity().getPackageManager().getApplicationInfo(mDebugApp,
515                        PackageManager.GET_DISABLED_COMPONENTS);
516                CharSequence lab = getActivity().getPackageManager().getApplicationLabel(ai);
517                label = lab != null ? lab.toString() : mDebugApp;
518            } catch (PackageManager.NameNotFoundException e) {
519                label = mDebugApp;
520            }
521            mDebugAppPref.setSummary(getResources().getString(R.string.debug_app_set, label));
522            mWaitForDebugger.setEnabled(true);
523            mHaveDebugSettings = true;
524        } else {
525            mDebugAppPref.setSummary(getResources().getString(R.string.debug_app_not_set));
526            mWaitForDebugger.setEnabled(false);
527        }
528    }
529
530    private void updateVerifyAppsOverUsbOptions() {
531        updateCheckBox(mVerifyAppsOverUsb, Settings.Global.getInt(getActivity().getContentResolver(),
532                Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) != 0);
533        mVerifyAppsOverUsb.setEnabled(enableVerifierSetting());
534    }
535
536    private void writeVerifyAppsOverUsbOptions() {
537        Settings.Global.putInt(getActivity().getContentResolver(),
538              Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, mVerifyAppsOverUsb.isChecked() ? 1 : 0);
539    }
540
541    private boolean enableVerifierSetting() {
542        final ContentResolver cr = getActivity().getContentResolver();
543        if (Settings.Global.getInt(cr, Settings.Global.ADB_ENABLED, 0) == 0) {
544            return false;
545        }
546        if (Settings.Global.getInt(cr, Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) == 0) {
547            return false;
548        } else {
549            final PackageManager pm = getActivity().getPackageManager();
550            final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
551            verification.setType(PACKAGE_MIME_TYPE);
552            verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
553            final List<ResolveInfo> receivers = pm.queryBroadcastReceivers(verification, 0);
554            if (receivers.size() == 0) {
555                return false;
556            }
557        }
558        return true;
559    }
560
561    private boolean showVerifierSetting() {
562        return Settings.Global.getInt(getActivity().getContentResolver(),
563                Settings.Global.PACKAGE_VERIFIER_SETTING_VISIBLE, 1) > 0;
564    }
565
566    private void updateBugreportOptions() {
567        if ("user".equals(Build.TYPE)) {
568            final ContentResolver resolver = getActivity().getContentResolver();
569            final boolean adbEnabled = Settings.Global.getInt(
570                    resolver, Settings.Global.ADB_ENABLED, 0) != 0;
571            if (adbEnabled) {
572                mBugreport.setEnabled(true);
573                mBugreportInPower.setEnabled(true);
574            } else {
575                mBugreport.setEnabled(false);
576                mBugreportInPower.setEnabled(false);
577                mBugreportInPower.setChecked(false);
578                Settings.Secure.putInt(resolver, Settings.Secure.BUGREPORT_IN_POWER_MENU, 0);
579            }
580        } else {
581            mBugreportInPower.setEnabled(true);
582        }
583    }
584
585    // Returns the current state of the system property that controls
586    // strictmode flashes.  One of:
587    //    0: not explicitly set one way or another
588    //    1: on
589    //    2: off
590    private static int currentStrictModeActiveIndex() {
591        if (TextUtils.isEmpty(SystemProperties.get(StrictMode.VISUAL_PROPERTY))) {
592            return 0;
593        }
594        boolean enabled = SystemProperties.getBoolean(StrictMode.VISUAL_PROPERTY, false);
595        return enabled ? 1 : 2;
596    }
597
598    private void writeStrictModeVisualOptions() {
599        try {
600            mWindowManager.setStrictModeVisualIndicatorPreference(mStrictMode.isChecked()
601                    ? "1" : "");
602        } catch (RemoteException e) {
603        }
604    }
605
606    private void updateStrictModeVisualOptions() {
607        updateCheckBox(mStrictMode, currentStrictModeActiveIndex() == 1);
608    }
609
610    private void writePointerLocationOptions() {
611        Settings.System.putInt(getActivity().getContentResolver(),
612                Settings.System.POINTER_LOCATION, mPointerLocation.isChecked() ? 1 : 0);
613    }
614
615    private void updatePointerLocationOptions() {
616        updateCheckBox(mPointerLocation, Settings.System.getInt(getActivity().getContentResolver(),
617                Settings.System.POINTER_LOCATION, 0) != 0);
618    }
619
620    private void writeShowTouchesOptions() {
621        Settings.System.putInt(getActivity().getContentResolver(),
622                Settings.System.SHOW_TOUCHES, mShowTouches.isChecked() ? 1 : 0);
623    }
624
625    private void updateShowTouchesOptions() {
626        updateCheckBox(mShowTouches, Settings.System.getInt(getActivity().getContentResolver(),
627                Settings.System.SHOW_TOUCHES, 0) != 0);
628    }
629
630    private void updateFlingerOptions() {
631        // magic communication with surface flinger.
632        try {
633            IBinder flinger = ServiceManager.getService("SurfaceFlinger");
634            if (flinger != null) {
635                Parcel data = Parcel.obtain();
636                Parcel reply = Parcel.obtain();
637                data.writeInterfaceToken("android.ui.ISurfaceComposer");
638                flinger.transact(1010, data, reply, 0);
639                @SuppressWarnings("unused")
640                int showCpu = reply.readInt();
641                @SuppressWarnings("unused")
642                int enableGL = reply.readInt();
643                int showUpdates = reply.readInt();
644                updateCheckBox(mShowScreenUpdates, showUpdates != 0);
645                @SuppressWarnings("unused")
646                int showBackground = reply.readInt();
647                int disableOverlays = reply.readInt();
648                updateCheckBox(mDisableOverlays, disableOverlays != 0);
649                reply.recycle();
650                data.recycle();
651            }
652        } catch (RemoteException ex) {
653        }
654    }
655
656    private void writeShowUpdatesOption() {
657        try {
658            IBinder flinger = ServiceManager.getService("SurfaceFlinger");
659            if (flinger != null) {
660                Parcel data = Parcel.obtain();
661                data.writeInterfaceToken("android.ui.ISurfaceComposer");
662                final int showUpdates = mShowScreenUpdates.isChecked() ? 1 : 0;
663                data.writeInt(showUpdates);
664                flinger.transact(1002, data, null, 0);
665                data.recycle();
666
667                updateFlingerOptions();
668            }
669        } catch (RemoteException ex) {
670        }
671    }
672
673    private void writeDisableOverlaysOption() {
674        try {
675            IBinder flinger = ServiceManager.getService("SurfaceFlinger");
676            if (flinger != null) {
677                Parcel data = Parcel.obtain();
678                data.writeInterfaceToken("android.ui.ISurfaceComposer");
679                final int disableOverlays = mDisableOverlays.isChecked() ? 1 : 0;
680                data.writeInt(disableOverlays);
681                flinger.transact(1008, data, null, 0);
682                data.recycle();
683
684                updateFlingerOptions();
685            }
686        } catch (RemoteException ex) {
687        }
688    }
689
690    private void updateHardwareUiOptions() {
691        updateCheckBox(mForceHardwareUi, SystemProperties.getBoolean(HARDWARE_UI_PROPERTY, false));
692    }
693
694    private void writeHardwareUiOptions() {
695        SystemProperties.set(HARDWARE_UI_PROPERTY, mForceHardwareUi.isChecked() ? "true" : "false");
696        pokeSystemProperties();
697    }
698
699    private void updateMsaaOptions() {
700        updateCheckBox(mForceMsaa, SystemProperties.getBoolean(MSAA_PROPERTY, false));
701    }
702
703    private void writeMsaaOptions() {
704        SystemProperties.set(MSAA_PROPERTY, mForceMsaa.isChecked() ? "true" : "false");
705        pokeSystemProperties();
706    }
707
708    private void updateTrackFrameTimeOptions() {
709        String value = SystemProperties.get(HardwareRenderer.PROFILE_PROPERTY);
710        if (value == null) {
711            value = "";
712        }
713
714        CharSequence[] values = mTrackFrameTime.getEntryValues();
715        for (int i = 0; i < values.length; i++) {
716            if (value.contentEquals(values[i])) {
717                mTrackFrameTime.setValueIndex(i);
718                mTrackFrameTime.setSummary(mTrackFrameTime.getEntries()[i]);
719                return;
720            }
721        }
722        mTrackFrameTime.setValueIndex(0);
723        mTrackFrameTime.setSummary(mTrackFrameTime.getEntries()[0]);
724    }
725
726    private void writeTrackFrameTimeOptions(Object newValue) {
727        SystemProperties.set(HardwareRenderer.PROFILE_PROPERTY,
728                newValue == null ? "" : newValue.toString());
729        pokeSystemProperties();
730        updateTrackFrameTimeOptions();
731    }
732
733    private void updateShowNonRectClipOptions() {
734        String value = SystemProperties.get(
735                HardwareRenderer.DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY);
736        if (value == null) {
737            value = "hide";
738        }
739
740        CharSequence[] values = mShowNonRectClip.getEntryValues();
741        for (int i = 0; i < values.length; i++) {
742            if (value.contentEquals(values[i])) {
743                mShowNonRectClip.setValueIndex(i);
744                mShowNonRectClip.setSummary(mShowNonRectClip.getEntries()[i]);
745                return;
746            }
747        }
748        mShowNonRectClip.setValueIndex(0);
749        mShowNonRectClip.setSummary(mShowNonRectClip.getEntries()[0]);
750    }
751
752    private void writeShowNonRectClipOptions(Object newValue) {
753        SystemProperties.set(HardwareRenderer.DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY,
754                newValue == null ? "" : newValue.toString());
755        pokeSystemProperties();
756        updateShowNonRectClipOptions();
757    }
758
759    private void updateShowHwScreenUpdatesOptions() {
760        updateCheckBox(mShowHwScreenUpdates,
761                SystemProperties.getBoolean(HardwareRenderer.DEBUG_DIRTY_REGIONS_PROPERTY, false));
762    }
763
764    private void writeShowHwScreenUpdatesOptions() {
765        SystemProperties.set(HardwareRenderer.DEBUG_DIRTY_REGIONS_PROPERTY,
766                mShowHwScreenUpdates.isChecked() ? "true" : null);
767        pokeSystemProperties();
768    }
769
770    private void updateShowHwLayersUpdatesOptions() {
771        updateCheckBox(mShowHwLayersUpdates, SystemProperties.getBoolean(
772                HardwareRenderer.DEBUG_SHOW_LAYERS_UPDATES_PROPERTY, false));
773    }
774
775    private void writeShowHwLayersUpdatesOptions() {
776        SystemProperties.set(HardwareRenderer.DEBUG_SHOW_LAYERS_UPDATES_PROPERTY,
777                mShowHwLayersUpdates.isChecked() ? "true" : null);
778        pokeSystemProperties();
779    }
780
781    private void updateShowHwOverdrawOptions() {
782        updateCheckBox(mShowHwOverdraw, SystemProperties.getBoolean(
783                HardwareRenderer.DEBUG_SHOW_OVERDRAW_PROPERTY, false));
784    }
785
786    private void writeShowHwOverdrawOptions() {
787        SystemProperties.set(HardwareRenderer.DEBUG_SHOW_OVERDRAW_PROPERTY,
788                mShowHwOverdraw.isChecked() ? "true" : null);
789        pokeSystemProperties();
790    }
791
792    private void updateDebugLayoutOptions() {
793        updateCheckBox(mDebugLayout,
794                SystemProperties.getBoolean(View.DEBUG_LAYOUT_PROPERTY, false));
795    }
796
797    private void writeDebugLayoutOptions() {
798        SystemProperties.set(View.DEBUG_LAYOUT_PROPERTY,
799                mDebugLayout.isChecked() ? "true" : "false");
800        pokeSystemProperties();
801    }
802
803    private void updateCpuUsageOptions() {
804        updateCheckBox(mShowCpuUsage, Settings.Global.getInt(getActivity().getContentResolver(),
805                Settings.Global.SHOW_PROCESSES, 0) != 0);
806    }
807
808    private void writeCpuUsageOptions() {
809        boolean value = mShowCpuUsage.isChecked();
810        Settings.Global.putInt(getActivity().getContentResolver(),
811                Settings.Global.SHOW_PROCESSES, value ? 1 : 0);
812        Intent service = (new Intent())
813                .setClassName("com.android.systemui", "com.android.systemui.LoadAverageService");
814        if (value) {
815            getActivity().startService(service);
816        } else {
817            getActivity().stopService(service);
818        }
819    }
820
821    private void writeImmediatelyDestroyActivitiesOptions() {
822        try {
823            ActivityManagerNative.getDefault().setAlwaysFinish(
824                    mImmediatelyDestroyActivities.isChecked());
825        } catch (RemoteException ex) {
826        }
827    }
828
829    private void updateImmediatelyDestroyActivitiesOptions() {
830        updateCheckBox(mImmediatelyDestroyActivities, Settings.Global.getInt(
831            getActivity().getContentResolver(), Settings.Global.ALWAYS_FINISH_ACTIVITIES, 0) != 0);
832    }
833
834    private void updateAnimationScaleValue(int which, ListPreference pref) {
835        try {
836            float scale = mWindowManager.getAnimationScale(which);
837            if (scale != 1) {
838                mHaveDebugSettings = true;
839            }
840            CharSequence[] values = pref.getEntryValues();
841            for (int i=0; i<values.length; i++) {
842                float val = Float.parseFloat(values[i].toString());
843                if (scale <= val) {
844                    pref.setValueIndex(i);
845                    pref.setSummary(pref.getEntries()[i]);
846                    return;
847                }
848            }
849            pref.setValueIndex(values.length-1);
850            pref.setSummary(pref.getEntries()[0]);
851        } catch (RemoteException e) {
852        }
853    }
854
855    private void updateAnimationScaleOptions() {
856        updateAnimationScaleValue(0, mWindowAnimationScale);
857        updateAnimationScaleValue(1, mTransitionAnimationScale);
858        updateAnimationScaleValue(2, mAnimatorDurationScale);
859    }
860
861    private void writeAnimationScaleOption(int which, ListPreference pref, Object newValue) {
862        try {
863            float scale = newValue != null ? Float.parseFloat(newValue.toString()) : 1;
864            mWindowManager.setAnimationScale(which, scale);
865            updateAnimationScaleValue(which, pref);
866        } catch (RemoteException e) {
867        }
868    }
869
870    private void updateOverlayDisplayDevicesOptions() {
871        String value = Settings.Global.getString(getActivity().getContentResolver(),
872                Settings.Global.OVERLAY_DISPLAY_DEVICES);
873        if (value == null) {
874            value = "";
875        }
876
877        CharSequence[] values = mOverlayDisplayDevices.getEntryValues();
878        for (int i = 0; i < values.length; i++) {
879            if (value.contentEquals(values[i])) {
880                mOverlayDisplayDevices.setValueIndex(i);
881                mOverlayDisplayDevices.setSummary(mOverlayDisplayDevices.getEntries()[i]);
882                return;
883            }
884        }
885        mOverlayDisplayDevices.setValueIndex(0);
886        mOverlayDisplayDevices.setSummary(mOverlayDisplayDevices.getEntries()[0]);
887    }
888
889    private void writeOverlayDisplayDevicesOptions(Object newValue) {
890        Settings.Global.putString(getActivity().getContentResolver(),
891                Settings.Global.OVERLAY_DISPLAY_DEVICES, (String)newValue);
892        updateOverlayDisplayDevicesOptions();
893    }
894
895    private void updateOpenGLTracesOptions() {
896        String value = SystemProperties.get(OPENGL_TRACES_PROPERTY);
897        if (value == null) {
898            value = "";
899        }
900
901        CharSequence[] values = mOpenGLTraces.getEntryValues();
902        for (int i = 0; i < values.length; i++) {
903            if (value.contentEquals(values[i])) {
904                mOpenGLTraces.setValueIndex(i);
905                mOpenGLTraces.setSummary(mOpenGLTraces.getEntries()[i]);
906                return;
907            }
908        }
909        mOpenGLTraces.setValueIndex(0);
910        mOpenGLTraces.setSummary(mOpenGLTraces.getEntries()[0]);
911    }
912
913    private void writeOpenGLTracesOptions(Object newValue) {
914        SystemProperties.set(OPENGL_TRACES_PROPERTY, newValue == null ? "" : newValue.toString());
915        pokeSystemProperties();
916        updateOpenGLTracesOptions();
917    }
918
919    private void updateAppProcessLimitOptions() {
920        try {
921            int limit = ActivityManagerNative.getDefault().getProcessLimit();
922            CharSequence[] values = mAppProcessLimit.getEntryValues();
923            for (int i=0; i<values.length; i++) {
924                int val = Integer.parseInt(values[i].toString());
925                if (val >= limit) {
926                    if (i != 0) {
927                        mHaveDebugSettings = true;
928                    }
929                    mAppProcessLimit.setValueIndex(i);
930                    mAppProcessLimit.setSummary(mAppProcessLimit.getEntries()[i]);
931                    return;
932                }
933            }
934            mAppProcessLimit.setValueIndex(0);
935            mAppProcessLimit.setSummary(mAppProcessLimit.getEntries()[0]);
936        } catch (RemoteException e) {
937        }
938    }
939
940    private void writeAppProcessLimitOptions(Object newValue) {
941        try {
942            int limit = newValue != null ? Integer.parseInt(newValue.toString()) : -1;
943            ActivityManagerNative.getDefault().setProcessLimit(limit);
944            updateAppProcessLimitOptions();
945        } catch (RemoteException e) {
946        }
947    }
948
949    private void writeShowAllANRsOptions() {
950        Settings.Secure.putInt(getActivity().getContentResolver(),
951                Settings.Secure.ANR_SHOW_BACKGROUND,
952                mShowAllANRs.isChecked() ? 1 : 0);
953    }
954
955    private void updateShowAllANRsOptions() {
956        updateCheckBox(mShowAllANRs, Settings.Secure.getInt(
957            getActivity().getContentResolver(), Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0);
958    }
959
960    @Override
961    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
962        if (buttonView == mEnabledSwitch) {
963            if (isChecked != mLastEnabledState) {
964                if (isChecked) {
965                    mDialogClicked = false;
966                    if (mEnableDialog != null) dismissDialogs();
967                    mEnableDialog = new AlertDialog.Builder(getActivity()).setMessage(
968                            getActivity().getResources().getString(
969                                    R.string.dev_settings_warning_message))
970                            .setTitle(R.string.dev_settings_warning_title)
971                            .setIconAttribute(android.R.attr.alertDialogIcon)
972                            .setPositiveButton(android.R.string.yes, this)
973                            .setNegativeButton(android.R.string.no, this)
974                            .show();
975                    mEnableDialog.setOnDismissListener(this);
976                } else {
977                    resetDangerousOptions();
978                    Settings.Global.putInt(getActivity().getContentResolver(),
979                            Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);
980                    mLastEnabledState = isChecked;
981                    setPrefsEnabledState(mLastEnabledState);
982                }
983            }
984        }
985    }
986
987    @Override
988    public void onActivityResult(int requestCode, int resultCode, Intent data) {
989        if (requestCode == RESULT_DEBUG_APP) {
990            if (resultCode == Activity.RESULT_OK) {
991                mDebugApp = data.getAction();
992                writeDebuggerOptions();
993                updateDebuggerOptions();
994            }
995        } else {
996            super.onActivityResult(requestCode, resultCode, data);
997        }
998    }
999
1000    @Override
1001    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
1002
1003        if (Utils.isMonkeyRunning()) {
1004            return false;
1005        }
1006
1007        if (preference == mEnableAdb) {
1008            if (mEnableAdb.isChecked()) {
1009                mDialogClicked = false;
1010                if (mAdbDialog != null) dismissDialogs();
1011                mAdbDialog = new AlertDialog.Builder(getActivity()).setMessage(
1012                        getActivity().getResources().getString(R.string.adb_warning_message))
1013                        .setTitle(R.string.adb_warning_title)
1014                        .setIconAttribute(android.R.attr.alertDialogIcon)
1015                        .setPositiveButton(android.R.string.yes, this)
1016                        .setNegativeButton(android.R.string.no, this)
1017                        .show();
1018                mAdbDialog.setOnDismissListener(this);
1019            } else {
1020                Settings.Global.putInt(getActivity().getContentResolver(),
1021                        Settings.Global.ADB_ENABLED, 0);
1022                mVerifyAppsOverUsb.setEnabled(false);
1023                mVerifyAppsOverUsb.setChecked(false);
1024                updateBugreportOptions();
1025            }
1026        } else if (preference == mClearAdbKeys) {
1027            if (mAdbKeysDialog != null) dismissDialogs();
1028            mAdbKeysDialog = new AlertDialog.Builder(getActivity())
1029                        .setMessage(R.string.adb_keys_warning_message)
1030                        .setPositiveButton(android.R.string.ok, this)
1031                        .setNegativeButton(android.R.string.cancel, null)
1032                        .show();
1033        } else if (preference == mBugreportInPower) {
1034            Settings.Secure.putInt(getActivity().getContentResolver(),
1035                    Settings.Secure.BUGREPORT_IN_POWER_MENU,
1036                    mBugreportInPower.isChecked() ? 1 : 0);
1037        } else if (preference == mKeepScreenOn) {
1038            Settings.Global.putInt(getActivity().getContentResolver(),
1039                    Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
1040                    mKeepScreenOn.isChecked() ?
1041                    (BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB) : 0);
1042        } else if (preference == mEnforceReadExternal) {
1043            if (mEnforceReadExternal.isChecked()) {
1044                ConfirmEnforceFragment.show(this);
1045            } else {
1046                setPermissionEnforced(getActivity(), READ_EXTERNAL_STORAGE, false);
1047            }
1048        } else if (preference == mAllowMockLocation) {
1049            Settings.Secure.putInt(getActivity().getContentResolver(),
1050                    Settings.Secure.ALLOW_MOCK_LOCATION,
1051                    mAllowMockLocation.isChecked() ? 1 : 0);
1052        } else if (preference == mDebugAppPref) {
1053            startActivityForResult(new Intent(getActivity(), AppPicker.class), RESULT_DEBUG_APP);
1054        } else if (preference == mWaitForDebugger) {
1055            writeDebuggerOptions();
1056        } else if (preference == mVerifyAppsOverUsb) {
1057            writeVerifyAppsOverUsbOptions();
1058        } else if (preference == mStrictMode) {
1059            writeStrictModeVisualOptions();
1060        } else if (preference == mPointerLocation) {
1061            writePointerLocationOptions();
1062        } else if (preference == mShowTouches) {
1063            writeShowTouchesOptions();
1064        } else if (preference == mShowScreenUpdates) {
1065            writeShowUpdatesOption();
1066        } else if (preference == mDisableOverlays) {
1067            writeDisableOverlaysOption();
1068        } else if (preference == mShowCpuUsage) {
1069            writeCpuUsageOptions();
1070        } else if (preference == mImmediatelyDestroyActivities) {
1071            writeImmediatelyDestroyActivitiesOptions();
1072        } else if (preference == mShowAllANRs) {
1073            writeShowAllANRsOptions();
1074        } else if (preference == mForceHardwareUi) {
1075            writeHardwareUiOptions();
1076        } else if (preference == mForceMsaa) {
1077            writeMsaaOptions();
1078        } else if (preference == mShowHwScreenUpdates) {
1079            writeShowHwScreenUpdatesOptions();
1080        } else if (preference == mShowHwLayersUpdates) {
1081            writeShowHwLayersUpdatesOptions();
1082        } else if (preference == mShowHwOverdraw) {
1083            writeShowHwOverdrawOptions();
1084        } else if (preference == mDebugLayout) {
1085            writeDebugLayoutOptions();
1086        }
1087
1088        return false;
1089    }
1090
1091    @Override
1092    public boolean onPreferenceChange(Preference preference, Object newValue) {
1093        if (HDCP_CHECKING_KEY.equals(preference.getKey())) {
1094            SystemProperties.set(HDCP_CHECKING_PROPERTY, newValue.toString());
1095            updateHdcpValues();
1096            pokeSystemProperties();
1097            return true;
1098        } else if (preference == mWindowAnimationScale) {
1099            writeAnimationScaleOption(0, mWindowAnimationScale, newValue);
1100            return true;
1101        } else if (preference == mTransitionAnimationScale) {
1102            writeAnimationScaleOption(1, mTransitionAnimationScale, newValue);
1103            return true;
1104        } else if (preference == mAnimatorDurationScale) {
1105            writeAnimationScaleOption(2, mAnimatorDurationScale, newValue);
1106            return true;
1107        } else if (preference == mOverlayDisplayDevices) {
1108            writeOverlayDisplayDevicesOptions(newValue);
1109            return true;
1110        } else if (preference == mOpenGLTraces) {
1111            writeOpenGLTracesOptions(newValue);
1112            return true;
1113        } else if (preference == mTrackFrameTime) {
1114            writeTrackFrameTimeOptions(newValue);
1115            return true;
1116        } else if (preference == mShowNonRectClip) {
1117            writeShowNonRectClipOptions(newValue);
1118            return true;
1119        } else if (preference == mAppProcessLimit) {
1120            writeAppProcessLimitOptions(newValue);
1121            return true;
1122        }
1123        return false;
1124    }
1125
1126    private void dismissDialogs() {
1127        if (mAdbDialog != null) {
1128            mAdbDialog.dismiss();
1129            mAdbDialog = null;
1130        }
1131        if (mAdbKeysDialog != null) {
1132            mAdbKeysDialog.dismiss();
1133            mAdbKeysDialog = null;
1134        }
1135        if (mEnableDialog != null) {
1136            mEnableDialog.dismiss();
1137            mEnableDialog = null;
1138        }
1139    }
1140
1141    public void onClick(DialogInterface dialog, int which) {
1142        if (dialog == mAdbDialog) {
1143            if (which == DialogInterface.BUTTON_POSITIVE) {
1144                mDialogClicked = true;
1145                Settings.Global.putInt(getActivity().getContentResolver(),
1146                        Settings.Global.ADB_ENABLED, 1);
1147                mVerifyAppsOverUsb.setEnabled(true);
1148                updateVerifyAppsOverUsbOptions();
1149                updateBugreportOptions();
1150            } else {
1151                // Reset the toggle
1152                mEnableAdb.setChecked(false);
1153            }
1154        } else if (dialog == mAdbKeysDialog) {
1155            if (which == DialogInterface.BUTTON_POSITIVE) {
1156                try {
1157                    IBinder b = ServiceManager.getService(Context.USB_SERVICE);
1158                    IUsbManager service = IUsbManager.Stub.asInterface(b);
1159                    service.clearUsbDebuggingKeys();
1160                } catch (RemoteException e) {
1161                    Log.e(TAG, "Unable to clear adb keys", e);
1162                }
1163            }
1164        } else if (dialog == mEnableDialog) {
1165            if (which == DialogInterface.BUTTON_POSITIVE) {
1166                mDialogClicked = true;
1167                Settings.Global.putInt(getActivity().getContentResolver(),
1168                        Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
1169                mLastEnabledState = true;
1170                setPrefsEnabledState(mLastEnabledState);
1171            } else {
1172                // Reset the toggle
1173                mEnabledSwitch.setChecked(false);
1174            }
1175        }
1176    }
1177
1178    public void onDismiss(DialogInterface dialog) {
1179        // Assuming that onClick gets called first
1180        if (dialog == mAdbDialog) {
1181            if (!mDialogClicked) {
1182                mEnableAdb.setChecked(false);
1183            }
1184            mAdbDialog = null;
1185        } else if (dialog == mEnableDialog) {
1186            if (!mDialogClicked) {
1187                mEnabledSwitch.setChecked(false);
1188            }
1189            mEnableDialog = null;
1190        }
1191    }
1192
1193    @Override
1194    public void onDestroy() {
1195        dismissDialogs();
1196        super.onDestroy();
1197    }
1198
1199    void pokeSystemProperties() {
1200        if (!mDontPokeProperties) {
1201            //noinspection unchecked
1202            (new SystemPropPoker()).execute();
1203        }
1204    }
1205
1206    static class SystemPropPoker extends AsyncTask<Void, Void, Void> {
1207        @Override
1208        protected Void doInBackground(Void... params) {
1209            String[] services;
1210            try {
1211                services = ServiceManager.listServices();
1212            } catch (RemoteException e) {
1213                return null;
1214            }
1215            for (String service : services) {
1216                IBinder obj = ServiceManager.checkService(service);
1217                if (obj != null) {
1218                    Parcel data = Parcel.obtain();
1219                    try {
1220                        obj.transact(IBinder.SYSPROPS_TRANSACTION, data, null, 0);
1221                    } catch (RemoteException e) {
1222                    } catch (Exception e) {
1223                        Log.i(TAG, "Somone wrote a bad service '" + service
1224                                + "' that doesn't like to be poked: " + e);
1225                    }
1226                    data.recycle();
1227                }
1228            }
1229            return null;
1230        }
1231    }
1232
1233    /**
1234     * Dialog to confirm enforcement of {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}.
1235     */
1236    public static class ConfirmEnforceFragment extends DialogFragment {
1237        public static void show(DevelopmentSettings parent) {
1238            final ConfirmEnforceFragment dialog = new ConfirmEnforceFragment();
1239            dialog.setTargetFragment(parent, 0);
1240            dialog.show(parent.getFragmentManager(), TAG_CONFIRM_ENFORCE);
1241        }
1242
1243        @Override
1244        public Dialog onCreateDialog(Bundle savedInstanceState) {
1245            final Context context = getActivity();
1246
1247            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
1248            builder.setTitle(R.string.enforce_read_external_confirm_title);
1249            builder.setMessage(R.string.enforce_read_external_confirm_message);
1250
1251            builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
1252                @Override
1253                public void onClick(DialogInterface dialog, int which) {
1254                    setPermissionEnforced(context, READ_EXTERNAL_STORAGE, true);
1255                    ((DevelopmentSettings) getTargetFragment()).updateAllOptions();
1256                }
1257            });
1258            builder.setNegativeButton(android.R.string.cancel, new OnClickListener() {
1259                @Override
1260                public void onClick(DialogInterface dialog, int which) {
1261                    ((DevelopmentSettings) getTargetFragment()).updateAllOptions();
1262                }
1263            });
1264
1265            return builder.create();
1266        }
1267    }
1268
1269    private static boolean isPermissionEnforced(String permission) {
1270        try {
1271            return ActivityThread.getPackageManager().isPermissionEnforced(permission);
1272        } catch (RemoteException e) {
1273            throw new RuntimeException("Problem talking with PackageManager", e);
1274        }
1275    }
1276
1277    private static void setPermissionEnforced(
1278            Context context, String permission, boolean enforced) {
1279        try {
1280            // TODO: offload to background thread
1281            ActivityThread.getPackageManager()
1282                    .setPermissionEnforced(READ_EXTERNAL_STORAGE, enforced);
1283        } catch (RemoteException e) {
1284            throw new RuntimeException("Problem talking with PackageManager", e);
1285        }
1286    }
1287}
1288