Merge "Create connected display presentation" into udc-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
33b4225ffa
@@ -62,6 +62,7 @@ class DefaultClockController(
|
||||
private val burmeseLineSpacing =
|
||||
resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale_burmese)
|
||||
private val defaultLineSpacing = resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale)
|
||||
protected var onSecondaryDisplay: Boolean = false
|
||||
|
||||
override val events: DefaultClockEvents
|
||||
override val config = ClockConfig()
|
||||
@@ -142,6 +143,11 @@ class DefaultClockController(
|
||||
view.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSizePx)
|
||||
recomputePadding(targetRegion)
|
||||
}
|
||||
|
||||
override fun onSecondaryDisplayChanged(onSecondaryDisplay: Boolean) {
|
||||
this@DefaultClockController.onSecondaryDisplay = onSecondaryDisplay
|
||||
recomputePadding(null)
|
||||
}
|
||||
}
|
||||
|
||||
open fun recomputePadding(targetRegion: Rect?) {}
|
||||
@@ -182,13 +188,19 @@ class DefaultClockController(
|
||||
override fun recomputePadding(targetRegion: Rect?) {
|
||||
// We center the view within the targetRegion instead of within the parent
|
||||
// view by computing the difference and adding that to the padding.
|
||||
val parent = view.parent
|
||||
val yDiff =
|
||||
if (targetRegion != null && parent is View && parent.isLaidOut())
|
||||
targetRegion.centerY() - parent.height / 2f
|
||||
else 0f
|
||||
val lp = view.getLayoutParams() as FrameLayout.LayoutParams
|
||||
lp.topMargin = (-0.5f * view.bottom + yDiff).toInt()
|
||||
lp.topMargin =
|
||||
if (onSecondaryDisplay) {
|
||||
// On the secondary display we don't want any additional top/bottom margin.
|
||||
0
|
||||
} else {
|
||||
val parent = view.parent
|
||||
val yDiff =
|
||||
if (targetRegion != null && parent is View && parent.isLaidOut())
|
||||
targetRegion.centerY() - parent.height / 2f
|
||||
else 0f
|
||||
(-0.5f * view.bottom + yDiff).toInt()
|
||||
}
|
||||
view.setLayoutParams(lp)
|
||||
}
|
||||
|
||||
|
||||
@@ -177,6 +177,9 @@ interface ClockFaceEvents {
|
||||
* targetRegion is relative to the parent view.
|
||||
*/
|
||||
fun onTargetRegionChanged(targetRegion: Rect?)
|
||||
|
||||
/** Called to notify the clock about its display. */
|
||||
fun onSecondaryDisplayChanged(onSecondaryDisplay: Boolean)
|
||||
}
|
||||
|
||||
/** Tick rates for clocks */
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
**
|
||||
** Copyright 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/presentation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<com.android.keyguard.KeyguardStatusView
|
||||
android:id="@+id/clock"
|
||||
android:layout_width="410dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include
|
||||
android:id="@+id/keyguard_clock_container"
|
||||
layout="@layout/keyguard_clock_switch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</com.android.keyguard.KeyguardStatusView>
|
||||
|
||||
</FrameLayout>
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.keyguard
|
||||
|
||||
import android.app.Presentation
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.Display
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import com.android.keyguard.dagger.KeyguardStatusViewComponent
|
||||
import com.android.systemui.R
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
/** [Presentation] shown in connected displays while on keyguard. */
|
||||
class ConnectedDisplayKeyguardPresentation
|
||||
@AssistedInject
|
||||
constructor(
|
||||
@Assisted display: Display,
|
||||
context: Context,
|
||||
private val keyguardStatusViewComponentFactory: KeyguardStatusViewComponent.Factory,
|
||||
) :
|
||||
Presentation(
|
||||
context,
|
||||
display,
|
||||
R.style.Theme_SystemUI_KeyguardPresentation,
|
||||
WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
|
||||
) {
|
||||
|
||||
private lateinit var keyguardStatusViewController: KeyguardStatusViewController
|
||||
private lateinit var clock: KeyguardStatusView
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContentView(
|
||||
LayoutInflater.from(context)
|
||||
.inflate(R.layout.keyguard_clock_presentation, /* root= */ null)
|
||||
)
|
||||
val window = window ?: error("no window available.")
|
||||
|
||||
// Logic to make the lock screen fullscreen
|
||||
window.decorView.systemUiVisibility =
|
||||
(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
|
||||
window.attributes.fitInsetsTypes = 0
|
||||
window.isNavigationBarContrastEnforced = false
|
||||
window.navigationBarColor = Color.TRANSPARENT
|
||||
|
||||
clock = findViewById(R.id.clock)
|
||||
keyguardStatusViewController =
|
||||
keyguardStatusViewComponentFactory.build(clock).keyguardStatusViewController.apply {
|
||||
setDisplayedOnSecondaryDisplay()
|
||||
init()
|
||||
}
|
||||
}
|
||||
|
||||
/** [ConnectedDisplayKeyguardPresentation] factory. */
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
/** Creates a new [Presentation] for the given [display]. */
|
||||
fun create(
|
||||
display: Display,
|
||||
): ConnectedDisplayKeyguardPresentation
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,5 @@
|
||||
package com.android.keyguard;
|
||||
|
||||
import static android.view.View.ALPHA;
|
||||
import static android.view.View.SCALE_X;
|
||||
import static android.view.View.SCALE_Y;
|
||||
import static android.view.View.TRANSLATION_Y;
|
||||
|
||||
import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_X_CLOCK_DESIGN;
|
||||
import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_Y_CLOCK_DESIGN;
|
||||
import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_Y_CLOCK_SIZE;
|
||||
@@ -145,6 +140,13 @@ public class KeyguardClockSwitch extends RelativeLayout {
|
||||
updateStatusArea(/* animate= */false);
|
||||
}
|
||||
|
||||
/** Sets whether the large clock is being shown on a connected display. */
|
||||
public void setLargeClockOnSecondaryDisplay(boolean onSecondaryDisplay) {
|
||||
if (mClock != null) {
|
||||
mClock.getLargeClock().getEvents().onSecondaryDisplayChanged(onSecondaryDisplay);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable split shade specific positioning
|
||||
*/
|
||||
|
||||
@@ -104,6 +104,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
|
||||
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
||||
|
||||
private boolean mShownOnSecondaryDisplay = false;
|
||||
private boolean mOnlyClock = false;
|
||||
private boolean mIsActiveDreamLockscreenHosted = false;
|
||||
private FeatureFlags mFeatureFlags;
|
||||
@@ -185,8 +186,18 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
}
|
||||
|
||||
/**
|
||||
* Mostly used for alternate displays, limit the information shown
|
||||
* When set, limits the information shown in an external display.
|
||||
*/
|
||||
public void setShownOnSecondaryDisplay(boolean shownOnSecondaryDisplay) {
|
||||
mShownOnSecondaryDisplay = shownOnSecondaryDisplay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mostly used for alternate displays, limit the information shown
|
||||
*
|
||||
* @deprecated use {@link KeyguardClockSwitchController#setShownOnSecondaryDisplay}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setOnlyClock(boolean onlyClock) {
|
||||
mOnlyClock = onlyClock;
|
||||
}
|
||||
@@ -221,6 +232,15 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
}
|
||||
}
|
||||
|
||||
private void hideSliceViewAndNotificationIconContainer() {
|
||||
View ksv = mView.findViewById(R.id.keyguard_slice_view);
|
||||
ksv.setVisibility(View.GONE);
|
||||
|
||||
View nic = mView.findViewById(
|
||||
R.id.left_aligned_notification_icon_container);
|
||||
nic.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewAttached() {
|
||||
mClockRegistry.registerClockChangeListener(mClockChangedListener);
|
||||
@@ -233,13 +253,15 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
mKeyguardDateWeatherViewInvisibility =
|
||||
mView.getResources().getInteger(R.integer.keyguard_date_weather_view_invisibility);
|
||||
|
||||
if (mOnlyClock) {
|
||||
View ksv = mView.findViewById(R.id.keyguard_slice_view);
|
||||
ksv.setVisibility(View.GONE);
|
||||
if (mShownOnSecondaryDisplay) {
|
||||
mView.setLargeClockOnSecondaryDisplay(true);
|
||||
displayClock(LARGE, /* animate= */ false);
|
||||
hideSliceViewAndNotificationIconContainer();
|
||||
return;
|
||||
}
|
||||
|
||||
View nic = mView.findViewById(
|
||||
R.id.left_aligned_notification_icon_container);
|
||||
nic.setVisibility(View.GONE);
|
||||
if (mOnlyClock) {
|
||||
hideSliceViewAndNotificationIconContainer();
|
||||
return;
|
||||
}
|
||||
updateAodIcons();
|
||||
|
||||
@@ -43,16 +43,19 @@ import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.dagger.qualifiers.UiBackground;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
import com.android.systemui.navigationbar.NavigationBarController;
|
||||
import com.android.systemui.navigationbar.NavigationBarView;
|
||||
import com.android.systemui.settings.DisplayTracker;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
|
||||
import dagger.Lazy;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import dagger.Lazy;
|
||||
|
||||
@SysUISingleton
|
||||
public class KeyguardDisplayManager {
|
||||
@@ -64,6 +67,9 @@ public class KeyguardDisplayManager {
|
||||
private final DisplayTracker mDisplayTracker;
|
||||
private final Lazy<NavigationBarController> mNavigationBarControllerLazy;
|
||||
private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
|
||||
private final ConnectedDisplayKeyguardPresentation.Factory
|
||||
mConnectedDisplayKeyguardPresentationFactory;
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
private final Context mContext;
|
||||
|
||||
private boolean mShowing;
|
||||
@@ -105,7 +111,10 @@ public class KeyguardDisplayManager {
|
||||
@Main Executor mainExecutor,
|
||||
@UiBackground Executor uiBgExecutor,
|
||||
DeviceStateHelper deviceStateHelper,
|
||||
KeyguardStateController keyguardStateController) {
|
||||
KeyguardStateController keyguardStateController,
|
||||
ConnectedDisplayKeyguardPresentation.Factory
|
||||
connectedDisplayKeyguardPresentationFactory,
|
||||
FeatureFlags featureFlags) {
|
||||
mContext = context;
|
||||
mNavigationBarControllerLazy = navigationBarControllerLazy;
|
||||
mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory;
|
||||
@@ -115,6 +124,8 @@ public class KeyguardDisplayManager {
|
||||
mDisplayTracker.addDisplayChangeCallback(mDisplayCallback, mainExecutor);
|
||||
mDeviceStateHelper = deviceStateHelper;
|
||||
mKeyguardStateController = keyguardStateController;
|
||||
mConnectedDisplayKeyguardPresentationFactory = connectedDisplayKeyguardPresentationFactory;
|
||||
mFeatureFlags = featureFlags;
|
||||
}
|
||||
|
||||
private boolean isKeyguardShowable(Display display) {
|
||||
@@ -185,8 +196,12 @@ public class KeyguardDisplayManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
KeyguardPresentation createPresentation(Display display) {
|
||||
return new KeyguardPresentation(mContext, display, mKeyguardStatusViewComponentFactory);
|
||||
Presentation createPresentation(Display display) {
|
||||
if (mFeatureFlags.isEnabled(Flags.ENABLE_CLOCK_KEYGUARD_PRESENTATION)) {
|
||||
return mConnectedDisplayKeyguardPresentationFactory.create(display);
|
||||
} else {
|
||||
return new KeyguardPresentation(mContext, display, mKeyguardStatusViewComponentFactory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -187,6 +187,11 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
|
||||
mConfigurationController.removeCallback(mConfigurationListener);
|
||||
}
|
||||
|
||||
/** Sets the StatusView as shown on an external display. */
|
||||
public void setDisplayedOnSecondaryDisplay() {
|
||||
mKeyguardClockSwitchController.setShownOnSecondaryDisplay(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called in notificationPanelViewController to avoid leak
|
||||
*/
|
||||
|
||||
@@ -769,6 +769,10 @@ object Flags {
|
||||
@JvmField
|
||||
val ONE_WAY_HAPTICS_API_MIGRATION = unreleasedFlag("oneway_haptics_api_migration")
|
||||
|
||||
/** TODO(b/296223317): Enables the new keyguard presentation containing a clock. */
|
||||
@JvmField
|
||||
val ENABLE_CLOCK_KEYGUARD_PRESENTATION = unreleasedFlag("enable_clock_keyguard_presentation")
|
||||
|
||||
/** Enable the Compose implementation of the PeopleSpaceActivity. */
|
||||
@JvmField
|
||||
val COMPOSE_PEOPLE_SPACE = unreleasedFlag("compose_people_space")
|
||||
|
||||
@@ -18,6 +18,8 @@ package com.android.keyguard;
|
||||
|
||||
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
|
||||
|
||||
import static com.android.systemui.flags.Flags.ENABLE_CLOCK_KEYGUARD_PRESENTATION;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
@@ -37,6 +39,7 @@ import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.keyguard.dagger.KeyguardStatusViewComponent;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.flags.FakeFeatureFlags;
|
||||
import com.android.systemui.navigationbar.NavigationBarController;
|
||||
import com.android.systemui.settings.FakeDisplayTracker;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
@@ -59,8 +62,13 @@ public class KeyguardDisplayManagerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
|
||||
@Mock
|
||||
private ConnectedDisplayKeyguardPresentation.Factory
|
||||
mConnectedDisplayKeyguardPresentationFactory;
|
||||
@Mock
|
||||
private KeyguardDisplayManager.KeyguardPresentation mKeyguardPresentation;
|
||||
@Mock
|
||||
private ConnectedDisplayKeyguardPresentation mConnectedDisplayKeyguardPresentation;
|
||||
@Mock
|
||||
private KeyguardDisplayManager.DeviceStateHelper mDeviceStateHelper;
|
||||
@Mock
|
||||
private KeyguardStateController mKeyguardStateController;
|
||||
@@ -69,7 +77,7 @@ public class KeyguardDisplayManagerTest extends SysuiTestCase {
|
||||
private Executor mBackgroundExecutor = Runnable::run;
|
||||
private KeyguardDisplayManager mManager;
|
||||
private FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext);
|
||||
|
||||
private FakeFeatureFlags mFakeFeatureFlags = new FakeFeatureFlags();
|
||||
// The default and secondary displays are both in the default group
|
||||
private Display mDefaultDisplay;
|
||||
private Display mSecondaryDisplay;
|
||||
@@ -80,10 +88,14 @@ public class KeyguardDisplayManagerTest extends SysuiTestCase {
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mFakeFeatureFlags.set(ENABLE_CLOCK_KEYGUARD_PRESENTATION, false);
|
||||
mManager = spy(new KeyguardDisplayManager(mContext, () -> mNavigationBarController,
|
||||
mKeyguardStatusViewComponentFactory, mDisplayTracker, mMainExecutor,
|
||||
mBackgroundExecutor, mDeviceStateHelper, mKeyguardStateController));
|
||||
mBackgroundExecutor, mDeviceStateHelper, mKeyguardStateController,
|
||||
mConnectedDisplayKeyguardPresentationFactory, mFakeFeatureFlags));
|
||||
doReturn(mKeyguardPresentation).when(mManager).createPresentation(any());
|
||||
doReturn(mConnectedDisplayKeyguardPresentation).when(
|
||||
mConnectedDisplayKeyguardPresentationFactory).create(any());
|
||||
|
||||
mDefaultDisplay = new Display(DisplayManagerGlobal.getInstance(), Display.DEFAULT_DISPLAY,
|
||||
new DisplayInfo(), DEFAULT_DISPLAY_ADJUSTMENTS);
|
||||
@@ -138,4 +150,15 @@ public class KeyguardDisplayManagerTest extends SysuiTestCase {
|
||||
when(mKeyguardStateController.isOccluded()).thenReturn(true);
|
||||
verify(mManager, never()).createPresentation(eq(mSecondaryDisplay));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShow_withClockPresentationFlagEnabled_presentationCreated() {
|
||||
when(mManager.createPresentation(any())).thenCallRealMethod();
|
||||
mFakeFeatureFlags.set(ENABLE_CLOCK_KEYGUARD_PRESENTATION, true);
|
||||
mDisplayTracker.setAllDisplays(new Display[]{mDefaultDisplay, mSecondaryDisplay});
|
||||
|
||||
mManager.show();
|
||||
|
||||
verify(mConnectedDisplayKeyguardPresentationFactory).create(eq(mSecondaryDisplay));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user