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

Commit 58b05ef7 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 9730367 from 2b2deec8 to tm-qpr3-release

Change-Id: I2c833b0807e687ae40c1595f72bd32c53077e84e
parents 2956bf9f 2b2deec8
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.window.TaskSnapshot;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.transition.Transitions;

@@ -372,7 +373,8 @@ public class PipAnimationController {

        void setAppIconContentOverlay(Context context, Rect bounds, ActivityInfo activityInfo) {
            reattachContentOverlay(
                    new PipContentOverlay.PipAppIconOverlay(context, bounds, activityInfo));
                    new PipContentOverlay.PipAppIconOverlay(context, bounds,
                            () -> new IconProvider(context).getIcon(activityInfo)));
        }

        private void reattachContentOverlay(PipContentOverlay overlay) {
+9 −28
Original line number Diff line number Diff line
@@ -20,9 +20,6 @@ import static android.util.TypedValue.COMPLEX_UNIT_DIP;

import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -35,6 +32,8 @@ import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.window.TaskSnapshot;

import java.util.function.Supplier;

/**
 * Represents the content overlay used during the entering PiP animation.
 */
@@ -177,7 +176,9 @@ public abstract class PipContentOverlay {
    /** A {@link PipContentOverlay} shows app icon on solid color background. */
    public static final class PipAppIconOverlay extends PipContentOverlay {
        private static final String TAG = PipAppIconOverlay.class.getSimpleName();
        private static final int APP_ICON_SIZE_DP = 48;
        // Align with the practical / reasonable launcher:iconImageSize as in
        // vendor/unbundled_google/packages/NexusLauncher/res/xml/device_profiles.xml
        private static final int APP_ICON_SIZE_DP = 66;

        private final Context mContext;
        private final int mAppIconSizePx;
@@ -187,14 +188,14 @@ public abstract class PipContentOverlay {

        private Bitmap mBitmap;

        public PipAppIconOverlay(Context context, Rect appBounds, ActivityInfo activityInfo) {
        public PipAppIconOverlay(Context context, Rect appBounds, Supplier<Drawable> iconSupplier) {
            mContext = context;
            mAppIconSizePx = (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, APP_ICON_SIZE_DP,
                    context.getResources().getDisplayMetrics());
            mAppBounds = new Rect(appBounds);
            mBitmap = Bitmap.createBitmap(appBounds.width(), appBounds.height(),
                    Bitmap.Config.ARGB_8888);
            prepareAppIconOverlay(activityInfo);
            prepareAppIconOverlay(iconSupplier);
            mLeash = new SurfaceControl.Builder(new SurfaceSession())
                    .setCallsite(TAG)
                    .setName(LAYER_NAME)
@@ -237,7 +238,7 @@ public abstract class PipContentOverlay {
            }
        }

        private void prepareAppIconOverlay(ActivityInfo activityInfo) {
        private void prepareAppIconOverlay(Supplier<Drawable> iconSupplier) {
            final Canvas canvas = new Canvas();
            canvas.setBitmap(mBitmap);
            final TypedArray ta = mContext.obtainStyledAttributes(new int[] {
@@ -251,8 +252,7 @@ public abstract class PipContentOverlay {
            } finally {
                ta.recycle();
            }
            final Drawable appIcon = loadActivityInfoIcon(activityInfo,
                    mContext.getResources().getConfiguration().densityDpi);
            final Drawable appIcon = iconSupplier.get();
            final Rect appIconBounds = new Rect(
                    mAppBounds.centerX() - mAppIconSizePx / 2,
                    mAppBounds.centerY() - mAppIconSizePx / 2,
@@ -262,24 +262,5 @@ public abstract class PipContentOverlay {
            appIcon.draw(canvas);
            mBitmap = mBitmap.copy(Bitmap.Config.HARDWARE, false /* mutable */);
        }

        // Copied from com.android.launcher3.icons.IconProvider#loadActivityInfoIcon
        private Drawable loadActivityInfoIcon(ActivityInfo ai, int density) {
            final int iconRes = ai.getIconResource();
            Drawable icon = null;
            // Get the preferred density icon from the app's resources
            if (density != 0 && iconRes != 0) {
                try {
                    final Resources resources = mContext.getPackageManager()
                            .getResourcesForApplication(ai.applicationInfo);
                    icon = resources.getDrawableForDensity(iconRes, density);
                } catch (PackageManager.NameNotFoundException | Resources.NotFoundException exc) { }
            }
            // Get the default density icon
            if (icon == null) {
                icon = ai.loadIcon(mContext.getPackageManager());
            }
            return icon;
        }
    }
}
+8 −1
Original line number Diff line number Diff line
@@ -803,8 +803,15 @@ public class PipTransition extends PipTransitionController {
            if (sourceHintRect == null) {
                // We use content overlay when there is no source rect hint to enter PiP use bounds
                // animation.
                // TODO(b/272819817): cleanup the null-check and extra logging.
                final boolean hasTopActivityInfo = taskInfo.topActivityInfo != null;
                if (!hasTopActivityInfo) {
                    ProtoLog.w(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                            "%s: TaskInfo.topActivityInfo is null", TAG);
                }
                if (SystemProperties.getBoolean(
                        "persist.wm.debug.enable_pip_app_icon_overlay", true)) {
                        "persist.wm.debug.enable_pip_app_icon_overlay", true)
                        && hasTopActivityInfo) {
                    animator.setAppIconContentOverlay(
                            mContext, currentBounds, taskInfo.topActivityInfo);
                } else {
+54 −37
Original line number Diff line number Diff line
@@ -96,9 +96,9 @@ public class RotationButtonController {
    private boolean mHoveringRotationSuggestion;
    private final AccessibilityManager mAccessibilityManager;
    private final TaskStackListenerImpl mTaskStackListener;
    private Consumer<Integer> mRotWatcherListener;

    private boolean mListenersRegistered = false;
    private boolean mRotationWatcherRegistered = false;
    private boolean mIsNavigationBarShowing;
    @SuppressLint("InlinedApi")
    private @WindowInsetsController.Behavior
@@ -140,22 +140,7 @@ public class RotationButtonController {
            // We need this to be scheduled as early as possible to beat the redrawing of
            // window in response to the orientation change.
            mMainThreadHandler.postAtFrontOfQueue(() -> {
                // If the screen rotation changes while locked, potentially update lock to flow with
                // new screen rotation and hide any showing suggestions.
                boolean rotationLocked = isRotationLocked();
                // The isVisible check makes the rotation button disappear when we are not locked
                // (e.g. for tabletop auto-rotate).
                if (rotationLocked || mRotationButton.isVisible()) {
                    // Do not allow a change in rotation to set user rotation when docked.
                    if (shouldOverrideUserLockPrefs(rotation) && rotationLocked && !mDocked) {
                        setRotationLockedAtAngle(rotation);
                    }
                    setRotateSuggestionButtonState(false /* visible */, true /* forced */);
                }

                if (mRotWatcherListener != null) {
                    mRotWatcherListener.accept(rotation);
                }
                onRotationWatcherChanged(rotation);
            });
        }
    };
@@ -206,8 +191,11 @@ public class RotationButtonController {
        return mContext;
    }

    /**
     * Called during Taskbar initialization.
     */
    public void init() {
        registerListeners();
        registerListeners(true /* registerRotationWatcher */);
        if (mContext.getDisplay().getDisplayId() != DEFAULT_DISPLAY) {
            // Currently there is no accelerometer sensor on non-default display, disable fixed
            // rotation for non-default display
@@ -215,11 +203,14 @@ public class RotationButtonController {
        }
    }

    /**
     * Called during Taskbar uninitialization.
     */
    public void onDestroy() {
        unregisterListeners();
    }

    public void registerListeners() {
    public void registerListeners(boolean registerRotationWatcher) {
        if (mListenersRegistered || getContext().getPackageManager().hasSystemFeature(FEATURE_PC)) {
            return;
        }
@@ -229,16 +220,19 @@ public class RotationButtonController {
        updateDockedState(mContext.registerReceiver(mDockedReceiver,
                new IntentFilter(Intent.ACTION_DOCK_EVENT)));

        if (registerRotationWatcher) {
            try {
                WindowManagerGlobal.getWindowManagerService()
                        .watchRotation(mRotationWatcher, DEFAULT_DISPLAY);
                mRotationWatcherRegistered = true;
            } catch (IllegalArgumentException e) {
                mListenersRegistered = false;
            Log.w(TAG, "RegisterListeners for the display failed");
                Log.w(TAG, "RegisterListeners for the display failed", e);
            } catch (RemoteException e) {
                Log.e(TAG, "RegisterListeners caught a RemoteException", e);
                return;
            }
        }

        TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
    }
@@ -251,18 +245,17 @@ public class RotationButtonController {
        mListenersRegistered = false;

        mContext.unregisterReceiver(mDockedReceiver);
        if (mRotationWatcherRegistered) {
            try {
            WindowManagerGlobal.getWindowManagerService().removeRotationWatcher(mRotationWatcher);
                WindowManagerGlobal.getWindowManagerService().removeRotationWatcher(
                        mRotationWatcher);
            } catch (RemoteException e) {
                Log.e(TAG, "UnregisterListeners caught a RemoteException", e);
                return;
            }

        TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
        }

    public void setRotationCallback(Consumer<Integer> watcher) {
        mRotWatcherListener = watcher;
        TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
    }

    public void setRotationLockedAtAngle(int rotationSuggestion) {
@@ -427,6 +420,30 @@ public class RotationButtonController {
        }
    }

    /**
     * Called when the rotation watcher rotation changes, either from the watcher registered
     * internally in this class, or a signal propagated from NavBarHelper.
     */
    public void onRotationWatcherChanged(int rotation) {
        if (!mListenersRegistered) {
            // Ignore if not registered
            return;
        }

        // If the screen rotation changes while locked, potentially update lock to flow with
        // new screen rotation and hide any showing suggestions.
        boolean rotationLocked = isRotationLocked();
        // The isVisible check makes the rotation button disappear when we are not locked
        // (e.g. for tabletop auto-rotate).
        if (rotationLocked || mRotationButton.isVisible()) {
            // Do not allow a change in rotation to set user rotation when docked.
            if (shouldOverrideUserLockPrefs(rotation) && rotationLocked && !mDocked) {
                setRotationLockedAtAngle(rotation);
            }
            setRotateSuggestionButtonState(false /* visible */, true /* forced */);
        }
    }

    public void onDisable2FlagChanged(int state2) {
        final boolean rotateSuggestionsDisabled = hasDisable2RotateSuggestionFlag(state2);
        if (rotateSuggestionsDisabled) onRotationSuggestionsDisabled();
+22 −12
Original line number Diff line number Diff line
@@ -41,8 +41,8 @@ import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_DISMISS_BOUNCER
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -60,7 +60,9 @@ import javax.inject.Provider
 * The ripple uses the accent color of the current theme.
 */
@CentralSurfacesScope
class AuthRippleController @Inject constructor(
class AuthRippleController
@Inject
constructor(
    private val centralSurfaces: CentralSurfaces,
    private val sysuiContext: Context,
    private val authController: AuthController,
@@ -70,18 +72,18 @@ class AuthRippleController @Inject constructor(
    private val wakefulnessLifecycle: WakefulnessLifecycle,
    private val commandRegistry: CommandRegistry,
    private val notificationShadeWindowController: NotificationShadeWindowController,
    private val bypassController: KeyguardBypassController,
    private val biometricUnlockController: BiometricUnlockController,
    private val udfpsControllerProvider: Provider<UdfpsController>,
    private val statusBarStateController: StatusBarStateController,
    private val featureFlags: FeatureFlags,
    private val logger: KeyguardLogger,
    rippleView: AuthRippleView?
) : ViewController<AuthRippleView>(rippleView), KeyguardStateController.Callback,
) :
    ViewController<AuthRippleView>(rippleView),
    KeyguardStateController.Callback,
    WakefulnessLifecycle.Observer {

    @VisibleForTesting
    internal var startLightRevealScrimOnKeyguardFadingAway = false
    @VisibleForTesting internal var startLightRevealScrimOnKeyguardFadingAway = false
    var lightRevealScrimAnimator: ValueAnimator? = null
    var fingerprintSensorLocation: Point? = null
    private var faceSensorLocation: Point? = null
@@ -90,6 +92,16 @@ class AuthRippleController @Inject constructor(
    private var udfpsController: UdfpsController? = null
    private var udfpsRadius: Float = -1f

    private val biometricModeListener = object : BiometricUnlockController.BiometricModeListener {
        override fun onModeChanged(mode: Int) {
            // isBiometricUnlock does not cover the scenario when biometrics unlocks
            // the device while the bouncer is showing.
            if (biometricUnlockController.isBiometricUnlock || mode == MODE_DISMISS_BOUNCER) {
                showUnlockRipple(biometricUnlockController.biometricType)
            }
        }
    }

    override fun onInit() {
        mView.setAlphaInDuration(sysuiContext.resources.getInteger(
                R.integer.auth_ripple_alpha_in_duration).toLong())
@@ -106,6 +118,7 @@ class AuthRippleController @Inject constructor(
        keyguardStateController.addCallback(this)
        wakefulnessLifecycle.addObserver(this)
        commandRegistry.registerCommand("auth-ripple") { AuthRippleCommand() }
        biometricUnlockController.addBiometricModeListener(biometricModeListener)
    }

    @VisibleForTesting
@@ -117,6 +130,7 @@ class AuthRippleController @Inject constructor(
        keyguardStateController.removeCallback(this)
        wakefulnessLifecycle.removeObserver(this)
        commandRegistry.unregisterCommand("auth-ripple")
        biometricUnlockController.removeBiometricModeListener(biometricModeListener)

        notificationShadeWindowController.setForcePluginOpen(false, this)
    }
@@ -147,9 +161,6 @@ class AuthRippleController @Inject constructor(
                showUnlockedRipple()
            }
        } else if (biometricSourceType == BiometricSourceType.FACE) {
            if (!bypassController.canBypass() && !authController.isUdfpsFingerDown) {
                return
            }
             faceSensorLocation?.let {
                mView.setSensorLocation(it)
                circleReveal = CircleReveal(
@@ -271,7 +282,6 @@ class AuthRippleController @Inject constructor(
                if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
                    mView.fadeDwellRipple()
                }
                showUnlockRipple(biometricSourceType)
            }

        override fun onBiometricAuthFailed(biometricSourceType: BiometricSourceType) {
Loading