Add Fingerprint Dialog to SysUI
Bug: 67497360 Test: Modify settings to use new API Change-Id: I93ef475852c15e4a1a2a54bdd23ae4b8a0b8b7d7
This commit is contained in:
25
packages/SystemUI/res/drawable/fingerprint_dialog_bg.xml
Normal file
25
packages/SystemUI/res/drawable/fingerprint_dialog_bg.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2018 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
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/fingerprint_dialog_bg_color" />
|
||||
<corners android:radius="1dp"
|
||||
android:topLeftRadius="16dp"
|
||||
android:topRightRadius="16dp"
|
||||
android:bottomLeftRadius="0dp"
|
||||
android:bottomRightRadius="0dp"/>
|
||||
</shape>
|
||||
107
packages/SystemUI/res/drawable/fingerprint_icon.xml
Normal file
107
packages/SystemUI/res/drawable/fingerprint_icon.xml
Normal file
@@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2018 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
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="60dp"
|
||||
android:height="60dp"
|
||||
android:viewportWidth="60"
|
||||
android:viewportHeight="60">
|
||||
|
||||
<path
|
||||
android:fillColor="#1A73E8"
|
||||
android:fillType="evenOdd"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M 30 0 C 46.5685424949 0 60 13.4314575051 60 30 C 60 46.5685424949 46.5685424949 60 30 60 C 13.4314575051 60 0 46.5685424949 0 30 C 0 13.4314575051 13.4314575051 0 30 0 Z" />
|
||||
<group
|
||||
android:translateX="17.727273"
|
||||
android:translateY="16.363636">
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M20.3065726,3.44516129 C20.1974817,3.44516129 20.0883908,3.41788856
|
||||
19.9929362,3.36334311 C17.3747544,2.01334311 15.111118,1.44061584
|
||||
12.3974817,1.44061584 C9.69748166,1.44061584 7.1338453,2.08152493
|
||||
4.80202711,3.36334311 C4.47475439,3.54061584 4.06566348,3.41788856
|
||||
3.87475439,3.09061584 C3.69748166,2.76334311 3.82020893,2.34061584
|
||||
4.14748166,2.16334311 C6.6838453,0.786070381 9.46566348,0.0769794721
|
||||
12.3974817,0.0769794721 C15.3020271,0.0769794721 17.8383908,0.717888563
|
||||
20.6202089,2.14970674 C20.961118,2.32697947 21.0838453,2.73607038
|
||||
20.9065726,3.06334311 C20.7838453,3.30879765 20.5520271,3.44516129
|
||||
20.3065726,3.44516129 L20.3065726,3.44516129 Z M0.792936205,10.6042522
|
||||
C0.656572568,10.6042522 0.520208932,10.5633431 0.397481659,10.4815249
|
||||
C0.0838452956,10.2633431 0.0156634774,9.84061584 0.233845296,9.52697947
|
||||
C1.5838453,7.61788856 3.30202711,6.11788856 5.34748166,5.06788856
|
||||
C9.62929984,2.85879765 15.111118,2.84516129 19.4065726,5.0542522
|
||||
C21.4520271,6.1042522 23.1702089,7.59061584 24.5202089,9.48607038
|
||||
C24.7383908,9.78607038 24.6702089,10.222434 24.3565726,10.4406158
|
||||
C24.0429362,10.6587977 23.6202089,10.5906158 23.4020271,10.2769795
|
||||
C22.1747544,8.55879765 20.6202089,7.20879765 18.7792998,6.26788856
|
||||
C14.8656635,4.26334311 9.86111802,4.26334311 5.96111802,6.28152493
|
||||
C4.10657257,7.23607038 2.55202711,8.59970674 1.32475439,10.3178886
|
||||
C1.21566348,10.5087977 1.01111802,10.6042522 0.792936205,10.6042522
|
||||
L0.792936205,10.6042522 Z M9.31566348,27.0633431 C9.13839075,27.0633431
|
||||
8.96111802,26.9951613 8.83839075,26.8587977 C7.65202711,25.672434
|
||||
7.01111802,24.9087977 6.09748166,23.2587977 C5.15657257,21.5815249
|
||||
4.66566348,19.5360704 4.66566348,17.3406158 C4.66566348,13.2906158
|
||||
8.12929984,9.99061584 12.3838453,9.99061584 C16.6383908,9.99061584
|
||||
20.1020271,13.2906158 20.1020271,17.3406158 C20.1020271,17.722434
|
||||
19.8020271,18.022434 19.4202089,18.022434 C19.0383908,18.022434
|
||||
18.7383908,17.722434 18.7383908,17.3406158 C18.7383908,14.0406158
|
||||
15.8883908,11.3542522 12.3838453,11.3542522 C8.87929984,11.3542522
|
||||
6.02929984,14.0406158 6.02929984,17.3406158 C6.02929984,19.3042522
|
||||
6.46566348,21.1178886 7.29748166,22.5906158 C8.17020893,24.1587977
|
||||
8.77020893,24.8269795 9.82020893,25.8906158 C10.0792998,26.1633431
|
||||
10.0792998,26.5860704 9.82020893,26.8587977 C9.67020893,26.9951613
|
||||
9.4929362,27.0633431 9.31566348,27.0633431 Z M19.0929362,24.5406158
|
||||
C17.4702089,24.5406158 16.0383908,24.1315249 14.8656635,23.3269795
|
||||
C12.8338453,21.9497067 11.6202089,19.7133431 11.6202089,17.3406158
|
||||
C11.6202089,16.9587977 11.9202089,16.6587977 12.3020271,16.6587977
|
||||
C12.6838453,16.6587977 12.9838453,16.9587977 12.9838453,17.3406158
|
||||
C12.9838453,19.2633431 13.9656635,21.0769795 15.6292998,22.1951613
|
||||
C16.5974817,22.8497067 17.7292998,23.1633431 19.0929362,23.1633431
|
||||
C19.4202089,23.1633431 19.9656635,23.122434 20.511118,23.0269795
|
||||
C20.8792998,22.9587977 21.2338453,23.2042522 21.3020271,23.5860704
|
||||
C21.3702089,23.9542522 21.1247544,24.3087977 20.7429362,24.3769795
|
||||
C19.9656635,24.5269795 19.2838453,24.5406158 19.0929362,24.5406158
|
||||
L19.0929362,24.5406158 Z M16.3520271,27.3497067 C16.2974817,27.3497067
|
||||
16.2292998,27.3360704 16.1747544,27.322434 C14.0065726,26.722434
|
||||
12.5883908,25.9178886 11.1020271,24.4587977 C9.1929362,22.5633431
|
||||
8.1429362,20.0406158 8.1429362,17.3406158 C8.1429362,15.1315249
|
||||
10.0247544,13.3315249 12.3429362,13.3315249 C14.661118,13.3315249
|
||||
16.5429362,15.1315249 16.5429362,17.3406158 C16.5429362,18.7997067
|
||||
17.811118,19.9860704 19.3792998,19.9860704 C20.9474817,19.9860704
|
||||
22.2156635,18.7997067 22.2156635,17.3406158 C22.2156635,12.1997067
|
||||
17.7838453,8.02697947 12.3292998,8.02697947 C8.45657257,8.02697947
|
||||
4.91111802,10.1815249 3.31566348,13.522434 C2.7838453,14.6269795
|
||||
2.51111802,15.922434 2.51111802,17.3406158 C2.51111802,18.4042522
|
||||
2.60657257,20.0815249 3.42475439,22.2633431 C3.56111802,22.6178886
|
||||
3.3838453,23.0133431 3.02929984,23.1360704 C2.67475439,23.272434
|
||||
2.27929984,23.0815249 2.15657257,22.7406158 C1.48839075,20.9542522
|
||||
1.16111802,19.1815249 1.16111802,17.3406158 C1.16111802,15.7042522
|
||||
1.47475439,14.2178886 2.08839075,12.922434 C3.90202711,9.11788856
|
||||
7.92475439,6.64970674 12.3292998,6.64970674 C18.5338453,6.64970674
|
||||
23.5792998,11.4360704 23.5792998,17.3269795 C23.5792998,19.5360704
|
||||
21.6974817,21.3360704 19.3792998,21.3360704 C17.061118,21.3360704
|
||||
15.1792998,19.5360704 15.1792998,17.3269795 C15.1792998,15.8678886
|
||||
13.911118,14.6815249 12.3429362,14.6815249 C10.7747544,14.6815249
|
||||
9.50657257,15.8678886 9.50657257,17.3269795 C9.50657257,19.6587977
|
||||
10.4065726,21.8406158 12.0565726,23.4769795 C13.3520271,24.7587977
|
||||
14.5929362,25.4678886 16.5156635,25.9997067 C16.8838453,26.0951613
|
||||
17.0883908,26.4769795 16.9929362,26.8315249 C16.9247544,27.1451613
|
||||
16.6383908,27.3497067 16.3520271,27.3497067 L16.3520271,27.3497067 Z" />
|
||||
</group>
|
||||
</vector>
|
||||
163
packages/SystemUI/res/layout/fingerprint_dialog.xml
Normal file
163
packages/SystemUI/res/layout/fingerprint_dialog.xml
Normal file
@@ -0,0 +1,163 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2018 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
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="bottom"
|
||||
android:background="@color/fingerprint_dialog_dim_color"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- This is not a Space since Spaces cannot be clicked -->
|
||||
<View
|
||||
android:id="@+id/space"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/dialog"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:elevation="2dp"
|
||||
android:background="@drawable/fingerprint_dialog_bg">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:elevation="2dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="@dimen/fingerprint_dialog_icon_size"
|
||||
android:layout_height="@dimen/fingerprint_dialog_icon_size"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:scaleType="centerInside" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toRightOf="@+id/icon"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textSize="20sp"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:textColor="@color/fingerprint_dialog_text_color"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subtitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toRightOf="@+id/icon"
|
||||
android:layout_below="@+id/title"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textSize="12sp"
|
||||
android:maxLines="2"
|
||||
android:textColor="@color/fingerprint_dialog_text_color"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="20dp"
|
||||
android:textSize="16sp"
|
||||
android:maxLines="4"
|
||||
android:textColor="@color/fingerprint_dialog_text_color"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/fingerprint_icon"
|
||||
android:layout_width="@dimen/fingerprint_dialog_fp_icon_size"
|
||||
android:layout_height="@dimen/fingerprint_dialog_fp_icon_size"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/fingerprint_icon"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/error"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd = "16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="60dp"
|
||||
android:textSize="12sp"
|
||||
android:visibility="invisible"
|
||||
android:gravity="center_horizontal"
|
||||
android:textColor="@color/fingerprint_error_message_color"/>
|
||||
|
||||
<LinearLayout android:id="@+id/buttonPanel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="54dip"
|
||||
android:orientation="vertical" >
|
||||
<LinearLayout
|
||||
style="?android:attr/buttonBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="4dip"
|
||||
android:paddingStart="2dip"
|
||||
android:paddingEnd="2dip"
|
||||
android:measureWithLargestChild="true">
|
||||
<LinearLayout android:id="@+id/leftSpacer"
|
||||
android:layout_weight="0.25"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone" />
|
||||
<!-- Positive Button -->
|
||||
<Button android:id="@+id/button1"
|
||||
android:layout_width="0dip"
|
||||
android:layout_gravity="start"
|
||||
android:layout_weight="1"
|
||||
style="?android:attr/buttonBarButtonStyle"
|
||||
android:maxLines="2"
|
||||
android:layout_height="wrap_content"/>
|
||||
<!-- Negative Button -->
|
||||
<Button android:id="@+id/button2"
|
||||
android:layout_width="0dip"
|
||||
android:layout_gravity="end"
|
||||
android:layout_weight="1"
|
||||
style="?android:attr/buttonBarButtonStyle"
|
||||
android:maxLines="2"
|
||||
android:layout_height="wrap_content" />
|
||||
<LinearLayout android:id="@+id/rightSpacer"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="0.25"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -156,6 +156,14 @@
|
||||
|
||||
<color name="zen_introduction">#ffffffff</color>
|
||||
|
||||
|
||||
<color name="smart_reply_button_text">#ff4285f4</color><!-- blue 500 -->
|
||||
<color name="smart_reply_button_background">#fff7f7f7</color>
|
||||
|
||||
<!-- Fingerprint dialog colors -->
|
||||
<color name="fingerprint_dialog_bg_color">#f4ffffff</color> <!-- 96% white -->
|
||||
<color name="fingerprint_dialog_text_color">#ff424242</color> <!-- gray 800-->
|
||||
<color name="fingerprint_dialog_dim_color">#80000000</color> <!-- 50% black -->
|
||||
<color name="fingerprint_error_message_color">#ff5722</color>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -889,4 +889,7 @@
|
||||
<dimen name="smart_reply_button_spacing">8dp</dimen>
|
||||
<dimen name="smart_reply_button_padding_vertical">4dp</dimen>
|
||||
<dimen name="smart_reply_button_font_size">14sp</dimen>
|
||||
|
||||
<dimen name="fingerprint_dialog_icon_size">44dp</dimen>
|
||||
<dimen name="fingerprint_dialog_fp_icon_size">60dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -16,17 +16,75 @@
|
||||
|
||||
package com.android.systemui.fingerprint;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.hardware.fingerprint.FingerprintDialog;
|
||||
import android.hardware.fingerprint.IFingerprintDialogReceiver;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.systemui.SystemUI;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
|
||||
public class FingerprintDialogImpl extends SystemUI implements CommandQueue.Callbacks {
|
||||
private static final String TAG = "FingerprintDialogImpl";
|
||||
private static final boolean DEBUG = false;
|
||||
private static final boolean DEBUG = true;
|
||||
|
||||
protected static final int MSG_SHOW_DIALOG = 1;
|
||||
protected static final int MSG_FINGERPRINT_AUTHENTICATED = 2;
|
||||
protected static final int MSG_FINGERPRINT_HELP = 3;
|
||||
protected static final int MSG_FINGERPRINT_ERROR = 4;
|
||||
protected static final int MSG_HIDE_DIALOG = 5;
|
||||
protected static final int MSG_BUTTON_NEGATIVE = 6;
|
||||
protected static final int MSG_USER_CANCELED = 7;
|
||||
protected static final int MSG_BUTTON_POSITIVE = 8;
|
||||
protected static final int MSG_CLEAR_MESSAGE = 9;
|
||||
|
||||
|
||||
private FingerprintDialogView mDialogView;
|
||||
private WindowManager mWindowManager;
|
||||
private IFingerprintDialogReceiver mReceiver;
|
||||
private boolean mDialogShowing;
|
||||
|
||||
private Handler mHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch(msg.what) {
|
||||
case MSG_SHOW_DIALOG:
|
||||
handleShowDialog((SomeArgs) msg.obj);
|
||||
break;
|
||||
case MSG_FINGERPRINT_AUTHENTICATED:
|
||||
handleFingerprintAuthenticated();
|
||||
break;
|
||||
case MSG_FINGERPRINT_HELP:
|
||||
handleFingerprintHelp((String) msg.obj);
|
||||
break;
|
||||
case MSG_FINGERPRINT_ERROR:
|
||||
handleFingerprintError((String) msg.obj);
|
||||
break;
|
||||
case MSG_HIDE_DIALOG:
|
||||
handleHideDialog((Boolean) msg.obj);
|
||||
break;
|
||||
case MSG_BUTTON_NEGATIVE:
|
||||
handleButtonNegative();
|
||||
break;
|
||||
case MSG_USER_CANCELED:
|
||||
handleUserCanceled();
|
||||
break;
|
||||
case MSG_BUTTON_POSITIVE:
|
||||
handleButtonPositive();
|
||||
break;
|
||||
case MSG_CLEAR_MESSAGE:
|
||||
handleClearMessage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
@@ -34,30 +92,129 @@ public class FingerprintDialogImpl extends SystemUI implements CommandQueue.Call
|
||||
return;
|
||||
}
|
||||
getComponent(CommandQueue.class).addCallbacks(this);
|
||||
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
|
||||
mDialogView = new FingerprintDialogView(mContext, mHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showFingerprintDialog(Bundle bundle, IFingerprintDialogReceiver receiver) {
|
||||
if (DEBUG) Log.d(TAG, "show fingerprint dialog");
|
||||
if (DEBUG) Log.d(TAG, "showFingerprintDialog");
|
||||
// Remove these messages as they are part of the previous client
|
||||
mHandler.removeMessages(MSG_FINGERPRINT_ERROR);
|
||||
mHandler.removeMessages(MSG_FINGERPRINT_HELP);
|
||||
mHandler.removeMessages(MSG_FINGERPRINT_AUTHENTICATED);
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = bundle;
|
||||
args.arg2 = receiver;
|
||||
mHandler.obtainMessage(MSG_SHOW_DIALOG, args).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFingerprintAuthenticated() {
|
||||
if (DEBUG) Log.d(TAG, "onFingerprintAuthenticated");
|
||||
mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFingerprintHelp(String message) {
|
||||
if (DEBUG) Log.d(TAG, "onFingerprintHelp: " + message);
|
||||
mHandler.obtainMessage(MSG_FINGERPRINT_HELP, message).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFingerprintError(String error) {
|
||||
if (DEBUG) Log.d(TAG, "onFingerprintError: " + error);
|
||||
mHandler.obtainMessage(MSG_FINGERPRINT_ERROR, error).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideFingerprintDialog() {
|
||||
if (DEBUG) Log.d(TAG, "hideFingerprintDialog");
|
||||
mHandler.obtainMessage(MSG_HIDE_DIALOG, false /* userCanceled */).sendToTarget();
|
||||
}
|
||||
|
||||
private void handleShowDialog(SomeArgs args) {
|
||||
if (DEBUG) Log.d(TAG, "handleShowDialog");
|
||||
if (mDialogShowing) {
|
||||
Log.w(TAG, "Dialog already showing");
|
||||
return;
|
||||
}
|
||||
mReceiver = (IFingerprintDialogReceiver) args.arg2;
|
||||
mDialogView.setBundle((Bundle)args.arg1);
|
||||
mWindowManager.addView(mDialogView, mDialogView.getLayoutParams());
|
||||
mDialogShowing = true;
|
||||
}
|
||||
|
||||
private void handleFingerprintAuthenticated() {
|
||||
if (DEBUG) Log.d(TAG, "handleFingerprintAuthenticated");
|
||||
handleHideDialog(false /* userCanceled */);
|
||||
}
|
||||
|
||||
private void handleFingerprintHelp(String message) {
|
||||
if (DEBUG) Log.d(TAG, "handleFingerprintHelp: " + message);
|
||||
mDialogView.showHelpMessage(message);
|
||||
}
|
||||
|
||||
private void handleFingerprintError(String error) {
|
||||
if (DEBUG) Log.d(TAG, "handleFingerprintError: " + error);
|
||||
if (!mDialogShowing) {
|
||||
if (DEBUG) Log.d(TAG, "Dialog already dismissed");
|
||||
return;
|
||||
}
|
||||
mDialogView.showErrorMessage(error);
|
||||
}
|
||||
|
||||
private void handleHideDialog(boolean userCanceled) {
|
||||
if (DEBUG) Log.d(TAG, "handleHideDialog");
|
||||
if (!mDialogShowing) {
|
||||
// This can happen if there's a race and we get called from both
|
||||
// onAuthenticated and onError, etc.
|
||||
Log.w(TAG, "Dialog already dismissed, userCanceled: " + userCanceled);
|
||||
return;
|
||||
}
|
||||
if (userCanceled) {
|
||||
try {
|
||||
mReceiver.onDialogDismissed(FingerprintDialog.DISMISSED_REASON_USER_CANCEL);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "RemoteException when hiding dialog", e);
|
||||
}
|
||||
}
|
||||
mReceiver = null;
|
||||
mWindowManager.removeView(mDialogView);
|
||||
mDialogShowing = false;
|
||||
}
|
||||
|
||||
private void handleButtonNegative() {
|
||||
if (mReceiver == null) {
|
||||
Log.e(TAG, "Receiver is null");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mReceiver.onDialogDismissed(FingerprintDialog.DISMISSED_REASON_NEGATIVE);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Remote exception when handling negative button", e);
|
||||
}
|
||||
handleHideDialog(false /* userCanceled */);
|
||||
}
|
||||
|
||||
private void handleButtonPositive() {
|
||||
if (mReceiver == null) {
|
||||
Log.e(TAG, "Receiver is null");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mReceiver.onDialogDismissed(FingerprintDialog.DISMISSED_REASON_POSITIVE);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Remote exception when handling positive button", e);
|
||||
}
|
||||
handleHideDialog(false /* userCanceled */);
|
||||
}
|
||||
|
||||
private void handleClearMessage() {
|
||||
mDialogView.clearMessage();
|
||||
}
|
||||
|
||||
private void handleUserCanceled() {
|
||||
handleHideDialog(true /* userCanceled */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.fingerprint;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.hardware.fingerprint.FingerprintDialog;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewPropertyAnimator;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.PackageManagerWrapper;
|
||||
|
||||
/**
|
||||
* This class loads the view for the system-provided dialog. The view consists of:
|
||||
* Application Icon, Title, Subtitle, Description, Fingerprint Icon, Error/Help message area,
|
||||
* and positive/negative buttons.
|
||||
*/
|
||||
public class FingerprintDialogView extends LinearLayout {
|
||||
|
||||
private static final String TAG = "FingerprintDialogView";
|
||||
|
||||
private static final int ANIMATION_VERTICAL_OFFSET_DP = 96;
|
||||
private static final int ANIMATION_DURATION = 250; // ms
|
||||
|
||||
private final IBinder mWindowToken = new Binder();
|
||||
private final WindowManager mWindowManager;
|
||||
private final ActivityManagerWrapper mActivityManagerWrapper;
|
||||
private final PackageManagerWrapper mPackageManageWrapper;
|
||||
private final Interpolator mLinearOutSlowIn;
|
||||
private final Interpolator mFastOutLinearIn;
|
||||
|
||||
private ViewGroup mLayout;
|
||||
private final TextView mErrorText;
|
||||
private Handler mHandler;
|
||||
private Bundle mBundle;
|
||||
private final float mDensity;
|
||||
private final LinearLayout mDialog;
|
||||
|
||||
public FingerprintDialogView(Context context, Handler handler) {
|
||||
super(context);
|
||||
mHandler = handler;
|
||||
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
|
||||
mPackageManageWrapper = PackageManagerWrapper.getInstance();
|
||||
mLinearOutSlowIn = AnimationUtils
|
||||
.loadInterpolator(getContext(), android.R.interpolator.linear_out_slow_in);
|
||||
mFastOutLinearIn = AnimationUtils
|
||||
.loadInterpolator(getContext(), android.R.interpolator.fast_out_linear_in);
|
||||
|
||||
// Create the dialog
|
||||
LayoutInflater factory = LayoutInflater.from(getContext());
|
||||
mLayout = (ViewGroup) factory.inflate(R.layout.fingerprint_dialog, this, false);
|
||||
addView(mLayout);
|
||||
|
||||
mDialog = mLayout.findViewById(R.id.dialog);
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
mWindowManager.getDefaultDisplay().getMetrics(metrics);
|
||||
mDensity = metrics.density;
|
||||
|
||||
mErrorText = mLayout.findViewById(R.id.error);
|
||||
|
||||
mLayout.setOnKeyListener(new View.OnKeyListener() {
|
||||
boolean downPressed = false;
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
if (keyCode != KeyEvent.KEYCODE_BACK) {
|
||||
return false;
|
||||
}
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN && downPressed == false) {
|
||||
downPressed = true;
|
||||
} else if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||
downPressed = false;
|
||||
} else if (event.getAction() == KeyEvent.ACTION_UP && downPressed == true) {
|
||||
downPressed = false;
|
||||
mHandler.obtainMessage(FingerprintDialogImpl.MSG_USER_CANCELED).sendToTarget();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
final View space = mLayout.findViewById(R.id.space);
|
||||
final Button negative = mLayout.findViewById(R.id.button2);
|
||||
final Button positive = mLayout.findViewById(R.id.button1);
|
||||
|
||||
space.setClickable(true);
|
||||
space.setOnTouchListener((View view, MotionEvent event) -> {
|
||||
mHandler.obtainMessage(FingerprintDialogImpl.MSG_HIDE_DIALOG, true /* userCanceled*/)
|
||||
.sendToTarget();
|
||||
return true;
|
||||
});
|
||||
|
||||
negative.setOnClickListener((View v) -> {
|
||||
mHandler.obtainMessage(FingerprintDialogImpl.MSG_BUTTON_NEGATIVE).sendToTarget();
|
||||
});
|
||||
|
||||
positive.setOnClickListener((View v) -> {
|
||||
mHandler.obtainMessage(FingerprintDialogImpl.MSG_BUTTON_POSITIVE).sendToTarget();
|
||||
});
|
||||
|
||||
mLayout.setFocusableInTouchMode(true);
|
||||
mLayout.requestFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
|
||||
final TextView title = mLayout.findViewById(R.id.title);
|
||||
final TextView subtitle = mLayout.findViewById(R.id.subtitle);
|
||||
final TextView description = mLayout.findViewById(R.id.description);
|
||||
final Button negative = mLayout.findViewById(R.id.button2);
|
||||
final ImageView image = mLayout.findViewById(R.id.icon);
|
||||
final Button positive = mLayout.findViewById(R.id.button1);
|
||||
final ImageView fingerprint_icon = mLayout.findViewById(R.id.fingerprint_icon);
|
||||
|
||||
title.setText(mBundle.getCharSequence(FingerprintDialog.KEY_TITLE));
|
||||
title.setSelected(true);
|
||||
subtitle.setText(mBundle.getCharSequence(FingerprintDialog.KEY_SUBTITLE));
|
||||
description.setText(mBundle.getCharSequence(FingerprintDialog.KEY_DESCRIPTION));
|
||||
negative.setText(mBundle.getCharSequence(FingerprintDialog.KEY_NEGATIVE_TEXT));
|
||||
image.setImageDrawable(getAppIcon());
|
||||
|
||||
final CharSequence positiveText =
|
||||
mBundle.getCharSequence(FingerprintDialog.KEY_POSITIVE_TEXT);
|
||||
positive.setText(positiveText); // needs to be set for marquee to work
|
||||
if (positiveText != null) {
|
||||
positive.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
positive.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// Dim the background and slide the dialog up
|
||||
mDialog.setTranslationY(ANIMATION_VERTICAL_OFFSET_DP * mDensity);
|
||||
mLayout.setAlpha(0f);
|
||||
postOnAnimation(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mLayout.animate()
|
||||
.alpha(1f)
|
||||
.setDuration(ANIMATION_DURATION)
|
||||
.setInterpolator(mLinearOutSlowIn)
|
||||
.withLayer()
|
||||
.start();
|
||||
mDialog.animate()
|
||||
.translationY(0)
|
||||
.setDuration(ANIMATION_DURATION)
|
||||
.setInterpolator(mLinearOutSlowIn)
|
||||
.withLayer()
|
||||
.start();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setBundle(Bundle bundle) {
|
||||
mBundle = bundle;
|
||||
}
|
||||
|
||||
protected void clearMessage() {
|
||||
mErrorText.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
private void showMessage(String message) {
|
||||
mHandler.removeMessages(FingerprintDialogImpl.MSG_CLEAR_MESSAGE);
|
||||
mErrorText.setText(message);
|
||||
mErrorText.setVisibility(View.VISIBLE);
|
||||
mHandler.sendMessageDelayed(mHandler.obtainMessage(FingerprintDialogImpl.MSG_CLEAR_MESSAGE),
|
||||
FingerprintDialog.HIDE_DIALOG_DELAY);
|
||||
}
|
||||
|
||||
public void showHelpMessage(String message) {
|
||||
showMessage(message);
|
||||
}
|
||||
|
||||
public void showErrorMessage(String error) {
|
||||
showMessage(error);
|
||||
mHandler.sendMessageDelayed(mHandler.obtainMessage(FingerprintDialogImpl.MSG_HIDE_DIALOG,
|
||||
false /* userCanceled */), FingerprintDialog.HIDE_DIALOG_DELAY);
|
||||
}
|
||||
|
||||
private Drawable getAppIcon() {
|
||||
final ActivityManager.RunningTaskInfo taskInfo = mActivityManagerWrapper.getRunningTask();
|
||||
final ComponentName cn = taskInfo.topActivity;
|
||||
final int userId = mActivityManagerWrapper.getCurrentUserId();
|
||||
final ActivityInfo activityInfo = mPackageManageWrapper.getActivityInfo(cn, userId);
|
||||
return mActivityManagerWrapper.getBadgedActivityIcon(activityInfo, userId);
|
||||
}
|
||||
|
||||
public WindowManager.LayoutParams getLayoutParams() {
|
||||
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
|
||||
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
|
||||
lp.setTitle("FingerprintDialogView");
|
||||
lp.token = mWindowToken;
|
||||
return lp;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user