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

Commit 1d548b6d authored by Ying Xu's avatar Ying Xu Committed by Android (Google) Code Review
Browse files

Merge "Extract the platform signals handling into settingslib"

parents b934e198 c71a4b6a
Loading
Loading
Loading
Loading
+63 −0
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.settingslib.mobile;

import android.telephony.Annotation;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;

/**
 * Holds the utility functions to create the RAT to MobileIconGroup mappings.
 */
public class MobileMappings {

    /**
     * Generates the RAT key from the TelephonyDisplayInfo.
     */
    public static String getIconKey(TelephonyDisplayInfo telephonyDisplayInfo) {
        if (telephonyDisplayInfo.getOverrideNetworkType()
                == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) {
            return toIconKey(telephonyDisplayInfo.getNetworkType());
        } else {
            return toDisplayIconKey(telephonyDisplayInfo.getOverrideNetworkType());
        }
    }

    /**
     * Converts the networkType into the RAT key.
     */
    public static String toIconKey(@Annotation.NetworkType int networkType) {
        return Integer.toString(networkType);
    }

    /**
     * Converts the displayNetworkType into the RAT key.
     */
    public static String toDisplayIconKey(@Annotation.OverrideNetworkType int displayNetworkType) {
        switch (displayNetworkType) {
            case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA:
                return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA";
            case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO:
                return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA_Plus";
            case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA:
                return toIconKey(TelephonyManager.NETWORK_TYPE_NR);
            case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE:
                return toIconKey(TelephonyManager.NETWORK_TYPE_NR) + "_Plus";
            default:
                return "unsupported";
        }
    }
}
+286 −0
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.settingslib.mobile;

import android.os.Handler;
import android.os.Looper;
import android.telephony.PhoneStateListener;
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.Log;

/**
 * Tracks the mobile signal status for the SysUI and Settings.
 *
 * This class is not threadsafe. All the mobile statuses monitored by this class is stored in
 * MobileStatus. Whoever uses this class should only rely on the MobileStatusTracker#Callback
 * to get the latest mobile statuses. Do not get mobile statues directly from
 * MobileStatusTracker#MobileStatus.
 */
public class MobileStatusTracker {
    private static final String TAG = "MobileStatusTracker";
    private final TelephonyManager mPhone;
    private final SubscriptionInfo mSubscriptionInfo;
    private final Callback mCallback;
    private final MobileStatus mMobileStatus;
    private final PhoneStateListener mPhoneStateListener;
    private final SubscriptionDefaults mDefaults;
    private final Handler mReceiverHandler;

    /**
     * MobileStatusTracker constructors
     *
     * @param phone The TelephonyManager which corresponds to the subscription being monitored.
     * @param receiverLooper The Looper on which the callback will be invoked.
     * @param info The subscription being monitored.
     * @param defaults The wrapper of the SubscriptionManager.
     * @param callback The callback to notify any changes of the mobile status, users should only
     *                 use this callback to get the latest mobile status.
     */
    public MobileStatusTracker(TelephonyManager phone, Looper receiverLooper,
            SubscriptionInfo info, SubscriptionDefaults defaults, Callback callback) {
        mPhone = phone;
        mReceiverHandler = new Handler(receiverLooper);
        mPhoneStateListener = new MobilePhoneStateListener();
        mSubscriptionInfo = info;
        mDefaults = defaults;
        mCallback = callback;
        mMobileStatus = new MobileStatus();
        updateDataSim();
        mReceiverHandler.post(() -> mCallback.onMobileStatusChanged(
                /* updateTelephony= */false, new MobileStatus(mMobileStatus)));
    }

    public PhoneStateListener getPhoneStateListener() {
        return mPhoneStateListener;
    }

    /**
     * Config the MobileStatusTracker to start or stop monitoring platform signals.
     */
    public void setListening(boolean listening) {
        if (listening) {
            mPhone.registerPhoneStateListener(mReceiverHandler::post, mPhoneStateListener);
        } else {
            mPhone.unregisterPhoneStateListener(mPhoneStateListener);
        }
    }

