DevelopmentSettings.java revision 498fbe470e8201ed6d4a1677025b274d9ca65e0b
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 android.app.ActivityManagerNative;
20import android.app.AlertDialog;
21import android.app.Dialog;
22import android.app.backup.IBackupManager;
23import android.content.ContentResolver;
24import android.content.Context;
25import android.content.DialogInterface;
26import android.content.Intent;
27import android.content.pm.PackageManager;
28import android.content.pm.VerifierDeviceIdentity;
29import android.os.BatteryManager;
30import android.os.Build;
31import android.os.Bundle;
32import android.os.IBinder;
33import android.os.Parcel;
34import android.os.RemoteException;
35import android.os.ServiceManager;
36import android.os.StrictMode;
37import android.os.SystemProperties;
38import android.preference.CheckBoxPreference;
39import android.preference.ListPreference;
40import android.preference.Preference;
41import android.preference.PreferenceFragment;
42import android.preference.PreferenceScreen;
43import android.preference.Preference.OnPreferenceChangeListener;
44import android.provider.Settings;
45import android.text.TextUtils;
46import android.view.IWindowManager;
47
48/*
49 * Displays preferences for application developers.
50 */
51public class DevelopmentSettings extends PreferenceFragment
52        implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
53                OnPreferenceChangeListener {
54
55    private static final String ENABLE_ADB = "enable_adb";
56
57    private static final String VERIFIER_DEVICE_IDENTIFIER = "verifier_device_identifier";
58    private static final String KEEP_SCREEN_ON = "keep_screen_on";
59    private static final String ALLOW_MOCK_LOCATION = "allow_mock_location";
60    private static final String HDCP_CHECKING_KEY = "hdcp_checking";
61    private static final String HDCP_CHECKING_PROPERTY = "persist.sys.hdcp_checking";
62    private static final String LOCAL_BACKUP_PASSWORD = "local_backup_password";
63
64    private static final String STRICT_MODE_KEY = "strict_mode";
65    private static final String POINTER_LOCATION_KEY = "pointer_location";
66    private static final String SHOW_TOUCHES_KEY = "show_touches";
67    private static final String SHOW_SCREEN_UPDATES_KEY = "show_screen_updates";
68    private static final String SHOW_CPU_USAGE_KEY = "show_cpu_usage";
69    private static final String WINDOW_ANIMATION_SCALE_KEY = "window_animation_scale";
70    private static final String TRANSITION_ANIMATION_SCALE_KEY = "transition_animation_scale";
71
72    private static final String IMMEDIATELY_DESTROY_ACTIVITIES_KEY
73            = "immediately_destroy_activities";
74    private static final String APP_PROCESS_LIMIT_KEY = "app_process_limit";
75
76    private static final String SHOW_ALL_ANRS_KEY = "show_all_anrs";
77
78    private IWindowManager mWindowManager;
79    private IBackupManager mBackupManager;
80
81    private CheckBoxPreference mEnableAdb;
82    private CheckBoxPreference mKeepScreenOn;
83    private CheckBoxPreference mAllowMockLocation;
84    private PreferenceScreen mPassword;
85
86    private CheckBoxPreference mStrictMode;
87    private CheckBoxPreference mPointerLocation;
88    private CheckBoxPreference mShowTouches;
89    private CheckBoxPreference mShowScreenUpdates;
90    private CheckBoxPreference mShowCpuUsage;
91    private ListPreference mWindowAnimationScale;
92    private ListPreference mTransitionAnimationScale;
93
94    private CheckBoxPreference mImmediatelyDestroyActivities;
95    private ListPreference mAppProcessLimit;
96
97    private CheckBoxPreference mShowAllANRs;
98
99    // To track whether Yes was clicked in the adb warning dialog
100    private boolean mOkClicked;
101
102    private Dialog mOkDialog;
103
104    @Override
105    public void onCreate(Bundle icicle) {
106        super.onCreate(icicle);
107
108        mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
109        mBackupManager = IBackupManager.Stub.asInterface(
110                ServiceManager.getService(Context.BACKUP_SERVICE));
111
112        addPreferencesFromResource(R.xml.development_prefs);
113
114        mEnableAdb = (CheckBoxPreference) findPreference(ENABLE_ADB);
115        mKeepScreenOn = (CheckBoxPreference) findPreference(KEEP_SCREEN_ON);
116        mAllowMockLocation = (CheckBoxPreference) findPreference(ALLOW_MOCK_LOCATION);
117        mPassword = (PreferenceScreen) findPreference(LOCAL_BACKUP_PASSWORD);
118
119        mStrictMode = (CheckBoxPreference) findPreference(STRICT_MODE_KEY);
120        mPointerLocation = (CheckBoxPreference) findPreference(POINTER_LOCATION_KEY);
121        mShowTouches = (CheckBoxPreference) findPreference(SHOW_TOUCHES_KEY);
122        mShowScreenUpdates = (CheckBoxPreference) findPreference(SHOW_SCREEN_UPDATES_KEY);
123        mShowCpuUsage = (CheckBoxPreference) findPreference(SHOW_CPU_USAGE_KEY);
124        mWindowAnimationScale = (ListPreference) findPreference(WINDOW_ANIMATION_SCALE_KEY);
125        mWindowAnimationScale.setOnPreferenceChangeListener(this);
126        mTransitionAnimationScale = (ListPreference) findPreference(TRANSITION_ANIMATION_SCALE_KEY);
127        mTransitionAnimationScale.setOnPreferenceChangeListener(this);
128
129        mImmediatelyDestroyActivities = (CheckBoxPreference) findPreference(
130                IMMEDIATELY_DESTROY_ACTIVITIES_KEY);
131        mAppProcessLimit = (ListPreference) findPreference(APP_PROCESS_LIMIT_KEY);
132        mAppProcessLimit.setOnPreferenceChangeListener(this);
133
134        mShowAllANRs = (CheckBoxPreference) findPreference(
135                SHOW_ALL_ANRS_KEY);
136
137        final Preference verifierDeviceIdentifier = findPreference(VERIFIER_DEVICE_IDENTIFIER);
138        final PackageManager pm = getActivity().getPackageManager();
139        final VerifierDeviceIdentity verifierIndentity = pm.getVerifierDeviceIdentity();
140        if (verifierIndentity != null) {
141            verifierDeviceIdentifier.setSummary(verifierIndentity.toString());
142        }
143
144        removeHdcpOptionsForProduction();
145    }
146
147    private void removeHdcpOptionsForProduction() {
148        if ("user".equals(Build.TYPE)) {
149            Preference hdcpChecking = findPreference(HDCP_CHECKING_KEY);
150            if (hdcpChecking != null) {
151                // Remove the preference
152                getPreferenceScreen().removePreference(hdcpChecking);
153            }
154        }
155    }
156
157    @Override
158    public void onResume() {
159        super.onResume();
160
161        final ContentResolver cr = getActivity().getContentResolver();
162        mEnableAdb.setChecked(Settings.Secure.getInt(cr,
163                Settings.Secure.ADB_ENABLED, 0) != 0);
164        mKeepScreenOn.setChecked(Settings.System.getInt(cr,
165                Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0) != 0);
166        mAllowMockLocation.setChecked(Settings.Secure.getInt(cr,
167                Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0);
168        updateHdcpValues();
169        updatePasswordSummary();
170        updateStrictModeVisualOptions();
171        updatePointerLocationOptions();
172        updateShowTouchesOptions();
173        updateFlingerOptions();
174        updateCpuUsageOptions();
175        updateAnimationScaleOptions();
176        updateImmediatelyDestroyActivitiesOptions();
177        updateAppProcessLimitOptions();
178        updateShowAllANRsOptions();
179    }
180
181    private void updateHdcpValues() {
182        int index = 1; // Defaults to drm-only. Needs to match with R.array.hdcp_checking_values
183        ListPreference hdcpChecking = (ListPreference) findPreference(HDCP_CHECKING_KEY);
184        if (hdcpChecking != null) {
185            String currentValue = SystemProperties.get(HDCP_CHECKING_PROPERTY);
186            String[] values = getResources().getStringArray(R.array.hdcp_checking_values);
187            String[] summaries = getResources().getStringArray(R.array.hdcp_checking_summaries);
188            for (int i = 0; i < values.length; i++) {
189                if (currentValue.equals(values[i])) {
190                    index = i;
191                    break;
192                }
193            }
194            hdcpChecking.setValue(values[index]);
195            hdcpChecking.setSummary(summaries[index]);
196            hdcpChecking.setOnPreferenceChangeListener(this);
197        }
198    }
199
200    private void updatePasswordSummary() {
201        try {
202            if (mBackupManager.hasBackupPassword()) {
203                mPassword.setSummary(R.string.local_backup_password_summary_change);
204            } else {
205                mPassword.setSummary(R.string.local_backup_password_summary_none);
206            }
207        } catch (RemoteException e) {
208            // Not much we can do here
209        }
210    }
211
212    // Returns the current state of the system property that controls
213    // strictmode flashes.  One of:
214    //    0: not explicitly set one way or another
215    //    1: on
216    //    2: off
217    private int currentStrictModeActiveIndex() {
218        if (TextUtils.isEmpty(SystemProperties.get(StrictMode.VISUAL_PROPERTY))) {
219            return 0;
220        }
221        boolean enabled = SystemProperties.getBoolean(StrictMode.VISUAL_PROPERTY, false);
222        return enabled ? 1 : 2;
223    }
224
225    private void writeStrictModeVisualOptions() {
226        try {
227            mWindowManager.setStrictModeVisualIndicatorPreference(mStrictMode.isChecked()
228                    ? "1" : "");
229        } catch (RemoteException e) {
230        }
231    }
232
233    private void updateStrictModeVisualOptions() {
234        mStrictMode.setChecked(currentStrictModeActiveIndex() == 1);
235    }
236
237    private void writePointerLocationOptions() {
238        Settings.System.putInt(getActivity().getContentResolver(),
239                Settings.System.POINTER_LOCATION, mPointerLocation.isChecked() ? 1 : 0);
240    }
241
242    private void updatePointerLocationOptions() {
243        mPointerLocation.setChecked(Settings.System.getInt(getActivity().getContentResolver(),
244                Settings.System.POINTER_LOCATION, 0) != 0);
245    }
246
247    private void writeShowTouchesOptions() {
248        Settings.System.putInt(getActivity().getContentResolver(),
249                Settings.System.SHOW_TOUCHES, mShowTouches.isChecked() ? 1 : 0);
250    }
251
252    private void updateShowTouchesOptions() {
253        mShowTouches.setChecked(Settings.System.getInt(getActivity().getContentResolver(),
254                Settings.System.SHOW_TOUCHES, 0) != 0);
255    }
256
257    private void updateFlingerOptions() {
258        // magic communication with surface flinger.
259        try {
260            IBinder flinger = ServiceManager.getService("SurfaceFlinger");
261            if (flinger != null) {
262                Parcel data = Parcel.obtain();
263                Parcel reply = Parcel.obtain();
264                data.writeInterfaceToken("android.ui.ISurfaceComposer");
265                flinger.transact(1010, data, reply, 0);
266                @SuppressWarnings("unused")
267                int showCpu = reply.readInt();
268                @SuppressWarnings("unused")
269                int enableGL = reply.readInt();
270                int showUpdates = reply.readInt();
271                mShowScreenUpdates.setChecked(showUpdates != 0);
272                @SuppressWarnings("unused")
273                int showBackground = reply.readInt();
274                reply.recycle();
275                data.recycle();
276            }
277        } catch (RemoteException ex) {
278        }
279    }
280
281    private void writeFlingerOptions() {
282        try {
283            IBinder flinger = ServiceManager.getService("SurfaceFlinger");
284            if (flinger != null) {
285                Parcel data = Parcel.obtain();
286                data.writeInterfaceToken("android.ui.ISurfaceComposer");
287                data.writeInt(mShowScreenUpdates.isChecked() ? 1 : 0);
288                flinger.transact(1002, data, null, 0);
289                data.recycle();
290
291                updateFlingerOptions();
292            }
293        } catch (RemoteException ex) {
294        }
295    }
296
297    private void updateCpuUsageOptions() {
298        mShowCpuUsage.setChecked(Settings.System.getInt(getActivity().getContentResolver(),
299                Settings.System.SHOW_PROCESSES, 0) != 0);
300    }
301
302    private void writeCpuUsageOptions() {
303        boolean value = mShowCpuUsage.isChecked();
304        Settings.System.putInt(getActivity().getContentResolver(),
305                Settings.System.SHOW_PROCESSES, value ? 1 : 0);
306        Intent service = (new Intent())
307                .setClassName("com.android.systemui", "com.android.systemui.LoadAverageService");
308        if (value) {
309            getActivity().startService(service);
310        } else {
311            getActivity().stopService(service);
312        }
313    }
314
315    private void writeImmediatelyDestroyActivitiesOptions() {
316        try {
317            ActivityManagerNative.getDefault().setAlwaysFinish(
318                    mImmediatelyDestroyActivities.isChecked());
319        } catch (RemoteException ex) {
320        }
321    }
322
323    private void updateImmediatelyDestroyActivitiesOptions() {
324        mImmediatelyDestroyActivities.setChecked(Settings.System.getInt(
325            getActivity().getContentResolver(), Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0);
326    }
327
328    private void updateAnimationScaleValue(int which, ListPreference pref) {
329        try {
330            float scale = mWindowManager.getAnimationScale(which);
331            CharSequence[] values = pref.getEntryValues();
332            for (int i=0; i<values.length; i++) {
333                float val = Float.parseFloat(values[i].toString());
334                if (scale <= val) {
335                    pref.setValueIndex(i);
336                    pref.setSummary(pref.getEntries()[i]);
337                    return;
338                }
339            }
340            pref.setValueIndex(values.length-1);
341            pref.setSummary(pref.getEntries()[0]);
342        } catch (RemoteException e) {
343        }
344    }
345
346    private void updateAnimationScaleOptions() {
347        updateAnimationScaleValue(0, mWindowAnimationScale);
348        updateAnimationScaleValue(1, mTransitionAnimationScale);
349    }
350
351    private void writeAnimationScaleOption(int which, ListPreference pref, Object newValue) {
352        try {
353            float scale = Float.parseFloat(newValue.toString());
354            mWindowManager.setAnimationScale(which, scale);
355            updateAnimationScaleValue(which, pref);
356        } catch (RemoteException e) {
357        }
358    }
359
360    private void updateAppProcessLimitOptions() {
361        try {
362            int limit = ActivityManagerNative.getDefault().getProcessLimit();
363            CharSequence[] values = mAppProcessLimit.getEntryValues();
364            for (int i=0; i<values.length; i++) {
365                int val = Integer.parseInt(values[i].toString());
366                if (val >= limit) {
367                    mAppProcessLimit.setValueIndex(i);
368                    mAppProcessLimit.setSummary(mAppProcessLimit.getEntries()[i]);
369                    return;
370                }
371            }
372            mAppProcessLimit.setValueIndex(0);
373            mAppProcessLimit.setSummary(mAppProcessLimit.getEntries()[0]);
374        } catch (RemoteException e) {
375        }
376    }
377
378    private void writeAppProcessLimitOptions(Object newValue) {
379        try {
380            int limit = Integer.parseInt(newValue.toString());
381            ActivityManagerNative.getDefault().setProcessLimit(limit);
382            updateAppProcessLimitOptions();
383        } catch (RemoteException e) {
384        }
385    }
386
387    private void writeShowAllANRsOptions() {
388        Settings.Secure.putInt(getActivity().getContentResolver(),
389                Settings.Secure.ANR_SHOW_BACKGROUND,
390                mShowAllANRs.isChecked() ? 1 : 0);
391    }
392
393    private void updateShowAllANRsOptions() {
394        mShowAllANRs.setChecked(Settings.Secure.getInt(
395            getActivity().getContentResolver(), Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0);
396    }
397
398    @Override
399    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
400
401        if (Utils.isMonkeyRunning()) {
402            return false;
403        }
404
405        if (preference == mEnableAdb) {
406            if (mEnableAdb.isChecked()) {
407                mOkClicked = false;
408                if (mOkDialog != null) dismissDialog();
409                mOkDialog = new AlertDialog.Builder(getActivity()).setMessage(
410                        getActivity().getResources().getString(R.string.adb_warning_message))
411                        .setTitle(R.string.adb_warning_title)
412                        .setIcon(android.R.drawable.ic_dialog_alert)
413                        .setPositiveButton(android.R.string.yes, this)
414                        .setNegativeButton(android.R.string.no, this)
415                        .show();
416                mOkDialog.setOnDismissListener(this);
417            } else {
418                Settings.Secure.putInt(getActivity().getContentResolver(),
419                        Settings.Secure.ADB_ENABLED, 0);
420            }
421        } else if (preference == mKeepScreenOn) {
422            Settings.System.putInt(getActivity().getContentResolver(),
423                    Settings.System.STAY_ON_WHILE_PLUGGED_IN,
424                    mKeepScreenOn.isChecked() ?
425                    (BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB) : 0);
426        } else if (preference == mAllowMockLocation) {
427            Settings.Secure.putInt(getActivity().getContentResolver(),
428                    Settings.Secure.ALLOW_MOCK_LOCATION,
429                    mAllowMockLocation.isChecked() ? 1 : 0);
430        } else if (preference == mStrictMode) {
431            writeStrictModeVisualOptions();
432        } else if (preference == mPointerLocation) {
433            writePointerLocationOptions();
434        } else if (preference == mShowTouches) {
435            writeShowTouchesOptions();
436        } else if (preference == mShowScreenUpdates) {
437            writeFlingerOptions();
438        } else if (preference == mShowCpuUsage) {
439            writeCpuUsageOptions();
440        } else if (preference == mImmediatelyDestroyActivities) {
441            writeImmediatelyDestroyActivitiesOptions();
442        } else if (preference == mShowAllANRs) {
443            writeShowAllANRsOptions();
444        }
445
446        return false;
447    }
448
449    @Override
450    public boolean onPreferenceChange(Preference preference, Object newValue) {
451        if (HDCP_CHECKING_KEY.equals(preference.getKey())) {
452            SystemProperties.set(HDCP_CHECKING_PROPERTY, newValue.toString());
453            updateHdcpValues();
454            return true;
455        } else if (preference == mWindowAnimationScale) {
456            writeAnimationScaleOption(0, mWindowAnimationScale, newValue);
457            return true;
458        } else if (preference == mTransitionAnimationScale) {
459            writeAnimationScaleOption(1, mTransitionAnimationScale, newValue);
460            return true;
461        } else if (preference == mAppProcessLimit) {
462            writeAppProcessLimitOptions(newValue);
463            return true;
464        }
465        return false;
466    }
467
468    private void dismissDialog() {
469        if (mOkDialog == null) return;
470        mOkDialog.dismiss();
471        mOkDialog = null;
472    }
473
474    public void onClick(DialogInterface dialog, int which) {
475        if (which == DialogInterface.BUTTON_POSITIVE) {
476            mOkClicked = true;
477            Settings.Secure.putInt(getActivity().getContentResolver(),
478                    Settings.Secure.ADB_ENABLED, 1);
479        } else {
480            // Reset the toggle
481            mEnableAdb.setChecked(false);
482        }
483    }
484
485    public void onDismiss(DialogInterface dialog) {
486        // Assuming that onClick gets called first
487        if (!mOkClicked) {
488            mEnableAdb.setChecked(false);
489        }
490    }
491
492    @Override
493    public void onDestroy() {
494        dismissDialog();
495        super.onDestroy();
496    }
497}
498