从Android的官方API可以查到,向上层提供接口的是FingerprintManager,它的代码在路径frameworks/base/core/java/android/hardware/fingerprint下。

/** * A class that coordinates access to the fingerprint hardware. * @deprecated See {@link BiometricPrompt} which shows a system-provided dialog upon starting * authentication. In a world where devices may have different types of biometric authentication, * it's much more realistic to have a system-provided authentication dialog since the method may * vary by vendor/device. */@Deprecated@SystemService(Context.FINGERPRINT_SERVICE)@RequiresFeature(PackageManager.FEATURE_FINGERPRINT)public class FingerprintManager implements BiometricFingerprintConstants

frameworks/base/core/java/android/hardware/fingerprint目录下内容其实很少,一共只有几个文件。

Android P 指纹 Framework_第1张图片

这里除了FingerprintManager之外,就只有Fingerprint一个类了,其他都是aidl文件。

粗略的看了下Fingerprint类,它里面的内容超级少,主要是包含了几个成员变量,用来记录指纹的信息。

/** * Container for fingerprint metadata. * @hide */public final class Fingerprint extends BiometricAuthenticator.BiometricIdentifier {    private CharSequence mName;    private int mGroupId;    private int mFingerId;    private long mDeviceId; // physical device this is associated with    public Fingerprint(CharSequence name, int groupId, int fingerId, long deviceId) {        mName = name;        mGroupId = groupId;        mFingerId = fingerId;        mDeviceId = deviceId;    }    //...}

如果仔细看代码的话,可以发现一个很神奇的东西,那个就Fingerprint类的所有成员都是private的,并且没有提供任何public的set方法!

这个就厉害了,因为有做过指纹部分的朋友一定记得指纹提供一个rename的接口。没有public的set方法,那它又是怎么实现rename接口的呢?

带着问题看源码!

rename方法在Manager中的实现如下:

/** * Renames the given fingerprint template * @param fpId the fingerprint id * @param userId the user who this fingerprint belongs to * @param newName the new name * * @hide */@RequiresPermission(MANAGE_FINGERPRINT)public void rename(int fpId, int userId, String newName) {        // Renames the given fpId        if (mService != null) {            try {                mService.rename(fpId, userId, newName);            } catch (RemoteException e) {                throw e.rethrowFromSystemServer();            }        } else {            Slog.w(TAG, "rename(): Service not connected!");        }}

这里先直接找到Manager的服务类:FingerprintService

指纹服务的相关代码在frameworks\base\services\core\java\com\android\server\fingerprint下。

/** * A service to manage multiple clients that want to access the fingerprint HAL API. * The service is responsible for maintaining a list of clients and dispatching all * fingerprint-related events. * * @hide */public class FingerprintService extends SystemService implements IHwBinder.DeathRecipient

看一下它里面的rename是在内部类FingerprintServiceWrapper中实现的,具体如下:

@Override // Binder callpublic void rename(final int fingerId, final int groupId, final String name) {    checkPermission(MANAGE_FINGERPRINT);    if (!isCurrentUserOrProfile(groupId)) {        return;    }    mHandler.post(new Runnable() {        @Override        public void run() {            mFingerprintUtils.renameFingerprintForUser(mContext, fingerId,                    groupId, name);        }    }}

找到同文件夹下FingerprintUtils类,这个是工具类,里面维护了一组FingerprintsUserState,具体得继续看FingerprintsUserState;

FingerprintsUserState中维护了一组Fingerprint,下面具体看下rename操作:

@GuardedBy("this")private final ArrayList mFingerprints = new ArrayList();//...public void renameFingerprint(int fingerId, CharSequence name) {    synchronized (this) {        for (int i = 0; i < mFingerprints.size(); i++) {            if (mFingerprints.get(i).getFingerId() == fingerId) {                Fingerprint old = mFingerprints.get(i);                mFingerprints.set(i, new Fingerprint(name, old.getGroupId(),                         old.getFingerId(), old.getDeviceId()));                scheduleWriteStateLocked();                break;            }        }    }}

这里可以看到,在rename的实现时,代码直接霸气的new一个Fingerprint对象,然后覆盖List中对应id的对象。

 

OK,以上只是一个小小的流程。

 

下面看下FingerprintManager的主要API:

public void enroll(byte [] token, CancellationSignal cancel, int flags,            int userId, EnrollmentCallback callback);public void remove(Fingerprint fp, int userId, RemovalCallback callback);public void rename(int fpId, int userId, String newName);public List getEnrolledFingerprints();//不是hide的方法public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler);public boolean hasEnrolledFingerprints();public boolean isHardwareDetected()

真正对三方开放的API只有最下面的三个,分别用来授权、判断是否录入过指纹、判断设备是否支持指纹器件。

这里面要特别提一下authenicate方法;

   /**     * Request authentication of a crypto object. This call warms up the fingerprint hardware     * and starts scanning for a fingerprint. It terminates when     * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or     * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at     * which point the object is no longer valid. The operation can be canceled by using the     * provided cancel object.     *     * @param crypto object associated with the call or null if none required.     * @param cancel an object that can be used to cancel authentication     * @param flags optional flags; should be 0     * @param callback an object to receive authentication events     * @param handler an optional handler to handle callback events     *     * @throws IllegalArgumentException if the crypto operation is not supported or is not backed     *         by Android Keystore     *         facility.     * @throws IllegalStateException if the crypto primitive is not initialized.     * @deprecated See {@link BiometricPrompt#authenticate(CancellationSignal, Executor,     * BiometricPrompt.AuthenticationCallback)} and {@link BiometricPrompt#authenticate(     * BiometricPrompt.CryptoObject, CancellationSignal, Executor,     * BiometricPrompt.AuthenticationCallback)}     */    @Deprecated    @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})    public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,            int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) {        authenticate(crypto, cancel, flags, callback, handler, mContext.getUserId());    }

