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

Commit 6d45f66b authored by mavishsu's avatar mavishsu Committed by android-build-merger
Browse files

Merge "Notify user to select back to global mode while no service." into pi-dev

am: 824b64bd

Change-Id: I17440ae58fb5630f1e67849062d579e647be1b26
parents c939affa 824b64bd
Loading
Loading
Loading
Loading
+87 −13
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.Message;
import android.os.PersistableBundle;
@@ -30,6 +31,8 @@ import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.util.NotificationChannelController;
@@ -38,6 +41,7 @@ import java.util.HashMap;
import java.util.Map;



/**
 * This contains Carrier specific logic based on the states/events
 * managed in ServiceStateTracker.
@@ -53,18 +57,70 @@ public class CarrierServiceStateTracker extends Handler {
    private static final int UNINITIALIZED_DELAY_VALUE = -1;
    private Phone mPhone;
    private ServiceStateTracker mSST;

    private final Map<Integer, NotificationType> mNotificationTypeMap = new HashMap<>();
    private int mPreviousSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    public static final int NOTIFICATION_PREF_NETWORK = 1000;
    public static final int NOTIFICATION_EMERGENCY_NETWORK = 1001;

    private final Map<Integer, NotificationType> mNotificationTypeMap = new HashMap<>();

    public CarrierServiceStateTracker(Phone phone, ServiceStateTracker sst) {
        this.mPhone = phone;
        this.mSST = sst;
        phone.getContext().registerReceiver(mBroadcastReceiver, new IntentFilter(
                CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
        // Listen for subscriber changes
        SubscriptionManager.from(mPhone.getContext()).addOnSubscriptionsChangedListener(
                new OnSubscriptionsChangedListener(this.getLooper()) {
                    @Override
                    public void onSubscriptionsChanged() {
                        int subId = mPhone.getSubId();
                        if (mPreviousSubId != subId) {
                            mPreviousSubId = subId;
                            registerPrefNetworkModeObserver();
                        }
                    }
                });

        registerNotificationTypes();
        registerPrefNetworkModeObserver();
    }

    private ContentObserver mPrefNetworkModeObserver = new ContentObserver(this) {
        @Override
        public void onChange(boolean selfChange) {
            handlePrefNetworkModeChanged();
        }
    };

    /**
     * Return preferred network mode observer
     */
    @VisibleForTesting
    public ContentObserver getContentObserver() {
        return mPrefNetworkModeObserver;
    }

    private void registerPrefNetworkModeObserver() {
        int subId = mPhone.getSubId();
        unregisterPrefNetworkModeObserver();
        if (SubscriptionManager.isValidSubscriptionId(subId)) {
            mPhone.getContext().getContentResolver().registerContentObserver(
                    Settings.Global.getUriFor(Settings.Global.PREFERRED_NETWORK_MODE + subId),
                    true,
                    mPrefNetworkModeObserver);
        }
    }

    private void unregisterPrefNetworkModeObserver() {
        mPhone.getContext().getContentResolver().unregisterContentObserver(
                mPrefNetworkModeObserver);
    }

    /**
     * Returns mNotificationTypeMap
     */
    @VisibleForTesting
    public Map<Integer, NotificationType> getNotificationTypeMap() {
        return mNotificationTypeMap;
    }

    private void registerNotificationTypes() {
@@ -152,6 +208,18 @@ public class CarrierServiceStateTracker extends Handler {
    private void handleConfigChanges() {
        for (Map.Entry<Integer, NotificationType> entry : mNotificationTypeMap.entrySet()) {
            NotificationType notificationType = entry.getValue();
            evaluateSendingMessageOrCancelNotification(notificationType);
        }
    }

    private void handlePrefNetworkModeChanged() {
        NotificationType notificationType = mNotificationTypeMap.get(NOTIFICATION_PREF_NETWORK);
        if (notificationType != null) {
            evaluateSendingMessageOrCancelNotification(notificationType);
        }
    }

    private void evaluateSendingMessageOrCancelNotification(NotificationType notificationType) {
        if (evaluateSendingMessage(notificationType)) {
            Message notificationMsg = obtainMessage(notificationType.getTypeId(), null);
            Rlog.i(LOG_TAG, "starting timer for notifications." + notificationType.getTypeId());
@@ -161,7 +229,6 @@ public class CarrierServiceStateTracker extends Handler {
            Rlog.i(LOG_TAG, "canceling notifications: " + notificationType.getTypeId());
        }
    }
    }

    /**
     * This method adds a level of indirection, and was created so we can unit the class.
@@ -240,6 +307,13 @@ public class CarrierServiceStateTracker extends Handler {
        getNotificationManager(context).cancel(notificationId);
    }

    /**
     * Dispose the CarrierServiceStateTracker.
     */
    public void dispose() {
        unregisterPrefNetworkModeObserver();
    }

    /**
     * Class that defines the different types of notifications.
     */
@@ -294,7 +368,7 @@ public class CarrierServiceStateTracker extends Handler {
            }
            this.mDelay = bundle.getInt(
                    CarrierConfigManager.KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT);
            Rlog.i(LOG_TAG, "reading time to delay notification emergency: " + mDelay);
            Rlog.i(LOG_TAG, "reading time to delay notification pref network: " + mDelay);
        }

        public int getDelay() {
+9 −0
Original line number Diff line number Diff line
@@ -581,6 +581,11 @@ public class ServiceStateTracker extends Handler {
            mDataRoamingOffRegistrants.notifyRegistrants();
        }

        // If we are previously in service, we need to notify that we are out of service now.
        if (mSS != null && mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) {
            mNetworkDetachedRegistrants.notifyRegistrants();
        }

        // If we are previously in service, we need to notify that we are out of service now.
        if (mSS != null && mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE) {
            mDetachedRegistrants.notifyRegistrants();
@@ -671,6 +676,10 @@ public class ServiceStateTracker extends Handler {
        mCi.unregisterForImsNetworkStateChanged(this);
        mPhone.getCarrierActionAgent().unregisterForCarrierAction(this,
                CARRIER_ACTION_SET_RADIO_ENABLED);
        if (mCSST != null) {
            mCSST.dispose();
            mCSST = null;
        }
    }

    public boolean getDesiredPowerState() {
+102 −26
Original line number Diff line number Diff line
@@ -16,7 +16,10 @@

package com.android.internal.telephony;

import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;

import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.isA;
@@ -27,18 +30,26 @@ import static org.mockito.Mockito.when;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.HandlerThread;
import android.os.Message;
import android.os.PersistableBundle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
import android.test.mock.MockContentResolver;
import android.test.suitebuilder.annotation.SmallTest;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.Map;

/**
 * Unit tests for {@link com.android.internal.telephony.CarrierServiceStateTracker}.
 */
@@ -46,25 +57,34 @@ public class CarrierServiceStateTrackerTest extends TelephonyTest {
    public static final String LOG_TAG = "CSST";
    public static final int TEST_TIMEOUT = 5000;

    private CarrierServiceStateTracker mSpyCarrierSST;
    private CarrierServiceStateTracker mCarrierSST;
    private CarrierServiceStateTrackerTestHandler mCarrierServiceStateTrackerTestHandler;
    private  CarrierServiceStateTracker.PrefNetworkNotification mPrefNetworkNotification;
    private  CarrierServiceStateTracker.EmergencyNetworkNotification mEmergencyNetworkNotification;
    private FakeContentResolver mFakeContentResolver;

    @Mock Context mContext;
    @Mock ServiceStateTracker mServiceStateTracker;
    @Mock NotificationManager mNotificationManager;
    @Mock Resources mResources;
    NotificationManager mNotificationManager;
    PersistableBundle mBundle;

    private class CarrierServiceStateTrackerTestHandler extends HandlerThread {
    private class FakeContentResolver extends MockContentResolver {
        @Override
        public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
            super.notifyChange(uri, observer, syncToNetwork);
            logd("onChanged(uri=" + uri + ")" + observer);
            if (observer != null) {
                observer.dispatchChange(false, uri);
            }
        }
    }

    private class CarrierServiceStateTrackerTestHandler extends HandlerThread {
        private CarrierServiceStateTrackerTestHandler(String name) {
            super(name);
        }

        @Override
        public void onLooperPrepared() {
            mCarrierSST = spy(new CarrierServiceStateTracker(mPhone, mServiceStateTracker));
            mCarrierSST = new CarrierServiceStateTracker(mPhone, mSST);
            mSpyCarrierSST = spy(mCarrierSST);
            setReady(true);
        }
    }
@@ -74,15 +94,31 @@ public class CarrierServiceStateTrackerTest extends TelephonyTest {
        MockitoAnnotations.initMocks(this);
        logd(LOG_TAG + "Setup!");
        super.setUp(getClass().getSimpleName());
        mBundle = mContextFixture.getCarrierConfigBundle();
        when(mPhone.getSubId()).thenReturn(1);
        mCarrierServiceStateTrackerTestHandler =
                new CarrierServiceStateTrackerTestHandler(getClass().getSimpleName());
        mCarrierServiceStateTrackerTestHandler.start();
        when(mContext.getResources()).thenReturn(mResources);
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        when(mContext.getApplicationInfo()).thenReturn(new ApplicationInfo());
        mFakeContentResolver = new CarrierServiceStateTrackerTest.FakeContentResolver();

        when(mPhone.getContext().getContentResolver()).thenReturn(mFakeContentResolver);

        doReturn(new ApplicationInfo()).when(mContext).getApplicationInfo();

        mNotificationManager = (NotificationManager) mContext.getSystemService(
                Context.NOTIFICATION_SERVICE);

        setDefaultValues();
        waitUntilReady();
    }

    private void setDefaultValues() {
        mBundle.putInt(CarrierConfigManager.KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT,
                0);
        mBundle.putInt(CarrierConfigManager.KEY_EMERGENCY_NOTIFICATION_DELAY_INT,
                0);
    }

    @After
    public void tearDown() throws Exception {
        mCarrierServiceStateTrackerTestHandler.quit();
@@ -93,12 +129,12 @@ public class CarrierServiceStateTrackerTest extends TelephonyTest {
    @SmallTest
    public void testCancelBothNotifications() {
        logd(LOG_TAG + ":testCancelBothNotifications()");
        Message notificationMsg = mCarrierSST.obtainMessage(
        Message notificationMsg = mSpyCarrierSST.obtainMessage(
                CarrierServiceStateTracker.CARRIER_EVENT_DATA_REGISTRATION, null);
        doReturn(false).when(mCarrierSST).evaluateSendingMessage(any());
        doReturn(mNotificationManager).when(mCarrierSST).getNotificationManager(any());
        mCarrierSST.handleMessage(notificationMsg);
        waitForHandlerAction(mCarrierSST, TEST_TIMEOUT);
        doReturn(false).when(mSpyCarrierSST).evaluateSendingMessage(any());
        doReturn(mNotificationManager).when(mSpyCarrierSST).getNotificationManager(any());
        mSpyCarrierSST.handleMessage(notificationMsg);
        waitForHandlerAction(mSpyCarrierSST, TEST_TIMEOUT);
        verify(mNotificationManager).cancel(
                CarrierServiceStateTracker.NOTIFICATION_EMERGENCY_NETWORK);
        verify(mNotificationManager).cancel(
@@ -110,18 +146,58 @@ public class CarrierServiceStateTrackerTest extends TelephonyTest {
    public void testSendBothNotifications() {
        logd(LOG_TAG + ":testSendBothNotifications()");
        Notification.Builder mNotificationBuilder = new Notification.Builder(mContext);
        Message notificationMsg = mCarrierSST.obtainMessage(
        Message notificationMsg = mSpyCarrierSST.obtainMessage(
                CarrierServiceStateTracker.CARRIER_EVENT_DATA_DEREGISTRATION, null);
        doReturn(true).when(mCarrierSST).evaluateSendingMessage(any());
        doReturn(false).when(mCarrierSST).isRadioOffOrAirplaneMode();
        doReturn(0).when(mCarrierSST).getDelay(any());
        doReturn(mNotificationBuilder).when(mCarrierSST).getNotificationBuilder(any());
        doReturn(mNotificationManager).when(mCarrierSST).getNotificationManager(any());
        mCarrierSST.handleMessage(notificationMsg);
        waitForHandlerAction(mCarrierSST, TEST_TIMEOUT);
        doReturn(true).when(mSpyCarrierSST).evaluateSendingMessage(any());
        doReturn(false).when(mSpyCarrierSST).isRadioOffOrAirplaneMode();
        doReturn(0).when(mSpyCarrierSST).getDelay(any());
        doReturn(mNotificationBuilder).when(mSpyCarrierSST).getNotificationBuilder(any());
        doReturn(mNotificationManager).when(mSpyCarrierSST).getNotificationManager(any());
        mSpyCarrierSST.handleMessage(notificationMsg);
        waitForHandlerAction(mSpyCarrierSST, TEST_TIMEOUT);
        verify(mNotificationManager).notify(
                eq(CarrierServiceStateTracker.NOTIFICATION_PREF_NETWORK), isA(Notification.class));
        verify(mNotificationManager).notify(
                eq(CarrierServiceStateTracker.NOTIFICATION_EMERGENCY_NETWORK), any());
    }

    @Test
    @SmallTest
    public void testSendPrefNetworkNotification() {
        logd(LOG_TAG + ":testSendPrefNetworkNotification()");
        Intent intent = new Intent().setAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
        mContext.sendBroadcast(intent);
        waitForMs(300);

        Map<Integer, CarrierServiceStateTracker.NotificationType> notificationTypeMap =
                mCarrierSST.getNotificationTypeMap();
        CarrierServiceStateTracker.NotificationType prefNetworkNotification =
                notificationTypeMap.get(CarrierServiceStateTracker.NOTIFICATION_PREF_NETWORK);
        CarrierServiceStateTracker.NotificationType spyPrefNetworkNotification = spy(
                prefNetworkNotification);
        notificationTypeMap.put(CarrierServiceStateTracker.NOTIFICATION_PREF_NETWORK,
                spyPrefNetworkNotification);
        Notification.Builder mNotificationBuilder = new Notification.Builder(mContext);
        doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mSST.mSS).getVoiceRegState();
        doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mSST.mSS).getDataRegState();
        doReturn(true).when(mSST).isRadioOn();
        doReturn(mNotificationBuilder).when(spyPrefNetworkNotification).getNotificationBuilder();

        String prefNetworkMode = Settings.Global.PREFERRED_NETWORK_MODE + mPhone.getSubId();
        Settings.Global.putInt(mFakeContentResolver, prefNetworkMode,
                RILConstants.NETWORK_MODE_LTE_CDMA_EVDO);
        mFakeContentResolver.notifyChange(
                Settings.Global.getUriFor(prefNetworkMode), mSpyCarrierSST.getContentObserver());
        waitForMs(500);
        verify(mNotificationManager).notify(
                eq(CarrierServiceStateTracker.NOTIFICATION_PREF_NETWORK), isA(Notification.class));

        Settings.Global.putInt(mFakeContentResolver, prefNetworkMode,
                RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
        mFakeContentResolver.notifyChange(
                Settings.Global.getUriFor(prefNetworkMode), mSpyCarrierSST.getContentObserver());
        waitForMs(500);
        verify(mNotificationManager, atLeast(1)).cancel(
                CarrierServiceStateTracker.NOTIFICATION_PREF_NETWORK);
    }
}