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