Merge "Do not repeatedly connect to flaky communal sources."

This commit is contained in:
Bryce Lee
2021-12-01 02:31:42 +00:00
committed by Android (Google) Code Review
3 changed files with 57 additions and 3 deletions

View File

@@ -682,6 +682,9 @@
attempts. -->
<integer name="config_communalSourceReconnectBaseDelay">1000</integer>
<!-- The minimum time in milliseconds for a connection to be considered connected. Any time -->
<integer name="config_connectionMinDuration">1000</integer>
<!-- Flag to activate notification to contents feature -->
<bool name="config_notificationToContents">false</bool>

View File

@@ -25,6 +25,7 @@ import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.time.SystemClock;
import com.google.common.util.concurrent.ListenableFuture;
@@ -43,10 +44,12 @@ public class CommunalSourcePrimer extends CoreStartable {
private static final String TAG = "CommunalSourcePrimer";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final SystemClock mSystemClock;
private final DelayableExecutor mMainExecutor;
private final CommunalSourceMonitor mMonitor;
private final int mBaseReconnectDelayMs;
private final int mMaxReconnectAttempts;
private final int mMinConnectionDuration;
private int mReconnectAttempts = 0;
private Runnable mCurrentReconnectCancelable;
@@ -65,11 +68,13 @@ public class CommunalSourcePrimer extends CoreStartable {
@Inject
public CommunalSourcePrimer(Context context, @Main Resources resources,
SystemClock clock,
DelayableExecutor mainExecutor,
CommunalSourceMonitor monitor,
Optional<CommunalSource.Connector> connector,
Optional<CommunalSource.Observer> observer) {
super(context);
mSystemClock = clock;
mMainExecutor = mainExecutor;
mMonitor = monitor;
mConnector = connector;
@@ -79,6 +84,8 @@ public class CommunalSourcePrimer extends CoreStartable {
R.integer.config_communalSourceMaxReconnectAttempts);
mBaseReconnectDelayMs = resources.getInteger(
R.integer.config_communalSourceReconnectBaseDelay);
mMinConnectionDuration = resources.getInteger(
R.integer.config_connectionMinDuration);
}
@Override
@@ -145,10 +152,17 @@ public class CommunalSourcePrimer extends CoreStartable {
mGetSourceFuture = mConnector.get().connect();
mGetSourceFuture.addListener(() -> {
try {
final long startTime = mSystemClock.currentTimeMillis();
Optional<CommunalSource> result = mGetSourceFuture.get();
if (result.isPresent()) {
final CommunalSource source = result.get();
source.addCallback(() -> initiateConnectionAttempt());
source.addCallback(() -> {
if (mSystemClock.currentTimeMillis() - startTime > mMinConnectionDuration) {
initiateConnectionAttempt();
} else {
scheduleConnectionAttempt();
}
});
mMonitor.setSource(source);
} else {
scheduleConnectionAttempt();

View File

@@ -50,6 +50,7 @@ public class CommunalSourcePrimerTest extends SysuiTestCase {
private static final String TEST_COMPONENT_NAME = "com.google.tests/.CommunalService";
private static final int MAX_RETRIES = 5;
private static final int RETRY_DELAY_MS = 1000;
private static final int CONNECTION_MIN_DURATION_MS = 5000;
@Mock
private Context mContext;
@@ -57,7 +58,8 @@ public class CommunalSourcePrimerTest extends SysuiTestCase {
@Mock
private Resources mResources;
private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
private FakeSystemClock mFakeClock = new FakeSystemClock();
private FakeExecutor mFakeExecutor = new FakeExecutor(mFakeClock);
@Mock
private CommunalSource mSource;
@@ -80,10 +82,14 @@ public class CommunalSourcePrimerTest extends SysuiTestCase {
.thenReturn(MAX_RETRIES);
when(mResources.getInteger(R.integer.config_communalSourceReconnectBaseDelay))
.thenReturn(RETRY_DELAY_MS);
when(mResources.getInteger(R.integer.config_communalSourceReconnectBaseDelay))
.thenReturn(RETRY_DELAY_MS);
when(mResources.getString(R.string.config_communalSourceComponent))
.thenReturn(TEST_COMPONENT_NAME);
when(mResources.getInteger(R.integer.config_connectionMinDuration))
.thenReturn(CONNECTION_MIN_DURATION_MS);
mPrimer = new CommunalSourcePrimer(mContext, mResources, mFakeExecutor,
mPrimer = new CommunalSourcePrimer(mContext, mResources, mFakeClock, mFakeExecutor,
mCommunalSourceMonitor, Optional.of(mConnector), Optional.of(mObserver));
}
@@ -123,6 +129,36 @@ public class CommunalSourcePrimerTest extends SysuiTestCase {
verify(mCommunalSourceMonitor, never()).setSource(Mockito.notNull());
}
@Test
public void testRetryOnDisconnectFailure() throws Exception {
when(mConnector.connect()).thenReturn(
CallbackToFutureAdapter.getFuture(completer -> {
completer.set(Optional.of(mSource));
return "test";
}));
mPrimer.onBootCompleted();
mFakeExecutor.runAllReady();
// Verify attempts happen. Note that we account for the retries plus initial attempt, which
// is not scheduled.
for (int attemptCount = 0; attemptCount < MAX_RETRIES + 1; attemptCount++) {
verify(mConnector, times(1)).connect();
clearInvocations(mConnector);
ArgumentCaptor<CommunalSource.Callback> callbackCaptor =
ArgumentCaptor.forClass(CommunalSource.Callback.class);
verify(mSource).addCallback(callbackCaptor.capture());
clearInvocations(mSource);
verify(mCommunalSourceMonitor).setSource(Mockito.notNull());
clearInvocations(mCommunalSourceMonitor);
callbackCaptor.getValue().onDisconnected();
mFakeExecutor.advanceClockToNext();
mFakeExecutor.runAllReady();
}
verify(mConnector, never()).connect();
}
@Test
public void testAttemptOnPackageChange() {
when(mConnector.connect()).thenReturn(
@@ -161,6 +197,7 @@ public class CommunalSourcePrimerTest extends SysuiTestCase {
verify(mSource).addCallback(callbackCaptor.capture());
clearInvocations(mConnector);
mFakeClock.advanceTime(CONNECTION_MIN_DURATION_MS + 1);
callbackCaptor.getValue().onDisconnected();
mFakeExecutor.runAllReady();