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