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

Commit 4246049c authored by Betty Chang's avatar Betty Chang Committed by Android (Google) Code Review
Browse files

Merge "Remove the Network rating provider item" into sc-dev

parents d647dece 8267a275
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -59,12 +59,6 @@
        </intent>
    </Preference>

    <Preference
        android:key="network_scorer_picker"
        android:title="@string/network_scorer_picker_title"
        android:fragment="com.android.settings.network.NetworkScorerPicker"
        settings:controller="com.android.settings.network.NetworkScorerPickerPreferenceController" />

    <Preference
        android:key="wifi_direct"
        android:title="@string/wifi_menu_p2p"
+0 −145
Original line number Diff line number Diff line
/*
 * 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.network;

import android.app.settings.SettingsEnums;
import android.content.Context;
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppData;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.R;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settingslib.widget.RadioButtonPreference;

import java.util.List;

/**
 * Fragment for choosing default network scorer.
 */
public class NetworkScorerPicker extends InstrumentedPreferenceFragment implements
        RadioButtonPreference.OnClickListener {

    private NetworkScoreManager mNetworkScoreManager;

    @Override
    public int getMetricsCategory() {
        return SettingsEnums.SETTINGS_NETWORK_SCORER;
    }

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        super.onCreatePreferences(savedInstanceState, rootKey);
        updateCandidates();
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mNetworkScoreManager = createNetworkScorerManager(context);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        final View view = super.onCreateView(inflater, container, savedInstanceState);
        // this is needed so the back button goes back to previous fragment
        setHasOptionsMenu(true);
        return view;
    }

    @Override
    protected int getPreferenceScreenResId() {
        return R.xml.network_scorer_picker_prefs;
    }

    @VisibleForTesting
    public void updateCandidates() {
        final PreferenceScreen screen = getPreferenceScreen();
        screen.removeAll();

        final List<NetworkScorerAppData> scorers = mNetworkScoreManager.getAllValidScorers();
        final String defaultAppKey = getActiveScorerPackage();

        final RadioButtonPreference nonePref = new RadioButtonPreference(getPrefContext());
        nonePref.setTitle(R.string.network_scorer_picker_none_preference);
        if (scorers.isEmpty()) {
            nonePref.setChecked(true);
        } else {
            nonePref.setKey(null);
            nonePref.setChecked(TextUtils.isEmpty(defaultAppKey));
            nonePref.setOnClickListener(this);
        }
        screen.addPreference(nonePref);

        final int numScorers = scorers.size();
        for (int i = 0; i < numScorers; i++) {
            final RadioButtonPreference pref = new RadioButtonPreference(getPrefContext());
            final NetworkScorerAppData appData = scorers.get(i);
            final String appKey = appData.getRecommendationServicePackageName();
            pref.setTitle(appData.getRecommendationServiceLabel());
            pref.setKey(appKey);
            pref.setChecked(TextUtils.equals(defaultAppKey, appKey));
            pref.setOnClickListener(this);
            screen.addPreference(pref);
        }
    }

    private String getActiveScorerPackage() {
        return mNetworkScoreManager.getActiveScorerPackage();
    }

    private boolean setActiveScorer(String key) {
        if (!TextUtils.equals(key, getActiveScorerPackage())) {
            return mNetworkScoreManager.setActiveScorer(key);
        }
        return false;
    }

    @Override
    public void onRadioButtonClicked(RadioButtonPreference selected) {
        final String selectedKey = selected.getKey();
        final boolean success = setActiveScorer(selectedKey);
        if (success) {
            updateCheckedState(selectedKey);
        }
    }

    private void updateCheckedState(String selectedKey) {
        final PreferenceScreen screen = getPreferenceScreen();
        final int count = screen.getPreferenceCount();
        for (int i = 0; i < count; i++) {
            final Preference pref = screen.getPreference(i);
            if (pref instanceof RadioButtonPreference) {
                final RadioButtonPreference radioPref = (RadioButtonPreference) pref;
                radioPref.setChecked(TextUtils.equals(pref.getKey(), selectedKey));
            }
        }
    }

    @VisibleForTesting
    NetworkScoreManager createNetworkScorerManager(Context context) {
        return (NetworkScoreManager) context.getSystemService(Context.NETWORK_SCORE_SERVICE);
    }
}
+0 −67
Original line number Diff line number Diff line
/*
 * 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.network;

import android.content.Context;
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppData;

import androidx.preference.Preference;

import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;

import java.util.List;

/**
 * {@link AbstractPreferenceController} that shows the active network scorer and toggles the
 * preference based on whether or not there are valid scorers installed.
 */
