diff options
6 files changed, 130 insertions, 254 deletions
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml b/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml index f4d34f4ca141..8a0dd125d88b 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 4e540de245dd..186bd7cc48c5 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 dec7d7992596..630610d1a85f 100644 --- a/packages/SystemUI/src/com/android/keyguard/ConnectedDisplayKeyguardPresentation.kt +++ b/packages/SystemUI/src/com/android/keyguard/ConnectedDisplayKeyguardPresentation.kt @@ -19,13 +19,22 @@ package com.android.keyguard 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 @@ constructor( @Assisted display: Display, context: Context, private val keyguardStatusViewComponentFactory: KeyguardStatusViewComponent.Factory, + private val clockRegistry: ClockRegistry, + private val clockEventController: ClockEventController, ) : Presentation( context, @@ -45,31 +56,74 @@ constructor( 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.") - // 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 + setFullscreen() clock = requireViewById(R.id.clock) keyguardStatusViewController = keyguardStatusViewComponentFactory - .build(clock, display) + .build(clock as KeyguardStatusView, display) .keyguardStatusViewController .apply { setDisplayedOnSecondaryDisplay() @@ -77,6 +131,61 @@ constructor( } } + 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 + 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 + } + /** [ConnectedDisplayKeyguardPresentation] factory. */ @AssistedFactory interface Factory { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java index 8a6f101b6c6c..0bb5c174444f 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java @@ -17,13 +17,10 @@ package com.android.keyguard; 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.util.SparseArray; 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 @@ public class KeyguardDisplayManager { 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 @@ public class KeyguardDisplayManager { @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 @@ public class KeyguardDisplayManager { mDeviceStateHelper = deviceStateHelper; mKeyguardStateController = keyguardStateController; mConnectedDisplayKeyguardPresentationFactory = connectedDisplayKeyguardPresentationFactory; - mFeatureFlags = featureFlags; } private boolean isKeyguardShowable(Display display) { @@ -197,11 +182,7 @@ public class KeyguardDisplayManager { } 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 @@ public class KeyguardDisplayManager { && 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 438f0f43acb6..cc36cfa6a30a 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 @@ 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,9 +35,7 @@ import android.view.DisplayInfo; 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 @@ public class KeyguardDisplayManagerTest extends SysuiTestCase { @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 @@ 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; @@ -88,15 +79,13 @@ 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, - 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 @@ public class KeyguardDisplayManagerTest extends SysuiTestCase { } @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 5102957c71ed..000000000000 --- 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 */); - } -} |