GVKun编程网logo

Android7.0指纹服务FingerprintService实例介绍(android设备指纹)

19

在本文中,我们将为您详细介绍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设备指纹)

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 的使用

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 中的 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进程中去,由该进程来响应服务,然后将处理的结果返回给这个用户应用程序。
NOTEservice 可以与组件通过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(); } …... FingerprintServiceSystemServer中创建并初始化,当检测到手机支持指纹功能的时候,就会启动这个服务 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详解及使用实例

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 介绍

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仅仅是一个插口linux删除命令,其中定义了transact方式,该方式有4个参数,第一个参数code在我们的远程调用中为函数编号,服务端接受到这个编号后,会去找寻Stub类中的静态变量,因而解析出是调用哪个函数,第二个和第三个参数_data、_reply为传入的参数和返回的值,都是经过序列化后的数据android linux内核层,最后一个参数flags为指示是否须要阻塞等待结果,0为阻塞等待,1为立刻返回。

全局搜索一下,可以发觉同目录下的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 linux内核层 Android 跨进程通信:IPC、Binder 与 ServiceManager 介绍的详细内容,更多请关注php中文网其它相关文章!

今天关于Android7.0指纹服务FingerprintService实例介绍android设备指纹的介绍到此结束,谢谢您的阅读,有关Android 8.0 以后使用后台 Service 服务 JobIntentService 的使用、Android Fingerprint 中的 IPC(Binder)、Android IntentService详解及使用实例、android linux内核层 Android 跨进程通信:IPC、Binder 与 ServiceManager 介绍等更多相关知识的信息可以在本站进行查询。

本文标签: