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