    private void updateDataSim() {
        int activeDataSubId = mDefaults.getActiveDataSubId();
        if (SubscriptionManager.isValidSubscriptionId(activeDataSubId)) {
            mMobileStatus.dataSim = activeDataSubId == mSubscriptionInfo.getSubscriptionId();
        } else {
            // There doesn't seem to be a data sim selected, however if
            // there isn't a MobileSignalController with dataSim set, then
            // QS won't get any callbacks and will be blank.  Instead
            // lets just assume we are the data sim (which will basically
            // show one at random) in QS until one is selected.  The user
            // should pick one soon after, so we shouldn't be in this state
            // for long.
            mMobileStatus.dataSim = true;
        }
    }

    private void setActivity(int activity) {
        mMobileStatus.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT
                || activity == TelephonyManager.DATA_ACTIVITY_IN;
        mMobileStatus.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT
                || activity == TelephonyManager.DATA_ACTIVITY_OUT;
    }

    private class MobilePhoneStateListener extends PhoneStateListener implements
            PhoneStateListener.ServiceStateChangedListener,
            PhoneStateListener.SignalStrengthsChangedListener,
            PhoneStateListener.CallStateChangedListener,
            PhoneStateListener.DataConnectionStateChangedListener,
            PhoneStateListener.DataActivityListener,
            PhoneStateListener.CarrierNetworkChangeListener,
            PhoneStateListener.ActiveDataSubscriptionIdChangedListener,
            PhoneStateListener.DisplayInfoChangedListener{

        @Override
        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength
                        + ((signalStrength == null) ? ""
                                : (" level=" + signalStrength.getLevel())));
            }
            mMobileStatus.signalStrength = signalStrength;
            mCallback.onMobileStatusChanged(
                    /* updateTelephony= */true, new MobileStatus(mMobileStatus));
        }

        @Override
        public void onServiceStateChanged(ServiceState state) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onServiceStateChanged voiceState="
                        + (state == null ? "" : state.getState())
                        + " dataState=" + (state == null ? "" : state.getDataRegistrationState()));
            }
            mMobileStatus.serviceState = state;
            mCallback.onMobileStatusChanged(
                    /* updateTelephony= */true, new MobileStatus(mMobileStatus));
        }

        @Override
        public void onDataConnectionStateChanged(int state, int networkType) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onDataConnectionStateChanged: state=" + state
                        + " type=" + networkType);
            }
            mMobileStatus.dataState = state;
            mCallback.onMobileStatusChanged(
                    /* updateTelephony= */true, new MobileStatus(mMobileStatus));
        }

        @Override
        public void onDataActivity(int direction) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onDataActivity: direction=" + direction);
            }
            setActivity(direction);
            mCallback.onMobileStatusChanged(
                    /* updateTelephony= */false, new MobileStatus(mMobileStatus));
        }

        @Override
        public void onCarrierNetworkChange(boolean active) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onCarrierNetworkChange: active=" + active);
            }
            mMobileStatus.carrierNetworkChangeMode = active;
            mCallback.onMobileStatusChanged(
                    /* updateTelephony= */true, new MobileStatus(mMobileStatus));
        }

        @Override
        public void onActiveDataSubscriptionIdChanged(int subId) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onActiveDataSubscriptionIdChanged: subId=" + subId);
            }
            updateDataSim();
            mCallback.onMobileStatusChanged(
                    /* updateTelephony= */true, new MobileStatus(mMobileStatus));
        }

        @Override
        public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onDisplayInfoChanged: telephonyDisplayInfo=" + telephonyDisplayInfo);
            }
            mMobileStatus.telephonyDisplayInfo = telephonyDisplayInfo;
            mCallback.onMobileStatusChanged(
                    /* updateTelephony= */ true, new MobileStatus(mMobileStatus));
        }
    }

    /**
     * Wrapper class of the SubscriptionManager, for mock testing purpose
     */
    public static class SubscriptionDefaults {
        public int getDefaultVoiceSubId() {
            return SubscriptionManager.getDefaultVoiceSubscriptionId();
        }

        public int getDefaultDataSubId() {
            return SubscriptionManager.getDefaultDataSubscriptionId();
        }

        public int getActiveDataSubId() {
            return SubscriptionManager.getActiveDataSubscriptionId();
        }
    }

    /**
     * Wrapper class which contains all the mobile status tracked by MobileStatusTracker.
     */
    public static class MobileStatus {
        public boolean activityIn;
        public boolean activityOut;
        public boolean dataSim;
        public boolean carrierNetworkChangeMode;
        public int dataState = TelephonyManager.DATA_DISCONNECTED;
        public ServiceState serviceState;
        public SignalStrength signalStrength;
        public TelephonyDisplayInfo telephonyDisplayInfo =
                new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);

        /**
         * Empty constructor
         */
        public MobileStatus() { }

        /**
         * Copy constructors
         *
         * @param status Source MobileStatus
         */
        public MobileStatus(MobileStatus status) {
            copyFrom(status);
        }

        protected void copyFrom(MobileStatus status) {
            activityIn = status.activityIn;
            activityOut = status.activityOut;
            dataSim = status.dataSim;
            carrierNetworkChangeMode = status.carrierNetworkChangeMode;
            dataState = status.dataState;
            // We don't do deep copy for the below members since they may be Mockito instances.
            serviceState = status.serviceState;
            signalStrength = status.signalStrength;
            telephonyDisplayInfo = status.telephonyDisplayInfo;
        }

        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            return builder.append("[activityIn=").append(activityIn).append(',')
                .append("activityOut=").append(activityOut).append(',')
                .append("dataSim=").append(dataSim).append(',')
                .append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode).append(',')
                .append("dataState=").append(dataState).append(',')
                .append("serviceState=").append(serviceState == null ? ""
                        : serviceState.toString()).append(',')
                .append("signalStrength=").append(signalStrength == null ? ""
                        : signalStrength.toString()).append(',')
                .append("telephonyDisplayInfo=").append(telephonyDisplayInfo == null ? ""
                        : telephonyDisplayInfo.toString()).append(']').toString();
        }
    }

    /**
     * Callback for notifying any changes of the mobile status.
     *
     * This callback will always be invoked on the receiverLooper which must be specified when
     * MobileStatusTracker is constructed.
     */
    public interface Callback {
        /**
         * Notify the mobile status has been updated.
         *
         * @param updateTelephony Whether needs to update other Telephony related parameters, this
         *                        is only used by SysUI.
         * @param mobileStatus Holds the latest mobile statuses
         */
        void onMobileStatusChanged(boolean updateTelephony, MobileStatus mobileStatus);
    }
}
+43 −123

