1 /* 2 * Copyright (C) 2017 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.development; 18 19 import static android.provider.Settings.Global.DEVELOPMENT_SETTINGS_ENABLED; 20 import static android.service.quicksettings.TileService.ACTION_QS_TILE_PREFERENCES; 21 22 import android.app.Activity; 23 import android.app.UiModeManager; 24 import android.app.settings.SettingsEnums; 25 import android.bluetooth.BluetoothA2dp; 26 import android.bluetooth.BluetoothAdapter; 27 import android.bluetooth.BluetoothCodecStatus; 28 import android.bluetooth.BluetoothProfile; 29 import android.content.BroadcastReceiver; 30 import android.content.ComponentName; 31 import android.content.ContentResolver; 32 import android.content.Context; 33 import android.content.Intent; 34 import android.content.IntentFilter; 35 import android.database.ContentObserver; 36 import android.net.Uri; 37 import android.os.Bundle; 38 import android.os.Handler; 39 import android.os.Looper; 40 import android.os.SystemProperties; 41 import android.os.UserManager; 42 import android.provider.Settings; 43 import android.text.TextUtils; 44 import android.util.Log; 45 import android.view.LayoutInflater; 46 import android.view.View; 47 import android.view.ViewGroup; 48 import android.widget.Switch; 49 50 import androidx.annotation.VisibleForTesting; 51 import androidx.localbroadcastmanager.content.LocalBroadcastManager; 52 53 import com.android.settings.R; 54 import com.android.settings.SettingsActivity; 55 import com.android.settings.Utils; 56 import com.android.settings.core.SubSettingLauncher; 57 import com.android.settings.dashboard.RestrictedDashboardFragment; 58 import com.android.settings.development.autofill.AutofillCategoryController; 59 import com.android.settings.development.autofill.AutofillLoggingLevelPreferenceController; 60 import com.android.settings.development.autofill.AutofillResetOptionsPreferenceController; 61 import com.android.settings.development.bluetooth.AbstractBluetoothDialogPreferenceController; 62 import com.android.settings.development.bluetooth.AbstractBluetoothPreferenceController; 63 import com.android.settings.development.bluetooth.BluetoothBitPerSampleDialogPreferenceController; 64 import com.android.settings.development.bluetooth.BluetoothChannelModeDialogPreferenceController; 65 import com.android.settings.development.bluetooth.BluetoothCodecDialogPreferenceController; 66 import com.android.settings.development.bluetooth.BluetoothHDAudioPreferenceController; 67 import com.android.settings.development.bluetooth.BluetoothQualityDialogPreferenceController; 68 import com.android.settings.development.bluetooth.BluetoothSampleRateDialogPreferenceController; 69 import com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController; 70 import com.android.settings.development.qstile.DevelopmentTiles; 71 import com.android.settings.development.storage.SharedDataPreferenceController; 72 import com.android.settings.overlay.FeatureFactory; 73 import com.android.settings.search.BaseSearchIndexProvider; 74 import com.android.settings.search.actionbar.SearchMenuController; 75 import com.android.settings.theme.ContrastPreferenceController; 76 import com.android.settings.widget.SettingsMainSwitchBar; 77 import com.android.settingslib.core.AbstractPreferenceController; 78 import com.android.settingslib.core.lifecycle.Lifecycle; 79 import com.android.settingslib.development.DeveloperOptionsPreferenceController; 80 import com.android.settingslib.development.DevelopmentSettingsEnabler; 81 import com.android.settingslib.development.SystemPropPoker; 82 import com.android.settingslib.search.SearchIndexable; 83 import com.android.settingslib.widget.OnMainSwitchChangeListener; 84 85 import com.google.android.setupcompat.util.WizardManagerHelper; 86 87 import java.util.ArrayList; 88 import java.util.List; 89 90 @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) 91 public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFragment 92 implements OnMainSwitchChangeListener, OemUnlockDialogHost, AdbDialogHost, 93 AdbClearKeysDialogHost, LogPersistDialogHost, 94 BluetoothRebootDialog.OnRebootDialogListener, 95 AbstractBluetoothPreferenceController.Callback, 96 NfcRebootDialog.OnNfcRebootDialogConfirmedListener, BluetoothSnoopLogHost { 97 98 private static final String TAG = "DevSettingsDashboard"; 99 100 private final BluetoothA2dpConfigStore mBluetoothA2dpConfigStore = 101 new BluetoothA2dpConfigStore(); 102 103 private boolean mIsAvailable = true; 104 private SettingsMainSwitchBar mSwitchBar; 105 private DevelopmentSwitchBarController mSwitchBarController; 106 private List<AbstractPreferenceController> mPreferenceControllers = new ArrayList<>(); 107 private BluetoothA2dp mBluetoothA2dp; 108 109 private final BroadcastReceiver mEnableAdbReceiver = new BroadcastReceiver() { 110 @Override 111 public void onReceive(Context context, Intent intent) { 112 for (AbstractPreferenceController controller : mPreferenceControllers) { 113 if (controller instanceof AdbOnChangeListener) { 114 ((AdbOnChangeListener) controller).onAdbSettingChanged(); 115 } 116 } 117 } 118 }; 119 120 private final BroadcastReceiver mBluetoothA2dpReceiver = new BroadcastReceiver() { 121 @Override 122 public void onReceive(Context context, Intent intent) { 123 Log.d(TAG, "mBluetoothA2dpReceiver.onReceive intent=" + intent); 124 String action = intent.getAction(); 125 126 if (BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED.equals(action)) { 127 BluetoothCodecStatus codecStatus = intent.getParcelableExtra( 128 BluetoothCodecStatus.EXTRA_CODEC_STATUS); 129 Log.d(TAG, "Received BluetoothCodecStatus=" + codecStatus); 130 for (AbstractPreferenceController controller : mPreferenceControllers) { 131 if (controller instanceof BluetoothServiceConnectionListener) { 132 ((BluetoothServiceConnectionListener) controller).onBluetoothCodecUpdated(); 133 } 134 } 135 } 136 } 137 }; 138 139 140 private final BluetoothProfile.ServiceListener mBluetoothA2dpServiceListener = 141 new BluetoothProfile.ServiceListener() { 142 @Override 143 public void onServiceConnected(int profile, 144 BluetoothProfile proxy) { 145 synchronized (mBluetoothA2dpConfigStore) { 146 mBluetoothA2dp = (BluetoothA2dp) proxy; 147 } 148 for (AbstractPreferenceController controller : mPreferenceControllers) { 149 if (controller instanceof BluetoothServiceConnectionListener) { 150 ((BluetoothServiceConnectionListener) controller) 151 .onBluetoothServiceConnected(mBluetoothA2dp); 152 } 153 } 154 } 155 156 @Override 157 public void onServiceDisconnected(int profile) { 158 synchronized (mBluetoothA2dpConfigStore) { 159 mBluetoothA2dp = null; 160 } 161 for (AbstractPreferenceController controller : mPreferenceControllers) { 162 if (controller instanceof BluetoothServiceConnectionListener) { 163 ((BluetoothServiceConnectionListener) controller) 164 .onBluetoothServiceDisconnected(); 165 } 166 } 167 } 168 }; 169 170 private final Runnable mSystemPropertiesChanged = new Runnable() { 171 @Override 172 public void run() { 173 synchronized (this) { 174 Activity activity = getActivity(); 175 if (activity != null) { 176 activity.runOnUiThread(() -> { 177 updatePreferenceStates(); 178 }); 179 } 180 } 181 } 182 }; 183 184 private final Uri mDevelopEnabled = Settings.Global.getUriFor(DEVELOPMENT_SETTINGS_ENABLED); 185 private final ContentObserver mDeveloperSettingsObserver = new ContentObserver(new Handler( 186 Looper.getMainLooper())) { 187 188 @Override 189 public void onChange(boolean selfChange, Uri uri) { 190 super.onChange(selfChange, uri); 191 final boolean developmentEnabledState = 192 DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(getContext()); 193 final boolean switchState = mSwitchBar.isChecked(); 194 195 // when developer options is enabled, but it is disabled by other privilege apps like: 196 // adb command, we should disable all items and finish the activity. 197 if (developmentEnabledState != switchState) { 198 if (developmentEnabledState) { 199 return; 200 } 201 disableDeveloperOptions(); 202 getActivity().runOnUiThread(() -> finishFragment()); 203 } 204 } 205 }; 206 DevelopmentSettingsDashboardFragment()207 public DevelopmentSettingsDashboardFragment() { 208 super(UserManager.DISALLOW_DEBUGGING_FEATURES); 209 } 210 211 @Override onStart()212 public void onStart() { 213 super.onStart(); 214 final ContentResolver cr = getContext().getContentResolver(); 215 cr.registerContentObserver(mDevelopEnabled, false, mDeveloperSettingsObserver); 216 } 217 218 @Override onStop()219 public void onStop() { 220 super.onStop(); 221 final ContentResolver cr = getContext().getContentResolver(); 222 cr.unregisterContentObserver(mDeveloperSettingsObserver); 223 } 224 225 @Override onCreate(Bundle icicle)226 public void onCreate(Bundle icicle) { 227 super.onCreate(icicle); 228 SearchMenuController.init(this); 229 if (Utils.isMonkeyRunning()) { 230 getActivity().finish(); 231 return; 232 } 233 } 234 235 @Override onActivityCreated(Bundle icicle)236 public void onActivityCreated(Bundle icicle) { 237 super.onActivityCreated(icicle); 238 // Apply page-level restrictions 239 setIfOnlyAvailableForAdmins(true); 240 if (isUiRestricted() || !WizardManagerHelper.isDeviceProvisioned(getActivity())) { 241 // Block access to developer options if the user is not the owner, if user policy 242 // restricts it, or if the device has not been provisioned 243 mIsAvailable = false; 244 // Show error message 245 if (!isUiRestrictedByOnlyAdmin()) { 246 getEmptyTextView().setText(R.string.development_settings_not_available); 247 } 248 getPreferenceScreen().removeAll(); 249 return; 250 } 251 // Set up primary switch 252 mSwitchBar = ((SettingsActivity) getActivity()).getSwitchBar(); 253 mSwitchBar.setTitle(getContext().getString(R.string.developer_options_main_switch_title)); 254 mSwitchBar.show(); 255 mSwitchBarController = new DevelopmentSwitchBarController( 256 this /* DevelopmentSettings */, mSwitchBar, mIsAvailable, 257 getSettingsLifecycle()); 258 259 // Restore UI state based on whether developer options is enabled 260 if (DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(getContext())) { 261 enableDeveloperOptions(); 262 handleQsTileLongPressActionIfAny(); 263 } else { 264 disableDeveloperOptions(); 265 } 266 } 267 268 @Override shouldSkipForInitialSUW()269 protected boolean shouldSkipForInitialSUW() { 270 return true; 271 } 272 273 /** 274 * Long-pressing a developer options quick settings tile will by default (see 275 * QS_TILE_PREFERENCES in the manifest) take you to the developer options page. 276 * Some tiles may want to go into their own page within the developer options. 277 */ handleQsTileLongPressActionIfAny()278 private void handleQsTileLongPressActionIfAny() { 279 Intent intent = getActivity().getIntent(); 280 if (intent == null || !TextUtils.equals(ACTION_QS_TILE_PREFERENCES, intent.getAction())) { 281 return; 282 } 283 284 Log.d(TAG, "Developer options started from qstile long-press"); 285 final ComponentName componentName = (ComponentName) intent.getParcelableExtra( 286 Intent.EXTRA_COMPONENT_NAME); 287 if (componentName == null) { 288 return; 289 } 290 291 if (DevelopmentTiles.WirelessDebugging.class.getName().equals( 292 componentName.getClassName()) && getDevelopmentOptionsController( 293 WirelessDebuggingPreferenceController.class).isAvailable()) { 294 Log.d(TAG, "Long press from wireless debugging qstile"); 295 new SubSettingLauncher(getContext()) 296 .setDestination(WirelessDebuggingFragment.class.getName()) 297 .setSourceMetricsCategory(SettingsEnums.SETTINGS_ADB_WIRELESS) 298 .launch(); 299 } 300 // Add other qstiles here 301 } 302 303 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)304 public View onCreateView(LayoutInflater inflater, ViewGroup container, 305 Bundle savedInstanceState) { 306 registerReceivers(); 307 SystemProperties.addChangeCallback(mSystemPropertiesChanged); 308 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 309 if (adapter != null) { 310 adapter.getProfileProxy(getActivity(), mBluetoothA2dpServiceListener, 311 BluetoothProfile.A2DP); 312 } 313 return super.onCreateView(inflater, container, savedInstanceState); 314 } 315 316 @Override onDestroyView()317 public void onDestroyView() { 318 super.onDestroyView(); 319 unregisterReceivers(); 320 321 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 322 if (adapter != null) { 323 adapter.closeProfileProxy(BluetoothProfile.A2DP, mBluetoothA2dp); 324 mBluetoothA2dp = null; 325 } 326 SystemProperties.removeChangeCallback(mSystemPropertiesChanged); 327 } 328 329 @Override getMetricsCategory()330 public int getMetricsCategory() { 331 return SettingsEnums.DEVELOPMENT; 332 } 333 334 @Override onSwitchChanged(Switch switchView, boolean isChecked)335 public void onSwitchChanged(Switch switchView, boolean isChecked) { 336 if (switchView != mSwitchBar.getSwitch()) { 337 return; 338 } 339 final boolean developmentEnabledState = 340 DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(getContext()); 341 if (isChecked != developmentEnabledState) { 342 if (isChecked) { 343 EnableDevelopmentSettingWarningDialog.show(this /* host */); 344 } else { 345 final BluetoothA2dpHwOffloadPreferenceController a2dpController = 346 getDevelopmentOptionsController( 347 BluetoothA2dpHwOffloadPreferenceController.class); 348 final BluetoothLeAudioHwOffloadPreferenceController leAudioController = 349 getDevelopmentOptionsController( 350 BluetoothLeAudioHwOffloadPreferenceController.class); 351 final NfcSnoopLogPreferenceController nfcSnoopLogController = 352 getDevelopmentOptionsController( 353 NfcSnoopLogPreferenceController.class); 354 final NfcVerboseVendorLogPreferenceController nfcVerboseLogController = 355 getDevelopmentOptionsController( 356 NfcVerboseVendorLogPreferenceController.class); 357 final GraphicsDriverEnableAngleAsSystemDriverController enableAngleController = 358 getDevelopmentOptionsController( 359 GraphicsDriverEnableAngleAsSystemDriverController.class); 360 // If hardware offload isn't default value, we must reboot after disable 361 // developer options. Show a dialog for the user to confirm. 362 if ((a2dpController == null || a2dpController.isDefaultValue()) 363 && (leAudioController == null || leAudioController.isDefaultValue()) 364 && (nfcSnoopLogController == null || nfcSnoopLogController.isDefaultValue()) 365 && (nfcVerboseLogController == null 366 || nfcVerboseLogController.isDefaultValue()) 367 && (enableAngleController == null 368 || enableAngleController.isDefaultValue())) { 369 disableDeveloperOptions(); 370 } else { 371 DisableDevSettingsDialogFragment.show(this /* host */); 372 } 373 } 374 FeatureFactory.getFactory( 375 getContext()).getSearchFeatureProvider().sendPreIndexIntent(getContext()); 376 } 377 } 378 379 @Override onOemUnlockDialogConfirmed()380 public void onOemUnlockDialogConfirmed() { 381 final OemUnlockPreferenceController controller = getDevelopmentOptionsController( 382 OemUnlockPreferenceController.class); 383 controller.onOemUnlockConfirmed(); 384 } 385 386 @Override onOemUnlockDialogDismissed()387 public void onOemUnlockDialogDismissed() { 388 final OemUnlockPreferenceController controller = getDevelopmentOptionsController( 389 OemUnlockPreferenceController.class); 390 controller.onOemUnlockDismissed(); 391 } 392 393 @Override onEnableAdbDialogConfirmed()394 public void onEnableAdbDialogConfirmed() { 395 final AdbPreferenceController controller = getDevelopmentOptionsController( 396 AdbPreferenceController.class); 397 controller.onAdbDialogConfirmed(); 398 399 } 400 401 @Override onEnableAdbDialogDismissed()402 public void onEnableAdbDialogDismissed() { 403 final AdbPreferenceController controller = getDevelopmentOptionsController( 404 AdbPreferenceController.class); 405 controller.onAdbDialogDismissed(); 406 } 407 408 @Override onAdbClearKeysDialogConfirmed()409 public void onAdbClearKeysDialogConfirmed() { 410 final ClearAdbKeysPreferenceController controller = getDevelopmentOptionsController( 411 ClearAdbKeysPreferenceController.class); 412 controller.onClearAdbKeysConfirmed(); 413 } 414 415 @Override onDisableLogPersistDialogConfirmed()416 public void onDisableLogPersistDialogConfirmed() { 417 final LogPersistPreferenceController controller = getDevelopmentOptionsController( 418 LogPersistPreferenceController.class); 419 controller.onDisableLogPersistDialogConfirmed(); 420 } 421 422 @Override onDisableLogPersistDialogRejected()423 public void onDisableLogPersistDialogRejected() { 424 final LogPersistPreferenceController controller = getDevelopmentOptionsController( 425 LogPersistPreferenceController.class); 426 controller.onDisableLogPersistDialogRejected(); 427 } 428 429 @Override onRebootDialogConfirmed()430 public void onRebootDialogConfirmed() { 431 final BluetoothA2dpHwOffloadPreferenceController a2dpController = 432 getDevelopmentOptionsController(BluetoothA2dpHwOffloadPreferenceController.class); 433 a2dpController.onRebootDialogConfirmed(); 434 435 final BluetoothLeAudioHwOffloadPreferenceController leAudioController = 436 getDevelopmentOptionsController( 437 BluetoothLeAudioHwOffloadPreferenceController.class); 438 leAudioController.onRebootDialogConfirmed(); 439 440 final BluetoothLeAudioPreferenceController leAudioFeatureController = 441 getDevelopmentOptionsController( 442 BluetoothLeAudioPreferenceController.class); 443 leAudioFeatureController.onRebootDialogConfirmed(); 444 445 final BluetoothLeAudioAllowListPreferenceController leAudioAllowListController = 446 getDevelopmentOptionsController( 447 BluetoothLeAudioAllowListPreferenceController.class); 448 leAudioAllowListController.onRebootDialogConfirmed(); 449 } 450 451 @Override onRebootDialogCanceled()452 public void onRebootDialogCanceled() { 453 final BluetoothA2dpHwOffloadPreferenceController a2dpController = 454 getDevelopmentOptionsController(BluetoothA2dpHwOffloadPreferenceController.class); 455 a2dpController.onRebootDialogCanceled(); 456 457 final BluetoothLeAudioHwOffloadPreferenceController leAudioController = 458 getDevelopmentOptionsController( 459 BluetoothLeAudioHwOffloadPreferenceController.class); 460 leAudioController.onRebootDialogCanceled(); 461 462 final BluetoothLeAudioPreferenceController leAudioFeatureController = 463 getDevelopmentOptionsController( 464 BluetoothLeAudioPreferenceController.class); 465 leAudioFeatureController.onRebootDialogCanceled(); 466 467 final BluetoothLeAudioAllowListPreferenceController leAudioAllowListController = 468 getDevelopmentOptionsController( 469 BluetoothLeAudioAllowListPreferenceController.class); 470 leAudioAllowListController.onRebootDialogCanceled(); 471 } 472 473 @Override onNfcRebootDialogConfirmed()474 public void onNfcRebootDialogConfirmed() { 475 final NfcSnoopLogPreferenceController controller = 476 getDevelopmentOptionsController(NfcSnoopLogPreferenceController.class); 477 controller.onNfcRebootDialogConfirmed(); 478 479 final NfcVerboseVendorLogPreferenceController vendorLogController = 480 getDevelopmentOptionsController(NfcVerboseVendorLogPreferenceController.class); 481 vendorLogController.onNfcRebootDialogConfirmed(); 482 } 483 484 @Override onNfcRebootDialogCanceled()485 public void onNfcRebootDialogCanceled() { 486 final NfcSnoopLogPreferenceController controller = 487 getDevelopmentOptionsController(NfcSnoopLogPreferenceController.class); 488 controller.onNfcRebootDialogCanceled(); 489 490 final NfcVerboseVendorLogPreferenceController vendorLogController = 491 getDevelopmentOptionsController(NfcVerboseVendorLogPreferenceController.class); 492 vendorLogController.onNfcRebootDialogCanceled(); 493 } 494 495 @Override onSettingChanged()496 public void onSettingChanged() { 497 final BluetoothSnoopLogFilterProfileMapPreferenceController controllerMap = 498 getDevelopmentOptionsController( 499 BluetoothSnoopLogFilterProfileMapPreferenceController.class); 500 final BluetoothSnoopLogFilterProfilePbapPreferenceController controllerPbap = 501 getDevelopmentOptionsController( 502 BluetoothSnoopLogFilterProfilePbapPreferenceController.class); 503 controllerMap.onSettingChanged(); 504 controllerPbap.onSettingChanged(); 505 } 506 507 @Override onActivityResult(int requestCode, int resultCode, Intent data)508 public void onActivityResult(int requestCode, int resultCode, Intent data) { 509 boolean handledResult = false; 510 for (AbstractPreferenceController controller : mPreferenceControllers) { 511 if (controller instanceof OnActivityResultListener) { 512 // We do not break early because it is possible for multiple controllers to 513 // handle the same result code. 514 handledResult |= 515 ((OnActivityResultListener) controller).onActivityResult( 516 requestCode, resultCode, data); 517 } 518 } 519 if (!handledResult) { 520 super.onActivityResult(requestCode, resultCode, data); 521 } 522 } 523 524 @Override getLogTag()525 protected String getLogTag() { 526 return TAG; 527 } 528 529 @Override getHelpResource()530 public int getHelpResource() { 531 return 0; 532 } 533 534 @Override getPreferenceScreenResId()535 protected int getPreferenceScreenResId() { 536 return Utils.isMonkeyRunning() ? R.xml.placeholder_prefs : R.xml.development_settings; 537 } 538 539 @Override createPreferenceControllers(Context context)540 protected List<AbstractPreferenceController> createPreferenceControllers(Context context) { 541 if (Utils.isMonkeyRunning()) { 542 mPreferenceControllers = new ArrayList<>(); 543 return null; 544 } 545 mPreferenceControllers = buildPreferenceControllers(context, getActivity(), 546 getSettingsLifecycle(), this /* devOptionsDashboardFragment */, 547 new BluetoothA2dpConfigStore()); 548 return mPreferenceControllers; 549 } 550 registerReceivers()551 private void registerReceivers() { 552 LocalBroadcastManager.getInstance(getContext()) 553 .registerReceiver(mEnableAdbReceiver, new IntentFilter( 554 AdbPreferenceController.ACTION_ENABLE_ADB_STATE_CHANGED)); 555 556 final IntentFilter filter = new IntentFilter(); 557 filter.addAction(BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED); 558 getActivity().registerReceiver(mBluetoothA2dpReceiver, filter); 559 } 560 unregisterReceivers()561 private void unregisterReceivers() { 562 LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(mEnableAdbReceiver); 563 getActivity().unregisterReceiver(mBluetoothA2dpReceiver); 564 } 565 enableDeveloperOptions()566 private void enableDeveloperOptions() { 567 if (Utils.isMonkeyRunning()) { 568 return; 569 } 570 DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(getContext(), true); 571 for (AbstractPreferenceController controller : mPreferenceControllers) { 572 if (controller instanceof DeveloperOptionsPreferenceController) { 573 ((DeveloperOptionsPreferenceController) controller).onDeveloperOptionsEnabled(); 574 } 575 } 576 } 577 disableDeveloperOptions()578 private void disableDeveloperOptions() { 579 if (Utils.isMonkeyRunning()) { 580 return; 581 } 582 DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(getContext(), false); 583 final SystemPropPoker poker = SystemPropPoker.getInstance(); 584 poker.blockPokes(); 585 for (AbstractPreferenceController controller : mPreferenceControllers) { 586 if (controller instanceof DeveloperOptionsPreferenceController) { 587 ((DeveloperOptionsPreferenceController) controller) 588 .onDeveloperOptionsDisabled(); 589 } 590 } 591 poker.unblockPokes(); 592 poker.poke(); 593 } 594 onEnableDevelopmentOptionsConfirmed()595 void onEnableDevelopmentOptionsConfirmed() { 596 enableDeveloperOptions(); 597 } 598 onEnableDevelopmentOptionsRejected()599 void onEnableDevelopmentOptionsRejected() { 600 // Reset the toggle 601 mSwitchBar.setChecked(false); 602 } 603 onDisableDevelopmentOptionsConfirmed()604 void onDisableDevelopmentOptionsConfirmed() { 605 disableDeveloperOptions(); 606 } 607 onDisableDevelopmentOptionsRejected()608 void onDisableDevelopmentOptionsRejected() { 609 // Reset the toggle 610 mSwitchBar.setChecked(true); 611 } 612 buildPreferenceControllers(Context context, Activity activity, Lifecycle lifecycle, DevelopmentSettingsDashboardFragment fragment, BluetoothA2dpConfigStore bluetoothA2dpConfigStore)613 private static List<AbstractPreferenceController> buildPreferenceControllers(Context context, 614 Activity activity, Lifecycle lifecycle, DevelopmentSettingsDashboardFragment fragment, 615 BluetoothA2dpConfigStore bluetoothA2dpConfigStore) { 616 final List<AbstractPreferenceController> controllers = new ArrayList<>(); 617 controllers.add(new MemoryUsagePreferenceController(context)); 618 controllers.add(new BugReportPreferenceController(context)); 619 controllers.add(new BugReportHandlerPreferenceController(context)); 620 controllers.add(new SystemServerHeapDumpPreferenceController(context)); 621 controllers.add(new DevelopmentMemtagPagePreferenceController(context, fragment)); 622 controllers.add(new LocalBackupPasswordPreferenceController(context)); 623 controllers.add(new StayAwakePreferenceController(context, lifecycle)); 624 controllers.add(new HdcpCheckingPreferenceController(context)); 625 controllers.add(new BluetoothSnoopLogPreferenceController(context, fragment)); 626 controllers.add(new DefaultLaunchPreferenceController(context, 627 "snoop_logger_filters_dashboard")); 628 controllers.add(new BluetoothSnoopLogFilterProfilePbapPreferenceController(context)); 629 controllers.add(new BluetoothSnoopLogFilterProfileMapPreferenceController(context)); 630 controllers.add(new OemUnlockPreferenceController(context, activity, fragment)); 631 controllers.add(new PictureColorModePreferenceController(context, lifecycle)); 632 controllers.add(new WebViewAppPreferenceController(context)); 633 controllers.add(new CoolColorTemperaturePreferenceController(context)); 634 controllers.add(new DisableAutomaticUpdatesPreferenceController(context)); 635 controllers.add(new SelectDSUPreferenceController(context)); 636 controllers.add(new AdbPreferenceController(context, fragment)); 637 controllers.add(new ClearAdbKeysPreferenceController(context, fragment)); 638 controllers.add(new WirelessDebuggingPreferenceController(context, lifecycle)); 639 controllers.add(new AdbAuthorizationTimeoutPreferenceController(context)); 640 controllers.add(new LocalTerminalPreferenceController(context)); 641 controllers.add(new BugReportInPowerPreferenceController(context)); 642 controllers.add(new AutomaticSystemServerHeapDumpPreferenceController(context)); 643 controllers.add(new MockLocationAppPreferenceController(context, fragment)); 644 controllers.add(new MockModemPreferenceController(context)); 645 controllers.add(new DebugViewAttributesPreferenceController(context)); 646 controllers.add(new SelectDebugAppPreferenceController(context, fragment)); 647 controllers.add(new WaitForDebuggerPreferenceController(context)); 648 controllers.add(new EnableGpuDebugLayersPreferenceController(context)); 649 controllers.add(new GraphicsDriverEnableAngleAsSystemDriverController(context, fragment)); 650 controllers.add(new ForcePeakRefreshRatePreferenceController(context)); 651 controllers.add(new EnableVerboseVendorLoggingPreferenceController(context)); 652 controllers.add(new VerifyAppsOverUsbPreferenceController(context)); 653 controllers.add(new ArtVerifierPreferenceController(context)); 654 controllers.add(new LogdSizePreferenceController(context)); 655 controllers.add(new LogPersistPreferenceController(context, fragment, lifecycle)); 656 controllers.add(new CameraLaserSensorPreferenceController(context)); 657 controllers.add(new WifiDisplayCertificationPreferenceController(context)); 658 controllers.add(new WifiVerboseLoggingPreferenceController(context)); 659 controllers.add(new WifiScanThrottlingPreferenceController(context)); 660 controllers.add(new WifiNonPersistentMacRandomizationPreferenceController(context)); 661 controllers.add(new MobileDataAlwaysOnPreferenceController(context)); 662 controllers.add(new TetheringHardwareAccelPreferenceController(context)); 663 controllers.add(new BluetoothDeviceNoNamePreferenceController(context)); 664 controllers.add(new BluetoothAbsoluteVolumePreferenceController(context)); 665 controllers.add(new BluetoothAvrcpVersionPreferenceController(context)); 666 controllers.add(new BluetoothMapVersionPreferenceController(context)); 667 controllers.add(new BluetoothLeAudioPreferenceController(context, fragment)); 668 controllers.add(new BluetoothLeAudioDeviceDetailsPreferenceController(context)); 669 controllers.add(new BluetoothLeAudioAllowListPreferenceController(context, fragment)); 670 controllers.add(new BluetoothA2dpHwOffloadPreferenceController(context, fragment)); 671 controllers.add(new BluetoothLeAudioHwOffloadPreferenceController(context, fragment)); 672 controllers.add(new BluetoothMaxConnectedAudioDevicesPreferenceController(context)); 673 controllers.add(new NfcStackDebugLogPreferenceController(context)); 674 controllers.add(new NfcSnoopLogPreferenceController(context, fragment)); 675 controllers.add(new NfcVerboseVendorLogPreferenceController(context, fragment)); 676 controllers.add(new ShowTapsPreferenceController(context)); 677 controllers.add(new PointerLocationPreferenceController(context)); 678 controllers.add(new ShowKeyPressesPreferenceController(context)); 679 controllers.add(new ShowSurfaceUpdatesPreferenceController(context)); 680 controllers.add(new ShowLayoutBoundsPreferenceController(context)); 681 controllers.add(new ShowRefreshRatePreferenceController(context)); 682 controllers.add(new RtlLayoutPreferenceController(context)); 683 controllers.add(new WindowAnimationScalePreferenceController(context)); 684 controllers.add(new EmulateDisplayCutoutPreferenceController(context)); 685 controllers.add(new TransparentNavigationBarPreferenceController(context)); 686 controllers.add(new TransitionAnimationScalePreferenceController(context)); 687 controllers.add(new AnimatorDurationScalePreferenceController(context)); 688 controllers.add(new SecondaryDisplayPreferenceController(context)); 689 controllers.add(new GpuViewUpdatesPreferenceController(context)); 690 controllers.add(new HardwareLayersUpdatesPreferenceController(context)); 691 controllers.add(new DebugGpuOverdrawPreferenceController(context)); 692 controllers.add(new DebugNonRectClipOperationsPreferenceController(context)); 693 controllers.add(new ForceDarkPreferenceController(context)); 694 controllers.add(new EnableBlursPreferenceController(context)); 695 controllers.add(new ForceMSAAPreferenceController(context)); 696 controllers.add(new HardwareOverlaysPreferenceController(context)); 697 controllers.add(new SimulateColorSpacePreferenceController(context)); 698 controllers.add(new UsbAudioRoutingPreferenceController(context)); 699 controllers.add(new StrictModePreferenceController(context)); 700 controllers.add(new ProfileGpuRenderingPreferenceController(context)); 701 controllers.add(new KeepActivitiesPreferenceController(context)); 702 controllers.add(new BackgroundProcessLimitPreferenceController(context)); 703 controllers.add(new CachedAppsFreezerPreferenceController(context)); 704 controllers.add(new ShowFirstCrashDialogPreferenceController(context)); 705 controllers.add(new AppsNotRespondingPreferenceController(context)); 706 controllers.add(new NotificationChannelWarningsPreferenceController(context)); 707 controllers.add(new AllowAppsOnExternalPreferenceController(context)); 708 controllers.add(new ResizableActivityPreferenceController(context)); 709 controllers.add(new FreeformWindowsPreferenceController(context, fragment)); 710 controllers.add(new DesktopModePreferenceController(context, fragment)); 711 controllers.add(new NonResizableMultiWindowPreferenceController(context)); 712 controllers.add(new ShortcutManagerThrottlingPreferenceController(context)); 713 controllers.add(new EnableGnssRawMeasFullTrackingPreferenceController(context)); 714 controllers.add(new DefaultLaunchPreferenceController(context, "running_apps")); 715 controllers.add(new DefaultLaunchPreferenceController(context, "demo_mode")); 716 controllers.add(new DefaultLaunchPreferenceController(context, "quick_settings_tiles")); 717 controllers.add(new DefaultLaunchPreferenceController(context, "feature_flags_dashboard")); 718 controllers.add(new DefaultUsbConfigurationPreferenceController(context)); 719 controllers.add(new DefaultLaunchPreferenceController(context, "density")); 720 controllers.add(new DefaultLaunchPreferenceController(context, "background_check")); 721 controllers.add(new DefaultLaunchPreferenceController(context, "inactive_apps")); 722 controllers.add(new TarePreferenceController(context)); 723 controllers.add(new AutofillCategoryController(context, lifecycle)); 724 controllers.add(new AutofillLoggingLevelPreferenceController(context, lifecycle)); 725 controllers.add(new AutofillResetOptionsPreferenceController(context)); 726 controllers.add(new BluetoothCodecDialogPreferenceController(context, lifecycle, 727 bluetoothA2dpConfigStore, fragment)); 728 controllers.add(new BluetoothSampleRateDialogPreferenceController(context, lifecycle, 729 bluetoothA2dpConfigStore)); 730 controllers.add(new BluetoothBitPerSampleDialogPreferenceController(context, lifecycle, 731 bluetoothA2dpConfigStore)); 732 controllers.add(new BluetoothQualityDialogPreferenceController(context, lifecycle, 733 bluetoothA2dpConfigStore)); 734 controllers.add(new BluetoothChannelModeDialogPreferenceController(context, lifecycle, 735 bluetoothA2dpConfigStore)); 736 controllers.add(new BluetoothHDAudioPreferenceController(context, lifecycle, 737 bluetoothA2dpConfigStore, fragment)); 738 controllers.add(new SharedDataPreferenceController(context)); 739 controllers.add(new OverlaySettingsPreferenceController(context)); 740 controllers.add(new StylusHandwritingPreferenceController(context)); 741 controllers.add(new IngressRateLimitPreferenceController((context))); 742 controllers.add(new BackAnimationPreferenceController(context, fragment)); 743 controllers.add(new PhantomProcessPreferenceController(context)); 744 controllers.add(new ContrastPreferenceController( 745 context, context.getSystemService(UiModeManager.class))); 746 controllers.add(new ForceEnableNotesRolePreferenceController(context)); 747 748 return controllers; 749 } 750 751 @VisibleForTesting getDevelopmentOptionsController(Class<T> clazz)752 <T extends AbstractPreferenceController> T getDevelopmentOptionsController(Class<T> clazz) { 753 return use(clazz); 754 } 755 756 @Override onBluetoothCodecChanged()757 public void onBluetoothCodecChanged() { 758 for (AbstractPreferenceController controller : mPreferenceControllers) { 759 if (controller instanceof AbstractBluetoothDialogPreferenceController 760 && !(controller instanceof BluetoothCodecDialogPreferenceController)) { 761 ((AbstractBluetoothDialogPreferenceController) controller) 762 .onBluetoothCodecUpdated(); 763 } 764 } 765 } 766 767 @Override onBluetoothHDAudioEnabled(boolean enabled)768 public void onBluetoothHDAudioEnabled(boolean enabled) { 769 for (AbstractPreferenceController controller : mPreferenceControllers) { 770 if (controller instanceof AbstractBluetoothDialogPreferenceController) { 771 ((AbstractBluetoothDialogPreferenceController) controller).onHDAudioEnabled( 772 enabled); 773 } 774 } 775 } 776 777 /** 778 * For Search. 779 */ 780 public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 781 new BaseSearchIndexProvider(R.xml.development_settings) { 782 783 @Override 784 protected boolean isPageSearchEnabled(Context context) { 785 return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context); 786 } 787 788 @Override 789 public List<AbstractPreferenceController> createPreferenceControllers(Context 790 context) { 791 return buildPreferenceControllers(context, null /* activity */, 792 null /* lifecycle */, null /* devOptionsDashboardFragment */, 793 null /* bluetoothA2dpConfigStore */); 794 } 795 }; 796 } 797