diff options
Diffstat (limited to 'tests/src/com/android/ims/FeatureConnectorTest.java')
-rw-r--r-- | tests/src/com/android/ims/FeatureConnectorTest.java | 422 |
1 files changed, 422 insertions, 0 deletions
diff --git a/tests/src/com/android/ims/FeatureConnectorTest.java b/tests/src/com/android/ims/FeatureConnectorTest.java new file mode 100644 index 00000000..e560ae66 --- /dev/null +++ b/tests/src/com/android/ims/FeatureConnectorTest.java @@ -0,0 +1,422 @@ +/* + * 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.ims; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doReturn; +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.Context; +import android.content.pm.PackageManager; +import android.os.IBinder; +import android.telephony.ims.ImsService; +import android.telephony.ims.aidl.IImsConfig; +import android.telephony.ims.aidl.IImsRegistration; +import android.telephony.ims.aidl.ISipTransport; +import android.telephony.ims.feature.ImsFeature; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import com.android.ims.internal.IImsServiceFeatureCallback; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(AndroidJUnit4.class) +public class FeatureConnectorTest extends ImsTestBase { + + private static class TestFeatureConnection extends FeatureConnection { + + public TestFeatureConnection(Context context, int slotId, IImsConfig c, + IImsRegistration r, ISipTransport s) { + super(context, slotId, c, r, s); + } + + @Override + protected Integer retrieveFeatureState() { + return null; + } + + @Override + protected void onFeatureCapabilitiesUpdated(long capabilities) { + } + } + + private static class TestManager implements FeatureUpdates { + + public IImsServiceFeatureCallback callback; + public TestFeatureConnection connection; + private Context mContext; + private int mPhoneId; + + + public TestManager(Context context, int phoneId) { + mContext = context; + mPhoneId = phoneId; + } + + @Override + public void registerFeatureCallback(int slotId, IImsServiceFeatureCallback cb) { + callback = cb; + } + + @Override + public void unregisterFeatureCallback(IImsServiceFeatureCallback cb) { + callback = null; + } + + @Override + public void associate(ImsFeatureContainer c) { + connection = new TestFeatureConnection(mContext, mPhoneId, c.imsConfig, + c.imsRegistration, c.sipTransport); + connection.setBinder(c.imsFeature); + } + + @Override + public void invalidate() { + connection = null; + } + + @Override + public void updateFeatureState(int state) { + assertNotNull(connection); + connection.updateFeatureState(state); + } + + @Override + public void updateFeatureCapabilities(long capabilities) { + connection.updateFeatureCapabilities(capabilities); + } + } + + private FeatureConnector<TestManager> mFeatureConnector; + private TestManager mTestManager; + @Mock private FeatureConnector.Listener<TestManager> mListener; + @Mock private IBinder feature; + @Mock private IImsRegistration reg; + @Mock private IImsConfig config; + @Mock private ISipTransport transport; + + private static final int PHONE_ID = 1; + private static final long TEST_CAPS = ImsService.CAPABILITY_EMERGENCY_OVER_MMTEL; + + @Before + public void setUp() throws Exception { + super.setUp(); + setImsSupportedFeature(true); + mTestManager = new TestManager(mContext, PHONE_ID); + when(feature.isBinderAlive()).thenReturn(true); + } + + @After + public void tearDown() throws Exception { + super.tearDown(); + } + + @Test + @SmallTest + public void testConnect() throws Exception { + createFeatureConnector(); + mFeatureConnector.connect(); + assertNotNull("connect should trigger the callback registration", mTestManager.callback); + + // simulate callback from ImsResolver + mTestManager.callback.imsFeatureCreated(createContainer()); + assertNotNull(mTestManager.connection); + assertEquals(TEST_CAPS, mTestManager.connection.getFeatureCapabilties()); + verify(mListener, never()).connectionReady(any()); + verify(mListener, never()).connectionUnavailable(anyInt()); + + // simulate callback from ImsResolver + mTestManager.callback.imsStatusChanged(ImsFeature.STATE_READY); + verify(mListener).connectionReady(mTestManager); + verify(mListener, never()).connectionUnavailable(anyInt()); + } + + @Test + @SmallTest + public void testConnectNotSupported() { + createFeatureConnector(); + // set not supported + setImsSupportedFeature(false); + + mFeatureConnector.connect(); + assertNull("connect should not the callback registration if not supported", + mTestManager.callback); + verify(mListener).connectionUnavailable( + FeatureConnector.UNAVAILABLE_REASON_IMS_UNSUPPORTED); + } + + @Test + @SmallTest + public void testConnectReadyNotReady() throws Exception { + createFeatureConnector(); + mFeatureConnector.connect(); + assertNotNull("connect should trigger the callback registration", mTestManager.callback); + // simulate callback from ImsResolver + mTestManager.callback.imsFeatureCreated(createContainer()); + mTestManager.callback.imsStatusChanged(ImsFeature.STATE_READY); + verify(mListener).connectionReady(mTestManager); + verify(mListener, never()).connectionUnavailable(anyInt()); + + mTestManager.callback.imsStatusChanged(ImsFeature.STATE_UNAVAILABLE); + assertNotNull("When not ready, the callback should still be registered", + mTestManager.callback); + assertNotNull("Do not invalidate the connection if not ready", mTestManager.connection); + verify(mListener).connectionReady(mTestManager); + verify(mListener).connectionUnavailable(FeatureConnector.UNAVAILABLE_REASON_NOT_READY); + } + + @Test + @SmallTest + public void testConnectReadyAndInitializing() throws Exception { + ArrayList<Integer> filterList = new ArrayList<>(); + filterList.add(ImsFeature.STATE_READY); + filterList.add(ImsFeature.STATE_INITIALIZING); + createFeatureConnector(filterList); + mFeatureConnector.connect(); + assertNotNull("connect should trigger the callback registration", mTestManager.callback); + // simulate callback from ImsResolver + mTestManager.callback.imsFeatureCreated(createContainer()); + verify(mListener, never()).connectionReady(mTestManager); + verify(mListener, never()).connectionUnavailable(anyInt()); + + mTestManager.callback.imsStatusChanged(ImsFeature.STATE_INITIALIZING); + assertNotNull("When not ready, the callback should still be registered", + mTestManager.callback); + assertNotNull("Do not invalidate the connection if not ready", mTestManager.connection); + verify(mListener).connectionReady(mTestManager); + verify(mListener, never()).connectionUnavailable(anyInt()); + + mTestManager.callback.imsStatusChanged(ImsFeature.STATE_READY); + assertNotNull("When not ready, the callback should still be registered", + mTestManager.callback); + assertNotNull("Do not invalidate the connection if not ready", mTestManager.connection); + // Should not notify ready multiple times + verify(mListener).connectionReady(mTestManager); + verify(mListener, never()).connectionUnavailable(anyInt()); + } + + @Test + @SmallTest + public void testConnectReadyAndUnavailable() throws Exception { + ArrayList<Integer> filterList = new ArrayList<>(); + filterList.add(ImsFeature.STATE_READY); + filterList.add(ImsFeature.STATE_INITIALIZING); + filterList.add(ImsFeature.STATE_UNAVAILABLE); + createFeatureConnector(filterList); + mFeatureConnector.connect(); + assertNotNull("connect should trigger the callback registration", mTestManager.callback); + // simulate callback from ImsResolver + mTestManager.callback.imsFeatureCreated(createContainer()); + verify(mListener).connectionReady(mTestManager); + verify(mListener, never()).connectionUnavailable(anyInt()); + + mTestManager.callback.imsStatusChanged(ImsFeature.STATE_UNAVAILABLE); + assertNotNull("When not ready, the callback should still be registered", + mTestManager.callback); + assertNotNull("Do not invalidate the connection if not ready", mTestManager.connection); + verify(mListener).connectionReady(mTestManager); + verify(mListener, never()).connectionUnavailable(anyInt()); + + mTestManager.callback.imsStatusChanged(ImsFeature.STATE_INITIALIZING); + assertNotNull("When not ready, the callback should still be registered", + mTestManager.callback); + assertNotNull("Do not invalidate the connection if not ready", mTestManager.connection); + // Should not notify ready multiple times + verify(mListener).connectionReady(mTestManager); + verify(mListener, never()).connectionUnavailable(anyInt()); + + mTestManager.callback.imsStatusChanged(ImsFeature.STATE_READY); + // Should not notify ready multiple times + verify(mListener).connectionReady(mTestManager); + verify(mListener, never()).connectionUnavailable(anyInt()); + } + + @Test + @SmallTest + public void testCantConnectToServer() throws Exception { + ArrayList<Integer> filterList = new ArrayList<>(); + filterList.add(ImsFeature.STATE_READY); + filterList.add(ImsFeature.STATE_INITIALIZING); + filterList.add(ImsFeature.STATE_UNAVAILABLE); + createFeatureConnector(filterList); + + mFeatureConnector.connect(); + mTestManager.callback.imsFeatureRemoved( + FeatureConnector.UNAVAILABLE_REASON_SERVER_UNAVAILABLE); + verify(mListener).connectionUnavailable( + FeatureConnector.UNAVAILABLE_REASON_SERVER_UNAVAILABLE); + + // Clear callback and ensure that the second connect tries to register a callback. + mTestManager.registerFeatureCallback(PHONE_ID, null); + mFeatureConnector.connect(); + assertNotNull("The register request should happen the second time as well.", + mTestManager.callback); + mTestManager.callback.imsFeatureRemoved( + FeatureConnector.UNAVAILABLE_REASON_SERVER_UNAVAILABLE); + // In the special case that UNAVAILABLE_REASON_SERVER_UNAVAILABLE is returned, we should get + // an unavailable callback every time because it will require connect to be called again. + verify(mListener,times(2)).connectionUnavailable( + FeatureConnector.UNAVAILABLE_REASON_SERVER_UNAVAILABLE); + } + + @Test + @SmallTest + public void testConnectReadyRemovedReady() throws Exception { + createFeatureConnector(); + mFeatureConnector.connect(); + assertNotNull("connect should trigger the callback registration", mTestManager.callback); + // simulate callback from ImsResolver + mTestManager.callback.imsFeatureCreated(createContainer()); + mTestManager.callback.imsStatusChanged(ImsFeature.STATE_READY); + verify(mListener).connectionReady(mTestManager); + verify(mListener, never()).connectionUnavailable(anyInt()); + + mTestManager.callback.imsFeatureRemoved(FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED); + assertNotNull("When not ready, the callback should still be registered", + mTestManager.callback); + verify(mListener).connectionReady(mTestManager); + verify(mListener).connectionUnavailable(FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED); + + mTestManager.callback.imsFeatureCreated(createContainer()); + mTestManager.callback.imsStatusChanged(ImsFeature.STATE_READY); + verify(mListener, times(2)).connectionReady(mTestManager); + verify(mListener).connectionUnavailable(FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED); + } + + @Test + @SmallTest + public void testConnectDisconnect() throws Exception { + createFeatureConnector(); + mFeatureConnector.connect(); + assertNotNull("connect should trigger the callback registration", mTestManager.callback); + // simulate callback from ImsResolver + mTestManager.callback.imsFeatureCreated(createContainer()); + mTestManager.callback.imsStatusChanged(ImsFeature.STATE_READY); + IImsServiceFeatureCallback oldCb = mTestManager.callback; + TestFeatureConnection testFc = mTestManager.connection; + + mFeatureConnector.disconnect(); + assertNull(mTestManager.callback); + assertNull(mTestManager.connection); + verify(mListener).connectionReady(mTestManager); + verify(mListener).connectionUnavailable(FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED); + + // make sure status/caps updates do not trigger more events after disconnect + oldCb.imsStatusChanged(ImsFeature.STATE_READY); + oldCb.imsStatusChanged(ImsFeature.STATE_UNAVAILABLE); + oldCb.updateCapabilities(0); + assertEquals(TEST_CAPS, testFc.getFeatureCapabilties()); + verify(mListener).connectionReady(mTestManager); + verify(mListener).connectionUnavailable(FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED); + } + + @Test + @SmallTest + public void testConnectDisconnectConnect() throws Exception { + createFeatureConnector(); + mFeatureConnector.connect(); + assertNotNull("connect should trigger the callback registration", mTestManager.callback); + // simulate callback from ImsResolver + mTestManager.callback.imsFeatureCreated(createContainer()); + mTestManager.callback.imsStatusChanged(ImsFeature.STATE_READY); + + mFeatureConnector.disconnect(); + assertNull(mTestManager.callback); + assertNull(mTestManager.connection); + verify(mListener).connectionReady(mTestManager); + verify(mListener).connectionUnavailable(FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED); + + mFeatureConnector.connect(); + assertNotNull(mTestManager.callback); + // simulate callback from ImsResolver + mTestManager.callback.imsFeatureCreated(createContainer()); + mTestManager.callback.imsStatusChanged(ImsFeature.STATE_READY); + assertNotNull(mTestManager.connection); + verify(mListener, times(2)).connectionReady(mTestManager); + verify(mListener).connectionUnavailable(FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED); + } + + @Test + @SmallTest + public void testUpdateCapabilities() throws Exception { + createFeatureConnector(); + mFeatureConnector.connect(); + assertNotNull("connect should trigger the callback registration", mTestManager.callback); + // simulate callback from ImsResolver + mTestManager.callback.imsFeatureCreated(createContainer()); + mTestManager.callback.imsStatusChanged(ImsFeature.STATE_READY); + assertEquals(TEST_CAPS, mTestManager.connection.getFeatureCapabilties()); + mTestManager.callback.updateCapabilities(0); + assertEquals(0, mTestManager.connection.getFeatureCapabilties()); + } + + @Test + @SmallTest + public void testUpdateStatus() throws Exception { + createFeatureConnector(); + mFeatureConnector.connect(); + assertNotNull("connect should trigger the callback registration", mTestManager.callback); + // simulate callback from ImsResolver + mTestManager.callback.imsFeatureCreated(createContainer()); + mTestManager.callback.imsStatusChanged(ImsFeature.STATE_READY); + assertEquals(ImsFeature.STATE_READY, mTestManager.connection.getFeatureState()); + } + + private void setImsSupportedFeature(boolean isSupported) { + if(isSupported) { + mContextFixture.addSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS); + } else { + mContextFixture.removeSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS); + } + } + + private ImsFeatureContainer createContainer() { + ImsFeatureContainer c = new ImsFeatureContainer(feature, config, reg, transport, + TEST_CAPS); + c.setState(ImsFeature.STATE_UNAVAILABLE); + return c; + } + + private void createFeatureConnector() { + ArrayList<Integer> filter = new ArrayList<>(); + filter.add(ImsFeature.STATE_READY); + createFeatureConnector(filter); + } + + private void createFeatureConnector(List<Integer> featureReadyFilter) { + mFeatureConnector = new FeatureConnector<>(mContext, PHONE_ID, + (c, p) -> mTestManager, "Test", featureReadyFilter, mListener, Runnable::run); + } +} |