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