Merge "Condition Refactor." into tm-qpr-dev am: a4ba2978e6

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20071267

Change-Id: I40497cc9c528762663477f106547c9ddfbbb9255
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Bryce Lee
2022-10-11 22:23:45 +00:00
committed by Automerger Merge Worker
5 changed files with 195 additions and 19 deletions

View File

@@ -34,9 +34,26 @@ public abstract class Condition implements CallbackController<Condition.Callback
private final String mTag = getClass().getSimpleName();
private final ArrayList<WeakReference<Callback>> mCallbacks = new ArrayList<>();
private boolean mIsConditionMet = false;
private final boolean mOverriding;
private Boolean mIsConditionMet;
private boolean mStarted = false;
private boolean mOverriding = false;
/**
* By default, conditions have an initial value of false and are not overriding.
*/
public Condition() {
this(false, false);
}
/**
* Constructor for specifying initial state and overriding condition attribute.
* @param initialConditionMet Initial state of the condition.
* @param overriding Whether this condition overrides others.
*/
protected Condition(Boolean initialConditionMet, boolean overriding) {
mIsConditionMet = initialConditionMet;
mOverriding = overriding;
}
/**
* Starts monitoring the condition.
@@ -48,14 +65,6 @@ public abstract class Condition implements CallbackController<Condition.Callback
*/
protected abstract void stop();
/**
* Sets whether this condition's value overrides others in determining the overall state.
*/
public void setOverriding(boolean overriding) {
mOverriding = overriding;
updateCondition(mIsConditionMet);
}
/**
* Returns whether the current condition overrides
*/
@@ -110,13 +119,31 @@ public abstract class Condition implements CallbackController<Condition.Callback
* @param isConditionMet True if the condition has been fulfilled. False otherwise.
*/
protected void updateCondition(boolean isConditionMet) {
if (mIsConditionMet == isConditionMet) {
if (mIsConditionMet != null && mIsConditionMet == isConditionMet) {
return;
}
if (shouldLog()) Log.d(mTag, "updating condition to " + isConditionMet);
mIsConditionMet = isConditionMet;
sendUpdate();
}
/**
* Clears the set condition value. This is purposefully separate from
* {@link #updateCondition(boolean)} to avoid confusion around {@code null} values.
*/
protected void clearCondition() {
if (mIsConditionMet == null) {
return;
}
if (shouldLog()) Log.d(mTag, "clearing condition");
mIsConditionMet = null;
sendUpdate();
}
private void sendUpdate() {
final Iterator<WeakReference<Callback>> iterator = mCallbacks.iterator();
while (iterator.hasNext()) {
final Callback cb = iterator.next().get();
@@ -128,8 +155,21 @@ public abstract class Condition implements CallbackController<Condition.Callback
}
}
/**
* Returns whether the condition is set. This method should be consulted to understand the
* value of {@link #isConditionMet()}.
* @return {@code true} if value is present, {@code false} otherwise.
*/
public boolean isConditionSet() {
return mIsConditionMet != null;
}
/**
* Returns whether the condition has been met. Note that this method will return {@code false}
* if the condition is not set as well.
*/
public boolean isConditionMet() {
return mIsConditionMet;
return Boolean.TRUE.equals(mIsConditionMet);
}
private boolean shouldLog() {

View File

@@ -57,12 +57,16 @@ public class Monitor {
}
public void update() {
// Only consider set conditions.
final Collection<Condition> setConditions = mSubscription.mConditions.stream()
.filter(Condition::isConditionSet).collect(Collectors.toSet());
// Overriding conditions do not override each other
final Collection<Condition> overridingConditions = mSubscription.mConditions.stream()
final Collection<Condition> overridingConditions = setConditions.stream()
.filter(Condition::isOverridingCondition).collect(Collectors.toSet());
final Collection<Condition> targetCollection = overridingConditions.isEmpty()
? mSubscription.mConditions : overridingConditions;
? setConditions : overridingConditions;
final boolean newAllConditionsMet = targetCollection.isEmpty() ? true : targetCollection
.stream()

View File

@@ -73,10 +73,16 @@ public class ConditionMonitorTest extends SysuiTestCase {
.addConditions(mConditions);
}
private Condition createMockCondition() {
final Condition condition = Mockito.mock(Condition.class);
when(condition.isConditionSet()).thenReturn(true);
return condition;
}
@Test
public void testOverridingCondition() {
final Condition overridingCondition = Mockito.mock(Condition.class);
final Condition regularCondition = Mockito.mock(Condition.class);
final Condition overridingCondition = createMockCondition();
final Condition regularCondition = createMockCondition();
final Monitor.Callback callback = Mockito.mock(Monitor.Callback.class);
final Monitor.Callback referenceCallback = Mockito.mock(Monitor.Callback.class);
@@ -127,9 +133,9 @@ public class ConditionMonitorTest extends SysuiTestCase {
*/
@Test
public void testMultipleOverridingConditions() {
final Condition overridingCondition = Mockito.mock(Condition.class);
final Condition overridingCondition2 = Mockito.mock(Condition.class);
final Condition regularCondition = Mockito.mock(Condition.class);
final Condition overridingCondition = createMockCondition();
final Condition overridingCondition2 = createMockCondition();
final Condition regularCondition = createMockCondition();
final Monitor.Callback callback = Mockito.mock(Monitor.Callback.class);
final Monitor monitor = new Monitor(mExecutor);
@@ -340,4 +346,114 @@ public class ConditionMonitorTest extends SysuiTestCase {
mExecutor.runAllReady();
verify(callback).onConditionsChanged(true);
}
@Test
public void clearCondition_shouldUpdateValue() {
mCondition1.fakeUpdateCondition(false);
mCondition2.fakeUpdateCondition(true);
mCondition3.fakeUpdateCondition(true);
final Monitor.Callback callback =
mock(Monitor.Callback.class);
mConditionMonitor.addSubscription(getDefaultBuilder(callback).build());
mExecutor.runAllReady();
verify(callback).onConditionsChanged(false);
mCondition1.clearCondition();
mExecutor.runAllReady();
verify(callback).onConditionsChanged(true);
}
@Test
public void unsetCondition_shouldNotAffectValue() {
final FakeCondition settableCondition = new FakeCondition(null, false);
mCondition1.fakeUpdateCondition(true);
mCondition2.fakeUpdateCondition(true);
mCondition3.fakeUpdateCondition(true);
final Monitor.Callback callback =
mock(Monitor.Callback.class);
mConditionMonitor.addSubscription(getDefaultBuilder(callback)
.addCondition(settableCondition)
.build());
mExecutor.runAllReady();
verify(callback).onConditionsChanged(true);
}
@Test
public void setUnsetCondition_shouldAffectValue() {
final FakeCondition settableCondition = new FakeCondition(null, false);
mCondition1.fakeUpdateCondition(true);
mCondition2.fakeUpdateCondition(true);
mCondition3.fakeUpdateCondition(true);
final Monitor.Callback callback =
mock(Monitor.Callback.class);
mConditionMonitor.addSubscription(getDefaultBuilder(callback)
.addCondition(settableCondition)
.build());
mExecutor.runAllReady();
verify(callback).onConditionsChanged(true);
clearInvocations(callback);
settableCondition.fakeUpdateCondition(false);
mExecutor.runAllReady();
verify(callback).onConditionsChanged(false);
clearInvocations(callback);
settableCondition.clearCondition();
mExecutor.runAllReady();
verify(callback).onConditionsChanged(true);
}
@Test
public void clearingOverridingCondition_shouldBeExcluded() {
final FakeCondition overridingCondition = new FakeCondition(true, true);
mCondition1.fakeUpdateCondition(false);
mCondition2.fakeUpdateCondition(false);
mCondition3.fakeUpdateCondition(false);
final Monitor.Callback callback =
mock(Monitor.Callback.class);
mConditionMonitor.addSubscription(getDefaultBuilder(callback)
.addCondition(overridingCondition)
.build());
mExecutor.runAllReady();
verify(callback).onConditionsChanged(true);
clearInvocations(callback);
overridingCondition.clearCondition();
mExecutor.runAllReady();
verify(callback).onConditionsChanged(false);
}
@Test
public void settingUnsetOverridingCondition_shouldBeIncluded() {
final FakeCondition overridingCondition = new FakeCondition(null, true);
mCondition1.fakeUpdateCondition(false);
mCondition2.fakeUpdateCondition(false);
mCondition3.fakeUpdateCondition(false);
final Monitor.Callback callback =
mock(Monitor.Callback.class);
mConditionMonitor.addSubscription(getDefaultBuilder(callback)
.addCondition(overridingCondition)
.build());
mExecutor.runAllReady();
verify(callback).onConditionsChanged(false);
clearInvocations(callback);
overridingCondition.fakeUpdateCondition(true);
mExecutor.runAllReady();
verify(callback).onConditionsChanged(true);
}
}

View File

@@ -133,4 +133,12 @@ public class ConditionTest extends SysuiTestCase {
mCondition.fakeUpdateCondition(false);
verify(callback, never()).onConditionChanged(eq(mCondition));
}
@Test
public void clearCondition_reportsNotSet() {
mCondition.fakeUpdateCondition(false);
assertThat(mCondition.isConditionSet()).isTrue();
mCondition.clearCondition();
assertThat(mCondition.isConditionSet()).isFalse();
}
}

View File

@@ -21,6 +21,14 @@ package com.android.systemui.util.condition;
* condition fulfillment.
*/
public class FakeCondition extends Condition {
FakeCondition() {
super();
}
FakeCondition(Boolean initialValue, Boolean overriding) {
super(initialValue, overriding);
}
@Override
public void start() {}