ConditionalCoreStartable Introduction.
This changelist introduces ConditionalCoreStartable, an abstract implementation of CoreStartable that allows conditions to gate actions from lifecycle events (start/boot completed). Bug: 261420431 Test: atest ConditionalCoreStartableTest Change-Id: Ib4121d375f509ec16e8d2e34cdbee4f92f2ed7d6
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.util.condition;
|
||||
|
||||
import com.android.systemui.CoreStartable;
|
||||
import com.android.systemui.shared.condition.Condition;
|
||||
import com.android.systemui.shared.condition.Monitor;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* {@link ConditionalCoreStartable} is a {@link com.android.systemui.CoreStartable} abstract
|
||||
* implementation where conditions must be met before routines are executed.
|
||||
*/
|
||||
public abstract class ConditionalCoreStartable implements CoreStartable {
|
||||
private final Monitor mMonitor;
|
||||
private final Set<Condition> mConditionSet;
|
||||
private Monitor.Subscription.Token mStartToken;
|
||||
private Monitor.Subscription.Token mBootCompletedToken;
|
||||
|
||||
public ConditionalCoreStartable(Monitor monitor) {
|
||||
this(monitor, null);
|
||||
}
|
||||
|
||||
public ConditionalCoreStartable(Monitor monitor, Set<Condition> conditionSet) {
|
||||
mMonitor = monitor;
|
||||
mConditionSet = conditionSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void start() {
|
||||
if (mConditionSet == null || mConditionSet.isEmpty()) {
|
||||
onStart();
|
||||
return;
|
||||
}
|
||||
|
||||
mStartToken = mMonitor.addSubscription(
|
||||
new Monitor.Subscription.Builder(allConditionsMet -> {
|
||||
if (allConditionsMet) {
|
||||
mMonitor.removeSubscription(mStartToken);
|
||||
mStartToken = null;
|
||||
onStart();
|
||||
}
|
||||
}).addConditions(mConditionSet)
|
||||
.build());
|
||||
}
|
||||
|
||||
protected abstract void onStart();
|
||||
|
||||
@Override
|
||||
public final void onBootCompleted() {
|
||||
if (mConditionSet == null || mConditionSet.isEmpty()) {
|
||||
bootCompleted();
|
||||
return;
|
||||
}
|
||||
|
||||
mBootCompletedToken = mMonitor.addSubscription(
|
||||
new Monitor.Subscription.Builder(allConditionsMet -> {
|
||||
if (allConditionsMet) {
|
||||
mMonitor.removeSubscription(mBootCompletedToken);
|
||||
mBootCompletedToken = null;
|
||||
bootCompleted();
|
||||
}
|
||||
}).addConditions(mConditionSet)
|
||||
.build());
|
||||
}
|
||||
|
||||
protected void bootCompleted() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.util.condition;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.testing.AndroidTestingRunner;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.CoreStartable;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.shared.condition.Condition;
|
||||
import com.android.systemui.shared.condition.Monitor;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class ConditionalCoreStartableTest extends SysuiTestCase {
|
||||
public static class FakeConditionalCoreStartable extends ConditionalCoreStartable {
|
||||
interface Callback {
|
||||
void onStart();
|
||||
void bootCompleted();
|
||||
}
|
||||
|
||||
private final Callback mCallback;
|
||||
|
||||
public FakeConditionalCoreStartable(Monitor monitor, Set<Condition> conditions,
|
||||
Callback callback) {
|
||||
super(monitor, conditions);
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
mCallback.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bootCompleted() {
|
||||
mCallback.bootCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final Set<Condition> mConditions = new HashSet<>();
|
||||
|
||||
@Mock
|
||||
Condition mCondition;
|
||||
|
||||
@Mock
|
||||
Monitor mMonitor;
|
||||
|
||||
@Mock
|
||||
FakeConditionalCoreStartable.Callback mCallback;
|
||||
|
||||
@Mock
|
||||
Monitor.Subscription.Token mSubscriptionToken;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mConditions.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that {@link ConditionalCoreStartable#onStart()} is predicated on conditions being
|
||||
* met.
|
||||
*/
|
||||
@Test
|
||||
public void testOnStartCallback() {
|
||||
final CoreStartable coreStartable =
|
||||
new FakeConditionalCoreStartable(mMonitor,
|
||||
new HashSet<>(Arrays.asList(mCondition)),
|
||||
mCallback);
|
||||
|
||||
when(mMonitor.addSubscription(any())).thenReturn(mSubscriptionToken);
|
||||
coreStartable.start();
|
||||
|
||||
final ArgumentCaptor<Monitor.Subscription> subscriptionCaptor = ArgumentCaptor.forClass(
|
||||
Monitor.Subscription.class);
|
||||
verify(mMonitor).addSubscription(subscriptionCaptor.capture());
|
||||
|
||||
final Monitor.Subscription subscription = subscriptionCaptor.getValue();
|
||||
|
||||
assertThat(subscription.getConditions()).containsExactly(mCondition);
|
||||
|
||||
verify(mCallback, never()).onStart();
|
||||
|
||||
subscription.getCallback().onConditionsChanged(true);
|
||||
|
||||
verify(mCallback).onStart();
|
||||
verify(mMonitor).removeSubscription(mSubscriptionToken);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verifies that {@link ConditionalCoreStartable#bootCompleted()} ()} is predicated on
|
||||
* conditions being met.
|
||||
*/
|
||||
@Test
|
||||
public void testBootCompleted() {
|
||||
final CoreStartable coreStartable =
|
||||
new FakeConditionalCoreStartable(mMonitor,
|
||||
new HashSet<>(Arrays.asList(mCondition)),
|
||||
mCallback);
|
||||
|
||||
when(mMonitor.addSubscription(any())).thenReturn(mSubscriptionToken);
|
||||
coreStartable.onBootCompleted();
|
||||
|
||||
final ArgumentCaptor<Monitor.Subscription> subscriptionCaptor = ArgumentCaptor.forClass(
|
||||
Monitor.Subscription.class);
|
||||
verify(mMonitor).addSubscription(subscriptionCaptor.capture());
|
||||
|
||||
final Monitor.Subscription subscription = subscriptionCaptor.getValue();
|
||||
|
||||
assertThat(subscription.getConditions()).containsExactly(mCondition);
|
||||
|
||||
verify(mCallback, never()).bootCompleted();
|
||||
|
||||
subscription.getCallback().onConditionsChanged(true);
|
||||
|
||||
verify(mCallback).bootCompleted();
|
||||
verify(mMonitor).removeSubscription(mSubscriptionToken);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user