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

Commit 7c8e8eb6 authored by Tom Hsu's avatar Tom Hsu Committed by Android (Google) Code Review
Browse files

Merge "[Provider mode] Display network type on mobile data preference."

parents 35a2791a b392d43f
Loading
Loading
Loading
Loading
+51 −9
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;

import static com.android.settings.network.telephony.MobileNetworkUtils.NO_CELL_DATA_TYPE_ICON;
import static com.android.settingslib.mobile.MobileMappings.getIconKey;
import static com.android.settingslib.mobile.MobileMappings.mapIconSets;

import android.content.BroadcastReceiver;
import android.content.Context;
@@ -31,6 +33,7 @@ import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
import android.util.ArraySet;

@@ -49,9 +52,12 @@ import com.android.settings.network.telephony.DataConnectivityListener;
import com.android.settings.network.telephony.MobileNetworkActivity;
import com.android.settings.network.telephony.MobileNetworkUtils;
import com.android.settings.network.telephony.SignalStrengthListener;
import com.android.settings.network.telephony.TelephonyDisplayInfoListener;
import com.android.settings.widget.GearPreference;
import com.android.settings.wifi.WifiPickerTrackerHelper;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.mobile.MobileMappings;
import com.android.settingslib.mobile.MobileMappings.Config;
import com.android.settingslib.net.SignalStrengthUtil;

