Service的启动与绑定


分析的源码基于android-8.0.0_r4

《安卓进阶解密》读书笔记

Service的启动过程

分为两部分介绍Service的启动过程

  • ContextImpl到AMS的调用过程
  • ActivityThread启动Service

ContextImpl -> AMS

时序图如下

Service的启动与绑定_1

要启动Service,我们会先调用startService方法,它在ContextWrapper中实现

    @Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }

mBase指的是ContextImpl.

ContextImpl::startService

    @Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }

ContextImpl::startServiceCommon

   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(), getAttributionTag(), user.getIdentifier());
            ...
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

ActivityManager.getService()获取到的是AMS的本地代理,通过AMS的本地代理,最终会调用到AMS的startService方法

进程切换:应用程序进程 -> AMS所在进程(SystemServer进程).

ActivityThread启动Service

时序图如下

Service的启动与绑定_2

AMS::startService

    @Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int 
            userId) throws TransactionTooLargeException {
    	 ...
    	 synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res;
            try {
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }

mServices的类型是ActiveServices方法

ActiveServices::startServiceLocked

    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String 
    		resolvedType,int callingPid, int callingUid, boolean fgRequired, String 
    		callingPackage, final int userId) throws TransactionTooLargeException {
    		
            ...
            //1.
            ServiceLookupResult res = retrieveServiceLocked(service, resolvedType,
             	callingPackage,callingPid, callingUid, userId, true, callerFg, false);
                    
            if (res == null) {
            	return null;
        	}
        	if (res.record == null) {
            	return new ComponentName("!", res.permission != null
                    ? res.permission : "private to package");
        	}
        	
        	//2.
        	ServiceRecord r = res.record;
   			...
   			//3.
   			ComponentName cmp = startServiceInnerLocked(smap, service,
            		r, callerFg, addToStarting);
        	return cmp;
   }
  • 注释1:调用retrieveServiceLocked方法,查找是否有与参数service对应的ServiceRecord信息,有则封装为ServiceLookupResult返回;没有则调用PackageManagerService去获取参数service对应的Service信息,并封装到ServiceRecord中,再将ServiceRecord封装为ServiceLookupResult返回

  • 注释2:获取参数Intent service对应的ServiceRecord

  • 注释3:调用startServiceInnerLocked,并将ServiceRecord r作为参数传递

ActiveServices::startServiceInnerLocked

    ComponentName startServiceInnerLocked(ServiceMap smap, Intent service,
            ServiceRecord r,boolean callerFg, boolean addToStarting)
            throws TransactionTooLargeException {
    	...
        String error = bringUpServiceLocked(r,service.getFlags(),callerFg,false,false);  
        if (error != null) {
            return new ComponentName("!!", error);
        }    
        ...    
        return r.name;    
    }

ActiveServices::bringUpServiceLocked

    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean 
    	execInFg,boolean whileRestarting, boolean permissionsReviewRequired)
		throws TransactionTooLargeException {
    	
        ...
        //1.获取Service想要在哪个进程中运行    
        final String procName = r.processName;
        String hostingType = "service";
        ProcessRecord app;

        if (!isolated) {
            //2.传入Service的uid和procName,通过AMS查询是否存在一个与Service对应的
            //ProcessRecord对象
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            ...
            //3.如果运行Service的应用程序进程存在    
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, 
                                   mAm.mProcessStats);
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } ...
            
            }
        } else {
            ...
        }
        
        //4.如果用来运行Service的应用程序进程不存在
        if (app == null && !permissionsReviewRequired) {
            //5.调用AMS的startProcessLocked方法,创建对应的应用程序进程
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingType, r.name, false, isolated, false)) == null) {
               ...
                return msg;
            }
            ...
        }
        ...       
    }

我们可以在AndroidManifest.xml中设置android:process,来新开启一个新进程运行Service,这种情况下程序不会进入注释3的If语句,而是会进入注释4的If语句;如果我们不指定android:process,默认情况下,Service会运行在应用程序的当前进程上面。这里我们讨论没有指定android:process的情况,即进入注释3,而不进入注释4。在注释3的If语句中,会调用realStartServiceLocked方法

ActiveServices::realStartServiceLocked

    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
    	 ...
         //为ServiceRecord的app变量赋值ProcessRecord类型的app变量,后面Service绑定时,会用到
         //这个判定条件
         r.app = app;
         ...
         try {
            ...
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
            Slog.w(TAG, "Application dead when creating service " + r);
            mAm.appDiedLocked(app);
            throw e;
        } finally {
            ...
        }
        ...
    }

