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