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