[RCS] Integrate the PresencePublisher in UserCapabilityExchangeImpl

Implement the interface PresencePublisher which was called from PresencePublication

Bug: 139262111
Test: atest UserCapabilityExchangeImplTest
Change-Id: I6f0d1ec3eec3aadfbf493b44771ae176536f7e15
diff --git a/tests/src/com/android/TestContext.java b/tests/src/com/android/TestContext.java
index c190be9..b1c6923 100644
--- a/tests/src/com/android/TestContext.java
+++ b/tests/src/com/android/TestContext.java
@@ -20,6 +20,7 @@
 import static org.mockito.Mockito.doReturn;
 
 import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -29,6 +30,7 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.telephony.ims.ImsManager;
 import android.test.mock.MockContext;
 
 import org.mockito.Mock;
@@ -42,6 +44,7 @@
     @Mock TelecomManager mMockTelecomManager;
     @Mock TelephonyManager mMockTelephonyManager;
     @Mock SubscriptionManager mMockSubscriptionManager;
+    @Mock ImsManager mMockImsManager;
 
     private PersistableBundle mCarrierConfig = new PersistableBundle();
 
@@ -89,6 +92,11 @@
     }
 
     @Override
+    public ContentResolver getContentResolver() {
+        return null;
+    }
+
+    @Override
     public Object getSystemService(String name) {
         switch (name) {
             case (Context.CARRIER_CONFIG_SERVICE) : {
@@ -103,6 +111,9 @@
             case (Context.TELEPHONY_SUBSCRIPTION_SERVICE) : {
                 return mMockSubscriptionManager;
             }
+            case(Context.TELEPHONY_IMS_SERVICE) : {
+                return mMockImsManager;
+            }
         }
         return null;
     }
diff --git a/tests/src/com/android/services/telephony/rcs/UserCapabilityExchangeImplTest.java b/tests/src/com/android/services/telephony/rcs/UserCapabilityExchangeImplTest.java
new file mode 100644
index 0000000..2457d28
--- /dev/null
+++ b/tests/src/com/android/services/telephony/rcs/UserCapabilityExchangeImplTest.java
@@ -0,0 +1,257 @@
+/*
+ * 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.services.telephony.rcs;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.Uri;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.RemoteCallbackList;
+import android.telephony.ims.ImsManager;
+import android.telephony.ims.ImsMmTelManager;
+import android.telephony.ims.RcsContactUceCapability;
+import android.telephony.ims.RegistrationManager;
+import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
+import android.telephony.ims.stub.RcsCapabilityExchange;
+import android.telephony.ims.stub.RcsPresenceExchangeImplBase;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+import com.android.ims.RcsFeatureManager;
+import com.android.ims.RcsFeatureManager.RcsFeatureCallbacks;
+import com.android.ims.ResultCode;
+import com.android.service.ims.presence.PresenceBase;
+import com.android.service.ims.presence.PresencePublication;
+import com.android.service.ims.presence.PresencePublisher;
+import com.android.service.ims.presence.PresenceSubscriber;
+import com.android.service.ims.presence.SubscribePublisher;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+import java.util.concurrent.Executor;
+
+@RunWith(AndroidJUnit4.class)
+public class UserCapabilityExchangeImplTest extends TelephonyTestBase {
+
+    private int  mSlotId = 0;
+    private int mSubId = 1;
+    private int mUpdatedSubId = 2;
+
+    @Captor ArgumentCaptor<IRcsUcePublishStateCallback> mPublishStateCallbacksCaptor;
+
+    @Mock PresencePublication mPresencePublication;
+    @Mock PresenceSubscriber mPresenceSubscriber;
+    @Mock RcsFeatureManager mRcsFeatureManager;
+    @Mock ImsMmTelManager mImsMmTelManager;
+    @Mock RemoteCallbackList<IRcsUcePublishStateCallback> mPublishStateCallbacks;
+
+    private Looper mLooper;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+
+        ImsManager imsManager =
+                (ImsManager) mContext.getSystemService(Context.TELEPHONY_IMS_SERVICE);
+        when(imsManager.getImsMmTelManager(mSubId)).thenReturn(mImsMmTelManager);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        super.tearDown();
+
+        if (mLooper != null) {
+            mLooper.quit();
+            mLooper = null;
+        }
+    }
+
+    @Test
+    public void testServiceConnected() throws Exception {
+        UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
+        uceImpl.onRcsConnected(mRcsFeatureManager);
+
+        verify(mRcsFeatureManager).addFeatureListenerCallback(any(RcsFeatureCallbacks.class));
+        verify(mPresencePublication).updatePresencePublisher(any(PresencePublisher.class));
+        verify(mPresenceSubscriber).updatePresenceSubscriber(any(SubscribePublisher.class));
+    }
+
+    @Test
+    public void testServiceDisconnected() throws Exception {
+        UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
+        uceImpl.onRcsDisconnected();
+
+        verify(mPresencePublication).removePresencePublisher();
+        verify(mPresenceSubscriber).removePresenceSubscriber();
+    }
+
+    @Test
+    public void testSubscriptionUpdated() throws Exception {
+        UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
+        uceImpl.onAssociatedSubscriptionUpdated(mUpdatedSubId);
+
+        verify(mImsMmTelManager).registerImsRegistrationCallback(any(Executor.class),
+                any(RegistrationManager.RegistrationCallback.class));
+        verify(mImsMmTelManager).registerMmTelCapabilityCallback(any(Executor.class),
+                any(ImsMmTelManager.CapabilityCallback.class));
+        verify(mPresencePublication).handleAssociatedSubscriptionChanged(mUpdatedSubId);
+        verify(mPresenceSubscriber).handleAssociatedSubscriptionChanged(mUpdatedSubId);
+    }
+
+    @Test
+    public void testUcePublishStateRetrieval() throws Exception {
+        UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
+        uceImpl.getUcePublishState();
+
+        verify(mPresencePublication).getPublishState();
+    }
+
+    @Test
+    public void testRegisterPublishStateCallbacks() throws Exception {
+        UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
+        uceImpl.registerPublishStateCallback(any(IRcsUcePublishStateCallback.class));
+        verify(mPublishStateCallbacks).register(mPublishStateCallbacksCaptor.capture());
+    }
+
+    @Test
+    public void testOnNotifyUpdateCapabilities() throws Exception {
+        UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
+        uceImpl.onRcsConnected(mRcsFeatureManager);
+
+        int triggerType = RcsPresenceExchangeImplBase.CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN;
+        uceImpl.mRcsFeatureCallback.onNotifyUpdateCapabilities(triggerType);
+        waitForMs(1000);
+
+        verify(mPresencePublication).onStackPublishRequested(triggerType);
+    }
+
+    @Test
+    public void testRequestPublicationWithSuccessfulResponse() throws Exception {
+        int taskId = 1;
+        int sipResponse = 200;
+        Uri contact = Uri.fromParts("sip", "test", null);
+        RcsContactUceCapability.Builder builder = new RcsContactUceCapability.Builder(contact);
+        RcsContactUceCapability capability = builder.build();
+
+        UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
+        uceImpl.onRcsConnected(mRcsFeatureManager);
+
+        doAnswer(invocation -> {
+            uceImpl.mRcsFeatureCallback.onCommandUpdate(RcsCapabilityExchange.COMMAND_CODE_SUCCESS,
+                    taskId);
+            uceImpl.mRcsFeatureCallback.onNetworkResponse(sipResponse, null, taskId);
+            return null;
+        }).when(mRcsFeatureManager).requestPublication(capability, taskId);
+
+        // Request publication
+        int result = uceImpl.requestPublication(capability, contact.toString(), taskId);
+
+        assertEquals(ResultCode.SUCCESS, result);
+        verify(mPresencePublication).onCommandStatusUpdated(taskId, taskId, ResultCode.SUCCESS);
+        verify(mPresencePublication).onSipResponse(taskId, sipResponse, null);
+    }
+
+    @Test
+    public void testRequestPublicationWithFailedResponse() throws Exception {
+        int taskId = 1;
+        Uri contact = Uri.fromParts("sip", "test", null);
+        RcsContactUceCapability.Builder builder = new RcsContactUceCapability.Builder(contact);
+        RcsContactUceCapability capability = builder.build();
+
+        UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
+        uceImpl.onRcsConnected(mRcsFeatureManager);
+
+        doAnswer(invocation -> {
+            uceImpl.mRcsFeatureCallback.onCommandUpdate(
+                    RcsCapabilityExchange.COMMAND_CODE_GENERIC_FAILURE, taskId);
+            return null;
+        }).when(mRcsFeatureManager).requestPublication(capability, taskId);
+
+        // Request publication
+        int result = uceImpl.requestPublication(capability, contact.toString(), taskId);
+
+        assertEquals(ResultCode.SUCCESS, result);
+        verify(mPresencePublication).onCommandStatusUpdated(taskId, taskId,
+                ResultCode.PUBLISH_GENERIC_FAILURE);
+    }
+
+    @Test
+    public void testUpdatePublisherState() throws Exception {
+        IRcsUcePublishStateCallback callback = Mockito.mock(IRcsUcePublishStateCallback.class);
+        doAnswer(invocation -> {
+            callback.onPublishStateChanged(anyInt());
+            return null;
+        }).when(mPublishStateCallbacks).broadcast(any());
+
+        UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
+        uceImpl.onRcsConnected(mRcsFeatureManager);
+        uceImpl.registerPublishStateCallback(callback);
+        uceImpl.updatePublisherState(PresenceBase.PUBLISH_STATE_200_OK);
+
+        assertEquals(PresenceBase.PUBLISH_STATE_200_OK, uceImpl.getPublisherState());
+        verify(callback).onPublishStateChanged(anyInt());
+    }
+
+    @Test
+    public void testUnpublish() throws Exception {
+        IRcsUcePublishStateCallback callback = Mockito.mock(IRcsUcePublishStateCallback.class);
+        doAnswer(invocation -> {
+            callback.onPublishStateChanged(anyInt());
+            return null;
+        }).when(mPublishStateCallbacks).broadcast(any());
+
+        UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
+        uceImpl.onRcsConnected(mRcsFeatureManager);
+        uceImpl.mRcsFeatureCallback.onUnpublish();
+        waitForMs(1000);
+
+        assertEquals(PresenceBase.PUBLISH_STATE_NOT_PUBLISHED, uceImpl.getPublisherState());
+        verify(callback).onPublishStateChanged(anyInt());
+    }
+
+    private UserCapabilityExchangeImpl createUserCapabilityExchangeImpl() throws Exception {
+        HandlerThread handlerThread = new HandlerThread("UceImplHandlerThread");
+        handlerThread.start();
+        mLooper = handlerThread.getLooper();
+        UserCapabilityExchangeImpl uceImpl = new UserCapabilityExchangeImpl(mContext, mSlotId,
+                mSubId, mLooper, mPresencePublication, mPresenceSubscriber,
+                mPublishStateCallbacks);
+        verify(mPresencePublication).handleAssociatedSubscriptionChanged(1);
+        verify(mPresenceSubscriber).handleAssociatedSubscriptionChanged(1);
+        waitForHandlerAction(uceImpl.getHandler(), 1000);
+        verify(mImsMmTelManager, atLeast(1)).registerImsRegistrationCallback(
+                any(Executor.class), any(RegistrationManager.RegistrationCallback.class));
+        verify(mContext).registerReceiver(any(), any());
+        return uceImpl;
+    }
+}