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