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