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