Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit acfca7c1 authored by Bryce Lee's avatar Bryce Lee
Browse files

SmartSpace Complication Introduction.

This changelist introduces the SmartSpace Complication, which provides the same at a glance view found on the lockscreen.

Bug: 213907299
Test: atest SmartSpaceComplicationTest
Change-Id: Id235112bd76f313e8678520035d90dc8672fd967
parent ee1f9361
Loading
Loading
Loading
Loading
+26 −24
Original line number Diff line number Diff line
@@ -20,30 +20,6 @@
    android:id="@+id/dream_overlay_complications_layer"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.constraintlayout.widget.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/complication_top_guide"
        app:layout_constraintGuide_percent="@dimen/dream_overlay_complication_guide_top_percent"
        android:orientation="horizontal"/>
    <androidx.constraintlayout.widget.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/complication_end_guide"
        app:layout_constraintGuide_percent="@dimen/dream_overlay_complication_guide_end_percent"
        android:orientation="vertical"/>
    <androidx.constraintlayout.widget.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/complication_bottom_guide"
        app:layout_constraintGuide_percent="@dimen/dream_overlay_complication_guide_bottom_percent"
        android:orientation="horizontal"/>
    <androidx.constraintlayout.widget.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/complication_start_guide"
        app:layout_constraintGuide_percent="@dimen/dream_overlay_complication_guide_start_percent"
        android:orientation="vertical"/>
    <TextClock
        android:id="@+id/time_view"
        android:layout_width="wrap_content"
@@ -55,6 +31,7 @@
        android:shadowRadius="2.0"
        android:singleLine="true"
        android:textSize="72sp"
        android:textColor="@android:color/white"
        app:layout_constraintBottom_toTopOf="@+id/date_view"
        app:layout_constraintStart_toStartOf="parent" />
    <TextClock
@@ -67,7 +44,32 @@
        android:format24Hour="EEE, MMM d"
        android:singleLine="true"
        android:textSize="18sp"
        android:textColor="@android:color/white"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="@+id/time_view"
        app:layout_constraintStart_toStartOf="@+id/time_view" />
    <androidx.constraintlayout.widget.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/complication_top_guide"
        app:layout_constraintGuide_percent="@dimen/dream_overlay_complication_guide_top_percent"
        android:orientation="horizontal"/>
    <androidx.constraintlayout.widget.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/complication_end_guide"
        app:layout_constraintGuide_percent="@dimen/dream_overlay_complication_guide_end_percent"
        android:orientation="vertical"/>
    <androidx.constraintlayout.widget.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/complication_bottom_guide"
        app:layout_constraintGuide_percent="@dimen/dream_overlay_complication_guide_bottom_percent"
        android:orientation="horizontal"/>
    <androidx.constraintlayout.widget.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/complication_start_guide"
        app:layout_constraintGuide_percent="@dimen/dream_overlay_complication_guide_start_percent"
        android:orientation="vertical"/>
</androidx.constraintlayout.widget.ConstraintLayout>
 No newline at end of file
+8 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import com.android.systemui.accessibility.WindowMagnification;
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.globalactions.GlobalActionsComponent;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.dagger.KeyguardModule;
@@ -218,4 +219,11 @@ public abstract class SystemUIBinder {
    @ClassKey(DreamOverlayRegistrant.class)
    public abstract CoreStartable bindDreamOverlayRegistrant(
            DreamOverlayRegistrant dreamOverlayRegistrant);

    /** Inject into SmartSpaceComplication.Registrant */
    @Binds
    @IntoMap
    @ClassKey(SmartSpaceComplication.Registrant.class)
    public abstract CoreStartable bindSmartSpaceComplicationRegistrant(
            SmartSpaceComplication.Registrant registrant);
}
+113 −0
Original line number Diff line number Diff line
/*
 * 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;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import com.android.systemui.CoreStartable;
import com.android.systemui.dreams.complication.Complication;
import com.android.systemui.dreams.complication.ComplicationLayoutParams;
import com.android.systemui.dreams.complication.ComplicationViewModel;
import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;

import javax.inject.Inject;

/**
 * {@link SmartSpaceComplication} embodies the SmartSpace view found on the lockscreen as a
 * {@link Complication}
 */
