• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.telephony.TelephonyManager.NETWORK_TYPE_BITMASK_GPRS;
20 import static android.telephony.TelephonyManager.NETWORK_TYPE_BITMASK_GSM;
21 import static android.text.format.DateUtils.DAY_IN_MILLIS;
22 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
23 
24 import static com.android.internal.telephony.TelephonyStatsLog.GBA_EVENT__FAILED_REASON__FEATURE_NOT_READY;
25 import static com.android.internal.telephony.TelephonyStatsLog.GBA_EVENT__FAILED_REASON__UNKNOWN;
26 import static com.android.internal.telephony.TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__ERROR;
27 import static com.android.internal.telephony.TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__PROVISIONING_XML;
28 import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS__EVENT__CLIENT_PARAMS_SENT;
29 import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS__EVENT__TRIGGER_RCS_RECONFIGURATION;
30 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS;
31 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS;
32 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MO;
33 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MT;
34 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__SETUP_DURATION__CALL_SETUP_DURATION_EXTREMELY_FAST;
35 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__SETUP_DURATION__CALL_SETUP_DURATION_VERY_FAST;
36 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__SETUP_DURATION__CALL_SETUP_DURATION_VERY_SLOW;
37 
38 import static org.junit.Assert.assertArrayEquals;
39 import static org.junit.Assert.assertEquals;
40 import static org.junit.Assert.assertNotNull;
41 import static org.junit.Assert.assertNull;
42 import static org.junit.Assert.assertTrue;
43 import static org.mockito.Mockito.anyInt;
44 import static org.mockito.Mockito.anyString;
45 import static org.mockito.Mockito.doReturn;
46 import static org.mockito.Mockito.eq;
47 import static org.mockito.Mockito.inOrder;
48 import static org.mockito.Mockito.mock;
49 import static org.mockito.Mockito.times;
50 
51 import android.annotation.Nullable;
52 import android.content.Context;
53 import android.os.Build;
54 import android.telephony.DisconnectCause;
55 import android.telephony.ServiceState;
56 import android.telephony.TelephonyManager;
57 import android.telephony.TelephonyProtoEnums;
58 import android.telephony.ims.ImsReasonInfo;
59 import android.telephony.ims.SipDelegateManager;
60 import android.test.suitebuilder.annotation.SmallTest;
61 
62 import com.android.internal.telephony.TelephonyStatsLog;
63 import com.android.internal.telephony.TelephonyTest;
64 import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch;
65 import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState;
66 import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession;
67 import com.android.internal.telephony.nano.PersistAtomsProto.GbaEvent;
68 import com.android.internal.telephony.nano.PersistAtomsProto.ImsDedicatedBearerEvent;
69 import com.android.internal.telephony.nano.PersistAtomsProto.ImsDedicatedBearerListenerEvent;
70 import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationFeatureTagStats;
71 import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationServiceDescStats;
72 import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationStats;
73 import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationTermination;
74 import com.android.internal.telephony.nano.PersistAtomsProto.PersistAtoms;
75 import com.android.internal.telephony.nano.PersistAtomsProto.PresenceNotifyEvent;
76 import com.android.internal.telephony.nano.PersistAtomsProto.RcsAcsProvisioningStats;
77 import com.android.internal.telephony.nano.PersistAtomsProto.RcsClientProvisioningStats;
78 import com.android.internal.telephony.nano.PersistAtomsProto.SipDelegateStats;
79 import com.android.internal.telephony.nano.PersistAtomsProto.SipMessageResponse;
80 import com.android.internal.telephony.nano.PersistAtomsProto.SipTransportFeatureTagStats;
81 import com.android.internal.telephony.nano.PersistAtomsProto.SipTransportSession;
82 import com.android.internal.telephony.nano.PersistAtomsProto.UceEventStats;
83 import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallRatUsage;
84 import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallSession;
85 import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession.Event.AudioCodec;
86 import com.android.internal.telephony.protobuf.nano.MessageNano;
87 
88 import org.junit.After;
89 import org.junit.Before;
90 import org.junit.Rule;
91 import org.junit.Test;
92 import org.junit.rules.TemporaryFolder;
93 import org.mockito.ArgumentCaptor;
94 import org.mockito.InOrder;
95 
96 import java.io.File;
97 import java.io.FileOutputStream;
98 import java.nio.charset.StandardCharsets;
99 import java.util.Arrays;
100 import java.util.Comparator;
101 import java.util.LinkedList;
102 import java.util.Queue;
103 
104 public class PersistAtomsStorageTest extends TelephonyTest {
105     private static final String TEST_FILE = "PersistAtomsStorageTest.pb";
106     private static final int MAX_NUM_CALL_SESSIONS = 50;
107     private static final long START_TIME_MILLIS = 2000L;
108     private static final int CARRIER1_ID = 1;
109     private static final int CARRIER2_ID = 1187;
110     private static final int CARRIER3_ID = 1435;
111     private static final int SLOT_ID1 = 1;
112     private static final int SLOT_ID2 = 2;
113     private static final int REGISTRATION1_TECH = 1;
114     private static final int REGISTRATION2_TECH = 2;
115 
116     // Mocked classes
117     private FileOutputStream mTestFileOutputStream;
118 
119     @Rule public TemporaryFolder mFolder = new TemporaryFolder();
120 
121     private File mTestFile;
122 
123     // call with SRVCC
124     private VoiceCallSession mCall1Proto;
125 
126     // call held after another incoming call, ended before the other call
127     private VoiceCallSession mCall2Proto;
128     private VoiceCallSession mCall3Proto;
129 
130     // failed call
131     private VoiceCallSession mCall4Proto;
132 
133     private VoiceCallRatUsage mCarrier1LteUsageProto;
134     private VoiceCallRatUsage mCarrier1UmtsUsageProto;
135     private VoiceCallRatUsage mCarrier2LteUsageProto;
136     private VoiceCallRatUsage mCarrier3LteUsageProto;
137     private VoiceCallRatUsage mCarrier3GsmUsageProto;
138 
139     private VoiceCallSession[] mVoiceCallSessions;
140     private VoiceCallRatUsage[] mVoiceCallRatUsages;
141 
142     // data service state switch for slot 0 and 1
143     private CellularDataServiceSwitch mServiceSwitch1Proto;
144     private CellularDataServiceSwitch mServiceSwitch2Proto;
145 
146     // service states for slot 0 and 1
147     private CellularServiceState mServiceState1Proto;
148     private CellularServiceState mServiceState2Proto;
149     private CellularServiceState mServiceState3Proto;
150     private CellularServiceState mServiceState4Proto;
151     private CellularServiceState mServiceState5Proto;
152 
153     private CellularDataServiceSwitch[] mServiceSwitches;
154     private CellularServiceState[] mServiceStates;
155 
156     // IMS registrations for slot 0 and 1
157     private ImsRegistrationStats mImsRegistrationStatsLte0;
158     private ImsRegistrationStats mImsRegistrationStatsWifi0;
159     private ImsRegistrationStats mImsRegistrationStatsLte1;
160 
161     // IMS registration terminations for slot 0 and 1
162     private ImsRegistrationTermination mImsRegistrationTerminationLte;
163     private ImsRegistrationTermination mImsRegistrationTerminationWifi;
164 
165     private ImsRegistrationStats[] mImsRegistrationStats;
166     private ImsRegistrationTermination[] mImsRegistrationTerminations;
167 
168     // Data call sessions
169     private DataCallSession mDataCallSession0;
170     private DataCallSession mDataCallSession1;
171 
172     // RCS registration feature tags for slot 0 and 1
173     private ImsRegistrationFeatureTagStats mImsRegistrationFeatureTagStats1Proto;
174     private ImsRegistrationFeatureTagStats mImsRegistrationFeatureTagStats2Proto;
175     private ImsRegistrationFeatureTagStats[] mImsRegistrationFeatureTagStatses;
176 
177     // RCS provisioning client stats for slot 0 and 1
178     private RcsClientProvisioningStats mRcsClientProvisioningStats1Proto;
179     private RcsClientProvisioningStats mRcsClientProvisioningStats2Proto;
180     private RcsClientProvisioningStats[] mRcsClientProvisioningStatses;
181 
182     // RCS provisioning ACS stats for slot 0 and 1
183     private RcsAcsProvisioningStats mRcsAcsProvisioningStats1Proto;
184     private RcsAcsProvisioningStats mRcsAcsProvisioningStats2Proto;
185     private RcsAcsProvisioningStats[] mRcsAcsProvisioningStatses;
186 
187     private ImsRegistrationServiceDescStats mImsRegistrationServiceIm;
188     private ImsRegistrationServiceDescStats mImsRegistrationServiceFt;
189     private ImsRegistrationServiceDescStats[] mImsRegistrationServiceDescStats;
190 
191     // IMS dedicated bearer listener event stats for slot 0 and 1
192     private ImsDedicatedBearerListenerEvent mImsDedicatedBearerListenerEvent1;
193     private ImsDedicatedBearerListenerEvent mImsDedicatedBearerListenerEvent2;
194     private ImsDedicatedBearerListenerEvent[] mImsDedicatedBearerListenerEvents;
195 
196     // IMS dedicated bearer event stats for slot 0 and 1
197     private ImsDedicatedBearerEvent mImsDedicatedBearerEvent1;
198     private ImsDedicatedBearerEvent mImsDedicatedBearerEvent2;
199     private ImsDedicatedBearerEvent[] mImsDedicatedBearerEvents;
200 
201     private UceEventStats mUceEventStats1;
202     private UceEventStats mUceEventStats2;
203     private UceEventStats[] mUceEventStatses;
204 
205     private PresenceNotifyEvent mPresenceNotifyEvent1;
206     private PresenceNotifyEvent mPresenceNotifyEvent2;
207     private PresenceNotifyEvent[] mPresenceNotifyEvents;
208 
209     private SipTransportFeatureTagStats mSipTransportFeatureTagStats1;
210     private SipTransportFeatureTagStats mSipTransportFeatureTagStats2;
211     private SipTransportFeatureTagStats[] mSipTransportFeatureTagStatsArray;
212 
213     private SipDelegateStats mSipDelegateStats1;
214     private SipDelegateStats mSipDelegateStats2;
215     private SipDelegateStats mSipDelegateStats3;
216     private SipDelegateStats[] mSipDelegateStatsArray;
217 
218     private GbaEvent mGbaEvent1;
219     private GbaEvent mGbaEvent2;
220     private GbaEvent[] mGbaEvent;
221 
222     private SipMessageResponse mSipMessageResponse1;
223     private SipMessageResponse mSipMessageResponse2;
224     private SipMessageResponse[] mSipMessageResponse;
225 
226     private SipTransportSession mSipTransportSession1;
227     private SipTransportSession mSipTransportSession2;
228     private SipTransportSession[] mSipTransportSession;
229 
makeTestData()230     private void makeTestData() {
231         // MO call with SRVCC (LTE to UMTS)
232         mCall1Proto = new VoiceCallSession();
233         mCall1Proto.bearerAtStart = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS;
234         mCall1Proto.bearerAtEnd = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS;
235         mCall1Proto.direction = VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MO;
236         mCall1Proto.setupDuration =
237                 VOICE_CALL_SESSION__SETUP_DURATION__CALL_SETUP_DURATION_VERY_FAST;
238         mCall1Proto.setupFailed = false;
239         mCall1Proto.disconnectReasonCode = DisconnectCause.LOCAL;
240         mCall1Proto.disconnectExtraCode = 0;
241         mCall1Proto.disconnectExtraMessage = "";
242         mCall1Proto.ratAtStart = TelephonyManager.NETWORK_TYPE_LTE;
243         mCall1Proto.ratAtEnd = TelephonyManager.NETWORK_TYPE_UMTS;
244         mCall1Proto.ratSwitchCount = 1L;
245         mCall1Proto.codecBitmask =
246                 (1 << AudioCodec.AUDIO_CODEC_EVS_SWB) | (1 << AudioCodec.AUDIO_CODEC_AMR);
247         mCall1Proto.concurrentCallCountAtStart = 0;
248         mCall1Proto.concurrentCallCountAtEnd = 0;
249         mCall1Proto.simSlotIndex = 0;
250         mCall1Proto.isMultiSim = false;
251         mCall1Proto.isEsim = false;
252         mCall1Proto.carrierId = CARRIER1_ID;
253         mCall1Proto.srvccCompleted = true;
254         mCall1Proto.srvccFailureCount = 0L;
255         mCall1Proto.srvccCancellationCount = 0L;
256         mCall1Proto.rttEnabled = false;
257         mCall1Proto.isEmergency = false;
258         mCall1Proto.isRoaming = false;
259 
260         // VoLTE MT call on DSDS/eSIM, hanged up by remote
261         // concurrent with mCall3Proto, started first and ended first
262         mCall2Proto = new VoiceCallSession();
263         mCall2Proto.bearerAtStart = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS;
264         mCall2Proto.bearerAtEnd = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS;
265         mCall2Proto.direction = VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MT;
266         mCall2Proto.setupDuration =
267                 VOICE_CALL_SESSION__SETUP_DURATION__CALL_SETUP_DURATION_VERY_FAST;
268         mCall2Proto.setupFailed = false;
269         mCall2Proto.disconnectReasonCode = ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE;
270         mCall2Proto.disconnectExtraCode = 0;
271         mCall2Proto.disconnectExtraMessage = "normal call clearing";
272         mCall2Proto.ratAtStart = TelephonyManager.NETWORK_TYPE_LTE;
273         mCall2Proto.ratAtEnd = TelephonyManager.NETWORK_TYPE_LTE;
274         mCall2Proto.ratSwitchCount = 0L;
275         mCall2Proto.codecBitmask = (1 << AudioCodec.AUDIO_CODEC_EVS_SWB);
276         mCall2Proto.concurrentCallCountAtStart = 0;
277         mCall2Proto.concurrentCallCountAtEnd = 1;
278         mCall2Proto.simSlotIndex = 1;
279         mCall2Proto.isMultiSim = true;
280         mCall2Proto.isEsim = true;
281         mCall2Proto.carrierId = CARRIER2_ID;
282         mCall2Proto.srvccCompleted = false;
283         mCall2Proto.srvccFailureCount = 0L;
284         mCall2Proto.srvccCancellationCount = 0L;
285         mCall2Proto.rttEnabled = false;
286         mCall2Proto.isEmergency = false;
287         mCall2Proto.isRoaming = false;
288 
289         // VoLTE MT call on DSDS/eSIM, hanged up by local, with RTT
290         // concurrent with mCall2Proto, started last and ended last
291         mCall3Proto = new VoiceCallSession();
292         mCall3Proto.bearerAtStart = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS;
293         mCall3Proto.bearerAtEnd = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS;
294         mCall3Proto.direction = VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MT;
295         mCall3Proto.setupDuration =
296                 VOICE_CALL_SESSION__SETUP_DURATION__CALL_SETUP_DURATION_EXTREMELY_FAST;
297         mCall3Proto.setupFailed = false;
298         mCall3Proto.disconnectReasonCode = ImsReasonInfo.CODE_USER_TERMINATED;
299         mCall3Proto.disconnectExtraCode = 0;
300         mCall3Proto.disconnectExtraMessage = "normal call clearing";
301         mCall3Proto.ratAtStart = TelephonyManager.NETWORK_TYPE_LTE;
302         mCall3Proto.ratAtEnd = TelephonyManager.NETWORK_TYPE_LTE;
303         mCall3Proto.ratSwitchCount = 0L;
304         mCall3Proto.codecBitmask = (1 << AudioCodec.AUDIO_CODEC_EVS_SWB);
305         mCall3Proto.concurrentCallCountAtStart = 1;
306         mCall3Proto.concurrentCallCountAtEnd = 0;
307         mCall3Proto.simSlotIndex = 1;
308         mCall3Proto.isMultiSim = true;
309         mCall3Proto.isEsim = true;
310         mCall3Proto.carrierId = CARRIER2_ID;
311         mCall3Proto.srvccCompleted = false;
312         mCall3Proto.srvccFailureCount = 0L;
313         mCall3Proto.srvccCancellationCount = 0L;
314         mCall3Proto.rttEnabled = true;
315         mCall3Proto.isEmergency = false;
316         mCall3Proto.isRoaming = false;
317 
318         // CS MO emergency call while camped on LTE
319         mCall4Proto = new VoiceCallSession();
320         mCall4Proto.bearerAtStart = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS;
321         mCall4Proto.bearerAtEnd = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS;
322         mCall4Proto.direction = VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MO;
323         mCall4Proto.setupDuration =
324                 VOICE_CALL_SESSION__SETUP_DURATION__CALL_SETUP_DURATION_VERY_SLOW;
325         mCall4Proto.setupFailed = true;
326         mCall4Proto.disconnectReasonCode = DisconnectCause.NORMAL;
327         mCall4Proto.disconnectExtraCode = 0;
328         mCall4Proto.disconnectExtraMessage = "";
329         mCall4Proto.ratAtStart = TelephonyManager.NETWORK_TYPE_LTE;
330         mCall4Proto.ratAtEnd = TelephonyManager.NETWORK_TYPE_GSM;
331         mCall4Proto.ratSwitchCount = 1L;
332         mCall4Proto.codecBitmask = (1 << AudioCodec.AUDIO_CODEC_AMR);
333         mCall4Proto.concurrentCallCountAtStart = 0;
334         mCall4Proto.concurrentCallCountAtEnd = 0;
335         mCall4Proto.simSlotIndex = 0;
336         mCall4Proto.isMultiSim = true;
337         mCall4Proto.isEsim = false;
338         mCall4Proto.carrierId = CARRIER3_ID;
339         mCall4Proto.srvccCompleted = false;
340         mCall4Proto.srvccFailureCount = 0L;
341         mCall4Proto.srvccCancellationCount = 0L;
342         mCall4Proto.rttEnabled = false;
343         mCall4Proto.isEmergency = true;
344         mCall4Proto.isRoaming = true;
345 
346         mCarrier1LteUsageProto = new VoiceCallRatUsage();
347         mCarrier1LteUsageProto.carrierId = CARRIER1_ID;
348         mCarrier1LteUsageProto.rat = TelephonyManager.NETWORK_TYPE_LTE;
349         mCarrier1LteUsageProto.callCount = 1L;
350         mCarrier1LteUsageProto.totalDurationMillis = 8000L;
351 
352         mCarrier1UmtsUsageProto = new VoiceCallRatUsage();
353         mCarrier1UmtsUsageProto.carrierId = CARRIER1_ID;
354         mCarrier1UmtsUsageProto.rat = TelephonyManager.NETWORK_TYPE_UMTS;
355         mCarrier1UmtsUsageProto.callCount = 1L;
356         mCarrier1UmtsUsageProto.totalDurationMillis = 6000L;
357 
358         mCarrier2LteUsageProto = new VoiceCallRatUsage();
359         mCarrier2LteUsageProto.carrierId = CARRIER2_ID;
360         mCarrier2LteUsageProto.rat = TelephonyManager.NETWORK_TYPE_LTE;
361         mCarrier2LteUsageProto.callCount = 2L;
362         mCarrier2LteUsageProto.totalDurationMillis = 20000L;
363 
364         mCarrier3LteUsageProto = new VoiceCallRatUsage();
365         mCarrier3LteUsageProto.carrierId = CARRIER3_ID;
366         mCarrier3LteUsageProto.rat = TelephonyManager.NETWORK_TYPE_LTE;
367         mCarrier3LteUsageProto.callCount = 1L;
368         mCarrier3LteUsageProto.totalDurationMillis = 1000L;
369 
370         mCarrier3GsmUsageProto = new VoiceCallRatUsage();
371         mCarrier3GsmUsageProto.carrierId = CARRIER3_ID;
372         mCarrier3GsmUsageProto.rat = TelephonyManager.NETWORK_TYPE_GSM;
373         mCarrier3GsmUsageProto.callCount = 1L;
374         mCarrier3GsmUsageProto.totalDurationMillis = 100000L;
375 
376         mVoiceCallRatUsages =
377                 new VoiceCallRatUsage[] {
378                     mCarrier1UmtsUsageProto,
379                     mCarrier1LteUsageProto,
380                     mCarrier2LteUsageProto,
381                     mCarrier3LteUsageProto,
382                     mCarrier3GsmUsageProto
383                 };
384         mVoiceCallSessions =
385                 new VoiceCallSession[] {mCall1Proto, mCall2Proto, mCall3Proto, mCall4Proto};
386 
387         // OOS to LTE on slot 0
388         mServiceSwitch1Proto = new CellularDataServiceSwitch();
389         mServiceSwitch1Proto.ratFrom = TelephonyManager.NETWORK_TYPE_UNKNOWN;
390         mServiceSwitch1Proto.ratTo = TelephonyManager.NETWORK_TYPE_LTE;
391         mServiceSwitch1Proto.simSlotIndex = 0;
392         mServiceSwitch1Proto.isMultiSim = true;
393         mServiceSwitch1Proto.carrierId = CARRIER1_ID;
394         mServiceSwitch1Proto.switchCount = 1;
395 
396         // LTE to UMTS on slot 1
397         mServiceSwitch2Proto = new CellularDataServiceSwitch();
398         mServiceSwitch2Proto.ratFrom = TelephonyManager.NETWORK_TYPE_LTE;
399         mServiceSwitch2Proto.ratTo = TelephonyManager.NETWORK_TYPE_UMTS;
400         mServiceSwitch2Proto.simSlotIndex = 0;
401         mServiceSwitch2Proto.isMultiSim = true;
402         mServiceSwitch2Proto.carrierId = CARRIER2_ID;
403         mServiceSwitch2Proto.switchCount = 2;
404 
405         // OOS on slot 0
406         mServiceState1Proto = new CellularServiceState();
407         mServiceState1Proto.voiceRat = TelephonyManager.NETWORK_TYPE_UNKNOWN;
408         mServiceState1Proto.dataRat = TelephonyManager.NETWORK_TYPE_UNKNOWN;
409         mServiceState1Proto.voiceRoamingType = ServiceState.ROAMING_TYPE_NOT_ROAMING;
410         mServiceState1Proto.dataRoamingType = ServiceState.ROAMING_TYPE_NOT_ROAMING;
411         mServiceState1Proto.isEndc = false;
412         mServiceState1Proto.simSlotIndex = 0;
413         mServiceState1Proto.isMultiSim = true;
414         mServiceState1Proto.carrierId = CARRIER1_ID;
415         mServiceState1Proto.totalTimeMillis = 5000L;
416         mServiceState1Proto.isEmergencyOnly = false;
417 
418         // LTE with ENDC on slot 0
419         mServiceState2Proto = new CellularServiceState();
420         mServiceState2Proto.voiceRat = TelephonyManager.NETWORK_TYPE_LTE;
421         mServiceState2Proto.dataRat = TelephonyManager.NETWORK_TYPE_LTE;
422         mServiceState2Proto.voiceRoamingType = ServiceState.ROAMING_TYPE_NOT_ROAMING;
423         mServiceState2Proto.dataRoamingType = ServiceState.ROAMING_TYPE_NOT_ROAMING;
424         mServiceState2Proto.isEndc = true;
425         mServiceState2Proto.simSlotIndex = 0;
426         mServiceState2Proto.isMultiSim = true;
427         mServiceState2Proto.carrierId = CARRIER1_ID;
428         mServiceState2Proto.totalTimeMillis = 15000L;
429         mServiceState2Proto.isEmergencyOnly = false;
430 
431         // LTE with WFC and roaming on slot 1
432         mServiceState3Proto = new CellularServiceState();
433         mServiceState3Proto.voiceRat = TelephonyManager.NETWORK_TYPE_IWLAN;
434         mServiceState3Proto.dataRat = TelephonyManager.NETWORK_TYPE_LTE;
435         mServiceState3Proto.voiceRoamingType = ServiceState.ROAMING_TYPE_INTERNATIONAL;
436         mServiceState3Proto.dataRoamingType = ServiceState.ROAMING_TYPE_INTERNATIONAL;
437         mServiceState3Proto.isEndc = false;
438         mServiceState3Proto.simSlotIndex = 1;
439         mServiceState3Proto.isMultiSim = true;
440         mServiceState3Proto.carrierId = CARRIER2_ID;
441         mServiceState3Proto.totalTimeMillis = 10000L;
442         mServiceState3Proto.isEmergencyOnly = false;
443 
444         // UMTS with roaming on slot 1
445         mServiceState4Proto = new CellularServiceState();
446         mServiceState4Proto.voiceRat = TelephonyManager.NETWORK_TYPE_UMTS;
447         mServiceState4Proto.dataRat = TelephonyManager.NETWORK_TYPE_UMTS;
448         mServiceState4Proto.voiceRoamingType = ServiceState.ROAMING_TYPE_INTERNATIONAL;
449         mServiceState4Proto.dataRoamingType = ServiceState.ROAMING_TYPE_INTERNATIONAL;
450         mServiceState4Proto.isEndc = false;
451         mServiceState4Proto.simSlotIndex = 1;
452         mServiceState4Proto.isMultiSim = true;
453         mServiceState4Proto.carrierId = CARRIER2_ID;
454         mServiceState4Proto.totalTimeMillis = 10000L;
455         mServiceState4Proto.isEmergencyOnly = false;
456 
457         // Limited service on slot 0
458         mServiceState5Proto = new CellularServiceState();
459         mServiceState5Proto.voiceRat = TelephonyManager.NETWORK_TYPE_UNKNOWN;
460         mServiceState5Proto.dataRat = TelephonyManager.NETWORK_TYPE_UNKNOWN;
461         mServiceState5Proto.voiceRoamingType = ServiceState.ROAMING_TYPE_NOT_ROAMING;
462         mServiceState5Proto.dataRoamingType = ServiceState.ROAMING_TYPE_NOT_ROAMING;
463         mServiceState5Proto.isEndc = false;
464         mServiceState5Proto.simSlotIndex = 0;
465         mServiceState5Proto.isMultiSim = true;
466         mServiceState5Proto.carrierId = CARRIER1_ID;
467         mServiceState5Proto.totalTimeMillis = 15000L;
468         mServiceState5Proto.isEmergencyOnly = true;
469 
470         mServiceSwitches =
471                 new CellularDataServiceSwitch[] {mServiceSwitch1Proto, mServiceSwitch2Proto};
472         mServiceStates =
473                 new CellularServiceState[] {
474                     mServiceState1Proto,
475                     mServiceState2Proto,
476                     mServiceState3Proto,
477                     mServiceState4Proto,
478                     mServiceState5Proto
479                 };
480 
481         // IMS over LTE on slot 0, registered for 5 seconds
482         mImsRegistrationStatsLte0 = new ImsRegistrationStats();
483         mImsRegistrationStatsLte0.carrierId = CARRIER1_ID;
484         mImsRegistrationStatsLte0.simSlotIndex = 0;
485         mImsRegistrationStatsLte0.rat = TelephonyManager.NETWORK_TYPE_LTE;
486         mImsRegistrationStatsLte0.registeredMillis = 5000L;
487         mImsRegistrationStatsLte0.voiceCapableMillis = 5000L;
488         mImsRegistrationStatsLte0.voiceAvailableMillis = 5000L;
489         mImsRegistrationStatsLte0.smsCapableMillis = 5000L;
490         mImsRegistrationStatsLte0.smsAvailableMillis = 5000L;
491         mImsRegistrationStatsLte0.videoCapableMillis = 5000L;
492         mImsRegistrationStatsLte0.videoAvailableMillis = 5000L;
493         mImsRegistrationStatsLte0.utCapableMillis = 5000L;
494         mImsRegistrationStatsLte0.utAvailableMillis = 5000L;
495 
496         // IMS over WiFi on slot 0, registered for 10 seconds (voice only)
497         mImsRegistrationStatsWifi0 = new ImsRegistrationStats();
498         mImsRegistrationStatsWifi0.carrierId = CARRIER2_ID;
499         mImsRegistrationStatsWifi0.simSlotIndex = 0;
500         mImsRegistrationStatsWifi0.rat = TelephonyManager.NETWORK_TYPE_IWLAN;
501         mImsRegistrationStatsWifi0.registeredMillis = 10000L;
502         mImsRegistrationStatsWifi0.voiceCapableMillis = 10000L;
503         mImsRegistrationStatsWifi0.voiceAvailableMillis = 10000L;
504 
505         // IMS over LTE on slot 1, registered for 20 seconds
506         mImsRegistrationStatsLte1 = new ImsRegistrationStats();
507         mImsRegistrationStatsLte1.carrierId = CARRIER1_ID;
508         mImsRegistrationStatsLte1.simSlotIndex = 0;
509         mImsRegistrationStatsLte1.rat = TelephonyManager.NETWORK_TYPE_LTE;
510         mImsRegistrationStatsLte1.registeredMillis = 20000L;
511         mImsRegistrationStatsLte1.voiceCapableMillis = 20000L;
512         mImsRegistrationStatsLte1.voiceAvailableMillis = 20000L;
513         mImsRegistrationStatsLte1.smsCapableMillis = 20000L;
514         mImsRegistrationStatsLte1.smsAvailableMillis = 20000L;
515         mImsRegistrationStatsLte1.videoCapableMillis = 20000L;
516         mImsRegistrationStatsLte1.videoAvailableMillis = 20000L;
517         mImsRegistrationStatsLte1.utCapableMillis = 20000L;
518         mImsRegistrationStatsLte1.utAvailableMillis = 20000L;
519 
520         // IMS terminations on LTE
521         mImsRegistrationTerminationLte = new ImsRegistrationTermination();
522         mImsRegistrationTerminationLte.carrierId = CARRIER1_ID;
523         mImsRegistrationTerminationLte.isMultiSim = true;
524         mImsRegistrationTerminationLte.ratAtEnd = TelephonyManager.NETWORK_TYPE_LTE;
525         mImsRegistrationTerminationLte.setupFailed = false;
526         mImsRegistrationTerminationLte.reasonCode = ImsReasonInfo.CODE_REGISTRATION_ERROR;
527         mImsRegistrationTerminationLte.extraCode = 999;
528         mImsRegistrationTerminationLte.extraMessage = "Request Timeout";
529         mImsRegistrationTerminationLte.count = 2;
530 
531         // IMS terminations on WiFi
532         mImsRegistrationTerminationWifi = new ImsRegistrationTermination();
533         mImsRegistrationTerminationWifi.carrierId = CARRIER2_ID;
534         mImsRegistrationTerminationWifi.isMultiSim = true;
535         mImsRegistrationTerminationWifi.ratAtEnd = TelephonyManager.NETWORK_TYPE_IWLAN;
536         mImsRegistrationTerminationWifi.setupFailed = false;
537         mImsRegistrationTerminationWifi.reasonCode = ImsReasonInfo.CODE_REGISTRATION_ERROR;
538         mImsRegistrationTerminationWifi.extraCode = 0;
539         mImsRegistrationTerminationWifi.extraMessage = "";
540         mImsRegistrationTerminationWifi.count = 1;
541 
542         mImsRegistrationStats =
543                 new ImsRegistrationStats[] {
544                     mImsRegistrationStatsLte0, mImsRegistrationStatsWifi0, mImsRegistrationStatsLte1
545                 };
546         mImsRegistrationTerminations =
547                 new ImsRegistrationTermination[] {
548                     mImsRegistrationTerminationLte, mImsRegistrationTerminationWifi
549                 };
550 
551         mDataCallSession0 = new DataCallSession();
552         mDataCallSession0.dimension = 111;
553         mDataCallSession0.carrierId = CARRIER1_ID;
554         mDataCallSession0.oosAtEnd = false;
555         mDataCallSession0.ratSwitchCount = 3L;
556         mDataCallSession0.setupFailed = false;
557         mDataCallSession0.durationMinutes = 20;
558         mDataCallSession0.ongoing = true;
559         mDataCallSession0.handoverFailureCauses = new int[]{3, 2, 1};
560         mDataCallSession0.handoverFailureRat = new int[]{5, 5, 6};
561 
562         mDataCallSession1 = new DataCallSession();
563         mDataCallSession1.dimension = 222;
564         mDataCallSession1.carrierId = CARRIER2_ID;
565         mDataCallSession1.oosAtEnd = true;
566         mDataCallSession1.ratSwitchCount = 1L;
567         mDataCallSession1.setupFailed = false;
568         mDataCallSession1.durationMinutes = 5;
569         mDataCallSession1.ongoing = false;
570 
571         // RCS registrtion feature tag slot 0
572         mImsRegistrationFeatureTagStats1Proto = new ImsRegistrationFeatureTagStats();
573         mImsRegistrationFeatureTagStats1Proto.carrierId = CARRIER1_ID;
574         mImsRegistrationFeatureTagStats1Proto.slotId = 0;
575         mImsRegistrationFeatureTagStats1Proto.featureTagName = 1;
576         mImsRegistrationFeatureTagStats1Proto.registrationTech = TelephonyManager.NETWORK_TYPE_LTE;
577         mImsRegistrationFeatureTagStats1Proto.registeredMillis = 3600L;
578 
579         // RCS registrtion feature tag slot 1
580         mImsRegistrationFeatureTagStats2Proto = new ImsRegistrationFeatureTagStats();
581         mImsRegistrationFeatureTagStats2Proto.carrierId = CARRIER2_ID;
582         mImsRegistrationFeatureTagStats2Proto.slotId = 1;
583         mImsRegistrationFeatureTagStats2Proto.featureTagName = 0;
584         mImsRegistrationFeatureTagStats2Proto.registrationTech = TelephonyManager.NETWORK_TYPE_LTE;
585         mImsRegistrationFeatureTagStats2Proto.registeredMillis = 3600L;
586 
587         mImsRegistrationFeatureTagStatses =
588                 new ImsRegistrationFeatureTagStats[] {
589                         mImsRegistrationFeatureTagStats1Proto,
590                         mImsRegistrationFeatureTagStats2Proto
591                 };
592 
593         // RCS client provisioning stats slot 0
594         mRcsClientProvisioningStats1Proto = new RcsClientProvisioningStats();
595         mRcsClientProvisioningStats1Proto.carrierId = CARRIER1_ID;
596         mRcsClientProvisioningStats1Proto.slotId = 0;
597         mRcsClientProvisioningStats1Proto.event =
598                 RCS_CLIENT_PROVISIONING_STATS__EVENT__CLIENT_PARAMS_SENT;
599         mRcsClientProvisioningStats1Proto.count = 1;
600 
601         // RCS client provisioning stats slot 1
602         mRcsClientProvisioningStats2Proto = new RcsClientProvisioningStats();
603         mRcsClientProvisioningStats2Proto.carrierId = CARRIER2_ID;
604         mRcsClientProvisioningStats2Proto.slotId = 1;
605         mRcsClientProvisioningStats2Proto.event =
606                 RCS_CLIENT_PROVISIONING_STATS__EVENT__TRIGGER_RCS_RECONFIGURATION;
607         mRcsClientProvisioningStats2Proto.count = 1;
608 
609         mRcsClientProvisioningStatses =
610                 new RcsClientProvisioningStats[] {
611                         mRcsClientProvisioningStats1Proto,
612                         mRcsClientProvisioningStats2Proto
613                 };
614 
615         // RCS ACS provisioning stats : error response
616         mRcsAcsProvisioningStats1Proto = new RcsAcsProvisioningStats();
617         mRcsAcsProvisioningStats1Proto.carrierId = CARRIER1_ID;
618         mRcsAcsProvisioningStats1Proto.slotId = 0;
619         mRcsAcsProvisioningStats1Proto.responseCode = 401;
620         mRcsAcsProvisioningStats1Proto.responseType =
621                 RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__ERROR;
622         mRcsAcsProvisioningStats1Proto.isSingleRegistrationEnabled = true;
623         mRcsAcsProvisioningStats1Proto.count = 1;
624         mRcsAcsProvisioningStats1Proto.stateTimerMillis = START_TIME_MILLIS;
625 
626         // RCS ACS provisioning stats : xml
627         mRcsAcsProvisioningStats2Proto = new RcsAcsProvisioningStats();
628         mRcsAcsProvisioningStats2Proto.carrierId = CARRIER1_ID;
629         mRcsAcsProvisioningStats2Proto.slotId = 0;
630         mRcsAcsProvisioningStats2Proto.responseCode = 200;
631         mRcsAcsProvisioningStats2Proto.responseType =
632                 RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__PROVISIONING_XML;
633         mRcsAcsProvisioningStats2Proto.isSingleRegistrationEnabled = true;
634         mRcsAcsProvisioningStats2Proto.count = 1;
635         mRcsAcsProvisioningStats2Proto.stateTimerMillis = START_TIME_MILLIS;
636 
637         mRcsAcsProvisioningStatses =
638                 new RcsAcsProvisioningStats[] {
639                         mRcsAcsProvisioningStats1Proto,
640                         mRcsAcsProvisioningStats2Proto
641                 };
642 
643         mImsRegistrationServiceIm = new ImsRegistrationServiceDescStats();
644         mImsRegistrationServiceIm.carrierId = CARRIER1_ID;
645         mImsRegistrationServiceIm.slotId = SLOT_ID1;
646         mImsRegistrationServiceIm.serviceIdName = 0;
647         mImsRegistrationServiceIm.serviceIdVersion = 1.0f;
648         mImsRegistrationServiceIm.registrationTech = REGISTRATION1_TECH;
649         mImsRegistrationServiceIm.publishedMillis = START_TIME_MILLIS;
650 
651         mImsRegistrationServiceFt = new ImsRegistrationServiceDescStats();
652         mImsRegistrationServiceFt.carrierId = CARRIER2_ID;
653         mImsRegistrationServiceFt.slotId = SLOT_ID2;
654         mImsRegistrationServiceFt.serviceIdName = 1;
655         mImsRegistrationServiceFt.serviceIdVersion = 2.0f;
656         mImsRegistrationServiceFt.registrationTech = REGISTRATION2_TECH;
657         mImsRegistrationServiceIm.publishedMillis = START_TIME_MILLIS;
658 
659         mImsRegistrationServiceDescStats =
660             new ImsRegistrationServiceDescStats[] {
661                 mImsRegistrationServiceIm, mImsRegistrationServiceFt
662             };
663 
664 
665         mImsDedicatedBearerListenerEvent1 = new ImsDedicatedBearerListenerEvent();
666         mImsDedicatedBearerListenerEvent1.carrierId = CARRIER1_ID;
667         mImsDedicatedBearerListenerEvent1.slotId = SLOT_ID1;
668         mImsDedicatedBearerListenerEvent1.ratAtEnd = TelephonyManager.NETWORK_TYPE_LTE;
669         mImsDedicatedBearerListenerEvent1.qci = 5;
670         mImsDedicatedBearerListenerEvent1.dedicatedBearerEstablished = true;
671         mImsDedicatedBearerListenerEvent1.eventCount = 1;
672 
673         mImsDedicatedBearerListenerEvent2 = new ImsDedicatedBearerListenerEvent();
674         mImsDedicatedBearerListenerEvent2.carrierId = CARRIER2_ID;
675         mImsDedicatedBearerListenerEvent2.slotId = SLOT_ID1;
676         mImsDedicatedBearerListenerEvent2.ratAtEnd = TelephonyManager.NETWORK_TYPE_NR;
677         mImsDedicatedBearerListenerEvent2.qci = 6;
678         mImsDedicatedBearerListenerEvent2.dedicatedBearerEstablished = true;
679         mImsDedicatedBearerListenerEvent2.eventCount = 1;
680 
681         mImsDedicatedBearerListenerEvents =
682                 new ImsDedicatedBearerListenerEvent[] {
683                     mImsDedicatedBearerListenerEvent1, mImsDedicatedBearerListenerEvent2
684                 };
685 
686 
687         mImsDedicatedBearerEvent1 = new ImsDedicatedBearerEvent();
688         mImsDedicatedBearerEvent1.carrierId = CARRIER1_ID;
689         mImsDedicatedBearerEvent1.slotId = SLOT_ID1;
690         mImsDedicatedBearerEvent1.ratAtEnd = TelephonyManager.NETWORK_TYPE_LTE;
691         mImsDedicatedBearerEvent1.qci = 5;
692         mImsDedicatedBearerEvent1.bearerState =
693                 TelephonyStatsLog.IMS_DEDICATED_BEARER_EVENT__BEARER_STATE__STATE_ADDED;
694         mImsDedicatedBearerEvent1.localConnectionInfoReceived = true;
695         mImsDedicatedBearerEvent1.remoteConnectionInfoReceived = true;
696         mImsDedicatedBearerEvent1.hasListeners = true;
697         mImsDedicatedBearerEvent1.count = 1;
698 
699         mImsDedicatedBearerEvent2 = new ImsDedicatedBearerEvent();
700         mImsDedicatedBearerEvent2.carrierId = CARRIER1_ID;
701         mImsDedicatedBearerEvent2.slotId = SLOT_ID1;
702         mImsDedicatedBearerEvent2.ratAtEnd = TelephonyManager.NETWORK_TYPE_NR;
703         mImsDedicatedBearerEvent2.qci = 6;
704         mImsDedicatedBearerEvent2.bearerState =
705                 TelephonyStatsLog.IMS_DEDICATED_BEARER_EVENT__BEARER_STATE__STATE_MODIFIED;
706         mImsDedicatedBearerEvent2.localConnectionInfoReceived = true;
707         mImsDedicatedBearerEvent2.remoteConnectionInfoReceived = true;
708         mImsDedicatedBearerEvent2.hasListeners = true;
709         mImsDedicatedBearerEvent2.count = 1;
710 
711         mImsDedicatedBearerEvents =
712                 new ImsDedicatedBearerEvent[] {
713                     mImsDedicatedBearerEvent1, mImsDedicatedBearerEvent2
714                 };
715 
716 
717         mUceEventStats1 = new UceEventStats();
718         mUceEventStats1.carrierId = CARRIER1_ID;
719         mUceEventStats1.slotId = SLOT_ID1;
720         mUceEventStats1.type = 1;
721         mUceEventStats1.successful = true;
722         mUceEventStats1.commandCode = 0;
723         mUceEventStats1.networkResponse = 200;
724         mUceEventStats1.count = 1;
725 
726         mUceEventStats2 = new UceEventStats();
727         mUceEventStats2.carrierId = CARRIER2_ID;
728         mUceEventStats2.slotId = SLOT_ID2;
729         mUceEventStats2.type = 2;
730         mUceEventStats2.successful = false;
731         mUceEventStats2.commandCode = 2;
732         mUceEventStats2.networkResponse = 0;
733         mUceEventStats2.count = 1;
734         mUceEventStatses = new UceEventStats[] {mUceEventStats1, mUceEventStats2};
735 
736         mPresenceNotifyEvent1 = new PresenceNotifyEvent();
737         mPresenceNotifyEvent1.carrierId = CARRIER1_ID;
738         mPresenceNotifyEvent1.slotId = SLOT_ID1;
739         mPresenceNotifyEvent1.reason = 1;
740         mPresenceNotifyEvent1.contentBodyReceived = true;
741         mPresenceNotifyEvent1.rcsCapsCount = 1;
742         mPresenceNotifyEvent1.mmtelCapsCount = 1;
743         mPresenceNotifyEvent1.noCapsCount = 0;
744         mPresenceNotifyEvent1.count = 1;
745 
746         mPresenceNotifyEvent2 = new PresenceNotifyEvent();
747         mPresenceNotifyEvent2.carrierId = CARRIER2_ID;
748         mPresenceNotifyEvent2.slotId = SLOT_ID2;
749         mPresenceNotifyEvent2.reason = 1;
750         mPresenceNotifyEvent2.contentBodyReceived = false;
751         mPresenceNotifyEvent2.rcsCapsCount = 0;
752         mPresenceNotifyEvent2.mmtelCapsCount = 0;
753         mPresenceNotifyEvent2.noCapsCount = 1;
754         mPresenceNotifyEvent2.count = 1;
755         mPresenceNotifyEvents = new PresenceNotifyEvent[] {mPresenceNotifyEvent1,
756                 mPresenceNotifyEvent2};
757 
758         //A destroyed SipDelegate
759         mSipDelegateStats1 = new SipDelegateStats();
760         mSipDelegateStats1.carrierId = CARRIER1_ID;
761         mSipDelegateStats1.slotId = SLOT_ID1;
762         mSipDelegateStats1.uptimeMillis = 1000L;
763         mSipDelegateStats1.destroyReason =
764                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP;
765 
766         //An active SipDelegate
767         mSipDelegateStats2 = new SipDelegateStats();
768         mSipDelegateStats2.carrierId = CARRIER1_ID;
769         mSipDelegateStats2.slotId = SLOT_ID1;
770         mSipDelegateStats2.uptimeMillis = 1000L;
771         mSipDelegateStats2.destroyReason =
772                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD;
773 
774         //An active SipDelegate
775         mSipDelegateStats3 = new SipDelegateStats();
776         mSipDelegateStats3.carrierId = CARRIER2_ID;
777         mSipDelegateStats3.slotId = SLOT_ID2;
778         mSipDelegateStats3.uptimeMillis = 3000L;
779         mSipDelegateStats3.destroyReason =
780                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN;
781 
782         //A registered SipTransportFeatureTag
783         mSipTransportFeatureTagStats1 = new SipTransportFeatureTagStats();
784         mSipTransportFeatureTagStats1.carrierId = CARRIER1_ID;
785         mSipTransportFeatureTagStats1.slotId = SLOT_ID1;
786         mSipTransportFeatureTagStats1.featureTagName = TelephonyProtoEnums.IMS_FEATURE_TAG_CHAT_IM;
787         mSipTransportFeatureTagStats1.sipTransportDeniedReason =  RcsStats.NONE;
788         mSipTransportFeatureTagStats1.sipTransportDeregisteredReason = RcsStats.NONE;
789         mSipTransportFeatureTagStats1.associatedMillis = 1000L;
790 
791         //A denied SipTransportFeatureTag
792         mSipTransportFeatureTagStats2 = new SipTransportFeatureTagStats();
793         mSipTransportFeatureTagStats2.carrierId = CARRIER1_ID;
794         mSipTransportFeatureTagStats2.slotId = SLOT_ID1;
795         mSipTransportFeatureTagStats2.featureTagName = 1;
796         mSipTransportFeatureTagStats2.sipTransportDeniedReason =
797                 SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE;
798         mSipTransportFeatureTagStats2.sipTransportDeregisteredReason = RcsStats.NONE;
799         mSipTransportFeatureTagStats2.associatedMillis = 1000L;
800 
801         mSipDelegateStatsArray = new SipDelegateStats[]{mSipDelegateStats2, mSipDelegateStats3};
802 
803         mSipTransportFeatureTagStatsArray = new SipTransportFeatureTagStats[]
804                 {mSipTransportFeatureTagStats1, mSipTransportFeatureTagStats2};
805 
806         mGbaEvent1 = new GbaEvent();
807         mGbaEvent1.carrierId = CARRIER1_ID;
808         mGbaEvent1.slotId = SLOT_ID1;
809         mGbaEvent1.successful = true;
810         mGbaEvent1.failedReason = GBA_EVENT__FAILED_REASON__UNKNOWN;
811         mGbaEvent1.count = 1;
812 
813         mGbaEvent2 = new GbaEvent();
814         mGbaEvent2.carrierId = CARRIER2_ID;
815         mGbaEvent2.slotId = SLOT_ID2;
816         mGbaEvent2.successful = false;
817         mGbaEvent2.failedReason = GBA_EVENT__FAILED_REASON__FEATURE_NOT_READY;
818         mGbaEvent2.count = 1;
819 
820         mGbaEvent = new GbaEvent[] {mGbaEvent1, mGbaEvent2};
821 
822         //stats slot 0
823         mSipMessageResponse1 = new SipMessageResponse();
824         mSipMessageResponse1.carrierId = CARRIER1_ID;
825         mSipMessageResponse1.slotId = SLOT_ID1;
826         //"INVITE"
827         mSipMessageResponse1.sipMessageMethod = 2;
828         mSipMessageResponse1.sipMessageResponse = 200;
829         mSipMessageResponse1.sipMessageDirection = 1;
830         mSipMessageResponse1.messageError = 0;
831         mSipMessageResponse1.count = 1;
832 
833         //stats slot 1
834         mSipMessageResponse2 = new SipMessageResponse();
835         mSipMessageResponse2.carrierId = CARRIER2_ID;
836         mSipMessageResponse2.slotId = SLOT_ID2;
837         //"INVITE"
838         mSipMessageResponse2.sipMessageMethod = 2;
839         mSipMessageResponse2.sipMessageResponse = 200;
840         mSipMessageResponse2.sipMessageDirection = 0;
841         mSipMessageResponse2.messageError = 0;
842         mSipMessageResponse2.count = 1;
843 
844         mSipMessageResponse =
845                 new SipMessageResponse[] {mSipMessageResponse1, mSipMessageResponse2};
846 
847         // stats slot 0
848         mSipTransportSession1 = new SipTransportSession();
849         mSipTransportSession1.carrierId = CARRIER1_ID;
850         mSipTransportSession1.slotId = SLOT_ID1;
851         //"INVITE"
852         mSipTransportSession1.sessionMethod = 2;
853         mSipTransportSession1.sipMessageDirection = 1;
854         mSipTransportSession1.sipResponse = 200;
855         mSipTransportSession1.sessionCount = 1;
856         mSipTransportSession1.endedGracefullyCount = 1;
857         mSipTransportSession1.isEndedGracefully = true;
858 
859         // stats slot 1
860         mSipTransportSession2 = new SipTransportSession();
861         mSipTransportSession2.carrierId = CARRIER2_ID;
862         mSipTransportSession2.slotId = SLOT_ID2;
863         //"INVITE"
864         mSipTransportSession2.sessionMethod = 2;
865         mSipTransportSession2.sipMessageDirection = 0;
866         mSipTransportSession2.sipResponse = 200;
867         mSipTransportSession2.sessionCount = 1;
868         mSipTransportSession2.endedGracefullyCount = 1;
869         mSipTransportSession2.isEndedGracefully = true;
870 
871         mSipTransportSession =
872                 new SipTransportSession[] {mSipTransportSession1, mSipTransportSession2};
873     }
874 
875     private static class TestablePersistAtomsStorage extends PersistAtomsStorage {
876         private long mTimeMillis = START_TIME_MILLIS;
877 
TestablePersistAtomsStorage(Context context)878         TestablePersistAtomsStorage(Context context) {
879             super(context);
880             // Remove delay for saving to persistent storage during tests.
881             mSaveImmediately = true;
882         }
883 
884         @Override
getWallTimeMillis()885         protected long getWallTimeMillis() {
886             // NOTE: super class constructor will be executed before private field is set, which
887             // gives the wrong start time (mTimeMillis will have its default value of 0L)
888             return mTimeMillis == 0L ? START_TIME_MILLIS : mTimeMillis;
889         }
890 
setTimeMillis(long timeMillis)891         private void setTimeMillis(long timeMillis) {
892             mTimeMillis = timeMillis;
893         }
894 
incTimeMillis(long timeMillis)895         private void incTimeMillis(long timeMillis) {
896             mTimeMillis += timeMillis;
897         }
898 
getAtomsProto()899         private PersistAtoms getAtomsProto() {
900             // NOTE: unlike other methods in PersistAtomsStorage, this is not synchronized, but
901             // should be fine since the test is single-threaded
902             return mAtoms;
903         }
904     }
905 
906     private TestablePersistAtomsStorage mPersistAtomsStorage;
907 
908     private static final Comparator<MessageNano> sProtoComparator =
909             new Comparator<>() {
910                 @Override
911                 public int compare(MessageNano o1, MessageNano o2) {
912                     if (o1 == o2) {
913                         return 0;
914                     }
915                     if (o1 == null) {
916                         return -1;
917                     }
918                     if (o2 == null) {
919                         return 1;
920                     }
921                     assertEquals(o1.getClass(), o2.getClass());
922                     return o1.toString().compareTo(o2.toString());
923                 }
924             };
925 
926     @Before
setUp()927     public void setUp() throws Exception {
928         super.setUp(getClass().getSimpleName());
929         mTestFileOutputStream = mock(FileOutputStream.class);
930         makeTestData();
931 
932         // by default, test loading with real file IO and saving with mocks
933         mTestFile = mFolder.newFile(TEST_FILE);
934         doReturn(mTestFileOutputStream).when(mContext).openFileOutput(anyString(), anyInt());
935         doReturn(mTestFile).when(mContext).getFileStreamPath(anyString());
936     }
937 
938     @After
tearDown()939     public void tearDown() throws Exception {
940         mTestFile.delete();
941         mTestFile = null;
942         mFolder = null;
943         mCall1Proto = null;
944         mCall2Proto = null;
945         mCall3Proto = null;
946         mCall4Proto = null;
947         mCarrier1LteUsageProto = null;
948         mCarrier1UmtsUsageProto = null;
949         mCarrier2LteUsageProto = null;
950         mCarrier3LteUsageProto = null;
951         mCarrier3GsmUsageProto = null;
952         mVoiceCallRatUsages = null;
953         mServiceSwitch1Proto = null;
954         mServiceSwitch2Proto = null;
955         mServiceState1Proto = null;
956         mServiceState2Proto = null;
957         mServiceState3Proto = null;
958         mServiceState4Proto = null;
959         mServiceState5Proto = null;
960         mServiceSwitches = null;
961         mServiceStates = null;
962         mImsRegistrationStatsLte0 = null;
963         mImsRegistrationStatsWifi0 = null;
964         mImsRegistrationStatsLte1 = null;
965         mImsRegistrationTerminationLte = null;
966         mImsRegistrationTerminationWifi = null;
967         mImsRegistrationStats = null;
968         mImsRegistrationTerminations = null;
969         mDataCallSession0 = null;
970         mDataCallSession1 = null;
971         mImsRegistrationFeatureTagStats1Proto = null;
972         mImsRegistrationFeatureTagStats2Proto = null;
973         mImsRegistrationFeatureTagStatses = null;
974         mRcsClientProvisioningStats1Proto = null;
975         mRcsClientProvisioningStats2Proto = null;
976         mRcsClientProvisioningStatses = null;
977         mRcsAcsProvisioningStats1Proto = null;
978         mRcsAcsProvisioningStats2Proto = null;
979         mRcsAcsProvisioningStatses = null;
980         mImsRegistrationServiceIm = null;
981         mImsRegistrationServiceFt = null;
982         mImsRegistrationServiceDescStats = null;
983         mImsDedicatedBearerListenerEvent1 = null;
984         mImsDedicatedBearerListenerEvent2 = null;
985         mImsDedicatedBearerListenerEvents = null;
986         mImsDedicatedBearerEvent1 = null;
987         mImsDedicatedBearerEvent2 = null;
988         mImsDedicatedBearerEvents = null;
989         mUceEventStats1 = null;
990         mUceEventStats2 = null;
991         mUceEventStatses = null;
992         mPresenceNotifyEvent1 = null;
993         mPresenceNotifyEvent2 = null;
994         mPresenceNotifyEvents = null;
995         mSipTransportFeatureTagStats1 = null;
996         mSipTransportFeatureTagStats2 = null;
997         mSipTransportFeatureTagStatsArray = null;
998         mSipDelegateStats1 = null;
999         mSipDelegateStats2 = null;
1000         mSipDelegateStats3 = null;
1001         mSipDelegateStatsArray = null;
1002         mGbaEvent1 = null;
1003         mGbaEvent2 = null;
1004         mGbaEvent = null;
1005         mSipMessageResponse1 = null;
1006         mSipMessageResponse2 = null;
1007         mSipMessageResponse = null;
1008         mSipTransportSession1 = null;
1009         mSipTransportSession2 = null;
1010         mSipTransportSession = null;
1011         super.tearDown();
1012     }
1013 
1014     @Test
1015     @SmallTest
loadAtoms_fileNotExist()1016     public void loadAtoms_fileNotExist() throws Exception {
1017         mTestFile.delete();
1018 
1019         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1020         mPersistAtomsStorage.incTimeMillis(100L);
1021 
1022         // no exception should be thrown, storage should be empty, pull time should be start time
1023         assertAllPullTimestampEquals(START_TIME_MILLIS);
1024         assertStorageIsEmptyForAllAtoms();
1025     }
1026 
1027     @Test
1028     @SmallTest
loadAtoms_unreadable()1029     public void loadAtoms_unreadable() throws Exception {
1030         createEmptyTestFile();
1031         mTestFile.setReadable(false);
1032 
1033         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1034         mPersistAtomsStorage.incTimeMillis(100L);
1035 
1036         // no exception should be thrown, storage should be empty, pull time should be start time
1037         assertAllPullTimestampEquals(START_TIME_MILLIS);
1038         assertStorageIsEmptyForAllAtoms();
1039     }
1040 
1041     @Test
1042     @SmallTest
loadAtoms_emptyProto()1043     public void loadAtoms_emptyProto() throws Exception {
1044         createEmptyTestFile();
1045 
1046         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1047         mPersistAtomsStorage.incTimeMillis(100L);
1048 
1049         // no exception should be thrown, storage should be empty, pull time should be start time
1050         assertAllPullTimestampEquals(START_TIME_MILLIS);
1051         assertStorageIsEmptyForAllAtoms();
1052     }
1053 
1054     @Test
1055     @SmallTest
loadAtoms_malformedFile()1056     public void loadAtoms_malformedFile() throws Exception {
1057         FileOutputStream stream = new FileOutputStream(mTestFile);
1058         stream.write("This is not a proto file.".getBytes(StandardCharsets.UTF_8));
1059         stream.close();
1060 
1061         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1062         mPersistAtomsStorage.incTimeMillis(100L);
1063 
1064         // no exception should be thrown, storage should be empty, pull time should be start time
1065         assertAllPullTimestampEquals(START_TIME_MILLIS);
1066         assertStorageIsEmptyForAllAtoms();
1067     }
1068 
1069     @Test
1070     @SmallTest
loadAtoms_pullTimeMissing()1071     public void loadAtoms_pullTimeMissing() throws Exception {
1072         // create test file with lastPullTimeMillis = 0L, i.e. default/unknown
1073         createTestFile(0L);
1074 
1075         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1076         mPersistAtomsStorage.incTimeMillis(100L);
1077 
1078         // no exception should be thrown, storage should be match, pull time should be start time
1079         assertAllPullTimestampEquals(START_TIME_MILLIS);
1080         assertProtoArrayEquals(mVoiceCallRatUsages, mPersistAtomsStorage.getVoiceCallRatUsages(0L));
1081         assertProtoArrayEquals(mVoiceCallSessions, mPersistAtomsStorage.getVoiceCallSessions(0L));
1082         assertProtoArrayEqualsIgnoringOrder(
1083                 mServiceStates, mPersistAtomsStorage.getCellularServiceStates(0L));
1084         assertProtoArrayEqualsIgnoringOrder(
1085                 mServiceSwitches, mPersistAtomsStorage.getCellularDataServiceSwitches(0L));
1086     }
1087 
1088     @Test
1089     @SmallTest
loadAtoms_validContents()1090     public void loadAtoms_validContents() throws Exception {
1091         createTestFile(/* lastPullTimeMillis= */ 100L);
1092 
1093         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1094 
1095         // no exception should be thrown, storage and pull time should match
1096         assertAllPullTimestampEquals(100L);
1097         assertProtoArrayEquals(mVoiceCallRatUsages, mPersistAtomsStorage.getVoiceCallRatUsages(0L));
1098         assertProtoArrayEquals(mVoiceCallSessions, mPersistAtomsStorage.getVoiceCallSessions(0L));
1099         assertProtoArrayEqualsIgnoringOrder(
1100                 mServiceStates, mPersistAtomsStorage.getCellularServiceStates(0L));
1101         assertProtoArrayEqualsIgnoringOrder(
1102                 mServiceSwitches, mPersistAtomsStorage.getCellularDataServiceSwitches(0L));
1103     }
1104 
1105     @Test
1106     @SmallTest
addVoiceCallSession_emptyProto()1107     public void addVoiceCallSession_emptyProto() throws Exception {
1108         createEmptyTestFile();
1109 
1110         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1111         mPersistAtomsStorage.addVoiceCallSession(mCall1Proto);
1112         mPersistAtomsStorage.incTimeMillis(100L);
1113 
1114         // call should be added successfully, there should be no RAT usage, changes should be saved
1115         verifyCurrentStateSavedToFileOnce();
1116         assertProtoArrayIsEmpty(mPersistAtomsStorage.getVoiceCallRatUsages(0L));
1117         VoiceCallSession[] voiceCallSession = mPersistAtomsStorage.getVoiceCallSessions(0L);
1118         assertProtoArrayEquals(new VoiceCallSession[] {mCall1Proto}, voiceCallSession);
1119     }
1120 
1121     @Test
1122     @SmallTest
addVoiceCallSession_withExistingCalls()1123     public void addVoiceCallSession_withExistingCalls() throws Exception {
1124         createTestFile(START_TIME_MILLIS);
1125 
1126         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1127         mPersistAtomsStorage.addVoiceCallSession(mCall1Proto);
1128         mPersistAtomsStorage.incTimeMillis(100L);
1129 
1130         // call should be added successfully, RAT usages should not change, changes should be saved
1131         assertProtoArrayEquals(mVoiceCallRatUsages, mPersistAtomsStorage.getVoiceCallRatUsages(0L));
1132         VoiceCallSession[] expectedVoiceCallSessions =
1133                 new VoiceCallSession[] {
1134                     mCall1Proto, mCall1Proto, mCall2Proto, mCall3Proto, mCall4Proto
1135                 };
1136         // call list is randomized at this point
1137         verifyCurrentStateSavedToFileOnce();
1138         assertProtoArrayEqualsIgnoringOrder(
1139                 expectedVoiceCallSessions, mPersistAtomsStorage.getVoiceCallSessions(0L));
1140     }
1141 
1142     @Test
1143     @SmallTest
addVoiceCallSession_tooManyCalls()1144     public void addVoiceCallSession_tooManyCalls() throws Exception {
1145         createEmptyTestFile();
1146 
1147         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1148         addRepeatedCalls(mPersistAtomsStorage, mCall1Proto, 50);
1149         mPersistAtomsStorage.addVoiceCallSession(mCall2Proto);
1150         mPersistAtomsStorage.incTimeMillis(100L);
1151 
1152         // one previous call should be evicted, the new call should be added
1153         verifyCurrentStateSavedToFileOnce();
1154         VoiceCallSession[] calls = mPersistAtomsStorage.getVoiceCallSessions(0L);
1155         assertHasCall(calls, mCall1Proto, /* expectedCount= */ 49);
1156         assertHasCall(calls, mCall2Proto, /* expectedCount= */ 1);
1157     }
1158 
1159     @Test
1160     @SmallTest
addVoiceCallSession_tooManyCalls_withEmergencyCalls()1161     public void addVoiceCallSession_tooManyCalls_withEmergencyCalls() throws Exception {
1162         createEmptyTestFile();
1163         // We initially have storage full of emergency calls except one.
1164         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1165         addRepeatedCalls(mPersistAtomsStorage, mCall4Proto, 49);
1166         mPersistAtomsStorage.addVoiceCallSession(mCall1Proto);
1167 
1168         mPersistAtomsStorage.addVoiceCallSession(mCall4Proto);
1169         mPersistAtomsStorage.incTimeMillis(100L);
1170 
1171         // after adding one more emergency call, the previous non-emergency call should be evicted
1172         verifyCurrentStateSavedToFileOnce();
1173         VoiceCallSession[] calls = mPersistAtomsStorage.getVoiceCallSessions(0L);
1174         assertHasCall(calls, mCall4Proto, /* expectedCount= */ 50);
1175     }
1176 
1177     @Test
1178     @SmallTest
addVoiceCallRatUsage_emptyProto()1179     public void addVoiceCallRatUsage_emptyProto() throws Exception {
1180         createEmptyTestFile();
1181         VoiceCallRatTracker ratTracker = VoiceCallRatTracker.fromProto(mVoiceCallRatUsages);
1182 
1183         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1184         mPersistAtomsStorage.addVoiceCallRatUsage(ratTracker);
1185         mPersistAtomsStorage.incTimeMillis(100L);
1186 
1187         // RAT should be added successfully, calls should not change, changes should be saved
1188         verifyCurrentStateSavedToFileOnce();
1189         assertProtoArrayEqualsIgnoringOrder(
1190                 mVoiceCallRatUsages, mPersistAtomsStorage.getVoiceCallRatUsages(0L));
1191         assertProtoArrayIsEmpty(mPersistAtomsStorage.getVoiceCallSessions(0L));
1192     }
1193 
1194     @Test
1195     @SmallTest
addVoiceCallRatUsage_withExistingUsages()1196     public void addVoiceCallRatUsage_withExistingUsages() throws Exception {
1197         createTestFile(START_TIME_MILLIS);
1198         VoiceCallRatTracker ratTracker = VoiceCallRatTracker.fromProto(mVoiceCallRatUsages);
1199 
1200         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1201         mPersistAtomsStorage.addVoiceCallRatUsage(ratTracker);
1202         mPersistAtomsStorage.incTimeMillis(100L);
1203 
1204         // RAT should be added successfully, calls should not change, changes should be saved
1205         // call count and duration should become doubled since mVoiceCallRatUsages applied through
1206         // both file and addVoiceCallRatUsage()
1207         verifyCurrentStateSavedToFileOnce();
1208         VoiceCallRatUsage[] expectedVoiceCallRatUsage =
1209                 multiplyVoiceCallRatUsage(mVoiceCallRatUsages, 2);
1210         assertProtoArrayEqualsIgnoringOrder(
1211                 expectedVoiceCallRatUsage, mPersistAtomsStorage.getVoiceCallRatUsages(0L));
1212         assertProtoArrayEquals(mVoiceCallSessions, mPersistAtomsStorage.getVoiceCallSessions(0L));
1213     }
1214 
1215     @Test
1216     @SmallTest
addVoiceCallRatUsage_empty()1217     public void addVoiceCallRatUsage_empty() throws Exception {
1218         createEmptyTestFile();
1219         VoiceCallRatTracker ratTracker = VoiceCallRatTracker.fromProto(new VoiceCallRatUsage[0]);
1220 
1221         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1222         mPersistAtomsStorage.addVoiceCallRatUsage(ratTracker);
1223         mPersistAtomsStorage.incTimeMillis(100L);
1224 
1225         // RAT should be added successfully, calls should not change
1226         // in this case saving is unnecessarily
1227         assertProtoArrayIsEmpty(mPersistAtomsStorage.getVoiceCallRatUsages(0L));
1228         assertProtoArrayIsEmpty(mPersistAtomsStorage.getVoiceCallSessions(0L));
1229     }
1230 
1231     @Test
1232     @SmallTest
getVoiceCallRatUsages_tooFrequent()1233     public void getVoiceCallRatUsages_tooFrequent() throws Exception {
1234         createTestFile(START_TIME_MILLIS);
1235 
1236         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1237         mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
1238         VoiceCallRatUsage[] voiceCallRatUsage = mPersistAtomsStorage.getVoiceCallRatUsages(100L);
1239 
1240         // should be denied
1241         assertNull(voiceCallRatUsage);
1242     }
1243 
1244     @Test
1245     @SmallTest
getVoiceCallRatUsages_withSavedAtoms()1246     public void getVoiceCallRatUsages_withSavedAtoms() throws Exception {
1247         createTestFile(START_TIME_MILLIS);
1248 
1249         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1250         mPersistAtomsStorage.incTimeMillis(100L);
1251         VoiceCallRatUsage[] voiceCallRatUsage1 = mPersistAtomsStorage.getVoiceCallRatUsages(50L);
1252         mPersistAtomsStorage.incTimeMillis(100L);
1253         VoiceCallRatUsage[] voiceCallRatUsage2 = mPersistAtomsStorage.getVoiceCallRatUsages(50L);
1254         long voiceCallSessionPullTimestampMillis =
1255                 mPersistAtomsStorage.getAtomsProto().voiceCallSessionPullTimestampMillis;
1256         VoiceCallSession[] voiceCallSession = mPersistAtomsStorage.getVoiceCallSessions(50L);
1257 
1258         // first set of results should equal to file contents, second should be empty, corresponding
1259         // pull timestamp should be updated and saved, other fields should be unaffected
1260         assertProtoArrayEquals(mVoiceCallRatUsages, voiceCallRatUsage1);
1261         assertProtoArrayIsEmpty(voiceCallRatUsage2);
1262         assertEquals(
1263                 START_TIME_MILLIS + 200L,
1264                 mPersistAtomsStorage.getAtomsProto().voiceCallRatUsagePullTimestampMillis);
1265         assertProtoArrayEquals(mVoiceCallSessions, voiceCallSession);
1266         assertEquals(START_TIME_MILLIS, voiceCallSessionPullTimestampMillis);
1267         InOrder inOrder = inOrder(mTestFileOutputStream);
1268         assertEquals(
1269                 START_TIME_MILLIS + 100L,
1270                 getAtomsWritten(inOrder).voiceCallRatUsagePullTimestampMillis);
1271         assertEquals(
1272                 START_TIME_MILLIS + 200L,
1273                 getAtomsWritten(inOrder).voiceCallRatUsagePullTimestampMillis);
1274         assertEquals(
1275                 START_TIME_MILLIS + 200L,
1276                 getAtomsWritten(inOrder).voiceCallSessionPullTimestampMillis);
1277         inOrder.verifyNoMoreInteractions();
1278     }
1279 
1280     @Test
1281     @SmallTest
getVoiceCallSessions_tooFrequent()1282     public void getVoiceCallSessions_tooFrequent() throws Exception {
1283         createTestFile(START_TIME_MILLIS);
1284 
1285         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1286         mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
1287         VoiceCallSession[] voiceCallSession = mPersistAtomsStorage.getVoiceCallSessions(100L);
1288 
1289         // should be denied
1290         assertNull(voiceCallSession);
1291     }
1292 
1293     @Test
1294     @SmallTest
getVoiceCallSessions_withSavedAtoms()1295     public void getVoiceCallSessions_withSavedAtoms() throws Exception {
1296         createTestFile(START_TIME_MILLIS);
1297 
1298         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1299         mPersistAtomsStorage.incTimeMillis(100L);
1300         VoiceCallSession[] voiceCallSession1 = mPersistAtomsStorage.getVoiceCallSessions(50L);
1301         mPersistAtomsStorage.incTimeMillis(100L);
1302         VoiceCallSession[] voiceCallSession2 = mPersistAtomsStorage.getVoiceCallSessions(50L);
1303         long voiceCallRatUsagePullTimestampMillis =
1304                 mPersistAtomsStorage.getAtomsProto().voiceCallRatUsagePullTimestampMillis;
1305         VoiceCallRatUsage[] voiceCallRatUsage = mPersistAtomsStorage.getVoiceCallRatUsages(50L);
1306 
1307         // first set of results should equal to file contents, second should be empty, corresponding
1308         // pull timestamp should be updated and saved, other fields should be unaffected
1309         assertProtoArrayEquals(mVoiceCallSessions, voiceCallSession1);
1310         assertProtoArrayIsEmpty(voiceCallSession2);
1311         assertEquals(
1312                 START_TIME_MILLIS + 200L,
1313                 mPersistAtomsStorage.getAtomsProto().voiceCallSessionPullTimestampMillis);
1314         assertProtoArrayEquals(mVoiceCallRatUsages, voiceCallRatUsage);
1315         assertEquals(START_TIME_MILLIS, voiceCallRatUsagePullTimestampMillis);
1316         InOrder inOrder = inOrder(mTestFileOutputStream);
1317         assertEquals(
1318                 START_TIME_MILLIS + 100L,
1319                 getAtomsWritten(inOrder).voiceCallSessionPullTimestampMillis);
1320         assertEquals(
1321                 START_TIME_MILLIS + 200L,
1322                 getAtomsWritten(inOrder).voiceCallSessionPullTimestampMillis);
1323         assertEquals(
1324                 START_TIME_MILLIS + 200L,
1325                 getAtomsWritten(inOrder).voiceCallRatUsagePullTimestampMillis);
1326         inOrder.verifyNoMoreInteractions();
1327     }
1328 
1329     @Test
1330     @SmallTest
addCellularServiceStateAndCellularDataServiceSwitch_emptyProto()1331     public void addCellularServiceStateAndCellularDataServiceSwitch_emptyProto() throws Exception {
1332         createEmptyTestFile();
1333 
1334         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1335         mPersistAtomsStorage.addCellularServiceStateAndCellularDataServiceSwitch(
1336                 mServiceState1Proto, mServiceSwitch1Proto);
1337         mPersistAtomsStorage.incTimeMillis(100L);
1338 
1339         // service state and service switch should be added successfully
1340         verifyCurrentStateSavedToFileOnce();
1341         CellularServiceState[] serviceStates = mPersistAtomsStorage.getCellularServiceStates(0L);
1342         CellularDataServiceSwitch[] serviceSwitches =
1343                 mPersistAtomsStorage.getCellularDataServiceSwitches(0L);
1344         assertProtoArrayEquals(new CellularServiceState[] {mServiceState1Proto}, serviceStates);
1345         assertProtoArrayEquals(
1346                 new CellularDataServiceSwitch[] {mServiceSwitch1Proto}, serviceSwitches);
1347     }
1348 
1349     @Test
1350     @SmallTest
addCellularServiceStateAndCellularDataServiceSwitch_withExistingEntries()1351     public void addCellularServiceStateAndCellularDataServiceSwitch_withExistingEntries()
1352             throws Exception {
1353         createEmptyTestFile();
1354         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1355         mPersistAtomsStorage.addCellularServiceStateAndCellularDataServiceSwitch(
1356                 mServiceState1Proto, mServiceSwitch1Proto);
1357 
1358         mPersistAtomsStorage.addCellularServiceStateAndCellularDataServiceSwitch(
1359                 mServiceState2Proto, mServiceSwitch2Proto);
1360         mPersistAtomsStorage.incTimeMillis(100L);
1361 
1362         // service state and service switch should be added successfully
1363         verifyCurrentStateSavedToFileOnce();
1364         CellularServiceState[] serviceStates = mPersistAtomsStorage.getCellularServiceStates(0L);
1365         CellularDataServiceSwitch[] serviceSwitches =
1366                 mPersistAtomsStorage.getCellularDataServiceSwitches(0L);
1367         assertProtoArrayEqualsIgnoringOrder(
1368                 new CellularServiceState[] {mServiceState1Proto, mServiceState2Proto},
1369                 serviceStates);
1370         assertProtoArrayEqualsIgnoringOrder(
1371                 new CellularDataServiceSwitch[] {mServiceSwitch1Proto, mServiceSwitch2Proto},
1372                 serviceSwitches);
1373     }
1374 
1375     @Test
1376     @SmallTest
addCellularServiceStateAndCellularDataServiceSwitch_updateExistingEntries()1377     public void addCellularServiceStateAndCellularDataServiceSwitch_updateExistingEntries()
1378             throws Exception {
1379         createTestFile(START_TIME_MILLIS);
1380         CellularServiceState newServiceState1Proto = copyOf(mServiceState1Proto);
1381         CellularDataServiceSwitch newServiceSwitch1Proto = copyOf(mServiceSwitch1Proto);
1382         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1383 
1384         mPersistAtomsStorage.addCellularServiceStateAndCellularDataServiceSwitch(
1385                 copyOf(mServiceState1Proto), copyOf(mServiceSwitch1Proto));
1386         mPersistAtomsStorage.incTimeMillis(100L);
1387 
1388         // mServiceState1Proto's duration and mServiceSwitch1Proto's switch should be doubled
1389         verifyCurrentStateSavedToFileOnce();
1390         CellularServiceState[] serviceStates = mPersistAtomsStorage.getCellularServiceStates(0L);
1391         newServiceState1Proto.totalTimeMillis *= 2;
1392         assertProtoArrayEqualsIgnoringOrder(
1393                 new CellularServiceState[] {
1394                     newServiceState1Proto,
1395                     mServiceState2Proto,
1396                     mServiceState3Proto,
1397                     mServiceState4Proto,
1398                     mServiceState5Proto
1399                 },
1400                 serviceStates);
1401         CellularDataServiceSwitch[] serviceSwitches =
1402                 mPersistAtomsStorage.getCellularDataServiceSwitches(0L);
1403         newServiceSwitch1Proto.switchCount *= 2;
1404         assertProtoArrayEqualsIgnoringOrder(
1405                 new CellularDataServiceSwitch[] {newServiceSwitch1Proto, mServiceSwitch2Proto},
1406                 serviceSwitches);
1407     }
1408 
1409     @Test
1410     @SmallTest
addCellularServiceStateAndCellularDataServiceSwitch_tooManyServiceStates()1411     public void addCellularServiceStateAndCellularDataServiceSwitch_tooManyServiceStates()
1412             throws Exception {
1413         createEmptyTestFile();
1414         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1415         Queue<CellularServiceState> expectedServiceStates = new LinkedList<>();
1416         Queue<CellularDataServiceSwitch> expectedServiceSwitches = new LinkedList<>();
1417 
1418         // Add 51 service states, with the first being least recent
1419         for (int i = 0; i < 51; i++) {
1420             CellularServiceState state = new CellularServiceState();
1421             state.voiceRat = i / 10;
1422             state.dataRat = i % 10;
1423             expectedServiceStates.add(state);
1424             CellularDataServiceSwitch serviceSwitch = new CellularDataServiceSwitch();
1425             serviceSwitch.ratFrom = i / 10;
1426             serviceSwitch.ratTo = i % 10;
1427             expectedServiceSwitches.add(serviceSwitch);
1428             mPersistAtomsStorage.addCellularServiceStateAndCellularDataServiceSwitch(
1429                     copyOf(state), copyOf(serviceSwitch));
1430             mPersistAtomsStorage.incTimeMillis(100L);
1431         }
1432 
1433         // The least recent (the first) service state should be evicted
1434         verifyCurrentStateSavedToFileOnce();
1435         CellularServiceState[] serviceStates = mPersistAtomsStorage.getCellularServiceStates(0L);
1436         expectedServiceStates.remove();
1437         assertProtoArrayEqualsIgnoringOrder(
1438                 expectedServiceStates.toArray(new CellularServiceState[0]), serviceStates);
1439         CellularDataServiceSwitch[] serviceSwitches =
1440                 mPersistAtomsStorage.getCellularDataServiceSwitches(0L);
1441         expectedServiceSwitches.remove();
1442         assertProtoArrayEqualsIgnoringOrder(
1443                 expectedServiceSwitches.toArray(new CellularDataServiceSwitch[0]), serviceSwitches);
1444     }
1445 
1446     @Test
1447     @SmallTest
getCellularDataServiceSwitches_tooFrequent()1448     public void getCellularDataServiceSwitches_tooFrequent() throws Exception {
1449         createTestFile(START_TIME_MILLIS);
1450 
1451         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1452         mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
1453         CellularDataServiceSwitch[] serviceSwitches =
1454                 mPersistAtomsStorage.getCellularDataServiceSwitches(100L);
1455 
1456         // should be denied
1457         assertNull(serviceSwitches);
1458     }
1459 
1460     @Test
1461     @SmallTest
getCellularDataServiceSwitches_withSavedAtoms()1462     public void getCellularDataServiceSwitches_withSavedAtoms() throws Exception {
1463         createTestFile(START_TIME_MILLIS);
1464 
1465         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1466         mPersistAtomsStorage.incTimeMillis(100L);
1467         CellularDataServiceSwitch[] serviceSwitches1 =
1468                 mPersistAtomsStorage.getCellularDataServiceSwitches(50L);
1469         mPersistAtomsStorage.incTimeMillis(100L);
1470         CellularDataServiceSwitch[] serviceSwitches2 =
1471                 mPersistAtomsStorage.getCellularDataServiceSwitches(50L);
1472 
1473         // first set of results should equal to file contents, second should be empty, corresponding
1474         // pull timestamp should be updated and saved
1475         assertProtoArrayEqualsIgnoringOrder(
1476                 new CellularDataServiceSwitch[] {mServiceSwitch1Proto, mServiceSwitch2Proto},
1477                 serviceSwitches1);
1478         assertProtoArrayEquals(new CellularDataServiceSwitch[0], serviceSwitches2);
1479         assertEquals(
1480                 START_TIME_MILLIS + 200L,
1481                 mPersistAtomsStorage.getAtomsProto().cellularDataServiceSwitchPullTimestampMillis);
1482         InOrder inOrder = inOrder(mTestFileOutputStream);
1483         assertEquals(
1484                 START_TIME_MILLIS + 100L,
1485                 getAtomsWritten(inOrder).cellularDataServiceSwitchPullTimestampMillis);
1486         assertEquals(
1487                 START_TIME_MILLIS + 200L,
1488                 getAtomsWritten(inOrder).cellularDataServiceSwitchPullTimestampMillis);
1489         inOrder.verifyNoMoreInteractions();
1490     }
1491 
1492     @Test
1493     @SmallTest
getCellularServiceStates_tooFrequent()1494     public void getCellularServiceStates_tooFrequent() throws Exception {
1495         createTestFile(START_TIME_MILLIS);
1496 
1497         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1498         mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
1499         CellularServiceState[] serviceStates = mPersistAtomsStorage.getCellularServiceStates(100L);
1500 
1501         // should be denied
1502         assertNull(serviceStates);
1503     }
1504 
1505     @Test
1506     @SmallTest
getCellularServiceStates_withSavedAtoms()1507     public void getCellularServiceStates_withSavedAtoms() throws Exception {
1508         createTestFile(START_TIME_MILLIS);
1509 
1510         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1511         mPersistAtomsStorage.incTimeMillis(100L);
1512         CellularServiceState[] serviceStates1 = mPersistAtomsStorage.getCellularServiceStates(50L);
1513         mPersistAtomsStorage.incTimeMillis(100L);
1514         CellularServiceState[] serviceStates2 = mPersistAtomsStorage.getCellularServiceStates(50L);
1515 
1516         // first set of results should equal to file contents, second should be empty, corresponding
1517         // pull timestamp should be updated and saved
1518         assertProtoArrayEqualsIgnoringOrder(
1519                 new CellularServiceState[] {
1520                     mServiceState1Proto,
1521                     mServiceState2Proto,
1522                     mServiceState3Proto,
1523                     mServiceState4Proto,
1524                     mServiceState5Proto
1525                 },
1526                 serviceStates1);
1527         assertProtoArrayEquals(new CellularServiceState[0], serviceStates2);
1528         assertEquals(
1529                 START_TIME_MILLIS + 200L,
1530                 mPersistAtomsStorage.getAtomsProto().cellularServiceStatePullTimestampMillis);
1531         InOrder inOrder = inOrder(mTestFileOutputStream);
1532         assertEquals(
1533                 START_TIME_MILLIS + 100L,
1534                 getAtomsWritten(inOrder).cellularServiceStatePullTimestampMillis);
1535         assertEquals(
1536                 START_TIME_MILLIS + 200L,
1537                 getAtomsWritten(inOrder).cellularServiceStatePullTimestampMillis);
1538         inOrder.verifyNoMoreInteractions();
1539     }
1540 
1541     @Test
1542     @SmallTest
addImsRegistrationStats_emptyProto()1543     public void addImsRegistrationStats_emptyProto() throws Exception {
1544         createEmptyTestFile();
1545 
1546         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1547         mPersistAtomsStorage.addImsRegistrationStats(copyOf(mImsRegistrationStatsLte0));
1548         mPersistAtomsStorage.incTimeMillis(DAY_IN_MILLIS);
1549 
1550         // service state and service switch should be added successfully
1551         verifyCurrentStateSavedToFileOnce();
1552         ImsRegistrationStats[] regStats = mPersistAtomsStorage.getImsRegistrationStats(0L);
1553         assertProtoArrayEquals(new ImsRegistrationStats[] {mImsRegistrationStatsLte0}, regStats);
1554     }
1555 
1556     @Test
1557     @SmallTest
addImsRegistrationStats_withExistingEntries()1558     public void addImsRegistrationStats_withExistingEntries() throws Exception {
1559         createEmptyTestFile();
1560         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1561         mPersistAtomsStorage.addImsRegistrationStats(copyOf(mImsRegistrationStatsLte0));
1562 
1563         mPersistAtomsStorage.addImsRegistrationStats(copyOf(mImsRegistrationStatsWifi0));
1564         mPersistAtomsStorage.incTimeMillis(DAY_IN_MILLIS);
1565 
1566         // service state and service switch should be added successfully
1567         verifyCurrentStateSavedToFileOnce();
1568         ImsRegistrationStats[] regStats = mPersistAtomsStorage.getImsRegistrationStats(0L);
1569         assertProtoArrayEqualsIgnoringOrder(
1570                 new ImsRegistrationStats[] {mImsRegistrationStatsLte0, mImsRegistrationStatsWifi0},
1571                 regStats);
1572     }
1573 
1574     @Test
1575     @SmallTest
addImsRegistrationStats_updateExistingEntries()1576     public void addImsRegistrationStats_updateExistingEntries() throws Exception {
1577         createTestFile(START_TIME_MILLIS);
1578         ImsRegistrationStats newImsRegistrationStatsLte0 = copyOf(mImsRegistrationStatsLte0);
1579         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1580 
1581         mPersistAtomsStorage.addImsRegistrationStats(copyOf(mImsRegistrationStatsLte0));
1582         mPersistAtomsStorage.incTimeMillis(DAY_IN_MILLIS);
1583 
1584         // mImsRegistrationStatsLte0's durations should be doubled
1585         verifyCurrentStateSavedToFileOnce();
1586         ImsRegistrationStats[] serviceStates = mPersistAtomsStorage.getImsRegistrationStats(0L);
1587         newImsRegistrationStatsLte0.registeredMillis *= 2;
1588         newImsRegistrationStatsLte0.voiceCapableMillis *= 2;
1589         newImsRegistrationStatsLte0.voiceAvailableMillis *= 2;
1590         newImsRegistrationStatsLte0.smsCapableMillis *= 2;
1591         newImsRegistrationStatsLte0.smsAvailableMillis *= 2;
1592         newImsRegistrationStatsLte0.videoCapableMillis *= 2;
1593         newImsRegistrationStatsLte0.videoAvailableMillis *= 2;
1594         newImsRegistrationStatsLte0.utCapableMillis *= 2;
1595         newImsRegistrationStatsLte0.utAvailableMillis *= 2;
1596         assertProtoArrayEqualsIgnoringOrder(
1597                 new ImsRegistrationStats[] {
1598                     newImsRegistrationStatsLte0,
1599                     mImsRegistrationStatsWifi0,
1600                     mImsRegistrationStatsLte1
1601                 },
1602                 serviceStates);
1603     }
1604 
1605     @Test
1606     @SmallTest
addImsRegistrationStats_tooManyRegistrationStats()1607     public void addImsRegistrationStats_tooManyRegistrationStats() throws Exception {
1608         createEmptyTestFile();
1609         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1610         Queue<ImsRegistrationStats> expectedRegistrationStats = new LinkedList<>();
1611 
1612         // Add 11 registration stats
1613         for (int i = 0; i < 11; i++) {
1614             ImsRegistrationStats stats = copyOf(mImsRegistrationStatsLte0);
1615             stats.rat = i;
1616             expectedRegistrationStats.add(stats);
1617             mPersistAtomsStorage.addImsRegistrationStats(stats);
1618             mPersistAtomsStorage.incTimeMillis(100L);
1619         }
1620 
1621         // The least recent (the first) registration stats should be evicted
1622         verifyCurrentStateSavedToFileOnce();
1623         ImsRegistrationStats[] stats = mPersistAtomsStorage.getImsRegistrationStats(0L);
1624         expectedRegistrationStats.remove();
1625         assertProtoArrayEqualsIgnoringOrder(
1626                 expectedRegistrationStats.toArray(new ImsRegistrationStats[0]), stats);
1627     }
1628 
1629     @Test
1630     @SmallTest
addImsRegistrationTermination_emptyProto()1631     public void addImsRegistrationTermination_emptyProto() throws Exception {
1632         createEmptyTestFile();
1633 
1634         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1635         mPersistAtomsStorage.addImsRegistrationTermination(mImsRegistrationTerminationLte);
1636         mPersistAtomsStorage.incTimeMillis(100L);
1637 
1638         // service state and service switch should be added successfully
1639         verifyCurrentStateSavedToFileOnce();
1640         ImsRegistrationTermination[] terminations =
1641                 mPersistAtomsStorage.getImsRegistrationTerminations(0L);
1642         assertProtoArrayEquals(
1643                 new ImsRegistrationTermination[] {mImsRegistrationTerminationLte}, terminations);
1644     }
1645 
1646     @Test
1647     @SmallTest
addImsRegistrationTermination_withExistingEntries()1648     public void addImsRegistrationTermination_withExistingEntries() throws Exception {
1649         createEmptyTestFile();
1650         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1651         mPersistAtomsStorage.addImsRegistrationTermination(mImsRegistrationTerminationLte);
1652 
1653         mPersistAtomsStorage.addImsRegistrationTermination(mImsRegistrationTerminationWifi);
1654         mPersistAtomsStorage.incTimeMillis(100L);
1655 
1656         // service state and service switch should be added successfully
1657         verifyCurrentStateSavedToFileOnce();
1658         ImsRegistrationTermination[] terminations =
1659                 mPersistAtomsStorage.getImsRegistrationTerminations(0L);
1660         assertProtoArrayEqualsIgnoringOrder(
1661                 new ImsRegistrationTermination[] {
1662                     mImsRegistrationTerminationLte, mImsRegistrationTerminationWifi
1663                 },
1664                 terminations);
1665     }
1666 
1667     @Test
1668     @SmallTest
addImsRegistrationTermination_updateExistingEntries()1669     public void addImsRegistrationTermination_updateExistingEntries() throws Exception {
1670         createTestFile(START_TIME_MILLIS);
1671         ImsRegistrationTermination newTermination = copyOf(mImsRegistrationTerminationWifi);
1672         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1673 
1674         mPersistAtomsStorage.addImsRegistrationTermination(copyOf(mImsRegistrationTerminationWifi));
1675         mPersistAtomsStorage.incTimeMillis(100L);
1676 
1677         // mImsRegistrationTerminationWifi's count should be doubled
1678         verifyCurrentStateSavedToFileOnce();
1679         ImsRegistrationTermination[] terminations =
1680                 mPersistAtomsStorage.getImsRegistrationTerminations(0L);
1681         newTermination.count *= 2;
1682         assertProtoArrayEqualsIgnoringOrder(
1683                 new ImsRegistrationTermination[] {mImsRegistrationTerminationLte, newTermination},
1684                 terminations);
1685     }
1686 
1687     @Test
1688     @SmallTest
addImsRegistrationTermination_tooManyTerminations()1689     public void addImsRegistrationTermination_tooManyTerminations() throws Exception {
1690         createEmptyTestFile();
1691         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1692         Queue<ImsRegistrationTermination> expectedTerminations = new LinkedList<>();
1693 
1694         // Add 11 registration terminations
1695         for (int i = 0; i < 11; i++) {
1696             ImsRegistrationTermination termination = copyOf(mImsRegistrationTerminationLte);
1697             termination.reasonCode = i;
1698             expectedTerminations.add(termination);
1699             mPersistAtomsStorage.addImsRegistrationTermination(termination);
1700             mPersistAtomsStorage.incTimeMillis(100L);
1701         }
1702 
1703         // The least recent (the first) registration termination should be evicted
1704         verifyCurrentStateSavedToFileOnce();
1705         ImsRegistrationTermination[] terminations =
1706                 mPersistAtomsStorage.getImsRegistrationTerminations(0L);
1707         expectedTerminations.remove();
1708         assertProtoArrayEqualsIgnoringOrder(
1709                 expectedTerminations.toArray(new ImsRegistrationTermination[0]), terminations);
1710     }
1711 
1712     @Test
1713     @SmallTest
getImsRegistrationStats_tooFrequent()1714     public void getImsRegistrationStats_tooFrequent() throws Exception {
1715         createTestFile(START_TIME_MILLIS);
1716 
1717         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1718         mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
1719         ImsRegistrationStats[] stats = mPersistAtomsStorage.getImsRegistrationStats(100L);
1720 
1721         // should be denied
1722         assertNull(stats);
1723     }
1724 
1725     @Test
1726     @SmallTest
getImsRegistrationStats_withSavedAtoms()1727     public void getImsRegistrationStats_withSavedAtoms() throws Exception {
1728         createTestFile(START_TIME_MILLIS);
1729 
1730         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1731         mPersistAtomsStorage.incTimeMillis(DAY_IN_MILLIS);
1732         ImsRegistrationStats[] stats1 = mPersistAtomsStorage.getImsRegistrationStats(50L);
1733         mPersistAtomsStorage.incTimeMillis(100L);
1734         ImsRegistrationStats[] stats2 = mPersistAtomsStorage.getImsRegistrationStats(50L);
1735 
1736         // first set of results should equal to file contents, second should be empty, corresponding
1737         // pull timestamp should be updated and saved
1738         assertProtoArrayEqualsIgnoringOrder(
1739                 new ImsRegistrationStats[] {
1740                     mImsRegistrationStatsLte0, mImsRegistrationStatsWifi0, mImsRegistrationStatsLte1
1741                 },
1742                 stats1);
1743         assertProtoArrayEquals(new ImsRegistrationStats[0], stats2);
1744         assertEquals(
1745                 START_TIME_MILLIS + DAY_IN_MILLIS + 100L,
1746                 mPersistAtomsStorage.getAtomsProto().imsRegistrationStatsPullTimestampMillis);
1747         InOrder inOrder = inOrder(mTestFileOutputStream);
1748         assertEquals(
1749                 START_TIME_MILLIS + DAY_IN_MILLIS,
1750                 getAtomsWritten(inOrder).imsRegistrationStatsPullTimestampMillis);
1751         assertEquals(
1752                 START_TIME_MILLIS + DAY_IN_MILLIS + 100L,
1753                 getAtomsWritten(inOrder).imsRegistrationStatsPullTimestampMillis);
1754         inOrder.verifyNoMoreInteractions();
1755     }
1756 
1757     @Test
1758     @SmallTest
getImsRegistrationTerminations_tooFrequent()1759     public void getImsRegistrationTerminations_tooFrequent() throws Exception {
1760         createTestFile(START_TIME_MILLIS);
1761 
1762         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1763         mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
1764         ImsRegistrationTermination[] terminations =
1765                 mPersistAtomsStorage.getImsRegistrationTerminations(100L);
1766 
1767         // should be denied
1768         assertNull(terminations);
1769     }
1770 
1771     @Test
1772     @SmallTest
getImsRegistrationTerminations_withSavedAtoms()1773     public void getImsRegistrationTerminations_withSavedAtoms() throws Exception {
1774         createTestFile(START_TIME_MILLIS);
1775 
1776         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1777         mPersistAtomsStorage.incTimeMillis(100L);
1778         ImsRegistrationTermination[] terminations1 =
1779                 mPersistAtomsStorage.getImsRegistrationTerminations(50L);
1780         mPersistAtomsStorage.incTimeMillis(100L);
1781         ImsRegistrationTermination[] terminations2 =
1782                 mPersistAtomsStorage.getImsRegistrationTerminations(50L);
1783 
1784         // first set of results should equal to file contents, second should be empty, corresponding
1785         // pull timestamp should be updated and saved
1786         assertProtoArrayEqualsIgnoringOrder(
1787                 new ImsRegistrationTermination[] {
1788                     mImsRegistrationTerminationLte, mImsRegistrationTerminationWifi
1789                 },
1790                 terminations1);
1791         assertProtoArrayEquals(new ImsRegistrationTermination[0], terminations2);
1792         assertEquals(
1793                 START_TIME_MILLIS + 200L,
1794                 mPersistAtomsStorage.getAtomsProto().imsRegistrationTerminationPullTimestampMillis);
1795         InOrder inOrder = inOrder(mTestFileOutputStream);
1796         assertEquals(
1797                 START_TIME_MILLIS + 100L,
1798                 getAtomsWritten(inOrder).imsRegistrationTerminationPullTimestampMillis);
1799         assertEquals(
1800                 START_TIME_MILLIS + 200L,
1801                 getAtomsWritten(inOrder).imsRegistrationTerminationPullTimestampMillis);
1802         inOrder.verifyNoMoreInteractions();
1803     }
1804 
1805     @Test
1806     @SmallTest
addDataCallSession_newEntry()1807     public void addDataCallSession_newEntry()
1808             throws Exception {
1809         createEmptyTestFile();
1810         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1811 
1812         mPersistAtomsStorage.addDataCallSession(mDataCallSession0);
1813         mPersistAtomsStorage.addDataCallSession(mDataCallSession1);
1814         mPersistAtomsStorage.incTimeMillis(100L);
1815 
1816         // there should be 2 data calls
1817         verifyCurrentStateSavedToFileOnce();
1818         DataCallSession[] dataCalls = mPersistAtomsStorage.getDataCallSessions(0L);
1819         assertProtoArrayEqualsIgnoringOrder(
1820                 new DataCallSession[]{mDataCallSession0, mDataCallSession1},
1821                 dataCalls);
1822         for (DataCallSession dataCallSession : dataCalls) {
1823             if (dataCallSession.dimension == mDataCallSession0.dimension) {
1824                 assertArrayEquals(new int[]{1, 2, 3}, dataCallSession.handoverFailureCauses);
1825                 assertArrayEquals(new int[]{6, 5, 5}, dataCallSession.handoverFailureRat);
1826             }
1827         }
1828     }
1829 
1830     @Test
1831     @SmallTest
addImsRegistrationFeatureTagStats_emptyProto()1832     public void addImsRegistrationFeatureTagStats_emptyProto() throws Exception {
1833         createEmptyTestFile();
1834 
1835         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1836         mPersistAtomsStorage
1837                 .addImsRegistrationFeatureTagStats(mImsRegistrationFeatureTagStats1Proto);
1838         mPersistAtomsStorage.incTimeMillis(100L);
1839 
1840         verifyCurrentStateSavedToFileOnce();
1841 
1842         ImsRegistrationFeatureTagStats[] expected =
1843                 new ImsRegistrationFeatureTagStats[] {
1844                         mImsRegistrationFeatureTagStats1Proto
1845                 };
1846         assertProtoArrayEquals(
1847                 expected, mPersistAtomsStorage.getImsRegistrationFeatureTagStats(0L));
1848     }
1849 
1850     @Test
1851     @SmallTest
addDataCallSession_existingEntry()1852     public void addDataCallSession_existingEntry()
1853             throws Exception {
1854         createEmptyTestFile();
1855         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1856         DataCallSession newDataCallSession0 = copyOf(mDataCallSession0);
1857         newDataCallSession0.ongoing = false;
1858         newDataCallSession0.ratAtEnd = TelephonyManager.NETWORK_TYPE_LTE;
1859         newDataCallSession0.durationMinutes = 10;
1860         newDataCallSession0.ratSwitchCount = 5;
1861         newDataCallSession0.handoverFailureCauses = new int[]{4};
1862         newDataCallSession0.handoverFailureRat = new int[]{4};
1863         DataCallSession totalDataCallSession0 = copyOf(newDataCallSession0);
1864         totalDataCallSession0.durationMinutes =
1865                 mDataCallSession0.durationMinutes + newDataCallSession0.durationMinutes;
1866         totalDataCallSession0.ratSwitchCount =
1867                 mDataCallSession0.ratSwitchCount + newDataCallSession0.ratSwitchCount;
1868         totalDataCallSession0.handoverFailureCauses = new int[]{1, 2, 3, 4};
1869         totalDataCallSession0.handoverFailureRat = new int[]{6, 5, 5, 4};
1870 
1871         mPersistAtomsStorage.addDataCallSession(mDataCallSession0);
1872         mPersistAtomsStorage.addDataCallSession(newDataCallSession0);
1873         mPersistAtomsStorage.incTimeMillis(100L);
1874 
1875         // there should be 1 data call
1876         verifyCurrentStateSavedToFileOnce();
1877         DataCallSession[] dataCalls = mPersistAtomsStorage.getDataCallSessions(0L);
1878         assertProtoArrayEqualsIgnoringOrder(
1879                 new DataCallSession[]{totalDataCallSession0}, dataCalls);
1880     }
1881 
1882     @Test
1883     @SmallTest
addImsRegistrationFeatureTagStats_withExistingEntries()1884     public void addImsRegistrationFeatureTagStats_withExistingEntries() throws Exception {
1885         createEmptyTestFile();
1886 
1887         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1888         mPersistAtomsStorage
1889                 .addImsRegistrationFeatureTagStats(mImsRegistrationFeatureTagStats1Proto);
1890         mPersistAtomsStorage.incTimeMillis(100L);
1891         mPersistAtomsStorage
1892                 .addImsRegistrationFeatureTagStats(mImsRegistrationFeatureTagStats2Proto);
1893         mPersistAtomsStorage.incTimeMillis(100L);
1894 
1895         verifyCurrentStateSavedToFileOnce();
1896 
1897         ImsRegistrationFeatureTagStats[] expected =
1898                 new ImsRegistrationFeatureTagStats[] {
1899                         mImsRegistrationFeatureTagStats1Proto,
1900                         mImsRegistrationFeatureTagStats2Proto
1901                 };
1902         // 2 atoms stored on initially and when try to add 2 same atoms, should be increased.
1903         assertProtoArrayEqualsIgnoringOrder(
1904                 expected, mPersistAtomsStorage.getImsRegistrationFeatureTagStats(0L));
1905     }
1906 
1907     @Test
1908     @SmallTest
addImsRegistrationFeatureTagStats_tooManyEntries()1909     public void addImsRegistrationFeatureTagStats_tooManyEntries() throws Exception {
1910         createEmptyTestFile();
1911 
1912         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1913 
1914         int maxCount = 10;
1915         for (int i = 0; i < maxCount; i++) {
1916             mPersistAtomsStorage
1917                     .addImsRegistrationFeatureTagStats(
1918                             copyOf(mImsRegistrationFeatureTagStats1Proto));
1919             mPersistAtomsStorage.incTimeMillis(100L);
1920         }
1921 
1922         mPersistAtomsStorage
1923                 .addImsRegistrationFeatureTagStats(copyOf(mImsRegistrationFeatureTagStats2Proto));
1924 
1925         verifyCurrentStateSavedToFileOnce();
1926 
1927         ImsRegistrationFeatureTagStats[] result =
1928                 mPersistAtomsStorage.getImsRegistrationFeatureTagStats(0L);
1929 
1930         // tried store 26 statses, but only 2 statses stored
1931         // total time 3600L * maxCount
1932         assertHasStatsCountTime(result, mImsRegistrationFeatureTagStats1Proto, 1,
1933                 maxCount * 3600L);
1934         // total time 3600L * 1
1935         assertHasStatsCountTime(result, mImsRegistrationFeatureTagStats2Proto, 1,
1936                 1 * 3600L);
1937     }
1938 
1939     @Test
1940     @SmallTest
getImsRegistrationFeatureTagStats_tooFrequent()1941     public void getImsRegistrationFeatureTagStats_tooFrequent() throws Exception {
1942         createTestFile(START_TIME_MILLIS);
1943 
1944         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1945         mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
1946         ImsRegistrationFeatureTagStats[] result =
1947                 mPersistAtomsStorage.getImsRegistrationFeatureTagStats(100L);
1948 
1949         // should be denied
1950         assertNull(result);
1951     }
1952 
1953     @Test
1954     @SmallTest
getImsRegistrationFeatureTagStats_withSavedAtoms()1955     public void getImsRegistrationFeatureTagStats_withSavedAtoms() throws Exception {
1956         createTestFile(START_TIME_MILLIS);
1957 
1958         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1959         mPersistAtomsStorage.incTimeMillis(100L);
1960         ImsRegistrationFeatureTagStats[] statses1 =
1961                 mPersistAtomsStorage.getImsRegistrationFeatureTagStats(50L);
1962         mPersistAtomsStorage.incTimeMillis(100L);
1963         ImsRegistrationFeatureTagStats[] statses2 =
1964                 mPersistAtomsStorage.getImsRegistrationFeatureTagStats(50L);
1965 
1966         // first results of get should have two atoms, second should be empty
1967         // pull timestamp should be updated and saved
1968         assertProtoArrayEqualsIgnoringOrder(mImsRegistrationFeatureTagStatses, statses1);
1969         assertProtoArrayEquals(new ImsRegistrationFeatureTagStats[0], statses2);
1970         assertEquals(
1971                 START_TIME_MILLIS + 200L,
1972                 mPersistAtomsStorage.getAtomsProto()
1973                         .imsRegistrationFeatureTagStatsPullTimestampMillis);
1974         InOrder inOrder = inOrder(mTestFileOutputStream);
1975         assertEquals(
1976                 START_TIME_MILLIS + 100L,
1977                 getAtomsWritten(inOrder).imsRegistrationFeatureTagStatsPullTimestampMillis);
1978         assertEquals(
1979                 START_TIME_MILLIS + 200L,
1980                 getAtomsWritten(inOrder).imsRegistrationFeatureTagStatsPullTimestampMillis);
1981         inOrder.verifyNoMoreInteractions();
1982     }
1983 
1984     @Test
1985     @SmallTest
addRcsClientProvisioningStats_emptyProto()1986     public void addRcsClientProvisioningStats_emptyProto() throws Exception {
1987         createEmptyTestFile();
1988 
1989         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
1990         mPersistAtomsStorage
1991                 .addRcsClientProvisioningStats(mRcsClientProvisioningStats1Proto);
1992         mPersistAtomsStorage.incTimeMillis(100L);
1993         mPersistAtomsStorage
1994                 .addRcsClientProvisioningStats(mRcsClientProvisioningStats2Proto);
1995         mPersistAtomsStorage.incTimeMillis(100L);
1996 
1997         verifyCurrentStateSavedToFileOnce();
1998 
1999         RcsClientProvisioningStats[] expected =
2000                 new RcsClientProvisioningStats[] {
2001                         mRcsClientProvisioningStats1Proto,
2002                         mRcsClientProvisioningStats2Proto
2003                 };
2004 
2005         assertProtoArrayEqualsIgnoringOrder(
2006                 expected, mPersistAtomsStorage.getRcsClientProvisioningStats(0L));
2007     }
2008 
2009     @Test
2010     @SmallTest
addRcsClientProvisioningStats_tooManyEntries()2011     public void addRcsClientProvisioningStats_tooManyEntries() throws Exception {
2012         createEmptyTestFile();
2013 
2014         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2015 
2016         // store 11 same atoms, but only 1 atoms stored with count 11
2017         for (int i = 0; i < 11; i++) {
2018             mPersistAtomsStorage
2019                     .addRcsClientProvisioningStats(mRcsClientProvisioningStats1Proto);
2020             mPersistAtomsStorage.incTimeMillis(100L);
2021         }
2022         // store 1 different atom and count 1
2023         mPersistAtomsStorage
2024                 .addRcsClientProvisioningStats(mRcsClientProvisioningStats2Proto);
2025 
2026         verifyCurrentStateSavedToFileOnce();
2027 
2028         RcsClientProvisioningStats[] result =
2029                 mPersistAtomsStorage.getRcsClientProvisioningStats(0L);
2030 
2031         // first atom has count 11, the other has 1
2032         assertHasStatsAndCount(result, mRcsClientProvisioningStats1Proto, 11);
2033         assertHasStatsAndCount(result, mRcsClientProvisioningStats2Proto, 1);
2034     }
2035 
2036     @Test
2037     @SmallTest
getRcsClientProvisioningStats_tooFrequent()2038     public void getRcsClientProvisioningStats_tooFrequent() throws Exception {
2039         createTestFile(START_TIME_MILLIS);
2040 
2041         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2042         mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
2043         RcsClientProvisioningStats[] result =
2044                 mPersistAtomsStorage.getRcsClientProvisioningStats(100L);
2045 
2046         // should be denied
2047         assertNull(result);
2048     }
2049 
2050     @Test
2051     @SmallTest
getRcsClientProvisioningStats_withSavedAtoms()2052     public void getRcsClientProvisioningStats_withSavedAtoms() throws Exception {
2053         createTestFile(START_TIME_MILLIS);
2054 
2055         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2056         mPersistAtomsStorage.incTimeMillis(100L);
2057         RcsClientProvisioningStats[] statses1 =
2058                 mPersistAtomsStorage.getRcsClientProvisioningStats(50L);
2059         mPersistAtomsStorage.incTimeMillis(100L);
2060         RcsClientProvisioningStats[] statses2 =
2061                 mPersistAtomsStorage.getRcsClientProvisioningStats(50L);
2062 
2063         // first results of get should have two atoms, second should be empty
2064         // pull timestamp should be updated and saved
2065         assertProtoArrayEqualsIgnoringOrder(mRcsClientProvisioningStatses, statses1);
2066         assertProtoArrayEquals(new RcsClientProvisioningStats[0], statses2);
2067         assertEquals(
2068                 START_TIME_MILLIS + 200L,
2069                 mPersistAtomsStorage.getAtomsProto()
2070                         .rcsClientProvisioningStatsPullTimestampMillis);
2071         InOrder inOrder = inOrder(mTestFileOutputStream);
2072         assertEquals(
2073                 START_TIME_MILLIS + 100L,
2074                 getAtomsWritten(inOrder).rcsClientProvisioningStatsPullTimestampMillis);
2075         assertEquals(
2076                 START_TIME_MILLIS + 200L,
2077                 getAtomsWritten(inOrder).rcsClientProvisioningStatsPullTimestampMillis);
2078         inOrder.verifyNoMoreInteractions();
2079     }
2080 
2081     @Test
2082     @SmallTest
addRcsAcsProvisioningStats_emptyProto()2083     public void addRcsAcsProvisioningStats_emptyProto() throws Exception {
2084         createEmptyTestFile();
2085 
2086         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2087         mPersistAtomsStorage
2088                 .addRcsAcsProvisioningStats(mRcsAcsProvisioningStats1Proto);
2089         mPersistAtomsStorage.incTimeMillis(100L);
2090         mPersistAtomsStorage
2091                 .addRcsAcsProvisioningStats(mRcsAcsProvisioningStats2Proto);
2092         mPersistAtomsStorage.incTimeMillis(100L);
2093 
2094         verifyCurrentStateSavedToFileOnce();
2095 
2096         RcsAcsProvisioningStats[] expected =
2097                 new RcsAcsProvisioningStats[] {
2098                         mRcsAcsProvisioningStats1Proto,
2099                         mRcsAcsProvisioningStats2Proto
2100                 };
2101 
2102         assertProtoArrayEqualsIgnoringOrder(
2103                 expected, mPersistAtomsStorage.getRcsAcsProvisioningStats(0L));
2104     }
2105 
2106     @Test
2107     @SmallTest
addRcsAcsProvisioningStats_updateExistingEntries()2108     public void addRcsAcsProvisioningStats_updateExistingEntries() throws Exception {
2109         final int maxCount = 5;
2110         final long duration = START_TIME_MILLIS;
2111         createEmptyTestFile();
2112 
2113         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2114 
2115         // store 5 same atoms (1Proto), but only 1 atoms stored with count 5, total time 2000L * 5
2116         // store 5 same atoms (2Proto), but only 1 atoms stored with count 5, total time 2000L * 5
2117 
2118         for (int i = 0; i < maxCount; i++) {
2119             mPersistAtomsStorage
2120                     .addRcsAcsProvisioningStats(copyOf(mRcsAcsProvisioningStats1Proto));
2121             mPersistAtomsStorage.incTimeMillis(100L);
2122             mPersistAtomsStorage
2123                     .addRcsAcsProvisioningStats(copyOf(mRcsAcsProvisioningStats2Proto));
2124             mPersistAtomsStorage.incTimeMillis(100L);
2125         }
2126         // add one more atoms (2Proto), count 6, total time 2000L * 6
2127         mPersistAtomsStorage
2128                 .addRcsAcsProvisioningStats(copyOf(mRcsAcsProvisioningStats2Proto));
2129         mPersistAtomsStorage.incTimeMillis(100L);
2130 
2131         verifyCurrentStateSavedToFileOnce();
2132 
2133         RcsAcsProvisioningStats[] result =
2134                 mPersistAtomsStorage.getRcsAcsProvisioningStats(0L);
2135 
2136         // atom (1Proto) : count = 5, time = 2000L * 5
2137         assertHasStatsAndCountDuration(
2138                 result, mRcsAcsProvisioningStats1Proto, 5, duration * maxCount);
2139         // atom (2Proto) : count = 6, time = 2000L * 6
2140         assertHasStatsAndCountDuration(
2141                 result, mRcsAcsProvisioningStats2Proto, 6, duration * (maxCount + 1));
2142     }
2143 
2144     @Test
2145     @SmallTest
getRcsAcsProvisioningStats_tooFrequent()2146     public void getRcsAcsProvisioningStats_tooFrequent() throws Exception {
2147         createTestFile(START_TIME_MILLIS);
2148 
2149         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2150         mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
2151         RcsAcsProvisioningStats[] result =
2152                 mPersistAtomsStorage.getRcsAcsProvisioningStats(100L);
2153 
2154         // should be denied
2155         assertNull(result);
2156     }
2157 
2158     @Test
2159     @SmallTest
getRcsAcstProvisioningStats_withSavedAtoms()2160     public void getRcsAcstProvisioningStats_withSavedAtoms() throws Exception {
2161         createTestFile(START_TIME_MILLIS);
2162 
2163         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2164         mPersistAtomsStorage.incTimeMillis(DAY_IN_MILLIS);
2165         RcsAcsProvisioningStats[] statses1 =
2166                 mPersistAtomsStorage.getRcsAcsProvisioningStats(DAY_IN_MILLIS - HOUR_IN_MILLIS);
2167         mPersistAtomsStorage.incTimeMillis(DAY_IN_MILLIS);
2168         RcsAcsProvisioningStats[] statses2 =
2169                 mPersistAtomsStorage.getRcsAcsProvisioningStats(DAY_IN_MILLIS - HOUR_IN_MILLIS);
2170 
2171         // first results of get should have two atoms, second should be empty
2172         // pull timestamp should be updated and saved
2173         assertProtoArrayEqualsIgnoringOrder(mRcsAcsProvisioningStatses, statses1);
2174         assertProtoArrayEquals(new RcsAcsProvisioningStats[0], statses2);
2175         assertEquals(
2176                 START_TIME_MILLIS + 2 * DAY_IN_MILLIS,
2177                 mPersistAtomsStorage.getAtomsProto()
2178                         .rcsAcsProvisioningStatsPullTimestampMillis);
2179         InOrder inOrder = inOrder(mTestFileOutputStream);
2180         assertEquals(
2181                 START_TIME_MILLIS + DAY_IN_MILLIS,
2182                 getAtomsWritten(inOrder).rcsAcsProvisioningStatsPullTimestampMillis);
2183         assertEquals(
2184                 START_TIME_MILLIS + 2 * DAY_IN_MILLIS,
2185                 getAtomsWritten(inOrder).rcsAcsProvisioningStatsPullTimestampMillis);
2186         inOrder.verifyNoMoreInteractions();
2187     }
2188 
2189     @Test
2190     @SmallTest
addImsRegistrationServiceDescStats_emptyProto()2191     public void addImsRegistrationServiceDescStats_emptyProto() throws Exception {
2192         createEmptyTestFile();
2193         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2194         mPersistAtomsStorage.addImsRegistrationServiceDescStats(mImsRegistrationServiceIm);
2195         mPersistAtomsStorage.incTimeMillis(100L);
2196 
2197         // service state and service switch should be added successfully
2198         verifyCurrentStateSavedToFileOnce();
2199         ImsRegistrationServiceDescStats[] outputs =
2200             mPersistAtomsStorage.getImsRegistrationServiceDescStats(0L);
2201         assertProtoArrayEquals(
2202                 new ImsRegistrationServiceDescStats[] {mImsRegistrationServiceIm}, outputs);
2203     }
2204 
2205     @Test
2206     @SmallTest
addImsRegistrationServiceDescStats_withExistingEntries()2207     public void addImsRegistrationServiceDescStats_withExistingEntries() throws Exception {
2208         createEmptyTestFile();
2209         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2210         mPersistAtomsStorage.addImsRegistrationServiceDescStats(mImsRegistrationServiceIm);
2211 
2212         mPersistAtomsStorage.addImsRegistrationServiceDescStats(mImsRegistrationServiceFt);
2213         mPersistAtomsStorage.incTimeMillis(100L);
2214 
2215         // service state and service switch should be added successfully
2216         verifyCurrentStateSavedToFileOnce();
2217         ImsRegistrationServiceDescStats[] output =
2218             mPersistAtomsStorage.getImsRegistrationServiceDescStats(0L);
2219         assertProtoArrayEqualsIgnoringOrder(
2220                 new ImsRegistrationServiceDescStats[] {
2221                     mImsRegistrationServiceIm,
2222                     mImsRegistrationServiceFt
2223                 },
2224                 output);
2225     }
2226 
2227     @Test
2228     @SmallTest
addImsRegistrationServiceDescStats_tooManyServiceDesc()2229     public void addImsRegistrationServiceDescStats_tooManyServiceDesc() throws Exception {
2230         createEmptyTestFile();
2231         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2232 
2233         Queue<ImsRegistrationServiceDescStats> expectedOutput = new LinkedList<>();
2234         // Add 101 registration terminations
2235         for (int i = 0; i < 26 + 1; i++) {
2236             ImsRegistrationServiceDescStats stats = copyOf(mImsRegistrationServiceIm);
2237             stats.registrationTech = i;
2238             expectedOutput.add(stats);
2239             mPersistAtomsStorage.addImsRegistrationServiceDescStats(stats);
2240             mPersistAtomsStorage.incTimeMillis(100L);
2241         }
2242         mPersistAtomsStorage.incTimeMillis(100L);
2243 
2244         // The least recent (the first) registration termination should be evicted
2245         verifyCurrentStateSavedToFileOnce();
2246         ImsRegistrationServiceDescStats[] output =
2247             mPersistAtomsStorage.getImsRegistrationServiceDescStats(0L);
2248         expectedOutput.remove();
2249         assertEquals(expectedOutput.size() - 1, output.length);
2250     }
2251 
2252     @Test
2253     @SmallTest
getImsRegistrationServiceDescStats_tooFrequent()2254     public void getImsRegistrationServiceDescStats_tooFrequent() throws Exception {
2255         createTestFile(START_TIME_MILLIS);
2256 
2257         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2258         mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
2259         ImsRegistrationServiceDescStats[] output =
2260             mPersistAtomsStorage.getImsRegistrationServiceDescStats(100L);
2261 
2262         // should be denied
2263         assertNull(output);
2264     }
2265 
2266     @Test
2267     @SmallTest
getImsRegistrationServiceDescStats_withSavedAtoms()2268     public void getImsRegistrationServiceDescStats_withSavedAtoms() throws Exception {
2269         createTestFile(START_TIME_MILLIS);
2270 
2271         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2272         mPersistAtomsStorage.incTimeMillis(100L);
2273         ImsRegistrationServiceDescStats[] output1 =
2274             mPersistAtomsStorage.getImsRegistrationServiceDescStats(50L);
2275         mPersistAtomsStorage.incTimeMillis(100L);
2276         ImsRegistrationServiceDescStats[] output2 =
2277             mPersistAtomsStorage.getImsRegistrationServiceDescStats(50L);
2278 
2279         // first set of results should equal to file contents, second should be empty, corresponding
2280         // pull timestamp should be updated and saved
2281         assertProtoArrayEqualsIgnoringOrder(
2282                 new ImsRegistrationServiceDescStats[] {
2283                     mImsRegistrationServiceIm,
2284                     mImsRegistrationServiceFt
2285                 },
2286                 output1);
2287         assertProtoArrayEquals(new ImsRegistrationServiceDescStats[0], output2);
2288         assertEquals(
2289                 START_TIME_MILLIS + 200L,
2290                 mPersistAtomsStorage.getAtomsProto()
2291                     .imsRegistrationServiceDescStatsPullTimestampMillis);
2292         InOrder inOrder = inOrder(mTestFileOutputStream);
2293         assertEquals(
2294                 START_TIME_MILLIS + 100L,
2295                 getAtomsWritten(inOrder).imsRegistrationServiceDescStatsPullTimestampMillis);
2296         assertEquals(
2297                 START_TIME_MILLIS + 200L,
2298                 getAtomsWritten(inOrder).imsRegistrationServiceDescStatsPullTimestampMillis);
2299         inOrder.verifyNoMoreInteractions();
2300     }
2301 
2302     @Test
2303     @SmallTest
getImsRegistrationStats_24hNormalization()2304     public void getImsRegistrationStats_24hNormalization() throws Exception {
2305         createEmptyTestFile();
2306         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2307         mPersistAtomsStorage.addImsRegistrationStats(copyOf(mImsRegistrationStatsWifi0));
2308         mPersistAtomsStorage.incTimeMillis(DAY_IN_MILLIS / 2);
2309 
2310         ImsRegistrationStats[] serviceStates = mPersistAtomsStorage.getImsRegistrationStats(0L);
2311         mImsRegistrationStatsWifi0.registeredMillis *= 2;
2312         mImsRegistrationStatsWifi0.voiceCapableMillis *= 2;
2313         mImsRegistrationStatsWifi0.voiceAvailableMillis *= 2;
2314         mImsRegistrationStatsWifi0.smsCapableMillis *= 2;
2315         mImsRegistrationStatsWifi0.smsAvailableMillis *= 2;
2316         mImsRegistrationStatsWifi0.videoCapableMillis *= 2;
2317         mImsRegistrationStatsWifi0.videoAvailableMillis *= 2;
2318         mImsRegistrationStatsWifi0.utCapableMillis *= 2;
2319         mImsRegistrationStatsWifi0.utAvailableMillis *= 2;
2320         assertProtoArrayEqualsIgnoringOrder(
2321                 new ImsRegistrationStats[] {
2322                     mImsRegistrationStatsWifi0
2323                 },
2324                 serviceStates);
2325     }
2326 
2327     @Test
getRcsAcsProvisioningStats_24h_normalization()2328     public void getRcsAcsProvisioningStats_24h_normalization() throws Exception {
2329         // in case pulling interval is greater than a day
2330         final long stateTimer = HOUR_IN_MILLIS;
2331         final long weightFactor = 2;
2332         createTestFile(START_TIME_MILLIS);
2333         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2334         RcsAcsProvisioningStats mSubjectStats = copyOf(mRcsAcsProvisioningStats1Proto);
2335 
2336         mSubjectStats.stateTimerMillis = stateTimer;
2337         mPersistAtomsStorage.addRcsAcsProvisioningStats(mSubjectStats);
2338         mPersistAtomsStorage.incTimeMillis(DAY_IN_MILLIS * weightFactor);
2339 
2340         RcsAcsProvisioningStats[] savedStats =
2341                 mPersistAtomsStorage.getRcsAcsProvisioningStats(0L);
2342 
2343         assertEquals(
2344                 (START_TIME_MILLIS + stateTimer) / weightFactor, savedStats[0].stateTimerMillis);
2345 
2346         // in case pulling interval is smaller than a day
2347         long incTimeMillis = DAY_IN_MILLIS * 23 / 24 + 1;
2348         mSubjectStats = copyOf(mRcsAcsProvisioningStats1Proto);
2349         mSubjectStats.stateTimerMillis = stateTimer;
2350         mPersistAtomsStorage.addRcsAcsProvisioningStats(mSubjectStats);
2351         mPersistAtomsStorage.incTimeMillis(incTimeMillis);
2352         savedStats =
2353                 mPersistAtomsStorage.getRcsAcsProvisioningStats(0L);
2354 
2355 
2356         assertEquals(stateTimer, savedStats[0].stateTimerMillis);
2357     }
2358 
2359     @Test
getSipDelegateStats_24h_normalization()2360     public void getSipDelegateStats_24h_normalization() throws Exception {
2361         final long stateTimer = HOUR_IN_MILLIS;
2362         final long weightFactor = 2;
2363         createTestFile(START_TIME_MILLIS);
2364         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2365         SipDelegateStats mSubjectStats = copyOf(mSipDelegateStats1);
2366         mSubjectStats.uptimeMillis = stateTimer;
2367         mPersistAtomsStorage.addSipDelegateStats(mSubjectStats);
2368         mPersistAtomsStorage.incTimeMillis(DAY_IN_MILLIS * weightFactor);
2369         SipDelegateStats[] savedStats =
2370                 mPersistAtomsStorage.getSipDelegateStats(0L);
2371         for (SipDelegateStats stat : savedStats) {
2372             if (stat.destroyReason
2373                     == SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP) {
2374                 assertEquals(stateTimer / weightFactor, stat.uptimeMillis);
2375             }
2376         }
2377 
2378         long incTimeMillis = DAY_IN_MILLIS * 23 / 24 + 1;
2379         mSubjectStats = copyOf(mSipDelegateStats1);
2380         mSubjectStats.uptimeMillis = stateTimer;
2381         mPersistAtomsStorage.addSipDelegateStats(mSubjectStats);
2382         mPersistAtomsStorage.incTimeMillis(incTimeMillis);
2383         savedStats =
2384                 mPersistAtomsStorage.getSipDelegateStats(0L);
2385         for (SipDelegateStats stat : savedStats) {
2386             if (stat.destroyReason
2387                     == SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP) {
2388                 assertEquals(stateTimer, stat.uptimeMillis);
2389             }
2390         }
2391     }
2392 
2393     @Test
getSipTransportFeatureTagStats_24h_normalization()2394     public void getSipTransportFeatureTagStats_24h_normalization() throws Exception {
2395         final long stateTimer = HOUR_IN_MILLIS;
2396         final long weightFactor = 2;
2397         createTestFile(START_TIME_MILLIS);
2398         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2399         SipTransportFeatureTagStats mSubjectStats = copyOf(mSipTransportFeatureTagStats1);
2400         mSubjectStats.associatedMillis = stateTimer;
2401         mPersistAtomsStorage.addSipTransportFeatureTagStats(mSubjectStats);
2402         mPersistAtomsStorage.incTimeMillis(DAY_IN_MILLIS * weightFactor);
2403         SipTransportFeatureTagStats[] savedStats =
2404                 mPersistAtomsStorage.getSipTransportFeatureTagStats(0L);
2405         assertEquals((stateTimer) / weightFactor, savedStats[0].associatedMillis);
2406 
2407         long incTimeMillis = DAY_IN_MILLIS * 23 / 24 + 1;
2408         mSubjectStats = copyOf(mSipTransportFeatureTagStats1);
2409         mSubjectStats.associatedMillis = stateTimer;
2410         mPersistAtomsStorage.addSipTransportFeatureTagStats(mSubjectStats);
2411         mPersistAtomsStorage.incTimeMillis(incTimeMillis);
2412         savedStats =
2413                 mPersistAtomsStorage.getSipTransportFeatureTagStats(0L);
2414         assertEquals(stateTimer, savedStats[0].associatedMillis);
2415     }
2416 
2417     @Test
getImsRegistrationServiceDescStats_24h_normalization()2418     public void getImsRegistrationServiceDescStats_24h_normalization() throws Exception {
2419         final long stateTimer = HOUR_IN_MILLIS;
2420         final long weightFactor = 2;
2421         createTestFile(START_TIME_MILLIS);
2422         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2423         ImsRegistrationServiceDescStats mSubjectStats = copyOf(mImsRegistrationServiceIm);
2424         mSubjectStats.publishedMillis = stateTimer;
2425         mPersistAtomsStorage.addImsRegistrationServiceDescStats(mSubjectStats);
2426         mPersistAtomsStorage.incTimeMillis(DAY_IN_MILLIS * weightFactor);
2427         ImsRegistrationServiceDescStats[] savedStats =
2428                 mPersistAtomsStorage.getImsRegistrationServiceDescStats(0L);
2429         assertEquals(
2430                 (START_TIME_MILLIS + stateTimer) / weightFactor, savedStats[0].publishedMillis);
2431 
2432         long incTimeMillis = DAY_IN_MILLIS * 23 / 24 + 1;
2433         mSubjectStats = copyOf(mImsRegistrationServiceIm);
2434         mSubjectStats.publishedMillis = stateTimer;
2435         mPersistAtomsStorage.addImsRegistrationServiceDescStats(mSubjectStats);
2436         mPersistAtomsStorage.incTimeMillis(incTimeMillis);
2437         savedStats =
2438                 mPersistAtomsStorage.getImsRegistrationServiceDescStats(0L);
2439         assertEquals(stateTimer, savedStats[0].publishedMillis);
2440     }
2441 
2442     @Test
2443     @SmallTest
addImsDedicatedBearerListenerEvent_emptyProto()2444     public void addImsDedicatedBearerListenerEvent_emptyProto() throws Exception {
2445         createEmptyTestFile();
2446         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2447         mPersistAtomsStorage.addImsDedicatedBearerListenerEvent(mImsDedicatedBearerListenerEvent1);
2448         mPersistAtomsStorage.incTimeMillis(100L);
2449 
2450         // service state and service switch should be added successfully
2451         verifyCurrentStateSavedToFileOnce();
2452         ImsDedicatedBearerListenerEvent[] outputs =
2453                 mPersistAtomsStorage.getImsDedicatedBearerListenerEvent(0L);
2454         assertProtoArrayEquals(
2455                 new ImsDedicatedBearerListenerEvent[] {mImsDedicatedBearerListenerEvent1}, outputs);
2456     }
2457 
2458     @Test
2459     @SmallTest
addImsDedicatedBearerListenerEvent_withExistingEntries()2460     public void addImsDedicatedBearerListenerEvent_withExistingEntries() throws Exception {
2461         createEmptyTestFile();
2462         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2463         mPersistAtomsStorage.addImsDedicatedBearerListenerEvent(mImsDedicatedBearerListenerEvent1);
2464 
2465         mPersistAtomsStorage.addImsDedicatedBearerListenerEvent(mImsDedicatedBearerListenerEvent2);
2466         mPersistAtomsStorage.incTimeMillis(100L);
2467 
2468         // service state and service switch should be added successfully
2469         verifyCurrentStateSavedToFileOnce();
2470         ImsDedicatedBearerListenerEvent[] output =
2471                 mPersistAtomsStorage.getImsDedicatedBearerListenerEvent(0L);
2472         assertProtoArrayEqualsIgnoringOrder(
2473                 new ImsDedicatedBearerListenerEvent[] {
2474                     mImsDedicatedBearerListenerEvent1, mImsDedicatedBearerListenerEvent2}, output);
2475     }
2476 
2477     @Test
2478     @SmallTest
addImsDedicatedBearerListenerEvent_withSameProto()2479     public void addImsDedicatedBearerListenerEvent_withSameProto() throws Exception {
2480         createEmptyTestFile();
2481         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2482 
2483         mPersistAtomsStorage.addImsDedicatedBearerListenerEvent(mImsDedicatedBearerListenerEvent1);
2484         mPersistAtomsStorage.addImsDedicatedBearerListenerEvent(mImsDedicatedBearerListenerEvent1);
2485         mPersistAtomsStorage.incTimeMillis(100L);
2486 
2487         // The least recent (the first) registration termination should be evicted
2488         verifyCurrentStateSavedToFileOnce();
2489         ImsDedicatedBearerListenerEvent[] output =
2490                 mPersistAtomsStorage.getImsDedicatedBearerListenerEvent(0L);
2491         assertEquals(mImsDedicatedBearerListenerEvent1.carrierId, output[0].carrierId);
2492         assertEquals(mImsDedicatedBearerListenerEvent1.slotId, output[0].slotId);
2493         assertEquals(mImsDedicatedBearerListenerEvent1.ratAtEnd, output[0].ratAtEnd);
2494         assertEquals(mImsDedicatedBearerListenerEvent1.qci, output[0].qci);
2495         assertEquals(mImsDedicatedBearerListenerEvent1.dedicatedBearerEstablished,
2496                 output[0].dedicatedBearerEstablished);
2497         assertEquals(mImsDedicatedBearerListenerEvent1.eventCount,
2498                 output[0].eventCount);
2499     }
2500 
2501     @Test
2502     @SmallTest
addImsDedicatedBearerEvent_emptyProto()2503     public void addImsDedicatedBearerEvent_emptyProto() throws Exception {
2504         createEmptyTestFile();
2505         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2506         mPersistAtomsStorage.addImsDedicatedBearerEvent(mImsDedicatedBearerEvent1);
2507         mPersistAtomsStorage.incTimeMillis(100L);
2508 
2509         // service state and service switch should be added successfully
2510         verifyCurrentStateSavedToFileOnce();
2511         ImsDedicatedBearerEvent[] outputs =
2512             mPersistAtomsStorage.getImsDedicatedBearerEvent(0L);
2513         assertProtoArrayEquals(
2514                 new ImsDedicatedBearerEvent[] {mImsDedicatedBearerEvent1}, outputs);
2515     }
2516 
2517     @Test
2518     @SmallTest
addImsDedicatedBearerEvent_withExistingEntries()2519     public void addImsDedicatedBearerEvent_withExistingEntries() throws Exception {
2520         createEmptyTestFile();
2521         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2522         mPersistAtomsStorage.addImsDedicatedBearerEvent(mImsDedicatedBearerEvent1);
2523 
2524         mPersistAtomsStorage.addImsDedicatedBearerEvent(mImsDedicatedBearerEvent2);
2525         mPersistAtomsStorage.incTimeMillis(100L);
2526 
2527         // service state and service switch should be added successfully
2528         verifyCurrentStateSavedToFileOnce();
2529         ImsDedicatedBearerEvent[] output =
2530             mPersistAtomsStorage.getImsDedicatedBearerEvent(0L);
2531         assertProtoArrayEqualsIgnoringOrder(
2532                     new ImsDedicatedBearerEvent[] {
2533                         mImsDedicatedBearerEvent1, mImsDedicatedBearerEvent2}, output);
2534     }
2535 
2536     @Test
2537     @SmallTest
addImsDedicatedBearerEvent_withSameProto()2538     public void addImsDedicatedBearerEvent_withSameProto() throws Exception {
2539         createEmptyTestFile();
2540         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2541 
2542         mPersistAtomsStorage.addImsDedicatedBearerEvent(mImsDedicatedBearerEvent1);
2543         mPersistAtomsStorage.addImsDedicatedBearerEvent(mImsDedicatedBearerEvent1);
2544         mPersistAtomsStorage.incTimeMillis(100L);
2545 
2546         // The least recent (the first) registration termination should be evicted
2547         verifyCurrentStateSavedToFileOnce();
2548         ImsDedicatedBearerEvent[] output =
2549             mPersistAtomsStorage.getImsDedicatedBearerEvent(0L);
2550         assertEquals(mImsDedicatedBearerEvent1.carrierId, output[0].carrierId);
2551         assertEquals(mImsDedicatedBearerEvent1.slotId, output[0].slotId);
2552         assertEquals(mImsDedicatedBearerEvent1.ratAtEnd, output[0].ratAtEnd);
2553         assertEquals(mImsDedicatedBearerEvent1.qci, output[0].qci);
2554         assertEquals(mImsDedicatedBearerEvent1.localConnectionInfoReceived,
2555                 output[0].localConnectionInfoReceived);
2556         assertEquals(mImsDedicatedBearerEvent1.remoteConnectionInfoReceived,
2557                 output[0].remoteConnectionInfoReceived);
2558         assertEquals(mImsDedicatedBearerEvent1.hasListeners,
2559                 output[0].hasListeners);
2560     }
2561 
2562     @Test
2563     @SmallTest
addImsDedicatedBearerEvent_tooManyEntries()2564     public void addImsDedicatedBearerEvent_tooManyEntries() throws Exception {
2565         createEmptyTestFile();
2566 
2567         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2568 
2569         // Add 11 stats, but max is 10
2570         for (int i = 0; i < 11; i++) {
2571             mPersistAtomsStorage.addImsDedicatedBearerEvent(mImsDedicatedBearerEvent1);
2572             mPersistAtomsStorage.incTimeMillis(100L);
2573         }
2574         mPersistAtomsStorage.addImsDedicatedBearerEvent(mImsDedicatedBearerEvent2);
2575 
2576         verifyCurrentStateSavedToFileOnce();
2577         ImsDedicatedBearerEvent[] stats =
2578             mPersistAtomsStorage.getImsDedicatedBearerEvent(0L);
2579         assertHasStatsAndCount(stats, mImsDedicatedBearerEvent1, 11);
2580         assertHasStatsAndCount(stats, mImsDedicatedBearerEvent2, 1);
2581     }
2582 
2583     @Test
2584     @SmallTest
addImsDedicatedBearerEvent_updateExistingEntries()2585     public void addImsDedicatedBearerEvent_updateExistingEntries() throws Exception {
2586         createTestFile(START_TIME_MILLIS);
2587         ImsDedicatedBearerEvent newStats = copyOf(mImsDedicatedBearerEvent1);
2588         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2589 
2590         mPersistAtomsStorage.addImsDedicatedBearerEvent(copyOf(mImsDedicatedBearerEvent1));
2591         mPersistAtomsStorage.incTimeMillis(100L);
2592 
2593         // mImsDedicatedBearerEvent1's count should be doubled
2594         verifyCurrentStateSavedToFileOnce();
2595         ImsDedicatedBearerEvent[] stats =
2596             mPersistAtomsStorage.getImsDedicatedBearerEvent(0L);
2597         newStats.count *= 2;
2598         assertProtoArrayEqualsIgnoringOrder(new ImsDedicatedBearerEvent[] {
2599                 mImsDedicatedBearerEvent2, newStats}, stats);
2600     }
2601 
2602 
2603     @Test
2604     @SmallTest
addUceEventStats_emptyProto()2605     public void addUceEventStats_emptyProto() throws Exception {
2606         createEmptyTestFile();
2607         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2608         mPersistAtomsStorage.addUceEventStats(mUceEventStats1);
2609         mPersistAtomsStorage.incTimeMillis(100L);
2610 
2611         // service state and service switch should be added successfully
2612         verifyCurrentStateSavedToFileOnce();
2613         UceEventStats[] outputs = mPersistAtomsStorage.getUceEventStats(0L);
2614         assertProtoArrayEquals(
2615                 new UceEventStats[] {mUceEventStats1}, outputs);
2616     }
2617 
2618     @Test
2619     @SmallTest
addUceEventStats_withExistingEntries()2620     public void addUceEventStats_withExistingEntries() throws Exception {
2621         createEmptyTestFile();
2622         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2623         mPersistAtomsStorage.addUceEventStats(mUceEventStats1);
2624 
2625         mPersistAtomsStorage.addUceEventStats(mUceEventStats2);
2626         mPersistAtomsStorage.incTimeMillis(100L);
2627 
2628         // service state and service switch should be added successfully
2629         verifyCurrentStateSavedToFileOnce();
2630         UceEventStats[] output = mPersistAtomsStorage.getUceEventStats(0L);
2631         assertProtoArrayEqualsIgnoringOrder(
2632                 new UceEventStats[] {mUceEventStats1, mUceEventStats2}, output);
2633     }
2634 
2635     @Test
2636     @SmallTest
addUceEventStats_withSameProto()2637     public void addUceEventStats_withSameProto() throws Exception {
2638         createEmptyTestFile();
2639         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2640 
2641         mPersistAtomsStorage.addUceEventStats(mUceEventStats1);
2642         mPersistAtomsStorage.addUceEventStats(mUceEventStats1);
2643         mPersistAtomsStorage.incTimeMillis(100L);
2644 
2645         // The least recent (the first) registration termination should be evicted
2646         verifyCurrentStateSavedToFileOnce();
2647         UceEventStats[] output = mPersistAtomsStorage.getUceEventStats(0L);
2648         assertEquals(mUceEventStats1.carrierId, output[0].carrierId);
2649         assertEquals(mUceEventStats1.slotId, output[0].slotId);
2650         assertEquals(mUceEventStats1.type, output[0].type);
2651         assertEquals(mUceEventStats1.successful, output[0].successful);
2652         assertEquals(mUceEventStats1.commandCode, output[0].commandCode);
2653         assertEquals(mUceEventStats1.networkResponse, output[0].networkResponse);
2654         assertEquals(2, output[0].count);
2655     }
2656 
2657     @Test
2658     @SmallTest
addPresenceNotifyEvent_withSameProto()2659     public void addPresenceNotifyEvent_withSameProto() throws Exception {
2660         createEmptyTestFile();
2661         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2662 
2663         PresenceNotifyEvent event1 = new PresenceNotifyEvent();
2664         event1.carrierId = CARRIER1_ID;
2665         event1.slotId = SLOT_ID1;
2666         event1.reason = 1;
2667         event1.contentBodyReceived = true;
2668         event1.rcsCapsCount = 1;
2669         event1.mmtelCapsCount = 1;
2670         event1.noCapsCount = 0;
2671         event1.count = 1;
2672 
2673         PresenceNotifyEvent event2 = copyOf(event1);
2674         event2.rcsCapsCount = 0;
2675 
2676         mPersistAtomsStorage.addPresenceNotifyEvent(event1);
2677         mPersistAtomsStorage.addPresenceNotifyEvent(event2);
2678 
2679         mPersistAtomsStorage.incTimeMillis(100L);
2680 
2681         // The least recent (the first) registration termination should be evicted
2682         verifyCurrentStateSavedToFileOnce();
2683         PresenceNotifyEvent[] output = mPersistAtomsStorage.getPresenceNotifyEvent(0L);
2684 
2685         assertEquals(event1.carrierId, output[0].carrierId);
2686         assertEquals(event1.slotId, output[0].slotId);
2687         assertEquals(event1.contentBodyReceived, output[0].contentBodyReceived);
2688         assertEquals(1, output[0].rcsCapsCount);
2689         assertEquals(2, output[0].mmtelCapsCount);
2690         assertEquals(2, output[0].count);
2691 
2692     }
2693     @Test
2694     @SmallTest
addPresenceNotifyEvent_withExistingEntries()2695     public void addPresenceNotifyEvent_withExistingEntries() throws Exception {
2696         createEmptyTestFile();
2697         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2698         mPersistAtomsStorage.addPresenceNotifyEvent(mPresenceNotifyEvent1);
2699         mPersistAtomsStorage.addPresenceNotifyEvent(mPresenceNotifyEvent2);
2700         mPersistAtomsStorage.incTimeMillis(100L);
2701 
2702         // service state and service switch should be added successfully
2703         verifyCurrentStateSavedToFileOnce();
2704         PresenceNotifyEvent[] output = mPersistAtomsStorage.getPresenceNotifyEvent(0L);
2705         assertProtoArrayEqualsIgnoringOrder(
2706                 new PresenceNotifyEvent[] {mPresenceNotifyEvent1, mPresenceNotifyEvent2}, output);
2707     }
2708 
2709     @Test
2710     @SmallTest
getPresenceNotifyEvent_tooFrequent()2711     public void getPresenceNotifyEvent_tooFrequent() throws Exception {
2712         createTestFile(START_TIME_MILLIS);
2713 
2714         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2715         mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
2716         PresenceNotifyEvent[] output = mPersistAtomsStorage.getPresenceNotifyEvent(100L);
2717 
2718         // should be denied
2719         assertNull(output);
2720     }
2721 
2722     @Test
2723     @SmallTest
getPresenceNotifyEvent_withSavedAtoms()2724     public void getPresenceNotifyEvent_withSavedAtoms() throws Exception {
2725         createTestFile(START_TIME_MILLIS);
2726 
2727         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2728         mPersistAtomsStorage.incTimeMillis(100L);
2729         PresenceNotifyEvent[] output1 = mPersistAtomsStorage.getPresenceNotifyEvent(50L);
2730         mPersistAtomsStorage.incTimeMillis(100L);
2731         PresenceNotifyEvent[] output2 = mPersistAtomsStorage.getPresenceNotifyEvent(50L);
2732 
2733         // first set of results should equal to file contents, second should be empty, corresponding
2734         // pull timestamp should be updated and saved
2735         assertProtoArrayEqualsIgnoringOrder(
2736                 new PresenceNotifyEvent[] {mPresenceNotifyEvent1, mPresenceNotifyEvent2}, output1);
2737         assertProtoArrayEquals(new PresenceNotifyEvent[0], output2);
2738         assertEquals(
2739                 START_TIME_MILLIS + 200L,
2740                 mPersistAtomsStorage.getAtomsProto().presenceNotifyEventPullTimestampMillis);
2741         InOrder inOrder = inOrder(mTestFileOutputStream);
2742         assertEquals(
2743                 START_TIME_MILLIS + 100L,
2744                 getAtomsWritten(inOrder).presenceNotifyEventPullTimestampMillis);
2745         assertEquals(
2746                 START_TIME_MILLIS + 200L,
2747                 getAtomsWritten(inOrder).presenceNotifyEventPullTimestampMillis);
2748         inOrder.verifyNoMoreInteractions();
2749     }
2750 
2751     @Test
2752     @SmallTest
addSipTransportFeatureTag_emptyProto()2753     public void addSipTransportFeatureTag_emptyProto() throws Exception {
2754         // verify add atom into new file
2755         createEmptyTestFile();
2756         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2757         mPersistAtomsStorage.addSipTransportFeatureTagStats(mSipTransportFeatureTagStats1);
2758         mPersistAtomsStorage.incTimeMillis(100L);
2759         verifyCurrentStateSavedToFileOnce();
2760 
2761         SipTransportFeatureTagStats[] outputs =
2762                 mPersistAtomsStorage.getSipTransportFeatureTagStats(0L);
2763         assertProtoArrayEquals(
2764                 new SipTransportFeatureTagStats[] {mSipTransportFeatureTagStats1}, outputs);
2765     }
2766 
2767     @Test
2768     @SmallTest
addSipTransportFeatureTagStats_withExistingEntries()2769     public void addSipTransportFeatureTagStats_withExistingEntries() throws Exception {
2770         // verify add atom on existing atom already stored
2771         createEmptyTestFile();
2772 
2773         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2774         //Add two different SipTransportFeatureTagStats.
2775         mPersistAtomsStorage.addSipTransportFeatureTagStats(mSipTransportFeatureTagStats1);
2776         mPersistAtomsStorage.addSipTransportFeatureTagStats(mSipTransportFeatureTagStats2);
2777         mPersistAtomsStorage.incTimeMillis(100L);
2778 
2779         // SipTransportFeatureTagStats should be added successfully
2780         verifyCurrentStateSavedToFileOnce();
2781         SipTransportFeatureTagStats[] outputs =
2782                 mPersistAtomsStorage.getSipTransportFeatureTagStats(0L);
2783 
2784         assertProtoArrayEqualsIgnoringOrder(new SipTransportFeatureTagStats[]
2785                 {mSipTransportFeatureTagStats1, mSipTransportFeatureTagStats2}, outputs);
2786     }
2787 
2788     @Test
2789     @SmallTest
addSipTransportFeatureTagStats_tooManyEntries()2790     public void addSipTransportFeatureTagStats_tooManyEntries() throws Exception {
2791         // verify add atom excess MAX count (100)
2792         createEmptyTestFile();
2793 
2794         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2795 
2796         // Try to add 26 stats where MAX is 25
2797         int max = 26;
2798         SipTransportFeatureTagStats[] overMaxSipTransportFeatureTagStats =
2799                 new SipTransportFeatureTagStats[max];
2800 
2801         for (int i = 0; i < max; i++) {
2802             overMaxSipTransportFeatureTagStats[i] = copyOf(mSipTransportFeatureTagStats1);
2803             overMaxSipTransportFeatureTagStats[i].sipTransportDeniedReason = i;
2804             mPersistAtomsStorage
2805                     .addSipTransportFeatureTagStats(overMaxSipTransportFeatureTagStats[i]);
2806             mPersistAtomsStorage.incTimeMillis(100L);
2807         }
2808 
2809         mPersistAtomsStorage
2810                 .addSipTransportFeatureTagStats(mSipTransportFeatureTagStats2);
2811         verifyCurrentStateSavedToFileOnce();
2812 
2813         SipTransportFeatureTagStats[] outputs =
2814                 mPersistAtomsStorage.getSipTransportFeatureTagStats(0L);
2815 
2816         // The last added SipTransportFeatureTagStat remains
2817         // and two old stats should be removed
2818         assertHasStats(outputs, overMaxSipTransportFeatureTagStats, max - 2);
2819         assertHasStats(outputs, mSipTransportFeatureTagStats2, 1);
2820     }
2821 
2822     @Test
2823     @SmallTest
addSipTransportFeatureTagStats_updateExistingEntries()2824     public void addSipTransportFeatureTagStats_updateExistingEntries() throws Exception {
2825         // verify count
2826         createTestFile(START_TIME_MILLIS);
2827 
2828         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2829         mPersistAtomsStorage.addSipTransportFeatureTagStats(copyOf(mSipTransportFeatureTagStats1));
2830         mPersistAtomsStorage.incTimeMillis(100L);
2831         verifyCurrentStateSavedToFileOnce();
2832 
2833         // SipTransportFeatureTag's durations should be doubled
2834         SipTransportFeatureTagStats newSipTransportFeatureTagStats1 =
2835                 copyOf(mSipTransportFeatureTagStats1);
2836         newSipTransportFeatureTagStats1.associatedMillis *= 2;
2837 
2838         SipTransportFeatureTagStats[] outputs =
2839                 mPersistAtomsStorage.getSipTransportFeatureTagStats(0L);
2840 
2841         assertProtoArrayEqualsIgnoringOrder(
2842                 new SipTransportFeatureTagStats[] {
2843                         newSipTransportFeatureTagStats1,
2844                         mSipTransportFeatureTagStats2
2845                 }, outputs);
2846     }
2847 
2848     @Test
2849     @SmallTest
getSipTransportFeatureTagStats_tooFrequent()2850     public void getSipTransportFeatureTagStats_tooFrequent() throws Exception {
2851         // verify get frequently
2852         createTestFile(START_TIME_MILLIS);
2853 
2854         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2855         mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
2856 
2857         SipTransportFeatureTagStats[] outputs =
2858                 mPersistAtomsStorage.getSipTransportFeatureTagStats(100L);
2859 
2860         // should be denied
2861         assertNull(outputs);
2862     }
2863 
2864     @Test
2865     @SmallTest
getSipTransportFeatureTagStats_withSavedAtoms()2866     public void getSipTransportFeatureTagStats_withSavedAtoms() throws Exception {
2867         // verify last get time after get atoms
2868         createTestFile(START_TIME_MILLIS);
2869 
2870         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2871         mPersistAtomsStorage.incTimeMillis(100L);
2872 
2873         SipTransportFeatureTagStats[] output1 =
2874                 mPersistAtomsStorage.getSipTransportFeatureTagStats(50L);
2875         mPersistAtomsStorage.incTimeMillis(100L);
2876         SipTransportFeatureTagStats[] output2 =
2877                 mPersistAtomsStorage.getSipTransportFeatureTagStats(50L);
2878 
2879         // first set of results should equal to file contents, second should be empty, corresponding
2880         // pull timestamp should be updated and saved
2881         assertProtoArrayEqualsIgnoringOrder(
2882                 new SipTransportFeatureTagStats[] {
2883                         mSipTransportFeatureTagStats1,
2884                         mSipTransportFeatureTagStats2
2885                 }, output1);
2886         assertProtoArrayEquals(new SipTransportFeatureTagStats[0], output2);
2887         assertEquals(START_TIME_MILLIS + 200L,
2888                 mPersistAtomsStorage.getAtomsProto()
2889                         .sipTransportFeatureTagStatsPullTimestampMillis);
2890 
2891         InOrder inOrder = inOrder(mTestFileOutputStream);
2892         assertEquals(START_TIME_MILLIS + 100L,
2893                 getAtomsWritten(inOrder).sipTransportFeatureTagStatsPullTimestampMillis);
2894         assertEquals(START_TIME_MILLIS + 200L,
2895                 getAtomsWritten(inOrder).sipTransportFeatureTagStatsPullTimestampMillis);
2896         inOrder.verifyNoMoreInteractions();
2897     }
2898 
2899     @Test
2900     @SmallTest
addSipDelegateStats_emptyProto()2901     public void addSipDelegateStats_emptyProto() throws Exception {
2902         // verify add atom into new file
2903         createEmptyTestFile();
2904 
2905         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2906         mPersistAtomsStorage.addSipDelegateStats(mSipDelegateStats1);
2907         mPersistAtomsStorage.incTimeMillis(100L);
2908         verifyCurrentStateSavedToFileOnce();
2909 
2910         SipDelegateStats[] outputs = mPersistAtomsStorage.getSipDelegateStats(0L);
2911         assertProtoArrayEquals(new SipDelegateStats[] {mSipDelegateStats1}, outputs);
2912     }
2913 
2914     @Test
2915     @SmallTest
addSipDelegateStats_withExistingEntries()2916     public void addSipDelegateStats_withExistingEntries() throws Exception {
2917         // verify add atom on existing atom already stored
2918         createEmptyTestFile();
2919 
2920         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2921         mPersistAtomsStorage.addSipDelegateStats(copyOf(mSipDelegateStats1));
2922         mPersistAtomsStorage.addSipDelegateStats(copyOf(mSipDelegateStats2));
2923         mPersistAtomsStorage.addSipDelegateStats(copyOf(mSipDelegateStats3));
2924         mPersistAtomsStorage.incTimeMillis(100L);
2925         // Three SipDelegateStats should be added successfully
2926         verifyCurrentStateSavedToFileOnce();
2927 
2928         SipDelegateStats[] outputs =
2929                 mPersistAtomsStorage.getSipDelegateStats(0L);
2930 
2931         assertProtoArrayEqualsIgnoringOrder(
2932                 new SipDelegateStats[] {mSipDelegateStats1, mSipDelegateStats2, mSipDelegateStats3},
2933                 outputs);
2934     }
2935 
2936     @Test
2937     @SmallTest
addSipDelegateStats_tooManyEntries()2938     public void addSipDelegateStats_tooManyEntries() throws Exception {
2939         // verify add atom excess MAX count
2940         createEmptyTestFile();
2941 
2942         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2943 
2944         // Try to add 11 stats where MAX is 10
2945         int max = 11;
2946         SipDelegateStats[] overMaxSipDelegateStats = new SipDelegateStats[max];
2947         for (int i = 0; i < max; i++) {
2948             overMaxSipDelegateStats[i] = copyOf(mSipDelegateStats1);
2949             mPersistAtomsStorage
2950                     .addSipDelegateStats(overMaxSipDelegateStats[i]);
2951             mPersistAtomsStorage.incTimeMillis(100L);
2952         }
2953         mPersistAtomsStorage.addSipDelegateStats(mSipDelegateStats3);
2954         verifyCurrentStateSavedToFileOnce();
2955 
2956         SipDelegateStats[] outputs =
2957                 mPersistAtomsStorage.getSipDelegateStats(0L);
2958 
2959         // The last added SipDelegate remains
2960         // and two old stats should be removed
2961         assertHasStats(outputs, overMaxSipDelegateStats, max - 2);
2962         assertHasStats(outputs, mSipDelegateStats3, 1);
2963     }
2964 
2965     @Test
2966     @SmallTest
addSipDelegateStats_updateExistingEntries()2967     public void addSipDelegateStats_updateExistingEntries() throws Exception {
2968         // verify count
2969         createTestFile(START_TIME_MILLIS);
2970 
2971         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2972         SipDelegateStats newSipDelegateStats3 = copyOf(mSipDelegateStats3);
2973         newSipDelegateStats3.destroyReason =
2974                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD;
2975         mPersistAtomsStorage.addSipDelegateStats(newSipDelegateStats3);
2976         mPersistAtomsStorage.incTimeMillis(100L);
2977 
2978         SipDelegateStats newSipDelegateStats1 = copyOf(mSipDelegateStats1);
2979         newSipDelegateStats1.destroyReason =
2980                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP;
2981         mPersistAtomsStorage.addSipDelegateStats(newSipDelegateStats1);
2982         mPersistAtomsStorage.incTimeMillis(100L);
2983         verifyCurrentStateSavedToFileOnce();
2984 
2985         SipDelegateStats[] outputs = mPersistAtomsStorage.getSipDelegateStats(0L);
2986 
2987         assertProtoArrayEqualsIgnoringOrder(
2988                 new SipDelegateStats[] {mSipDelegateStats2, mSipDelegateStats3,
2989                         newSipDelegateStats3, newSipDelegateStats1}, outputs);
2990     }
2991 
2992     @Test
2993     @SmallTest
getSipDelegateStats_tooFrequent()2994     public void getSipDelegateStats_tooFrequent() throws Exception {
2995         // verify get frequently
2996         createTestFile(START_TIME_MILLIS);
2997 
2998         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
2999         mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
3000 
3001         SipDelegateStats[] outputs = mPersistAtomsStorage.getSipDelegateStats(100L);
3002         // should be denied
3003         assertNull(outputs);
3004     }
3005 
3006     @Test
3007     @SmallTest
getSipDelegateStats_withSavedAtoms()3008     public void getSipDelegateStats_withSavedAtoms() throws Exception {
3009         // verify last get time after get atoms
3010         createTestFile(START_TIME_MILLIS);
3011 
3012         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3013         mPersistAtomsStorage.incTimeMillis(100L);
3014 
3015         SipDelegateStats[] output1 = mPersistAtomsStorage.getSipDelegateStats(50L);
3016         mPersistAtomsStorage.incTimeMillis(100L);
3017         SipDelegateStats[] output2 = mPersistAtomsStorage.getSipDelegateStats(50L);
3018 
3019         // first set of results should equal to file contents, second should be empty, corresponding
3020         // pull timestamp should be updated and saved
3021         assertProtoArrayEqualsIgnoringOrder(
3022                 new SipDelegateStats[] {
3023                         mSipDelegateStats2,
3024                         mSipDelegateStats3}, output1);
3025         assertProtoArrayEquals(new SipDelegateStats[0], output2);
3026         assertEquals(
3027                 START_TIME_MILLIS + 200L,
3028                 mPersistAtomsStorage.getAtomsProto().sipDelegateStatsPullTimestampMillis);
3029         InOrder inOrder = inOrder(mTestFileOutputStream);
3030         assertEquals(
3031                 START_TIME_MILLIS + 100L,
3032                 getAtomsWritten(inOrder).sipDelegateStatsPullTimestampMillis);
3033         assertEquals(
3034                 START_TIME_MILLIS + 200L,
3035                 getAtomsWritten(inOrder).sipDelegateStatsPullTimestampMillis);
3036         inOrder.verifyNoMoreInteractions();
3037     }
3038 
3039     @Test
3040     @SmallTest
addGbaEvent_emptyProto()3041     public void addGbaEvent_emptyProto() throws Exception {
3042         createEmptyTestFile();
3043         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3044         mPersistAtomsStorage.addGbaEvent(mGbaEvent1);
3045         mPersistAtomsStorage.incTimeMillis(100L);
3046 
3047         // gba event should be added successfully
3048         verifyCurrentStateSavedToFileOnce();
3049         GbaEvent[] stats = mPersistAtomsStorage.getGbaEvent(0L);
3050         assertProtoArrayEquals(new GbaEvent[] {mGbaEvent1}, stats);
3051     }
3052 
3053     @Test
3054     @SmallTest
addGbaEvent_withExistingEntries()3055     public void addGbaEvent_withExistingEntries() throws Exception {
3056         createEmptyTestFile();
3057         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3058         mPersistAtomsStorage.addGbaEvent(mGbaEvent1);
3059         mPersistAtomsStorage.incTimeMillis(100L);
3060         mPersistAtomsStorage.addGbaEvent(mGbaEvent2);
3061         mPersistAtomsStorage.incTimeMillis(100L);
3062 
3063         // gba event1, gba event2 should be added successfully
3064         verifyCurrentStateSavedToFileOnce();
3065         GbaEvent[] stats = mPersistAtomsStorage.getGbaEvent(0L);
3066         assertProtoArrayEqualsIgnoringOrder(
3067                 new GbaEvent[] {mGbaEvent1, mGbaEvent2}, stats);
3068     }
3069 
3070     @Test
3071     @SmallTest
addGbaEvent_tooManyEntries()3072     public void addGbaEvent_tooManyEntries() throws Exception {
3073         createEmptyTestFile();
3074 
3075         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3076 
3077         // Add 11 stats, but max is 10
3078         for (int i = 0; i < 11; i++) {
3079             mPersistAtomsStorage.addGbaEvent(mGbaEvent1);
3080             mPersistAtomsStorage.incTimeMillis(100L);
3081         }
3082         mPersistAtomsStorage.addGbaEvent(mGbaEvent2);
3083 
3084         verifyCurrentStateSavedToFileOnce();
3085         GbaEvent[] stats = mPersistAtomsStorage.getGbaEvent(0L);
3086         assertHasStatsAndCount(stats, mGbaEvent1, 11);
3087         assertHasStatsAndCount(stats, mGbaEvent2, 1);
3088     }
3089 
3090     @Test
3091     @SmallTest
addGbaEvent_updateExistingEntries()3092     public void addGbaEvent_updateExistingEntries() throws Exception {
3093         createTestFile(START_TIME_MILLIS);
3094         GbaEvent newStats = copyOf(mGbaEvent1);
3095         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3096 
3097         mPersistAtomsStorage.addGbaEvent(copyOf(mGbaEvent1));
3098         mPersistAtomsStorage.incTimeMillis(100L);
3099 
3100         // mGbaEvent1's count should be doubled
3101         verifyCurrentStateSavedToFileOnce();
3102         GbaEvent[] stats =
3103                 mPersistAtomsStorage.getGbaEvent(0L);
3104         newStats.count *= 2;
3105         assertProtoArrayEqualsIgnoringOrder(new GbaEvent[] {mGbaEvent2, newStats}, stats);
3106     }
3107 
3108     @Test
3109     @SmallTest
addSipMessageResponse_emptyProto()3110     public void addSipMessageResponse_emptyProto() throws Exception {
3111         createEmptyTestFile();
3112         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3113         mPersistAtomsStorage.addSipMessageResponse(mSipMessageResponse1);
3114         mPersistAtomsStorage.incTimeMillis(100L);
3115 
3116         verifyCurrentStateSavedToFileOnce();
3117         SipMessageResponse[] expected = mPersistAtomsStorage.getSipMessageResponse(0L);
3118         assertProtoArrayEquals(new SipMessageResponse[] {mSipMessageResponse1}, expected);
3119     }
3120 
3121     @Test
3122     @SmallTest
addSipMessageResponse_withExistingEntries()3123     public void addSipMessageResponse_withExistingEntries() throws Exception {
3124         createEmptyTestFile();
3125         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3126         mPersistAtomsStorage.addSipMessageResponse(mSipMessageResponse1);
3127         mPersistAtomsStorage.incTimeMillis(100L);
3128         mPersistAtomsStorage.addSipMessageResponse(mSipMessageResponse2);
3129         mPersistAtomsStorage.incTimeMillis(100L);
3130 
3131         verifyCurrentStateSavedToFileOnce();
3132         SipMessageResponse[] expected =
3133                 new SipMessageResponse[] {mSipMessageResponse1, mSipMessageResponse2};
3134 
3135         assertProtoArrayEqualsIgnoringOrder(
3136                 expected, mPersistAtomsStorage.getSipMessageResponse(0L));
3137     }
3138 
3139     @Test
3140     @SmallTest
addSipMessageResponse_tooManyEntries()3141     public void addSipMessageResponse_tooManyEntries() throws Exception {
3142         createEmptyTestFile();
3143         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3144 
3145         // store 11 same atoms, but only 1 atoms stored with count 11
3146         for (int i = 0; i < 11; i++) {
3147             mPersistAtomsStorage.addSipMessageResponse(mSipMessageResponse1);
3148             mPersistAtomsStorage.incTimeMillis(100L);
3149         }
3150         // store 1 different atom and count 1
3151         mPersistAtomsStorage.addSipMessageResponse(mSipMessageResponse2);
3152 
3153         verifyCurrentStateSavedToFileOnce();
3154         SipMessageResponse[] result = mPersistAtomsStorage.getSipMessageResponse(0L);
3155 
3156         // first atom has count 11, the other has 1
3157         assertHasStats(result, mSipMessageResponse1, 11);
3158         assertHasStats(result, mSipMessageResponse2, 1);
3159     }
3160 
3161     @Test
3162     @SmallTest
addSipMessageResponse_updateExistingEntries()3163     public void addSipMessageResponse_updateExistingEntries() throws Exception {
3164         createTestFile(START_TIME_MILLIS);
3165         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3166         mPersistAtomsStorage.addSipMessageResponse(copyOf(mSipMessageResponse2));
3167         mPersistAtomsStorage.incTimeMillis(100L);
3168         verifyCurrentStateSavedToFileOnce();
3169 
3170         SipMessageResponse[] outputs = mPersistAtomsStorage.getSipMessageResponse(0L);
3171         SipMessageResponse newSipMessageResponse = copyOf(mSipMessageResponse2);
3172         newSipMessageResponse.count *= 2;
3173         assertProtoArrayEqualsIgnoringOrder(
3174                 new SipMessageResponse[] {mSipMessageResponse1, newSipMessageResponse}, outputs);
3175     }
3176 
3177     @Test
3178     @SmallTest
addCompleteSipTransportSession_emptyProto()3179     public void addCompleteSipTransportSession_emptyProto() throws Exception {
3180         createEmptyTestFile();
3181         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3182         mPersistAtomsStorage.addCompleteSipTransportSession(mSipTransportSession1);
3183         mPersistAtomsStorage.incTimeMillis(100L);
3184 
3185         verifyCurrentStateSavedToFileOnce();
3186         SipTransportSession[] expected = mPersistAtomsStorage.getSipTransportSession(0L);
3187         assertProtoArrayEquals(new SipTransportSession[] {mSipTransportSession1}, expected);
3188     }
3189 
3190     @Test
3191     @SmallTest
addCompleteSipTransportSession_withExistingEntries()3192     public void addCompleteSipTransportSession_withExistingEntries() throws Exception {
3193         createEmptyTestFile();
3194         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3195         mPersistAtomsStorage.addCompleteSipTransportSession(mSipTransportSession1);
3196         mPersistAtomsStorage.incTimeMillis(100L);
3197         mPersistAtomsStorage.addCompleteSipTransportSession(mSipTransportSession2);
3198         mPersistAtomsStorage.incTimeMillis(100L);
3199 
3200         verifyCurrentStateSavedToFileOnce();
3201         SipTransportSession[] expected =
3202                 new SipTransportSession[] {mSipTransportSession1, mSipTransportSession2};
3203 
3204         assertProtoArrayEqualsIgnoringOrder(
3205                 expected, mPersistAtomsStorage.getSipTransportSession(0L));
3206     }
3207 
3208     @Test
3209     @SmallTest
addCompleteSipTransportSession_tooManyEntries()3210     public void addCompleteSipTransportSession_tooManyEntries() throws Exception {
3211         createEmptyTestFile();
3212         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3213 
3214         // store 11 same atoms, but only 1 atoms stored with count 11
3215         for (int i = 0; i < 11; i++) {
3216             mPersistAtomsStorage.addCompleteSipTransportSession(mSipTransportSession1);
3217             mPersistAtomsStorage.incTimeMillis(100L);
3218         }
3219         // store 1 different atom and count 1
3220         mPersistAtomsStorage.addCompleteSipTransportSession(mSipTransportSession2);
3221 
3222         verifyCurrentStateSavedToFileOnce();
3223         SipTransportSession[] result = mPersistAtomsStorage.getSipTransportSession(0L);
3224 
3225         // first atom has count 11, the other has 1
3226         assertHasStats(result, mSipTransportSession1, 11);
3227         assertHasStats(result, mSipTransportSession2, 1);
3228     }
3229 
3230     @Test
3231     @SmallTest
addCompleteSipTransportSession_updateExistingEntries()3232     public void addCompleteSipTransportSession_updateExistingEntries() throws Exception {
3233         createTestFile(START_TIME_MILLIS);
3234         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3235         mPersistAtomsStorage.addCompleteSipTransportSession(copyOf(mSipTransportSession2));
3236         mPersistAtomsStorage.incTimeMillis(100L);
3237         verifyCurrentStateSavedToFileOnce();
3238 
3239         SipTransportSession[] outputs = mPersistAtomsStorage.getSipTransportSession(0L);
3240         SipTransportSession newSipTransportSession = copyOf(mSipTransportSession2);
3241         newSipTransportSession.sessionCount *= 2;
3242         newSipTransportSession.endedGracefullyCount *= 2;
3243         assertProtoArrayEqualsIgnoringOrder(
3244                 new SipTransportSession[] {mSipTransportSession1,
3245                         newSipTransportSession}, outputs);
3246     }
3247 
3248     @Test
3249     @SmallTest
getUnmeteredNetworks_noExistingEntry()3250     public void getUnmeteredNetworks_noExistingEntry() throws Exception {
3251         createTestFile(START_TIME_MILLIS);
3252         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3253         InOrder inOrder = inOrder(mTestFileOutputStream);
3254 
3255         assertEquals(0L, mPersistAtomsStorage.getUnmeteredNetworks(1, 0));
3256 
3257         inOrder.verifyNoMoreInteractions();
3258     }
3259 
3260     @Test
3261     @SmallTest
getUnmeteredNetworks()3262     public void getUnmeteredNetworks() throws Exception {
3263         createTestFile(START_TIME_MILLIS);
3264         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3265         InOrder inOrder = inOrder(mTestFileOutputStream);
3266 
3267         mPersistAtomsStorage.addUnmeteredNetworks(0, 0, NETWORK_TYPE_BITMASK_GPRS);
3268         inOrder.verify(mTestFileOutputStream, times(1))
3269                 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto())));
3270         inOrder.verify(mTestFileOutputStream, times(1)).close();
3271         inOrder.verifyNoMoreInteractions();
3272 
3273         assertEquals(NETWORK_TYPE_BITMASK_GPRS, mPersistAtomsStorage.getUnmeteredNetworks(0, 0));
3274         inOrder.verify(mTestFileOutputStream, times(1))
3275                 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto())));
3276         inOrder.verify(mTestFileOutputStream, times(1)).close();
3277         inOrder.verifyNoMoreInteractions();
3278 
3279         assertEquals(0L, mPersistAtomsStorage.getUnmeteredNetworks(0, 0));
3280         inOrder.verifyNoMoreInteractions();
3281     }
3282 
3283     @Test
3284     @SmallTest
getUnmeteredNetworks_carrierIdMismatch()3285     public void getUnmeteredNetworks_carrierIdMismatch() throws Exception {
3286         createTestFile(START_TIME_MILLIS);
3287         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3288         InOrder inOrder = inOrder(mTestFileOutputStream);
3289 
3290         mPersistAtomsStorage.addUnmeteredNetworks(0, 0, NETWORK_TYPE_BITMASK_GPRS);
3291         inOrder.verify(mTestFileOutputStream, times(1))
3292                 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto())));
3293         inOrder.verify(mTestFileOutputStream, times(1)).close();
3294         inOrder.verifyNoMoreInteractions();
3295 
3296         assertEquals(0L, mPersistAtomsStorage.getUnmeteredNetworks(0, 1));
3297         inOrder.verify(mTestFileOutputStream, times(1))
3298                 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto())));
3299         inOrder.verify(mTestFileOutputStream, times(1)).close();
3300         inOrder.verifyNoMoreInteractions();
3301 
3302         assertEquals(0L, mPersistAtomsStorage.getUnmeteredNetworks(0, 0));
3303         inOrder.verifyNoMoreInteractions();
3304     }
3305 
3306     @Test
3307     @SmallTest
addUnmeteredNetworks()3308     public void addUnmeteredNetworks() throws Exception {
3309         createTestFile(START_TIME_MILLIS);
3310         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3311         InOrder inOrder = inOrder(mTestFileOutputStream);
3312 
3313         mPersistAtomsStorage.addUnmeteredNetworks(0, 0, NETWORK_TYPE_BITMASK_GPRS);
3314         inOrder.verify(mTestFileOutputStream, times(1))
3315                 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto())));
3316         inOrder.verify(mTestFileOutputStream, times(1)).close();
3317         inOrder.verifyNoMoreInteractions();
3318 
3319         mPersistAtomsStorage.addUnmeteredNetworks(0, 0, NETWORK_TYPE_BITMASK_GSM);
3320         inOrder.verify(mTestFileOutputStream, times(1))
3321                 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto())));
3322         inOrder.verify(mTestFileOutputStream, times(1)).close();
3323         inOrder.verifyNoMoreInteractions();
3324 
3325         assertEquals(
3326                 NETWORK_TYPE_BITMASK_GPRS | NETWORK_TYPE_BITMASK_GSM,
3327                 mPersistAtomsStorage.getUnmeteredNetworks(0, 0));
3328         inOrder.verify(mTestFileOutputStream, times(1))
3329                 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto())));
3330         inOrder.verify(mTestFileOutputStream, times(1)).close();
3331         inOrder.verifyNoMoreInteractions();
3332 
3333         assertEquals(0, mPersistAtomsStorage.getUnmeteredNetworks(0, 0));
3334         inOrder.verifyNoMoreInteractions();
3335 
3336         mPersistAtomsStorage.addUnmeteredNetworks(1, 2, NETWORK_TYPE_BITMASK_GPRS);
3337         inOrder.verify(mTestFileOutputStream, times(1))
3338                 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto())));
3339         inOrder.verify(mTestFileOutputStream, times(1)).close();
3340         inOrder.verifyNoMoreInteractions();
3341 
3342         mPersistAtomsStorage.addUnmeteredNetworks(1, 2, NETWORK_TYPE_BITMASK_GSM);
3343         inOrder.verify(mTestFileOutputStream, times(1))
3344                 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto())));
3345         inOrder.verify(mTestFileOutputStream, times(1)).close();
3346         inOrder.verifyNoMoreInteractions();
3347 
3348         assertEquals(
3349                 NETWORK_TYPE_BITMASK_GPRS | NETWORK_TYPE_BITMASK_GSM,
3350                 mPersistAtomsStorage.getUnmeteredNetworks(1, 2));
3351         inOrder.verify(mTestFileOutputStream, times(1))
3352                 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto())));
3353         inOrder.verify(mTestFileOutputStream, times(1)).close();
3354         inOrder.verifyNoMoreInteractions();
3355 
3356         assertEquals(0, mPersistAtomsStorage.getUnmeteredNetworks(1, 2));
3357         inOrder.verifyNoMoreInteractions();
3358     }
3359 
3360     @Test
3361     @SmallTest
addUnmeteredNetworks_carrierIdMismatch()3362     public void addUnmeteredNetworks_carrierIdMismatch() throws Exception {
3363         createTestFile(START_TIME_MILLIS);
3364         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3365         InOrder inOrder = inOrder(mTestFileOutputStream);
3366 
3367         mPersistAtomsStorage.addUnmeteredNetworks(0, 0, NETWORK_TYPE_BITMASK_GPRS);
3368         inOrder.verify(mTestFileOutputStream, times(1))
3369                 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto())));
3370         inOrder.verify(mTestFileOutputStream, times(1)).close();
3371         inOrder.verifyNoMoreInteractions();
3372 
3373         mPersistAtomsStorage.addUnmeteredNetworks(0, 1, NETWORK_TYPE_BITMASK_GSM);
3374         inOrder.verify(mTestFileOutputStream, times(1))
3375                 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto())));
3376         inOrder.verify(mTestFileOutputStream, times(1)).close();
3377         inOrder.verifyNoMoreInteractions();
3378 
3379         assertEquals(NETWORK_TYPE_BITMASK_GSM, mPersistAtomsStorage.getUnmeteredNetworks(0, 1));
3380         inOrder.verify(mTestFileOutputStream, times(1))
3381                 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto())));
3382         inOrder.verify(mTestFileOutputStream, times(1)).close();
3383         inOrder.verifyNoMoreInteractions();
3384 
3385         assertEquals(0L, mPersistAtomsStorage.getUnmeteredNetworks(0, 1));
3386         inOrder.verifyNoMoreInteractions();
3387     }
3388 
3389     @Test
3390     @SmallTest
addUnmeteredNetworks_sameBitmask()3391     public void addUnmeteredNetworks_sameBitmask() throws Exception {
3392         createTestFile(START_TIME_MILLIS);
3393         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3394         InOrder inOrder = inOrder(mTestFileOutputStream);
3395 
3396         mPersistAtomsStorage.addUnmeteredNetworks(0, 0, NETWORK_TYPE_BITMASK_GPRS);
3397         inOrder.verify(mTestFileOutputStream, times(1))
3398                 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto())));
3399         inOrder.verify(mTestFileOutputStream, times(1)).close();
3400         inOrder.verifyNoMoreInteractions();
3401 
3402         mPersistAtomsStorage.addUnmeteredNetworks(0, 0, NETWORK_TYPE_BITMASK_GPRS);
3403         inOrder.verifyNoMoreInteractions();
3404 
3405         assertEquals(NETWORK_TYPE_BITMASK_GPRS, mPersistAtomsStorage.getUnmeteredNetworks(0, 0));
3406         inOrder.verify(mTestFileOutputStream, times(1))
3407                 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto())));
3408         inOrder.verify(mTestFileOutputStream, times(1)).close();
3409         inOrder.verifyNoMoreInteractions();
3410     }
3411 
3412     @Test
3413     @SmallTest
clearAtoms()3414     public void clearAtoms() throws Exception {
3415         createTestFile(START_TIME_MILLIS);
3416         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
3417         mPersistAtomsStorage.addCompleteSipTransportSession(copyOf(mSipTransportSession1));
3418         mPersistAtomsStorage.incTimeMillis(100L);
3419         verifyCurrentStateSavedToFileOnce();
3420 
3421         mPersistAtomsStorage.addUceEventStats(mUceEventStats1);
3422         mPersistAtomsStorage.incTimeMillis(100L);
3423         verifyCurrentStateSavedToFileOnce();
3424 
3425         mPersistAtomsStorage.clearAtoms();
3426         verifyCurrentStateSavedToFileOnce();
3427         UceEventStats[] uceEventStats = mPersistAtomsStorage.getUceEventStats(0L);
3428         assertEquals(null, uceEventStats);
3429         SipTransportSession[] sipTransportSession = mPersistAtomsStorage.getSipTransportSession(0L);
3430         assertEquals(null, sipTransportSession);
3431     }
3432 
3433     /* Utilities */
3434 
createEmptyTestFile()3435     private void createEmptyTestFile() throws Exception {
3436         PersistAtoms atoms = new PersistAtoms();
3437         FileOutputStream stream = new FileOutputStream(mTestFile);
3438         stream.write(PersistAtoms.toByteArray(atoms));
3439         stream.close();
3440     }
3441 
createTestFile(long lastPullTimeMillis)3442     private void createTestFile(long lastPullTimeMillis) throws Exception {
3443         PersistAtoms atoms = new PersistAtoms();
3444         atoms.buildFingerprint = Build.FINGERPRINT;
3445         atoms.voiceCallRatUsagePullTimestampMillis = lastPullTimeMillis;
3446         atoms.voiceCallRatUsage = mVoiceCallRatUsages;
3447         atoms.voiceCallSessionPullTimestampMillis = lastPullTimeMillis;
3448         atoms.voiceCallSession = mVoiceCallSessions;
3449         atoms.cellularServiceStatePullTimestampMillis = lastPullTimeMillis;
3450         atoms.cellularServiceState = mServiceStates;
3451         atoms.cellularDataServiceSwitchPullTimestampMillis = lastPullTimeMillis;
3452         atoms.cellularDataServiceSwitch = mServiceSwitches;
3453         atoms.imsRegistrationStatsPullTimestampMillis = lastPullTimeMillis;
3454         atoms.imsRegistrationStats = mImsRegistrationStats;
3455         atoms.imsRegistrationTerminationPullTimestampMillis = lastPullTimeMillis;
3456         atoms.imsRegistrationTermination = mImsRegistrationTerminations;
3457         atoms.imsRegistrationFeatureTagStatsPullTimestampMillis = lastPullTimeMillis;
3458         atoms.imsRegistrationFeatureTagStats = mImsRegistrationFeatureTagStatses;
3459         atoms.rcsClientProvisioningStatsPullTimestampMillis = lastPullTimeMillis;
3460         atoms.rcsClientProvisioningStats = mRcsClientProvisioningStatses;
3461         atoms.rcsAcsProvisioningStatsPullTimestampMillis = lastPullTimeMillis;
3462         atoms.rcsAcsProvisioningStats = mRcsAcsProvisioningStatses;
3463         atoms.imsRegistrationServiceDescStatsPullTimestampMillis = lastPullTimeMillis;
3464         atoms.imsRegistrationServiceDescStats = mImsRegistrationServiceDescStats;
3465         atoms.imsDedicatedBearerListenerEventPullTimestampMillis = lastPullTimeMillis;
3466         atoms.imsDedicatedBearerListenerEvent = mImsDedicatedBearerListenerEvents;
3467         atoms.imsDedicatedBearerEventPullTimestampMillis = lastPullTimeMillis;
3468         atoms.imsDedicatedBearerEvent = mImsDedicatedBearerEvents;
3469         atoms.uceEventStatsPullTimestampMillis = lastPullTimeMillis;
3470         atoms.uceEventStats = mUceEventStatses;
3471         atoms.presenceNotifyEventPullTimestampMillis = lastPullTimeMillis;
3472         atoms.presenceNotifyEvent = mPresenceNotifyEvents;
3473         atoms.sipTransportFeatureTagStatsPullTimestampMillis = lastPullTimeMillis;
3474         atoms.sipTransportFeatureTagStats = mSipTransportFeatureTagStatsArray;
3475         atoms.sipDelegateStatsPullTimestampMillis = lastPullTimeMillis;
3476         atoms.sipDelegateStats = mSipDelegateStatsArray;
3477         atoms.gbaEventPullTimestampMillis = lastPullTimeMillis;
3478         atoms.gbaEvent = mGbaEvent;
3479         atoms.sipMessageResponsePullTimestampMillis = lastPullTimeMillis;
3480         atoms.sipMessageResponse = mSipMessageResponse;
3481         atoms.sipTransportSessionPullTimestampMillis = lastPullTimeMillis;
3482         atoms.sipTransportSession = mSipTransportSession;
3483         FileOutputStream stream = new FileOutputStream(mTestFile);
3484         stream.write(PersistAtoms.toByteArray(atoms));
3485         stream.close();
3486     }
3487 
getAtomsWritten(@ullable InOrder inOrder)3488     private PersistAtoms getAtomsWritten(@Nullable InOrder inOrder) throws Exception {
3489         if (inOrder == null) {
3490             inOrder = inOrder(mTestFileOutputStream);
3491         }
3492         ArgumentCaptor bytesCaptor = ArgumentCaptor.forClass(Object.class);
3493         inOrder.verify(mTestFileOutputStream, times(1)).write((byte[]) bytesCaptor.capture());
3494         PersistAtoms savedAtoms = PersistAtoms.parseFrom((byte[]) bytesCaptor.getValue());
3495         inOrder.verify(mTestFileOutputStream, times(1)).close();
3496         return savedAtoms;
3497     }
3498 
addRepeatedCalls( PersistAtomsStorage storage, VoiceCallSession call, int count)3499     private static void addRepeatedCalls(
3500             PersistAtomsStorage storage, VoiceCallSession call, int count) {
3501         for (int i = 0; i < count; i++) {
3502             storage.addVoiceCallSession(call);
3503         }
3504     }
3505 
multiplyVoiceCallRatUsage( VoiceCallRatUsage[] usages, int times)3506     private static VoiceCallRatUsage[] multiplyVoiceCallRatUsage(
3507             VoiceCallRatUsage[] usages, int times) {
3508         VoiceCallRatUsage[] multipliedUsages = new VoiceCallRatUsage[usages.length];
3509         for (int i = 0; i < usages.length; i++) {
3510             multipliedUsages[i] = new VoiceCallRatUsage();
3511             multipliedUsages[i].carrierId = usages[i].carrierId;
3512             multipliedUsages[i].rat = usages[i].rat;
3513             multipliedUsages[i].callCount = usages[i].callCount * 2;
3514             multipliedUsages[i].totalDurationMillis = usages[i].totalDurationMillis * 2;
3515         }
3516         return multipliedUsages;
3517     }
3518 
copyOf(CellularServiceState source)3519     private static CellularServiceState copyOf(CellularServiceState source) throws Exception {
3520         return CellularServiceState.parseFrom(MessageNano.toByteArray(source));
3521     }
3522 
copyOf(CellularDataServiceSwitch source)3523     private static CellularDataServiceSwitch copyOf(CellularDataServiceSwitch source)
3524             throws Exception {
3525         return CellularDataServiceSwitch.parseFrom(MessageNano.toByteArray(source));
3526     }
3527 
copyOf(ImsRegistrationStats source)3528     private static ImsRegistrationStats copyOf(ImsRegistrationStats source) throws Exception {
3529         return ImsRegistrationStats.parseFrom(MessageNano.toByteArray(source));
3530     }
3531 
copyOf(ImsRegistrationTermination source)3532     private static ImsRegistrationTermination copyOf(ImsRegistrationTermination source)
3533             throws Exception {
3534         return ImsRegistrationTermination.parseFrom(MessageNano.toByteArray(source));
3535     }
3536 
copyOf(DataCallSession source)3537     private static DataCallSession copyOf(DataCallSession source)
3538             throws Exception {
3539         return DataCallSession.parseFrom(MessageNano.toByteArray(source));
3540     }
3541 
copyOf(ImsRegistrationFeatureTagStats source)3542     private static ImsRegistrationFeatureTagStats copyOf(ImsRegistrationFeatureTagStats source)
3543             throws Exception {
3544         return ImsRegistrationFeatureTagStats.parseFrom(MessageNano.toByteArray(source));
3545     }
3546 
copyOf(RcsAcsProvisioningStats source)3547     private static RcsAcsProvisioningStats copyOf(RcsAcsProvisioningStats source)
3548             throws Exception {
3549         return RcsAcsProvisioningStats.parseFrom(MessageNano.toByteArray(source));
3550     }
3551 
copyOf(ImsRegistrationServiceDescStats source)3552     private static ImsRegistrationServiceDescStats copyOf(ImsRegistrationServiceDescStats source)
3553             throws Exception {
3554         return ImsRegistrationServiceDescStats.parseFrom(MessageNano.toByteArray(source));
3555     }
3556 
copyOf(ImsDedicatedBearerListenerEvent source)3557     private static ImsDedicatedBearerListenerEvent copyOf(ImsDedicatedBearerListenerEvent source)
3558             throws Exception {
3559         return ImsDedicatedBearerListenerEvent.parseFrom(MessageNano.toByteArray(source));
3560     }
3561 
copyOf(ImsDedicatedBearerEvent source)3562     private static ImsDedicatedBearerEvent copyOf(ImsDedicatedBearerEvent source)
3563             throws Exception {
3564         return ImsDedicatedBearerEvent.parseFrom(MessageNano.toByteArray(source));
3565     }
3566 
copyOf(UceEventStats source)3567     private static UceEventStats copyOf(UceEventStats source)
3568             throws Exception {
3569         return UceEventStats.parseFrom(MessageNano.toByteArray(source));
3570     }
3571 
copyOf(PresenceNotifyEvent source)3572     private static PresenceNotifyEvent copyOf(PresenceNotifyEvent source)
3573             throws Exception {
3574         return PresenceNotifyEvent.parseFrom(MessageNano.toByteArray(source));
3575     }
3576 
copyOf(SipDelegateStats source)3577     private static SipDelegateStats copyOf(SipDelegateStats source)
3578             throws Exception {
3579         return SipDelegateStats.parseFrom(MessageNano.toByteArray(source));
3580     }
copyOf(SipTransportFeatureTagStats source)3581     private static SipTransportFeatureTagStats copyOf(SipTransportFeatureTagStats source)
3582             throws Exception {
3583         return SipTransportFeatureTagStats.parseFrom(MessageNano.toByteArray(source));
3584     }
3585 
copyOf(GbaEvent source)3586     private static GbaEvent copyOf(GbaEvent source)
3587             throws Exception {
3588         return GbaEvent.parseFrom(MessageNano.toByteArray(source));
3589     }
3590 
copyOf(SipMessageResponse source)3591     private static SipMessageResponse copyOf(SipMessageResponse source)
3592             throws Exception {
3593         return SipMessageResponse.parseFrom(MessageNano.toByteArray(source));
3594     }
3595 
copyOf(SipTransportSession source)3596     private static SipTransportSession copyOf(SipTransportSession source)
3597             throws Exception {
3598         return SipTransportSession.parseFrom(MessageNano.toByteArray(source));
3599     }
3600 
assertAllPullTimestampEquals(long timestamp)3601     private void assertAllPullTimestampEquals(long timestamp) {
3602         assertEquals(
3603                 timestamp,
3604                 mPersistAtomsStorage.getAtomsProto().voiceCallRatUsagePullTimestampMillis);
3605         assertEquals(
3606                 timestamp,
3607                 mPersistAtomsStorage.getAtomsProto().voiceCallSessionPullTimestampMillis);
3608         assertEquals(
3609                 timestamp,
3610                 mPersistAtomsStorage.getAtomsProto().cellularServiceStatePullTimestampMillis);
3611         assertEquals(
3612                 timestamp,
3613                 mPersistAtomsStorage.getAtomsProto().cellularDataServiceSwitchPullTimestampMillis);
3614     }
3615 
assertStorageIsEmptyForAllAtoms()3616     private void assertStorageIsEmptyForAllAtoms() {
3617         assertProtoArrayIsEmpty(mPersistAtomsStorage.getVoiceCallRatUsages(0L));
3618         assertProtoArrayIsEmpty(mPersistAtomsStorage.getVoiceCallSessions(0L));
3619         assertProtoArrayIsEmpty(mPersistAtomsStorage.getCellularServiceStates(0L));
3620         assertProtoArrayIsEmpty(mPersistAtomsStorage.getCellularDataServiceSwitches(0L));
3621     }
3622 
assertProtoArrayIsEmpty(T[] array)3623     private static <T extends MessageNano> void assertProtoArrayIsEmpty(T[] array) {
3624         assertNotNull(array);
3625         assertEquals(0, array.length);
3626     }
3627 
assertProtoArrayEquals(MessageNano[] expected, MessageNano[] actual)3628     private static void assertProtoArrayEquals(MessageNano[] expected, MessageNano[] actual) {
3629         assertNotNull(expected);
3630         assertNotNull(actual);
3631         String message =
3632                 "Expected:\n" + Arrays.toString(expected) + "\nGot:\n" + Arrays.toString(actual);
3633         assertEquals(message, expected.length, actual.length);
3634         for (int i = 0; i < expected.length; i++) {
3635             assertTrue(message, MessageNano.messageNanoEquals(expected[i], actual[i]));
3636         }
3637     }
3638 
assertProtoArrayEqualsIgnoringOrder( MessageNano[] expected, MessageNano[] actual)3639     private static void assertProtoArrayEqualsIgnoringOrder(
3640             MessageNano[] expected, MessageNano[] actual) {
3641         assertNotNull(expected);
3642         assertNotNull(actual);
3643         expected = expected.clone();
3644         actual = actual.clone();
3645         Arrays.sort(expected, sProtoComparator);
3646         Arrays.sort(actual, sProtoComparator);
3647         assertProtoArrayEquals(expected, actual);
3648     }
3649 
assertHasCall( VoiceCallSession[] calls, @Nullable VoiceCallSession expectedCall, int expectedCount)3650     private static void assertHasCall(
3651             VoiceCallSession[] calls, @Nullable VoiceCallSession expectedCall, int expectedCount) {
3652         assertNotNull(calls);
3653         int actualCount = 0;
3654         for (VoiceCallSession call : calls) {
3655             if (call != null && expectedCall != null) {
3656                 if (MessageNano.messageNanoEquals(call, expectedCall)) {
3657                     actualCount++;
3658                 }
3659             }
3660         }
3661         assertEquals(expectedCount, actualCount);
3662     }
3663 
verifyCurrentStateSavedToFileOnce()3664     private void verifyCurrentStateSavedToFileOnce() throws Exception {
3665         InOrder inOrder = inOrder(mTestFileOutputStream);
3666         inOrder.verify(mTestFileOutputStream, times(1))
3667                 .write(eq(PersistAtoms.toByteArray(mPersistAtomsStorage.getAtomsProto())));
3668         inOrder.verify(mTestFileOutputStream, times(1)).close();
3669         inOrder.verifyNoMoreInteractions();
3670     }
3671 
assertHasStatsCountTime( ImsRegistrationFeatureTagStats[] statses, @Nullable ImsRegistrationFeatureTagStats expectedStats, int expectedCount, long expectedTime)3672     private static void assertHasStatsCountTime(
3673             ImsRegistrationFeatureTagStats[] statses,
3674             @Nullable ImsRegistrationFeatureTagStats expectedStats,
3675             int expectedCount, long expectedTime) {
3676         assertNotNull(statses);
3677         int actualCount = 0;
3678         long actualTime = 0;
3679         for (ImsRegistrationFeatureTagStats stats : statses) {
3680             if (stats != null && expectedStats != null) {
3681                 if (stats.carrierId == expectedStats.carrierId
3682                         && stats.slotId == expectedStats.slotId
3683                         && stats.featureTagName == expectedStats.featureTagName
3684                         && stats.registrationTech == expectedStats.registrationTech) {
3685                     actualCount++;
3686                     actualTime += stats.registeredMillis;
3687                 }
3688             }
3689         }
3690         assertEquals(expectedCount, actualCount);
3691         assertEquals(expectedTime, actualTime);
3692     }
3693 
assertHasStatsAndCount( RcsClientProvisioningStats[] statses, @Nullable RcsClientProvisioningStats expectedStats, int expectedCount)3694     private static void assertHasStatsAndCount(
3695             RcsClientProvisioningStats[] statses,
3696             @Nullable RcsClientProvisioningStats expectedStats, int expectedCount) {
3697         assertNotNull(statses);
3698         int actualCount = -1;
3699         for (RcsClientProvisioningStats stats : statses) {
3700             if (stats.carrierId == expectedStats.carrierId
3701                     && stats.slotId == expectedStats.slotId
3702                     && stats.event == expectedStats.event) {
3703                 actualCount = stats.count;
3704             }
3705         }
3706         assertEquals(expectedCount, actualCount);
3707     }
3708 
assertHasStats( ImsDedicatedBearerListenerEvent[] statses, @Nullable ImsDedicatedBearerListenerEvent expectedStats, int expectedCount)3709     private static void assertHasStats(
3710             ImsDedicatedBearerListenerEvent[] statses,
3711             @Nullable ImsDedicatedBearerListenerEvent expectedStats, int expectedCount) {
3712         assertNotNull(statses);
3713         int actualCount = 0;
3714         for (ImsDedicatedBearerListenerEvent stats : statses) {
3715             if (stats != null && expectedStats != null) {
3716                 if (MessageNano.messageNanoEquals(stats, expectedStats)) {
3717                     actualCount++;
3718                 }
3719             }
3720         }
3721         assertEquals(expectedCount, actualCount);
3722     }
3723 
assertHasStatsAndCount( ImsDedicatedBearerEvent[] statses, @Nullable ImsDedicatedBearerEvent expectedStats, int expectedCount)3724     private static void assertHasStatsAndCount(
3725             ImsDedicatedBearerEvent[] statses,
3726             @Nullable ImsDedicatedBearerEvent expectedStats, int expectedCount) {
3727         assertNotNull(statses);
3728         int actualCount = -1;
3729         for (ImsDedicatedBearerEvent stats : statses) {
3730             if (stats.carrierId == expectedStats.carrierId
3731                     && stats.slotId == expectedStats.slotId
3732                     && stats.ratAtEnd == expectedStats.ratAtEnd
3733                     && stats.qci == expectedStats.qci
3734                     && stats.bearerState == expectedStats.bearerState
3735                     && stats.localConnectionInfoReceived
3736                             == expectedStats.localConnectionInfoReceived
3737                     && stats.remoteConnectionInfoReceived
3738                             == expectedStats.remoteConnectionInfoReceived
3739                     && stats.hasListeners == expectedStats.hasListeners) {
3740                 actualCount = stats.count;
3741             }
3742         }
3743         assertEquals(expectedCount, actualCount);
3744     }
3745 
assertHasStatsAndCountDuration( RcsAcsProvisioningStats[] statses, @Nullable RcsAcsProvisioningStats expectedStats, int count, long duration)3746     private static void assertHasStatsAndCountDuration(
3747             RcsAcsProvisioningStats[] statses,
3748             @Nullable RcsAcsProvisioningStats expectedStats, int count, long duration) {
3749         assertNotNull(statses);
3750         int actualCount = -1;
3751         long actualDuration = -1;
3752         for (RcsAcsProvisioningStats stats : statses) {
3753             if (stats.carrierId == expectedStats.carrierId
3754                     && stats.slotId == expectedStats.slotId
3755                     && stats.responseCode == expectedStats.responseCode
3756                     && stats.responseType == expectedStats.responseType
3757                     && stats.isSingleRegistrationEnabled
3758                             == expectedStats.isSingleRegistrationEnabled) {
3759                 actualCount = stats.count;
3760                 actualDuration = stats.stateTimerMillis;
3761             }
3762         }
3763         assertEquals(count, actualCount);
3764         assertEquals(duration, actualDuration);
3765     }
3766 
assertHasStats(SipDelegateStats[] results, Object expectedStats, int expectedCount)3767     private static void assertHasStats(SipDelegateStats[] results,
3768             Object expectedStats, int expectedCount) {
3769         assertNotNull(results);
3770         assertNotNull(expectedStats);
3771 
3772         int realCount = 0;
3773         if (expectedStats instanceof SipDelegateStats[]) {
3774             SipDelegateStats[] expectedResults = (SipDelegateStats[]) expectedStats;
3775             for (SipDelegateStats stat: results) {
3776                 for (SipDelegateStats estat : expectedResults) {
3777                     if (stat != null && estat != null) {
3778                         if (MessageNano.messageNanoEquals(stat, estat)) {
3779                             realCount++;
3780                             break;
3781                         }
3782                     }
3783                 }
3784             }
3785         } else {
3786             SipDelegateStats expectedResult = (SipDelegateStats) expectedStats;
3787             for (SipDelegateStats stat : results) {
3788                 if (stat != null && expectedStats != null) {
3789                     if (MessageNano.messageNanoEquals(stat, expectedResult)) {
3790                         realCount++;
3791                     }
3792                 }
3793             }
3794         }
3795         assertEquals(expectedCount, realCount);
3796     }
3797 
assertHasStats(SipTransportFeatureTagStats[] results, Object expectedStats, int expectedCount)3798     private static void assertHasStats(SipTransportFeatureTagStats[] results,
3799             Object expectedStats, int expectedCount) {
3800         assertNotNull(results);
3801         assertNotNull(expectedStats);
3802 
3803         int realCount = 0;
3804         if (expectedStats instanceof SipTransportFeatureTagStats[]) {
3805             SipTransportFeatureTagStats[] expectedResults =
3806                     (SipTransportFeatureTagStats[]) expectedStats;
3807             for (SipTransportFeatureTagStats stat: results) {
3808                 for (SipTransportFeatureTagStats estat : expectedResults) {
3809                     if (stat != null && estat != null) {
3810                         if (MessageNano.messageNanoEquals(stat, estat)) {
3811                             realCount++;
3812                             break;
3813                         }
3814                     }
3815                 }
3816             }
3817         } else {
3818             SipTransportFeatureTagStats expectedResult =
3819                     (SipTransportFeatureTagStats) expectedStats;
3820             for (SipTransportFeatureTagStats stat : results) {
3821                 if (stat != null && expectedStats != null) {
3822                     if (MessageNano.messageNanoEquals(stat, expectedResult)) {
3823                         realCount++;
3824                     }
3825                 }
3826             }
3827         }
3828         assertEquals(expectedCount, realCount);
3829     }
3830 
assertHasStatsAndCount( GbaEvent[] statses, @Nullable GbaEvent expectedStats, int expectedCount)3831     private static void assertHasStatsAndCount(
3832             GbaEvent[] statses,
3833             @Nullable GbaEvent expectedStats, int expectedCount) {
3834         assertNotNull(statses);
3835         int actualCount = -1;
3836         for (GbaEvent stats : statses) {
3837             if (stats.carrierId == expectedStats.carrierId
3838                     && stats.slotId == expectedStats.slotId
3839                     && stats.successful == expectedStats.successful
3840                     && stats.failedReason == expectedStats.failedReason) {
3841                 actualCount = stats.count;
3842             }
3843         }
3844         assertEquals(expectedCount, actualCount);
3845     }
3846 
assertHasStats( SipMessageResponse[] statses, @Nullable SipMessageResponse expectedStats, int expectedCount)3847     private static void assertHasStats(
3848             SipMessageResponse[] statses,
3849             @Nullable SipMessageResponse expectedStats, int expectedCount) {
3850         assertNotNull(statses);
3851         int actualCount = -1;
3852         for (SipMessageResponse stats : statses) {
3853             if (stats.carrierId == expectedStats.carrierId
3854                     && stats.slotId == expectedStats.slotId
3855                     && stats.sipMessageMethod == expectedStats.sipMessageMethod
3856                     && stats.sipMessageResponse == expectedStats.sipMessageResponse
3857                     && stats.sipMessageDirection == expectedStats.sipMessageDirection) {
3858                 actualCount = stats.count;
3859             }
3860         }
3861         assertEquals(expectedCount, actualCount);
3862     }
3863 
assertHasStats( SipTransportSession[] statses, @Nullable SipTransportSession expectedStats, int expectedCount)3864     private static void assertHasStats(
3865             SipTransportSession[] statses,
3866             @Nullable SipTransportSession expectedStats, int expectedCount) {
3867         assertNotNull(statses);
3868         int actualCount = -1;
3869         for (SipTransportSession stats : statses) {
3870             if (stats.carrierId == expectedStats.carrierId
3871                     && stats.slotId == expectedStats.slotId
3872                     && stats.sessionMethod == expectedStats.sessionMethod
3873                     && stats.sipMessageDirection == expectedStats.sipMessageDirection
3874                     && stats.sipResponse == expectedStats.sipResponse) {
3875                 actualCount = stats.sessionCount;
3876             }
3877         }
3878         assertEquals(expectedCount, actualCount);
3879     }
3880 }
3881