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