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

Commit 484466e2 authored by Kevin Chyn's avatar Kevin Chyn
Browse files

Animate panel to transparent if profile is managed

For managed profiles, we need to show the managed device background with
the device admin color theme during credential UI. Since it's shown on
the "background" view behind the panel, we can animate/fade the biometric
view down, and slide in the credential UI on the "background" layer.

Bug: 140127687

Test: manual test with device admin
Test: atest com.android.systemui.biometrics
Change-Id: I2d0a1b4367912e4bf6ddf701ad68fc387501f048
parent c70d6b83
Loading
Loading
Loading
Loading
+32 −8
Original line number Original line Diff line number Diff line
@@ -46,6 +46,8 @@ import com.android.systemui.R;


import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;


/**
/**
 * Contains the Biometric views (title, subtitle, icon, buttons, etc) and its controllers.
 * Contains the Biometric views (title, subtitle, icon, buttons, etc) and its controllers.
@@ -376,7 +378,16 @@ public abstract class AuthBiometricView extends LinearLayout {
                    0 /* animateDurationMs */);
                    0 /* animateDurationMs */);
            mSize = newSize;
            mSize = newSize;
        } else if (newSize == AuthDialog.SIZE_LARGE) {
        } else if (newSize == AuthDialog.SIZE_LARGE) {
            final float translationY = getResources().getDimension(
            final boolean isManagedProfile = Utils.isManagedProfile(mContext, mUserId);

            // If it's a managed profile, animate the contents and panel down, since the credential
            // contents will be shown on the same "layer" as the background. If it's not a managed
            // profile, animate the contents up and expand the panel to full-screen - the credential
            // contents will be shown on the same "layer" as the panel.
            final float translationY = isManagedProfile ?
                    -getResources().getDimension(
                            R.dimen.biometric_dialog_animation_translation_offset)
                    : getResources().getDimension(
                            R.dimen.biometric_dialog_medium_to_large_translation_offset);
                            R.dimen.biometric_dialog_medium_to_large_translation_offset);
            final AuthBiometricView biometricView = this;
            final AuthBiometricView biometricView = this;


@@ -407,13 +418,26 @@ public abstract class AuthBiometricView extends LinearLayout {
                biometricView.setAlpha(opacity);
                biometricView.setAlpha(opacity);
            });
            });


            if (!isManagedProfile) {
                mPanelController.setUseFullScreen(true);
                mPanelController.setUseFullScreen(true);
                mPanelController.updateForContentDimensions(
                mPanelController.updateForContentDimensions(
                        mPanelController.getContainerWidth(),
                        mPanelController.getContainerWidth(),
                        mPanelController.getContainerHeight(),
                        mPanelController.getContainerHeight(),
                        mInjector.getMediumToLargeAnimationDurationMs());
                        mInjector.getMediumToLargeAnimationDurationMs());
            }

            // Start the animations together
            AnimatorSet as = new AnimatorSet();
            AnimatorSet as = new AnimatorSet();
            as.play(translationAnimator).with(opacityAnimator);
            List<Animator> animators = new ArrayList<>();
            animators.add(translationAnimator);
            animators.add(opacityAnimator);
            if (isManagedProfile) {
                animators.add(mPanelController.getTranslationAnimator(translationY));
                animators.add(mPanelController.getAlphaAnimator(0));
            }
            as.playTogether(animators);
            as.setDuration(isManagedProfile ? mInjector.getMediumToLargeAnimationDurationMs()
                    : mInjector.getMediumToLargeAnimationDurationMs() * 2 / 3);
            as.start();
            as.start();
        } else {
        } else {
            Log.e(TAG, "Unknown transition from: " + mSize + " to: " + newSize);
            Log.e(TAG, "Unknown transition from: " + mSize + " to: " + newSize);
+9 −6
Original line number Original line Diff line number Diff line
@@ -165,8 +165,9 @@ public class AuthContainerView extends LinearLayout
                    R.layout.auth_container_view, root, false /* attachToRoot */);
                    R.layout.auth_container_view, root, false /* attachToRoot */);
        }
        }


        AuthPanelController getPanelController(Context context, View panelView) {
        AuthPanelController getPanelController(Context context, View panelView,
            return new AuthPanelController(context, panelView);
                boolean isManagedProfile) {
            return new AuthPanelController(context, panelView, isManagedProfile);
        }
        }


        ImageView getBackgroundView(FrameLayout parent) {
        ImageView getBackgroundView(FrameLayout parent) {
@@ -234,8 +235,10 @@ public class AuthContainerView extends LinearLayout
        final LayoutInflater factory = LayoutInflater.from(mContext);
        final LayoutInflater factory = LayoutInflater.from(mContext);
        mFrameLayout = mInjector.inflateContainerView(factory, this);
        mFrameLayout = mInjector.inflateContainerView(factory, this);


        final boolean isManagedProfile = Utils.isManagedProfile(mContext, mConfig.mUserId);

        mPanelView = mInjector.getPanelView(mFrameLayout);
        mPanelView = mInjector.getPanelView(mFrameLayout);
        mPanelController = mInjector.getPanelController(mContext, mPanelView);
        mPanelController = mInjector.getPanelController(mContext, mPanelView, isManagedProfile);


        // Inflate biometric view only if necessary.
        // Inflate biometric view only if necessary.
        if (Utils.isBiometricAllowed(mConfig.mBiometricPromptBundle)) {
        if (Utils.isBiometricAllowed(mConfig.mBiometricPromptBundle)) {
@@ -257,11 +260,11 @@ public class AuthContainerView extends LinearLayout
        mBiometricScrollView = mInjector.getBiometricScrollView(mFrameLayout);
        mBiometricScrollView = mInjector.getBiometricScrollView(mFrameLayout);
        mBackgroundView = mInjector.getBackgroundView(mFrameLayout);
        mBackgroundView = mInjector.getBackgroundView(mFrameLayout);


        UserManager userManager = mContext.getSystemService(UserManager.class);

        DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
        if (isManagedProfile) {
        if (userManager.isManagedProfile(mConfig.mUserId)) {
            final Drawable image = getResources().getDrawable(R.drawable.work_challenge_background,
            final Drawable image = getResources().getDrawable(R.drawable.work_challenge_background,
                    mContext.getTheme());
                    mContext.getTheme());
            final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
            image.setColorFilter(dpm.getOrganizationColorForUser(mConfig.mUserId),
            image.setColorFilter(dpm.getOrganizationColorForUser(mConfig.mUserId),
                    PorterDuff.Mode.DARKEN);
                    PorterDuff.Mode.DARKEN);
            mBackgroundView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            mBackgroundView.setScaleType(ImageView.ScaleType.CENTER_CROP);
+43 −2
Original line number Original line Diff line number Diff line
@@ -19,10 +19,12 @@ package com.android.systemui.biometrics;
import android.animation.AnimatorSet;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Outline;
import android.graphics.Outline;
import android.util.Log;
import android.util.Log;
import android.view.View;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.view.ViewOutlineProvider;
import android.view.animation.AccelerateDecelerateInterpolator;


import com.android.systemui.R;
import com.android.systemui.R;


@@ -36,6 +38,7 @@ public class AuthPanelController extends ViewOutlineProvider {


    private final Context mContext;
    private final Context mContext;
    private final View mPanelView;
    private final View mPanelView;
    private final boolean mIsManagedProfile;


    private boolean mUseFullScreen;
    private boolean mUseFullScreen;


@@ -77,6 +80,24 @@ public class AuthPanelController extends ViewOutlineProvider {
        mUseFullScreen = fullScreen;
        mUseFullScreen = fullScreen;
    }
    }


    public ValueAnimator getTranslationAnimator(float relativeTranslationY) {
        final ValueAnimator animator = ValueAnimator.ofFloat(
                mPanelView.getY(), mPanelView.getY() - relativeTranslationY);
        animator.addUpdateListener(animation -> {
            final float translation = (float) animation.getAnimatedValue();
            mPanelView.setTranslationY(translation);
        });
        return animator;
    }

    public ValueAnimator getAlphaAnimator(float alpha) {
        final ValueAnimator animator = ValueAnimator.ofFloat(mPanelView.getAlpha(), alpha);
        animator.addUpdateListener(animation -> {
            mPanelView.setAlpha((float) animation.getAnimatedValue());
        });
        return animator;
    }

    public void updateForContentDimensions(int contentWidth, int contentHeight,
    public void updateForContentDimensions(int contentWidth, int contentHeight,
            int animateDurationMs) {
            int animateDurationMs) {
        if (DEBUG) {
        if (DEBUG) {
@@ -95,6 +116,13 @@ public class AuthPanelController extends ViewOutlineProvider {
        final float cornerRadius = mUseFullScreen ? 0 : mContext.getResources()
        final float cornerRadius = mUseFullScreen ? 0 : mContext.getResources()
                .getDimension(R.dimen.biometric_dialog_corner_size);
                .getDimension(R.dimen.biometric_dialog_corner_size);


        // When going to full-screen for managed profiles, fade away so the managed profile
        // background behind this view becomes visible.
        final boolean shouldFadeAway = mUseFullScreen && mIsManagedProfile;
        final int alpha = shouldFadeAway ? 0 : 255;
        final float elevation = shouldFadeAway ? 0 :
                mContext.getResources().getDimension(R.dimen.biometric_dialog_elevation);

        if (animateDurationMs > 0) {
        if (animateDurationMs > 0) {
            // Animate margin
            // Animate margin
            ValueAnimator marginAnimator = ValueAnimator.ofInt(mMargin, margin);
            ValueAnimator marginAnimator = ValueAnimator.ofInt(mMargin, margin);
@@ -122,16 +150,28 @@ public class AuthPanelController extends ViewOutlineProvider {
                mContentWidth = (int) animation.getAnimatedValue();
                mContentWidth = (int) animation.getAnimatedValue();
            });
            });


            // Animate background
            ValueAnimator alphaAnimator = ValueAnimator.ofInt(
                    mPanelView.getBackground().getAlpha(), alpha);
            alphaAnimator.addUpdateListener((animation) -> {
                if (shouldFadeAway) {
                    mPanelView.getBackground().setAlpha((int) animation.getAnimatedValue());
                }
            });

            // Play together
            // Play together
            AnimatorSet as = new AnimatorSet();
            AnimatorSet as = new AnimatorSet();
            as.setDuration(animateDurationMs);
            as.setDuration(animateDurationMs);
            as.playTogether(cornerAnimator, heightAnimator, widthAnimator, marginAnimator);
            as.setInterpolator(new AccelerateDecelerateInterpolator());
            as.playTogether(cornerAnimator, widthAnimator, marginAnimator, alphaAnimator);
            as.start();
            as.start();

        } else {
        } else {
            mMargin = margin;
            mMargin = margin;
            mCornerRadius = cornerRadius;
            mCornerRadius = cornerRadius;
            mContentWidth = contentWidth;
            mContentWidth = contentWidth;
            mContentHeight = contentHeight;
            mContentHeight = contentHeight;
            mPanelView.getBackground().setAlpha(alpha);
            mPanelView.invalidateOutline();
            mPanelView.invalidateOutline();
        }
        }
    }
    }
@@ -144,9 +184,10 @@ public class AuthPanelController extends ViewOutlineProvider {
        return mContainerHeight;
        return mContainerHeight;
    }
    }


    AuthPanelController(Context context, View panelView) {
    AuthPanelController(Context context, View panelView, boolean isManagedProfile) {
        mContext = context;
        mContext = context;
        mPanelView = panelView;
        mPanelView = panelView;
        mIsManagedProfile = isManagedProfile;
        mCornerRadius = context.getResources()
        mCornerRadius = context.getResources()
                .getDimension(R.dimen.biometric_dialog_corner_size);
                .getDimension(R.dimen.biometric_dialog_corner_size);
        mMargin = (int) context.getResources()
        mMargin = (int) context.getResources()
+6 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ import android.content.Context;
import android.hardware.biometrics.Authenticator;
import android.hardware.biometrics.Authenticator;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricPrompt;
import android.os.Bundle;
import android.os.Bundle;
import android.os.UserManager;
import android.util.DisplayMetrics;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup;
@@ -99,4 +100,9 @@ public class Utils {
                return CREDENTIAL_PASSWORD;
                return CREDENTIAL_PASSWORD;
        }
        }
    }
    }

    static boolean isManagedProfile(Context context, int userId) {
        final UserManager userManager = context.getSystemService(UserManager.class);
        return userManager.isManagedProfile(userId);
    }
}
}
+2 −1
Original line number Original line Diff line number Diff line
@@ -192,7 +192,8 @@ public class AuthContainerViewTest extends SysuiTestCase {
        }
        }


        @Override
        @Override
        public AuthPanelController getPanelController(Context context, View view) {
        public AuthPanelController getPanelController(Context context, View view,
                boolean isManagedProfile) {
            return mock(AuthPanelController.class);
            return mock(AuthPanelController.class);
        }
        }