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

Commit 46f7ae69 authored by Sarah Chin's avatar Sarah Chin Committed by android-build-merger
Browse files

Merge "Remove Thread.sleep in Telephony unittests" into stage-aosp-master am: 5cab9411

am: ae4b6a8b

Change-Id: Iaa3d124cf491f7a17f11c2328295feb5b9fb8996
parents e1f95f42 ae4b6a8b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ android_test {
        "services.net",
        "telephony-common",
        "truth-prebuilt",
        "testables",
    ],

    platform_apis: true,
+18 −33
Original line number Diff line number Diff line
@@ -29,17 +29,19 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
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.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;

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

import java.util.Map;
@@ -47,32 +49,19 @@ import java.util.Map;
/**
 * Unit tests for {@link com.android.internal.telephony.CarrierServiceStateTracker}.
 */
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
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 static final int SUB_ID = 1;

    NotificationManager mNotificationManager;
    PersistableBundle mBundle;

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

        @Override
        public void onLooperPrepared() {
            mCarrierSST = new CarrierServiceStateTracker(mPhone, mSST);
            mSpyCarrierSST = spy(mCarrierSST);
            setReady(true);
        }
    }

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
@@ -80,27 +69,23 @@ public class CarrierServiceStateTrackerTest extends TelephonyTest {
        super.setUp(getClass().getSimpleName());
        mBundle = mContextFixture.getCarrierConfigBundle();
        when(mPhone.getSubId()).thenReturn(SUB_ID);
        mCarrierServiceStateTrackerTestHandler =
                new CarrierServiceStateTrackerTestHandler(getClass().getSimpleName());
        mCarrierServiceStateTrackerTestHandler.start();
        mCarrierSST = new CarrierServiceStateTracker(mPhone, mSST);
        mSpyCarrierSST = spy(mCarrierSST);

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

        setDefaultValues();
        waitUntilReady();
        processAllMessages();
    }

    private void setDefaultValues() {
        mBundle.putInt(CarrierConfigManager.KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT,
                0);
        mBundle.putInt(CarrierConfigManager.KEY_EMERGENCY_NOTIFICATION_DELAY_INT,
                0);
        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();
        super.tearDown();
    }

