1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ims.rcs.uce.presence.publish; 18 19 import static android.telephony.ims.RcsContactPresenceTuple.TUPLE_BASIC_STATUS_OPEN; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.anyInt; 23 import static org.mockito.ArgumentMatchers.anyLong; 24 import static org.mockito.ArgumentMatchers.eq; 25 import static org.mockito.Mockito.doReturn; 26 import static org.mockito.Mockito.never; 27 import static org.mockito.Mockito.verify; 28 29 import android.content.Context; 30 import android.net.Uri; 31 import android.telephony.ims.RcsContactPresenceTuple; 32 import android.telephony.ims.RcsContactUceCapability; 33 import android.telephony.ims.SipDetails; 34 35 import androidx.test.ext.junit.runners.AndroidJUnit4; 36 import androidx.test.filters.SmallTest; 37 38 import com.android.ims.ImsTestBase; 39 import com.android.ims.RcsFeatureManager; 40 import com.android.ims.rcs.uce.UceStatsWriter; 41 import com.android.ims.rcs.uce.presence.publish.PublishController.PublishControllerCallback; 42 43 import org.junit.After; 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 import org.mockito.Mock; 48 49 import java.time.Instant; 50 import java.util.Optional; 51 @RunWith(AndroidJUnit4.class) 52 public class PublishProcessorTest extends ImsTestBase { 53 54 @Mock RcsFeatureManager mRcsFeatureManager; 55 @Mock DeviceCapabilityInfo mDeviceCapabilities; 56 @Mock PublishControllerCallback mPublishCtrlCallback; 57 @Mock PublishProcessorState mProcessorState; 58 @Mock PublishRequestResponse mResponseCallback; 59 @Mock UceStatsWriter mUceStatsWriter; 60 61 private int mSub = 1; 62 private long mTaskId = 1L; 63 64 public static class TestPublishProcessor extends PublishProcessor { TestPublishProcessor(Context context, int subId, DeviceCapabilityInfo capabilityInfo, PublishControllerCallback publishCtrlCallback, UceStatsWriter instance)65 public TestPublishProcessor(Context context, int subId, 66 DeviceCapabilityInfo capabilityInfo, 67 PublishControllerCallback publishCtrlCallback, 68 UceStatsWriter instance) { 69 super(context, subId, capabilityInfo, publishCtrlCallback, instance); 70 } 71 72 @Override isEabProvisioned()73 protected boolean isEabProvisioned() { 74 return true; 75 } 76 } 77 78 @Before setUp()79 public void setUp() throws Exception { 80 super.setUp(); 81 doReturn(true).when(mProcessorState).isPublishAllowedAtThisTime(); 82 doReturn(mTaskId).when(mProcessorState).getCurrentTaskId(); 83 84 doReturn(true).when(mDeviceCapabilities).isImsRegistered(); 85 RcsContactUceCapability capability = getRcsContactUceCapability(); 86 doReturn(capability).when(mDeviceCapabilities).getChangedPresenceCapability(any()); 87 doReturn(capability).when(mDeviceCapabilities).getDeviceCapabilities(anyInt(), any()); 88 89 doReturn(mTaskId).when(mResponseCallback).getTaskId(); 90 } 91 92 @After tearDown()93 public void tearDown() throws Exception { 94 super.tearDown(); 95 } 96 97 @Test 98 @SmallTest testDoPublish()99 public void testDoPublish() throws Exception { 100 PublishProcessor publishProcessor = getPublishProcessor(); 101 102 publishProcessor.doPublish(PublishController.PUBLISH_TRIGGER_SERVICE); 103 104 verify(mDeviceCapabilities).getDeviceCapabilities(anyInt(), any()); 105 verify(mProcessorState).setPublishingFlag(true); 106 verify(mRcsFeatureManager).requestPublication(any(), any()); 107 verify(mPublishCtrlCallback).setupRequestCanceledTimer(anyLong(), anyLong()); 108 verify(mPublishCtrlCallback).notifyPendingPublishRequest(); 109 } 110 111 @Test 112 @SmallTest testPublishWithoutResetRetryCount()113 public void testPublishWithoutResetRetryCount() throws Exception { 114 PublishProcessor publishProcessor = getPublishProcessor(); 115 116 publishProcessor.doPublish(PublishController.PUBLISH_TRIGGER_RETRY); 117 verify(mDeviceCapabilities).getChangedPresenceCapability(any()); 118 verify(mProcessorState, never()).resetRetryCount(); 119 } 120 121 @Test 122 @SmallTest testNotPublishWhenImsNotRegistered()123 public void testNotPublishWhenImsNotRegistered() throws Exception { 124 doReturn(false).when(mDeviceCapabilities).isImsRegistered(); 125 PublishProcessor publishProcessor = getPublishProcessor(); 126 127 publishProcessor.doPublish(PublishController.PUBLISH_TRIGGER_RETRY); 128 129 verify(mRcsFeatureManager, never()).requestPublication(any(), any()); 130 } 131 132 @Test 133 @SmallTest testNotPublishWhenReachMaximumRetries()134 public void testNotPublishWhenReachMaximumRetries() throws Exception { 135 doReturn(true).when(mProcessorState).isPublishingNow(); 136 doReturn(mTaskId).when(mProcessorState).getCurrentTaskId(); 137 doReturn(mTaskId).when(mResponseCallback).getTaskId(); 138 doReturn(true).when(mResponseCallback).needRetry(); 139 doReturn(true).when(mProcessorState).isReachMaximumRetries(); 140 PublishProcessor publishProcessor = getPublishProcessor(); 141 142 publishProcessor.onNetworkResponse(mResponseCallback); 143 144 verify(mPublishCtrlCallback).updatePublishRequestResult(anyInt(), any(), any(), eq(null)); 145 verify(mResponseCallback).onDestroy(); 146 verify(mProcessorState).setPublishingFlag(false); 147 verify(mPublishCtrlCallback).clearRequestCanceledTimer(); 148 } 149 150 @Test 151 @SmallTest testNotPublishWhenCurrentTimeNotAllowed()152 public void testNotPublishWhenCurrentTimeNotAllowed() throws Exception { 153 doReturn(false).when(mProcessorState).isPublishAllowedAtThisTime(); 154 PublishProcessor publishProcessor = getPublishProcessor(); 155 156 publishProcessor.doPublish(PublishController.PUBLISH_TRIGGER_RETRY); 157 158 verify(mPublishCtrlCallback).requestPublishFromInternal( 159 eq(PublishController.PUBLISH_TRIGGER_RETRY)); 160 verify(mRcsFeatureManager, never()).requestPublication(any(), any()); 161 } 162 163 @Test 164 @SmallTest testCommandErrorWithRetry()165 public void testCommandErrorWithRetry() throws Exception { 166 doReturn(true).when(mProcessorState).isPublishingNow(); 167 doReturn(mTaskId).when(mProcessorState).getCurrentTaskId(); 168 doReturn(mTaskId).when(mResponseCallback).getTaskId(); 169 doReturn(true).when(mResponseCallback).needRetry(); 170 doReturn(Optional.of(10)).when(mResponseCallback).getCmdErrorCode(); 171 172 PublishProcessor publishProcessor = getPublishProcessor(); 173 174 publishProcessor.onCommandError(mResponseCallback); 175 176 verify(mDeviceCapabilities).setPresencePublishResult(false); 177 verify(mProcessorState).increaseRetryCount(); 178 verify(mPublishCtrlCallback).requestPublishFromInternal( 179 eq(PublishController.PUBLISH_TRIGGER_RETRY)); 180 verify(mResponseCallback).onDestroy(); 181 verify(mProcessorState).setPublishingFlag(false); 182 verify(mPublishCtrlCallback).clearRequestCanceledTimer(); 183 verify(mUceStatsWriter).setUceEvent(eq(mSub), eq(UceStatsWriter.PUBLISH_EVENT), eq(true), 184 eq(10), eq(0)); 185 } 186 187 @Test 188 @SmallTest testCommandErrorWithoutRetry()189 public void testCommandErrorWithoutRetry() throws Exception { 190 doReturn(true).when(mProcessorState).isPublishingNow(); 191 doReturn(mTaskId).when(mProcessorState).getCurrentTaskId(); 192 doReturn(mTaskId).when(mResponseCallback).getTaskId(); 193 doReturn(false).when(mResponseCallback).needRetry(); 194 doReturn(true).when(mResponseCallback).isRequestSuccess(); 195 PublishProcessor publishProcessor = getPublishProcessor(); 196 197 publishProcessor.onCommandError(mResponseCallback); 198 199 verify(mDeviceCapabilities).setPresencePublishResult(true); 200 verify(mPublishCtrlCallback).updatePublishRequestResult(anyInt(), any(), any(), eq(null)); 201 verify(mResponseCallback).onDestroy(); 202 verify(mProcessorState).setPublishingFlag(false); 203 verify(mPublishCtrlCallback).clearRequestCanceledTimer(); 204 } 205 206 @Test 207 @SmallTest testNetworkResponseWithRetry()208 public void testNetworkResponseWithRetry() throws Exception { 209 doReturn(true).when(mProcessorState).isPublishingNow(); 210 doReturn(mTaskId).when(mProcessorState).getCurrentTaskId(); 211 doReturn(mTaskId).when(mResponseCallback).getTaskId(); 212 doReturn(true).when(mResponseCallback).needRetry(); 213 PublishProcessor publishProcessor = getPublishProcessor(); 214 215 publishProcessor.onNetworkResponse(mResponseCallback); 216 217 verify(mDeviceCapabilities).setPresencePublishResult(false); 218 verify(mProcessorState).increaseRetryCount(); 219 verify(mPublishCtrlCallback).requestPublishFromInternal( 220 eq(PublishController.PUBLISH_TRIGGER_RETRY)); 221 verify(mResponseCallback).onDestroy(); 222 verify(mProcessorState).setPublishingFlag(false); 223 verify(mPublishCtrlCallback).clearRequestCanceledTimer(); 224 } 225 226 @Test 227 @SmallTest testNetworkResponseSuccessful()228 public void testNetworkResponseSuccessful() throws Exception { 229 doReturn(true).when(mProcessorState).isPublishingNow(); 230 doReturn(mTaskId).when(mProcessorState).getCurrentTaskId(); 231 doReturn(mTaskId).when(mResponseCallback).getTaskId(); 232 doReturn(false).when(mResponseCallback).needRetry(); 233 doReturn(true).when(mResponseCallback).isRequestSuccess(); 234 doReturn(Optional.of(200)).when(mResponseCallback).getNetworkRespSipCode(); 235 236 SipDetails details = new SipDetails.Builder(SipDetails.METHOD_PUBLISH) 237 .setCSeq(10).setSipResponseCode(200, "OK").setCallId("CallId").build(); 238 Optional<SipDetails> sipDetails = Optional.ofNullable(details); 239 doReturn(sipDetails).when(mResponseCallback).getSipDetails(); 240 241 PublishProcessor publishProcessor = getPublishProcessor(); 242 243 publishProcessor.onNetworkResponse(mResponseCallback); 244 SipDetails actualInfo = sipDetails.orElse(null); 245 246 verify(mDeviceCapabilities).setPresencePublishResult(true); 247 verify(mPublishCtrlCallback).updatePublishRequestResult(anyInt(), any(), any(), 248 eq(actualInfo)); 249 verify(mResponseCallback).onDestroy(); 250 verify(mProcessorState).setPublishingFlag(false); 251 verify(mPublishCtrlCallback).clearRequestCanceledTimer(); 252 253 verify(mUceStatsWriter).setUceEvent(eq(mSub), eq(UceStatsWriter.PUBLISH_EVENT), eq(true), 254 eq(0), eq(200)); 255 } 256 257 @Test 258 @SmallTest testCancelPublishRequest()259 public void testCancelPublishRequest() throws Exception { 260 PublishProcessor publishProcessor = getPublishProcessor(); 261 262 publishProcessor.cancelPublishRequest(mTaskId); 263 264 verify(mProcessorState).setPublishingFlag(false); 265 verify(mPublishCtrlCallback).clearRequestCanceledTimer(); 266 } 267 268 @Test 269 @SmallTest testPublishUpdated()270 public void testPublishUpdated() throws Exception { 271 Instant responseTime = Instant.now(); 272 doReturn(responseTime).when(mResponseCallback).getResponseTimestamp(); 273 doReturn(true).when(mResponseCallback).isRequestSuccess(); 274 275 doReturn(0).when(mResponseCallback).getPublishState(); 276 doReturn("").when(mResponseCallback).getPidfXml(); 277 278 SipDetails details = new SipDetails.Builder(SipDetails.METHOD_PUBLISH) 279 .setCSeq(10).setSipResponseCode(200, "").setCallId("CallId").build(); 280 Optional<SipDetails> sipDetails = Optional.ofNullable(details); 281 doReturn(sipDetails).when(mResponseCallback).getSipDetails(); 282 283 PublishProcessor publishProcessor = getPublishProcessor(); 284 285 publishProcessor.publishUpdated(mResponseCallback); 286 SipDetails actualInfo = sipDetails.orElse(null); 287 288 verify(mDeviceCapabilities).setPresencePublishResult(true); 289 verify(mProcessorState).setLastPublishedTime(any()); 290 verify(mProcessorState).resetRetryCount(); 291 verify(mPublishCtrlCallback).updatePublishRequestResult(anyInt(), any(), any(), 292 eq(actualInfo)); 293 } 294 getPublishProcessor()295 private PublishProcessor getPublishProcessor() { 296 PublishProcessor publishProcessor = new TestPublishProcessor(mContext, mSub, 297 mDeviceCapabilities, mPublishCtrlCallback, mUceStatsWriter); 298 publishProcessor.setProcessorState(mProcessorState); 299 publishProcessor.onRcsConnected(mRcsFeatureManager); 300 return publishProcessor; 301 } 302 getRcsContactUceCapability()303 private RcsContactUceCapability getRcsContactUceCapability() { 304 Uri contact = Uri.fromParts("sip", "test", null); 305 306 RcsContactUceCapability.PresenceBuilder builder = 307 new RcsContactUceCapability.PresenceBuilder(contact, 308 RcsContactUceCapability.SOURCE_TYPE_CACHED, 309 RcsContactUceCapability.REQUEST_RESULT_FOUND); 310 311 RcsContactPresenceTuple.Builder tupleBuilder = new RcsContactPresenceTuple.Builder( 312 TUPLE_BASIC_STATUS_OPEN, RcsContactPresenceTuple.SERVICE_ID_MMTEL, "1.0"); 313 314 builder.addCapabilityTuple(tupleBuilder.build()); 315 return builder.build(); 316 } 317 } 318