Android中的指纹模块虽然相对来说不是那么复杂,但是它也是麻雀虽小五脏俱全。
本文将通过Fingerprint模块来分析Android中的Binder机制。
在指纹的整个框架中,有3个地方用到了IPC机制(包括获取指纹服务的一个)。
FingerprintManager-------FingerprintService
FingerprintService--------JNI------HAL
中间文件
Android O
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/core/java/android/hardware/fingerprint/
Android P
还没有找到。可能已经打包到相关的jar包中,中间文件看不到。
在Android系统中,系统服务运行在一个专门的进程中,这个进程有个名字叫systemserver。该进程在系统启动的时候,就被加载和启动。 Binder机制:系统中有一个专门来管理系统服务的类,叫做ServiceManager,负责注册和管理所有的系统服务。当某个应用程序想要使用系统服务时,需要通过服务的代理来调用服务。由于客户应用程序是运行在自己的进程中,由于与systemserver进程是彼此独立的,因此代理需要通过进程间通讯将请求发送到目标systemserver进程中去,由该进程来响应服务,然后将处理的结果返回给这个用户应用程序。 NOTE:service 可以与组件通过IPC机制进行交互(Binder)
FingerprintManager类中的所有功能都依赖于一个名叫mService的字段来实现。这个字段的类型就是IFingerprintService,它就是我们所说的代理(client端只有通过服务的代理才能够申请到指纹的服务,该服务在systemserver中)。在FingerprintManager中是通过IFingerprintService这个代理来获得FingerprintService这个系统服务的。 代理就是aidl编译出来的类,是IPC的重要体现。
FingerprintManager.java
/**
* @hide 文档注释
*/ public FingerprintManager(Context context, IFingerprintService service) { mContext = context; mService = service; if (mService == null) { Slog.v(TAG, "FingerprintManagerService was null"); } mHandler = new MyHandler(context); } //既然在构造函数中初始化这个字段,那我们找到FingerprintManager被new的地方也即是该构造函数被调用的地方: //frameworks/base/core/java/android/app/SystemServiceRegistry.java registerService(Context.FINGERPRINT_SERVICE, FingerprintManager.class, new CachedServiceFetcher<FingerprintManager>() { @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); } } ); 在这里我们看到 ServiceManager这个类,这个类是专门来管理系统服务的,通过它我们可以获得特定服务的实现类对象: IBinder binder = ServiceManager.getService(Context.FINGERPRINT_SERVICE); 接着将其转换成服务的代理: IFingerprintService service = IfingerprintService.Stub.asInterface(binder); 存放在FingerprintManager中: new FingerprintManager(ctx.getOuterContext(), service); 至此完成了客户端FingerprintManager到服务端 FINGERPRINT_SERVICE 的连接。 这里的 FINGERPRINT_SERVICE与FingerprintService之间又有什么关联吗? public class FingerprintService extends SystemService implements IHwBinder.DeathRecipient { // FingerprintService是系统服务中的一员,
//SystemService: import com.android.server.SystemService;
frameworks/base/services/core/java/com/android/server/SystemService.java /** * Called when the dependencies listed in the @Service class-annotation are available * and after the chosen start phase. * When this method returns, the service should be published. */ public abstract void onStart(); //frameworks/base/services/core/java/com/android/server/fingerprint/FingerprintService.java /** * 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 { ......
接着看到FingerprintService下的onStart方法
@Override public void onStart() { publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper()); SystemServerInitThreadPool.get().submit(this::getFingerprintDaemon, TAG + ".onStart"); listenForUserSwitches(); } ...... /frameworks/base/services/java/com/android/server/SystemServer.java /** * Starts a miscellaneous grab bag of stuff that has yet to be refactored * and organized. */ private void startOtherServices() { ….. if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { traceBeginAndSlog("StartFingerprintSensor"); mSystemServiceManager.startService(FingerprintService.class); traceEnd(); } …... FingerprintService在 SystemServer中创建并初始化,当检测到手机支持指纹功能的时候,就会启动这个服务 frameworks/base/services/core/java/com/android/server/SystemServiceManager.java : mSystemServiceManager
FingerprintService在初始化后会建立和HAL层的通信,即连接到BiometricsFingerprint,拿到用于通信的IBiometricsFingerprint对象(binder)
本质上来说,除去安全相关的策略外,指纹的功能是依赖硬件实现的,FingerprintService也只是充当了framework java层与native层的消息传递者罢了,所以指纹的识别,录入和监听都是向BiometricsFingerprint(fingerprintd)发送命令和获取相应的结果。
既然FingerprintService已经注册并且启动成功,那么接下来如何去使用指纹服务呢(如何去拿到服务中提供的API)? 指纹服务的代理IFingerprintService 既然已经通过参数传到FingerprintManager中,当然是通过FingerprintManager去调用相关的API。 那么在app层我们是如何获得FingerprintManager的(方法?),并分析?
方法:
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE); //经典方法 } or context.getSystemService( FingerprintManager.class) 分析:
// FingerprintService.java @Override public void onStart() { publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper()); IFingerprintDaemon daemon = getFingerprintDaemon(); if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId); listenForUserSwitches(); } ServiceManager /frameworks/base/core/java/android/os/ServiceManager.java /** * Returns a reference to a service with the given name. * * @param name the name of the service to get * @return a reference to the service, or <code>null</code> if the service doesn't exist */ public static IBinder getService(String name) { try { IBinder service = sCache.get(name); if (service != null) { return service; } else { return getIServiceManager().getService(name); } } catch (RemoteException e) { Log.e(TAG, "error in getService", e); } return null; } /** * Place a new @a service called @a name into the service * manager. * * @param name the name of the new service * @param service the service object */ public static void addService(String name, IBinder service) { try { getIServiceManager().addService(name, service, false); } catch (RemoteException e) { Log.e(TAG, "error in addService", e); } } /** * Place a new @a service called @a name into the service * manager. * * @param name the name of the new service * @param service the service object * @param allowIsolated set to true to allow isolated sandboxed processes * to access this service */ public static void addService(String name, IBinder service, boolean allowIsolated) { try { getIServiceManager().addService(name, service, allowIsolated); } catch (RemoteException e) { Log.e(TAG, "error in addService", e); } } //Android O /frameworks/base/core/java/android/app/SystemServiceRegistry.java registerService(Context.FINGERPRINT_SERVICE, FingerprintManager.class, new CachedServiceFetcher<FingerprintManager>() { @Override public FingerprintManager createService(ContextImpl ctx) { IBinder binder = ServiceManager.getService(Context.FINGERPRINT_SERVICE); IFingerprintService service = IFingerprintService.Stub.asInterface(binder); return new FingerprintManager(ctx.getOuterContext(), service); }}); /packages/apps/Settings/src/com/android/settings/Utils.java public static FingerprintManager getFingerprintManagerOrNull(Context context) { if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { return context.getSystemService(FingerprintManager.class); } else { return null; } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Activity activity = getActivity(); //拿到FingerprintManager的对象,接着使用当中的API mFingerprintManager = Utils.getFingerprintManagerOrNull(activity);
NOTE:FingerprintService与FingerprintManager之所以要使用IPC并不是放置位置上的距离,而是由于它们彼此处在独立的进程中。
相关类简述
1、com.android.server.SystemServer
本身由zygote进程运行,用来启动各种各样的系统服务(SystemService)
2、com.android.server.SystemService
运行在系统进程中的service,每个SystemService都是有生命周期的,所有的生命周期函数都是运行在SystemServer的主线程当中。
- 每个SystemService都有一个参数为Context的构造函数,用来初始化SystemService;
- 调用onstart()使得SystemService处于运行状态,在这种状态下,该SystemService可以通过publishBinderService(String, IBinder) 方法来向外提供服务(binder interface),
- 在启动阶段onBootPhase(int)会被不停的调用直到运行到PHASE_BOOT_COMPLETED阶段(启动阶段的最后阶段),在启动的每一阶段都可以完成一些特殊的任务。
3、 com.android.server.SystemServiceManager
负责管理SystemService的创建、启动以及其他生命周期函数
4、android.app.ActivityManager
用来和系统中所有运行的Activity进行交互,运行在用户进程中;
IActivityManager是一个系统服务,对于上层应用,IActivityManager不希望把所有的接口都暴露出来,因而使用ActivityManager作为中介来访问IActivityManager提供的功能。ActivityManager是通过ActivityManagerNative.getDefault()来获取到IActivityManager这个接口的。因为ActivityManager是运行在用户进程的,因而getDefault()获取的是ActivityManagerProxy.
参考博客:
https://www.jianshu.com/p/abab3b44c6b0
ActivityManagerService简要分析
https://www.jianshu.com/p/6c625e4323a1