其中flags暂时没用起来,直接设置为0。 

这里稍微讲下crypto objiect。它是的一个内部类。暂时支持三种类型对象。如下:

   /**     * A wrapper class for the crypto objects supported by FingerprintManager. Currently the     * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects.     * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.CryptoObject}     */

这个参数用于加密,保护指纹在使用过程中不被恶意软件截获和篡改。
Google的示例中用的是Cipher的加密对象。 
需要结束监听的话,使用CancellationSignal对象的cancel方法即可。

 

上面提到过Manager里面的API具体实现都是Service中。

Manager中保存有Service的对象private IFingerprintService mService;

这对象看命名方式就可以大概猜到是个AIDL了;

/** * Communication channel from client to the fingerprint service. * @hide */interface IFingerprintService

它是在Manager的构造函数作为参数传入的,找到创建Manager的地方:

frameworks/base/core/java/android/app/SystemServiceRegistry.java

registerService(Context.FINGERPRINT_SERVICE, FingerprintManager.class,        new CachedServiceFetcher() {    @Override    public FingerprintManager createService(ContextImpl ctx) throws ServiceNotFoundException {        final IBinder binder;        if (ctx.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.O) {            binder = ServiceManager.getServiceOrThrow(Context.FINGERPRINT_SERVICE);        } else {            binder = ServiceManager.getService(Context.FINGERPRINT_SERVICE);        }        IFingerprintService service = IFingerprintService.Stub.asInterface(binder);        return new FingerprintManager(ctx.getOuterContext(), service);}});

从这里看,关键字是Context.FINGERPRINT_SERVICE这个服务!

这时候,灵机一动看一眼FingerprintService(通过搜索可以搜到FingerprintService),它的onStart方法中有发布这个服务,发布的是它的内部类FingerprintServiceWrapper,这里就解释了为什么之前Manager里面的rename方法最后会在FingerprintServiceWrapper被搜索到。

@Overridepublic void onStart() {    publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());    SystemServerInitThreadPool.get().submit(this::getFingerprintDaemon, TAG + ".onStart");    listenForUserSwitches();}

而FingerprintService本身是在frameworks/base/services/java/com/android/server/SystemServer.java中启动的;

if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {    traceBeginAndSlog("StartFingerprintSensor");    mSystemServiceManager.startService(FingerprintService.class);    traceEnd();}

 

 下面来看一下一个消息反馈的AIDL:IFingerprintServiceReceiver;

/** * Communication channel from the FingerprintService back to FingerprintManager. * @hide */oneway interface IFingerprintServiceReceiver {    void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining);    void onAcquired(long deviceId, int acquiredInfo, int vendorCode);    void onAuthenticationSucceeded(long deviceId, in Fingerprint fp, int userId);    void onAuthenticationFailed(long deviceId);    void onError(long deviceId, int error, int vendorCode);    void onRemoved(long deviceId, int fingerId, int groupId, int remaining);    void onEnumerated(long deviceId, int fingerId, int groupId, int remaining);}

它的实例在Manager中;

private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub

作为参数被传递给Service,实现消息反馈机制。

 

如果仔细看下FingerprintService所在的文件夹,除了之前提到过的FingerprintService、FingerprintUtils和FingerprintsUserState以外就只剩下大量和ClientMonitor 相关的类了;

/** * Abstract base class for keeping track and dispatching events from fingerprint HAL to the * the current client.  Subclasses are responsible for coordinating the interaction with * fingerprint HAL for the specific action (e.g. authenticate, enroll, enumerate, etc.). */public abstract class ClientMonitor implements IBinder.DeathRecipient

它的子类包括AuthenticationClient、EnrollClient、EnumerateClient、InternalEnumerateClient、InternalRemovalClient和RemovalClient。

它们是真正负责和更下层的HAL层交互的类。

HAL层有关的内容这里暂不讨论。

 

这样的话,大概的一组流程被整理出来,FingerprintManager内部持有FingerprintService内部类FingerprintServiceWrapper的AIDL,FingerprintManager的API都是调用FingerprintServiceWrapper提供的接口实现的,同时通过参数实现IFingerprintServiceReceiver消息回传。

Android P 指纹 Framework_第2张图片

这里还有一点可以提一下,那就是指纹授权时的震动;

  1. frameworks/base/services/core/java/com/android/server/fingerprint/AuthenticationClient.java中会在授权成功或失败后调用vibrateSuccess()和vibrateError()方法实现不同的震动效果
  2. frameworks/base/services/core/java/com/android/server/fingerprint/ClientMonitor.java有vibrateSuccess()和vibrateError()两个方法的具体实现
  3. 在ClientMonitor中可以看到frameworks\base\core\java\android\os\VibrationEffect.java是真正实现震动的类
  4. 可以通过用VibrationEffect的createOneShot或createWaveform方法创建想要的震动效果

更多相关文章

  1. 更改Android AVD模拟器创建路径位置的方法
  2. Android Button的背景图片拉伸变形解决方法
  3. Android 设备指纹
  4. android设置textview限制字数以省略号显示的方法
  5. Android子控件超出父控件方法
  6. Android Studio下载及离线升级方法

随机推荐

  1. Android Dialog 去除其中的Title
  2. 4. android 滚动视图
  3. android 获取屏幕的方向
  4. Android DOC文档分析——Dialog
  5. 关于android studio报错transformClasses
  6. Android studio Caused by: org.gradle.a
  7. AndroidManifest.xml配置文件选项详解
  8. 【stagefrightplayer】1 调用过程
  9. ubuntu10.10下的android源码下载及编译
  10. Android与php服务器交互实例