本文基于aosp8.0源码分析
Service的启动 Service的启动分两种,一种startService,另一种bindService
StartService 一般我们会在Activity中通过startService来启动一个服务
Activity.startService 其内部实际上是由ContextWrapper的startService来启动,实际启动的地方是在ContextImpl.startService
ContextImpl.startService 1 2 3 4 5 @Override public ComponentName startService (Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, false , mUser); }
ContextImpl.startServiceCommon 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 private ComponentName startServiceCommon (Intent service, boolean requireForeground, UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(this ); ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( getContentResolver()), requireForeground, getOpPackageName(), user.getIdentifier()); if (cn != null ) { if (cn.getPackageName().equals("!" )) { throw new SecurityException ( "Not allowed to start service " + service + " without permission " + cn.getClassName()); } else if (cn.getPackageName().equals("!!" )) { throw new SecurityException ( "Unable to start service " + service + ": " + cn.getClassName()); } else if (cn.getPackageName().equals("?" )) { throw new IllegalStateException ( "Not allowed to start service " + service + ": " + cn.getClassName()); } } return cn; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
这里首选需要验证服务,5.0之后隐世服务就不被允许,何为隐世,未指定包名,未指定类名
1 2 3 public static IActivityManager getService () { return IActivityManagerSingleton.get(); }
从ServiceManager中获取ActivityManager的IBinder对象
通过IPC获取了ActivityManagerService对象
每个系统服务都采用了AIDL的方式进行,不直接对外暴露代理
IActivityManager.aidl 该文件对应的native实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class BpActivityManager : public BpInterface<IActivityManager>{ public : explicit BpActivityManager (const sp<IBinder>& impl) : BpInterface<IActivityManager>(impl) { } virtual int openContentUri (const String16& stringUri) { Parcel data, reply; data.writeInterfaceToken (IActivityManager::getInterfaceDescriptor ()); data.writeString16 (stringUri); status_t ret = remote ()->transact (OPEN_CONTENT_URI_TRANSACTION, data, & reply); int fd = -1 ; if (ret == NO_ERROR) { int32_t exceptionCode = reply.readExceptionCode (); if (!exceptionCode) { if (reply.readInt32 () != 0 ) { fd = fcntl (reply.readParcelFileDescriptor (), F_DUPFD_CLOEXEC, 0 ); } } else { ALOGD ("openContentUri(%s) caught exception %d\n" , String8 (stringUri).string (), exceptionCode); } } return fd; } };
ActivityManagerService.startService 1 2 3 4 5 6 7 8 9 10 11 12 public class ActivityManagerService extends IActivityManager .Stub {@Override public ComponentName startService (IApplicationThread caller, Intent service, String resolvedType, boolean requireForeground, String callingPackage, int userId) throws TransactionTooLargeException { ... res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, requireForeground, callingPackage, userId); ... } }
ActivityManagerService就是ActivityManager定义的AIDL的具体实现
调用ActiveServices.startServiceLocked
ActiveServices.startServiceLocked 1 2 3 4 5 6 7 8 ComponentName startServiceLocked (IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId) throws TransactionTooLargeException { ... ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); ... }
检查Service调用者合法性。创建并缓存Service信息
ActiveServices.startServiceInnerLocked 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ComponentName startServiceInnerLocked (ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { ServiceState stracker = r.getTracker(); if (stracker != null ) { stracker.setStarted(true , mAm.mProcessStats.getMemFactorLocked(), r.lastActivity); } r.callStart = false ; synchronized (r.stats.getBatteryStats()) { r.stats.startRunningLocked(); } String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false , false ); if (error != null ) { return new ComponentName ("!!" , error); } if (r.startRequested && addToStarting) { boolean first = smap.mStartingBackground.size() == 0 ; smap.mStartingBackground.add(r); r.startingBgTimeout = SystemClock.uptimeMillis() + mAm.mConstants.BG_START_TIMEOUT; if (DEBUG_DELAYED_SERVICE) { RuntimeException here = new RuntimeException ("here" ); here.fillInStackTrace(); Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r, here); } else if (DEBUG_DELAYED_STARTS) { Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r); } if (first) { smap.rescheduleDelayedStartsLocked(); } } else if (callerFg || r.fgRequired) { smap.ensureNotStartingBackgroundLocked(r); } return r.name; }
调用bringUpServiceLocked,处理返回结果
ActiveService.bringUpServiceLocked 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 private String bringUpServiceLocked (ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException { if (r.app != null && r.app.thread != null ) { sendServiceArgsLocked(r, execInFg, false ); return null ; } ... app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false ); if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app); if (app != null && app.thread != null ) { try { app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats); realStartServiceLocked(r, app, execInFg); return null ; } catch (TransactionTooLargeException e) { throw e; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting service " + r.shortName, e); } } ... }
如果服务已经启动,调用sendserviceArgsLocked。首次创建。获取进程信息。调用realStartServiceLocked
ActiveServices.realStartServiceLocked 1 2 3 4 5 6 7 8 9 10 11 12 13 private final void realStartServiceLocked (ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { ... final boolean newService = app.services.add(r); ... ... app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); ... sendServiceArgsLocked(r, execInFg, true ); }
更新服务优先级。通知ApplicationThread创建启动Service。之后调用sendServiceArgsLocked,其作用,处理Service参数,并回调onStartCommand
ActivityThread.scheduleCreateService 1 2 3 4 5 6 7 8 9 10 public final void scheduleCreateService (IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) { updateProcessState(processState, false ); CreateServiceData s = new CreateServiceData (); s.token = token; s.info = info; s.compatInfo = compatInfo; sendMessage(H.CREATE_SERVICE, s); }
BindService bindService的流程,跟startService很相似。
ActiveServices.bindServiceLocked 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int bindServiceLocked (IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String callingPackage, final int userId) throws TransactionTooLargeException { ... ArrayList<ConnectionRecord> clist = s.connections.get(binder); if (clist == null ) { clist = new ArrayList <ConnectionRecord>(); s.connections.put(binder, clist); } clist.add(c); b.connections.add(c); if (activity != null ) { if (activity.connections == null ) { activity.connections = new HashSet <ConnectionRecord>(); } activity.connections.add(c); } b.client.connections.add(c); ... if ((flags&Context.BIND_AUTO_CREATE) != 0 ) { s.lastActivity = SystemClock.uptimeMillis(); if (bringUpServiceLocked(s, service.getFlags(), callerFg, false , permissionsReviewRequired) != null ) { return 0 ; } } ... }
ServiceRecord存储每个Binder,也就是ServiceConnection。内部的数据结构都是Set,确保Binder唯一。调用bringUpServiceLocked
ActiveServices.bringUpServiceLocked 1 2 3 4 5 private String bringUpServiceLocked (ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException { }
首次绑定Service的过程和startService一样。也是调用realStartServiceLocked。非首次也是调用sendServiceArgsLocked,这个函数中,如果有startService的话,那么会发出消息通知ApplicationThread需要处理onStartCommand。BindService下,会直接返回
1 2 3 4 5 6 7 8 private final void realStartServiceLocked (ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { ... ... requestServiceBindingsLocked(r, execInFg); }
创建过程一样。创建完之后会检查是否有Binder。如果有直接通知ApplicationThread需要绑定服务。
总结 客户端发起启动服务请求,通过IPC的方式通知SystemServer进程中的ActivityManagerService,然后通知ApplicationThread创建服务
时序图 StartService
BindService