public class NetworkScorerPickerPreferenceController extends BasePreferenceController {

    private final NetworkScoreManager mNetworkScoreManager;

    public NetworkScorerPickerPreferenceController(Context context, String key) {
        super(context, key);
        mNetworkScoreManager =
                (NetworkScoreManager) mContext.getSystemService(Context.NETWORK_SCORE_SERVICE);
    }

    @Override
    public int getAvailabilityStatus() {
        return AVAILABLE;
    }

    @Override
    public void updateState(Preference preference) {
        final List<NetworkScorerAppData> allValidScorers =
                mNetworkScoreManager.getAllValidScorers();
        boolean enabled = !allValidScorers.isEmpty();
        preference.setEnabled(enabled);
        if (!enabled) {
            preference.setSummary(null);
            return;
        }

        NetworkScorerAppData scorer = mNetworkScoreManager.getActiveScorer();
        if (scorer == null) {
            preference.setSummary(mContext.getString(
                    R.string.network_scorer_picker_none_preference));
        } else {
            preference.setSummary(scorer.getRecommendationServiceLabel());
        }
    }
}
+0 −206
Original line number Diff line number Diff line
/*
 * 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.network;

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

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.ComponentName;
import android.content.Context;
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppData;

import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;

import com.android.settings.R;
import com.android.settingslib.widget.RadioButtonPreference;

import com.google.android.collect.Lists;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
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 NetworkScorerPickerTest {

    private static final String TEST_SCORER_PACKAGE_1 = "Test Package 1";
    private static final String TEST_SCORER_CLASS_1 = "Test Class 1";
    private static final String TEST_SCORER_LABEL_1 = "Test Label 1";
    private static final String TEST_SCORER_PACKAGE_2 = "Test Package 2";

    private Context mContext;
    @Mock
    private NetworkScoreManager mNetworkScoreManager;
    @Mock
    private PreferenceScreen mPreferenceScreen;

    private TestFragment mFragment;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mContext = RuntimeEnvironment.application;
        mFragment = new TestFragment(mContext, mPreferenceScreen, mNetworkScoreManager);
        mFragment.onAttach(mContext);
    }

    @Test
    public void testOnRadioButtonClicked_success() {
        RadioButtonPreference pref = new RadioButtonPreference(mContext);
        pref.setKey(TEST_SCORER_PACKAGE_1);
        when(mPreferenceScreen.getPreference(anyInt())).thenReturn(pref);
        when(mPreferenceScreen.getPreferenceCount()).thenReturn(1);
        when(mNetworkScoreManager.setActiveScorer(TEST_SCORER_PACKAGE_1)).thenReturn(true);
        when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(TEST_SCORER_PACKAGE_2);

        mFragment.onRadioButtonClicked(pref);

        verify(mNetworkScoreManager).setActiveScorer(TEST_SCORER_PACKAGE_1);
        assertThat(pref.isChecked()).isTrue();
    }

    @Test
    public void testOnRadioButtonClicked_currentScorer_doNothing() {
        RadioButtonPreference pref = new RadioButtonPreference(mContext);
        pref.setKey(TEST_SCORER_PACKAGE_1);
        pref.setChecked(true);
        when(mPreferenceScreen.getPreference(anyInt())).thenReturn(pref);
        when(mPreferenceScreen.getPreferenceCount()).thenReturn(1);
        when(mNetworkScoreManager.setActiveScorer(TEST_SCORER_PACKAGE_1)).thenReturn(true);
        when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(TEST_SCORER_PACKAGE_1);

        mFragment.onRadioButtonClicked(pref);

        verify(mNetworkScoreManager, never()).setActiveScorer(any());
        assertThat(pref.isChecked()).isTrue();
    }

    @Test
    public void testUpdateCandidates_noValidScorers_nonePreference() {
        when(mNetworkScoreManager.getAllValidScorers()).thenReturn(new ArrayList<>());
        ArgumentCaptor<RadioButtonPreference> arg =
                ArgumentCaptor.forClass(RadioButtonPreference.class);

        mFragment.updateCandidates();

        verify(mPreferenceScreen).addPreference(arg.capture());
        assertThat(arg.getValue().getTitle())
                .isEqualTo(mContext.getString(R.string.network_scorer_picker_none_preference));
        assertThat(arg.getValue().isChecked()).isTrue();
    }

    @Test
    public void testUpdateCandidates_validScorers_noActiveScorer() {
        ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE_1, TEST_SCORER_CLASS_1);
        NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
                0, scorer, TEST_SCORER_LABEL_1, null /* enableUseOpenWifiActivity */,
                null /* networkAvailableNotificationChannelId */);
        when(mNetworkScoreManager.getAllValidScorers()).thenReturn(
                Lists.newArrayList(scorerAppData));
        when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(null);

        ArgumentCaptor<RadioButtonPreference> arg =
                ArgumentCaptor.forClass(RadioButtonPreference.class);

        mFragment.updateCandidates();

        verify(mPreferenceScreen, times(2)).addPreference(arg.capture());

        final RadioButtonPreference nonePref = arg.getAllValues().get(0);
        assertThat(nonePref.getKey()).isNull();
        assertThat(nonePref.isChecked()).isTrue();

        final RadioButtonPreference testScorerPref = arg.getAllValues().get(1);
        assertThat(testScorerPref.getTitle()).isEqualTo(TEST_SCORER_LABEL_1);
        assertThat(testScorerPref.isChecked()).isFalse();
    }

    @Test
    public void testUpdateCandidates_validScorer() {
        ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE_1, TEST_SCORER_CLASS_1);
        NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
                0, scorer, TEST_SCORER_LABEL_1, null /* enableUseOpenWifiActivity */,
                null /* networkAvailableNotificationChannelId */);
        when(mNetworkScoreManager.getAllValidScorers()).thenReturn(
                Lists.newArrayList(scorerAppData));
        when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(TEST_SCORER_PACKAGE_1);
        ArgumentCaptor<RadioButtonPreference> arg =
                ArgumentCaptor.forClass(RadioButtonPreference.class);

        mFragment.updateCandidates();

        // The first preference added is the "none" preference and the second is the
        // pref for the test scorer.
        verify(mPreferenceScreen, times(2)).addPreference(arg.capture());
        // Returns the last captured value which is expected to be the test scorer pref.
        RadioButtonPreference pref = arg.getValue();
        assertThat(pref.getTitle()).isEqualTo(TEST_SCORER_LABEL_1);
        assertThat(pref.isChecked()).isTrue();
    }

    public static class TestFragment extends NetworkScorerPicker {

        private final Context mContext;
        private final PreferenceScreen mScreen;
        private final PreferenceManager mPrefManager;
        private final NetworkScoreManager mNetworkScoreManager;

        public TestFragment(Context context, PreferenceScreen preferenceScreen,
                NetworkScoreManager networkScoreManager) {
            mContext = context;
            mScreen = preferenceScreen;
            mNetworkScoreManager = networkScoreManager;
            mPrefManager = mock(PreferenceManager.class);
            when(mPrefManager.getContext()).thenReturn(context);
        }

        @Override
        public Context getContext() {
            return mContext;
        }

        @Override
        public PreferenceManager getPreferenceManager() {
            return mPrefManager;
        }

        @Override
        public PreferenceScreen getPreferenceScreen() {
            return mScreen;
        }

        @Override
        NetworkScoreManager createNetworkScorerManager(Context context) {
            return mNetworkScoreManager;
        }
    }
}
+0 −148
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.network;

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

import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.ComponentName;
import android.content.Context;
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppData;

import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.Collections;

@RunWith(AndroidJUnit4.class)
public class NetworkScorerPickerPreferenceControllerTest {

    private static final String TEST_SCORER_PACKAGE = "Test Package";
    private static final String TEST_SCORER_CLASS = "Test Class";
    private static final String TEST_SCORER_LABEL = "Test Label";

    private Context mContext;
    @Mock
    private NetworkScoreManager mNetworkScorer;

    private NetworkScorerPickerPreferenceController mController;


    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mContext = spy(ApplicationProvider.getApplicationContext());
        doReturn(mNetworkScorer).when(mContext).getSystemService(Context.NETWORK_SCORE_SERVICE);

        mController = new NetworkScorerPickerPreferenceController(mContext, "test_key");
    }

    @Test
    public void testIsAvailable_shouldAlwaysReturnTrue() {
        assertThat(mController.isAvailable()).isTrue();
    }

    @Test
    public void updateState_preferenceSetSummaryAsActiveScorerLabel() {

        ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE, TEST_SCORER_CLASS);

        NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
                0, scorer, TEST_SCORER_LABEL, null /* enableUseOpenWifiActivity */,
                null /* networkAvailableNotificationChannelId */);

        when(mNetworkScorer.getAllValidScorers())
                .thenReturn(Collections.singletonList(scorerAppData));

        when(mNetworkScorer.getActiveScorer()).thenReturn(scorerAppData);

        Preference preference = mock(Preference.class);

        mController.updateState(preference);

        verify(preference).setSummary(TEST_SCORER_LABEL);
    }

    @Test
    public void updateState_scorersAvailable_noActiveScorer_preferenceSetSummaryToNone() {
        ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE, TEST_SCORER_CLASS);
        NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
                0, scorer, TEST_SCORER_LABEL, null /* enableUseOpenWifiActivity */,
                null /* networkAvailableNotificationChannelId */);
        when(mNetworkScorer.getAllValidScorers())
                .thenReturn(Collections.singletonList(scorerAppData));
        when(mNetworkScorer.getActiveScorer()).thenReturn(null);

        Preference preference = mock(Preference.class);

        mController.updateState(preference);

        Context context = ApplicationProvider.getApplicationContext();

        verify(preference).setSummary(
                resourceString("network_scorer_picker_none_preference"));
    }

    @Test
    public void updateState_scorersAvailable_preferenceEnabled() {
        ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE, TEST_SCORER_CLASS);
        NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
                0, scorer, TEST_SCORER_LABEL, null /* enableUseOpenWifiActivity */,
                null /* networkAvailableNotificationChannelId */);
        when(mNetworkScorer.getAllValidScorers())
                .thenReturn(Collections.singletonList(scorerAppData));

        Preference preference = mock(Preference.class);

        mController.updateState(preference);

        verify(preference).setEnabled(true);
    }

    @Test
    public void updateState_noScorersAvailable_preferenceDisabled() {
        when(mNetworkScorer.getAllValidScorers())
                .thenReturn(Collections.emptyList());
        Preference preference = mock(Preference.class);

        mController.updateState(preference);

        verify(preference).setEnabled(false);
        verify(preference).setSummary(null);
    }

    public int resourceId(String type, String name) {
        return mContext.getResources().getIdentifier(name, type, mContext.getPackageName());
    }

    public String resourceString(String name) {
        return mContext.getResources().getString(resourceId("string", name));
    }
}