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.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.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.search.BaseSearchIndexProvider;
48 import com.android.settings.search.Indexable;
49 import com.android.settings.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 master 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 BugReportPreferenceController(context));
407         controllers.add(new SystemServerHeapDumpPreferenceController(context));
408         controllers.add(new LocalBackupPasswordPreferenceController(context));
409         controllers.add(new StayAwakePreferenceController(context, lifecycle));
410         controllers.add(new HdcpCheckingPreferenceController(context));
411         controllers.add(new BluetoothSnoopLogPreferenceController(context));
412         controllers.add(new OemUnlockPreferenceController(context, activity, fragment));
413         controllers.add(new FileEncryptionPreferenceController(context));
414         controllers.add(new PictureColorModePreferenceController(context, lifecycle));
415         controllers.add(new WebViewAppPreferenceController(context));
416         controllers.add(new CoolColorTemperaturePreferenceController(context));
417         controllers.add(new DisableAutomaticUpdatesPreferenceController(context));
418         controllers.add(new AdbPreferenceController(context, fragment));
419         controllers.add(new ClearAdbKeysPreferenceController(context, fragment));
420         controllers.add(new WirelessDebuggingPreferenceController(context, lifecycle));
421         controllers.add(new LocalTerminalPreferenceController(context));
422         controllers.add(new BugReportInPowerPreferenceController(context));
423         controllers.add(new AutomaticSystemServerHeapDumpPreferenceController(context));
424         controllers.add(new MockLocationAppPreferenceController(context, fragment));
425         controllers.add(new DebugViewAttributesPreferenceController(context));
426         controllers.add(new SelectDebugAppPreferenceController(context, fragment));
427         controllers.add(new WaitForDebuggerPreferenceController(context));
428         controllers.add(new EnableGpuDebugLayersPreferenceController(context));
429         controllers.add(new VerifyAppsOverUsbPreferenceController(context));
430         controllers.add(new ArtVerifierPreferenceController(context));
431         controllers.add(new LogdSizePreferenceController(context));
432         controllers.add(new LogPersistPreferenceController(context, fragment, lifecycle));
433         controllers.add(new CameraLaserSensorPreferenceController(context));
434         controllers.add(new WifiDisplayCertificationPreferenceController(context));
435         controllers.add(new WifiVerboseLoggingPreferenceController(context));
436         controllers.add(new WifiScanThrottlingPreferenceController(context));
437         controllers.add(new MobileDataAlwaysOnPreferenceController(context));
438         controllers.add(new TetheringHardwareAccelPreferenceController(context));
439         controllers.add(new BluetoothDeviceNoNamePreferenceController(context));
440         controllers.add(new BluetoothAbsoluteVolumePreferenceController(context));
441         controllers.add(new BluetoothAvrcpVersionPreferenceController(context));
442         controllers.add(new BluetoothMapVersionPreferenceController(context));
443         controllers.add(new BluetoothA2dpHwOffloadPreferenceController(context, fragment));
444         controllers.add(new BluetoothAudioCodecPreferenceController(context, lifecycle,
445                 bluetoothA2dpConfigStore));
446         controllers.add(new BluetoothAudioSampleRatePreferenceController(context, lifecycle,
447                 bluetoothA2dpConfigStore));
448         controllers.add(new BluetoothAudioBitsPerSamplePreferenceController(context, lifecycle,
449                 bluetoothA2dpConfigStore));
450         controllers.add(new BluetoothAudioChannelModePreferenceController(context, lifecycle,
451                 bluetoothA2dpConfigStore));
452         controllers.add(new BluetoothAudioQualityPreferenceController(context, lifecycle,
453                 bluetoothA2dpConfigStore));
454         controllers.add(new BluetoothMaxConnectedAudioDevicesPreferenceController(context));
455         controllers.add(new ShowTapsPreferenceController(context));
456         controllers.add(new PointerLocationPreferenceController(context));
457         controllers.add(new ShowSurfaceUpdatesPreferenceController(context));
458         controllers.add(new ShowLayoutBoundsPreferenceController(context));
459         controllers.add(new RtlLayoutPreferenceController(context));
460         controllers.add(new WindowAnimationScalePreferenceController(context));
461         controllers.add(new EmulateDisplayCutoutPreferenceController(context));
462         controllers.add(new TransitionAnimationScalePreferenceController(context));
463         controllers.add(new AnimatorDurationScalePreferenceController(context));
464         controllers.add(new SecondaryDisplayPreferenceController(context));
465         controllers.add(new GpuViewUpdatesPreferenceController(context));
466         controllers.add(new HardwareLayersUpdatesPreferenceController(context));
467         controllers.add(new DebugGpuOverdrawPreferenceController(context));
468         controllers.add(new DebugNonRectClipOperationsPreferenceController(context));
469         controllers.add(new ForceDarkPreferenceController(context));
470         controllers.add(new ForceMSAAPreferenceController(context));
471         controllers.add(new HardwareOverlaysPreferenceController(context));
472         controllers.add(new SimulateColorSpacePreferenceController(context));
473         controllers.add(new UsbAudioRoutingPreferenceController(context));
474         controllers.add(new StrictModePreferenceController(context));
475         controllers.add(new ProfileGpuRenderingPreferenceController(context));
476         controllers.add(new KeepActivitiesPreferenceController(context));
477         controllers.add(new BackgroundProcessLimitPreferenceController(context));
478         controllers.add(new ShowFirstCrashDialogPreferenceController(context));
479         controllers.add(new AppsNotRespondingPreferenceController(context));
480         controllers.add(new NotificationChannelWarningsPreferenceController(context));
481         controllers.add(new AllowAppsOnExternalPreferenceController(context));
482         controllers.add(new ResizableActivityPreferenceController(context));
483         controllers.add(new FreeformWindowsPreferenceController(context));
484         controllers.add(new DesktopModePreferenceController(context));
485         controllers.add(new ShortcutManagerThrottlingPreferenceController(context));
486         controllers.add(new BubbleGlobalPreferenceController(context));
487         controllers.add(new EnableGnssRawMeasFullTrackingPreferenceController(context));
488         controllers.add(new DefaultLaunchPreferenceController(context, "running_apps"));
489         controllers.add(new DefaultLaunchPreferenceController(context, "demo_mode"));
490         controllers.add(new DefaultLaunchPreferenceController(context, "quick_settings_tiles"));
491         controllers.add(new DefaultLaunchPreferenceController(context, "feature_flags_dashboard"));
492         controllers.add(
493             new DefaultLaunchPreferenceController(context, "default_usb_configuration"));
494         controllers.add(new DefaultLaunchPreferenceController(context, "density"));
495         controllers.add(new DefaultLaunchPreferenceController(context, "background_check"));
496         controllers.add(new DefaultLaunchPreferenceController(context, "inactive_apps"));
497         controllers.add(new AutofillLoggingLevelPreferenceController(context, lifecycle));
498         controllers.add(new AutofillResetOptionsPreferenceController(context));
499         controllers.add(new TrustAgentsExtendUnlockPreferenceController(context));
500         controllers.add(new TrustLostLocksScreenPreferenceController(context));
501         return controllers;
502     }
503 
504     @VisibleForTesting
getDevelopmentOptionsController(Class<T> clazz)505     <T extends AbstractPreferenceController> T getDevelopmentOptionsController(Class<T> clazz) {
506         return use(clazz);
507     }
508 
509     /**
510      * For Search.
511      */
512     public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
513             new BaseSearchIndexProvider() {
514 
515                 @Override
516                 protected boolean isPageSearchEnabled(Context context) {
517                     return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context);
518                 }
519 
520                 @Override
521                 public List<SearchIndexableResource> getXmlResourcesToIndex(
522                         Context context, boolean enabled) {
523 
524                     final SearchIndexableResource sir = new SearchIndexableResource(context);
525                     sir.xmlResId = R.xml.development_settings;
526                     return Arrays.asList(sir);
527                 }
528 
529                 @Override
530                 public List<AbstractPreferenceController> createPreferenceControllers(Context
531                         context) {
532                     return buildPreferenceControllers(context, null /* activity */,
533                             null /* lifecycle */, null /* devOptionsDashboardFragment */,
534                             null /* bluetoothA2dpConfigStore */);
535                 }
536             };
537 }
538