public class SmartSpaceComplication implements Complication {
    /**
     * {@link CoreStartable} responsbile for registering {@link SmartSpaceComplication} with
     * SystemUI.
     */
    public static class Registrant extends CoreStartable {
        private final LockscreenSmartspaceController mSmartSpaceController;
        private final DreamOverlayStateController mDreamOverlayStateController;
        private final SmartSpaceComplication mComplication;

        /**
         * Default constructor for {@link SmartSpaceComplication}.
         */
        @Inject
        public Registrant(Context context,
                DreamOverlayStateController dreamOverlayStateController,
                SmartSpaceComplication smartSpaceComplication,
                LockscreenSmartspaceController smartSpaceController) {
            super(context);
            mDreamOverlayStateController = dreamOverlayStateController;
            mComplication = smartSpaceComplication;
            mSmartSpaceController = smartSpaceController;
        }

        @Override
        public void start() {
            if (mSmartSpaceController.isEnabled()) {
                mDreamOverlayStateController.addComplication(mComplication);
            }
        }
    }

    private static class SmartSpaceComplicationViewHolder implements ViewHolder {
        private final LockscreenSmartspaceController mSmartSpaceController;
        private final Context mContext;

        protected SmartSpaceComplicationViewHolder(
                Context context,
                LockscreenSmartspaceController smartSpaceController) {
            mSmartSpaceController = smartSpaceController;
            mContext = context;
        }

        @Override
        public View getView() {
            final FrameLayout smartSpaceContainer = new FrameLayout(mContext);
            smartSpaceContainer.addView(
                    mSmartSpaceController.buildAndConnectView(smartSpaceContainer),
                    new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                            ViewGroup.LayoutParams.WRAP_CONTENT));

            return smartSpaceContainer;
        }

        @Override
        public ComplicationLayoutParams getLayoutParams() {
            return new ComplicationLayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT,
                    ComplicationLayoutParams.POSITION_TOP | ComplicationLayoutParams.POSITION_START,
                    ComplicationLayoutParams.DIRECTION_DOWN,
                    0, true);
        }
    }

    private final LockscreenSmartspaceController mSmartSpaceController;
    private final Context mContext;

    @Inject
    public SmartSpaceComplication(Context context,
            LockscreenSmartspaceController smartSpaceController) {
        mContext = context;
        mSmartSpaceController = smartSpaceController;
    }

    @Override
    public ViewHolder createView(ComplicationViewModel model) {
        return new SmartSpaceComplicationViewHolder(mContext, mSmartSpaceController);
    }
}
+77 −0
Original line number Diff line number Diff line
/*
 * 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;

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.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 SmartSpaceComplicationTest extends SysuiTestCase {
    @Mock
    private Context mContext;

    @Mock
    private LockscreenSmartspaceController mSmartspaceController;

    @Mock
    private DreamOverlayStateController mDreamOverlayStateController;

    @Mock
    private SmartSpaceComplication mComplication;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    /**
     * Ensures {@link SmartSpaceComplication} is only registered when it is available.
     */
    @Test
    public void testAvailability() {
        when(mSmartspaceController.isEnabled()).thenReturn(false);

        final SmartSpaceComplication.Registrant registrant = new SmartSpaceComplication.Registrant(
                mContext,
                mDreamOverlayStateController,
                mComplication,
                mSmartspaceController);
        registrant.start();
        verify(mDreamOverlayStateController, never()).addComplication(any());

        when(mSmartspaceController.isEnabled()).thenReturn(true);
        registrant.start();
        verify(mDreamOverlayStateController).addComplication(eq(mComplication));
    }
}