1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.telephony.metrics;
18 
19 import static com.android.internal.telephony.TelephonyStatsLog.CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS;
20 import static com.android.internal.telephony.TelephonyStatsLog.CARRIER_ROAMING_SATELLITE_SESSION;
21 import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_DATA_SERVICE_SWITCH;
22 import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_SERVICE_STATE;
23 import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SHORT_CODE_SMS;
24 import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_CONFIG_UPDATER;
25 import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_ENTITLEMENT;
26 import static com.android.internal.telephony.TelephonyStatsLog.SIM_SLOT_STATE;
27 import static com.android.internal.telephony.TelephonyStatsLog.SUPPORTED_RADIO_ACCESS_FAMILY;
28 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_RAT_USAGE;
29 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION;
30 import static com.android.internal.telephony.util.TelephonyUtils.IS_DEBUGGABLE;
31 
32 import static com.google.common.truth.Truth.assertThat;
33 
34 import static org.mockito.Mockito.anyLong;
35 import static org.mockito.Mockito.doReturn;
36 import static org.mockito.Mockito.eq;
37 import static org.mockito.Mockito.mock;
38 import static org.mockito.Mockito.times;
39 import static org.mockito.Mockito.verify;
40 import static org.mockito.Mockito.verifyNoMoreInteractions;
41 
42 import android.app.StatsManager;
43 import android.telephony.TelephonyManager;
44 import android.util.StatsEvent;
45 
46 import androidx.test.filters.SmallTest;
47 
48 import com.android.internal.telephony.Phone;
49 import com.android.internal.telephony.PhoneFactory;
50 import com.android.internal.telephony.TelephonyTest;
51 import com.android.internal.telephony.flags.FeatureFlags;
52 import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteControllerStats;
53 import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteSession;
54 import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch;
55 import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState;
56 import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingShortCodeSms;
57 import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteConfigUpdater;
58 import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteEntitlement;
59 import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallRatUsage;
60 import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallSession;
61 import com.android.internal.telephony.uicc.IccCardStatus.CardState;
62 import com.android.internal.telephony.uicc.UiccCard;
63 import com.android.internal.telephony.uicc.UiccController;
64 import com.android.internal.telephony.uicc.UiccPort;
65 import com.android.internal.telephony.uicc.UiccProfile;
66 import com.android.internal.telephony.uicc.UiccSlot;
67 
68 import org.junit.After;
69 import org.junit.Before;
70 import org.junit.Test;
71 
72 import java.util.ArrayList;
73 import java.util.List;
74 
75 public class MetricsCollectorTest extends TelephonyTest {
76     private static final StatsManager.PullAtomMetadata POLICY_PULL_DAILY =
77             new StatsManager.PullAtomMetadata.Builder()
78                     .setCoolDownMillis(24L * 3600L * 1000L)
79                     .build();
80     private static final long MIN_COOLDOWN_MILLIS = 23L * 3600L * 1000L;
81     private static final long POWER_CORRELATED_MIN_COOLDOWN_MILLIS =
82             IS_DEBUGGABLE ? 4L *  60L * 1000L : 5L * 3600L * 1000L;
83     private static final long MIN_CALLS_PER_BUCKET = 5L;
84 
85     // NOTE: these fields are currently 32-bit internally and padded to 64-bit by TelephonyManager
86     private static final int SUPPORTED_RAF_1 =
87             (int) TelephonyManager.NETWORK_TYPE_BITMASK_GSM
88                     | (int) TelephonyManager.NETWORK_TYPE_BITMASK_LTE
89                     | (int) TelephonyManager.NETWORK_TYPE_BITMASK_NR;
90     private static final int SUPPORTED_RAF_2 =
91             (int) TelephonyManager.NETWORK_TYPE_BITMASK_GSM
92                     | (int) TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT
93                     | (int) TelephonyManager.NETWORK_TYPE_BITMASK_UMTS;
94     private static final int SUPPORTED_RAF_BOTH = SUPPORTED_RAF_1 | SUPPORTED_RAF_2;
95 
96     // TODO: if we want to check puller registration by mocking StatsManager, we will have to enable
97     // inline mocking since the StatsManager class is final
98 
99     // b/153195691: we cannot verify the contents of StatsEvent as its getters are marked with @hide
100 
101     // Mocked classes
102     private Phone mSecondPhone;
103     private UiccSlot mPhysicalSlot;
104     private UiccSlot mEsimSlot;
105     private UiccCard mActiveCard;
106     private UiccPort mActivePort;
107     private ServiceStateStats mServiceStateStats;
108     private VonrHelper mVonrHelper;
109     private FeatureFlags mFeatureFlags;
110 
111     private MetricsCollector mMetricsCollector;
112 
113     @Before
setUp()114     public void setUp() throws Exception {
115         super.setUp(getClass().getSimpleName());
116         mSecondPhone = mock(Phone.class);
117         mPhysicalSlot = mock(UiccSlot.class);
118         mEsimSlot = mock(UiccSlot.class);
119         mActiveCard = mock(UiccCard.class);
120         mActivePort = mock(UiccPort.class);
121         mServiceStateStats = mock(ServiceStateStats.class);
122         mVonrHelper = mock(VonrHelper.class);
123         mFeatureFlags = mock(FeatureFlags.class);
124         mMetricsCollector =
125                 new MetricsCollector(mContext, mPersistAtomsStorage,
126                         mDeviceStateHelper, mVonrHelper, mDefaultNetworkMonitor, mFeatureFlags);
127         doReturn(mSST).when(mSecondPhone).getServiceStateTracker();
128         doReturn(mServiceStateStats).when(mSST).getServiceStateStats();
129     }
130 
131     @After
tearDown()132     public void tearDown() throws Exception {
133         mMetricsCollector = null;
134         super.tearDown();
135     }
136 
137     @Test
138     @SmallTest
onPullAtom_simSlotState_bothSimPresent()139     public void onPullAtom_simSlotState_bothSimPresent() {
140         // these have been tested extensively in SimSlotStateTest, here we verify atom generation
141         UiccProfile activeProfile = mock(UiccProfile.class);
142         doReturn(4).when(activeProfile).getNumApplications();
143         doReturn(activeProfile).when(mActivePort).getUiccProfile();
144         doReturn(true).when(mPhysicalSlot).isActive();
145         doReturn(CardState.CARDSTATE_PRESENT).when(mPhysicalSlot).getCardState();
146         doReturn(false).when(mPhysicalSlot).isEuicc();
147         doReturn(true).when(mEsimSlot).isActive();
148         doReturn(CardState.CARDSTATE_PRESENT).when(mEsimSlot).getCardState();
149         doReturn(true).when(mEsimSlot).isEuicc();
150         doReturn(mActiveCard).when(mEsimSlot).getUiccCard();
151         doReturn(new UiccPort[] {mActivePort}).when(mActiveCard).getUiccPortList();
152         doReturn(new UiccSlot[] {mPhysicalSlot, mEsimSlot}).when(mUiccController).getUiccSlots();
153         doReturn(mPhysicalSlot).when(mUiccController).getUiccSlot(eq(0));
154         doReturn(mEsimSlot).when(mUiccController).getUiccSlot(eq(1));
155         StatsEvent expectedAtom =
156                 StatsEvent.newBuilder()
157                         .setAtomId(SIM_SLOT_STATE)
158                         .writeInt(2)
159                         .writeInt(2)
160                         .writeInt(1)
161                         .build();
162         List<StatsEvent> actualAtoms = new ArrayList<>();
163 
164         int result = mMetricsCollector.onPullAtom(SIM_SLOT_STATE, actualAtoms);
165 
166         assertThat(actualAtoms).hasSize(1);
167         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
168         // TODO(b/153196254): verify atom contents
169     }
170 
171     @Test
172     @SmallTest
onPullAtom_simSlotState_beforeUiccControllerReady()173     public void onPullAtom_simSlotState_beforeUiccControllerReady() throws Exception {
174         // there is a slight chance that MetricsCollector gets pulled after registration while
175         // PhoneFactory havne't made UiccController yet, RuntimeException will be thrown
176         replaceInstance(UiccController.class, "mInstance", mUiccController, null);
177         List<StatsEvent> actualAtoms = new ArrayList<>();
178 
179         int result = mMetricsCollector.onPullAtom(SIM_SLOT_STATE, actualAtoms);
180 
181         assertThat(actualAtoms).hasSize(0);
182         assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
183     }
184 
185     @Test
186     @SmallTest
onPullAtom_supportedRadioAccessFamily_singlePhone()187     public void onPullAtom_supportedRadioAccessFamily_singlePhone() {
188         doReturn(SUPPORTED_RAF_1).when(mPhone).getRadioAccessFamily();
189         StatsEvent expectedAtom =
190                 StatsEvent.newBuilder()
191                         .setAtomId(SUPPORTED_RADIO_ACCESS_FAMILY)
192                         .writeLong(SUPPORTED_RAF_1)
193                         .build();
194         List<StatsEvent> actualAtoms = new ArrayList<>();
195 
196         int result = mMetricsCollector.onPullAtom(SUPPORTED_RADIO_ACCESS_FAMILY, actualAtoms);
197 
198         assertThat(actualAtoms).hasSize(1);
199         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
200         // TODO(b/153196254): verify atom contents
201     }
202 
203     @Test
204     @SmallTest
onPullAtom_supportedRadioAccessFamily_dualPhones()205     public void onPullAtom_supportedRadioAccessFamily_dualPhones() {
206         doReturn(SUPPORTED_RAF_1).when(mPhone).getRadioAccessFamily();
207         doReturn(SUPPORTED_RAF_2).when(mSecondPhone).getRadioAccessFamily();
208         mPhones = new Phone[] {mPhone, mSecondPhone};
209         StatsEvent expectedAtom =
210                 StatsEvent.newBuilder()
211                         .setAtomId(SUPPORTED_RADIO_ACCESS_FAMILY)
212                         .writeLong(SUPPORTED_RAF_BOTH)
213                         .build();
214         List<StatsEvent> actualAtoms = new ArrayList<>();
215 
216         int result = mMetricsCollector.onPullAtom(SUPPORTED_RADIO_ACCESS_FAMILY, actualAtoms);
217 
218         assertThat(actualAtoms).hasSize(1);
219         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
220         // TODO(b/153196254): verify atom contents
221     }
222 
223     @Test
224     @SmallTest
onPullAtom_supportedRadioAccessFamily_dualPhonesWithUnknownRaf()225     public void onPullAtom_supportedRadioAccessFamily_dualPhonesWithUnknownRaf() {
226         doReturn(SUPPORTED_RAF_1).when(mPhone).getRadioAccessFamily();
227         doReturn((int) TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN)
228                 .when(mSecondPhone)
229                 .getRadioAccessFamily();
230         mPhones = new Phone[] {mPhone, mSecondPhone};
231         StatsEvent expectedAtom =
232                 StatsEvent.newBuilder()
233                         .setAtomId(SUPPORTED_RADIO_ACCESS_FAMILY)
234                         .writeLong(SUPPORTED_RAF_1)
235                         .build();
236         List<StatsEvent> actualAtoms = new ArrayList<>();
237 
238         int result = mMetricsCollector.onPullAtom(SUPPORTED_RADIO_ACCESS_FAMILY, actualAtoms);
239 
240         assertThat(actualAtoms).hasSize(1);
241         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
242         // TODO(b/153196254): verify atom contents
243     }
244 
245     @Test
246     @SmallTest
onPullAtom_supportedRadioAccessFamily_beforePhoneReady()247     public void onPullAtom_supportedRadioAccessFamily_beforePhoneReady() throws Exception {
248         replaceInstance(PhoneFactory.class, "sMadeDefaults", true, false);
249         List<StatsEvent> actualAtoms = new ArrayList<>();
250 
251         int result = mMetricsCollector.onPullAtom(SUPPORTED_RADIO_ACCESS_FAMILY, actualAtoms);
252 
253         assertThat(actualAtoms).hasSize(0);
254         assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
255     }
256 
257     @Test
258     @SmallTest
onPullAtom_voiceCallRatUsage_empty()259     public void onPullAtom_voiceCallRatUsage_empty() throws Exception {
260         doReturn(new VoiceCallRatUsage[0])
261                 .when(mPersistAtomsStorage)
262                 .getVoiceCallRatUsages(anyLong());
263         List<StatsEvent> actualAtoms = new ArrayList<>();
264 
265         int result = mMetricsCollector.onPullAtom(VOICE_CALL_RAT_USAGE, actualAtoms);
266 
267         assertThat(actualAtoms).hasSize(0);
268         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
269     }
270 
271     @Test
272     @SmallTest
onPullAtom_voiceCallRatUsage_tooFrequent()273     public void onPullAtom_voiceCallRatUsage_tooFrequent() throws Exception {
274         doReturn(null).when(mPersistAtomsStorage).getVoiceCallRatUsages(anyLong());
275         List<StatsEvent> actualAtoms = new ArrayList<>();
276 
277         int result = mMetricsCollector.onPullAtom(VOICE_CALL_RAT_USAGE, actualAtoms);
278 
279         assertThat(actualAtoms).hasSize(0);
280         assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
281         verify(mPersistAtomsStorage, times(1)).getVoiceCallRatUsages(eq(MIN_COOLDOWN_MILLIS));
282         verifyNoMoreInteractions(mPersistAtomsStorage);
283     }
284 
285     @Test
286     @SmallTest
onPullAtom_voiceCallRatUsage_bucketWithTooFewCalls()287     public void onPullAtom_voiceCallRatUsage_bucketWithTooFewCalls() throws Exception {
288         VoiceCallRatUsage usage1 = new VoiceCallRatUsage();
289         usage1.callCount = MIN_CALLS_PER_BUCKET;
290         VoiceCallRatUsage usage2 = new VoiceCallRatUsage();
291         usage2.callCount = MIN_CALLS_PER_BUCKET - 1L;
292         doReturn(new VoiceCallRatUsage[] {usage1, usage1, usage1, usage2})
293                 .when(mPersistAtomsStorage)
294                 .getVoiceCallRatUsages(anyLong());
295         List<StatsEvent> actualAtoms = new ArrayList<>();
296 
297         int result = mMetricsCollector.onPullAtom(VOICE_CALL_RAT_USAGE, actualAtoms);
298 
299         assertThat(actualAtoms).hasSize(3); // usage 2 should be dropped
300         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
301         // TODO(b/153196254): verify atom contents
302     }
303 
304     @Test
305     @SmallTest
onPullAtom_voiceCallSession_empty()306     public void onPullAtom_voiceCallSession_empty() throws Exception {
307         doReturn(new VoiceCallSession[0])
308                 .when(mPersistAtomsStorage)
309                 .getVoiceCallSessions(anyLong());
310         List<StatsEvent> actualAtoms = new ArrayList<>();
311 
312         int result = mMetricsCollector.onPullAtom(VOICE_CALL_SESSION, actualAtoms);
313 
314         assertThat(actualAtoms).hasSize(0);
315         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
316     }
317 
318     @Test
319     @SmallTest
onPullAtom_voiceCallSession_tooFrequent()320     public void onPullAtom_voiceCallSession_tooFrequent() throws Exception {
321         doReturn(null).when(mPersistAtomsStorage).getVoiceCallSessions(anyLong());
322         List<StatsEvent> actualAtoms = new ArrayList<>();
323 
324         int result = mMetricsCollector.onPullAtom(VOICE_CALL_SESSION, actualAtoms);
325 
326         assertThat(actualAtoms).hasSize(0);
327         assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
328         verify(mPersistAtomsStorage, times(1)).getVoiceCallSessions(eq(MIN_COOLDOWN_MILLIS));
329         verifyNoMoreInteractions(mPersistAtomsStorage);
330     }
331 
332     @Test
333     @SmallTest
onPullAtom_voiceCallSession_multipleCalls()334     public void onPullAtom_voiceCallSession_multipleCalls() throws Exception {
335         VoiceCallSession call = new VoiceCallSession();
336         doReturn(new VoiceCallSession[] {call, call, call, call})
337                 .when(mPersistAtomsStorage)
338                 .getVoiceCallSessions(anyLong());
339         List<StatsEvent> actualAtoms = new ArrayList<>();
340 
341         int result = mMetricsCollector.onPullAtom(VOICE_CALL_SESSION, actualAtoms);
342 
343         assertThat(actualAtoms).hasSize(4);
344         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
345         // TODO(b/153196254): verify atom contents
346     }
347 
348     @Test
349     @SmallTest
onPullAtom_cellularDataServiceSwitch_empty()350     public void onPullAtom_cellularDataServiceSwitch_empty() throws Exception {
351         doReturn(new CellularDataServiceSwitch[0])
352                 .when(mPersistAtomsStorage)
353                 .getCellularDataServiceSwitches(anyLong());
354         List<StatsEvent> actualAtoms = new ArrayList<>();
355 
356         int result = mMetricsCollector.onPullAtom(CELLULAR_DATA_SERVICE_SWITCH, actualAtoms);
357 
358         assertThat(actualAtoms).hasSize(0);
359         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
360         // TODO(b/153196254): verify atom contents
361     }
362 
363     @Test
364     @SmallTest
onPullAtom_cellularDataServiceSwitch_tooFrequent()365     public void onPullAtom_cellularDataServiceSwitch_tooFrequent() throws Exception {
366         doReturn(null).when(mPersistAtomsStorage).getCellularDataServiceSwitches(anyLong());
367         List<StatsEvent> actualAtoms = new ArrayList<>();
368 
369         int result = mMetricsCollector.onPullAtom(CELLULAR_DATA_SERVICE_SWITCH, actualAtoms);
370 
371         assertThat(actualAtoms).hasSize(0);
372         assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
373         verify(mPersistAtomsStorage, times(1))
374                 .getCellularDataServiceSwitches(eq(MIN_COOLDOWN_MILLIS));
375         verifyNoMoreInteractions(mPersistAtomsStorage);
376     }
377 
378     @Test
379     @SmallTest
onPullAtom_cellularDataServiceSwitch_multipleSwitches()380     public void onPullAtom_cellularDataServiceSwitch_multipleSwitches() throws Exception {
381         CellularDataServiceSwitch serviceSwitch = new CellularDataServiceSwitch();
382         doReturn(new CellularDataServiceSwitch[] {serviceSwitch, serviceSwitch, serviceSwitch})
383                 .when(mPersistAtomsStorage)
384                 .getCellularDataServiceSwitches(anyLong());
385         List<StatsEvent> actualAtoms = new ArrayList<>();
386 
387         int result = mMetricsCollector.onPullAtom(CELLULAR_DATA_SERVICE_SWITCH, actualAtoms);
388 
389         assertThat(actualAtoms).hasSize(3);
390         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
391         // TODO(b/153196254): verify atom contents
392     }
393 
394     @Test
395     @SmallTest
onPullAtom_cellularServiceState_empty()396     public void onPullAtom_cellularServiceState_empty() throws Exception {
397         doReturn(new CellularServiceState[0])
398                 .when(mPersistAtomsStorage)
399                 .getCellularServiceStates(anyLong());
400         List<StatsEvent> actualAtoms = new ArrayList<>();
401 
402         int result = mMetricsCollector.onPullAtom(CELLULAR_SERVICE_STATE, actualAtoms);
403 
404         assertThat(actualAtoms).hasSize(0);
405         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
406         // TODO(b/153196254): verify atom contents
407     }
408 
409     @Test
410     @SmallTest
onPullAtom_cellularServiceState_tooFrequent()411     public void onPullAtom_cellularServiceState_tooFrequent() throws Exception {
412         doReturn(null).when(mPersistAtomsStorage).getCellularServiceStates(anyLong());
413         mContextFixture.putIntResource(
414                 com.android.internal.R.integer.config_metrics_pull_cooldown_millis,
415                 (int) POWER_CORRELATED_MIN_COOLDOWN_MILLIS);
416         List<StatsEvent> actualAtoms = new ArrayList<>();
417 
418         int result = mMetricsCollector.onPullAtom(CELLULAR_SERVICE_STATE, actualAtoms);
419 
420         assertThat(actualAtoms).hasSize(0);
421         assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
422         verify(mPersistAtomsStorage, times(1)).getCellularServiceStates(
423                 eq(POWER_CORRELATED_MIN_COOLDOWN_MILLIS));
424         verifyNoMoreInteractions(mPersistAtomsStorage);
425     }
426 
427     @Test
428     @SmallTest
onPullAtom_cellularServiceState_multipleStates()429     public void onPullAtom_cellularServiceState_multipleStates() throws Exception {
430         CellularServiceState state = new CellularServiceState();
431         doReturn(new CellularServiceState[] {state, state, state})
432                 .when(mPersistAtomsStorage)
433                 .getCellularServiceStates(anyLong());
434         List<StatsEvent> actualAtoms = new ArrayList<>();
435 
436         int result = mMetricsCollector.onPullAtom(CELLULAR_SERVICE_STATE, actualAtoms);
437 
438         assertThat(actualAtoms).hasSize(3);
439         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
440         // TODO(b/153196254): verify atom contents
441     }
442 
443     @Test
onPullAtom_outgoingShortCodeSms_empty()444     public void onPullAtom_outgoingShortCodeSms_empty() {
445         doReturn(new OutgoingShortCodeSms[0]).when(mPersistAtomsStorage)
446                 .getOutgoingShortCodeSms(anyLong());
447         List<StatsEvent> actualAtoms = new ArrayList<>();
448 
449         int result = mMetricsCollector.onPullAtom(OUTGOING_SHORT_CODE_SMS, actualAtoms);
450 
451         assertThat(actualAtoms).hasSize(0);
452         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
453     }
454 
455     @Test
onPullAtom_outgoingShortCodeSms_tooFrequent()456     public void onPullAtom_outgoingShortCodeSms_tooFrequent() {
457         doReturn(null).when(mPersistAtomsStorage).getOutgoingShortCodeSms(anyLong());
458         List<StatsEvent> actualAtoms = new ArrayList<>();
459 
460         int result = mMetricsCollector.onPullAtom(OUTGOING_SHORT_CODE_SMS, actualAtoms);
461 
462         assertThat(actualAtoms).hasSize(0);
463         assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
464         verify(mPersistAtomsStorage, times(1))
465                 .getOutgoingShortCodeSms(eq(MIN_COOLDOWN_MILLIS));
466         verifyNoMoreInteractions(mPersistAtomsStorage);
467     }
468 
469     @Test
onPullAtom_outgoingShortCodeSms_multipleSms()470     public void onPullAtom_outgoingShortCodeSms_multipleSms() {
471         OutgoingShortCodeSms outgoingShortCodeSms = new OutgoingShortCodeSms();
472         doReturn(new OutgoingShortCodeSms[] {outgoingShortCodeSms, outgoingShortCodeSms,
473                 outgoingShortCodeSms, outgoingShortCodeSms})
474                 .when(mPersistAtomsStorage)
475                 .getOutgoingShortCodeSms(anyLong());
476         List<StatsEvent> actualAtoms = new ArrayList<>();
477 
478         int result = mMetricsCollector.onPullAtom(OUTGOING_SHORT_CODE_SMS, actualAtoms);
479 
480         assertThat(actualAtoms).hasSize(4);
481         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
482     }
483 
484     @Test
onPullAtom_carrierRoamingSatelliteSession_empty()485     public void onPullAtom_carrierRoamingSatelliteSession_empty() {
486         doReturn(new CarrierRoamingSatelliteSession[0]).when(mPersistAtomsStorage)
487                 .getCarrierRoamingSatelliteSessionStats(anyLong());
488         List<StatsEvent> actualAtoms = new ArrayList<>();
489 
490         int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_SESSION, actualAtoms);
491 
492         assertThat(actualAtoms).hasSize(0);
493         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
494     }
495 
496     @Test
onPullAtom_carrierRoamingSatelliteSession_tooFrequent()497     public void onPullAtom_carrierRoamingSatelliteSession_tooFrequent() {
498         doReturn(null).when(mPersistAtomsStorage)
499                 .getCarrierRoamingSatelliteSessionStats(anyLong());
500         List<StatsEvent> actualAtoms = new ArrayList<>();
501 
502         int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_SESSION, actualAtoms);
503 
504         assertThat(actualAtoms).hasSize(0);
505         assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
506         verify(mPersistAtomsStorage, times(1))
507                 .getCarrierRoamingSatelliteSessionStats(eq(MIN_COOLDOWN_MILLIS));
508         verifyNoMoreInteractions(mPersistAtomsStorage);
509     }
510 
511     @Test
onPullAtom_carrierRoamingSatelliteSession_multipleAtoms()512     public void onPullAtom_carrierRoamingSatelliteSession_multipleAtoms() {
513         CarrierRoamingSatelliteSession carrierRoamingSatelliteSession =
514                 new CarrierRoamingSatelliteSession();
515         doReturn(new CarrierRoamingSatelliteSession[] {carrierRoamingSatelliteSession,
516                 carrierRoamingSatelliteSession, carrierRoamingSatelliteSession,
517                 carrierRoamingSatelliteSession})
518                 .when(mPersistAtomsStorage)
519                 .getCarrierRoamingSatelliteSessionStats(anyLong());
520         List<StatsEvent> actualAtoms = new ArrayList<>();
521 
522         int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_SESSION, actualAtoms);
523 
524         assertThat(actualAtoms).hasSize(4);
525         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
526     }
527 
528     @Test
onPullAtom_carrierRoamingSatelliteControllerStats_empty()529     public void onPullAtom_carrierRoamingSatelliteControllerStats_empty() {
530         doReturn(new CarrierRoamingSatelliteControllerStats[0]).when(mPersistAtomsStorage)
531                 .getCarrierRoamingSatelliteControllerStats(anyLong());
532         List<StatsEvent> actualAtoms = new ArrayList<>();
533 
534         int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS,
535                 actualAtoms);
536 
537         assertThat(actualAtoms).hasSize(0);
538         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
539     }
540 
541     @Test
onPullAtom_carrierRoamingSatelliteControllerStats_multipleAtoms()542     public void onPullAtom_carrierRoamingSatelliteControllerStats_multipleAtoms() {
543         CarrierRoamingSatelliteControllerStats carrierRoamingSatelliteControllerStats =
544                 new CarrierRoamingSatelliteControllerStats();
545         doReturn(new CarrierRoamingSatelliteControllerStats[] {
546                 carrierRoamingSatelliteControllerStats})
547                 .when(mPersistAtomsStorage)
548                 .getCarrierRoamingSatelliteControllerStats(anyLong());
549         List<StatsEvent> actualAtoms = new ArrayList<>();
550 
551         int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS,
552                 actualAtoms);
553 
554         assertThat(actualAtoms).hasSize(1);
555         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
556     }
557 
558     @Test
onPullAtom_carrierRoamingSatelliteControllerStats_tooFrequent()559     public void onPullAtom_carrierRoamingSatelliteControllerStats_tooFrequent() {
560         doReturn(null).when(mPersistAtomsStorage)
561                 .getCarrierRoamingSatelliteControllerStats(anyLong());
562         List<StatsEvent> actualAtoms = new ArrayList<>();
563 
564         int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS,
565                 actualAtoms);
566 
567         assertThat(actualAtoms).hasSize(0);
568         assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
569         verify(mPersistAtomsStorage, times(1))
570                 .getCarrierRoamingSatelliteControllerStats(eq(MIN_COOLDOWN_MILLIS));
571         verifyNoMoreInteractions(mPersistAtomsStorage);
572     }
573 
574     @Test
onPullAtom_satelliteEntitlement_empty()575     public void onPullAtom_satelliteEntitlement_empty() {
576         doReturn(new SatelliteEntitlement[0]).when(mPersistAtomsStorage)
577                 .getSatelliteEntitlementStats(anyLong());
578         List<StatsEvent> actualAtoms = new ArrayList<>();
579 
580         int result = mMetricsCollector.onPullAtom(SATELLITE_ENTITLEMENT, actualAtoms);
581 
582         assertThat(actualAtoms).hasSize(0);
583         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
584     }
585 
586     @Test
onPullAtom_satelliteEntitlement_tooFrequent()587     public void onPullAtom_satelliteEntitlement_tooFrequent() {
588         doReturn(null).when(mPersistAtomsStorage).getSatelliteEntitlementStats(
589                 anyLong());
590         List<StatsEvent> actualAtoms = new ArrayList<>();
591 
592         int result = mMetricsCollector.onPullAtom(SATELLITE_ENTITLEMENT, actualAtoms);
593 
594         assertThat(actualAtoms).hasSize(0);
595         assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
596         verify(mPersistAtomsStorage, times(1))
597                 .getSatelliteEntitlementStats(eq(MIN_COOLDOWN_MILLIS));
598         verifyNoMoreInteractions(mPersistAtomsStorage);
599     }
600 
601     @Test
onPullAtom_satelliteEntitlement_multipleAtoms()602     public void onPullAtom_satelliteEntitlement_multipleAtoms() {
603         SatelliteEntitlement satelliteEntitlement = new SatelliteEntitlement();
604         doReturn(new SatelliteEntitlement[] {satelliteEntitlement, satelliteEntitlement,
605                 satelliteEntitlement, satelliteEntitlement})
606                 .when(mPersistAtomsStorage)
607                 .getSatelliteEntitlementStats(anyLong());
608         List<StatsEvent> actualAtoms = new ArrayList<>();
609 
610         int result = mMetricsCollector.onPullAtom(SATELLITE_ENTITLEMENT, actualAtoms);
611 
612         assertThat(actualAtoms).hasSize(4);
613         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
614     }
615 
616     @Test
onPullAtom_satelliteConfigUpdater_empty()617     public void onPullAtom_satelliteConfigUpdater_empty() {
618         doReturn(new SatelliteConfigUpdater[0]).when(mPersistAtomsStorage)
619                 .getSatelliteConfigUpdaterStats(anyLong());
620         List<StatsEvent> actualAtoms = new ArrayList<>();
621 
622         int result = mMetricsCollector.onPullAtom(SATELLITE_CONFIG_UPDATER, actualAtoms);
623 
624         assertThat(actualAtoms).hasSize(0);
625         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
626     }
627 
628     @Test
onPullAtom_satelliteConfigUpdater_tooFrequent()629     public void onPullAtom_satelliteConfigUpdater_tooFrequent() {
630         doReturn(null).when(mPersistAtomsStorage).getSatelliteConfigUpdaterStats(
631                 anyLong());
632         List<StatsEvent> actualAtoms = new ArrayList<>();
633 
634         int result = mMetricsCollector.onPullAtom(SATELLITE_CONFIG_UPDATER, actualAtoms);
635 
636         assertThat(actualAtoms).hasSize(0);
637         assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
638         verify(mPersistAtomsStorage, times(1))
639                 .getSatelliteConfigUpdaterStats(eq(MIN_COOLDOWN_MILLIS));
640         verifyNoMoreInteractions(mPersistAtomsStorage);
641     }
642 
643     @Test
onPullAtom_satelliteConfigUpdater_multipleAtoms()644     public void onPullAtom_satelliteConfigUpdater_multipleAtoms() {
645         SatelliteConfigUpdater satelliteConfigUpdater = new SatelliteConfigUpdater();
646         doReturn(new SatelliteConfigUpdater[] {satelliteConfigUpdater, satelliteConfigUpdater,
647                 satelliteConfigUpdater, satelliteConfigUpdater})
648                 .when(mPersistAtomsStorage)
649                 .getSatelliteConfigUpdaterStats(anyLong());
650         List<StatsEvent> actualAtoms = new ArrayList<>();
651 
652         int result = mMetricsCollector.onPullAtom(SATELLITE_CONFIG_UPDATER, actualAtoms);
653 
654         assertThat(actualAtoms).hasSize(4);
655         assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
656     }
657 }
658