import java.util.Collections;
@@ -73,7 +79,7 @@ import java.util.Set;
public class SubscriptionsPreferenceController extends AbstractPreferenceController implements
        LifecycleObserver, SubscriptionsChangeListener.SubscriptionsChangeListenerClient,
        MobileDataEnabledListener.Client, DataConnectivityListener.Client,
        SignalStrengthListener.Callback {
        SignalStrengthListener.Callback, TelephonyDisplayInfoListener.Callback {
    private static final String TAG = "SubscriptionsPrefCntrlr";

    private UpdateListener mUpdateListener;
@@ -85,6 +91,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
    private MobileDataEnabledListener mDataEnabledListener;
    private DataConnectivityListener mConnectivityListener;
    private SignalStrengthListener mSignalStrengthListener;
    private TelephonyDisplayInfoListener mTelephonyDisplayInfoListener;
    private WifiPickerTrackerHelper mWifiPickerTrackerHelper;

    @VisibleForTesting
@@ -93,6 +100,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (action.equals(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
                mConfig = mSubsPrefCtrlInjector.getConfig(mContext);
                update();
            }
        }
@@ -102,8 +110,12 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
    private Map<Integer, Preference> mSubscriptionPreferences;
    private int mStartOrder;
    private GearPreference mSubsGearPref;

    private Config mConfig = null;
    private SubsPrefCtrlInjector mSubsPrefCtrlInjector;
    private TelephonyDisplayInfo mTelephonyDisplayInfo =
            new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
                    TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);

    /**
     * This interface lets a parent of this class know that some change happened - this could
     * either be because overall availability changed, or because we've added/removed/updated some
@@ -140,8 +152,10 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
        mDataEnabledListener = new MobileDataEnabledListener(context, this);
        mConnectivityListener = new DataConnectivityListener(context, this);
        mSignalStrengthListener = new SignalStrengthListener(context, this);
        mTelephonyDisplayInfoListener = new TelephonyDisplayInfoListener(context, this);
        lifecycle.addObserver(this);
        mSubsPrefCtrlInjector = createSubsPrefCtrlInjector();
        mConfig = mSubsPrefCtrlInjector.getConfig(mContext);
    }

    private void registerDataSubscriptionChangedReceiver() {
@@ -163,6 +177,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
        mDataEnabledListener.start(mSubsPrefCtrlInjector.getDefaultDataSubscriptionId());
        mConnectivityListener.start();
        mSignalStrengthListener.resume();
        mTelephonyDisplayInfoListener.resume();
        registerDataSubscriptionChangedReceiver();
        update();
    }
@@ -173,6 +188,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
        mDataEnabledListener.stop();
        mConnectivityListener.stop();
        mSignalStrengthListener.pause();
        mTelephonyDisplayInfoListener.pause();
        unRegisterDataSubscriptionChangedReceiver();
    }

@@ -196,6 +212,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl

            mSubscriptionPreferences.clear();
            mSignalStrengthListener.updateSubscriptionIds(Collections.emptySet());
            mTelephonyDisplayInfoListener.updateSubscriptionIds(Collections.emptySet());
            mUpdateListener.onChildrenUpdated();
            return;
        }
@@ -226,22 +243,23 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl

        mSubsGearPref.setTitle(subInfo.getDisplayName());
        mSubsGearPref.setOrder(mStartOrder);
        //TODO(b/176141828) Wait for api provided by system ui.
        mSubsGearPref.setSummary(getMobilePreferenceSummary());
        mSubsGearPref.setSummary(getMobilePreferenceSummary(subInfo.getSubscriptionId()));
        mSubsGearPref.setIcon(getIcon(subInfo.getSubscriptionId()));
        mPreferenceGroup.addPreference(mSubsGearPref);

        final Set<Integer> activeDataSubIds = new ArraySet<>();
        activeDataSubIds.add(subInfo.getSubscriptionId());
        mSignalStrengthListener.updateSubscriptionIds(activeDataSubIds);
        mTelephonyDisplayInfoListener.updateSubscriptionIds(activeDataSubIds);
        mUpdateListener.onChildrenUpdated();
    }

    private String getMobilePreferenceSummary() {
        //TODO(b/176141828) Waiting for the api provided by system UI.
        String result = "5G";
        if (MobileNetworkUtils.activeNetworkIsCellular(mContext)) {
            result = "Active, " + result;
    private String getMobilePreferenceSummary(int subId) {
        String result = mSubsPrefCtrlInjector.getNetworkType(
                mContext, mConfig, mTelephonyDisplayInfo, subId);
        if (!result.isEmpty() && mSubsPrefCtrlInjector.isActiveCellularNetwork(mContext)) {
            result = mContext.getString(R.string.preference_summary_default_combination,
                    mContext.getString(R.string.mobile_data_connection_active), result);
        }
        return result;
    }
@@ -462,6 +480,12 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
        update();
    }

    @Override
    public void onTelephonyDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) {
        mTelephonyDisplayInfo = telephonyDisplayInfo;
        update();
    }

    @VisibleForTesting
    boolean canSubscriptionBeDisplayed(Context context, int subId) {
        return (SubscriptionUtil.getAvailableSubscription(context,
@@ -534,6 +558,24 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
            return Utils.isProviderModelEnabled(context);
        }

        /**
         * Get config for carrier customization.
         */
        public Config getConfig(Context context) {
            return MobileMappings.Config.readConfig(context);
        }

        /**
         * Get current mobile network type.
         */
        public String getNetworkType(Context context, Config config,
                TelephonyDisplayInfo telephonyDisplayInfo, int subId) {
            String iconKey = getIconKey(telephonyDisplayInfo);
            int resId = mapIconSets(config).get(iconKey).dataContentDescription;
            return resId != 0
                ? SubscriptionManager.getResourcesForSubId(context, subId).getString(resId) : "";
        }

        /**
         * Get signal icon with different signal level.
         */
+111 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.telephony;

import android.content.Context;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
import android.util.ArraySet;

import com.google.common.collect.Sets;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Help to listen telephony display info change to subscriptions.
 * TODO(b/177647571): unit test is needed.
 */
public class TelephonyDisplayInfoListener {

    private TelephonyManager mBaseTelephonyManager;
    private Callback mCallback;
    private Map<Integer, PhoneStateListener> mListeners;

    private TelephonyDisplayInfo mTelephonyDisplayInfo =
            new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
                    TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
    /**
     * Interface of callback and to use notify TelephonyDisplayInfo change.
     */
    public interface Callback {
        /**
         * Used to notify TelephonyDisplayInfo change.
         */
        void onTelephonyDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo);
    }

    public TelephonyDisplayInfoListener(Context context, Callback callback) {
        mBaseTelephonyManager = context.getSystemService(TelephonyManager.class);
        mCallback = callback;
        mListeners = new HashMap<>();
    }
    /**
     * Get TelephonyDisplayInfo.
     */
    public TelephonyDisplayInfo getTelephonyDisplayInfo() {
        return mTelephonyDisplayInfo;
    }

    /** Resumes listening telephony display info changes to the set of ids from the last call to
     * {@link #updateSubscriptionIds(Set)}  */
    public void resume() {
        for (int subId : mListeners.keySet()) {
            startListening(subId);
        }
    }

    /** Pauses listening for telephony display info changes */
    public void pause() {
        for (int subId : mListeners.keySet()) {
            stopListening(subId);
        }
    }

    /** Updates the set of ids we want to be listening for, beginning to listen for any new ids and
     * stopping listening for any ids not contained in the new set */
    public void updateSubscriptionIds(Set<Integer> ids) {
        Set<Integer> currentIds = new ArraySet<>(mListeners.keySet());
        for (int idToRemove : Sets.difference(currentIds, ids)) {
            stopListening(idToRemove);
            mListeners.remove(idToRemove);
        }
        for (int idToAdd : Sets.difference(ids, currentIds)) {
            PhoneStateListener listener = new PhoneStateListener() {
                @Override
                public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) {
                    mTelephonyDisplayInfo = telephonyDisplayInfo;
                    mCallback.onTelephonyDisplayInfoChanged(telephonyDisplayInfo);
                }
            };
            mListeners.put(idToAdd, listener);
            startListening(idToAdd);
        }
    }

    private void startListening(int subId) {
        TelephonyManager mgr = mBaseTelephonyManager.createForSubscriptionId(subId);
        mgr.listen(mListeners.get(subId), PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED);
    }

    private void stopListening(int subId) {
        TelephonyManager mgr = mBaseTelephonyManager.createForSubscriptionId(subId);
        mgr.listen(mListeners.get(subId), PhoneStateListener.LISTEN_NONE);
    }
}
+90 −1
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;