@@ -113,7 +98,7 @@ public class CarrierServiceStateTrackerTest extends TelephonyTest {
        doReturn(false).when(mSpyCarrierSST).evaluateSendingMessage(any());
        doReturn(mNotificationManager).when(mSpyCarrierSST).getNotificationManager(any());
        mSpyCarrierSST.handleMessage(notificationMsg);
        waitForHandlerAction(mSpyCarrierSST, TEST_TIMEOUT);
        processAllMessages();
        verify(mNotificationManager).cancel(
                CarrierServiceStateTracker.EMERGENCY_NOTIFICATION_TAG, SUB_ID);
        verify(mNotificationManager).cancel(
@@ -134,7 +119,7 @@ public class CarrierServiceStateTrackerTest extends TelephonyTest {
        doReturn(mNotificationBuilder).when(mSpyCarrierSST).getNotificationBuilder(any());
        doReturn(mNotificationManager).when(mSpyCarrierSST).getNotificationManager(any());
        mSpyCarrierSST.handleMessage(notificationMsg);
        waitForHandlerAction(mSpyCarrierSST, TEST_TIMEOUT);
        processAllMessages();
        verify(mNotificationManager).notify(
                eq(CarrierServiceStateTracker.EMERGENCY_NOTIFICATION_TAG),
                eq(SUB_ID), isA(Notification.class));
@@ -149,7 +134,7 @@ public class CarrierServiceStateTrackerTest extends TelephonyTest {
        logd(LOG_TAG + ":testSendPrefNetworkNotification()");
        Intent intent = new Intent().setAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
        mContext.sendBroadcast(intent);
        waitForLastHandlerAction(mCarrierServiceStateTrackerTestHandler.getThreadHandler());
        processAllMessages();

        Map<Integer, CarrierServiceStateTracker.NotificationType> notificationTypeMap =
                mCarrierSST.getNotificationTypeMap();
@@ -170,7 +155,7 @@ public class CarrierServiceStateTrackerTest extends TelephonyTest {
                RILConstants.NETWORK_MODE_LTE_CDMA_EVDO);
        mSpyCarrierSST.getContentObserver().dispatchChange(false,
                Settings.Global.getUriFor(prefNetworkMode));
        waitForLastHandlerAction(mCarrierServiceStateTrackerTestHandler.getThreadHandler());
        processAllMessages();
        verify(mNotificationManager, atLeast(1)).notify(
                eq(CarrierServiceStateTracker.PREF_NETWORK_NOTIFICATION_TAG),
                eq(SUB_ID), isA(Notification.class));
@@ -180,7 +165,7 @@ public class CarrierServiceStateTrackerTest extends TelephonyTest {
                RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
        mSpyCarrierSST.getContentObserver().dispatchChange(false,
                Settings.Global.getUriFor(prefNetworkMode));
        waitForLastHandlerAction(mCarrierServiceStateTrackerTestHandler.getThreadHandler());
        processAllMessages();
        verify(mNotificationManager, atLeast(1)).cancel(
                CarrierServiceStateTracker.PREF_NETWORK_NOTIFICATION_TAG, SUB_ID);
    }
@@ -191,7 +176,7 @@ public class CarrierServiceStateTrackerTest extends TelephonyTest {
        logd(LOG_TAG + ":testSendEmergencyNetworkNotification()");
        Intent intent = new Intent().setAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
        mContext.sendBroadcast(intent);
        waitForLastHandlerAction(mCarrierServiceStateTrackerTestHandler.getThreadHandler());
        processAllMessages();

        Map<Integer, CarrierServiceStateTracker.NotificationType> notificationTypeMap =
                mCarrierSST.getNotificationTypeMap();
@@ -210,14 +195,14 @@ public class CarrierServiceStateTrackerTest extends TelephonyTest {
        Message notificationMsg = mSpyCarrierSST.obtainMessage(
                CarrierServiceStateTracker.CARRIER_EVENT_IMS_CAPABILITIES_CHANGED, null);
        mSpyCarrierSST.handleMessage(notificationMsg);
        waitForHandlerAction(mSpyCarrierSST, TEST_TIMEOUT);
        processAllMessages();
        verify(mNotificationManager).notify(
                eq(CarrierServiceStateTracker.EMERGENCY_NOTIFICATION_TAG),
                eq(SUB_ID), isA(Notification.class));

        doReturn(false).when(mPhone).isWifiCallingEnabled();
        mSpyCarrierSST.handleMessage(notificationMsg);
        waitForHandlerAction(mSpyCarrierSST, TEST_TIMEOUT);
        processAllMessages();
        verify(mNotificationManager, atLeast(2)).cancel(
                CarrierServiceStateTracker.EMERGENCY_NOTIFICATION_TAG, SUB_ID);
    }
+97 −182

File changed.

Preview size limit exceeded, changes collapsed.

+108 −2
Original line number Diff line number Diff line
@@ -45,6 +45,8 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.IDeviceIdleController;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
import android.os.RegistrantList;
import android.os.ServiceManager;
import android.provider.BlockedNumberContract;
@@ -60,6 +62,7 @@ import android.telephony.euicc.EuiccManager;
import android.telephony.ims.ImsCallProfile;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
import android.testing.TestableLooper;
import android.util.Log;
import android.util.Singleton;

@@ -101,6 +104,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -116,6 +120,23 @@ public abstract class TelephonyTest {
            new ArrayList<String>(), EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
            EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);

    private static final Field MESSAGE_QUEUE_FIELD;
    private static final Field MESSAGE_WHEN_FIELD;
    private static final Field MESSAGE_NEXT_FIELD;

    static {
        try {
            MESSAGE_QUEUE_FIELD = MessageQueue.class.getDeclaredField("mMessages");
            MESSAGE_QUEUE_FIELD.setAccessible(true);
            MESSAGE_WHEN_FIELD = Message.class.getDeclaredField("when");
            MESSAGE_WHEN_FIELD.setAccessible(true);
            MESSAGE_NEXT_FIELD = Message.class.getDeclaredField("next");
            MESSAGE_NEXT_FIELD.setAccessible(true);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException("Failed to initialize TelephonyTest", e);
        }
    }

    @Mock
    protected GsmCdmaPhone mPhone;
    @Mock
@@ -261,7 +282,8 @@ public abstract class TelephonyTest {
    private boolean mReady;
    protected HashMap<String, IBinder> mServiceManagerMockedServices = new HashMap<>();
    protected Phone[] mPhones;

    protected List<TestableLooper> mTestableLoopers = new ArrayList<>();
    protected TestableLooper mTestableLooper;

    protected HashMap<Integer, ImsManager> mImsManagerInstances = new HashMap<>();
    private HashMap<InstanceKey, Object> mOldInstances = new HashMap<InstanceKey, Object>();
@@ -592,12 +614,24 @@ public abstract class TelephonyTest {
        assertNotNull("Failed to set up SubscriptionController singleton",
                SubscriptionController.getInstance());
        setReady(false);
        // create default TestableLooper for test and add to list of monitored loopers
        mTestableLooper = TestableLooper.get(TelephonyTest.this);
        if (mTestableLooper != null) {
            monitorTestableLooper(mTestableLooper);
        }
    }

    protected void tearDown() throws Exception {

        // unmonitor TestableLooper
        if (mTestableLooper != null) {
            unmonitorTestableLooper(mTestableLooper);
        }
        mSimulatedCommands.dispose();

        // destroy all created TestableLoopers so they can be reused
        for (TestableLooper looper : mTestableLoopers) {
            looper.destroy();
        }
        SharedPreferences sharedPreferences = mContext.getSharedPreferences((String) null, 0);
        sharedPreferences.edit().clear().commit();

@@ -701,6 +735,7 @@ public abstract class TelephonyTest {
                "mContentProvider", providerHolder, iContentProvider);
    }

    // TODO(b/138886216): remove method after refactor
    protected final void waitForHandlerAction(Handler h, long timeoutMillis) {
        final CountDownLatch lock = new CountDownLatch(1);
        h.post(lock::countDown);
@@ -739,6 +774,7 @@ public abstract class TelephonyTest {
        assertTrue("Handler was not empty before timeout elapsed", timeoutCount < 5);
    }

    // TODO(b/138886216): remove method after refactor
    protected final void waitForHandlerActionDelayed(Handler h, long timeoutMillis, long delayMs) {
        final CountDownLatch lock = new CountDownLatch(1);
        h.postDelayed(lock::countDown, delayMs);
@@ -766,4 +802,74 @@ public abstract class TelephonyTest {
        }
        return null;
    }

    /**
     * Add a TestableLooper to the list of monitored loopers
     * @param looper added if it doesn't already exist
     */
    public void monitorTestableLooper(TestableLooper looper) {
        if (!mTestableLoopers.contains(looper)) {
            mTestableLoopers.add(looper);
        }
    }

    /**
     * Remove a TestableLooper from the list of monitored loopers
     * @param looper removed if it does exist
     */
    public void unmonitorTestableLooper(TestableLooper looper) {
        if (mTestableLoopers.contains(looper)) {
            mTestableLoopers.remove(looper);
        }
    }

    /**
     * Handle all messages that can be processed at the current time
     * for all monitored TestableLoopers
     */
    public void processAllMessages() {
        if (mTestableLoopers.isEmpty()) {
            fail("mTestableLoopers is empty. Please make sure to add @RunWithLooper annotation");
        }
        while (!areAllTestableLoopersIdle()) {
            for (TestableLooper looper : mTestableLoopers) looper.processAllMessages();
        }
    }

    /**
     * Check if there are any messages to be processed in any monitored TestableLooper
     * Delayed messages to be handled at a later time will be ignored
     * @return true if there are no messages that can be handled at the current time
     *         across all monitored TestableLoopers
     */
    private boolean areAllTestableLoopersIdle() {
        for (TestableLooper looper : mTestableLoopers) {
            if (!looper.getLooper().getQueue().isIdle()) return false;
        }
        return true;
    }

    /**
     * Effectively moves time forward by reducing the time of all messages
     * for all monitored TestableLoopers
     * @param milliSeconds number of milliseconds to move time forward by
     */
    public void moveTimeForward(long milliSeconds) {
        for (TestableLooper looper : mTestableLoopers) {
            MessageQueue queue = looper.getLooper().getQueue();
            try {
                Message msg = (Message) MESSAGE_QUEUE_FIELD.get(queue);
                while (msg != null) {
                    long updatedWhen = msg.getWhen() - milliSeconds;
                    if (updatedWhen < 0) {
                        updatedWhen = 0;
                    }
                    MESSAGE_WHEN_FIELD.set(msg, updatedWhen);
                    msg = (Message) MESSAGE_NEXT_FIELD.get(msg);
                }
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Access failed in TelephonyTest", e);
            }
        }
    }
}