OSDN Git Service

Add base preference for new Bluetooth developer option
authortimhypeng <timhypeng@google.com>
Tue, 26 Nov 2019 05:20:47 +0000 (13:20 +0800)
committertimhypeng <timhypeng@google.com>
Thu, 28 Nov 2019 09:09:36 +0000 (17:09 +0800)
Bug: 142227996
Test: manual
Change-Id: I23c11072a326473bdc7ce169c6c2fb970a8f828d

src/com/android/settings/development/bluetooth/BaseBluetoothDialogPreference.java [new file with mode: 0644]
tests/robotests/src/com/android/settings/development/bluetooth/BaseBluetoothDialogPreferenceTest.java [new file with mode: 0644]

diff --git a/src/com/android/settings/development/bluetooth/BaseBluetoothDialogPreference.java b/src/com/android/settings/development/bluetooth/BaseBluetoothDialogPreference.java
new file mode 100644 (file)
index 0000000..08a450b
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2019 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.bluetooth;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.TextView;
+
+import com.android.settings.R;
+import com.android.settingslib.CustomDialogPreferenceCompat;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Abstract class for Bluetooth A2DP config preference in developer option.
+ */
+public abstract class BaseBluetoothDialogPreference extends CustomDialogPreferenceCompat implements
+        RadioGroup.OnCheckedChangeListener{
+    private static final String TAG = "BaseBluetoothDlgPref";
+
+    protected List<Integer> mRadioButtonIds = new ArrayList<>();
+    protected List<String> mRadioButtonStrings = new ArrayList<>();
+    protected List<String> mSummaryStrings = new ArrayList<>();
+
+    private Callback mCallback;
+
+    public BaseBluetoothDialogPreference(Context context) {
+        super(context);
+    }
+
+    public BaseBluetoothDialogPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public BaseBluetoothDialogPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public BaseBluetoothDialogPreference(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    protected void onBindDialogView(View view) {
+        super.onBindDialogView(view);
+        if (mCallback == null) {
+            Log.e(TAG, "Unable to show dialog by the callback is null");
+            return;
+        }
+        if (mRadioButtonStrings.size() != mRadioButtonIds.size()) {
+            Log.e(TAG, "Unable to show dialog by the view and string size are not matched");
+            return;
+        }
+        final int currentIndex = mCallback.getCurrentConfigIndex();
+        if (currentIndex < 0 || currentIndex >= mRadioButtonIds.size()) {
+            Log.e(TAG, "Unable to show dialog by the incorrect index: " + currentIndex);
+            return;
+        }
+        // Initial radio button group
+        final RadioGroup radioGroup = view.findViewById(getRadioButtonGroupId());
+        if (radioGroup == null) {
+            Log.e(TAG, "Unable to show dialog by no radio button group: "
+                    + getRadioButtonGroupId());
+            return;
+        }
+        radioGroup.check(mRadioButtonIds.get(currentIndex));
+        radioGroup.setOnCheckedChangeListener(this);
+        // Initial radio button
+        final List<Integer> selectableIndex = mCallback.getSelectableIndex();
+        RadioButton radioButton;
+        for (int i = 0; i < mRadioButtonStrings.size(); i++) {
+            radioButton = view.findViewById(mRadioButtonIds.get(i));
+            if (radioButton == null) {
+                Log.e(TAG, "Unable to show dialog by no radio button:" + mRadioButtonIds.get(i));
+                return;
+            }
+            radioButton.setText(mRadioButtonStrings.get(i));
+            radioButton.setEnabled(selectableIndex.contains(i));
+        }
+        // View will be invisible when all options are enabled.
+        if (selectableIndex.size() == mRadioButtonIds.size()) {
+            final TextView helpTextView = view.findViewById(R.id.bluetooth_audio_codec_help_info);
+            helpTextView.setVisibility(View.GONE);
+        }
+    }
+
+    @Override
+    public void onCheckedChanged(RadioGroup group, int checkedId) {
+        if (mCallback == null) {
+            Log.e(TAG, "Callback is null");
+            return;
+        }
+        mCallback.onIndexUpdated(mRadioButtonIds.indexOf(checkedId));
+        getDialog().dismiss();
+    }
+
+    /**
+     * Method to set callback.
+     */
+    public void setCallback(Callback callback) {
+        mCallback = callback;
+    }
+
+    /**
+     * Method to get summary strings by index.
+     */
+    protected String generateSummary(int index) {
+        if (index > mSummaryStrings.size()) {
+            Log.e(TAG, "Unable to get summary of " + index + ". Size is " + mSummaryStrings.size());
+            return null;
+        }
+        return index == getDefaultIndex() ? mSummaryStrings.get(getDefaultIndex()) :
+                String.format(getContext().getResources().getString(
+                        R.string.bluetooth_select_a2dp_codec_streaming_label),
+                        mSummaryStrings.get(index));
+    }
+
+    /**
+     * Method to get default index.
+     */
+    protected int getDefaultIndex() {
+        return 0;
+    }
+
+    /**
+     * Method to get radio button group id.
+     */
+    protected abstract int getRadioButtonGroupId();
+
+    /**
+     * Callback interface for this class to manipulate data from controller.
+     */
+    public interface Callback {
+        /**
+         * Method to get current Bluetooth A2DP config index.
+         */
+        int getCurrentConfigIndex();
+        /**
+         * Method to get selectable config index which means supported by phone and device.
+         *
+         * @return the available {@link List} of the Bluetooth A2DP config.
+         */
+        List<Integer> getSelectableIndex();
+        /**
+         * Method to notify controller when user changes config.
+         *
+         * @param index for the selected index.
+         */
+        void onIndexUpdated(int index);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BaseBluetoothDialogPreferenceTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BaseBluetoothDialogPreferenceTest.java
new file mode 100644 (file)
index 0000000..8a34930
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2019 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.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.view.View;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.TextView;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public class BaseBluetoothDialogPreferenceTest {
+
+    private static final int ID1 = 99;
+    private static final int ID2 = 100;
+    private static final int RADIOGROUP_ID = 101;
+    private static final int TEXT_VIEW_ID = R.id.bluetooth_audio_codec_help_info;
+    private static final String BUTTON1 = "Test button1";
+    private static final String BUTTON2 = "Test button2";
+    private static final String SUMMARY1 = "Test summary1";
+    private static final String SUMMARY2 = "Test summary2";
+
+    @Mock
+    private BaseBluetoothDialogPreference.Callback mCallback;
+    @Mock
+    private Dialog mDialog;
+    @Mock
+    private View mView;
+
+    private BaseBluetoothDialogPreference mPreference;
+    private Context mContext;
+    private RadioButton mRadioButton1;
+    private RadioButton mRadioButton2;
+    private RadioGroup mRadioGroup;
+    private TextView mTextView;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mPreference = spy(new BaseBluetoothDialogPreferenceImpl(mContext));
+        mRadioButton1 = new RadioButton(mContext);
+        mRadioButton1.setId(ID1);
+        mRadioButton2 = new RadioButton(mContext);
+        mRadioButton2.setId(ID2);
+        mRadioGroup = new RadioGroup(mContext);
+        mRadioGroup.addView(mRadioButton1);
+        mRadioGroup.addView(mRadioButton2);
+        mTextView = new TextView(mContext);
+        mPreference.mRadioButtonIds.add(ID1);
+        mPreference.mRadioButtonIds.add(ID2);
+        mPreference.mRadioButtonStrings.add(BUTTON1);
+        mPreference.mRadioButtonStrings.add(BUTTON2);
+        mPreference.mSummaryStrings.add(SUMMARY1);
+        mPreference.mSummaryStrings.add(SUMMARY2);
+        mPreference.setCallback(mCallback);
+        when(mView.findViewById(mPreference.getRadioButtonGroupId())).thenReturn(mRadioGroup);
+    }
+
+    @Test
+    public void onBindDialogView_checkRadioButtonsSelection() {
+        when(mCallback.getCurrentConfigIndex()).thenReturn(1);
+
+        assertThat(mRadioGroup.getCheckedRadioButtonId()).isNotEqualTo(ID2);
+        mPreference.onBindDialogView(mView);
+
+        assertThat(mRadioGroup.getCheckedRadioButtonId()).isEqualTo(ID2);
+    }
+
+    @Test
+    public void onBindDialogView_checkRadioButtonsText() {
+        when(mView.findViewById(ID1)).thenReturn(mRadioButton1);
+        when(mView.findViewById(ID2)).thenReturn(mRadioButton2);
+
+        assertThat(mRadioButton1.getText()).isNotEqualTo(BUTTON1);
+        assertThat(mRadioButton2.getText()).isNotEqualTo(BUTTON2);
+        mPreference.onBindDialogView(mView);
+
+        assertThat(mRadioButton1.getText()).isEqualTo(BUTTON1);
+        assertThat(mRadioButton2.getText()).isEqualTo(BUTTON2);
+    }
+
+    @Test
+    public void onBindDialogView_checkRadioButtonsState() {
+        when(mView.findViewById(ID1)).thenReturn(mRadioButton1);
+        when(mView.findViewById(ID2)).thenReturn(mRadioButton2);
+        List<Integer> indexes = new ArrayList<>();
+        indexes.add(0);
+        when(mCallback.getSelectableIndex()).thenReturn(indexes);
+
+        assertThat(mRadioButton1.isEnabled()).isTrue();
+        assertThat(mRadioButton2.isEnabled()).isTrue();
+        mPreference.onBindDialogView(mView);
+
+        assertThat(mRadioButton1.isEnabled()).isTrue();
+        assertThat(mRadioButton2.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void onBindDialogView_allButtonsEnabled_hideHelpText() {
+        when(mView.findViewById(ID1)).thenReturn(mRadioButton1);
+        when(mView.findViewById(ID2)).thenReturn(mRadioButton2);
+        when(mView.findViewById(TEXT_VIEW_ID)).thenReturn(mTextView);
+        List<Integer> indexes = new ArrayList<>();
+        indexes.add(0);
+        indexes.add(1);
+        when(mCallback.getSelectableIndex()).thenReturn(indexes);
+
+        assertThat(mTextView.getVisibility()).isEqualTo(View.VISIBLE);
+        mPreference.onBindDialogView(mView);
+        assertThat(mTextView.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void onBindDialogView_buttonDisabled_showHelpText() {
+        when(mView.findViewById(ID1)).thenReturn(mRadioButton1);
+        when(mView.findViewById(ID2)).thenReturn(mRadioButton2);
+        when(mView.findViewById(TEXT_VIEW_ID)).thenReturn(mTextView);
+        List<Integer> indexes = new ArrayList<>();
+        indexes.add(0);
+        when(mCallback.getSelectableIndex()).thenReturn(indexes);
+
+        mPreference.onBindDialogView(mView);
+        assertThat(mTextView.getVisibility()).isEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void onCheckedChanged_verifyIndex() {
+        when(mPreference.getDialog()).thenReturn(mDialog);
+
+        mPreference.onCheckedChanged(mRadioGroup, ID2);
+        verify(mCallback).onIndexUpdated(1);
+    }
+
+    @Test
+    public void generateSummary_checkString() {
+        final String summary = String.format(mContext.getResources().getString(
+                R.string.bluetooth_select_a2dp_codec_streaming_label), SUMMARY2);
+
+        assertThat(mPreference.generateSummary(1)).isEqualTo(summary);
+    }
+
+
+    private static class BaseBluetoothDialogPreferenceImpl extends BaseBluetoothDialogPreference {
+
+        private BaseBluetoothDialogPreferenceImpl(Context context) {
+            super(context);
+        }
+
+        @Override
+        protected int getRadioButtonGroupId() {
+            return RADIOGROUP_ID;
+        }
+    }
+}