import androidx.lifecycle.LifecycleOwner;
@@ -62,6 +63,7 @@ import com.android.settings.network.SubscriptionsPreferenceController.SubsPrefCt
import com.android.settings.testutils.ResourcesUtils;
import com.android.settings.wifi.WifiPickerTrackerHelper;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.mobile.MobileMappings;

import org.junit.After;
import org.junit.Before;
@@ -102,7 +104,6 @@ public class SubscriptionsPreferenceControllerTest {
    private PreferenceScreen mPreferenceScreen;
    private PreferenceManager mPreferenceManager;
    private NetworkCapabilities mNetworkCapabilities;

    private FakeSubscriptionsPreferenceController mController;
    private static SubsPrefCtrlInjector sInjector;

@@ -134,6 +135,7 @@ public class SubscriptionsPreferenceControllerTest {

        mOnChildUpdatedCount = 0;
        mUpdateListener = () -> mOnChildUpdatedCount++;

        sInjector = spy(new SubsPrefCtrlInjector());
        initializeMethod(true, 1, 1, 1, false, false);
        mController =  new FakeSubscriptionsPreferenceController(mContext, mLifecycle,
@@ -408,6 +410,45 @@ public class SubscriptionsPreferenceControllerTest {
        assertThat(mPreferenceCategory.getPreference(0).getTitle()).isEqualTo("sub1");
    }

    @Test
    @UiThreadTest
    public void displayPreference_providerAndHasMultiSimAndActive_connectedAndRat() {
        final String expectedSummary = "Connected / 5G";
        final String networkType = "5G";
        final List<SubscriptionInfo> sub = setupMockSubscriptions(2);
        doReturn(true).when(sInjector).isProviderModelEnabled(mContext);
        doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
        setupGetIconConditions(sub.get(0).getSubscriptionId(), true, true,
                TelephonyManager.DATA_CONNECTED, ServiceState.STATE_IN_SERVICE);
        doReturn(mock(MobileMappings.Config.class)).when(sInjector).getConfig(mContext);
        doReturn(networkType)
                .when(sInjector).getNetworkType(any(), any(), any(), anyInt());

        mController.onResume();
        mController.displayPreference(mPreferenceScreen);

        assertThat(mPreferenceCategory.getPreference(0).getSummary()).isEqualTo(expectedSummary);
    }

    @Test
    @UiThreadTest
    public void displayPreference_providerAndHasMultiSimAndNotActive_showRatOnly() {
        final String expectedSummary = "5G";
        final String networkType = "5G";
        final List<SubscriptionInfo> sub = setupMockSubscriptions(2);
        doReturn(true).when(sInjector).isProviderModelEnabled(mContext);
        doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
        setupGetIconConditions(sub.get(0).getSubscriptionId(), false, true,
                TelephonyManager.DATA_CONNECTED, ServiceState.STATE_IN_SERVICE);
        doReturn(networkType)
                .when(sInjector).getNetworkType(any(), any(), any(), anyInt());

        mController.onResume();
        mController.displayPreference(mPreferenceScreen);

        assertThat(mPreferenceCategory.getPreference(0).getSummary()).isEqualTo(expectedSummary);
    }

    @Test
    @UiThreadTest
    public void displayPreference_providerAndNoSim_noPreference() {
@@ -420,6 +461,54 @@ public class SubscriptionsPreferenceControllerTest {
        assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(0);
    }

    @Test
    @UiThreadTest
    public void onTelephonyDisplayInfoChanged_providerAndHasMultiSimAndActive_connectedAndRat() {
        final String expectedSummary = "Connected / LTE";
        final String networkType = "LTE";
        final List<SubscriptionInfo> sub = setupMockSubscriptions(2);
        final TelephonyDisplayInfo telephonyDisplayInfo =
                new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
        doReturn(true).when(sInjector).isProviderModelEnabled(mContext);
        doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
        setupGetIconConditions(sub.get(0).getSubscriptionId(), true, true,
                TelephonyManager.DATA_CONNECTED, ServiceState.STATE_IN_SERVICE);
        doReturn(mock(MobileMappings.Config.class)).when(sInjector).getConfig(mContext);
        doReturn(networkType)
                .when(sInjector).getNetworkType(any(), any(), any(), anyInt());

        mController.onResume();
        mController.displayPreference(mPreferenceScreen);
        mController.onTelephonyDisplayInfoChanged(telephonyDisplayInfo);

        assertThat(mPreferenceCategory.getPreference(0).getSummary()).isEqualTo(expectedSummary);
    }

    @Test
    @UiThreadTest
    public void onTelephonyDisplayInfoChanged_providerAndHasMultiSimAndNotActive_showRat() {
        final String expectedSummary = "LTE";
        final String networkType = "LTE";
        final List<SubscriptionInfo> sub = setupMockSubscriptions(2);
        final TelephonyDisplayInfo telephonyDisplayInfo =
                new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
        doReturn(true).when(sInjector).isProviderModelEnabled(mContext);
        doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
        setupGetIconConditions(sub.get(0).getSubscriptionId(), false, true,
                TelephonyManager.DATA_CONNECTED, ServiceState.STATE_IN_SERVICE);
        doReturn(mock(MobileMappings.Config.class)).when(sInjector).getConfig(mContext);
        doReturn(networkType)
                .when(sInjector).getNetworkType(any(), any(), any(), anyInt());

        mController.onResume();
        mController.displayPreference(mPreferenceScreen);
        mController.onTelephonyDisplayInfoChanged(telephonyDisplayInfo);

        assertThat(mPreferenceCategory.getPreference(0).getSummary()).isEqualTo(expectedSummary);
    }

    @Test
    @UiThreadTest
    public void onAirplaneModeChanged_providerAndHasSim_noPreference() {