在本文中,我们将为您详细介绍Android7.0指纹服务FingerprintService实例介绍的相关知识,并且为您解答关于android设备指纹的疑问,此外,我们还会提供一些关于Android8
在本文中,我们将为您详细介绍Android7.0指纹服务FingerprintService实例介绍的相关知识,并且为您解答关于android设备指纹的疑问,此外,我们还会提供一些关于Android 8.0 以后使用后台 Service 服务 JobIntentService 的使用、Android Fingerprint 中的 IPC(Binder)、Android IntentService详解及使用实例、android linux内核层 Android 跨进程通信:IPC、Binder 与 ServiceManager 介绍的有用信息。
本文目录一览:- Android7.0指纹服务FingerprintService实例介绍(android设备指纹)
- Android 8.0 以后使用后台 Service 服务 JobIntentService 的使用
- Android Fingerprint 中的 IPC(Binder)
- Android IntentService详解及使用实例
- android linux内核层 Android 跨进程通信:IPC、Binder 与 ServiceManager 介绍
Android7.0指纹服务FingerprintService实例介绍(android设备指纹)
指纹服务是Android系统中一个较为简单的服务(相比于AMS,WMS等),也比较独立,功能上包括几点
- 指纹的录入与删除
- 指纹认证
- 指纹的安全策略(错误次数判定)
和其他的system service 一样,应用程序通过FingerprintManager实现与FingerprintService的通信,除了上面所说的功能之外,FingerprintManager提供了一些别的的接口,重要的接口都会要求系统级别的权限,并且也不是公开的api(指纹的录入,删除,重命名,重置错误计数等)
/** * Obtain the list of enrolled fingerprints templates. * @return list of current fingerprint items * * @hide */ @RequiresPermission(USE_FINGERPRINT) public List<Fingerprint> getEnrolledFingerprints(int userId) { if (mService != null) try { return mService.getEnrolledFingerprints(userId,mContext.getopPackageName()); } catch (remoteexception e) { throw e.rethrowFromSystemServer(); } return null; } /** * @hide */ @RequiresPermission(allOf = { USE_FINGERPRINT,INteraCT_ACROSS_USERS}) public boolean hasEnrolledFingerprints(int userId) { if (mService != null) try { return mService.hasEnrolledFingerprints(userId,mContext.getopPackageName()); } catch (remoteexception e) { throw e.rethrowFromSystemServer(); } return false; } /** * Determine if fingerprint hardware is present and functional. * * @return true if hardware is present and functional,false otherwise. */ @RequiresPermission(USE_FINGERPRINT) public boolean isHardwareDetected() { if (mService != null) { try { long deviceid = 0; /* Todo: plumb hardware id to FPMS */ return mService.isHardwareDetected(deviceid,mContext.getopPackageName()); } catch (remoteexception e) { throw e.rethrowFromSystemServer(); } } else { Log.w(TAG,"isFingerprintHardwareDetected(): Service not connected!"); } return false; }
FingerprintService的启动过程
FingerprintService在system server中创建并初始化,当检测到手机支持指纹功能的时候就会启动这个service
... if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { mSystemServiceManager.startService(FingerprintService.class); } ...
FingerprintService在初始化后会建立和HAL层的通信,即连接到fingerprintd,拿到用于通信的IFingerprintDaemon对象(binder)
public void onStart() { publishBinderService(Context.FINGERPRINT_SERVICE,new FingerprintServiceWrapper()); IFingerprintDaemon daemon = getFingerprintDaemon(); listenForUserSwitches(); } public IFingerprintDaemon getFingerprintDaemon() { if (mDaemon == null) { mDaemon = IFingerprintDaemon.Stub.asInterface(ServiceManager.getService(FINGERPRINTD)); if (mDaemon != null) { try { mDaemon.asBinder().linkToDeath(this,0); mDaemon.init(mDaemonCallback); mHaldeviceid = mDaemon.openHal(); if (mHaldeviceid != 0) { updateActiveGroup(ActivityManager.getCurrentUser(),null); } else { Slog.w(TAG,"Failed to open Fingerprint HAL!"); Metricslogger.count(mContext,"fingerprintd_openhal_error",1); mDaemon = null; } } catch (remoteexception e) { Slog.e(TAG,"Failed to open fingeprintd HAL",e); mDaemon = null; // try again later! } } else { Slog.w(TAG,"fingerprint service not available"); } } return mDaemon; }
本质上来说,除去安全相关的策略外,指纹的功能是依赖硬件实现的,FingerprintService也只是充当了framework java层与native层的消息传递者罢了,所以指纹的识别,录入和监听都是向fingerprintd发送命令和获取相应的结果
指纹监听认证过程
以指纹认证为例,介绍这一过程,录入和删除的过程和认证类似,不重复描述
FingerprintManager
public void authenticate(@Nullable CryptoObject crypto,@Nullable CancellationSignal cancel,int flags,@NonNull AuthenticationCallback callback,Handler handler,int userId) { if (callback == null) { throw new IllegalArgumentException("Must supply an authentication callback"); } if (cancel != null) { if (cancel.isCanceled()) { Log.w(TAG,"authentication already canceled"); return; } else { cancel.setonCancelListener(new OnAuthenticationCancelListener(crypto)); } } if (mService != null) try { useHandler(handler); mAuthenticationCallback = callback; mCryptoObject = crypto; long sessionId = crypto != null ? crypto.getopId() : 0; mService.authenticate(mToken,sessionId,userId,mServiceReceiver,flags,mContext.getopPackageName()); } catch (remoteexception e) { Log.w(TAG,"Remote exception while authenticating: ",e); if (callback != null) { // Though this may not be a hardware issue,it will cause apps to give up or try // again later. callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE,getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE)); } } }
可以看到,最终仍然是向FingerprintService发送消息,但是开启指纹认证的函数传入了两个比较重要的参数,一个是CancellationSignal对象,用于取消指纹认证,另一个是指纹认证的回调对象AuthenticationCallback
public static abstract class AuthenticationCallback { public void onAuthenticationError(int errorCode,CharSequence errString) { } public void onAuthenticationHelp(int helpCode,CharSequence helpString) { } public void onAuthenticationSucceeded(AuthenticationResult result) { } public void onAuthenticationFailed() { } public void onAuthenticationAcquired(int acquireInfo) {} };
看函数名称也能知道其功能,他们分别代表了指纹认证时的回调结果(成功,失败,检测到指纹,认证异常等),参数包含了具体的信息,这些信息在FingerprintManager中都有对应的常量定义,有兴趣可以查看代码
FingerprintService
public void authenticate(final IBinder token,final long opId,final int groupId,final IFingerprintServiceReceiver receiver,final int flags,final String opPackageName) { final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getCallingUserId(); final int pid = Binder.getCallingPid(); final boolean restricted = isRestricted(); mHandler.post(new Runnable() { @Override public void run() { if (!canUseFingerprint(opPackageName,true /* foregroundOnly */,callingUid,pid)) { if (DEBUG) Slog.v(TAG,"authenticate(): reject " + opPackageName); return; } Metricslogger.histogram(mContext,"fingerprint_token",opId != 0L ? 1 : 0); // Get performance stats object for this user. HashMap<Integer,PerformanceStats> pmap = (opId == 0) ? mPerformanceMap : mCryptoPerformanceMap; PerformanceStats stats = pmap.get(mCurrentUserId); if (stats == null) { stats = new PerformanceStats(); pmap.put(mCurrentUserId,stats); } mPerformanceStats = stats; startAuthentication(token,opId,callingUserId,groupId,receiver,restricted,opPackageName); } }); }
前面会有对包名,userid以及应用进程是否在在前台的检查,继续看
private void startAuthentication(IBinder token,long opId,int callingUserId,int groupId,IFingerprintServiceReceiver receiver,boolean restricted,String opPackageName) { updateActiveGroup(groupId,opPackageName); if (DEBUG) Slog.v(TAG,"startAuthentication(" + opPackageName + ")"); AuthenticationClient client = new AuthenticationClient(getContext(),mHaldeviceid,token,mCurrentUserId,opPackageName) { @Override public boolean handleFailedAttempt() { mFailedAttempts++; if (mFailedAttempts == MAX_Failed_ATTEMPTS) { mPerformanceStats.lockout++; } if (inLockoutMode()) { // Failing multiple times will continue to push out the lockout time. scheduleLockoutReset(); return true; } return false; } @Override public void resetFailedAttempts() { FingerprintService.this.resetFailedAttempts(); } @Override public void notifyUserActivity() { FingerprintService.this.userActivity(); } @Override public IFingerprintDaemon getFingerprintDaemon() { return FingerprintService.this.getFingerprintDaemon(); } }; if (inLockoutMode()) { Slog.v(TAG,"In lockout mode; disallowing authentication"); // Don't bother starting the client. Just send the error message. if (!client.onError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) { Slog.w(TAG,"Cannot send timeout message to client"); } return; } startClient(client,true /* initiatedByClient */); }
AuthenticationClient继承自ClientMonitor,用于处理指纹认证相关的功能事务,ClientMonitor的其他子类如RemovalMonior,EnrollMonitor也是如此,ClientMonitor会直接与fingerprintd通信,其核心是调用其start()或stop()方法,
对于AuthenticationClient而言
private void startClient(ClientMonitor newClient,boolean initiatedByClient) { ClientMonitor currentClient = mCurrentClient; if (currentClient != null) { if (DEBUG) Slog.v(TAG,"request stop current client " + currentClient.getownerString()); currentClient.stop(initiatedByClient); mPendingClient = newClient; mHandler.removeCallbacks(mResetClientState); mHandler.postDelayed(mResetClientState,CANCEL_TIMEOUT_LIMIT); } else if (newClient != null) { mCurrentClient = newClient; if (DEBUG) Slog.v(TAG,"starting client " + newClient.getClass().getSuperclass().getSimpleName() + "(" + newClient.getownerString() + ")" + ",initiatedByClient = " + initiatedByClient + ")"); newClient.start(); } } public int start() { IFingerprintDaemon daemon = getFingerprintDaemon(); if (daemon == null) { Slog.w(TAG,"start authentication: no fingeprintd!"); return ERROR_ESRCH; } try { final int result = daemon.authenticate(mOpId,getGroupId()); if (result != 0) { Slog.w(TAG,"startAuthentication Failed,result=" + result); Metricslogger.histogram(getContext(),"fingeprintd_auth_start_error",result); onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE); return result; } if (DEBUG) Slog.w(TAG,"client " + getownerString() + " is authenticating..."); } catch (remoteexception e) { Slog.e(TAG,"startAuthentication Failed",e); return ERROR_ESRCH; } return 0; // success }
向底层发送认证命令后就只需要等待认证结果就可以了,前面我们说到在初始化的时候会建立与fingerprintd的通信,其核心是下面这行代码
mDaemon.init(mDaemonCallback);
mDaemonCallback是一个binder对象,接受来自底层的结果,然后通过FingerprintService和FingerManager一层层把结果发送到应用程序中去。
8.0的一些变化
8.0上的fingerprintd变化很大,甚至都不叫fingerprintd了,当然这是native层的东西,这里不讨论,对于FingerprintService而言,一个显著的变化是安全策略的调整
- 8.0之前,指纹只能错误5次,达到5次时会禁止指纹认证,同时开启30秒倒计时,等待结束后重置错误计数,继续认证
- 8.0之后,依然是每错误5次就会倒计时30秒,然而30秒结束后错误计数并不会被清空,8.0上加入了最大20次的限制,累计错误20次之后就无法使用指纹认证功能了,只能用密码的方式才能重置错误计数
private static final int MAX_Failed_ATTEMPTS_LOCKOUT_TIMED = 5; private static final int MAX_Failed_ATTEMPTS_LOCKOUT_PERMANENT = 20; private int getLockoutMode() { if (mFailedAttempts >= MAX_Failed_ATTEMPTS_LOCKOUT_PERMANENT) { return AuthenticationClient.LOCKOUT_PERMANENT; } else if (mFailedAttempts > 0 && mTimedLockoutCleared == false && (mFailedAttempts % MAX_Failed_ATTEMPTS_LOCKOUT_TIMED == 0)) { return AuthenticationClient.LOCKOUT_TIMED; } return AuthenticationClient.LOCKOUT_NONE; }
总结
以上所述是小编给大家介绍的Android7.0指纹服务FingerprintService实例介绍,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!
Android 8.0 以后使用后台 Service 服务 JobIntentService 的使用
由于Android8.0以后不能使用后台服务,使用Service需要使用ContextCompat.startForegroundService启动前台服务,而且通知栏有Notification显示该Service正在运行,这可能会带来不好的用户体验。
如果还是希望使用服务在后台默默工作,通过使用服务开启子进程等等,可以使用JobIntentService。下面的具体的代码:
public class TestService extends JobIntentService {
private static final int JOB_ID = 1000;
public static void enqueueWork(Context context, Intent work) {
enqueueWork(context, TestService.class, JOB_ID, work);
}
@Override
protected void onHandleWork(@NonNull Intent intent) {
// TODO:
}
}
<service
android:name=".service.TestService"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" //重要1
/>
<uses-permission android:name="android.permission.WAKE_LOCK"/> //重要2
//@Override
//public IBinder onBind(@NonNull Intent intent) { //重要3,大坑,不能重写onBind方法,重写的话要返回super.onBind(),否则onHandleWork不会回调。
// return null;
//}
//重要4,重写onStartCommand方法时要返回super.onStartCommand()
Intent intent = new Intent(MainActivity.this,TestService.class);
intent.putExtra("key","value");
TestService.enqueueWork(MainActivity.this,intent);
Android Fingerprint 中的 IPC(Binder)
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
Android7.0 指纹服务 FingerprintService 介绍
Android IntentService详解及使用实例
Android IntentService详解
一、IntentService简介
IntentService是Service的子类,比普通的Service增加了额外的功能。先看Service本身存在两个问题:
- Service不会专门启动一条单独的进程,Service与它所在应用位于同一个进程中;
- Service也不是专门一条新线程,因此不应该在Service中直接处理耗时的任务;
二、IntentService特征
- 会创建独立的worker线程来处理所有的Intent请求;
- 会创建独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程问题;
- 所有请求处理完成后,IntentService会自动停止,无需调用stopSelf()方法停止Service;
- 为Service的onBind()提供默认实现,返回null;
- 为Service的onStartCommand提供默认实现,将请求Intent添加到队列中;
三、使用步骤(详情参考Service项目)
继承IntentService类,并重写onHandleIntent()方法即可;
MainActivity.Java文件
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void startService(View source) { // 创建所需要启动的Service的Intent Intent intent = new Intent(this,MyService.class); startService(intent); } public void startIntentService(View source) { // 创建需要启动的IntentService的Intent Intent intent = new Intent(this,MyIntentService.class); startService(intent); } }
MyIntentService.java文件
public class MyIntentService extends IntentService { public MyIntentService() { super("MyIntentService"); } @Override protected void onHandleIntent(Intent intent) { // IntentService会使用单独的线程来执行该方法的代码 // 该方法内执行耗时任务,比如下载文件,此处只是让线程等待20秒 long endTime = System.currentTimeMillis() + 20 * 1000; System.out.println("onStart"); while (System.currentTimeMillis() < endTime) { synchronized (this) { try { wait(endTime - System.currentTimeMillis()); } catch (InterruptedException e) { e.printstacktrace(); } } } System.out.println("----耗时任务执行完成---"); } }
MyService.java文件
public class MyService extends Service { @Override public IBinder onBind(Intent arg0) { return null; } @Override public int onStartCommand(Intent intent,int flags,int startId) { // 该方法内执行耗时任务可能导致ANR(Application Not Responding)异常 long endTime = System.currentTimeMillis() + 20 * 1000; System.out.println("onStart"); while (System.currentTimeMillis() < endTime) { synchronized (this) { try { wait(endTime - System.currentTimeMillis()); } catch (InterruptedException e) { e.printstacktrace(); } } } System.out.println("----耗时任务执行完成---"); return START_STICKY; } }
运行上述代码,启动MyIntentService的会使用单独的worker线程,因此不会阻塞前台的UI线程;而MyService会。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
android linux内核层 Android 跨进程通信:IPC、Binder 与 ServiceManager 介绍
ebpf在Android安全上的应用:结合binder完成一个行为检查沙箱(上篇)一、IPC简单介绍
IPC是Inter-ProcessCommunication的简写,含意为进程间通讯或则跨进程通讯,是指两个进程之间进行数据交换的过程。
Android在哪些时侯会有跨进程通讯的须要?Android在恳求系统服务的时侯会有跨进程通讯的需求,比如访问手机通信录、获取定位等等行为,本文的目标即是实现一个简易的捕捉这种行为的沙箱
二、binder简单介绍
Binder是Android中的一种跨进程通讯形式,可以理解为是IPC的一种具体实现方法
三、ServiceManager简单介绍
ServiceManager是Android中一个及其重要的系统服务,从它的名称上就可以晓得,它是用于管理系统服务的
ServiceManager由init进程启动
ServiceManager负责了以下的一些功能:服务的注册与查找、进程间通讯、系统服务的启动与唤起、提供系统服务的清单实例
binder驱动决定了底层的通讯详情,这么ServiceManager则相当于导航,告诉具体的通讯该如何走,达到那儿等
四、通信剖析4.1顾客端调用JAVA层剖析
以WifiManager类的getConnectInfo函数(该函数获取wifi信息)为例进行剖析
ctrl+左键查看引用,可以发觉该函数定义在.wifi.WifiManager类中,如右图所示:
从上图可以看见,getConnectInfo函数具体代码只有一句thrownewRuntimeException("Stub!");,这告诉我们这个函数是由rom中相同的类去取代执行,该函数在这被定义是编译所须要(PS:可以参考),在android源码中的目录frameworks/base/wifi/java/amdroid/net/wifi下我们可以找到该类,之后找到该函数的具体实现,如右图所示:
可以发觉该函数调用了IWifiManager的getConnectionInfo函数,在frameworks/base/wifi/java/amdroid/net/wifi目录下可以找到IWifiManager.aidl文件,该aidl中定义了getConnectionInfo函数,如右图所示:
这儿须要引入一个概念---AIDL,AIDL是android的一种插口语言,用于公开android服务的插口,借此来实现跨进程的函数调用。AIDL在编译时会生成两个类,即Stub和Proxy两个类,Stub类是服务端具象层的彰显,Proxy是顾客端获取的实例,android通过proxy-stub这些设计模式实现了IPC
下边写一个aidl文件之后生成相应的java代码来瞧瞧是如何实现调用的,首先,我们在androidstudio中随意找一个项目,之后新建一个aidl文件,如右图所示:
之后Build->MakeProbject即可生成,生成的路径坐落build/generated/aidl_source_output_dir/debug/out/包名,如右图所示:
观察生成后的java文件可发觉,Proxy类早已生成,在Proxy类中我们可以找到我们定义的函数,如右图所示:
具体剖析一下该函数,首先通过obtain函数生成了一个Parcel实例,之后调用Parcel的write系列函数进行写入,虽然就是一个序列化的过程,之后调用了IBinder的transact函数,跟踪剖析一下该函数,在目录frameworks/base/core/java/android/os下可以找到该java文件,如右图所示:
可以发觉,IBinder仅仅是一个插口
全局搜索一下,可以发觉同目录下的BinderProxy类实现了该插口(PS:值得注意的是,同目录下边还存在一个Binder类,也实现了该插口,但Binder类是服务端的实现,而不是顾客端的实现),如右图所示:
剖析该函数,可以发觉最后迈向了transactNative函数,到此为止,进行IPC通讯顾客端java层早已剖析完毕
4.2顾客端调用Native层剖析
全局搜索一下transactNative函数,可以发觉该函数在native层中注册信息,如右图所示:
跟踪一下android_os_BinderProxy_transact函数,可以发觉该函数首先通过getBPNativeData(env,obj)->mObject.get()获取到了一个BpBinder对象,之后调用了BpBinder的transact函数,如右图所示:
继续跟进下去,可以发觉步入了IPCThreadState的transact函数,如右图所示:
接着跟进,可以发觉首先调用writeTransactionData函数,该函数作用为填充binder_transaction_data结构体,为发送到binder驱动做打算,之后调用waitForResponse等待返回,如右图所示:
跟进waitForResponse函数,可以发觉该函数最重要的就是调用talkWithDriver函数,剖析一下talkWithDriver函数,可以发觉最终调用了ioctl,如右图所示:
四处为止,顾客端native层剖析完毕
4.3内核层剖析(binder驱动剖析)
到此处android linux内核层,我们的ebpf程序就可以开始捕捉之后解析数据格式了
当用户层调用ioctl时,会步入内核态,步入binder_ioctl内核函数(ps:可在内核设备源码中的binder.c找到相应的描述符),剖析一下binder_ioctl函数,可发觉该函数主要作用为在两个进程之间首发数据,我们的通讯数据ioctl命令是BINDER_WRITE_READ,当遇见该命令的时侯,会调用binder_ioctl_write_read函数,如右图所示:
跟进binder_ioctl_write_read函数,可以发觉,该函数首先将unsignedlong类型的arg参数指向的地址的值读取到结构体binder_write_read中,说明当ioctl命令为BINDER_WRITE_READ时,传递进来的参数为指向结构的binder_write_read的表针,如右图所示:
到这儿虽然我们内核态的剖析早已可以结束了,我们早已观察到了我们想要的数据了,即binder_write_read结构体,可以看一下该结构体的定义,如下所示:
<em> 复制代码</em><em> 隐藏代码<br></em><span>struct</span> <span>binder_write_read</span> {<br> <span>binder_size_t</span> write_size; <span>/* 写内容的数据总大小 */</span><br> <span>binder_size_t</span> write_consumed; <span>/* 记录了从缓冲区读取写内容的大小 */</span><br> <span>binder_uintptr_t</span> write_buffer; <span>/* 写内容的数据的虚拟地址 */</span><br> <span>binder_size_t</span> read_size; <span>/* 读内容的数据总大小 */</span><br> <span>binder_size_t</span> read_consumed; <span>/* 记录了从缓冲区读取读内容的大小 */</span><br> <span>binder_uintptr_t</span> read_buffer; <span>/* 读内容的数据的虚拟地址 */</span><br>};
这个结构体是拿来描述进程间通讯过程中所传输的数据,我们读取从顾客端发送到服务端的通讯包只须要关注write_size、write_consumed、write_buffer,其中,write_buffer指向的是一个链表,这个字段中就包含了binder_transaction_data结构体,这个结构体在native层writeTransactionData函数填充的,我们的目标通讯包即是这个结构体,其中,write_buffer和read_buffer指向的数据结构大致如下:
通常来说,驱动会一次性传递多条命令和地址的组合,而我们要在其中找到binder_transaction_data结构体对应的指令,在binder.h头文件中我们可以找到驱动定义的所有指令(+/refs/heads/android-mainline/include/uapi/linux/android/binder.h),如右图所示:
可以发觉,BC_TRANSACTION和BC_REPLY指令都对应着binder_transaction_data结构体参数,但我们只须要顾客端发往驱动的数据包,所以我们只须要BC_TRANSACTION指令对应的参数即可
经过前面的剖析,我们找到了我们须要的核心数据---binder_transaction_data结构体,现今来看一下该结构体的定义,定义如下:
<em> 复制代码</em><em> 隐藏代码<br></em><span>struct</span> <span>binder_transaction_data</span> {<br> <span>union</span> {<br> __u32 handle;<br> <span>binder_uintptr_t</span> ptr;<br> } target; <span>/* 该事务的目标对象 */</span><br> <span>binder_uintptr_t</span> cookie; <span>/* 只有当事务是由Binder驱动传递给用户空间时,cookie才有意思,它的值是处理该事务的Server位于C++层的本地Binder对象 */</span><br> __u32 code; <span>/* 方法编号 */</span><br> __u32 flags;<br> <span>pid_t</span> sender_pid;<br> <span>uid_t</span> sender_euid;<br> <span>binder_size_t</span> data_size; <span>/* 数据长度 */</span><br> <span>binder_size_t</span> offsets_size; <span>/* 若包含对象,对象的数据大小 */</span><br> <span>union</span> {<br> <span>struct</span> {<br> <span>binder_uintptr_t</span> buffer; <span>/* 参数地址 */</span><br> <span>binder_uintptr_t</span> offsets; <span>/* 参数对象地址 */</span><br> } ptr;<br> __u8 buf[<span>8</span>];<br> } data; <span>/* 数据 */</span><br>};
有了该数据结构linux安装,我们就可以晓得顾客端调用服务端的函数的函数、参数等数据了
五、实现疗效
PS:整套系统用于商业,就不做开源处理了,这儿只给出核心结构体复印的截图,就不再发后端的截图了
读取手机通信录(ps:这儿读取下来的数据采用了Toast复印的,所以将捕捉到的Toast相应的通讯包也一起复印了下来,下同):
获取
获取wifi信息:
六、其他
里面当然我们只剖析到了发送部份,反过来,虽然我们也可以读取返回包甚至于更改返回包,就可用于对风控的对抗,比如在内核态中更改APP恳求的设备标示信息(其实前提是app走系统提供的驱动通讯),亦或则用于逆向的工作,比如过root检查等等。
这部份验证代码就暂不放下来了,感兴趣的可以自己实现一下
-官方峰会
公众号设置“星标”,您不会错过新的消息通知
如开放注册、精华文章和周边活动等公告
以上就是android
今天关于Android7.0指纹服务FingerprintService实例介绍和android设备指纹的介绍到此结束,谢谢您的阅读,有关Android 8.0 以后使用后台 Service 服务 JobIntentService 的使用、Android Fingerprint 中的 IPC(Binder)、Android IntentService详解及使用实例、android linux内核层 Android 跨进程通信:IPC、Binder 与 ServiceManager 介绍等更多相关知识的信息可以在本站进行查询。
本文标签: