AnalyticsTests.java revision a0a43d51041c9efbe04f7c65236c9e90c3e79346
1/* 2 * Copyright (C) 2016 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 17package com.android.server.telecom.tests; 18 19import android.content.Context; 20import android.telecom.Connection; 21import android.telecom.DisconnectCause; 22import android.telecom.InCallService; 23import android.telecom.Log; 24import android.telecom.ParcelableCallAnalytics; 25import android.telecom.TelecomAnalytics; 26import android.telecom.TelecomManager; 27import android.telecom.VideoCallImpl; 28import android.telecom.VideoProfile; 29import android.test.suitebuilder.annotation.MediumTest; 30import android.test.suitebuilder.annotation.SmallTest; 31import android.util.Base64; 32 33import com.android.internal.util.IndentingPrintWriter; 34import com.android.server.telecom.Analytics; 35import com.android.server.telecom.LogUtils; 36import com.android.server.telecom.TelecomLogClass; 37 38import java.io.PrintWriter; 39import java.io.StringWriter; 40import java.util.HashSet; 41import java.util.List; 42import java.util.Map; 43import java.util.Set; 44import java.util.concurrent.CountDownLatch; 45import java.util.concurrent.TimeUnit; 46 47import static org.mockito.Matchers.any; 48import static org.mockito.Matchers.anyInt; 49import static org.mockito.Mockito.doAnswer; 50import static org.mockito.Mockito.mock; 51 52public class AnalyticsTests extends TelecomSystemTest { 53 @MediumTest 54 public void testAnalyticsSingleCall() throws Exception { 55 IdPair testCall = startAndMakeActiveIncomingCall( 56 "650-555-1212", 57 mPhoneAccountA0.getAccountHandle(), 58 mConnectionServiceFixtureA); 59 60 Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData(); 61 62 assertTrue(analyticsMap.containsKey(testCall.mCallId)); 63 64 Analytics.CallInfoImpl callAnalytics = analyticsMap.get(testCall.mCallId); 65 assertTrue(callAnalytics.startTime > 0); 66 assertEquals(0, callAnalytics.endTime); 67 assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics.callDirection); 68 assertFalse(callAnalytics.isInterrupted); 69 assertNull(callAnalytics.callTerminationReason); 70 assertEquals(mConnectionServiceComponentNameA.flattenToShortString(), 71 callAnalytics.connectionService); 72 73 mConnectionServiceFixtureA. 74 sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR); 75 76 analyticsMap = Analytics.cloneData(); 77 callAnalytics = analyticsMap.get(testCall.mCallId); 78 assertTrue(callAnalytics.endTime > 0); 79 assertNotNull(callAnalytics.callTerminationReason); 80 assertEquals(DisconnectCause.ERROR, callAnalytics.callTerminationReason.getCode()); 81 82 StringWriter sr = new StringWriter(); 83 IndentingPrintWriter ip = new IndentingPrintWriter(sr, " "); 84 Analytics.dump(ip); 85 String dumpResult = sr.toString(); 86 String[] expectedFields = {"startTime", "endTime", "direction", "isAdditionalCall", 87 "isInterrupted", "callTechnologies", "callTerminationReason", "connectionService"}; 88 for (String field : expectedFields) { 89 assertTrue(dumpResult.contains(field)); 90 } 91 } 92 93 @MediumTest 94 public void testAnalyticsDumping() throws Exception { 95 Analytics.reset(); 96 IdPair testCall = startAndMakeActiveIncomingCall( 97 "650-555-1212", 98 mPhoneAccountA0.getAccountHandle(), 99 mConnectionServiceFixtureA); 100 101 mConnectionServiceFixtureA. 102 sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR); 103 Analytics.CallInfoImpl expectedAnalytics = Analytics.cloneData().get(testCall.mCallId); 104 105 TelecomManager tm = (TelecomManager) mSpyContext.getSystemService(Context.TELECOM_SERVICE); 106 List<ParcelableCallAnalytics> analyticsList = tm.dumpAnalytics().getCallAnalytics(); 107 108 assertEquals(1, analyticsList.size()); 109 ParcelableCallAnalytics pCA = analyticsList.get(0); 110 111 assertTrue(Math.abs(expectedAnalytics.startTime - pCA.getStartTimeMillis()) < 112 ParcelableCallAnalytics.MILLIS_IN_5_MINUTES); 113 assertEquals(0, pCA.getStartTimeMillis() % ParcelableCallAnalytics.MILLIS_IN_5_MINUTES); 114 assertTrue(Math.abs((expectedAnalytics.endTime - expectedAnalytics.startTime) - 115 pCA.getCallDurationMillis()) < ParcelableCallAnalytics.MILLIS_IN_1_SECOND); 116 assertEquals(0, pCA.getCallDurationMillis() % ParcelableCallAnalytics.MILLIS_IN_1_SECOND); 117 118 assertEquals(expectedAnalytics.callDirection, pCA.getCallType()); 119 assertEquals(expectedAnalytics.isAdditionalCall, pCA.isAdditionalCall()); 120 assertEquals(expectedAnalytics.isInterrupted, pCA.isInterrupted()); 121 assertEquals(expectedAnalytics.callTechnologies, pCA.getCallTechnologies()); 122 assertEquals(expectedAnalytics.callTerminationReason.getCode(), 123 pCA.getCallTerminationCode()); 124 assertEquals(expectedAnalytics.connectionService, pCA.getConnectionService()); 125 List<ParcelableCallAnalytics.AnalyticsEvent> analyticsEvents = pCA.analyticsEvents(); 126 Set<Integer> capturedEvents = new HashSet<>(); 127 for (ParcelableCallAnalytics.AnalyticsEvent e : analyticsEvents) { 128 capturedEvents.add(e.getEventName()); 129 assertIsRoundedToOneSigFig(e.getTimeSinceLastEvent()); 130 } 131 assertTrue(capturedEvents.contains(ParcelableCallAnalytics.AnalyticsEvent.SET_ACTIVE)); 132 assertTrue(capturedEvents.contains( 133 ParcelableCallAnalytics.AnalyticsEvent.FILTERING_INITIATED)); 134 } 135 136 @MediumTest 137 public void testAnalyticsTwoCalls() throws Exception { 138 IdPair testCall1 = startAndMakeActiveIncomingCall( 139 "650-555-1212", 140 mPhoneAccountA0.getAccountHandle(), 141 mConnectionServiceFixtureA); 142 IdPair testCall2 = startAndMakeActiveOutgoingCall( 143 "650-555-1213", 144 mPhoneAccountA0.getAccountHandle(), 145 mConnectionServiceFixtureA); 146 147 Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData(); 148 assertTrue(analyticsMap.containsKey(testCall1.mCallId)); 149 assertTrue(analyticsMap.containsKey(testCall2.mCallId)); 150 151 Analytics.CallInfoImpl callAnalytics1 = analyticsMap.get(testCall1.mCallId); 152 Analytics.CallInfoImpl callAnalytics2 = analyticsMap.get(testCall2.mCallId); 153 assertTrue(callAnalytics1.startTime > 0); 154 assertTrue(callAnalytics2.startTime > 0); 155 assertEquals(0, callAnalytics1.endTime); 156 assertEquals(0, callAnalytics2.endTime); 157 158 assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics1.callDirection); 159 assertEquals(Analytics.OUTGOING_DIRECTION, callAnalytics2.callDirection); 160 161 assertTrue(callAnalytics1.isInterrupted); 162 assertTrue(callAnalytics2.isAdditionalCall); 163 164 assertNull(callAnalytics1.callTerminationReason); 165 assertNull(callAnalytics2.callTerminationReason); 166 167 assertEquals(mConnectionServiceComponentNameA.flattenToShortString(), 168 callAnalytics1.connectionService); 169 assertEquals(mConnectionServiceComponentNameA.flattenToShortString(), 170 callAnalytics1.connectionService); 171 172 mConnectionServiceFixtureA. 173 sendSetDisconnected(testCall2.mConnectionId, DisconnectCause.REMOTE); 174 mConnectionServiceFixtureA. 175 sendSetDisconnected(testCall1.mConnectionId, DisconnectCause.ERROR); 176 177 analyticsMap = Analytics.cloneData(); 178 callAnalytics1 = analyticsMap.get(testCall1.mCallId); 179 callAnalytics2 = analyticsMap.get(testCall2.mCallId); 180 assertTrue(callAnalytics1.endTime > 0); 181 assertTrue(callAnalytics2.endTime > 0); 182 assertNotNull(callAnalytics1.callTerminationReason); 183 assertNotNull(callAnalytics2.callTerminationReason); 184 assertEquals(DisconnectCause.ERROR, callAnalytics1.callTerminationReason.getCode()); 185 assertEquals(DisconnectCause.REMOTE, callAnalytics2.callTerminationReason.getCode()); 186 } 187 188 @MediumTest 189 public void testAnalyticsVideo() throws Exception { 190 Analytics.reset(); 191 IdPair callIds = startAndMakeActiveOutgoingCall( 192 "650-555-1212", 193 mPhoneAccountA0.getAccountHandle(), 194 mConnectionServiceFixtureA); 195 196 CountDownLatch counter = new CountDownLatch(1); 197 InCallService.VideoCall.Callback callback = mock(InCallService.VideoCall.Callback.class); 198 199 doAnswer(invocation -> { 200 counter.countDown(); 201 return null; 202 }).when(callback) 203 .onSessionModifyResponseReceived(anyInt(), any(VideoProfile.class), 204 any(VideoProfile.class)); 205 206 mConnectionServiceFixtureA.sendSetVideoProvider( 207 mConnectionServiceFixtureA.mLatestConnectionId); 208 InCallService.VideoCall videoCall = 209 mInCallServiceFixtureX.getCall(callIds.mCallId).getVideoCallImpl( 210 mInCallServiceComponentNameX.getPackageName()); 211 videoCall.registerCallback(callback); 212 ((VideoCallImpl) videoCall).setVideoState(VideoProfile.STATE_BIDIRECTIONAL); 213 214 videoCall.sendSessionModifyRequest(new VideoProfile(VideoProfile.STATE_RX_ENABLED)); 215 counter.await(10000, TimeUnit.MILLISECONDS); 216 217 StringWriter sw = new StringWriter(); 218 PrintWriter pw = new PrintWriter(sw); 219 Analytics.dumpToEncodedProto(pw, new String[]{}); 220 TelecomLogClass.TelecomLog analyticsProto = 221 TelecomLogClass.TelecomLog.parseFrom(Base64.decode(sw.toString(), Base64.DEFAULT)); 222 223 assertEquals(1, analyticsProto.callLogs.length); 224 TelecomLogClass.VideoEvent[] videoEvents = analyticsProto.callLogs[0].videoEvents; 225 assertEquals(2, videoEvents.length); 226 227 assertEquals(Analytics.SEND_LOCAL_SESSION_MODIFY_REQUEST, videoEvents[0].getEventName()); 228 assertEquals(VideoProfile.STATE_RX_ENABLED, videoEvents[0].getVideoState()); 229 assertEquals(-1, videoEvents[0].getTimeSinceLastEventMillis()); 230 231 assertEquals(Analytics.RECEIVE_REMOTE_SESSION_MODIFY_RESPONSE, 232 videoEvents[1].getEventName()); 233 assertEquals(VideoProfile.STATE_RX_ENABLED, videoEvents[1].getVideoState()); 234 assertIsRoundedToOneSigFig(videoEvents[1].getTimeSinceLastEventMillis()); 235 } 236 237 @SmallTest 238 public void testAnalyticsRounding() { 239 long[] testVals = {0, -1, -10, -100, -57836, 1, 10, 100, 1000, 458457}; 240 long[] expected = {0, -1, -10, -100, -60000, 1, 10, 100, 1000, 500000}; 241 for (int i = 0; i < testVals.length; i++) { 242 assertEquals(expected[i], Analytics.roundToOneSigFig(testVals[i])); 243 } 244 } 245 246 @SmallTest 247 public void testAnalyticsLogSessionTiming() throws Exception { 248 long minTime = 50; 249 Log.startSession(LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL); 250 Thread.sleep(minTime); 251 Log.endSession(); 252 TelecomManager tm = (TelecomManager) mSpyContext.getSystemService(Context.TELECOM_SERVICE); 253 List<TelecomAnalytics.SessionTiming> sessions = tm.dumpAnalytics().getSessionTimings(); 254 sessions.stream() 255 .filter(s -> LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL.equals( 256 Analytics.sSessionIdToLogSession.get(s.getKey()))) 257 .forEach(s -> assertTrue(s.getTime() >= minTime)); 258 } 259 260 @MediumTest 261 public void testAnalyticsDumpToProto() throws Exception { 262 Analytics.reset(); 263 IdPair testCall = startAndMakeActiveIncomingCall( 264 "650-555-1212", 265 mPhoneAccountA0.getAccountHandle(), 266 mConnectionServiceFixtureA); 267 268 mConnectionServiceFixtureA. 269 sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR); 270 Analytics.CallInfoImpl expectedAnalytics = Analytics.cloneData().get(testCall.mCallId); 271 272 StringWriter sw = new StringWriter(); 273 PrintWriter pw = new PrintWriter(sw); 274 Analytics.dumpToEncodedProto(pw, new String[]{}); 275 TelecomLogClass.TelecomLog analyticsProto = 276 TelecomLogClass.TelecomLog.parseFrom(Base64.decode(sw.toString(), Base64.DEFAULT)); 277 278 assertEquals(1, analyticsProto.callLogs.length); 279 TelecomLogClass.CallLog callLog = analyticsProto.callLogs[0]; 280 281 assertTrue(Math.abs(expectedAnalytics.startTime - callLog.getStartTime5Min()) < 282 ParcelableCallAnalytics.MILLIS_IN_5_MINUTES); 283 assertEquals(0, callLog.getStartTime5Min() % ParcelableCallAnalytics.MILLIS_IN_5_MINUTES); 284 assertTrue(Math.abs((expectedAnalytics.endTime - expectedAnalytics.startTime) - 285 callLog.getCallDurationMillis()) < ParcelableCallAnalytics.MILLIS_IN_1_SECOND); 286 assertEquals(0, 287 callLog.getCallDurationMillis() % ParcelableCallAnalytics.MILLIS_IN_1_SECOND); 288 289 assertEquals(expectedAnalytics.callDirection, callLog.getType()); 290 assertEquals(expectedAnalytics.isAdditionalCall, callLog.getIsAdditionalCall()); 291 assertEquals(expectedAnalytics.isInterrupted, callLog.getIsInterrupted()); 292 assertEquals(expectedAnalytics.callTechnologies, callLog.getCallTechnologies()); 293 assertEquals(expectedAnalytics.callTerminationReason.getCode(), 294 callLog.getCallTerminationCode()); 295 assertEquals(expectedAnalytics.connectionService, callLog.connectionService[0]); 296 TelecomLogClass.Event[] analyticsEvents = callLog.callEvents; 297 Set<Integer> capturedEvents = new HashSet<>(); 298 for (TelecomLogClass.Event e : analyticsEvents) { 299 capturedEvents.add(e.getEventName()); 300 assertIsRoundedToOneSigFig(e.getTimeSinceLastEventMillis()); 301 } 302 assertTrue(capturedEvents.contains(ParcelableCallAnalytics.AnalyticsEvent.SET_ACTIVE)); 303 assertTrue(capturedEvents.contains( 304 ParcelableCallAnalytics.AnalyticsEvent.FILTERING_INITIATED)); 305 } 306 307 @MediumTest 308 public void testAnalyticsConnectionProperties() throws Exception { 309 Analytics.reset(); 310 IdPair testCall = startAndMakeActiveIncomingCall( 311 "650-555-1212", 312 mPhoneAccountA0.getAccountHandle(), 313 mConnectionServiceFixtureA); 314 315 int properties1 = Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE 316 | Connection.PROPERTY_WIFI 317 | Connection.PROPERTY_EMERGENCY_CALLBACK_MODE; 318 int properties2 = Connection.PROPERTY_HIGH_DEF_AUDIO 319 | Connection.PROPERTY_WIFI; 320 int expectedProperties = properties1 | properties2; 321 322 mConnectionServiceFixtureA.mConnectionById.get(testCall.mConnectionId).properties = 323 properties1; 324 mConnectionServiceFixtureA.sendSetConnectionProperties(testCall.mConnectionId); 325 mConnectionServiceFixtureA.mConnectionById.get(testCall.mConnectionId).properties = 326 properties2; 327 mConnectionServiceFixtureA.sendSetConnectionProperties(testCall.mConnectionId); 328 329 mConnectionServiceFixtureA. 330 sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR); 331 332 StringWriter sw = new StringWriter(); 333 PrintWriter pw = new PrintWriter(sw); 334 Analytics.dumpToEncodedProto(pw, new String[]{}); 335 TelecomLogClass.TelecomLog analyticsProto = 336 TelecomLogClass.TelecomLog.parseFrom(Base64.decode(sw.toString(), Base64.DEFAULT)); 337 338 assertEquals(expectedProperties, 339 analyticsProto.callLogs[0].getConnectionProperties() & expectedProperties); 340 } 341 342 private void assertIsRoundedToOneSigFig(long x) { 343 assertEquals(x, Analytics.roundToOneSigFig(x)); 344 } 345} 346