Loading src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java +19 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,25 @@ public class BluetoothA2dpHwOffloadPreferenceController extends DeveloperOptions } } @Override protected void onDeveloperOptionsSwitchDisabled() { super.onDeveloperOptionsSwitchDisabled(); final boolean offloadSupported = SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false); if (offloadSupported) { ((SwitchPreference) mPreference).setChecked(false); SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, "false"); } } public boolean isDefaultValue() { final boolean offloadSupported = SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false); final boolean offloadDisabled = SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false); return offloadSupported ? !offloadDisabled : true; } public void onA2dpHwDialogConfirmed() { final boolean offloadDisabled = SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false); Loading src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java +19 −1 Original line number Diff line number Diff line Loading @@ -221,7 +221,16 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra if (isChecked) { EnableDevelopmentSettingWarningDialog.show(this /* host */); } else { final BluetoothA2dpHwOffloadPreferenceController controller = getDevelopmentOptionsController( BluetoothA2dpHwOffloadPreferenceController.class); // If A2DP hardware offload isn't default value, we must reboot after disable // developer options. Show a dialog for the user to confirm. if (controller == null || controller.isDefaultValue()) { disableDeveloperOptions(); } else { DisableDevSettingsDialogFragment.show(this /* host */); } } } } Loading Loading @@ -380,6 +389,15 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra mSwitchBar.setChecked(false); } void onDisableDevelopmentOptionsConfirmed() { disableDeveloperOptions(); } void onDisableDevelopmentOptionsRejected() { // Reset the toggle mSwitchBar.setChecked(true); } private static List<AbstractPreferenceController> buildPreferenceControllers(Context context, Activity activity, Lifecycle lifecycle, DevelopmentSettingsDashboardFragment fragment, BluetoothA2dpConfigStore bluetoothA2dpConfigStore) { Loading src/com/android/settings/development/DisableDevSettingsDialogFragment.java 0 → 100644 +88 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.development; import android.app.Dialog; import android.content.DialogInterface; import android.os.Bundle; import android.os.PowerManager; import android.util.Log; import androidx.annotation.VisibleForTesting; import androidx.fragment.app.Fragment; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.FragmentManager; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; public class DisableDevSettingsDialogFragment extends InstrumentedDialogFragment implements DialogInterface.OnClickListener { public static final String TAG = "DisableDevSettingDlg"; @VisibleForTesting static DisableDevSettingsDialogFragment newInstance() { final DisableDevSettingsDialogFragment dialog = new DisableDevSettingsDialogFragment(); return dialog; } public static void show(DevelopmentSettingsDashboardFragment host) { final DisableDevSettingsDialogFragment dialog = new DisableDevSettingsDialogFragment(); dialog.setTargetFragment(host, 0 /* requestCode */); final FragmentManager manager = host.getActivity().getSupportFragmentManager(); dialog.show(manager, TAG); } @Override public int getMetricsCategory() { return MetricsProto.MetricsEvent.DIALOG_DISABLE_DEVELOPMENT_OPTIONS; } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { // Reuse the same text of disable_a2dp_hw_offload_dialog. // The text is generic enough to be used for turning off Dev options. return new AlertDialog.Builder(getActivity()) .setMessage(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message) .setTitle(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title) .setPositiveButton( R.string.bluetooth_disable_a2dp_hw_offload_dialog_confirm, this) .setNegativeButton( R.string.bluetooth_disable_a2dp_hw_offload_dialog_cancel, this) .create(); } @Override public void onClick(DialogInterface dialog, int which) { Fragment fragment = getTargetFragment(); if (!(fragment instanceof DevelopmentSettingsDashboardFragment)){ Log.e(TAG, "getTargetFragment return unexpected type"); } final DevelopmentSettingsDashboardFragment host = (DevelopmentSettingsDashboardFragment) fragment; if (which == DialogInterface.BUTTON_POSITIVE) { host.onDisableDevelopmentOptionsConfirmed(); PowerManager pm = getContext().getSystemService(PowerManager.class); pm.reboot(null); } else { host.onDisableDevelopmentOptionsRejected(); } } } tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java +43 −1 Original line number Diff line number Diff line Loading @@ -28,10 +28,15 @@ import android.content.Context; import android.provider.SearchIndexableResource; import android.provider.Settings; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.FragmentActivity; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.shadow.SettingsShadowResources; import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl; import com.android.settings.testutils.shadow.ShadowAlertDialogCompat; import com.android.settings.testutils.shadow.ShadowUserManager; import com.android.settings.widget.SwitchBar; import com.android.settings.widget.ToggleSwitch; Loading @@ -47,12 +52,14 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; import org.robolectric.shadows.androidx.fragment.FragmentController; import org.robolectric.util.ReflectionHelpers; import java.util.List; @RunWith(SettingsRobolectricTestRunner.class) @Config(shadows = ShadowUserManager.class) @Config(shadows = {ShadowUserManager.class, ShadowAlertDialogCompat.class, SettingsShadowResourcesImpl.class}) public class DevelopmentSettingsDashboardFragmentTest { private ToggleSwitch mSwitch; Loading Loading @@ -178,6 +185,29 @@ public class DevelopmentSettingsDashboardFragmentTest { assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isFalse(); } @Test @Config(shadows = ShadowDisableDevSettingsDialogFragment.class) public void onSwitchChanged_turnOff_andOffloadIsNotDefaultValue_shouldShowWarningDialog() { final BluetoothA2dpHwOffloadPreferenceController controller = mock(BluetoothA2dpHwOffloadPreferenceController.class); when(mDashboard.getContext()).thenReturn(mContext); when(mDashboard.getDevelopmentOptionsController( BluetoothA2dpHwOffloadPreferenceController.class)).thenReturn(controller); when(controller.isDefaultValue()).thenReturn(false); Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1); mDashboard.onSwitchChanged(mSwitch, false /* isChecked */); AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); assertThat(dialog).isNotNull(); ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog); assertThat(shadowDialog.getTitle()).isEqualTo( mContext.getString(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title)); assertThat(shadowDialog.getMessage()).isEqualTo( mContext.getString(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message)); } @Test public void onOemUnlockDialogConfirmed_shouldCallControllerOemConfirmed() { final OemUnlockPreferenceController controller = mock(OemUnlockPreferenceController.class); Loading Loading @@ -264,6 +294,18 @@ public class DevelopmentSettingsDashboardFragmentTest { } } @Implements(DisableDevSettingsDialogFragment.class) public static class ShadowDisableDevSettingsDialogFragment { @Implementation public static void show(DevelopmentSettingsDashboardFragment host) { DisableDevSettingsDialogFragment mFragment = spy(DisableDevSettingsDialogFragment.newInstance()); FragmentController.setupFragment(mFragment, FragmentActivity.class, 0 /* containerViewId */, null /* bundle */); } } @Implements(PictureColorModePreferenceController.class) public static class ShadowPictureColorModePreferenceController { @Implementation Loading Loading
src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java +19 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,25 @@ public class BluetoothA2dpHwOffloadPreferenceController extends DeveloperOptions } } @Override protected void onDeveloperOptionsSwitchDisabled() { super.onDeveloperOptionsSwitchDisabled(); final boolean offloadSupported = SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false); if (offloadSupported) { ((SwitchPreference) mPreference).setChecked(false); SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, "false"); } } public boolean isDefaultValue() { final boolean offloadSupported = SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false); final boolean offloadDisabled = SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false); return offloadSupported ? !offloadDisabled : true; } public void onA2dpHwDialogConfirmed() { final boolean offloadDisabled = SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false); Loading
src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java +19 −1 Original line number Diff line number Diff line Loading @@ -221,7 +221,16 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra if (isChecked) { EnableDevelopmentSettingWarningDialog.show(this /* host */); } else { final BluetoothA2dpHwOffloadPreferenceController controller = getDevelopmentOptionsController( BluetoothA2dpHwOffloadPreferenceController.class); // If A2DP hardware offload isn't default value, we must reboot after disable // developer options. Show a dialog for the user to confirm. if (controller == null || controller.isDefaultValue()) { disableDeveloperOptions(); } else { DisableDevSettingsDialogFragment.show(this /* host */); } } } } Loading Loading @@ -380,6 +389,15 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra mSwitchBar.setChecked(false); } void onDisableDevelopmentOptionsConfirmed() { disableDeveloperOptions(); } void onDisableDevelopmentOptionsRejected() { // Reset the toggle mSwitchBar.setChecked(true); } private static List<AbstractPreferenceController> buildPreferenceControllers(Context context, Activity activity, Lifecycle lifecycle, DevelopmentSettingsDashboardFragment fragment, BluetoothA2dpConfigStore bluetoothA2dpConfigStore) { Loading
src/com/android/settings/development/DisableDevSettingsDialogFragment.java 0 → 100644 +88 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.development; import android.app.Dialog; import android.content.DialogInterface; import android.os.Bundle; import android.os.PowerManager; import android.util.Log; import androidx.annotation.VisibleForTesting; import androidx.fragment.app.Fragment; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.FragmentManager; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; public class DisableDevSettingsDialogFragment extends InstrumentedDialogFragment implements DialogInterface.OnClickListener { public static final String TAG = "DisableDevSettingDlg"; @VisibleForTesting static DisableDevSettingsDialogFragment newInstance() { final DisableDevSettingsDialogFragment dialog = new DisableDevSettingsDialogFragment(); return dialog; } public static void show(DevelopmentSettingsDashboardFragment host) { final DisableDevSettingsDialogFragment dialog = new DisableDevSettingsDialogFragment(); dialog.setTargetFragment(host, 0 /* requestCode */); final FragmentManager manager = host.getActivity().getSupportFragmentManager(); dialog.show(manager, TAG); } @Override public int getMetricsCategory() { return MetricsProto.MetricsEvent.DIALOG_DISABLE_DEVELOPMENT_OPTIONS; } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { // Reuse the same text of disable_a2dp_hw_offload_dialog. // The text is generic enough to be used for turning off Dev options. return new AlertDialog.Builder(getActivity()) .setMessage(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message) .setTitle(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title) .setPositiveButton( R.string.bluetooth_disable_a2dp_hw_offload_dialog_confirm, this) .setNegativeButton( R.string.bluetooth_disable_a2dp_hw_offload_dialog_cancel, this) .create(); } @Override public void onClick(DialogInterface dialog, int which) { Fragment fragment = getTargetFragment(); if (!(fragment instanceof DevelopmentSettingsDashboardFragment)){ Log.e(TAG, "getTargetFragment return unexpected type"); } final DevelopmentSettingsDashboardFragment host = (DevelopmentSettingsDashboardFragment) fragment; if (which == DialogInterface.BUTTON_POSITIVE) { host.onDisableDevelopmentOptionsConfirmed(); PowerManager pm = getContext().getSystemService(PowerManager.class); pm.reboot(null); } else { host.onDisableDevelopmentOptionsRejected(); } } }
tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java +43 −1 Original line number Diff line number Diff line Loading @@ -28,10 +28,15 @@ import android.content.Context; import android.provider.SearchIndexableResource; import android.provider.Settings; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.FragmentActivity; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.shadow.SettingsShadowResources; import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl; import com.android.settings.testutils.shadow.ShadowAlertDialogCompat; import com.android.settings.testutils.shadow.ShadowUserManager; import com.android.settings.widget.SwitchBar; import com.android.settings.widget.ToggleSwitch; Loading @@ -47,12 +52,14 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; import org.robolectric.shadows.androidx.fragment.FragmentController; import org.robolectric.util.ReflectionHelpers; import java.util.List; @RunWith(SettingsRobolectricTestRunner.class) @Config(shadows = ShadowUserManager.class) @Config(shadows = {ShadowUserManager.class, ShadowAlertDialogCompat.class, SettingsShadowResourcesImpl.class}) public class DevelopmentSettingsDashboardFragmentTest { private ToggleSwitch mSwitch; Loading Loading @@ -178,6 +185,29 @@ public class DevelopmentSettingsDashboardFragmentTest { assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isFalse(); } @Test @Config(shadows = ShadowDisableDevSettingsDialogFragment.class) public void onSwitchChanged_turnOff_andOffloadIsNotDefaultValue_shouldShowWarningDialog() { final BluetoothA2dpHwOffloadPreferenceController controller = mock(BluetoothA2dpHwOffloadPreferenceController.class); when(mDashboard.getContext()).thenReturn(mContext); when(mDashboard.getDevelopmentOptionsController( BluetoothA2dpHwOffloadPreferenceController.class)).thenReturn(controller); when(controller.isDefaultValue()).thenReturn(false); Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1); mDashboard.onSwitchChanged(mSwitch, false /* isChecked */); AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); assertThat(dialog).isNotNull(); ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog); assertThat(shadowDialog.getTitle()).isEqualTo( mContext.getString(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title)); assertThat(shadowDialog.getMessage()).isEqualTo( mContext.getString(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message)); } @Test public void onOemUnlockDialogConfirmed_shouldCallControllerOemConfirmed() { final OemUnlockPreferenceController controller = mock(OemUnlockPreferenceController.class); Loading Loading @@ -264,6 +294,18 @@ public class DevelopmentSettingsDashboardFragmentTest { } } @Implements(DisableDevSettingsDialogFragment.class) public static class ShadowDisableDevSettingsDialogFragment { @Implementation public static void show(DevelopmentSettingsDashboardFragment host) { DisableDevSettingsDialogFragment mFragment = spy(DisableDevSettingsDialogFragment.newInstance()); FragmentController.setupFragment(mFragment, FragmentActivity.class, 0 /* containerViewId */, null /* bundle */); } } @Implements(PictureColorModePreferenceController.class) public static class ShadowPictureColorModePreferenceController { @Implementation Loading