Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 342bbad5 authored by Edgar Wang's avatar Edgar Wang Committed by Android (Google) Code Review
Browse files

Merge "Move UpdatableListPreferenceDialogFragment to Settings"

parents c9845835 82f785b0
Loading
Loading
Loading
Loading
+0 −174
Original line number Diff line number Diff line
/*
 * 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.settingslib.widget;

import android.content.res.TypedArray;
import android.os.Bundle;
import android.widget.ArrayAdapter;

import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog.Builder;
import androidx.preference.ListPreference;
import androidx.preference.PreferenceDialogFragmentCompat;

import com.android.settingslib.core.instrumentation.Instrumentable;

import java.util.ArrayList;

/**
 * {@link PreferenceDialogFragmentCompat} that updates the available options
 * when {@code onListPreferenceUpdated} is called."
 */
public class UpdatableListPreferenceDialogFragment extends PreferenceDialogFragmentCompat implements
        Instrumentable {

    private static final String SAVE_STATE_INDEX = "UpdatableListPreferenceDialogFragment.index";
    private static final String SAVE_STATE_ENTRIES =
            "UpdatableListPreferenceDialogFragment.entries";
    private static final String SAVE_STATE_ENTRY_VALUES =
            "UpdatableListPreferenceDialogFragment.entryValues";
    private static final String METRICS_CATEGORY_KEY = "metrics_category_key";
    private ArrayAdapter mAdapter;
    private int mClickedDialogEntryIndex;
    private ArrayList<CharSequence> mEntries;
    private CharSequence[] mEntryValues;
    private int mMetricsCategory = METRICS_CATEGORY_UNKNOWN;

    /**
     * Creates a new instance of {@link UpdatableListPreferenceDialogFragment}.
     */
    public static UpdatableListPreferenceDialogFragment newInstance(
            String key, int metricsCategory) {
        UpdatableListPreferenceDialogFragment fragment =
                new UpdatableListPreferenceDialogFragment();
        Bundle args = new Bundle(1);
        args.putString(ARG_KEY, key);
        args.putInt(METRICS_CATEGORY_KEY, metricsCategory);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final Bundle bundle = getArguments();
        mMetricsCategory =
                bundle.getInt(METRICS_CATEGORY_KEY, METRICS_CATEGORY_UNKNOWN);
        if (savedInstanceState == null) {
            mEntries = new ArrayList<>();
            setPreferenceData(getListPreference());
        } else {
            mClickedDialogEntryIndex = savedInstanceState.getInt(SAVE_STATE_INDEX, 0);
            mEntries = savedInstanceState.getCharSequenceArrayList(SAVE_STATE_ENTRIES);
            mEntryValues =
                    savedInstanceState.getCharSequenceArray(SAVE_STATE_ENTRY_VALUES);
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(SAVE_STATE_INDEX, mClickedDialogEntryIndex);
        outState.putCharSequenceArrayList(SAVE_STATE_ENTRIES, mEntries);
        outState.putCharSequenceArray(SAVE_STATE_ENTRY_VALUES, mEntryValues);
    }

    @Override
    public void onDialogClosed(boolean positiveResult) {
        if (positiveResult && mClickedDialogEntryIndex >= 0) {
            final ListPreference preference = getListPreference();
            final String value = mEntryValues[mClickedDialogEntryIndex].toString();
            if (preference.callChangeListener(value)) {
                preference.setValue(value);
            }
        }
    }

    @VisibleForTesting
    void setAdapter(ArrayAdapter adapter) {
        mAdapter = adapter;
    }

    @VisibleForTesting
    void setEntries(ArrayList<CharSequence> entries) {
        mEntries = entries;
    }

    @VisibleForTesting
    ArrayAdapter getAdapter() {
        return mAdapter;
    }

    @VisibleForTesting
    void setMetricsCategory(Bundle bundle) {
        mMetricsCategory =
                bundle.getInt(METRICS_CATEGORY_KEY, METRICS_CATEGORY_UNKNOWN);
    }

    @Override
    protected void onPrepareDialogBuilder(Builder builder) {
        super.onPrepareDialogBuilder(builder);
        final TypedArray a = getContext().obtainStyledAttributes(
                null,
                com.android.internal.R.styleable.AlertDialog,
                com.android.internal.R.attr.alertDialogStyle, 0);

        mAdapter = new ArrayAdapter<>(
                getContext(),
                a.getResourceId(
                        com.android.internal.R.styleable.AlertDialog_singleChoiceItemLayout,
                        com.android.internal.R.layout.select_dialog_singlechoice),
                mEntries);

        builder.setSingleChoiceItems(mAdapter, mClickedDialogEntryIndex,
                (dialog, which) -> {
                    mClickedDialogEntryIndex = which;
                    onClick(dialog, -1);
                    dialog.dismiss();
                });
        builder.setPositiveButton(null, null);
        a.recycle();
    }

    @Override
    public int getMetricsCategory() {
        return mMetricsCategory;
    }

    @VisibleForTesting
    ListPreference getListPreference() {
        return (ListPreference) getPreference();
    }

    private void setPreferenceData(ListPreference preference) {
        mEntries.clear();
        mClickedDialogEntryIndex = preference.findIndexOfValue(preference.getValue());
        for (CharSequence entry : preference.getEntries()) {
            mEntries.add(entry);
        }
        mEntryValues = preference.getEntryValues();
    }

    /**
     * Update new data set for list preference.
     */
    public void onListPreferenceUpdated(ListPreference preference) {
        if (mAdapter != null) {
            setPreferenceData(preference);
            mAdapter.notifyDataSetChanged();
        }
    }
}
+0 −98
Original line number Diff line number Diff line
/*
 * 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.settingslib.widget;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;

import android.content.Context;
import android.widget.ArrayAdapter;

import androidx.preference.ListPreference;

import com.android.internal.logging.nano.MetricsProto;

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;

@RunWith(RobolectricTestRunner.class)
public class UpdatableListPreferenceDialogFragmentTest {

    private static final String KEY = "Test_Key";
    @Mock
    private UpdatableListPreferenceDialogFragment mUpdatableListPrefDlgFragment;
    private Context mContext;
    private ArrayAdapter mAdapter;
    private ArrayList<CharSequence> mEntries;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mContext = RuntimeEnvironment.application;

        mUpdatableListPrefDlgFragment = spy(UpdatableListPreferenceDialogFragment
                .newInstance(KEY, MetricsProto.MetricsEvent.DIALOG_SWITCH_A2DP_DEVICES));
        mEntries = new ArrayList<>();
        mUpdatableListPrefDlgFragment.setEntries(mEntries);
        mUpdatableListPrefDlgFragment
                .setMetricsCategory(mUpdatableListPrefDlgFragment.getArguments());
        initAdapter();
    }

    private void initAdapter() {
        mAdapter = spy(new ArrayAdapter<>(
                mContext,
                com.android.internal.R.layout.select_dialog_singlechoice,
                mEntries));
        mUpdatableListPrefDlgFragment.setAdapter(mAdapter);
    }

    @Test
    public void getMetricsCategory() {
        assertThat(mUpdatableListPrefDlgFragment.getMetricsCategory())
                .isEqualTo(MetricsProto.MetricsEvent.DIALOG_SWITCH_A2DP_DEVICES);
    }

    @Test
    public void onListPreferenceUpdated_verifyAdapterCanBeUpdate() {
        assertThat(mUpdatableListPrefDlgFragment.getAdapter().getCount()).isEqualTo(0);

        ListPreference listPreference = new ListPreference(mContext);
        final CharSequence[] charSequences = {"Test_DEVICE_1", "Test_DEVICE_2"};
        listPreference.setEntries(charSequences);
        mUpdatableListPrefDlgFragment.onListPreferenceUpdated(listPreference);

        assertThat(mUpdatableListPrefDlgFragment.getAdapter().getCount()).isEqualTo(2);
    }

    @Test
    public void onDialogClosed_emptyPreference() {
        mUpdatableListPrefDlgFragment.onDialogClosed(false);

        verify(mUpdatableListPrefDlgFragment, never()).getListPreference();
    }
}