File changed.

Preview size limit exceeded, changes collapsed.

+1 −15
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ import androidx.annotation.NonNull;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults;
import com.android.settingslib.net.DataUsageController;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
@@ -391,7 +392,6 @@ public class NetworkControllerImpl extends BroadcastReceiver
                }
            }
        });

        updateMobileControllers();

        // Initial setup of emergency information. Handled as if we had received a sticky broadcast
@@ -1202,20 +1202,6 @@ public class NetworkControllerImpl extends BroadcastReceiver
        }
    };

    public static class SubscriptionDefaults {
        public int getDefaultVoiceSubId() {
            return SubscriptionManager.getDefaultVoiceSubscriptionId();
        }

        public int getDefaultDataSubId() {
            return SubscriptionManager.getDefaultDataSubscriptionId();
        }

        public int getActiveDataSubId() {
            return SubscriptionManager.getActiveDataSubscriptionId();
        }
    }

    @VisibleForTesting
    static class Config {
        boolean showAtLeast3G = false;
+2 −2
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ import android.util.Log;
import androidx.test.InstrumentationRegistry;

import com.android.settingslib.graph.SignalDrawable;
import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults;
import com.android.settingslib.net.DataUsageController;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
@@ -70,7 +71,6 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceP
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;

import org.junit.Before;
import org.junit.Rule;
@@ -225,7 +225,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
        setDefaultSubId(mSubId);
        setSubscriptions(mSubId);
        mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId);
        mPhoneStateListener = mMobileSignalController.mPhoneStateListener;
        mPhoneStateListener = mMobileSignalController.mMobileStatusTracker.getPhoneStateListener();

        ArgumentCaptor<ConnectivityManager.NetworkCallback> callbackArg =
            ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);