app.threadIApplicationThread类型,真正实现是ApplicationThreadapp.thread获取到的是ApplicationThread的代理.

进程切换:AMS所在进程(SystemServer进程) -> 应用进程的Binder线程.

ApplicationThread::scheduleCreateService

        public final void scheduleCreateService(IBinder token,
                ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
            updateProcessState(processState, false);
            //将启动Service的参数封装成CreateServiceData
            CreateServiceData s = new CreateServiceData();
            s.token = token;
            s.info = info;
            s.compatInfo = compatInfo;

            sendMessage(H.CREATE_SERVICE, s);
        }

sendMessage方法

   private void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
   }

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

向主线程的消息管理类H mH发送消息.

线程切换:应用程序Binder线程 -> 应用程序主线程.

H::handleMessage,H是ActivityThread的内部类

private class H extends Handler {
	...
    public void handleMessage(Message msg) {
        ...
        case CREATE_SERVICE:
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, 
                             ("serviceCreate: " + String.valueOf(msg.obj)));
            handleCreateService((CreateServiceData)msg.obj);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            break;
        ...
    }    
    ...
}

调用ActivityThread::handleCreateService

	private void handleCreateService(CreateServiceData data) {
        ...

        //1.获取要启动Service的应用程序的LoadedApk
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            //2.获取类加载器
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            //3.创建Service实例
            service = (Service) cl.loadClass(data.info.name).newInstance();
        } catch (Exception e) {
           ...
        }

        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
			//4.创建Service的上下文环境ContextImpl对象
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);
			//5.尝试创建Application,makeApplication内部会调用Application的onCreate
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //6.初始化Service
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            //7.调用Service的onCreate,这样Service就启动了
            service.onCreate();
            //8.将启动的Service加入到ActivityThread的成员变量mServices中,这里的data.token
            //实际上是ServiceRecord(ServiceRecord继承至Binder),service的类型是Service,
            //mServices是ArrayMap类型
            mServices.put(data.token, service);
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            ...
        }
    }

到这里,Service就启动起来了

Service的绑定过程

几个相关的类型

  • ServiceRecord:用于描述一个Service(ServiceRecord继承至Binder,后面有将ServiceRecord转型的场景)

  • ProcessRecord:一个进程的信息

  • ConnectionRecord:用于描述应用程序进程和Service建立的一次通信

  • IntentBindRecord:用于描述绑定Service的Intent

  • AppBindRecord:应用程序进程通过Intent绑定Service时,会通过AppBindRecord来维护Service与应用程序进程之间的关联。其内部存储了谁绑定的Service(ProcessRecord)、被绑定的Service(ServiceRecord)、绑定Service的Intent(IntentBindRecord)和所有绑定通信记录的信息(ArraySet)

分为两部分

  • ContextImpl到AMS的调用过程
  • Service的绑定过程
    • 前半部分
    • 后半部分

ContextImpl -> AMS

时序图如下

Service的启动与绑定_3

ContextWrapper::bindService

    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        return mBase.bindService(service, conn, flags);
    }

ContextImpl::bindService

    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
                Process.myUserHandle());
    }

mMainThread:ActivityThread mMainThread

mMainThread.getHandler():H mH

ContextImpl::bindServiceCommon

 private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, 
          Handler handler, UserHandle user) {
     
     	IServiceConnection sd;
        if (conn == null) {
            throw new IllegalArgumentException("connection is null");
        }
        if (mPackageInfo != null) {
            //通过LoadedApk,将ServiceConnection封装为IServiceConnection,它实现了Binder机制
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, 
                                                   flags);
        } else {
            throw new RuntimeException("Not supported in system context");
        }
        validateServiceIntent(service);
     
      try {
            ...
            //通过Binder机制,调用AMS的bindService,并且传入了参数IServiceConnection sd    
            int res = ActivityManager.getService().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());
            if (res < 0) {
                throw new SecurityException(
                        "Not allowed to bind to service " + service);
            }
            return res != 0;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
 }

进程切换:应用程序进程 -> AMS所在进程(SystemServer进程).

Service绑定过程

前半部分

时序图如下

Service的启动与绑定_4

AMS::bindService

    public int bindService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String 
            callingPackage,int userId) throws TransactionTooLargeException { 
       
        ...
        synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        }
    }

