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