DevelopmentSettings.java revision 2f926bbb0036d7a5988ea427c70b11a48d782979
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 java.util.ArrayList;
20
21import android.app.ActionBar;
22import android.app.Activity;
23import android.app.ActivityManagerNative;
24import android.app.AlertDialog;
25import android.app.Dialog;
26import android.app.backup.IBackupManager;
27import android.content.ContentResolver;
28import android.content.Context;
29import android.content.DialogInterface;
30import android.content.Intent;
31import android.content.pm.ApplicationInfo;
32import android.content.pm.PackageManager;
33import android.os.BatteryManager;
34import android.os.Build;
35import android.os.Bundle;
36import android.os.IBinder;
37import android.os.Parcel;
38import android.os.RemoteException;
39import android.os.ServiceManager;
40import android.os.StrictMode;
41import android.os.SystemProperties;
42import android.preference.CheckBoxPreference;
43import android.preference.ListPreference;
44import android.preference.Preference;
45import android.preference.PreferenceFragment;
46import android.preference.PreferenceScreen;
47import android.preference.Preference.OnPreferenceChangeListener;
48import android.provider.Settings;
49import android.text.TextUtils;
50import android.view.Gravity;
51import android.view.HardwareRenderer;
52import android.view.IWindowManager;
53import android.view.View;
54import android.widget.CompoundButton;
55import android.widget.Switch;
56
57/*
58 * Displays preferences for application developers.
59 */
60public class DevelopmentSettings extends PreferenceFragment
61        implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
62                OnPreferenceChangeListener, CompoundButton.OnCheckedChangeListener {
63
64    private static final String ENABLE_ADB = "enable_adb";
65    private static final String KEEP_SCREEN_ON = "keep_screen_on";
66    private static final String ALLOW_MOCK_LOCATION = "allow_mock_location";
67    private static final String HDCP_CHECKING_KEY = "hdcp_checking";
68    private static final String HDCP_CHECKING_PROPERTY = "persist.sys.hdcp_checking";
69    private static final String LOCAL_BACKUP_PASSWORD = "local_backup_password";
70    private static final String HARDWARE_UI_PROPERTY = "persist.sys.ui.hw";
71
72    private static final String DEBUG_APP_KEY = "debug_app";
73    private static final String WAIT_FOR_DEBUGGER_KEY = "wait_for_debugger";
74    private static final String STRICT_MODE_KEY = "strict_mode";
75    private static final String POINTER_LOCATION_KEY = "pointer_location";
76    private static final String SHOW_TOUCHES_KEY = "show_touches";
77    private static final String SHOW_SCREEN_UPDATES_KEY = "show_screen_updates";
78    private static final String DISABLE_OVERLAYS_KEY = "disable_overlays";
79    private static final String SHOW_CPU_USAGE_KEY = "show_cpu_usage";
80    private static final String FORCE_HARDWARE_UI_KEY = "force_hw_ui";
81    private static final String TRACK_FRAME_TIME_KEY = "track_frame_time";
82    private static final String SHOW_HW_SCREEN_UPDATES_KEY = "show_hw_screen_udpates";
83    private static final String DEBUG_LAYOUT_KEY = "debug_layout";
84    private static final String WINDOW_ANIMATION_SCALE_KEY = "window_animation_scale";
85    private static final String TRANSITION_ANIMATION_SCALE_KEY = "transition_animation_scale";
86    private static final String ANIMATOR_DURATION_SCALE_KEY = "animator_duration_scale";
87
88    private static final String IMMEDIATELY_DESTROY_ACTIVITIES_KEY
89            = "immediately_destroy_activities";
90    private static final String APP_PROCESS_LIMIT_KEY = "app_process_limit";
91
92    private static final String SHOW_ALL_ANRS_KEY = "show_all_anrs";
93
94    private static final int RESULT_DEBUG_APP = 1000;
95
96    private IWindowManager mWindowManager;
97    private IBackupManager mBackupManager;
98
99    private Switch mEnabledSwitch;
100    private boolean mLastEnabledState;
101
102    private CheckBoxPreference mEnableAdb;
103    private CheckBoxPreference mKeepScreenOn;
104    private CheckBoxPreference mAllowMockLocation;
105    private PreferenceScreen mPassword;
106
107    private String mDebugApp;
108    private Preference mDebugAppPref;
109    private CheckBoxPreference mWaitForDebugger;
110
111    private CheckBoxPreference mStrictMode;
112    private CheckBoxPreference mPointerLocation;
113    private CheckBoxPreference mShowTouches;
114    private CheckBoxPreference mShowScreenUpdates;
115    private CheckBoxPreference mDisableOverlays;
116    private CheckBoxPreference mShowCpuUsage;
117    private CheckBoxPreference mForceHardwareUi;
118    private CheckBoxPreference mTrackFrameTime;
119    private CheckBoxPreference mShowHwScreenUpdates;
120    private CheckBoxPreference mDebugLayout;
121    private ListPreference mWindowAnimationScale;
122    private ListPreference mTransitionAnimationScale;
123    private ListPreference mAnimatorDurationScale;
124
125    private CheckBoxPreference mImmediatelyDestroyActivities;
126    private ListPreference mAppProcessLimit;
127
128    private CheckBoxPreference mShowAllANRs;
129
130    private final ArrayList<Preference> mAllPrefs = new ArrayList<Preference>();
131    private final ArrayList<CheckBoxPreference> mResetCbPrefs
132            = new ArrayList<CheckBoxPreference>();
133
134    // To track whether a confirmation dialog was clicked.
135    private boolean mDialogClicked;
136    private Dialog mEnableDialog;
137    private Dialog mAdbDialog;
138
139    @Override
140    public void onCreate(Bundle icicle) {
141        super.onCreate(icicle);
142
143        mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
144        mBackupManager = IBackupManager.Stub.asInterface(
145                ServiceManager.getService(Context.BACKUP_SERVICE));
146
147        addPreferencesFromResource(R.xml.development_prefs);
148
149        mEnableAdb = findAndInitCheckboxPref(ENABLE_ADB);
150        mKeepScreenOn = findAndInitCheckboxPref(KEEP_SCREEN_ON);
151        mAllowMockLocation = findAndInitCheckboxPref(ALLOW_MOCK_LOCATION);
152        mPassword = (PreferenceScreen) findPreference(LOCAL_BACKUP_PASSWORD);
153        mAllPrefs.add(mPassword);
154
155        mDebugAppPref = findPreference(DEBUG_APP_KEY);
156        mAllPrefs.add(mDebugAppPref);
157        mWaitForDebugger = findAndInitCheckboxPref(WAIT_FOR_DEBUGGER_KEY);
158        mStrictMode = findAndInitCheckboxPref(STRICT_MODE_KEY);
159        mPointerLocation = findAndInitCheckboxPref(POINTER_LOCATION_KEY);
160        mShowTouches = findAndInitCheckboxPref(SHOW_TOUCHES_KEY);
161        mShowScreenUpdates = findAndInitCheckboxPref(SHOW_SCREEN_UPDATES_KEY);
162        mDisableOverlays = findAndInitCheckboxPref(DISABLE_OVERLAYS_KEY);
163        mShowCpuUsage = findAndInitCheckboxPref(SHOW_CPU_USAGE_KEY);
164        mForceHardwareUi = findAndInitCheckboxPref(FORCE_HARDWARE_UI_KEY);
165        mTrackFrameTime = findAndInitCheckboxPref(TRACK_FRAME_TIME_KEY);
166        mShowHwScreenUpdates = findAndInitCheckboxPref(SHOW_HW_SCREEN_UPDATES_KEY);
167        mDebugLayout = findAndInitCheckboxPref(DEBUG_LAYOUT_KEY);
168        mWindowAnimationScale = (ListPreference) findPreference(WINDOW_ANIMATION_SCALE_KEY);
169        mAllPrefs.add(mWindowAnimationScale);
170        mWindowAnimationScale.setOnPreferenceChangeListener(this);
171        mTransitionAnimationScale = (ListPreference) findPreference(TRANSITION_ANIMATION_SCALE_KEY);
172        mAllPrefs.add(mTransitionAnimationScale);
173        mTransitionAnimationScale.setOnPreferenceChangeListener(this);
174        mAnimatorDurationScale = (ListPreference) findPreference(ANIMATOR_DURATION_SCALE_KEY);
175        mAllPrefs.add(mAnimatorDurationScale);
176        mAnimatorDurationScale.setOnPreferenceChangeListener(this);
177
178        mImmediatelyDestroyActivities = (CheckBoxPreference) findPreference(
179                IMMEDIATELY_DESTROY_ACTIVITIES_KEY);
180        mAllPrefs.add(mImmediatelyDestroyActivities);
181        mResetCbPrefs.add(mImmediatelyDestroyActivities);
182        mAppProcessLimit = (ListPreference) findPreference(APP_PROCESS_LIMIT_KEY);
183        mAllPrefs.add(mAppProcessLimit);
184        mAppProcessLimit.setOnPreferenceChangeListener(this);
185
186        mShowAllANRs = (CheckBoxPreference) findPreference(
187                SHOW_ALL_ANRS_KEY);
188        mAllPrefs.add(mShowAllANRs);
189        mResetCbPrefs.add(mShowAllANRs);
190
191        Preference hdcpChecking = findPreference(HDCP_CHECKING_KEY);
192        if (hdcpChecking != null) {
193            mAllPrefs.add(hdcpChecking);
194        }
195        removeHdcpOptionsForProduction();
196    }
197
198    private CheckBoxPreference findAndInitCheckboxPref(String key) {
199        CheckBoxPreference pref = (CheckBoxPreference) findPreference(key);
200        if (pref == null) {
201            throw new IllegalArgumentException("Cannot find preference with key = " + key);
202        }
203        mAllPrefs.add(pref);
204        mResetCbPrefs.add(pref);
205        return pref;
206    }
207
208    @Override
209    public void onActivityCreated(Bundle savedInstanceState) {
210        super.onActivityCreated(savedInstanceState);
211
212        final Activity activity = getActivity();
213        mEnabledSwitch = new Switch(activity);
214
215        final int padding = activity.getResources().getDimensionPixelSize(
216                R.dimen.action_bar_switch_padding);
217        mEnabledSwitch.setPadding(0, 0, padding, 0);
218        mEnabledSwitch.setOnCheckedChangeListener(this);
219    }
220
221    @Override
222    public void onStart() {
223        super.onStart();
224        final Activity activity = getActivity();
225        activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
226                ActionBar.DISPLAY_SHOW_CUSTOM);
227        activity.getActionBar().setCustomView(mEnabledSwitch, new ActionBar.LayoutParams(
228                ActionBar.LayoutParams.WRAP_CONTENT,
229                ActionBar.LayoutParams.WRAP_CONTENT,
230                Gravity.CENTER_VERTICAL | Gravity.RIGHT));
231    }
232
233    @Override
234    public void onStop() {
235        super.onStop();
236        final Activity activity = getActivity();
237        activity.getActionBar().setDisplayOptions(0, ActionBar.DISPLAY_SHOW_CUSTOM);
238        activity.getActionBar().setCustomView(null);
239    }
240
241    private void removeHdcpOptionsForProduction() {
242        if ("user".equals(Build.TYPE)) {
243            Preference hdcpChecking = findPreference(HDCP_CHECKING_KEY);
244            if (hdcpChecking != null) {
245                // Remove the preference
246                getPreferenceScreen().removePreference(hdcpChecking);
247                mAllPrefs.remove(hdcpChecking);
248            }
249        }
250    }
251
252    private void setPrefsEnabledState(boolean enabled) {
253        for (int i = 0; i < mAllPrefs.size(); i++) {
254            mAllPrefs.get(i).setEnabled(enabled);
255        }
256        updateAllOptions();
257    }
258
259    @Override
260    public void onResume() {
261        super.onResume();
262
263        final ContentResolver cr = getActivity().getContentResolver();
264        mLastEnabledState = Settings.Secure.getInt(cr,
265                Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
266        mEnabledSwitch.setChecked(mLastEnabledState);
267        setPrefsEnabledState(mLastEnabledState);
268    }
269
270    private void updateAllOptions() {
271        final ContentResolver cr = getActivity().getContentResolver();
272        mEnableAdb.setChecked(Settings.Secure.getInt(cr,
273                Settings.Secure.ADB_ENABLED, 0) != 0);
274        mKeepScreenOn.setChecked(Settings.System.getInt(cr,
275                Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0) != 0);
276        mAllowMockLocation.setChecked(Settings.Secure.getInt(cr,
277                Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0);
278        updateHdcpValues();
279        updatePasswordSummary();
280        updateDebuggerOptions();
281        updateStrictModeVisualOptions();
282        updatePointerLocationOptions();
283        updateShowTouchesOptions();
284        updateFlingerOptions();
285        updateCpuUsageOptions();
286        updateHardwareUiOptions();
287        updateTrackFrameTimeOptions();
288        updateShowHwScreenUpdatesOptions();
289        updateDebugLayoutOptions();
290        updateAnimationScaleOptions();
291        updateImmediatelyDestroyActivitiesOptions();
292        updateAppProcessLimitOptions();
293        updateShowAllANRsOptions();
294    }
295
296    private void resetDangerousOptions() {
297        for (int i=0; i<mResetCbPrefs.size(); i++) {
298            CheckBoxPreference cb = mResetCbPrefs.get(i);
299            if (cb.isChecked()) {
300                cb.setChecked(false);
301                onPreferenceTreeClick(null, cb);
302            }
303        }
304        resetDebuggerOptions();
305        writeAnimationScaleOption(0, mWindowAnimationScale, null);
306        writeAnimationScaleOption(1, mTransitionAnimationScale, null);
307        writeAnimationScaleOption(2, mAnimatorDurationScale, null);
308        writeAppProcessLimitOptions(null);
309        updateAllOptions();
310    }
311
312    private void updateHdcpValues() {
313        int index = 1; // Defaults to drm-only. Needs to match with R.array.hdcp_checking_values
314        ListPreference hdcpChecking = (ListPreference) findPreference(HDCP_CHECKING_KEY);
315        if (hdcpChecking != null) {
316            String currentValue = SystemProperties.get(HDCP_CHECKING_PROPERTY);
317            String[] values = getResources().getStringArray(R.array.hdcp_checking_values);
318            String[] summaries = getResources().getStringArray(R.array.hdcp_checking_summaries);
319            for (int i = 0; i < values.length; i++) {
320                if (currentValue.equals(values[i])) {
321                    index = i;
322                    break;
323                }
324            }
325            hdcpChecking.setValue(values[index]);
326            hdcpChecking.setSummary(summaries[index]);
327            hdcpChecking.setOnPreferenceChangeListener(this);
328        }
329    }
330
331    private void updatePasswordSummary() {
332        try {
333            if (mBackupManager.hasBackupPassword()) {
334                mPassword.setSummary(R.string.local_backup_password_summary_change);
335            } else {
336                mPassword.setSummary(R.string.local_backup_password_summary_none);
337            }
338        } catch (RemoteException e) {
339            // Not much we can do here
340        }
341    }
342
343    private void writeDebuggerOptions() {
344        try {
345            ActivityManagerNative.getDefault().setDebugApp(
346                mDebugApp, mWaitForDebugger.isChecked(), true);
347        } catch (RemoteException ex) {
348        }
349    }
350
351    private static void resetDebuggerOptions() {
352        try {
353            ActivityManagerNative.getDefault().setDebugApp(
354                    null, false, true);
355        } catch (RemoteException ex) {
356        }
357    }
358
359    private void updateDebuggerOptions() {
360        mDebugApp = Settings.System.getString(
361                getActivity().getContentResolver(), Settings.System.DEBUG_APP);
362        mWaitForDebugger.setChecked(Settings.System.getInt(
363                getActivity().getContentResolver(), Settings.System.WAIT_FOR_DEBUGGER, 0) != 0);
364        if (mDebugApp != null && mDebugApp.length() > 0) {
365            String label;
366            try {
367                ApplicationInfo ai = getActivity().getPackageManager().getApplicationInfo(mDebugApp,
368                        PackageManager.GET_DISABLED_COMPONENTS);
369                CharSequence lab = getActivity().getPackageManager().getApplicationLabel(ai);
370                label = lab != null ? lab.toString() : mDebugApp;
371            } catch (PackageManager.NameNotFoundException e) {
372                label = mDebugApp;
373            }
374            mDebugAppPref.setSummary(getResources().getString(R.string.debug_app_set, label));
375            mWaitForDebugger.setEnabled(true);
376        } else {
377            mDebugAppPref.setSummary(getResources().getString(R.string.debug_app_not_set));
378            mWaitForDebugger.setEnabled(false);
379        }
380    }
381
382    // Returns the current state of the system property that controls
383    // strictmode flashes.  One of:
384    //    0: not explicitly set one way or another
385    //    1: on
386    //    2: off
387    private static int currentStrictModeActiveIndex() {
388        if (TextUtils.isEmpty(SystemProperties.get(StrictMode.VISUAL_PROPERTY))) {
389            return 0;
390        }
391        boolean enabled = SystemProperties.getBoolean(StrictMode.VISUAL_PROPERTY, false);
392        return enabled ? 1 : 2;
393    }
394
395    private void writeStrictModeVisualOptions() {
396        try {
397            mWindowManager.setStrictModeVisualIndicatorPreference(mStrictMode.isChecked()
398                    ? "1" : "");
399        } catch (RemoteException e) {
400        }
401    }
402
403    private void updateStrictModeVisualOptions() {
404        mStrictMode.setChecked(currentStrictModeActiveIndex() == 1);
405    }
406
407    private void writePointerLocationOptions() {
408        Settings.System.putInt(getActivity().getContentResolver(),
409                Settings.System.POINTER_LOCATION, mPointerLocation.isChecked() ? 1 : 0);
410    }
411
412    private void updatePointerLocationOptions() {
413        mPointerLocation.setChecked(Settings.System.getInt(getActivity().getContentResolver(),
414                Settings.System.POINTER_LOCATION, 0) != 0);
415    }
416
417    private void writeShowTouchesOptions() {
418        Settings.System.putInt(getActivity().getContentResolver(),
419                Settings.System.SHOW_TOUCHES, mShowTouches.isChecked() ? 1 : 0);
420    }
421
422    private void updateShowTouchesOptions() {
423        mShowTouches.setChecked(Settings.System.getInt(getActivity().getContentResolver(),
424                Settings.System.SHOW_TOUCHES, 0) != 0);
425    }
426
427    private void updateFlingerOptions() {
428        // magic communication with surface flinger.
429        try {
430            IBinder flinger = ServiceManager.getService("SurfaceFlinger");
431            if (flinger != null) {
432                Parcel data = Parcel.obtain();
433                Parcel reply = Parcel.obtain();
434                data.writeInterfaceToken("android.ui.ISurfaceComposer");
435                flinger.transact(1010, data, reply, 0);
436                @SuppressWarnings("unused")
437                int showCpu = reply.readInt();
438                @SuppressWarnings("unused")
439                int enableGL = reply.readInt();
440                int showUpdates = reply.readInt();
441                mShowScreenUpdates.setChecked(showUpdates != 0);
442                @SuppressWarnings("unused")
443                int showBackground = reply.readInt();
444                int disableOverlays = reply.readInt();
445                mDisableOverlays.setChecked(disableOverlays != 0);
446                reply.recycle();
447                data.recycle();
448            }
449        } catch (RemoteException ex) {
450        }
451    }
452
453    private void writeShowUpdatesOption() {
454        try {
455            IBinder flinger = ServiceManager.getService("SurfaceFlinger");
456            if (flinger != null) {
457                Parcel data = Parcel.obtain();
458                data.writeInterfaceToken("android.ui.ISurfaceComposer");
459                final int showUpdates = mShowScreenUpdates.isChecked() ? 1 : 0;
460                data.writeInt(showUpdates);
461                flinger.transact(1002, data, null, 0);
462                data.recycle();
463
464                updateFlingerOptions();
465            }
466        } catch (RemoteException ex) {
467        }
468    }
469
470    private void writeDisableOverlaysOption() {
471        try {
472            IBinder flinger = ServiceManager.getService("SurfaceFlinger");
473            if (flinger != null) {
474                Parcel data = Parcel.obtain();
475                data.writeInterfaceToken("android.ui.ISurfaceComposer");
476                final int disableOverlays = mDisableOverlays.isChecked() ? 1 : 0;
477                data.writeInt(disableOverlays);
478                flinger.transact(1008, data, null, 0);
479                data.recycle();
480
481                updateFlingerOptions();
482            }
483        } catch (RemoteException ex) {
484        }
485    }
486
487    private void updateHardwareUiOptions() {
488        mForceHardwareUi.setChecked(SystemProperties.getBoolean(HARDWARE_UI_PROPERTY, false));
489    }
490
491    private void writeHardwareUiOptions() {
492        SystemProperties.set(HARDWARE_UI_PROPERTY, mForceHardwareUi.isChecked() ? "true" : "false");
493    }
494
495    private void updateTrackFrameTimeOptions() {
496        mTrackFrameTime.setChecked(
497                SystemProperties.getBoolean(HardwareRenderer.PROFILE_PROPERTY, false));
498    }
499
500    private void writeTrackFrameTimeOptions() {
501        SystemProperties.set(HardwareRenderer.PROFILE_PROPERTY,
502                mTrackFrameTime.isChecked() ? "true" : "false");
503    }
504
505    private void updateShowHwScreenUpdatesOptions() {
506        mShowHwScreenUpdates.setChecked(
507                SystemProperties.getBoolean(HardwareRenderer.DEBUG_DIRTY_REGIONS_PROPERTY, false));
508    }
509
510    private void writeShowHwScreenUpdatesOptions() {
511        SystemProperties.set(HardwareRenderer.DEBUG_DIRTY_REGIONS_PROPERTY,
512                mShowHwScreenUpdates.isChecked() ? "true" : "false");
513    }
514
515    private void updateDebugLayoutOptions() {
516        mDebugLayout.setChecked(
517                SystemProperties.getBoolean(View.DEBUG_LAYOUT_PROPERTY, false));
518    }
519
520    private void writeDebugLayoutOptions() {
521        SystemProperties.set(View.DEBUG_LAYOUT_PROPERTY,
522                mDebugLayout.isChecked() ? "true" : "false");
523    }
524
525    private void updateCpuUsageOptions() {
526        mShowCpuUsage.setChecked(Settings.System.getInt(getActivity().getContentResolver(),
527                Settings.System.SHOW_PROCESSES, 0) != 0);
528    }
529
530    private void writeCpuUsageOptions() {
531        boolean value = mShowCpuUsage.isChecked();
532        Settings.System.putInt(getActivity().getContentResolver(),
533                Settings.System.SHOW_PROCESSES, value ? 1 : 0);
534        Intent service = (new Intent())
535                .setClassName("com.android.systemui", "com.android.systemui.LoadAverageService");
536        if (value) {
537            getActivity().startService(service);
538        } else {
539            getActivity().stopService(service);
540        }
541    }
542
543    private void writeImmediatelyDestroyActivitiesOptions() {
544        try {
545            ActivityManagerNative.getDefault().setAlwaysFinish(
546                    mImmediatelyDestroyActivities.isChecked());
547        } catch (RemoteException ex) {
548        }
549    }
550
551    private void updateImmediatelyDestroyActivitiesOptions() {
552        mImmediatelyDestroyActivities.setChecked(Settings.System.getInt(
553            getActivity().getContentResolver(), Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0);
554    }
555
556    private void updateAnimationScaleValue(int which, ListPreference pref) {
557        try {
558            float scale = mWindowManager.getAnimationScale(which);
559            CharSequence[] values = pref.getEntryValues();
560            for (int i=0; i<values.length; i++) {
561                float val = Float.parseFloat(values[i].toString());
562                if (scale <= val) {
563                    pref.setValueIndex(i);
564                    pref.setSummary(pref.getEntries()[i]);
565                    return;
566                }
567            }
568            pref.setValueIndex(values.length-1);
569            pref.setSummary(pref.getEntries()[0]);
570        } catch (RemoteException e) {
571        }
572    }
573
574    private void updateAnimationScaleOptions() {
575        updateAnimationScaleValue(0, mWindowAnimationScale);
576        updateAnimationScaleValue(1, mTransitionAnimationScale);
577        updateAnimationScaleValue(2, mAnimatorDurationScale);
578    }
579
580    private void writeAnimationScaleOption(int which, ListPreference pref, Object newValue) {
581        try {
582            float scale = newValue != null ? Float.parseFloat(newValue.toString()) : 1;
583            mWindowManager.setAnimationScale(which, scale);
584            updateAnimationScaleValue(which, pref);
585        } catch (RemoteException e) {
586        }
587    }
588
589    private void updateAppProcessLimitOptions() {
590        try {
591            int limit = ActivityManagerNative.getDefault().getProcessLimit();
592            CharSequence[] values = mAppProcessLimit.getEntryValues();
593            for (int i=0; i<values.length; i++) {
594                int val = Integer.parseInt(values[i].toString());
595                if (val >= limit) {
596                    mAppProcessLimit.setValueIndex(i);
597                    mAppProcessLimit.setSummary(mAppProcessLimit.getEntries()[i]);
598                    return;
599                }
600            }
601            mAppProcessLimit.setValueIndex(0);
602            mAppProcessLimit.setSummary(mAppProcessLimit.getEntries()[0]);
603        } catch (RemoteException e) {
604        }
605    }
606
607    private void writeAppProcessLimitOptions(Object newValue) {
608        try {
609            int limit = newValue != null ? Integer.parseInt(newValue.toString()) : -1;
610            ActivityManagerNative.getDefault().setProcessLimit(limit);
611            updateAppProcessLimitOptions();
612        } catch (RemoteException e) {
613        }
614    }
615
616    private void writeShowAllANRsOptions() {
617        Settings.Secure.putInt(getActivity().getContentResolver(),
618                Settings.Secure.ANR_SHOW_BACKGROUND,
619                mShowAllANRs.isChecked() ? 1 : 0);
620    }
621
622    private void updateShowAllANRsOptions() {
623        mShowAllANRs.setChecked(Settings.Secure.getInt(
624            getActivity().getContentResolver(), Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0);
625    }
626
627    @Override
628    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
629        if (buttonView == mEnabledSwitch) {
630            if (isChecked != mLastEnabledState) {
631                if (isChecked) {
632                    mDialogClicked = false;
633                    if (mEnableDialog != null) dismissDialogs();
634                    mEnableDialog = new AlertDialog.Builder(getActivity()).setMessage(
635                            getActivity().getResources().getString(
636                                    R.string.dev_settings_warning_message))
637                            .setTitle(R.string.dev_settings_warning_title)
638                            .setIcon(android.R.drawable.ic_dialog_alert)
639                            .setPositiveButton(android.R.string.yes, this)
640                            .setNegativeButton(android.R.string.no, this)
641                            .show();
642                    mEnableDialog.setOnDismissListener(this);
643                } else {
644                    resetDangerousOptions();
645                    Settings.Secure.putInt(getActivity().getContentResolver(),
646                            Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED, 0);
647                    mLastEnabledState = isChecked;
648                    setPrefsEnabledState(mLastEnabledState);
649                }
650            }
651        }
652    }
653
654    @Override
655    public void onActivityResult(int requestCode, int resultCode, Intent data) {
656        if (requestCode == RESULT_DEBUG_APP) {
657            if (resultCode == Activity.RESULT_OK) {
658                mDebugApp = data.getAction();
659                writeDebuggerOptions();
660                updateDebuggerOptions();
661            }
662        } else {
663            super.onActivityResult(requestCode, resultCode, data);
664        }
665    }
666
667    @Override
668    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
669
670        if (Utils.isMonkeyRunning()) {
671            return false;
672        }
673
674        if (preference == mEnableAdb) {
675            if (mEnableAdb.isChecked()) {
676                mDialogClicked = false;
677                if (mAdbDialog != null) dismissDialogs();
678                mAdbDialog = new AlertDialog.Builder(getActivity()).setMessage(
679                        getActivity().getResources().getString(R.string.adb_warning_message))
680                        .setTitle(R.string.adb_warning_title)
681                        .setIcon(android.R.drawable.ic_dialog_alert)
682                        .setPositiveButton(android.R.string.yes, this)
683                        .setNegativeButton(android.R.string.no, this)
684                        .show();
685                mAdbDialog.setOnDismissListener(this);
686            } else {
687                Settings.Secure.putInt(getActivity().getContentResolver(),
688                        Settings.Secure.ADB_ENABLED, 0);
689            }
690        } else if (preference == mKeepScreenOn) {
691            Settings.System.putInt(getActivity().getContentResolver(),
692                    Settings.System.STAY_ON_WHILE_PLUGGED_IN,
693                    mKeepScreenOn.isChecked() ?
694                    (BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB) : 0);
695        } else if (preference == mAllowMockLocation) {
696            Settings.Secure.putInt(getActivity().getContentResolver(),
697                    Settings.Secure.ALLOW_MOCK_LOCATION,
698                    mAllowMockLocation.isChecked() ? 1 : 0);
699        } else if (preference == mDebugAppPref) {
700            startActivityForResult(new Intent(getActivity(), AppPicker.class), RESULT_DEBUG_APP);
701        } else if (preference == mWaitForDebugger) {
702            writeDebuggerOptions();
703        } else if (preference == mStrictMode) {
704            writeStrictModeVisualOptions();
705        } else if (preference == mPointerLocation) {
706            writePointerLocationOptions();
707        } else if (preference == mShowTouches) {
708            writeShowTouchesOptions();
709        } else if (preference == mShowScreenUpdates) {
710            writeShowUpdatesOption();
711        } else if (preference == mDisableOverlays) {
712            writeDisableOverlaysOption();
713        } else if (preference == mShowCpuUsage) {
714            writeCpuUsageOptions();
715        } else if (preference == mImmediatelyDestroyActivities) {
716            writeImmediatelyDestroyActivitiesOptions();
717        } else if (preference == mShowAllANRs) {
718            writeShowAllANRsOptions();
719        } else if (preference == mForceHardwareUi) {
720            writeHardwareUiOptions();
721        } else if (preference == mTrackFrameTime) {
722            writeTrackFrameTimeOptions();
723        } else if (preference == mShowHwScreenUpdates) {
724            writeShowHwScreenUpdatesOptions();
725        } else if (preference == mDebugLayout) {
726            writeDebugLayoutOptions();
727        }
728
729        return false;
730    }
731
732    @Override
733    public boolean onPreferenceChange(Preference preference, Object newValue) {
734        if (HDCP_CHECKING_KEY.equals(preference.getKey())) {
735            SystemProperties.set(HDCP_CHECKING_PROPERTY, newValue.toString());
736            updateHdcpValues();
737            return true;
738        } else if (preference == mWindowAnimationScale) {
739            writeAnimationScaleOption(0, mWindowAnimationScale, newValue);
740            return true;
741        } else if (preference == mTransitionAnimationScale) {
742            writeAnimationScaleOption(1, mTransitionAnimationScale, newValue);
743            return true;
744        } else if (preference == mAnimatorDurationScale) {
745            writeAnimationScaleOption(2, mAnimatorDurationScale, newValue);
746            return true;
747        } else if (preference == mAppProcessLimit) {
748            writeAppProcessLimitOptions(newValue);
749            return true;
750        }
751        return false;
752    }
753
754    private void dismissDialogs() {
755        if (mAdbDialog != null) {
756            mAdbDialog.dismiss();
757            mAdbDialog = null;
758        }
759        if (mEnableDialog != null) {
760            mEnableDialog.dismiss();
761            mEnableDialog = null;
762        }
763    }
764
765    public void onClick(DialogInterface dialog, int which) {
766        if (dialog == mAdbDialog) {
767            if (which == DialogInterface.BUTTON_POSITIVE) {
768                mDialogClicked = true;
769                Settings.Secure.putInt(getActivity().getContentResolver(),
770                        Settings.Secure.ADB_ENABLED, 1);
771            } else {
772                // Reset the toggle
773                mEnableAdb.setChecked(false);
774            }
775        } else if (dialog == mEnableDialog) {
776            if (which == DialogInterface.BUTTON_POSITIVE) {
777                mDialogClicked = true;
778                Settings.Secure.putInt(getActivity().getContentResolver(),
779                        Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED, 1);
780                mLastEnabledState = true;
781                setPrefsEnabledState(mLastEnabledState);
782            } else {
783                // Reset the toggle
784                mEnabledSwitch.setChecked(false);
785            }
786        }
787    }
788
789    public void onDismiss(DialogInterface dialog) {
790        // Assuming that onClick gets called first
791        if (dialog == mAdbDialog) {
792            if (!mDialogClicked) {
793                mEnableAdb.setChecked(false);
794            }
795            mAdbDialog = null;
796        } else if (dialog == mEnableDialog) {
797            if (!mDialogClicked) {
798                mEnabledSwitch.setChecked(false);
799            }
800            mEnableDialog = null;
801        }
802    }
803
804    @Override
805    public void onDestroy() {
806        dismissDialogs();
807        super.onDestroy();
808    }
809}
810