Merge "Fix keyguard on secondary displays" into main
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml b/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
index f4d34f4..8a0dd12 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
@@ -27,7 +27,7 @@
<com.android.keyguard.KeyguardStatusView
android:id="@+id/clock"
android:orientation="vertical"
- android:layout_width="410dp"
+ android:layout_width="@dimen/keyguard_presentation_width"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 4e540de..186bd7c 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -173,4 +173,6 @@
<dimen name="sfps_progress_bar_thickness">6dp</dimen>
<!-- Padding from the edge of the screen for the progress bar -->
<dimen name="sfps_progress_bar_padding_from_edge">7dp</dimen>
+
+ <dimen name="keyguard_presentation_width">410dp</dimen>
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/ConnectedDisplayKeyguardPresentation.kt b/packages/SystemUI/src/com/android/keyguard/ConnectedDisplayKeyguardPresentation.kt
index dec7d79..630610d 100644
--- a/packages/SystemUI/src/com/android/keyguard/ConnectedDisplayKeyguardPresentation.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ConnectedDisplayKeyguardPresentation.kt
@@ -19,13 +19,22 @@
import android.app.Presentation
import android.content.Context
import android.graphics.Color
+import android.graphics.Rect
import android.os.Bundle
import android.view.Display
+import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.WindowManager
+import android.widget.FrameLayout
+import android.widget.FrameLayout.LayoutParams
import com.android.keyguard.dagger.KeyguardStatusViewComponent
+import com.android.systemui.Flags.migrateClocksToBlueprint
+import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.plugins.clocks.ClockFaceController
import com.android.systemui.res.R
+import com.android.systemui.shared.clocks.ClockRegistry
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@@ -37,6 +46,8 @@
@Assisted display: Display,
context: Context,
private val keyguardStatusViewComponentFactory: KeyguardStatusViewComponent.Factory,
+ private val clockRegistry: ClockRegistry,
+ private val clockEventController: ClockEventController,
) :
Presentation(
context,
@@ -45,18 +56,126 @@
WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
) {
+ private lateinit var rootView: FrameLayout
+ private var clock: View? = null
private lateinit var keyguardStatusViewController: KeyguardStatusViewController
- private lateinit var clock: KeyguardStatusView
+ private lateinit var faceController: ClockFaceController
+ private lateinit var clockFrame: FrameLayout
+
+ private val clockChangedListener =
+ object : ClockRegistry.ClockChangeListener {
+ override fun onCurrentClockChanged() {
+ setClock(clockRegistry.createCurrentClock())
+ }
+
+ override fun onAvailableClocksChanged() {}
+ }
+
+ private val layoutChangeListener =
+ object : View.OnLayoutChangeListener {
+ override fun onLayoutChange(
+ view: View,
+ left: Int,
+ top: Int,
+ right: Int,
+ bottom: Int,
+ oldLeft: Int,
+ oldTop: Int,
+ oldRight: Int,
+ oldBottom: Int
+ ) {
+ clock?.let {
+ faceController.events.onTargetRegionChanged(
+ Rect(it.left, it.top, it.width, it.height)
+ )
+ }
+ }
+ }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ if (migrateClocksToBlueprint()) {
+ onCreateV2()
+ } else {
+ onCreate()
+ }
+ }
+
+ fun onCreateV2() {
+ rootView = FrameLayout(getContext(), null)
+ rootView.setClipChildren(false)
+ setContentView(rootView)
+
+ setFullscreen()
+
+ setClock(clockRegistry.createCurrentClock())
+ }
+
+ fun onCreate() {
setContentView(
LayoutInflater.from(context)
.inflate(R.layout.keyguard_clock_presentation, /* root= */ null)
)
- val window = window ?: error("no window available.")
+ setFullscreen()
+
+ clock = requireViewById(R.id.clock)
+ keyguardStatusViewController =
+ keyguardStatusViewComponentFactory
+ .build(clock as KeyguardStatusView, display)
+ .keyguardStatusViewController
+ .apply {
+ setDisplayedOnSecondaryDisplay()
+ init()
+ }
+ }
+
+ override fun onAttachedToWindow() {
+ if (migrateClocksToBlueprint()) {
+ clockRegistry.registerClockChangeListener(clockChangedListener)
+ clockEventController.registerListeners(clock!!)
+
+ faceController.animations.enter()
+ }
+ }
+
+ override fun onDetachedFromWindow() {
+ if (migrateClocksToBlueprint()) {
+ clockEventController.unregisterListeners()
+ clockRegistry.unregisterClockChangeListener(clockChangedListener)
+ }
+
+ super.onDetachedFromWindow()
+ }
+
+ override fun onDisplayChanged() {
+ val window = window ?: error("no window available.")
+ window.getDecorView().requestLayout()
+ }
+
+ private fun setClock(clockController: ClockController) {
+ clock?.removeOnLayoutChangeListener(layoutChangeListener)
+ rootView.removeAllViews()
+
+ faceController = clockController.largeClock
+ clock = faceController.view.also { it.addOnLayoutChangeListener(layoutChangeListener) }
+ rootView.addView(
+ clock,
+ FrameLayout.LayoutParams(
+ context.resources.getDimensionPixelSize(R.dimen.keyguard_presentation_width),
+ WRAP_CONTENT,
+ Gravity.CENTER,
+ )
+ )
+
+ clockEventController.clock = clockController
+ clockEventController.setLargeClockOnSecondaryDisplay(true)
+ faceController.events.onSecondaryDisplayChanged(true)
+ }
+
+ private fun setFullscreen() {
+ val window = window ?: error("no window available.")
// Logic to make the lock screen fullscreen
window.decorView.systemUiVisibility =
(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
@@ -65,16 +184,6 @@
window.attributes.fitInsetsTypes = 0
window.isNavigationBarContrastEnforced = false
window.navigationBarColor = Color.TRANSPARENT
-
- clock = requireViewById(R.id.clock)
- keyguardStatusViewController =
- keyguardStatusViewComponentFactory
- .build(clock, display)
- .keyguardStatusViewController
- .apply {
- setDisplayedOnSecondaryDisplay()
- init()
- }
}
/** [ConnectedDisplayKeyguardPresentation] factory. */
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index 8a6f101..0bb5c17 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -17,13 +17,10 @@
import android.app.Presentation;
import android.content.Context;
-import android.graphics.Color;
-import android.graphics.Rect;
import android.hardware.devicestate.DeviceStateManager;
import android.hardware.display.DisplayManager;
import android.media.MediaRouter;
import android.media.MediaRouter.RouteInfo;
-import android.os.Bundle;
import android.os.Trace;
import android.text.TextUtils;
import android.util.Log;
@@ -31,20 +28,14 @@
import android.view.Display;
import android.view.DisplayAddress;
import android.view.DisplayInfo;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import androidx.annotation.Nullable;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.keyguard.dagger.KeyguardStatusViewComponent;
-import com.android.systemui.res.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;
@@ -66,10 +57,8 @@
private final DisplayManager mDisplayService;
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;
@@ -106,18 +95,15 @@
@Inject
public KeyguardDisplayManager(Context context,
Lazy<NavigationBarController> navigationBarControllerLazy,
- KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory,
DisplayTracker displayTracker,
@Main Executor mainExecutor,
@UiBackground Executor uiBgExecutor,
DeviceStateHelper deviceStateHelper,
KeyguardStateController keyguardStateController,
ConnectedDisplayKeyguardPresentation.Factory
- connectedDisplayKeyguardPresentationFactory,
- FeatureFlags featureFlags) {
+ connectedDisplayKeyguardPresentationFactory) {
mContext = context;
mNavigationBarControllerLazy = navigationBarControllerLazy;
- mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory;
uiBgExecutor.execute(() -> mMediaRouter = mContext.getSystemService(MediaRouter.class));
mDisplayService = mContext.getSystemService(DisplayManager.class);
mDisplayTracker = displayTracker;
@@ -125,7 +111,6 @@
mDeviceStateHelper = deviceStateHelper;
mKeyguardStateController = keyguardStateController;
mConnectedDisplayKeyguardPresentationFactory = connectedDisplayKeyguardPresentationFactory;
- mFeatureFlags = featureFlags;
}
private boolean isKeyguardShowable(Display display) {
@@ -197,11 +182,7 @@
}
Presentation createPresentation(Display display) {
- if (mFeatureFlags.isEnabled(Flags.ENABLE_CLOCK_KEYGUARD_PRESENTATION)) {
- return mConnectedDisplayKeyguardPresentationFactory.create(display);
- } else {
- return new KeyguardPresentation(mContext, display, mKeyguardStatusViewComponentFactory);
- }
+ return mConnectedDisplayKeyguardPresentationFactory.create(display);
}
/**
@@ -347,92 +328,4 @@
&& mRearDisplayPhysicalAddress.equals(display.getAddress());
}
}
-
-
- @VisibleForTesting
- static final class KeyguardPresentation extends Presentation {
- private static final int VIDEO_SAFE_REGION = 80; // Percentage of display width & height
- private static final int MOVE_CLOCK_TIMEOUT = 10000; // 10s
- private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
- private KeyguardClockSwitchController mKeyguardClockSwitchController;
- private View mClock;
- private int mUsableWidth;
- private int mUsableHeight;
- private int mMarginTop;
- private int mMarginLeft;
- Runnable mMoveTextRunnable = new Runnable() {
- @Override
- public void run() {
- int x = mMarginLeft + (int) (Math.random() * (mUsableWidth - mClock.getWidth()));
- int y = mMarginTop + (int) (Math.random() * (mUsableHeight - mClock.getHeight()));
- mClock.setTranslationX(x);
- mClock.setTranslationY(y);
- mClock.postDelayed(mMoveTextRunnable, MOVE_CLOCK_TIMEOUT);
- }
- };
-
- KeyguardPresentation(Context context, Display display,
- KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory) {
- super(context, display, R.style.Theme_SystemUI_KeyguardPresentation,
- WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory;
- setCancelable(false);
- }
-
- @Override
- public void cancel() {
- // Do not allow anything to cancel KeyguardPresentation except KeyguardDisplayManager.
- }
-
- @Override
- public void onDetachedFromWindow() {
- mClock.removeCallbacks(mMoveTextRunnable);
- }
-
- @Override
- public void onDisplayChanged() {
- updateBounds();
- getWindow().getDecorView().requestLayout();
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- updateBounds();
-
- setContentView(LayoutInflater.from(getContext())
- .inflate(R.layout.keyguard_presentation, null));
-
- // Logic to make the lock screen fullscreen
- getWindow().getDecorView().setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
- getWindow().getAttributes().setFitInsetsTypes(0 /* types */);
- getWindow().setNavigationBarContrastEnforced(false);
- getWindow().setNavigationBarColor(Color.TRANSPARENT);
-
- mClock = findViewById(R.id.clock);
-
- // Avoid screen burn in
- mClock.post(mMoveTextRunnable);
-
- mKeyguardClockSwitchController = mKeyguardStatusViewComponentFactory
- .build(findViewById(R.id.clock), getDisplay())
- .getKeyguardClockSwitchController();
-
- mKeyguardClockSwitchController.setOnlyClock(true);
- mKeyguardClockSwitchController.init();
- }
-
- private void updateBounds() {
- final Rect bounds = getWindow().getWindowManager().getMaximumWindowMetrics()
- .getBounds();
- mUsableWidth = VIDEO_SAFE_REGION * bounds.width() / 100;
- mUsableHeight = VIDEO_SAFE_REGION * bounds.height() / 100;
- mMarginLeft = (100 - VIDEO_SAFE_REGION) * bounds.width() / 200;
- mMarginTop = (100 - VIDEO_SAFE_REGION) * bounds.height() / 200;
- }
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardDisplayManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardDisplayManagerTest.java
index 438f0f4..cc36cfa 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardDisplayManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardDisplayManagerTest.java
@@ -18,8 +18,6 @@
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,9 +35,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;
@@ -60,13 +56,9 @@
@Mock
private NavigationBarController mNavigationBarController;
@Mock
- private KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
- @Mock
private ConnectedDisplayKeyguardPresentation.Factory
mConnectedDisplayKeyguardPresentationFactory;
@Mock
- private KeyguardDisplayManager.KeyguardPresentation mKeyguardPresentation;
- @Mock
private ConnectedDisplayKeyguardPresentation mConnectedDisplayKeyguardPresentation;
@Mock
private KeyguardDisplayManager.DeviceStateHelper mDeviceStateHelper;
@@ -77,7 +69,6 @@
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;
@@ -88,15 +79,13 @@
@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,
- mConnectedDisplayKeyguardPresentationFactory, mFakeFeatureFlags));
- doReturn(mKeyguardPresentation).when(mManager).createPresentation(any());
+ mDisplayTracker, mMainExecutor, mBackgroundExecutor, mDeviceStateHelper,
+ mKeyguardStateController, mConnectedDisplayKeyguardPresentationFactory));
doReturn(mConnectedDisplayKeyguardPresentation).when(
mConnectedDisplayKeyguardPresentationFactory).create(any());
-
+ doReturn(mConnectedDisplayKeyguardPresentation).when(mManager)
+ .createPresentation(any());
mDefaultDisplay = new Display(DisplayManagerGlobal.getInstance(), Display.DEFAULT_DISPLAY,
new DisplayInfo(), DEFAULT_DISPLAY_ADJUSTMENTS);
mSecondaryDisplay = new Display(DisplayManagerGlobal.getInstance(),
@@ -152,9 +141,8 @@
}
@Test
- public void testShow_withClockPresentationFlagEnabled_presentationCreated() {
+ public void testShow_presentationCreated() {
when(mManager.createPresentation(any())).thenCallRealMethod();
- mFakeFeatureFlags.set(ENABLE_CLOCK_KEYGUARD_PRESENTATION, true);
mDisplayTracker.setAllDisplays(new Display[]{mDefaultDisplay, mSecondaryDisplay});
mManager.show();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
deleted file mode 100644
index 5102957..0000000
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2019 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 static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.hardware.display.DisplayManager;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.util.AttributeSet;
-import android.view.Display;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.keyguard.KeyguardDisplayManager.KeyguardPresentation;
-import com.android.keyguard.dagger.KeyguardStatusViewComponent;
-import com.android.systemui.res.R;
-import com.android.systemui.SysuiTestCase;
-
-import org.junit.After;
-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)
-@TestableLooper.RunWithLooper
-public class KeyguardPresentationTest extends SysuiTestCase {
-
- @Mock
- KeyguardClockSwitch mMockKeyguardClockSwitch;
- @Mock
- KeyguardSliceView mMockKeyguardSliceView;
- @Mock
- KeyguardStatusView mMockKeyguardStatusView;
- @Mock
- private KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
- @Mock
- private KeyguardStatusViewComponent mKeyguardStatusViewComponent;
- @Mock
- private KeyguardClockSwitchController mKeyguardClockSwitchController;
-
- LayoutInflater mLayoutInflater;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- when(mMockKeyguardClockSwitch.getContext()).thenReturn(mContext);
- when(mMockKeyguardSliceView.getContext()).thenReturn(mContext);
- when(mMockKeyguardStatusView.getContext()).thenReturn(mContext);
- when(mMockKeyguardStatusView.findViewById(R.id.clock)).thenReturn(mMockKeyguardStatusView);
- when(mKeyguardStatusViewComponentFactory.build(any(KeyguardStatusView.class),
- any(Display.class)))
- .thenReturn(mKeyguardStatusViewComponent);
- when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
- .thenReturn(mKeyguardClockSwitchController);
-
- allowTestableLooperAsMainThread();
-
- mLayoutInflater = LayoutInflater.from(mContext);
- mLayoutInflater.setPrivateFactory(new LayoutInflater.Factory2() {
-
- @Override
- public View onCreateView(View parent, String name, Context context,
- AttributeSet attrs) {
- return onCreateView(name, context, attrs);
- }
-
- @Override
- public View onCreateView(String name, Context context, AttributeSet attrs) {
- if ("com.android.keyguard.KeyguardStatusView".equals(name)) {
- return mMockKeyguardStatusView;
- } else if ("com.android.keyguard.KeyguardClockSwitch".equals(name)) {
- return mMockKeyguardClockSwitch;
- } else if ("com.android.keyguard.KeyguardSliceView".equals(name)) {
- return mMockKeyguardStatusView;
- }
- return null;
- }
- });
- }
-
- @After
- public void tearDown() {
- disallowTestableLooperAsMainThread();
- }
-
- @Test
- public void testInflation_doesntCrash() {
- final Display display = mContext.getSystemService(DisplayManager.class).getDisplay(
- Display.DEFAULT_DISPLAY);
- KeyguardPresentation keyguardPresentation = new KeyguardPresentation(mContext, display,
- mKeyguardStatusViewComponentFactory);
- keyguardPresentation.onCreate(null /*savedInstanceState */);
- }
-}