ActiveServices::bindServiceLocked

  int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException{
  		...
         try {
           	...
            //1.s类型是ServiceRecord;callerApp类型是ProcessRecord    
            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
            //内部会将IServiceConnectionRecord connection赋值给ConnectionRecord的变量conn 
            ConnectionRecord c = new ConnectionRecord(b, activity,
                    connection, flags, clientLabel, clientIntent);
			...

            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                //2.如果绑定服务时的flag为BIND_AUTO_CREATE,则会调用bringUpServiceLocked启动
                //Service,关于Service的启动前面已经阐述
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                        permissionsReviewRequired) != null) {
                    return 0;
                }
            }

            ...

            //3.这里s.app的类型是ProcessRecord,s.app!=null,表示Service已经运行,
            //  b.intent.received表示当前应用程序进程已经接收到绑定Service时返回的Binder,即
            //  Service的onBind方法返回的Binder
            if (s.app != null && b.intent.received) {
                // Service is already running, so we can immediately
                // publish the connection.
                try {
                    //4.
                    c.conn.connected(s.name, b.intent.binder, false);
                } catch (Exception e) {
                    ...
                }

                //5.
                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                    //6.
                    requestServiceBindingLocked(s, b.intent, callerFg, true);
                }
            } else if (!b.intent.requested) {//7.
                //8.
                requestServiceBindingLocked(s, b.intent, callerFg, false);
            }

            getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);

        } finally {
            Binder.restoreCallingIdentity(origId);
        }

        return 1;            
  }
  • 注释3:在Service启动时,ActiveServices::realStartServiceLocked方法中,会为ServiceRecordapp变量赋值。注释3的分支不是我们要分析的情况
  • 注释4:c.conn.connected,这里会通过Binder机制,切回应用程序进程,如果调用到这一个方法,其实是快要绑定完成了,后面会讲到(这里考虑应用进程对Service第一次绑定,且是第一个应用进程对该Service进行绑定的情况,所以不会走到注释3的分支,而是走注释7的分支)
  • 注释5:如果当前应用程序进程是第一个与Service进行绑定的,并且Service已经调用过onUnBind方法,则走到注释6
  • 注释7:如果应用进程的Client端没有发送过绑定Service的请求,则走到注释8。注释7的分支是我们要分析的情况。
  • 注释6和注释8的区别:在于调用方法requestServiceBindingLocked的最后一个参数,该参数为rebind,注释6中该值为true,注释8中该值为false

ActiveServices::requestServiceBindingLocked

    # rebind:false
	private final boolean requestServiceBindingLocked(ServiceRecord r,  
    		IntentBindRecord i, boolean execInFg, boolean rebind)
             throws TransactionTooLargeException {
    	 ...
         //1.   
         if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
                bumpServiceExecutingLocked(r, execInFg, "bind");
                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
                //2.
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
                if (!rebind) {
                    i.requested = true;
                }
                i.hasBound = true;
                i.doRebind = false;
            } catch (TransactionTooLargeException e) {
                ...
            } catch (RemoteException e) {
                ...
            }
        }
        return true;
            
    }
  • 注释1:左边的判定条件!i.requested || rebindi.requested表示是否发送过绑定Service的请求,这里分析的情况中,!i.requested的值为true,左边的判定条件成立;右边的i.apps.size() > 0也为true,具体分析查看 书本P115~116.
  • 注释2:r.app.thread类型为IApplicationThread,具体实现为ApplicationThread

进程切换:AMS所在进程(SystemServer进程)->应用程序Binder线程.

ActivityThread.ApplicationThread::scheduleBindService

    public final void scheduleBindService(IBinder token, Intent intent,
                                          boolean rebind, int processState) {
        updateProcessState(processState, false);
        BindServiceData s = new BindServiceData();
        s.token = token;
        s.intent = intent;
        s.rebind = rebind;
        ...
        sendMessage(H.BIND_SERVICE, s);
    }

ActivityThread::sendMessage

    private void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
    }

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

线程切换:应用程序Binder线程->应用程序主线程.

ActivityThread.H::handleMessage

public void handleMessage(Message msg) {
	...
     case BIND_SERVICE:
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
        handleBindService((BindServiceData)msg.obj);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        break;
    ...    
}

