Move Complication logic out of DreamOverlay.

This changelist lifts the complication logic, including the
ComplicatHostViewController and ComplicationLayoutEngine, out of
DreamOverlay. This allows these components to be used elsewhere.
Complications are now bound into the DreamOverlayComponent,
passed through from the DreamOverlayService.

Test: atest DreamOverlayServiceTest
Bug: 261781069
Change-Id: I81879e6050d4d0cdeeac69b74acb4fbd548647f5
This commit is contained in:
Bryce Lee
2022-12-07 11:18:28 -08:00
parent bdd33e3b59
commit 1a33563df3
9 changed files with 97 additions and 59 deletions

View File

@@ -45,7 +45,10 @@ import com.android.systemui.dreams.complication.Complication;
import com.android.systemui.dreams.complication.dagger.ComplicationComponent;
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
import com.android.systemui.dreams.touch.DreamOverlayTouchMonitor;
import com.android.systemui.touch.TouchInsetManager;
import java.util.Arrays;
import java.util.HashSet;
import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -84,6 +87,9 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
private final ComplicationComponent mComplicationComponent;
private final com.android.systemui.dreams.dreamcomplication.dagger.ComplicationComponent
mDreamComplicationComponent;
private final DreamOverlayComponent mDreamOverlayComponent;
private final DreamOverlayLifecycleOwner mLifecycleOwner;
@@ -135,10 +141,13 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
DreamOverlayLifecycleOwner lifecycleOwner,
WindowManager windowManager,
ComplicationComponent.Factory complicationComponentFactory,
com.android.systemui.dreams.dreamcomplication.dagger.ComplicationComponent.Factory
dreamComplicationComponentFactory,
DreamOverlayComponent.Factory dreamOverlayComponentFactory,
DreamOverlayStateController stateController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
UiEventLogger uiEventLogger,
TouchInsetManager touchInsetManager,
@Nullable @Named(LowLightDreamModule.LOW_LIGHT_DREAM_COMPONENT)
ComponentName lowLightDreamComponent) {
mContext = context;
@@ -154,9 +163,14 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
final Complication.Host host =
() -> mExecutor.execute(DreamOverlayService.this::requestExit);
mComplicationComponent = complicationComponentFactory.create();
mDreamOverlayComponent =
dreamOverlayComponentFactory.create(lifecycleOwner, viewModelStore, host, null);
mComplicationComponent = complicationComponentFactory.create(lifecycleOwner, host,
viewModelStore, touchInsetManager);
mDreamComplicationComponent = dreamComplicationComponentFactory.create(
mComplicationComponent.getVisibilityController(), touchInsetManager);
mDreamOverlayComponent = dreamOverlayComponentFactory.create(lifecycleOwner,
mComplicationComponent.getComplicationHostViewController(), touchInsetManager,
new HashSet<>(Arrays.asList(
mDreamComplicationComponent.getHideComplicationTouchHandler())));
mLifecycleOwner = lifecycleOwner;
mLifecycleRegistry = mLifecycleOwner.getRegistry();

View File

@@ -30,7 +30,7 @@ import androidx.constraintlayout.widget.Constraints;
import com.android.systemui.R;
import com.android.systemui.dreams.complication.ComplicationLayoutParams.Position;
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
import com.android.systemui.dreams.complication.dagger.ComplicationModule;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.touch.TouchInsetManager;
@@ -50,7 +50,7 @@ import javax.inject.Named;
* their layout parameters and attributes. The management of this set is done by
* {@link ComplicationHostViewController}.
*/
@DreamOverlayComponent.DreamOverlayScope
@ComplicationModule.ComplicationScope
public class ComplicationLayoutEngine implements Complication.VisibilityController {
public static final String TAG = "ComplicationLayoutEng";

View File

@@ -1,12 +1,29 @@
package com.android.systemui.dreams.complication.dagger
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModelStore
import com.android.systemui.dreams.complication.Complication
import com.android.systemui.dreams.complication.ComplicationHostViewController
import com.android.systemui.dreams.complication.ComplicationLayoutEngine
import com.android.systemui.touch.TouchInsetManager
import dagger.BindsInstance
import dagger.Subcomponent
@Subcomponent
@Subcomponent(modules = [ComplicationModule::class])
@ComplicationModule.ComplicationScope
interface ComplicationComponent {
/** Factory for generating [ComplicationComponent]. */
@Subcomponent.Factory
interface Factory {
fun create(): ComplicationComponent
fun create(
@BindsInstance lifecycleOwner: LifecycleOwner,
@BindsInstance host: Complication.Host,
@BindsInstance viewModelStore: ViewModelStore,
@BindsInstance touchInsetManager: TouchInsetManager
): ComplicationComponent
}
fun getComplicationHostViewController(): ComplicationHostViewController
fun getVisibilityController(): ComplicationLayoutEngine
}

View File

@@ -24,13 +24,12 @@ import androidx.constraintlayout.widget.ConstraintLayout;
import com.android.internal.util.Preconditions;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
import javax.inject.Named;
import dagger.Module;
import dagger.Provides;
import javax.inject.Named;
/**
* Module for providing a scoped host view.
*/
@@ -49,7 +48,7 @@ public abstract class ComplicationHostViewModule {
*/
@Provides
@Named(SCOPED_COMPLICATIONS_LAYOUT)
@DreamOverlayComponent.DreamOverlayScope
@ComplicationModule.ComplicationScope
static ConstraintLayout providesComplicationHostView(
LayoutInflater layoutInflater) {
return Preconditions.checkNotNull((ConstraintLayout)
@@ -60,7 +59,6 @@ public abstract class ComplicationHostViewModule {
@Provides
@Named(COMPLICATION_MARGIN_DEFAULT)
@DreamOverlayComponent.DreamOverlayScope
static int providesComplicationPadding(@Main Resources resources) {
return resources.getDimensionPixelSize(R.dimen.dream_overlay_complication_margin);
}
@@ -70,7 +68,6 @@ public abstract class ComplicationHostViewModule {
*/
@Provides
@Named(COMPLICATIONS_FADE_OUT_DURATION)
@DreamOverlayComponent.DreamOverlayScope
static int providesComplicationsFadeOutDuration(@Main Resources resources) {
return resources.getInteger(R.integer.complicationFadeOutMs);
}
@@ -80,7 +77,6 @@ public abstract class ComplicationHostViewModule {
*/
@Provides
@Named(COMPLICATIONS_FADE_OUT_DELAY)
@DreamOverlayComponent.DreamOverlayScope
static int providesComplicationsFadeOutDelay(@Main Resources resources) {
return resources.getInteger(R.integer.complicationFadeOutDelayMs);
}
@@ -90,7 +86,6 @@ public abstract class ComplicationHostViewModule {
*/
@Provides
@Named(COMPLICATIONS_FADE_IN_DURATION)
@DreamOverlayComponent.DreamOverlayScope
static int providesComplicationsFadeInDuration(@Main Resources resources) {
return resources.getInteger(R.integer.complicationFadeInMs);
}
@@ -100,7 +95,6 @@ public abstract class ComplicationHostViewModule {
*/
@Provides
@Named(COMPLICATIONS_RESTORE_TIMEOUT)
@DreamOverlayComponent.DreamOverlayScope
static int providesComplicationsRestoreTimeout(@Main Resources resources) {
return resources.getInteger(R.integer.complicationRestoreMs);
}

View File

@@ -24,16 +24,16 @@ import androidx.lifecycle.ViewModelStore;
import com.android.systemui.dreams.complication.Complication;
import com.android.systemui.dreams.complication.ComplicationCollectionViewModel;
import com.android.systemui.dreams.complication.ComplicationLayoutEngine;
import com.android.systemui.touch.TouchInsetManager;
import dagger.Module;
import dagger.Provides;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import javax.inject.Named;
import javax.inject.Scope;
import dagger.Module;
import dagger.Provides;
/**
* Module for housing components related to rendering complications.
*/
@@ -73,4 +73,13 @@ public interface ComplicationModule {
ComplicationLayoutEngine engine) {
return engine;
}
/**
* Provides a new touch inset session instance for complication logic.
*/
@Provides
static TouchInsetManager.TouchInsetSession providesTouchInsetSession(
TouchInsetManager manager) {
return manager.createSession();
}
}

View File

@@ -23,14 +23,13 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
import android.annotation.Nullable;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ViewModelStore;
import com.android.systemui.dreams.DreamOverlayContainerViewController;
import com.android.systemui.dreams.complication.Complication;
import com.android.systemui.dreams.complication.dagger.ComplicationModule;
import com.android.systemui.dreams.complication.ComplicationHostViewController;
import com.android.systemui.dreams.touch.DreamOverlayTouchMonitor;
import com.android.systemui.dreams.touch.DreamTouchHandler;
import com.android.systemui.dreams.touch.dagger.DreamTouchModule;
import com.android.systemui.touch.TouchInsetManager;
import dagger.BindsInstance;
import dagger.Subcomponent;
@@ -48,7 +47,6 @@ import javax.inject.Scope;
@Subcomponent(modules = {
DreamTouchModule.class,
DreamOverlayModule.class,
ComplicationModule.class,
})
@DreamOverlayComponent.DreamOverlayScope
public interface DreamOverlayComponent {
@@ -57,8 +55,8 @@ public interface DreamOverlayComponent {
interface Factory {
DreamOverlayComponent create(
@BindsInstance LifecycleOwner lifecycleOwner,
@BindsInstance ViewModelStore store,
@BindsInstance Complication.Host host,
@BindsInstance ComplicationHostViewController complicationHostViewController,
@BindsInstance TouchInsetManager touchInsetManager,
@BindsInstance @Named(DREAM_TOUCH_HANDLERS) @Nullable
Set<DreamTouchHandler> dreamTouchHandlers);
}

View File

@@ -29,20 +29,15 @@ import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.DreamOverlayContainerView;
import com.android.systemui.dreams.DreamOverlayStatusBarView;
import com.android.systemui.dreams.complication.Complication;
import com.android.systemui.dreams.dreamcomplication.HideComplicationTouchHandler;
import com.android.systemui.dreams.dreamcomplication.dagger.ComplicationComponent;
import com.android.systemui.dreams.touch.DreamTouchHandler;
import com.android.systemui.touch.TouchInsetManager;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.ElementsIntoSet;
import dagger.multibindings.IntoSet;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Executor;
import javax.inject.Named;
@@ -106,13 +101,6 @@ public abstract class DreamOverlayModule {
return manager.createSession();
}
/** */
@Provides
@DreamOverlayComponent.DreamOverlayScope
public static TouchInsetManager providesTouchInsetManager(@Main Executor executor) {
return new TouchInsetManager(executor);
}
/** */
@Provides
@DreamOverlayComponent.DreamOverlayScope
@@ -263,18 +251,4 @@ public abstract class DreamOverlayModule {
@Named(DREAM_TOUCH_HANDLERS) @Nullable Set<DreamTouchHandler> touchHandlers) {
return touchHandlers != null ? touchHandlers : new HashSet<>();
}
/**
* Provides {@link HideComplicationTouchHandler} for inclusion in touch handling over the dream.
*/
@Provides
@IntoSet
public static DreamTouchHandler providesHideComplicationTouchHandler(
ComplicationComponent.Factory componentFactory,
Complication.VisibilityController visibilityController,
TouchInsetManager touchInsetManager) {
ComplicationComponent component =
componentFactory.create(visibilityController, touchInsetManager);
return component.getHideComplicationTouchHandler();
}
}

View File

@@ -24,12 +24,16 @@ import android.view.View;
import androidx.concurrent.futures.CallbackToFutureAdapter;
import com.android.systemui.dagger.qualifiers.Main;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.Executor;
import javax.inject.Inject;
/**
* {@link TouchInsetManager} handles setting the touchable inset regions for a given View. This
* is useful for passing through touch events for all but select areas.
@@ -141,7 +145,8 @@ public class TouchInsetManager {
* Default constructor.
* @param executor An {@link Executor} to marshal all operations on.
*/
public TouchInsetManager(Executor executor) {
@Inject
public TouchInsetManager(@Main Executor executor) {
mExecutor = executor;
}

View File

@@ -19,7 +19,6 @@ package com.android.systemui.dreams;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -45,9 +44,12 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.UiEventLogger;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dreams.complication.ComplicationLayoutEngine;
import com.android.systemui.dreams.complication.dagger.ComplicationComponent;
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
import com.android.systemui.dreams.dreamcomplication.HideComplicationTouchHandler;
import com.android.systemui.dreams.touch.DreamOverlayTouchMonitor;
import com.android.systemui.touch.TouchInsetManager;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.utils.leaks.LeakCheckedTest;
@@ -93,6 +95,20 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
@Mock
ComplicationComponent mComplicationComponent;
@Mock
ComplicationLayoutEngine mComplicationVisibilityController;
@Mock
com.android.systemui.dreams.dreamcomplication.dagger.ComplicationComponent.Factory
mDreamComplicationComponentFactory;
@Mock
com.android.systemui.dreams.dreamcomplication.dagger.ComplicationComponent
mDreamComplicationComponent;
@Mock
HideComplicationTouchHandler mHideComplicationTouchHandler;
@Mock
DreamOverlayComponent.Factory mDreamOverlayComponentFactory;
@@ -117,6 +133,9 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
@Mock
ViewGroup mDreamOverlayContainerViewParent;
@Mock
TouchInsetManager mTouchInsetManager;
@Mock
UiEventLogger mUiEventLogger;
@@ -136,25 +155,33 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
when(mDreamOverlayComponent.getDreamOverlayTouchMonitor())
.thenReturn(mDreamOverlayTouchMonitor);
when(mComplicationComponentFactory
.create())
.create(any(), any(), any(), any()))
.thenReturn(mComplicationComponent);
// TODO(b/261781069): A touch handler should be passed in from the complication component
// when the complication component is introduced.
when(mComplicationComponent.getVisibilityController())
.thenReturn(mComplicationVisibilityController);
when(mDreamComplicationComponent.getHideComplicationTouchHandler())
.thenReturn(mHideComplicationTouchHandler);
when(mDreamComplicationComponentFactory
.create(any(), any()))
.thenReturn(mDreamComplicationComponent);
when(mDreamOverlayComponentFactory
.create(any(), any(), any(), isNull()))
.create(any(), any(), any(), any()))
.thenReturn(mDreamOverlayComponent);
when(mDreamOverlayContainerViewController.getContainerView())
.thenReturn(mDreamOverlayContainerView);
mService = new DreamOverlayService(mContext,
mService = new DreamOverlayService(
mContext,
mMainExecutor,
mLifecycleOwner,
mWindowManager,
mComplicationComponentFactory,
mDreamComplicationComponentFactory,
mDreamOverlayComponentFactory,
mStateController,
mKeyguardUpdateMonitor,
mUiEventLogger,
mTouchInsetManager,
LOW_LIGHT_COMPONENT);
}