1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package android.support.v4.hardware.fingerprint; 18 19 import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; 20 21 import android.annotation.SuppressLint; 22 import android.content.Context; 23 import android.content.pm.PackageManager; 24 import android.hardware.fingerprint.FingerprintManager; 25 import android.os.Handler; 26 import android.support.annotation.RequiresApi; 27 import android.support.annotation.RestrictTo; 28 29 import java.security.Signature; 30 31 import javax.crypto.Cipher; 32 import javax.crypto.Mac; 33 34 /** 35 * Actual FingerprintManagerCompat implementation for API level 23 and later. 36 * @hide 37 */ 38 @RequiresApi(23) 39 @RestrictTo(LIBRARY_GROUP) 40 public final class FingerprintManagerCompatApi23 { 41 42 private static FingerprintManager getFingerprintManagerOrNull(Context context) { 43 if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { 44 return context.getSystemService(FingerprintManager.class); 45 } else { 46 return null; 47 } 48 } 49 50 // We expect developers to add android.permission.USE_FINGERPRINT to their manifest if they 51 // use this API. 52 @SuppressLint("MissingPermission") 53 static boolean hasEnrolledFingerprints(Context context) { 54 final FingerprintManager fp = getFingerprintManagerOrNull(context); 55 return (fp != null) && fp.hasEnrolledFingerprints(); 56 } 57 58 // We expect developers to add android.permission.USE_FINGERPRINT to their manifest if they 59 // use this API. 60 @SuppressLint("MissingPermission") 61 static boolean isHardwareDetected(Context context) { 62 final FingerprintManager fp = getFingerprintManagerOrNull(context); 63 return (fp != null) && fp.isHardwareDetected(); 64 } 65 66 // We expect developers to add android.permission.USE_FINGERPRINT to their manifest if they 67 // use this API. 68 @SuppressLint("MissingPermission") 69 static void authenticate(Context context, CryptoObject crypto, int flags, Object cancel, 70 AuthenticationCallback callback, Handler handler) { 71 final FingerprintManager fp = getFingerprintManagerOrNull(context); 72 if (fp != null) { 73 fp.authenticate(wrapCryptoObject(crypto), 74 (android.os.CancellationSignal) cancel, flags, 75 wrapCallback(callback), handler); 76 } 77 } 78 79 private static FingerprintManager.CryptoObject wrapCryptoObject(CryptoObject cryptoObject) { 80 if (cryptoObject == null) { 81 return null; 82 } else if (cryptoObject.getCipher() != null) { 83 return new FingerprintManager.CryptoObject(cryptoObject.getCipher()); 84 } else if (cryptoObject.getSignature() != null) { 85 return new FingerprintManager.CryptoObject(cryptoObject.getSignature()); 86 } else if (cryptoObject.getMac() != null) { 87 return new FingerprintManager.CryptoObject(cryptoObject.getMac()); 88 } else { 89 return null; 90 } 91 } 92 93 private static CryptoObject unwrapCryptoObject(FingerprintManager.CryptoObject cryptoObject) { 94 if (cryptoObject == null) { 95 return null; 96 } else if (cryptoObject.getCipher() != null) { 97 return new CryptoObject(cryptoObject.getCipher()); 98 } else if (cryptoObject.getSignature() != null) { 99 return new CryptoObject(cryptoObject.getSignature()); 100 } else if (cryptoObject.getMac() != null) { 101 return new CryptoObject(cryptoObject.getMac()); 102 } else { 103 return null; 104 } 105 } 106 107 private static FingerprintManager.AuthenticationCallback wrapCallback( 108 final AuthenticationCallback callback) { 109 return new FingerprintManager.AuthenticationCallback() { 110 @Override 111 public void onAuthenticationError(int errMsgId, CharSequence errString) { 112 callback.onAuthenticationError(errMsgId, errString); 113 } 114 115 @Override 116 public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { 117 callback.onAuthenticationHelp(helpMsgId, helpString); 118 } 119 120 @Override 121 public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) { 122 callback.onAuthenticationSucceeded(new AuthenticationResultInternal( 123 unwrapCryptoObject(result.getCryptoObject()))); 124 } 125 126 @Override 127 public void onAuthenticationFailed() { 128 callback.onAuthenticationFailed(); 129 } 130 }; 131 } 132 133 public static class CryptoObject { 134 135 private final Signature mSignature; 136 private final Cipher mCipher; 137 private final Mac mMac; 138 139 public CryptoObject(Signature signature) { 140 mSignature = signature; 141 mCipher = null; 142 mMac = null; 143 } 144 145 public CryptoObject(Cipher cipher) { 146 mCipher = cipher; 147 mSignature = null; 148 mMac = null; 149 } 150 151 public CryptoObject(Mac mac) { 152 mMac = mac; 153 mCipher = null; 154 mSignature = null; 155 } 156 157 public Signature getSignature() { return mSignature; } 158 public Cipher getCipher() { return mCipher; } 159 public Mac getMac() { return mMac; } 160 } 161 162 public static final class AuthenticationResultInternal { 163 private CryptoObject mCryptoObject; 164 165 public AuthenticationResultInternal(CryptoObject crypto) { 166 mCryptoObject = crypto; 167 } 168 169 public CryptoObject getCryptoObject() { return mCryptoObject; } 170 } 171 172 public static abstract class AuthenticationCallback { 173 174 public void onAuthenticationError(int errMsgId, CharSequence errString) { } 175 public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { } 176 public void onAuthenticationSucceeded(AuthenticationResultInternal result) { } 177 public void onAuthenticationFailed() { } 178 } 179 } 180