Merge changes I3a38af76,I5e21de05 am: b261573ab0
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/2618634 Change-Id: I40bccf34f6ad08817ea12e5ea89aff9aa5c97bb3 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -94,6 +94,7 @@ public class AutomaticOnOffKeepaliveTracker {
|
||||
private static final int ADJUST_TCP_POLLING_DELAY_MS = 2000;
|
||||
private static final String AUTOMATIC_ON_OFF_KEEPALIVE_VERSION =
|
||||
"automatic_on_off_keepalive_version";
|
||||
public static final long METRICS_COLLECTION_DURATION_MS = 24 * 60 * 60 * 1_000L;
|
||||
|
||||
// ConnectivityService parses message constants from itself and AutomaticOnOffKeepaliveTracker
|
||||
// with MessageUtils for debugging purposes, and crashes if some messages have the same values.
|
||||
@@ -180,6 +181,9 @@ public class AutomaticOnOffKeepaliveTracker {
|
||||
private final LocalLog mEventLog = new LocalLog(MAX_EVENTS_LOGS);
|
||||
|
||||
private final KeepaliveStatsTracker mKeepaliveStatsTracker;
|
||||
|
||||
private final long mMetricsWriteTimeBase;
|
||||
|
||||
/**
|
||||
* Information about a managed keepalive.
|
||||
*
|
||||
@@ -311,7 +315,26 @@ public class AutomaticOnOffKeepaliveTracker {
|
||||
mContext, mConnectivityServiceHandler);
|
||||
|
||||
mAlarmManager = mDependencies.getAlarmManager(context);
|
||||
mKeepaliveStatsTracker = new KeepaliveStatsTracker(context, handler);
|
||||
mKeepaliveStatsTracker =
|
||||
mDependencies.newKeepaliveStatsTracker(context, handler);
|
||||
|
||||
final long time = mDependencies.getElapsedRealtime();
|
||||
mMetricsWriteTimeBase = time % METRICS_COLLECTION_DURATION_MS;
|
||||
final long triggerAtMillis = mMetricsWriteTimeBase + METRICS_COLLECTION_DURATION_MS;
|
||||
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtMillis, TAG,
|
||||
this::writeMetricsAndRescheduleAlarm, handler);
|
||||
}
|
||||
|
||||
private void writeMetricsAndRescheduleAlarm() {
|
||||
mKeepaliveStatsTracker.writeAndResetMetrics();
|
||||
|
||||
final long time = mDependencies.getElapsedRealtime();
|
||||
final long triggerAtMillis =
|
||||
mMetricsWriteTimeBase
|
||||
+ (time - time % METRICS_COLLECTION_DURATION_MS)
|
||||
+ METRICS_COLLECTION_DURATION_MS;
|
||||
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtMillis, TAG,
|
||||
this::writeMetricsAndRescheduleAlarm, mConnectivityServiceHandler);
|
||||
}
|
||||
|
||||
private void startTcpPollingAlarm(@NonNull AutomaticOnOffKeepalive ki) {
|
||||
@@ -897,6 +920,14 @@ public class AutomaticOnOffKeepaliveTracker {
|
||||
return new KeepaliveTracker(mContext, connectivityserviceHander);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new KeepaliveStatsTracker.
|
||||
*/
|
||||
public KeepaliveStatsTracker newKeepaliveStatsTracker(@NonNull Context context,
|
||||
@NonNull Handler connectivityserviceHander) {
|
||||
return new KeepaliveStatsTracker(context, connectivityserviceHander);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find out if a feature is enabled from DeviceConfig.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,10 @@ package com.android.server.connectivity;
|
||||
import static android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkSpecifier;
|
||||
@@ -42,6 +45,8 @@ import com.android.metrics.DurationPerNumOfKeepalive;
|
||||
import com.android.metrics.KeepaliveLifetimeForCarrier;
|
||||
import com.android.metrics.KeepaliveLifetimePerCarrier;
|
||||
import com.android.modules.utils.BackgroundThread;
|
||||
import com.android.net.module.util.CollectionUtils;
|
||||
import com.android.server.ConnectivityStatsLog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -67,9 +72,7 @@ public class KeepaliveStatsTracker {
|
||||
// Mapping of subId to carrierId. Updates are received from OnSubscriptionsChangedListener
|
||||
private final SparseIntArray mCachedCarrierIdPerSubId = new SparseIntArray();
|
||||
// The default subscription id obtained from SubscriptionManager.getDefaultSubscriptionId.
|
||||
// Updates are done from the OnSubscriptionsChangedListener. Note that there is no callback done
|
||||
// to OnSubscriptionsChangedListener when the default sub id changes.
|
||||
// TODO: Register a listener for the default subId when it is possible.
|
||||
// Updates are received from the ACTION_DEFAULT_SUBSCRIPTION_CHANGED broadcast.
|
||||
private int mCachedDefaultSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||
|
||||
// Class to store network information, lifetime durations and active state of a keepalive.
|
||||
@@ -267,6 +270,19 @@ public class KeepaliveStatsTracker {
|
||||
Objects.requireNonNull(context.getSystemService(SubscriptionManager.class));
|
||||
|
||||
mLastUpdateDurationsTimestamp = mDependencies.getElapsedRealtime();
|
||||
context.registerReceiver(
|
||||
new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
mCachedDefaultSubscriptionId =
|
||||
intent.getIntExtra(
|
||||
SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
|
||||
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
||||
}
|
||||
},
|
||||
new IntentFilter(SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED),
|
||||
/* broadcastPermission= */ null,
|
||||
mConnectivityServiceHandler);
|
||||
|
||||
// The default constructor for OnSubscriptionsChangedListener will always implicitly grab
|
||||
// the looper of the current thread. In the case the current thread does not have a looper,
|
||||
@@ -284,11 +300,8 @@ public class KeepaliveStatsTracker {
|
||||
// but not necessarily empty, simply ignore it. Another call to the
|
||||
// listener will be invoked in the future.
|
||||
if (activeSubInfoList == null) return;
|
||||
final int defaultSubId =
|
||||
subscriptionManager.getDefaultSubscriptionId();
|
||||
mConnectivityServiceHandler.post(() -> {
|
||||
mCachedCarrierIdPerSubId.clear();
|
||||
mCachedDefaultSubscriptionId = defaultSubId;
|
||||
|
||||
for (final SubscriptionInfo subInfo : activeSubInfoList) {
|
||||
mCachedCarrierIdPerSubId.put(subInfo.getSubscriptionId(),
|
||||
@@ -592,6 +605,7 @@ public class KeepaliveStatsTracker {
|
||||
*
|
||||
* @return the DailykeepaliveInfoReported proto that was built.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public @NonNull DailykeepaliveInfoReported buildAndResetMetrics() {
|
||||
ensureRunningOnHandlerThread();
|
||||
final long timeNow = mDependencies.getElapsedRealtime();
|
||||
@@ -620,6 +634,20 @@ public class KeepaliveStatsTracker {
|
||||
return metrics;
|
||||
}
|
||||
|
||||
/** Writes the stored metrics to ConnectivityStatsLog and resets. */
|
||||
public void writeAndResetMetrics() {
|
||||
ensureRunningOnHandlerThread();
|
||||
final DailykeepaliveInfoReported dailyKeepaliveInfoReported = buildAndResetMetrics();
|
||||
ConnectivityStatsLog.write(
|
||||
ConnectivityStatsLog.DAILY_KEEPALIVE_INFO_REPORTED,
|
||||
dailyKeepaliveInfoReported.getDurationPerNumOfKeepalive().toByteArray(),
|
||||
dailyKeepaliveInfoReported.getKeepaliveLifetimePerCarrier().toByteArray(),
|
||||
dailyKeepaliveInfoReported.getKeepaliveRequests(),
|
||||
dailyKeepaliveInfoReported.getAutomaticKeepaliveRequests(),
|
||||
dailyKeepaliveInfoReported.getDistinctUserCount(),
|
||||
CollectionUtils.toIntArray(dailyKeepaliveInfoReported.getUidList()));
|
||||
}
|
||||
|
||||
private void ensureRunningOnHandlerThread() {
|
||||
if (mConnectivityServiceHandler.getLooper().getThread() != Thread.currentThread()) {
|
||||
throw new IllegalStateException(
|
||||
|
||||
@@ -21,6 +21,7 @@ import static android.net.ConnectivityManager.TYPE_MOBILE;
|
||||
import static android.net.NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||
|
||||
import static com.android.server.connectivity.AutomaticOnOffKeepaliveTracker.METRICS_COLLECTION_DURATION_MS;
|
||||
import static com.android.testutils.HandlerUtils.visibleOnHandlerThread;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -42,6 +43,7 @@ import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.ignoreStubs;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
@@ -125,6 +127,7 @@ public class AutomaticOnOffKeepaliveTrackerTest {
|
||||
@Mock NetworkAgentInfo mNai;
|
||||
@Mock SubscriptionManager mSubscriptionManager;
|
||||
|
||||
KeepaliveStatsTracker mKeepaliveStatsTracker;
|
||||
TestKeepaliveTracker mKeepaliveTracker;
|
||||
AOOTestHandler mTestHandler;
|
||||
TestTcpKeepaliveController mTcpController;
|
||||
@@ -344,8 +347,14 @@ public class AutomaticOnOffKeepaliveTrackerTest {
|
||||
mTestHandler = new AOOTestHandler(mHandlerThread.getLooper());
|
||||
mTcpController = new TestTcpKeepaliveController(mTestHandler);
|
||||
mKeepaliveTracker = new TestKeepaliveTracker(mCtx, mTestHandler, mTcpController);
|
||||
mKeepaliveStatsTracker = spy(new KeepaliveStatsTracker(mCtx, mTestHandler));
|
||||
doReturn(mKeepaliveTracker).when(mDependencies).newKeepaliveTracker(mCtx, mTestHandler);
|
||||
doReturn(mKeepaliveStatsTracker)
|
||||
.when(mDependencies)
|
||||
.newKeepaliveStatsTracker(mCtx, mTestHandler);
|
||||
|
||||
doReturn(true).when(mDependencies).isFeatureEnabled(any(), anyBoolean());
|
||||
doReturn(0L).when(mDependencies).getElapsedRealtime();
|
||||
mAOOKeepaliveTracker =
|
||||
new AutomaticOnOffKeepaliveTracker(mCtx, mTestHandler, mDependencies);
|
||||
}
|
||||
@@ -499,6 +508,30 @@ public class AutomaticOnOffKeepaliveTrackerTest {
|
||||
assertEquals(testInfo.underpinnedNetwork, mTestHandler.mLastAutoKi.getUnderpinnedNetwork());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlarm_writeMetrics() throws Exception {
|
||||
final ArgumentCaptor<AlarmManager.OnAlarmListener> listenerCaptor =
|
||||
ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
|
||||
|
||||
// First AlarmManager.set call from the constructor.
|
||||
verify(mAlarmManager).set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
|
||||
eq(METRICS_COLLECTION_DURATION_MS), any() /* tag */, listenerCaptor.capture(),
|
||||
eq(mTestHandler));
|
||||
|
||||
final AlarmManager.OnAlarmListener listener = listenerCaptor.getValue();
|
||||
|
||||
doReturn(METRICS_COLLECTION_DURATION_MS).when(mDependencies).getElapsedRealtime();
|
||||
// For realism, the listener should be posted on the handler
|
||||
mTestHandler.post(() -> listener.onAlarm());
|
||||
HandlerUtils.waitForIdle(mTestHandler, TIMEOUT_MS);
|
||||
|
||||
verify(mKeepaliveStatsTracker).writeAndResetMetrics();
|
||||
// Alarm is rescheduled.
|
||||
verify(mAlarmManager).set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
|
||||
eq(METRICS_COLLECTION_DURATION_MS * 2),
|
||||
any() /* tag */, listenerCaptor.capture(), eq(mTestHandler));
|
||||
}
|
||||
|
||||
private void setupResponseWithSocketExisting() throws Exception {
|
||||
final ByteBuffer tcpBufferV6 = getByteBuffer(TEST_RESPONSE_BYTES);
|
||||
final ByteBuffer tcpBufferV4 = getByteBuffer(TEST_RESPONSE_BYTES);
|
||||
|
||||
@@ -27,12 +27,15 @@ import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doCallRealMethod;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.TelephonyNetworkSpecifier;
|
||||
@@ -109,6 +112,18 @@ public class KeepaliveStatsTrackerTest {
|
||||
@Mock private KeepaliveStatsTracker.Dependencies mDependencies;
|
||||
@Mock private SubscriptionManager mSubscriptionManager;
|
||||
|
||||
private void triggerBroadcastDefaultSubId(int subId) {
|
||||
final ArgumentCaptor<BroadcastReceiver> receiverCaptor =
|
||||
ArgumentCaptor.forClass(BroadcastReceiver.class);
|
||||
verify(mContext).registerReceiver(receiverCaptor.capture(), /* filter= */ any(),
|
||||
/* broadcastPermission= */ any(), eq(mTestHandler));
|
||||
final Intent intent =
|
||||
new Intent(TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED);
|
||||
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
|
||||
|
||||
receiverCaptor.getValue().onReceive(mContext, intent);
|
||||
}
|
||||
|
||||
private OnSubscriptionsChangedListener getOnSubscriptionsChangedListener() {
|
||||
final ArgumentCaptor<OnSubscriptionsChangedListener> listenerCaptor =
|
||||
ArgumentCaptor.forClass(OnSubscriptionsChangedListener.class);
|
||||
@@ -1128,4 +1143,53 @@ public class KeepaliveStatsTrackerTest {
|
||||
writeTime * 3 - startTime1 - startTime2 - startTime3)
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateDefaultSubId() {
|
||||
final int startTime1 = 1000;
|
||||
final int startTime2 = 3000;
|
||||
final int writeTime = 5000;
|
||||
|
||||
// No TelephonyNetworkSpecifier set with subId to force the use of default subId.
|
||||
final NetworkCapabilities nc =
|
||||
new NetworkCapabilities.Builder().addTransportType(TRANSPORT_CELLULAR).build();
|
||||
onStartKeepalive(startTime1, TEST_SLOT, nc);
|
||||
// Update default subId
|
||||
triggerBroadcastDefaultSubId(TEST_SUB_ID_1);
|
||||
onStartKeepalive(startTime2, TEST_SLOT2, nc);
|
||||
|
||||
final DailykeepaliveInfoReported dailyKeepaliveInfoReported =
|
||||
buildKeepaliveMetrics(writeTime);
|
||||
|
||||
final int[] expectRegisteredDurations =
|
||||
new int[] {startTime1, startTime2 - startTime1, writeTime - startTime2};
|
||||
final int[] expectActiveDurations =
|
||||
new int[] {startTime1, startTime2 - startTime1, writeTime - startTime2};
|
||||
// Expect the carrier id of the first keepalive to be unknown
|
||||
final KeepaliveCarrierStats expectKeepaliveCarrierStats1 =
|
||||
new KeepaliveCarrierStats(
|
||||
TelephonyManager.UNKNOWN_CARRIER_ID,
|
||||
/* transportTypes= */ (1 << TRANSPORT_CELLULAR),
|
||||
TEST_KEEPALIVE_INTERVAL_SEC * 1000,
|
||||
writeTime - startTime1,
|
||||
writeTime - startTime1);
|
||||
// Expect the carrier id of the second keepalive to be TEST_CARRIER_ID_1, from TEST_SUB_ID_1
|
||||
final KeepaliveCarrierStats expectKeepaliveCarrierStats2 =
|
||||
new KeepaliveCarrierStats(
|
||||
TEST_CARRIER_ID_1,
|
||||
/* transportTypes= */ (1 << TRANSPORT_CELLULAR),
|
||||
TEST_KEEPALIVE_INTERVAL_SEC * 1000,
|
||||
writeTime - startTime2,
|
||||
writeTime - startTime2);
|
||||
assertDailyKeepaliveInfoReported(
|
||||
dailyKeepaliveInfoReported,
|
||||
/* expectRequestsCount= */ 2,
|
||||
/* expectAutoRequestsCount= */ 2,
|
||||
/* expectAppUids= */ new int[] {TEST_UID},
|
||||
expectRegisteredDurations,
|
||||
expectActiveDurations,
|
||||
new KeepaliveCarrierStats[] {
|
||||
expectKeepaliveCarrierStats1, expectKeepaliveCarrierStats2
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user