diff --git a/src/com/android/settings/development/DevelopmentSettings.java b/src/com/android/settings/development/DevelopmentSettings.java index 1a3c3adab36..0af3dd4cfcc 100644 --- a/src/com/android/settings/development/DevelopmentSettings.java +++ b/src/com/android/settings/development/DevelopmentSettings.java @@ -96,6 +96,7 @@ import com.android.settings.widget.SwitchBar; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import com.android.settingslib.RestrictedSwitchPreference; +import com.android.settingslib.core.ConfirmationDialogController; import com.android.settingslib.development.AbstractEnableAdbPreferenceController; import com.android.settingslib.development.DevelopmentSettingsEnabler; import com.android.settingslib.development.SystemPropPoker; @@ -211,6 +212,10 @@ public class DevelopmentSettings extends RestrictedSettingsFragment private static final int[] MOCK_LOCATION_APP_OPS = new int[]{AppOpsManager.OP_MOCK_LOCATION}; + private static final String STATE_SHOWING_DIALOG_KEY = "showing_dialog_key"; + + private String mPendingDialogKey; + private IWindowManager mWindowManager; private IBackupManager mBackupManager; private IWebViewUpdateService mWebViewUpdateService; @@ -342,6 +347,11 @@ public class DevelopmentSettings extends RestrictedSettingsFragment public void onCreate(Bundle icicle) { super.onCreate(icicle); + if (icicle != null) { + // Don't show this in onCreate since we might be on the back stack + mPendingDialogKey = icicle.getString(STATE_SHOWING_DIALOG_KEY); + } + mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); mBackupManager = IBackupManager.Stub.asInterface( ServiceManager.getService(Context.BACKUP_SERVICE)); @@ -654,6 +664,11 @@ public class DevelopmentSettings extends RestrictedSettingsFragment mColorModePreference.startListening(); mColorModePreference.updateCurrentAndSupported(); } + + if (mPendingDialogKey != null) { + recreateDialogForKey(mPendingDialogKey); + mPendingDialogKey = null; + } } @Override @@ -664,6 +679,12 @@ public class DevelopmentSettings extends RestrictedSettingsFragment } } + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(STATE_SHOWING_DIALOG_KEY, getKeyForShowingDialog()); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -2334,8 +2355,44 @@ public class DevelopmentSettings extends RestrictedSettingsFragment return false; } + /** + * Iterates through preference controllers that show confirmation dialogs and returns the + * preference key for the first currently showing dialog. Ideally there should only ever be one. + * @return Preference key, or null if no dialog is showing + */ + private String getKeyForShowingDialog() { + // TODO: iterate through a fragment-wide list of PreferenceControllers and just pick out the + // ConfirmationDialogController objects + final List dialogControllers = new ArrayList<>(2); + dialogControllers.add(mEnableAdbController); + dialogControllers.add(mLogpersistController); + for (ConfirmationDialogController dialogController : dialogControllers) { + if (dialogController.isConfirmationDialogShowing()) { + return dialogController.getPreferenceKey(); + } + } + return null; + } + + /** + * Re-show the dialog we lost previously + * @param preferenceKey Key for the preference the dialog is for + */ + private void recreateDialogForKey(String preferenceKey) { + // TODO: iterate through a fragment-wide list of PreferenceControllers and just pick out the + // ConfirmationDialogController objects + final List dialogControllers = new ArrayList<>(2); + dialogControllers.add(mEnableAdbController); + dialogControllers.add(mLogpersistController); + for (ConfirmationDialogController dialogController : dialogControllers) { + if (TextUtils.equals(preferenceKey, dialogController.getPreferenceKey())) { + dialogController.showConfirmationDialog(findPreference(preferenceKey)); + } + } + } + private void dismissDialogs() { - mEnableAdbController.dismissDialogs(); + mEnableAdbController.dismissConfirmationDialog(); if (mAdbKeysDialog != null) { mAdbKeysDialog.dismiss(); mAdbKeysDialog = null; @@ -2344,7 +2401,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment mEnableDialog.dismiss(); mEnableDialog = null; } - mLogpersistController.dismissDialogs(); + mLogpersistController.dismissConfirmationDialog(); } public void onClick(DialogInterface dialog, int which) { diff --git a/src/com/android/settings/development/EnableAdbPreferenceController.java b/src/com/android/settings/development/EnableAdbPreferenceController.java index a159f0a8a2f..bd6267badf1 100644 --- a/src/com/android/settings/development/EnableAdbPreferenceController.java +++ b/src/com/android/settings/development/EnableAdbPreferenceController.java @@ -19,8 +19,9 @@ package com.android.settings.development; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; -import android.provider.Settings; -import android.support.v14.preference.SwitchPreference; +import android.support.annotation.Nullable; +import android.support.v7.preference.Preference; +import android.support.v7.preference.TwoStatePreference; import com.android.settings.R; import com.android.settings.core.PreferenceControllerMixin; @@ -37,33 +38,43 @@ public class EnableAdbPreferenceController extends AbstractEnableAdbPreferenceCo } @Override - public void showConfirmationDialog(SwitchPreference preference) { + public void showConfirmationDialog(@Nullable Preference preference) { + if (preference == null) { + return; + } + final TwoStatePreference twoStatePreference = (TwoStatePreference) preference; mDialogClicked = false; - dismissDialogs(); + dismissConfirmationDialog(); mAdbDialog = new AlertDialog.Builder(mContext).setMessage( mContext.getString(R.string.adb_warning_message)) .setTitle(R.string.adb_warning_title) .setPositiveButton(android.R.string.yes, (dialog, which) -> { mDialogClicked = true; writeAdbSetting(true); + twoStatePreference.setChecked(true); }) - .setNegativeButton(android.R.string.no, (dialog, which) -> { - preference.setChecked(false); - }) + .setNegativeButton(android.R.string.no, + (dialog, which) -> twoStatePreference.setChecked(false)) .show(); mAdbDialog.setOnDismissListener(dialog -> { // Assuming that onClick gets called first if (!mDialogClicked) { - preference.setChecked(false); + twoStatePreference.setChecked(false); } mAdbDialog = null; }); } - public void dismissDialogs() { + @Override + public void dismissConfirmationDialog() { if (mAdbDialog != null) { mAdbDialog.dismiss(); mAdbDialog = null; } } + + @Override + public boolean isConfirmationDialogShowing() { + return mAdbDialog != null; + } } diff --git a/src/com/android/settings/development/LogpersistPreferenceController.java b/src/com/android/settings/development/LogpersistPreferenceController.java index 5baac3d186b..a1ca186cca8 100644 --- a/src/com/android/settings/development/LogpersistPreferenceController.java +++ b/src/com/android/settings/development/LogpersistPreferenceController.java @@ -19,8 +19,10 @@ package com.android.settings.development; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; -import android.support.v7.preference.ListPreference; +import android.support.annotation.Nullable; +import android.support.v7.preference.Preference; +import com.android.settings.R; import com.android.settings.core.PreferenceControllerMixin; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.development.AbstractLogpersistPreferenceController; @@ -35,23 +37,30 @@ public class LogpersistPreferenceController extends AbstractLogpersistPreference } @Override - public void showConfirmationDialog(ListPreference preference) { - if (mLogpersistClearDialog != null) dismissDialogs(); - mLogpersistClearDialog = new AlertDialog.Builder(mContext).setMessage( - mContext.getString( - com.android.settingslib.R.string.dev_logpersist_clear_warning_message)) - .setTitle(com.android.settingslib.R.string.dev_logpersist_clear_warning_title) + public void showConfirmationDialog(@Nullable Preference preference) { + if (preference == null) { + return; + } + if (mLogpersistClearDialog != null) dismissConfirmationDialog(); + mLogpersistClearDialog = new AlertDialog.Builder(mContext) + .setMessage(R.string.dev_logpersist_clear_warning_message) + .setTitle(R.string.dev_logpersist_clear_warning_title) .setPositiveButton(android.R.string.yes, (dialog, which) -> setLogpersistOff(true)) .setNegativeButton(android.R.string.no, (dialog, which) -> updateLogpersistValues()) .show(); mLogpersistClearDialog.setOnDismissListener(dialog -> mLogpersistClearDialog = null); - } - public void dismissDialogs() { + @Override + public void dismissConfirmationDialog() { if (mLogpersistClearDialog != null) { mLogpersistClearDialog.dismiss(); mLogpersistClearDialog = null; } } + + @Override + public boolean isConfirmationDialogShowing() { + return mLogpersistClearDialog != null; + } } diff --git a/tests/robotests/src/com/android/settings/development/EnableAdbPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/EnableAdbPreferenceControllerTest.java new file mode 100644 index 00000000000..6dcfbf2bc3d --- /dev/null +++ b/tests/robotests/src/com/android/settings/development/EnableAdbPreferenceControllerTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2017 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 static com.google.common.truth.Truth.assertThat; + +import android.support.v14.preference.SwitchPreference; + +import com.android.settings.TestConfig; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class EnableAdbPreferenceControllerTest { + + @Mock + private SwitchPreference mSwitchPreference; + + private EnableAdbPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mController + = new EnableAdbPreferenceController(RuntimeEnvironment.application); + } + + @Test + public void testIsConfirmationDialogShowing() { + assertThat(mController.isConfirmationDialogShowing()).isFalse(); + mController.showConfirmationDialog(mSwitchPreference); + assertThat(mController.isConfirmationDialogShowing()).isTrue(); + mController.dismissConfirmationDialog(); + assertThat(mController.isConfirmationDialogShowing()).isFalse(); + } +} diff --git a/tests/robotests/src/com/android/settings/development/LogpersistPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/LogpersistPreferenceControllerTest.java new file mode 100644 index 00000000000..450f29da696 --- /dev/null +++ b/tests/robotests/src/com/android/settings/development/LogpersistPreferenceControllerTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2017 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 static com.google.common.truth.Truth.assertThat; + +import android.support.v7.preference.ListPreference; + +import com.android.settings.TestConfig; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settingslib.core.lifecycle.Lifecycle; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class LogpersistPreferenceControllerTest { + + private Lifecycle mLifecycle = new Lifecycle(); + + @Mock + private ListPreference mListPreference; + + private LogpersistPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mController + = new LogpersistPreferenceController(RuntimeEnvironment.application, mLifecycle); + } + + @Test + public void testIsConfirmationDialogShowing() { + assertThat(mController.isConfirmationDialogShowing()).isFalse(); + mController.showConfirmationDialog(mListPreference); + assertThat(mController.isConfirmationDialogShowing()).isTrue(); + mController.dismissConfirmationDialog(); + assertThat(mController.isConfirmationDialogShowing()).isFalse(); + } +}