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

Commit 4f5d03fc authored by Hao Dong's avatar Hao Dong
Browse files

Fix logo res not found with systemui context

Flag: android.hardware.biometrics.custom_biometric_prompt
Bug: 341697368
Test: atest BiometricPromptRequestTest
Test: atest PromptViewModelTest
Test: Manual test on test app

Change-Id: I2e8f5023ab70a9061c6ab25cc4ce423ed64d2de6
parent 8e4d3fdc
Loading
Loading
Loading
Loading
+38 −2
Original line number Original line Diff line number Diff line
@@ -38,6 +38,9 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Binder;
import android.os.Binder;
@@ -193,7 +196,11 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
        @RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED)
        @RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED)
        @NonNull
        @NonNull
        public BiometricPrompt.Builder setLogoRes(@DrawableRes int logoRes) {
        public BiometricPrompt.Builder setLogoRes(@DrawableRes int logoRes) {
            mPromptInfo.setLogoRes(logoRes);
            if (mPromptInfo.getLogoBitmap() != null) {
                throw new IllegalStateException(
                        "Exclusively one of logo resource or logo bitmap can be set");
            }
            mPromptInfo.setLogo(logoRes, convertDrawableToBitmap(mContext.getDrawable(logoRes)));
            return this;
            return this;
        }
        }


@@ -212,7 +219,11 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
        @RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED)
        @RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED)
        @NonNull
        @NonNull
        public BiometricPrompt.Builder setLogoBitmap(@NonNull Bitmap logoBitmap) {
        public BiometricPrompt.Builder setLogoBitmap(@NonNull Bitmap logoBitmap) {
            mPromptInfo.setLogoBitmap(logoBitmap);
            if (mPromptInfo.getLogoRes() != -1) {
                throw new IllegalStateException(
                        "Exclusively one of logo resource or logo bitmap can be set");
            }
            mPromptInfo.setLogo(-1, logoBitmap);
            return this;
            return this;
        }
        }


