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