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.internal.telephony.metrics; 18 19 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS; 20 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS; 21 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MO; 22 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MT; 23 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__SETUP_DURATION__CALL_SETUP_DURATION_EXTREMELY_FAST; 24 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__SETUP_DURATION__CALL_SETUP_DURATION_VERY_FAST; 25 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__SETUP_DURATION__CALL_SETUP_DURATION_VERY_SLOW; 26 27 import static org.junit.Assert.assertEquals; 28 import static org.junit.Assert.assertNotNull; 29 import static org.junit.Assert.assertNull; 30 import static org.junit.Assert.assertTrue; 31 import static org.mockito.Mockito.anyInt; 32 import static org.mockito.Mockito.anyString; 33 import static org.mockito.Mockito.doReturn; 34 import static org.mockito.Mockito.eq; 35 import static org.mockito.Mockito.inOrder; 36 import static org.mockito.Mockito.times; 37 38 import android.annotation.Nullable; 39 import android.content.Context; 40 import android.os.Build; 41 import android.telephony.DisconnectCause; 42 import android.telephony.ServiceState; 43 import android.telephony.TelephonyManager; 44 import android.telephony.ims.ImsReasonInfo; 45 import android.test.suitebuilder.annotation.SmallTest; 46 47 import com.android.internal.telephony.TelephonyTest; 48 import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch; 49 import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState; 50 import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationStats; 51 import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationTermination; 52 import com.android.internal.telephony.nano.PersistAtomsProto.PersistAtoms; 53 import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallRatUsage; 54 import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallSession; 55 import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession.Event.AudioCodec; 56 import com.android.internal.telephony.protobuf.nano.MessageNano; 57 58 import org.junit.After; 59 import org.junit.Before; 60 import org.junit.Rule; 61 import org.junit.Test; 62 import org.junit.rules.TemporaryFolder; 63 import org.mockito.ArgumentCaptor; 64 import org.mockito.InOrder; 65 import org.mockito.Mock; 66 67 import java.io.File; 68 import java.io.FileOutputStream; 69 import java.nio.charset.StandardCharsets; 70 import java.util.Arrays; 71 import java.util.Comparator; 72 import java.util.LinkedList; 73 import java.util.Queue; 74 75 public class PersistAtomsStorageTest extends TelephonyTest { 76 private static final String TEST_FILE = "PersistAtomsStorageTest.pb"; 77 private static final int MAX_NUM_CALL_SESSIONS = 50; 78 private static final long START_TIME_MILLIS = 2000L; 79 private static final int CARRIER1_ID = 1; 80 private static final int CARRIER2_ID = 1187; 81 private static final int CARRIER3_ID = 1435; 82 83 @Mock private FileOutputStream mTestFileOutputStream; 84 85 @Rule public TemporaryFolder mFolder = new TemporaryFolder(); 86 87 private File mTestFile; 88 89 // call with SRVCC 90 private VoiceCallSession mCall1Proto; 91 92 // call held after another incoming call, ended before the other call 93 private VoiceCallSession mCall2Proto; 94 private VoiceCallSession mCall3Proto; 95 96 // failed call 97 private VoiceCallSession mCall4Proto; 98 99 private VoiceCallRatUsage mCarrier1LteUsageProto; 100 private VoiceCallRatUsage mCarrier1UmtsUsageProto; 101 private VoiceCallRatUsage mCarrier2LteUsageProto; 102 private VoiceCallRatUsage mCarrier3LteUsageProto; 103 private VoiceCallRatUsage mCarrier3GsmUsageProto; 104 105 private VoiceCallSession[] mVoiceCallSessions; 106 private VoiceCallRatUsage[] mVoiceCallRatUsages; 107 108 // data service state switch for slot 0 and 1 109 private CellularDataServiceSwitch mServiceSwitch1Proto; 110 private CellularDataServiceSwitch mServiceSwitch2Proto; 111 112 // service states for slot 0 and 1 113 private CellularServiceState mServiceState1Proto; 114 private CellularServiceState mServiceState2Proto; 115 private CellularServiceState mServiceState3Proto; 116 private CellularServiceState mServiceState4Proto; 117 118 private CellularDataServiceSwitch[] mServiceSwitches; 119 private CellularServiceState[] mServiceStates; 120 121 // IMS registrations for slot 0 and 1 122 private ImsRegistrationStats mImsRegistrationStatsLte0; 123 private ImsRegistrationStats mImsRegistrationStatsWifi0; 124 private ImsRegistrationStats mImsRegistrationStatsLte1; 125 126 // IMS registration terminations for slot 0 and 1 127 private ImsRegistrationTermination mImsRegistrationTerminationLte; 128 private ImsRegistrationTermination mImsRegistrationTerminationWifi; 129 130 private ImsRegistrationStats[] mImsRegistrationStats; 131 private ImsRegistrationTermination[] mImsRegistrationTerminations; 132 makeTestData()133 private void makeTestData() { 134 // MO call with SRVCC (LTE to UMTS) 135 mCall1Proto = new VoiceCallSession(); 136 mCall1Proto.bearerAtStart = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS; 137 mCall1Proto.bearerAtEnd = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS; 138 mCall1Proto.direction = VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MO; 139 mCall1Proto.setupDuration = 140 VOICE_CALL_SESSION__SETUP_DURATION__CALL_SETUP_DURATION_VERY_FAST; 141 mCall1Proto.setupFailed = false; 142 mCall1Proto.disconnectReasonCode = DisconnectCause.LOCAL; 143 mCall1Proto.disconnectExtraCode = 0; 144 mCall1Proto.disconnectExtraMessage = ""; 145 mCall1Proto.ratAtStart = TelephonyManager.NETWORK_TYPE_LTE; 146 mCall1Proto.ratAtEnd = TelephonyManager.NETWORK_TYPE_UMTS; 147 mCall1Proto.ratSwitchCount = 1L; 148 mCall1Proto.codecBitmask = 149 (1 << AudioCodec.AUDIO_CODEC_EVS_SWB) | (1 << AudioCodec.AUDIO_CODEC_AMR); 150 mCall1Proto.concurrentCallCountAtStart = 0; 151 mCall1Proto.concurrentCallCountAtEnd = 0; 152 mCall1Proto.simSlotIndex = 0; 153 mCall1Proto.isMultiSim = false; 154 mCall1Proto.isEsim = false; 155 mCall1Proto.carrierId = CARRIER1_ID; 156 mCall1Proto.srvccCompleted = true; 157 mCall1Proto.srvccFailureCount = 0L; 158 mCall1Proto.srvccCancellationCount = 0L; 159 mCall1Proto.rttEnabled = false; 160 mCall1Proto.isEmergency = false; 161 mCall1Proto.isRoaming = false; 162 163 // VoLTE MT call on DSDS/eSIM, hanged up by remote 164 // concurrent with mCall3Proto, started first and ended first 165 mCall2Proto = new VoiceCallSession(); 166 mCall2Proto.bearerAtStart = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS; 167 mCall2Proto.bearerAtEnd = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS; 168 mCall2Proto.direction = VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MT; 169 mCall2Proto.setupDuration = 170 VOICE_CALL_SESSION__SETUP_DURATION__CALL_SETUP_DURATION_VERY_FAST; 171 mCall2Proto.setupFailed = false; 172 mCall2Proto.disconnectReasonCode = ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE; 173 mCall2Proto.disconnectExtraCode = 0; 174 mCall2Proto.disconnectExtraMessage = "normal call clearing"; 175 mCall2Proto.ratAtStart = TelephonyManager.NETWORK_TYPE_LTE; 176 mCall2Proto.ratAtEnd = TelephonyManager.NETWORK_TYPE_LTE; 177 mCall2Proto.ratSwitchCount = 0L; 178 mCall2Proto.codecBitmask = (1 << AudioCodec.AUDIO_CODEC_EVS_SWB); 179 mCall2Proto.concurrentCallCountAtStart = 0; 180 mCall2Proto.concurrentCallCountAtEnd = 1; 181 mCall2Proto.simSlotIndex = 1; 182 mCall2Proto.isMultiSim = true; 183 mCall2Proto.isEsim = true; 184 mCall2Proto.carrierId = CARRIER2_ID; 185 mCall2Proto.srvccCompleted = false; 186 mCall2Proto.srvccFailureCount = 0L; 187 mCall2Proto.srvccCancellationCount = 0L; 188 mCall2Proto.rttEnabled = false; 189 mCall2Proto.isEmergency = false; 190 mCall2Proto.isRoaming = false; 191 192 // VoLTE MT call on DSDS/eSIM, hanged up by local, with RTT 193 // concurrent with mCall2Proto, started last and ended last 194 mCall3Proto = new VoiceCallSession(); 195 mCall3Proto.bearerAtStart = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS; 196 mCall3Proto.bearerAtEnd = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS; 197 mCall3Proto.direction = VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MT; 198 mCall3Proto.setupDuration = 199 VOICE_CALL_SESSION__SETUP_DURATION__CALL_SETUP_DURATION_EXTREMELY_FAST; 200 mCall3Proto.setupFailed = false; 201 mCall3Proto.disconnectReasonCode = ImsReasonInfo.CODE_USER_TERMINATED; 202 mCall3Proto.disconnectExtraCode = 0; 203 mCall3Proto.disconnectExtraMessage = "normal call clearing"; 204 mCall3Proto.ratAtStart = TelephonyManager.NETWORK_TYPE_LTE; 205 mCall3Proto.ratAtEnd = TelephonyManager.NETWORK_TYPE_LTE; 206 mCall3Proto.ratSwitchCount = 0L; 207 mCall3Proto.codecBitmask = (1 << AudioCodec.AUDIO_CODEC_EVS_SWB); 208 mCall3Proto.concurrentCallCountAtStart = 1; 209 mCall3Proto.concurrentCallCountAtEnd = 0; 210 mCall3Proto.simSlotIndex = 1; 211 mCall3Proto.isMultiSim = true; 212 mCall3Proto.isEsim = true; 213 mCall3Proto.carrierId = CARRIER2_ID; 214 mCall3Proto.srvccCompleted = false; 215 mCall3Proto.srvccFailureCount = 0L; 216 mCall3Proto.srvccCancellationCount = 0L; 217 mCall3Proto.rttEnabled = true; 218 mCall3Proto.isEmergency = false; 219 mCall3Proto.isRoaming = false; 220 221 // CS MO call while camped on LTE 222 mCall4Proto = new VoiceCallSession(); 223 mCall4Proto.bearerAtStart = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS; 224 mCall4Proto.bearerAtEnd = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS; 225 mCall4Proto.direction = VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MO; 226 mCall4Proto.setupDuration = 227 VOICE_CALL_SESSION__SETUP_DURATION__CALL_SETUP_DURATION_VERY_SLOW; 228 mCall4Proto.setupFailed = true; 229 mCall4Proto.disconnectReasonCode = DisconnectCause.NORMAL; 230 mCall4Proto.disconnectExtraCode = 0; 231 mCall4Proto.disconnectExtraMessage = ""; 232 mCall4Proto.ratAtStart = TelephonyManager.NETWORK_TYPE_LTE; 233 mCall4Proto.ratAtEnd = TelephonyManager.NETWORK_TYPE_GSM; 234 mCall4Proto.ratSwitchCount = 1L; 235 mCall4Proto.codecBitmask = (1 << AudioCodec.AUDIO_CODEC_AMR); 236 mCall4Proto.concurrentCallCountAtStart = 0; 237 mCall4Proto.concurrentCallCountAtEnd = 0; 238 mCall4Proto.simSlotIndex = 0; 239 mCall4Proto.isMultiSim = true; 240 mCall4Proto.isEsim = false; 241 mCall4Proto.carrierId = CARRIER3_ID; 242 mCall4Proto.srvccCompleted = false; 243 mCall4Proto.srvccFailureCount = 0L; 244 mCall4Proto.srvccCancellationCount = 0L; 245 mCall4Proto.rttEnabled = false; 246 mCall4Proto.isEmergency = false; 247 mCall4Proto.isRoaming = true; 248 249 mCarrier1LteUsageProto = new VoiceCallRatUsage(); 250 mCarrier1LteUsageProto.carrierId = CARRIER1_ID; 251 mCarrier1LteUsageProto.rat = TelephonyManager.NETWORK_TYPE_LTE; 252 mCarrier1LteUsageProto.callCount = 1L; 253 mCarrier1LteUsageProto.totalDurationMillis = 8000L; 254 255 mCarrier1UmtsUsageProto = new VoiceCallRatUsage(); 256 mCarrier1UmtsUsageProto.carrierId = CARRIER1_ID; 257 mCarrier1UmtsUsageProto.rat = TelephonyManager.NETWORK_TYPE_UMTS; 258 mCarrier1UmtsUsageProto.callCount = 1L; 259 mCarrier1UmtsUsageProto.totalDurationMillis = 6000L; 260 261 mCarrier2LteUsageProto = new VoiceCallRatUsage(); 262 mCarrier2LteUsageProto.carrierId = CARRIER2_ID; 263 mCarrier2LteUsageProto.rat = TelephonyManager.NETWORK_TYPE_LTE; 264 mCarrier2LteUsageProto.callCount = 2L; 265 mCarrier2LteUsageProto.totalDurationMillis = 20000L; 266 267 mCarrier3LteUsageProto = new VoiceCallRatUsage(); 268 mCarrier3LteUsageProto.carrierId = CARRIER3_ID; 269 mCarrier3LteUsageProto.rat = TelephonyManager.NETWORK_TYPE_LTE; 270 mCarrier3LteUsageProto.callCount = 1L; 271 mCarrier3LteUsageProto.totalDurationMillis = 1000L; 272 273 mCarrier3GsmUsageProto = new VoiceCallRatUsage(); 274 mCarrier3GsmUsageProto.carrierId = CARRIER3_ID; 275 mCarrier3GsmUsageProto.rat = TelephonyManager.NETWORK_TYPE_GSM; 276 mCarrier3GsmUsageProto.callCount = 1L; 277 mCarrier3GsmUsageProto.totalDurationMillis = 100000L; 278 279 mVoiceCallRatUsages = 280 new VoiceCallRatUsage[] { 281 mCarrier1UmtsUsageProto, 282 mCarrier1LteUsageProto, 283 mCarrier2LteUsageProto, 284 mCarrier3LteUsageProto, 285 mCarrier3GsmUsageProto 286 }; 287 mVoiceCallSessions = 288 new VoiceCallSession[] {mCall1Proto, mCall2Proto, mCall3Proto, mCall4Proto}; 289 290 // OOS to LTE on slot 0 291 mServiceSwitch1Proto = new CellularDataServiceSwitch(); 292 mServiceSwitch1Proto.ratFrom = TelephonyManager.NETWORK_TYPE_UNKNOWN; 293 mServiceSwitch1Proto.ratTo = TelephonyManager.NETWORK_TYPE_LTE; 294 mServiceSwitch1Proto.simSlotIndex = 0; 295 mServiceSwitch1Proto.isMultiSim = true; 296 mServiceSwitch1Proto.carrierId = CARRIER1_ID; 297 mServiceSwitch1Proto.switchCount = 1; 298 299 // LTE to UMTS on slot 1 300 mServiceSwitch2Proto = new CellularDataServiceSwitch(); 301 mServiceSwitch2Proto.ratFrom = TelephonyManager.NETWORK_TYPE_LTE; 302 mServiceSwitch2Proto.ratTo = TelephonyManager.NETWORK_TYPE_UMTS; 303 mServiceSwitch2Proto.simSlotIndex = 0; 304 mServiceSwitch2Proto.isMultiSim = true; 305 mServiceSwitch2Proto.carrierId = CARRIER2_ID; 306 mServiceSwitch2Proto.switchCount = 2; 307 308 // OOS on slot 0 309 mServiceState1Proto = new CellularServiceState(); 310 mServiceState1Proto.voiceRat = TelephonyManager.NETWORK_TYPE_UNKNOWN; 311 mServiceState1Proto.dataRat = TelephonyManager.NETWORK_TYPE_UNKNOWN; 312 mServiceState1Proto.voiceRoamingType = ServiceState.ROAMING_TYPE_NOT_ROAMING; 313 mServiceState1Proto.dataRoamingType = ServiceState.ROAMING_TYPE_NOT_ROAMING; 314 mServiceState1Proto.isEndc = false; 315 mServiceState1Proto.simSlotIndex = 0; 316 mServiceState1Proto.isMultiSim = true; 317 mServiceState1Proto.carrierId = CARRIER1_ID; 318 mServiceState1Proto.totalTimeMillis = 5000L; 319 320 // LTE with ENDC on slot 0 321 mServiceState2Proto = new CellularServiceState(); 322 mServiceState2Proto.voiceRat = TelephonyManager.NETWORK_TYPE_LTE; 323 mServiceState2Proto.dataRat = TelephonyManager.NETWORK_TYPE_LTE; 324 mServiceState2Proto.voiceRoamingType = ServiceState.ROAMING_TYPE_NOT_ROAMING; 325 mServiceState2Proto.dataRoamingType = ServiceState.ROAMING_TYPE_NOT_ROAMING; 326 mServiceState2Proto.isEndc = true; 327 mServiceState2Proto.simSlotIndex = 0; 328 mServiceState2Proto.isMultiSim = true; 329 mServiceState2Proto.carrierId = CARRIER1_ID; 330 mServiceState2Proto.totalTimeMillis = 15000L; 331 332 // LTE with WFC and roaming on slot 1 333 mServiceState3Proto = new CellularServiceState(); 334 mServiceState3Proto.voiceRat = TelephonyManager.NETWORK_TYPE_IWLAN; 335 mServiceState3Proto.dataRat = TelephonyManager.NETWORK_TYPE_LTE; 336 mServiceState3Proto.voiceRoamingType = ServiceState.ROAMING_TYPE_INTERNATIONAL; 337 mServiceState3Proto.dataRoamingType = ServiceState.ROAMING_TYPE_INTERNATIONAL; 338 mServiceState3Proto.isEndc = false; 339 mServiceState3Proto.simSlotIndex = 1; 340 mServiceState3Proto.isMultiSim = true; 341 mServiceState3Proto.carrierId = CARRIER2_ID; 342 mServiceState3Proto.totalTimeMillis = 10000L; 343 344 // UMTS with roaming on slot 1 345 mServiceState4Proto = new CellularServiceState(); 346 mServiceState4Proto.voiceRat = TelephonyManager.NETWORK_TYPE_UMTS; 347 mServiceState4Proto.dataRat = TelephonyManager.NETWORK_TYPE_UMTS; 348 mServiceState4Proto.voiceRoamingType = ServiceState.ROAMING_TYPE_INTERNATIONAL; 349 mServiceState4Proto.dataRoamingType = ServiceState.ROAMING_TYPE_INTERNATIONAL; 350 mServiceState4Proto.isEndc = false; 351 mServiceState4Proto.simSlotIndex = 1; 352 mServiceState4Proto.isMultiSim = true; 353 mServiceState4Proto.carrierId = CARRIER2_ID; 354 mServiceState4Proto.totalTimeMillis = 10000L; 355 356 mServiceSwitches = 357 new CellularDataServiceSwitch[] {mServiceSwitch1Proto, mServiceSwitch2Proto}; 358 mServiceStates = 359 new CellularServiceState[] { 360 mServiceState1Proto, 361 mServiceState2Proto, 362 mServiceState3Proto, 363 mServiceState4Proto 364 }; 365 366 // IMS over LTE on slot 0, registered for 5 seconds 367 mImsRegistrationStatsLte0 = new ImsRegistrationStats(); 368 mImsRegistrationStatsLte0.carrierId = CARRIER1_ID; 369 mImsRegistrationStatsLte0.simSlotIndex = 0; 370 mImsRegistrationStatsLte0.rat = TelephonyManager.NETWORK_TYPE_LTE; 371 mImsRegistrationStatsLte0.registeredMillis = 5000L; 372 mImsRegistrationStatsLte0.voiceCapableMillis = 5000L; 373 mImsRegistrationStatsLte0.voiceAvailableMillis = 5000L; 374 mImsRegistrationStatsLte0.smsCapableMillis = 5000L; 375 mImsRegistrationStatsLte0.smsAvailableMillis = 5000L; 376 mImsRegistrationStatsLte0.videoCapableMillis = 5000L; 377 mImsRegistrationStatsLte0.videoAvailableMillis = 5000L; 378 mImsRegistrationStatsLte0.utCapableMillis = 5000L; 379 mImsRegistrationStatsLte0.utAvailableMillis = 5000L; 380 381 // IMS over WiFi on slot 0, registered for 10 seconds (voice only) 382 mImsRegistrationStatsWifi0 = new ImsRegistrationStats(); 383 mImsRegistrationStatsWifi0.carrierId = CARRIER2_ID; 384 mImsRegistrationStatsWifi0.simSlotIndex = 0; 385 mImsRegistrationStatsWifi0.rat = TelephonyManager.NETWORK_TYPE_IWLAN; 386 mImsRegistrationStatsWifi0.registeredMillis = 10000L; 387 mImsRegistrationStatsWifi0.voiceCapableMillis = 10000L; 388 mImsRegistrationStatsWifi0.voiceAvailableMillis = 10000L; 389 390 // IMS over LTE on slot 1, registered for 20 seconds 391 mImsRegistrationStatsLte1 = new ImsRegistrationStats(); 392 mImsRegistrationStatsLte1.carrierId = CARRIER1_ID; 393 mImsRegistrationStatsLte1.simSlotIndex = 0; 394 mImsRegistrationStatsLte1.rat = TelephonyManager.NETWORK_TYPE_LTE; 395 mImsRegistrationStatsLte1.registeredMillis = 20000L; 396 mImsRegistrationStatsLte1.voiceCapableMillis = 20000L; 397 mImsRegistrationStatsLte1.voiceAvailableMillis = 20000L; 398 mImsRegistrationStatsLte1.smsCapableMillis = 20000L; 399 mImsRegistrationStatsLte1.smsAvailableMillis = 20000L; 400 mImsRegistrationStatsLte1.videoCapableMillis = 20000L; 401 mImsRegistrationStatsLte1.videoAvailableMillis = 20000L; 402 mImsRegistrationStatsLte1.utCapableMillis = 20000L; 403 mImsRegistrationStatsLte1.utAvailableMillis = 20000L; 404 405 // IMS terminations on LTE 406 mImsRegistrationTerminationLte = new ImsRegistrationTermination(); 407 mImsRegistrationTerminationLte.carrierId = CARRIER1_ID; 408 mImsRegistrationTerminationLte.isMultiSim = true; 409 mImsRegistrationTerminationLte.ratAtEnd = TelephonyManager.NETWORK_TYPE_LTE; 410 mImsRegistrationTerminationLte.setupFailed = false; 411 mImsRegistrationTerminationLte.reasonCode = ImsReasonInfo.CODE_REGISTRATION_ERROR; 412 mImsRegistrationTerminationLte.extraCode = 999; 413 mImsRegistrationTerminationLte.extraMessage = "Request Timeout"; 414 mImsRegistrationTerminationLte.count = 2; 415 416 // IMS terminations on WiFi 417 mImsRegistrationTerminationWifi = new ImsRegistrationTermination(); 418 mImsRegistrationTerminationWifi.carrierId = CARRIER2_ID; 419 mImsRegistrationTerminationWifi.isMultiSim = true; 420 mImsRegistrationTerminationWifi.ratAtEnd = TelephonyManager.NETWORK_TYPE_IWLAN; 421 mImsRegistrationTerminationWifi.setupFailed = false; 422 mImsRegistrationTerminationWifi.reasonCode = ImsReasonInfo.CODE_REGISTRATION_ERROR; 423 mImsRegistrationTerminationWifi.extraCode = 0; 424 mImsRegistrationTerminationWifi.extraMessage = ""; 425 mImsRegistrationTerminationWifi.count = 1; 426 427 mImsRegistrationStats = 428 new ImsRegistrationStats[] { 429 mImsRegistrationStatsLte0, mImsRegistrationStatsWifi0, mImsRegistrationStatsLte1 430 }; 431 mImsRegistrationTerminations = 432 new ImsRegistrationTermination[] { 433 mImsRegistrationTerminationLte, mImsRegistrationTerminationWifi 434 }; 435 } 436 437 private static class TestablePersistAtomsStorage extends PersistAtomsStorage { 438 private long mTimeMillis = START_TIME_MILLIS; 439 TestablePersistAtomsStorage(Context context)440 TestablePersistAtomsStorage(Context context) { 441 super(context); 442 // Remove delay for saving to persistent storage during tests. 443 mSaveImmediately = true; 444 } 445 446 @Override getWallTimeMillis()447 protected long getWallTimeMillis() { 448 // NOTE: super class constructor will be executed before private field is set, which 449 // gives the wrong start time (mTimeMillis will have its default value of 0L) 450 return mTimeMillis == 0L ? START_TIME_MILLIS : mTimeMillis; 451 } 452 setTimeMillis(long timeMillis)453 private void setTimeMillis(long timeMillis) { 454 mTimeMillis = timeMillis; 455 } 456 incTimeMillis(long timeMillis)457 private void incTimeMillis(long timeMillis) { 458 mTimeMillis += timeMillis; 459 } 460 getAtomsProto()461 private PersistAtoms getAtomsProto() { 462 // NOTE: unlike other methods in PersistAtomsStorage, this is not synchronized, but 463 // should be fine since the test is single-threaded 464 return mAtoms; 465 } 466 } 467 468 private TestablePersistAtomsStorage mPersistAtomsStorage; 469 470 private static final Comparator<MessageNano> sProtoComparator = 471 new Comparator<>() { 472 @Override 473 public int compare(MessageNano o1, MessageNano o2) { 474 if (o1 == o2) { 475 return 0; 476 } 477 if (o1 == null) { 478 return -1; 479 } 480 if (o2 == null) { 481 return 1; 482 } 483 assertEquals(o1.getClass(), o2.getClass()); 484 return o1.toString().compareTo(o2.toString()); 485 } 486 }; 487 488 @Before setUp()489 public void setUp() throws Exception { 490 super.setUp(getClass().getSimpleName()); 491 makeTestData(); 492 493 // by default, test loading with real file IO and saving with mocks 494 mTestFile = mFolder.newFile(TEST_FILE); 495 doReturn(mTestFileOutputStream).when(mContext).openFileOutput(anyString(), anyInt()); 496 doReturn(mTestFile).when(mContext).getFileStreamPath(anyString()); 497 } 498 499 @After tearDown()500 public void tearDown() throws Exception { 501 mTestFile.delete(); 502 super.tearDown(); 503 } 504 505 @Test 506 @SmallTest loadAtoms_fileNotExist()507 public void loadAtoms_fileNotExist() throws Exception { 508 mTestFile.delete(); 509 510 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 511 mPersistAtomsStorage.incTimeMillis(100L); 512 513 // no exception should be thrown, storage should be empty, pull time should be start time 514 assertAllPullTimestampEquals(START_TIME_MILLIS); 515 assertStorageIsEmptyForAllAtoms(); 516 } 517 518 @Test 519 @SmallTest loadAtoms_unreadable()520 public void loadAtoms_unreadable() throws Exception { 521 createEmptyTestFile(); 522 mTestFile.setReadable(false); 523 524 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 525 mPersistAtomsStorage.incTimeMillis(100L); 526 527 // no exception should be thrown, storage should be empty, pull time should be start time 528 assertAllPullTimestampEquals(START_TIME_MILLIS); 529 assertStorageIsEmptyForAllAtoms(); 530 } 531 532 @Test 533 @SmallTest loadAtoms_emptyProto()534 public void loadAtoms_emptyProto() throws Exception { 535 createEmptyTestFile(); 536 537 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 538 mPersistAtomsStorage.incTimeMillis(100L); 539 540 // no exception should be thrown, storage should be empty, pull time should be start time 541 assertAllPullTimestampEquals(START_TIME_MILLIS); 542 assertStorageIsEmptyForAllAtoms(); 543 } 544 545 @Test 546 @SmallTest loadAtoms_malformedFile()547 public void loadAtoms_malformedFile() throws Exception { 548 FileOutputStream stream = new FileOutputStream(mTestFile); 549 stream.write("This is not a proto file.".getBytes(StandardCharsets.UTF_8)); 550 stream.close(); 551 552 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 553 mPersistAtomsStorage.incTimeMillis(100L); 554 555 // no exception should be thrown, storage should be empty, pull time should be start time 556 assertAllPullTimestampEquals(START_TIME_MILLIS); 557 assertStorageIsEmptyForAllAtoms(); 558 } 559 560 @Test 561 @SmallTest loadAtoms_pullTimeMissing()562 public void loadAtoms_pullTimeMissing() throws Exception { 563 // create test file with lastPullTimeMillis = 0L, i.e. default/unknown 564 createTestFile(0L); 565 566 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 567 mPersistAtomsStorage.incTimeMillis(100L); 568 569 // no exception should be thrown, storage should be match, pull time should be start time 570 assertAllPullTimestampEquals(START_TIME_MILLIS); 571 assertProtoArrayEquals(mVoiceCallRatUsages, mPersistAtomsStorage.getVoiceCallRatUsages(0L)); 572 assertProtoArrayEquals(mVoiceCallSessions, mPersistAtomsStorage.getVoiceCallSessions(0L)); 573 assertProtoArrayEqualsIgnoringOrder( 574 mServiceStates, mPersistAtomsStorage.getCellularServiceStates(0L)); 575 assertProtoArrayEqualsIgnoringOrder( 576 mServiceSwitches, mPersistAtomsStorage.getCellularDataServiceSwitches(0L)); 577 } 578 579 @Test 580 @SmallTest loadAtoms_validContents()581 public void loadAtoms_validContents() throws Exception { 582 createTestFile(/* lastPullTimeMillis= */ 100L); 583 584 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 585 586 // no exception should be thrown, storage and pull time should match 587 assertAllPullTimestampEquals(100L); 588 assertProtoArrayEquals(mVoiceCallRatUsages, mPersistAtomsStorage.getVoiceCallRatUsages(0L)); 589 assertProtoArrayEquals(mVoiceCallSessions, mPersistAtomsStorage.getVoiceCallSessions(0L)); 590 assertProtoArrayEqualsIgnoringOrder( 591 mServiceStates, mPersistAtomsStorage.getCellularServiceStates(0L)); 592 assertProtoArrayEqualsIgnoringOrder( 593 mServiceSwitches, mPersistAtomsStorage.getCellularDataServiceSwitches(0L)); 594 } 595 596 @Test 597 @SmallTest addVoiceCallSession_emptyProto()598 public void addVoiceCallSession_emptyProto() throws Exception { 599 createEmptyTestFile(); 600 601 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 602 mPersistAtomsStorage.addVoiceCallSession(mCall1Proto); 603 mPersistAtomsStorage.incTimeMillis(100L); 604 605 // call should be added successfully, there should be no RAT usage, changes should be saved 606 verifyCurrentStateSavedToFileOnce(); 607 assertProtoArrayIsEmpty(mPersistAtomsStorage.getVoiceCallRatUsages(0L)); 608 VoiceCallSession[] voiceCallSession = mPersistAtomsStorage.getVoiceCallSessions(0L); 609 assertProtoArrayEquals(new VoiceCallSession[] {mCall1Proto}, voiceCallSession); 610 } 611 612 @Test 613 @SmallTest addVoiceCallSession_withExistingCalls()614 public void addVoiceCallSession_withExistingCalls() throws Exception { 615 createTestFile(START_TIME_MILLIS); 616 617 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 618 mPersistAtomsStorage.addVoiceCallSession(mCall1Proto); 619 mPersistAtomsStorage.incTimeMillis(100L); 620 621 // call should be added successfully, RAT usages should not change, changes should be saved 622 assertProtoArrayEquals(mVoiceCallRatUsages, mPersistAtomsStorage.getVoiceCallRatUsages(0L)); 623 VoiceCallSession[] expectedVoiceCallSessions = 624 new VoiceCallSession[] { 625 mCall1Proto, mCall1Proto, mCall2Proto, mCall3Proto, mCall4Proto 626 }; 627 // call list is randomized at this point 628 verifyCurrentStateSavedToFileOnce(); 629 assertProtoArrayEqualsIgnoringOrder( 630 expectedVoiceCallSessions, mPersistAtomsStorage.getVoiceCallSessions(0L)); 631 } 632 633 @Test 634 @SmallTest addVoiceCallSession_tooManyCalls()635 public void addVoiceCallSession_tooManyCalls() throws Exception { 636 createEmptyTestFile(); 637 638 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 639 addRepeatedCalls(mPersistAtomsStorage, mCall1Proto, 50); 640 mPersistAtomsStorage.addVoiceCallSession(mCall2Proto); 641 mPersistAtomsStorage.incTimeMillis(100L); 642 643 // one previous call should be evicted, the new call should be added 644 verifyCurrentStateSavedToFileOnce(); 645 VoiceCallSession[] calls = mPersistAtomsStorage.getVoiceCallSessions(0L); 646 assertHasCall(calls, mCall1Proto, /* expectedCount= */ 49); 647 assertHasCall(calls, mCall2Proto, /* expectedCount= */ 1); 648 } 649 650 @Test 651 @SmallTest addVoiceCallRatUsage_emptyProto()652 public void addVoiceCallRatUsage_emptyProto() throws Exception { 653 createEmptyTestFile(); 654 VoiceCallRatTracker ratTracker = VoiceCallRatTracker.fromProto(mVoiceCallRatUsages); 655 656 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 657 mPersistAtomsStorage.addVoiceCallRatUsage(ratTracker); 658 mPersistAtomsStorage.incTimeMillis(100L); 659 660 // RAT should be added successfully, calls should not change, changes should be saved 661 verifyCurrentStateSavedToFileOnce(); 662 assertProtoArrayEqualsIgnoringOrder( 663 mVoiceCallRatUsages, mPersistAtomsStorage.getVoiceCallRatUsages(0L)); 664 assertProtoArrayIsEmpty(mPersistAtomsStorage.getVoiceCallSessions(0L)); 665 } 666 667 @Test 668 @SmallTest addVoiceCallRatUsage_withExistingUsages()669 public void addVoiceCallRatUsage_withExistingUsages() throws Exception { 670 createTestFile(START_TIME_MILLIS); 671 VoiceCallRatTracker ratTracker = VoiceCallRatTracker.fromProto(mVoiceCallRatUsages); 672 673 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 674 mPersistAtomsStorage.addVoiceCallRatUsage(ratTracker); 675 mPersistAtomsStorage.incTimeMillis(100L); 676 677 // RAT should be added successfully, calls should not change, changes should be saved 678 // call count and duration should become doubled since mVoiceCallRatUsages applied through 679 // both file and addVoiceCallRatUsage() 680 verifyCurrentStateSavedToFileOnce(); 681 VoiceCallRatUsage[] expectedVoiceCallRatUsage = 682 multiplyVoiceCallRatUsage(mVoiceCallRatUsages, 2); 683 assertProtoArrayEqualsIgnoringOrder( 684 expectedVoiceCallRatUsage, mPersistAtomsStorage.getVoiceCallRatUsages(0L)); 685 assertProtoArrayEquals(mVoiceCallSessions, mPersistAtomsStorage.getVoiceCallSessions(0L)); 686 } 687 688 @Test 689 @SmallTest addVoiceCallRatUsage_empty()690 public void addVoiceCallRatUsage_empty() throws Exception { 691 createEmptyTestFile(); 692 VoiceCallRatTracker ratTracker = VoiceCallRatTracker.fromProto(new VoiceCallRatUsage[0]); 693 694 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 695 mPersistAtomsStorage.addVoiceCallRatUsage(ratTracker); 696 mPersistAtomsStorage.incTimeMillis(100L); 697 698 // RAT should be added successfully, calls should not change 699 // in this case saving is unnecessarily 700 assertProtoArrayIsEmpty(mPersistAtomsStorage.getVoiceCallRatUsages(0L)); 701 assertProtoArrayIsEmpty(mPersistAtomsStorage.getVoiceCallSessions(0L)); 702 } 703 704 @Test 705 @SmallTest getVoiceCallRatUsages_tooFrequent()706 public void getVoiceCallRatUsages_tooFrequent() throws Exception { 707 createTestFile(START_TIME_MILLIS); 708 709 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 710 mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum 711 VoiceCallRatUsage[] voiceCallRatUsage = mPersistAtomsStorage.getVoiceCallRatUsages(100L); 712 713 // should be denied 714 assertNull(voiceCallRatUsage); 715 } 716 717 @Test 718 @SmallTest getVoiceCallRatUsages_withSavedAtoms()719 public void getVoiceCallRatUsages_withSavedAtoms() throws Exception { 720 createTestFile(START_TIME_MILLIS); 721 722 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 723 mPersistAtomsStorage.incTimeMillis(100L); 724 VoiceCallRatUsage[] voiceCallRatUsage1 = mPersistAtomsStorage.getVoiceCallRatUsages(50L); 725 mPersistAtomsStorage.incTimeMillis(100L); 726 VoiceCallRatUsage[] voiceCallRatUsage2 = mPersistAtomsStorage.getVoiceCallRatUsages(50L); 727 long voiceCallSessionPullTimestampMillis = 728 mPersistAtomsStorage.getAtomsProto().voiceCallSessionPullTimestampMillis; 729 VoiceCallSession[] voiceCallSession = mPersistAtomsStorage.getVoiceCallSessions(50L); 730 731 // first set of results should equal to file contents, second should be empty, corresponding 732 // pull timestamp should be updated and saved, other fields should be unaffected 733 assertProtoArrayEquals(mVoiceCallRatUsages, voiceCallRatUsage1); 734 assertProtoArrayIsEmpty(voiceCallRatUsage2); 735 assertEquals( 736 START_TIME_MILLIS + 200L, 737 mPersistAtomsStorage.getAtomsProto().voiceCallRatUsagePullTimestampMillis); 738 assertProtoArrayEquals(mVoiceCallSessions, voiceCallSession); 739 assertEquals(START_TIME_MILLIS, voiceCallSessionPullTimestampMillis); 740 InOrder inOrder = inOrder(mTestFileOutputStream); 741 assertEquals( 742 START_TIME_MILLIS + 100L, 743 getAtomsWritten(inOrder).voiceCallRatUsagePullTimestampMillis); 744 assertEquals( 745 START_TIME_MILLIS + 200L, 746 getAtomsWritten(inOrder).voiceCallRatUsagePullTimestampMillis); 747 assertEquals( 748 START_TIME_MILLIS + 200L, 749 getAtomsWritten(inOrder).voiceCallSessionPullTimestampMillis); 750 inOrder.verifyNoMoreInteractions(); 751 } 752 753 @Test 754 @SmallTest getVoiceCallSessions_tooFrequent()755 public void getVoiceCallSessions_tooFrequent() throws Exception { 756 createTestFile(START_TIME_MILLIS); 757 758 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 759 mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum 760 VoiceCallSession[] voiceCallSession = mPersistAtomsStorage.getVoiceCallSessions(100L); 761 762 // should be denied 763 assertNull(voiceCallSession); 764 } 765 766 @Test 767 @SmallTest getVoiceCallSessions_withSavedAtoms()768 public void getVoiceCallSessions_withSavedAtoms() throws Exception { 769 createTestFile(START_TIME_MILLIS); 770 771 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 772 mPersistAtomsStorage.incTimeMillis(100L); 773 VoiceCallSession[] voiceCallSession1 = mPersistAtomsStorage.getVoiceCallSessions(50L); 774 mPersistAtomsStorage.incTimeMillis(100L); 775 VoiceCallSession[] voiceCallSession2 = mPersistAtomsStorage.getVoiceCallSessions(50L); 776 long voiceCallRatUsagePullTimestampMillis = 777 mPersistAtomsStorage.getAtomsProto().voiceCallRatUsagePullTimestampMillis; 778 VoiceCallRatUsage[] voiceCallRatUsage = mPersistAtomsStorage.getVoiceCallRatUsages(50L); 779 780 // first set of results should equal to file contents, second should be empty, corresponding 781 // pull timestamp should be updated and saved, other fields should be unaffected 782 assertProtoArrayEquals(mVoiceCallSessions, voiceCallSession1); 783 assertProtoArrayIsEmpty(voiceCallSession2); 784 assertEquals( 785 START_TIME_MILLIS + 200L, 786 mPersistAtomsStorage.getAtomsProto().voiceCallSessionPullTimestampMillis); 787 assertProtoArrayEquals(mVoiceCallRatUsages, voiceCallRatUsage); 788 assertEquals(START_TIME_MILLIS, voiceCallRatUsagePullTimestampMillis); 789 InOrder inOrder = inOrder(mTestFileOutputStream); 790 assertEquals( 791 START_TIME_MILLIS + 100L, 792 getAtomsWritten(inOrder).voiceCallSessionPullTimestampMillis); 793 assertEquals( 794 START_TIME_MILLIS + 200L, 795 getAtomsWritten(inOrder).voiceCallSessionPullTimestampMillis); 796 assertEquals( 797 START_TIME_MILLIS + 200L, 798 getAtomsWritten(inOrder).voiceCallRatUsagePullTimestampMillis); 799 inOrder.verifyNoMoreInteractions(); 800 } 801 802 @Test 803 @SmallTest addCellularServiceStateAndCellularDataServiceSwitch_emptyProto()804 public void addCellularServiceStateAndCellularDataServiceSwitch_emptyProto() throws Exception { 805 createEmptyTestFile(); 806 807 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 808 mPersistAtomsStorage.addCellularServiceStateAndCellularDataServiceSwitch( 809 mServiceState1Proto, mServiceSwitch1Proto); 810 mPersistAtomsStorage.incTimeMillis(100L); 811 812 // service state and service switch should be added successfully 813 verifyCurrentStateSavedToFileOnce(); 814 CellularServiceState[] serviceStates = mPersistAtomsStorage.getCellularServiceStates(0L); 815 CellularDataServiceSwitch[] serviceSwitches = 816 mPersistAtomsStorage.getCellularDataServiceSwitches(0L); 817 assertProtoArrayEquals(new CellularServiceState[] {mServiceState1Proto}, serviceStates); 818 assertProtoArrayEquals( 819 new CellularDataServiceSwitch[] {mServiceSwitch1Proto}, serviceSwitches); 820 } 821 822 @Test 823 @SmallTest addCellularServiceStateAndCellularDataServiceSwitch_withExistingEntries()824 public void addCellularServiceStateAndCellularDataServiceSwitch_withExistingEntries() 825 throws Exception { 826 createEmptyTestFile(); 827 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 828 mPersistAtomsStorage.addCellularServiceStateAndCellularDataServiceSwitch( 829 mServiceState1Proto, mServiceSwitch1Proto); 830 831 mPersistAtomsStorage.addCellularServiceStateAndCellularDataServiceSwitch( 832 mServiceState2Proto, mServiceSwitch2Proto); 833 mPersistAtomsStorage.incTimeMillis(100L); 834 835 // service state and service switch should be added successfully 836 verifyCurrentStateSavedToFileOnce(); 837 CellularServiceState[] serviceStates = mPersistAtomsStorage.getCellularServiceStates(0L); 838 CellularDataServiceSwitch[] serviceSwitches = 839 mPersistAtomsStorage.getCellularDataServiceSwitches(0L); 840 assertProtoArrayEqualsIgnoringOrder( 841 new CellularServiceState[] {mServiceState1Proto, mServiceState2Proto}, 842 serviceStates); 843 assertProtoArrayEqualsIgnoringOrder( 844 new CellularDataServiceSwitch[] {mServiceSwitch1Proto, mServiceSwitch2Proto}, 845 serviceSwitches); 846 } 847 848 @Test 849 @SmallTest addCellularServiceStateAndCellularDataServiceSwitch_updateExistingEntries()850 public void addCellularServiceStateAndCellularDataServiceSwitch_updateExistingEntries() 851 throws Exception { 852 createTestFile(START_TIME_MILLIS); 853 CellularServiceState newServiceState1Proto = copyOf(mServiceState1Proto); 854 CellularDataServiceSwitch newServiceSwitch1Proto = copyOf(mServiceSwitch1Proto); 855 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 856 857 mPersistAtomsStorage.addCellularServiceStateAndCellularDataServiceSwitch( 858 copyOf(mServiceState1Proto), copyOf(mServiceSwitch1Proto)); 859 mPersistAtomsStorage.incTimeMillis(100L); 860 861 // mServiceState1Proto's duration and mServiceSwitch1Proto's switch should be doubled 862 verifyCurrentStateSavedToFileOnce(); 863 CellularServiceState[] serviceStates = mPersistAtomsStorage.getCellularServiceStates(0L); 864 newServiceState1Proto.totalTimeMillis *= 2; 865 assertProtoArrayEqualsIgnoringOrder( 866 new CellularServiceState[] { 867 newServiceState1Proto, 868 mServiceState2Proto, 869 mServiceState3Proto, 870 mServiceState4Proto 871 }, 872 serviceStates); 873 CellularDataServiceSwitch[] serviceSwitches = 874 mPersistAtomsStorage.getCellularDataServiceSwitches(0L); 875 newServiceSwitch1Proto.switchCount *= 2; 876 assertProtoArrayEqualsIgnoringOrder( 877 new CellularDataServiceSwitch[] {newServiceSwitch1Proto, mServiceSwitch2Proto}, 878 serviceSwitches); 879 } 880 881 @Test 882 @SmallTest addCellularServiceStateAndCellularDataServiceSwitch_tooManyServiceStates()883 public void addCellularServiceStateAndCellularDataServiceSwitch_tooManyServiceStates() 884 throws Exception { 885 createEmptyTestFile(); 886 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 887 Queue<CellularServiceState> expectedServiceStates = new LinkedList<>(); 888 Queue<CellularDataServiceSwitch> expectedServiceSwitches = new LinkedList<>(); 889 890 // Add 51 service states, with the first being least recent 891 for (int i = 0; i < 51; i++) { 892 CellularServiceState state = new CellularServiceState(); 893 state.voiceRat = i / 10; 894 state.dataRat = i % 10; 895 expectedServiceStates.add(state); 896 CellularDataServiceSwitch serviceSwitch = new CellularDataServiceSwitch(); 897 serviceSwitch.ratFrom = i / 10; 898 serviceSwitch.ratTo = i % 10; 899 expectedServiceSwitches.add(serviceSwitch); 900 mPersistAtomsStorage.addCellularServiceStateAndCellularDataServiceSwitch( 901 copyOf(state), copyOf(serviceSwitch)); 902 mPersistAtomsStorage.incTimeMillis(100L); 903 } 904 905 // The least recent (the first) service state should be evicted 906 verifyCurrentStateSavedToFileOnce(); 907 CellularServiceState[] serviceStates = mPersistAtomsStorage.getCellularServiceStates(0L); 908 expectedServiceStates.remove(); 909 assertProtoArrayEqualsIgnoringOrder( 910 expectedServiceStates.toArray(new CellularServiceState[0]), serviceStates); 911 CellularDataServiceSwitch[] serviceSwitches = 912 mPersistAtomsStorage.getCellularDataServiceSwitches(0L); 913 expectedServiceSwitches.remove(); 914 assertProtoArrayEqualsIgnoringOrder( 915 expectedServiceSwitches.toArray(new CellularDataServiceSwitch[0]), serviceSwitches); 916 } 917 918 @Test 919 @SmallTest getCellularDataServiceSwitches_tooFrequent()920 public void getCellularDataServiceSwitches_tooFrequent() throws Exception { 921 createTestFile(START_TIME_MILLIS); 922 923 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 924 mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum 925 CellularDataServiceSwitch[] serviceSwitches = 926 mPersistAtomsStorage.getCellularDataServiceSwitches(100L); 927 928 // should be denied 929 assertNull(serviceSwitches); 930 } 931 932 @Test 933 @SmallTest getCellularDataServiceSwitches_withSavedAtoms()934 public void getCellularDataServiceSwitches_withSavedAtoms() throws Exception { 935 createTestFile(START_TIME_MILLIS); 936 937 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 938 mPersistAtomsStorage.incTimeMillis(100L); 939 CellularDataServiceSwitch[] serviceSwitches1 = 940 mPersistAtomsStorage.getCellularDataServiceSwitches(50L); 941 mPersistAtomsStorage.incTimeMillis(100L); 942 CellularDataServiceSwitch[] serviceSwitches2 = 943 mPersistAtomsStorage.getCellularDataServiceSwitches(50L); 944 945 // first set of results should equal to file contents, second should be empty, corresponding 946 // pull timestamp should be updated and saved 947 assertProtoArrayEqualsIgnoringOrder( 948 new CellularDataServiceSwitch[] {mServiceSwitch1Proto, mServiceSwitch2Proto}, 949 serviceSwitches1); 950 assertProtoArrayEquals(new CellularDataServiceSwitch[0], serviceSwitches2); 951 assertEquals( 952 START_TIME_MILLIS + 200L, 953 mPersistAtomsStorage.getAtomsProto().cellularDataServiceSwitchPullTimestampMillis); 954 InOrder inOrder = inOrder(mTestFileOutputStream); 955 assertEquals( 956 START_TIME_MILLIS + 100L, 957 getAtomsWritten(inOrder).cellularDataServiceSwitchPullTimestampMillis); 958 assertEquals( 959 START_TIME_MILLIS + 200L, 960 getAtomsWritten(inOrder).cellularDataServiceSwitchPullTimestampMillis); 961 inOrder.verifyNoMoreInteractions(); 962 } 963 964 @Test 965 @SmallTest getCellularServiceStates_tooFrequent()966 public void getCellularServiceStates_tooFrequent() throws Exception { 967 createTestFile(START_TIME_MILLIS); 968 969 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 970 mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum 971 CellularServiceState[] serviceStates = mPersistAtomsStorage.getCellularServiceStates(100L); 972 973 // should be denied 974 assertNull(serviceStates); 975 } 976 977 @Test 978 @SmallTest getCellularServiceStates_withSavedAtoms()979 public void getCellularServiceStates_withSavedAtoms() throws Exception { 980 createTestFile(START_TIME_MILLIS); 981 982 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 983 mPersistAtomsStorage.incTimeMillis(100L); 984 CellularServiceState[] serviceStates1 = mPersistAtomsStorage.getCellularServiceStates(50L); 985 mPersistAtomsStorage.incTimeMillis(100L); 986 CellularServiceState[] serviceStates2 = mPersistAtomsStorage.getCellularServiceStates(50L); 987 988 // first set of results should equal to file contents, second should be empty, corresponding 989 // pull timestamp should be updated and saved 990 assertProtoArrayEqualsIgnoringOrder( 991 new CellularServiceState[] { 992 mServiceState1Proto, 993 mServiceState2Proto, 994 mServiceState3Proto, 995 mServiceState4Proto 996 }, 997 serviceStates1); 998 assertProtoArrayEquals(new CellularServiceState[0], serviceStates2); 999 assertEquals( 1000 START_TIME_MILLIS + 200L, 1001 mPersistAtomsStorage.getAtomsProto().cellularServiceStatePullTimestampMillis); 1002 InOrder inOrder = inOrder(mTestFileOutputStream); 1003 assertEquals( 1004 START_TIME_MILLIS + 100L, 1005 getAtomsWritten(inOrder).cellularServiceStatePullTimestampMillis); 1006 assertEquals( 1007 START_TIME_MILLIS + 200L, 1008 getAtomsWritten(inOrder).cellularServiceStatePullTimestampMillis); 1009 inOrder.verifyNoMoreInteractions(); 1010 } 1011 1012 @Test 1013 @SmallTest addImsRegistrationStats_emptyProto()1014 public void addImsRegistrationStats_emptyProto() throws Exception { 1015 createEmptyTestFile(); 1016 1017 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 1018 mPersistAtomsStorage.addImsRegistrationStats(mImsRegistrationStatsLte0); 1019 mPersistAtomsStorage.incTimeMillis(100L); 1020 1021 // service state and service switch should be added successfully 1022 verifyCurrentStateSavedToFileOnce(); 1023 ImsRegistrationStats[] regStats = mPersistAtomsStorage.getImsRegistrationStats(0L); 1024 assertProtoArrayEquals(new ImsRegistrationStats[] {mImsRegistrationStatsLte0}, regStats); 1025 } 1026 1027 @Test 1028 @SmallTest addImsRegistrationStats_withExistingEntries()1029 public void addImsRegistrationStats_withExistingEntries() throws Exception { 1030 createEmptyTestFile(); 1031 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 1032 mPersistAtomsStorage.addImsRegistrationStats(mImsRegistrationStatsLte0); 1033 1034 mPersistAtomsStorage.addImsRegistrationStats(mImsRegistrationStatsWifi0); 1035 mPersistAtomsStorage.incTimeMillis(100L); 1036 1037 // service state and service switch should be added successfully 1038 verifyCurrentStateSavedToFileOnce(); 1039 ImsRegistrationStats[] regStats = mPersistAtomsStorage.getImsRegistrationStats(0L); 1040 assertProtoArrayEqualsIgnoringOrder( 1041 new ImsRegistrationStats[] {mImsRegistrationStatsLte0, mImsRegistrationStatsWifi0}, 1042 regStats); 1043 } 1044 1045 @Test 1046 @SmallTest addImsRegistrationStats_updateExistingEntries()1047 public void addImsRegistrationStats_updateExistingEntries() throws Exception { 1048 createTestFile(START_TIME_MILLIS); 1049 ImsRegistrationStats newImsRegistrationStatsLte0 = copyOf(mImsRegistrationStatsLte0); 1050 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 1051 1052 mPersistAtomsStorage.addImsRegistrationStats(copyOf(mImsRegistrationStatsLte0)); 1053 mPersistAtomsStorage.incTimeMillis(100L); 1054 1055 // mImsRegistrationStatsLte0's durations should be doubled 1056 verifyCurrentStateSavedToFileOnce(); 1057 ImsRegistrationStats[] serviceStates = mPersistAtomsStorage.getImsRegistrationStats(0L); 1058 newImsRegistrationStatsLte0.registeredMillis *= 2; 1059 newImsRegistrationStatsLte0.voiceCapableMillis *= 2; 1060 newImsRegistrationStatsLte0.voiceAvailableMillis *= 2; 1061 newImsRegistrationStatsLte0.smsCapableMillis *= 2; 1062 newImsRegistrationStatsLte0.smsAvailableMillis *= 2; 1063 newImsRegistrationStatsLte0.videoCapableMillis *= 2; 1064 newImsRegistrationStatsLte0.videoAvailableMillis *= 2; 1065 newImsRegistrationStatsLte0.utCapableMillis *= 2; 1066 newImsRegistrationStatsLte0.utAvailableMillis *= 2; 1067 assertProtoArrayEqualsIgnoringOrder( 1068 new ImsRegistrationStats[] { 1069 newImsRegistrationStatsLte0, 1070 mImsRegistrationStatsWifi0, 1071 mImsRegistrationStatsLte1 1072 }, 1073 serviceStates); 1074 } 1075 1076 @Test 1077 @SmallTest addImsRegistrationStats_tooManyRegistrationStats()1078 public void addImsRegistrationStats_tooManyRegistrationStats() throws Exception { 1079 createEmptyTestFile(); 1080 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 1081 Queue<ImsRegistrationStats> expectedRegistrationStats = new LinkedList<>(); 1082 1083 // Add 11 registration stats 1084 for (int i = 0; i < 11; i++) { 1085 ImsRegistrationStats stats = copyOf(mImsRegistrationStatsLte0); 1086 stats.rat = i; 1087 expectedRegistrationStats.add(stats); 1088 mPersistAtomsStorage.addImsRegistrationStats(stats); 1089 mPersistAtomsStorage.incTimeMillis(100L); 1090 } 1091 1092 // The least recent (the first) registration stats should be evicted 1093 verifyCurrentStateSavedToFileOnce(); 1094 ImsRegistrationStats[] stats = mPersistAtomsStorage.getImsRegistrationStats(0L); 1095 expectedRegistrationStats.remove(); 1096 assertProtoArrayEqualsIgnoringOrder( 1097 expectedRegistrationStats.toArray(new ImsRegistrationStats[0]), stats); 1098 } 1099 1100 @Test 1101 @SmallTest addImsRegistrationTermination_emptyProto()1102 public void addImsRegistrationTermination_emptyProto() throws Exception { 1103 createEmptyTestFile(); 1104 1105 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 1106 mPersistAtomsStorage.addImsRegistrationTermination(mImsRegistrationTerminationLte); 1107 mPersistAtomsStorage.incTimeMillis(100L); 1108 1109 // service state and service switch should be added successfully 1110 verifyCurrentStateSavedToFileOnce(); 1111 ImsRegistrationTermination[] terminations = 1112 mPersistAtomsStorage.getImsRegistrationTerminations(0L); 1113 assertProtoArrayEquals( 1114 new ImsRegistrationTermination[] {mImsRegistrationTerminationLte}, terminations); 1115 } 1116 1117 @Test 1118 @SmallTest addImsRegistrationTermination_withExistingEntries()1119 public void addImsRegistrationTermination_withExistingEntries() throws Exception { 1120 createEmptyTestFile(); 1121 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 1122 mPersistAtomsStorage.addImsRegistrationTermination(mImsRegistrationTerminationLte); 1123 1124 mPersistAtomsStorage.addImsRegistrationTermination(mImsRegistrationTerminationWifi); 1125 mPersistAtomsStorage.incTimeMillis(100L); 1126 1127 // service state and service switch should be added successfully 1128 verifyCurrentStateSavedToFileOnce(); 1129 ImsRegistrationTermination[] terminations = 1130 mPersistAtomsStorage.getImsRegistrationTerminations(0L); 1131 assertProtoArrayEqualsIgnoringOrder( 1132 new ImsRegistrationTermination[] { 1133 mImsRegistrationTerminationLte, mImsRegistrationTerminationWifi 1134 }, 1135 terminations); 1136 } 1137 1138 @Test 1139 @SmallTest addImsRegistrationTermination_updateExistingEntries()1140 public void addImsRegistrationTermination_updateExistingEntries() throws Exception { 1141 createTestFile(START_TIME_MILLIS); 1142 ImsRegistrationTermination newTermination = copyOf(mImsRegistrationTerminationWifi); 1143 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 1144 1145 mPersistAtomsStorage.addImsRegistrationTermination(copyOf(mImsRegistrationTerminationWifi)); 1146 mPersistAtomsStorage.incTimeMillis(100L); 1147 1148 // mImsRegistrationTerminationWifi's count should be doubled 1149 verifyCurrentStateSavedToFileOnce(); 1150 ImsRegistrationTermination[] terminations = 1151 mPersistAtomsStorage.getImsRegistrationTerminations(0L); 1152 newTermination.count *= 2; 1153 assertProtoArrayEqualsIgnoringOrder( 1154 new ImsRegistrationTermination[] {mImsRegistrationTerminationLte, newTermination}, 1155 terminations); 1156 } 1157 1158 @Test 1159 @SmallTest addImsRegistrationTermination_tooManyTerminations()1160 public void addImsRegistrationTermination_tooManyTerminations() throws Exception { 1161 createEmptyTestFile(); 1162 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 1163 Queue<ImsRegistrationTermination> expectedTerminations = new LinkedList<>(); 1164 1165 // Add 11 registration terminations 1166 for (int i = 0; i < 11; i++) { 1167 ImsRegistrationTermination termination = copyOf(mImsRegistrationTerminationLte); 1168 termination.reasonCode = i; 1169 expectedTerminations.add(termination); 1170 mPersistAtomsStorage.addImsRegistrationTermination(termination); 1171 mPersistAtomsStorage.incTimeMillis(100L); 1172 } 1173 1174 // The least recent (the first) registration termination should be evicted 1175 verifyCurrentStateSavedToFileOnce(); 1176 ImsRegistrationTermination[] terminations = 1177 mPersistAtomsStorage.getImsRegistrationTerminations(0L); 1178 expectedTerminations.remove(); 1179 assertProtoArrayEqualsIgnoringOrder( 1180 expectedTerminations.toArray(new ImsRegistrationTermination[0]), terminations); 1181 } 1182 1183 @Test 1184 @SmallTest getImsRegistrationStats_tooFrequent()1185 public void getImsRegistrationStats_tooFrequent() throws Exception { 1186 createTestFile(START_TIME_MILLIS); 1187 1188 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 1189 mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum 1190 ImsRegistrationStats[] stats = mPersistAtomsStorage.getImsRegistrationStats(100L); 1191 1192 // should be denied 1193 assertNull(stats); 1194 } 1195 1196 @Test 1197 @SmallTest getImsRegistrationStats_withSavedAtoms()1198 public void getImsRegistrationStats_withSavedAtoms() throws Exception { 1199 createTestFile(START_TIME_MILLIS); 1200 1201 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 1202 mPersistAtomsStorage.incTimeMillis(100L); 1203 ImsRegistrationStats[] stats1 = mPersistAtomsStorage.getImsRegistrationStats(50L); 1204 mPersistAtomsStorage.incTimeMillis(100L); 1205 ImsRegistrationStats[] stats2 = mPersistAtomsStorage.getImsRegistrationStats(50L); 1206 1207 // first set of results should equal to file contents, second should be empty, corresponding 1208 // pull timestamp should be updated and saved 1209 assertProtoArrayEqualsIgnoringOrder( 1210 new ImsRegistrationStats[] { 1211 mImsRegistrationStatsLte0, mImsRegistrationStatsWifi0, mImsRegistrationStatsLte1 1212 }, 1213 stats1); 1214 assertProtoArrayEquals(new ImsRegistrationStats[0], stats2); 1215 assertEquals( 1216 START_TIME_MILLIS + 200L, 1217 mPersistAtomsStorage.getAtomsProto().imsRegistrationStatsPullTimestampMillis); 1218 InOrder inOrder = inOrder(mTestFileOutputStream); 1219 assertEquals( 1220 START_TIME_MILLIS + 100L, 1221 getAtomsWritten(inOrder).imsRegistrationStatsPullTimestampMillis); 1222 assertEquals( 1223 START_TIME_MILLIS + 200L, 1224 getAtomsWritten(inOrder).imsRegistrationStatsPullTimestampMillis); 1225 inOrder.verifyNoMoreInteractions(); 1226 } 1227 1228 @Test 1229 @SmallTest getImsRegistrationTerminations_tooFrequent()1230 public void getImsRegistrationTerminations_tooFrequent() throws Exception { 1231 createTestFile(START_TIME_MILLIS); 1232 1233 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 1234 mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum 1235 ImsRegistrationTermination[] terminations = 1236 mPersistAtomsStorage.getImsRegistrationTerminations(100L); 1237 1238 // should be denied 1239 assertNull(terminations); 1240 } 1241 1242 @Test 1243 @SmallTest getImsRegistrationTerminations_withSavedAtoms()1244 public void getImsRegistrationTerminations_withSavedAtoms() throws Exception { 1245 createTestFile(START_TIME_MILLIS); 1246 1247 mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); 1248 mPersistAtomsStorage.incTimeMillis(100L); 1249 ImsRegistrationTermination[] terminations1 = 1250 mPersistAtomsStorage.getImsRegistrationTerminations(50L); 1251 mPersistAtomsStorage.incTimeMillis(100L); 1252 ImsRegistrationTermination[] terminations2 = 1253 mPersistAtomsStorage.getImsRegistrationTerminations(50L); 1254 1255 // first set of results should equal to file contents, second should be empty, corresponding 1256 // pull timestamp should be updated and saved 1257 assertProtoArrayEqualsIgnoringOrder( 1258 new ImsRegistrationTermination[] { 1259 mImsRegistrationTerminationLte, mImsRegistrationTerminationWifi 1260 }, 1261 terminations1); 1262 assertProtoArrayEquals(new ImsRegistrationTermination[0], terminations2); 1263 assertEquals( 1264 START_TIME_MILLIS + 200L, 1265 mPersistAtomsStorage.getAtomsProto().imsRegistrationTerminationPullTimestampMillis); 1266 InOrder inOrder = inOrder(mTestFileOutputStream); 1267 assertEquals( 1268 START_TIME_MILLIS + 100L, 1269 getAtomsWritten(inOrder).imsRegistrationTerminationPullTimestampMillis); 1270 assertEquals( 1271 START_TIME_MILLIS + 200L, 1272 getAtomsWritten(inOrder).imsRegistrationTerminationPullTimestampMillis); 1273 inOrder.verifyNoMoreInteractions(); 1274 } 1275 1276 /* Utilities */ 1277 createEmptyTestFile()1278 private void createEmptyTestFile() throws Exception { 1279 PersistAtoms atoms = new PersistAtoms(); 1280 FileOutputStream stream = new FileOutputStream(mTestFile); 1281 stream.write(PersistAtoms.toByteArray(atoms)); 1282 stream.close(); 1283 } 1284 createTestFile(long lastPullTimeMillis)1285 private void createTestFile(long lastPullTimeMillis) throws Exception { 1286 PersistAtoms atoms = new PersistAtoms(); 1287 atoms.buildFingerprint = Build.FINGERPRINT; 1288 atoms.voiceCallRatUsagePullTimestampMillis = lastPullTimeMillis; 1289 atoms.voiceCallRatUsage = mVoiceCallRatUsages; 1290 atoms.voiceCallSessionPullTimestampMillis = lastPullTimeMillis; 1291 atoms.voiceCallSession = mVoiceCallSessions; 1292 atoms.cellularServiceStatePullTimestampMillis = lastPullTimeMillis; 1293 atoms.cellularServiceState = mServiceStates; 1294 atoms.cellularDataServiceSwitchPullTimestampMillis = lastPullTimeMillis; 1295 atoms.cellularDataServiceSwitch = mServiceSwitches; 1296 atoms.imsRegistrationStatsPullTimestampMillis = lastPullTimeMillis; 1297 atoms.imsRegistrationStats = mImsRegistrationStats; 1298 atoms.imsRegistrationTerminationPullTimestampMillis = lastPullTimeMillis; 1299 atoms.imsRegistrationTermination = mImsRegistrationTerminations; 1300 FileOutputStream stream = new FileOutputStream(mTestFile); 1301 stream.write(PersistAtoms.toByteArray(atoms)); 1302 stream.close(); 1303 } 1304 getAtomsWritten(@ullable InOrder inOrder)1305 private PersistAtoms getAtomsWritten(@Nullable InOrder inOrder) throws Exception { 1306 if (inOrder == null) { 1307 inOrder = inOrder(mTestFileOutputStream); 1308 } 1309 ArgumentCaptor bytesCaptor = ArgumentCaptor.forClass(Object.class); 1310 inOrder.verify(mTestFileOutputStream, times(1)).write((byte[]) bytesCaptor.capture()); 1311 PersistAtoms savedAtoms = PersistAtoms.parseFrom((byte[]) bytesCaptor.getValue()); 1312 inOrder.verify(mTestFileOutputStream, times(1)).close(); 1313 return savedAtoms; 1314 } 1315 addRepeatedCalls( PersistAtomsStorage storage, VoiceCallSession call, int count)1316 private static void addRepeatedCalls( 1317 PersistAtomsStorage storage, VoiceCallSession call, int count) { 1318 for (int i = 0; i < count; i++) { 1319 storage.addVoiceCallSession(call); 1320 } 1321 } 1322 multiplyVoiceCallRatUsage( VoiceCallRatUsage[] usages, int times)1323 private static VoiceCallRatUsage[] multiplyVoiceCallRatUsage( 1324 VoiceCallRatUsage[] usages, int times) { 1325 VoiceCallRatUsage[] multipliedUsages = new VoiceCallRatUsage[usages.length]; 1326 for (int i = 0; i < usages.length; i++) { 1327 multipliedUsages[i] = new VoiceCallRatUsage(); 1328 multipliedUsages[i].carrierId = usages[i].carrierId; 1329 multipliedUsages[i].rat = usages[i].rat; 1330 multipliedUsages[i].callCount = usages[i].callCount * 2; 1331 multipliedUsages[i].totalDurationMillis = usages[i].totalDurationMillis * 2; 1332 } 1333 return multipliedUsages; 1334 } 1335 copyOf(CellularServiceState source)1336 private static CellularServiceState copyOf(CellularServiceState source) throws Exception { 1337 return CellularServiceState.parseFrom(MessageNano.toByteArray(source)); 1338 } 1339 copyOf(CellularDataServiceSwitch source)1340 private static CellularDataServiceSwitch copyOf(CellularDataServiceSwitch source) 1341 throws Exception { 1342 return CellularDataServiceSwitch.parseFrom(MessageNano.toByteArray(source)); 1343 } 1344 copyOf(ImsRegistrationStats source)1345 private static ImsRegistrationStats copyOf(ImsRegistrationStats source) throws Exception { 1346 return ImsRegistrationStats.parseFrom(MessageNano.toByteArray(source)); 1347 } 1348 copyOf(ImsRegistrationTermination source)1349 private static ImsRegistrationTermination copyOf(ImsRegistrationTermination source) 1350 throws Exception { 1351 return ImsRegistrationTermination.parseFrom(MessageNano.toByteArray(source)); 1352 } 1353 assertAllPullTimestampEquals(long timestamp)1354 private void assertAllPullTimestampEquals(long timestamp) { 1355 assertEquals( 1356 timestamp, 1357 mPersistAtomsStorage.getAtomsProto().voiceCallRatUsagePullTimestampMillis); 1358 assertEquals( 1359 timestamp, 1360 mPersistAtomsStorage.getAtomsProto().voiceCallSessionPullTimestampMillis); 1361 assertEquals( 1362 timestamp, 1363 mPersistAtomsStorage.getAtomsProto().cellularServiceStatePullTimestampMillis); 1364 assertEquals( 1365 timestamp, 1366 mPersistAtomsStorage.getAtomsProto().cellularDataServiceSwitchPullTimestampMillis); 1367 } 1368 assertStorageIsEmptyForAllAtoms()1369 private void assertStorageIsEmptyForAllAtoms() { 1370 assertProtoArrayIsEmpty(mPersistAtomsStorage.getVoiceCallRatUsages(0L)); 1371 assertProtoArrayIsEmpty(mPersistAtomsStorage.getVoiceCallSessions(0L)); 1372 assertProtoArrayIsEmpty(mPersistAtomsStorage.getCellularServiceStates(0L)); 1373 assertProtoArrayIsEmpty(mPersistAtomsStorage.getCellularDataServiceSwitches(0L)); 1374 } 1375 assertProtoArrayIsEmpty(T[] array)1376 private static <T extends MessageNano> void assertProtoArrayIsEmpty(T[] array) { 1377 assertNotNull(array); 1378 assertEquals(0, array.length); 1379 } 1380 assertProtoArrayEquals(MessageNano[] expected, MessageNano[] actual)1381 private static void assertProtoArrayEquals(MessageNano[] expected, MessageNano[] actual) { 1382 assertNotNull(expected); 1383 assertNotNull(actual); 1384 String message = 1385 "Expected:\n" + Arrays.toString(expected) + "\nGot:\n" + Arrays.toString(actual); 1386 assertEquals(message, expected.length, actual.length); 1387 for (int i = 0; i < expected.length; i++) { 1388 assertTrue(message, MessageNano.messageNanoEquals(expected[i], actual[i])); 1389 } 1390 } 1391 assertProtoArrayEqualsIgnoringOrder( MessageNano[] expected, MessageNano[] actual)1392 private static void assertProtoArrayEqualsIgnoringOrder( 1393 MessageNano[] expected, MessageNano[] actual) { 1394 assertNotNull(expected); 1395 assertNotNull(actual); 1396 expected = expected.clone(); 1397 actual = actual.clone(); 1398 Arrays.sort(expected, sProtoComparator); 1399 Arrays.sort(actual, sProtoComparator); 1400 assertProtoArrayEquals(expected, actual); 1401 } 1402 assertHasCall( VoiceCallSession[] calls, @Nullable VoiceCallSession expectedCall, int expectedCount)1403 private static void assertHasCall( 1404 VoiceCallSession[] calls, @Nullable VoiceCallSession expectedCall, int expectedCount) { 1405 assertNotNull(calls); 1406 int actualCount = 0; 1407 for (VoiceCallSession call : calls) { 1408 if (call != null && expectedCall != null) { 1409 if (MessageNano.messageNanoEquals(call, expectedCall)) { 1410 actualCount++; 1411 } 1412 } 1413 } 1414 assertEquals(expectedCount, actualCount); 1415 } 1416 verifyCurrentStateSavedToFileOnce()1417 private void verifyCurrentStateSavedToFileOnce() throws Exception { 1418 InOrder inOrder = inOrder(mTestFileOutputStream); 1419 inOrder.verify(mTestFileOutputStream, times(1)) 1420 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto()))); 1421 inOrder.verify(mTestFileOutputStream, times(1)).close(); 1422 inOrder.verifyNoMoreInteractions(); 1423 } 1424 } 1425