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