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