/* * 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.systemui.biometrics import android.Manifest import android.annotation.IntDef import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_MANAGED import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING import android.content.Context import android.content.pm.PackageManager import android.graphics.Insets import android.hardware.biometrics.BiometricManager.Authenticators import android.hardware.biometrics.PromptInfo import android.hardware.biometrics.SensorPropertiesInternal import android.os.UserManager import android.util.DisplayMetrics import android.view.ViewGroup import android.view.WindowInsets import android.view.WindowManager import android.view.WindowMetrics import android.view.accessibility.AccessibilityEvent import android.view.accessibility.AccessibilityManager import com.android.internal.widget.LockPatternUtils import java.lang.annotation.Retention import java.lang.annotation.RetentionPolicy object Utils { const val CREDENTIAL_PIN = 1 const val CREDENTIAL_PATTERN = 2 const val CREDENTIAL_PASSWORD = 3 /** Base set of layout flags for fingerprint overlay widgets. */ const val FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS = (WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) @JvmStatic fun dpToPixels(context: Context, dp: Float): Float { val density = context.resources.displayMetrics.densityDpi.toFloat() return dp * (density / DisplayMetrics.DENSITY_DEFAULT) } /** * Note: Talkback 14.0 has new rate-limitation design to reduce frequency * of TYPE_WINDOW_CONTENT_CHANGED events to once every 30 seconds. * (context: b/281765653#comment18) * Using {@link View#announceForAccessibility} instead as workaround when sending events * exceeding this frequency is required. */ @JvmStatic fun notifyAccessibilityContentChanged(am: AccessibilityManager, view: ViewGroup) { if (!am.isEnabled) { return } val event = AccessibilityEvent.obtain() event.eventType = AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED event.contentChangeTypes = AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE view.sendAccessibilityEventUnchecked(event) view.notifySubtreeAccessibilityStateChanged( view, view, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE ) } @JvmStatic fun isDeviceCredentialAllowed(promptInfo: PromptInfo): Boolean = (promptInfo.authenticators and Authenticators.DEVICE_CREDENTIAL) != 0 @JvmStatic fun isBiometricAllowed(promptInfo: PromptInfo): Boolean = (promptInfo.authenticators and Authenticators.BIOMETRIC_WEAK) != 0 @JvmStatic @CredentialType fun getCredentialType(utils: LockPatternUtils, userId: Int): Int = when (utils.getKeyguardStoredPasswordQuality(userId)) { PASSWORD_QUALITY_SOMETHING -> CREDENTIAL_PATTERN PASSWORD_QUALITY_NUMERIC, PASSWORD_QUALITY_NUMERIC_COMPLEX -> CREDENTIAL_PIN PASSWORD_QUALITY_ALPHABETIC, PASSWORD_QUALITY_ALPHANUMERIC, PASSWORD_QUALITY_COMPLEX, PASSWORD_QUALITY_MANAGED -> CREDENTIAL_PASSWORD else -> CREDENTIAL_PASSWORD } @JvmStatic fun isManagedProfile(context: Context, userId: Int): Boolean = context.getSystemService(UserManager::class.java)?.isManagedProfile(userId) ?: false @JvmStatic fun <T : SensorPropertiesInternal> findFirstSensorProperties( properties: List<T>?, sensorIds: IntArray ): T? = properties?.firstOrNull { sensorIds.contains(it.sensorId) } @JvmStatic fun isSystem(context: Context, clientPackage: String?): Boolean { val hasPermission = (context.checkCallingOrSelfPermission(Manifest.permission.USE_BIOMETRIC_INTERNAL) == PackageManager.PERMISSION_GRANTED) return hasPermission && "android" == clientPackage } @JvmStatic fun getNavbarInsets(context: Context): Insets { val windowManager: WindowManager? = context.getSystemService(WindowManager::class.java) val windowMetrics: WindowMetrics? = windowManager?.maximumWindowMetrics return windowMetrics?.windowInsets?.getInsets(WindowInsets.Type.navigationBars()) ?: Insets.NONE } @Retention(RetentionPolicy.SOURCE) @IntDef(CREDENTIAL_PIN, CREDENTIAL_PATTERN, CREDENTIAL_PASSWORD) internal annotation class CredentialType }