diff options
13 files changed, 419 insertions, 255 deletions
diff --git a/packages/SystemUI/res/layout-land/auth_credential_password_pin_content_view.xml b/packages/SystemUI/res/layout-land/auth_credential_password_pin_content_view.xml new file mode 100644 index 000000000000..24222f7642be --- /dev/null +++ b/packages/SystemUI/res/layout-land/auth_credential_password_pin_content_view.xml @@ -0,0 +1,101 @@ +<!-- + ~ 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. + --> + +<merge xmlns:android="http://schemas.android.com/apk/res/android"> + + <RelativeLayout + android:id="@+id/auth_credential_header" + style="?headerStyle" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1"> + + <ImageView + android:id="@+id/icon" + style="?headerIconStyle" + android:layout_alignParentLeft="true" + android:layout_alignParentTop="true" + android:contentDescription="@null"/> + + <TextView + android:id="@+id/title" + style="?titleTextAppearance" + android:layout_below="@id/icon" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + + <TextView + android:id="@+id/subtitle" + style="?subTitleTextAppearance" + android:layout_below="@id/title" + android:layout_alignParentLeft="true" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + + <TextView + android:id="@+id/description" + style="?descriptionTextAppearance" + android:layout_below="@id/subtitle" + android:layout_alignParentLeft="true" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + + </RelativeLayout> + + <FrameLayout + android:id="@+id/auth_credential_input" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:orientation="vertical"> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:orientation="vertical"> + + <ImeAwareEditText + android:id="@+id/lockPassword" + style="?passwordTextAppearance" + android:layout_width="208dp" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:imeOptions="actionNext|flagNoFullscreen|flagForceAscii" + android:inputType="textPassword" + android:minHeight="48dp"/> + + <TextView + android:id="@+id/error" + style="?errorTextAppearance" + android:layout_gravity="center_horizontal" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> + </LinearLayout> + + <Button + android:id="@+id/emergencyCallButton" + style="@style/AuthCredentialEmergencyButtonStyle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone" + android:layout_gravity="center_horizontal|bottom" + android:layout_marginTop="12dp" + android:layout_marginBottom="12dp" + android:text="@string/work_challenge_emergency_button_text"/> + </FrameLayout> + +</merge> diff --git a/packages/SystemUI/res/layout-land/auth_credential_password_view.xml b/packages/SystemUI/res/layout-land/auth_credential_password_view.xml index e439f775f8ea..8ac7583088f9 100644 --- a/packages/SystemUI/res/layout-land/auth_credential_password_view.xml +++ b/packages/SystemUI/res/layout-land/auth_credential_password_view.xml @@ -23,84 +23,6 @@ android:elevation="@dimen/biometric_dialog_elevation" android:theme="?app:attr/lockPinPasswordStyle"> - <RelativeLayout - android:id="@+id/auth_credential_header" - style="?headerStyle" - android:layout_width="wrap_content" - android:layout_height="match_parent"> - - <ImageView - android:id="@+id/icon" - style="?headerIconStyle" - android:layout_alignParentLeft="true" - android:layout_alignParentTop="true" - android:contentDescription="@null"/> - - <TextView - android:id="@+id/title" - style="?titleTextAppearance" - android:layout_below="@id/icon" - android:layout_width="match_parent" - android:layout_height="wrap_content" /> - - <TextView - android:id="@+id/subtitle" - style="?subTitleTextAppearance" - android:layout_below="@id/title" - android:layout_alignParentLeft="true" - android:layout_width="match_parent" - android:layout_height="wrap_content" /> - - <TextView - android:id="@+id/description" - style="?descriptionTextAppearance" - android:layout_below="@id/subtitle" - android:layout_alignParentLeft="true" - android:layout_width="match_parent" - android:layout_height="wrap_content" /> - - </RelativeLayout> - - <FrameLayout - android:id="@+id/auth_credential_input" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - - <LinearLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal|top" - android:orientation="vertical"> - - <ImeAwareEditText - android:id="@+id/lockPassword" - style="?passwordTextAppearance" - android:layout_width="208dp" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:imeOptions="actionNext|flagNoFullscreen|flagForceAscii" - android:inputType="textPassword" - android:minHeight="48dp"/> - - <TextView - android:id="@+id/error" - style="?errorTextAppearance" - android:layout_gravity="center_horizontal" - android:layout_width="wrap_content" - android:layout_height="wrap_content"/> - </LinearLayout> - - <Button - android:id="@+id/emergencyCallButton" - style="@style/AuthCredentialEmergencyButtonStyle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:visibility="gone" - android:layout_gravity="center_horizontal|bottom" - android:layout_marginTop="12dp" - android:layout_marginBottom="12dp" - android:text="@string/work_challenge_emergency_button_text"/> - </FrameLayout> + <include layout="@layout/auth_credential_password_pin_content_view" /> </com.android.systemui.biometrics.ui.CredentialPasswordView>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout-land/auth_credential_pin_view.xml b/packages/SystemUI/res/layout-land/auth_credential_pin_view.xml new file mode 100644 index 000000000000..8ac7583088f9 --- /dev/null +++ b/packages/SystemUI/res/layout-land/auth_credential_pin_view.xml @@ -0,0 +1,28 @@ +<!-- + ~ Copyright (C) 2020 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. + --> + +<com.android.systemui.biometrics.ui.CredentialPasswordView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal" + android:elevation="@dimen/biometric_dialog_elevation" + android:theme="?app:attr/lockPinPasswordStyle"> + + <include layout="@layout/auth_credential_password_pin_content_view" /> + +</com.android.systemui.biometrics.ui.CredentialPasswordView>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/auth_credential_password_pin_content_view.xml b/packages/SystemUI/res/layout/auth_credential_password_pin_content_view.xml new file mode 100644 index 000000000000..11284fd2237b --- /dev/null +++ b/packages/SystemUI/res/layout/auth_credential_password_pin_content_view.xml @@ -0,0 +1,104 @@ +<!-- + ~ 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. + --> + +<merge xmlns:android="http://schemas.android.com/apk/res/android"> + + <ScrollView + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <RelativeLayout + android:id="@+id/auth_credential_header" + style="?headerStyle" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingBottom="0dp"> + + <ImageView + android:id="@+id/icon" + style="?headerIconStyle" + android:layout_alignParentLeft="true" + android:layout_alignParentTop="true" + android:contentDescription="@null" /> + + <TextView + android:id="@+id/title" + style="?titleTextAppearance" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/icon" /> + + <TextView + android:id="@+id/subtitle" + style="?subTitleTextAppearance" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/title" /> + + <TextView + android:id="@+id/description" + style="?descriptionTextAppearance" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/subtitle" /> + + </RelativeLayout> + + </ScrollView> + + <FrameLayout + android:id="@+id/auth_credential_input" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:orientation="vertical"> + + <ImeAwareEditText + android:id="@+id/lockPassword" + style="?passwordTextAppearance" + android:layout_width="208dp" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:imeOptions="actionNext|flagNoFullscreen|flagForceAscii" + android:inputType="textPassword" + android:minHeight="48dp"/> + + <TextView + android:id="@+id/error" + style="?errorTextAppearance" + android:layout_gravity="center_horizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> + </LinearLayout> + + <Button + android:id="@+id/emergencyCallButton" + style="@style/AuthCredentialEmergencyButtonStyle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone" + android:layout_gravity="center_horizontal|bottom" + android:layout_marginTop="12dp" + android:layout_marginBottom="12dp" + android:text="@string/work_challenge_emergency_button_text"/> + </FrameLayout> + +</merge> diff --git a/packages/SystemUI/res/layout/auth_credential_password_view.xml b/packages/SystemUI/res/layout/auth_credential_password_view.xml index 9336845f20f7..f8d9a87d5e54 100644 --- a/packages/SystemUI/res/layout/auth_credential_password_view.xml +++ b/packages/SystemUI/res/layout/auth_credential_password_view.xml @@ -23,88 +23,6 @@ android:orientation="vertical" android:theme="?app:attr/lockPinPasswordStyle"> - <ScrollView - android:id="@+id/auth_credential_header" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - - <RelativeLayout - style="?headerStyle" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - - <ImageView - android:id="@+id/icon" - style="?headerIconStyle" - android:layout_alignParentLeft="true" - android:layout_alignParentTop="true" - android:contentDescription="@null" /> - - <TextView - android:id="@+id/title" - style="?titleTextAppearance" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_below="@id/icon" /> - - <TextView - android:id="@+id/subtitle" - style="?subTitleTextAppearance" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_below="@id/title" /> - - <TextView - android:id="@+id/description" - style="?descriptionTextAppearance" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_below="@id/subtitle" /> - - </RelativeLayout> - - </ScrollView> - - <FrameLayout - android:id="@+id/auth_credential_input" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal|top" - android:orientation="vertical"> - - <ImeAwareEditText - android:id="@+id/lockPassword" - style="?passwordTextAppearance" - android:layout_width="208dp" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:imeOptions="actionNext|flagNoFullscreen|flagForceAscii" - android:inputType="textPassword" - android:minHeight="48dp"/> - - <TextView - android:id="@+id/error" - style="?errorTextAppearance" - android:layout_gravity="center_horizontal" - android:layout_width="match_parent" - android:layout_height="wrap_content"/> - </LinearLayout> - - <Button - android:id="@+id/emergencyCallButton" - style="@style/AuthCredentialEmergencyButtonStyle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:visibility="gone" - android:layout_gravity="center_horizontal|bottom" - android:layout_marginTop="12dp" - android:layout_marginBottom="12dp" - android:text="@string/work_challenge_emergency_button_text"/> - </FrameLayout> + <include layout="@layout/auth_credential_password_pin_content_view" /> </com.android.systemui.biometrics.ui.CredentialPasswordView>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/auth_credential_pin_view.xml b/packages/SystemUI/res/layout/auth_credential_pin_view.xml new file mode 100644 index 000000000000..a1cf807af088 --- /dev/null +++ b/packages/SystemUI/res/layout/auth_credential_pin_view.xml @@ -0,0 +1,28 @@ +<!-- + ~ 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. + --> + +<com.android.systemui.biometrics.ui.CredentialPasswordView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:elevation="@dimen/biometric_dialog_elevation" + android:orientation="vertical" + android:theme="?app:attr/lockPinPasswordStyle"> + + <include layout="@layout/auth_credential_password_pin_content_view" /> + +</com.android.systemui.biometrics.ui.CredentialPasswordView>
\ No newline at end of file diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml index fd1de25e8174..04eae64013b3 100644 --- a/packages/SystemUI/res/values/ids.xml +++ b/packages/SystemUI/res/values/ids.xml @@ -223,6 +223,9 @@ <!-- Communal mode --> <item type="id" name="communal_widget_wrapper" /> + <!-- Values assigned to the views in Biometrics Prompt --> + <item type="id" name="pin_pad"/> + <!-- Used to tag views programmatically added to the smartspace area so they can be more easily removed later. diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java index 802a550c4d29..7464c8803c99 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java @@ -499,6 +499,8 @@ public class AuthContainerView extends LinearLayout R.layout.auth_credential_pattern_view, null, false); break; case Utils.CREDENTIAL_PIN: + mCredentialView = factory.inflate(R.layout.auth_credential_pin_view, null, false); + break; case Utils.CREDENTIAL_PASSWORD: mCredentialView = factory.inflate( R.layout.auth_credential_password_view, null, false); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPasswordView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPasswordView.kt index 709fe855fbfc..6c5cc4835787 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPasswordView.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPasswordView.kt @@ -8,11 +8,8 @@ import android.view.View import android.view.WindowInsets import android.view.WindowInsets.Type.ime import android.view.accessibility.AccessibilityManager -import android.widget.ImageView -import android.widget.ImeAwareEditText import android.widget.LinearLayout import android.widget.TextView -import androidx.core.view.isGone import com.android.systemui.R import com.android.systemui.biometrics.AuthPanelController import com.android.systemui.biometrics.ui.binder.CredentialViewBinder @@ -22,14 +19,6 @@ import com.android.systemui.biometrics.ui.viewmodel.CredentialViewModel class CredentialPasswordView(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs), CredentialView, View.OnApplyWindowInsetsListener { - private lateinit var titleView: TextView - private lateinit var subtitleView: TextView - private lateinit var descriptionView: TextView - private lateinit var iconView: ImageView - private lateinit var passwordField: ImeAwareEditText - private lateinit var credentialHeader: View - private lateinit var credentialInput: View - private var bottomInset: Int = 0 private val accessibilityManager by lazy { @@ -48,90 +37,32 @@ class CredentialPasswordView(context: Context, attrs: AttributeSet?) : override fun onFinishInflate() { super.onFinishInflate() - - titleView = requireViewById(R.id.title) - subtitleView = requireViewById(R.id.subtitle) - descriptionView = requireViewById(R.id.description) - iconView = requireViewById(R.id.icon) - passwordField = requireViewById(R.id.lockPassword) - credentialHeader = requireViewById(R.id.auth_credential_header) - credentialInput = requireViewById(R.id.auth_credential_input) - setOnApplyWindowInsetsListener(this) } - override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) { - super.onLayout(changed, left, top, right, bottom) - - val inputLeftBound: Int - var inputTopBound: Int - var headerRightBound = right - var headerTopBounds = top - var headerBottomBounds = bottom - val subTitleBottom: Int = if (subtitleView.isGone) titleView.bottom else subtitleView.bottom - val descBottom = if (descriptionView.isGone) subTitleBottom else descriptionView.bottom - if (resources.configuration.orientation == ORIENTATION_LANDSCAPE) { - inputTopBound = (bottom - credentialInput.height) / 2 - inputLeftBound = (right - left) / 2 - headerRightBound = inputLeftBound - if (descriptionView.bottom > headerBottomBounds) { - headerTopBounds -= iconView.bottom.coerceAtMost(bottomInset) - credentialHeader.layout(left, headerTopBounds, headerRightBound, bottom) - } - } else { - inputTopBound = descBottom + (bottom - descBottom - credentialInput.height) / 2 - inputLeftBound = (right - left - credentialInput.width) / 2 - - if (bottom - inputTopBound < credentialInput.height) { - inputTopBound = bottom - credentialInput.height - } - - if (descriptionView.bottom > inputTopBound) { - credentialHeader.layout(left, headerTopBounds, headerRightBound, inputTopBound) - } - } - - credentialInput.layout(inputLeftBound, inputTopBound, right, bottom) - } - - override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec) - - val newWidth = MeasureSpec.getSize(widthMeasureSpec) - val newHeight = MeasureSpec.getSize(heightMeasureSpec) - bottomInset - - setMeasuredDimension(newWidth, newHeight) - - val halfWidthSpec = MeasureSpec.makeMeasureSpec(width / 2, MeasureSpec.AT_MOST) - val fullHeightSpec = MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.UNSPECIFIED) - if (resources.configuration.orientation == ORIENTATION_LANDSCAPE) { - measureChildren(halfWidthSpec, fullHeightSpec) - } else { - measureChildren(widthMeasureSpec, fullHeightSpec) - } - } - override fun onApplyWindowInsets(v: View, insets: WindowInsets): WindowInsets { - val bottomInsets = insets.getInsets(ime()) - if (bottomInset != bottomInsets.bottom) { - bottomInset = bottomInsets.bottom - - if (bottomInset > 0 && resources.configuration.orientation == ORIENTATION_LANDSCAPE) { - titleView.isSingleLine = true - titleView.ellipsize = TextUtils.TruncateAt.MARQUEE - titleView.marqueeRepeatLimit = -1 - // select to enable marquee unless a screen reader is enabled - titleView.isSelected = accessibilityManager?.shouldMarquee() ?: false - } else { - titleView.isSingleLine = false - titleView.ellipsize = null - // select to enable marquee unless a screen reader is enabled - titleView.isSelected = false + val imeBottomInset = insets.getInsets(ime()).bottom + if (bottomInset != imeBottomInset) { + val titleView: TextView? = findViewById(R.id.title) + if (titleView != null) { + if ( + bottomInset > 0 && resources.configuration.orientation == ORIENTATION_LANDSCAPE + ) { + titleView.isSingleLine = true + titleView.ellipsize = TextUtils.TruncateAt.MARQUEE + titleView.marqueeRepeatLimit = -1 + // select to enable marquee unless a screen reader is enabled + titleView.isSelected = accessibilityManager.shouldMarquee() + } else { + titleView.isSingleLine = false + titleView.ellipsize = null + // select to enable marquee unless a screen reader is enabled + titleView.isSelected = false + } } - - requestLayout() } - return insets + setPadding(paddingLeft, paddingTop, paddingRight, imeBottomInset) + return insets.inset(0, 0, 0, imeBottomInset) } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/IPinPad.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/IPinPad.kt new file mode 100644 index 000000000000..cf6865c0fe8e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/IPinPad.kt @@ -0,0 +1,42 @@ +/* + * 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.systemui.biometrics.ui + +/** + * Interface for PinPad in auth_credential_pin_view. This is needed when a custom pin pad is + * preferred to the IME To use a PinPad, one needs to implement IPinPad interface and provide it in + * auth_credential_pin_view and specify the id as [pin_pad] + */ +interface IPinPad { + fun setPinPadClickListener(pinPadClickListener: PinPadClickListener) +} + +/** The call back interface for onClick event in the view. */ +interface PinPadClickListener { + /** + * One of the digit key has been clicked. + * + * @param digit A String representing a digit between 0 and 9. + */ + fun onDigitKeyClick(digit: String?) + + /** The backspace key has been clicked. */ + fun onBackspaceClick() + + /** The enter key has been clicked. */ + fun onEnterKeyClick() +} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialPasswordViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialPasswordViewBinder.kt index c27d71522c2f..996b62e084cb 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialPasswordViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialPasswordViewBinder.kt @@ -15,6 +15,7 @@ import androidx.lifecycle.repeatOnLifecycle import com.android.systemui.R import com.android.systemui.biometrics.ui.CredentialPasswordView import com.android.systemui.biometrics.ui.CredentialView +import com.android.systemui.biometrics.ui.IPinPad import com.android.systemui.biometrics.ui.viewmodel.CredentialViewModel import com.android.systemui.lifecycle.repeatWhenAttached import kotlinx.coroutines.awaitCancellation @@ -53,13 +54,19 @@ object CredentialPasswordViewBinder { } ) passwordField.setOnKeyListener(OnBackButtonListener(onBackInvokedCallback)) - + val pinPadView = view.findViewById(R.id.pin_pad) as? IPinPad + if (pinPadView != null) { + PinPadViewBinder.bind(pinPadView, view) + } repeatOnLifecycle(Lifecycle.State.STARTED) { // dismiss on a valid credential check launch { viewModel.validatedAttestation.collect { attestation -> if (attestation != null) { - imeManager.hideSoftInputFromWindow(view.windowToken, 0 /* flags */) + imeManager.hideSoftInputFromWindow( + view.windowToken, + 0 // flag + ) host.onCredentialMatched(attestation) } else { passwordField.setText("") diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialViewBinder.kt index 4ac9f967920f..25fe61916644 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialViewBinder.kt @@ -47,6 +47,7 @@ object CredentialViewBinder { val descriptionView: TextView = view.requireViewById(R.id.description) val iconView: ImageView? = view.findViewById(R.id.icon) val errorView: TextView = view.requireViewById(R.id.error) + val cancelButton: Button? = view.findViewById(R.id.cancel_button) val emergencyButtonView: Button = view.requireViewById(R.id.emergencyCallButton) var errorTimer: Job? = null @@ -60,7 +61,7 @@ object CredentialViewBinder { updateForContentDimensions( containerWidth, containerHeight, - 0 /* animateDurationMs */ + 0 // animateDurationMs ) } } @@ -103,7 +104,18 @@ object CredentialViewBinder { } } } - .collect { errorView.textOrHide = it } + .collect { it -> + val hasError = !it.isNullOrBlank() + errorView.visibility = + if (hasError) { + View.VISIBLE + } else if (cancelButton != null) { + View.INVISIBLE + } else { + View.GONE + } + errorView.text = if (hasError) it else "" + } } // show an extra dialog if the remaining attempts becomes low @@ -117,6 +129,8 @@ object CredentialViewBinder { } } + cancelButton?.setOnClickListener { host.onCredentialAborted() } + // bind the auth widget when (view) { is CredentialPasswordView -> diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PinPadViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PinPadViewBinder.kt new file mode 100644 index 000000000000..906206c27455 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PinPadViewBinder.kt @@ -0,0 +1,64 @@ +/* + * 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.systemui.biometrics.ui.binder + +import android.view.KeyEvent +import android.widget.ImeAwareEditText +import com.android.internal.widget.LockscreenCredential +import com.android.systemui.R +import com.android.systemui.biometrics.ui.CredentialPasswordView +import com.android.systemui.biometrics.ui.IPinPad +import com.android.systemui.biometrics.ui.PinPadClickListener + +/** Binder for IPinPad */ +object PinPadViewBinder { + /** Implements a PinPadClickListener inside a pin pad */ + @JvmStatic + fun bind(view: IPinPad, credentialPasswordView: CredentialPasswordView) { + val passwordField: ImeAwareEditText = + credentialPasswordView.requireViewById(R.id.lockPassword) + view.setPinPadClickListener( + object : PinPadClickListener { + + override fun onDigitKeyClick(digit: String?) { + passwordField.append(digit) + } + + override fun onBackspaceClick() { + val pin = LockscreenCredential.createPinOrNone(passwordField.text) + if (pin.size() > 0) { + passwordField.text.delete( + passwordField.selectionEnd - 1, + passwordField.selectionEnd + ) + } + pin.zeroize() + } + + override fun onEnterKeyClick() { + passwordField.dispatchKeyEvent( + KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, 0) + ) + passwordField.dispatchKeyEvent( + KeyEvent(0, 0, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0) + ) + } + } + ) + } +} |