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

Commit c202ca4b authored by Coco Duan's avatar Coco Duan Committed by Android (Google) Code Review
Browse files

Merge "Hide views on lockscreen when wallpaper dream is active" into udc-qpr-dev

parents 4f0a4c94 e75c63e9
Loading
Loading
Loading
Loading
+38 −1
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;

import static com.android.keyguard.KeyguardClockSwitch.LARGE;
import static com.android.keyguard.KeyguardClockSwitch.SMALL;
import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;

import android.annotation.Nullable;
import android.database.ContentObserver;
@@ -33,12 +35,15 @@ import android.widget.FrameLayout;
import android.widget.LinearLayout;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.core.LogLevel;
import com.android.systemui.log.dagger.KeyguardClockLog;
@@ -58,6 +63,7 @@ import com.android.systemui.util.settings.SecureSettings;

import java.io.PrintWriter;
import java.util.Locale;
import java.util.function.Consumer;

import javax.inject.Inject;

@@ -99,8 +105,20 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
    private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;

    private boolean mOnlyClock = false;
    private boolean mIsActiveDreamLockscreenHosted = false;
    private FeatureFlags mFeatureFlags;
    private KeyguardInteractor mKeyguardInteractor;
    private final DelayableExecutor mUiExecutor;
    private boolean mCanShowDoubleLineClock = true;
    @VisibleForTesting
    final Consumer<Boolean> mIsActiveDreamLockscreenHostedCallback =
            (Boolean isLockscreenHosted) -> {
                if (mIsActiveDreamLockscreenHosted == isLockscreenHosted) {
                    return;
                }
                mIsActiveDreamLockscreenHosted = isLockscreenHosted;
                updateKeyguardStatusAreaVisibility();
            };
    private final ContentObserver mDoubleLineClockObserver = new ContentObserver(null) {
        @Override
        public void onChange(boolean change) {
@@ -137,7 +155,9 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
            @Main DelayableExecutor uiExecutor,
            DumpManager dumpManager,
            ClockEventController clockEventController,
            @KeyguardClockLog LogBuffer logBuffer) {
            @KeyguardClockLog LogBuffer logBuffer,
            KeyguardInteractor keyguardInteractor,
            FeatureFlags featureFlags) {
        super(keyguardClockSwitch);
        mStatusBarStateController = statusBarStateController;
        mClockRegistry = clockRegistry;
@@ -151,6 +171,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
        mClockEventController = clockEventController;
        mLogBuffer = logBuffer;
        mView.setLogBuffer(mLogBuffer);
        mFeatureFlags = featureFlags;
        mKeyguardInteractor = keyguardInteractor;

        mClockChangedListener = new ClockRegistry.ClockChangeListener() {
            @Override
@@ -191,6 +213,12 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS

        mDumpManager.unregisterDumpable(getClass().toString()); // unregister previous clocks
        mDumpManager.registerDumpable(getClass().toString(), this);

        if (mFeatureFlags.isEnabled(LOCKSCREEN_WALLPAPER_DREAM_ENABLED)) {
            mStatusArea = mView.findViewById(R.id.keyguard_status_area);
            collectFlow(mStatusArea, mKeyguardInteractor.isActiveDreamLockscreenHosted(),
                    mIsActiveDreamLockscreenHostedCallback);
        }
    }

    @Override
@@ -524,6 +552,15 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
        }
    }

    private void updateKeyguardStatusAreaVisibility() {
        if (mStatusArea != null) {
            mUiExecutor.execute(() -> {
                mStatusArea.setVisibility(
                        mIsActiveDreamLockscreenHosted ? View.INVISIBLE : View.VISIBLE);
            });
        }
    }

    /**
     * Sets the clipChildren property on relevant views, to allow the smartspace to draw out of
     * bounds during the unlock transition.
+20 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static com.android.keyguard.LockIconView.ICON_LOCK;
import static com.android.keyguard.LockIconView.ICON_UNLOCK;
import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
import static com.android.systemui.flags.Flags.DOZING_MIGRATION_1;
import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;

import android.content.res.Configuration;
@@ -124,6 +125,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
    private int mActivePointerId = -1;

    private boolean mIsDozing;
    private boolean mIsActiveDreamLockscreenHosted;
    private boolean mIsBouncerShowing;
    private boolean mRunningFPS;
    private boolean mCanDismissLockScreen;
@@ -165,6 +167,13 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
        updateVisibility();
    };

    @VisibleForTesting
    final Consumer<Boolean> mIsActiveDreamLockscreenHostedCallback =
            (Boolean isLockscreenHosted) -> {
                mIsActiveDreamLockscreenHosted = isLockscreenHosted;
                updateVisibility();
            };

    @Inject
    public LockIconViewController(
            @Nullable LockIconView view,
@@ -224,6 +233,11 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
                    mDozeTransitionCallback);
            collectFlow(mView, mKeyguardInteractor.isDozing(), mIsDozingCallback);
        }

        if (mFeatureFlags.isEnabled(LOCKSCREEN_WALLPAPER_DREAM_ENABLED)) {
            collectFlow(mView, mKeyguardInteractor.isActiveDreamLockscreenHosted(),
                    mIsActiveDreamLockscreenHostedCallback);
        }
    }

    @Override
@@ -289,6 +303,11 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
            return;
        }

        if (mIsKeyguardShowing && mIsActiveDreamLockscreenHosted) {
            mView.setVisibility(View.INVISIBLE);
            return;
        }

        boolean wasShowingFpIcon = mUdfpsEnrolled && !mShowUnlockIcon && !mShowLockIcon
                && !mShowAodUnlockedIcon && !mShowAodLockIcon;
        mShowLockIcon = !mCanDismissLockScreen && isLockScreen()
@@ -436,6 +455,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
        pw.println(" mInterpolatedDarkAmount: " + mInterpolatedDarkAmount);
        pw.println(" mSensorTouchLocation: " + mSensorTouchLocation);
        pw.println(" mDefaultPaddingPx: " + mDefaultPaddingPx);
        pw.println(" mIsActiveDreamLockscreenHosted: " + mIsActiveDreamLockscreenHosted);

        if (mView != null) {
            mView.dump(pw, args);
+29 −2
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED;
import static com.android.systemui.DejankUtils.whitelistIpcs;
import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.IMPORTANT_MSG_MIN_DURATION;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY;
@@ -43,6 +44,7 @@ import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewCont
import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_ON;
import static com.android.systemui.log.core.LogLevel.ERROR;
import static com.android.systemui.plugins.FalsingManager.LOW_PENALTY;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;

import android.app.AlarmManager;
import android.app.admin.DevicePolicyManager;
@@ -96,6 +98,7 @@ import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.KeyguardIndication;
import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.util.IndicationHelper;
import com.android.systemui.log.core.LogLevel;
import com.android.systemui.plugins.FalsingManager;
@@ -114,6 +117,7 @@ import java.io.PrintWriter;
import java.text.NumberFormat;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;

import javax.inject.Inject;

@@ -171,7 +175,7 @@ public class KeyguardIndicationController {
    public KeyguardIndicationRotateTextViewController mRotateTextViewController;
    private BroadcastReceiver mBroadcastReceiver;
    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;

    private KeyguardInteractor mKeyguardInteractor;
    private String mPersistentUnlockMessage;
    private String mAlignmentIndication;
    private CharSequence mTrustGrantedIndication;
@@ -205,7 +209,17 @@ public class KeyguardIndicationController {
    private KeyguardUpdateMonitorCallback mUpdateMonitorCallback;

    private boolean mDozing;
    private boolean mIsActiveDreamLockscreenHosted;
    private final ScreenLifecycle mScreenLifecycle;
    @VisibleForTesting
    final Consumer<Boolean> mIsActiveDreamLockscreenHostedCallback =
            (Boolean isLockscreenHosted) -> {
                if (mIsActiveDreamLockscreenHosted == isLockscreenHosted) {
                    return;
                }
                mIsActiveDreamLockscreenHosted = isLockscreenHosted;
                updateDeviceEntryIndication(false);
            };
    private final ScreenLifecycle.Observer mScreenObserver =
            new ScreenLifecycle.Observer() {
        @Override
@@ -261,7 +275,8 @@ public class KeyguardIndicationController {
            UserTracker userTracker,
            BouncerMessageInteractor bouncerMessageInteractor,
            FeatureFlags flags,
            IndicationHelper indicationHelper
            IndicationHelper indicationHelper,
            KeyguardInteractor keyguardInteractor
    ) {
        mContext = context;
        mBroadcastDispatcher = broadcastDispatcher;
@@ -289,6 +304,7 @@ public class KeyguardIndicationController {
        mBouncerMessageInteractor = bouncerMessageInteractor;
        mFeatureFlags = flags;
        mIndicationHelper = indicationHelper;
        mKeyguardInteractor = keyguardInteractor;

        mFaceAcquiredMessageDeferral = faceHelpMessageDeferral;
        mCoExFaceAcquisitionMsgIdsToShow = new HashSet<>();
@@ -371,6 +387,10 @@ public class KeyguardIndicationController {
            intentFilter.addAction(Intent.ACTION_USER_REMOVED);
            mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, intentFilter);
        }
        if (mFeatureFlags.isEnabled(LOCKSCREEN_WALLPAPER_DREAM_ENABLED)) {
            collectFlow(mIndicationArea, mKeyguardInteractor.isActiveDreamLockscreenHosted(),
                    mIsActiveDreamLockscreenHostedCallback);
        }
    }

    /**
@@ -878,6 +898,12 @@ public class KeyguardIndicationController {
            return;
        }

        // Device is dreaming and the dream is hosted in lockscreen
        if (mIsActiveDreamLockscreenHosted) {
            mIndicationArea.setVisibility(GONE);
            return;
        }

        // A few places might need to hide the indication, so always start by making it visible
        mIndicationArea.setVisibility(VISIBLE);

@@ -1069,6 +1095,7 @@ public class KeyguardIndicationController {
        pw.println("  mBiometricMessageFollowUp: " + mBiometricMessageFollowUp);
        pw.println("  mBatteryLevel: " + mBatteryLevel);
        pw.println("  mBatteryPresent: " + mBatteryPresent);
        pw.println("  mIsActiveDreamLockscreenHosted: " + mIsActiveDreamLockscreenHosted);
        pw.println("  AOD text: " + (
                mTopIndicationView == null ? null : mTopIndicationView.getText()));
        pw.println("  computePowerIndication(): " + computePowerIndication());
+210 −0
Original line number Diff line number Diff line
/*
 * 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 static android.view.View.INVISIBLE;

import static com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR;
import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.res.Resources;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
import com.android.systemui.log.LogBuffer;
import com.android.systemui.plugins.ClockAnimations;
import com.android.systemui.plugins.ClockController;
import com.android.systemui.plugins.ClockEvents;
import com.android.systemui.plugins.ClockFaceConfig;
import com.android.systemui.plugins.ClockFaceController;
import com.android.systemui.plugins.ClockFaceEvents;
import com.android.systemui.plugins.ClockTickRate;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.clocks.AnimatableClockView;
import com.android.systemui.shared.clocks.ClockRegistry;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.time.FakeSystemClock;

import org.junit.Before;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

public class KeyguardClockSwitchControllerBaseTest extends SysuiTestCase {

    @Mock
    protected KeyguardClockSwitch mView;
    @Mock
    protected StatusBarStateController mStatusBarStateController;
    @Mock
    protected ClockRegistry mClockRegistry;
    @Mock
    KeyguardSliceViewController mKeyguardSliceViewController;
    @Mock
    NotificationIconAreaController mNotificationIconAreaController;
    @Mock
    LockscreenSmartspaceController mSmartspaceController;

    @Mock
    Resources mResources;
    @Mock
    KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
    @Mock
    protected ClockController mClockController;
    @Mock
    protected ClockFaceController mLargeClockController;
    @Mock
    protected ClockFaceController mSmallClockController;
    @Mock
    protected ClockAnimations mClockAnimations;
    @Mock
    protected ClockEvents mClockEvents;
    @Mock
    protected ClockFaceEvents mClockFaceEvents;
    @Mock
    DumpManager mDumpManager;
    @Mock
    ClockEventController mClockEventController;

    @Mock
    protected NotificationIconContainer mNotificationIcons;
    @Mock
    protected AnimatableClockView mSmallClockView;
    @Mock
    protected AnimatableClockView mLargeClockView;
    @Mock
    protected FrameLayout mSmallClockFrame;
    @Mock
    protected FrameLayout mLargeClockFrame;
    @Mock
    protected SecureSettings mSecureSettings;
    @Mock
    protected LogBuffer mLogBuffer;

    protected final View mFakeDateView = (View) (new ViewGroup(mContext) {
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {}
    });
    protected final View mFakeWeatherView = new View(mContext);
    protected final View mFakeSmartspaceView = new View(mContext);

    protected KeyguardClockSwitchController mController;
    protected View mSliceView;
    protected LinearLayout mStatusArea;
    protected FakeExecutor mExecutor;
    protected FakeFeatureFlags mFakeFeatureFlags;
    @Captor protected ArgumentCaptor<View.OnAttachStateChangeListener> mAttachCaptor =
            ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);

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

        when(mView.findViewById(R.id.left_aligned_notification_icon_container))
                .thenReturn(mNotificationIcons);
        when(mNotificationIcons.getLayoutParams()).thenReturn(
                mock(RelativeLayout.LayoutParams.class));
        when(mView.getContext()).thenReturn(getContext());
        when(mView.getResources()).thenReturn(mResources);
        when(mResources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin))
                .thenReturn(100);
        when(mResources.getDimensionPixelSize(R.dimen.keyguard_large_clock_top_margin))
                .thenReturn(-200);
        when(mResources.getInteger(R.integer.keyguard_date_weather_view_invisibility))
                .thenReturn(INVISIBLE);

        when(mView.findViewById(R.id.lockscreen_clock_view_large)).thenReturn(mLargeClockFrame);
        when(mView.findViewById(R.id.lockscreen_clock_view)).thenReturn(mSmallClockFrame);
        when(mSmallClockView.getContext()).thenReturn(getContext());
        when(mLargeClockView.getContext()).thenReturn(getContext());

        when(mView.isAttachedToWindow()).thenReturn(true);
        when(mSmartspaceController.buildAndConnectDateView(any())).thenReturn(mFakeDateView);
        when(mSmartspaceController.buildAndConnectWeatherView(any())).thenReturn(mFakeWeatherView);
        when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mFakeSmartspaceView);
        mExecutor = new FakeExecutor(new FakeSystemClock());
        mFakeFeatureFlags = new FakeFeatureFlags();
        mFakeFeatureFlags.set(FACE_AUTH_REFACTOR, false);
        mFakeFeatureFlags.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false);
        mController = new KeyguardClockSwitchController(
                mView,
                mStatusBarStateController,
                mClockRegistry,
                mKeyguardSliceViewController,
                mNotificationIconAreaController,
                mSmartspaceController,
                mKeyguardUnlockAnimationController,
                mSecureSettings,
                mExecutor,
                mDumpManager,
                mClockEventController,
                mLogBuffer,
                KeyguardInteractorFactory.create(mFakeFeatureFlags).getKeyguardInteractor(),
                mFakeFeatureFlags
        );

        when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
        when(mLargeClockController.getView()).thenReturn(mLargeClockView);
        when(mSmallClockController.getView()).thenReturn(mSmallClockView);
        when(mClockController.getLargeClock()).thenReturn(mLargeClockController);
        when(mClockController.getSmallClock()).thenReturn(mSmallClockController);
        when(mClockController.getEvents()).thenReturn(mClockEvents);
        when(mSmallClockController.getEvents()).thenReturn(mClockFaceEvents);
        when(mLargeClockController.getEvents()).thenReturn(mClockFaceEvents);
        when(mLargeClockController.getAnimations()).thenReturn(mClockAnimations);
        when(mSmallClockController.getAnimations()).thenReturn(mClockAnimations);
        when(mClockRegistry.createCurrentClock()).thenReturn(mClockController);
        when(mClockEventController.getClock()).thenReturn(mClockController);
        when(mSmallClockController.getConfig())
                .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false));
        when(mLargeClockController.getConfig())
                .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false));

        mSliceView = new View(getContext());
        when(mView.findViewById(R.id.keyguard_slice_view)).thenReturn(mSliceView);
        mStatusArea = new LinearLayout(getContext());
        when(mView.findViewById(R.id.keyguard_status_area)).thenReturn(mStatusArea);
    }

    protected void init() {
        mController.init();

        verify(mView, atLeast(1)).addOnAttachStateChangeListener(mAttachCaptor.capture());
        mAttachCaptor.getValue().onViewAttachedToWindow(mView);
    }
}
+2 −155

File changed.

Preview size limit exceeded, changes collapsed.

Loading