1 /*
2  * Copyright (C) 2022 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.server.connectivity;
18 
19 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
20 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
21 
22 import static com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
23 import static com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
24 import static com.android.testutils.HandlerUtils.visibleOnHandlerThread;
25 
26 import static org.junit.Assert.assertArrayEquals;
27 import static org.junit.Assert.assertEquals;
28 import static org.junit.Assert.assertFalse;
29 import static org.junit.Assert.assertThrows;
30 import static org.junit.Assert.assertTrue;
31 import static org.junit.Assert.fail;
32 import static org.mockito.ArgumentMatchers.any;
33 import static org.mockito.ArgumentMatchers.anyLong;
34 import static org.mockito.ArgumentMatchers.argThat;
35 import static org.mockito.ArgumentMatchers.eq;
36 import static org.mockito.Mockito.doCallRealMethod;
37 import static org.mockito.Mockito.doReturn;
38 import static org.mockito.Mockito.mock;
39 import static org.mockito.Mockito.never;
40 import static org.mockito.Mockito.times;
41 import static org.mockito.Mockito.verify;
42 
43 import android.content.BroadcastReceiver;
44 import android.content.Context;
45 import android.content.Intent;
46 import android.net.Network;
47 import android.net.NetworkCapabilities;
48 import android.net.TelephonyNetworkSpecifier;
49 import android.net.wifi.WifiInfo;
50 import android.os.Build;
51 import android.os.Handler;
52 import android.os.HandlerThread;
53 import android.telephony.SubscriptionInfo;
54 import android.telephony.SubscriptionManager;
55 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
56 import android.telephony.TelephonyManager;
57 
58 import androidx.test.filters.SmallTest;
59 
60 import com.android.metrics.DailykeepaliveInfoReported;
61 import com.android.metrics.DurationForNumOfKeepalive;
62 import com.android.metrics.DurationPerNumOfKeepalive;
63 import com.android.metrics.KeepaliveLifetimeForCarrier;
64 import com.android.metrics.KeepaliveLifetimePerCarrier;
65 import com.android.modules.utils.BackgroundThread;
66 import com.android.net.module.util.CollectionUtils;
67 import com.android.testutils.DevSdkIgnoreRule;
68 import com.android.testutils.DevSdkIgnoreRunner;
69 import com.android.testutils.HandlerUtils;
70 
71 import org.junit.After;
72 import org.junit.Before;
73 import org.junit.Rule;
74 import org.junit.Test;
75 import org.junit.runner.RunWith;
76 import org.mockito.ArgumentCaptor;
77 import org.mockito.Mock;
78 import org.mockito.MockitoAnnotations;
79 
80 import java.util.Arrays;
81 import java.util.HashSet;
82 import java.util.List;
83 import java.util.Set;
84 
85 @RunWith(DevSdkIgnoreRunner.class)
86 @SmallTest
87 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
88 public class KeepaliveStatsTrackerTest {
89     private static final int TIMEOUT_MS = 30_000;
90 
91     private static final int TEST_SLOT = 1;
92     private static final int TEST_SLOT2 = 2;
93     private static final int TEST_KEEPALIVE_INTERVAL_SEC = 10;
94     private static final int TEST_KEEPALIVE_INTERVAL2_SEC = 20;
95     private static final int TEST_SUB_ID_1 = 1;
96     private static final int TEST_SUB_ID_2 = 2;
97     private static final int TEST_CARRIER_ID_1 = 135;
98     private static final int TEST_CARRIER_ID_2 = 246;
99     private static final Network TEST_NETWORK = new Network(123);
100     private static final NetworkCapabilities TEST_NETWORK_CAPABILITIES =
101             buildCellNetworkCapabilitiesWithSubId(TEST_SUB_ID_1);
102     private static final NetworkCapabilities TEST_NETWORK_CAPABILITIES_2 =
103             buildCellNetworkCapabilitiesWithSubId(TEST_SUB_ID_2);
104     private static final int TEST_UID = 1234;
105 
buildCellNetworkCapabilitiesWithSubId(int subId)106     private static NetworkCapabilities buildCellNetworkCapabilitiesWithSubId(int subId) {
107         final TelephonyNetworkSpecifier telephonyNetworkSpecifier =
108                 new TelephonyNetworkSpecifier.Builder().setSubscriptionId(subId).build();
109         return new NetworkCapabilities.Builder()
110                 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
111                 .setNetworkSpecifier(telephonyNetworkSpecifier)
112                 .build();
113     }
114 
115     @Rule public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
116 
117     private HandlerThread mHandlerThread;
118     private Handler mTestHandler;
119 
120     private KeepaliveStatsTracker mKeepaliveStatsTracker;
121 
122     @Mock private Context mContext;
123     @Mock private KeepaliveStatsTracker.Dependencies mDependencies;
124     @Mock private SubscriptionManager mSubscriptionManager;
125 
getBroadcastReceiver()126     private BroadcastReceiver getBroadcastReceiver() {
127         final ArgumentCaptor<BroadcastReceiver> receiverCaptor =
128                 ArgumentCaptor.forClass(BroadcastReceiver.class);
129         verify(mContext).registerReceiver(
130                 receiverCaptor.capture(),
131                 argThat(intentFilter -> intentFilter.matchAction(
132                         SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED)),
133                 /* broadcastPermission= */ any(),
134                 eq(mTestHandler));
135 
136         return receiverCaptor.getValue();
137     }
138 
triggerBroadcastDefaultSubId(int subId)139     private void triggerBroadcastDefaultSubId(int subId) {
140         final Intent intent =
141                 new Intent(SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED);
142         intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
143 
144         getBroadcastReceiver().onReceive(mContext, intent);
145     }
146 
getOnSubscriptionsChangedListener()147     private OnSubscriptionsChangedListener getOnSubscriptionsChangedListener() {
148         final ArgumentCaptor<OnSubscriptionsChangedListener> listenerCaptor =
149                 ArgumentCaptor.forClass(OnSubscriptionsChangedListener.class);
150         verify(mSubscriptionManager)
151                 .addOnSubscriptionsChangedListener(any(), listenerCaptor.capture());
152         return listenerCaptor.getValue();
153     }
154 
155     private static final class KeepaliveCarrierStats {
156         public final int carrierId;
157         public final int transportTypes;
158         public final int intervalMs;
159         public final int lifetimeMs;
160         public final int activeLifetimeMs;
161 
KeepaliveCarrierStats( int carrierId, int transportTypes, int intervalMs, int lifetimeMs, int activeLifetimeMs)162         KeepaliveCarrierStats(
163                 int carrierId,
164                 int transportTypes,
165                 int intervalMs,
166                 int lifetimeMs,
167                 int activeLifetimeMs) {
168             this.carrierId = carrierId;
169             this.transportTypes = transportTypes;
170             this.intervalMs = intervalMs;
171             this.lifetimeMs = lifetimeMs;
172             this.activeLifetimeMs = activeLifetimeMs;
173         }
174 
175         // Equals method on only the key, (carrierId, tranportTypes, intervalMs)
176         @Override
equals(Object o)177         public boolean equals(Object o) {
178             if (this == o) return true;
179             if (o == null || getClass() != o.getClass()) return false;
180 
181             final KeepaliveCarrierStats that = (KeepaliveCarrierStats) o;
182 
183             return carrierId == that.carrierId && transportTypes == that.transportTypes
184                     && intervalMs == that.intervalMs;
185         }
186 
187         @Override
hashCode()188         public int hashCode() {
189             return carrierId + 3 * transportTypes + 5 * intervalMs;
190         }
191     }
192 
193     // Use the default test carrier id, transportType and keepalive interval.
getDefaultCarrierStats(int lifetimeMs, int activeLifetimeMs)194     private KeepaliveCarrierStats getDefaultCarrierStats(int lifetimeMs, int activeLifetimeMs) {
195         return new KeepaliveCarrierStats(
196                 TEST_CARRIER_ID_1,
197                 /* transportTypes= */ (1 << TRANSPORT_CELLULAR),
198                 TEST_KEEPALIVE_INTERVAL_SEC * 1000,
199                 lifetimeMs,
200                 activeLifetimeMs);
201     }
202 
mockService(String serviceName, Class<T> serviceClass, T service)203     private <T> void mockService(String serviceName, Class<T> serviceClass, T service) {
204         doReturn(serviceName).when(mContext).getSystemServiceName(serviceClass);
205         doReturn(service).when(mContext).getSystemService(serviceName);
206         if (mContext.getSystemService(serviceClass) == null) {
207             // Test is using mockito-extended
208             doCallRealMethod().when(mContext).getSystemService(serviceClass);
209         }
210     }
211 
makeSubInfoMock(int subId, int carrierId)212     private SubscriptionInfo makeSubInfoMock(int subId, int carrierId) {
213         final SubscriptionInfo subInfo = mock(SubscriptionInfo.class);
214         doReturn(subId).when(subInfo).getSubscriptionId();
215         doReturn(carrierId).when(subInfo).getCarrierId();
216         return subInfo;
217     }
218 
219     @Before
setUp()220     public void setUp() {
221         MockitoAnnotations.initMocks(this);
222         mockService(Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class,
223                 mSubscriptionManager);
224 
225         final SubscriptionInfo subInfo1 = makeSubInfoMock(TEST_SUB_ID_1, TEST_CARRIER_ID_1);
226         final SubscriptionInfo subInfo2 = makeSubInfoMock(TEST_SUB_ID_2, TEST_CARRIER_ID_2);
227 
228         doReturn(List.of(subInfo1, subInfo2))
229                 .when(mSubscriptionManager)
230                 .getActiveSubscriptionInfoList();
231 
232         mHandlerThread = new HandlerThread("KeepaliveStatsTrackerTest");
233         mHandlerThread.start();
234         mTestHandler = new Handler(mHandlerThread.getLooper());
235 
236         setElapsedRealtime(0);
237         mKeepaliveStatsTracker = new KeepaliveStatsTracker(mContext, mTestHandler, mDependencies);
238         HandlerUtils.waitForIdle(BackgroundThread.getHandler(), TIMEOUT_MS);
239 
240         // Initial onSubscriptionsChanged.
241         getOnSubscriptionsChangedListener().onSubscriptionsChanged();
242         HandlerUtils.waitForIdle(mTestHandler, TIMEOUT_MS);
243     }
244 
245     @After
tearDown()246     public void tearDown() throws Exception {
247         if (mHandlerThread != null) {
248             mHandlerThread.quitSafely();
249             mHandlerThread.join();
250         }
251     }
252 
setElapsedRealtime(long time)253     private void setElapsedRealtime(long time) {
254         doReturn(time).when(mDependencies).getElapsedRealtime();
255     }
256 
buildKeepaliveMetrics(long time)257     private DailykeepaliveInfoReported buildKeepaliveMetrics(long time) {
258         setElapsedRealtime(time);
259 
260         return visibleOnHandlerThread(
261                 mTestHandler, () -> mKeepaliveStatsTracker.buildKeepaliveMetrics());
262     }
263 
buildAndResetMetrics(long time)264     private DailykeepaliveInfoReported buildAndResetMetrics(long time) {
265         setElapsedRealtime(time);
266 
267         return visibleOnHandlerThread(
268                 mTestHandler, () -> mKeepaliveStatsTracker.buildAndResetMetrics());
269     }
270 
onStartKeepalive(long time, int slot)271     private void onStartKeepalive(long time, int slot) {
272         onStartKeepalive(time, slot, TEST_KEEPALIVE_INTERVAL_SEC);
273     }
274 
onStartKeepalive(long time, int slot, int intervalSeconds)275     private void onStartKeepalive(long time, int slot, int intervalSeconds) {
276         onStartKeepalive(time, slot, TEST_NETWORK_CAPABILITIES, intervalSeconds);
277     }
278 
onStartKeepalive(long time, int slot, NetworkCapabilities nc)279     private void onStartKeepalive(long time, int slot, NetworkCapabilities nc) {
280         onStartKeepalive(time, slot, nc, TEST_KEEPALIVE_INTERVAL_SEC);
281     }
282 
onStartKeepalive( long time, int slot, NetworkCapabilities nc, int intervalSeconds)283     private void onStartKeepalive(
284             long time, int slot, NetworkCapabilities nc, int intervalSeconds) {
285         onStartKeepalive(time, slot, nc, intervalSeconds, TEST_UID, /* isAutoKeepalive= */ true);
286     }
287 
onStartKeepalive(long time, int slot, NetworkCapabilities nc, int intervalSeconds, int uid, boolean isAutoKeepalive)288     private void onStartKeepalive(long time, int slot, NetworkCapabilities nc, int intervalSeconds,
289             int uid, boolean isAutoKeepalive) {
290         setElapsedRealtime(time);
291         visibleOnHandlerThread(mTestHandler, () ->
292                 mKeepaliveStatsTracker.onStartKeepalive(TEST_NETWORK, slot, nc, intervalSeconds,
293                         uid, isAutoKeepalive));
294     }
295 
onPauseKeepalive(long time, int slot)296     private void onPauseKeepalive(long time, int slot) {
297         setElapsedRealtime(time);
298         visibleOnHandlerThread(
299                 mTestHandler, () -> mKeepaliveStatsTracker.onPauseKeepalive(TEST_NETWORK, slot));
300     }
301 
onResumeKeepalive(long time, int slot)302     private void onResumeKeepalive(long time, int slot) {
303         setElapsedRealtime(time);
304         visibleOnHandlerThread(
305                 mTestHandler, () -> mKeepaliveStatsTracker.onResumeKeepalive(TEST_NETWORK, slot));
306     }
307 
onStopKeepalive(long time, int slot)308     private void onStopKeepalive(long time, int slot) {
309         setElapsedRealtime(time);
310         visibleOnHandlerThread(
311                 mTestHandler, () -> mKeepaliveStatsTracker.onStopKeepalive(TEST_NETWORK, slot));
312     }
313 
314     @Test
testEnsureRunningOnHandlerThread()315     public void testEnsureRunningOnHandlerThread() {
316         // Not running on handler thread
317         assertThrows(
318                 IllegalStateException.class,
319                 () -> mKeepaliveStatsTracker.onStartKeepalive(
320                         TEST_NETWORK,
321                         TEST_SLOT,
322                         TEST_NETWORK_CAPABILITIES,
323                         TEST_KEEPALIVE_INTERVAL_SEC,
324                         TEST_UID,
325                         /* isAutoKeepalive */ true));
326         assertThrows(
327                 IllegalStateException.class,
328                 () -> mKeepaliveStatsTracker.onPauseKeepalive(TEST_NETWORK, TEST_SLOT));
329         assertThrows(
330                 IllegalStateException.class,
331                 () -> mKeepaliveStatsTracker.onResumeKeepalive(TEST_NETWORK, TEST_SLOT));
332         assertThrows(
333                 IllegalStateException.class,
334                 () -> mKeepaliveStatsTracker.onStopKeepalive(TEST_NETWORK, TEST_SLOT));
335         assertThrows(
336                 IllegalStateException.class, () -> mKeepaliveStatsTracker.buildKeepaliveMetrics());
337         assertThrows(
338                 IllegalStateException.class, () -> mKeepaliveStatsTracker.buildAndResetMetrics());
339     }
340 
341     /**
342      * Asserts that a DurationPerNumOfKeepalive contains expected values
343      *
344      * @param expectRegisteredDurations integer array where the index is the number of concurrent
345      *     keepalives and the value is the expected duration of time that the tracker is in a state
346      *     with the given number of keepalives registered.
347      * @param expectActiveDurations integer array where the index is the number of concurrent
348      *     keepalives and the value is the expected duration of time that the tracker is in a state
349      *     with the given number of keepalives active.
350      * @param actualDurationsPerNumOfKeepalive the DurationPerNumOfKeepalive message to assert.
351      */
assertDurationMetrics( int[] expectRegisteredDurations, int[] expectActiveDurations, DurationPerNumOfKeepalive actualDurationsPerNumOfKeepalive)352     private void assertDurationMetrics(
353             int[] expectRegisteredDurations,
354             int[] expectActiveDurations,
355             DurationPerNumOfKeepalive actualDurationsPerNumOfKeepalive) {
356         final int maxNumOfKeepalive = expectRegisteredDurations.length;
357         assertEquals(maxNumOfKeepalive, expectActiveDurations.length);
358         assertEquals(
359                 maxNumOfKeepalive,
360                 actualDurationsPerNumOfKeepalive.getDurationForNumOfKeepaliveCount());
361         for (int numOfKeepalive = 0; numOfKeepalive < maxNumOfKeepalive; numOfKeepalive++) {
362             final DurationForNumOfKeepalive actualDurations =
363                     actualDurationsPerNumOfKeepalive.getDurationForNumOfKeepalive(numOfKeepalive);
364 
365             assertEquals(numOfKeepalive, actualDurations.getNumOfKeepalive());
366             assertEquals(
367                     expectRegisteredDurations[numOfKeepalive],
368                     actualDurations.getKeepaliveRegisteredDurationsMsec());
369             assertEquals(
370                     expectActiveDurations[numOfKeepalive],
371                     actualDurations.getKeepaliveActiveDurationsMsec());
372         }
373     }
374 
375     /**
376      * Asserts the actual KeepaliveLifetimePerCarrier contains an expected KeepaliveCarrierStats.
377      * This finds and checks only for the (carrierId, transportTypes, intervalMs) of the given
378      * expectKeepaliveCarrierStats and asserts the lifetime metrics.
379      *
380      * @param expectKeepaliveCarrierStats a keepalive lifetime metric that is expected to be in the
381      *     proto.
382      * @param actualKeepaliveLifetimePerCarrier the KeepaliveLifetimePerCarrier message to assert.
383      */
findAndAssertCarrierLifetimeMetrics( KeepaliveCarrierStats expectKeepaliveCarrierStats, KeepaliveLifetimePerCarrier actualKeepaliveLifetimePerCarrier)384     private void findAndAssertCarrierLifetimeMetrics(
385             KeepaliveCarrierStats expectKeepaliveCarrierStats,
386             KeepaliveLifetimePerCarrier actualKeepaliveLifetimePerCarrier) {
387         for (KeepaliveLifetimeForCarrier keepaliveLifetimeForCarrier :
388                 actualKeepaliveLifetimePerCarrier.getKeepaliveLifetimeForCarrierList()) {
389             if (expectKeepaliveCarrierStats.carrierId == keepaliveLifetimeForCarrier.getCarrierId()
390                     && expectKeepaliveCarrierStats.transportTypes
391                             == keepaliveLifetimeForCarrier.getTransportTypes()
392                     && expectKeepaliveCarrierStats.intervalMs
393                             == keepaliveLifetimeForCarrier.getIntervalsMsec()) {
394                 assertEquals(
395                         expectKeepaliveCarrierStats.lifetimeMs,
396                         keepaliveLifetimeForCarrier.getLifetimeMsec());
397                 assertEquals(
398                         expectKeepaliveCarrierStats.activeLifetimeMs,
399                         keepaliveLifetimeForCarrier.getActiveLifetimeMsec());
400                 return;
401             }
402         }
403         fail("KeepaliveLifetimeForCarrier not found for a given expected KeepaliveCarrierStats");
404     }
405 
assertNoDuplicates(Object[] arr)406     private void assertNoDuplicates(Object[] arr) {
407         final Set<Object> s = new HashSet<Object>(Arrays.asList(arr));
408         assertEquals(arr.length, s.size());
409     }
410 
411     /**
412      * Asserts that a KeepaliveLifetimePerCarrier contains all the expected KeepaliveCarrierStats.
413      *
414      * @param expectKeepaliveCarrierStatsArray an array of keepalive lifetime metrics that is
415      *     expected to be in the KeepaliveLifetimePerCarrier.
416      * @param actualKeepaliveLifetimePerCarrier the KeepaliveLifetimePerCarrier message to assert.
417      */
assertCarrierLifetimeMetrics( KeepaliveCarrierStats[] expectKeepaliveCarrierStatsArray, KeepaliveLifetimePerCarrier actualKeepaliveLifetimePerCarrier)418     private void assertCarrierLifetimeMetrics(
419             KeepaliveCarrierStats[] expectKeepaliveCarrierStatsArray,
420             KeepaliveLifetimePerCarrier actualKeepaliveLifetimePerCarrier) {
421         assertNoDuplicates(expectKeepaliveCarrierStatsArray);
422         assertEquals(
423                 expectKeepaliveCarrierStatsArray.length,
424                 actualKeepaliveLifetimePerCarrier.getKeepaliveLifetimeForCarrierCount());
425         for (KeepaliveCarrierStats keepaliveCarrierStats : expectKeepaliveCarrierStatsArray) {
426             findAndAssertCarrierLifetimeMetrics(
427                     keepaliveCarrierStats, actualKeepaliveLifetimePerCarrier);
428         }
429     }
430 
assertDailyKeepaliveInfoReported( DailykeepaliveInfoReported dailyKeepaliveInfoReported, int expectRequestsCount, int expectAutoRequestsCount, int[] expectAppUids, int[] expectRegisteredDurations, int[] expectActiveDurations, KeepaliveCarrierStats[] expectKeepaliveCarrierStatsArray)431     private void assertDailyKeepaliveInfoReported(
432             DailykeepaliveInfoReported dailyKeepaliveInfoReported,
433             int expectRequestsCount,
434             int expectAutoRequestsCount,
435             int[] expectAppUids,
436             int[] expectRegisteredDurations,
437             int[] expectActiveDurations,
438             KeepaliveCarrierStats[] expectKeepaliveCarrierStatsArray) {
439         assertEquals(expectRequestsCount, dailyKeepaliveInfoReported.getKeepaliveRequests());
440         assertEquals(
441                 expectAutoRequestsCount,
442                 dailyKeepaliveInfoReported.getAutomaticKeepaliveRequests());
443         assertEquals(expectAppUids.length, dailyKeepaliveInfoReported.getDistinctUserCount());
444 
445         final int[] uidArray = CollectionUtils.toIntArray(dailyKeepaliveInfoReported.getUidList());
446         assertArrayEquals(expectAppUids, uidArray);
447 
448         final DurationPerNumOfKeepalive actualDurations =
449                 dailyKeepaliveInfoReported.getDurationPerNumOfKeepalive();
450         assertDurationMetrics(expectRegisteredDurations, expectActiveDurations, actualDurations);
451 
452         final KeepaliveLifetimePerCarrier actualCarrierLifetime =
453                 dailyKeepaliveInfoReported.getKeepaliveLifetimePerCarrier();
454 
455         assertCarrierLifetimeMetrics(expectKeepaliveCarrierStatsArray, actualCarrierLifetime);
456     }
457 
458     // The KeepaliveStatsTracker will be disabled when an error occurs with the keepalive states.
459     // Most tests should assert that the tracker is still active to ensure no errors occurred.
assertKeepaliveStatsTrackerActive()460     private void assertKeepaliveStatsTrackerActive() {
461         assertTrue(mKeepaliveStatsTracker.isEnabled());
462     }
463 
assertKeepaliveStatsTrackerDisabled()464     private void assertKeepaliveStatsTrackerDisabled() {
465         assertFalse(mKeepaliveStatsTracker.isEnabled());
466 
467         final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener();
468         // BackgroundThread will remove the OnSubscriptionsChangedListener.
469         HandlerUtils.waitForIdle(BackgroundThread.getHandler(), TIMEOUT_MS);
470         verify(mSubscriptionManager).removeOnSubscriptionsChangedListener(listener);
471 
472         final BroadcastReceiver receiver = getBroadcastReceiver();
473         verify(mContext).unregisterReceiver(receiver);
474     }
475 
476     @Test
testNoKeepalive()477     public void testNoKeepalive() {
478         final int writeTime = 5000;
479 
480         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
481                 buildKeepaliveMetrics(writeTime);
482 
483         // Expect that the durations are all in numOfKeepalive = 0.
484         final int[] expectRegisteredDurations = new int[] {writeTime};
485         final int[] expectActiveDurations = new int[] {writeTime};
486 
487         assertDailyKeepaliveInfoReported(
488                 dailyKeepaliveInfoReported,
489                 /* expectRequestsCount= */ 0,
490                 /* expectAutoRequestsCount= */ 0,
491                 /* expectAppUids= */ new int[0],
492                 expectRegisteredDurations,
493                 expectActiveDurations,
494                 new KeepaliveCarrierStats[0]);
495         assertKeepaliveStatsTrackerActive();
496     }
497 
498     /*
499      * Diagram of test (not to scale):
500      * Key: S - Start/Stop, P - Pause, R - Resume, W - Write
501      *
502      * Keepalive     S                          W
503      * Timeline  |------------------------------|
504      */
505     @Test
testOneKeepalive_startOnly()506     public void testOneKeepalive_startOnly() {
507         final int startTime = 1000;
508         final int writeTime = 5000;
509 
510         onStartKeepalive(startTime, TEST_SLOT);
511 
512         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
513                 buildKeepaliveMetrics(writeTime);
514 
515         // The keepalive is never stopped, expect the duration for numberOfKeepalive of 1 to range
516         // from startTime to writeTime.
517         final int[] expectRegisteredDurations = new int[] {startTime, writeTime - startTime};
518         final int[] expectActiveDurations = new int[] {startTime, writeTime - startTime};
519         assertDailyKeepaliveInfoReported(
520                 dailyKeepaliveInfoReported,
521                 /* expectRequestsCount= */ 1,
522                 /* expectAutoRequestsCount= */ 1,
523                 /* expectAppUids= */ new int[] {TEST_UID},
524                 expectRegisteredDurations,
525                 expectActiveDurations,
526                 new KeepaliveCarrierStats[] {
527                     getDefaultCarrierStats(expectRegisteredDurations[1], expectActiveDurations[1])
528                 });
529         assertKeepaliveStatsTrackerActive();
530     }
531 
532     /*
533      * Diagram of test (not to scale):
534      * Key: S - Start/Stop, P - Pause, R - Resume, W - Write
535      *
536      * Keepalive     S       P                  W
537      * Timeline  |------------------------------|
538      */
539     @Test
testOneKeepalive_paused()540     public void testOneKeepalive_paused() {
541         final int startTime = 1000;
542         final int pauseTime = 2030;
543         final int writeTime = 5000;
544 
545         onStartKeepalive(startTime, TEST_SLOT);
546 
547         onPauseKeepalive(pauseTime, TEST_SLOT);
548 
549         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
550                 buildKeepaliveMetrics(writeTime);
551 
552         // The keepalive is paused but not stopped, expect the registered duration for
553         // numberOfKeepalive of 1 to still range from startTime to writeTime while the active
554         // duration stops at pauseTime.
555         final int[] expectRegisteredDurations = new int[] {startTime, writeTime - startTime};
556         final int[] expectActiveDurations =
557                 new int[] {startTime + (writeTime - pauseTime), pauseTime - startTime};
558         assertDailyKeepaliveInfoReported(
559                 dailyKeepaliveInfoReported,
560                 /* expectRequestsCount= */ 1,
561                 /* expectAutoRequestsCount= */ 1,
562                 /* expectAppUids= */ new int[] {TEST_UID},
563                 expectRegisteredDurations,
564                 expectActiveDurations,
565                 new KeepaliveCarrierStats[] {
566                     getDefaultCarrierStats(expectRegisteredDurations[1], expectActiveDurations[1])
567                 });
568         assertKeepaliveStatsTrackerActive();
569     }
570 
571     /*
572      * Diagram of test (not to scale):
573      * Key: S - Start/Stop, P - Pause, R - Resume, W - Write
574      *
575      * Keepalive     S       P        R         W
576      * Timeline  |------------------------------|
577      */
578     @Test
testOneKeepalive_resumed()579     public void testOneKeepalive_resumed() {
580         final int startTime = 1000;
581         final int pauseTime = 2030;
582         final int resumeTime = 3450;
583         final int writeTime = 5000;
584 
585         onStartKeepalive(startTime, TEST_SLOT);
586 
587         onPauseKeepalive(pauseTime, TEST_SLOT);
588 
589         onResumeKeepalive(resumeTime, TEST_SLOT);
590 
591         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
592                 buildKeepaliveMetrics(writeTime);
593 
594         // The keepalive is paused and resumed but not stopped, expect the registered duration for
595         // numberOfKeepalive of 1 to still range from startTime to writeTime while the active
596         // duration stops at pauseTime but resumes at resumeTime and stops at writeTime.
597         final int[] expectRegisteredDurations = new int[] {startTime, writeTime - startTime};
598         final int[] expectActiveDurations =
599                 new int[] {
600                     startTime + (resumeTime - pauseTime),
601                     (pauseTime - startTime) + (writeTime - resumeTime)
602                 };
603         assertDailyKeepaliveInfoReported(
604                 dailyKeepaliveInfoReported,
605                 /* expectRequestsCount= */ 1,
606                 /* expectAutoRequestsCount= */ 1,
607                 /* expectAppUids= */ new int[] {TEST_UID},
608                 expectRegisteredDurations,
609                 expectActiveDurations,
610                 new KeepaliveCarrierStats[] {
611                     getDefaultCarrierStats(expectRegisteredDurations[1], expectActiveDurations[1])
612                 });
613         assertKeepaliveStatsTrackerActive();
614     }
615 
616     /*
617      * Diagram of test (not to scale):
618      * Key: S - Start/Stop, P - Pause, R - Resume, W - Write
619      *
620      * Keepalive     S       P      R     S     W
621      * Timeline  |------------------------------|
622      */
623     @Test
testOneKeepalive_stopped()624     public void testOneKeepalive_stopped() {
625         final int startTime = 1000;
626         final int pauseTime = 2930;
627         final int resumeTime = 3452;
628         final int stopTime = 4157;
629         final int writeTime = 5000;
630 
631         onStartKeepalive(startTime, TEST_SLOT);
632 
633         onPauseKeepalive(pauseTime, TEST_SLOT);
634 
635         onResumeKeepalive(resumeTime, TEST_SLOT);
636 
637         onStopKeepalive(stopTime, TEST_SLOT);
638 
639         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
640                 buildKeepaliveMetrics(writeTime);
641 
642         // The keepalive is now stopped, expect the registered duration for numberOfKeepalive of 1
643         // to now range from startTime to stopTime while the active duration stops at pauseTime but
644         // resumes at resumeTime and stops again at stopTime.
645         final int[] expectRegisteredDurations =
646                 new int[] {startTime + (writeTime - stopTime), stopTime - startTime};
647         final int[] expectActiveDurations =
648                 new int[] {
649                     startTime + (resumeTime - pauseTime) + (writeTime - stopTime),
650                     (pauseTime - startTime) + (stopTime - resumeTime)
651                 };
652         assertDailyKeepaliveInfoReported(
653                 dailyKeepaliveInfoReported,
654                 /* expectRequestsCount= */ 1,
655                 /* expectAutoRequestsCount= */ 1,
656                 /* expectAppUids= */ new int[] {TEST_UID},
657                 expectRegisteredDurations,
658                 expectActiveDurations,
659                 new KeepaliveCarrierStats[] {
660                     getDefaultCarrierStats(expectRegisteredDurations[1], expectActiveDurations[1])
661                 });
662         assertKeepaliveStatsTrackerActive();
663     }
664 
665     /*
666      * Diagram of test (not to scale):
667      * Key: S - Start/Stop, P - Pause, R - Resume, W - Write
668      *
669      * Keepalive     S       P            S     W
670      * Timeline  |------------------------------|
671      */
672     @Test
testOneKeepalive_pausedStopped()673     public void testOneKeepalive_pausedStopped() {
674         final int startTime = 1000;
675         final int pauseTime = 2930;
676         final int stopTime = 4157;
677         final int writeTime = 5000;
678 
679         onStartKeepalive(startTime, TEST_SLOT);
680 
681         onPauseKeepalive(pauseTime, TEST_SLOT);
682 
683         onStopKeepalive(stopTime, TEST_SLOT);
684 
685         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
686                 buildKeepaliveMetrics(writeTime);
687 
688         // The keepalive is stopped while paused, expect the registered duration for
689         // numberOfKeepalive of 1 to range from startTime to stopTime while the active duration
690         // simply stops at pauseTime.
691         final int[] expectRegisteredDurations =
692                 new int[] {startTime + (writeTime - stopTime), stopTime - startTime};
693         final int[] expectActiveDurations =
694                 new int[] {startTime + (writeTime - pauseTime), (pauseTime - startTime)};
695         assertDailyKeepaliveInfoReported(
696                 dailyKeepaliveInfoReported,
697                 /* expectRequestsCount= */ 1,
698                 /* expectAutoRequestsCount= */ 1,
699                 /* expectAppUids= */ new int[] {TEST_UID},
700                 expectRegisteredDurations,
701                 expectActiveDurations,
702                 new KeepaliveCarrierStats[] {
703                     getDefaultCarrierStats(expectRegisteredDurations[1], expectActiveDurations[1])
704                 });
705         assertKeepaliveStatsTrackerActive();
706     }
707 
708     /*
709      * Diagram of test (not to scale):
710      * Key: S - Start/Stop, P - Pause, R - Resume, W - Write
711      *
712      * Keepalive     S  P R P R P R       S     W
713      * Timeline  |------------------------------|
714      */
715     @Test
testOneKeepalive_multiplePauses()716     public void testOneKeepalive_multiplePauses() {
717         final int startTime = 1000;
718         // Alternating timestamps of pause and resume
719         final int[] pauseResumeTimes = new int[] {1200, 1400, 1700, 2000, 2400, 2800};
720         final int stopTime = 4000;
721         final int writeTime = 5000;
722 
723         onStartKeepalive(startTime, TEST_SLOT);
724 
725         for (int i = 0; i < pauseResumeTimes.length; i++) {
726             if (i % 2 == 0) {
727                 onPauseKeepalive(pauseResumeTimes[i], TEST_SLOT);
728             } else {
729                 onResumeKeepalive(pauseResumeTimes[i], TEST_SLOT);
730             }
731         }
732 
733         onStopKeepalive(stopTime, TEST_SLOT);
734 
735         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
736                 buildKeepaliveMetrics(writeTime);
737 
738         final int[] expectRegisteredDurations =
739                 new int[] {startTime + (writeTime - stopTime), stopTime - startTime};
740         final int[] expectActiveDurations =
741                 new int[] {
742                     startTime + /* sum of (Resume - Pause) */ (900) + (writeTime - stopTime),
743                     (pauseResumeTimes[0] - startTime)
744                             + /* sum of (Pause - Resume) */ (700)
745                             + (stopTime - pauseResumeTimes[5])
746                 };
747         assertDailyKeepaliveInfoReported(
748                 dailyKeepaliveInfoReported,
749                 /* expectRequestsCount= */ 1,
750                 /* expectAutoRequestsCount= */ 1,
751                 /* expectAppUids= */ new int[] {TEST_UID},
752                 expectRegisteredDurations,
753                 expectActiveDurations,
754                 new KeepaliveCarrierStats[] {
755                     getDefaultCarrierStats(expectRegisteredDurations[1], expectActiveDurations[1])
756                 });
757         assertKeepaliveStatsTrackerActive();
758     }
759 
760     /*
761      * Diagram of test (not to scale):
762      * Key: S - Start/Stop, P - Pause, R - Resume, W - Write
763      *
764      * Keepalive1    S1  P1     R1         S1    W
765      * Keepalive2           S2     P2   R2       W
766      * Timeline   |------------------------------|
767      */
768     @Test
testTwoKeepalives()769     public void testTwoKeepalives() {
770         // The suffix 1/2 indicates which keepalive it is referring to.
771         final int startTime1 = 1000;
772         final int pauseTime1 = 1500;
773         final int startTime2 = 2000;
774         final int resumeTime1 = 2500;
775         final int pauseTime2 = 3000;
776         final int resumeTime2 = 3500;
777         final int stopTime1 = 4157;
778         final int writeTime = 5000;
779 
780         onStartKeepalive(startTime1, TEST_SLOT);
781 
782         onPauseKeepalive(pauseTime1, TEST_SLOT);
783 
784         onStartKeepalive(startTime2, TEST_SLOT2);
785 
786         onResumeKeepalive(resumeTime1, TEST_SLOT);
787 
788         onPauseKeepalive(pauseTime2, TEST_SLOT2);
789 
790         onResumeKeepalive(resumeTime2, TEST_SLOT2);
791 
792         onStopKeepalive(stopTime1, TEST_SLOT);
793 
794         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
795                 buildKeepaliveMetrics(writeTime);
796 
797         // With two keepalives, the number of concurrent keepalives can vary from 0-2 depending on
798         // both keepalive states.
799         final int[] expectRegisteredDurations =
800                 new int[] {
801                     startTime1,
802                     // 1 registered keepalive before keepalive2 starts and after keepalive1 stops.
803                     (startTime2 - startTime1) + (writeTime - stopTime1),
804                     // 2 registered keepalives between keepalive2 start and keepalive1 stop.
805                     stopTime1 - startTime2
806                 };
807 
808         final int[] expectActiveDurations =
809                 new int[] {
810                     // 0 active keepalives when keepalive1 is paused before keepalive2 starts.
811                     startTime1 + (startTime2 - pauseTime1),
812                     // 1 active keepalive before keepalive1 is paused.
813                     (pauseTime1 - startTime1)
814                             // before keepalive1 is resumed and after keepalive2 starts.
815                             + (resumeTime1 - startTime2)
816                             // during keepalive2 is paused since keepalive1 has been resumed.
817                             + (resumeTime2 - pauseTime2)
818                             // after keepalive1 stops since keepalive2 has been resumed.
819                             + (writeTime - stopTime1),
820                     // 2 active keepalives before keepalive2 is paused and before keepalive1 stops.
821                     (pauseTime2 - resumeTime1) + (stopTime1 - resumeTime2)
822                 };
823 
824         assertDailyKeepaliveInfoReported(
825                 dailyKeepaliveInfoReported,
826                 /* expectRequestsCount= */ 2,
827                 /* expectAutoRequestsCount= */ 2,
828                 /* expectAppUids= */ new int[] {TEST_UID},
829                 expectRegisteredDurations,
830                 expectActiveDurations,
831                 // The carrier stats are aggregated here since the keepalives have the same
832                 // (carrierId, transportTypes, intervalMs).
833                 new KeepaliveCarrierStats[] {
834                     getDefaultCarrierStats(
835                             expectRegisteredDurations[1] + 2 * expectRegisteredDurations[2],
836                             expectActiveDurations[1] + 2 * expectActiveDurations[2])
837                 });
838         assertKeepaliveStatsTrackerActive();
839     }
840 
841     /*
842      * Diagram of test (not to scale):
843      * Key: S - Start/Stop, P - Pause, R - Resume, W - Write
844      *
845      * Keepalive     S   W(reset+W)         S    W
846      * Timeline   |------------------------------|
847      */
848     @Test
testResetMetrics()849     public void testResetMetrics() {
850         final int startTime = 1000;
851         final int writeTime = 5000;
852         final int stopTime = 7000;
853         final int writeTime2 = 10000;
854 
855         onStartKeepalive(startTime, TEST_SLOT);
856 
857         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
858                 buildAndResetMetrics(writeTime);
859 
860         // Same expect as testOneKeepalive_startOnly
861         final int[] expectRegisteredDurations = new int[] {startTime, writeTime - startTime};
862         final int[] expectActiveDurations = new int[] {startTime, writeTime - startTime};
863         assertDailyKeepaliveInfoReported(
864                 dailyKeepaliveInfoReported,
865                 /* expectRequestsCount= */ 1,
866                 /* expectAutoRequestsCount= */ 1,
867                 /* expectAppUids= */ new int[] {TEST_UID},
868                 expectRegisteredDurations,
869                 expectActiveDurations,
870                 new KeepaliveCarrierStats[] {
871                     getDefaultCarrierStats(expectRegisteredDurations[1], expectActiveDurations[1])
872                 });
873 
874         // Check metrics was reset from above.
875         final DailykeepaliveInfoReported dailyKeepaliveInfoReported2 =
876                 buildKeepaliveMetrics(writeTime);
877 
878         // Expect the stored durations to be 0 but still contain the number of keepalive = 1.
879         assertDailyKeepaliveInfoReported(
880                 dailyKeepaliveInfoReported2,
881                 /* expectRequestsCount= */ 1,
882                 /* expectAutoRequestsCount= */ 1,
883                 /* expectAppUids= */ new int[] {TEST_UID},
884                 /* expectRegisteredDurations= */ new int[] {0, 0},
885                 /* expectActiveDurations= */ new int[] {0, 0},
886                 new KeepaliveCarrierStats[] {getDefaultCarrierStats(0, 0)});
887 
888         // Expect that the keepalive is still registered after resetting so it can be stopped.
889         onStopKeepalive(stopTime, TEST_SLOT);
890 
891         final DailykeepaliveInfoReported dailyKeepaliveInfoReported3 =
892                 buildKeepaliveMetrics(writeTime2);
893 
894         final int[] expectRegisteredDurations2 =
895                 new int[] {writeTime2 - stopTime, stopTime - writeTime};
896         final int[] expectActiveDurations2 =
897                 new int[] {writeTime2 - stopTime, stopTime - writeTime};
898         assertDailyKeepaliveInfoReported(
899                 dailyKeepaliveInfoReported3,
900                 /* expectRequestsCount= */ 1,
901                 /* expectAutoRequestsCount= */ 1,
902                 /* expectAppUids= */ new int[] {TEST_UID},
903                 expectRegisteredDurations2,
904                 expectActiveDurations2,
905                 new KeepaliveCarrierStats[] {
906                     getDefaultCarrierStats(expectRegisteredDurations2[1], expectActiveDurations2[1])
907                 });
908         assertKeepaliveStatsTrackerActive();
909     }
910 
911     /*
912      * Diagram of test (not to scale):
913      * Key: S - Start/Stop, P - Pause, R - Resume, W - Write
914      *
915      * Keepalive1     S1      S1  W+reset         W
916      * Keepalive2         S2      W+reset         W
917      * Timeline    |------------------------------|
918      */
919     @Test
testResetMetrics_twoKeepalives()920     public void testResetMetrics_twoKeepalives() {
921         final int startTime1 = 1000;
922         final int startTime2 = 2000;
923         final int stopTime1 = 4157;
924         final int writeTime = 5000;
925         final int writeTime2 = 10000;
926 
927         onStartKeepalive(startTime1, TEST_SLOT);
928 
929         onStartKeepalive(startTime2, TEST_SLOT2, TEST_NETWORK_CAPABILITIES_2,
930                 TEST_KEEPALIVE_INTERVAL2_SEC);
931 
932         onStopKeepalive(stopTime1, TEST_SLOT);
933 
934         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
935                 buildAndResetMetrics(writeTime);
936 
937         final int[] expectRegisteredDurations =
938                 new int[] {
939                     startTime1,
940                     // 1 keepalive before keepalive2 starts and after keepalive1 stops.
941                     (startTime2 - startTime1) + (writeTime - stopTime1),
942                     stopTime1 - startTime2
943                 };
944         // Since there is no pause, expect the same as registered durations.
945         final int[] expectActiveDurations =
946                 new int[] {
947                     startTime1,
948                     (startTime2 - startTime1) + (writeTime - stopTime1),
949                     stopTime1 - startTime2
950                 };
951 
952         // Lifetime carrier stats are independent of each other since they have different intervals.
953         final KeepaliveCarrierStats expectKeepaliveCarrierStats1 =
954                 getDefaultCarrierStats(stopTime1 - startTime1, stopTime1 - startTime1);
955         final KeepaliveCarrierStats expectKeepaliveCarrierStats2 =
956                 new KeepaliveCarrierStats(
957                         TEST_CARRIER_ID_2,
958                         /* transportTypes= */ (1 << TRANSPORT_CELLULAR),
959                         TEST_KEEPALIVE_INTERVAL2_SEC * 1000,
960                         writeTime - startTime2,
961                         writeTime - startTime2);
962 
963         assertDailyKeepaliveInfoReported(
964                 dailyKeepaliveInfoReported,
965                 /* expectRequestsCount= */ 2,
966                 /* expectAutoRequestsCount= */ 2,
967                 /* expectAppUids= */ new int[] {TEST_UID},
968                 expectRegisteredDurations,
969                 expectActiveDurations,
970                 new KeepaliveCarrierStats[] {
971                     expectKeepaliveCarrierStats1, expectKeepaliveCarrierStats2
972                 });
973 
974         final DailykeepaliveInfoReported dailyKeepaliveInfoReported2 =
975                 buildKeepaliveMetrics(writeTime2);
976 
977         // Only 1 keepalive is registered and active since the reset until the writeTime2.
978         final int[] expectRegisteredDurations2 = new int[] {0, writeTime2 - writeTime};
979         final int[] expectActiveDurations2 = new int[] {0, writeTime2 - writeTime};
980 
981         // Only the keepalive with interval of intervalSec2 is present.
982         final KeepaliveCarrierStats expectKeepaliveCarrierStats3 =
983                 new KeepaliveCarrierStats(
984                         TEST_CARRIER_ID_2,
985                         /* transportTypes= */ (1 << TRANSPORT_CELLULAR),
986                         TEST_KEEPALIVE_INTERVAL2_SEC * 1000,
987                         writeTime2 - writeTime,
988                         writeTime2 - writeTime);
989 
990         assertDailyKeepaliveInfoReported(
991                 dailyKeepaliveInfoReported2,
992                 /* expectRequestsCount= */ 1,
993                 /* expectAutoRequestsCount= */ 1,
994                 /* expectAppUids= */ new int[] {TEST_UID},
995                 expectRegisteredDurations2,
996                 expectActiveDurations2,
997                 new KeepaliveCarrierStats[] {expectKeepaliveCarrierStats3});
998         assertKeepaliveStatsTrackerActive();
999     }
1000 
1001     @Test
testReusableSlot_keepaliveNotStopped()1002     public void testReusableSlot_keepaliveNotStopped() {
1003         final int startTime1 = 1000;
1004         final int startTime2 = 2000;
1005         final int writeTime = 5000;
1006 
1007         onStartKeepalive(startTime1, TEST_SLOT);
1008 
1009         // Attempt to use the same (network, slot)
1010         onStartKeepalive(startTime2, TEST_SLOT);
1011         // Starting a 2nd keepalive on the same slot is unexpected and an error so the stats tracker
1012         // is disabled.
1013         assertKeepaliveStatsTrackerDisabled();
1014 
1015         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
1016                 buildKeepaliveMetrics(writeTime);
1017 
1018         // Expect the duration to be from startTime1 and not startTime2, it should not start again.
1019         final int[] expectRegisteredDurations = new int[] {startTime1, writeTime - startTime1};
1020         final int[] expectActiveDurations = new int[] {startTime1, writeTime - startTime1};
1021 
1022         assertDailyKeepaliveInfoReported(
1023                 dailyKeepaliveInfoReported,
1024                 /* expectRequestsCount= */ 1,
1025                 /* expectAutoRequestsCount= */ 1,
1026                 /* expectAppUids= */ new int[] {TEST_UID},
1027                 expectRegisteredDurations,
1028                 expectActiveDurations,
1029                 new KeepaliveCarrierStats[] {
1030                     getDefaultCarrierStats(expectRegisteredDurations[1], expectActiveDurations[1])
1031                 });
1032     }
1033 
1034     @Test
testReusableSlot_keepaliveStopped()1035     public void testReusableSlot_keepaliveStopped() {
1036         final int startTime1 = 1000;
1037         final int stopTime = 2000;
1038         final int startTime2 = 3000;
1039         final int writeTime = 5000;
1040 
1041         onStartKeepalive(startTime1, TEST_SLOT);
1042 
1043         onStopKeepalive(stopTime, TEST_SLOT);
1044 
1045         // Attempt to use the same (network, slot)
1046         onStartKeepalive(startTime2, TEST_SLOT);
1047 
1048         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
1049                 buildKeepaliveMetrics(writeTime);
1050 
1051         // Expect the durations to be an aggregate of both periods.
1052         // i.e. onStartKeepalive works on the same (network, slot) if it has been stopped.
1053         final int[] expectRegisteredDurations =
1054                 new int[] {
1055                     startTime1 + (startTime2 - stopTime),
1056                     (stopTime - startTime1) + (writeTime - startTime2)
1057                 };
1058         final int[] expectActiveDurations =
1059                 new int[] {
1060                     startTime1 + (startTime2 - stopTime),
1061                     (stopTime - startTime1) + (writeTime - startTime2)
1062                 };
1063 
1064         assertDailyKeepaliveInfoReported(
1065                 dailyKeepaliveInfoReported,
1066                 /* expectRequestsCount= */ 2,
1067                 /* expectAutoRequestsCount= */ 2,
1068                 /* expectAppUids= */ new int[] {TEST_UID},
1069                 expectRegisteredDurations,
1070                 expectActiveDurations,
1071                 new KeepaliveCarrierStats[] {
1072                     getDefaultCarrierStats(expectRegisteredDurations[1], expectActiveDurations[1])
1073                 });
1074         assertKeepaliveStatsTrackerActive();
1075     }
1076 
1077     @Test
testCarrierIdChange_changeBeforeStart()1078     public void testCarrierIdChange_changeBeforeStart() {
1079         // Update the list to only have sub_id_2 with carrier_id_1.
1080         final SubscriptionInfo subInfo = makeSubInfoMock(TEST_SUB_ID_2, TEST_CARRIER_ID_1);
1081         doReturn(List.of(subInfo)).when(mSubscriptionManager).getActiveSubscriptionInfoList();
1082 
1083         getOnSubscriptionsChangedListener().onSubscriptionsChanged();
1084         HandlerUtils.waitForIdle(mTestHandler, TIMEOUT_MS);
1085 
1086         final int startTime = 1000;
1087         final int writeTime = 5000;
1088 
1089         onStartKeepalive(startTime, TEST_SLOT, TEST_NETWORK_CAPABILITIES);
1090         onStartKeepalive(startTime, TEST_SLOT2, TEST_NETWORK_CAPABILITIES_2);
1091 
1092         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
1093                 buildKeepaliveMetrics(writeTime);
1094 
1095         // The network with sub_id_1 has an unknown carrier id.
1096         final KeepaliveCarrierStats expectKeepaliveCarrierStats1 =
1097                 new KeepaliveCarrierStats(
1098                         TelephonyManager.UNKNOWN_CARRIER_ID,
1099                         /* transportTypes= */ (1 << TRANSPORT_CELLULAR),
1100                         TEST_KEEPALIVE_INTERVAL_SEC * 1000,
1101                         writeTime - startTime,
1102                         writeTime - startTime);
1103 
1104         // The network with sub_id_2 has carrier_id_1.
1105         final KeepaliveCarrierStats expectKeepaliveCarrierStats2 =
1106                 new KeepaliveCarrierStats(
1107                         TEST_CARRIER_ID_1,
1108                         /* transportTypes= */ (1 << TRANSPORT_CELLULAR),
1109                         TEST_KEEPALIVE_INTERVAL_SEC * 1000,
1110                         writeTime - startTime,
1111                         writeTime - startTime);
1112         assertDailyKeepaliveInfoReported(
1113                 dailyKeepaliveInfoReported,
1114                 /* expectRequestsCount= */ 2,
1115                 /* expectAutoRequestsCount= */ 2,
1116                 /* expectAppUids= */ new int[] {TEST_UID},
1117                 /* expectRegisteredDurations= */ new int[] {startTime, 0, writeTime - startTime},
1118                 /* expectActiveDurations= */ new int[] {startTime, 0, writeTime - startTime},
1119                 new KeepaliveCarrierStats[] {
1120                     expectKeepaliveCarrierStats1, expectKeepaliveCarrierStats2
1121                 });
1122         assertKeepaliveStatsTrackerActive();
1123     }
1124 
1125     @Test
testCarrierIdFromWifiInfo()1126     public void testCarrierIdFromWifiInfo() {
1127         final int startTime = 1000;
1128         final int writeTime = 5000;
1129 
1130         final WifiInfo wifiInfo = mock(WifiInfo.class);
1131         final WifiInfo wifiInfoCopy = mock(WifiInfo.class);
1132 
1133         // Building NetworkCapabilities stores a copy of the WifiInfo with makeCopy.
1134         doReturn(wifiInfoCopy).when(wifiInfo).makeCopy(anyLong());
1135         doReturn(TEST_SUB_ID_1).when(wifiInfo).getSubscriptionId();
1136         doReturn(TEST_SUB_ID_1).when(wifiInfoCopy).getSubscriptionId();
1137         final NetworkCapabilities nc =
1138                 new NetworkCapabilities.Builder()
1139                         .addTransportType(TRANSPORT_WIFI)
1140                         .setTransportInfo(wifiInfo)
1141                         .build();
1142 
1143         onStartKeepalive(startTime, TEST_SLOT, nc);
1144 
1145         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
1146                 buildKeepaliveMetrics(writeTime);
1147 
1148         final KeepaliveCarrierStats expectKeepaliveCarrierStats =
1149                 new KeepaliveCarrierStats(
1150                         TEST_CARRIER_ID_1,
1151                         /* transportTypes= */ (1 << TRANSPORT_WIFI),
1152                         TEST_KEEPALIVE_INTERVAL_SEC * 1000,
1153                         writeTime - startTime,
1154                         writeTime - startTime);
1155 
1156         assertDailyKeepaliveInfoReported(
1157                 dailyKeepaliveInfoReported,
1158                 /* expectRequestsCount= */ 1,
1159                 /* expectAutoRequestsCount= */ 1,
1160                 /* expectAppUids= */ new int[] {TEST_UID},
1161                 /* expectRegisteredDurations= */ new int[] {startTime, writeTime - startTime},
1162                 /* expectActiveDurations= */ new int[] {startTime, writeTime - startTime},
1163                 new KeepaliveCarrierStats[] {expectKeepaliveCarrierStats});
1164         assertKeepaliveStatsTrackerActive();
1165     }
1166 
1167     @Test
testKeepaliveCountsAndUids()1168     public void testKeepaliveCountsAndUids() {
1169         final int startTime1 = 1000, startTime2 = 2000, startTime3 = 3000;
1170         final int writeTime = 5000;
1171         final int[] uids = new int[] {TEST_UID, TEST_UID + 1, TEST_UID + 2};
1172         onStartKeepalive(startTime1, TEST_SLOT, TEST_NETWORK_CAPABILITIES,
1173                 TEST_KEEPALIVE_INTERVAL_SEC, uids[0], /* isAutoKeepalive= */ true);
1174         onStartKeepalive(startTime2, TEST_SLOT + 1, TEST_NETWORK_CAPABILITIES,
1175                 TEST_KEEPALIVE_INTERVAL_SEC, uids[1], /* isAutoKeepalive= */ false);
1176         onStartKeepalive(startTime3, TEST_SLOT + 2, TEST_NETWORK_CAPABILITIES,
1177                 TEST_KEEPALIVE_INTERVAL_SEC, uids[2], /* isAutoKeepalive= */ true);
1178 
1179         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
1180                 buildKeepaliveMetrics(writeTime);
1181         final int[] expectRegisteredDurations =
1182                 new int[] {
1183                     startTime1,
1184                     (startTime2 - startTime1),
1185                     (startTime3 - startTime2),
1186                     (writeTime - startTime3)
1187                 };
1188         final int[] expectActiveDurations =
1189                 new int[] {
1190                     startTime1,
1191                     (startTime2 - startTime1),
1192                     (startTime3 - startTime2),
1193                     (writeTime - startTime3)
1194                 };
1195         assertDailyKeepaliveInfoReported(
1196                 dailyKeepaliveInfoReported,
1197                 /* expectRequestsCount= */ 3,
1198                 /* expectAutoRequestsCount= */ 2,
1199                 /* expectAppUids= */ uids,
1200                 expectRegisteredDurations,
1201                 expectActiveDurations,
1202                 new KeepaliveCarrierStats[] {
1203                     getDefaultCarrierStats(
1204                             writeTime * 3 - startTime1 - startTime2 - startTime3,
1205                             writeTime * 3 - startTime1 - startTime2 - startTime3)
1206                 });
1207         assertKeepaliveStatsTrackerActive();
1208     }
1209 
1210     @Test
testUpdateDefaultSubId()1211     public void testUpdateDefaultSubId() {
1212         final int startTime1 = 1000;
1213         final int startTime2 = 3000;
1214         final int writeTime = 5000;
1215 
1216         // No TelephonyNetworkSpecifier set with subId to force the use of default subId.
1217         final NetworkCapabilities nc =
1218                 new NetworkCapabilities.Builder().addTransportType(TRANSPORT_CELLULAR).build();
1219         onStartKeepalive(startTime1, TEST_SLOT, nc);
1220         // Update default subId
1221         triggerBroadcastDefaultSubId(TEST_SUB_ID_1);
1222         onStartKeepalive(startTime2, TEST_SLOT2, nc);
1223 
1224         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
1225                 buildKeepaliveMetrics(writeTime);
1226 
1227         final int[] expectRegisteredDurations =
1228                 new int[] {startTime1, startTime2 - startTime1, writeTime - startTime2};
1229         final int[] expectActiveDurations =
1230                 new int[] {startTime1, startTime2 - startTime1, writeTime - startTime2};
1231         // Expect the carrier id of the first keepalive to be unknown
1232         final KeepaliveCarrierStats expectKeepaliveCarrierStats1 =
1233                 new KeepaliveCarrierStats(
1234                         TelephonyManager.UNKNOWN_CARRIER_ID,
1235                         /* transportTypes= */ (1 << TRANSPORT_CELLULAR),
1236                         TEST_KEEPALIVE_INTERVAL_SEC * 1000,
1237                         writeTime - startTime1,
1238                         writeTime - startTime1);
1239         // Expect the carrier id of the second keepalive to be TEST_CARRIER_ID_1, from TEST_SUB_ID_1
1240         final KeepaliveCarrierStats expectKeepaliveCarrierStats2 =
1241                 new KeepaliveCarrierStats(
1242                         TEST_CARRIER_ID_1,
1243                         /* transportTypes= */ (1 << TRANSPORT_CELLULAR),
1244                         TEST_KEEPALIVE_INTERVAL_SEC * 1000,
1245                         writeTime - startTime2,
1246                         writeTime - startTime2);
1247         assertDailyKeepaliveInfoReported(
1248                 dailyKeepaliveInfoReported,
1249                 /* expectRequestsCount= */ 2,
1250                 /* expectAutoRequestsCount= */ 2,
1251                 /* expectAppUids= */ new int[] {TEST_UID},
1252                 expectRegisteredDurations,
1253                 expectActiveDurations,
1254                 new KeepaliveCarrierStats[] {
1255                     expectKeepaliveCarrierStats1, expectKeepaliveCarrierStats2
1256                 });
1257         assertKeepaliveStatsTrackerActive();
1258     }
1259 
1260     @Test
1261     @IgnoreAfter(Build.VERSION_CODES.S_V2)
testWriteMetrics_doNothingBeforeT()1262     public void testWriteMetrics_doNothingBeforeT() {
1263         // Keepalive stats use repeated atoms, which are only supported on T+. If written to statsd
1264         // on S- they will bootloop the system, so they must not be sent on S-. See b/289471411.
1265         final int writeTime = 1000;
1266         setElapsedRealtime(writeTime);
1267         visibleOnHandlerThread(mTestHandler, () -> mKeepaliveStatsTracker.writeAndResetMetrics());
1268         verify(mDependencies, never()).writeStats(any());
1269     }
1270 
1271     @Test
1272     @IgnoreUpTo(Build.VERSION_CODES.S_V2)
testWriteMetrics()1273     public void testWriteMetrics() {
1274         final int writeTime = 1000;
1275 
1276         final ArgumentCaptor<DailykeepaliveInfoReported> dailyKeepaliveInfoReportedCaptor =
1277                 ArgumentCaptor.forClass(DailykeepaliveInfoReported.class);
1278 
1279         setElapsedRealtime(writeTime);
1280         visibleOnHandlerThread(mTestHandler, () -> mKeepaliveStatsTracker.writeAndResetMetrics());
1281         // Ensure writeStats is called with the correct DailykeepaliveInfoReported metrics.
1282         verify(mDependencies).writeStats(dailyKeepaliveInfoReportedCaptor.capture());
1283         final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
1284                 dailyKeepaliveInfoReportedCaptor.getValue();
1285 
1286         // Same as the no keepalive case
1287         final int[] expectRegisteredDurations = new int[] {writeTime};
1288         final int[] expectActiveDurations = new int[] {writeTime};
1289         assertDailyKeepaliveInfoReported(
1290                 dailyKeepaliveInfoReported,
1291                 /* expectRequestsCount= */ 0,
1292                 /* expectAutoRequestsCount= */ 0,
1293                 /* expectAppUids= */ new int[0],
1294                 expectRegisteredDurations,
1295                 expectActiveDurations,
1296                 new KeepaliveCarrierStats[0]);
1297 
1298         assertTrue(mKeepaliveStatsTracker.allMetricsExpected(dailyKeepaliveInfoReported));
1299 
1300         // Write time after 27 hours.
1301         final int writeTime2 = 27 * 60 * 60 * 1000;
1302         setElapsedRealtime(writeTime2);
1303 
1304         visibleOnHandlerThread(mTestHandler, () -> mKeepaliveStatsTracker.writeAndResetMetrics());
1305         verify(mDependencies, times(2)).writeStats(dailyKeepaliveInfoReportedCaptor.capture());
1306         final DailykeepaliveInfoReported dailyKeepaliveInfoReported2 =
1307                 dailyKeepaliveInfoReportedCaptor.getValue();
1308 
1309         assertFalse(mKeepaliveStatsTracker.allMetricsExpected(dailyKeepaliveInfoReported2));
1310     }
1311 }
1312