@@ -1516,4 +1527,29 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
    private static boolean isCredentialAllowed(@Authenticators.Types int allowedAuthenticators) {
    private static boolean isCredentialAllowed(@Authenticators.Types int allowedAuthenticators) {
        return (allowedAuthenticators & Authenticators.DEVICE_CREDENTIAL) != 0;
        return (allowedAuthenticators & Authenticators.DEVICE_CREDENTIAL) != 0;
    }
    }

    /** Converts {@code drawable} to a {@link Bitmap}. */
    private static Bitmap convertDrawableToBitmap(Drawable drawable) {
        if (drawable == null) {
            return null;
        }

        if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable) drawable).getBitmap();
        }

        Bitmap bitmap;
        if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
            bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
            // Single color bitmap will be created of 1x1 pixel
        } else {
            bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
                    drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        }

        final Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);
        return bitmap;
    }
}
}
+26 −13
Original line number Original line Diff line number Diff line
@@ -217,14 +217,17 @@ public class PromptInfo implements Parcelable {
    // LINT.ThenChange(frameworks/base/core/java/android/hardware/biometrics/BiometricPrompt.java)
    // LINT.ThenChange(frameworks/base/core/java/android/hardware/biometrics/BiometricPrompt.java)


    // Setters
    // Setters
    public void setLogoRes(@DrawableRes int logoRes) {
        mLogoRes = logoRes;
        checkOnlyOneLogoSet();
    }


    public void setLogoBitmap(@NonNull Bitmap logoBitmap) {
    /**
     * Sets logo res and bitmap
     *
     * @param logoRes    The logo res set by the app; Or -1 if the app sets bitmap directly.
     * @param logoBitmap The bitmap from logoRes if the app sets logoRes; Or the bitmap set by the
     *                   app directly.
     */
    public void setLogo(@DrawableRes int logoRes, @NonNull Bitmap logoBitmap) {
        mLogoRes = logoRes;
        mLogoBitmap = logoBitmap;
        mLogoBitmap = logoBitmap;
        checkOnlyOneLogoSet();
    }
    }


    public void setLogoDescription(@NonNull String logoDescription) {
    public void setLogoDescription(@NonNull String logoDescription) {
@@ -326,13 +329,29 @@ public class PromptInfo implements Parcelable {
    }
    }


    // Getters
    // Getters

    /**
     * Returns the logo bitmap either from logo resource or bitmap passed in from the app.
     */
    public Bitmap getLogo() {
        return mLogoBitmap;
    }

    /**
     * Returns the logo res set by the app.
     */
    @DrawableRes
    @DrawableRes
    public int getLogoRes() {
    public int getLogoRes() {
        return mLogoRes;
        return mLogoRes;
    }
    }


    /**
     * Returns the logo bitmap set by the app.
     */
    public Bitmap getLogoBitmap() {
    public Bitmap getLogoBitmap() {
        return mLogoBitmap;
        // If mLogoRes has been set, return null since mLogoBitmap is from the res, but not from
        // the app directly.
        return mLogoRes == -1 ? mLogoBitmap : null;
    }
    }


    public String getLogoDescription() {
    public String getLogoDescription() {
@@ -436,10 +455,4 @@ public class PromptInfo implements Parcelable {
        return mComponentNameForConfirmDeviceCredentialActivity;
        return mComponentNameForConfirmDeviceCredentialActivity;
    }
    }


    private void checkOnlyOneLogoSet() {
        if (mLogoRes != -1 && mLogoBitmap != null) {
            throw new IllegalStateException(
                    "Exclusively one of logo resource or logo bitmap can be set");
        }
    }
}
}
+3 −2
Original line number Original line Diff line number Diff line
@@ -131,8 +131,9 @@ internal fun promptInfo(
    negativeButton: String = "neg",
    negativeButton: String = "neg",
): PromptInfo {
): PromptInfo {
    val info = PromptInfo()
    val info = PromptInfo()
    info.logoRes = logoRes
    if (logoBitmap != null) {
    info.logoBitmap = logoBitmap
        info.setLogo(logoRes, logoBitmap)
    }
    info.logoDescription = logoDescription
    info.logoDescription = logoDescription
    info.title = title
    info.title = title
    info.subtitle = subtitle
    info.subtitle = subtitle
+26 −0
Original line number Original line Diff line number Diff line
@@ -25,7 +25,11 @@ import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
import android.content.Context
import android.content.Context
import android.content.pm.PackageManager
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Insets
import android.graphics.Insets
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.hardware.biometrics.BiometricManager.Authenticators
import android.hardware.biometrics.BiometricManager.Authenticators
import android.hardware.biometrics.PromptInfo
import android.hardware.biometrics.PromptInfo
import android.hardware.biometrics.SensorPropertiesInternal
import android.hardware.biometrics.SensorPropertiesInternal
@@ -122,4 +126,26 @@ object Utils {
        return windowMetrics?.windowInsets?.getInsets(WindowInsets.Type.navigationBars())
        return windowMetrics?.windowInsets?.getInsets(WindowInsets.Type.navigationBars())
            ?: Insets.NONE
            ?: Insets.NONE
    }
    }

    /** Converts `drawable` to a [Bitmap]. */
    @JvmStatic
    fun Drawable?.toBitmap(): Bitmap? {
        if (this == null) {
            return null
        }
        if (this is BitmapDrawable) {
            return bitmap
        }
        val bitmap: Bitmap =
            if (intrinsicWidth <= 0 || intrinsicHeight <= 0) {
                Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
                // Single color bitmap will be created of 1x1 pixel
            } else {
                Bitmap.createBitmap(intrinsicWidth, intrinsicHeight, Bitmap.Config.ARGB_8888)
            }
        val canvas = Canvas(bitmap)
        setBounds(0, 0, canvas.width, canvas.height)
        draw(canvas)
        return bitmap
    }
}
}
+1 −2
Original line number Original line Diff line number Diff line
@@ -40,8 +40,7 @@ sealed class BiometricPromptRequest(
            operationInfo = operationInfo,
            operationInfo = operationInfo,
            showEmergencyCallButton = info.isShowEmergencyCallButton
            showEmergencyCallButton = info.isShowEmergencyCallButton
        ) {
        ) {
        val logoRes: Int = info.logoRes
        val logoBitmap: Bitmap? = info.logo
        val logoBitmap: Bitmap? = info.logoBitmap
        val logoDescription: String? = info.logoDescription
        val logoDescription: String? = info.logoDescription
        val negativeButtonText: String = info.negativeButtonText?.toString() ?: ""
        val negativeButtonText: String = info.negativeButtonText?.toString() ?: ""
        val componentNameForConfirmDeviceCredentialActivity: ComponentName? =
        val componentNameForConfirmDeviceCredentialActivity: ComponentName? =
Loading