从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目录下内容其实很少,一共只有几个文件。

这里除了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消息回传。

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

  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基本组件
  2. Android(安卓)实现开关灯效果
  3. Android:如何设计一个完全不可见的Activity?
  4. android日历实现
  5. Android(安卓)Button的背景图片拉伸变形解决方法
  6. Android(安卓)拖拽效果实现代码分享 - ORIETech
  7. android WebView解析
  8. android实现签名功能
  9. Android(安卓)Studio实现人民币与美元的转换

随机推荐

  1. 我们怎么解决机械硬盘既慢又容易坏的问题
  2. 从DDR到DDR4,内存核心频率其实基本上就没
  3. 【讲清楚,说明白!】Ansible使用role实战
  4. 实际测试内存在顺序IO和随机IO时的访问延
  5. 自学第七十八天
  6. 拆解固态硬盘结构
  7. 一次系统调用开销到底有多大?
  8. 新建一个空文件占用多少磁盘空间?
  9. 只有1个字节的文件实际占用多少磁盘空间
  10. NUMA架构下的内存访问延迟区别!