ActivityThread::handleBindService

     private void handleBindService(BindServiceData data) {
        //1.获取要绑定的Service
		Service s = mServices.get(data.token);
        ...
         if (s != null) {
            try {
                data.intent.setExtrasClassLoader(s.getClassLoader());
                data.intent.prepareToEnterProcess();
                try {
                    //2.
                    if (!data.rebind) {
                        //3.
                        IBinder binder = s.onBind(data.intent);
                        //4.
                        ActivityManager.getService().publishService(
                                data.token, data.intent, binder);
                    //5.
                    } else {
                        s.onRebind(data.intent);
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                    ensureJitEnabled();
                } ...
                    
            } catch (Exception e) {
                ...
            }
        }     
         
     }
  • 注释2:前面说过,我们要分析的情况是rebind的值为false,所以这里我们要分析的是注释2的If语句
  • 注释3:调用ServiceonBind方法获取IBinder,也就是调用我们代码中的ServiceonBind方法,到这里Service就处于绑定状态
  • 注释5:结合前面的bindServiceLocked方法,可以得出,如果当前应用程序进程第一个与Service进行绑定,并且Service已经调用过onUnBind方法,则会调用Service的onRebind方法
  • 注释4:调用AMS的publishService方法

进程切换:应用程序进程->AMS所在进程(SystemServer进程).

后半部分

时序图如下

Service的启动与绑定_5

AMS::publishService

    public void publishService(IBinder token, Intent intent, IBinder service) {
        // Refuse possible leaked file descriptors
        if (intent != null && intent.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        synchronized(this) {
            if (!(token instanceof ServiceRecord)) {
                throw new IllegalArgumentException("Invalid service token");
            }
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }

ActiveServices::publishServiceLocked

 void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
 	...
    for (int conni=r.connections.size()-1; conni>=0; conni--) {
        ArrayList clist = r.connections.valueAt(conni);
        for (int i=0; i

主要关注c.conn.connected语句,c.conn的类型是IserviceConnection,真正的实现是LoadedApk.ServiceDispatcher.InnerConnection,这里c.conn获取到的是一个代理,调用它的方法,会使进程切回应用程序进程

进程切换:AMS所在进程(SystemServer进程)->应用程序Binder线程.

LoadedApk.ServiceDispatcher.InnerConnection

    private static class InnerConnection extends IServiceConnection.Stub {
        final WeakReference mDispatcher;

        InnerConnection(LoadedApk.ServiceDispatcher sd) {
            mDispatcher = new WeakReference(sd);
        }

        public void connected(ComponentName name, IBinder service, boolean dead)
            throws RemoteException {
            LoadedApk.ServiceDispatcher sd = mDispatcher.get();
            if (sd != null) {
                sd.connected(name, service, dead);
            }
        }
    }

connected方法中,调用了LoadedApk.ServiceDispatcherconnected方法

LoadedApk.ServiceDispatcher::connected

    public void connected(ComponentName name, IBinder service, boolean dead) {
        if (mActivityThread != null) {
            mActivityThread.post(new RunConnection(name, service, 0, dead));
        } else {
            doConnected(name, service, dead);
        }
    }

mActivityThreadHandler类型,实际上指向的是H,调用Hpost方法,将线程切换到主线程

线程切换:应用程序Binder线程->应用程序主线程.

LoadedApk.RunConnection::run

    private final class RunConnection implements Runnable {
        RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
            mName = name;
            mService = service;
            mCommand = command;
            mDead = dead;
        }

        public void run() {
            if (mCommand == 0) {
                doConnected(mName, mService, mDead);
            } else if (mCommand == 1) {
                doDeath(mName, mService);
            }
        }

        final ComponentName mName;
        final IBinder mService;
        final int mCommand;
        final boolean mDead;
    }

这里的mCommand == 0,执行ServiceDispatcherdoConnected方法

ServiceDispatcher::doConnected

    public void doConnected(ComponentName name, IBinder service, boolean dead) {
        ...
        // If there was an old service, it is now disconnected.
        if (old != null) {
            mConnection.onServiceDisconnected(name);
        }
        if (dead) {
            mConnection.onBindingDied(name);
        }
        // If there is a new service, it is now connected.
        if (service != null) {
            mConnection.onServiceConnected(name, service);
        }
    }

这里的service就是ActivityThread::handleBindService中,调用ServiceonBind方法返回的IBinder。这里调用了ServiceConnection mConnectiononServiceConnected方法,那么客户端实现的接口类ServiceConnection中的onServiceConnected方法就会被执行了。至此,Service的绑定过程就分析完成。

参考

《安卓进阶解密》