From 078fb82e834cafb45cd61351ef76134b4a885cb6 Mon Sep 17 00:00:00 2001 From: Nick Ning Date: Thu, 27 Jan 2022 15:11:50 +0000 Subject: [PATCH] Added Complication implementations for Dream Weather, Clock Time, and Clock Time. Implemented all three complications layer native widgets. Bug: 213906528 Test: aTest DreamWeatherComplicationTest DreamClockTimeComplicationTest DreamClockDateComplicationTest Change-Id: I24d8f58f0f8f4baa1ed64f6a9a7644825be5dd51 --- .../dream_overlay_complication_clock_date.xml | 30 +++ .../dream_overlay_complication_clock_time.xml | 29 +++ .../dream_overlay_complication_weather.xml | 27 +++ .../dream_overlay_complications_layer.xml | 28 --- packages/SystemUI/res/values/dimens.xml | 10 + .../systemui/dagger/SystemUIBinder.java | 24 +++ .../DreamClockDateComplication.java | 106 +++++++++++ .../DreamClockTimeComplication.java | 106 +++++++++++ .../DreamWeatherComplication.java | 180 ++++++++++++++++++ .../DreamClockDateComplicationComponent.java | 111 +++++++++++ .../DreamClockTimeComplicationComponent.java | 111 +++++++++++ .../DreamWeatherComplicationComponent.java | 111 +++++++++++ .../dagger/RegisteredComplicationsModule.java | 33 ++++ .../systemui/dreams/dagger/DreamModule.java | 2 + .../DreamClockDateComplicationTest.java | 66 +++++++ .../DreamClockTimeComplicationTest.java | 66 +++++++ .../DreamWeatherComplicationTest.java | 79 ++++++++ 17 files changed, 1091 insertions(+), 28 deletions(-) create mode 100644 packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml create mode 100644 packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml create mode 100644 packages/SystemUI/res/layout/dream_overlay_complication_weather.xml create mode 100644 packages/SystemUI/src/com/android/systemui/dreams/complication/DreamClockDateComplication.java create mode 100644 packages/SystemUI/src/com/android/systemui/dreams/complication/DreamClockTimeComplication.java create mode 100644 packages/SystemUI/src/com/android/systemui/dreams/complication/DreamWeatherComplication.java create mode 100644 packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockDateComplicationComponent.java create mode 100644 packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockTimeComplicationComponent.java create mode 100644 packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamWeatherComplicationComponent.java create mode 100644 packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java create mode 100644 packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamClockDateComplicationTest.java create mode 100644 packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamClockTimeComplicationTest.java create mode 100644 packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamWeatherComplicationTest.java diff --git a/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml b/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml new file mode 100644 index 0000000000000..b6f516fd2042a --- /dev/null +++ b/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml @@ -0,0 +1,30 @@ + + + diff --git a/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml b/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml new file mode 100644 index 0000000000000..a41d34f8ab41f --- /dev/null +++ b/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml @@ -0,0 +1,29 @@ + + + diff --git a/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml b/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml new file mode 100644 index 0000000000000..08f0d6781b045 --- /dev/null +++ b/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml @@ -0,0 +1,27 @@ + + + diff --git a/packages/SystemUI/res/layout/dream_overlay_complications_layer.xml b/packages/SystemUI/res/layout/dream_overlay_complications_layer.xml index 2d565a1a04fca..f4eb32f7cf22e 100644 --- a/packages/SystemUI/res/layout/dream_overlay_complications_layer.xml +++ b/packages/SystemUI/res/layout/dream_overlay_complications_layer.xml @@ -20,34 +20,6 @@ android:id="@+id/dream_overlay_complications_layer" android:layout_width="match_parent" android:layout_height="match_parent"> - - 100dp + + 50dp + 72sp + 60dp + 50dp + 18sp + 20dp + 50dp + 18sp + diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java index 41287b60fbf87..ec2beb15959e7 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java @@ -27,6 +27,9 @@ import com.android.systemui.biometrics.AuthController; import com.android.systemui.clipboardoverlay.ClipboardListener; import com.android.systemui.dreams.DreamOverlayRegistrant; import com.android.systemui.dreams.SmartSpaceComplication; +import com.android.systemui.dreams.complication.DreamClockDateComplication; +import com.android.systemui.dreams.complication.DreamClockTimeComplication; +import com.android.systemui.dreams.complication.DreamWeatherComplication; import com.android.systemui.globalactions.GlobalActionsComponent; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.dagger.KeyguardModule; @@ -234,4 +237,25 @@ public abstract class SystemUIBinder { @ClassKey(MediaDreamSentinel.class) public abstract CoreStartable bindMediaDreamSentinel( MediaDreamSentinel sentinel); + + /** Inject into DreamClockTimeComplication.Registrant */ + @Binds + @IntoMap + @ClassKey(DreamClockTimeComplication.Registrant.class) + public abstract CoreStartable bindDreamClockTimeComplicationRegistrant( + DreamClockTimeComplication.Registrant registrant); + + /** Inject into DreamClockDateComplication.Registrant */ + @Binds + @IntoMap + @ClassKey(DreamClockDateComplication.Registrant.class) + public abstract CoreStartable bindDreamClockDateComplicationRegistrant( + DreamClockDateComplication.Registrant registrant); + + /** Inject into DreamWeatherComplication.Registrant */ + @Binds + @IntoMap + @ClassKey(DreamWeatherComplication.Registrant.class) + public abstract CoreStartable bindDreamWeatherComplicationRegistrant( + DreamWeatherComplication.Registrant registrant); } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamClockDateComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamClockDateComplication.java new file mode 100644 index 0000000000000..59c52b9e402b4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamClockDateComplication.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2022 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.dreams.complication; + +import static com.android.systemui.dreams.complication.dagger.DreamClockDateComplicationComponent.DreamClockDateComplicationModule.DREAM_CLOCK_DATE_COMPLICATION_LAYOUT_PARAMS; +import static com.android.systemui.dreams.complication.dagger.DreamClockDateComplicationComponent.DreamClockDateComplicationModule.DREAM_CLOCK_DATE_COMPLICATION_VIEW; + +import android.content.Context; +import android.view.View; + +import com.android.systemui.CoreStartable; +import com.android.systemui.dreams.DreamOverlayStateController; +import com.android.systemui.dreams.complication.dagger.DreamClockDateComplicationComponent; + +import javax.inject.Inject; +import javax.inject.Named; + +/** + * Clock Date Complication that produce Clock Date view holder. + */ +public class DreamClockDateComplication implements Complication { + DreamClockDateComplicationComponent.Factory mComponentFactory; + + /** + * Default constructor for {@link DreamClockDateComplication}. + */ + @Inject + public DreamClockDateComplication( + DreamClockDateComplicationComponent.Factory componentFactory) { + mComponentFactory = componentFactory; + } + + /** + * Create {@link DreamClockDateViewHolder}. + */ + @Override + public ViewHolder createView(ComplicationViewModel model) { + return mComponentFactory.create().getViewHolder(); + } + + /** + * {@link CoreStartable} responsbile for registering {@link DreamClockDateComplication} with + * SystemUI. + */ + public static class Registrant extends CoreStartable { + private final DreamOverlayStateController mDreamOverlayStateController; + private final DreamClockDateComplication mComplication; + + /** + * Default constructor to register {@link DreamClockDateComplication}. + */ + @Inject + public Registrant(Context context, + DreamOverlayStateController dreamOverlayStateController, + DreamClockDateComplication dreamClockDateComplication) { + super(context); + mDreamOverlayStateController = dreamOverlayStateController; + mComplication = dreamClockDateComplication; + } + + @Override + public void start() { + mDreamOverlayStateController.addComplication(mComplication); + } + } + + /** + * ViewHolder to contain value/logic associated with a Clock Date Complication View. + */ + public static class DreamClockDateViewHolder implements ViewHolder { + private final View mView; + private final ComplicationLayoutParams mLayoutParams; + + @Inject + DreamClockDateViewHolder(@Named(DREAM_CLOCK_DATE_COMPLICATION_VIEW) View view, + @Named(DREAM_CLOCK_DATE_COMPLICATION_LAYOUT_PARAMS) + ComplicationLayoutParams layoutParams) { + mView = view; + mLayoutParams = layoutParams; + } + + @Override + public View getView() { + return mView; + } + + @Override + public ComplicationLayoutParams getLayoutParams() { + return mLayoutParams; + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamClockTimeComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamClockTimeComplication.java new file mode 100644 index 0000000000000..b0c3a424cc921 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamClockTimeComplication.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2022 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.dreams.complication; + +import static com.android.systemui.dreams.complication.dagger.DreamClockTimeComplicationComponent.DreamClockTimeComplicationModule.DREAM_CLOCK_TIME_COMPLICATION_LAYOUT_PARAMS; +import static com.android.systemui.dreams.complication.dagger.DreamClockTimeComplicationComponent.DreamClockTimeComplicationModule.DREAM_CLOCK_TIME_COMPLICATION_VIEW; + +import android.content.Context; +import android.view.View; + +import com.android.systemui.CoreStartable; +import com.android.systemui.dreams.DreamOverlayStateController; +import com.android.systemui.dreams.complication.dagger.DreamClockTimeComplicationComponent; + +import javax.inject.Inject; +import javax.inject.Named; + +/** + * Clock Time Complication that produce Clock Time view holder. + */ +public class DreamClockTimeComplication implements Complication { + DreamClockTimeComplicationComponent.Factory mComponentFactory; + + /** + * Default constructor for {@link DreamClockTimeComplication}. + */ + @Inject + public DreamClockTimeComplication( + DreamClockTimeComplicationComponent.Factory componentFactory) { + mComponentFactory = componentFactory; + } + + /** + * Create {@link DreamClockTimeViewHolder}. + */ + @Override + public ViewHolder createView(ComplicationViewModel model) { + return mComponentFactory.create().getViewHolder(); + } + + /** + * {@link CoreStartable} responsbile for registering {@link DreamClockTimeComplication} with + * SystemUI. + */ + public static class Registrant extends CoreStartable { + private final DreamOverlayStateController mDreamOverlayStateController; + private final DreamClockTimeComplication mComplication; + + /** + * Default constructor to register {@link DreamClockTimeComplication}. + */ + @Inject + public Registrant(Context context, + DreamOverlayStateController dreamOverlayStateController, + DreamClockTimeComplication dreamClockTimeComplication) { + super(context); + mDreamOverlayStateController = dreamOverlayStateController; + mComplication = dreamClockTimeComplication; + } + + @Override + public void start() { + mDreamOverlayStateController.addComplication(mComplication); + } + } + + /** + * ViewHolder to contain value/logic associated with a Clock Time Complication View. + */ + public static class DreamClockTimeViewHolder implements ViewHolder { + private final View mView; + private final ComplicationLayoutParams mLayoutParams; + + @Inject + DreamClockTimeViewHolder(@Named(DREAM_CLOCK_TIME_COMPLICATION_VIEW) View view, + @Named(DREAM_CLOCK_TIME_COMPLICATION_LAYOUT_PARAMS) + ComplicationLayoutParams layoutParams) { + mView = view; + mLayoutParams = layoutParams; + } + + @Override + public View getView() { + return mView; + } + + @Override + public ComplicationLayoutParams getLayoutParams() { + return mLayoutParams; + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamWeatherComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamWeatherComplication.java new file mode 100644 index 0000000000000..cbdbef3ae57e3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamWeatherComplication.java @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2022 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.dreams.complication; + +import static com.android.systemui.dreams.complication.dagger.DreamWeatherComplicationComponent.DreamWeatherComplicationModule.DREAM_WEATHER_COMPLICATION_LAYOUT_PARAMS; +import static com.android.systemui.dreams.complication.dagger.DreamWeatherComplicationComponent.DreamWeatherComplicationModule.DREAM_WEATHER_COMPLICATION_VIEW; + +import android.app.smartspace.SmartspaceAction; +import android.app.smartspace.SmartspaceTarget; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; +import android.text.TextUtils; +import android.widget.TextView; + +import com.android.systemui.CoreStartable; +import com.android.systemui.R; +import com.android.systemui.dreams.DreamOverlayStateController; +import com.android.systemui.dreams.complication.dagger.DreamWeatherComplicationComponent; +import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener; +import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController; +import com.android.systemui.util.ViewController; + +import javax.inject.Inject; +import javax.inject.Named; + +/** + * Weather Complication that produce Weather view holder. + */ +public class DreamWeatherComplication implements Complication { + DreamWeatherComplicationComponent.Factory mComponentFactory; + + /** + * Default constructor for {@link DreamWeatherComplication}. + */ + @Inject + public DreamWeatherComplication( + DreamWeatherComplicationComponent.Factory componentFactory) { + mComponentFactory = componentFactory; + } + + /** + * Create {@link DreamWeatherViewHolder}. + */ + @Override + public ViewHolder createView(ComplicationViewModel model) { + return mComponentFactory.create().getViewHolder(); + } + + /** + * {@link CoreStartable} for registering {@link DreamWeatherComplication} with SystemUI. + */ + public static class Registrant extends CoreStartable { + private final LockscreenSmartspaceController mSmartSpaceController; + private final DreamOverlayStateController mDreamOverlayStateController; + private final DreamWeatherComplication mComplication; + + /** + * Default constructor to register {@link DreamWeatherComplication}. + */ + @Inject + public Registrant(Context context, + LockscreenSmartspaceController smartspaceController, + DreamOverlayStateController dreamOverlayStateController, + DreamWeatherComplication dreamWeatherComplication) { + super(context); + mSmartSpaceController = smartspaceController; + mDreamOverlayStateController = dreamOverlayStateController; + mComplication = dreamWeatherComplication; + } + + @Override + public void start() { + if (mSmartSpaceController.isEnabled()) { + mDreamOverlayStateController.addComplication(mComplication); + } + } + } + + /** + * ViewHolder to contain value/logic associated with a Weather Complication View. + */ + public static class DreamWeatherViewHolder implements ViewHolder { + private final TextView mView; + private final ComplicationLayoutParams mLayoutParams; + private final DreamWeatherViewController mViewController; + + @Inject + DreamWeatherViewHolder( + @Named(DREAM_WEATHER_COMPLICATION_VIEW) TextView view, + DreamWeatherViewController controller, + @Named(DREAM_WEATHER_COMPLICATION_LAYOUT_PARAMS) + ComplicationLayoutParams layoutParams) { + mView = view; + mLayoutParams = layoutParams; + mViewController = controller; + mViewController.init(); + } + + @Override + public TextView getView() { + return mView; + } + + @Override + public ComplicationLayoutParams getLayoutParams() { + return mLayoutParams; + } + } + + /** + * ViewController to contain value/logic associated with a Weather Complication View. + */ + static class DreamWeatherViewController extends ViewController { + private final LockscreenSmartspaceController mSmartSpaceController; + private SmartspaceTargetListener mSmartspaceTargetListener; + + @Inject + DreamWeatherViewController( + @Named(DREAM_WEATHER_COMPLICATION_VIEW) TextView view, + LockscreenSmartspaceController smartspaceController + ) { + super(view); + mSmartSpaceController = smartspaceController; + } + + @Override + protected void onViewAttached() { + mSmartspaceTargetListener = targets -> targets.forEach( + t -> { + if (t instanceof SmartspaceTarget + && ((SmartspaceTarget) t).getFeatureType() + == SmartspaceTarget.FEATURE_WEATHER) { + final SmartspaceTarget target = (SmartspaceTarget) t; + final SmartspaceAction headerAction = target.getHeaderAction(); + if (headerAction == null || TextUtils.isEmpty( + headerAction.getTitle())) { + return; + } + + String temperature = headerAction.getTitle().toString(); + mView.setText(temperature); + final Icon icon = headerAction.getIcon(); + if (icon != null) { + final int iconSize = + getResources().getDimensionPixelSize( + R.dimen.smart_action_button_icon_size); + final Drawable iconDrawable = icon.loadDrawable(getContext()); + iconDrawable.setBounds(0, 0, iconSize, iconSize); + mView.setCompoundDrawables(iconDrawable, null, null, null); + mView.setCompoundDrawablePadding( + getResources().getDimensionPixelSize( + R.dimen.smart_action_button_icon_padding)); + + } + } + }); + mSmartSpaceController.addListener(mSmartspaceTargetListener); + } + + @Override + protected void onViewDetached() { + mSmartSpaceController.removeListener(mSmartspaceTargetListener); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockDateComplicationComponent.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockDateComplicationComponent.java new file mode 100644 index 0000000000000..eaffb1ca5b3ef --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockDateComplicationComponent.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2022 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.dreams.complication.dagger; + + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.android.internal.util.Preconditions; +import com.android.systemui.R; +import com.android.systemui.dreams.complication.ComplicationLayoutParams; +import com.android.systemui.dreams.complication.DreamClockDateComplication.DreamClockDateViewHolder; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; + +import javax.inject.Named; +import javax.inject.Scope; + +import dagger.Module; +import dagger.Provides; +import dagger.Subcomponent; + +/** + * {@link DreamClockDateComplicationComponent} is responsible for generating dependencies + * surrounding the + * Clock Date {@link com.android.systemui.dreams.complication.Complication}, such as the layout + * details. + */ +@Subcomponent(modules = { + DreamClockDateComplicationComponent.DreamClockDateComplicationModule.class, +}) +@DreamClockDateComplicationComponent.DreamClockDateComplicationScope +public interface DreamClockDateComplicationComponent { + /** + * Creates {@link DreamClockDateViewHolder}. + */ + DreamClockDateViewHolder getViewHolder(); + + @Documented + @Retention(RUNTIME) + @Scope + @interface DreamClockDateComplicationScope { + } + + /** + * Generates {@link DreamClockDateComplicationComponent}. + */ + @Subcomponent.Factory + interface Factory { + DreamClockDateComplicationComponent create(); + } + + /** + * Scoped values for {@link DreamClockDateComplicationComponent}. + */ + @Module + interface DreamClockDateComplicationModule { + String DREAM_CLOCK_DATE_COMPLICATION_VIEW = "clock_date_complication_view"; + String DREAM_CLOCK_DATE_COMPLICATION_LAYOUT_PARAMS = + "clock_date_complication_layout_params"; + // Order weight of insert into parent container + int INSERT_ORDER_WEIGHT = 2; + + /** + * Provides the complication view. + */ + @Provides + @DreamClockDateComplicationScope + @Named(DREAM_CLOCK_DATE_COMPLICATION_VIEW) + static View provideComplicationView(LayoutInflater layoutInflater) { + return Preconditions.checkNotNull( + layoutInflater.inflate(R.layout.dream_overlay_complication_clock_date, + null, false), + "R.layout.dream_overlay_complication_clock_date did not properly inflated"); + } + + /** + * Provides the layout parameters for the complication view. + */ + @Provides + @DreamClockDateComplicationScope + @Named(DREAM_CLOCK_DATE_COMPLICATION_LAYOUT_PARAMS) + static ComplicationLayoutParams provideLayoutParams() { + return new ComplicationLayoutParams(0, + ViewGroup.LayoutParams.WRAP_CONTENT, + ComplicationLayoutParams.POSITION_BOTTOM + | ComplicationLayoutParams.POSITION_START, + ComplicationLayoutParams.DIRECTION_END, + INSERT_ORDER_WEIGHT, + true); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockTimeComplicationComponent.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockTimeComplicationComponent.java new file mode 100644 index 0000000000000..053c5b345760e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockTimeComplicationComponent.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2022 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.dreams.complication.dagger; + + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.android.internal.util.Preconditions; +import com.android.systemui.R; +import com.android.systemui.dreams.complication.ComplicationLayoutParams; +import com.android.systemui.dreams.complication.DreamClockTimeComplication.DreamClockTimeViewHolder; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; + +import javax.inject.Named; +import javax.inject.Scope; + +import dagger.Module; +import dagger.Provides; +import dagger.Subcomponent; + +/** + * {@link DreamClockTimeComplicationComponent} is responsible for generating dependencies + * surrounding the + * Clock Time {@link com.android.systemui.dreams.complication.Complication}, such as the layout + * details. + */ +@Subcomponent(modules = { + DreamClockTimeComplicationComponent.DreamClockTimeComplicationModule.class, +}) +@DreamClockTimeComplicationComponent.DreamClockTimeComplicationScope +public interface DreamClockTimeComplicationComponent { + /** + * Creates {@link DreamClockTimeViewHolder}. + */ + DreamClockTimeViewHolder getViewHolder(); + + @Documented + @Retention(RUNTIME) + @Scope + @interface DreamClockTimeComplicationScope { + } + + /** + * Generates {@link DreamClockTimeComplicationComponent}. + */ + @Subcomponent.Factory + interface Factory { + DreamClockTimeComplicationComponent create(); + } + + /** + * Scoped values for {@link DreamClockTimeComplicationComponent}. + */ + @Module + interface DreamClockTimeComplicationModule { + String DREAM_CLOCK_TIME_COMPLICATION_VIEW = "clock_time_complication_view"; + String DREAM_CLOCK_TIME_COMPLICATION_LAYOUT_PARAMS = + "clock_time_complication_layout_params"; + // Order weight of insert into parent container + int INSERT_ORDER_WEIGHT = 0; + + /** + * Provides the complication view. + */ + @Provides + @DreamClockTimeComplicationScope + @Named(DREAM_CLOCK_TIME_COMPLICATION_VIEW) + static View provideComplicationView(LayoutInflater layoutInflater) { + return Preconditions.checkNotNull( + layoutInflater.inflate(R.layout.dream_overlay_complication_clock_time, + null, false), + "R.layout.dream_overlay_complication_clock_time did not properly inflated"); + } + + /** + * Provides the layout parameters for the complication view. + */ + @Provides + @DreamClockTimeComplicationScope + @Named(DREAM_CLOCK_TIME_COMPLICATION_LAYOUT_PARAMS) + static ComplicationLayoutParams provideLayoutParams() { + return new ComplicationLayoutParams(0, + ViewGroup.LayoutParams.WRAP_CONTENT, + ComplicationLayoutParams.POSITION_BOTTOM + | ComplicationLayoutParams.POSITION_START, + ComplicationLayoutParams.DIRECTION_UP, + INSERT_ORDER_WEIGHT, + true); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamWeatherComplicationComponent.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamWeatherComplicationComponent.java new file mode 100644 index 0000000000000..a282594ff282e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamWeatherComplicationComponent.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2022 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.dreams.complication.dagger; + + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import android.view.LayoutInflater; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.android.internal.util.Preconditions; +import com.android.systemui.R; +import com.android.systemui.dreams.complication.ComplicationLayoutParams; +import com.android.systemui.dreams.complication.DreamWeatherComplication.DreamWeatherViewHolder; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; + +import javax.inject.Named; +import javax.inject.Scope; + +import dagger.Module; +import dagger.Provides; +import dagger.Subcomponent; + +/** + * {@link DreamWeatherComplicationComponent} is responsible for generating dependencies surrounding + * the + * Clock Date {@link com.android.systemui.dreams.complication.Complication}, such as the layout + * details. + */ +@Subcomponent(modules = { + DreamWeatherComplicationComponent.DreamWeatherComplicationModule.class, +}) +@DreamWeatherComplicationComponent.DreamWeatherComplicationScope +public interface DreamWeatherComplicationComponent { + /** + * Creates {@link DreamWeatherViewHolder}. + */ + DreamWeatherViewHolder getViewHolder(); + + @Documented + @Retention(RUNTIME) + @Scope + @interface DreamWeatherComplicationScope { + } + + /** + * Generates {@link DreamWeatherComplicationComponent}. + */ + @Subcomponent.Factory + interface Factory { + DreamWeatherComplicationComponent create(); + } + + /** + * Scoped values for {@link DreamWeatherComplicationComponent}. + */ + @Module + interface DreamWeatherComplicationModule { + String DREAM_WEATHER_COMPLICATION_VIEW = "weather_complication_view"; + String DREAM_WEATHER_COMPLICATION_LAYOUT_PARAMS = + "weather_complication_layout_params"; + // Order weight of insert into parent container + int INSERT_ORDER_WEIGHT = 1; + + /** + * Provides the complication view. + */ + @Provides + @DreamWeatherComplicationScope + @Named(DREAM_WEATHER_COMPLICATION_VIEW) + static TextView provideComplicationView(LayoutInflater layoutInflater) { + return Preconditions.checkNotNull((TextView) + layoutInflater.inflate(R.layout.dream_overlay_complication_weather, + null, false), + "R.layout.dream_overlay_complication_weather did not properly inflated"); + } + + /** + * Provides the layout parameters for the complication view. + */ + @Provides + @DreamWeatherComplicationScope + @Named(DREAM_WEATHER_COMPLICATION_LAYOUT_PARAMS) + static ComplicationLayoutParams provideLayoutParams() { + return new ComplicationLayoutParams(0, + ViewGroup.LayoutParams.WRAP_CONTENT, + ComplicationLayoutParams.POSITION_BOTTOM + | ComplicationLayoutParams.POSITION_START, + ComplicationLayoutParams.DIRECTION_END, + INSERT_ORDER_WEIGHT, + true); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java new file mode 100644 index 0000000000000..8e4fb3783f4a6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022 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.dreams.complication.dagger; + +import com.android.systemui.dagger.SystemUIBinder; + +import dagger.Module; + +/** + * Module for all components with corresponding dream layer complications registered in + * {@link SystemUIBinder}. + */ +@Module(subcomponents = { + DreamClockTimeComplicationComponent.class, + DreamClockDateComplicationComponent.class, + DreamWeatherComplicationComponent.class, +}) +public interface RegisteredComplicationsModule { +} diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java index 3d2f924563f38..d8af9e5f1f4af 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java @@ -16,6 +16,7 @@ package com.android.systemui.dreams.dagger; +import com.android.systemui.dreams.complication.dagger.RegisteredComplicationsModule; import com.android.systemui.dreams.touch.dagger.DreamTouchModule; import dagger.Module; @@ -25,6 +26,7 @@ import dagger.Module; */ @Module(includes = { DreamTouchModule.class, + RegisteredComplicationsModule.class, }, subcomponents = { DreamOverlayComponent.class, diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamClockDateComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamClockDateComplicationTest.java new file mode 100644 index 0000000000000..b02c506be8be7 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamClockDateComplicationTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2022 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.dreams.complication; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.testing.AndroidTestingRunner; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.dreams.DreamOverlayStateController; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +public class DreamClockDateComplicationTest extends SysuiTestCase { + @SuppressWarnings("HidingField") + @Mock + private Context mContext; + + @Mock + private DreamOverlayStateController mDreamOverlayStateController; + + @Mock + private DreamClockDateComplication mComplication; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + } + + /** + * Ensures {@link DreamClockDateComplication} is registered. + */ + @Test + public void testComplicationAdded() { + final DreamClockDateComplication.Registrant registrant = + new DreamClockDateComplication.Registrant( + mContext, + mDreamOverlayStateController, + mComplication); + registrant.start(); + verify(mDreamOverlayStateController).addComplication(eq(mComplication)); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamClockTimeComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamClockTimeComplicationTest.java new file mode 100644 index 0000000000000..088b4d5136fff --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamClockTimeComplicationTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2022 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.dreams.complication; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.testing.AndroidTestingRunner; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.dreams.DreamOverlayStateController; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +public class DreamClockTimeComplicationTest extends SysuiTestCase { + @SuppressWarnings("HidingField") + @Mock + private Context mContext; + + @Mock + private DreamOverlayStateController mDreamOverlayStateController; + + @Mock + private DreamClockTimeComplication mComplication; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + } + + /** + * Ensures {@link DreamClockTimeComplication} is registered. + */ + @Test + public void testComplicationAdded() { + final DreamClockTimeComplication.Registrant registrant = + new DreamClockTimeComplication.Registrant( + mContext, + mDreamOverlayStateController, + mComplication); + registrant.start(); + verify(mDreamOverlayStateController).addComplication(eq(mComplication)); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamWeatherComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamWeatherComplicationTest.java new file mode 100644 index 0000000000000..151742af7e1a8 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamWeatherComplicationTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2022 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.dreams.complication; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.testing.AndroidTestingRunner; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.dreams.DreamOverlayStateController; +import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +public class DreamWeatherComplicationTest extends SysuiTestCase { + @SuppressWarnings("HidingField") + @Mock + private Context mContext; + + @Mock + private LockscreenSmartspaceController mSmartspaceController; + + @Mock + private DreamOverlayStateController mDreamOverlayStateController; + + @Mock + private DreamWeatherComplication mComplication; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + } + + /** + * Ensures {@link DreamWeatherComplication} is only registered when it is available. + */ + @Test + public void testComplicationAvailability() { + when(mSmartspaceController.isEnabled()).thenReturn(false); + final DreamWeatherComplication.Registrant registrant = + new DreamWeatherComplication.Registrant( + mContext, + mSmartspaceController, + mDreamOverlayStateController, + mComplication); + registrant.start(); + verify(mDreamOverlayStateController, never()).addComplication(any()); + + when(mSmartspaceController.isEnabled()).thenReturn(true); + registrant.start(); + verify(mDreamOverlayStateController).addComplication(eq(mComplication)); + } +}