1 /* 2 * Copyright (C) 2019 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.car.developeroptions.development; 18 19 import android.app.Activity; 20 import android.app.settings.SettingsEnums; 21 import android.bluetooth.BluetoothA2dp; 22 import android.bluetooth.BluetoothAdapter; 23 import android.bluetooth.BluetoothCodecStatus; 24 import android.bluetooth.BluetoothProfile; 25 import android.content.BroadcastReceiver; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.IntentFilter; 29 import android.os.Bundle; 30 import android.os.UserManager; 31 import android.provider.SearchIndexableResource; 32 import android.util.Log; 33 import android.view.LayoutInflater; 34 import android.view.View; 35 import android.view.ViewGroup; 36 import android.widget.Switch; 37 38 import androidx.annotation.VisibleForTesting; 39 import androidx.localbroadcastmanager.content.LocalBroadcastManager; 40 41 import com.android.car.developeroptions.R; 42 import com.android.car.developeroptions.SettingsActivity; 43 import com.android.car.developeroptions.Utils; 44 import com.android.car.developeroptions.dashboard.RestrictedDashboardFragment; 45 import com.android.car.developeroptions.development.autofill.AutofillLoggingLevelPreferenceController; 46 import com.android.car.developeroptions.development.autofill.AutofillResetOptionsPreferenceController; 47 import com.android.car.developeroptions.search.BaseSearchIndexProvider; 48 import com.android.car.developeroptions.search.Indexable; 49 import com.android.car.developeroptions.widget.SwitchBar; 50 import com.android.settingslib.core.AbstractPreferenceController; 51 import com.android.settingslib.core.lifecycle.Lifecycle; 52 import com.android.settingslib.development.DeveloperOptionsPreferenceController; 53 import com.android.settingslib.development.DevelopmentSettingsEnabler; 54 import com.android.settingslib.development.SystemPropPoker; 55 import com.android.settingslib.search.SearchIndexable; 56 57 import java.util.ArrayList; 58 import java.util.Arrays; 59 import java.util.List; 60 61 @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) 62 public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFragment 63 implements SwitchBar.OnSwitchChangeListener, OemUnlockDialogHost, AdbDialogHost, 64 AdbClearKeysDialogHost, LogPersistDialogHost, 65 BluetoothA2dpHwOffloadRebootDialog.OnA2dpHwDialogConfirmedListener { 66 67 private static final String TAG = "DevSettingsDashboard"; 68 69 private final BluetoothA2dpConfigStore mBluetoothA2dpConfigStore = 70 new BluetoothA2dpConfigStore(); 71 72 private boolean mIsAvailable = true; 73 private SwitchBar mSwitchBar; 74 private DevelopmentSwitchBarController mSwitchBarController; 75 private List<AbstractPreferenceController> mPreferenceControllers = new ArrayList<>(); 76 private BluetoothA2dp mBluetoothA2dp; 77 78 private final BroadcastReceiver mEnableAdbReceiver = new BroadcastReceiver() { 79 @Override 80 public void onReceive(Context context, Intent intent) { 81 for (AbstractPreferenceController controller : mPreferenceControllers) { 82 if (controller instanceof AdbOnChangeListener) { 83 ((AdbOnChangeListener) controller).onAdbSettingChanged(); 84 } 85 } 86 } 87 }; 88 89 private final BroadcastReceiver mBluetoothA2dpReceiver = new BroadcastReceiver() { 90 @Override 91 public void onReceive(Context context, Intent intent) { 92 Log.d(TAG, "mBluetoothA2dpReceiver.onReceive intent=" + intent); 93 String action = intent.getAction(); 94 95 if (BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED.equals(action)) { 96 BluetoothCodecStatus codecStatus = intent.getParcelableExtra( 97 BluetoothCodecStatus.EXTRA_CODEC_STATUS); 98 Log.d(TAG, "Received BluetoothCodecStatus=" + codecStatus); 99 for (AbstractPreferenceController controller : mPreferenceControllers) { 100 if (controller instanceof BluetoothServiceConnectionListener) { 101 ((BluetoothServiceConnectionListener) controller).onBluetoothCodecUpdated(); 102 } 103 } 104 } 105 } 106 }; 107 108 109 private final BluetoothProfile.ServiceListener mBluetoothA2dpServiceListener = 110 new BluetoothProfile.ServiceListener() { 111 @Override 112 public void onServiceConnected(int profile, 113 BluetoothProfile proxy) { 114 synchronized (mBluetoothA2dpConfigStore) { 115 mBluetoothA2dp = (BluetoothA2dp) proxy; 116 } 117 for (AbstractPreferenceController controller : mPreferenceControllers) { 118 if (controller instanceof BluetoothServiceConnectionListener) { 119 ((BluetoothServiceConnectionListener) controller) 120 .onBluetoothServiceConnected(mBluetoothA2dp); 121 } 122 } 123 } 124 125 @Override 126 public void onServiceDisconnected(int profile) { 127 synchronized (mBluetoothA2dpConfigStore) { 128 mBluetoothA2dp = null; 129 } 130 for (AbstractPreferenceController controller : mPreferenceControllers) { 131 if (controller instanceof BluetoothServiceConnectionListener) { 132 ((BluetoothServiceConnectionListener) controller) 133 .onBluetoothServiceDisconnected(); 134 } 135 } 136 } 137 }; 138 DevelopmentSettingsDashboardFragment()139 public DevelopmentSettingsDashboardFragment() { 140 super(UserManager.DISALLOW_DEBUGGING_FEATURES); 141 } 142 143 @Override onCreate(Bundle icicle)144 public void onCreate(Bundle icicle) { 145 super.onCreate(icicle); 146 if (Utils.isMonkeyRunning()) { 147 getActivity().finish(); 148 return; 149 } 150 } 151 152 @Override onActivityCreated(Bundle icicle)153 public void onActivityCreated(Bundle icicle) { 154 super.onActivityCreated(icicle); 155 // Apply page-level restrictions 156 setIfOnlyAvailableForAdmins(true); 157 if (isUiRestricted() || !Utils.isDeviceProvisioned(getActivity())) { 158 // Block access to developer options if the user is not the owner, if user policy 159 // restricts it, or if the device has not been provisioned 160 mIsAvailable = false; 161 // Show error message 162 if (!isUiRestrictedByOnlyAdmin()) { 163 getEmptyTextView().setText(R.string.development_settings_not_available); 164 } 165 getPreferenceScreen().removeAll(); 166 return; 167 } 168 // Set up global switch 169 mSwitchBar = ((SettingsActivity) getActivity()).getSwitchBar(); 170 mSwitchBarController = new DevelopmentSwitchBarController( 171 this /* DevelopmentSettings */, mSwitchBar, mIsAvailable, 172 getSettingsLifecycle()); 173 mSwitchBar.show(); 174 175 // Restore UI state based on whether developer options is enabled 176 if (DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(getContext())) { 177 enableDeveloperOptions(); 178 } else { 179 disableDeveloperOptions(); 180 } 181 } 182 183 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)184 public View onCreateView(LayoutInflater inflater, ViewGroup container, 185 Bundle savedInstanceState) { 186 registerReceivers(); 187 188 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 189 if (adapter != null) { 190 adapter.getProfileProxy(getActivity(), mBluetoothA2dpServiceListener, 191 BluetoothProfile.A2DP); 192 } 193 return super.onCreateView(inflater, container, savedInstanceState); 194 } 195 196 @Override onDestroyView()197 public void onDestroyView() { 198 super.onDestroyView(); 199 unregisterReceivers(); 200 201 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 202 if (adapter != null) { 203 adapter.closeProfileProxy(BluetoothProfile.A2DP, mBluetoothA2dp); 204 mBluetoothA2dp = null; 205 } 206 } 207 208 @Override getMetricsCategory()209 public int getMetricsCategory() { 210 return SettingsEnums.DEVELOPMENT; 211 } 212 213 @Override onSwitchChanged(Switch switchView, boolean isChecked)214 public void onSwitchChanged(Switch switchView, boolean isChecked) { 215 if (switchView != mSwitchBar.getSwitch()) { 216 return; 217 } 218 final boolean developmentEnabledState = 219 DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(getContext()); 220 if (isChecked != developmentEnabledState) { 221 if (isChecked) { 222 EnableDevelopmentSettingWarningDialog.show(this /* host */); 223 } else { 224 final BluetoothA2dpHwOffloadPreferenceController controller = 225 getDevelopmentOptionsController( 226 BluetoothA2dpHwOffloadPreferenceController.class); 227 // If A2DP hardware offload isn't default value, we must reboot after disable 228 // developer options. Show a dialog for the user to confirm. 229 if (controller == null || controller.isDefaultValue()) { 230 disableDeveloperOptions(); 231 } else { 232 DisableDevSettingsDialogFragment.show(this /* host */); 233 } 234 } 235 } 236 } 237 238 @Override onOemUnlockDialogConfirmed()239 public void onOemUnlockDialogConfirmed() { 240 final OemUnlockPreferenceController controller = getDevelopmentOptionsController( 241 OemUnlockPreferenceController.class); 242 controller.onOemUnlockConfirmed(); 243 } 244 245 @Override onOemUnlockDialogDismissed()246 public void onOemUnlockDialogDismissed() { 247 final OemUnlockPreferenceController controller = getDevelopmentOptionsController( 248 OemUnlockPreferenceController.class); 249 controller.onOemUnlockDismissed(); 250 } 251 252 @Override onEnableAdbDialogConfirmed()253 public void onEnableAdbDialogConfirmed() { 254 final AdbPreferenceController controller = getDevelopmentOptionsController( 255 AdbPreferenceController.class); 256 controller.onAdbDialogConfirmed(); 257 258 } 259 260 @Override onEnableAdbDialogDismissed()261 public void onEnableAdbDialogDismissed() { 262 final AdbPreferenceController controller = getDevelopmentOptionsController( 263 AdbPreferenceController.class); 264 controller.onAdbDialogDismissed(); 265 } 266 267 @Override onAdbClearKeysDialogConfirmed()268 public void onAdbClearKeysDialogConfirmed() { 269 final ClearAdbKeysPreferenceController controller = getDevelopmentOptionsController( 270 ClearAdbKeysPreferenceController.class); 271 controller.onClearAdbKeysConfirmed(); 272 } 273 274 @Override onDisableLogPersistDialogConfirmed()275 public void onDisableLogPersistDialogConfirmed() { 276 final LogPersistPreferenceController controller = getDevelopmentOptionsController( 277 LogPersistPreferenceController.class); 278 controller.onDisableLogPersistDialogConfirmed(); 279 } 280 281 @Override onDisableLogPersistDialogRejected()282 public void onDisableLogPersistDialogRejected() { 283 final LogPersistPreferenceController controller = getDevelopmentOptionsController( 284 LogPersistPreferenceController.class); 285 controller.onDisableLogPersistDialogRejected(); 286 } 287 288 @Override onA2dpHwDialogConfirmed()289 public void onA2dpHwDialogConfirmed() { 290 final BluetoothA2dpHwOffloadPreferenceController controller = 291 getDevelopmentOptionsController(BluetoothA2dpHwOffloadPreferenceController.class); 292 controller.onA2dpHwDialogConfirmed(); 293 } 294 295 @Override onActivityResult(int requestCode, int resultCode, Intent data)296 public void onActivityResult(int requestCode, int resultCode, Intent data) { 297 boolean handledResult = false; 298 for (AbstractPreferenceController controller : mPreferenceControllers) { 299 if (controller instanceof OnActivityResultListener) { 300 // We do not break early because it is possible for multiple controllers to 301 // handle the same result code. 302 handledResult |= 303 ((OnActivityResultListener) controller).onActivityResult( 304 requestCode, resultCode, data); 305 } 306 } 307 if (!handledResult) { 308 super.onActivityResult(requestCode, resultCode, data); 309 } 310 } 311 312 @Override getLogTag()313 protected String getLogTag() { 314 return TAG; 315 } 316 317 @Override getHelpResource()318 public int getHelpResource() { 319 return 0; 320 } 321 322 @Override getPreferenceScreenResId()323 protected int getPreferenceScreenResId() { 324 return Utils.isMonkeyRunning()? R.xml.placeholder_prefs : R.xml.development_settings; 325 } 326 327 @Override createPreferenceControllers(Context context)328 protected List<AbstractPreferenceController> createPreferenceControllers(Context context) { 329 if (Utils.isMonkeyRunning()) { 330 mPreferenceControllers = new ArrayList<>(); 331 return null; 332 } 333 mPreferenceControllers = buildPreferenceControllers(context, getActivity(), 334 getSettingsLifecycle(), this /* devOptionsDashboardFragment */, 335 new BluetoothA2dpConfigStore()); 336 return mPreferenceControllers; 337 } 338 registerReceivers()339 private void registerReceivers() { 340 LocalBroadcastManager.getInstance(getContext()) 341 .registerReceiver(mEnableAdbReceiver, new IntentFilter( 342 AdbPreferenceController.ACTION_ENABLE_ADB_STATE_CHANGED)); 343 344 final IntentFilter filter = new IntentFilter(); 345 filter.addAction(BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED); 346 getActivity().registerReceiver(mBluetoothA2dpReceiver, filter); 347 } 348 unregisterReceivers()349 private void unregisterReceivers() { 350 LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(mEnableAdbReceiver); 351 getActivity().unregisterReceiver(mBluetoothA2dpReceiver); 352 } 353 enableDeveloperOptions()354 private void enableDeveloperOptions() { 355 if (Utils.isMonkeyRunning()) { 356 return; 357 } 358 DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(getContext(), true); 359 for (AbstractPreferenceController controller : mPreferenceControllers) { 360 if (controller instanceof DeveloperOptionsPreferenceController) { 361 ((DeveloperOptionsPreferenceController) controller).onDeveloperOptionsEnabled(); 362 } 363 } 364 } 365 disableDeveloperOptions()366 private void disableDeveloperOptions() { 367 if (Utils.isMonkeyRunning()) { 368 return; 369 } 370 DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(getContext(), false); 371 final SystemPropPoker poker = SystemPropPoker.getInstance(); 372 poker.blockPokes(); 373 for (AbstractPreferenceController controller : mPreferenceControllers) { 374 if (controller instanceof DeveloperOptionsPreferenceController) { 375 ((DeveloperOptionsPreferenceController) controller) 376 .onDeveloperOptionsDisabled(); 377 } 378 } 379 poker.unblockPokes(); 380 poker.poke(); 381 } 382 onEnableDevelopmentOptionsConfirmed()383 void onEnableDevelopmentOptionsConfirmed() { 384 enableDeveloperOptions(); 385 } 386 onEnableDevelopmentOptionsRejected()387 void onEnableDevelopmentOptionsRejected() { 388 // Reset the toggle 389 mSwitchBar.setChecked(false); 390 } 391 onDisableDevelopmentOptionsConfirmed()392 void onDisableDevelopmentOptionsConfirmed() { 393 disableDeveloperOptions(); 394 } 395 onDisableDevelopmentOptionsRejected()396 void onDisableDevelopmentOptionsRejected() { 397 // Reset the toggle 398 mSwitchBar.setChecked(true); 399 } 400 buildPreferenceControllers(Context context, Activity activity, Lifecycle lifecycle, DevelopmentSettingsDashboardFragment fragment, BluetoothA2dpConfigStore bluetoothA2dpConfigStore)401 private static List<AbstractPreferenceController> buildPreferenceControllers(Context context, 402 Activity activity, Lifecycle lifecycle, DevelopmentSettingsDashboardFragment fragment, 403 BluetoothA2dpConfigStore bluetoothA2dpConfigStore) { 404 final List<AbstractPreferenceController> controllers = new ArrayList<>(); 405 controllers.add(new MemoryUsagePreferenceController(context)); 406 controllers.add(new SystemServerHeapDumpPreferenceController(context)); 407 controllers.add(new LocalBackupPasswordPreferenceController(context)); 408 controllers.add(new StayAwakePreferenceController(context, lifecycle)); 409 controllers.add(new HdcpCheckingPreferenceController(context)); 410 controllers.add(new BluetoothSnoopLogPreferenceController(context)); 411 controllers.add(new OemUnlockPreferenceController(context, activity, fragment)); 412 controllers.add(new FileEncryptionPreferenceController(context)); 413 controllers.add(new PictureColorModePreferenceController(context, lifecycle)); 414 controllers.add(new WebViewAppPreferenceController(context)); 415 controllers.add(new CoolColorTemperaturePreferenceController(context)); 416 controllers.add(new DisableAutomaticUpdatesPreferenceController(context)); 417 controllers.add(new AdbPreferenceController(context, fragment)); 418 controllers.add(new ClearAdbKeysPreferenceController(context, fragment)); 419 controllers.add(new LocalTerminalPreferenceController(context)); 420 controllers.add(new AutomaticSystemServerHeapDumpPreferenceController(context)); 421 controllers.add(new MockLocationAppPreferenceController(context, fragment)); 422 controllers.add(new DebugViewAttributesPreferenceController(context)); 423 controllers.add(new SelectDebugAppPreferenceController(context, fragment)); 424 controllers.add(new WaitForDebuggerPreferenceController(context)); 425 controllers.add(new EnableGpuDebugLayersPreferenceController(context)); 426 controllers.add(new VerifyAppsOverUsbPreferenceController(context)); 427 controllers.add(new ArtVerifierPreferenceController(context)); 428 controllers.add(new LogdSizePreferenceController(context)); 429 controllers.add(new LogPersistPreferenceController(context, fragment, lifecycle)); 430 controllers.add(new CameraLaserSensorPreferenceController(context)); 431 controllers.add(new WifiDisplayCertificationPreferenceController(context)); 432 controllers.add(new WifiVerboseLoggingPreferenceController(context)); 433 controllers.add(new MobileDataAlwaysOnPreferenceController(context)); 434 controllers.add(new TetheringHardwareAccelPreferenceController(context)); 435 controllers.add(new BluetoothDeviceNoNamePreferenceController(context)); 436 controllers.add(new BluetoothAbsoluteVolumePreferenceController(context)); 437 controllers.add(new BluetoothAvrcpVersionPreferenceController(context)); 438 controllers.add(new BluetoothA2dpHwOffloadPreferenceController(context, fragment)); 439 controllers.add(new BluetoothAudioCodecPreferenceController(context, lifecycle, 440 bluetoothA2dpConfigStore)); 441 controllers.add(new BluetoothAudioSampleRatePreferenceController(context, lifecycle, 442 bluetoothA2dpConfigStore)); 443 controllers.add(new BluetoothAudioBitsPerSamplePreferenceController(context, lifecycle, 444 bluetoothA2dpConfigStore)); 445 controllers.add(new BluetoothAudioChannelModePreferenceController(context, lifecycle, 446 bluetoothA2dpConfigStore)); 447 controllers.add(new BluetoothAudioQualityPreferenceController(context, lifecycle, 448 bluetoothA2dpConfigStore)); 449 controllers.add(new BluetoothMaxConnectedAudioDevicesPreferenceController(context)); 450 controllers.add(new ShowTapsPreferenceController(context)); 451 controllers.add(new PointerLocationPreferenceController(context)); 452 controllers.add(new ShowSurfaceUpdatesPreferenceController(context)); 453 controllers.add(new ShowLayoutBoundsPreferenceController(context)); 454 controllers.add(new RtlLayoutPreferenceController(context)); 455 controllers.add(new WindowAnimationScalePreferenceController(context)); 456 controllers.add(new EmulateDisplayCutoutPreferenceController(context)); 457 controllers.add(new TransitionAnimationScalePreferenceController(context)); 458 controllers.add(new AnimatorDurationScalePreferenceController(context)); 459 controllers.add(new SecondaryDisplayPreferenceController(context)); 460 controllers.add(new GpuViewUpdatesPreferenceController(context)); 461 controllers.add(new HardwareLayersUpdatesPreferenceController(context)); 462 controllers.add(new DebugGpuOverdrawPreferenceController(context)); 463 controllers.add(new DebugNonRectClipOperationsPreferenceController(context)); 464 controllers.add(new ForceDarkPreferenceController(context)); 465 controllers.add(new ForceMSAAPreferenceController(context)); 466 controllers.add(new HardwareOverlaysPreferenceController(context)); 467 controllers.add(new SimulateColorSpacePreferenceController(context)); 468 controllers.add(new UsbAudioRoutingPreferenceController(context)); 469 controllers.add(new StrictModePreferenceController(context)); 470 controllers.add(new ProfileGpuRenderingPreferenceController(context)); 471 controllers.add(new KeepActivitiesPreferenceController(context)); 472 controllers.add(new BackgroundProcessLimitPreferenceController(context)); 473 controllers.add(new ShowFirstCrashDialogPreferenceController(context)); 474 controllers.add(new AppsNotRespondingPreferenceController(context)); 475 controllers.add(new NotificationChannelWarningsPreferenceController(context)); 476 controllers.add(new AllowAppsOnExternalPreferenceController(context)); 477 controllers.add(new ResizableActivityPreferenceController(context)); 478 controllers.add(new FreeformWindowsPreferenceController(context)); 479 controllers.add(new DesktopModePreferenceController(context)); 480 controllers.add(new ShortcutManagerThrottlingPreferenceController(context)); 481 controllers.add(new EnableGnssRawMeasFullTrackingPreferenceController(context)); 482 controllers.add(new EnableUserSwitchMessageController(context)); 483 controllers.add(new DefaultLaunchPreferenceController(context, "running_apps")); 484 controllers.add(new DefaultLaunchPreferenceController(context, "demo_mode")); 485 controllers.add(new DefaultLaunchPreferenceController(context, "quick_settings_tiles")); 486 controllers.add(new DefaultLaunchPreferenceController(context, "feature_flags_dashboard")); 487 controllers.add( 488 new DefaultLaunchPreferenceController(context, "default_usb_configuration")); 489 controllers.add(new DefaultLaunchPreferenceController(context, "density")); 490 controllers.add(new DefaultLaunchPreferenceController(context, "background_check")); 491 controllers.add(new DefaultLaunchPreferenceController(context, "inactive_apps")); 492 controllers.add(new AutofillLoggingLevelPreferenceController(context, lifecycle)); 493 controllers.add(new AutofillResetOptionsPreferenceController(context)); 494 controllers.add(new OverlayCategoryPreferenceController(context, 495 "android.theme.customization.accent_color")); 496 controllers.add(new OverlayCategoryPreferenceController(context, 497 "android.theme.customization.font")); 498 controllers.add(new OverlayCategoryPreferenceController(context, 499 "android.theme.customization.adaptive_icon_shape")); 500 controllers.add(new TrustAgentsExtendUnlockPreferenceController(context)); 501 controllers.add(new TrustLostLocksScreenPreferenceController(context)); 502 return controllers; 503 } 504 505 @VisibleForTesting getDevelopmentOptionsController(Class<T> clazz)506 <T extends AbstractPreferenceController> T getDevelopmentOptionsController(Class<T> clazz) { 507 return use(clazz); 508 } 509 510 /** 511 * For Search. 512 */ 513 public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 514 new BaseSearchIndexProvider() { 515 516 @Override 517 protected boolean isPageSearchEnabled(Context context) { 518 return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context); 519 } 520 521 @Override 522 public List<SearchIndexableResource> getXmlResourcesToIndex( 523 Context context, boolean enabled) { 524 525 final SearchIndexableResource sir = new SearchIndexableResource(context); 526 sir.xmlResId = R.xml.development_settings; 527 return Arrays.asList(sir); 528 } 529 530 @Override 531 public List<AbstractPreferenceController> createPreferenceControllers(Context 532 context) { 533 return buildPreferenceControllers(context, null /* activity */, 534 null /* lifecycle */, null /* devOptionsDashboardFragment */, 535 null /* bluetoothA2dpConfigStore */); 536 } 537 }; 538 } 539